diff --git a/images/themes/default/mActionNewComposer.png b/images/themes/default/mActionNewComposer.png new file mode 100644 index 00000000000..c2c34ea5cda Binary files /dev/null and b/images/themes/default/mActionNewComposer.png differ diff --git a/src/app/composer/qgscomposer.cpp b/src/app/composer/qgscomposer.cpp index 3637b5498a4..8c9ea7463cf 100644 --- a/src/app/composer/qgscomposer.cpp +++ b/src/app/composer/qgscomposer.cpp @@ -65,9 +65,10 @@ #include #include "qgslogger.h" -QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) +QgsComposer::QgsComposer( QgisApp *qgis, const QString& id ): QMainWindow(), mId( id ) { setupUi( this ); + setAttribute( Qt::WA_DeleteOnClose ); setupTheme(); QToolButton* orderingToolButton = new QToolButton( this ); @@ -106,7 +107,7 @@ QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) toggleActionGroup->addAction( mActionSelectMoveItem ); toggleActionGroup->setExclusive( true ); - setWindowTitle( tr( "QGIS - print composer" ) ); + setWindowTitle( mId ); mActionAddNewMap->setCheckable( true ); mActionAddNewLabel->setCheckable( true ); @@ -116,17 +117,21 @@ QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) mActionAddImage->setCheckable( true ); mActionMoveItemContent->setCheckable( true ); +#ifdef Q_WS_MAC QMenu *appMenu = menuBar()->addMenu( tr( "QGIS" ) ); appMenu->addAction( QgisApp::instance()->actionAbout() ); appMenu->addAction( QgisApp::instance()->actionOptions() ); +#endif QMenu *fileMenu = menuBar()->addMenu( tr( "File" ) ); - fileMenu->addAction( tr( "Close" ), this, SLOT( close() ), tr( "Ctrl+W" ) ); fileMenu->addAction( mActionExportAsImage ); fileMenu->addAction( mActionExportAsPDF ); fileMenu->addAction( mActionExportAsSVG ); fileMenu->addSeparator(); fileMenu->addAction( mActionPrint ); + fileMenu->addSeparator(); + fileMenu->addAction( mActionQuit ); + QObject::connect( mActionQuit, SIGNAL( triggered() ), this, SLOT( close() ) ); QMenu *viewMenu = menuBar()->addMenu( tr( "View" ) ); viewMenu->addAction( mActionZoomIn ); @@ -159,14 +164,13 @@ QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) #endif #endif - - // Create action to select this window and add it to Window menu - mWindowAction = new QAction( windowTitle(), this ); - connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) ); - mQgis = qgis; mFirstTime = true; + // Create action to select this window + mWindowAction = new QAction( windowTitle(), this ); + connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) ); + QgsDebugMsg( "entered." ); setMouseTracking( true ); @@ -188,8 +192,6 @@ QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) mCompositionOptionsLayout->setMargin( 0 ); mCompositionOptionsLayout->addWidget( compositionWidget ); - mPrinter = 0; - QGridLayout *l = new QGridLayout( mViewFrame ); l->setMargin( 0 ); l->addWidget( mView, 0, 0 ); @@ -206,10 +208,9 @@ QgsComposer::QgsComposer( QgisApp *qgis ): QMainWindow(), mFirstPaint( true ) mView->setFocus(); - //connect with signals from QgsProject to read/write project files + //connect with signals from QgsProject to write project files if ( QgsProject::instance() ) { - connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument& ) ), this, SLOT( readXML( const QDomDocument& ) ) ); connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument& ) ), this, SLOT( writeXML( QDomDocument& ) ) ); } } @@ -229,6 +230,7 @@ void QgsComposer::setupTheme() { //now set all the icons - getThemeIcon will fall back to default theme if its //missing from active theme + mActionQuit->setIcon( QgisApp::getThemeIcon( "/mActionFileExit.png" ) ); mActionLoadFromTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileOpen.png" ) ); mActionSaveAsTemplate->setIcon( QgisApp::getThemeIcon( "/mActionFileSaveAs.png" ) ); mActionExportAsImage->setIcon( QgisApp::getThemeIcon( "/mActionSaveMapAsImage.png" ) ); @@ -290,29 +292,6 @@ void QgsComposer::open( void ) } } -void QgsComposer::paintEvent( QPaintEvent* event ) -{ - QMainWindow::paintEvent( event ); -#if 0 //MH: disabled for now as there are segfaults on some systems - //The cached content of the composer maps need to be recreated it is the first paint event of the composer after reading from XML file. - //Otherwise the resolution of the composer map is not suitable for screen - if ( mFirstPaint ) - { - QMap::iterator it = mItemWidgetMap.begin(); - for ( ; it != mItemWidgetMap.constEnd(); ++it ) - { - QgsComposerMap* cm = qobject_cast( it.key() ); - if ( cm ) - { - mFirstPaint = false; - cm->cache(); - cm->update(); - } - } - } -#endif //0 -} - void QgsComposer::activate() { raise(); @@ -320,6 +299,26 @@ void QgsComposer::activate() activateWindow(); } +void QgsComposer::closeEvent( QCloseEvent *event ) +{ + if ( QMessageBox::warning( 0, tr( "Remove composer?" ), tr( "Do you really want to remove the composer instance '%1'?" ).arg( mId ), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel ) == QMessageBox::Ok ) + { + mQgis->checkOutComposer( this ); + event->accept(); + } + else + { + event->ignore(); + } +#if 0 + QMainWindow::closeEvent( event ); + if ( event->isAccepted() ) + { + QgisApp::instance()->removeWindow( mWindowAction ); + } +#endif //0 +} + #ifdef Q_WS_MAC void QgsComposer::changeEvent( QEvent* event ) { @@ -338,15 +337,6 @@ void QgsComposer::changeEvent( QEvent* event ) } } -void QgsComposer::closeEvent( QCloseEvent *event ) -{ - QMainWindow::closeEvent( event ); - if ( event->isAccepted() ) - { - QgisApp::instance()->removeWindow( mWindowAction ); - } -} - void QgsComposer::showEvent( QShowEvent *event ) { QMainWindow::showEvent( event ); @@ -1031,6 +1021,7 @@ void QgsComposer::writeXML( QDomDocument& doc ) void QgsComposer::writeXML( QDomNode& parentNode, QDomDocument& doc ) { QDomElement composerElem = doc.createElement( "Composer" ); + composerElem.setAttribute( "id", mId ); parentNode.appendChild( composerElem ); //store composer items: @@ -1049,6 +1040,145 @@ void QgsComposer::writeXML( QDomNode& parentNode, QDomDocument& doc ) } } +void QgsComposer::readXML( const QDomDocument& doc ) +{ + QDomNodeList composerNodeList = doc.elementsByTagName( "Composer" ); + if ( composerNodeList.size() < 1 ) + { + return; + } + readXML( composerNodeList.at( 0 ).toElement(), doc ); +} + +void QgsComposer::readXML( const QDomElement& composerElem, const QDomDocument& doc ) +{ + mId = composerElem.attribute( "id", "" ); + setWindowTitle( mId ); + + // Create action to select this window + delete mWindowAction; + mWindowAction = new QAction( windowTitle(), this ); + connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) ); + + //delete composer view and composition + delete mView; + mView = 0; + //delete every child of mViewFrame + QObjectList viewFrameChildren = mViewFrame->children(); + QObjectList::iterator it = viewFrameChildren.begin(); + for ( ; it != viewFrameChildren.end(); ++it ) + { + delete( *it ); + } + //delete composition widget + QgsCompositionWidget* oldCompositionWidget = qobject_cast( mCompositionOptionsFrame->children().at( 0 ) ); + delete oldCompositionWidget; + delete mCompositionOptionsLayout; + mCompositionOptionsLayout = 0; + + mView = new QgsComposerView( mViewFrame ); + connectSlots(); + + mComposition = new QgsComposition( mQgis->mapCanvas()->mapRenderer() ); + mComposition->readXML( composerElem, doc ); + + QGridLayout *l = new QGridLayout( mViewFrame ); + l->setMargin( 0 ); + l->addWidget( mView, 0, 0 ); + + //create compositionwidget + QgsCompositionWidget* compositionWidget = new QgsCompositionWidget( mCompositionOptionsFrame, mComposition ); + QObject::connect( mComposition, SIGNAL( paperSizeChanged() ), compositionWidget, SLOT( displayCompositionWidthHeight() ) ); + compositionWidget->show(); + + mCompositionOptionsLayout = new QGridLayout( mCompositionOptionsFrame ); + mCompositionOptionsLayout->setMargin( 0 ); + mCompositionOptionsLayout->addWidget( compositionWidget ); + + //read and restore all the items + + //composer labels + QDomNodeList composerLabelList = composerElem.elementsByTagName( "ComposerLabel" ); + for ( int i = 0; i < composerLabelList.size(); ++i ) + { + QDomElement currentComposerLabelElem = composerLabelList.at( i ).toElement(); + QgsComposerLabel* newLabel = new QgsComposerLabel( mComposition ); + newLabel->readXML( currentComposerLabelElem, doc ); + addComposerLabel( newLabel ); + mComposition->addItem( newLabel ); + mComposition->update(); + mComposition->clearSelection(); + newLabel->setSelected( true ); + showItemOptions( newLabel ); + } + + //composer maps + QDomNodeList composerMapList = composerElem.elementsByTagName( "ComposerMap" ); + for ( int i = 0; i < composerMapList.size(); ++i ) + { + QDomElement currentComposerMapElem = composerMapList.at( i ).toElement(); + QgsComposerMap* newMap = new QgsComposerMap( mComposition ); + newMap->readXML( currentComposerMapElem, doc ); + addComposerMap( newMap ); + mComposition->addItem( newMap ); + mComposition->update(); + mComposition->clearSelection(); + newMap->setSelected( true ); + showItemOptions( newMap ); + } + + //composer scalebars + QDomNodeList composerScaleBarList = composerElem.elementsByTagName( "ComposerScaleBar" ); + for ( int i = 0; i < composerScaleBarList.size(); ++i ) + { + QDomElement currentScaleBarElem = composerScaleBarList.at( i ).toElement(); + QgsComposerScaleBar* newScaleBar = new QgsComposerScaleBar( mComposition ); + newScaleBar->readXML( currentScaleBarElem, doc ); + addComposerScaleBar( newScaleBar ); + mComposition->addItem( newScaleBar ); + mComposition->update(); + mComposition->clearSelection(); + newScaleBar->setSelected( true ); + showItemOptions( newScaleBar ); + } + + //composer legends + QDomNodeList composerLegendList = composerElem.elementsByTagName( "ComposerLegend" ); + for ( int i = 0; i < composerLegendList.size(); ++i ) + { + QDomElement currentLegendElem = composerLegendList.at( i ).toElement(); + QgsComposerLegend* newLegend = new QgsComposerLegend( mComposition ); + newLegend->readXML( currentLegendElem, doc ); + addComposerLegend( newLegend ); + mComposition->addItem( newLegend ); + mComposition->update(); + mComposition->clearSelection(); + newLegend->setSelected( true ); + showItemOptions( newLegend ); + } + + //composer pictures + QDomNodeList composerPictureList = composerElem.elementsByTagName( "ComposerPicture" ); + for ( int i = 0; i < composerPictureList.size(); ++i ) + { + QDomElement currentPictureElem = composerPictureList.at( i ).toElement(); + QgsComposerPicture* newPicture = new QgsComposerPicture( mComposition ); + newPicture->readXML( currentPictureElem, doc ); + addComposerPicture( newPicture ); + mComposition->addItem( newPicture ); + mComposition->update(); + mComposition->clearSelection(); + newPicture->setSelected( true ); + showItemOptions( newPicture ); + } + + mComposition->sortZList(); + mView->setComposition( mComposition ); + + setSelectionTool(); +} + +#if 0 void QgsComposer::readXML( const QDomDocument& doc ) { //look for Composer element @@ -1058,6 +1188,7 @@ void QgsComposer::readXML( const QDomDocument& doc ) return; //nothing to do... } QDomElement composerElem = nl.at( 0 ).toElement(); + mId = composerElem.attribute( "id", "" ); //look for Composition element QDomNodeList cnl = composerElem.elementsByTagName( "Composition" ); @@ -1187,6 +1318,7 @@ void QgsComposer::readXML( const QDomDocument& doc ) setSelectionTool(); } +#endif //0 void QgsComposer::addComposerMap( QgsComposerMap* map ) { diff --git a/src/app/composer/qgscomposer.h b/src/app/composer/qgscomposer.h index 0811a9941f5..0b434662289 100644 --- a/src/app/composer/qgscomposer.h +++ b/src/app/composer/qgscomposer.h @@ -31,7 +31,6 @@ class QgsComposition; class QgsMapCanvas; class QGridLayout; -class QPrinter; class QDomNode; class QDomDocument; class QMoveEvent; @@ -47,7 +46,7 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase Q_OBJECT public: - QgsComposer( QgisApp *qgis ); + QgsComposer( QgisApp *qgis, const QString& id ); ~QgsComposer(); //! Set the pixmap / icons on the toolbar buttons @@ -74,6 +73,10 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase //! Restore the window and toolbar state void restoreWindowState(); + QAction* windowAction() {return mWindowAction;} + + QString id() const {return mId;} + protected: //! Move event virtual void moveEvent( QMoveEvent * ); @@ -81,13 +84,13 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase //! Resize event virtual void resizeEvent( QResizeEvent * ); + //! Close event (remove window from menu) + virtual void closeEvent( QCloseEvent * ); + #ifdef Q_WS_MAC //! Change event (update window menu on ActivationChange) virtual void changeEvent( QEvent * ); - //! Close event (remove window from menu) - virtual void closeEvent( QCloseEvent * ); - //! Show event (add window to menu) virtual void showEvent( QShowEvent * ); #endif @@ -218,13 +221,10 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase //! Sets state from Dom document void readXML( const QDomDocument& doc ); + void readXML( const QDomElement& composerElem, const QDomDocument& doc ); void setSelectionTool(); - protected: - - void paintEvent( QPaintEvent* event ); - private slots: //! Raise, unminimize and activate this window @@ -235,9 +235,6 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase /**Establishes the signal slot connection for the class*/ void connectSlots(); - //! returns new world matrix for canvas view after zoom with factor scaleChange - QMatrix updateMatrix( double scaleChange ); - //! True if a composer map contains a WMS layer bool containsWMSLayer() const; @@ -252,15 +249,16 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase //! Writes state under DOM element void writeXML( QDomNode& parentNode, QDomDocument& doc ); + + /**Identification string*/ + QString mId; + //! Pointer to composer view QgsComposerView *mView; //! Current composition QgsComposition *mComposition; - //! Printer - QPrinter *mPrinter; - //! Pointer to QGIS application QgisApp *mQgis; @@ -282,9 +280,6 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase //! Window menu action to select this window QAction *mWindowAction; - /**False if first paint already happened (used to create cache of composer maps for screen resolution after reading from project files)*/ - bool mFirstPaint; - //! Help context id static const int context_id = 985715179; diff --git a/src/app/composer/qgscomposermapwidget.cpp b/src/app/composer/qgscomposermapwidget.cpp index 1b921725567..b4962e93541 100644 --- a/src/app/composer/qgscomposermapwidget.cpp +++ b/src/app/composer/qgscomposermapwidget.cpp @@ -702,5 +702,6 @@ void QgsComposerMapWidget::on_mCoordinatePrecisionSpinBox_valueChanged( int valu return; } mComposerMap->setGridAnnotationPrecision( value ); + mComposerMap->updateBoundingRect(); mComposerMap->update(); } diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 5cb806755fc..cb4a3367e7e 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -327,7 +327,6 @@ QgisApp *QgisApp::smInstance = 0; QgisApp::QgisApp( QSplashScreen *splash, QWidget * parent, Qt::WFlags fl ) : QMainWindow( parent, fl ), mSplash( splash ), - mComposer( 0 ), mPythonConsole( NULL ), mPythonUtils( NULL ) { @@ -372,7 +371,6 @@ QgisApp::QgisApp( QSplashScreen *splash, QWidget * parent, Qt::WFlags fl ) readSettings(); updateRecentProjectPaths(); - mComposer = new QgsComposer( this ); // Map composer mInternalClipboard = new QgsClipboard; // create clipboard mQgisInterface = new QgisAppInterface( this ); // create the interfce @@ -464,9 +462,9 @@ QgisApp::QgisApp( QSplashScreen *splash, QWidget * parent, Qt::WFlags fl ) qApp->processEvents(); //finally show all the application settings as initialised above - QgsDebugMsg( "\n\n\nApplication Settings:\n--------------------------\n"); + QgsDebugMsg( "\n\n\nApplication Settings:\n--------------------------\n" ); QgsDebugMsg( QgsApplication::showSettings() ); - QgsDebugMsg( "\n--------------------------\n\n\n"); + QgsDebugMsg( "\n--------------------------\n\n\n" ); mMapCanvas->freeze( false ); } // QgisApp ctor @@ -503,6 +501,8 @@ QgisApp::~QgisApp() delete mPythonConsole; delete mPythonUtils; + deletePrintComposers(); + // delete map layer registry and provider registry QgsApplication::exitQgis(); } @@ -591,10 +591,10 @@ void QgisApp::createActions() mActionSaveMapAsImage->setStatusTip( tr( "Save map as image" ) ); connect( mActionSaveMapAsImage, SIGNAL( triggered() ), this, SLOT( saveMapAsImage() ) ); - mActionPrintComposer = new QAction( getThemeIcon( "mActionFilePrint.png" ), tr( "&Print Composer" ), this ); - shortcuts->registerAction( mActionPrintComposer, tr( "Ctrl+P", "Print Composer" ) ); - mActionPrintComposer->setStatusTip( tr( "Print Composer" ) ); - connect( mActionPrintComposer, SIGNAL( triggered() ), this, SLOT( filePrint() ) ); + mActionNewPrintComposer = new QAction( getThemeIcon( "mActionFilePrint.png" ), tr( "&New Print Composer" ), this ); + shortcuts->registerAction( mActionNewPrintComposer, tr( "Ctrl+P", "New Print Composer" ) ); + mActionNewPrintComposer->setStatusTip( tr( "New Print Composer" ) ); + connect( mActionNewPrintComposer, SIGNAL( triggered() ), this, SLOT( newPrintComposer() ) ); mActionExit = new QAction( getThemeIcon( "mActionFileExit.png" ), tr( "Exit" ), this ); shortcuts->registerAction( mActionExit, tr( "Ctrl+Q", "Exit QGIS" ) ); @@ -1166,7 +1166,7 @@ void QgisApp::createMenus() mActionFileSeparator3 = mFileMenu->addSeparator(); } - mFileMenu->addAction( mActionPrintComposer ); + mFileMenu->addAction( mActionNewPrintComposer ); mActionFileSeparator4 = mFileMenu->addSeparator(); mFileMenu->addAction( mActionExit ); @@ -1332,6 +1332,10 @@ void QgisApp::createMenus() mActionWindowSeparator2 = mWindowMenu->addSeparator(); #endif + //Print composers menu + + mPrintComposersMenu = menuBar()->addMenu( tr( "Print Composers" ) ); + // Help Menu menuBar()->addSeparator(); @@ -1364,7 +1368,7 @@ void QgisApp::createToolBars() mFileToolBar->addAction( mActionOpenProject ); mFileToolBar->addAction( mActionSaveProject ); mFileToolBar->addAction( mActionSaveProjectAs ); - mFileToolBar->addAction( mActionPrintComposer ); + mFileToolBar->addAction( mActionNewPrintComposer ); mFileToolBar->addAction( mActionAddOgrLayer ); mFileToolBar->addAction( mActionAddRasterLayer ); #ifdef HAVE_POSTGRESQL @@ -1629,7 +1633,7 @@ void QgisApp::setTheme( QString theThemeName ) mActionOpenProject->setIcon( getThemeIcon( "/mActionFileOpen.png" ) ); mActionSaveProject->setIcon( getThemeIcon( "/mActionFileSave.png" ) ); mActionSaveProjectAs->setIcon( getThemeIcon( "/mActionFileSaveAs.png" ) ); - mActionPrintComposer->setIcon( getThemeIcon( "/mActionFilePrint.png" ) ); + mActionNewPrintComposer->setIcon( getThemeIcon( "/mActionNewComposer.png" ) ); mActionSaveMapAsImage->setIcon( getThemeIcon( "/mActionSaveMapAsImage.png" ) ); mActionExit->setIcon( getThemeIcon( "/mActionFileExit.png" ) ); mActionAddOgrLayer->setIcon( getThemeIcon( "/mActionAddOgrLayer.png" ) ); @@ -1695,10 +1699,13 @@ void QgisApp::setTheme( QString theThemeName ) mActionAddWmsLayer->setIcon( getThemeIcon( "/mActionAddWmsLayer.png" ) ); mActionAddToOverview->setIcon( getThemeIcon( "/mActionInOverview.png" ) ); - if ( mComposer ) + //change themes of all composers + QMap::iterator composerIt = mPrintComposers.begin(); + for ( ; composerIt != mPrintComposers.end(); ++composerIt ) { - mComposer->setupTheme(); + composerIt.value()->setupTheme(); } + emit currentThemeChanged( theThemeName ); } @@ -3056,9 +3063,7 @@ void QgisApp::fileExit() if ( saveDirty() ) { - delete mComposer; - mComposer = 0; - + deletePrintComposers(); mMapCanvas->freeze( true ); removeAllLayers(); qApp->exit( 0 ); @@ -3081,8 +3086,7 @@ void QgisApp::fileNew( bool thePromptToSaveFlag ) return; } - delete mComposer; - mComposer = new QgsComposer( this ); + deletePrintComposers(); if ( thePromptToSaveFlag ) { @@ -3299,9 +3303,7 @@ void QgisApp::fileOpen() // Persist last used project dir settings.setValue( "/UI/lastProjectDir", myPath ); - delete mComposer; - mComposer = new QgsComposer( this ); - + deletePrintComposers(); // clear out any stuff from previous project mMapCanvas->freeze( true ); removeAllLayers(); @@ -3347,6 +3349,9 @@ void QgisApp::fileOpen() // project so that they can check any project // specific plug-in state + //load the composers in the project + loadComposersFromProject( fullPath ); + // add this to the list of recently used project files saveRecentProjectPath( fullPath, settings ); @@ -3367,10 +3372,7 @@ bool QgisApp::addProject( QString projectFile ) QApplication::setOverrideCursor( Qt::WaitCursor ); - //clear the composer - delete mComposer; - mComposer = new QgsComposer( this ); - + deletePrintComposers(); // clear the map canvas removeAllLayers(); @@ -3442,6 +3444,8 @@ bool QgisApp::addProject( QString projectFile ) // project so that they can check any project // specific plug-in state + loadComposersFromProject( projectFile ); + // add this to the list of recently used project files QSettings settings; saveRecentProjectPath( projectFile, settings ); @@ -3680,13 +3684,41 @@ bool QgisApp::openLayer( const QString & fileName ) return ok; } -void QgisApp::filePrint() +void QgisApp::newPrintComposer() { if ( mMapCanvas && mMapCanvas->isDrawing() ) { return; } - mComposer->open(); + + //ask user about name + bool composerExists = true; + QString composerId; + while ( composerExists ) + { + composerId = QInputDialog::getText( 0, tr( "Enter id string for composer" ), tr( "id:" ) ); + if ( composerId.isNull() ) + { + return; + } + + if ( mPrintComposers.contains( composerId ) ) + { + QMessageBox::critical( 0, tr( "Composer id already exists" ), tr( "The entered composer id '%1' already exists. Please enter a different id" ).arg( composerId ) ); + } + else + { + composerExists = false; + } + } + + //create new composer object + QgsComposer* newComposerObject = new QgsComposer( this, composerId ); + //add it to the map of existing print composers + mPrintComposers.insert( composerId, newComposerObject ); + //and place action into print composers menu + mPrintComposersMenu->addAction( newComposerObject->windowAction() ); + newComposerObject->open(); } void QgisApp::saveMapAsImage() @@ -4167,6 +4199,65 @@ QgsGeometry* QgisApp::unionGeometries( const QgsVectorLayer* vl, QgsFeatureList& return unionGeom; } +QList QgisApp::printComposers() +{ + QList composerList; + QMap::iterator it = mPrintComposers.begin(); + for ( ; it != mPrintComposers.end(); ++it ) + { + composerList.push_back( it.value() ); + } + return composerList; +} + +void QgisApp::checkOutComposer( QgsComposer* c ) +{ + if ( !c ) + { + return; + } + mPrintComposers.remove( c->id() ); + mPrintComposersMenu->removeAction( c->windowAction() ); +} + +bool QgisApp::loadComposersFromProject( const QString& projectFilePath ) +{ + //create dom document from file + QDomDocument projectDom; + QFile projectFile( projectFilePath ); + if ( !projectFile.open( QIODevice::ReadOnly ) ) + { + return false; + } + + if ( !projectDom.setContent( &projectFile, false ) ) + { + return false; + } + + //restore each composer + QDomNodeList composerNodes = projectDom.elementsByTagName( "Composer" ); + for ( int i = 0; i < composerNodes.size(); ++i ) + { + QgsComposer* composer = new QgsComposer( this, "" ); + composer->readXML( composerNodes.at( i ).toElement(), projectDom ); + mPrintComposers.insert( composer->id(), composer ); + mPrintComposersMenu->addAction( composer->windowAction() ); + composer->showMinimized(); + composer->zoomFull(); + } +} + +void QgisApp::deletePrintComposers() +{ + QMap::iterator it = mPrintComposers.begin(); + for ( ; it != mPrintComposers.end(); ++it ) + { + delete it.value(); + } + mPrintComposers.clear(); +} + void QgisApp::mergeSelectedFeatures() { //get active layer (hopefully vector) @@ -5596,9 +5687,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer ) //merge tool needs editable layer and provider with the capability of adding and deleting features if ( vlayer->isEditable() && - (dprovider->capabilities() & QgsVectorDataProvider::DeleteFeatures) && - (dprovider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues) && - (dprovider->capabilities() & QgsVectorDataProvider::AddFeatures) ) + ( dprovider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && + ( dprovider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) && + ( dprovider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { mActionMergeFeatures->setEnabled( layerHasSelection ); } diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h index b00937c162f..075e849d3b5 100644 --- a/src/app/qgisapp.h +++ b/src/app/qgisapp.h @@ -143,8 +143,6 @@ class QgisApp : public QMainWindow /** Get the mapcanvas object from the app */ QgsMapCanvas * mapCanvas() { return mMapCanvas; }; - QgsComposer* printComposer() {return mComposer;} - //! Set theme (icons) void setTheme( QString themeName = "default" ); //! Setup the toolbar popup menus for a given theme @@ -196,6 +194,12 @@ class QgisApp : public QMainWindow * windows which are hidden rather than deleted when closed. */ void removeWindow( QAction *action ); + /**Returns the print composers*/ + QList printComposers(); + /**Unregisters a composer instance but does _not_ delete it. This method is usually called from within QgsComposer::closeEvent before + the composer deletes itself using the Qt::WA_DeleteOnClose flag*/ + void checkOutComposer( QgsComposer* c ); + //! Actions to be inserted in menus and toolbars QAction *actionNewProject() { return mActionNewProject; } QAction *actionOpenProject() { return mActionOpenProject; } @@ -206,7 +210,7 @@ class QgisApp : public QMainWindow QAction *actionFileSeparator2() { return mActionFileSeparator2; } QAction *actionProjectProperties() { return mActionProjectProperties; } QAction *actionFileSeparator3() { return mActionFileSeparator3; } - QAction *actionPrintComposer() { return mActionPrintComposer; } + QAction *actionNewPrintComposer() { return mActionNewPrintComposer; } QAction *actionFileSeparator4() { return mActionFileSeparator4; } QAction *actionExit() { return mActionExit; } @@ -315,6 +319,7 @@ class QgisApp : public QMainWindow QMenu *firstRightStandardMenu() { return mHelpMenu; } QMenu *windowMenu() { return NULL; } #endif + QMenu *printComposersMenu() {return mPrintComposersMenu;} QMenu *helpMenu() { return mHelpMenu; } //! Toolbars @@ -443,7 +448,7 @@ class QgisApp : public QMainWindow //! Create a new empty vector layer void newVectorLayer(); //! Print the current map view frame - void filePrint(); + void newPrintComposer(); //! Add all loaded layers into the overview - overides qgisappbase method void addAllToOverview(); //! Remove all loaded layers from the overview - overides qgisappbase method @@ -675,6 +680,11 @@ class QgisApp : public QMainWindow @return 0 in case of error*/ QgsGeometry* unionGeometries( const QgsVectorLayer* vl, QgsFeatureList& featureList ); + /**Deletes all the composer objects and clears mPrintComposers*/ + void deletePrintComposers(); + /**Creates the composer instances in a project file and adds them to the menu*/ + bool loadComposersFromProject( const QString& projectFilePath ); + /// QgisApp aren't copyable QgisApp( QgisApp const & ); /// QgisApp aren't copyable @@ -715,7 +725,7 @@ class QgisApp : public QMainWindow QAction *mActionFileSeparator2; QAction *mActionProjectProperties; QAction *mActionFileSeparator3; - QAction *mActionPrintComposer; + QAction *mActionNewPrintComposer; QAction *mActionFileSeparator4; QAction *mActionExit; @@ -831,6 +841,7 @@ class QgisApp : public QMainWindow #ifdef Q_WS_MAC QMenu *mWindowMenu; #endif + QMenu *mPrintComposersMenu; QMenu *mHelpMenu; // docks ------------------------------------------ @@ -932,8 +943,8 @@ class QgisApp : public QMainWindow QgsHelpViewer *mHelpViewer; //! list of recently opened/saved project files QStringList mRecentProjectPaths; - //! Map composer - QgsComposer *mComposer; + //! Print composers of this project, accessible by id string + QMap mPrintComposers; //! How to determine the number of decimal places used to //! display the mouse position bool mMousePrecisionAutomatic; diff --git a/src/app/qgisappinterface.cpp b/src/app/qgisappinterface.cpp index 13ae0a09d03..92dcd33bc37 100644 --- a/src/app/qgisappinterface.cpp +++ b/src/app/qgisappinterface.cpp @@ -152,13 +152,17 @@ QList QgisAppInterface::activeComposers() QList composerViewList; if ( qgis ) { - QgsComposer* c = qgis->printComposer(); - if ( c ) + QList composerList = qgis->printComposers(); + QList::iterator it = composerList.begin(); + for ( ; it != composerList.end(); ++it ) { - QgsComposerView* v = c->view(); - if ( v ) + if ( *it ) { - composerViewList.push_back( v ); + QgsComposerView* v = ( *it )->view(); + if ( v ) + { + composerViewList.push_back( v ); + } } } } @@ -228,7 +232,7 @@ QAction *QgisAppInterface::actionSaveMapAsImage() { return qgis->actionSaveMapAs QAction *QgisAppInterface::actionFileSeparator2() { return qgis->actionFileSeparator2(); } QAction *QgisAppInterface::actionProjectProperties() { return qgis->actionProjectProperties(); } QAction *QgisAppInterface::actionFileSeparator3() { return qgis->actionFileSeparator3(); } -QAction *QgisAppInterface::actionPrintComposer() { return qgis->actionPrintComposer(); } +QAction *QgisAppInterface::actionPrintComposer() { return qgis->actionNewPrintComposer(); } QAction *QgisAppInterface::actionFileSeparator4() { return qgis->actionFileSeparator4(); } QAction *QgisAppInterface::actionExit() { return qgis->actionExit(); } diff --git a/src/core/composer/qgscomposeritem.cpp b/src/core/composer/qgscomposeritem.cpp index 499bca1caa5..0111e963faf 100644 --- a/src/core/composer/qgscomposeritem.cpp +++ b/src/core/composer/qgscomposeritem.cpp @@ -204,11 +204,11 @@ bool QgsComposerItem::_readXML( const QDomElement& itemElem, const QDomDocument& return false; } + mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble(); + setSceneRect( QRectF( x, y, width, height ) ); setZValue( itemElem.attribute( "zValue" ).toDouble() ); - mLastValidViewScaleFactor = itemElem.attribute( "lastValidViewScaleFactor", "-1" ).toDouble(); - //pen QDomNodeList frameColorList = itemElem.elementsByTagName( "FrameColor" ); if ( frameColorList.size() > 0 ) diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h index 0a1fed58ced..658dbe047f6 100644 --- a/src/core/composer/qgscomposition.h +++ b/src/core/composer/qgscomposition.h @@ -16,6 +16,7 @@ #ifndef QGSCOMPOSITION_H #define QGSCOMPOSITION_H +#include #include #include @@ -25,7 +26,6 @@ class QgsPaperItem; class QGraphicsRectItem; class QgsMapRenderer; -class QDomDocument; class QDomElement; /** \ingroup MapComposer diff --git a/src/ui/qgscomposerbase.ui b/src/ui/qgscomposerbase.ui index 0b735dd5b96..27ae1791f32 100644 --- a/src/ui/qgscomposerbase.ui +++ b/src/ui/qgscomposerbase.ui @@ -1,7 +1,8 @@ - + + QgsComposerBase - - + + 0 0 @@ -9,146 +10,122 @@ 609 - + true - + MainWindow - - + + true - - - - + + + + true - + Qt::Horizontal - - + + true - + QFrame::StyledPanel - + QFrame::Raised - - - + + + 0 0 - + 150 10 - + 32767 32767 - + 1 - - + + General - - + + 9 - - 9 - - - 9 - - - 9 - - + 6 - - 6 - - - - + + + QFrame::StyledPanel - + QFrame::Raised - - - + + + false - - + + 0 0 - - - - + + + + 0 0 - + Composition - - + + Item - - + + 9 - - 9 - - - 9 - - - 9 - - + 6 - - 6 - - - - - + + + + @@ -156,291 +133,316 @@ - - - - QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::NoButton + + + + QDialogButtonBox::Help - - + + Qt::Horizontal - + TopToolBarArea - + false - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - ../themes/default/mActionFilePrint.png + + + + ../themes/default/mActionFilePrint.png../themes/default/mActionFilePrint.png - + &Print... - - - ../themes/default/mActionZoomFullExtent.png + + + + ../themes/default/mActionZoomFullExtent.png../themes/default/mActionZoomFullExtent.png - + Zoom Full - - - ../themes/default/mActionZoomIn.png + + + + ../themes/default/mActionZoomIn.png../themes/default/mActionZoomIn.png - + Zoom In - - - ../themes/default/mActionZoomOut.png + + + + ../themes/default/mActionZoomOut.png../themes/default/mActionZoomOut.png - + Zoom Out - - - ../themes/default/mActionAddMap.png + + + + ../themes/default/mActionAddMap.png../themes/default/mActionAddMap.png - + Add Map - + Add new map - - - ../themes/default/mActionLabel.png + + + + ../themes/default/mActionLabel.png../themes/default/mActionLabel.png - + Add Label - + Add new label - - - ../themes/default/mActionAddLegend.png + + + + ../themes/default/mActionAddLegend.png../themes/default/mActionAddLegend.png - + Add Vector Legend - + Add new vect legend - - - ../themes/default/mActionPan.png + + + + ../themes/default/mActionPan.png../themes/default/mActionPan.png - + Move Item - + Select/Move item - - - ../themes/default/mActionSaveMapAsImage.png + + + + ../themes/default/mActionSaveMapAsImage.png../themes/default/mActionSaveMapAsImage.png - + Export as Image... - - - ../themes/default/mActionSaveAsPDF.png + + + + ../themes/default/mActionSaveAsPDF.png../themes/default/mActionSaveAsPDF.png - + Export as PDF... - - - ../themes/default/mActionSaveAsSVG.png + + + + ../themes/default/mActionSaveAsSVG.png../themes/default/mActionSaveAsSVG.png - + Export as SVG... - - - ../../plugins/scale_bar/icon.xpm + + + + ../../plugins/scale_bar/icon.xpm../../plugins/scale_bar/icon.xpm - + Add Scalebar - + Add new scalebar - - - ../themes/default/mActionDraw.png + + + + ../themes/default/mActionDraw.png../themes/default/mActionDraw.png - + Refresh - + Refresh view - - - ../themes/default/mActionAddImage.png + + + + ../themes/default/mActionAddImage.png../themes/default/mActionAddImage.png - + Add Image - - + + Move Content - + Move item content - - + + Group - + Group items - - + + Ungroup - + Ungroup items - - + + Raise - + Raise selected items - - + + Lower - + Lower selected items - - + + Bring to Front - + Move selected items to top - - + + Send to Back - + Move selected items to bottom - - + + Load From template - - + + Save as template - - + + Align left - + Align selected items left - - + + Align center - + Align center horizontal - - + + Align right - + Align selected items right - - + + Align top - + Align selected items to top - - + + Align center vertical - + Align center vertical - - + + Align bottom - + Align selected items bottom + + + &Quit + + + Quit + + + Ctrl+Q + + mOptionsTabWidget @@ -455,11 +457,11 @@ QgsComposerBase close() - + 612 583 - + 735 567