3 changes: 3 additions & 0 deletions images/images.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
<file>themes/default/mActionZoomOut.png</file>
<file>themes/default/mActionZoomToLayer.png</file>
<file>themes/default/mActionZoomToSelected.png</file>
<file>themes/default/mIconClose.png</file>
<file>themes/default/mIconConnect.png</file>
<file>themes/default/mIconDbSchema.png</file>
<file>themes/default/mIconDelete.png</file>
Expand Down Expand Up @@ -369,6 +370,7 @@
<file>themes/gis/mActionZoomOut.png</file>
<file>themes/gis/mActionZoomToLayer.png</file>
<file>themes/gis/mActionZoomToSelected.png</file>
<file>themes/gis/mIconClose.png</file>
<file>themes/gis/mIconEditable.png</file>
<file>themes/gis/mIconLineLayer.png</file>
<file>themes/gis/mIconPointLayer.png</file>
Expand Down Expand Up @@ -400,6 +402,7 @@
<file>themes/gis/mIconWcs.png</file>
<file>themes/gis/mIconWms.png</file>
<file>themes/gis/mIconWfs.png</file>
<file>themes/gis/mIconWarn.png</file>
<file>themes/gis/mIconSpatialite.png</file>
<file>themes/gis/mIconRaster.png</file>
<file>themes/gis/mIconPostgis.png</file>
Expand Down
Binary file added images/themes/default/mIconClose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/themes/default/mIconWarn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/gis/mIconClose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/themes/gis/mIconWarn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions python/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,57 @@ def pluginDirectory(packageName):
""" return directory where the plugin resides. Plugin must be loaded already """
return os.path.dirname(sys.modules[packageName].__file__)

def reloadProjectMacros():
# unload old macros
unloadProjectMacros()

from qgis.core import QgsProject
code, ok = QgsProject.instance().readEntry("Macros", "/pythonCode")
if not ok or code.isEmpty():
return

# create a new empty python module
import imp
mod = imp.new_module("proj_macros_mod")

# set the module code and store it sys.modules
exec unicode(code) in mod.__dict__
sys.modules["proj_macros_mod"] = mod

# load new macros
openProjectMacro()

def unloadProjectMacros():
if "proj_macros_mod" not in sys.modules:
return
# unload old macros
closeProjectMacro()
# destroy the reference to the module
del sys.modules["proj_macros_mod"]


def openProjectMacro():
if "proj_macros_mod" not in sys.modules:
return
mod = sys.modules["proj_macros_mod"]
if hasattr(mod, 'openProject'):
mod.openProject()

def saveProjectMacro():
if "proj_macros_mod" not in sys.modules:
return
mod = sys.modules["proj_macros_mod"]
if hasattr(mod, 'saveProject'):
mod.saveProject()

def closeProjectMacro():
if "proj_macros_mod" not in sys.modules:
return
mod = sys.modules["proj_macros_mod"]
if hasattr(mod, 'closeProject'):
mod.closeProject()


#######################
# IMPORT wrapper

Expand Down
114 changes: 97 additions & 17 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
#include "qgsmaptip.h"
#include "qgsmergeattributesdialog.h"
#include "qgsmessageviewer.h"
#include "qgsmessagebar.h"
#include "qgsmimedatautils.h"
#include "qgsmessagelog.h"
#include "qgsmultibandcolorrenderer.h"
Expand Down Expand Up @@ -455,16 +456,29 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
QSettings settings;
setFontSize( settings.value( "/fontPointSize", QGIS_DEFAULT_FONTSIZE ).toInt() );

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( this, "theMapCanvas" );
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 ) );
setCentralWidget( mMapCanvas );

centralLayout->addWidget( mMapCanvas, 0, 0, 2, 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 );

//set the focus to the map canvas
mMapCanvas->setFocus();

Expand Down Expand Up @@ -493,6 +507,20 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
updateProjectFromTemplates();
activateDeactivateLayerRelatedActions( NULL );

// create the notification widget for macros
mMacrosWarn = QgsMessageBar::createMessage( tr( "Security warning:" ),
tr( "macros have been disabled." ),
QgsApplication::getThemeIcon( "/mIconWarn.png" ),
mInfoBar );

QToolButton *btnEnableMacros = new QToolButton( mMacrosWarn );
btnEnableMacros->setText( tr( "Enable" ) );
btnEnableMacros->setStyleSheet( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" );
btnEnableMacros->setCursor( Qt::PointingHandCursor );
connect( btnEnableMacros, SIGNAL( clicked() ), mInfoBar, SLOT( popWidget() ) );
connect( btnEnableMacros, SIGNAL( clicked() ), this, SLOT( enableProjectMacros() ) );
mMacrosWarn->layout()->addWidget( btnEnableMacros );

addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget );
mUndoWidget->hide();

Expand Down Expand Up @@ -628,6 +656,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,
QgsMessageLog::logMessage( tr( "QGIS Ready!" ) );

mMapTipsVisible = false;
mTrustedMacros = false;

// setup drag drop
setAcceptDrops( true );
Expand Down Expand Up @@ -813,6 +842,13 @@ void QgisApp::readSettings()

// Add the recently accessed project file paths to the File menu
mRecentProjectPaths = settings.value( "/UI/recentProjectsList" ).toStringList();

// 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 );
}
}


Expand Down Expand Up @@ -2949,10 +2985,7 @@ void QgisApp::fileExit()

if ( saveDirty() )
{
deletePrintComposers();
removeAnnotationItems();
mMapCanvas->freeze( true );
removeAllLayers();
closeProject();
qApp->exit( 0 );
}
}
Expand Down Expand Up @@ -2999,11 +3032,7 @@ void QgisApp::fileNew( bool thePromptToSaveFlag, bool forceBlank )
}
}

deletePrintComposers();
removeAnnotationItems();

mMapCanvas->freeze( true );
removeAllLayers();
closeProject();
mMapCanvas->clear();

QgsProject* prj = QgsProject::instance();
Expand Down Expand Up @@ -3185,6 +3214,8 @@ void QgisApp::fileOpen()
return;
}

closeProject();

// Fix by Tim - getting the dirPath from the dialog
// directly truncates the last node in the dir path.
// This is a workaround for that
Expand All @@ -3193,12 +3224,6 @@ void QgisApp::fileOpen()
// Persist last used project dir
settings.setValue( "/UI/lastProjectDir", myPath );

deletePrintComposers();
removeAnnotationItems();
// clear out any stuff from previous project
mMapCanvas->freeze( true );
removeAllLayers();

QgsProject::instance()->setFileName( fullPath );

if ( ! QgsProject::instance()->read() )
Expand All @@ -3219,6 +3244,26 @@ void QgisApp::fileOpen()
mScaleEdit->updateScales( QgsProject::instance()->readListEntry( "Scales", "/ScalesList" ) );
}

// does the project have any macros?
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
if ( !QgsProject::instance()->readEntry( "Macros", "/pythonCode", QString::null ).isEmpty() )
{
int enableMacros = settings.value( "/qgis/enableMacros", 1 ).toInt();
// 0 = never, 1 = ask, 2 = just for this session, 3 = always

if ( enableMacros == 3 || enableMacros == 2 )
{
enableProjectMacros();
}
else if ( enableMacros == 1 ) // ask
{
// display the macros notification widget
mInfoBar->pushWidget( mMacrosWarn, 1 );
}
}
}

emit projectRead(); // let plug-ins know that we've read in a new
// project so that they can check any project
// specific plug-in state
Expand All @@ -3231,6 +3276,14 @@ void QgisApp::fileOpen()
}
} // QgisApp::fileOpen

void QgisApp::enableProjectMacros()
{
mTrustedMacros = true;

// load macros
QgsPythonRunner::run( "qgis.utils.reloadProjectMacros()" );
}


/**
adds a saved project to qgis, usually called on startup by specifying a
Expand Down Expand Up @@ -3370,6 +3423,13 @@ bool QgisApp::fileSave()
QgsProject::instance()->error() );
return false;
}

// run the saved project macro
if ( mTrustedMacros )
{
QgsPythonRunner::run( "qgis.utils.saveProjectMacro();" );
}

return true;
} // QgisApp::fileSave

Expand Down Expand Up @@ -5873,6 +5933,26 @@ bool QgisApp::saveDirty()
return answer != QMessageBox::Cancel;
} // QgisApp::saveDirty()

void QgisApp::closeProject()
{
// unload the project macros before changing anything
if ( mTrustedMacros )
{
QgsPythonRunner::run( "qgis.utils.unloadProjectMacros();" );
}

// remove the warning message from the bar if present
mInfoBar->popWidget( mMacrosWarn );

mTrustedMacros = false;

deletePrintComposers();
removeAnnotationItems();
// clear out any stuff from project
mMapCanvas->freeze( true );
removeAllLayers();
}


void QgisApp::changeEvent( QEvent* event )
{
Expand Down
15 changes: 14 additions & 1 deletion src/app/qgisapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class QgsGPSInformationWidget;
class QgsDecorationItem;

class QgsMessageLogViewer;
class QgsMessageBar;

class QgsScaleComboBox;

Expand Down Expand Up @@ -888,6 +889,12 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
void renderDecorationItems( QPainter *p );
void projectReadDecorationItems( );

//! clear out any stuff from project
void closeProject();

//! trust and load project macros
void enableProjectMacros();

signals:
/** emitted when a key is pressed and we want non widget sublasses to be able
to pick up on this (e.g. maplayer) */
Expand Down Expand Up @@ -972,7 +979,6 @@ class QgisApp : public QMainWindow, private Ui::MainWindow
/**Deletes all the composer objects and clears mPrintComposers*/
void deletePrintComposers();


void saveAsVectorFileGeneral( bool saveOnlySelection );

/**Returns all annotation items in the canvas*/
Expand Down Expand Up @@ -1228,6 +1234,13 @@ class QgisApp : public QMainWindow, private Ui::MainWindow

QString mOldScale;

//! the user has trusted the project macros
bool mTrustedMacros;

//! a bar to display warnings in a non-blocker manner
QgsMessageBar *mInfoBar;
QWidget *mMacrosWarn;

#ifdef HAVE_TOUCH
bool gestureEvent( QGestureEvent *event );
void tapAndHoldTriggered( QTapAndHoldGesture *gesture );
Expand Down
2 changes: 2 additions & 0 deletions src/app/qgsoptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :

chbAskToSaveProjectChanges->setChecked( settings.value( "qgis/askToSaveProjectChanges", QVariant( true ) ).toBool() );
chbWarnOldProjectVersion->setChecked( settings.value( "/qgis/warnOldProjectVersion", QVariant( true ) ).toBool() );
cmbEnableMacros->setCurrentIndex( settings.value( "/qgis/enableMacros", 1 ).toInt() );

// templates
cbxProjectDefaultNew->setChecked( settings.value( "/qgis/newProjectDefault", QVariant( false ) ).toBool() );
Expand Down Expand Up @@ -843,6 +844,7 @@ void QgsOptions::saveOptions()
settings.setValue( "/qgis/projectTemplateDir", leTemplateFolder->text() );
QgisApp::instance()->updateProjectFromTemplates();
}
settings.setValue( "/qgis/enableMacros", cmbEnableMacros->currentIndex() );

settings.setValue( "/qgis/nullValue", leNullValue->text() );
settings.setValue( "/qgis/style", cmbStyle->currentText() );
Expand Down
Loading