1
0
mirror of https://github.com/qgis/QGIS.git synced 2025-04-29 00:03:59 -04:00

Make sure variable editor widgets always show current variables

On behalf of Faunalia, sponsored by ENEL
This commit is contained in:
Nyall Dawson 2016-07-19 11:59:44 +10:00
parent 9e5357c0fc
commit c7ffdfa5e9
19 changed files with 161 additions and 19 deletions

@ -900,4 +900,9 @@ class QgsComposition : QGraphicsScene
/** Is emitted when the composition has an updated status bar message for the composer window*/ /** Is emitted when the composition has an updated status bar message for the composer window*/
void statusMsgChanged( QString message ); 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 ); bool x11EventFilter ( XEvent * event );
%End %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: signals:
//! @note not available in python bindings //! @note not available in python bindings
// void preNotify( QObject * receiver, QEvent * event, bool * done ); // 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();
}; };

@ -397,6 +397,11 @@ class QgsProject : QObject
//! Emitted when the home path of the project changes //! Emitted when the home path of the project changes
void homePathChanged(); void homePathChanged();
/** Emitted whenever the expression variables stored in the project have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();
public slots: public slots:
/** /**
@ -408,6 +413,13 @@ class QgsProject : QObject
*/ */
void setDirty( bool b = true ); 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: private:
QgsProject(); // private 'cause it's a singleton QgsProject(); // private 'cause it's a singleton

@ -23,6 +23,7 @@
#include "qgspoint.h" #include "qgspoint.h"
#include "qgsdatadefinedbutton.h" #include "qgsdatadefinedbutton.h"
#include "qgsexpressioncontext.h" #include "qgsexpressioncontext.h"
#include "qgsproject.h"
#include <QColorDialog> #include <QColorDialog>
#include <QPen> #include <QPen>
@ -109,6 +110,14 @@ QgsVectorLayer* QgsComposerItemBaseWidget::atlasCoverageLayer() const
//QgsComposerItemWidget //QgsComposerItemWidget
void QgsComposerItemWidget::updateVariables()
{
QgsExpressionContext* context = mItem->createExpressionContext();
mVariableEditor->setContext( context );
mVariableEditor->setEditableScopeIndex( context->scopeCount() - 1 );
delete context;
}
QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem* item ) QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem* item )
: QgsComposerItemBaseWidget( parent, item ) : QgsComposerItemBaseWidget( parent, item )
, mItem( item ) , mItem( item )
@ -141,12 +150,17 @@ QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem*
connect( mTransparencySlider, SIGNAL( valueChanged( int ) ), mTransparencySpnBx, SLOT( setValue( int ) ) ); connect( mTransparencySlider, SIGNAL( valueChanged( int ) ), mTransparencySpnBx, SLOT( setValue( int ) ) );
QgsExpressionContext* context = mItem->createExpressionContext(); updateVariables();
mVariableEditor->setContext( context );
mVariableEditor->setEditableScopeIndex( context->scopeCount() - 1 );
delete context;
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) ); 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 //connect atlas signals to data defined buttons
QgsAtlasComposition* atlas = atlasComposition(); QgsAtlasComposition* atlas = atlasComposition();

@ -142,8 +142,7 @@ class QgsComposerItemWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
private slots: private slots:
void variablesChanged(); void variablesChanged();
void updateVariables();
}; };
#endif //QGSCOMPOSERITEMWIDGET_H #endif //QGSCOMPOSERITEMWIDGET_H

@ -23,6 +23,7 @@
#include "qgssymbolv2selectordialog.h" #include "qgssymbolv2selectordialog.h"
#include "qgssymbollayerv2utils.h" #include "qgssymbollayerv2utils.h"
#include "qgsexpressioncontext.h" #include "qgsexpressioncontext.h"
#include "qgsproject.h"
#include <QColorDialog> #include <QColorDialog>
#include <QWidget> #include <QWidget>
#include <QPrinter> //for screen resolution #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 //read with/height from composition and find suitable entries to display
displayCompositionWidthHeight(); displayCompositionWidthHeight();
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() ); updateVariables();
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope() );
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::compositionScope( mComposition ) );
mVariableEditor->reloadContext();
mVariableEditor->setEditableScopeIndex( 2 );
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) ); 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 ) if ( mComposition )
{ {
@ -209,6 +212,16 @@ void QgsCompositionWidget::resizeMarginsChanged()
mLeftMarginSpinBox->value() ); 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 ) void QgsCompositionWidget::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn, QgsComposerObject::DataDefinedProperty property )
{ {
if ( !mComposition ) if ( !mComposition )

@ -83,6 +83,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
void resizeMarginsChanged(); void resizeMarginsChanged();
void updateVariables();
private: private:
QgsComposition* mComposition; QgsComposition* mComposition;
QMap<QString, QgsCompositionPaper> mPaperMap; QMap<QString, QgsCompositionPaper> mPaperMap;

@ -1481,6 +1481,12 @@ void QgsOptions::saveOptions()
} }
saveDefaultDatumTransformations(); saveDefaultDatumTransformations();
QgsApplication* app = qobject_cast<QgsApplication*>( QgsApplication::instance() );
if ( app )
{
app->emitSettingsChanged();
}
} }
void QgsOptions::rejectOptions() void QgsOptions::rejectOptions()

@ -1187,6 +1187,7 @@ void QgsProjectProperties::apply()
//save variables //save variables
QgsExpressionContextUtils::setProjectVariables( mVariableEditor->variablesInActiveScope() ); QgsExpressionContextUtils::setProjectVariables( mVariableEditor->variablesInActiveScope() );
QgsProject::instance()->emitVariablesChanged();
emit refresh(); emit refresh();
} }

@ -1069,6 +1069,8 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
updateBounds(); updateBounds();
emit variablesChanged();
return true; return true;
} }
@ -3506,6 +3508,9 @@ void QgsComposition::setDataDefinedProperty( const QgsComposerObject::DataDefine
void QgsComposition::setCustomProperty( const QString& key, const QVariant& value ) void QgsComposition::setCustomProperty( const QString& key, const QVariant& value )
{ {
mCustomProperties.setValue( key, value ); mCustomProperties.setValue( key, value );
if ( key.startsWith( "variable" ) )
emit variablesChanged();
} }
QVariant QgsComposition::customProperty( const QString& key, const QVariant& defaultValue ) const QVariant QgsComposition::customProperty( const QString& key, const QVariant& defaultValue ) const

@ -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*/ /** Is emitted when the composition has an updated status bar message for the composer window*/
void statusMsgChanged( const QString& message ); 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 QgsComposerObject; //for accessing dataDefinedEvaluate, readDataDefinedPropertyMap and writeDataDefinedPropertyMap
friend class QgsComposerModel; //for accessing updateZValues (should not be public) friend class QgsComposerModel; //for accessing updateZValues (should not be public)
friend class TestQgsComposition; friend class TestQgsComposition;

@ -1371,3 +1371,8 @@ void QgsApplication::setMaxThreads( int maxThreads )
QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) ); QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
} }
void QgsApplication::emitSettingsChanged()
{
emit settingsChanged();
}

@ -364,10 +364,26 @@ class CORE_EXPORT QgsApplication : public QApplication
} }
#endif #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: signals:
//! @note not available in python bindings //! @note not available in python bindings
void preNotify( QObject * receiver, QEvent * event, bool * done ); 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: private:
static void copyPath( const QString& src, const QString& dst ); static void copyPath( const QString& src, const QString& dst );
static QObject* ABISYM( mFileOpenEventReceiver ); static QObject* ABISYM( mFileOpenEventReceiver );

@ -412,6 +412,11 @@ void QgsProject::setDirty( bool b )
imp_->dirty = b; imp_->dirty = b;
} }
void QgsProject::emitVariablesChanged()
{
emit variablesChanged();
}
void QgsProject::setFileName( const QString& name ) void QgsProject::setFileName( const QString& name )
{ {
if ( name == imp_->file.fileName() ) if ( name == imp_->file.fileName() )

@ -462,6 +462,11 @@ class CORE_EXPORT QgsProject : public QObject
//! Emitted when the home path of the project changes //! Emitted when the home path of the project changes
void homePathChanged(); void homePathChanged();
/** Emitted whenever the expression variables stored in the project have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();
public slots: public slots:
/** /**
@ -473,6 +478,13 @@ class CORE_EXPORT QgsProject : public QObject
*/ */
void setDirty( bool b = true ); 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: private slots:
void onMapLayersAdded( const QList<QgsMapLayer*>& layers ); void onMapLayersAdded( const QList<QgsMapLayer*>& layers );
void cleanTransactionGroups( bool force = false ); void cleanTransactionGroups( bool force = false );

@ -65,12 +65,6 @@ class GUI_EXPORT QgsVariableEditorWidget : public QWidget
*/ */
QgsExpressionContext* context() const { return mContext.data(); } 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 /** Sets the editable scope for the widget. Only variables from the editable scope can
* be modified by users. * be modified by users.
* @param scopeIndex index of current editable scope. Set to -1 to disable * @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; 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: signals:
/** Emitted when the user has modified a scope using the widget. /** Emitted when the user has modified a scope using the widget.

@ -83,6 +83,7 @@ void TestQgsApplication::platformName()
QCOMPARE( QgsApplication::platform(), QString( "desktop" ) ); QCOMPARE( QgsApplication::platform(), QString( "desktop" ) );
} }
void TestQgsApplication::checkPaths() void TestQgsApplication::checkPaths()
{ {
QString myPath = QgsApplication::authorsFilePath(); QString myPath = QgsApplication::authorsFilePath();

@ -53,6 +53,7 @@ class TestQgsComposition : public QObject
void resizeToContentsMargin(); void resizeToContentsMargin();
void resizeToContentsMultiPage(); void resizeToContentsMultiPage();
void georeference(); void georeference();
void variablesEdited();
private: private:
QgsComposition *mComposition; QgsComposition *mComposition;
@ -583,5 +584,19 @@ void TestQgsComposition::georeference()
delete composition; 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 ) QTEST_MAIN( TestQgsComposition )
#include "testqgscomposition.moc" #include "testqgscomposition.moc"

@ -31,6 +31,7 @@ class TestQgsProject : public QObject
void testReadPath(); void testReadPath();
void testProjectUnits(); void testProjectUnits();
void variablesChanged();
}; };
void TestQgsProject::init() void TestQgsProject::init()
@ -124,6 +125,13 @@ void TestQgsProject::testProjectUnits()
QCOMPARE( prj->areaUnits(), QgsUnitTypes::Acres ); QCOMPARE( prj->areaUnits(), QgsUnitTypes::Acres );
} }
void TestQgsProject::variablesChanged()
{
QSignalSpy spyVariablesChanged( QgsProject::instance(), SIGNAL( variablesChanged() ) );
QgsProject::instance()->emitVariablesChanged();
QVERIFY( spyVariablesChanged.count() == 1 );
}
QTEST_MAIN( TestQgsProject ) QTEST_MAIN( TestQgsProject )
#include "testqgsproject.moc" #include "testqgsproject.moc"