From 0c777dd7d38a25b7a0e85f8e05c22502c5bd89d2 Mon Sep 17 00:00:00 2001 From: Larry Shaffer Date: Mon, 25 Feb 2013 20:34:22 -0700 Subject: [PATCH] Add unique title input dialog for new and duplicate composers - Allows user to title composer before creation (optionally based on existing composer titles) - Helps limit duplicate titles - Non-GUI generation of new and duplicate composers not restricted (unchanged) - Duplicate composer slot now free of GUI interruptions - Change from hiding of duplicate composer (during template loading) to pausing updates to give user feedback --- src/app/composer/qgscomposer.cpp | 7 +- src/app/composer/qgscomposermanager.cpp | 18 ++- src/app/qgisapp.cpp | 143 +++++++++++++++--------- src/app/qgisapp.h | 11 +- 4 files changed, 119 insertions(+), 60 deletions(-) diff --git a/src/app/composer/qgscomposer.cpp b/src/app/composer/qgscomposer.cpp index f8cd8a9122fd..3fef80ced558 100644 --- a/src/app/composer/qgscomposer.cpp +++ b/src/app/composer/qgscomposer.cpp @@ -1346,7 +1346,12 @@ void QgsComposer::on_mActionNewComposer_triggered() void QgsComposer::on_mActionDuplicateComposer_triggered() { - mQgis->duplicateComposer( this, this ); + QString newTitle = mQgis->uniqueComposerTitle( this, false, title() + tr( " copy" ) ); + if ( newTitle.isNull() ) + { + return; + } + mQgis->duplicateComposer( this, newTitle ); } void QgsComposer::on_mActionComposerManager_triggered() diff --git a/src/app/composer/qgscomposermanager.cpp b/src/app/composer/qgscomposermanager.cpp index 6fc5b24f72e0..19f28f959fb6 100644 --- a/src/app/composer/qgscomposermanager.cpp +++ b/src/app/composer/qgscomposermanager.cpp @@ -109,7 +109,13 @@ void QgsComposerManager::on_mAddButton_clicked() { QgsComposer* newComposer = 0; - newComposer = QgisApp::instance()->createNewComposer(); + QString title = QgisApp::instance()->uniqueComposerTitle( this, true ); + if ( title.isNull() ) + { + return; + } + + newComposer = QgisApp::instance()->createNewComposer( title ); if ( !newComposer ) { return; @@ -226,17 +232,25 @@ void QgsComposerManager::duplicate_clicked() } QgsComposer* currentComposer = 0; + QString currentTitle; QMap::iterator it = mItemComposerMap.find( item ); if ( it != mItemComposerMap.end() ) { currentComposer = it.value(); + currentTitle = it.value()->title(); } else { return; } - QgsComposer* newComposer = QgisApp::instance()->duplicateComposer( currentComposer, this ); + QString newTitle = QgisApp::instance()->uniqueComposerTitle( this, false, currentTitle + tr( " copy" ) ); + if ( newTitle.isNull() ) + { + return; + } + + QgsComposer* newComposer = QgisApp::instance()->duplicateComposer( currentComposer, newTitle ); if ( newComposer ) { diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 1fa4525c04be..53900a7e5dc8 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -3842,7 +3842,12 @@ void QgisApp::newPrintComposer() return; } - createNewComposer(); + QString title = uniqueComposerTitle( this, true ); + if ( title.isNull() ) + { + return; + } + createNewComposer( title ); } void QgisApp::showComposerManager() @@ -4604,12 +4609,79 @@ QgsGeometry* QgisApp::unionGeometries( const QgsVectorLayer* vl, QgsFeatureList& return unionGeom; } -QgsComposer* QgisApp::createNewComposer() +QString QgisApp::uniqueComposerTitle( QWidget* parent, bool acceptEmpty, const QString& currentName ) +{ + if ( !parent ) + { + parent = this; + } + bool ok = false; + bool titleValid = false; + QString newTitle = QString( currentName ); + QString chooseMsg = tr( "Create unique print composer title" ); + if ( acceptEmpty ) + { + chooseMsg += "\n" + tr( "(title generated if left empty)" ); + } + QString titleMsg = chooseMsg; + + QStringList cNames; + cNames << newTitle; + foreach ( QgsComposer* c, printComposers() ) + { + cNames << c->title(); + } + + while ( !titleValid ) + { + newTitle = QInputDialog::getItem( parent, + tr( "Composer title" ), + titleMsg, + cNames, + cNames.indexOf( newTitle ), + true, + &ok ); + if ( !ok ) + { + return QString::null; + } + + if ( newTitle.isEmpty() ) + { + if ( !acceptEmpty ) + { + titleMsg = chooseMsg + "\n\n" + tr( "Title can not be empty!" ); + } + else + { + newTitle = QString( "" ); + titleValid = true; + } + } + else if ( cNames.indexOf( newTitle, 1 ) >= 0 ) + { + cNames[0] = QString( "" ); // clear non-unique name + titleMsg = chooseMsg + "\n\n" + tr( "Title already exists!" ); + } + else + { + titleValid = true; + } + } + + return newTitle; +} + +QgsComposer* QgisApp::createNewComposer( QString title ) { //ask user about name mLastComposerId++; + if ( title.isEmpty() ) + { + title = tr( "Composer %1" ).arg( mLastComposerId ); + } //create new composer object - QgsComposer* newComposerObject = new QgsComposer( this, tr( "Composer %1" ).arg( mLastComposerId ) ); + QgsComposer* newComposerObject = new QgsComposer( this, title ); //add it to the map of existing print composers mPrintComposers.insert( newComposerObject ); @@ -4632,13 +4704,9 @@ void QgisApp::deleteComposer( QgsComposer* c ) delete c; } -QgsComposer* QgisApp::duplicateComposer( QgsComposer* currentComposer, QWidget* parent ) +QgsComposer* QgisApp::duplicateComposer( QgsComposer* currentComposer, QString title ) { QgsComposer* newComposer = 0; - if ( !parent ) - { - parent = this; - } // test that current composer template write is valid QDomDocument currentDoc; @@ -4646,70 +4714,35 @@ QgsComposer* QgisApp::duplicateComposer( QgsComposer* currentComposer, QWidget* QDomElement compositionElem = currentDoc.documentElement().firstChildElement( "Composition" ); if ( compositionElem.isNull() ) { - QMessageBox::warning( parent, - tr( "Write error" ), - tr( "Error, selected composer could not be stored as temporary template" ) ); + QgsDebugMsg( "selected composer could not be stored as temporary template" ); return newComposer; } - QList cNames; - foreach ( QgsComposer* c, printComposers() ) - { - cNames << c->title(); - } - - bool ok = false; - bool titleValid = false; - QString newTitle = currentComposer->title() + tr( " copy" ); - QString chooseMsg = tr( "Choose title" ); - QString titleMsg = chooseMsg; - while ( !titleValid ) + if ( title.isEmpty() ) { - newTitle = QInputDialog::getText( parent, - tr( "New title" ), - titleMsg, - QLineEdit::Normal, - newTitle, - &ok ); - if ( !ok ) - { - return newComposer; - } - - if ( cNames.contains( newTitle ) ) - { - titleMsg = chooseMsg + tr( "\n (title already exists!)" ); - } - else if ( newTitle.isEmpty() ) - { - titleMsg = chooseMsg + tr( "\n (title can not be empty!)" ); - } - else - { - titleValid = true; - } + // TODO: inject a bit of randomness in auto-titles? + title = currentComposer->title() + tr( " copy" ); } - newComposer = createNewComposer(); + newComposer = createNewComposer( title ); if ( !newComposer ) { - QMessageBox::warning( parent, - tr( "Composer error" ), - tr( "Error, could not create new composer" ) ); + QgsDebugMsg( "could not create new composer" ); return newComposer; } - newComposer->hide(); // until template is loaded (faster) + // disable updates until template is loaded (may be faster, but still gives user feedback), + // but is not as fast as hiding composer until template is loaded + newComposer->setUpdatesEnabled( false ); QApplication::setOverrideCursor( Qt::BusyCursor ); if ( !newComposer->composition()->loadFromTemplate( currentDoc, 0, false ) ) { deleteComposer( newComposer ); - QMessageBox::warning( parent, - tr( "Read error" ), - tr( "Error, composer could not be duplicated" ) ); + newComposer = 0; + QgsDebugMsg( "Error, composer could not be duplicated" ); return newComposer; } - newComposer->setTitle( newTitle ); + newComposer->setUpdatesEnabled( true ); newComposer->activate(); QApplication::restoreOverrideCursor(); diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index 75983ea1dec1..2ddd4fb336c8 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -214,14 +214,21 @@ class QgisApp : public QMainWindow, private Ui::MainWindow /**Returns the print composers*/ QSet printComposers() const {return mPrintComposers;} + /** Get a unique title from user for new and duplicate composers + * @param acceptEmpty whether to accept empty titles (one will be generated) + * @param currentTitle base name for initial title choice + * @return QString::null if user cancels input dialog + * @note added in 1.9 + */ + QString uniqueComposerTitle( QWidget* parent, bool acceptEmpty, const QString& currentTitle = QString( "" ) ); /**Creates a new composer and returns a pointer to it*/ - QgsComposer* createNewComposer(); + QgsComposer* createNewComposer( QString title = QString( "" ) ); /**Deletes a composer and removes entry from Set*/ void deleteComposer( QgsComposer* c ); /** Duplicates a composer and adds it to Set * @note added in 1.9 */ - QgsComposer* duplicateComposer( QgsComposer* currentComposer, QWidget* parent ); + QgsComposer* duplicateComposer( QgsComposer* currentComposer, QString title = QString( "" ) ); /** overloaded function used to sort menu entries alphabetically */ QMenu* createPopupMenu();