Skip to content
Permalink
Browse files

Make sure variable editor widgets always show current variables

On behalf of Faunalia, sponsored by ENEL

(cherry-picked from c7ffdfa)
  • Loading branch information
nyalldawson committed Jul 19, 2016
1 parent b6a967a commit e2a03df096782d390211f6dbd31e1614371ed09c
@@ -856,4 +856,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();
};
@@ -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();
};
@@ -345,6 +345,20 @@ class QgsProject : QObject

void snapSettingsChanged();

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

public slots:

/** 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
@@ -23,6 +23,7 @@
#include "qgspoint.h"
#include "qgsdatadefinedbutton.h"
#include "qgsexpressioncontext.h"
#include "qgsproject.h"
#include <QColorDialog>
#include <QPen>

@@ -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 )
@@ -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();
@@ -142,8 +142,7 @@ class QgsComposerItemWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
private slots:

void variablesChanged();


void updateVariables();
};

#endif //QGSCOMPOSERITEMWIDGET_H
@@ -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
@@ -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 )
{
@@ -221,6 +224,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 )
@@ -88,6 +88,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase

void resizeMarginsChanged();

void updateVariables();

private:
QgsComposition* mComposition;
QMap<QString, QgsCompositionPaper> mPaperMap;
@@ -1418,6 +1418,12 @@ void QgsOptions::saveOptions()
}

saveDefaultDatumTransformations();

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

void QgsOptions::rejectOptions()
@@ -1151,6 +1151,7 @@ void QgsProjectProperties::apply()

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

emit refresh();
}
@@ -1057,6 +1057,8 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu

updateBounds();

emit variablesChanged();

return true;
}

@@ -3287,6 +3289,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
@@ -1088,6 +1088,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)
};
@@ -1361,3 +1361,8 @@ void QgsApplication::setMaxThreads( int maxThreads )
QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
}

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

@@ -363,10 +363,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 );
@@ -417,6 +417,10 @@ void QgsProject::setDirty( bool b )
dirty( b );
}

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


void QgsProject::setFileName( QString const &name )
@@ -391,6 +391,20 @@ class CORE_EXPORT QgsProject : public QObject

void snapSettingsChanged();

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

public slots:

/** 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
@@ -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
@@ -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.
@@ -83,6 +83,7 @@ void TestQgsApplication::platformName()
QCOMPARE( QgsApplication::platform(), QString( "desktop" ) );
}


void TestQgsApplication::checkPaths()
{
QString myPath = QgsApplication::authorsFilePath();
@@ -51,6 +51,7 @@ class TestQgsComposition : public QObject
void resizeToContents();
void resizeToContentsMargin();
void resizeToContentsMultiPage();
void variablesEdited();

private:
QgsComposition *mComposition;
@@ -511,5 +512,19 @@ void TestQgsComposition::resizeToContentsMultiPage()
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"
@@ -31,6 +31,7 @@ class TestQgsProject : public QObject

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

void TestQgsProject::init()
@@ -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 e2a03df

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