1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/
19 // File: QtxPathDialog.cxx
20 // Author: Sergey TELKOV
22 #include "QtxPathDialog.h"
24 #include "QtxGroupBox.h"
30 #include <qlineedit.h>
31 #include <qfileinfo.h>
32 #include <qobjectlist.h>
33 #include <qstringlist.h>
34 #include <qfiledialog.h>
35 #include <qmessagebox.h>
36 #include <qpushbutton.h>
38 static const char* open_icon[] = {
66 QtxPathDialog::QtxPathDialog( const bool import, QWidget* parent, const bool modal, const bool resize, const int buttons, WFlags f )
67 : QtxDialog( parent, 0, modal, resize, buttons, f ),
74 setCaption( tr( import ? "Open file" : "Save file" ) );
76 setDefaultEntry( createFileEntry( tr( "File name" ), import ? OpenFile : SaveFile ) );
77 QLineEdit* le = fileEntry( defaultEntry() );
79 le->setMinimumWidth( 200 );
89 QtxPathDialog::QtxPathDialog( QWidget* parent, const bool modal, const bool resize, const int buttons, WFlags f )
90 : QtxDialog( parent, 0, modal, resize, buttons, f ),
101 QtxPathDialog::~QtxPathDialog()
108 QString QtxPathDialog::fileName() const
110 return fileName( defaultEntry() );
115 \param txt - new file name
116 \param autoExtension - auto extension determination by file
118 void QtxPathDialog::setFileName( const QString& txt, const bool autoExtension )
120 setFileName( defaultEntry(), txt, autoExtension );
126 QString QtxPathDialog::filter() const
132 Changes filter (filter is a list of masks, separated by ';;')
133 \param fltr - new filter
135 void QtxPathDialog::setFilter( const QString& fltr )
143 void QtxPathDialog::show()
145 if ( hasVisibleChildren( myEntriesFrame ) )
146 myEntriesFrame->show();
148 myEntriesFrame->hide();
150 if ( hasVisibleChildren( myOptionsFrame ) )
151 myOptionsFrame->show();
153 myOptionsFrame->hide();
159 SLOT: called if user click button to show standard file dialog
161 void QtxPathDialog::onBrowse()
163 const QObject* obj = sender();
167 for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
168 if ( it.data().btn == obj )
174 FileEntry& entry = myEntries[id];
176 bool isDir = entry.mode != OpenFile && entry.mode != SaveFile;
180 entry.dlg = new QFileDialog( QDir::current().path(), QString::null, this, 0, true );
181 entry.dlg->setCaption( caption() );
182 switch ( entry.mode )
188 entry.dlg->setMode( QFileDialog::DirectoryOnly );
191 entry.dlg->setMode( QFileDialog::AnyFile );
195 entry.dlg->setMode( QFileDialog::ExistingFile );
201 entry.dlg->setFilters( prepareFilters() );
202 entry.dlg->setSelection( fileName( id ) );
204 if ( entry.dlg->exec() != Accepted )
207 QString fName = entry.dlg->selectedFile();
209 if ( fName.isEmpty() )
212 if ( QFileInfo( fName ).extension().isEmpty() && !isDir )
213 fName = autoExtension( fName, entry.dlg->selectedFilter() );
215 fName = QDir::convertSeparators( fName );
216 QString prev = QDir::convertSeparators( fileName( id ) );
219 while ( prev.length() && prev.at( prev.length() - 1 ) == QDir::separator() )
220 prev.remove( prev.length() - 1, 1 );
221 while ( fName.length() && fName.at( fName.length() - 1 ) == QDir::separator() )
222 fName.remove( fName.length() - 1, 1 );
228 setFileName( id, fName );
229 fileNameChanged( id, fName );
231 if ( id == defaultEntry() )
232 emit fileNameChanged( fName );
236 SLOT: called if user presses RETURN in line edit
238 void QtxPathDialog::onReturnPressed()
240 const QObject* obj = sender();
243 for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
244 if ( it.data().edit == obj )
250 fileNameChanged( id, fileName( id ) );
252 if ( id == defaultEntry() )
253 emit fileNameChanged( fileName() );
257 SLOT: called if text in line edit is changed
259 void QtxPathDialog::onTextChanged( const QString& )
265 Checks validity of text and according to it enables/disables OK, Yes buttons
267 void QtxPathDialog::validate()
269 setButtonEnabled( isValid(), OK | Yes );
273 \return true if selected file is valid
275 bool QtxPathDialog::isValid()
278 for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && ok; ++it )
279 if ( it.data().edit->isEnabled() )
280 ok = !it.data().edit->text().stripWhiteSpace().isEmpty();
286 \return true entered data is accepted
288 bool QtxPathDialog::acceptData() const
292 QWidget* parent = (QWidget*)this;
294 FileEntryMap::ConstIterator it;
295 for ( it = myEntries.begin(); it != myEntries.end() && ok; ++it )
297 const FileEntry& entry = it.data();
298 QFileInfo fileInfo( entry.edit->text() );
299 if ( entry.edit->text().isEmpty() )
301 QMessageBox::critical( parent, caption(), tr( "File name not specified" ),
302 QMessageBox::Ok, QMessageBox::NoButton );
305 else switch ( entry.mode )
308 if ( !fileInfo.exists() )
310 QMessageBox::critical( parent, caption(), tr( "File \"%1\" does not exist" ).arg( fileInfo.filePath() ),
311 QMessageBox::Ok, QMessageBox::NoButton );
316 if ( fileInfo.exists() )
317 ok = QMessageBox::warning( parent, caption(), tr( "File \"%1\" already exist. Do you want to overwrite it?" ).arg( fileInfo.filePath() ),
318 QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
321 if ( !fileInfo.exists() || !fileInfo.isDir() )
323 QMessageBox::critical( parent, caption(), tr( "Directory \"%1\" does not exist" ).arg( fileInfo.filePath() ),
324 QMessageBox::Ok, QMessageBox::NoButton );
329 if ( fileInfo.exists() && !fileInfo.isDir() )
331 QMessageBox::critical( parent, caption(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
332 QMessageBox::Ok, QMessageBox::NoButton );
337 if ( fileInfo.exists() )
339 if ( !fileInfo.isDir() )
341 QMessageBox::critical( parent, caption(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
342 QMessageBox::Ok, QMessageBox::NoButton );
345 else if ( QDir( fileInfo.filePath() ).count() > 2 )
346 ok = QMessageBox::warning( parent, caption(), tr( "Directory \"%1\" not empty. Do you want to remove all files in this directory?" ).arg( fileInfo.filePath() ),
347 QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
355 entry.edit->setFocus();
362 Some custom activity on file name changing (must be redefined, default implementation is empty
364 void QtxPathDialog::fileNameChanged( int, QString )
369 \return frame with options
371 QFrame* QtxPathDialog::optionsFrame()
373 return myOptionsFrame;
378 \param id - id of file entry
380 QString QtxPathDialog::fileName( const int id ) const
383 if ( myEntries.contains( id ) )
384 res = myEntries[id].edit->text();
390 Change file name of file entry
391 \param id - id of file entry
392 \param txt - new file name
393 \param autoExt - assign extension automatically
395 void QtxPathDialog::setFileName( const int id, const QString& txt, const bool autoExt )
398 QLineEdit* le = fileEntry( id, mode );
402 if ( autoExt && ( mode == OpenFile || mode == SaveFile ) )
403 le->setText( autoExtension( txt ) );
410 \return line edit of file entry
411 \param id - id of file entry
413 QLineEdit* QtxPathDialog::fileEntry( const int id ) const
416 if ( myEntries.contains( id ) )
417 le = myEntries[id].edit;
423 \return line edit and mode of file entry
424 \param id - id of file entry
425 \param theMode - for return mode of file entry
427 QLineEdit* QtxPathDialog::fileEntry( const int theId, int& theMode ) const
430 if ( myEntries.contains( theId ) )
432 le = myEntries[theId].edit;
433 theMode = myEntries[theId].mode;
441 \return id of just created file entry
442 \param lab - title of entry
443 \param mode - mode of entry
444 \param id - proposed id (if it is -1, then id will be chosen automatically)
446 int QtxPathDialog::createFileEntry( const QString& lab, const int mode, const int id )
452 while ( myEntries.contains( num ) )
460 new QLabel( lab, myEntriesFrame );
461 entry.edit = new QLineEdit( myEntriesFrame );
462 entry.btn = new QPushButton( myEntriesFrame );
463 entry.btn->setAutoDefault( false );
464 entry.btn->setPixmap( QPixmap( open_icon ) );
466 connect( entry.btn, SIGNAL( clicked() ), this, SLOT( onBrowse() ) );
467 connect( entry.edit, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) );
468 connect( entry.edit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
470 myEntries.insert( num, entry );
476 \return id of default entry
478 int QtxPathDialog::defaultEntry() const
484 Change default entry id
485 \param id - new default entry id
487 void QtxPathDialog::setDefaultEntry( const int id )
493 Initialize dialog layout
495 void QtxPathDialog::initialize()
497 setCaption( tr( "File dialog" ) );
499 QVBoxLayout* main = new QVBoxLayout( mainFrame() );
500 QtxGroupBox* mainGroup = new QtxGroupBox( 1, Qt::Horizontal, "", mainFrame() );
501 mainGroup->setFrameStyle( QFrame::NoFrame );
502 mainGroup->setInsideMargin( 0 );
503 main->addWidget( mainGroup );
505 myEntriesFrame = new QGroupBox( 3, Qt::Horizontal, "", mainGroup );
506 myOptionsFrame = new QFrame( mainGroup );
510 \return list of filters
512 QStringList QtxPathDialog::prepareFilters() const
515 if ( !myFilter.isEmpty() )
517 res = QStringList::split( ";;", myFilter );
518 bool allFilter = false;
519 for ( QStringList::ConstIterator it = res.begin(); it != res.end() && !allFilter; ++it )
521 QStringList wildCards = filterWildCards( *it );
522 allFilter = wildCards.findIndex( "*.*" ) != -1;
526 res.append( tr( "All files (*.*)" ) );
533 \return list of filters with filtered wild cards
535 QStringList QtxPathDialog::filterWildCards( const QString& theFilter ) const
539 int b = theFilter.findRev( "(" );
540 int e = theFilter.findRev( ")" );
541 if ( b != -1 && e != -1 )
543 QString content = theFilter.mid( b + 1, e - b - 1 ).stripWhiteSpace();
544 QStringList lst = QStringList::split( " ", content );
545 for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
546 if ( (*it).find( "." ) != -1 )
547 res.append( (*it).stripWhiteSpace() );
553 \return file name with assigned extension
554 \param theFileName - source file name
555 \param theFilter - list of filters
557 QString QtxPathDialog::autoExtension( const QString& theFileName, const QString& theFilter ) const
559 QString fName = theFileName;
561 if ( fName.isEmpty() )
564 QString filter = theFilter;
565 if ( filter.isEmpty() )
567 QStringList filters = prepareFilters();
568 if ( !filters.isEmpty() )
569 filter = filters.first();
572 QStringList wildCards = filterWildCards( filter );
573 if ( !wildCards.isEmpty() )
575 QString ext = wildCards.first();
576 if ( ext.find( "." ) != -1 )
577 ext = ext.mid( ext.find( "." ) + 1 );
579 if ( !ext.isEmpty() && !ext.contains( "*" ) )
580 fName = QDir::convertSeparators( fName ) + QString( "." ) + ext;
587 \return true if widget has visible children
590 bool QtxPathDialog::hasVisibleChildren( QWidget* wid ) const
595 const QObjectList* aChildren = wid->children();
598 for ( QObjectListIt it( *aChildren ); it.current() && !res; ++it )
600 if ( it.current()->isWidgetType() )
601 res = ((QWidget*)it.current())->isVisibleTo( wid );