Back to index

salome-gui  6.5.0
QtxPathDialog.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File:      QtxPathDialog.cxx
00024 // Author:    Sergey TELKOV
00025 //
00026 #include "QtxPathDialog.h"
00027 
00028 #include "QtxGridBox.h"
00029 #include "QtxGroupBox.h"
00030 
00031 #include <QDir>
00032 #include <QLabel>
00033 #include <QPixmap>
00034 #include <QLayout>
00035 #include <QLineEdit>
00036 #include <QObjectList>
00037 #include <QStringList>
00038 #include <QFileDialog>
00039 #include <QMessageBox>
00040 #include <QPushButton>
00041 
00042 static const char* open_icon[] = {
00043 "16 16 5 1",
00044 "  c none",
00045 ". c #ffff00",
00046 "# c #848200",
00047 "a c #ffffff",
00048 "b c #000000",
00049 "                ",
00050 "          bbb   ",
00051 "         b   b b",
00052 "              bb",
00053 "  bbb        bbb",
00054 " ba.abbbbbbb    ",
00055 " b.a.a.a.a.b    ",
00056 " ba.a.a.a.ab    ",
00057 " b.a.abbbbbbbbbb",
00058 " ba.ab#########b",
00059 " b.ab#########b ",
00060 " bab#########b  ",
00061 " bb#########b   ",
00062 " bbbbbbbbbbb    ",
00063 "                ",
00064 "                "
00065 };
00066 
00093 QtxPathDialog::QtxPathDialog( const bool import, QWidget* parent, const bool modal,
00094                               const bool resize, const int buttons, Qt::WindowFlags f )
00095 : QtxDialog( parent, modal, resize, buttons, f ),
00096   myDefault( -1 ),
00097   myEntriesFrame( 0 ),
00098   myOptionsFrame( 0 )
00099 {
00100   initialize();
00101   
00102   setWindowTitle( tr( import ? "Open file" : "Save file" ) );
00103   
00104   setDefaultEntry( createFileEntry( tr( "File name" ), import ? OpenFile : SaveFile ) );
00105   QLineEdit* le = fileEntry( defaultEntry() );
00106   if ( le )
00107     le->setMinimumWidth( 200 );
00108   
00109   validate();
00110 
00111   setFocusProxy( le );
00112 
00113   updateVisibility();
00114 }
00115 
00124 QtxPathDialog::QtxPathDialog( QWidget* parent, const bool modal,
00125                               const bool resize, const int buttons, Qt::WindowFlags f )
00126 : QtxDialog( parent, modal, resize, buttons, f ),
00127   myDefault( -1 ),
00128   myEntriesFrame( 0 ),
00129   myOptionsFrame( 0 )
00130 {
00131   initialize();
00132 
00133   updateVisibility();
00134 }
00135 
00139 QtxPathDialog::~QtxPathDialog()
00140 {
00141 }
00142 
00147 QString QtxPathDialog::fileName() const
00148 {
00149   return fileName( defaultEntry() );
00150 }
00151 
00157 void QtxPathDialog::setFileName( const QString& txt, const bool autoExtension )
00158 {
00159   setFileName( defaultEntry(), txt, autoExtension );
00160 }
00161 
00166 QString QtxPathDialog::filter() const
00167 {
00168   return filter( defaultEntry() );
00169 }
00170 
00179 void QtxPathDialog::setFilter( const QString& fltr )
00180 {
00181   setFilter( defaultEntry(), fltr );
00182 }
00183 
00188 void QtxPathDialog::setVisible( bool on )
00189 {
00190   if ( on )
00191     updateVisibility();
00192 
00193   QtxDialog::setVisible( on );
00194 }
00195 
00200 void QtxPathDialog::onBrowse()
00201 {
00202   const QObject* obj = sender();
00203 
00204   int id = -1;
00205   
00206   for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
00207   {
00208     if ( it.value().btn == obj )
00209       id = it.key();
00210   }
00211   
00212   if ( id == -1 )
00213     return;
00214   
00215   FileEntry& entry = myEntries[id];
00216   
00217   bool isDir = entry.mode != OpenFile && entry.mode != SaveFile;
00218   
00219   if ( !entry.dlg )
00220   {
00221     entry.dlg = new QFileDialog( this, windowTitle(), QDir::current().path() );
00222     switch ( entry.mode )
00223     {
00224     case NewDir:
00225     case OpenDir:
00226     case SaveDir:
00227       isDir = true;
00228       entry.dlg->setFileMode( QFileDialog::DirectoryOnly );
00229       break;
00230     case SaveFile:
00231       entry.dlg->setFileMode( QFileDialog::AnyFile );
00232       break;
00233     case OpenFile:
00234     default:
00235       entry.dlg->setFileMode( QFileDialog::ExistingFiles );
00236       break;
00237     }
00238   }
00239   
00240   if ( !isDir )
00241   {
00242     QStringList fList = prepareFilters( entry.filter );
00243     if ( !fList.isEmpty() )
00244       entry.dlg->setFilters( fList );
00245   }
00246   entry.dlg->selectFile( fileName( id ) );
00247 
00248   if ( entry.dlg->exec() != Accepted )
00249     return;
00250   
00251   QStringList fileList = entry.dlg->selectedFiles();
00252   QString fName = !fileList.isEmpty() ? fileList.first() : QString();
00253   
00254   if ( fName.isEmpty() )
00255     return;
00256   
00257   if ( Qtx::extension( fName ).isEmpty() && !isDir )
00258     fName = autoExtension( fName, entry.dlg->selectedFilter() );
00259 
00260   fName = QDir::convertSeparators( fName );
00261   QString prev = QDir::convertSeparators( fileName( id ) );
00262   if ( isDir )
00263   {
00264     while ( prev.length() && prev.at( prev.length() - 1 ) == QDir::separator() )
00265       prev.remove( prev.length() - 1, 1 );
00266     while ( fName.length() && fName.at( fName.length() - 1 ) == QDir::separator() )
00267       fName.remove( fName.length() - 1, 1 );
00268   }
00269   
00270   if ( prev == fName )
00271     return;
00272   
00273   setFileName( id, fName );
00274   fileNameChanged( id, fName );
00275   
00276   if ( id == defaultEntry() )
00277     emit fileNameChanged( fName );
00278 }
00279 
00283 void QtxPathDialog::onReturnPressed()
00284 {
00285   const QObject* obj = sender();
00286   
00287   int id = -1;
00288   for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && id == -1; ++it )
00289   {
00290     if ( it.value().edit == obj )
00291       id = it.key();
00292   }
00293 
00294   if ( id == -1 )
00295     return;
00296   
00297   fileNameChanged( id, fileName( id ) );
00298   
00299   if ( id == defaultEntry() )
00300     emit fileNameChanged( fileName() );
00301 }
00302 
00307 void QtxPathDialog::onTextChanged( const QString& /*txt*/ )
00308 {
00309   validate();
00310 }
00311 
00316 void QtxPathDialog::validate()
00317 {
00318   setButtonEnabled( isValid(), OK | Yes );
00319 }
00320 
00325 bool QtxPathDialog::isValid()
00326 {
00327   bool ok = true;
00328   for ( FileEntryMap::Iterator it = myEntries.begin(); it != myEntries.end() && ok; ++it )
00329   {
00330     if ( it.value().edit->isEnabled() )
00331       ok = !it.value().edit->text().trimmed().isEmpty();
00332   }
00333   
00334   return ok;
00335 }
00336 
00341 bool QtxPathDialog::acceptData() const
00342 {
00343   bool ok = true;
00344         
00345   QWidget* parent = (QWidget*)this;
00346 
00347   FileEntryMap::ConstIterator it;
00348   for ( it = myEntries.begin(); it != myEntries.end() && ok; ++it )
00349   {
00350     const FileEntry& entry = it.value();
00351     QFileInfo fileInfo( entry.edit->text() );
00352     if ( entry.edit->text().isEmpty() )
00353     {
00354       QMessageBox::critical( parent, windowTitle(), tr( "File name not specified" ),
00355                              QMessageBox::Ok, QMessageBox::NoButton );
00356       ok = false;
00357     }
00358     else switch ( entry.mode )
00359     {
00360     case OpenFile:
00361       if ( !fileInfo.exists() )
00362       {
00363         QMessageBox::critical( parent, windowTitle(), tr( "File \"%1\" does not exist" ).arg( fileInfo.filePath() ),
00364                                QMessageBox::Ok, QMessageBox::NoButton );
00365         ok = false;
00366       }
00367       break;
00368     case SaveFile:
00369       if ( fileInfo.exists() )
00370         ok = QMessageBox::warning( parent, windowTitle(), tr( "File \"%1\" already exist. Do you want to overwrite it?" ).arg( fileInfo.filePath() ),
00371                                    QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
00372       break;
00373     case OpenDir:
00374       if ( !fileInfo.exists() || !fileInfo.isDir() )
00375       {
00376         QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" does not exist" ).arg( fileInfo.filePath() ),
00377                                QMessageBox::Ok, QMessageBox::NoButton );
00378         ok = false;
00379       }
00380       break;
00381     case SaveDir:
00382       if ( fileInfo.exists() && !fileInfo.isDir() )
00383       {
00384         QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
00385                                QMessageBox::Ok, QMessageBox::NoButton );
00386         ok = false;
00387       }
00388       break;
00389     case NewDir:
00390       if ( fileInfo.exists() )
00391       {
00392         if ( !fileInfo.isDir() )
00393         {
00394           QMessageBox::critical( parent, windowTitle(), tr( "Directory \"%1\" can't be created because file with the same name exist" ).arg( fileInfo.filePath() ),
00395                                  QMessageBox::Ok, QMessageBox::NoButton );
00396           ok = false;
00397         }
00398         else if ( QDir( fileInfo.filePath() ).count() > 2 )
00399           ok = QMessageBox::warning( parent, windowTitle(), tr( "Directory \"%1\" not empty. Do you want to remove all files in this directory?" ).arg( fileInfo.filePath() ),
00400                                      QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
00401       }
00402       break;
00403     default:
00404       break;
00405     }
00406     
00407     if ( !ok )
00408       entry.edit->setFocus();
00409   }
00410   
00411   return ok;
00412 }
00413 
00423 void QtxPathDialog::fileNameChanged( int /*id*/, QString /*fileName*/ )
00424 {
00425 }
00426 
00437 QFrame* QtxPathDialog::optionsFrame()
00438 {
00439   return myOptionsFrame;
00440 }
00441 
00447 QString QtxPathDialog::fileName( const int id ) const
00448 {
00449   QString res;
00450   if ( myEntries.contains( id ) )
00451     res = myEntries[id].edit->text();
00452   return res;
00453 }
00454 
00461 void QtxPathDialog::setFileName( const int id, const QString& txt, const bool autoExt )
00462 {
00463   int mode;
00464   QLineEdit* le = fileEntry( id, mode );
00465         
00466   if ( le )
00467   {
00468     if ( autoExt && ( mode == OpenFile || mode == SaveFile ) )
00469       le->setText( autoExtension( txt, filter( id ) ) );
00470     else
00471       le->setText( txt );
00472   }
00473 }
00474 
00480 QString QtxPathDialog::filter( const int id ) const
00481 {
00482   QString res;
00483   if ( myEntries.contains( id ) )
00484     res = myEntries[id].filter;
00485   return res;
00486 }
00487 
00493 void QtxPathDialog::setFilter( const int id, const QString& filter )
00494 {
00495   if ( myEntries.contains( id ) )
00496     myEntries[id].filter = filter;
00497 }
00498 
00504 QLineEdit* QtxPathDialog::fileEntry( const int id ) const
00505 {
00506   QLineEdit* le = 0;
00507   if ( myEntries.contains( id ) )
00508     le = myEntries[id].edit;
00509   
00510   return le;
00511 }
00512 
00519 QLineEdit* QtxPathDialog::fileEntry( const int theId, int& theMode ) const
00520 {
00521   QLineEdit* le = 0;
00522   if ( myEntries.contains( theId ) )
00523   {
00524     le = myEntries[theId].edit;
00525     theMode = myEntries[theId].mode;
00526   }
00527   
00528   return le;
00529 }
00530 
00542 int QtxPathDialog::createFileEntry( const QString& lab, const int mode, 
00543                                                             const QString& filter, const int id )
00544 {
00545   int num = id;
00546   if ( num == -1 )
00547   {
00548     num--;
00549     while ( myEntries.contains( num ) )
00550       num--;
00551   }
00552   
00553   FileEntry entry;
00554   entry.dlg = 0;
00555   entry.mode = mode;
00556   entry.filter = filter;
00557   
00558   new QLabel( lab, myEntriesFrame );
00559   entry.edit = new QLineEdit( myEntriesFrame );
00560 
00561   entry.btn = new QPushButton( myEntriesFrame );
00562   entry.btn->setAutoDefault( false );
00563   entry.btn->setIcon( QPixmap( open_icon ) );
00564 
00565   Qtx::PathType type = Qtx::PT_OpenFile;
00566   switch ( mode )
00567   {
00568   case OpenFile:
00569     type = Qtx::PT_OpenFile;
00570     break;
00571   case SaveFile:
00572     type = Qtx::PT_SaveFile;
00573     break;
00574   case OpenDir:
00575   case SaveDir:
00576   case NewDir:
00577     type = Qtx::PT_Directory;
00578     break;
00579   }
00580   entry.edit->setCompleter( Qtx::pathCompleter( type, filter ) );
00581 
00582   connect( entry.btn, SIGNAL( clicked() ), this, SLOT( onBrowse() ) );
00583   connect( entry.edit, SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) );
00584   connect( entry.edit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) );
00585   
00586   myEntries.insert( num, entry );
00587   
00588   return num;
00589 }
00590 
00595 int QtxPathDialog::defaultEntry() const
00596 {
00597   return myDefault;
00598 }
00599 
00604 void QtxPathDialog::setDefaultEntry( const int id )
00605 {
00606   myDefault = id;
00607 }
00608 
00612 void QtxPathDialog::initialize()
00613 {
00614   setWindowTitle( tr( "File dialog" ) );
00615 
00616   QVBoxLayout* main = new QVBoxLayout( mainFrame() );
00617   main->setMargin( 0 );
00618 
00619   QtxGroupBox* base = new QtxGroupBox( "", mainFrame() );
00620   main->addWidget( base );
00621   
00622   QtxGridBox*  mainGroup = new QtxGridBox( 1, Qt::Horizontal, base, 0 );
00623   base->setWidget( mainGroup );
00624   
00625   myEntriesFrame = new QtxGridBox( 3, Qt::Horizontal, mainGroup );
00626   myOptionsFrame = new QFrame( mainGroup );
00627 }
00628 
00634 QStringList QtxPathDialog::prepareFilters( const QString& filter ) const
00635 {
00636   QStringList res;
00637   bool allFilter = false;
00638   if ( !filter.isEmpty() )
00639   {
00640     res = filter.split( ";;" );
00641     for ( QStringList::ConstIterator it = res.begin(); it != res.end() && !allFilter; ++it )
00642     {
00643       QStringList wildCards = filterWildCards( *it );
00644       allFilter = wildCards.indexOf( "*.*" ) != -1;
00645     }
00646   }
00647   
00648   if ( !allFilter )
00649     res.append( tr( "All files (*.*)" ) );
00650   
00651   return res;
00652 }
00653 
00659 QStringList QtxPathDialog::filterWildCards( const QString& theFilter ) const
00660 {
00661   QStringList res;
00662 
00663   int b = theFilter.lastIndexOf( "(" );
00664   int e = theFilter.lastIndexOf( ")" );
00665   if ( b != -1 && e != -1 )
00666   {
00667     QString content = theFilter.mid( b + 1, e - b - 1 ).trimmed();
00668     QStringList lst = content.split( " " );
00669     for ( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it )
00670     {
00671       if ( (*it).indexOf( "." ) != -1 )
00672         res.append( (*it).trimmed() );
00673     }
00674   }
00675   return res;
00676 }
00677 
00684 QString QtxPathDialog::autoExtension( const QString& theFileName, const QString& theFilter ) const
00685 {
00686   QString fName = theFileName;
00687 
00688   if ( fName.isEmpty() )
00689     return fName;
00690   
00691   QString filter;
00692   QStringList filters = prepareFilters( theFilter );
00693   if ( !filters.isEmpty() )
00694     filter = filters.first();
00695 
00696   QStringList wildCards = filterWildCards( filter );
00697   if ( !wildCards.isEmpty() )
00698   {
00699     QString ext = wildCards.first();
00700     if ( ext.indexOf( "." ) != -1 )
00701       ext = ext.mid( ext.indexOf( "." ) + 1 );
00702     
00703     if ( !ext.isEmpty() && !ext.contains( "*" ) )
00704       fName = QDir::convertSeparators( fName ) + QString( "." ) + ext;
00705   }
00706   
00707   return fName;
00708 }
00709 
00715 bool QtxPathDialog::hasVisibleChildren( QWidget* wid ) const
00716 {
00717   bool res = false;
00718   if ( wid )
00719   {
00720     const QObjectList& aChildren = wid->children();
00721     for ( QObjectList::const_iterator it = aChildren.begin(); it != aChildren.end() && !res; ++it )
00722     {
00723       if ( (*it)->isWidgetType() )
00724         res = ((QWidget*)(*it))->isVisibleTo( wid );
00725     }
00726   }
00727   return res;
00728 }
00729 
00733 void QtxPathDialog::updateVisibility()
00734 {
00735   if ( hasVisibleChildren( myEntriesFrame ) )
00736     myEntriesFrame->show();
00737   else
00738     myEntriesFrame->hide();
00739   
00740   if ( hasVisibleChildren( myOptionsFrame ) )
00741     myOptionsFrame->show();
00742   else
00743     myOptionsFrame->hide();
00744 }