Skip to content
Permalink
Browse files

[FEATURE] Shell functionality for creating new canvases

Allows new "map views" to be created in the main QGIS interface.
These are map canvases, but with limited functionality (ie
no use of map tools beyond pan tool).
  • Loading branch information
nyalldawson committed Mar 13, 2017
1 parent 2654c72 commit 29d77b0ce1e8b90368039285d2121e436dae5840
@@ -556,6 +556,7 @@
<file>themes/default/processingAlgorithm.svg</file>
<file>themes/default/processingResult.svg</file>
<file>themes/default/search.svg</file>
<file>themes/default/mActionNewMap.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="24"
width="24"
version="1.1"
id="svg23"
sodipodi:docname="mActionNewMap.svg"
inkscape:version="0.92.1 r">
<metadata
id="metadata29">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs27" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1463"
inkscape:window-height="554"
id="namedview25"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="1.3220339"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="0"
inkscape:current-layer="svg23" />
<linearGradient
id="a"
gradientUnits="userSpaceOnUse"
x1="3.5"
x2="11.5"
y1="19.5"
y2="19.5"
gradientTransform="translate(0,-8)">
<stop
offset="0"
stop-color="#b7b7b7"
id="stop2" />
<stop
offset="1"
stop-color="#e6e6e6"
id="stop4" />
</linearGradient>
<path
inkscape:connector-curvature="0"
style="fill:url(#a);fill-rule:evenodd;stroke:#9a9a9a"
id="path7"
d="m 21.5,21.5 h -17 c -1,0 -1.977816,-1.420625 -2,-2.5 V 2.5 h 19 z" />
<path
style="fill:#e6e6e6;fill-rule:evenodd;stroke:#9a9a9a"
inkscape:connector-curvature="0"
id="path9"
d="m 6.5,1.9999996 c -1,-0.9999995 -3,-0.9999995 -4,0 V 18 c 1,-1 3,-1 4,0 z" />
<g
id="g16"
transform="translate(33)">
<rect
style="fill:#c4a000"
id="rect10"
y="13"
x="-20"
width="11"
rx="2.0114901"
height="11" />
<path
style="fill:#fcffff"
inkscape:connector-curvature="0"
id="path12"
d="m -15,14 v 2.0625 c -0.537663,0.111041 -1.024662,0.383291 -1.375,0.78125 l -1.78125,-1.03125 -0.5,0.875 1.78125,1.03125 C -16.957063,17.966182 -17,18.225145 -17,18.5 c 0,0.274855 0.04294,0.533818 0.125,0.78125 l -1.78125,1.03125 0.5,0.875 1.78125,-1.03125 c 0.352503,0.40042 0.832682,0.670182 1.375,0.78125 V 23 h 1 v -2.0625 c 0.537663,-0.111041 1.024662,-0.383291 1.375,-0.78125 l 1.78125,1.03125 0.5,-0.875 -1.78125,-1.03125 C -12.042937,19.033818 -12,18.774855 -12,18.5 c 0,-0.274855 -0.04294,-0.533818 -0.125,-0.78125 l 1.78125,-1.03125 -0.5,-0.875 -1.78125,1.03125 C -12.977503,16.44333 -13.457682,16.173568 -14,16.0625 V 14 Z m 0.5,3.5 c 0.552,0 1,0.448 1,1 0,0.552 -0.448,1 -1,1 -0.552,0 -1,-0.448 -1,-1 0,-0.552 0.448,-1 1,-1 z" />
<path
style="opacity:0.3;fill:#fcffff;fill-rule:evenodd"
inkscape:connector-curvature="0"
id="path14"
d="m -19,19 9,-0.0096 c 0,0 0,0 0,-2 C -10,14 -11,14 -14.5,14 c -3.5,0 -4.5,0 -4.5,3 0,2 0,2 0,2 z" />
</g>
</svg>
@@ -58,7 +58,15 @@ class QgisInterface : QObject

/* Exposed functions */

//! Zoom to full extent of map layers
virtual QList< QgsMapCanvas* > mapCanvases() = 0;

virtual QgsMapCanvas* createNewMapCanvas( const QString& name ) = 0;

public slots:




virtual void zoomFull() = 0;

//! Zoom to previous view extent
@@ -1663,6 +1663,7 @@ void QgisApp::createActions()
connect( mActionSaveProject, SIGNAL( triggered() ), this, SLOT( fileSave() ) );
connect( mActionSaveProjectAs, SIGNAL( triggered() ), this, SLOT( fileSaveAs() ) );
connect( mActionSaveMapAsImage, SIGNAL( triggered() ), this, SLOT( saveMapAsImage() ) );
connect( mActionNewMapCanvas, &QAction::triggered, this, &QgisApp::newMapCanvas );
connect( mActionNewPrintComposer, SIGNAL( triggered() ), this, SLOT( newPrintComposer() ) );
connect( mActionShowComposerManager, SIGNAL( triggered() ), this, SLOT( showComposerManager() ) );
connect( mActionExit, SIGNAL( triggered() ), this, SLOT( fileExit() ) );
@@ -3100,6 +3101,35 @@ QgsMapCanvas *QgisApp::mapCanvas()
return mMapCanvas;
}

QgsMapCanvas *QgisApp::createNewMapCanvas( const QString &name )
{
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
{
if ( canvas->objectName() == name )
{
QString errorMessage = tr( "A map canvas with name '%1' already exists!" ).arg( name );
QgsDebugMsg( errorMessage );
return nullptr;
}
}

QgsMapCanvas *mapCanvas = new QgsMapCanvas( this );
\
mapCanvas->freeze( true );
mapCanvas->setObjectName( name );

QDockWidget *mapWidget = new QDockWidget( name, this );
mapWidget->setAllowedAreas( Qt::AllDockWidgetAreas );
mapWidget->setWidget( mapCanvas );
applyProjectSettingsToCanvas( mapCanvas );

mapCanvas->setDestinationCrs( QgsProject::instance()->crs() );

addDockWidget( Qt::RightDockWidgetArea, mapWidget );
mapCanvas->freeze( false );
return mapCanvas;
}

QgsMessageBar *QgisApp::messageBar()
{
Q_ASSERT( mInfoBar );
@@ -7042,6 +7072,11 @@ QList<QgsMapCanvasAnnotationItem *> QgisApp::annotationItems()
return itemList;
}

QList<QgsMapCanvas *> QgisApp::mapCanvases()
{
return findChildren< QgsMapCanvas * >();
}

void QgisApp::removeAnnotationItems()
{
if ( !mMapCanvas )
@@ -9595,6 +9630,30 @@ void QgisApp::embedLayers()
}
}

void QgisApp::newMapCanvas()
{
int i = 1;

bool existing = true;
QList< QgsMapCanvas * > existingCanvases = mapCanvases();
QString name;
while ( existing )
{
name = tr( "Map %1" ).arg( i++ );
existing = false;
Q_FOREACH ( QgsMapCanvas *canvas, existingCanvases )
{
if ( canvas->objectName() == name )
{
existing = true;
break;
}
}
}

createNewMapCanvas( name );
}

void QgisApp::setExtent( const QgsRectangle &rect )
{
mMapCanvas->setExtent( rect );
@@ -231,6 +231,14 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
//! Get the mapcanvas object from the app
QgsMapCanvas *mapCanvas();

/**
* Returns a list of all map canvases open in the app.
*/
QList< QgsMapCanvas * > mapCanvases();

//! Create a new map canvas with the specified unique \a name
QgsMapCanvas *createNewMapCanvas( const QString &name );

//! Return the messageBar object which allows displaying unobtrusive messages to the user.
QgsMessageBar *messageBar();

@@ -1024,6 +1032,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void showAlignRasterTool();
void embedLayers();

//! Creates a new map canvas view
void newMapCanvas();

//! Create a new empty vector layer
void newVectorLayer();
//! Create a new memory layer
@@ -1513,6 +1524,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow

//! Returns all annotation items in the canvas
QList<QgsMapCanvasAnnotationItem *> annotationItems();

//! Removes annotation items in the canvas
void removeAnnotationItems();

@@ -1754,6 +1766,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QSplashScreen *mSplash = nullptr;
//! list of recently opened/saved project files
QList<QgsWelcomePageItemsModel::RecentProjectData> mRecentProjects;

//! Print composers of this project, accessible by id string
QSet<QgsComposer *> mPrintComposers;
//! QGIS-internal vector feature clipboard
@@ -331,6 +331,16 @@ QgsMapCanvas *QgisAppInterface::mapCanvas()
return qgis->mapCanvas();
}

QList<QgsMapCanvas *> QgisAppInterface::mapCanvases()
{
return qgis->mapCanvases();
}

QgsMapCanvas *QgisAppInterface::createNewMapCanvas( const QString &name )
{
return qgis->createNewMapCanvas( name );
}

QgsLayerTreeMapCanvasBridge *QgisAppInterface::layerTreeCanvasBridge()
{
return qgis->layerTreeCanvasBridge();
@@ -179,6 +179,9 @@ class APP_EXPORT QgisAppInterface : public QgisInterface
//! Return a pointer to the map canvas used by qgisapp
QgsMapCanvas *mapCanvas() override;

QList< QgsMapCanvas * > mapCanvases() override;
QgsMapCanvas *createNewMapCanvas( const QString &name ) override;

/**
* Returns a pointer to the layer tree canvas bridge
*
@@ -104,6 +104,18 @@ class GUI_EXPORT QgisInterface : public QObject
*/
virtual bool removeCustomActionForLayerType( QAction *action ) = 0;

/**
* Returns a list of all map canvases open in the app.
* @note added in QGIS 3.0
*/
virtual QList< QgsMapCanvas * > mapCanvases() = 0;

/**
* Create a new map canvas with the specified unique \a name.
* @note added in QGIS 3.0
*/
virtual QgsMapCanvas *createNewMapCanvas( const QString &name ) = 0;

public slots: // TODO: do these functions really need to be slots?

/* Exposed functions */
@@ -53,7 +53,9 @@
<addaction name="mActionDxfExport"/>
<addaction name="mActionDwgImport"/>
<addaction name="separator"/>
<addaction name="mActionNewMapCanvas"/>
<addaction name="mActionSnappingOptions"/>
<addaction name="separator"/>
<addaction name="mActionNewPrintComposer"/>
<addaction name="mActionShowComposerManager"/>
<addaction name="mPrintComposersMenu"/>
@@ -332,6 +334,7 @@
<addaction name="mActionOpenProject"/>
<addaction name="mActionSaveProject"/>
<addaction name="mActionSaveProjectAs"/>
<addaction name="mActionNewMapCanvas"/>
<addaction name="mActionNewPrintComposer"/>
<addaction name="mActionShowComposerManager"/>
</widget>
@@ -640,6 +643,21 @@
<string>Save as &amp;Image...</string>
</property>
</action>
<action name="mActionNewMapCanvas">
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionNewMap.svg</normaloff>:/images/themes/default/mActionNewMap.svg</iconset>
</property>
<property name="text">
<string>New &amp;Map View</string>
</property>
<property name="toolTip">
<string>New Map View</string>
</property>
<property name="shortcut">
<string>Ctrl+M</string>
</property>
</action>
<action name="mActionNewPrintComposer">
<property name="icon">
<iconset resource="../../images/images.qrc">

0 comments on commit 29d77b0

Please sign in to comment.
You can’t perform that action at this time.