From 162fc2a41225bd9c090b883664df86294407f860 Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 16 Jun 2005 12:15:09 +0000 Subject: [PATCH] Implement File Open/Save dialog with "Quick Directory" list controls. --- src/STD/STD_Application.cxx | 110 ++++++------ src/STD/STD_Application.h | 2 + src/SUIT/SUIT_FileDlg.cxx | 214 +++++++++++++++--------- src/SUIT/SUIT_FileDlg.h | 18 +- src/SUIT/SUIT_FileValidator.cxx | 2 +- src/SUIT/SUIT_FileValidator.h | 2 + src/SUIT/resources/SUIT_msg_en.po | 43 +++++ src/SalomeApp/SalomeApp_Application.cxx | 10 +- src/SalomeApp/SalomeApp_Application.h | 2 + 9 files changed, 275 insertions(+), 128 deletions(-) diff --git a/src/STD/STD_Application.cxx b/src/STD/STD_Application.cxx index 73bd2eff8..3ad2b67fa 100755 --- a/src/STD/STD_Application.cxx +++ b/src/STD/STD_Application.cxx @@ -225,7 +225,7 @@ void STD_Application::onNewDoc() void STD_Application::onOpenDoc() { // It is preferrable to use OS-specific file dialog box here !!! - QString aName = QFileDialog::getOpenFileName( QString::null, getFileFilter(), desktop() ); + QString aName = getFileName( true ); if ( aName.isNull() ) return; @@ -364,59 +364,16 @@ bool STD_Application::onSaveAsDoc() if ( !study ) return false; - QString aName; - QString aUsedFilter; - QString anOldPath = study->studyName(); - - bool isOk = false; - while ( !isOk ) - { - // It is preferrable to use OS-specific file dialog box here !!! - aName = QFileDialog::getSaveFileName( anOldPath, getFileFilter(), desktop(), - 0, QString::null, &aUsedFilter); - - if ( aName.isNull() ) - isOk = true; - else - { - if ( !getFileFilter().isNull() ) // check exstension and add if it is necessary - { - int aStart = aUsedFilter.find( '*' ); - int aEnd = aUsedFilter.find( ')', aStart + 1 ); - QString aExt = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 ); - if ( aExt.contains( '*' ) == 0 ) // if it is not *.* - { - // Check that there is an extension at the end of the name - QString aNameTail = aName.right( aExt.length() ); - if ( aNameTail != aExt ) - aName += aExt; - } - } - if ( QFileInfo( aName ).exists() ) - { - int aAnswer = SUIT_MessageBox::warn2( desktop(), tr( "TIT_FILE_SAVEAS" ), - tr( "MSG_FILE_EXISTS" ).arg( aName ), - tr( "BUT_YES" ), tr( "BUT_NO" ), 1, 2, 2 ); - if ( aAnswer != 2 ) - isOk = true; - else - anOldPath = aName; // Not to return to the same initial dir at each "while" step - } - else - isOk = true; - - if ( isOk ) - isOk = study->saveDocumentAs( aName ); - } - } + QString aName = getFileName( false ); if ( aName.isNull() ) return false; + bool isOk = study->saveDocumentAs( aName ); updateDesktopTitle(); updateCommandsStatus(); - return true; + return isOk; } void STD_Application::onExit() @@ -632,3 +589,62 @@ void STD_Application::onConnectPopupRequest( SUIT_PopupClient* client, QContextM popup->exec( e->globalPos() ); delete popup; } + +QString STD_Application::getFileName( bool open ) +{ + if ( open ) + { + return QFileDialog::getOpenFileName( QString::null, getFileFilter(), desktop() ); + } + else + { + SUIT_Study* study = activeStudy(); + QString aName; + QString aUsedFilter; + QString anOldPath = study->studyName(); + + bool isOk = false; + while ( !isOk ) + { + // It is preferrable to use OS-specific file dialog box here !!! + aName = QFileDialog::getSaveFileName( anOldPath, getFileFilter(), desktop(), + 0, QString::null, &aUsedFilter); + + if ( aName.isNull() ) + isOk = true; + else + { + if ( !getFileFilter().isNull() ) // check extension and add if it is necessary + { + int aStart = aUsedFilter.find( '*' ); + int aEnd = aUsedFilter.find( ')', aStart + 1 ); + QString aExt = aUsedFilter.mid( aStart + 1, aEnd - aStart - 1 ); + if ( aExt.contains( '*' ) == 0 ) // if it is not *.* + { + // Check that there is an extension at the end of the name + QString aNameTail = aName.right( aExt.length() ); + if ( aNameTail != aExt ) + aName += aExt; + } + } + if ( QFileInfo( aName ).exists() ) + { + int aAnswer = SUIT_MessageBox::warn3( desktop(), tr( "TIT_FILE_SAVEAS" ), + tr( "MSG_FILE_EXISTS" ).arg( aName ), + tr( "BUT_YES" ), tr( "BUT_NO" ), tr( "BUT_CANCEL" ), 1, 2, 3, 1 ); + if ( aAnswer == 3 ) { // cancelled + aName = QString::null; + isOk = true; + } + else if ( aAnswer == 2 ) // not save to this file + anOldPath = aName; // not to return to the same initial dir at each "while" step + else // overwrite the existing file + isOk = true; + } + else + isOk = true; + } + } + return aName; + } +} diff --git a/src/STD/STD_Application.h b/src/STD/STD_Application.h index 886761ad7..bb8c25a02 100755 --- a/src/STD/STD_Application.h +++ b/src/STD/STD_Application.h @@ -99,6 +99,8 @@ protected: virtual void setActiveViewManager( SUIT_ViewManager* ); + virtual QString getFileName( bool ); + private: ViewManagerList myViewMgrs; SUIT_ViewManager* myActiveViewMgr; diff --git a/src/SUIT/SUIT_FileDlg.cxx b/src/SUIT/SUIT_FileDlg.cxx index ed53aad95..0c6b5df36 100755 --- a/src/SUIT/SUIT_FileDlg.cxx +++ b/src/SUIT/SUIT_FileDlg.cxx @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,71 +26,80 @@ Constructor SUIT_FileDlg::SUIT_FileDlg( QWidget* parent, bool open, bool showQuickDir, bool modal ) : QFileDialog( parent, 0, modal ), myValidator( 0 ), -myQuickCombo( 0 ), +myQuickCombo( 0 ), myQuickButton( 0 ), myQuickLab( 0 ), myOpen( open ) { if ( parent->icon() ) setIcon( *parent->icon() ); setSizeGripEnabled( true ); - if (showQuickDir) { + if ( showQuickDir ) { // inserting quick dir combo box - QLabel* lab = new QLabel(tr("Quick path:"), this); + myQuickLab = new QLabel(tr("LAB_QUICK_PATH"), this); myQuickCombo = new QComboBox(false, this); myQuickCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); myQuickCombo->setMinimumSize(MIN_COMBO_SIZE, 0); - // the following is a workaround for proper layouting of custom widgets =========== - QPushButton* btn = new QPushButton(this); - btn->setEnabled(false); - QPalette pal = btn->palette(); - QColorGroup ca = pal.active(); - ca.setColor(QColorGroup::Light, palette().active().background()); - ca.setColor(QColorGroup::Midlight, palette().active().background()); - ca.setColor(QColorGroup::Dark, palette().active().background()); - ca.setColor(QColorGroup::Mid, palette().active().background()); - ca.setColor(QColorGroup::Shadow, palette().active().background()); - QColorGroup ci = pal.inactive(); - ci.setColor(QColorGroup::Light, palette().inactive().background()); - ci.setColor(QColorGroup::Midlight, palette().inactive().background()); - ci.setColor(QColorGroup::Dark, palette().inactive().background()); - ci.setColor(QColorGroup::Mid, palette().inactive().background()); - ci.setColor(QColorGroup::Shadow, palette().inactive().background()); - QColorGroup cd = pal.disabled(); - cd.setColor(QColorGroup::Light, palette().disabled().background()); - cd.setColor(QColorGroup::Midlight, palette().disabled().background()); - cd.setColor(QColorGroup::Dark, palette().disabled().background()); - cd.setColor(QColorGroup::Mid, palette().disabled().background()); - cd.setColor(QColorGroup::Shadow, palette().disabled().background()); - pal.setActive(ca); pal.setInactive(ci); pal.setDisabled(cd); - btn->setPalette(pal); - // ================================================================================ + myQuickButton = new QPushButton(tr("BUT_ADD_PATH"), this); - connect(myQuickCombo, SIGNAL(activated(const QString&)), this, SLOT(quickDir(const QString&))); - addWidgets(lab, myQuickCombo, btn); + connect(myQuickCombo, SIGNAL(activated(const QString&)), this, SLOT(quickDir(const QString&))); + connect(myQuickButton, SIGNAL(clicked()), this, SLOT(addQuickDir())); + addWidgets(myQuickLab, myQuickCombo, myQuickButton); // getting dir list from settings QString dirs; SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); if ( resMgr ) - dirs = resMgr->stringValue( "FileDlg", "QuickDirList" ); + dirs = resMgr->stringValue( "FileDlg", QString( "QuickDirList" ) ); QStringList dirList = QStringList::split(';', dirs, false); if (dirList.count() > 0) { for (unsigned i = 0; i < dirList.count(); i++) - myQuickCombo->insertItem(dirList[i]); + myQuickCombo->insertItem(dirList[i]); } else { myQuickCombo->insertItem(QDir::homeDirPath()); } + } + setMode( myOpen ? ExistingFile : AnyFile ); + setCaption( myOpen ? tr( "INF_DESK_DOC_OPEN" ) : tr( "INF_DESK_DOC_SAVE" ) ); + + // If last visited path doesn't exist -> switch to the first preferred path + if ( !myLastVisitedPath.isEmpty() ) { + if ( !processPath( myLastVisitedPath ) && showQuickDir ) + processPath( myQuickCombo->text( 0 ) ); + } + else { + if ( showQuickDir ) + processPath(myQuickCombo->text( 0 ) ); + } - // the following is a workaround for proper layouting of custom widgets =========== + // set default file validator + myValidator = new SUIT_FileValidator(this); +} + +/*! +Destructor +*/ +SUIT_FileDlg::~SUIT_FileDlg() +{ + setValidator( 0 ); +} + +/*! + Redefined from QFileDialog. +*/ +void SUIT_FileDlg::polish() +{ + QFileDialog::polish(); + if ( myQuickButton && myQuickLab ) { + // the following is a workaround for proper layouting of custom widgets QValueList buttonList; QValueList labelList; const QObjectList *list = children(); QObjectListIt it(*list); - int maxButWidth = lab->sizeHint().width(); - int maxLabWidth = btn->sizeHint().width(); + int maxButWidth = myQuickLab->sizeHint().width(); + int maxLabWidth = myQuickButton->sizeHint().width(); for (; it.current() ; ++it) { if ( it.current()->isA( "QLabel" ) ) { @@ -113,40 +123,16 @@ myOpen( open ) for ( lListIt = labelList.begin(); lListIt != labelList.end(); ++lListIt ) (*lListIt)->setFixedWidth( maxLabWidth ); } - // ================================================================================ } - setMode( myOpen ? ExistingFile : AnyFile ); - setCaption( myOpen ? tr( "INF_DESK_DOC_OPEN" ) : tr( "INF_DESK_DOC_SAVE" ) ); - - if (showQuickDir) { - if (myLastVisitedPath.isNull() || myLastVisitedPath.isEmpty()) { - // If no last visited path exists -> switch to the first preferred path - processPath(myQuickCombo->text(0)); - } - else if ( !processPath(myLastVisitedPath) ) { - // If last visited path doesn't exist -> switch to the first preferred path - processPath(myQuickCombo->text(0)); - } - } - - myValidator = new SUIT_FileValidator(this); - -} - -/*! -Destructor -*/ -SUIT_FileDlg::~SUIT_FileDlg() -{ } /*! Sets validator for file names to open/save -Deletes previous validator +Deletes previous validator if the dialog owns it. */ void SUIT_FileDlg::setValidator( SUIT_FileValidator* v ) { - if (myValidator) + if ( myValidator && myValidator->parent() == this ) delete myValidator; myValidator = v; } @@ -175,8 +161,10 @@ if the selected name is valid ( see 'acceptData()' ) void SUIT_FileDlg::accept() { // mySelectedFile = QFileDialog::selectedFile().simplifyWhiteSpace(); //VSR- 06/12/02 - mySelectedFile = QFileDialog::selectedFile(); //VSR+ 06/12/02 - addExtension(); + if ( mode() != ExistingFiles ) { + mySelectedFile = QFileDialog::selectedFile(); //VSR+ 06/12/02 + addExtension(); + } // mySelectedFile = mySelectedFile.simplifyWhiteSpace(); //VSR- 06/12/02 /* Qt 2.2.2 BUG: accept() is called twice if you validate @@ -209,7 +197,17 @@ bool SUIT_FileDlg::acceptData() if ( myValidator ) { if ( isOpenDlg() ) - return myValidator->canOpen( selectedFile() ); + if ( mode() == ExistingFiles ) { + QStringList fileNames = selectedFiles(); + for ( int i = 0; i < fileNames.count(); i++ ) { + if ( !myValidator->canOpen( fileNames[i] ) ) + return false; + } + return true; + } + else { + return myValidator->canOpen( selectedFile() ); + } else return myValidator->canSave( selectedFile() ); } @@ -264,7 +262,7 @@ void SUIT_FileDlg::addExtension() if ( anExtRExp.match(anExt) == -1 ) //if a selected file extension does not match to filter's list { //remove a point if it is at the word end - int aExtLen = anExt.length(); + int aExtLen = anExt.length(); if (anExt[ aExtLen - 1 ] == '.') anExt.truncate( aExtLen - 1 ); index = wildcard.findRev( '.' ); if ( index >= 0 ) @@ -291,6 +289,7 @@ bool SUIT_FileDlg::processPath( const QString& path ) else { if ( QFileInfo( fi.dirPath() ).exists() ) { setDir( fi.dirPath() ); + setSelection( path ); return true; } } @@ -313,17 +312,54 @@ void SUIT_FileDlg::quickDir(const QString& dirPath) processPath(dirPath); } } - +/*! + Called when user presses "Add" button - adds current directory to quick directory + list and to the preferences +*/ +void SUIT_FileDlg::addQuickDir() +{ + QString dp = dirPath(); + if ( !dp.isEmpty() ) { + QDir dir( dp ); + // getting dir list from settings + QString dirs; + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + if ( resMgr ) + dirs = resMgr->stringValue( "FileDlg", QString( "QuickDirList" ) ); + QStringList dirList = QStringList::split(';', dirs, false); + bool found = false; + bool emptyAndHome = false; + if ( dirList.count() > 0 ) { + for ( unsigned i = 0; i < dirList.count(); i++ ) { + QDir aDir( dirList[i] ); + if ( aDir.canonicalPath().isNull() && dirList[i] == dir.absPath() || + !aDir.canonicalPath().isNull() && aDir.exists() && aDir.canonicalPath() == dir.canonicalPath() ) { + found = true; + break; + } + } + } + else { + emptyAndHome = dir.canonicalPath() == QDir(QDir::homeDirPath()).canonicalPath(); + } + if ( !found ) { + dirList.append( dp ); + resMgr->setValue( "FileDlg", QString( "QuickDirList" ), dirList.join(";") ); + if ( !emptyAndHome ) + myQuickCombo->insertItem( dp ); + } + } +} /*! Returns the file name for Open/Save [ static ] */ -QString SUIT_FileDlg::getFileName( QWidget* parent, - const QString& initial, - const QStringList& filters, - const QString& caption, - bool open, - bool showQuickDir, - SUIT_FileValidator* validator ) +QString SUIT_FileDlg::getFileName( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption, + bool open, + bool showQuickDir, + SUIT_FileValidator* validator ) { SUIT_FileDlg* fd = new SUIT_FileDlg( parent, open, showQuickDir, true ); if ( !caption.isEmpty() ) @@ -341,10 +377,38 @@ QString SUIT_FileDlg::getFileName( QWidget* parent, return filename; } + +/*! + Returns the list of files to be opened [ static ] +*/ +QStringList SUIT_FileDlg::getOpenFileNames( QWidget* parent, + const QString& initial, + const QStringList& filters, + const QString& caption, + bool showQuickDir, + SUIT_FileValidator* validator ) +{ + SUIT_FileDlg* fd = new SUIT_FileDlg( parent, true, showQuickDir, true ); + fd->setMode( ExistingFiles ); + if ( !caption.isEmpty() ) + fd->setCaption( caption ); + if ( !initial.isEmpty() ) { + fd->processPath( initial ); // VSR 24/03/03 check for existing of directory has been added to avoid QFileDialog's bug + } + fd->setFilters( filters ); + if ( validator ) + fd->setValidator( validator ); + fd->exec(); + QStringList filenames = fd->selectedFiles(); + delete fd; + qApp->processEvents(); + return filenames; +} + /*! Existing directory selection dialog [ static ] */ -QString SUIT_FileDlg::getExistingDirectory ( QWidget* parent, +QString SUIT_FileDlg::getExistingDirectory( QWidget* parent, const QString& initial, const QString& caption, bool showQuickDir ) @@ -356,7 +420,7 @@ QString SUIT_FileDlg::getExistingDirectory ( QWidget* parent, fd->processPath( initial ); // VSR 24/03/03 check for existing of directory has been added to avoid QFileDialog's bug } fd->setMode( DirectoryOnly ); - fd->setFilters(tr("DIRECTORIES_FILTER")); + fd->setFilters(tr("INF_DIRECTORIES_FILTER")); fd->exec(); QString dirname = fd->selectedFile(); delete fd; diff --git a/src/SUIT/SUIT_FileDlg.h b/src/SUIT/SUIT_FileDlg.h index 3f6b96815..cd33167a7 100755 --- a/src/SUIT/SUIT_FileDlg.h +++ b/src/SUIT/SUIT_FileDlg.h @@ -3,10 +3,11 @@ #include "SUIT.h" -#include #include -class SUIT_ResourceMgr; +class QLabel; +class QComboBox; +class QPushButton; class SUIT_FileValidator; class SUIT_EXPORT SUIT_FileDlg : public QFileDialog @@ -24,10 +25,16 @@ public: void setValidator( SUIT_FileValidator* ); static QString getFileName( QWidget* parent, const QString& initial, const QStringList& filters, - const QString& caption, bool open, bool showQuickDir = true, + const QString& caption, const bool open, const bool showQuickDir = true, SUIT_FileValidator* validator = 0 ); + static QStringList getOpenFileNames( QWidget* parent, const QString& initial, const QStringList& filters, + const QString& caption, bool showQuickDir = true, + SUIT_FileValidator* validator = 0 ); static QString getExistingDirectory( QWidget* parent, const QString& initial, - const QString& caption, bool showQuickDir = true ); + const QString& caption, const bool showQuickDir = true ); + +public slots: + void polish(); private: bool acceptData(); @@ -38,12 +45,15 @@ protected slots: void accept(); void reject(); void quickDir( const QString& ); + void addQuickDir(); protected: bool myOpen; /* open/save selector */ QString mySelectedFile; /* selected filename */ SUIT_FileValidator* myValidator; /* file validator */ + QLabel* myQuickLab; /* quick dir combo box */ QComboBox* myQuickCombo; /* quick dir combo box */ + QPushButton* myQuickButton; /* quick dir add button */ static QString myLastVisitedPath; /* last visited path */ }; diff --git a/src/SUIT/SUIT_FileValidator.cxx b/src/SUIT/SUIT_FileValidator.cxx index 8a27a9d38..c10bfc2af 100755 --- a/src/SUIT/SUIT_FileValidator.cxx +++ b/src/SUIT/SUIT_FileValidator.cxx @@ -28,7 +28,7 @@ bool SUIT_FileValidator::canOpen( const QString& file ) if ( !QFile::exists( file ) ) { SUIT_MessageBox::error1( myParent, QObject::tr( "ERR_ERROR" ), - QObject::tr( "ERR_DOC_FILENOTEXIST" ).arg( file ), + QObject::tr( "ERR_FILE_NOT_EXIST" ).arg( file ), QObject::tr( "BUT_OK" ) ); return false; } diff --git a/src/SUIT/SUIT_FileValidator.h b/src/SUIT/SUIT_FileValidator.h index ebd0f8dcb..dfc96c88f 100755 --- a/src/SUIT/SUIT_FileValidator.h +++ b/src/SUIT/SUIT_FileValidator.h @@ -23,6 +23,8 @@ public: virtual bool canOpen( const QString& file ); virtual bool canSave( const QString& file ); + QWidget* parent() const { return myParent; } + private: QWidget* myParent; }; diff --git a/src/SUIT/resources/SUIT_msg_en.po b/src/SUIT/resources/SUIT_msg_en.po index 93e5da6f5..32d03cff3 100755 --- a/src/SUIT/resources/SUIT_msg_en.po +++ b/src/SUIT/resources/SUIT_msg_en.po @@ -32,3 +32,46 @@ msgstr "Arranges the windows as nonoverlapping vertical tiles" msgid "PRP_DESK_WINDOW_ACTIVATE" msgstr "Activates this window" + +msgid "LAB_QUICK_PATH" +msgstr "Quick path:" + +msgid "BUT_ADD_PATH" +msgstr "Add path" + +msgid "INF_DESK_DOC_OPEN" +msgstr "Open File" + +msgid "INF_DESK_DOC_SAVE" +msgstr "Save File" + +msgid "ERR_ERROR" +msgstr "Error" + +msgid "WRN_WARNING" +msgstr "Warning" + +msgid "ERR_DIR_NOT_EXIST" +msgstr "The directory \"%1\" does not exist!" + +msgid "ERR_FILE_NOT_EXIST" +msgstr "The file \"%1\" does not exist!" + +msgid "ERR_PERMISSION_DENIED" +msgstr "Can't save file \"%1\".\nPermission denied." + +msgid "BUT_OK" +msgstr "&OK" + +msgid "BUT_YES" +msgstr "&Yes" + +msgid "BUT_NO" +msgstr "&No" + +msgid "INF_DIRECTORIES_FILTER" +msgstr "Directories" + +msgid "QUE_FILE_EXISTS" +msgstr "The file \"%1\" already exists.\nDo you want to overwrite it?" + diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index 401317f2d..e069305cf 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -843,7 +843,7 @@ void SalomeApp_Application::onLoadScript( ) filtersList.append(tr("PYTHON_FILES_FILTER")); filtersList.append(tr("ALL_FILES_FILTER")); - QString aFile = SUIT_FileDlg::getFileName(desktop(), "", filtersList, tr("TOT_DESK_FILE_LOAD_SCRIPT"), true, false); + QString aFile = SUIT_FileDlg::getFileName(desktop(), "", filtersList, tr("TOT_DESK_FILE_LOAD_SCRIPT"), true, true ); if(!aFile.isEmpty()) { QString command = QString("execfile(\"%1\")").arg(aFile); @@ -1127,3 +1127,11 @@ void SalomeApp_Application::onProperties() //study->updateCaptions(); } + +QString SalomeApp_Application::getFileName( bool open ) +{ + QStringList filtersList; + filtersList.append( getFileFilter() ); + QString initial = open ? QString( "" ) : ( activeStudy() ? activeStudy()->studyName() : QString( "" ) ); + return SUIT_FileDlg::getFileName( desktop(), initial, filtersList, QString::null, open, true ); +} diff --git a/src/SalomeApp/SalomeApp_Application.h b/src/SalomeApp/SalomeApp_Application.h index e1d83d2b8..b6328e688 100644 --- a/src/SalomeApp/SalomeApp_Application.h +++ b/src/SalomeApp/SalomeApp_Application.h @@ -125,6 +125,8 @@ protected: virtual void beforeCloseDoc( SUIT_Study* ); virtual void afterCloseDoc(); + virtual QString getFileName( bool ); + private slots: void onNewWindow(); void onModuleActivation( QAction* ); -- 2.39.2