Skip to content
Permalink
Browse files
[FEATURE] Add duplicate function to composer manager and composer ui
- Addresses feature request #7203
- Add actions to composer that trigger main app's, instead of referencing
- Allows Ctrl(Cmd)-P to initiate printing (instead of a new composer)
- Allows Ctrl(Cmd)-N to create new composer
- Use new templateXML function when saving composer template
  • Loading branch information
dakcarto committed Feb 24, 2013
1 parent 3e6c803 commit 5ac7d036b3b604353ca227bc86f5b342e096f1ff
@@ -69,6 +69,7 @@
<file>themes/default/mActionDeleteVertex.png</file>
<file>themes/default/mActionDeselectAll.png</file>
<file>themes/default/mActionDraw.png</file>
<file>themes/default/mActionDuplicateComposer.png</file>
<file>themes/default/mActionEditCopy.png</file>
<file>themes/default/mActionEditCut.png</file>
<file>themes/default/mActionEditPaste.png</file>
@@ -316,6 +317,7 @@
<file>themes/gis/mActionDeleteVertex.png</file>
<file>themes/gis/mActionDeselectAll.png</file>
<file>themes/gis/mActionDraw.png</file>
<file>themes/gis/mActionDuplicateComposer.png</file>
<file>themes/gis/mActionEditCopy.png</file>
<file>themes/gis/mActionEditCut.png</file>
<file>themes/gis/mActionEditPaste.png</file>
Binary file not shown.
Binary file not shown.
@@ -94,14 +94,6 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
int size = settings.value( "/IconSize", QGIS_ICON_SIZE ).toInt();
setIconSize( QSize( size, size ) );

// ability to save parent project from composer
mSaveProjectAction = mQgis->actionSaveProject();
QToolButton* saveProjectToolButton = new QToolButton( this );
saveProjectToolButton->addAction( mSaveProjectAction );
saveProjectToolButton->setDefaultAction( mSaveProjectAction );
mComposerToolbar->insertWidget( mActionLoadFromTemplate, saveProjectToolButton );
mComposerToolbar->insertSeparator( mActionLoadFromTemplate );

QToolButton* orderingToolButton = new QToolButton( this );
orderingToolButton->setPopupMode( QToolButton::InstantPopup );
orderingToolButton->setAutoRaise( true );
@@ -171,10 +163,11 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
#endif

QMenu *composerMenu = menuBar()->addMenu( tr( "Composer" ) );
composerMenu->addAction( mSaveProjectAction );
composerMenu->addAction( mActionSaveProject );
composerMenu->addSeparator();
composerMenu->addAction( mQgis->actionNewPrintComposer() );
composerMenu->addAction( mQgis->actionShowComposerManager() );
composerMenu->addAction( mActionNewComposer );
composerMenu->addAction( mActionDuplicateComposer );
composerMenu->addAction( mActionComposerManager );

mPrintComposersMenu = new QMenu( tr( "Print Composers" ), this );
mPrintComposersMenu->setObjectName( "mPrintComposersMenu" );
@@ -360,6 +353,10 @@ void QgsComposer::setupTheme()
//now set all the icons - getThemeIcon will fall back to default theme if its
//missing from active theme
mActionQuit->setIcon( QgsApplication::getThemeIcon( "/mActionFileExit.png" ) );
mActionSaveProject->setIcon( QgsApplication::getThemeIcon( "/mActionFileSave.png" ) );
mActionNewComposer->setIcon( QgsApplication::getThemeIcon( "/mActionNewComposer.png" ) );
mActionDuplicateComposer->setIcon( QgsApplication::getThemeIcon( "/mActionDuplicateComposer.png" ) );
mActionComposerManager->setIcon( QgsApplication::getThemeIcon( "/mActionComposerManager.png" ) );
mActionLoadFromTemplate->setIcon( QgsApplication::getThemeIcon( "/mActionFileOpen.png" ) );
mActionSaveAsTemplate->setIcon( QgsApplication::getThemeIcon( "/mActionFileSaveAs.png" ) );
mActionExportAsImage->setIcon( QgsApplication::getThemeIcon( "/mActionSaveMapAsImage.png" ) );
@@ -1337,6 +1334,26 @@ void QgsComposer::on_mActionAddArrow_triggered()
}
}

void QgsComposer::on_mActionSaveProject_triggered()
{
mQgis->actionSaveProject()->trigger();
}

void QgsComposer::on_mActionNewComposer_triggered()
{
mQgis->actionNewPrintComposer()->trigger();
}

void QgsComposer::on_mActionDuplicateComposer_triggered()
{
mQgis->duplicateComposer( this, this );
}

void QgsComposer::on_mActionComposerManager_triggered()
{
mQgis->actionShowComposerManager()->trigger();
}

void QgsComposer::on_mActionSaveAsTemplate_triggered()
{
//show file dialog
@@ -1366,7 +1383,7 @@ void QgsComposer::on_mActionSaveAsTemplate_triggered()
}

QDomDocument saveDocument;
writeXML( saveDocument, saveDocument );
templateXML( saveDocument );

if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
{
@@ -1633,6 +1650,11 @@ void QgsComposer::writeXML( QDomNode& parentNode, QDomDocument& doc )
mComposition->atlasComposition().writeXML( composerElem, doc );
}

void QgsComposer::templateXML( QDomDocument& doc )
{
writeXML( doc, doc );
}

void QgsComposer::readXML( const QDomDocument& doc )
{
QDomNodeList composerNodeList = doc.elementsByTagName( "Composer" );
@@ -168,6 +168,22 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase

void on_mActionAddHtml_triggered();

//! Save parent project
//! @note added in 1.9
void on_mActionSaveProject_triggered();

//! Create new composer
//! @note added in 1.9
void on_mActionNewComposer_triggered();

//! Duplicate current composer
//! @note added in 1.9
void on_mActionDuplicateComposer_triggered();

//! Show composer manager
//! @note added in 1.9
void on_mActionComposerManager_triggered();

//! Save composer as template
void on_mActionSaveAsTemplate_triggered();

@@ -259,6 +275,9 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! Stores state in Dom node
void writeXML( QDomDocument& doc );

//! Stores only template as base Dom node
void templateXML( QDomDocument& doc );

//! Sets state from Dom document
void readXML( const QDomDocument& doc );
void readXML( const QDomElement& composerElem, const QDomDocument& doc, bool fromTemplate = false );
@@ -342,10 +361,6 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
QMenu* mPanelMenu;
QMenu* mToolbarMenu;

//! Save parent Project action
//! @note added in 1.9
QAction *mSaveProjectAction;

//! Print Composers menu as mirror of main app's
//! @note added in 1.9
QMenu* mPrintComposersMenu;
@@ -40,6 +40,10 @@ QgsComposerManager::QgsComposerManager( QWidget * parent, Qt::WindowFlags f ): Q
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
connect( pb, SIGNAL( clicked() ), this, SLOT( show_clicked() ) );

pb = new QPushButton( tr( "&Duplicate" ) );
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
connect( pb, SIGNAL( clicked() ), this, SLOT( duplicate_clicked() ) );

pb = new QPushButton( tr( "&Remove" ) );
mButtonBox->addButton( pb, QDialogButtonBox::ActionRole );
connect( pb, SIGNAL( clicked() ), this, SLOT( remove_clicked() ) );
@@ -213,6 +217,34 @@ void QgsComposerManager::show_clicked()
close();
}

void QgsComposerManager::duplicate_clicked()
{
QListWidgetItem* item = mComposerListWidget->currentItem();
if ( !item )
{
return;
}

QgsComposer* currentComposer = 0;
QMap<QListWidgetItem*, QgsComposer*>::iterator it = mItemComposerMap.find( item );
if ( it != mItemComposerMap.end() )
{
currentComposer = it.value();
}
else
{
return;
}

QgsComposer* newComposer = QgisApp::instance()->duplicateComposer( currentComposer, this );

if ( newComposer )
{
// no need to add new composer to list widget, if just closing this->exec();
close();
}
}

void QgsComposerManager::rename_clicked()
{
QListWidgetItem* item = mComposerListWidget->currentItem();
@@ -47,6 +47,10 @@ class QgsComposerManager: public QDialog, private Ui::QgsComposerManagerBase
void on_mAddButton_clicked();
void remove_clicked();
void show_clicked();
/** Duplicate composer
* @note added in 1.9
*/
void duplicate_clicked();
void rename_clicked();
void on_mComposerListWidget_itemChanged( QListWidgetItem * item );
};
@@ -4632,6 +4632,90 @@ void QgisApp::deleteComposer( QgsComposer* c )
delete c;
}

QgsComposer* QgisApp::duplicateComposer( QgsComposer* currentComposer, QWidget* parent )
{
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" ) );
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 )
{
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;
}
}

newComposer = createNewComposer();
if ( !newComposer )
{
QMessageBox::warning( parent,
tr( "Composer error" ),
tr( "Error, could not create new composer" ) );
return newComposer;
}
newComposer->hide(); // until template is loaded (faster)

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" ) );
return newComposer;
}
newComposer->setTitle( newTitle );
newComposer->activate();
QApplication::restoreOverrideCursor();

return newComposer;
}

bool QgisApp::loadComposersFromProject( const QDomDocument& doc )
{
if ( doc.isNull() )
@@ -218,6 +218,10 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
QgsComposer* createNewComposer();
/**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 );

/** overloaded function used to sort menu entries alphabetically */
QMenu* createPopupMenu();
@@ -56,6 +56,11 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="mActionSaveProject"/>
<addaction name="separator"/>
<addaction name="mActionNewComposer"/>
<addaction name="mActionDuplicateComposer"/>
<addaction name="mActionComposerManager"/>
<addaction name="mActionLoadFromTemplate"/>
<addaction name="mActionSaveAsTemplate"/>
<addaction name="separator"/>
@@ -126,6 +131,9 @@
<property name="text">
<string>&amp;Print...</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
<action name="mActionZoomAll">
<property name="icon">
@@ -410,6 +418,9 @@
<property name="text">
<string>Page Setup</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+P</string>
</property>
</action>
<action name="mActionUndo">
<property name="icon">
@@ -480,12 +491,50 @@
<bool>true</bool>
</property>
<property name="text">
<string>Add html</string>
<string>Add HTML</string>
</property>
<property name="toolTip">
<string>Add html frame</string>
</property>
</action>
<action name="mActionComposerManager">
<property name="text">
<string>Composer Manager</string>
</property>
<property name="toolTip">
<string>Composer Manager</string>
</property>
</action>
<action name="mActionNewComposer">
<property name="text">
<string>&amp;New Composer</string>
</property>
<property name="toolTip">
<string>New Composer</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="mActionSaveProject">
<property name="text">
<string>&amp;Save Project</string>
</property>
<property name="toolTip">
<string>Save Project</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="mActionDuplicateComposer">
<property name="text">
<string>&amp;Duplicate Composer</string>
</property>
<property name="toolTip">
<string>Duplicate Composer</string>
</property>
</action>
</widget>
<resources>
<include location="../../images/images.qrc"/>

0 comments on commit 5ac7d03

Please sign in to comment.