]> SALOME platform Git repositories - modules/gui.git/blob - src/SUIT/SUIT_FileDlg.cxx
Salome HOME
[bos #42871] Clipping plane remains applied after being deleted
[modules/gui.git] / src / SUIT / SUIT_FileDlg.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : SUIT_FileDlg.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 //
26 /*!
27   \class SUIT_FileDlg
28   \brief An extension of the Qt Open/Save file dialog box.
29
30   The class SUIT_FileDlg provides a set of static methods which canbe used
31   for file or directories selection:
32   - getFileName() for single file opening or saving
33   - getOpenFileNames() for mulktiple files opening
34   - getExistingDirectory() for existing directory selection
35
36   Examples:
37   \code
38   // select file to dump contents of the view
39   QStringList filters;
40   filters << "Image files (*.bmp *.gif *.jpg )" << "All files (*)";
41   QString fileName = SUIT_FileDlg::getFileName( desktop(), 
42                                                 QString(), 
43                                                 filters, 
44                                                 "Dump view",
45                                                 false );
46   if ( !fileName.isEmpty() ) {
47     ... writing image to the file 
48   }
49
50   // select list of files to open in the editor windows
51   QStringList filters;
52   filters << "*.cpp | *.cxx | *.c++" << "*.h | *.hpp | *.hxx";
53   QStringList fileNames = SUIT_FileDlg::getOpenFileName( desktop(),
54                                                          QString(), 
55                                                          filters, 
56                                                          QString() );
57   if ( !fileNames.isEmpty() ) {
58     ... open files
59   }
60   \endcode
61
62   The class SUIT_FileDlg can be subclassed to implement custom file 
63   dialog boxes. The class provides a set of methods which can be used
64   in subclasses:
65   - setCheckPermissions() - to enable/disable check of files/directories
66     permissions
67   - setValidator() - to use custom file validator
68   - addWidgets() - to add custom widgets to the lower part of the 
69     dialog box
70   - getLastVisitedDirectory() - to get last visited directory
71   - acceptData() - can be used ti customize user selection validation
72
73   \sa SUIT_FileValidator class.
74 */
75
76 #include "SUIT_FileDlg.h"
77
78 #include "SUIT_Tools.h"   
79 #include "SUIT_Session.h"
80 #include "SUIT_MessageBox.h"
81 #include "SUIT_ResourceMgr.h"
82 #include "SUIT_FileValidator.h"
83 #include "Qtx.h"
84
85 #include <QDir>
86 #include <QEvent>
87 #include <QRegExp>
88 #include <QLabel>
89 #include <QComboBox>
90 #include <QPushButton>
91 #include <QGridLayout>
92 #include <QApplication>
93 #include <QListView>
94 #include <QLineEdit>
95 #include <QUrl>
96 #include <QStandardPaths>
97
98 /*!
99   \brief Defines extension behavior.
100
101   If the selected file name has extension which does not match the selected filter
102   and this variable is set to \c true, the file extension is ignored and new one
103   (from current file filter will be added.
104   \sa addExtension()
105 */
106 const bool IGNORE_NON_MATCHING_EXTENSION = true;
107
108 QString SUIT_FileDlg::myLastVisitedPath;
109
110 /*!
111   \brief Constructor.
112   \param parent parent widget
113   \param open if \c true dialog box is used for file opening, otherwise - for saving
114   \param showQuickDir if \c true the quick directory list widgets will be shown
115   \param modal if \c true the dialog box will be modal
116 */
117 SUIT_FileDlg::SUIT_FileDlg( QWidget* parent, bool open, bool showQuickDir, bool modal )
118 : QFileDialog( parent ),
119   myValidator( 0 ),
120   myQuickLab( 0 ),
121   myQuickCombo( 0 ),
122   myQuickButton( 0 ),
123   myCheckPermissions( true )
124 {
125   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
126   setOption(QFileDialog::DontUseNativeDialog, true);
127   setModal( modal );
128   setSizeGripEnabled( true );
129   if ( parent )
130     setWindowIcon( parent->windowIcon() );
131
132   // standard side bar URLs
133   myUrls << QStandardPaths::writableLocation( QStandardPaths::ApplicationsLocation );
134   myUrls << QStandardPaths::writableLocation( QStandardPaths::HomeLocation );
135   myUrls << qgetenv( "DATA_DIR" );
136
137   // add quick directories widgets
138   if ( showQuickDir ) {
139     myQuickLab    = new QLabel( tr( "LAB_QUICK_PATH" ), this );
140     myQuickCombo  = new QComboBox( this );
141     myQuickButton = new QPushButton( tr( "BUT_ADD_PATH" ), this );
142     
143     if ( addWidgets( myQuickLab, myQuickCombo, myQuickButton ) ) {
144       connect( myQuickCombo,  SIGNAL( activated( const QString& ) ), this, SLOT( quickDir( const QString& ) ) );
145       connect( myQuickButton, SIGNAL( clicked() ),                   this, SLOT( addQuickDir() ) );
146
147       // retrieve directories list from the resources
148       QStringList dirList;
149   
150       if ( resMgr )
151         dirList = resMgr->stringValue( "FileDlg", "QuickDirList" ).split( ';', QString::SkipEmptyParts );
152
153       if ( dirList.isEmpty() ) 
154         dirList << QDir::homePath();
155
156       for ( int i = 0; i < dirList.count(); i++ ) {
157         // add to combo box
158         myQuickCombo->addItem( dirList[i] );
159         // add to side bar
160         myUrls << dirList[i];
161       }
162     }
163     else {
164       delete myQuickLab;    myQuickLab = 0;
165       delete myQuickCombo;  myQuickCombo = 0;
166       delete myQuickButton; myQuickButton = 0;
167     }
168   }
169
170   // update side bar
171   updateSideBar();
172
173   setAcceptMode( open ? AcceptOpen: AcceptSave );
174   setWindowTitle( open ? tr( "INF_DESK_DOC_OPEN" ) : tr( "INF_DESK_DOC_SAVE" ) );
175
176   bool showCurrentDirInitial = resMgr ? resMgr->booleanValue( "FileDlg", "ShowCurDirInitial", false ) : false;
177
178   // If last visited path doesn't exist -> switch to the first preferred path
179   if ( !myLastVisitedPath.isEmpty() ) {
180     if ( !processPath( myLastVisitedPath ) && showQuickDir )
181       processPath( myQuickCombo->itemText( 0 ) );
182   }
183   else if ( showCurrentDirInitial ) {
184     processPath( QDir::currentPath() );
185   }
186   else if ( showQuickDir ) {
187     processPath( myQuickCombo->itemText( 0 ) );
188   }
189
190   // set default file validator
191   myValidator = new SUIT_FileValidator( this );
192 }
193
194 /*!
195   \brief Constructor.
196   \param parent parent widget
197   \param initial initial file (or directory) dialog box to be opened on
198   \param filters file filters list
199   \param caption dialog box title
200   \param open if \c true dialog box is used for file opening, otherwise - for saving
201   \param showQuickDir if \c true the quick directory list widgets will be shown
202   \param validator custom file validator
203 */
204 SUIT_FileDlg::SUIT_FileDlg(QWidget* parent,
205                            const QString& initial,
206                            const QStringList& filters,
207                            const QString& caption /* = QString()*/,
208                            const bool open /* = true*/,
209                            const bool showQuickDir /* = true*/,
210                            SUIT_FileValidator* validator /* = 0*/)
211 : SUIT_FileDlg (parent, open, showQuickDir, true)
212 {
213   setFileMode(open ? ExistingFile : AnyFile);
214
215   QString tmpfilename = initial;
216   tmpfilename = tmpfilename.simplified();
217   tmpfilename = tmpfilename.replace(QRegExp("\\*"), "").replace(QRegExp("\\?"), "" );
218   if (!tmpfilename.isEmpty())
219     processPath(tmpfilename);
220
221   if (filters.isEmpty())
222     setNameFilter(tr("ALL_FILES_FILTER")); // All files (*)
223   else
224     setNameFilters(filters);
225
226   if (!caption.isEmpty())
227     setWindowTitle(caption);
228
229   if (validator)
230     setValidator(validator);
231 }
232
233 /*!
234   \brief Destructor.
235 */
236 SUIT_FileDlg::~SUIT_FileDlg() 
237 {
238   setValidator( 0 );
239 }
240
241
242 /*! 
243   \brief Check if the dialog box is used for opening or saving the file.
244   \return \c true if dialog is used for file opening and \c false otherwise
245 */
246 bool SUIT_FileDlg::isOpenDlg() const
247 {
248   return acceptMode() == AcceptOpen;
249 }
250
251 /*!
252   \brief Get 'check file permissions' flag.
253   \return flag value
254   \sa setCheckPermissions()
255 */
256 bool SUIT_FileDlg::checkPermissions() const
257 {
258   return myCheckPermissions;
259 }
260
261 /*!
262   \brief Set 'check file permissions' flag.
263  
264   If this flag is set and file validator is not null,
265   the validator will check the file permissions also.
266
267   \param checkPerm new flag value
268   \sa checkPermissions()
269 */
270 void SUIT_FileDlg::setCheckPermissions( const bool checkPerm )
271 {
272   myCheckPermissions = checkPerm;
273 }
274
275 /*!
276   \brief Get file validator.
277   \return current file validator
278   \sa setValidator()
279 */
280 SUIT_FileValidator* SUIT_FileDlg::validator() const
281 {
282   return myValidator;
283 }
284
285 /*!
286   \brief Set file validator.
287  
288   Destroys previous validator if the dialog owns it.
289
290   \param v new file validator
291   \sa validator()
292 */
293 void SUIT_FileDlg::setValidator( SUIT_FileValidator* v )
294 {
295   if ( myValidator && myValidator->parent() == this )
296     delete myValidator;
297   myValidator = v;
298 }
299
300 /*!
301   \brief Adds the specified widgets to the bottom of the file dialog. 
302   
303   The first widget (usually label) \a l is placed underneath the "file name" 
304   and the "file types" labels. 
305   The widget \a w is placed underneath the file types combobox.
306   The last widget (usually button) \a b is placed underneath the Cancel push button. 
307
308   In general, the widgets can be arbitrary. This method is added to support 
309   the functionality provided by the Qt series 3.x.
310
311   If you don't want to have one of the widgets added, pass 0 in that widget's position. 
312   Every time this function is called, a new row of widgets is added to the bottom of the 
313   file dialog. 
314
315   \param l first widget (e.g. text label)
316   \param w second widget (e.g. combo box)
317   \param b third widget (e.g. push button)
318   \return \c true if widgets have been added successfully
319 */
320 bool SUIT_FileDlg::addWidgets( QWidget* l, QWidget* w, QWidget* b )
321 {
322   QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
323   if ( grid ) {
324     int row = grid->rowCount();
325     int columns = grid->columnCount();
326     if ( l ) 
327       grid->addWidget( l, row, 0 );
328     if ( w )
329       grid->addWidget( w, row, 1, 1, columns-2 );
330     if ( b )
331       grid->addWidget( b, row, columns-1 );
332     return true;
333   }
334   return false;
335 }
336
337 /*!
338   \brief Get list of selected files.
339   \return selected file names
340 */
341 QStringList SUIT_FileDlg::selectedFiles() const
342 {
343   QStringList files = QFileDialog::selectedFiles();
344   if ( fileMode() != DirectoryOnly && fileMode() != Directory ) {
345     QMutableListIterator<QString> it( files );
346     while ( it.hasNext() ) {
347       QString f = it.next();
348       QFileInfo finfo( f );
349       if ( !finfo.isDir() )
350         it.setValue( addExtension( f ) );
351     }
352   }
353   return files;
354 }
355
356 /*!
357   \brief Get selected file.
358   \return selected file name or null string if file is not selected
359 */
360 QString SUIT_FileDlg::selectedFile() const
361 {
362   QStringList files = selectedFiles();
363   return files.count() > 0 ? files[0] : QString();
364 }
365
366 /*!
367   \brief Get last visited directory.
368
369   Note, that last visited path is memorized only if the 
370   dialog box is accepted.
371
372   \return last visited directory
373 */
374 QString SUIT_FileDlg::getLastVisitedDirectory()
375 {
376   return myLastVisitedPath;
377 }
378
379 /*!
380   \brief Customize events processing.
381   \param e event
382   \return \c true if the event e was recognized and processed
383 */
384 bool SUIT_FileDlg::event( QEvent* e )
385 {
386   bool res = QFileDialog::event( e );
387
388   if ( e->type() == QEvent::Polish )
389     polish();
390
391   return res;
392 }
393
394 /*!
395   \brief Get line edit which is used to enter file name.
396   \return line edit widget or0 if it could not be found
397 */
398 QLineEdit* SUIT_FileDlg::lineEdit() const
399 {
400   QLineEdit* ebox = 0;
401   QList<QLineEdit*> editBoxes = findChildren<QLineEdit*>();
402   QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
403   if ( grid ) {
404     int idx = 10000;
405     for ( int i = 0; i < editBoxes.count(); i++ ) {
406       int widx = grid->indexOf( editBoxes[ i ] );
407       if ( widx >= 0 )
408         idx = qMin( idx, widx );
409     }
410     if ( grid->itemAt( idx )  )
411       ebox = qobject_cast<QLineEdit*>( grid->itemAt( idx )->widget() );
412   }
413   return ebox;
414 }
415
416 /*! 
417   \brief Validate user selection.
418
419   The validation is done by calling the corresponding methods
420   of the validator. If the validator is not set, this method
421   always returns \c true.
422
423   This method can be re-implemented in the subclasses to customize
424   the file dialog behavior.
425   Another solution could be implementing own file validator class.
426
427   \return \c true if user selection (file(s) or directory) is valid
428   \sa SUIT_FileValidator class, validator(), setValidator()
429 */
430 bool SUIT_FileDlg::acceptData()
431 {    
432   QStringList files = selectedFiles();
433   if ( files.isEmpty() )
434     return false;
435
436   // special case for ".."
437   if ( lineEdit() ) {
438     QString txt = lineEdit()->text();
439     if ( txt == ".." ) {
440       QDir dir = directory();
441       if ( dir.cdUp() ) {
442         setDirectory( dir );
443         bool block = lineEdit()->blockSignals( true );
444         lineEdit()->setText( ".." );
445         lineEdit()->selectAll();
446         lineEdit()->setFocus( Qt::OtherFocusReason );
447         lineEdit()->blockSignals( block );
448         return false;
449       }
450     }
451     else if ( fileMode() != DirectoryOnly ) {
452       QStringList fs = txt.split( " ", QString::SkipEmptyParts );
453       for ( int i = 0; i < fs.count(); i++ ) {
454         QString wc = fs.at( i );
455         if ( wc.startsWith( "\"" ) && wc.endsWith( "\"" ) )
456           wc = wc.mid( 1, wc.length()-2 );
457         if ( hasWildCards( wc ) ) {
458           addFilter( wc );
459           lineEdit()->clear();
460           return false;
461         }
462       }
463     }
464   }
465
466   // special case for wildcards
467   for ( int i = 0; i < files.count(); ++i ) {
468   }
469
470   bool bOk = true;
471
472   switch ( fileMode() ) {
473   case DirectoryOnly:
474   case Directory: 
475     {
476       QString fn = files.first();
477       if ( validator() ) {
478         bOk = isOpenDlg() ? validator()->canReadDir( fn, checkPermissions() ) : 
479                             validator()->canWriteDir( fn, checkPermissions() );
480       }
481       break;
482     }
483   case AnyFile: 
484     {
485       QString fn = files.first();
486       QFileInfo info( fn );
487       if ( info.isDir() ) {
488         setDirectory( info.absoluteFilePath() );
489         if ( lineEdit() ) {
490           lineEdit()->selectAll();
491           lineEdit()->setFocus( Qt::OtherFocusReason );
492         }
493         return false;
494       }
495       // validation is not required
496       if ( validator() ) {
497         bOk = isOpenDlg() ? validator()->canOpen( fn, checkPermissions() ) : 
498                             validator()->canSave( fn, checkPermissions() );
499       }
500       break;
501     }
502   case ExistingFile:
503   case ExistingFiles: 
504     {
505       for ( int i = 0; i < files.count(); ++i ) {
506         QFileInfo info( files.at( i ) );
507         if ( info.isDir() ) {
508           setDirectory( info.absoluteFilePath() );
509           if ( lineEdit() ) {
510             lineEdit()->selectAll();
511             lineEdit()->setFocus( Qt::OtherFocusReason );
512           }
513           return false;
514         }
515         if ( validator() ) {
516           bOk = isOpenDlg() ? validator()->canOpen( files.at( i ), checkPermissions() ) : 
517                               validator()->canSave( files.at( i ), checkPermissions() );
518         if ( !bOk )
519           return false;
520         }
521       }
522       break;
523     }
524   }
525
526   if ( bOk )
527     emit filesSelected( files );
528
529   return bOk;
530 }
531
532 /*!
533   \brief Add an extension to the specified file name.
534  
535   The extension is extracted from the active filter.
536
537   \param fileName file name to be processed
538   \return fileName with the extension added
539 */
540 QString SUIT_FileDlg::addExtension( const QString& fileName ) const
541 {
542   QString fname = fileName.trimmed();
543
544   // check if file name entered is empty
545   if ( fname.isEmpty() )
546     return fileName;
547
548   // current file extension
549   QString anExt = "." + SUIT_Tools::extension(fname, true).trimmed();
550
551   // If the file already has extension and it does not match the filter there are two choices:
552   // - to leave it 'as is'
553   // - to ignore it
554   // The behavior is defined by IGNORE_NON_MATCHING_EXTENSION constant
555   if ( anExt != "." && !IGNORE_NON_MATCHING_EXTENSION )
556     return fileName;
557
558   QRegExp r( QString::fromLatin1("\\(?[a-zA-Z0-9.*? +;#|]*\\)?$") );
559   int index = r.indexIn( selectedNameFilter().trimmed() );
560
561   if ( QFileInfo( fileName ).exists() )
562     return fileName; // if file exists return as is
563
564   if ( index >= 0 ) {            
565     // Create wildcard regular expression basing on selected filter 
566     // in order to validate a file extension.
567     // Due to transformations from the filter list (*.txt *.*xx *.c++ SUIT*.* ) we 
568     // will have the pattern (\.txt|\..*xx|\.c\+\+|\..*) (as we validate extension only, 
569     // we remove everything except extension mask from the pattern
570     QString wildcard = selectedNameFilter().mid( index, r.matchedLength() ).trimmed();
571     // replace '|' and ';' separators by space symbol and also brackets if there are some
572     wildcard.replace( QRegExp( "[\\|;|(|)]" )," " ); 
573
574     QString aPattern = wildcard.replace( QRegExp( "(^| )(\\s*)[0-9a-zA-Z*_?]*\\."), " \\." ).trimmed().
575                                          replace( QRegExp( "\\s+" ), "|" ).replace( QRegExp( "[?]" ),".?" ).
576                                          replace( QRegExp( "[*]" ),".*" ).replace( QRegExp( "[+]" ),"\\+" );
577
578     // now we get the list of all extension masks and remove all which does not contain wildcard symbols
579     QStringList extList = aPattern.split( "|", QString::SkipEmptyParts );
580     for ( int i = extList.count() - 1; i >= 0; i-- ) {
581       if ( !extList[i].contains( "." ) )
582         extList.removeAt( i );
583     }
584     aPattern = extList.join( "|" );
585
586     // finalize pattern
587     QRegExp anExtRExp( "^("+ aPattern + ")$" );
588
589     // Check if the current file extension matches the pattern
590     if ( !anExtRExp.exactMatch( anExt ) ) {
591       // find first appropriate extension in the selected filter 
592       // (it should be without wildcard symbols)
593       for ( int i = 0; i < extList.count(); i++ ) {
594         QString newExt = extList[i].replace( QRegExp( "[\\\\][+]" ),"+" );
595         int res = newExt.lastIndexOf( '.' );
596         if ( res >= 0 )
597           newExt = newExt.mid( res + 1 );
598         if ( newExt.indexOf( QRegExp("[*|?]" ) ) < 0 ) {
599           fname += fname.endsWith( "." ) ? newExt : QString( "." ) + newExt;
600           return fname;
601         }
602       }
603     }
604   }
605   return fileName;
606 }
607
608 /*!
609   \brief Processes selection : tries to set specified sirectory or filename
610   as current file dialog selection.
611   \param path file or directory path
612   \return \c true if \a path is processed correctly and \c false otherwise
613 */
614 bool SUIT_FileDlg::processPath( const QString& path )
615 {
616   if ( !path.isNull() ) {
617     QFileInfo fi( path );
618     if ( fi.exists() ) {
619       if ( fi.isFile() )
620         selectFile( path );
621       else if ( fi.isDir() )
622         setDirectory( path );
623       return true;
624     }
625     QString dirPath = SUIT_Tools::dir( path, false );
626     if ( !dirPath.isEmpty() && QFileInfo( dirPath ).exists() )
627       setDirectory( dirPath );
628     selectFile( SUIT_Tools::file( path ) );
629     return true;
630   }
631   return false;
632 }
633
634 /*!
635   \brief Add file filter and activates it.
636   \param filter new file filter
637 */
638 void SUIT_FileDlg::addFilter( const QString& filter )
639 {
640   QStringList flist = nameFilters();
641   if ( !flist.contains( filter ) ) {
642     flist << filter;
643     setNameFilters( flist );
644   }
645   selectNameFilter( filter );
646 }
647
648 /*!
649   \brief Check if the string contains wildcard symbols.
650   \param s string to be checked (for example, file name)
651   \return \c true if string contains "*" or "?" symbols
652 */
653 bool SUIT_FileDlg::hasWildCards( const QString& s )
654 {
655   return s.contains( QRegExp("[*|?]") );
656 }
657
658 /*!
659   \brief Called when the user presses "Open"or "Save" button.
660
661   Verifies the user choice and closes dialog box, setting the return code to QDialog::Accepted
662
663   \sa acceptData()
664 */
665 void SUIT_FileDlg::accept()
666 {
667   if ( acceptData() ) {
668     myLastVisitedPath = directory().path();
669     QDialog::accept();        
670   }
671 }
672
673 /*!
674   \brief Called when user selects directory from the "Quick Dir" combo box.
675
676   Browses the file dialog to the specified directory (if it is valid).
677
678   \param dirPath selected directory
679 */
680 void SUIT_FileDlg::quickDir( const QString& dirPath )
681 {
682   if ( !QDir( dirPath ).exists() )
683     SUIT_MessageBox::critical( this, tr( "ERR_ERROR" ), tr( "ERR_DIR_NOT_EXIST" ).arg( dirPath ) );
684   else
685     processPath( dirPath );
686 }
687
688 /*!
689   \brief Called when user presses "Quick Dir Add" button.
690   
691   Adds current directory to the quick directories list and to the preferences.
692 */
693 void SUIT_FileDlg::addQuickDir()
694 {
695   QString dp = directory().path();
696   if ( !dp.isEmpty() ) {
697     QDir dir( dp );
698
699     QStringList dirList;
700
701     SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
702     if ( resMgr )
703       dirList = resMgr->stringValue( "FileDlg", "QuickDirList" ).split( ';', QString::SkipEmptyParts );
704
705     bool found = false;
706     bool emptyAndHome = false;
707     if ( dirList.count() > 0 ) {
708       for ( int i = 0; i < dirList.count() && !found; i++ )  {
709         QDir aDir( dirList[i] );
710         if ( ( aDir.canonicalPath().isNull() && dirList[i] == dir.absolutePath() ) ||
711              ( !aDir.canonicalPath().isNull() && aDir.exists() &&  
712              aDir.canonicalPath() == dir.canonicalPath() ) ) {
713           found = true;
714         }
715       }
716     }
717     else {
718       emptyAndHome = dir.canonicalPath() == QDir( QDir::homePath() ).canonicalPath();
719     }
720
721     if ( !found ) {
722       dirList << dp;
723       resMgr->setValue( "FileDlg", "QuickDirList", dirList.join( ";" ) );
724
725       if ( !emptyAndHome ) {
726         // add to combo box
727         myQuickCombo->addItem( dp );
728         // add to side bar
729         myUrls << dp;
730       }
731
732       // update side bar
733       updateSideBar();
734     }
735   }
736 }
737
738 /*!
739   \brief Polish the dialog box.
740 */
741 void SUIT_FileDlg::polish()
742 {
743   QList<QPushButton*> buttons = findChildren<QPushButton*>();
744
745   int maxBtnWidth = 0;
746
747   for ( QList<QPushButton*>::const_iterator it = buttons.begin(); 
748         it != buttons.end(); ++it )
749     maxBtnWidth = qMax( maxBtnWidth, (*it)->sizeHint().width() );
750
751   for ( QList<QPushButton*>::const_iterator it = buttons.begin(); 
752         it != buttons.end(); ++it ) {
753     (*it)->setDefault( false );
754     (*it)->setAutoDefault( false );
755     (*it)->setFixedWidth( maxBtnWidth );
756   }
757
758   QList<QListView*> views = findChildren<QListView*>();
759   for ( QList<QListView*>::const_iterator it = views.begin(); 
760         it != views.end(); ++it ) {
761     (*it)->setViewMode( QListView::ListMode );
762   }
763 }
764
765 /*!
766   \brief Update side bar URLs list
767 */
768 void SUIT_FileDlg::updateSideBar()
769 {
770   QList<QUrl> urls;
771
772   foreach ( QString url, myUrls ) {
773     if ( !url.isEmpty() && QFileInfo( url ).exists() )
774       urls << QUrl::fromLocalFile( url );
775   }
776
777   setSidebarUrls( urls );
778 }
779
780 /*!
781   \brief Show dialog box for the file opening/saving.
782
783   This method can be used to select the file for opening
784   or saving. The behavior is defined by the \a open parameter.
785   Note, that selection validation depends on the dialog mode used.
786
787   If \a initial parameter is not null string it is used as starting directory
788   or file at which dialog box is opened.
789   
790   The parameter \a filters defines file filters (wildcards) to be used.
791   If filters list is empty, "All files (*)" is used by default.
792   
793   The parameter \a caption is used as dialog box title. If it is
794   is empty, the default title is used.
795   
796   The parameter \a showQuickDir specifies if it is necessary to 
797   show additional quick directories list controls in the bottom part
798   of the dialog box.
799
800   The validation of the user selection is done with help of the file 
801   validator (SUIT_FileValidator class). The last parameter \a validator
802   can be used to pass the custom file validator to the dialog box.
803   
804   \param parent parent widget
805   \param initial initial file (or directory) dialog box to be opened on
806   \param filters file filters list
807   \param caption dialog box title
808   \param open if \c true dialog box is used for file opening, otherwise - for saving
809   \param showQuickDir if \c true the quick directory list widgets will be shown
810   \param validator custom file validator
811   \return selected file name or null string if dialog box is cancelled
812   \sa getOpenFileNames(), getExistingDirectory()
813 */
814 QString SUIT_FileDlg::getFileName( QWidget* parent, const QString& initial, 
815                                    const QStringList& filters, const QString& caption, 
816                                    const bool open, const bool showQuickDir,
817                                    SUIT_FileValidator* validator )
818 {
819   SUIT_FileDlg fd(parent, initial, filters, caption, open, showQuickDir, validator);
820
821   QString filename;
822
823   if ( fd.exec() == QDialog::Accepted )
824     filename = fd.selectedFile();
825
826   QApplication::processEvents();
827
828   return filename;
829 }
830
831 /*!
832   \brief Show dialog box for the file opening/saving.
833   \overload
834
835   This method can be used to select the file for opening
836   or saving. The behavior is defined by the \a open parameter.
837   Note, that selection validation depends on the dialog mode used.
838
839   If \a initial parameter is not null string it is used as starting directory
840   or file at which dialog box is opened.
841   
842   The parameter \a filters defines file filters (wildcards) to be used.
843   This is the list of wildcards, separated by the ";;" symbols.
844   If filters list is empty, "All files (*)" is used by default.
845   
846   The parameter \a caption is used as dialog box title. If it is
847   is empty, the default title is used.
848   
849   The parameter \a showQuickDir specifies if it is necessary to 
850   show additional quick directories list controls in the bottom part
851   of the dialog box.
852
853   The validation of the user selection is done with help of the file 
854   validator (SUIT_FileValidator class). The last parameter \a validator
855   can be used to pass the custom file validator to the dialog box.
856   
857   \param parent parent widget
858   \param initial initial file (or directory) dialog box to be opened on
859   \param filters file filters separated by ";;"
860   \param caption dialog box title
861   \param open if \c true dialog box is used for file opening, otherwise - for saving
862   \param showQuickDir if \c true the quick directory list widgets will be shown
863   \param validator custom file validator
864   \return selected file name or null string if dialog box is cancelled
865   \sa getOpenFileNames(), getExistingDirectory()
866 */
867 QString SUIT_FileDlg::getFileName( QWidget* parent, const QString& initial, 
868                                    const QString& filters, const QString& caption, 
869                                    const bool open, const bool showQuickDir,
870                                    SUIT_FileValidator* validator )
871 {
872   return getFileName( parent, initial, filters.split( ";;", QString::SkipEmptyParts ), 
873                       caption, open, showQuickDir, validator );
874 }
875
876 /*!
877   \brief Show dialog box for the file opening/saving.
878
879   This method can be used to select the file for opening
880   or saving. The behavior is defined by the \a open parameter.
881   Note, that selection validation depends on the dialog mode used.
882
883   If \a initial parameter is not null string it is used as starting directory
884   or file at which dialog box is opened.
885
886   The parameter \a filters defines file filters (wildcards) to be used.
887   If filters list is empty, "All files (*)" is used by default.
888
889   The parameter \a selectedFilter outputs a filter selected by user.
890
891   The parameter \a caption is used as dialog box title. If it is
892   is empty, the default title is used.
893
894   The parameter \a showQuickDir specifies if it is necessary to 
895   show additional quick directories list controls in the bottom part
896   of the dialog box.
897
898   The validation of the user selection is done with help of the file 
899   validator (SUIT_FileValidator class). The last parameter \a validator
900   can be used to pass the custom file validator to the dialog box.
901
902   \param parent parent widget
903   \param initial initial file (or directory) dialog box to be opened on
904   \param filters file filters list
905   \param selectedFilter outputs a filter selected by user
906   \param caption dialog box title
907   \param open if \c true dialog box is used for file opening, otherwise - for saving
908   \param showQuickDir if \c true the quick directory list widgets will be shown
909   \param validator custom file validator
910   \return selected file name or null string if dialog box is cancelled
911   \sa getOpenFileNames(), getExistingDirectory()
912 */
913 QString SUIT_FileDlg::getFileName(QWidget* parent,
914                                   const QString& initial,
915                                   const QStringList& filters,
916                                   QString& selectedFilter,
917                                   const QString& caption /* = QString()*/,
918                                   const bool open /* = true*/,
919                                   const bool showQuickDir /* = true*/,
920                                   SUIT_FileValidator* validator /* = 0*/)
921 {            
922   SUIT_FileDlg fd(parent, initial, filters, caption, open, showQuickDir, validator);
923
924   QString filename;
925   if (fd.exec() == QDialog::Accepted)
926   {
927     filename = fd.selectedFile();
928     selectedFilter = fd.selectedNameFilter();
929   }
930
931   QApplication::processEvents();
932
933   return filename;
934 }
935
936 /*!
937   \brief Show dialog box for the multiple files selection.
938
939   If \a initial parameter is not null string it is used as starting directory
940   or file at which dialog box is opened.
941   
942   The parameter \a filters defines file filters (wildcards) to be used.
943   If filters list is empty, "All files (*)" is used by default.
944   
945   The parameter \a caption is used as dialog box title. If it is
946   is empty, the default title is used.
947   
948   The parameter \a showQuickDir specifies if it is necessary to 
949   show additional quick directories list controls in the bottom part
950   of the dialog box.
951
952   The validation of the user selection is done with help of the file 
953   validator (SUIT_FileValidator class). The last parameter \a validator
954   can be used to pass the custom file validator to the dialog box.
955   
956   \param parent parent widget
957   \param initial initial file (or directory) dialog box to be opened on
958   \param filters file filters list
959   \param caption dialog box title
960   \param showQuickDir if \c true the quick directory list widgets will be shown
961   \param validator custom file validator
962   \return selected file names or empty list if dialog box is cancelled
963   \sa getFileName(), getExistingDirectory()
964 */
965 QStringList SUIT_FileDlg::getOpenFileNames( QWidget* parent, const QString& initial,
966                                             const QStringList& filters, const QString& caption,
967                                             const bool showQuickDir, 
968                                             SUIT_FileValidator* validator )
969 {            
970   SUIT_FileDlg fd( parent, true, showQuickDir, true );
971
972   fd.setFileMode( ExistingFiles );
973
974   if ( filters.isEmpty() )
975     fd.setNameFilter( tr( "ALL_FILES_FILTER" ) ); // All files (*)
976   else
977     fd.setNameFilters( filters );
978
979   if ( !caption.isEmpty() )
980     fd.setWindowTitle( caption );
981
982   if ( !initial.isEmpty() )
983     fd.processPath( initial );
984
985   if ( validator )
986     fd.setValidator( validator );
987
988   QStringList filenames;
989
990   if ( fd.exec() == QDialog::Accepted )
991     filenames = fd.selectedFiles();
992
993   QApplication::processEvents();
994
995   return filenames;
996 }
997
998 /*!
999   \brief Show dialog box for the multiple file opening.
1000   \overload
1001
1002   If \a initial parameter is not null string it is used as starting directory
1003   or file at which dialog box is opened.
1004   
1005   The parameter \a filters defines file filters (wildcards) to be used.
1006   This is the list of wildcards, separated by the ";;" symbols.
1007   If filters list is empty, "All files (*)" is used by default.
1008   
1009   The parameter \a caption is used as dialog box title. If it is
1010   is empty, the default title is used.
1011   
1012   The parameter \a showQuickDir specifies if it is necessary to 
1013   show additional quick directories list controls in the bottom part
1014   of the dialog box.
1015
1016   The validation of the user selection is done with help of the file 
1017   validator (SUIT_FileValidator class). The last parameter \a validator
1018   can be used to pass the custom file validator to the dialog box.
1019   
1020   \param parent parent widget
1021   \param initial initial file (or directory) dialog box to be opened on
1022   \param filters file filters separated by ";;"
1023   \param caption dialog box title
1024   \param showQuickDir if \c true the quick directory list widgets will be shown
1025   \param validator custom file validator
1026   \return selected file names or empty list if dialog box is cancelled
1027   \sa getFileName(), getExistingDirectory()
1028 */
1029 QStringList SUIT_FileDlg::getOpenFileNames( QWidget* parent, const QString& initial,
1030                                             const QString& filters, const QString& caption,
1031                                             const bool showQuickDir,
1032                                             SUIT_FileValidator* validator )
1033 {
1034   return getOpenFileNames( parent, initial, filters.split( ";;", QString::SkipEmptyParts ), 
1035                            caption, showQuickDir, validator );
1036 }
1037
1038 /*!
1039   \brief Show dialog box for the existing directory selection.
1040
1041   If \a initial parameter is not null string it is used as starting directory
1042   at which dialog box is opened.
1043   
1044   The parameter \a caption is used as dialog box title. If it is
1045   is empty, the default title is used.
1046   
1047   The parameter \a showQuickDir specifies if it is necessary to 
1048   show additional quick directories list controls in the bottom part
1049   of the dialog box.
1050
1051   The validation of the user selection is done with help of the file 
1052   validator (SUIT_FileValidator class). The last parameter \a validator
1053   can be used to pass the custom file validator to the dialog box.
1054   
1055   \param parent parent widget
1056   \param initial initial directory dialog box to be opened on
1057   \param caption dialog box title
1058   \param showQuickDir if \c true the quick directory list widgets will be shown
1059   \param validator custom file validator
1060   \return selected directory name or null string if dialog box is cancelled
1061   \sa getFileName(), getOpenFileNames()
1062 */
1063 QString SUIT_FileDlg::getExistingDirectory( QWidget* parent, const QString& initial,
1064                                             const QString& caption, const bool showQuickDir,
1065                                             SUIT_FileValidator* validator )
1066 {
1067   SUIT_FileDlg fd( parent, true, showQuickDir, true );
1068
1069   fd.setFileMode( DirectoryOnly );
1070
1071   if ( !caption.isEmpty() )
1072     fd.setWindowTitle( caption );
1073
1074   if ( !initial.isEmpty() )
1075     fd.processPath( initial );
1076   
1077   if ( validator )
1078     fd.setValidator( validator );
1079
1080   QString dirname;
1081
1082   if ( fd.exec() == QDialog::Accepted )
1083     dirname = fd.selectedFile();
1084
1085   QApplication::processEvents();
1086
1087   return dirname;
1088 }
1089
1090 /*!
1091   \brief Get last visited path
1092   \return last visited path
1093 */
1094 QString SUIT_FileDlg::getLastVisitedPath()
1095 {
1096   return myLastVisitedPath;
1097 }
1098
1099 /*!
1100   \brief Selects current file
1101
1102   This version of selectFile() methods works similar to Qt version 3.x:
1103   it selects the given file as current and it changes the current file dialog's directory
1104   to the directory of the file
1105   
1106   \param f - new current file name 
1107 */
1108 void SUIT_FileDlg::selectFile( const QString& f )
1109 {
1110   QFileDialog::selectFile( QFileInfo( f ).baseName() );
1111   if ( !Qtx::dir( f, false ).isEmpty() )
1112     setDirectory( QFileInfo( f ).absolutePath() );
1113 }