Skip to content

Commit

Permalink
Make sure variable editor widgets always show current variables
Browse files Browse the repository at this point in the history
On behalf of Faunalia, sponsored by ENEL

(cherry-picked from c7ffdfa)
  • Loading branch information
nyalldawson committed Jul 19, 2016
1 parent 8f2eb81 commit 56fda9e
Show file tree
Hide file tree
Showing 19 changed files with 161 additions and 19 deletions.
5 changes: 5 additions & 0 deletions python/core/composer/qgscomposition.sip
Expand Up @@ -900,4 +900,9 @@ class QgsComposition : QGraphicsScene

/** Is emitted when the composition has an updated status bar message for the composer window*/
void statusMsgChanged( QString message );

/** Emitted whenever the expression variables stored in the composition have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();
};
16 changes: 16 additions & 0 deletions python/core/qgsapplication.sip
Expand Up @@ -379,7 +379,23 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
bool x11EventFilter ( XEvent * event );
%End

public slots:

/** Causes the application instance to emit the settingsChanged() signal. This should
* be called whenever global, application-wide settings are altered to advise listeners
* that they may need to update their state.
* @see settingsChanged()
* @note added in QGIS 3.0
*/
void emitSettingsChanged();

signals:
//! @note not available in python bindings
// void preNotify( QObject * receiver, QEvent * event, bool * done );

/** Emitted whenever any global, application-wide settings are changed.
* @note added in QGIS 3.0
* @see emitSettingsChanged()
*/
void settingsChanged();
};
12 changes: 12 additions & 0 deletions python/core/qgsproject.sip
Expand Up @@ -391,6 +391,11 @@ class QgsProject : QObject
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );

/** Emitted whenever the expression variables stored in the project have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();

public slots:

/**
Expand All @@ -402,6 +407,13 @@ class QgsProject : QObject
*/
void setDirty( bool b = true );

/** Causes the project to emit the variablesChanged() signal. This should
* be called whenever expression variables related to the project are changed.
* @see variablesChanged()
* @note added in QGIS 3.0
*/
void emitVariablesChanged();

private:

QgsProject(); // private 'cause it's a singleton
Expand Down
24 changes: 19 additions & 5 deletions src/app/composer/qgscomposeritemwidget.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgspoint.h"
#include "qgsdatadefinedbutton.h"
#include "qgsexpressioncontext.h"
#include "qgsproject.h"
#include <QColorDialog>
#include <QPen>

Expand Down Expand Up @@ -109,6 +110,14 @@ QgsVectorLayer* QgsComposerItemBaseWidget::atlasCoverageLayer() const

//QgsComposerItemWidget

void QgsComposerItemWidget::updateVariables()
{
QgsExpressionContext* context = mItem->createExpressionContext();
mVariableEditor->setContext( context );
mVariableEditor->setEditableScopeIndex( context->scopeCount() - 1 );
delete context;
}

QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem* item )
: QgsComposerItemBaseWidget( parent, item )
, mItem( item )
Expand Down Expand Up @@ -141,12 +150,17 @@ QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem*

connect( mTransparencySlider, SIGNAL( valueChanged( int ) ), mTransparencySpnBx, SLOT( setValue( int ) ) );

QgsExpressionContext* context = mItem->createExpressionContext();
mVariableEditor->setContext( context );
mVariableEditor->setEditableScopeIndex( context->scopeCount() - 1 );
delete context;

updateVariables();
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) );
// listen out for variable edits
QgsApplication* app = qobject_cast<QgsApplication*>( QgsApplication::instance() );
if ( app )
{
connect( app, SIGNAL( settingsChanged() ), this, SLOT( updateVariables() ) );
}
connect( QgsProject::instance(), SIGNAL( variablesChanged() ), this, SLOT( updateVariables() ) );
if ( mItem->composition() )
connect( mItem->composition(), SIGNAL( variablesChanged() ), this, SLOT( updateVariables() ) );

//connect atlas signals to data defined buttons
QgsAtlasComposition* atlas = atlasComposition();
Expand Down
3 changes: 1 addition & 2 deletions src/app/composer/qgscomposeritemwidget.h
Expand Up @@ -142,8 +142,7 @@ class QgsComposerItemWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
private slots:

void variablesChanged();


void updateVariables();
};

#endif //QGSCOMPOSERITEMWIDGET_H
25 changes: 19 additions & 6 deletions src/app/composer/qgscompositionwidget.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgssymbolv2selectordialog.h"
#include "qgssymbollayerv2utils.h"
#include "qgsexpressioncontext.h"
#include "qgsproject.h"
#include <QColorDialog>
#include <QWidget>
#include <QPrinter> //for screen resolution
Expand All @@ -45,13 +46,15 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c )
//read with/height from composition and find suitable entries to display
displayCompositionWidthHeight();

mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope() );
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::compositionScope( mComposition ) );
mVariableEditor->reloadContext();
mVariableEditor->setEditableScopeIndex( 2 );

updateVariables();
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) );
// listen out for variable edits
QgsApplication* app = qobject_cast<QgsApplication*>( QgsApplication::instance() );
if ( app )
{
connect( app, SIGNAL( settingsChanged() ), this, SLOT( updateVariables() ) );
}
connect( QgsProject::instance(), SIGNAL( variablesChanged() ), this, SLOT( updateVariables() ) );

if ( mComposition )
{
Expand Down Expand Up @@ -209,6 +212,16 @@ void QgsCompositionWidget::resizeMarginsChanged()
mLeftMarginSpinBox->value() );
}

void QgsCompositionWidget::updateVariables()
{
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope()
<< QgsExpressionContextUtils::compositionScope( mComposition );
mVariableEditor->setContext( &context );
mVariableEditor->setEditableScopeIndex( 2 );
}

void QgsCompositionWidget::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn, QgsComposerObject::DataDefinedProperty property )
{
if ( !mComposition )
Expand Down
2 changes: 2 additions & 0 deletions src/app/composer/qgscompositionwidget.h
Expand Up @@ -84,6 +84,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase

void resizeMarginsChanged();

void updateVariables();

private:
QgsComposition* mComposition;
QMap<QString, QgsCompositionPaper> mPaperMap;
Expand Down
6 changes: 6 additions & 0 deletions src/app/qgsoptions.cpp
Expand Up @@ -1480,6 +1480,12 @@ void QgsOptions::saveOptions()
}

saveDefaultDatumTransformations();

QgsApplication* app = qobject_cast<QgsApplication*>( QgsApplication::instance() );
if ( app )
{
app->emitSettingsChanged();
}
}

void QgsOptions::rejectOptions()
Expand Down
1 change: 1 addition & 0 deletions src/app/qgsprojectproperties.cpp
Expand Up @@ -1187,6 +1187,7 @@ void QgsProjectProperties::apply()

//save variables
QgsExpressionContextUtils::setProjectVariables( mVariableEditor->variablesInActiveScope() );
QgsProject::instance()->emitVariablesChanged();

emit refresh();
}
Expand Down
5 changes: 5 additions & 0 deletions src/core/composer/qgscomposition.cpp
Expand Up @@ -1068,6 +1068,8 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu

updateBounds();

emit variablesChanged();

return true;
}

Expand Down Expand Up @@ -3505,6 +3507,9 @@ void QgsComposition::setDataDefinedProperty( const QgsComposerObject::DataDefine
void QgsComposition::setCustomProperty( const QString& key, const QVariant& value )
{
mCustomProperties.setValue( key, value );

if ( key.startsWith( "variable" ) )
emit variablesChanged();
}

QVariant QgsComposition::customProperty( const QString& key, const QVariant& defaultValue ) const
Expand Down
5 changes: 5 additions & 0 deletions src/core/composer/qgscomposition.h
Expand Up @@ -1146,6 +1146,11 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
/** Is emitted when the composition has an updated status bar message for the composer window*/
void statusMsgChanged( const QString& message );

/** Emitted whenever the expression variables stored in the composition have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();

friend class QgsComposerObject; //for accessing dataDefinedEvaluate, readDataDefinedPropertyMap and writeDataDefinedPropertyMap
friend class QgsComposerModel; //for accessing updateZValues (should not be public)
friend class TestQgsComposition;
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -1371,3 +1371,8 @@ void QgsApplication::setMaxThreads( int maxThreads )
QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
}

void QgsApplication::emitSettingsChanged()
{
emit settingsChanged();
}

16 changes: 16 additions & 0 deletions src/core/qgsapplication.h
Expand Up @@ -364,10 +364,26 @@ class CORE_EXPORT QgsApplication : public QApplication
}
#endif

public slots:

/** Causes the application instance to emit the settingsChanged() signal. This should
* be called whenever global, application-wide settings are altered to advise listeners
* that they may need to update their state.
* @see settingsChanged()
* @note added in QGIS 3.0
*/
void emitSettingsChanged();

signals:
//! @note not available in python bindings
void preNotify( QObject * receiver, QEvent * event, bool * done );

/** Emitted whenever any global, application-wide settings are changed.
* @note added in QGIS 3.0
* @see emitSettingsChanged()
*/
void settingsChanged();

private:
static void copyPath( const QString& src, const QString& dst );
static QObject* ABISYM( mFileOpenEventReceiver );
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsproject.cpp
Expand Up @@ -412,6 +412,11 @@ void QgsProject::setDirty( bool b )
imp_->dirty = b;
}

void QgsProject::emitVariablesChanged()
{
emit variablesChanged();
}

void QgsProject::setFileName( const QString& name )
{
imp_->file.setFileName( name );
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsproject.h
Expand Up @@ -455,6 +455,11 @@ class CORE_EXPORT QgsProject : public QObject
//! Emitted when the list of layer which are excluded from map identification changes
void nonIdentifiableLayersChanged( QStringList nonIdentifiableLayers );

/** Emitted whenever the expression variables stored in the project have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();

public slots:

/**
Expand All @@ -466,6 +471,13 @@ class CORE_EXPORT QgsProject : public QObject
*/
void setDirty( bool b = true );

/** Causes the project to emit the variablesChanged() signal. This should
* be called whenever expression variables related to the project are changed.
* @see variablesChanged()
* @note added in QGIS 3.0
*/
void emitVariablesChanged();

private slots:
void onMapLayersAdded( const QList<QgsMapLayer*>& layers );
void cleanTransactionGroups( bool force = false );
Expand Down
14 changes: 8 additions & 6 deletions src/gui/qgsvariableeditorwidget.h
Expand Up @@ -65,12 +65,6 @@ class GUI_EXPORT QgsVariableEditorWidget : public QWidget
*/
QgsExpressionContext* context() const { return mContext.data(); }

/** Reloads all scopes from the editor's current context. This method should be called
* after adding or removing scopes from the attached context.
* @see context()
*/
void reloadContext();

/** Sets the editable scope for the widget. Only variables from the editable scope can
* be modified by users.
* @param scopeIndex index of current editable scope. Set to -1 to disable
Expand Down Expand Up @@ -107,6 +101,14 @@ class GUI_EXPORT QgsVariableEditorWidget : public QWidget
*/
QgsStringMap variablesInActiveScope() const;

public slots:

/** Reloads all scopes from the editor's current context. This method should be called
* after adding or removing scopes from the attached context.
* @see context()
*/
void reloadContext();

signals:

/** Emitted when the user has modified a scope using the widget.
Expand Down
1 change: 1 addition & 0 deletions tests/src/core/testqgsapplication.cpp
Expand Up @@ -83,6 +83,7 @@ void TestQgsApplication::platformName()
QCOMPARE( QgsApplication::platform(), QString( "desktop" ) );
}


void TestQgsApplication::checkPaths()
{
QString myPath = QgsApplication::authorsFilePath();
Expand Down
15 changes: 15 additions & 0 deletions tests/src/core/testqgscomposition.cpp
Expand Up @@ -53,6 +53,7 @@ class TestQgsComposition : public QObject
void resizeToContentsMargin();
void resizeToContentsMultiPage();
void georeference();
void variablesEdited();

private:
QgsComposition *mComposition;
Expand Down Expand Up @@ -583,5 +584,19 @@ void TestQgsComposition::georeference()
delete composition;
}

void TestQgsComposition::variablesEdited()
{
QgsMapSettings ms;
QgsComposition c( ms );
QSignalSpy spyVariablesChanged( &c, SIGNAL( variablesChanged() ) );

c.setCustomProperty( "not a variable", "1" );
QVERIFY( spyVariablesChanged.count() == 0 );
c.setCustomProperty( "variableNames", "1" );
QVERIFY( spyVariablesChanged.count() == 1 );
c.setCustomProperty( "variableValues", "1" );
QVERIFY( spyVariablesChanged.count() == 2 );
}

QTEST_MAIN( TestQgsComposition )
#include "testqgscomposition.moc"
8 changes: 8 additions & 0 deletions tests/src/core/testqgsproject.cpp
Expand Up @@ -31,6 +31,7 @@ class TestQgsProject : public QObject

void testReadPath();
void testProjectUnits();
void variablesChanged();
};

void TestQgsProject::init()
Expand Down Expand Up @@ -124,6 +125,13 @@ void TestQgsProject::testProjectUnits()
QCOMPARE( prj->areaUnits(), QgsUnitTypes::Acres );
}

void TestQgsProject::variablesChanged()
{
QSignalSpy spyVariablesChanged( QgsProject::instance(), SIGNAL( variablesChanged() ) );
QgsProject::instance()->emitVariablesChanged();
QVERIFY( spyVariablesChanged.count() == 1 );
}


QTEST_MAIN( TestQgsProject )
#include "testqgsproject.moc"

0 comments on commit 56fda9e

Please sign in to comment.