Salome HOME
80e4be11dcd8fc4a301fcd27b5af3251318335ff
[modules/gui.git] / src / SUIT / SUIT_FileDlg.cxx
1 // Copyright (C) 2007-2023  CEA/DEN, EDF R&D, 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 Destructor.
196 */
197 SUIT_FileDlg::~SUIT_FileDlg() 
198 {
199   setValidator( 0 );
200 }
201
202
203 /*! 
204   \brief Check if the dialog box is used for opening or saving the file.
205   \return \c true if dialog is used for file opening and \c false otherwise
206 */
207 bool SUIT_FileDlg::isOpenDlg() const
208 {
209   return acceptMode() == AcceptOpen;
210 }
211
212 /*!
213   \brief Get 'check file permissions' flag.
214   \return flag value
215   \sa setCheckPermissions()
216 */
217 bool SUIT_FileDlg::checkPermissions() const
218 {
219   return myCheckPermissions;
220 }
221
222 /*!
223   \brief Set 'check file permissions' flag.
224  
225   If this flag is set and file validator is not null,
226   the validator will check the file permissions also.
227
228   \param checkPerm new flag value
229   \sa checkPermissions()
230 */
231 void SUIT_FileDlg::setCheckPermissions( const bool checkPerm )
232 {
233   myCheckPermissions = checkPerm;
234 }
235
236 /*!
237   \brief Get file validator.
238   \return current file validator
239   \sa setValidator()
240 */
241 SUIT_FileValidator* SUIT_FileDlg::validator() const
242 {
243   return myValidator;
244 }
245
246 /*!
247   \brief Set file validator.
248  
249   Destroys previous validator if the dialog owns it.
250
251   \param v new file validator
252   \sa validator()
253 */
254 void SUIT_FileDlg::setValidator( SUIT_FileValidator* v )
255 {
256   if ( myValidator && myValidator->parent() == this )
257     delete myValidator;
258   myValidator = v;
259 }
260
261 /*!
262   \brief Adds the specified widgets to the bottom of the file dialog. 
263   
264   The first widget (usually label) \a l is placed underneath the "file name" 
265   and the "file types" labels. 
266   The widget \a w is placed underneath the file types combobox.
267   The last widget (usually button) \a b is placed underneath the Cancel push button. 
268
269   In general, the widgets can be arbitrary. This method is added to support 
270   the functionality provided by the Qt series 3.x.
271
272   If you don't want to have one of the widgets added, pass 0 in that widget's position. 
273   Every time this function is called, a new row of widgets is added to the bottom of the 
274   file dialog. 
275
276   \param l first widget (e.g. text label)
277   \param w second widget (e.g. combo box)
278   \param b third widget (e.g. push button)
279   \return \c true if widgets have been added successfully
280 */
281 bool SUIT_FileDlg::addWidgets( QWidget* l, QWidget* w, QWidget* b )
282 {
283   QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
284   if ( grid ) {
285     int row = grid->rowCount();
286     int columns = grid->columnCount();
287     if ( l ) 
288       grid->addWidget( l, row, 0 );
289     if ( w )
290       grid->addWidget( w, row, 1, 1, columns-2 );
291     if ( b )
292       grid->addWidget( b, row, columns-1 );
293     return true;
294   }
295   return false;
296 }
297
298 /*!
299   \brief Get list of selected files.
300   \return selected file names
301 */
302 QStringList SUIT_FileDlg::selectedFiles() const
303 {
304   QStringList files = QFileDialog::selectedFiles();
305   if ( fileMode() != DirectoryOnly && fileMode() != Directory ) {
306     QMutableListIterator<QString> it( files );
307     while ( it.hasNext() ) {
308       QString f = it.next();
309       QFileInfo finfo( f );
310       if ( !finfo.isDir() )
311         it.setValue( addExtension( f ) );
312     }
313   }
314   return files;
315 }
316
317 /*!
318   \brief Get selected file.
319   \return selected file name or null string if file is not selected
320 */
321 QString SUIT_FileDlg::selectedFile() const
322 {
323   QStringList files = selectedFiles();
324   return files.count() > 0 ? files[0] : QString();
325 }
326
327 /*!
328   \brief Get last visited directory.
329
330   Note, that last visited path is memorized only if the 
331   dialog box is accepted.
332
333   \return last visited directory
334 */
335 QString SUIT_FileDlg::getLastVisitedDirectory()
336 {
337   return myLastVisitedPath;
338 }
339
340 /*!
341   \brief Customize events processing.
342   \param e event
343   \return \c true if the event e was recognized and processed
344 */
345 bool SUIT_FileDlg::event( QEvent* e )
346 {
347   bool res = QFileDialog::event( e );
348
349   if ( e->type() == QEvent::Polish )
350     polish();
351
352   return res;
353 }
354
355 /*!
356   \brief Get line edit which is used to enter file name.
357   \return line edit widget or0 if it could not be found
358 */
359 QLineEdit* SUIT_FileDlg::lineEdit() const
360 {
361   QLineEdit* ebox = 0;
362   QList<QLineEdit*> editBoxes = findChildren<QLineEdit*>();
363   QGridLayout* grid = ::qobject_cast<QGridLayout*>( layout() );
364   if ( grid ) {
365     int idx = 10000;
366     for ( int i = 0; i < editBoxes.count(); i++ ) {
367       int widx = grid->indexOf( editBoxes[ i ] );
368       if ( widx >= 0 )
369         idx = qMin( idx, widx );
370     }
371     if ( grid->itemAt( idx )  )
372       ebox = qobject_cast<QLineEdit*>( grid->itemAt( idx )->widget() );
373   }
374   return ebox;
375 }
376
377 /*! 
378   \brief Validate user selection.
379
380   The validation is done by calling the corresponding methods
381   of the validator. If the validator is not set, this method
382   always returns \c true.
383
384   This method can be re-implemented in the subclasses to customize
385   the file dialog behavior.
386   Another solution could be implementing own file validator class.
387
388   \return \c true if user selection (file(s) or directory) is valid
389   \sa SUIT_FileValidator class, validator(), setValidator()
390 */
391 bool SUIT_FileDlg::acceptData()
392 {    
393   QStringList files = selectedFiles();
394   if ( files.isEmpty() )
395     return false;
396
397   // special case for ".."
398   if ( lineEdit() ) {
399     QString txt = lineEdit()->text();
400     if ( txt == ".." ) {
401       QDir dir = directory();
402       if ( dir.cdUp() ) {
403         setDirectory( dir );
404         bool block = lineEdit()->blockSignals( true );
405         lineEdit()->setText( ".." );
406         lineEdit()->selectAll();
407         lineEdit()->setFocus( Qt::OtherFocusReason );
408         lineEdit()->blockSignals( block );
409         return false;
410       }
411     }
412     else if ( fileMode() != DirectoryOnly ) {
413       QStringList fs = txt.split( " ", QString::SkipEmptyParts );
414       for ( int i = 0; i < fs.count(); i++ ) {
415         QString wc = fs.at( i );
416         if ( wc.startsWith( "\"" ) && wc.endsWith( "\"" ) )
417           wc = wc.mid( 1, wc.length()-2 );
418         if ( hasWildCards( wc ) ) {
419           addFilter( wc );
420           lineEdit()->clear();
421           return false;
422         }
423       }
424     }
425   }
426
427   // special case for wildcards
428   for ( int i = 0; i < files.count(); ++i ) {
429   }
430
431   bool bOk = true;
432
433   switch ( fileMode() ) {
434   case DirectoryOnly:
435   case Directory: 
436     {
437       QString fn = files.first();
438       if ( validator() ) {
439         bOk = isOpenDlg() ? validator()->canReadDir( fn, checkPermissions() ) : 
440                             validator()->canWriteDir( fn, checkPermissions() );
441       }
442       break;
443     }
444   case AnyFile: 
445     {
446       QString fn = files.first();
447       QFileInfo info( fn );
448       if ( info.isDir() ) {
449         setDirectory( info.absoluteFilePath() );
450         if ( lineEdit() ) {
451           lineEdit()->selectAll();
452           lineEdit()->setFocus( Qt::OtherFocusReason );
453         }
454         return false;
455       }
456       // validation is not required
457       if ( validator() ) {
458         bOk = isOpenDlg() ? validator()->canOpen( fn, checkPermissions() ) : 
459                             validator()->canSave( fn, checkPermissions() );
460       }
461       break;
462     }
463   case ExistingFile:
464   case ExistingFiles: 
465     {
466       for ( int i = 0; i < files.count(); ++i ) {
467         QFileInfo info( files.at( i ) );
468         if ( info.isDir() ) {
469           setDirectory( info.absoluteFilePath() );
470           if ( lineEdit() ) {
471             lineEdit()->selectAll();
472             lineEdit()->setFocus( Qt::OtherFocusReason );
473           }
474           return false;
475         }
476         if ( validator() ) {
477           bOk = isOpenDlg() ? validator()->canOpen( files.at( i ), checkPermissions() ) : 
478                               validator()->canSave( files.at( i ), checkPermissions() );
479         if ( !bOk )
480           return false;
481         }
482       }
483       break;
484     }
485   }
486
487   if ( bOk )
488     emit filesSelected( files );
489
490   return bOk;
491 }
492
493 /*!
494   \brief Add an extension to the specified file name.
495  
496   The extension is extracted from the active filter.
497
498   \param fileName file name to be processed
499   \return fileName with the extension added
500 */
501 QString SUIT_FileDlg::addExtension( const QString& fileName ) const
502 {
503   QString fname = fileName.trimmed();
504
505   // check if file name entered is empty
506   if ( fname.isEmpty() )
507     return fileName;
508
509   // current file extension
510   QString anExt = "." + SUIT_Tools::extension( fname ).trimmed();
511
512   // If the file already has extension and it does not match the filter there are two choices:
513   // - to leave it 'as is'
514   // - to ignore it
515   // The behavior is defined by IGNORE_NON_MATCHING_EXTENSION constant
516   if ( anExt != "." && !IGNORE_NON_MATCHING_EXTENSION )
517     return fileName;
518
519   QRegExp r( QString::fromLatin1("\\(?[a-zA-Z0-9.*? +;#|]*\\)?$") );
520   int index = r.indexIn( selectedNameFilter().trimmed() );
521
522   if ( QFileInfo( fileName ).exists() )
523     return fileName; // if file exists return as is
524
525   if ( index >= 0 ) {            
526     // Create wildcard regular expression basing on selected filter 
527     // in order to validate a file extension.
528     // Due to transformations from the filter list (*.txt *.*xx *.c++ SUIT*.* ) we 
529     // will have the pattern (\.txt|\..*xx|\.c\+\+|\..*) (as we validate extension only, 
530     // we remove everything except extension mask from the pattern
531     QString wildcard = selectedNameFilter().mid( index, r.matchedLength() ).trimmed();
532     // replace '|' and ';' separators by space symbol and also brackets if there are some
533     wildcard.replace( QRegExp( "[\\|;|(|)]" )," " ); 
534
535     QString aPattern = wildcard.replace( QRegExp( "(^| )(\\s*)[0-9a-zA-Z*_?]*\\."), " \\." ).trimmed().
536                                          replace( QRegExp( "\\s+" ), "|" ).replace( QRegExp( "[?]" ),".?" ).
537                                          replace( QRegExp( "[*]" ),".*" ).replace( QRegExp( "[+]" ),"\\+" );
538
539     // now we get the list of all extension masks and remove all which does not contain wildcard symbols
540     QStringList extList = aPattern.split( "|", QString::SkipEmptyParts );
541     for ( int i = extList.count() - 1; i >= 0; i-- ) {
542       if ( !extList[i].contains( "." ) )
543         extList.removeAt( i );
544     }
545     aPattern = extList.join( "|" );
546
547     // finalize pattern
548     QRegExp anExtRExp( "^("+ aPattern + ")$" );
549
550     // Check if the current file extension matches the pattern
551     if ( !anExtRExp.exactMatch( anExt ) ) {
552       // find first appropriate extension in the selected filter 
553       // (it should be without wildcard symbols)
554       for ( int i = 0; i < extList.count(); i++ ) {
555         QString newExt = extList[i].replace( QRegExp( "[\\\\][+]" ),"+" );
556         int res = newExt.lastIndexOf( '.' );
557         if ( res >= 0 )
558           newExt = newExt.mid( res + 1 );
559         if ( newExt.indexOf( QRegExp("[*|?]" ) ) < 0 ) {
560           fname += fname.endsWith( "." ) ? newExt : QString( "." ) + newExt;
561           return fname;
562         }
563       }
564     }
565   }
566   return fileName;
567 }
568
569 /*!
570   \brief Processes selection : tries to set specified sirectory or filename
571   as current file dialog selection.
572   \param path file or directory path
573   \return \c true if \a path is processed correctly and \c false otherwise
574 */
575 bool SUIT_FileDlg::processPath( const QString& path )
576 {
577   if ( !path.isNull() ) {
578     QFileInfo fi( path );
579     if ( fi.exists() ) {
580       if ( fi.isFile() )
581         selectFile( path );
582       else if ( fi.isDir() )
583         setDirectory( path );
584       return true;
585     }
586     QString dirPath = SUIT_Tools::dir( path, false );
587     if ( !dirPath.isEmpty() && QFileInfo( dirPath ).exists() )
588       setDirectory( dirPath );
589     selectFile( SUIT_Tools::file( path ) );
590     return true;
591   }
592   return false;
593 }
594
595 /*!
596   \brief Add file filter and activates it.
597   \param filter new file filter
598 */
599 void SUIT_FileDlg::addFilter( const QString& filter )
600 {
601   QStringList flist = nameFilters();
602   if ( !flist.contains( filter ) ) {
603     flist << filter;
604     setNameFilters( flist );
605   }
606   selectNameFilter( filter );
607 }
608
609 /*!
610   \brief Check if the string contains wildcard symbols.
611   \param s string to be checked (for example, file name)
612   \return \c true if string contains "*" or "?" symbols
613 */
614 bool SUIT_FileDlg::hasWildCards( const QString& s )
615 {
616   return s.contains( QRegExp("[*|?]") );
617 }
618
619 /*!
620   \brief Called when the user presses "Open"or "Save" button.
621
622   Verifies the user choice and closes dialog box, setting the return code to QDialog::Accepted
623
624   \sa acceptData()
625 */
626 void SUIT_FileDlg::accept()
627 {
628   if ( acceptData() ) {
629     myLastVisitedPath = directory().path();
630     QDialog::accept();        
631   }
632 }
633
634 /*!
635   \brief Called when user selects directory from the "Quick Dir" combo box.
636
637   Browses the file dialog to the specified directory (if it is valid).
638
639   \param dirPath selected directory
640 */
641 void SUIT_FileDlg::quickDir( const QString& dirPath )
642 {
643   if ( !QDir( dirPath ).exists() )
644     SUIT_MessageBox::critical( this, tr( "ERR_ERROR" ), tr( "ERR_DIR_NOT_EXIST" ).arg( dirPath ) );
645   else
646     processPath( dirPath );
647 }
648
649 /*!
650   \brief Called when user presses "Quick Dir Add" button.
651   
652   Adds current directory to the quick directories list and to the preferences.
653 */
654 void SUIT_FileDlg::addQuickDir()
655 {
656   QString dp = directory().path();
657   if ( !dp.isEmpty() ) {
658     QDir dir( dp );
659
660     QStringList dirList;
661
662     SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
663     if ( resMgr )
664       dirList = resMgr->stringValue( "FileDlg", "QuickDirList" ).split( ';', QString::SkipEmptyParts );
665
666     bool found = false;
667     bool emptyAndHome = false;
668     if ( dirList.count() > 0 ) {
669       for ( int i = 0; i < dirList.count() && !found; i++ )  {
670         QDir aDir( dirList[i] );
671         if ( ( aDir.canonicalPath().isNull() && dirList[i] == dir.absolutePath() ) ||
672              ( !aDir.canonicalPath().isNull() && aDir.exists() &&  
673              aDir.canonicalPath() == dir.canonicalPath() ) ) {
674           found = true;
675         }
676       }
677     }
678     else {
679       emptyAndHome = dir.canonicalPath() == QDir( QDir::homePath() ).canonicalPath();
680     }
681
682     if ( !found ) {
683       dirList << dp;
684       resMgr->setValue( "FileDlg", "QuickDirList", dirList.join( ";" ) );
685
686       if ( !emptyAndHome ) {
687         // add to combo box
688         myQuickCombo->addItem( dp );
689         // add to side bar
690         myUrls << dp;
691       }
692
693       // update side bar
694       updateSideBar();
695     }
696   }
697 }
698
699 /*!
700   \brief Polish the dialog box.
701 */
702 void SUIT_FileDlg::polish()
703 {
704   QList<QPushButton*> buttons = findChildren<QPushButton*>();
705
706   int maxBtnWidth = 0;
707
708   for ( QList<QPushButton*>::const_iterator it = buttons.begin(); 
709         it != buttons.end(); ++it )
710     maxBtnWidth = qMax( maxBtnWidth, (*it)->sizeHint().width() );
711
712   for ( QList<QPushButton*>::const_iterator it = buttons.begin(); 
713         it != buttons.end(); ++it ) {
714     (*it)->setDefault( false );
715     (*it)->setAutoDefault( false );
716     (*it)->setFixedWidth( maxBtnWidth );
717   }
718
719   QList<QListView*> views = findChildren<QListView*>();
720   for ( QList<QListView*>::const_iterator it = views.begin(); 
721         it != views.end(); ++it ) {
722     (*it)->setViewMode( QListView::ListMode );
723   }
724 }
725
726 /*!
727   \brief Update side bar URLs list
728 */
729 void SUIT_FileDlg::updateSideBar()
730 {
731   QList<QUrl> urls;
732
733   foreach ( QString url, myUrls ) {
734     if ( !url.isEmpty() && QFileInfo( url ).exists() )
735       urls << QUrl::fromLocalFile( url );
736   }
737
738   setSidebarUrls( urls );
739 }
740
741 /*!
742   \brief Show dialog box for the file opening/saving.
743
744   This method can be used to select the file for opening
745   or saving. The behavior is defined by the \a open parameter.
746   Note, that selection validation depends on the dialog mode used.
747
748   If \a initial parameter is not null string it is used as starting directory
749   or file at which dialog box is opened.
750   
751   The parameter \a filters defines file filters (wildcards) to be used.
752   If filters list is empty, "All files (*)" is used by default.
753   
754   The parameter \a caption is used as dialog box title. If it is
755   is empty, the default title is used.
756   
757   The parameter \a showQuickDir specifies if it is necessary to 
758   show additional quick directories list controls in the bottom part
759   of the dialog box.
760
761   The validation of the user selection is done with help of the file 
762   validator (SUIT_FileValidator class). The last parameter \a validator
763   can be used to pass the custom file validator to the dialog box.
764   
765   \param parent parent widget
766   \param initial initial file (or directory) dialog box to be opened on
767   \param filters file filters list
768   \param caption dialog box title
769   \param open if \c true dialog box is used for file opening, otherwise - for saving
770   \param showQuickDir if \c true the quick directory list widgets will be shown
771   \param validator custom file validator
772   \return selected file name or null string if dialog box is cancelled
773   \sa getOpenFileNames(), getExistingDirectory()
774 */
775 QString SUIT_FileDlg::getFileName( QWidget* parent, const QString& initial, 
776                                    const QStringList& filters, const QString& caption, 
777                                    const bool open, const bool showQuickDir,
778                                    SUIT_FileValidator* validator )
779 {            
780   SUIT_FileDlg fd( parent, open, showQuickDir, true );    
781
782   fd.setFileMode( open ? ExistingFile : AnyFile );
783
784   QString tmpfilename = initial;
785   tmpfilename = tmpfilename.simplified();
786   tmpfilename = tmpfilename.replace(QRegExp("\\*"), "" ).replace(QRegExp("\\?"), "" );
787
788   if ( filters.isEmpty() )
789     fd.setNameFilter( tr( "ALL_FILES_FILTER" ) ); // All files (*)
790   else
791     fd.setNameFilters( filters );
792
793   if ( !caption.isEmpty() )
794     fd.setWindowTitle( caption );
795
796   if ( !tmpfilename.isEmpty() )
797     fd.processPath( tmpfilename );
798
799   if ( validator )
800     fd.setValidator( validator );
801
802   QString filename;
803
804   if ( fd.exec() == QDialog::Accepted )
805     filename = fd.selectedFile();
806
807   QApplication::processEvents();
808
809   return filename;
810 }
811
812 /*!
813   \brief Show dialog box for the file opening/saving.
814   \overload
815
816   This method can be used to select the file for opening
817   or saving. The behavior is defined by the \a open parameter.
818   Note, that selection validation depends on the dialog mode used.
819
820   If \a initial parameter is not null string it is used as starting directory
821   or file at which dialog box is opened.
822   
823   The parameter \a filters defines file filters (wildcards) to be used.
824   This is the list of wildcards, separated by the ";;" symbols.
825   If filters list is empty, "All files (*)" is used by default.
826   
827   The parameter \a caption is used as dialog box title. If it is
828   is empty, the default title is used.
829   
830   The parameter \a showQuickDir specifies if it is necessary to 
831   show additional quick directories list controls in the bottom part
832   of the dialog box.
833
834   The validation of the user selection is done with help of the file 
835   validator (SUIT_FileValidator class). The last parameter \a validator
836   can be used to pass the custom file validator to the dialog box.
837   
838   \param parent parent widget
839   \param initial initial file (or directory) dialog box to be opened on
840   \param filters file filters separated by ";;"
841   \param caption dialog box title
842   \param open if \c true dialog box is used for file opening, otherwise - for saving
843   \param showQuickDir if \c true the quick directory list widgets will be shown
844   \param validator custom file validator
845   \return selected file name or null string if dialog box is cancelled
846   \sa getOpenFileNames(), getExistingDirectory()
847 */
848 QString SUIT_FileDlg::getFileName( QWidget* parent, const QString& initial, 
849                                    const QString& filters, const QString& caption, 
850                                    const bool open, const bool showQuickDir,
851                                    SUIT_FileValidator* validator )
852 {
853   return getFileName( parent, initial, filters.split( ";;", QString::SkipEmptyParts ), 
854                       caption, open, showQuickDir, validator );
855 }
856
857 /*!
858   \brief Show dialog box for the multiple files selection.
859
860   If \a initial parameter is not null string it is used as starting directory
861   or file at which dialog box is opened.
862   
863   The parameter \a filters defines file filters (wildcards) to be used.
864   If filters list is empty, "All files (*)" is used by default.
865   
866   The parameter \a caption is used as dialog box title. If it is
867   is empty, the default title is used.
868   
869   The parameter \a showQuickDir specifies if it is necessary to 
870   show additional quick directories list controls in the bottom part
871   of the dialog box.
872
873   The validation of the user selection is done with help of the file 
874   validator (SUIT_FileValidator class). The last parameter \a validator
875   can be used to pass the custom file validator to the dialog box.
876   
877   \param parent parent widget
878   \param initial initial file (or directory) dialog box to be opened on
879   \param filters file filters list
880   \param caption dialog box title
881   \param showQuickDir if \c true the quick directory list widgets will be shown
882   \param validator custom file validator
883   \return selected file names or empty list if dialog box is cancelled
884   \sa getFileName(), getExistingDirectory()
885 */
886 QStringList SUIT_FileDlg::getOpenFileNames( QWidget* parent, const QString& initial,
887                                             const QStringList& filters, const QString& caption,
888                                             const bool showQuickDir, 
889                                             SUIT_FileValidator* validator )
890 {            
891   SUIT_FileDlg fd( parent, true, showQuickDir, true );
892
893   fd.setFileMode( ExistingFiles );
894
895   if ( filters.isEmpty() )
896     fd.setNameFilter( tr( "ALL_FILES_FILTER" ) ); // All files (*)
897   else
898     fd.setNameFilters( filters );
899
900   if ( !caption.isEmpty() )
901     fd.setWindowTitle( caption );
902
903   if ( !initial.isEmpty() )
904     fd.processPath( initial );
905
906   if ( validator )
907     fd.setValidator( validator );
908
909   QStringList filenames;
910
911   if ( fd.exec() == QDialog::Accepted )
912     filenames = fd.selectedFiles();
913
914   QApplication::processEvents();
915
916   return filenames;
917 }
918
919 /*!
920   \brief Show dialog box for the multiple file opening.
921   \overload
922
923   If \a initial parameter is not null string it is used as starting directory
924   or file at which dialog box is opened.
925   
926   The parameter \a filters defines file filters (wildcards) to be used.
927   This is the list of wildcards, separated by the ";;" symbols.
928   If filters list is empty, "All files (*)" is used by default.
929   
930   The parameter \a caption is used as dialog box title. If it is
931   is empty, the default title is used.
932   
933   The parameter \a showQuickDir specifies if it is necessary to 
934   show additional quick directories list controls in the bottom part
935   of the dialog box.
936
937   The validation of the user selection is done with help of the file 
938   validator (SUIT_FileValidator class). The last parameter \a validator
939   can be used to pass the custom file validator to the dialog box.
940   
941   \param parent parent widget
942   \param initial initial file (or directory) dialog box to be opened on
943   \param filters file filters separated by ";;"
944   \param caption dialog box title
945   \param showQuickDir if \c true the quick directory list widgets will be shown
946   \param validator custom file validator
947   \return selected file names or empty list if dialog box is cancelled
948   \sa getFileName(), getExistingDirectory()
949 */
950 QStringList SUIT_FileDlg::getOpenFileNames( QWidget* parent, const QString& initial,
951                                             const QString& filters, const QString& caption,
952                                             const bool showQuickDir,
953                                             SUIT_FileValidator* validator )
954 {
955   return getOpenFileNames( parent, initial, filters.split( ";;", QString::SkipEmptyParts ), 
956                            caption, showQuickDir, validator );
957 }
958
959 /*!
960   \brief Show dialog box for the existing directory selection.
961
962   If \a initial parameter is not null string it is used as starting directory
963   at which dialog box is opened.
964   
965   The parameter \a caption is used as dialog box title. If it is
966   is empty, the default title is used.
967   
968   The parameter \a showQuickDir specifies if it is necessary to 
969   show additional quick directories list controls in the bottom part
970   of the dialog box.
971
972   The validation of the user selection is done with help of the file 
973   validator (SUIT_FileValidator class). The last parameter \a validator
974   can be used to pass the custom file validator to the dialog box.
975   
976   \param parent parent widget
977   \param initial initial directory dialog box to be opened on
978   \param caption dialog box title
979   \param showQuickDir if \c true the quick directory list widgets will be shown
980   \param validator custom file validator
981   \return selected directory name or null string if dialog box is cancelled
982   \sa getFileName(), getOpenFileNames()
983 */
984 QString SUIT_FileDlg::getExistingDirectory( QWidget* parent, const QString& initial,
985                                             const QString& caption, const bool showQuickDir,
986                                             SUIT_FileValidator* validator )
987 {
988   SUIT_FileDlg fd( parent, true, showQuickDir, true );
989
990   fd.setFileMode( DirectoryOnly );
991
992   if ( !caption.isEmpty() )
993     fd.setWindowTitle( caption );
994
995   if ( !initial.isEmpty() )
996     fd.processPath( initial );
997   
998   if ( validator )
999     fd.setValidator( validator );
1000
1001   QString dirname;
1002
1003   if ( fd.exec() == QDialog::Accepted )
1004     dirname = fd.selectedFile();
1005
1006   QApplication::processEvents();
1007
1008   return dirname;
1009 }
1010
1011 /*!
1012   \brief Get last visited path
1013   \return last visited path
1014 */
1015 QString SUIT_FileDlg::getLastVisitedPath()
1016 {
1017   return myLastVisitedPath;
1018 }
1019
1020 /*!
1021   \brief Selects current file
1022
1023   This version of selectFile() methods works similar to Qt version 3.x:
1024   it selects the given file as current and it changes the current file dialog's directory
1025   to the directory of the file
1026   
1027   \param f - new current file name 
1028 */
1029 void SUIT_FileDlg::selectFile( const QString& f )
1030 {
1031   QFileDialog::selectFile( QFileInfo( f ).baseName() );
1032   if ( !Qtx::dir( f, false ).isEmpty() )
1033     setDirectory( QFileInfo( f ).absolutePath() );
1034 }