Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
10754 lines (9222 sloc) 361.389 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. *
* *
***************************************************************************/
//
// QT4 includes make sure to use the new <CamelCase> style!
//
#include <QAction>
#include <QApplication>
#include <QBitmap>
#include <QCheckBox>
#include <QClipboard>
#include <QColor>
#include <QCursor>
#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialog>
#include <QDir>
#include <QDockWidget>
#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 <QSettings>
#include <QSpinBox>
#include <QSplashScreen>
#include <QStatusBar>
#include <QStringList>
#include <QTcpSocket>
#include <QTextStream>
#include <QtGlobal>
#include <QThread>
#include <QTimer>
#include <QToolButton>
#include <QUuid>
#include <QVBoxLayout>
#include <QWhatsThis>
#include <QWidgetAction>
#include <qgsnetworkaccessmanager.h>
#include <qgsapplication.h>
#include <qgscomposition.h>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QAuthenticator>
#include <QNetworkDiskCache>
//
// 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 "qgsattributeaction.h"
#include "qgsattributetabledialog.h"
#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 "qgscredentialdialog.h"
#include "qgscursors.h"
#include "qgscustomization.h"
#include "qgscustomlayerorderwidget.h"
#include "qgscustomprojectiondialog.h"
#include "qgsdatasourceuri.h"
#include "qgsdatumtransformdialog.h"
#include "qgsdxfexport.h"
#include "qgsdxfexportdialog.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 "qgsformannotationitem.h"
#include "qgsfieldcalculator.h"
#include "qgshtmlannotationitem.h"
#include "qgsgenericprojectionselector.h"
#include "qgsgpsinformationwidget.h"
#include "qgsguivectorlayertools.h"
#include "qgslabelinggui.h"
#include "qgslayerdefinition.h"
#include "qgslayertree.h"
#include "qgslayertreemapcanvasbridge.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeregistrybridge.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgslayertreeviewdefaultactions.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmapcanvassnappingutils.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaplayerstyleguiutils.h"
#include "qgsmapoverviewcanvas.h"
#include "qgsmaprenderer.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 "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 "qgsrectangle.h"
#include "qgsscalecombobox.h"
#include "qgsscalevisibilitydialog.h"
#include "qgsshortcutsmanager.h"
#include "qgssinglebandgrayrenderer.h"
#include "qgssnappingdialog.h"
#include "qgssponsors.h"
#include "qgsstatisticalsummarydockwidget.h"
#include "qgssvgannotationitem.h"
#include "qgstextannotationitem.h"
#include "qgstipgui.h"
#include "qgsundowidget.h"
#include "qgsuserinputdockwidget.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorfilewriter.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerproperties.h"
#include "qgsvisibilitypresets.h"
#include "qgsmessagelogviewer.h"
#include "qgsdataitem.h"
#include "qgsmaplayeractionregistry.h"
#include "qgswelcomepage.h"
#include "qgsmaprendererparalleljob.h"
#include "qgsversioninfo.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 <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 "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 "qgspythonutils.h"
#ifndef Q_OS_WIN
#include <dlfcn.h>
#else
#include <windows.h>
#include <DbgHelp.h>
#endif
#ifdef HAVE_TOUCH
#include "qgsmaptooltouch.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 ( QString( QGis::QGIS_VERSION ).endsWith( "Master" ) )
{
caption += QString( "%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() == QApplication::instance()->thread() )
return new QgsMessageViewer( QgisApp::instance() );
else
return new QgsMessageOutputConsole();
}
static void customSrsValidation_( QgsCoordinateReferenceSystem &srs )
{
QgisApp::instance()->emitCustomSrsValidation( srs );
}
void QgisApp::emitCustomSrsValidation( QgsCoordinateReferenceSystem &srs )
{
emit customSrsValidation( srs );
}
void QgisApp::layerTreeViewDoubleClicked( const QModelIndex& index )
{
Q_UNUSED( index )
QSettings settings;
switch ( settings.value( "/qgis/legendDoubleClickAction", 0 ).toInt() )
{
case 0:
QgisApp::instance()->layerProperties();
break;
case 1:
QgisApp::instance()->attributeTable();
break;
default:
break;
}
}
void QgisApp::activeLayerChanged( QgsMapLayer* layer )
{
if ( mMapCanvas )
mMapCanvas->setCurrentLayer( layer );
}
/**
* 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::validateSrs( QgsCoordinateReferenceSystem &srs )
{
static QString authid = QString::null;
QSettings mySettings;
QString myDefaultProjectionOption = mySettings.value( "/Projections/defaultBehaviour", "prompt" ).toString();
if ( myDefaultProjectionOption == "prompt" )
{
// @note this class is not a descendent of QWidget so we can't pass
// it in the ctor of the layer projection selector
QgsGenericProjectionSelector *mySelector = new QgsGenericProjectionSelector();
mySelector->setMessage( srs.validationHint() ); //shows a generic message, if not specified
if ( authid.isNull() )
authid = QgisApp::instance()->mapCanvas()->mapSettings().destinationCrs().authid();
QgsCoordinateReferenceSystem defaultCrs;
if ( defaultCrs.createFromOgcWmsCrs( authid ) )
{
mySelector->setSelectedCrsId( defaultCrs.srsid() );
}
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->selectedCrsId() ) );
authid = mySelector->selectedAuthId();
srs.createFromOgcWmsCrs( mySelector->selectedAuthId() );
}
if ( waiting )
QApplication::restoreOverrideCursor();
delete mySelector;
}
else if ( myDefaultProjectionOption == "useProject" )
{
// XXX TODO: Change project to store selected CS as 'projectCRS' not 'selectedWkt'
authid = QgisApp::instance()->mapCanvas()->mapSettings().destinationCrs().authid();
srs.createFromOgcWmsCrs( authid );
QgsDebugMsg( "Layer srs set from project: " + authid );
messageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to project CRS %1 - %2" ).arg( authid ).arg( srs.description() ), QgsMessageBar::WARNING, messageTimeout() );
}
else ///Projections/defaultBehaviour==useGlobal
{
authid = mySettings.value( "/Projections/layerDefaultCrs", GEO_EPSG_CRS_AUTHID ).toString();
srs.createFromOgcWmsCrs( authid );
QgsDebugMsg( "Layer srs set from default: " + authid );
messageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to CRS %1 - %2" ).arg( authid ).arg( srs.description() ), QgsMessageBar::WARNING, messageTimeout() );
}
}
static bool cmpByText_( QAction* a, QAction* b )
{
return QString::localeAwareCompare( a->text(), b->text() ) < 0;
}
QgisApp *QgisApp::smInstance = 0;
// constructor starts here
QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent, Qt::WindowFlags fl )
: QMainWindow( parent, fl )
#ifdef Q_OS_WIN
, mSkipNextContextMenuEvent( 0 )
#endif
, mNonEditMapTool( 0 )
, mScaleLabel( 0 )
, mScaleEdit( 0 )
, mScaleEditValidator( 0 )
, mCoordsLabel( 0 )
, mCoordsEdit( 0 )
, mCoordsEditValidator( 0 )
, mRotationLabel( 0 )
, mRotationEdit( 0 )
, mRotationEditValidator( 0 )
, mProgressBar( 0 )
, mRenderSuppressionCBox( 0 )
, mOnTheFlyProjectionStatusLabel( 0 )
, mOnTheFlyProjectionStatusButton( 0 )
, mMessageButton( 0 )
, mFeatureActionMenu( 0 )
, mPopupMenu( 0 )
, mDatabaseMenu( 0 )
, mWebMenu( 0 )
, mToolPopupOverviews( 0 )
, mToolPopupDisplay( 0 )
, mLayerTreeCanvasBridge( 0 )
, mSplash( splash )
, mMousePrecisionDecimalPlaces( 0 )
, mInternalClipboard( 0 )
, mShowProjectionTab( false )
, mPythonUtils( 0 )
, mComposerManager( 0 )
, mpTileScaleWidget( 0 )
, mpGpsWidget( 0 )
, mSnappingUtils( 0 )
, mProjectLastModified()
, mWelcomePage( 0 )
, mCentralContainer( 0 )
{
if ( smInstance )
{
QMessageBox::critical(
this,
tr( "Multiple Instances of QgisApp" ),
tr( "Multiple instances of QGIS application object detected.\nPlease contact the developers.\n" ) );
abort();
}
smInstance = this;
namSetup();
// load GUI: actions, menus, toolbars
setupUi( this );
//////////
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::createDB( &dbError ) )
{
QMessageBox::critical( this, tr( "Private qgis.db" ), dbError );
}
// Create the themes folder for the user
QgsApplication::createThemeFolder();
mSplash->showMessage( tr( "Reading settings" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
mSplash->showMessage( tr( "Setting up the GUI" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
QSettings settings;
// set up stylesheet builder and apply saved or default style options
mStyleSheetBuilder = new QgisAppStyleSheet( this );
connect( mStyleSheetBuilder, SIGNAL( appStyleSheetChanged( const QString& ) ),
this, SLOT( setAppStyleSheet( const QString& ) ) );
mStyleSheetBuilder->buildStyleSheet( mStyleSheetBuilder->defaultOptions() );
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
mMapCanvas = new QgsMapCanvas( centralWidget, "theMapCanvas" );
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( "/qgis/default_canvas_color_red", 255 ).toInt();
int myGreen = settings.value( "/qgis/default_canvas_color_green", 255 ).toInt();
int myBlue = settings.value( "/qgis/default_canvas_color_blue", 255 ).toInt();
mMapCanvas->setCanvasColor( QColor( myRed, myGreen, myBlue ) );
// what type of project to auto-open
mProjOpen = settings.value( "/qgis/projOpenAtLaunch", 0 ).toInt();
mWelcomePage = new QgsWelcomePage;
mCentralContainer = new QStackedWidget;
mCentralContainer->insertWidget( 0, mMapCanvas );
mCentralContainer->insertWidget( 1, mWelcomePage );
centralLayout->addWidget( mCentralContainer, 0, 0, 2, 1 );
connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( showMapCanvas() ) );
mCentralContainer->setCurrentIndex( mProjOpen ? 0 : 1 );
// a bar to warn the user with non-blocking messages
mInfoBar = new QgsMessageBar( centralWidget );
mInfoBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
centralLayout->addWidget( mInfoBar, 0, 0, 1, 1 );
// User Input Dock Widget
mUserInputDockWidget = new QgsUserInputDockWidget( this );
mUserInputDockWidget->setObjectName( "UserInputDockWidget" );
//set the focus to the map canvas
mMapCanvas->setFocus();
mLayerTreeView = new QgsLayerTreeView( this );
mLayerTreeView->setObjectName( "theLayerTreeView" ); // "theLayerTreeView" used to find this canonical instance later
// create undo widget
mUndoWidget = new QgsUndoWidget( NULL, mMapCanvas );
mUndoWidget->setObjectName( "Undo" );
// Advanced Digitizing dock
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
mAdvancedDigitizingDockWidget->setObjectName( "AdvancedDigitizingTools" );
// Statistical Summary dock
mStatisticalSummaryDockWidget = new QgsStatisticalSummaryDockWidget( this );
mStatisticalSummaryDockWidget->setObjectName( "StatistalSummaryDockWidget" );
// Bookmarks dock
mBookMarksDockWidget = new QgsBookmarks( this );
mBookMarksDockWidget->setObjectName( "BookmarksDockWidget" );
mSnappingUtils = new QgsMapCanvasSnappingUtils( mMapCanvas, this );
mMapCanvas->setSnappingUtils( mSnappingUtils );
connect( QgsProject::instance(), SIGNAL( snapSettingsChanged() ), mSnappingUtils, SLOT( readConfigFromProject() ) );
connect( this, SIGNAL( projectRead() ), mSnappingUtils, SLOT( readConfigFromProject() ) );
createActions();
createActionGroups();
createMenus();
createToolBars();
createStatusBar();
createCanvasTools();
mMapCanvas->freeze();
initLayerTreeView();
createOverview();
createMapTips();
createDecorations();
readSettings();
updateRecentProjectPaths();
updateProjectFromTemplates();
legendLayerSelectionChanged();
mSaveRollbackInProgress = false;
// initialize the plugin manager
mPluginManager = new QgsPluginManager( this, restorePlugins );
addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget );
mUndoWidget->hide();
mSnappingDialog = new QgsSnappingDialog( this, mMapCanvas );
mSnappingDialog->setObjectName( "SnappingOption" );
mBrowserWidget = new QgsBrowserDockWidget( tr( "Browser Panel" ), this );
mBrowserWidget->setObjectName( "Browser" );
addDockWidget( Qt::LeftDockWidgetArea, mBrowserWidget );
mBrowserWidget->hide();
mBrowserWidget2 = new QgsBrowserDockWidget( tr( "Browser Panel (2)" ), this );
mBrowserWidget2->setObjectName( "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 QDockWidget( tr( "GPS Information Panel" ), this );
mpGpsDock->setObjectName( "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 = 0;
mLogViewer = new QgsMessageLogViewer( statusBar(), this );
mLogDock = new QDockWidget( tr( "Log Messages Panel" ), this );
mLogDock->setObjectName( "MessageLog" );
mLogDock->setAllowedAreas( Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea );
addDockWidget( Qt::BottomDockWidgetArea, mLogDock );
mLogDock->setWidget( mLogViewer );
mLogDock->hide();
connect( mMessageButton, SIGNAL( toggled( bool ) ), mLogDock, SLOT( setVisible( bool ) ) );
connect( mLogDock, SIGNAL( visibilityChanged( bool ) ), mMessageButton, SLOT( setChecked( bool ) ) );
mVectorLayerTools = new QgsGuiVectorLayerTools();
// Init the editor widget types
QgsEditorWidgetRegistry::initEditors( mMapCanvas, mInfoBar );
mInternalClipboard = new QgsClipboard; // create clipboard
connect( mInternalClipboard, SIGNAL( changed() ), this, SLOT( 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( NULL ); // after members were created
connect( QgsMapLayerActionRegistry::instance(), SIGNAL( changed() ), this, SLOT( refreshActionFeatureAction() ) );
// set application's caption
QString caption = tr( "QGIS - %1 ('%2')" ).arg( QGis::QGIS_VERSION ).arg( QGis::QGIS_RELEASE_NAME );
setWindowTitle( caption );
QgsMessageLog::logMessage( tr( "QGIS starting..." ), QString::null, QgsMessageLog::INFO );
// set QGIS specific srs validation
connect( this, SIGNAL( customSrsValidation( QgsCoordinateReferenceSystem& ) ),
this, SLOT( validateSrs( QgsCoordinateReferenceSystem& ) ) );
QgsCoordinateReferenceSystem::setCustomSrsValidation( 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( "plugins/searchPathsForPlugins", "" ).toString();
if ( !myPaths.isEmpty() )
{
QStringList myPathList = myPaths.split( "|" );
QgsPluginRegistry::instance()->restoreSessionPlugins( myPathList );
}
}
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
// initialize the plugin installer to start fetching repositories in background
QgsPythonRunner::run( "import pyplugin_installer" );
QgsPythonRunner::run( "pyplugin_installer.initPluginInstaller()" );
// enable Python in the Plugin Manager and pass the PythonUtils to it
mPluginManager->setPythonUtils( mPythonUtils );
}
else if ( mActionShowPythonDialog )
{
// python is disabled so get rid of the action for python console
delete mActionShowPythonDialog;
mActionShowPythonDialog = 0;
}
// Set icon size of toolbars
int size = settings.value( "/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 initialised before trying to restore their state.
//
mSplash->showMessage( tr( "Restoring window state" ), Qt::AlignHCenter | Qt::AlignBottom );
qApp->processEvents();
restoreWindowState();
// do main window customization - after window state has been restored, before the window is shown
QgsCustomization::instance()->updateMainWindow( mToolbarMenu );
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;
mTrustedMacros = false;
// setup drag drop
setAcceptDrops( true );
mFullScreenMode = false;
mPrevScreenModeMaximized = false;
show();
qApp->processEvents();
mMapCanvas->freeze( false );
mMapCanvas->clearExtentHistory(); // reset zoomnext/zoomlast
mLastComposerId = 0;
// Show a nice tip of the day
if ( settings.value( QString( "/qgis/showTips%1" ).arg( QGis::QGIS_VERSION_INT / 100 ), true ).toBool() )
{
mSplash->hide();
QgsTipGui myTip;
myTip.exec();
}
else
{
QgsDebugMsg( "Tips are disabled" );
}
#ifdef HAVE_TOUCH
//add reacting to long click in touch
grabGesture( Qt::TapAndHoldGesture );
#else
//remove mActionTouch button
delete mActionTouch;
mActionTouch = 0;
#endif
// supposedly all actions have been added, now register them to the shortcut manager
QgsShortcutsManager::instance()->registerAllChildrenActions( this );
QgsProviderRegistry::instance()->registerGuis( this );
// update windows
qApp->processEvents();
fileNewBlank(); // prepare empty project, also skips any default templates from loading
// 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
} // QgisApp ctor
QgisApp::QgisApp()
: QMainWindow( 0, 0 )
, mStyleSheetBuilder( 0 )
, mActionPluginSeparator1( 0 )
, mActionPluginSeparator2( 0 )
, mActionRasterSeparator( 0 )
, mMapToolGroup( 0 )
, mPreviewGroup( 0 )
#ifdef Q_OS_MAC
, mWindowMenu( 0 )
#endif
, mPanelMenu( 0 )
, mToolbarMenu( 0 )
, mLayerTreeDock( 0 )
, mLayerOrderDock( 0 )
, mOverviewDock( 0 )
, mpGpsDock( 0 )
, mLogDock( 0 )
, mNonEditMapTool( 0 )
, mScaleLabel( 0 )
, mScaleEdit( 0 )
, mScaleEditValidator( 0 )
, mCoordsLabel( 0 )
, mCoordsEdit( 0 )
, mCoordsEditValidator( 0 )
, mRotationLabel( 0 )
, mRotationEdit( 0 )
, mRotationEditValidator( 0 )
, mProgressBar( 0 )
, mRenderSuppressionCBox( 0 )
, mToggleExtentsViewButton( 0 )
, mOnTheFlyProjectionStatusLabel( 0 )
, mOnTheFlyProjectionStatusButton( 0 )
, mMessageButton( 0 )
, mFeatureActionMenu( 0 )
, mPopupMenu( 0 )
, mDatabaseMenu( 0 )
, mWebMenu( 0 )
, mToolPopupOverviews( 0 )
, mToolPopupDisplay( 0 )
, mMapCanvas( 0 )
, mLayerTreeView( 0 )
, mLayerTreeCanvasBridge( 0 )
, mMapLayerOrder( 0 )
, mOverviewMapCursor( 0 )
, mMapWindow( 0 )
, mQgisInterface( 0 )
, mSplash( 0 )
, mMousePrecisionDecimalPlaces( 0 )
, mInternalClipboard( 0 )
, mShowProjectionTab( false )
, mpMapTipsTimer( 0 )
, mDizzyTimer( 0 )
, mpMaptip( 0 )
, mMapTipsVisible( false )
, mFullScreenMode( false )
, mPrevScreenModeMaximized( false )
, mSaveRollbackInProgress( false )
, mPythonUtils( 0 )
, mBrowserWidget( 0 )
, mBrowserWidget2( 0 )
, mAdvancedDigitizingDockWidget( 0 )
, mStatisticalSummaryDockWidget( 0 )
, mBookMarksDockWidget( 0 )
, mSnappingDialog( 0 )
, mPluginManager( 0 )
, mComposerManager( 0 )
, mpTileScaleWidget( 0 )
, mLastComposerId( 0 )
, mpGpsWidget( 0 )
, mLastMapToolMessage( 0 )
, mLogViewer( 0 )
, mTrustedMacros( false )
, mMacrosWarn( 0 )
, mUserInputDockWidget( 0 )
, mVectorLayerTools( 0 )
, mActionFilterLegend( 0 )
, mSnappingUtils( 0 )
, mProjectLastModified()
, mWelcomePage( 0 )
, mCentralContainer( 0 )
{
smInstance = this;
setupUi( this );
mInternalClipboard = new QgsClipboard;
mMapCanvas = new QgsMapCanvas();
mMapCanvas->freeze();
mLayerTreeView = new QgsLayerTreeView( this );
mUndoWidget = new QgsUndoWidget( NULL, mMapCanvas );
mInfoBar = new QgsMessageBar( centralWidget() );
// More tests may need more members to be initialized
}
QgisApp::~QgisApp()
{
mMapCanvas->stopRendering();
delete mInternalClipboard;
delete mQgisInterface;
delete mStyleSheetBuilder;
delete mMapTools.mZoomIn;
delete mMapTools.mZoomOut;
delete mMapTools.mPan;
#ifdef HAVE_TOUCH
delete mMapTools.mTouch;
#endif
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.mMoveLabel;
delete mMapTools.mNodeTool;
delete mMapTools.mOffsetCurve;
delete mMapTools.mPinLabels;
delete mMapTools.mReshapeFeatures;
delete mMapTools.mRotateFeature;
delete mMapTools.mRotateLabel;
delete mMapTools.mRotatePointSymbolsTool;
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 mVectorLayerTools;
delete mWelcomePage;
deletePrintComposers();
removeAnnotationItems();
// cancel request for FileOpen events
QgsApplication::setFileOpenEventReceiver( 0 );
QgsApplication::exitQgis();
delete QgsProject::instance();
delete mPythonUtils;
}
void QgisApp::dragEnterEvent( QDragEnterEvent *event )
{
if ( event->mimeData()->hasUrls() || event->mimeData()->hasFormat( "application/x-vnd.qgis.qgis.uri" ) )
{
event->acceptProposedAction();
}
}
void QgisApp::dropEvent( QDropEvent *event )
{
mMapCanvas->freeze();
// get the file list
QList<QUrl>::iterator i;
QList<QUrl>urls = event->mimeData()->urls();
for ( i = urls.begin(); i != urls.end(); ++i )
{
QString fileName = i->toLocalFile();
// 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() )
{
openFile( fileName );
}
}
if ( QgsMimeDataUtils::isUriList( event->mimeData() ) )
{
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
foreach ( const QgsMimeDataUtils::Uri& u, lst )
{
QString uri = crsAndFormatAdjustedLayerUri( u.uri, u.supportedCrs, u.supportedFormats );
if ( u.layerType == "vector" )
{
addVectorLayer( uri, u.name, u.providerKey );
}
else if ( u.layerType == "raster" )
{
addRasterLayer( uri, u.name, u.providerKey );
}
else if ( u.layerType == "plugin" )
{
addPluginLayer( uri, u.name, u.providerKey );
}
}
}
mMapCanvas->freeze( false );
mMapCanvas->refresh();
event->acceptProposedAction();
}
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;
}
#ifdef HAVE_TOUCH
else if ( event->type() == QEvent::Gesture )
{
done = gestureEvent( static_cast<QGestureEvent*>( event ) );
}
#endif
else
{
// pass other events to base class
done = QMainWindow::event( event );
}
return done;
}
QgisAppStyleSheet* QgisApp::styleSheetBuilder()
{
Q_ASSERT( mStyleSheetBuilder );
return mStyleSheetBuilder;
}
// restore any application settings stored in QSettings
void QgisApp::readSettings()
{
QSettings settings;
QString themename = settings.value( "UI/UITheme", "default" ).toString();
setTheme( themename );
// Read legacy settings
mRecentProjects.clear();
settings.beginGroup( "/UI" );
// Migrate old recent projects if first time with new system
if ( !settings.childGroups().contains( "recentProjects" ) )
{
QStringList oldRecentProjects = settings.value( "/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( "/UI/recentProjects" );
QStringList projectKeys = settings.childGroups();
Q_FOREACH ( const QString& key, projectKeys )
{
QgsWelcomePageItemsModel::RecentProjectData data;
settings.beginGroup( key );
data.title = settings.value( "title" ).toString();
data.path = settings.value( "path" ).toString();
data.previewImagePath = settings.value( "previewImage" ).toString();
settings.endGroup();
mRecentProjects.append( data );
}
settings.endGroup();
// this is a new session! reset enable macros value to "ask"
// whether set to "just for this session"
if ( settings.value( "/qgis/enableMacros", 1 ).toInt() == 2 )
{
settings.setValue( "/qgis/enableMacros", 1 );
}
}
//////////////////////////////////////////////////////////////////////
// Set Up the gui toolbars, menus, statusbar etc
//////////////////////////////////////////////////////////////////////
void QgisApp::createActions()
{
mActionPluginSeparator1 = NULL; // plugin list separator will be created when the first plugin is loaded
mActionPluginSeparator2 = NULL; // python separator will be created only if python is found
mActionRasterSeparator = NULL; // raster plugins list separator will be created when the first plugin is loaded
// Project Menu Items
connect( mActionNewProject, SIGNAL( triggered() ), this, SLOT( fileNew() ) );
connect( mActionNewBlankProject, SIGNAL( triggered() ), this, SLOT( fileNewBlank() ) );
connect( mActionOpenProject, SIGNAL( triggered() ), this, SLOT( fileOpen() ) );
connect( mActionSaveProject, SIGNAL( triggered() ), this, SLOT( fileSave() ) );
connect( mActionSaveProjectAs, SIGNAL( triggered() ), this, SLOT( fileSaveAs() ) );
connect( mActionSaveMapAsImage, SIGNAL( triggered() ), this, SLOT( saveMapAsImage() ) );
connect( mActionNewPrintComposer, SIGNAL( triggered() ), this, SLOT( newPrintComposer() ) );
connect( mActionShowComposerManager, SIGNAL( triggered() ), this, SLOT( showComposerManager() ) );
connect( mActionExit, SIGNAL( triggered() ), this, SLOT( fileExit() ) );
connect( mActionDxfExport, SIGNAL( triggered() ), this, SLOT( dxfExport() ) );
// Edit Menu Items
connect( mActionUndo, SIGNAL( triggered() ), mUndoWidget, SLOT( undo() ) );
connect( mActionRedo, SIGNAL( triggered() ), mUndoWidget, SLOT( redo() ) );
connect( mActionCutFeatures, SIGNAL( triggered() ), this, SLOT( editCut() ) );
connect( mActionCopyFeatures, SIGNAL( triggered() ), this, SLOT( editCopy() ) );
connect( mActionPasteFeatures, SIGNAL( triggered() ), this, SLOT( editPaste() ) );
connect( mActionPasteAsNewVector, SIGNAL( triggered() ), this, SLOT( pasteAsNewVector() ) );
connect( mActionPasteAsNewMemoryVector, SIGNAL( triggered() ), this, SLOT( pasteAsNewMemoryVector() ) );
connect( mActionCopyStyle, SIGNAL( triggered() ), this, SLOT( copyStyle() ) );
connect( mActionPasteStyle, SIGNAL( triggered() ), this, SLOT( pasteStyle() ) );
connect( mActionAddFeature, SIGNAL( triggered() ), this, SLOT( addFeature() ) );
connect( mActionCircularStringCurvePoint, SIGNAL( triggered() ), this, SLOT( circularStringCurvePoint() ) );
connect( mActionCircularStringRadius, SIGNAL( triggered() ), this, SLOT( circularStringRadius() ) );
connect( mActionMoveFeature, SIGNAL( triggered() ), this, SLOT( moveFeature() ) );
connect( mActionRotateFeature, SIGNAL( triggered() ), this, SLOT( rotateFeature() ) );
connect( mActionReshapeFeatures, SIGNAL( triggered() ), this, SLOT( reshapeFeatures() ) );
connect( mActionSplitFeatures, SIGNAL( triggered() ), this, SLOT( splitFeatures() ) );
connect( mActionSplitParts, SIGNAL( triggered() ), this, SLOT( splitParts() ) );
connect( mActionDeleteSelected, SIGNAL( triggered() ), this, SLOT( deleteSelected() ) );
connect( mActionAddRing, SIGNAL( triggered() ), this, SLOT( addRing() ) );
connect( mActionFillRing, SIGNAL( triggered() ), this, SLOT( fillRing() ) );
connect( mActionAddPart, SIGNAL( triggered() ), this, SLOT( addPart() ) );
connect( mActionSimplifyFeature, SIGNAL( triggered() ), this, SLOT( simplifyFeature() ) );
connect( mActionDeleteRing, SIGNAL( triggered() ), this, SLOT( deleteRing() ) );
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
connect( mActionMergeFeatures, SIGNAL( triggered() ), this, SLOT( mergeSelectedFeatures() ) );
connect( mActionMergeFeatureAttributes, SIGNAL( triggered() ), this, SLOT( mergeAttributesOfSelectedFeatures() ) );
connect( mActionNodeTool, SIGNAL( triggered() ), this, SLOT( nodeTool() ) );
connect( mActionRotatePointSymbols, SIGNAL( triggered() ), this, SLOT( rotatePointSymbols() ) );
connect( mActionSnappingOptions, SIGNAL( triggered() ), this, SLOT( snappingOptions() ) );
connect( mActionOffsetCurve, SIGNAL( triggered() ), this, SLOT( offsetCurve() ) );
// View Menu Items
#ifdef HAVE_TOUCH
connect( mActionTouch, SIGNAL( triggered() ), this, SLOT( touch() ) );
#endif
connect( mActionPan, SIGNAL( triggered() ), this, SLOT( pan() ) );
connect( mActionPanToSelected, SIGNAL( triggered() ), this, SLOT( panToSelected() ) );
connect( mActionZoomIn, SIGNAL( triggered() ), this, SLOT( zoomIn() ) );
connect( mActionZoomOut, SIGNAL( triggered() ), this, SLOT( zoomOut() ) );
connect( mActionSelectFeatures, SIGNAL( triggered() ), this, SLOT( selectFeatures() ) );
connect( mActionSelectPolygon, SIGNAL( triggered() ), this, SLOT( selectByPolygon() ) );
connect( mActionSelectFreehand, SIGNAL( triggered() ), this, SLOT( selectByFreehand() ) );
connect( mActionSelectRadius, SIGNAL( triggered() ), this, SLOT( selectByRadius() ) );
connect( mActionDeselectAll, SIGNAL( triggered() ), this, SLOT( deselectAll() ) );
connect( mActionSelectByExpression, SIGNAL( triggered() ), this, SLOT( selectByExpression() ) );
connect( mActionIdentify, SIGNAL( triggered() ), this, SLOT( identify() ) );
connect( mActionFeatureAction, SIGNAL( triggered() ), this, SLOT( doFeatureAction() ) );
connect( mActionMeasure, SIGNAL( triggered() ), this, SLOT( measure() ) );
connect( mActionMeasureArea, SIGNAL( triggered() ), this, SLOT( measureArea() ) );
connect( mActionMeasureAngle, SIGNAL( triggered() ), this, SLOT( measureAngle() ) );
connect( mActionZoomFullExtent, SIGNAL( triggered() ), this, SLOT( zoomFull() ) );
connect( mActionZoomToLayer, SIGNAL( triggered() ), this, SLOT( zoomToLayerExtent() ) );
connect( mActionZoomToSelected, SIGNAL( triggered() ), this, SLOT( zoomToSelected() ) );
connect( mActionZoomLast, SIGNAL( triggered() ), this, SLOT( zoomToPrevious() ) );
connect( mActionZoomNext, SIGNAL( triggered() ), this, SLOT( zoomToNext() ) );
connect( mActionZoomActualSize, SIGNAL( triggered() ), this, SLOT( zoomActualSize() ) );
connect( mActionMapTips, SIGNAL( triggered() ), this, SLOT( toggleMapTips() ) );
connect( mActionNewBookmark, SIGNAL( triggered() ), this, SLOT( newBookmark() ) );
connect( mActionShowBookmarks, SIGNAL( triggered() ), this, SLOT( showBookmarks() ) );
connect( mActionDraw, SIGNAL( triggered() ), this, SLOT( refreshMapCanvas() ) );
connect( mActionTextAnnotation, SIGNAL( triggered() ), this, SLOT( addTextAnnotation() ) );
connect( mActionFormAnnotation, SIGNAL( triggered() ), this, SLOT( addFormAnnotation() ) );
connect( mActionHtmlAnnotation, SIGNAL( triggered() ), this, SLOT( addHtmlAnnotation() ) );
connect( mActionSvgAnnotation, SIGNAL( triggered() ), this, SLOT( addSvgAnnotation() ) );
connect( mActionAnnotation, SIGNAL( triggered() ), this, SLOT( modifyAnnotation() ) );
connect( mActionLabeling, SIGNAL( triggered() ), this, SLOT( labeling() ) );
connect( mActionStatisticalSummary, SIGNAL( triggered( ) ), this, SLOT( showStatisticsDockWidget() ) );
// Layer Menu Items
connect( mActionNewVectorLayer, SIGNAL( triggered() ), this, SLOT( newVectorLayer() ) );
connect( mActionNewSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( newSpatialiteLayer() ) );
connect( mActionNewMemoryLayer, SIGNAL( triggered() ), this, SLOT( newMemoryLayer() ) );
connect( mActionShowRasterCalculator, SIGNAL( triggered() ), this, SLOT( showRasterCalculator() ) );
connect( mActionShowAlignRasterTool, SIGNAL( triggered() ), this, SLOT( showAlignRasterTool() ) );
connect( mActionEmbedLayers, SIGNAL( triggered() ), this, SLOT( embedLayers() ) );
connect( mActionAddLayerDefinition, SIGNAL( triggered() ), this, SLOT( addLayerDefinition() ) );
connect( mActionAddOgrLayer, SIGNAL( triggered() ), this, SLOT( addVectorLayer() ) );
connect( mActionAddRasterLayer, SIGNAL( triggered() ), this, SLOT( addRasterLayer() ) );
connect( mActionAddPgLayer, SIGNAL( triggered() ), this, SLOT( addDatabaseLayer() ) );
connect( mActionAddSpatiaLiteLayer, SIGNAL( triggered() ), this, SLOT( addSpatiaLiteLayer() ) );
connect( mActionAddMssqlLayer, SIGNAL( triggered() ), this, SLOT( addMssqlLayer() ) );
connect( mActionAddOracleLayer, SIGNAL( triggered() ), this, SLOT( addOracleLayer() ) );
connect( mActionAddWmsLayer, SIGNAL( triggered() ), this, SLOT( addWmsLayer() ) );
connect( mActionAddWcsLayer, SIGNAL( triggered() ), this, SLOT( addWcsLayer() ) );
connect( mActionAddWfsLayer, SIGNAL( triggered() ), this, SLOT( addWfsLayer() ) );
connect( mActionAddDelimitedText, SIGNAL( triggered() ), this, SLOT( addDelimitedTextLayer() ) );
connect( mActionOpenTable, SIGNAL( triggered() ), this, SLOT( attributeTable() ) );
connect( mActionOpenFieldCalc, SIGNAL( triggered() ), this, SLOT( fieldCalculator() ) );
connect( mActionToggleEditing, SIGNAL( triggered() ), this, SLOT( toggleEditing() ) );
connect( mActionSaveLayerEdits, SIGNAL( triggered() ), this, SLOT( saveActiveLayerEdits() ) );
connect( mActionSaveEdits, SIGNAL( triggered() ), this, SLOT( saveEdits() ) );
connect( mActionSaveAllEdits, SIGNAL( triggered() ), this, SLOT( saveAllEdits() ) );
connect( mActionRollbackEdits, SIGNAL( triggered() ), this, SLOT( rollbackEdits() ) );
connect( mActionRollbackAllEdits, SIGNAL( triggered() ), this, SLOT( rollbackAllEdits() ) );
connect( mActionCancelEdits, SIGNAL( triggered() ), this, SLOT( cancelEdits() ) );
connect( mActionCancelAllEdits, SIGNAL( triggered() ), this, SLOT( cancelAllEdits() ) );
connect( mActionLayerSaveAs, SIGNAL( triggered() ), this, SLOT( saveAsFile() ) );
connect( mActionSaveLayerDefinition, SIGNAL( triggered() ), this, SLOT( saveAsLayerDefinition() ) );
connect( mActionRemoveLayer, SIGNAL( triggered() ), this, SLOT( removeLayer() ) );
connect( mActionDuplicateLayer, SIGNAL( triggered() ), this, SLOT( duplicateLayers() ) );
connect( mActionSetLayerScaleVisibility, SIGNAL( triggered() ), this, SLOT( setLayerScaleVisibility() ) );
connect( mActionSetLayerCRS, SIGNAL( triggered() ), this, SLOT( setLayerCRS() ) );
connect( mActionSetProjectCRSFromLayer, SIGNAL( triggered() ), this, SLOT( setProjectCRSFromLayer() ) );
connect( mActionLayerProperties, SIGNAL( triggered() ), this, SLOT( layerProperties() ) );
connect( mActionLayerSubsetString, SIGNAL( triggered() ), this, SLOT( layerSubsetString() ) );
connect( mActionAddToOverview, SIGNAL( triggered() ), this, SLOT( isInOverview() ) );
connect( mActionAddAllToOverview, SIGNAL( triggered() ), this, SLOT( addAllToOverview() ) );
connect( mActionRemoveAllFromOverview, SIGNAL( triggered() ), this, SLOT( removeAllFromOverview() ) );
connect( mActionShowAllLayers, SIGNAL( triggered() ), this, SLOT( showAllLayers() ) );
connect( mActionHideAllLayers, SIGNAL( triggered() ), this, SLOT( hideAllLayers() ) );
connect( mActionShowSelectedLayers, SIGNAL( triggered() ), this, SLOT( showSelectedLayers() ) );
connect( mActionHideSelectedLayers, SIGNAL( triggered() ), this, SLOT( hideSelectedLayers() ) );
// Plugin Menu Items
connect( mActionManagePlugins, SIGNAL( triggered() ), this, SLOT( showPluginManager() ) );
connect( mActionShowPythonDialog, SIGNAL( triggered() ), this, SLOT( showPythonDialog() ) );
// Settings Menu Items
connect( mActionToggleFullScreen, SIGNAL( triggered() ), this, SLOT( toggleFullScreen() ) );
connect( mActionProjectProperties, SIGNAL( triggered() ), this, SLOT( projectProperties() ) );
connect( mActionOptions, SIGNAL( triggered() ), this, SLOT( options() ) );
connect( mActionCustomProjection, SIGNAL( triggered() ), this, SLOT( customProjection() ) );
connect( mActionConfigureShortcuts, SIGNAL( triggered() ), this, SLOT( configureShortcuts() ) );
connect( mActionStyleManagerV2, SIGNAL( triggered() ), this, SLOT( showStyleManagerV2() ) );
connect( mActionCustomization, SIGNAL( triggered() ), this, SLOT( 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, SIGNAL( triggered() ), this, SLOT( localHistogramStretch() ) );
connect( mActionFullHistogramStretch, SIGNAL( triggered() ), this, SLOT( fullHistogramStretch() ) );
connect( mActionLocalCumulativeCutStretch, SIGNAL( triggered() ), this, SLOT( localCumulativeCutStretch() ) );
connect( mActionFullCumulativeCutStretch, SIGNAL( triggered() ), this, SLOT( fullCumulativeCutStretch() ) );
connect( mActionIncreaseBrightness, SIGNAL( triggered() ), this, SLOT( increaseBrightness() ) );
connect( mActionDecreaseBrightness, SIGNAL( triggered() ), this, SLOT( decreaseBrightness() ) );
connect( mActionIncreaseContrast, SIGNAL( triggered() ), this, SLOT( increaseContrast() ) );
connect( mActionDecreaseContrast, SIGNAL( triggered() ), this, SLOT( decreaseContrast() ) );
// Vector Menu Items
connect( mActionOSMDownload, SIGNAL( triggered() ), this, SLOT( osmDownloadDialog() ) );
connect( mActionOSMImport, SIGNAL( triggered() ), this, SLOT( osmImportDialog() ) );
connect( mActionOSMExport, SIGNAL( triggered() ), this, SLOT( osmExportDialog() ) );
// Help Menu Items
#ifdef Q_OS_MAC
mActionHelpContents->setShortcut( QString( "Ctrl+?" ) );
mActionQgisHomePage->setShortcut( QString() );
#endif
mActionHelpContents->setEnabled( QFileInfo( QgsApplication::pkgDataPath() + "/doc/index.html" ).exists() );
connect( mActionHelpContents, SIGNAL( triggered() ), this, SLOT( helpContents() ) );
connect( mActionHelpAPI, SIGNAL( triggered() ), this, SLOT( apiDocumentation() ) );
connect( mActionNeedSupport, SIGNAL( triggered() ), this, SLOT( supportProviders() ) );
connect( mActionQgisHomePage, SIGNAL( triggered() ), this, SLOT( helpQgisHomePage() ) );
connect( mActionCheckQgisVersion, SIGNAL( triggered() ), this, SLOT( checkQgisVersion() ) );
connect( mActionAbout, SIGNAL( triggered() ), this, SLOT( about() ) );
connect( mActionSponsors, SIGNAL( triggered() ), this, SLOT( sponsors() ) );
connect( mActionShowPinnedLabels, SIGNAL( toggled( bool ) ), this, SLOT( showPinnedLabels( bool ) ) );
connect( mActionPinLabels, SIGNAL( triggered() ), this, SLOT( pinLabels() ) );
connect( mActionShowHideLabels, SIGNAL( triggered() ), this, SLOT( showHideLabels() ) );
connect( mActionMoveLabel, SIGNAL( triggered() ), this, SLOT( moveLabel() ) );
connect( mActionRotateLabel, SIGNAL( triggered() ), this, SLOT( rotateLabel() ) );
connect( mActionChangeLabelProperties, SIGNAL( triggered() ), this, SLOT( changeLabelProperties() ) );
#ifndef HAVE_POSTGRESQL
delete mActionAddPgLayer;
mActionAddPgLayer = 0;
#endif
#ifndef HAVE_MSSQL
delete mActionAddMssqlLayer;
mActionAddMssqlLayer = 0;
#endif
#ifndef HAVE_ORACLE
delete mActionAddOracleLayer;
mActionAddOracleLayer = 0;
#endif
}
#include "qgsstylev2.h"
#include "qgsstylev2managerdialog.h"
void QgisApp::showStyleManagerV2()
{
QgsStyleV2ManagerDialog dlg( QgsStyleV2::defaultStyle(), this );
dlg.exec();
}
void QgisApp::writeAnnotationItemsToProject( QDomDocument& doc )
{
QList<QgsAnnotationItem*> items = annotationItems();
QList<QgsAnnotationItem*>::const_iterator itemIt = items.constBegin();
for ( ; itemIt != items.constEnd(); ++itemIt )
{
if ( ! *itemIt )
{
continue;
}
( *itemIt )->writeXML( doc );
}
}
void QgisApp::showPythonDialog()
{
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
}
void QgisApp::createActionGroups()
{
//
// Map Tool Group
mMapToolGroup = new QActionGroup( this );
#ifdef HAVE_TOUCH
mMapToolGroup->addAction( mActionTouch );
#endif
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( mActionMeasure );
mMapToolGroup->addAction( mActionMeasureArea );
mMapToolGroup->addAction( mActionMeasureAngle );
mMapToolGroup->addAction( mActionAddFeature );
mMapToolGroup->addAction( mActionCircularStringCurvePoint );
mMapToolGroup->addAction( mActionCircularStringRadius );
mMapToolGroup->addAction( mActionMoveFeature );
mMapToolGroup->addAction( mActionRotateFeature );
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
mMapToolGroup->addAction( mActionOffsetCurve );
#endif
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( 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
foreach ( QgsComposer *c, mPrintComposers )
{
c->setStyleSheet( stylesheet );
}
}
int QgisApp::messageTimeout()
{
QSettings settings;
return settings.value( "/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.
*/
// Panel and Toolbar Submenus
mPanelMenu = new QMenu( tr( "Panels" ), this );
mPanelMenu->setObjectName( "mPanelMenu" );
mToolbarMenu = new QMenu( tr( "Toolbars" ), this );
mToolbarMenu->setObjectName( "mToolbarMenu" );
// Get platform for menu layout customization (Gnome, Kde, Mac, Win)
QDialogButtonBox::ButtonLayout layout =
QDialogButtonBox::ButtonLayout( style()->styleHint( QStyle::SH_DialogButtonLayout, 0, this ) );
// Project Menu
// Connect once for the entire submenu.
connect( mRecentProjectsMenu, SIGNAL( triggered( QAction * ) ),
this, SLOT( openProject( QAction * ) ) );
connect( mProjectFromTemplateMenu, SIGNAL( triggered( QAction * ) ),
this, SLOT( fileNewFromTemplateAction( QAction * ) ) );
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 );
}
else
{
// on the top of the settings menu
QAction* before = mActionProjectProperties;
mSettingsMenu->insertMenu( before, mPanelMenu );
mSettingsMenu->insertMenu( before, mToolbarMenu );
mSettingsMenu->insertAction( before, mActionToggleFullScreen );
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 );
mProjectMenu->addAction( mActionOptions );
// 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( "mDatabaseMenu" );
// Web Menu
// don't add it yet, wait for a plugin
mWebMenu = new QMenu( tr( "&Web" ), menuBar() );
mWebMenu->setObjectName( "mWebMenu" );
// Help menu
// add What's this button to it
QAction* before = mActionHelpAPI;
QAction* actionWhatsThis = QWhatsThis::createAction( this );
actionWhatsThis->setIcon( QgsApplication::getThemeIcon( "/mActionWhatsThis.svg" ) );
mHelpMenu->insertAction( before, actionWhatsThis );
}
void QgisApp::createToolBars()
{
QSettings 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;
QList<QAction*> toolbarMenuActions;
// Set action names so that they can be used in customization
foreach ( QToolBar *toolBar, toolbarMenuToolBars )
{
toolBar->toggleViewAction()->setObjectName( "mActionToggle" + toolBar->objectName().mid( 1 ) );
toolbarMenuActions << toolBar->toggleViewAction();
}
// sort actions in toolbar menu
qSort( toolbarMenuActions.begin(), toolbarMenuActions.end(), cmpByText_ );
mToolbarMenu->addActions( toolbarMenuActions );
// select tool button
QToolButton *bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
QList<QAction*> selectActions;
selectActions << mActionSelectFeatures << mActionSelectPolygon
<< mActionSelectFreehand << mActionSelectRadius;
bt->addActions( selectActions );
QAction* defSelectAction = mActionSelectFeatures;
switch ( settings.value( "/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( mActionDeselectAll, bt );
selectAction->setObjectName( "ActionSelect" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// feature action tool button
bt = new QToolButton( mAttributesToolBar );
bt->setPopupMode( QToolButton::MenuButtonPopup );
bt->setDefaultAction( mActionFeatureAction );
mFeatureActionMenu = new QMenu( bt );
connect( mFeatureActionMenu, SIGNAL( triggered( QAction * ) ), this, SLOT( updateDefaultFeatureAction( QAction * ) ) );
connect( mFeatureActionMenu, SIGNAL( aboutToShow() ), this, SLOT( refreshFeatureActions() ) );
bt->setMenu( mFeatureActionMenu );
QAction* featureActionAction = mAttributesToolBar->insertWidget( selectAction, bt );
featureActionAction->setObjectName( "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( "/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( "ActionMeasure" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// 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( "/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( "ActionAnnotation" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
// 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( mActionNewSpatiaLiteLayer );
bt->addAction( mActionNewVectorLayer );
bt->addAction( mActionNewMemoryLayer );
QAction* defNewLayerAction = mActionNewVectorLayer;
switch ( settings.value( "/UI/defaultNewLayer", 1 ).toInt() )
{
case 0: defNewLayerAction = mActionNewSpatiaLiteLayer; break;
case 1: defNewLayerAction = mActionNewVectorLayer; break;
case 2: defNewLayerAction = mActionNewMemoryLayer; break;
}
bt->setDefaultAction( defNewLayerAction );
QAction* newLayerAction = mLayerToolBar->addWidget( bt );
newLayerAction->setObjectName( "ActionNewLayer" );
connect( bt, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
//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, SIGNAL( triggered( QAction * ) ), this, SLOT( toolButtonActionTriggered( QAction * ) ) );
mDigitizeToolBar->insertWidget( mActionMoveFeature, tbAddCircularString );
// Help Toolbar
QAction* actionWhatsThis = QWhatsThis::createAction( this );
actionWhatsThis->setIcon( QgsApplication::getThemeIcon( "/mActionWhatsThis.svg" ) );
mHelpToolBar->addAction( actionWhatsThis );
// Cad toolbar
mAdvancedDigitizeToolBar->insertAction( mActionUndo, mAdvancedDigitizingDockWidget->enableAction() );
}
void QgisApp::createStatusBar()
{
//remove borders from children under Windows
statusBar()->setStyleSheet( "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( "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, SIGNAL( renderStarting() ), this, SLOT( canvasRefreshStarted() ) );
connect( mMapCanvas, SIGNAL( mapCanvasRefreshed() ), this, SLOT( canvasRefreshFinished() ) );
// 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( "Arial", 9 );
statusBar()->setFont( myFont );
//toggle to switch between mouse pos and extents display in status bar widget
mToggleExtentsViewButton = new QToolButton( statusBar() );
mToggleExtentsViewButton->setObjectName( "mToggleExtentsViewButton" );
mToggleExtentsViewButton->setMaximumWidth( 20 );
//mToggleExtentsViewButton->setMaximumHeight( 20 );
mToggleExtentsViewButton->setIcon( QgsApplication::getThemeIcon( "tracking.png" ) );
mToggleExtentsViewButton->setToolTip( tr( "Toggle extents and mouse position display" ) );
mToggleExtentsViewButton->setCheckable( true );
connect( mToggleExtentsViewButton, SIGNAL( toggled( bool ) ), this, SLOT( extentsViewToggled( bool ) ) );
statusBar()->addPermanentWidget( mToggleExtentsViewButton, 0 );
// add a label to show current position
mCoordsLabel = new QLabel( QString(), statusBar() );
mCoordsLabel->setObjectName( "mCoordsLabel" );
mCoordsLabel->setFont( myFont );
mCoordsLabel->setMinimumWidth( 10 );
//mCoordsLabel->setMaximumHeight( 20 );
mCoordsLabel->setMargin( 3 );
mCoordsLabel->setAlignment( Qt::AlignCenter );
mCoordsLabel->setFrameStyle( QFrame::NoFrame );
mCoordsLabel->setText( tr( "Coordinate:" ) );
mCoordsLabel->setToolTip( tr( "Current map coordinate" ) );
statusBar()->addPermanentWidget( mCoordsLabel, 0 );
//coords status bar widget
mCoordsEdit = new QLineEdit( QString(), statusBar() );
mCoordsEdit->setObjectName( "mCoordsEdit" );
mCoordsEdit->setFont( myFont );
mCoordsEdit->setMinimumWidth( 10 );
mCoordsEdit->setMaximumWidth( 300 );
//mCoordsEdit->setMaximumHeight( 20 );
mCoordsEdit->setContentsMargins( 0, 0, 0, 0 );
mCoordsEdit->setAlignment( Qt::AlignCenter );
QRegExp coordValidator( "[+-]?\\d+\\.?\\d*\\s*,\\s*[+-]?\\d+\\.?\\d*" );
mCoordsEditValidator = new QRegExpValidator( coordValidator, mCoordsEdit );
mCoordsEdit->setWhatsThis( tr( "Shows the map coordinates at the "
"current cursor position. The display is continuously updated "
"as the mouse is moved. It also allows editing to set the canvas "
"center to a given position. The format is lat,lon or east,north" ) );
mCoordsEdit->setToolTip( tr( "Current map coordinate (lat,lon or east,north)" ) );
statusBar()->addPermanentWidget( mCoordsEdit, 0 );
connect( mCoordsEdit, SIGNAL( returnPressed() ), this, SLOT( userCenter() ) );
mDizzyTimer = new QTimer( this );
connect( mDizzyTimer, SIGNAL( timeout() ), this, SLOT( dizzy() ) );
// add a label to show current scale
mScaleLabel = new QLabel( QString(), statusBar() );
mScaleLabel->setObjectName( "mScaleLable" );
mScaleLabel->setFont( myFont );
mScaleLabel->setMinimumWidth( 10 );
//mScaleLabel->setMaximumHeight( 20 );
mScaleLabel->setMargin( 3 );
mScaleLabel->setAlignment( Qt::AlignCenter );
mScaleLabel->setFrameStyle( QFrame::NoFrame );
mScaleLabel->setText( tr( "Scale " ) );
mScaleLabel->setToolTip( tr( "Current map scale" ) );
statusBar()->addPermanentWidget( mScaleLabel, 0 );
mScaleEdit = new QgsScaleComboBox( statusBar() );
mScaleEdit->setObjectName( "mScaleEdit" );
mScaleEdit->setFont( myFont );
// seems setFont() change font only for popup not for line edit,
// so we need to set font for it separately
mScaleEdit->lineEdit()->setFont( myFont );
mScaleEdit->setMinimumWidth( 10 );
mScaleEdit->setContentsMargins( 0, 0, 0, 0 );
mScaleEdit->setWhatsThis( tr( "Displays the current map scale" ) );
mScaleEdit->setToolTip( tr( "Current map scale (formatted as x:y)" ) );
statusBar()->addPermanentWidget( mScaleEdit, 0 );
connect( mScaleEdit, SIGNAL( scaleChanged() ), this, SLOT( userScale() ) );
if ( QgsMapCanvas::rotationEnabled() )
{
// add a widget to show/set current rotation
mRotationLabel = new QLabel( QString(), statusBar() );
mRotationLabel->setObjectName( "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( "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->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, SIGNAL( valueChanged( double ) ), this, SLOT( userRotation() ) );
showRotation();
}
// render suppression status bar widget
mRenderSuppressionCBox = new QCheckBox( tr( "Render" ), statusBar() );
mRenderSuppressionCBox->setObjectName( "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( "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( mScaleLabel->height() );
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( "mIconProjectionEnabled.png" ) );
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 behaviour." ) );
mOnTheFlyProjectionStatusButton->setToolTip( tr( "CRS status - Click "
"to open coordinate reference system dialog" ) );
connect( mOnTheFlyProjectionStatusButton, SIGNAL( clicked() ),
this, SLOT( 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( "bubble.svg" ) );
mMessageButton->setToolTip( tr( "Messages" ) );
mMessageButton->setWhatsThis( tr( "Messages" ) );
mMessageButton->setToolButtonStyle( Qt::ToolButtonTextBesideIcon );
mMessageButton->setObjectName( "mMessageLogViewerButton" );
mMessageButton->setMaximumHeight( mScaleLabel->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 *>();
foreach ( QToolBar * toolbar, toolbars )
{
QString className = toolbar->parent()->metaObject()->className();
if ( className == "QgisApp" )
{
toolbar->setIconSize( QSize( size, size ) );
}
else
{
toolbar->setIconSize( QSize( dockSize, dockSize ) );
}
}
foreach ( QgsComposer *c, mPrintComposers )
{
c->setIconSizes( size );
}
}
void QgisApp::setTheme( QString theThemeName )
{
/*****************************************************************
// 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( theThemeName );
//QgsDebugMsg("Setting theme to \n" + theThemeName);
mActionNewProject->setIcon( QgsApplication::getThemeIcon( "/mActionFileNew.svg" ) );
mActionOpenProject->setIcon( QgsApplication::getThemeIcon( "/mActionFileOpen.svg" ) );
mActionSaveProject->setIcon( QgsApplication::getThemeIcon( "/mActionFileSave.svg" ) );
mActionSaveProjectAs->setIcon( QgsApplication::getThemeIcon( "/mActionFileSaveAs.svg" ) );
mActionNewPrintComposer->setIcon( QgsApplication::getThemeIcon( "/mActionNewComposer.svg" ) );
mActionShowComposerManager->setIcon( QgsApplication::getThemeIcon( "/mActionComposerManager.svg" ) );
mActionSaveMapAsImage->setIcon( QgsApplication::getThemeIcon( "/mActionSaveMapAsImage.png" ) );
mActionExit->setIcon( QgsApplication::getThemeIcon( "/mActionFileExit.png" ) );
mActionAddOgrLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddOgrLayer.svg" ) );
mActionAddRasterLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddRasterLayer.svg" ) );
#ifdef HAVE_POSTGRESQL
mActionAddPgLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddPostgisLayer.svg" ) );
#endif
mActionNewSpatiaLiteLayer->setIcon( QgsApplication::getThemeIcon( "/mActionNewSpatiaLiteLayer.svg" ) );
mActionAddSpatiaLiteLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddSpatiaLiteLayer.svg" ) );
#ifdef HAVE_MSSQL
mActionAddMssqlLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddMssqlLayer.svg" ) );
#endif
#ifdef HAVE_ORACLE
mActionAddOracleLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddOracleLayer.svg" ) );
#endif
mActionRemoveLayer->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveLayer.svg" ) );
mActionDuplicateLayer->setIcon( QgsApplication::getThemeIcon( "/mActionDuplicateLayer.svg" ) );
mActionSetLayerCRS->setIcon( QgsApplication::getThemeIcon( "/mActionSetLayerCRS.png" ) );
mActionSetProjectCRSFromLayer->setIcon( QgsApplication::getThemeIcon( "/mActionSetProjectCRSFromLayer.png" ) );
mActionNewVectorLayer->setIcon( QgsApplication::getThemeIcon( "/mActionNewVectorLayer.svg" ) );
mActionNewMemoryLayer->setIcon( QgsApplication::getThemeIcon( "/mActionCreateMemory.png" ) );
mActionAddAllToOverview->setIcon( QgsApplication::getThemeIcon( "/mActionAddAllToOverview.svg" ) );
mActionHideAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionHideAllLayers.png" ) );
mActionShowAllLayers->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.png" ) );
mActionHideSelectedLayers->setIcon( QgsApplication::getThemeIcon( "/mActionHideSelectedLayers.png" ) );
mActionShowSelectedLayers->setIcon( QgsApplication::getThemeIcon( "/mActionShowSelectedLayers.png" ) );
mActionRemoveAllFromOverview->setIcon( QgsApplication::getThemeIcon( "/mActionRemoveAllFromOverview.svg" ) );
mActionToggleFullScreen->setIcon( QgsApplication::getThemeIcon( "/mActionToggleFullScreen.png" ) );
mActionProjectProperties->setIcon( QgsApplication::getThemeIcon( "/mActionProjectProperties.png" ) );
mActionManagePlugins->setIcon( QgsApplication::getThemeIcon( "/mActionShowPluginManager.svg" ) );
mActionShowPythonDialog->setIcon( QgsApplication::getThemeIcon( "console/iconRunConsole.png" ) );
mActionCheckQgisVersion->setIcon( QgsApplication::getThemeIcon( "/mActionCheckQgisVersion.png" ) );
mActionOptions->setIcon( QgsApplication::getThemeIcon( "/mActionOptions.svg" ) );
mActionConfigureShortcuts->setIcon( QgsApplication::getThemeIcon( "/mActionOptions.svg" ) );
mActionCustomization->setIcon( QgsApplication::getThemeIcon( "/mActionOptions.svg" ) );
mActionHelpContents->setIcon( QgsApplication::getThemeIcon( "/mActionHelpContents.svg" ) );
mActionLocalHistogramStretch->setIcon( QgsApplication::getThemeIcon( "/mActionLocalHistogramStretch.png" ) );
mActionFullHistogramStretch->setIcon( QgsApplication::getThemeIcon( "/mActionFullHistogramStretch.png" ) );
mActionIncreaseBrightness->setIcon( QgsApplication::getThemeIcon( "/mActionIncreaseBrightness.svg" ) );
mActionDecreaseBrightness->setIcon( QgsApplication::getThemeIcon( "/mActionDecreaseBrightness.svg" ) );
mActionIncreaseContrast->setIcon( QgsApplication::getThemeIcon( "/mActionIncreaseContrast.svg" ) );
mActionDecreaseContrast->setIcon( QgsApplication::getThemeIcon( "/mActionDecreaseContrast.svg" ) );
mActionZoomActualSize->setIcon( QgsApplication::getThemeIcon( "/mActionZoomNative.png" ) );
mActionQgisHomePage->setIcon( QgsApplication::getThemeIcon( "/mActionQgisHomePage.png" ) );
mActionAbout->setIcon( QgsApplication::getThemeIcon( "/mActionHelpAbout.png" ) );
mActionSponsors->setIcon( QgsApplication::getThemeIcon( "/mActionHelpSponsors.png" ) );
mActionDraw->setIcon( QgsApplication::getThemeIcon( "/mActionDraw.svg" ) );
mActionToggleEditing->setIcon( QgsApplication::getThemeIcon( "/mActionToggleEditing.svg" ) );
mActionSaveLayerEdits->setIcon( QgsApplication::getThemeIcon( "/mActionSaveAllEdits.svg" ) );
mActionAllEdits->setIcon( QgsApplication::getThemeIcon( "/mActionAllEdits.svg" ) );
mActionSaveEdits->setIcon( QgsApplication::getThemeIcon( "/mActionSaveEdits.svg" ) );
mActionSaveAllEdits->setIcon( QgsApplication::getThemeIcon( "/mActionSaveAllEdits.svg" ) );
mActionRollbackEdits->setIcon( QgsApplication::getThemeIcon( "/mActionRollbackEdits.svg" ) );
mActionRollbackAllEdits->setIcon( QgsApplication::getThemeIcon( "/mActionRollbackAllEdits.svg" ) );
mActionCancelEdits->setIcon( QgsApplication::getThemeIcon( "/mActionCancelEdits.svg" ) );
mActionCancelAllEdits->setIcon( QgsApplication::getThemeIcon( "/mActionCancelAllEdits.svg" ) );
mActionCutFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditCut.png" ) );
mActionCopyFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditCopy.png" ) );
mActionPasteFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionEditPaste.png" ) );
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionCapturePoint.png" ) );
mActionMoveFeature->setIcon( QgsApplication::getThemeIcon( "/mActionMoveFeature.png" ) );
mActionRotateFeature->setIcon( QgsApplication::getThemeIcon( "/mActionRotateFeature.png" ) );
mActionReshapeFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionReshape.png" ) );
mActionSplitFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionSplitFeatures.svg" ) );
mActionSplitParts->setIcon( QgsApplication::getThemeIcon( "/mActionSplitParts.svg" ) );
mActionDeleteSelected->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteSelected.svg" ) );
mActionNodeTool->setIcon( QgsApplication::getThemeIcon( "/mActionNodeTool.png" ) );
mActionSimplifyFeature->setIcon( QgsApplication::getThemeIcon( "/mActionSimplify.png" ) );
mActionUndo->setIcon( QgsApplication::getThemeIcon( "/mActionUndo.png" ) );
mActionRedo->setIcon( QgsApplication::getThemeIcon( "/mActionRedo.png" ) );
mActionAddRing->setIcon( QgsApplication::getThemeIcon( "/mActionAddRing.png" ) );
mActionFillRing->setIcon( QgsApplication::getThemeIcon( "/mActionFillRing.svg" ) );
mActionAddPart->setIcon( QgsApplication::getThemeIcon( "/mActionAddPart.png" ) );
mActionDeleteRing->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteRing.png" ) );
mActionDeletePart->setIcon( QgsApplication::getThemeIcon( "/mActionDeletePart.png" ) );
mActionMergeFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionMergeFeatures.png" ) );
mActionOffsetCurve->setIcon( QgsApplication::getThemeIcon( "/mActionOffsetCurve.png" ) );
mActionMergeFeatureAttributes->setIcon( QgsApplication::getThemeIcon( "/mActionMergeFeatureAttributes.png" ) );
mActionRotatePointSymbols->setIcon( QgsApplication::getThemeIcon( "mActionRotatePointSymbols.png" ) );
mActionZoomIn->setIcon( QgsApplication::getThemeIcon( "/mActionZoomIn.svg" ) );
mActionZoomOut->setIcon( QgsApplication::getThemeIcon( "/mActionZoomOut.svg" ) );
mActionZoomFullExtent->setIcon( QgsApplication::getThemeIcon( "/mActionZoomFullExtent.svg" ) );
mActionZoomToSelected->setIcon( QgsApplication::getThemeIcon( "/mActionZoomToSelected.svg" ) );
mActionShowRasterCalculator->setIcon( QgsApplication::getThemeIcon( "/mActionShowRasterCalculator.png" ) );
#ifdef HAVE_TOUCH
mActionTouch->setIcon( QgsApplication::getThemeIcon( "/mActionTouch.svg" ) );
#endif
mActionPan->setIcon( QgsApplication::getThemeIcon( "/mActionPan.svg" ) );
mActionPanToSelected->setIcon( QgsApplication::getThemeIcon( "/mActionPanToSelected.svg" ) );
mActionZoomLast->setIcon( QgsApplication::getThemeIcon( "/mActionZoomLast.svg" ) );
mActionZoomNext->setIcon( QgsApplication::getThemeIcon( "/mActionZoomNext.svg" ) );
mActionZoomToLayer->setIcon( QgsApplication::getThemeIcon( "/mActionZoomToLayer.svg" ) );
mActionZoomActualSize->setIcon( QgsApplication::getThemeIcon( "/mActionZoomActual.svg" ) );
mActionIdentify->setIcon( QgsApplication::getThemeIcon( "/mActionIdentify.svg" ) );
mActionFeatureAction->setIcon( QgsApplication::getThemeIcon( "/mAction.svg" ) );
mActionSelectFeatures->setIcon( QgsApplication::getThemeIcon( "/mActionSelectRectangle.svg" ) );
mActionSelectPolygon->setIcon( QgsApplication::getThemeIcon( "/mActionSelectPolygon.svg" ) );
mActionSelectFreehand->setIcon( QgsApplication::getThemeIcon( "/mActionSelectFreehand.svg" ) );
mActionSelectRadius->setIcon( QgsApplication::getThemeIcon( "/mActionSelectRadius.svg" ) );
mActionDeselectAll->setIcon( QgsApplication::getThemeIcon( "/mActionDeselectAll.svg" ) );
mActionSelectByExpression->setIcon( QgsApplication::getThemeIcon( "/mIconExpressionSelect.svg" ) );
mActionOpenTable->setIcon( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ) );
mActionOpenFieldCalc->setIcon( QgsApplication::getThemeIcon( "/mActionCalculateField.png" ) );
mActionMeasure->setIcon( QgsApplication::getThemeIcon( "/mActionMeasure.png" ) );
mActionMeasureArea->setIcon( QgsApplication::getThemeIcon( "/mActionMeasureArea.png" ) );
mActionMeasureAngle->setIcon( QgsApplication::getThemeIcon( "/mActionMeasureAngle.png" ) );
mActionMapTips->setIcon( QgsApplication::getThemeIcon( "/mActionMapTips.png" ) );
mActionShowBookmarks->setIcon( QgsApplication::getThemeIcon( "/mActionShowBookmarks.png" ) );
mActionNewBookmark->setIcon( QgsApplication::getThemeIcon( "/mActionNewBookmark.png" ) );
mActionCustomProjection->setIcon( QgsApplication::getThemeIcon( "/mActionCustomProjection.svg" ) );
mActionAddWmsLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddWmsLayer.svg" ) );
mActionAddWcsLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddWcsLayer.svg" ) );
mActionAddWfsLayer->setIcon( QgsApplication::getThemeIcon( "/mActionAddWfsLayer.svg" ) );
mActionAddToOverview->setIcon( QgsApplication::getThemeIcon( "/mActionInOverview.svg" ) );
mActionAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionAnnotation.png" ) );
mActionFormAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionFormAnnotation.png" ) );
mActionHtmlAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionFormAnnotation.png" ) );
mActionTextAnnotation->setIcon( QgsApplication::getThemeIcon( "/mActionTextAnnotation.png" ) );
mActionLabeling->setIcon( QgsApplication::getThemeIcon( "/mActionLabeling.png" ) );
mActionShowPinnedLabels->setIcon( QgsApplication::getThemeIcon( "/mActionShowPinnedLabels.svg" ) );
mActionPinLabels->setIcon( QgsApplication::getThemeIcon( "/mActionPinLabels.svg" ) );
mActionShowHideLabels->setIcon( QgsApplication::getThemeIcon( "/mActionShowHideLabels.svg" ) );
mActionMoveLabel->setIcon( QgsApplication::getThemeIcon( "/mActionMoveLabel.png" ) );
mActionRotateLabel->setIcon( QgsApplication::getThemeIcon( "/mActionRotateLabel.svg" ) );
mActionChangeLabelProperties->setIcon( QgsApplication::getThemeIcon( "/mActionChangeLabelProperties.png" ) );
mActionDecorationCopyright->setIcon( QgsApplication::getThemeIcon( "/copyright_label.png" ) );
mActionDecorationNorthArrow->setIcon( QgsApplication::getThemeIcon( "/north_arrow.png" ) );
mActionDecorationScaleBar->setIcon( QgsApplication::getThemeIcon( "/scale_bar.png" ) );
mActionDecorationGrid->setIcon( QgsApplication::getThemeIcon( "/transformed.png" ) );
//change themes of all composers
QSet<QgsComposer*>::iterator composerIt = mPrintComposers.begin();
for ( ; composerIt != mPrintComposers.end(); ++composerIt )
{
( *composerIt )->setupTheme();
}
emit currentThemeChanged( theThemeName );
}
void QgisApp::setupConnections()
{
// connect the "cleanup" slot
connect( qApp, SIGNAL( aboutToQuit() ), this, SLOT( saveWindowState() ) );
// signal when mouse moved over window (coords display in status bar)
connect( mMapCanvas, SIGNAL( xyCoordinates( const QgsPoint & ) ),
this, SLOT( showMouseCoordinate( const QgsPoint & ) ) );
connect( mMapCanvas, SIGNAL( extentsChanged() ),
this, SLOT( showExtents() ) );
connect( mMapCanvas, SIGNAL( scaleChanged( double ) ),
this, SLOT( showScale( double ) ) );
connect( mMapCanvas, SIGNAL( rotationChanged( double ) ),
this, SLOT( showRotation() ) );
connect( mMapCanvas, SIGNAL( scaleChanged( double ) ),
this, SLOT( updateMouseCoordinatePrecision() ) );
connect( mMapCanvas, SIGNAL( mapToolSet( QgsMapTool *, QgsMapTool * ) ),
this, SLOT( mapToolChanged( QgsMapTool *, QgsMapTool * ) ) );
connect( mMapCanvas, SIGNAL( selectionChanged( QgsMapLayer * ) ),
this, SLOT( selectionChanged( QgsMapLayer * ) ) );
connect( mMapCanvas, SIGNAL( extentsChanged() ),
this, SLOT( markDirty() ) );
connect( mMapCanvas, SIGNAL( layersChanged() ),
this, SLOT( markDirty() ) );
connect( mMapCanvas, SIGNAL( zoomLastStatusChanged( bool ) ),
mActionZoomLast, SLOT( setEnabled( bool ) ) );
connect( mMapCanvas, SIGNAL( zoomNextStatusChanged( bool ) ),
mActionZoomNext, SLOT( setEnabled( bool ) ) );
connect( mRenderSuppressionCBox, SIGNAL( toggled( bool ) ),
mMapCanvas, SLOT( setRenderFlag( bool ) ) );
// connect MapCanvas keyPress event so we can check if selected feature collection must be deleted
connect( mMapCanvas, SIGNAL( keyPressed( QKeyEvent * ) ),
this, SLOT( mapCanvas_keyPressed( QKeyEvent * ) ) );
// connect renderer
connect( mMapCanvas, SIGNAL( hasCrsTransformEnabledChanged( bool ) ),
this, SLOT( hasCrsTransformEnabled( bool ) ) );
connect( mMapCanvas, SIGNAL( destinationCrsChanged() ),
this, SLOT( destinationCrsChanged() ) );
// connect legend signals
connect( mLayerTreeView, SIGNAL( currentLayerChanged( QgsMapLayer * ) ),
this, SLOT( activateDeactivateLayerRelatedActions( QgsMapLayer * ) ) );
connect( mLayerTreeView->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SLOT( legendLayerSelectionChanged() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ),
this, SLOT( markDirty() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ),
this, SLOT( updateNewLayerInsertionPoint() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ),
this, SLOT( markDirty() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( removedChildren( QgsLayerTreeNode*, int, int ) ),
this, SLOT( updateNewLayerInsertionPoint() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( visibilityChanged( QgsLayerTreeNode*, Qt::CheckState ) ),
this, SLOT( markDirty() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( customPropertyChanged( QgsLayerTreeNode*, QString ) ),
this, SLOT( markDirty() ) );
// connect map layer registry
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer *> ) ),
this, SLOT( layersWereAdded( QList<QgsMapLayer *> ) ) );
connect( QgsMapLayerRegistry::instance(),
SIGNAL( layersWillBeRemoved( QStringList ) ),
this, SLOT( removingLayers( QStringList ) ) );
// connect initialization signal
connect( this, SIGNAL( initializationCompleted() ),
this, SLOT( fileOpenAfterLaunch() ) );
// Connect warning dialog from project reading
connect( QgsProject::instance(), SIGNAL( oldProjectVersionWarning( QString ) ),
this, SLOT( oldProjectVersionWarning( QString ) ) );
connect( QgsProject::instance(), SIGNAL( layerLoaded( int, int ) ),
this, SLOT( showProgress( int, int ) ) );
connect( QgsProject::instance(), SIGNAL( loadingLayer( QString ) ),
this, SLOT( showStatusMessage( QString ) ) );
connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
this, SLOT( readProject( const QDomDocument & ) ) );
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
this, SLOT( writeProject( QDomDocument & ) ) );
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument& ) ),
this, SLOT( writeAnnotationItemsToProject( QDomDocument& ) ) );
connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ), this, SLOT( loadComposersFromProject( const QDomDocument& ) ) );
connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ), this, SLOT( loadAnnotationItemsFromProject( const QDomDocument& ) ) );
connect( this, SIGNAL( projectRead() ),
this, SLOT( fileOpenedOKAfterLaunch() ) );
// connect preview modes actions
connect( mActionPreviewModeOff, SIGNAL( triggered() ), this, SLOT( disablePreviewMode() ) );
connect( mActionPreviewModeGrayscale, SIGNAL( triggered() ), this, SLOT( activateGrayscalePreview() ) );
connect( mActionPreviewModeMono, SIGNAL( triggered() ), this, SLOT( activateMonoPreview() ) );
connect( mActionPreviewProtanope, SIGNAL( triggered() ), this, SLOT( activateProtanopePreview() ) );
connect( mActionPreviewDeuteranope, SIGNAL( triggered() ), this, SLOT( activateDeuteranopePreview() ) );
// handle deprecated labels in project for QGIS 2.0
connect( this, SIGNAL( newProject() ),
this, SLOT( checkForDeprecatedLabelsInProject() ) );
connect( this, SIGNAL( projectRead() ),
this, SLOT( checkForDeprecatedLabelsInProject() ) );
// setup undo/redo actions
connect( mUndoWidget, SIGNAL( undoStackChanged() ), this, SLOT( updateUndoActions() ) );
}
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 );
#ifdef HAVE_TOUCH
mMapTools.mTouch = new QgsMapToolTouch( mMapCanvas );
mMapTools.mTouch->setAction( mActionTouch );
#endif
mMapTools.mIdentify = new QgsMapToolIdentifyAction( mMapCanvas );
mMapTools.mIdentify->setAction( mActionIdentify );
connect( mMapTools.mIdentify, SIGNAL( copyToClipboard( QgsFeatureStore & ) ),
this, SLOT( copyFeatures( QgsFeatureStore & ) ) );
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 );
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas );
mMapTools.mRotateFeature->setAction( mActionRotateFeature );
//need at least geos 3.3 for OffsetCurve tool
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
mMapTools.mOffsetCurve = new QgsMapToolOffsetCurve( mMapCanvas );
mMapTools.mOffsetCurve->setAction( mActionOffsetCurve );
#else
mAdvancedDigitizeToolBar->removeAction( mActionOffsetCurve );
mEditMenu->removeAction( mActionOffsetCurve );
mMapTools.mOffsetCurve = 0;
#endif //GEOS_VERSION
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.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 initialised or we will get crashes in some situations
mNonEditMapTool = mMapTools.mPan;
}
void QgisApp::createOverview()
{
// overview canvas
QgsMapOverviewCanvas* overviewCanvas = new QgsMapOverviewCanvas( NULL, mMapCanvas );
overviewCanvas->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." ) );
QBitmap overviewPanBmp = QBitmap::fromData( QSize( 16, 16 ), pan_bits );
QBitmap overviewPanBmpMask = QBitmap::fromData( QSize( 16, 16 ), pan_mask_bits );
mOverviewMapCursor = new QCursor( overviewPanBmp, overviewPanBmpMask, 0, 0 ); //set upper left corner as hot spot - this is better when extent marker is small; hand won't cover the marker
overviewCanvas->setCursor( *mOverviewMapCursor );
// QVBoxLayout *myOverviewLayout = new QVBoxLayout;
// myOverviewLayout->addWidget(overviewCanvas);
// overviewFrame->setLayout(myOverviewLayout);
mOverviewDock = new QDockWidget( tr( "Overview Panel" ), this );
mOverviewDock->setObjectName( "Overview" );
mOverviewDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
mOverviewDock->setWidget( overviewCanvas );
addDockWidget( Qt::LeftDockWidgetArea, mOverviewDock );
// add to the Panel submenu
mPanelMenu->addAction( mOverviewDock->toggleViewAction() );
mMapCanvas->enableOverviewMode( overviewCanvas );
// moved here to set anti aliasing to both map canvas and overview
QSettings mySettings;
// Anti Aliasing enabled by default as of QGIS 1.7
mMapCanvas->enableAntiAliasing( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() );
int action = mySettings.value( "/qgis/wheel_action", 2 ).toInt();
double zoomFactor = mySettings.value( "/qgis/zoom_factor", 2 ).toDouble();
mMapCanvas->setWheelAction(( QgsMapCanvas::WheelAction ) action, zoomFactor );
mMapCanvas->setCachingEnabled( mySettings.value( "/qgis/enable_render_caching", true ).toBool() );
mMapCanvas->setParallelRenderingEnabled( mySettings.value( "/qgis/parallel_rendering", false ).toBool() );
mMapCanvas->setMapUpdateInterval( mySettings.value( "/qgis/map_update_interval", 250 ).toInt() );
}
void QgisApp::addDockWidget( Qt::DockWidgetArea theArea, QDockWidget * thepDockWidget )
{
QMainWindow::addDockWidget( theArea, 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
mMapCanvas->refresh();
}
void QgisApp::removeDockWidget( QDockWidget * thepDockWidget )
{
QMainWindow::removeDockWidget( thepDockWidget );
mPanelMenu->removeAction( thepDockWidget->toggleViewAction() );
}
QToolBar *QgisApp::addToolBar( 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;
}
QgsMessageBar* QgisApp::messageBar()
{
Q_ASSERT( mInfoBar );
return mInfoBar;
}
void QgisApp::addUserInputWidget( QWidget *widget )
{
mUserInputDockWidget->addUserInputWidget( widget );
}
void QgisApp::initLayerTreeView()
{
mLayerTreeView->setWhatsThis( tr( "Map legend that displays all the layers currently on the map canvas. Click on the check box to turn a layer on or off. Double click on a layer in the legend to customize its appearance and set other properties." ) );
mLayerTreeDock = new QDockWidget( tr( "Layers Panel" ), this );
mLayerTreeDock->setObjectName( "Layers" );
mLayerTreeDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
QgsLayerTreeModel* model = new QgsLayerTreeModel( QgsProject::instance()->layerTreeRoot(), this );
#ifdef ENABLE_MODELTEST
new ModelTest( model, this );
#endif
model->setFlag( QgsLayerTreeModel::AllowNodeReorder );
model->setFlag( QgsLayerTreeModel::AllowNodeRename );
model->setFlag( QgsLayerTreeModel::AllowNodeChangeVisibility );
model->setFlag( QgsLayerTreeModel::ShowLegendAsTree );
model->setAutoCollapseLegendNodes( 10 );
mLayerTreeView->setModel( model );
mLayerTreeView->setMenuProvider( new QgsAppLayerTreeViewMenuProvider( mLayerTreeView, mMapCanvas ) );
setupLayerTreeViewFromSettings();
connect( mLayerTreeView, SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( layerTreeViewDoubleClicked( QModelIndex ) ) );
connect( mLayerTreeView, SIGNAL( currentLayerChanged( QgsMapLayer* ) ), this, SLOT( activeLayerChanged( QgsMapLayer* ) ) );
connect( mLayerTreeView->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SLOT( updateNewLayerInsertionPoint() ) );
connect( QgsProject::instance()->layerTreeRegistryBridge(), SIGNAL( addedLayersToLayerTree( QList<QgsMapLayer*> ) ),
this, SLOT( autoSelectAddedLayer( QList<QgsMapLayer*> ) ) );
// add group action
QAction* actionAddGroup = new QAction( tr( "Add Group" ), this );
actionAddGroup->setIcon( QgsApplication::getThemeIcon( "/mActionAddGroup.svg" ) );
actionAddGroup->setToolTip( tr( "Add Group" ) );
connect( actionAddGroup, SIGNAL( triggered( bool ) ), mLayerTreeView->defaultActions(), SLOT( addGroup() ) );
// visibility groups tool button
QToolButton* btnVisibilityPresets = new QToolButton;
btnVisibilityPresets->setAutoRaise( true );
btnVisibilityPresets->setToolTip( tr( "Manage Layer Visibility" ) );
btnVisibilityPresets->setIcon( QgsApplication::getThemeIcon( "/mActionShowAllLayers.svg" ) );
btnVisibilityPresets->setPopupMode( QToolButton::InstantPopup );
btnVisibilityPresets->setMenu( QgsVisibilityPresets::instance()->menu() );
// filter legend action
mActionFilterLegend = new QAction( tr( "Filter Legend By Map Content" ), this );
mActionFilterLegend->setCheckable( true );
mActionFilterLegend->setToolTip( tr( "Filter Legend By Map Content" ) );
mActionFilterLegend->setIcon( QgsApplication::getThemeIcon( "/mActionFilter2.svg" ) );
connect( mActionFilterLegend, SIGNAL( triggered( bool ) ), this, SLOT( toggleFilterLegendByMap() ) );
// expand / collapse tool buttons
QAction* actionExpandAll = new QAction( tr( "Expand All" ), this );
actionExpandAll->setIcon( QgsApplication::getThemeIcon( "/mActionExpandTree.svg" ) );
actionExpandAll->setToolTip( tr( "Expand All" ) );
connect( actionExpandAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( expandAll() ) );
QAction* actionCollapseAll = new QAction( tr( "Collapse All" ), this );
actionCollapseAll->setIcon( QgsApplication::getThemeIcon( "/mActionCollapseTree.svg" ) );
actionCollapseAll->setToolTip( tr( "Collapse All" ) );
connect( actionCollapseAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( collapseAll() ) );
QToolBar* toolbar = new QToolBar();
toolbar->setIconSize( QSize( 16, 16 ) );
toolbar->addAction( actionAddGroup );
toolbar->addWidget( btnVisibilityPresets );
toolbar->addAction( mActionFilterLegend );
toolbar->addAction( actionExpandAll );
toolbar->addAction( actionCollapseAll );
toolbar->addAction( mActionRemoveLayer );
QVBoxLayout* vboxLayout = new QVBoxLayout;
vboxLayout->setMargin( 0 );
vboxLayout->addWidget( toolbar );
vboxLayout->addWidget( mLayerTreeView );
QWidget* w = new QWidget;
w->setLayout( vboxLayout );
mLayerTreeDock->setWidget( w );
addDockWidget( Qt::LeftDockWidgetArea, mLayerTreeDock );
mLayerTreeCanvasBridge = new QgsLayerTreeMapCanvasBridge( QgsProject::instance()->layerTreeRoot(), mMapCanvas, this );
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument& ) ), mLayerTreeCanvasBridge, SLOT( writeProject( QDomDocument& ) ) );
connect( QgsProject::instance(), SIGNAL( readProject( QDomDocument ) ), mLayerTreeCanvasBridge, SLOT( readProject( QDomDocument ) ) );
bool otfTransformAutoEnable = QSettings().value( "/Projections/otfTransformAutoEnable", true ).toBool();
mLayerTreeCanvasBridge->setAutoEnableCrsTransform( otfTransformAutoEnable );
mMapLayerOrder = new QgsCustomLayerOrderWidget( mLayerTreeCanvasBridge, this );
mMapLayerOrder->setObjectName( "theMapLayerOrder" );
mMapLayerOrder->setWhatsThis( tr( "Map layer list that displays all layers in drawing order." ) );
mLayerOrderDock = new QDockWidget( tr( "Layer Order Panel" ), this );
mLayerOrderDock->setObjectName( "LayerOrder" );
mLayerOrderDock->setAllowedAreas( Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea );
mLayerOrderDock->setWidget( mMapLayerOrder );
addDockWidget( Qt::LeftDockWidgetArea, mLayerOrderDock );
mLayerOrderDock->hide();
}
void QgisApp::setupLayerTreeViewFromSettings()
{
QSettings s;
QgsLayerTreeModel* model = mLayerTreeView->layerTreeModel();
model->setFlag( QgsLayerTreeModel::ShowRasterPreviewIcon, s.value( "/qgis/createRasterLegendIcons", false ).toBool() );
QFont fontLayer, fontGroup;
fontLayer.setBold( s.value( "/qgis/legendLayersBold", true ).toBool() );
fontGroup.setBold( s.value( "/qgis/legendGroupsBold", false ).toBool() );
model->setLayerTreeNodeFont( QgsLayerTreeNode::NodeLayer, fontLayer );
model->setLayerTreeNodeFont( QgsLayerTreeNode::NodeGroup, fontGroup );
}
void QgisApp::updateNewLayerInsertionPoint()
{
// defaults
QgsLayerTreeGroup* parentGroup = mLayerTreeView->layerTreeModel()->rootGroup();
int index = 0;
QModelIndex current = mLayerTreeView->currentIndex();
if ( current.isValid() )
{
if ( QgsLayerTreeNode* currentNode = mLayerTreeView->currentNode() )
{
// if the insertion point is actually a group, insert new layers into the group
if ( QgsLayerTree::isGroup( currentNode ) )
{
QgsProject::instance()->layerTreeRegistryBridge()->setLayerInsertionPoint( QgsLayerTree::toGroup( currentNode ), 0 );
return;
}
// otherwise just set the insertion point in front of the current node
QgsLayerTreeNode* parentNode = currentNode->parent();
if ( QgsLayerTree::isGroup( parentNode ) )
parentGroup = QgsLayerTree::toGroup( parentNode );
}
index = current.row();
}
QgsProject::instance()->layerTreeRegistryBridge()->setLayerInsertionPoint( parentGroup, index );
}
void QgisApp::autoSelectAddedLayer( QList<QgsMapLayer*> layers )
{
if ( layers.count() )
{
QgsLayerTreeLayer* nodeLayer = QgsProject::instance()->layerTreeRoot()->findLayer( layers[0]->id() );
if ( !nodeLayer )
return;
QModelIndex index = mLayerTreeView->layerTreeModel()->node2index( nodeLayer );
mLayerTreeView->setCurrentIndex( index );
}
}
void QgisApp::createMapTips()
{
// Set up the timer for maptips. The timer is reset everytime the mouse is moved
mpMapTipsTimer = new QTimer( mMapCanvas );
// connect the timer to the maptips slot
connect( mpMapTipsTimer, SIGNAL( timeout() ), this, SLOT( showMapTip() ) );
// set the interval to 0.850 seconds - timer will be started next time the mouse moves
mpMapTipsTimer->setInterval( 850 );
// Create the maptips object
mpMaptip = new QgsMapTip();
}
void QgisApp::createDecorations()
{
QgsDecorationCopyright* mDecorationCopyright = new QgsDecorationCopyright( this );
connect( mActionDecorationCopyright, SIGNAL( triggered() ), mDecorationCopyright, SLOT( run() ) );
QgsDecorationNorthArrow* mDecorationNorthArrow = new QgsDecorationNorthArrow( this );
connect( mActionDecorationNorthArrow, SIGNAL( triggered() ), mDecorationNorthArrow, SLOT( run() ) );
QgsDecorationScaleBar* mDecorationScaleBar = new QgsDecorationScaleBar( this );
connect( mActionDecorationScaleBar, SIGNAL( triggered() ), mDecorationScaleBar, SLOT( run() ) );
QgsDecorationGrid* mDecorationGrid = new QgsDecorationGrid( this );
connect( mActionDecorationGrid, SIGNAL( triggered() ), mDecorationGrid, SLOT( run() ) );
// add the decorations in a particular order so they are rendered in that order
addDecorationItem( mDecorationGrid );
addDecorationItem( mDecorationCopyright );
addDecorationItem( mDecorationNorthArrow );
addDecorationItem( mDecorationScaleBar );
connect( mMapCanvas, SIGNAL( renderComplete( QPainter * ) ), this, SLOT( renderDecorationItems( QPainter * ) ) );
connect( this, SIGNAL( newProject() ), this, SLOT( projectReadDecorationItems() ) );
connect( this, SIGNAL( projectRead() ), this, SLOT( projectReadDecorationItems() ) );
}
void QgisApp::renderDecorationItems( QPainter *p )
{
foreach ( QgsDecorationItem* item, mDecorationItems )
{
item->render( p );
}
}
void QgisApp::projectReadDecorationItems()
{
foreach ( QgsDecorationItem* item, mDecorationItems )
{
item->projectRead();
}
}
// Update project menu with the current list of recently accessed projects
void QgisApp::updateRecentProjectPaths()
{
mRecentProjectsMenu->clear();
Q_FOREACH ( const QgsWelcomePageItemsModel::RecentProjectData& recentProject, mRecentProjects )
{
QAction* action = mRecentProjectsMenu->addAction( QString( "%1 (%2)" ).arg( recentProject.title ).arg( recentProject.path ) );
action->setEnabled( QFile::exists(( recentProject.path ) ) );
action->setData( recentProject.path );
}
if ( mWelcomePage )
mWelcomePage->setRecentProjects( mRecentProjects );
} // QgisApp::updateRecentProjectPaths
// add this file to the recently opened/saved projects list
void QgisApp::saveRecentProjectPath( QString projectPath, bool savePreviewImage )
{
QSettings settings;
// Get canonical absolute path
QFileInfo myFileInfo( projectPath );
QgsWelcomePageItemsModel::RecentProjectData projectData;
projectData.path = myFileInfo.absoluteFilePath();
projectData.title = QgsProject::instance()->title();
if ( projectData.title.isEmpty() )
projectData.title = projectData.path;
if ( savePreviewImage )
{
// Generate a unique file name
QString fileName( QCryptographicHash::hash(( projectData.path.toUtf8() ), QCryptographicHash::Md5 ).toHex() );
QString previewDir = QString( "%1/previewImages" ).arg( QgsApplication::qgisSettingsDirPath() );
projectData.previewImagePath = QString( "%1/%2.png" ).arg( previewDir ).arg( fileName );
QDir().mkdir( previewDir );
// Render the map canvas
QSize previewSize( 250, 177 ); // h = w / sqrt(2)
QRect previewRect( QPoint(( mMapCanvas->width() - previewSize.width() ) / 2
, ( mMapCanvas->height() - previewSize.height() ) / 2 )
, previewSize );
QPixmap previewImage( previewSize );
QPainter previewPainter( &previewImage );
mMapCanvas->render( &previewPainter, QRect( QPoint(), previewSize ), previewRect );
// Save
previewImage.save( projectData.previewImagePath );
}
else
{
int idx = mRecentProjects.indexOf( projectData );
if ( idx != -1 )
projectData.previewImagePath = mRecentProjects.at( idx ).previewImagePath;
}
// If this file is already in the list, remove it
mRecentProjects.removeAll( projectData );
// Prepend this file to the list
mRecentProjects.prepend( projectData );
// Keep the list to 8 items by trimming excess off the bottom
// And remove the associated image
while ( mRecentProjects.count() > 10 )
{
QFile( mRecentProjects.takeLast().previewImagePath ).remove();
}
settings.remove( "/UI/recentProjects" );
int idx = 0;
// Persist the list
Q_FOREACH ( const QgsWelcomePageItemsModel::RecentProjectData& recentProject, mRecentProjects )
{
++idx;
settings.beginGroup( QString( "/UI/recentProjects/%1" ).arg( idx ) );
settings.setValue( "title", recentProject.title );
settings.setValue( "path", recentProject.path );
settings.setValue( "previewImage", recentProject.previewImagePath );
settings.endGroup();
}
// Update menu list of paths
updateRecentProjectPaths();
} // QgisApp::saveRecentProjectPath
// Update project menu with the project templates
void QgisApp::updateProjectFromTemplates()
{
// get list of project files in template dir
QSettings settings;
QString templateDirName = settings.value( "/qgis/projectTemplateDir",
QgsApplication::qgisSettingsDirPath() + "project_templates" ).toString();
QDir templateDir( templateDirName );
QStringList filters( "*.qgs" );
templateDir.setNameFilters( filters );
QStringList templateFiles = templateDir.entryList( filters );
// Remove existing entries
mProjectFromTemplateMenu->clear();
// Add entries
foreach ( QString templateFile, templateFiles )
{
mProjectFromTemplateMenu->addAction( templateFile );
}
// add <blank> entry, which loads a blank template (regardless of "default template")
if ( settings.value( "/qgis/newProjectDefault", QVariant( false ) ).toBool() )
mProjectFromTemplateMenu->addAction( tr( "< Blank >" ) );
} // QgisApp::updateProjectFromTemplates
void QgisApp::saveWindowState()
{
// store window and toolbar positions
QSettings settings;
// store the toolbar/dock widget settings using Qt4 settings API
settings.setValue( "/UI/state", saveState() );
// store window geometry
settings.setValue( "/UI/geometry", saveGeometry() );
QgsPluginRegistry::instance()->unloadAll();
}
#include "ui_defaults.h"
void QgisApp::restoreWindowState()
{
// restore the toolbar and dock widgets positions using Qt4 settings API
QSettings settings;
if ( !restoreState( settings.value( "/UI/state", QByteArray::fromRawData(( char * )defaultUIstate, sizeof defaultUIstate ) ).toByteArray() ) )
{
QgsDebugMsg( "restore of UI state failed" );
}
// restore window geometry
if ( !restoreGeometry( settings.value( "/UI/geometry", QByteArray::fromRawData(( char * )defaultUIgeometry, sizeof defaultUIgeometry ) ).toByteArray() ) )
{
QgsDebugMsg( "restore of UI geometry failed" );
}
}
///////////// END OF GUI SETUP ROUTINES ///////////////
void QgisApp::sponsors()
{
QgsSponsors * sponsors = new QgsSponsors( this );
sponsors->show();
sponsors->raise();
sponsors->activateWindow();
}
void QgisApp::about()
{
static QgsAbout *abt = NULL;
if ( !abt )
{
QApplication::setOverrideCursor( Qt::WaitCursor );
abt = new QgsAbout( this );
QString versionString = "<html><body><div align='center'><table width='100%'>";
versionString += "<tr>";
versionString += "<td>" + tr( "QGIS version" ) + "</td><td>" + QGis::QGIS_VERSION + "</td>";
versionString += "<td>" + tr( "QGIS code revision" ) + QString( "</td><td><a href=\"https://github.com/qgis/QGIS/commit/%1\">%1</a></td>" ).arg( QGis::QGIS_DEV_VERSION );
versionString += "</tr><tr>";
versionString += "<td>" + tr( "Compiled against Qt" ) + "</td><td>" + QT_VERSION_STR + "</td>";
versionString += "<td>" + tr( "Running against Qt" ) + "</td><td>" + qVersion() + "</td>";
versionString += "</tr><tr>";
versionString += "<td>" + tr( "Compiled against GDAL/OGR" ) + "</td><td>" + GDAL_RELEASE_NAME + "</td>";
versionString += "<td>" + tr( "Running against GDAL/OGR" ) + "</td><td>" + GDALVersionInfo( "RELEASE_NAME" ) + "</td>";
versionString += "</tr><tr>";
versionString += "<td>" + tr( "Compiled against GEOS" ) + "</td><td>" + GEOS_CAPI_VERSION + "</td>";
versionString += "<td>" + tr( "Running against GEOS" ) + "</td><td>" + GEOSversion() + "</td>";
versionString += "</tr><tr>";
versionString += "<td>" + tr( "PostgreSQL Client Version" ) + "</td><td>";
#ifdef HAVE_POSTGRESQL
versionString += PG_VERSION;
#else
versionString += tr( "No support." );
#endif
versionString += "</td>";
versionString += "<td>" + tr( "SpatiaLite Version" ) + "</td><td>";
versionString += spatialite_version();
versionString += "</td>";
versionString += "</tr><tr>";
versionString += "<td>" + tr( "QWT Version" ) + "</td><td>" + QWT_VERSION_STR + "</td>";
versionString += "<td>" + tr( "PROJ.4 Version" ) + "</td><td>" + QString::number( PJ_VERSION ) + "</td>";
versionString += "</tr><tr>";
versionString += "<td>" + tr( "QScintilla2 Version" ) + "</td><td>" + QSCINTILLA_VERSION_STR + "</td>";
#ifdef QGISDEBUG
versionString += "<td colspan=2>" + tr( "This copy of QGIS writes debugging output." ) + "</td>";
#endif
versionString += "</tr></table></div></body></html>";
abt->setVersion( versionString );
QApplication::restoreOverrideCursor();
}
abt->show();
abt->raise();
abt->activateWindow();
}
void QgisApp::addLayerDefinition()
{
QString path = QFileDialog::getOpenFileName( this, "Add Layer Definition File", QDir::home().path(), "*.qlr" );
if ( path.isEmpty() )
return;
openLayerDefinition( path );
}
QString QgisApp::crsAndFormatAdjustedLayerUri( const QString &uri, const QStringList &supportedCrs, const QStringList &supportedFormats ) const
{
QString newuri = uri;
// Adjust layer CRS to project CRS
QgsCoordinateReferenceSystem testCrs;
foreach ( QString c, supportedCrs )
{
testCrs.createFromOgcWmsCrs( c );
if ( testCrs == mMapCanvas->mapSettings().destinationCrs() )
{
newuri.replace( QRegExp( "crs=[^&]+" ), "crs=" + c );
QgsDebugMsg( QString( "Changing layer crs to %1, new uri: %2" ).arg( c, uri ) );
break;
}
}
// Use the last used image format
QString lastImageEncoding = QSettings().value( "/qgis/lastWmsImageEncoding", "image/png" ).toString();
foreach ( QString fmt, supportedFormats )
{
if ( fmt == lastImageEncoding )
{
newuri.replace( QRegExp( "format=[^&]+" ), "format=" + fmt );
QgsDebugMsg( QString( "Changing layer format to %1, new uri: %2" ).arg( fmt, uri ) );
break;
}
}
return newuri;
}
/**
This method prompts the user for a list of vector file names with a dialog.
*/
void QgisApp::addVectorLayer()
{
mMapCanvas->freeze();
QgsOpenVectorLayerDialog *ovl = new QgsOpenVectorLayerDialog( this );
if ( ovl->exec() )
{
QStringList selectedSources = ovl->dataSources();
QString enc = ovl->encoding();
if ( !selectedSources.isEmpty() )
{
addVectorLayers( selectedSources, enc, ovl->dataSourceType() );
}
}
mMapCanvas->freeze( false );
mMapCanvas->refresh();
delete ovl;
}
bool QgisApp::addVectorLayers( const QStringList &theLayerQStringList, const QString &enc, const QString &dataSourceType )
{
bool wasfrozen = mMapCanvas->isFrozen();
QList<QgsMapLayer *> myList;
foreach ( QString src, theLayerQStringList )
{
src = src.trimmed();
QString base;
if ( dataSourceType == "file" )
{
QFileInfo fi( src );
base = fi.completeBaseName();
// if needed prompt for zipitem layers
QString vsiPrefix = QgsZipItem::vsiPrefix( src );
if ( ! src.startsWith( "/vsi", Qt::CaseInsensitive ) &&
( vsiPrefix == "/vsizip/" || vsiPrefix == "/vsitar/" ) )
{
if ( askUserForZipItemLayers( src ) )
continue;
}
}
else if ( dataSourceType == "database" )
{
base = src;
}
else //directory //protocol
{
QFileInfo fi( src );
base = fi.completeBaseName();
}
QgsDebugMsg( "completeBaseName: " + base );
// create the layer
QgsVectorLayer *layer = new QgsVectorLayer( src, base, "ogr", false );
Q_CHECK_PTR( layer );
if ( ! layer )
{
mMapCanvas->freeze( false );
// Let render() do its own cursor management
// QApplication::restoreOverrideCursor();
// XXX insert meaningful whine to the user here
return false;
}
if ( layer->isValid() )
{
layer->setProviderEncoding( enc );
QStringList sublayers = layer->dataProvider()->subLayers();
QgsDebugMsg( QString( "got valid layer with %1 sublayers" ).arg( sublayers.count() ) );
// If the newly created layer has more than 1 layer of data available, we show the
// sublayers selection dialog so the user can select the sublayers to actually load.
if ( sublayers.count() > 1 )
{
askUserForOGRSublayers( layer );
// The first layer loaded is not useful in that case. The user can select it in
// the list if he wants to load it.
delete layer;
}
else if ( sublayers.count() > 0 ) // there is 1 layer of data available
{
//set friendly name for datasources with only one layer
QStringList sublayers = layer->dataProvider()->subLayers();
QStringList elements = sublayers.at( 0 ).split( ":" );
if ( layer->storageType() != "GeoJSON" )
{
while ( elements.size() > 4 )
{
elements[1] += ":" + elements[2];
elements.removeAt( 2 );
}
layer->setLayerName( elements.at( 1 ) );
}
myList << layer;
}
else
{
QString msg = tr( "%1 doesn't have any layers" ).arg( src );
messageBar()->pushMessage( tr( "Invalid Data Source" ), msg, QgsMessageBar::CRITICAL, messageTimeout() );
delete layer;
}
}
else
{
QString msg = tr( "%1 is not a valid or recognized data source" ).arg( src );
messageBar()->pushMessage( tr( "Invalid Data Source" ), msg, QgsMessageBar::CRITICAL, messageTimeout() );
// since the layer is bad, stomp on it
delete layer;
}
}
// make sure at least one layer was successfully added
if ( myList.count() == 0 )
{
return false;
}
// Register this layer with the layers registry
QgsMapLayerRegistry::instance()->addMapLayers( myList );
foreach ( QgsMapLayer *l, myList )
{
bool ok;
l->loadDefaultStyle( ok );
}
// Only update the map if we frozen in this method
// Let the caller do it otherwise
if ( !wasfrozen )
{
mMapCanvas->freeze( false );
mMapCanvas->refresh();
}
// Let render() do its own cursor management
// QApplication::restoreOverrideCursor();
// statusBar()->showMessage( mMapCanvas->extent().toString( 2 ) );
return true;
} // QgisApp::addVectorLayer()
// present a dialog to choose zipitem layers
bool QgisApp::askUserForZipItemLayers( QString path )
{
bool ok = false;
QVector<QgsDataItem*> childItems;
QgsZipItem *zipItem = 0;
QSettings settings;
int promptLayers = settings.value( "/qgis/promptForRasterSublayers", 1 ).toInt();
QgsDebugMsg( "askUserForZipItemLayers( " + path + ")" );
// if scanZipBrowser == no: skip to the next file
if ( settings.value( "/qgis/scanZipInBrowser2", "basic" ).toString() == "no" )
{
return false;
}
zipItem = new QgsZipItem( 0, path, path );
if ( ! zipItem )
return false;
zipItem->populate();
QgsDebugMsg( QString( "Path= %1 got zipitem with %2 children" ).arg( path ).arg( zipItem->rowCount() ) );
// if 1 or 0 child found, exit so a normal item is created by gdal or ogr provider
if ( zipItem->rowCount() <= 1 )
{
delete zipItem;
return false;
}
// if promptLayers=Load all, load all layers without prompting
if ( promptLayers == 3 )
{
childItems = zipItem->children();
}
// exit if promptLayers=Never
else if ( promptLayers == 2 )
{
delete zipItem;
return false;
}
else
{
// We initialize a selection dialog and display it.
QgsSublayersDialog chooseSublayersDialog( QgsSublayersDialog::Vsifile, "vsi", this );
QStringList layers;
for ( int i = 0; i < zipItem->children().size(); i++ )
{
QgsDataItem *item = zipItem->children()[i];
QgsLayerItem *layerItem = dynamic_cast<QgsLayerItem *>( item );
if ( layerItem )
{
QgsDebugMsgLevel( QString( "item path=%1 provider=%2" ).arg( item->path() ).arg( layerItem->providerKey() ), 2 );
}
if ( layerItem && layerItem->providerKey() == "gdal" )
{
layers << QString( "%1|%2|%3" ).arg( i ).arg( item->name() ).arg( "Raster" );
}
else if ( layerItem && layerItem->providerKey() == "ogr" )
{
layers << QString( "%1|%2|%3" ).arg( i ).arg( item->name() ).arg( tr( "Vector" ) );
}
}
chooseSublayersDialog.populateLayerTable( layers, "|" );
if ( chooseSublayersDialog.exec() )
{
foreach ( int i, chooseSublayersDialog.selectionIndexes() )
{
childItems << zipItem->children()[i];
}
}
}
if ( childItems.isEmpty() )
{
// return true so dialog doesn't popup again (#6225) - hopefully this doesn't create other trouble
ok = true;
}
// add childItems
foreach ( QgsDataItem* item, childItems )
{
QgsLayerItem *layerItem = dynamic_cast<QgsLayerItem *>( item );
if ( !layerItem )
continue;
QgsDebugMsg( QString( "item path=%1 provider=%2" ).arg( item->path() ).arg( layerItem->providerKey() ) );
if ( layerItem->providerKey() == "gdal" )
{
if ( addRasterLayer( item->path(), QFileInfo( item->name() ).completeBaseName() ) )
ok = true;
}
else if ( layerItem->providerKey() == "ogr" )
{
if ( addVectorLayers( QStringList( item->path() ), "System", "file" ) )
ok = true;
}
}
delete zipItem;