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

View File

@ -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();
};

View File

@ -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();
};

View File

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

View File

@ -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();

View File

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

View File

@ -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 )
{
@ -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 )

View File

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

View File

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

View File

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

View File

@ -1069,6 +1069,8 @@ bool QgsComposition::readXML( const QDomElement& compositionElem, const QDomDocu
updateBounds();
emit variablesChanged();
return true;
}
@ -3506,6 +3508,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

View File

@ -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;

View File

@ -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();
}

View File

@ -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 );

View File

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

View File

@ -462,6 +462,11 @@ class CORE_EXPORT QgsProject : public QObject
//! Emitted when the home path of the project changes
void homePathChanged();
/** Emitted whenever the expression variables stored in the project have been changed.
* @note added in QGIS 3.0
*/
void variablesChanged();
public slots:
/**
@ -473,6 +478,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 );

View File

@ -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.

View File

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

View File

@ -53,6 +53,7 @@ class TestQgsComposition : public QObject
void resizeToContentsMargin();
void resizeToContentsMultiPage();
void georeference();
void variablesEdited();
private:
QgsComposition *mComposition;
@ -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"

View File

@ -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"