Skip to content
Permalink
Browse files
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
  • Loading branch information
dakcarto committed Feb 26, 2013
1 parent 208c920 commit 0c777dd7d38a25b7a0e85f8e05c22502c5bd89d2
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 60 deletions.
@@ -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()
@@ -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<QListWidgetItem*, QgsComposer*>::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 )
{
@@ -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,84 +4704,45 @@ 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;
currentComposer->templateXML( currentDoc );
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<QString> 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();

@@ -214,14 +214,21 @@ class QgisApp : public QMainWindow, private Ui::MainWindow

/**Returns the print composers*/
QSet<QgsComposer*> 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();

0 comments on commit 0c777dd

Please sign in to comment.