Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
12534 lines (10800 sloc) 426 KB
/***************************************************************************
qgisapp.cpp - description
-------------------
begin : Sat Jun 22 2002
copyright : (C) 2002 by Gary E.Sherman
email : sherman at mrcc.com
Romans 3:23=>Romans 6:23=>Romans 10:9,10=>Romans 12
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QAction>
#include <QApplication>
#include <QBitmap>
#include <QCheckBox>
#include <QClipboard>
#include <QColor>
#include <QCursor>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialog>
#include <QDialogButtonBox>
#include <QDir>
#include <QEvent>
#include <QFile>
#include <QFileInfo>
#include <QImageWriter>
#include <QInputDialog>
#include <QKeyEvent>
#include <QLabel>
#include <QLibrary>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QPainter>
#include <QPictureIO>
#include <QPixmap>
#include <QPoint>
#include <QPrinter>
#include <QProcess>
#include <QProgressBar>
#include <QProgressDialog>
#include <QRegExp>
#include <QRegExpValidator>
#include <QShortcut>
#include <QSpinBox>
#include <QSplashScreen>
#ifndef QT_NO_SSL
#include <QSslConfiguration>
#endif
#include <QStatusBar>
#include <QStringList>
#include <QSystemTrayIcon>
#include <QTcpSocket>
#include <QTextStream>
#include <QtGlobal>
#include <QThread>
#include <QTimer>
#include <QToolButton>
#include <QUuid>
#include <QVBoxLayout>
#include <QWhatsThis>
#include <QWidgetAction>
#include <qgssettings.h>
#include <qgsnetworkaccessmanager.h>
#include <qgsapplication.h>
#include <qgscomposition.h>
#include <qgslayerstylingwidget.h>
#include "qgstaskmanager.h"
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QAuthenticator>
#ifdef Q_OS_WIN
#include <QWinTaskbarButton>
#include <QWinTaskbarProgress>
#endif
#ifdef Q_OS_WIN
#include <QtWinExtras/QWinJumpList>
#include <QtWinExtras/QWinJumpListItem>
#include <QtWinExtras/QWinJumpListCategory>
#endif
//
// Mac OS X Includes
// Must include before GEOS 3 due to unqualified use of 'Point'
//
#ifdef Q_OS_MACX
#include <ApplicationServices/ApplicationServices.h>
// check macro breaks QItemDelegate
#ifdef check
#undef check
#endif
#endif
//
// QGIS Specific Includes
//
#include "qgisapp.h"
#include "qgisappinterface.h"
#include "qgisappstylesheet.h"
#include "qgis.h"
#include "qgisplugin.h"
#include "qgsabout.h"
#include "qgsalignrasterdialog.h"
#include "qgsapplayertreeviewmenuprovider.h"
#include "qgsapplication.h"
#include "qgsactionmanager.h"
#include "qgsannotationmanager.h"
#include "qgsannotationregistry.h"
#include "qgsattributetabledialog.h"
#include "qgsattributedialog.h"
#include "qgsauthmanager.h"
#include "qgsauthguiutils.h"
#ifndef QT_NO_SSL
#include "qgsauthcertutils.h"
#include "qgsauthsslerrorsdialog.h"
#endif
#include "qgsbookmarks.h"
#include "qgsbrowserdockwidget.h"
#include "qgsadvanceddigitizingdockwidget.h"
#include "qgsclipboard.h"
#include "qgscomposer.h"
#include "qgscomposermanager.h"
#include "qgscomposerview.h"
#include "qgsconfigureshortcutsdialog.h"
#include "qgscoordinatetransform.h"
#include "qgscoordinateutils.h"
#include "qgscredentialdialog.h"
#include "qgscursors.h"
#include "qgscustomdrophandler.h"
#include "qgscustomization.h"
#include "qgscustomlayerorderwidget.h"
#include "qgscustomprojectiondialog.h"
#include "qgsdatasourceuri.h"
#include "qgsdatumtransformdialog.h"
#include "qgsdoublespinbox.h"
#include "qgsdockwidget.h"
#include "qgsdxfexport.h"
#include "qgsdxfexportdialog.h"
#include "qgsdwgimportdialog.h"
#include "qgsdecorationcopyright.h"
#include "qgsdecorationnortharrow.h"
#include "qgsdecorationscalebar.h"
#include "qgsdecorationgrid.h"
#include "qgsencodingfiledialog.h"
#include "qgserror.h"
#include "qgserrordialog.h"
#include "qgsexception.h"
#include "qgsexpressionselectiondialog.h"
#include "qgsfeature.h"
#include "qgsfieldcalculator.h"
#include "qgsfieldformatter.h"
#include "qgsfieldformatterregistry.h"
#include "qgsformannotation.h"
#include "qgisgui.h"
#include "qgshtmlannotation.h"
#include "qgsprojectionselectiondialog.h"
#include "qgsgpsinformationwidget.h"
#include "qgsguivectorlayertools.h"
#include "qgslabelingwidget.h"
#include "qgsdiagramproperties.h"
#include "qgslayerdefinition.h"
#include "qgslayertree.h"
#include "qgslayertreemapcanvasbridge.h"
#include "qgslayertreemodel.h"
#include "qgslayertreemodellegendnode.h"
#include "qgslayertreeregistrybridge.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgslayertreeviewdefaultactions.h"
#include "qgslayoutmanager.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmapcanvasdockwidget.h"
#include "qgsmapcanvassnappingutils.h"
#include "qgsmapcanvastracer.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerstyleguiutils.h"
#include "qgsmapoverviewcanvas.h"
#include "qgsmapsettings.h"
#include "qgsmaptip.h"
#include "qgsmergeattributesdialog.h"
#include "qgsmessageviewer.h"
#include "qgsmessagebar.h"
#include "qgsmessagebaritem.h"
#include "qgsmimedatautils.h"
#include "qgsmessagelog.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsnewvectorlayerdialog.h"
#include "qgsnewmemorylayerdialog.h"
#include "qgsoptions.h"
#include "qgspluginlayer.h"
#include "qgspluginlayerregistry.h"
#include "qgspluginmanager.h"
#include "qgspluginregistry.h"
#include "qgspoint.h"
#include "qgsruntimeprofiler.h"
#include "qgshandlebadlayers.h"
#include "qgsproject.h"
#include "qgsprojectlayergroupdialog.h"
#include "qgsprojectproperties.h"
#include "qgsproviderregistry.h"
#include "qgspythonrunner.h"
#include "qgsquerybuilder.h"
#include "qgsrastercalcdialog.h"
#include "qgsrasterfilewriter.h"
#include "qgsrasteriterator.h"
#include "qgsrasterlayer.h"
#include "qgsrasterlayerproperties.h"
#include "qgsrasternuller.h"
#include "qgsbrightnesscontrastfilter.h"
#include "qgsrasterrenderer.h"
#include "qgsrasterlayersaveasdialog.h"
#include "qgsrasterprojector.h"
#include "qgsrectangle.h"
#include "qgsscalevisibilitydialog.h"
#include "qgsgroupwmsdatadialog.h"
#include "qgsselectbyformdialog.h"
#include "qgsshortcutsmanager.h"
#include "qgssinglebandgrayrenderer.h"
#include "qgssnappingwidget.h"
#include "qgssourceselectdialog.h"
#include "qgssponsors.h"
#include "qgsstatisticalsummarydockwidget.h"
#include "qgsstatusbarcoordinateswidget.h"
#include "qgsstatusbarmagnifierwidget.h"
#include "qgsstatusbarscalewidget.h"
#include "qgsstyle.h"
#include "qgssvgannotation.h"
#include "qgstaskmanager.h"
#include "qgstaskmanagerwidget.h"
#include "qgssymbolselectordialog.h"
#include "qgstextannotation.h"
#include "qgstipgui.h"
#include "qgsundowidget.h"
#include "qgsuserinputdockwidget.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorfilewriter.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerproperties.h"
#include "qgsmapthemes.h"
#include "qgsmessagelogviewer.h"
#include "qgsdataitem.h"
#include "qgsmaplayeractionregistry.h"
#include "qgswelcomepage.h"
#include "qgsversioninfo.h"
#include "qgslegendfilterbutton.h"
#include "qgsvirtuallayerdefinition.h"
#include "qgsvirtuallayerdefinitionutils.h"
#include "qgstransaction.h"
#include "qgstransactiongroup.h"
#include "qgsvectorlayerjoininfo.h"
#include "qgsvectorlayerutils.h"
#include "qgshelp.h"
#include "qgsvectorfilewritertask.h"
#include "qgsnewnamedialog.h"
#include "qgssublayersdialog.h"
#include "ogr/qgsopenvectorlayerdialog.h"
#include "ogr/qgsvectorlayersaveasdialog.h"
#include "qgsosmdownloaddialog.h"
#include "qgsosmimportdialog.h"
#include "qgsosmexportdialog.h"
#ifdef ENABLE_MODELTEST
#include "modeltest.h"
#endif
//
// GDAL/OGR includes
//
#include <ogr_api.h>
#include <gdal_version.h>
#include <proj_api.h>
//
// Other includes
//
#include <algorithm>
#include <cassert>
#include <cmath>
#include <functional>
#include <iomanip>
#include <list>
#include <memory>
#include <vector>
//
// Map tools
//
#include "qgsmaptooladdfeature.h"
#include "qgsmaptooladdpart.h"
#include "qgsmaptooladdring.h"
#include "qgsmaptoolfillring.h"
#include "qgsmaptoolannotation.h"
#include "qgsmaptoolcircularstringcurvepoint.h"
#include "qgsmaptoolcircularstringradius.h"
#include "qgsmaptooldeletering.h"
#include "qgsmaptooldeletepart.h"
#include "qgsmaptoolfeatureaction.h"
#include "qgsmaptoolformannotation.h"
#include "qgsmaptoolhtmlannotation.h"
#include "qgsmaptoolidentifyaction.h"
#include "qgsmaptoolmeasureangle.h"
#include "qgsmaptoolmovefeature.h"
#include "qgsmaptoolrotatefeature.h"
#include "qgsmaptooloffsetcurve.h"
#include "qgsmaptooloffsetpointsymbol.h"
#include "qgsmaptoolpan.h"
#include "qgsmaptoolselect.h"
#include "qgsmaptoolselectrectangle.h"
#include "qgsmaptoolselectfreehand.h"
#include "qgsmaptoolselectpolygon.h"
#include "qgsmaptoolselectradius.h"
#include "qgsmaptoolsvgannotation.h"
#include "qgsmaptoolreshape.h"
#include "qgsmaptoolrotatepointsymbols.h"
#include "qgsmaptoolsplitfeatures.h"
#include "qgsmaptoolsplitparts.h"
#include "qgsmaptooltextannotation.h"
#include "qgsmaptoolzoom.h"
#include "qgsmaptoolsimplify.h"
#include "qgsmeasuretool.h"
#include "qgsmaptoolpinlabels.h"
#include "qgsmaptoolshowhidelabels.h"
#include "qgsmaptoolmovelabel.h"
#include "qgsmaptoolrotatelabel.h"
#include "qgsmaptoolchangelabelproperties.h"
#include "nodetool/qgsmaptoolnodetool.h"
// Editor widgets
#include "qgseditorwidgetregistry.h"
//
// Conditional Includes
//
#ifdef HAVE_PGCONFIG
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include <pg_config.h>
#else
#define PG_VERSION "unknown"
#endif
#include <sqlite3.h>
extern "C"
{
#include <spatialite.h>
}
#include "qgsnewspatialitelayerdialog.h"
#include "qgsnewgeopackagelayerdialog.h"
#ifdef WITH_BINDINGS
#include "qgspythonutils.h"
#endif
#ifndef Q_OS_WIN
#include <dlfcn.h>
#else
#include <windows.h>
#include <DbgHelp.h>
#endif
class QTreeWidgetItem;
/** Set the application title bar text
If the current project title is null
if the project file is null then
set title text to just application name and version
else
set set title text to the project file name
else
set the title text to project title
*/
static void setTitleBarText_( QWidget &qgisApp )
{
QString caption = QgisApp::tr( "QGIS " );
if ( Qgis::QGIS_VERSION.endsWith( QLatin1String( "Master" ) ) )
{
caption += QStringLiteral( "%1" ).arg( Qgis::QGIS_DEV_VERSION );
}
else
{
caption += Qgis::QGIS_VERSION;
}
if ( QgsProject::instance()->title().isEmpty() )
{
if ( QgsProject::instance()->fileName().isEmpty() )
{
// no project title nor file name, so just leave caption with
// application name and version
}
else
{
QFileInfo projectFileInfo( QgsProject::instance()->fileName() );
caption += " - " + projectFileInfo.completeBaseName();
}
}
else
{
caption += " - " + QgsProject::instance()->title();
}
qgisApp.setWindowTitle( caption );
} // setTitleBarText_( QWidget * qgisApp )
/**
Creator function for output viewer
*/
static QgsMessageOutput *messageOutputViewer_()
{
if ( QThread::currentThread() == qApp->thread() )
return new QgsMessageViewer( QgisApp::instance() );
else
return new QgsMessageOutputConsole();
}
static void customSrsValidation_( QgsCoordinateReferenceSystem &srs )
{
QgisApp::instance()->emitCustomCrsValidation( srs );
}
void QgisApp::emitCustomCrsValidation( QgsCoordinateReferenceSystem &srs )
{
emit customCrsValidation( srs );
}
void QgisApp::layerTreeViewDoubleClicked( const QModelIndex &index )
{
Q_UNUSED( index )
QgsSettings settings;
switch ( settings.value( QStringLiteral( "qgis/legendDoubleClickAction" ), 0 ).toInt() )
{
case 0:
{
//show properties
if ( mLayerTreeView )
{
// if it's a legend node, open symbol editor directly
if ( QgsSymbolLegendNode *node = dynamic_cast<QgsSymbolLegendNode *>( mLayerTreeView->currentLegendNode() ) )
{
const QgsSymbol *originalSymbol = node->symbol();
if ( !originalSymbol )
return;
std::unique_ptr< QgsSymbol > symbol( originalSymbol->clone() );
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( node->layerNode()->layer() );
QgsSymbolSelectorDialog dlg( symbol.get(), QgsStyle::defaultStyle(), vlayer, this );
QgsSymbolWidgetContext context;
context.setMapCanvas( mMapCanvas );
dlg.setContext( context );
if ( dlg.exec() )
{
node->setSymbol( symbol.release() );
}
return;
}
}
QgisApp::instance()->layerProperties();
break;
}
case 1:
QgisApp::instance()->attributeTable();
break;
case 2:
mapStyleDock( true );
break;
default:
break;
}
}
void QgisApp::activeLayerChanged( QgsMapLayer *layer )
{
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
canvas->setCurrentLayer( layer );
if ( mUndoWidget )
{
if ( layer )
{
mUndoWidget->setUndoStack( layer->undoStack() );
}
else
{
mUndoWidget->destroyStack();
}
updateUndoActions();
}
}
/**
* This function contains forced validation of CRS used in QGIS.
* There are 3 options depending on the settings:
* - ask for CRS using projection selecter
* - use project's CRS
* - use predefined global CRS
*/
void QgisApp::validateCrs( QgsCoordinateReferenceSystem &srs )
{
static QString sAuthId = QString::null;
QgsSettings mySettings;
QString myDefaultProjectionOption = mySettings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString();
if ( myDefaultProjectionOption == QLatin1String( "prompt" ) )
{
// @note this class is not a descendent of QWidget so we can't pass
// it in the ctor of the layer projection selector
QgsProjectionSelectionDialog *mySelector = new QgsProjectionSelectionDialog();
mySelector->setMessage( srs.validationHint() ); //shows a generic message, if not specified
if ( sAuthId.isNull() )
sAuthId = QgsProject::instance()->crs().authid();
QgsCoordinateReferenceSystem defaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( sAuthId );
if ( defaultCrs.isValid() )
{
mySelector->setCrs( defaultCrs );
}
bool waiting = QApplication::overrideCursor() && QApplication::overrideCursor()->shape() == Qt::WaitCursor;
if ( waiting )
QApplication::setOverrideCursor( Qt::ArrowCursor );
if ( mySelector->exec() )
{
QgsDebugMsg( "Layer srs set from dialog: " + QString::number( mySelector->crs().srsid() ) );
srs = mySelector->crs();
sAuthId = srs.authid();
}
if ( waiting )
QApplication::restoreOverrideCursor();
delete mySelector;
}
else if ( myDefaultProjectionOption == QLatin1String( "useProject" ) )
{
// XXX TODO: Change project to store selected CS as 'projectCRS' not 'selectedWkt'
sAuthId = QgsProject::instance()->crs().authid();
srs.createFromOgcWmsCrs( sAuthId );
QgsDebugMsg( "Layer srs set from project: " + sAuthId );
messageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to project CRS %1 - %2" ).arg( sAuthId, srs.description() ), QgsMessageBar::WARNING, messageTimeout() );
}
else ///Projections/defaultBehavior==useGlobal
{
sAuthId = mySettings.value( QStringLiteral( "Projections/layerDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
srs.createFromOgcWmsCrs( sAuthId );
QgsDebugMsg( "Layer srs set from default: " + sAuthId );
messageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to CRS %1 - %2" ).arg( sAuthId, srs.description() ), QgsMessageBar::WARNING, messageTimeout() );
}
}
static bool cmpByText_( QAction *a, QAction *b )
{
return QString::localeAwareCompare( a->text(), b->text() ) < 0;
}
QgisApp *QgisApp::sInstance = nullptr;
// constructor starts here
QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCheck, QWidget *parent, Qt::WindowFlags fl )
: QMainWindow( parent, fl )
, mNonEditMapTool( nullptr )
, mScaleWidget( nullptr )
, mMagnifierWidget( nullptr )
, mCoordsEdit( nullptr )
, mRotationLabel( nullptr )
, mRotationEdit( nullptr )
, mRotationEditValidator( nullptr )
, mProgressBar( nullptr )
, mRenderSuppressionCBox( nullptr )
, mOnTheFlyProjectionStatusLabel( nullptr )
, mOnTheFlyProjectionStatusButton( nullptr )
, mMessageButton( nullptr )
, mFeatureActionMenu( nullptr )
, mPopupMenu( nullptr )
, mDatabaseMenu( nullptr )
, mWebMenu( nullptr )
, mToolPopupOverviews( nullptr )
, mToolPopupDisplay( nullptr )
, mLayerTreeCanvasBridge( nullptr )
, mSplash( splash )
, mInternalClipboard( nullptr )
, mShowProjectionTab( false )
, mPythonUtils( nullptr )
, mSnappingWidget( nullptr )
, mMapStylingDock( nullptr )
, mComposerManager( nullptr )
, mpTileScaleWidget( nullptr )
, mpGpsWidget( nullptr )
, mTracer( nullptr )
, mSnappingUtils( nullptr )
, mProjectLastModified()
, mWelcomePage( nullptr )
, mCentralContainer( nullptr )
{
if ( sInstance )
{
QMessageBox::critical(
this,
tr( "Multiple Instances of QgisApp" ),
tr( "Multiple instances of QGIS application object detected.\nPlease contact the developers.\n" ) );
abort();
}
sInstance = this;
QgsRuntimeProfiler *profiler = QgsApplication::profiler();
namSetup();
// load GUI: actions, menus, toolbars
profiler->beginGroup( QStringLiteral( "qgisapp" ) );
profiler->beginGroup( QStringLiteral( "startup" ) );
startProfile( QStringLiteral( "Setting up UI" ) );
setupUi( this );
endProfile();
#if QT_VERSION >= 0x050600
setDockOptions( dockOptions() | QMainWindow::GroupedDragging ) ;
#endif
//////////
startProfile( QStringLiteral( "Checking database" ) );
mSplash->showMessage( tr( "Checking database" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
// Do this early on before anyone else opens it and prevents us copying it
QString dbError;
if ( !QgsApplication::createDatabase( &dbError ) )
{
QMessageBox::critical( this, tr( "Private qgis.db" ), dbError );
}
endProfile();
startProfile( QStringLiteral( "Initializing authentication" ) );
mSplash->showMessage( tr( "Initializing authentication" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
QgsAuthManager::instance()->init( QgsApplication::pluginPath() );
if ( !QgsAuthManager::instance()->isDisabled() )
{
masterPasswordSetup();
}
endProfile();
// Create the themes folder for the user
startProfile( QStringLiteral( "Creating theme folder" ) );
QgsApplication::createThemeFolder();
endProfile();
mSplash->showMessage( tr( "Reading settings" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
mSplash->showMessage( tr( "Setting up the GUI" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
QgsSettings settings;
startProfile( QStringLiteral( "Building style sheet" ) );
// set up stylesheet builder and apply saved or default style options
mStyleSheetBuilder = new QgisAppStyleSheet( this );
connect( mStyleSheetBuilder, &QgisAppStyleSheet::appStyleSheetChanged,
this, &QgisApp::setAppStyleSheet );
mStyleSheetBuilder->buildStyleSheet( mStyleSheetBuilder->defaultOptions() );
endProfile();
QWidget *centralWidget = this->centralWidget();
QGridLayout *centralLayout = new QGridLayout( centralWidget );
centralWidget->setLayout( centralLayout );
centralLayout->setContentsMargins( 0, 0, 0, 0 );
// "theMapCanvas" used to find this canonical instance later
startProfile( QStringLiteral( "Creating map canvas" ) );
mMapCanvas = new QgsMapCanvas( centralWidget );
mMapCanvas->setObjectName( QStringLiteral( "theMapCanvas" ) );
connect( mMapCanvas, &QgsMapCanvas::messageEmitted, this, &QgisApp::displayMessage );
mMapCanvas->setWhatsThis( tr( "Map canvas. This is where raster and vector "
"layers are displayed when added to the map" ) );
// set canvas color right away
int myRed = settings.value( QStringLiteral( "qgis/default_canvas_color_red" ), 255 ).toInt();
int myGreen = settings.value( QStringLiteral( "qgis/default_canvas_color_green" ), 255 ).toInt();
int myBlue = settings.value( QStringLiteral( "qgis/default_canvas_color_blue" ), 255 ).toInt();
mMapCanvas->setCanvasColor( QColor( myRed, myGreen, myBlue ) );
endProfile();
// what type of project to auto-open
mProjOpen = settings.value( QStringLiteral( "qgis/projOpenAtLaunch" ), 0 ).toInt();
startProfile( QStringLiteral( "Welcome page" ) );
mWelcomePage = new QgsWelcomePage( skipVersionCheck );
endProfile();
mCentralContainer = new QStackedWidget;
mCentralContainer->insertWidget( 0, mMapCanvas );
mCentralContainer->insertWidget( 1, mWelcomePage );
centralLayout->addWidget( mCentralContainer, 0, 0, 2, 1 );
connect( mMapCanvas, &QgsMapCanvas::layersChanged, this, &QgisApp::showMapCanvas );
mCentralContainer->setCurrentIndex( mProjOpen ? 0 : 1 );
// a bar to warn the user with non-blocking messages
startProfile( QStringLiteral( "Message bar" ) );
mInfoBar = new QgsMessageBar( centralWidget );
mInfoBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
centralLayout->addWidget( mInfoBar, 0, 0, 1, 1 );
endProfile();
startProfile( QStringLiteral( "User input dock" ) );
// User Input Dock Widget
mUserInputDockWidget = new QgsUserInputDockWidget( this );
mUserInputDockWidget->setObjectName( QStringLiteral( "UserInputDockWidget" ) );
endProfile();
//set the focus to the map canvas
mMapCanvas->setFocus();
startProfile( QStringLiteral( "Layer tree" ) );
mLayerTreeView = new QgsLayerTreeView( this );
mLayerTreeView->setObjectName( QStringLiteral( "theLayerTreeView" ) ); // "theLayerTreeView" used to find this canonical instance later
endProfile();
// create undo widget
startProfile( QStringLiteral( "Undo dock" ) );
mUndoDock = new QgsDockWidget( tr( "Undo/Redo Panel" ), this );
mUndoWidget = new QgsUndoWidget( mUndoDock, mMapCanvas );
mUndoWidget->setObjectName( QStringLiteral( "Undo" ) );
mUndoDock->setWidget( mUndoWidget );
mUndoDock->setObjectName( QStringLiteral( "undo/redo dock" ) );
endProfile();
// Advanced Digitizing dock
startProfile( QStringLiteral( "Advanced digitize panel" ) );
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
mAdvancedDigitizingDockWidget->setObjectName( QStringLiteral( "AdvancedDigitizingTools" ) );
endProfile();
// Statistical Summary dock
startProfile( QStringLiteral( "Stats dock" ) );
mStatisticalSummaryDockWidget = new QgsStatisticalSummaryDockWidget( this );
mStatisticalSummaryDockWidget->setObjectName( QStringLiteral( "StatistalSummaryDockWidget" ) );
endProfile();
// Bookmarks dock
startProfile( QStringLiteral( "Bookmarks widget" ) );
mBookMarksDockWidget = new QgsBookmarks( this );
mBookMarksDockWidget->setObjectName( QStringLiteral( "BookmarksDockWidget" ) );
endProfile();
startProfile( QStringLiteral( "Snapping utils" ) );
mSnappingUtils = new QgsMapCanvasSnappingUtils( mMapCanvas, this );
mMapCanvas->setSnappingUtils( mSnappingUtils );
connect( QgsProject::instance(), &QgsProject::snappingConfigChanged, mSnappingUtils, &QgsSnappingUtils::setConfig );
connect( mSnappingUtils, &QgsSnappingUtils::configChanged, QgsProject::instance(), &QgsProject::setSnappingConfig );
endProfile();
functionProfile( &QgisApp::createActions, this, QStringLiteral( "Create actions" ) );
functionProfile( &QgisApp::createActionGroups, this, QStringLiteral( "Create action group" ) );
functionProfile( &QgisApp::createMenus, this, QStringLiteral( "Create menus" ) );
functionProfile( &QgisApp::createToolBars, this, QStringLiteral( "Toolbars" ) );
functionProfile( &QgisApp::createStatusBar, this, QStringLiteral( "Status bar" ) );
functionProfile( &QgisApp::createCanvasTools, this, QStringLiteral( "Create canvas tools" ) );
mMapCanvas->freeze();
applyDefaultSettingsToCanvas( mMapCanvas );
functionProfile( &QgisApp::initLayerTreeView, this, QStringLiteral( "Init Layer tree view" ) );
functionProfile( &QgisApp::createOverview, this, QStringLiteral( "Create overview" ) );
functionProfile( &QgisApp::createMapTips, this, QStringLiteral( "Create map tips" ) );
functionProfile( &QgisApp::createDecorations, this, QStringLiteral( "Create decorations" ) );
functionProfile( &QgisApp::readSettings, this, QStringLiteral( "Read settings" ) );
functionProfile( &QgisApp::updateRecentProjectPaths, this, QStringLiteral( "Update recent project paths" ) );
functionProfile( &QgisApp::updateProjectFromTemplates, this, QStringLiteral( "Update project from templates" ) );
functionProfile( &QgisApp::legendLayerSelectionChanged, this, QStringLiteral( "Legend layer selection changed" ) );
QgsApplication::annotationRegistry()->addAnnotationType( QgsAnnotationMetadata( QStringLiteral( "FormAnnotationItem" ), &QgsFormAnnotation::create ) );
connect( QgsProject::instance()->annotationManager(), &QgsAnnotationManager::annotationAdded, this, &QgisApp::annotationCreated );
mSaveRollbackInProgress = false;
QString templateDirName = settings.value( QStringLiteral( "qgis/projectTemplateDir" ),
QgsApplication::qgisSettingsDirPath() + "project_templates" ).toString();
if ( !QFileInfo::exists( templateDirName ) )
{
// create default template directory
if ( !QDir().mkdir( QgsApplication::qgisSettingsDirPath() + "project_templates" ) )
templateDirName.clear();
}
if ( !templateDirName.isEmpty() ) // template directory exists, so watch it!
{
QFileSystemWatcher *projectsTemplateWatcher = new QFileSystemWatcher( this );
projectsTemplateWatcher->addPath( templateDirName );
connect( projectsTemplateWatcher, &QFileSystemWatcher::directoryChanged, this, [this] { updateProjectFromTemplates(); } );
}
// initialize the plugin manager
startProfile( QStringLiteral( "Plugin manager" ) );
mPluginManager = new QgsPluginManager( this, restorePlugins );
endProfile();
addDockWidget( Qt::LeftDockWidgetArea, mUndoDock );
mUndoDock->hide();
startProfile( QStringLiteral( "Layer Style dock" ) );
mMapStylingDock = new QgsDockWidget( this );
mMapStylingDock->setWindowTitle( tr( "Layer Styling" ) );
mMapStylingDock->setObjectName( QStringLiteral( "LayerStyling" ) );
mMapStyleWidget = new QgsLayerStylingWidget( mMapCanvas, mMapLayerPanelFactories );
mMapStylingDock->setWidget( mMapStyleWidget );
connect( mMapStyleWidget, &QgsLayerStylingWidget::styleChanged, this, &QgisApp::updateLabelToolButtons );
connect( mMapStylingDock, &QDockWidget::visibilityChanged, mActionStyleDock, &QAction::setChecked );
addDockWidget( Qt::RightDockWidgetArea, mMapStylingDock );
mMapStylingDock->hide();
endProfile();
startProfile( QStringLiteral( "Snapping dialog" ) );
mSnappingDialogWidget = new QgsSnappingWidget( QgsProject::instance(), mMapCanvas, this );
QString mainSnappingWidgetMode = QgsSettings().value( QStringLiteral( "/qgis/mainSnappingWidgetMode" ), "dialog" ).toString();
if ( mainSnappingWidgetMode == QLatin1String( "dock" ) )
{
QgsDockWidget *dock = new QgsDockWidget( tr( "Snapping and Digitizing Options" ), QgisApp::instance() );
dock->setAllowedAreas( Qt::AllDockWidgetAreas );
dock->setWidget( mSnappingDialogWidget );
dock->setObjectName( QStringLiteral( "Snapping and Digitizing Options" ) );
addDockWidget( Qt::LeftDockWidgetArea, dock );
mSnappingDialogContainer = dock;
dock->hide();
}
else
{
QDialog *dialog = new QDialog( this );
dialog->setWindowTitle( tr( "Project snapping settings" ) );
QVBoxLayout *layout = new QVBoxLayout( dialog );
layout->addWidget( mSnappingDialogWidget );
layout->setMargin( 0 );
mSnappingDialogContainer = dialog;
}
endProfile();
mBrowserWidget = new QgsBrowserDockWidget( tr( "Browser Panel" ), this );
mBrowserWidget->setObjectName( QStringLiteral( "Browser" ) );
addDockWidget( Qt::LeftDockWidgetArea, mBrowserWidget );
mBrowserWidget->hide();
mBrowserWidget2 = new QgsBrowserDockWidget( tr( "Browser Panel (2)" ), this );
mBrowserWidget2->setObjectName( QStringLiteral( "Browser2" ) );
addDockWidget( Qt::LeftDockWidgetArea, mBrowserWidget2 );
mBrowserWidget2->hide();
addDockWidget( Qt::LeftDockWidgetArea, mAdvancedDigitizingDockWidget );
mAdvancedDigitizingDockWidget->hide();
addDockWidget( Qt::LeftDockWidgetArea, mStatisticalSummaryDockWidget );
mStatisticalSummaryDockWidget->hide();
addDockWidget( Qt::LeftDockWidgetArea, mBookMarksDockWidget );
mBookMarksDockWidget->hide();
QMainWindow::addDockWidget( Qt::BottomDockWidgetArea, mUserInputDockWidget );
mUserInputDockWidget->setFloating( true );
// create the GPS tool on starting QGIS - this is like the browser
mpGpsWidget = new QgsGPSInformationWidget( mMapCanvas );
//create the dock widget
mpGpsDock = new QgsDockWidget( tr( "GPS Information Panel" ), this );
mpGpsDock->setObjectName( QStringLiteral( "GPSInformation" ) );
mpGpsDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
addDockWidget( Qt::LeftDockWidgetArea, mpGpsDock );
// add to the Panel submenu
// now add our widget to the dock - ownership of the widget is passed to the dock
mpGpsDock->setWidget( mpGpsWidget );
mpGpsDock->hide();
mLastMapToolMessage = nullptr;
mLogViewer = new QgsMessageLogViewer( statusBar(), this );
mLogDock = new QgsDockWidget( tr( "Log Messages Panel" ), this );
mLogDock->setObjectName( QStringLiteral( "MessageLog" ) );
mLogDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea );
addDockWidget( Qt::BottomDockWidgetArea, mLogDock );
mLogDock->setWidget( mLogViewer );
mLogDock->hide();
connect( mMessageButton, &QAbstractButton::toggled, mLogDock, &QWidget::setVisible );
connect( mLogDock, &QDockWidget::visibilityChanged, mMessageButton, &QAbstractButton::setChecked );
connect( QgsApplication::messageLog(), static_cast < void ( QgsMessageLog::* )( bool ) >( &QgsMessageLog::messageReceived ), this, &QgisApp::toggleLogMessageIcon );
connect( mMessageButton, &QAbstractButton::toggled, this, &QgisApp::toggleLogMessageIcon );
mVectorLayerTools = new QgsGuiVectorLayerTools();
// Init the editor widget types
QgsEditorWidgetRegistry::initEditors( mMapCanvas, mInfoBar );
mInternalClipboard = new QgsClipboard; // create clipboard
connect( mInternalClipboard, &QgsClipboard::changed, this, &QgisApp::clipboardChanged );
mQgisInterface = new QgisAppInterface( this ); // create the interfce
#ifdef Q_OS_MAC
// action for Window menu (create before generating WindowTitleChange event))
mWindowAction = new QAction( this );
connect( mWindowAction, SIGNAL( triggered() ), this, SLOT( activate() ) );
// add this window to Window menu
addWindow( mWindowAction );
#endif
activateDeactivateLayerRelatedActions( nullptr ); // after members were created
connect( QgsMapLayerActionRegistry::instance(), &QgsMapLayerActionRegistry::changed, this, &QgisApp::refreshActionFeatureAction );
// set application's caption
QString caption = tr( "QGIS - %1 ('%2')" ).arg( Qgis::QGIS_VERSION, Qgis::QGIS_RELEASE_NAME );
setWindowTitle( caption );
QgsMessageLog::logMessage( tr( "QGIS starting..." ), QString::null, QgsMessageLog::INFO );
// set QGIS specific srs validation
connect( this, &QgisApp::customCrsValidation,
this, &QgisApp::validateCrs );
QgsCoordinateReferenceSystem::setCustomCrsValidation( customSrsValidation_ );
// set graphical message output
QgsMessageOutput::setMessageOutputCreator( messageOutputViewer_ );
// set graphical credential requester
new QgsCredentialDialog( this );
qApp->processEvents();
// load providers
mSplash->showMessage( tr( "Checking provider plugins" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
QgsApplication::initQgis();
mSplash->showMessage( tr( "Starting Python" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
loadPythonSupport();
// Create the plugin registry and load plugins
// load any plugins that were running in the last session
mSplash->showMessage( tr( "Restoring loaded plugins" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
QgsPluginRegistry::instance()->setQgisInterface( mQgisInterface );
if ( restorePlugins )
{
// Restoring of plugins can be disabled with --noplugins command line option
// because some plugins may cause QGIS to crash during startup
QgsPluginRegistry::instance()->restoreSessionPlugins( QgsApplication::pluginPath() );
// Also restore plugins from user specified plugin directories
QString myPaths = settings.value( QStringLiteral( "plugins/searchPathsForPlugins" ), "" ).toString();
if ( !myPaths.isEmpty() )
{
QStringList myPathList = myPaths.split( '|' );
QgsPluginRegistry::instance()->restoreSessionPlugins( myPathList );
}
}
#ifdef WITH_BINDINGS
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
startProfile( QStringLiteral( "initPluginInstaller" ) );
// initialize the plugin installer to start fetching repositories in background
QgsPythonRunner::run( QStringLiteral( "import pyplugin_installer" ) );
QgsPythonRunner::run( QStringLiteral( "pyplugin_installer.initPluginInstaller()" ) );
// enable Python in the Plugin Manager and pass the PythonUtils to it
mPluginManager->setPythonUtils( mPythonUtils );
endProfile();
}
else if ( mActionShowPythonDialog || mActionInstallFromZip )
#endif
{
// python is disabled so get rid of the action for python console
// and installing plugin from ZUIP
delete mActionShowPythonDialog;
delete mActionInstallFromZip;
mActionShowPythonDialog = nullptr;
mActionInstallFromZip = nullptr;
}
// Set icon size of toolbars
int size = settings.value( QStringLiteral( "IconSize" ), QGIS_ICON_SIZE ).toInt();
setIconSizes( size );
mSplash->showMessage( tr( "Initializing file filters" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
// now build vector and raster file filters
mVectorFileFilter = QgsProviderRegistry::instance()->fileVectorFilters();
mRasterFileFilter = QgsProviderRegistry::instance()->fileRasterFilters();
// set handler for missing layers (will be owned by QgsProject)
QgsProject::instance()->setBadLayerHandler( new QgsHandleBadLayersHandler() );
#if 0
// Set the background color for toolbox and overview as they default to
// white instead of the window color
QPalette myPalette = toolBox->palette();
myPalette.setColor( QPalette::Button, myPalette.window().color() );
toolBox->setPalette( myPalette );
//do the same for legend control
myPalette = toolBox->palette();
myPalette.setColor( QPalette::Button, myPalette.window().color() );
mMapLegend->setPalette( myPalette );
//and for overview control this is done in createOverView method
#endif
// Do this last in the ctor to ensure that all members are instantiated properly
setupConnections();
//
// Please make sure this is the last thing the ctor does so that we can ensure the
// widgets are all initialized before trying to restore their state.
//
mSplash->showMessage( tr( "Restoring window state" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
startProfile( QStringLiteral( "Restore window state" ) );
restoreWindowState();
endProfile();
// do main window customization - after window state has been restored, before the window is shown
startProfile( QStringLiteral( "Update customiziation on main window" ) );
QgsCustomization::instance()->updateMainWindow( mToolbarMenu );
endProfile();
mSplash->showMessage( tr( "Populate saved styles" ), Qt::AlignHCenter | Qt::AlignBottom );
startProfile( QStringLiteral( "Populate saved styles" ) );
QgsStyle::defaultStyle();
endProfile();
mSplash->showMessage( tr( "QGIS Ready!" ), Qt::AlignHCenter | Qt::AlignBottom );
QgsMessageLog::logMessage( QgsApplication::showSettings(), QString::null, QgsMessageLog::INFO );
QgsMessageLog::logMessage( tr( "QGIS Ready!" ), QString::null, QgsMessageLog::INFO );
mMapTipsVisible = false;
// This turns on the map tip if they where active in the last session
if ( settings.value( QStringLiteral( "qgis/enableMapTips" ), false ).toBool() )
{
toggleMapTips( true );
}
mTrustedMacros = false;
// setup drag drop
setAcceptDrops( true );
mFullScreenMode = false;
mPrevScreenModeMaximized = false;
startProfile( QStringLiteral( "Show main window" ) );
show();
qApp->processEvents();
endProfile();
mMapCanvas->freeze( false );
mMapCanvas->clearExtentHistory(); // reset zoomnext/zoomlast
QShortcut *zoomInShortCut = new QShortcut( QKeySequence( tr( "Ctrl++" ) ), this );
connect( zoomInShortCut, &QShortcut::activated, mMapCanvas, &QgsMapCanvas::zoomIn );
zoomInShortCut->setObjectName( QStringLiteral( "ZoomInToCanvas" ) );
zoomInShortCut->setWhatsThis( tr( "Zoom in to canvas" ) );
zoomInShortCut->setProperty( "Icon", QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ) );
QShortcut *zoomShortCut2 = new QShortcut( QKeySequence( tr( "Ctrl+=" ) ), this );
connect( zoomShortCut2, &QShortcut::activated, mMapCanvas, &QgsMapCanvas::zoomIn );
zoomShortCut2->setObjectName( QStringLiteral( "ZoomInToCanvas2" ) );
zoomShortCut2->setWhatsThis( tr( "Zoom in to canvas (secondary)" ) );
zoomShortCut2->setProperty( "Icon", QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ) );
QShortcut *zoomOutShortCut = new QShortcut( QKeySequence( tr( "Ctrl+-" ) ), this );
connect( zoomOutShortCut, &QShortcut::activated, mMapCanvas, &QgsMapCanvas::zoomOut );
zoomOutShortCut->setObjectName( QStringLiteral( "ZoomOutOfCanvas" ) );
zoomOutShortCut->setWhatsThis( tr( "Zoom out of canvas" ) );
zoomOutShortCut->setProperty( "Icon", QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomOut.svg" ) ) );
//also make ctrl+alt+= a shortcut to switch to zoom in map tool
QShortcut *zoomInToolShortCut = new QShortcut( QKeySequence( tr( "Ctrl+Alt+=" ) ), this );
connect( zoomInToolShortCut, &QShortcut::activated, this, &QgisApp::zoomIn );
zoomInToolShortCut->setObjectName( QStringLiteral( "ZoomIn2" ) );
zoomInToolShortCut->setWhatsThis( tr( "Zoom in (secondary)" ) );
zoomInToolShortCut->setProperty( "Icon", QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ) );
QShortcut *toggleSnapping = new QShortcut( QKeySequence( tr( "S" ) ), this );
toggleSnapping->setObjectName( "toggleSnapping" );
toggleSnapping->setWhatsThis( tr( "Toggle snapping" ) );
toggleSnapping->setProperty( "Icon", QgsApplication::getThemeIcon( "/mIconSnapping.svg" ) );
connect( toggleSnapping, &QShortcut::activated, mSnappingUtils, &QgsSnappingUtils::toggleEnabled );
// Show a nice tip of the day
if ( settings.value( QStringLiteral( "qgis/showTips%1" ).arg( Qgis::QGIS_VERSION_INT / 100 ), true ).toBool() )
{
mSplash->hide();
QgsTipGui myTip( this );
myTip.exec();
}
else
{
QgsDebugMsg( "Tips are disabled" );
}
if ( ! QTouchDevice::devices().isEmpty() )
{
//add reacting to long click in touch
grabGesture( Qt::TapAndHoldGesture );
}
mTray = new QSystemTrayIcon();
mTray->setIcon( QIcon( QgsApplication::appIconPath() ) );
mTray->hide();
connect( QgsApplication::taskManager(), &QgsTaskManager::statusChanged, this, &QgisApp::onTaskCompleteShowNotify );
#ifdef Q_OS_WIN
QWinTaskbarButton *taskButton = new QWinTaskbarButton( this );
taskButton->setWindow( windowHandle() );
QWinTaskbarProgress *taskProgress = taskButton->progress();
taskProgress->setVisible( false );
connect( QgsApplication::taskManager(), &QgsTaskManager::taskAdded, taskProgress, [taskProgress] { taskProgress->setMaximum( 0 ); taskProgress->show(); }
);
connect( QgsApplication::taskManager(), &QgsTaskManager::finalTaskProgressChanged, taskProgress, [taskProgress]( double val ) { taskProgress->setMaximum( 100 ); taskProgress->show(); taskProgress->setValue( val ); }
);
connect( QgsApplication::taskManager(), &QgsTaskManager::allTasksFinished, taskProgress, &QWinTaskbarProgress::hide );
#endif
// supposedly all actions have been added, now register them to the shortcut manager
QgsShortcutsManager::instance()->registerAllChildren( this );
QgsProviderRegistry::instance()->registerGuis( this );
setupLayoutManagerConnections();
// update windows
qApp->processEvents();
// notify user if authentication system is disabled
( void )QgsAuthGuiUtils::isDisabled( messageBar() );
startProfile( QStringLiteral( "New project" ) );
fileNewBlank(); // prepare empty project, also skips any default templates from loading
endProfile();
// request notification of FileOpen events (double clicking a file icon in Mac OS X Finder)
// should come after fileNewBlank to ensure project is properly set up to receive any data source files
QgsApplication::setFileOpenEventReceiver( this );
#ifdef ANDROID
toggleFullScreen();
#endif
profiler->endGroup();
QgsDebugMsg( "PROFILE TIMES" );
QgsDebugMsg( QString( "PROFILE TIMES TOTAL - %1 " ).arg( profiler->totalTime() ) );
#ifdef QGISDEBUG
QList<QPair<QString, double> > profileTimes = profiler->profileTimes();
QList<QPair<QString, double> >::const_iterator it = profileTimes.constBegin();
for ( ; it != profileTimes.constEnd(); ++it )
{
QString name = ( *it ).first;
double time = ( *it ).second;
QgsDebugMsg( QString( " - %1 - %2" ).arg( name ).arg( time ) );
}
#endif
} // QgisApp ctor
QgisApp::QgisApp()
: QMainWindow( nullptr, 0 )
, mStyleSheetBuilder( nullptr )
, mActionPluginSeparator1( nullptr )
, mActionPluginSeparator2( nullptr )
, mActionRasterSeparator( nullptr )
, mMapToolGroup( nullptr )
, mPreviewGroup( nullptr )
#ifdef Q_OS_MAC
, mWindowMenu( 0 )
#endif
, mPanelMenu( nullptr )
, mToolbarMenu( nullptr )
, mLayerTreeDock( nullptr )
, mLayerOrderDock( nullptr )
, mOverviewDock( nullptr )
, mpGpsDock( nullptr )
, mLogDock( nullptr )
, mNonEditMapTool( nullptr )
, mTaskManagerWidget( nullptr )
, mScaleWidget( nullptr )
, mMagnifierWidget( nullptr )
, mCoordsEdit( nullptr )
, mRotationLabel( nullptr )
, mRotationEdit( nullptr )
, mRotationEditValidator( nullptr )
, mProgressBar( nullptr )
, mRenderSuppressionCBox( nullptr )
, mOnTheFlyProjectionStatusLabel( nullptr )
, mOnTheFlyProjectionStatusButton( nullptr )
, mMessageButton( nullptr )
, mFeatureActionMenu( nullptr )
, mPopupMenu( nullptr )
, mDatabaseMenu( nullptr )
, mWebMenu( nullptr )
, mToolPopupOverviews( nullptr )
, mToolPopupDisplay( nullptr )
, mMapCanvas( nullptr )
, mOverviewCanvas( nullptr )
, mLayerTreeView( nullptr )
, mLayerTreeCanvasBridge( nullptr )
, mMapLayerOrder( nullptr )
, mOverviewMapCursor( nullptr )
, mMapWindow( nullptr )
, mQgisInterface( nullptr )
, mSplash( nullptr )
, mInternalClipboard( nullptr )
, mShowProjectionTab( false )
, mpMapTipsTimer( nullptr )
, mpMaptip( nullptr )
, mMapTipsVisible( false )
, mFullScreenMode( false )
, mPrevScreenModeMaximized( false )
, mSaveRollbackInProgress( false )
, mPythonUtils( nullptr )
, mUndoWidget( nullptr )
, mUndoDock( nullptr )
, mBrowserWidget( nullptr )
, mBrowserWidget2( nullptr )
, mAdvancedDigitizingDockWidget( nullptr )
, mStatisticalSummaryDockWidget( nullptr )
, mBookMarksDockWidget( nullptr )
, mSnappingWidget( nullptr )
, mSnappingDialogContainer( nullptr )
, mSnappingDialogWidget( nullptr )
, mPluginManager( nullptr )
, mMapStylingDock( nullptr )
, mMapStyleWidget( nullptr )
, mComposerManager( nullptr )
, mpTileScaleWidget( nullptr )
, mpGpsWidget( nullptr )
, mLastMapToolMessage( nullptr )
, mLogViewer( nullptr )
, mTrustedMacros( false )
, mMacrosWarn( nullptr )
, mUserInputDockWidget( nullptr )
, mVectorLayerTools( nullptr )
, mTracer( nullptr )
, mActionFilterLegend( nullptr )
, mActionStyleDock( nullptr )
, mLegendExpressionFilterButton( nullptr )
, mSnappingUtils( nullptr )
, mProjectLastModified()
, mWelcomePage( nullptr )
, mCentralContainer( nullptr )
, mProjOpen( 0 )
{
sInstance = this;
setupUi( this );
mInternalClipboard = new QgsClipboard;
mMapCanvas = new QgsMapCanvas();
connect( mMapCanvas, &QgsMapCanvas::messageEmitted, this, &QgisApp::displayMessage );
mMapCanvas->freeze();
mLayerTreeView = new QgsLayerTreeView( this );
mUndoWidget = new QgsUndoWidget( nullptr, mMapCanvas );
mInfoBar = new QgsMessageBar( centralWidget() );
// More tests may need more members to be initialized
}
QgisApp::~QgisApp()
{
stopRendering();
delete mInternalClipboard;
delete mQgisInterface;
delete mStyleSheetBuilder;
delete mMapTools.mZoomIn;
delete mMapTools.mZoomOut;
delete mMapTools.mPan;
delete mMapTools.mAddFeature;
delete mMapTools.mAddPart;
delete mMapTools.mAddRing;
delete mMapTools.mFillRing;
delete mMapTools.mAnnotation;
delete mMapTools.mChangeLabelProperties;
delete mMapTools.mDeletePart;
delete mMapTools.mDeleteRing;
delete mMapTools.mFeatureAction;
delete mMapTools.mFormAnnotation;
delete mMapTools.mHtmlAnnotation;
delete mMapTools.mIdentify;
delete mMapTools.mMeasureAngle;
delete mMapTools.mMeasureArea;
delete mMapTools.mMeasureDist;
delete mMapTools.mMoveFeature;
delete mMapTools.mMoveFeatureCopy;
delete mMapTools.mMoveLabel;
delete mMapTools.mNodeTool;
delete mMapTools.mOffsetCurve;
delete mMapTools.mPinLabels;
delete mMapTools.mReshapeFeatures;
delete mMapTools.mRotateFeature;
delete mMapTools.mRotateLabel;
delete mMapTools.mRotatePointSymbolsTool;
delete mMapTools.mOffsetPointSymbolTool;
delete mMapTools.mSelectFreehand;
delete mMapTools.mSelectPolygon;
delete mMapTools.mSelectRadius;
delete mMapTools.mSelectFeatures;
delete mMapTools.mShowHideLabels;
delete mMapTools.mSimplifyFeature;
delete mMapTools.mSplitFeatures;
delete mMapTools.mSplitParts;
delete mMapTools.mSvgAnnotation;
delete mMapTools.mTextAnnotation;
delete mMapTools.mCircularStringCurvePoint;
delete mMapTools.mCircularStringRadius;
delete mpMaptip;
delete mpGpsWidget;
delete mOverviewMapCursor;
delete mComposerManager;
delete mTracer;
delete mVectorLayerTools;
delete mWelcomePage;
deletePrintComposers();
removeAnnotationItems();
// cancel request for FileOpen events
QgsApplication::setFileOpenEventReceiver( nullptr );
QgsApplication::exitQgis();
delete QgsProject::instance();
delete mPythonUtils;
delete mTray;
}
void QgisApp::dragEnterEvent( QDragEnterEvent *event )
{
if ( event->mimeData()->hasUrls() || event->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
{
// the mime data are coming from layer tree, so ignore that, do not import those layers again
if ( !event->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) )
event->acceptProposedAction();
}
}
void QgisApp::dropEvent( QDropEvent *event )
{
// dragging app is locked for the duration of dropEvent. This causes explorer windows to hang
// while large projects/layers are loaded. So instead we return from dropEvent as quickly as possible
// and do the actual handling of the drop after a very short timeout
QTimer *timer = new QTimer( this );
timer->setSingleShot( true );
timer->setInterval( 50 );
// get the file list
QList<QUrl>::iterator i;
QList<QUrl>urls = event->mimeData()->urls();
QStringList files;
for ( i = urls.begin(); i != urls.end(); ++i )
{
QString fileName = i->toLocalFile();
#ifdef Q_OS_MAC
// Mac OS X 10.10, under Qt4.8 ,changes dropped URL format
// https://bugreports.qt.io/browse/QTBUG-40449
// [pzion 20150805] Work around
if ( fileName.startsWith( "/.file/id=" ) )
{
QgsDebugMsg( "Mac dropped URL with /.file/id= (converting)" );
CFStringRef relCFStringRef =
CFStringCreateWithCString(
kCFAllocatorDefault,
fileName.toUtf8().constData(),
kCFStringEncodingUTF8
);
CFURLRef relCFURL =
CFURLCreateWithFileSystemPath(
kCFAllocatorDefault,
relCFStringRef,
kCFURLPOSIXPathStyle,
false // isDirectory
);
CFErrorRef error = 0;
CFURLRef absCFURL =
CFURLCreateFilePathURL(
kCFAllocatorDefault,
relCFURL,
&error
);
if ( !error )
{
static const CFIndex maxAbsPathCStrBufLen = 4096;
char absPathCStr[maxAbsPathCStrBufLen];
if ( CFURLGetFileSystemRepresentation(
absCFURL,
true, // resolveAgainstBase
reinterpret_cast<UInt8 *>( &absPathCStr[0] ),
maxAbsPathCStrBufLen ) )
{
fileName = QString( absPathCStr );
}
}
CFRelease( absCFURL );
CFRelease( relCFURL );
CFRelease( relCFStringRef );
}
#endif
// seems that some drag and drop operations include an empty url
// so we test for length to make sure we have something
if ( !fileName.isEmpty() )
{
files << fileName;
}
}
timer->setProperty( "files", files );
QgsMimeDataUtils::UriList lst;
if ( QgsMimeDataUtils::isUriList( event->mimeData() ) )
{
lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
}
timer->setProperty( "uris", QVariant::fromValue( lst ) );
connect( timer, &QTimer::timeout, this, &QgisApp::dropEventTimeout );
event->acceptProposedAction();
timer->start();
}
void QgisApp::dropEventTimeout()
{
freezeCanvases();
QStringList files = sender()->property( "files" ).toStringList();
sender()->deleteLater();
Q_FOREACH ( const QString &file, files )
{
openFile( file );
}
QgsMimeDataUtils::UriList lst = sender()->property( "uris" ).value<QgsMimeDataUtils::UriList>();
if ( !lst.isEmpty() )
{
handleDropUriList( lst );
}
freezeCanvases( false );
refreshMapCanvas();
}
void QgisApp::annotationCreated( QgsAnnotation *annotation )
{
// create canvas annotation item for annotation
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
{
QgsMapCanvasAnnotationItem *canvasItem = new QgsMapCanvasAnnotationItem( annotation, canvas );
Q_UNUSED( canvasItem ); //item is already added automatically to canvas scene
}
}
void QgisApp::registerCustomDropHandler( QgsCustomDropHandler *handler )
{
if ( !mCustomDropHandlers.contains( handler ) )
mCustomDropHandlers << handler;
}
void QgisApp::unregisterCustomDropHandler( QgsCustomDropHandler *handler )
{
mCustomDropHandlers.removeOne( handler );
}
void QgisApp::handleDropUriList( const QgsMimeDataUtils::UriList &lst )
{
Q_FOREACH ( const QgsMimeDataUtils::Uri &u, lst )
{
QString uri = crsAndFormatAdjustedLayerUri( u.uri, u.supportedCrs, u.supportedFormats );
if ( u.layerType == QLatin1String( "vector" ) )
{
addVectorLayer( uri, u.name, u.providerKey );
}
else if ( u.layerType == QLatin1String( "raster" ) )
{
addRasterLayer( uri, u.name, u.providerKey );
}
else if ( u.layerType == QLatin1String( "plugin" ) )
{
addPluginLayer( uri, u.name, u.providerKey );
}
else if ( u.layerType == QLatin1String( "custom" ) )
{
Q_FOREACH ( QgsCustomDropHandler *handler, mCustomDropHandlers )
{
if ( handler->key() == u.providerKey )
{
handler->handleDrop( u );
break;
}
}
}
}
}
bool QgisApp::event( QEvent *event )
{
bool done = false;
if ( event->type() == QEvent::FileOpen )
{
// handle FileOpen event (double clicking a file icon in Mac OS X Finder)
QFileOpenEvent *foe = static_cast<QFileOpenEvent *>( event );
openFile( foe->file() );
done = true;
}
else if ( !QTouchDevice::devices().isEmpty() && event->type() == QEvent::Gesture )
{
done = gestureEvent( static_cast<QGestureEvent *>( event ) );
}
else
{
// pass other events to base class
done = QMainWindow::event( event );
}
return done;
}
QgisAppStyleSheet *QgisApp::styleSheetBuilder()
{
Q_ASSERT( mStyleSheetBuilder );
return mStyleSheetBuilder;
}
void QgisApp::readRecentProjects()
{
QgsSettings settings;
mRecentProjects.clear();
settings.beginGroup( QStringLiteral( "UI" ) );
// Migrate old recent projects if first time with new system
if ( !settings.childGroups().contains( QStringLiteral( "recentProjects" ) ) )
{
QStringList oldRecentProjects = settings.value( QStringLiteral( "UI/recentProjectsList" ) ).toStringList();
Q_FOREACH ( const QString &project, oldRecentProjects )
{
QgsWelcomePageItemsModel::RecentProjectData data;
data.path = project;
data.title = project;
mRecentProjects.append( data );
}
}
settings.endGroup();
settings.beginGroup( QStringLiteral( "UI/recentProjects" ) );
QStringList projectKeysList = settings.childGroups();
//convert list to int values to obtain proper order
QList<int> projectKeys;
Q_FOREACH ( const QString &key, projectKeysList )
{
projectKeys.append( key.toInt() );
}
std::sort( projectKeys.begin(), projectKeys.end() );
Q_FOREACH ( int key, projectKeys )
{
QgsWelcomePageItemsModel::RecentProjectData data;
settings.beginGroup( QString::number( key ) );
data.title = settings.value( QStringLiteral( "title" ) ).toString();
data.path = settings.value( QStringLiteral( "path" ) ).toString();
data.previewImagePath = settings.value( QStringLiteral( "previewImage" ) ).toString();
data.crs = settings.value( QStringLiteral( "crs" ) ).toString();
settings.endGroup();
mRecentProjects.append( data );
}
settings.endGroup();
}
void QgisApp::applyProjectSettingsToCanvas( QgsMapCanvas *canvas )
{
int red = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), 255 );
int green = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), 255 );
int blue = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), 255 );
QColor myColor = QColor( red, green, blue );
canvas->setCanvasColor( myColor );
int alpha = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorAlphaPart" ), 255 );
red = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorRedPart" ), 255 );
green = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorGreenPart" ), 255 );
blue = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/SelectionColorBluePart" ), 0 );
myColor = QColor( red, green, blue, alpha );
canvas->setSelectionColor( myColor );
}
void QgisApp::applyDefaultSettingsToCanvas( QgsMapCanvas *canvas )
{
QgsSettings settings;
canvas->enableAntiAliasing( settings.value( QStringLiteral( "qgis/enable_anti_aliasing" ), true ).toBool() );
double zoomFactor = settings.value( QStringLiteral( "qgis/zoom_factor" ), 2 ).toDouble();
canvas->setWheelFactor( zoomFactor );
canvas->setCachingEnabled( settings.value( QStringLiteral( "qgis/enable_render_caching" ), true ).toBool() );
canvas->setParallelRenderingEnabled( settings.value( QStringLiteral( "qgis/parallel_rendering" ), true ).toBool() );
canvas->setMapUpdateInterval( settings.value( QStringLiteral( "qgis/map_update_interval" ), 250 ).toInt() );
canvas->setSegmentationTolerance( settings.value( QStringLiteral( "qgis/segmentationTolerance" ), "0.01745" ).toDouble() );
canvas->setSegmentationToleranceType( QgsAbstractGeometry::SegmentationToleranceType( settings.value( QStringLiteral( "qgis/segmentationToleranceType" ), "0" ).toInt() ) );
}
QgsCoordinateReferenceSystem QgisApp::defaultCrsForNewLayers() const
{
QgsSettings settings;
QgsCoordinateReferenceSystem defaultCrs;
if ( settings.value( QStringLiteral( "/Projections/defaultBehavior" ), QStringLiteral( "prompt" ) ).toString() == QStringLiteral( "useProject" )
|| settings.value( QStringLiteral( "/Projections/defaultBehavior" ), QStringLiteral( "prompt" ) ).toString() == QStringLiteral( "prompt" ) )
{
// for new layers if the new layer crs method is set to either prompt or use project, then we use the project crs
// (since "prompt" has no meaning here - the prompt will always be shown, it's just deciding on the default choice in the prompt!)
defaultCrs = QgsProject::instance()->crs();
}
else
{
// global crs
QString layerDefaultCrs = settings.value( QStringLiteral( "/Projections/layerDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
defaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( layerDefaultCrs );
}
return defaultCrs;
}
void QgisApp::readSettings()
{
QgsSettings settings;
QString themename = settings.value( QStringLiteral( "UI/UITheme" ), "default" ).toString();
setTheme( themename );
// Read legacy settings
readRecentProjects();
// this is a new session! reset enable macros value to "ask"
// whether set to "just for this session"
if ( settings.value( QStringLiteral( "qgis/enableMacros" ), 1 ).toInt() == 2 )
{
settings.setValue( QStringLiteral( "qgis/enableMacros" ), 1 );
}
}
//////////////////////////////////////////////////////////////////////
// Set Up the gui toolbars, menus, statusbar etc
//////////////////////////////////////////////////////////////////////
void QgisApp::createActions()
{
mActionPluginSeparator1 = nullptr; // plugin list separator will be created when the first plugin is loaded
mActionPluginSeparator2 = nullptr; // python separator will be created only if python is found
mActionRasterSeparator = nullptr; // raster plugins list separator will be created when the first plugin is loaded
// Project Menu Items
connect( mActionNewProject, &QAction::triggered, this, [ = ] { fileNew(); } );
connect( mActionNewBlankProject, &QAction::triggered, this, &QgisApp::fileNewBlank );
connect( mActionOpenProject, &QAction::triggered, this, &QgisApp::fileOpen );
connect( mActionSaveProject, &QAction::triggered, this, &QgisApp::fileSave );
connect( mActionSaveProjectAs, &QAction::triggered, this, &QgisApp::fileSaveAs );
connect( mActionSaveMapAsImage, &QAction::triggered, this, [ = ] { saveMapAsImage(); } );
connect( mActionNewMapCanvas, &QAction::triggered, this, &QgisApp::newMapCanvas );
connect( mActionNewPrintComposer, &QAction::triggered, this, &QgisApp::newPrintComposer );
connect( mActionShowComposerManager, &QAction::triggered, this, &QgisApp::showComposerManager );
connect( mActionExit, &QAction::triggered, this, &QgisApp::fileExit );
connect( mActionDxfExport, &QAction::triggered, this, &QgisApp::dxfExport );
connect( mActionDwgImport, &QAction::triggered, this, &QgisApp::dwgImport );
// Edit Menu Items
connect( mActionUndo, &QAction::triggered, mUndoWidget, &QgsUndoWidget::undo );
connect( mActionRedo, &QAction::triggered, mUndoWidget, &QgsUndoWidget::redo );
connect( mActionCutFeatures, &QAction::triggered, this, [ = ] { editCut(); } );
connect( mActionCopyFeatures, &QAction::triggered, this, [ = ] { editCopy(); } );
connect( mActionPasteFeatures, &QAction::triggered, this, [ = ] { editPaste(); } );
connect( mActionPasteAsNewVector, &QAction::triggered, this, &QgisApp::pasteAsNewVector );
connect( mActionPasteAsNewMemoryVector, &QAction::triggered, this, [ = ] { pasteAsNewMemoryVector(); } );
connect( mActionCopyStyle, &QAction::triggered, this, [ = ] { copyStyle(); } );
connect( mActionPasteStyle, &QAction::triggered, this, [ = ] { pasteStyle(); } );
connect( mActionAddFeature, &QAction::triggered, this, &QgisApp::addFeature );
connect( mActionCircularStringCurvePoint, &QAction::triggered, this, &QgisApp::circularStringCurvePoint );
connect( mActionCircularStringRadius, &QAction::triggered, this, &QgisApp::circularStringRadius );
connect( mActionMoveFeature, &QAction::triggered, this, &QgisApp::moveFeature );
connect( mActionMoveFeatureCopy, &QAction::triggered, this, &QgisApp::moveFeatureCopy );
connect( mActionRotateFeature, &QAction::triggered, this, &QgisApp::rotateFeature );
connect( mActionReshapeFeatures, &QAction::triggered, this, &QgisApp::reshapeFeatures );
connect( mActionSplitFeatures, &QAction::triggered, this, &QgisApp::splitFeatures );
connect( mActionSplitParts, &QAction::triggered, this, &QgisApp::splitParts );
connect( mActionDeleteSelected, &QAction::triggered, this, [ = ] { deleteSelected(); } );
connect( mActionAddRing, &QAction::triggered, this, &QgisApp::addRing );
connect( mActionFillRing, &QAction::triggered, this, &QgisApp::fillRing );
connect( mActionAddPart, &QAction::triggered, this, &QgisApp::addPart );
connect( mActionSimplifyFeature, &QAction::triggered, this, &QgisApp::simplifyFeature );
connect( mActionDeleteRing, &QAction::triggered, this, &QgisApp::deleteRing );
connect( mActionDeletePart, &QAction::triggered, this, &QgisApp::deletePart );
connect( mActionMergeFeatures, &QAction::triggered, this, &QgisApp::mergeSelectedFeatures );
connect( mActionMergeFeatureAttributes, &QAction::triggered, this, &QgisApp::mergeAttributesOfSelectedFeatures );
connect( mActionMultiEditAttributes, &QAction::triggered, this, &QgisApp::modifyAttributesOfSelectedFeatures );
connect( mActionNodeTool, &QAction::triggered, this, &QgisApp::nodeTool );
connect( mActionRotatePointSymbols, &QAction::triggered, this, &QgisApp::rotatePointSymbols );
connect( mActionOffsetPointSymbol, &QAction::triggered, this, &QgisApp::offsetPointSymbol );
connect( mActionSnappingOptions, &QAction::triggered, this, &QgisApp::snappingOptions );
connect( mActionOffsetCurve, &QAction::triggered, this, &QgisApp::offsetCurve );
// View Menu Items
connect( mActionPan, &QAction::triggered, this, &QgisApp::pan );
connect( mActionPanToSelected, &QAction::triggered, this, &QgisApp::panToSelected );
connect( mActionZoomIn, &QAction::triggered, this, &QgisApp::zoomIn );
connect( mActionZoomOut, &QAction::triggered, this, &QgisApp::zoomOut );
connect( mActionSelectFeatures, &QAction::triggered, this, &QgisApp::selectFeatures );
connect( mActionSelectPolygon, &QAction::triggered, this, &QgisApp::selectByPolygon );
connect( mActionSelectFreehand, &QAction::triggered, this, &QgisApp::selectByFreehand );
connect( mActionSelectRadius, &QAction::triggered, this, &QgisApp::selectByRadius );
connect( mActionDeselectAll, &QAction::triggered, this, &QgisApp::deselectAll );
connect( mActionSelectAll, &QAction::triggered, this, &QgisApp::selectAll );
connect( mActionInvertSelection, &QAction::triggered, this, &QgisApp::invertSelection );
connect( mActionSelectByExpression, &QAction::triggered, this, &QgisApp::selectByExpression );
connect( mActionSelectByForm, &QAction::triggered, this, &QgisApp::selectByForm );
connect( mActionIdentify, &QAction::triggered, this, &QgisApp::identify );
connect( mActionFeatureAction, &QAction::triggered, this, &QgisApp::doFeatureAction );
connect( mActionMeasure, &QAction::triggered, this, &QgisApp::measure );
connect( mActionMeasureArea, &QAction::triggered, this, &QgisApp::measureArea );
connect( mActionMeasureAngle, &QAction::triggered, this, &QgisApp::measureAngle );
connect( mActionZoomFullExtent, &QAction::triggered, this, &QgisApp::zoomFull );
connect( mActionZoomToLayer, &QAction::triggered, this, &QgisApp::zoomToLayerExtent );
connect( mActionZoomToSelected, &QAction::triggered, this, &QgisApp::zoomToSelected );
connect( mActionZoomLast, &QAction::triggered, this, &QgisApp::zoomToPrevious );
connect( mActionZoomNext, &QAction::triggered, this, &QgisApp::zoomToNext );
connect( mActionZoomActualSize, &QAction::triggered, this, &QgisApp::zoomActualSize );
connect( mActionMapTips, &QAction::toggled, this, &QgisApp::toggleMapTips );
connect( mActionNewBookmark, &QAction::triggered, this, &QgisApp::newBookmark );
connect( mActionShowBookmarks, &QAction::triggered, this, &QgisApp::showBookmarks );
connect( mActionDraw, &QAction::triggered, this, &QgisApp::refreshMapCanvas );
connect( mActionTextAnnotation, &QAction::triggered, this, &QgisApp::addTextAnnotation );
connect( mActionFormAnnotation, &QAction::triggered, this, &QgisApp::addFormAnnotation );
connect( mActionHtmlAnnotation, &QAction::triggered, this, &QgisApp::addHtmlAnnotation );
connect( mActionSvgAnnotation, &QAction::triggered, this, &QgisApp::addSvgAnnotation );
connect( mActionAnnotation, &QAction::triggered, this, &QgisApp::modifyAnnotation );
connect( mActionLabeling, &QAction::triggered, this, &QgisApp::labeling );
connect( mActionStatisticalSummary, &QAction::triggered, this, &QgisApp::showStatisticsDockWidget );
// Layer Menu Items
connect( mActionNewVectorLayer, &QAction::triggered, this, &QgisApp::newVectorLayer );
connect( mActionNewSpatiaLiteLayer, &QAction::triggered, this, &QgisApp::newSpatialiteLayer );
connect( mActionNewGeoPackageLayer, &QAction::triggered, this, &QgisApp::newGeoPackageLayer );
connect( mActionNewMemoryLayer, &QAction::triggered, this, &QgisApp::newMemoryLayer );
connect( mActionShowRasterCalculator, &QAction::triggered, this, &QgisApp::showRasterCalculator );
connect( mActionShowAlignRasterTool, &QAction::triggered, this, &QgisApp::showAlignRasterTool );
connect( mActionEmbedLayers, &QAction::triggered, this, &QgisApp::embedLayers );
connect( mActionAddLayerDefinition, &QAction::triggered, this, &QgisApp::addLayerDefinition );
connect( mActionAddOgrLayer, &QAction::triggered, this, [ = ] { addVectorLayer(); } );
connect( mActionAddRasterLayer, &QAction::triggered, this, [ = ] { addRasterLayer(); } );
connect( mActionAddPgLayer, &QAction::triggered, this, &QgisApp::addDatabaseLayer );
connect( mActionAddSpatiaLiteLayer, &QAction::triggered, this, &QgisApp::addSpatiaLiteLayer );
connect( mActionAddMssqlLayer, &QAction::triggered, this, &QgisApp::addMssqlLayer );
connect( mActionAddDb2Layer, &QAction::triggered, this, &QgisApp::addDb2Layer );
connect( mActionAddOracleLayer, &QAction::triggered, this, &QgisApp::addOracleLayer );
connect( mActionAddWmsLayer, &QAction::triggered, this, &QgisApp::addWmsLayer );
connect( mActionAddWcsLayer, &QAction::triggered, this, &QgisApp::addWcsLayer );
connect( mActionAddWfsLayer, &QAction::triggered, this, [ = ] { addWfsLayer(); } );
connect( mActionAddAfsLayer, &QAction::triggered, this, [ = ] { addAfsLayer(); } );
connect( mActionAddAmsLayer, &QAction::triggered, this, [ = ] { addAmsLayer(); } );
connect( mActionAddDelimitedText, &QAction::triggered, this, &QgisApp::addDelimitedTextLayer );
connect( mActionAddVirtualLayer, &QAction::triggered, this, &QgisApp::addVirtualLayer );
connect( mActionOpenTable, &QAction::triggered, this, &QgisApp::attributeTable );
connect( mActionOpenFieldCalc, &QAction::triggered, this, &QgisApp::fieldCalculator );
connect( mActionToggleEditing, &QAction::triggered, this, [ = ] { toggleEditing(); } );
connect( mActionSaveLayerEdits, &QAction::triggered, this, &QgisApp::saveActiveLayerEdits );
connect( mActionSaveEdits, &QAction::triggered, this, [ = ] { saveEdits(); } );
connect( mActionSaveAllEdits, &QAction::triggered, this, &QgisApp::saveAllEdits );
connect( mActionRollbackEdits, &QAction::triggered, this, &QgisApp::rollbackEdits );
connect( mActionRollbackAllEdits, &QAction::triggered, this, &QgisApp::rollbackAllEdits );
connect( mActionCancelEdits, &QAction::triggered, this, [ = ] { cancelEdits(); } );
connect( mActionCancelAllEdits, &QAction::triggered, this, &QgisApp::cancelAllEdits );
connect( mActionLayerSaveAs, &QAction::triggered, this, &QgisApp::saveAsFile );
connect( mActionSaveLayerDefinition, &QAction::triggered, this, &QgisApp::saveAsLayerDefinition );
connect( mActionRemoveLayer, &QAction::triggered, this, &QgisApp::removeLayer );
connect( mActionDuplicateLayer, &QAction::triggered, this, [ = ] { duplicateLayers(); } );
connect( mActionSetLayerScaleVisibility, &QAction::triggered, this, &QgisApp::setLayerScaleVisibility );
connect( mActionSetLayerCRS, &QAction::triggered, this, &QgisApp::setLayerCrs );
connect( mActionSetProjectCRSFromLayer, &QAction::triggered, this, &QgisApp::setProjectCrsFromLayer );
connect( mActionLayerProperties, &QAction::triggered, this, &QgisApp::layerProperties );
connect( mActionLayerSubsetString, &QAction::triggered, this, &QgisApp::layerSubsetString );
connect( mActionAddToOverview, &QAction::triggered, this, &QgisApp::isInOverview );
connect( mActionAddAllToOverview, &QAction::triggered, this, &QgisApp::addAllToOverview );
connect( mActionRemoveAllFromOverview, &QAction::triggered, this, &QgisApp::removeAllFromOverview );
connect( mActionShowAllLayers, &QAction::triggered, this, &QgisApp::showAllLayers );
connect( mActionHideAllLayers, &QAction::triggered, this, &QgisApp::hideAllLayers );
connect( mActionShowSelectedLayers, &QAction::triggered, this, &QgisApp::showSelectedLayers );
connect( mActionHideSelectedLayers, &QAction::triggered, this, &QgisApp::hideSelectedLayers );
connect( mActionHideDeselectedLayers, &QAction::triggered, this, &QgisApp::hideDeselectedLayers );
// Plugin Menu Items
connect( mActionManagePlugins, &QAction::triggered, this, &QgisApp::showPluginManager );
connect( mActionInstallFromZip, &QAction::triggered, this, &QgisApp::installPluginFromZip );
connect( mActionShowPythonDialog, &QAction::triggered, this, &QgisApp::showPythonDialog );
// Settings Menu Items
connect( mActionToggleFullScreen, &QAction::triggered, this, &QgisApp::toggleFullScreen );
connect( mActionTogglePanelsVisibility, &QAction::triggered, this, &QgisApp::togglePanelsVisibility );
connect( mActionProjectProperties, &QAction::triggered, this, &QgisApp::projectProperties );
connect( mActionOptions, &QAction::triggered, this, &QgisApp::options );
connect( mActionCustomProjection, &QAction::triggered, this, &QgisApp::customProjection );
connect( mActionConfigureShortcuts, &QAction::triggered, this, &QgisApp::configureShortcuts );
connect( mActionStyleManager, &QAction::triggered, this, &QgisApp::showStyleManager );
connect( mActionCustomization, &QAction::triggered, this, &QgisApp::customize );
#ifdef Q_OS_MAC
// Window Menu Items
mActionWindowMinimize = new QAction( tr( "Minimize" ), this );
mActionWindowMinimize->setShortcut( tr( "Ctrl+M", "Minimize Window" ) );
mActionWindowMinimize->setStatusTip( tr( "Minimizes the active window to the dock" ) );
connect( mActionWindowMinimize, SIGNAL( triggered() ), this, SLOT( showActiveWindowMinimized() ) );
mActionWindowZoom = new QAction( tr( "Zoom" ), this );
mActionWindowZoom->setStatusTip( tr( "Toggles between a predefined size and the window size set by the user" ) );
connect( mActionWindowZoom, SIGNAL( triggered() ), this, SLOT( toggleActiveWindowMaximized() ) );
mActionWindowAllToFront = new QAction( tr( "Bring All to Front" ), this );
mActionWindowAllToFront->setStatusTip( tr( "Bring forward all open windows" ) );
connect( mActionWindowAllToFront, SIGNAL( triggered() ), this, SLOT( bringAllToFront() ) );
// list of open windows
mWindowActions = new QActionGroup( this );
#endif
// Vector edits menu
QMenu *menuAllEdits = new QMenu( tr( "Current Edits" ), this );
menuAllEdits->addAction( mActionSaveEdits );
menuAllEdits->addAction( mActionRollbackEdits );
menuAllEdits->addAction( mActionCancelEdits );
menuAllEdits->addSeparator();
menuAllEdits->addAction( mActionSaveAllEdits );
menuAllEdits->addAction( mActionRollbackAllEdits );
menuAllEdits->addAction( mActionCancelAllEdits );
mActionAllEdits->setMenu( menuAllEdits );
// Raster toolbar items
connect( mActionLocalHistogramStretch, &QAction::triggered, this, &QgisApp::localHistogramStretch );
connect( mActionFullHistogramStretch, &QAction::triggered, this, &QgisApp::fullHistogramStretch );
connect( mActionLocalCumulativeCutStretch, &QAction::triggered, this, &QgisApp::localCumulativeCutStretch );
connect( mActionFullCumulativeCutStretch, &QAction::triggered, this, &QgisApp::fullCumulativeCutStretch );
connect( mActionIncreaseBrightness, &QAction::triggered, this, &QgisApp::increaseBrightness );
connect( mActionDecreaseBrightness, &QAction::triggered, this, &QgisApp::decreaseBrightness );
connect( mActionIncreaseContrast, &QAction::triggered, this, &QgisApp::increaseContrast );
connect( mActionDecreaseContrast, &QAction::triggered, this, &QgisApp::decreaseContrast );
// Vector Menu Items
connect( mActionOSMDownload, &QAction::triggered, this, &QgisApp::osmDownloadDialog );
connect( mActionOSMImport, &QAction::triggered, this, &QgisApp::osmImportDialog );
connect( mActionOSMExport, &QAction::triggered, this, &QgisApp::osmExportDialog );
// Help Menu Items
#ifdef Q_OS_MAC
mActionHelpContents->setShortcut( QString( "Ctrl+?" ) );
mActionQgisHomePage->setShortcut( QString() );
mActionReportaBug->setShortcut( QString() );
#endif
mActionHelpContents->setEnabled( QFileInfo::exists( QgsApplication::pkgDataPath() + "/doc/index.html" ) );
connect( mActionHelpContents, &QAction::triggered, this, &QgisApp::helpContents );
connect( mActionHelpAPI, &QAction::triggered, this, &QgisApp::apiDocumentation );
connect( mActionReportaBug, &QAction::triggered, this, &QgisApp::reportaBug );
connect( mActionNeedSupport, &QAction::triggered, this, &QgisApp::supportProviders );
connect( mActionQgisHomePage, &QAction::triggered, this, &QgisApp::helpQgisHomePage );
connect( mActionCheckQgisVersion, &QAction::triggered, this, &QgisApp::checkQgisVersion );
connect( mActionAbout, &QAction::triggered, this, &QgisApp::about );
connect( mActionSponsors, &QAction::triggered, this, &QgisApp::sponsors );
connect( mActionShowPinnedLabels, &QAction::toggled, this, &QgisApp::showPinnedLabels );
connect( mActionPinLabels, &QAction::triggered, this, &QgisApp::pinLabels );
connect( mActionShowHideLabels, &QAction::triggered, this, &QgisApp::showHideLabels );
connect( mActionMoveLabel, &QAction::triggered, this, &QgisApp::moveLabel );
connect( mActionRotateLabel, &QAction::triggered, this, &QgisApp::rotateLabel );
connect( mActionChangeLabelProperties, &QAction::triggered, this, &QgisApp::changeLabelProperties );
connect( mActionDiagramProperties, &QAction::triggered, this, &QgisApp::diagramProperties );
#ifndef HAVE_POSTGRESQL
delete mActionAddPgLayer;
mActionAddPgLayer = 0;
#endif
#ifndef HAVE_ORACLE
delete mActionAddOracleLayer;
mActionAddOracleLayer = nullptr;
#endif
}
#include "qgsstyle.h"
#include "qgsstylemanagerdialog.h"
void QgisApp::showStyleManager()
{
QgsStyleManagerDialog dlg( QgsStyle::defaultStyle(), this );
dlg.exec();
}
void QgisApp::showPythonDialog()
{
#ifdef WITH_BINDINGS
if ( !mPythonUtils || !mPythonUtils->isEnabled() )
return;
bool res = mPythonUtils->runString(
"import console\n"
"console.show_console()\n", tr( "Failed to open Python console:" ), false );
if ( !res )
{
QString className, text;
mPythonUtils->getError( className, text );
messageBar()->pushMessage( tr( "Error" ), tr( "Failed to open Python console:" ) + '\n' + className + ": " + text, QgsMessageBar::WARNING );
}
#ifdef Q_OS_MAC
else
{
addWindow( mActionShowPythonDialog );
}
#endif
#endif
}
void QgisApp::createActionGroups()
{
//
// Map Tool Group
mMapToolGroup = new QActionGroup( this );
mMapToolGroup->addAction( mActionPan );
mMapToolGroup->addAction( mActionZoomIn );
mMapToolGroup->addAction( mActionZoomOut );
mMapToolGroup->addAction( mActionIdentify );
mMapToolGroup->addAction( mActionFeatureAction );
mMapToolGroup->addAction( mActionSelectFeatures );
mMapToolGroup->addAction( mActionSelectPolygon );
mMapToolGroup->addAction( mActionSelectFreehand );
mMapToolGroup->addAction( mActionSelectRadius );
mMapToolGroup->addAction( mActionDeselectAll );
mMapToolGroup->addAction( mActionSelectAll );
mMapToolGroup->addAction( mActionInvertSelection );
mMapToolGroup->addAction( mActionMeasure );
mMapToolGroup->addAction( mActionMeasureArea );
mMapToolGroup->addAction( mActionMeasureAngle );
mMapToolGroup->addAction( mActionAddFeature );
mMapToolGroup->addAction( mActionCircularStringCurvePoint );
mMapToolGroup->addAction( mActionCircularStringRadius );
mMapToolGroup->addAction( mActionMoveFeature );
mMapToolGroup->addAction( mActionMoveFeatureCopy );
mMapToolGroup->addAction( mActionRotateFeature );
mMapToolGroup->addAction( mActionOffsetCurve );
mMapToolGroup->addAction( mActionReshapeFeatures );
mMapToolGroup->addAction( mActionSplitFeatures );
mMapToolGroup->addAction( mActionSplitParts );
mMapToolGroup->addAction( mActionDeleteSelected );
mMapToolGroup->addAction( mActionAddRing );
mMapToolGroup->addAction( mActionFillRing );
mMapToolGroup->addAction( mActionAddPart );
mMapToolGroup->addAction( mActionSimplifyFeature );
mMapToolGroup->addAction( mActionDeleteRing );
mMapToolGroup->addAction( mActionDeletePart );
mMapToolGroup->addAction( mActionMergeFeatures );
mMapToolGroup->addAction( mActionMergeFeatureAttributes );
mMapToolGroup->addAction( mActionNodeTool );
mMapToolGroup->addAction( mActionRotatePointSymbols );
mMapToolGroup->addAction( mActionOffsetPointSymbol );
mMapToolGroup->addAction( mActionPinLabels );
mMapToolGroup->addAction( mActionShowHideLabels );
mMapToolGroup->addAction( mActionMoveLabel );
mMapToolGroup->addAction( mActionRotateLabel );
mMapToolGroup->addAction( mActionChangeLabelProperties );
//
// Preview Modes Group
QActionGroup *mPreviewGroup = new QActionGroup( this );
mPreviewGroup->setExclusive( true );
mActionPreviewModeOff->setActionGroup( mPreviewGroup );
mActionPreviewModeGrayscale->setActionGroup( mPreviewGroup );
mActionPreviewModeMono->setActionGroup( mPreviewGroup );
mActionPreviewProtanope->setActionGroup( mPreviewGroup );
mActionPreviewDeuteranope->setActionGroup( mPreviewGroup );
}
void QgisApp::setAppStyleSheet( const QString &stylesheet )
{
setStyleSheet( stylesheet );
// cascade styles to any current project composers
Q_FOREACH ( QgsComposer *c, mPrintComposers )
{
c->setStyleSheet( stylesheet );
}
}
int QgisApp::messageTimeout()
{
QgsSettings settings;
return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
}
void QgisApp::createMenus()
{
/*
* The User Interface Guidelines for each platform specify different locations
* for the following items.
*
* Project Properties:
* Gnome, Mac, Win - File/Project menu above print commands (Win doesn't specify)
* Kde - Settings menu
*
* Custom CRS, Options:
* Gnome - bottom of Edit menu
* Mac - Application menu (moved automatically by Qt)
* Kde, Win - Settings menu (Win should use Tools menu but we don't have one)
*
* Panel and Toolbar submenus, Toggle Full Screen:
* Gnome, Mac, Win - View menu
* Kde - Settings menu
*
* For Mac, About and Exit are also automatically moved by Qt to the Application menu.
*/
// Layer menu
// Panel and Toolbar Submenus
mPanelMenu = new QMenu( tr( "Panels" ), this );
mPanelMenu->setObjectName( QStringLiteral( "mPanelMenu" ) );
mToolbarMenu = new QMenu( tr( "Toolbars" ), this );
mToolbarMenu->setObjectName( QStringLiteral( "mToolbarMenu" ) );
// Get platform for menu layout customization (Gnome, Kde, Mac, Win)
QDialogButtonBox::ButtonLayout layout =
QDialogButtonBox::ButtonLayout( style()->styleHint( QStyle::SH_DialogButtonLayout, nullptr, this ) );
// Project Menu
// Connect once for the entire submenu.
connect( mRecentProjectsMenu, &QMenu::triggered, this, static_cast < void ( QgisApp::* )( QAction *action ) >( &QgisApp::openProject ) );
connect( mProjectFromTemplateMenu, &QMenu::triggered,
this, &QgisApp::fileNewFromTemplateAction );
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout || layout == QDialogButtonBox::WinLayout )
{
QAction *before = mActionNewPrintComposer;
mSettingsMenu->removeAction( mActionProjectProperties );
mProjectMenu->insertAction( before, mActionProjectProperties );
mProjectMenu->insertSeparator( before );
}
// View Menu
if ( layout != QDialogButtonBox::KdeLayout )
{
mViewMenu->addSeparator();
mViewMenu->addMenu( mPanelMenu );
mViewMenu->addMenu( mToolbarMenu );
mViewMenu->addAction( mActionToggleFullScreen );
mViewMenu->addAction( mActionTogglePanelsVisibility );
}
else
{
// on the top of the settings menu
QAction *before = mActionProjectProperties;
mSettingsMenu->insertMenu( before, mPanelMenu );
mSettingsMenu->insertMenu( before, mToolbarMenu );
mSettingsMenu->insertAction( before, mActionToggleFullScreen );
mSettingsMenu->insertAction( before, mActionTogglePanelsVisibility );
mSettingsMenu->insertSeparator( before );
}
#ifdef Q_OS_MAC
//disabled for OSX - see #10761
//also see http://qt-project.org/forums/viewthread/3630 QGraphicsEffects are not well supported on OSX
mMenuPreviewMode->menuAction()->setVisible( false );
#endif
#ifdef Q_OS_MAC
// keep plugins from hijacking About and Preferences application menus
// these duplicate actions will be moved to application menus by Qt
mProjectMenu->addAction( mActionAbout );
QAction *actionPrefs = new QAction( tr( "Preferences..." ), this );
actionPrefs->setMenuRole( QAction::PreferencesRole );
actionPrefs->setIcon( mActionOptions->icon() );
connect( actionPrefs, &QAction::triggered, this, &QgisApp::options );
mProjectMenu->addAction( actionPrefs );
// Window Menu
mWindowMenu = new QMenu( tr( "Window" ), this );
mWindowMenu->addAction( mActionWindowMinimize );
mWindowMenu->addAction( mActionWindowZoom );
mWindowMenu->addSeparator();
mWindowMenu->addAction( mActionWindowAllToFront );
mWindowMenu->addSeparator();
// insert before Help menu, as per Mac OS convention
menuBar()->insertMenu( mHelpMenu->menuAction(), mWindowMenu );
#endif
// Database Menu
// don't add it yet, wait for a plugin
mDatabaseMenu = new QMenu( tr( "&Database" ), menuBar() );
mDatabaseMenu->setObjectName( QStringLiteral( "mDatabaseMenu" ) );
// Web Menu
// don't add it yet, wait for a plugin
mWebMenu = new QMenu( tr( "&Web" ), menuBar() );
mWebMenu->setObjectName( QStringLiteral( "mWebMenu" ) );
// Help menu
// add What's this button to it
QAction *before = mActionHelpAPI;
QAction *actionWhatsThis = QWhatsThis::createAction( this );
actionWhatsThis->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionWhatsThis.svg" ) ) );
mHelpMenu->insertAction( before, actionWhatsThis );
}
void QgisApp::createToolBars()
{
QgsSettings settings;
// QSize myIconSize ( 32,32 ); //large icons
// Note: we need to set each object name to ensure that
// qmainwindow::saveState and qmainwindow::restoreState
// work properly
QList<QToolBar *> toolbarMenuToolBars;
toolbarMenuToolBars << mFileToolBar
<< mLayerToolBar
<< mDigitizeToolBar
<< mAdvancedDigitizeToolBar
<< mMapNavToolBar
<< mAttributesToolBar
<< mPluginToolBar
<< mHelpToolBar
<< mRasterToolBar
<< mVectorToolBar
<< mDatabaseToolBar
<< mWebToolBar
<< mLabelToolBar;
mSnappingWidget = new QgsSnappingWidget( QgsProject::instance(), mMapCanvas, mSnappingToolBar );
mSnappingWidget->setObjectName( QStringLiteral( "mSnappingWidget" ) );
connect( mSnappingWidget, &QgsSnappingWidget::snappingConfigChanged, QgsProject::instance(), [ = ] { QgsProject::instance()->setSnappingConfig( mSnappingWidget->config() ); } );
mSnappingToolBar->addWidget( mSnappingWidget );
mTracer = new QgsMapCanvasTracer( mMapCanvas, messageBar() );
mTracer->setActionEnableTracing( mSnappingWidget->enableTracingAction() );
QList<QAction *> toolbarMenuActions;
// Set action names so that they can be used in customization
Q_FOREACH ( QToolBar *toolBar, toolbarMenuToolBars )
{
toolBar->toggleViewAction()->setObjectName( "mActionToggle" + toolBar->objectName().mid( 1 ) );
toolbarMenuActions << toolBar->toggleViewAction();
}
// sort actions in toolbar menu
std::sort( toolbarMenuActions.begin(), toolbarMenuActions.end(), cmpByText_ );
mToolbarMenu->addActions( toolbarMenuActions );
// selection tool button
QToolButton *bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
QList<QAction *> selectActions;
selectActions << mActionSelectByForm << mActionSelectByExpression << mActionSelectAll
<< mActionInvertSelection;
bt->addActions( selectActions );
bt->setDefaultAction( mActionSelectByForm );
QAction *selectionAction = mAttributesToolBar->insertWidget( mActionDeselectAll, bt );
selectionAction->setObjectName( QStringLiteral( "ActionSelection" ) );
// select tool button
bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
QList<QAction *> selectionActions;
selectionActions << mActionSelectFeatures << mActionSelectPolygon
<< mActionSelectFreehand << mActionSelectRadius;
bt->addActions( selectionActions );
QAction *defSelectAction = mActionSelectFeatures;
switch ( settings.value( QStringLiteral( "UI/selectTool" ), 0 ).toInt() )
{
case 0:
defSelectAction = mActionSelectFeatures;
break;
case 1:
defSelectAction = mActionSelectFeatures;
break;
case 2:
defSelectAction = mActionSelectRadius;
break;
case 3:
defSelectAction = mActionSelectPolygon;
break;
case 4:
defSelectAction = mActionSelectFreehand;
break;
}
bt->setDefaultAction( defSelectAction );
QAction *selectAction = mAttributesToolBar->insertWidget( selectionAction, bt );
selectAction->setObjectName( QStringLiteral( "ActionSelect" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// feature action tool button
bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->setDefaultAction( mActionFeatureAction );
mFeatureActionMenu = new QMenu( bt );
connect( mFeatureActionMenu, &QMenu::triggered, this, &QgisApp::updateDefaultFeatureAction );
connect( mFeatureActionMenu, &QMenu::triggered, this, &QgisApp::doFeatureAction );
connect( mFeatureActionMenu, &QMenu::aboutToShow, this, &QgisApp::refreshFeatureActions );
bt->setMenu( mFeatureActionMenu );
QAction *featureActionAction = mAttributesToolBar->insertWidget( selectAction, bt );
featureActionAction->setObjectName( QStringLiteral( "ActionFeatureAction" ) );
// measure tool button
bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionMeasure );
bt->addAction( mActionMeasureArea );
bt->addAction( mActionMeasureAngle );
QAction *defMeasureAction = mActionMeasure;
switch ( settings.value( QStringLiteral( "UI/measureTool" ), 0 ).toInt() )
{
case 0:
defMeasureAction = mActionMeasure;
break;
case 1:
defMeasureAction = mActionMeasureArea;
break;
case 2:
defMeasureAction = mActionMeasureAngle;
break;
}
bt->setDefaultAction( defMeasureAction );
QAction *measureAction = mAttributesToolBar->insertWidget( mActionMapTips, bt );
measureAction->setObjectName( QStringLiteral( "ActionMeasure" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// annotation tool button
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionTextAnnotation );
bt->addAction( mActionFormAnnotation );
bt->addAction( mActionHtmlAnnotation );
bt->addAction( mActionSvgAnnotation );
bt->addAction( mActionAnnotation );
QAction *defAnnotationAction = mActionTextAnnotation;
switch ( settings.value( QStringLiteral( "UI/annotationTool" ), 0 ).toInt() )
{
case 0:
defAnnotationAction = mActionTextAnnotation;
break;
case 1:
defAnnotationAction = mActionFormAnnotation;
break;
case 2:
defAnnotationAction = mActionHtmlAnnotation;
break;
case 3:
defAnnotationAction = mActionSvgAnnotation;
break;
case 4:
defAnnotationAction = mActionAnnotation;
break;
}
bt->setDefaultAction( defAnnotationAction );
QAction *annotationAction = mAttributesToolBar->addWidget( bt );
annotationAction->setObjectName( QStringLiteral( "ActionAnnotation" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// vector layer edits tool buttons
QToolButton *tbAllEdits = qobject_cast<QToolButton *>( mDigitizeToolBar->widgetForAction( mActionAllEdits ) );
tbAllEdits->setPopupMode( QToolButton::InstantPopup );
// new layer tool button
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionNewVectorLayer );
bt->addAction( mActionNewSpatiaLiteLayer );
bt->addAction( mActionNewGeoPackageLayer );
bt->addAction( mActionNewMemoryLayer );
QAction *defNewLayerAction = mActionNewVectorLayer;
switch ( settings.value( QStringLiteral( "UI/defaultNewLayer" ), 1 ).toInt() )
{
case 0:
defNewLayerAction = mActionNewSpatiaLiteLayer;
break;
case 1:
defNewLayerAction = mActionNewVectorLayer;
break;
case 2:
defNewLayerAction = mActionNewMemoryLayer;
break;
case 3:
defNewLayerAction = mActionNewGeoPackageLayer;
break;
}
bt->setDefaultAction( defNewLayerAction );
QAction *newLayerAction = mLayerToolBar->addWidget( bt );
newLayerAction->setObjectName( QStringLiteral( "ActionNewLayer" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// map service tool button
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionAddWmsLayer );
bt->addAction( mActionAddAmsLayer );
QAction *defMapServiceAction = mActionAddWmsLayer;
switch ( settings.value( QStringLiteral( "UI/defaultMapService" ), 0 ).toInt() )
{
case 0:
defMapServiceAction = mActionAddWmsLayer;
break;
case 1:
defMapServiceAction = mActionAddAmsLayer;
break;
};
bt->setDefaultAction( defMapServiceAction );
QAction *mapServiceAction = mLayerToolBar->insertWidget( mActionAddWmsLayer, bt );
mLayerToolBar->removeAction( mActionAddWmsLayer );
mapServiceAction->setObjectName( QStringLiteral( "ActionMapService" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// feature service tool button
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionAddWfsLayer );
bt->addAction( mActionAddAfsLayer );
QAction *defFeatureServiceAction = mActionAddWfsLayer;
switch ( settings.value( QStringLiteral( "UI/defaultFeatureService" ), 0 ).toInt() )
{
case 0:
defFeatureServiceAction = mActionAddWfsLayer;
break;
case 1:
defFeatureServiceAction = mActionAddAfsLayer;
break;
};
bt->setDefaultAction( defFeatureServiceAction );
QAction *featureServiceAction = mLayerToolBar->insertWidget( mActionAddWfsLayer, bt );
mLayerToolBar->removeAction( mActionAddWfsLayer );
featureServiceAction->setObjectName( QStringLiteral( "ActionFeatureService" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// add db layer button
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
if ( mActionAddPgLayer )
bt->addAction( mActionAddPgLayer );
if ( mActionAddMssqlLayer )
bt->addAction( mActionAddMssqlLayer );
if ( mActionAddDb2Layer )
bt->addAction( mActionAddDb2Layer );
if ( mActionAddOracleLayer )
bt->addAction( mActionAddOracleLayer );
QAction *defAddDbLayerAction = mActionAddPgLayer;
switch ( settings.value( QStringLiteral( "UI/defaultAddDbLayerAction" ), 0 ).toInt() )
{
case 0:
defAddDbLayerAction = mActionAddPgLayer;
break;
case 1:
defAddDbLayerAction = mActionAddMssqlLayer;
break;
case 2:
defAddDbLayerAction = mActionAddDb2Layer;
break;
case 3:
defAddDbLayerAction = mActionAddOracleLayer;
break;
}
if ( defAddDbLayerAction )
bt->setDefaultAction( defAddDbLayerAction );
QAction *addDbLayerAction = mLayerToolBar->insertWidget( mapServiceAction, bt );
addDbLayerAction->setObjectName( QStringLiteral( "ActionAddDbLayer" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
QLayout *layout = mLayerToolBar->layout();
for ( int i = 0; i < layout->count(); ++i )
{
layout->itemAt( i )->setAlignment( Qt::AlignLeft );
}
//circular string digitize tool button
QToolButton *tbAddCircularString = new QToolButton( mDigitizeToolBar );
tbAddCircularString->setPopupMode( QToolButton::MenuButtonPopup );
tbAddCircularString->addAction( mActionCircularStringCurvePoint );
tbAddCircularString->addAction( mActionCircularStringRadius );
tbAddCircularString->setDefaultAction( mActionCircularStringCurvePoint );
connect( tbAddCircularString, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
mDigitizeToolBar->insertWidget( mActionNodeTool, tbAddCircularString );
// move feature tool button
QToolButton *moveFeatureButton = new QToolButton( mDigitizeToolBar );
moveFeatureButton->setPopupMode( QToolButton::MenuButtonPopup );
moveFeatureButton->addAction( mActionMoveFeature );
moveFeatureButton->addAction( mActionMoveFeatureCopy );
QAction *defAction = mActionMoveFeature;
switch ( settings.value( QStringLiteral( "UI/defaultMoveTool" ), 0 ).toInt() )
{
case 0:
defAction = mActionMoveFeature;
break;
case 1:
defAction = mActionMoveFeatureCopy;
break;
};
moveFeatureButton->setDefaultAction( defAction );
connect( moveFeatureButton, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
mDigitizeToolBar->insertWidget( mActionNodeTool, moveFeatureButton );
bt = new QToolButton();
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->addAction( mActionRotatePointSymbols );
bt->addAction( mActionOffsetPointSymbol );
QAction *defPointSymbolAction = mActionRotatePointSymbols;
switch ( settings.value( QStringLiteral( "UI/defaultPointSymbolAction" ), 0 ).toInt() )
{
case 0:
defPointSymbolAction = mActionRotatePointSymbols;
break;
case 1:
defPointSymbolAction = mActionOffsetPointSymbol;
break;
}
bt->setDefaultAction( defPointSymbolAction );
QAction *pointSymbolAction = mAdvancedDigitizeToolBar->addWidget( bt );
pointSymbolAction->setObjectName( QStringLiteral( "ActionPointSymbolTools" ) );
connect( bt, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
// Cad toolbar
mAdvancedDigitizeToolBar->insertAction( mActionRotateFeature, mAdvancedDigitizingDockWidget->enableAction() );
}
void QgisApp::createStatusBar()
{
//remove borders from children under Windows
statusBar()->setStyleSheet( QStringLiteral( "QStatusBar::item {border: none;}" ) );
// Add a panel to the status bar for the scale, coords and progress
// And also rendering suppression checkbox
mProgressBar = new QProgressBar( statusBar() );
mProgressBar->setObjectName( QStringLiteral( "mProgressBar" ) );
mProgressBar->setMaximumWidth( 100 );
mProgressBar->hide();
mProgressBar->setWhatsThis( tr( "Progress bar that displays the status "
"of rendering layers and other time-intensive operations" ) );
statusBar()->addPermanentWidget( mProgressBar, 1 );
connect( mMapCanvas, &QgsMapCanvas::renderStarting, this, &QgisApp::canvasRefreshStarted );
connect( mMapCanvas, &QgsMapCanvas::mapCanvasRefreshed, this, &QgisApp::canvasRefreshFinished );
mTaskManagerWidget = new QgsTaskManagerStatusBarWidget( QgsApplication::taskManager(), statusBar() );
statusBar()->addPermanentWidget( mTaskManagerWidget, 0 );
// Bumped the font up one point size since 8 was too
// small on some platforms. A point size of 9 still provides
// plenty of display space on 1024x768 resolutions
QFont myFont( QStringLiteral( "Arial" ), 9 );
statusBar()->setFont( myFont );
//coords status bar widget
mCoordsEdit = new QgsStatusBarCoordinatesWidget( statusBar() );
mCoordsEdit->setObjectName( QStringLiteral( "mCoordsEdit" ) );
mCoordsEdit->setMapCanvas( mMapCanvas );
mCoordsEdit->setFont( myFont );
statusBar()->addPermanentWidget( mCoordsEdit, 0 );
mScaleWidget = new QgsStatusBarScaleWidget( mMapCanvas, statusBar() );
mScaleWidget->setObjectName( QStringLiteral( "mScaleWidget" ) );
mScaleWidget->setFont( myFont );
connect( mScaleWidget, &QgsStatusBarScaleWidget::scaleLockChanged, mMapCanvas, &QgsMapCanvas::setScaleLocked );
statusBar()->addPermanentWidget( mScaleWidget, 0 );
// zoom widget
mMagnifierWidget = new QgsStatusBarMagnifierWidget( statusBar() );
mMagnifierWidget->setObjectName( QStringLiteral( "mMagnifierWidget" ) );
mMagnifierWidget->setFont( myFont );
connect( mMapCanvas, &QgsMapCanvas::magnificationChanged, mMagnifierWidget, &QgsStatusBarMagnifierWidget::updateMagnification );
connect( mMagnifierWidget, &QgsStatusBarMagnifierWidget::magnificationChanged, mMapCanvas, &QgsMapCanvas::setMagnificationFactor );
mMagnifierWidget->updateMagnification( QSettings().value( QStringLiteral( "/qgis/magnifier_factor_default" ), 1.0 ).toDouble() );
statusBar()->addPermanentWidget( mMagnifierWidget, 0 );
// add a widget to show/set current rotation
mRotationLabel = new QLabel( QString(), statusBar() );
mRotationLabel->setObjectName( QStringLiteral( "mRotationLabel" ) );
mRotationLabel->setFont( myFont );
mRotationLabel->setMinimumWidth( 10 );
//mRotationLabel->setMaximumHeight( 20 );
mRotationLabel->setMargin( 3 );
mRotationLabel->setAlignment( Qt::AlignCenter );
mRotationLabel->setFrameStyle( QFrame::NoFrame );
mRotationLabel->setText( tr( "Rotation" ) );
mRotationLabel->setToolTip( tr( "Current clockwise map rotation in degrees" ) );
statusBar()->addPermanentWidget( mRotationLabel, 0 );
mRotationEdit = new QgsDoubleSpinBox( statusBar() );
mRotationEdit->setObjectName( QStringLiteral( "mRotationEdit" ) );
mRotationEdit->setClearValue( 0.0 );
mRotationEdit->setKeyboardTracking( false );
mRotationEdit->setMaximumWidth( 120 );
mRotationEdit->setDecimals( 1 );
mRotationEdit->setRange( -180.0, 180.0 );
mRotationEdit->setWrapping( true );
mRotationEdit->setSingleStep( 5.0 );
mRotationEdit->setFont( myFont );
mRotationEdit->setSuffix( trUtf8( " °" ) );
mRotationEdit->setWhatsThis( tr( "Shows the current map clockwise rotation "
"in degrees. It also allows editing to set "
"the rotation" ) );
mRotationEdit->setToolTip( tr( "Current clockwise map rotation in degrees" ) );
statusBar()->addPermanentWidget( mRotationEdit, 0 );
connect( mRotationEdit, static_cast < void ( QgsDoubleSpinBox::* )( double ) > ( &QgsDoubleSpinBox::valueChanged ), this, &QgisApp::userRotation );
showRotation();
// render suppression status bar widget
mRenderSuppressionCBox = new QCheckBox( tr( "Render" ), statusBar() );
mRenderSuppressionCBox->setObjectName( QStringLiteral( "mRenderSuppressionCBox" ) );
mRenderSuppressionCBox->setChecked( true );
mRenderSuppressionCBox->setFont( myFont );
mRenderSuppressionCBox->setWhatsThis( tr( "When checked, the map layers "
"are rendered in response to map navigation commands and other "
"events. When not checked, no rendering is done. This allows you "
"to add a large number of layers and symbolize them before rendering." ) );
mRenderSuppressionCBox->setToolTip( tr( "Toggle map rendering" ) );
statusBar()->addPermanentWidget( mRenderSuppressionCBox, 0 );
// On the fly projection status bar icon
// Changed this to a tool button since a QPushButton is
// sculpted on OS X and the icon is never displayed [gsherman]
mOnTheFlyProjectionStatusButton = new QToolButton( statusBar() );
mOnTheFlyProjectionStatusButton->setAutoRaise( true );
mOnTheFlyProjectionStatusButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
mOnTheFlyProjectionStatusButton->setObjectName( QStringLiteral( "mOntheFlyProjectionStatusButton" ) );
// Maintain uniform widget height in status bar by setting button height same as labels
// For Qt/Mac 3.3, the default toolbutton height is 30 and labels were expanding to match
mOnTheFlyProjectionStatusButton->setMaximumHeight( mScaleWidget->height() );
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconProjectionEnabled.svg" ) ) );
mOnTheFlyProjectionStatusButton->setWhatsThis( tr( "This icon shows whether "
"on the fly coordinate reference system transformation is enabled or not. "
"Click the icon to bring up "
"the project properties dialog to alter this behavior." ) );
mOnTheFlyProjectionStatusButton->setToolTip( tr( "CRS status - Click "
"to open coordinate reference system dialog" ) );
connect( mOnTheFlyProjectionStatusButton, &QAbstractButton::clicked,
this, &QgisApp::projectPropertiesProjections );//bring up the project props dialog when clicked
statusBar()->addPermanentWidget( mOnTheFlyProjectionStatusButton, 0 );
statusBar()->showMessage( tr( "Ready" ) );
mMessageButton = new QToolButton( statusBar() );
mMessageButton->setAutoRaise( true );
mMessageButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mMessageLogRead.svg" ) ) );
mMessageButton->setToolTip( tr( "Messages" ) );
mMessageButton->setWhatsThis( tr( "Messages" ) );
mMessageButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
mMessageButton->setObjectName( QStringLiteral( "mMessageLogViewerButton" ) );
mMessageButton->setMaximumHeight( mScaleWidget->height() );
mMessageButton->setCheckable( true );
statusBar()->addPermanentWidget( mMessageButton, 0 );
}
void QgisApp::setIconSizes( int size )
{
int dockSize;
if ( size > 32 )
{
dockSize = size - 16;
}
else if ( size == 32 )
{
dockSize = 24;
}
else
{
dockSize = 16;
}
//Set the icon size of for all the toolbars created in the future.
setIconSize( QSize( size, size ) );
//Change all current icon sizes.
QList<QToolBar *> toolbars = findChildren<QToolBar *>();
Q_FOREACH ( QToolBar *toolbar, toolbars )
{
QString className = toolbar->parent()->metaObject()->className();
if ( className == QLatin1String( "QgisApp" ) )
{
toolbar->setIconSize( QSize( size, size ) );
}
else
{
toolbar->setIconSize( QSize( dockSize, dockSize ) );
}
}
Q_FOREACH ( QgsComposer *c, mPrintComposers )
{
c->setIconSizes( size );
}
}
void QgisApp::setTheme( const QString &themeName )
{
/*****************************************************************
// Init the toolbar icons by setting the icon for each action.
// All toolbar/menu items must be a QAction in order for this
// to work.
//
// When new toolbar/menu QAction objects are added to the interface,
// add an entry below to set the icon
//
// PNG names must match those defined for the default theme. The
// default theme is installed in <prefix>/share/qgis/themes/default.
//
// New core themes can be added by creating a subdirectory under src/themes
// and modifying the appropriate CMakeLists.txt files. User contributed themes
// will be installed directly into <prefix>/share/qgis/themes/<themedir>.
//
// Themes can be selected from the preferences dialog. The dialog parses
// the themes directory and builds a list of themes (ie subdirectories)
// for the user to choose from.
//
*/
QgsApplication::setUITheme( themeName );
//QgsDebugMsg("Setting theme to \n" + themeName);
mActionNewProject->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileNew.svg" ) ) );
mActionOpenProject->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileOpen.svg" ) ) );
mActionSaveProject->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileSave.svg" ) ) );
mActionSaveProjectAs->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileSaveAs.svg" ) ) );
mActionNewPrintComposer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewComposer.svg" ) ) );
mActionShowComposerManager->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionComposerManager.svg" ) ) );
mActionSaveMapAsImage->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveMapAsImage.svg" ) ) );
mActionExit->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFileExit.png" ) ) );
mActionAddOgrLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddOgrLayer.svg" ) ) );
mActionAddRasterLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddRasterLayer.svg" ) ) );
#ifdef HAVE_POSTGRESQL
mActionAddPgLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddPostgisLayer.svg" ) ) );
#endif
mActionNewSpatiaLiteLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewSpatiaLiteLayer.svg" ) ) );
mActionAddSpatiaLiteLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddSpatiaLiteLayer.svg" ) ) );
mActionAddMssqlLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddMssqlLayer.svg" ) ) );
mActionAddDb2Layer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddDb2Layer.svg" ) ) );
#ifdef HAVE_ORACLE
mActionAddOracleLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddOracleLayer.svg" ) );
#endif
mActionRemoveLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveLayer.svg" ) ) );
mActionDuplicateLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDuplicateLayer.svg" ) ) );
mActionSetLayerCRS->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetLayerCRS.png" ) ) );
mActionSetProjectCRSFromLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSetProjectCRSFromLayer.png" ) ) );
mActionNewVectorLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewVectorLayer.svg" ) ) );
mActionNewMemoryLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCreateMemory.svg" ) ) );
mActionAddAllToOverview->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddAllToOverview.svg" ) ) );
mActionHideAllLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHideAllLayers.svg" ) ) );
mActionShowAllLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowAllLayers.svg" ) ) );
mActionHideSelectedLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHideSelectedLayers.svg" ) ) );
mActionHideDeselectedLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHideDeselectedLayers.svg" ) ) );
mActionShowSelectedLayers->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowSelectedLayers.svg" ) ) );
mActionRemoveAllFromOverview->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRemoveAllFromOverview.svg" ) ) );
mActionToggleFullScreen->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleFullScreen.png" ) ) );
mActionProjectProperties->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionProjectProperties.png" ) ) );
mActionManagePlugins->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowPluginManager.svg" ) ) );
mActionInstallFromZip->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInstallPluginFromZip.svg" ) ) );
mActionShowPythonDialog->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "console/iconRunConsole.png" ) ) );
mActionCheckQgisVersion->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconSuccess.svg" ) ) );
mActionOptions->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOptions.svg" ) ) );
mActionConfigureShortcuts->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionKeyboardShortcuts.svg" ) ) );
mActionCustomization->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInterfaceCustomization.svg" ) ) );
mActionHelpContents->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHelpContents.svg" ) ) );
mActionLocalHistogramStretch->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionLocalHistogramStretch.svg" ) ) );
mActionFullHistogramStretch->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFullHistogramStretch.svg" ) ) );
mActionIncreaseBrightness->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIncreaseBrightness.svg" ) ) );
mActionDecreaseBrightness->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDecreaseBrightness.svg" ) ) );
mActionIncreaseContrast->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIncreaseContrast.svg" ) ) );
mActionDecreaseContrast->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDecreaseContrast.svg" ) ) );
mActionZoomActualSize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomNative.png" ) ) );
mActionQgisHomePage->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionQgisHomePage.png" ) ) );
mActionAbout->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHelpAbout.svg" ) ) );
mActionSponsors->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHelpSponsors.png" ) ) );
mActionDraw->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDraw.svg" ) ) );
mActionToggleEditing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionToggleEditing.svg" ) ) );
mActionSaveLayerEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveAllEdits.svg" ) ) );
mActionAllEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAllEdits.svg" ) ) );
mActionSaveEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveEdits.svg" ) ) );
mActionSaveAllEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSaveAllEdits.svg" ) ) );
mActionRollbackEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRollbackEdits.svg" ) ) );
mActionRollbackAllEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRollbackAllEdits.svg" ) ) );
mActionCancelEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCancelEdits.svg" ) ) );
mActionCancelAllEdits->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCancelAllEdits.svg" ) ) );
mActionCutFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditCut.svg" ) ) );
mActionCopyFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditCopy.svg" ) ) );
mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionEditPaste.svg" ) ) );
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCapturePoint.svg" ) ) );
mActionMoveFeature->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMoveFeaturePoint.svg" ) ) );
mActionMoveFeatureCopy->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMoveFeatureCopyPoint.svg" ) ) );
mActionRotateFeature->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRotateFeature.svg" ) ) );
mActionReshapeFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionReshape.svg" ) ) );
mActionSplitFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSplitFeatures.svg" ) ) );
mActionSplitParts->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSplitParts.svg" ) ) );
mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ) );
mActionNodeTool->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNodeTool.svg" ) ) );
mActionSimplifyFeature->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSimplify.svg" ) ) );
mActionUndo->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
mActionRedo->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRedo.svg" ) ) );
mActionAddRing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddRing.svg" ) ) );
mActionFillRing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFillRing.svg" ) ) );
mActionAddPart->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddPart.svg" ) ) );
mActionDeleteRing->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteRing.svg" ) ) );
mActionDeletePart->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeletePart.svg" ) ) );
mActionMergeFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMergeFeatures.svg" ) ) );
mActionOffsetCurve->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOffsetCurve.svg" ) ) );
mActionMergeFeatureAttributes->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMergeFeatureAttributes.svg" ) ) );
mActionRotatePointSymbols->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionRotatePointSymbols.svg" ) ) );
mActionOffsetPointSymbol->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionOffsetPointSymbols.svg" ) ) );
mActionZoomIn->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomIn.svg" ) ) );
mActionZoomOut->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomOut.svg" ) ) );
mActionZoomFullExtent->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomFullExtent.svg" ) ) );
mActionZoomToSelected->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToSelected.svg" ) ) );
mActionShowRasterCalculator->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowRasterCalculator.png" ) ) );
mActionPan->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPan.svg" ) ) );
mActionPanToSelected->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPanToSelected.svg" ) ) );
mActionZoomLast->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomLast.svg" ) ) );
mActionZoomNext->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomNext.svg" ) ) );
mActionZoomToLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomToLayer.svg" ) ) );
mActionZoomActualSize->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionZoomActual.svg" ) ) );
mActionIdentify->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionIdentify.svg" ) ) );
mActionFeatureAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mAction.svg" ) ) );
mActionSelectFeatures->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectRectangle.svg" ) ) );
mActionSelectPolygon->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectPolygon.svg" ) ) );
mActionSelectFreehand->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectFreehand.svg" ) ) );
mActionSelectRadius->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectRadius.svg" ) ) );
mActionDeselectAll->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeselectAll.svg" ) ) );
mActionSelectAll->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSelectAll.svg" ) ) );
mActionInvertSelection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInvertSelection.svg" ) ) );
mActionSelectByExpression->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionSelect.svg" ) ) );
mActionSelectByForm->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconFormSelect.svg" ) ) );
mActionOpenTable->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionOpenTable.svg" ) ) );
mActionOpenFieldCalc->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCalculateField.svg" ) ) );
mActionMeasure->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasure.svg" ) ) );
mActionMeasureArea->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasureArea.svg" ) ) );
mActionMeasureAngle->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMeasureAngle.svg" ) ) );
mActionMapTips->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMapTips.svg" ) ) );
mActionShowBookmarks->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowBookmarks.svg" ) ) );
mActionNewBookmark->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionNewBookmark.svg" ) ) );
mActionCustomProjection->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionCustomProjection.svg" ) ) );
mActionAddWmsLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddWmsLayer.svg" ) ) );
mActionAddWcsLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddWcsLayer.svg" ) ) );
mActionAddWfsLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddWfsLayer.svg" ) ) );
mActionAddAfsLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddAfsLayer.svg" ) ) );
mActionAddAmsLayer->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddAmsLayer.svg" ) ) );
mActionAddToOverview->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionInOverview.svg" ) ) );
mActionAnnotation->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionAnnotation.svg" ) ) );
mActionFormAnnotation->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionFormAnnotation.svg" ) ) );
mActionHtmlAnnotation->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionHtmlAnnotation.svg" ) ) );
mActionSvgAnnotation->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionSvgAnnotation.svg" ) ) );
mActionTextAnnotation->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionTextAnnotation.svg" ) ) );
mActionLabeling->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionLabeling.svg" ) ) );
mActionShowPinnedLabels->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowPinnedLabels.svg" ) ) );
mActionPinLabels->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionPinLabels.svg" ) ) );
mActionShowHideLabels->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionShowHideLabels.svg" ) ) );
mActionMoveLabel->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionMoveLabel.svg" ) ) );
mActionRotateLabel->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRotateLabel.svg" ) ) );
mActionChangeLabelProperties->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionChangeLabelProperties.svg" ) ) );
mActionDiagramProperties->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/diagram.svg" ) ) );
mActionDecorationCopyright->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/copyright_label.svg" ) ) );
mActionDecorationNorthArrow->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/north_arrow.png" ) ) );
mActionDecorationScaleBar->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionScaleBar.svg" ) ) );
mActionDecorationGrid->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/transformed.svg" ) ) );
//change themes of all composers
QSet<QgsComposer *>::const_iterator composerIt = mPrintComposers.constBegin();
for ( ; composerIt != mPrintComposers.constEnd(); ++composerIt )
{
( *composerIt )->setupTheme();
}
emit currentThemeChanged( themeName );
}
void QgisApp::setupConnections()
{
// connect the "cleanup" slot
connect( qApp, &QApplication::aboutToQuit, this, &QgisApp::saveWindowState );
// signal when mouse moved over window (coords display in status bar)
connect( mMapCanvas, &QgsMapCanvas::xyCoordinates, this, &QgisApp::saveLastMousePosition );
connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgisApp::extentChanged );
connect( mMapCanvas, &QgsMapCanvas::scaleChanged, this, &QgisApp::showScale );
connect( mMapCanvas, &QgsMapCanvas::rotationChanged, this, &QgisApp::showRotation );
connect( mMapCanvas, &QgsMapCanvas::scaleChanged,
this, &QgisApp::updateMouseCoordinatePrecision );
connect( mMapCanvas, &QgsMapCanvas::mapToolSet,
this, &QgisApp::mapToolChanged );
connect( mMapCanvas, &QgsMapCanvas::selectionChanged,
this, &QgisApp::selectionChanged );
connect( mMapCanvas, &QgsMapCanvas::extentsChanged,
this, &QgisApp::markDirty );
connect( mMapCanvas, &QgsMapCanvas::layersChanged,
this, &QgisApp::markDirty );
connect( mMapCanvas, &QgsMapCanvas::zoomLastStatusChanged,
mActionZoomLast, &QAction::setEnabled );
connect( mMapCanvas, &QgsMapCanvas::zoomNextStatusChanged,
mActionZoomNext, &QAction::setEnabled );
connect( mRenderSuppressionCBox, &QAbstractButton::toggled,
this, [ = ]( bool flag )
{
Q_FOREACH ( QgsMapCanvas *canvas, mapCanvases() )
canvas->setRenderFlag( flag );
}
);
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged,
this, &QgisApp::reprojectAnnotations );
// connect MapCanvas keyPress event so we can check if selected feature collection must be deleted
connect( mMapCanvas, &QgsMapCanvas::keyPressed,
this, &QgisApp::mapCanvas_keyPressed );
// project crs connections
connect( QgsProject::instance(), &QgsProject::crsChanged,
this, &QgisApp::updateCrsStatusBar );
connect( QgsProject::instance(), &QgsProject::crsChanged,
this, [ = ]
{
mMapCanvas->setDestinationCrs( QgsProject::instance()->crs() );
} );
// connect legend signals
connect( mLayerTreeView, &QgsLayerTreeView::currentLayerChanged,
this, &QgisApp::activateDeactivateLayerRelatedActions );
connect( mLayerTreeView, &QgsLayerTreeView::currentLayerChanged,
this, &QgisApp::setMapStyleDockLayer );
connect( mLayerTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgisApp::legendLayerSelectionChanged );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::addedChildren,
this, &QgisApp::markDirty );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::addedChildren,
this, &QgisApp::updateNewLayerInsertionPoint );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::removedChildren,
this, &QgisApp::markDirty );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::removedChildren,
this, &QgisApp::updateNewLayerInsertionPoint );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::visibilityChanged,
this, &QgisApp::markDirty );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), &QgsLayerTreeNode::customPropertyChanged,
this, &QgisApp::markDirty );
// connect map layer registry
connect( QgsProject::instance(), &QgsProject::layersAdded,
this, &QgisApp::layersWereAdded );
connect( QgsProject::instance(),
static_cast < void ( QgsProject::* )( const QStringList & ) >( &QgsProject::layersWillBeRemoved ),
this, &QgisApp::removingLayers );
// connect initialization signal
connect( this, &QgisApp::initializationCompleted,
this, &QgisApp::fileOpenAfterLaunch );
// Connect warning dialog from project reading
connect( QgsProject::instance(), &QgsProject::oldProjectVersionWarning,
this, &QgisApp::oldProjectVersionWarning );
connect( QgsProject::instance(), &QgsProject::layerLoaded,
this, &QgisApp::showProgress );
connect( QgsProject::instance(), &QgsProject::loadingLayer,
this, &QgisApp::showStatusMessage );
connect( QgsProject::instance(), &QgsProject::readProject,
this, &QgisApp::readProject );
connect( QgsProject::instance(), &QgsProject::writeProject,
this, &QgisApp::writeProject );
connect( this, &QgisApp::projectRead,
this, &QgisApp::fileOpenedOKAfterLaunch );
connect( QgsProject::instance(), &QgsProject::transactionGroupsChanged, this, &QgisApp::onTransactionGroupsChanged );
// connect preview modes actions
connect( mActionPreviewModeOff, &QAction::triggered, this, &QgisApp::disablePreviewMode );
connect( mActionPreviewModeGrayscale, &QAction::triggered, this, &QgisApp::activateGrayscalePreview );
connect( mActionPreviewModeMono, &QAction::triggered, this, &QgisApp::activateMonoPreview );
connect( mActionPreviewProtanope, &QAction::triggered, this, &QgisApp::activateProtanopePreview );
connect( mActionPreviewDeuteranope, &QAction::triggered, this, &QgisApp::activateDeuteranopePreview );
// setup undo/redo actions
connect( mUndoWidget, &QgsUndoWidget::undoStackChanged, this, &QgisApp::updateUndoActions );
connect( mPrintComposersMenu, &QMenu::aboutToShow, this, &QgisApp::composerMenuAboutToShow );
connect( QgsProject::instance()->layoutManager(), &QgsLayoutManager::compositionAboutToBeRemoved, this, &QgisApp::compositionAboutToBeRemoved );
}
void QgisApp::createCanvasTools()
{
// create tools
mMapTools.mZoomIn = new QgsMapToolZoom( mMapCanvas, false /* zoomIn */ );
mMapTools.mZoomIn->setAction( mActionZoomIn );
mMapTools.mZoomOut = new QgsMapToolZoom( mMapCanvas, true /* zoomOut */ );
mMapTools.mZoomOut->setAction( mActionZoomOut );
mMapTools.mPan = new QgsMapToolPan( mMapCanvas );
mMapTools.mPan->setAction( mActionPan );
mMapTools.mIdentify = new QgsMapToolIdentifyAction( mMapCanvas );
mMapTools.mIdentify->setAction( mActionIdentify );
connect( mMapTools.mIdentify, &QgsMapToolIdentifyAction::copyToClipboard,
this, &QgisApp::copyFeatures );
mMapTools.mFeatureAction = new QgsMapToolFeatureAction( mMapCanvas );
mMapTools.mFeatureAction->setAction( mActionFeatureAction );
mMapTools.mMeasureDist = new QgsMeasureTool( mMapCanvas, false /* area */ );
mMapTools.mMeasureDist->setAction( mActionMeasure );
mMapTools.mMeasureArea = new QgsMeasureTool( mMapCanvas, true /* area */ );
mMapTools.mMeasureArea->setAction( mActionMeasureArea );
mMapTools.mMeasureAngle = new QgsMapToolMeasureAngle( mMapCanvas );
mMapTools.mMeasureAngle->setAction( mActionMeasureAngle );
mMapTools.mTextAnnotation = new QgsMapToolTextAnnotation( mMapCanvas );
mMapTools.mTextAnnotation->setAction( mActionTextAnnotation );
mMapTools.mFormAnnotation = new QgsMapToolFormAnnotation( mMapCanvas );
mMapTools.mFormAnnotation->setAction( mActionFormAnnotation );
mMapTools.mHtmlAnnotation = new QgsMapToolHtmlAnnotation( mMapCanvas );
mMapTools.mHtmlAnnotation->setAction( mActionHtmlAnnotation );
mMapTools.mSvgAnnotation = new QgsMapToolSvgAnnotation( mMapCanvas );
mMapTools.mSvgAnnotation->setAction( mActionSvgAnnotation );
mMapTools.mAnnotation = new QgsMapToolAnnotation( mMapCanvas );
mMapTools.mAnnotation->setAction( mActionAnnotation );
mMapTools.mAddFeature = new QgsMapToolAddFeature( mMapCanvas );
mMapTools.mAddFeature->setAction( mActionAddFeature );
mMapTools.mCircularStringCurvePoint = new QgsMapToolCircularStringCurvePoint( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mCircularStringCurvePoint->setAction( mActionCircularStringCurvePoint );
mMapTools.mCircularStringRadius = new QgsMapToolCircularStringRadius( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mCircularStringRadius->setAction( mActionCircularStringRadius );
mMapTools.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas, QgsMapToolMoveFeature::Move );
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
mMapTools.mMoveFeatureCopy = new QgsMapToolMoveFeature( mMapCanvas, QgsMapToolMoveFeature::CopyMove );
mMapTools.mMoveFeatureCopy->setAction( mActionMoveFeatureCopy );
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas );
mMapTools.mRotateFeature->setAction( mActionRotateFeature );
mMapTools.mOffsetCurve = new QgsMapToolOffsetCurve( mMapCanvas );
mMapTools.mOffsetCurve->setAction( mActionOffsetCurve );
mMapTools.mReshapeFeatures = new QgsMapToolReshape( mMapCanvas );
mMapTools.mReshapeFeatures->setAction( mActionReshapeFeatures );
mMapTools.mSplitFeatures = new QgsMapToolSplitFeatures( mMapCanvas );
mMapTools.mSplitFeatures->setAction( mActionSplitFeatures );
mMapTools.mSplitParts = new QgsMapToolSplitParts( mMapCanvas );
mMapTools.mSplitParts->setAction( mActionSplitParts );
mMapTools.mSelectFeatures = new QgsMapToolSelectFeatures( mMapCanvas );
mMapTools.mSelectFeatures->setAction( mActionSelectFeatures );
mMapTools.mSelectPolygon = new QgsMapToolSelectPolygon( mMapCanvas );
mMapTools.mSelectPolygon->setAction( mActionSelectPolygon );
mMapTools.mSelectFreehand = new QgsMapToolSelectFreehand( mMapCanvas );
mMapTools.mSelectFreehand->setAction( mActionSelectFreehand );
mMapTools.mSelectRadius = new QgsMapToolSelectRadius( mMapCanvas );
mMapTools.mSelectRadius->setAction( mActionSelectRadius );
mMapTools.mAddRing = new QgsMapToolAddRing( mMapCanvas );
mMapTools.mAddRing->setAction( mActionAddRing );
mMapTools.mFillRing = new QgsMapToolFillRing( mMapCanvas );
mMapTools.mFillRing->setAction( mActionFillRing );
mMapTools.mAddPart = new QgsMapToolAddPart( mMapCanvas );
mMapTools.mAddPart->setAction( mActionAddPart );
mMapTools.mSimplifyFeature = new QgsMapToolSimplify( mMapCanvas );
mMapTools.mSimplifyFeature->setAction( mActionSimplifyFeature );
mMapTools.mDeleteRing = new QgsMapToolDeleteRing( mMapCanvas );
mMapTools.mDeleteRing->setAction( mActionDeleteRing );
mMapTools.mDeletePart = new QgsMapToolDeletePart( mMapCanvas );
mMapTools.mDeletePart->setAction( mActionDeletePart );
mMapTools.mNodeTool = new QgsMapToolNodeTool( mMapCanvas );
mMapTools.mNodeTool->setAction( mActionNodeTool );
mMapTools.mRotatePointSymbolsTool = new QgsMapToolRotatePointSymbols( mMapCanvas );
mMapTools.mRotatePointSymbolsTool->setAction( mActionRotatePointSymbols );
mMapTools.mOffsetPointSymbolTool = new QgsMapToolOffsetPointSymbol( mMapCanvas );
mMapTools.mOffsetPointSymbolTool->setAction( mActionOffsetPointSymbol );
mMapTools.mPinLabels = new QgsMapToolPinLabels( mMapCanvas );
mMapTools.mPinLabels->setAction( mActionPinLabels );
mMapTools.mShowHideLabels = new QgsMapToolShowHideLabels( mMapCanvas );
mMapTools.mShowHideLabels->setAction( mActionShowHideLabels );
mMapTools.mMoveLabel = new QgsMapToolMoveLabel( mMapCanvas );
mMapTools.mMoveLabel->setAction( mActionMoveLabel );
mMapTools.mRotateLabel = new QgsMapToolRotateLabel( mMapCanvas );
mMapTools.mRotateLabel->setAction( mActionRotateLabel );
mMapTools.mChangeLabelProperties = new QgsMapToolChangeLabelProperties( mMapCanvas );
mMapTools.mChangeLabelProperties->setAction( mActionChangeLabelProperties );
//ensure that non edit tool is initialized or we will get crashes in some situations
mNonEditMapTool = mMapTools.mPan;
}
void QgisApp::createOverview()
{
// overview canvas
mOverviewCanvas = new QgsMapOverviewCanvas( nullptr, mMapCanvas );
//set canvas color to default
QgsSettings settings;
int red = settings.value( QStringLiteral( "qgis/default_canvas_color_red" ), 255 ).toInt();
int green = settings.value( QStringLiteral( "qgis/default_canvas_color_green" ), 255 ).toInt();
int blue = settings.value( QStringLiteral( "qgis/default_canvas_color_blue" ), 255 ).toInt();
mOverviewCanvas->setBackgroundColor( QColor( red, green, blue ) );
mOverviewCanvas->setWhatsThis( tr( "Map overview canvas. This canvas can be used to display a locator map that shows the current extent of the map canvas. The current extent is shown as a red rectangle. Any layer on the map can be added to the overview canvas." ) );
mOverviewMapCursor = new QCursor( Qt::OpenHandCursor );
mOverviewCanvas->setCursor( *mOverviewMapCursor );
// QVBoxLayout *myOverviewLayout = new QVBoxLayout;
// myOverviewLayout->addWidget(overviewCanvas);
// overviewFrame->setLayout(myOverviewLayout);
mOverviewDock = new QgsDockWidget( tr( "Overview Panel" ), this );
mOverviewDock->setObjectName( QStringLiteral( "Overview" ) );
mOverviewDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
mOverviewDock->setWidget( mOverviewCanvas );
addDockWidget( Qt::LeftDockWidgetArea, mOverviewDock );
// add to the Panel submenu
mPanelMenu->addAction( mOverviewDock->toggleViewAction() );
mLayerTreeCanvasBridge->setOvervewCanvas( mOverviewCanvas );
}
void QgisApp::addDockWidget( Qt::DockWidgetArea area, QDockWidget *thepDockWidget )
{
QMainWindow::addDockWidget( area, thepDockWidget );
// Make the right and left docks consume all vertical space and top
// and bottom docks nest between them
setCorner( Qt::TopLeftCorner, Qt::LeftDockWidgetArea );
setCorner( Qt::BottomLeftCorner, Qt::LeftDockWidgetArea );
setCorner( Qt::TopRightCorner, Qt::RightDockWidgetArea );
setCorner( Qt::BottomRightCorner, Qt::RightDockWidgetArea );
// add to the Panel submenu
mPanelMenu->addAction( thepDockWidget->toggleViewAction() );
thepDockWidget->show();
// refresh the map canvas
refreshMapCanvas();
}
void QgisApp::removeDockWidget( QDockWidget *thepDockWidget )
{
QMainWindow::removeDockWidget( thepDockWidget );
mPanelMenu->removeAction( thepDockWidget->toggleViewAction() );
}
QToolBar *QgisApp::addToolBar( const QString &name )
{
QToolBar *toolBar = QMainWindow::addToolBar( name );
// add to the Toolbar submenu
mToolbarMenu->addAction( toolBar->toggleViewAction() );
return toolBar;
}
void QgisApp::addToolBar( QToolBar *toolBar, Qt::ToolBarArea area )
{
QMainWindow::addToolBar( area, toolBar );
// add to the Toolbar submenu
mToolbarMenu->addAction( toolBar->toggleViewAction() );
}
QgsLayerTreeView *QgisApp::layerTreeView()
{
Q_ASSERT( mLayerTreeView );
return mLayerTreeView;
}
QgsPluginManager *QgisApp::pluginManager()
{
Q_ASSERT( mPluginManager );
return mPluginManager;
}
QgsMapCanvas *QgisApp::mapCanvas()
{
Q_ASSERT( mMapCanvas );
return mMapCanvas;
}
QgsMapCanvas *QgisApp::createNewMapCanvas( const QString &name )
{
QgsMapCanvasDockWidget *dock = createNewMapCanvasDock( name );
if ( !dock )
return nullptr;
dock->mapCanvas()->setLayers( mMapCanvas->layers() );
dock->mapCanvas()->setExtent( mMapCanvas->extent() );
dock->mapCanvas()->setDestinationCrs( QgsProject::instance()->crs() );
dock->mapCanvas()->freeze( false );
return dock->mapCanvas();
}
QgsMapCanvasDockWidget *QgisApp::createNewMapCanvasDock( const QString &name, bool isFloating, const QRect &dockGeometry, Qt::DockWidgetArea area )
{
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;
}
}
QgsMapCanvasDockWidget *mapCanvasWidget = new QgsMapCanvasDockWidget( name, this );
mapCanvasWidget->setAllowedAreas( Qt::AllDockWidgetAreas );
mapCanvasWidget->setMainCanvas( mMapCanvas );
QgsMapCanvas *mapCanvas = mapCanvasWidget->mapCanvas();
mapCanvas->freeze( true );
mapCanvas->setObjectName( name );
connect( mapCanvas, &QgsMapCanvas::messageEmitted, this, &QgisApp::displayMessage );
connect( mLayerTreeCanvasBridge, &QgsLayerTreeMapCanvasBridge::canvasLayersChanged, mapCanvas, &QgsMapCanvas::setLayers );
applyProjectSettingsToCanvas( mapCanvas );
applyDefaultSettingsToCanvas( mapCanvas );
// add existing annotations to canvas
Q_FOREACH ( QgsAnnotation *annotation, QgsProject::instance()->annotationManager()->annotations() )
{
QgsMapCanvasAnnotationItem *canvasItem = new QgsMapCanvasAnnotationItem( annotation, mapCanvas );
Q_UNUSED( canvasItem ); //item is already added automatically to canvas scene