attachment widget: data defined button for document type

This commit is contained in:
Denis Rouzaud 2017-05-10 16:09:20 +02:00
parent 87052a7712
commit 922b162b86
16 changed files with 733 additions and 125 deletions

View File

@ -56,7 +56,6 @@ core/qgsprojectbadlayerhandler.sip
core/qgsprojectproperty.sip
core/qgssnappingconfig.sip
core/qgsprojectversion.sip
core/qgsproperty.sip
core/qgspropertycollection.sip
core/qgspythonrunner.sip
core/qgsrange.sip
@ -339,7 +338,6 @@ gui/qgsprojectionselectiondialog.sip
gui/qgsprojectionselectiontreewidget.sip
gui/qgsprojectionselectionwidget.sip
gui/qgspropertyassistantwidget.sip
gui/qgspropertyoverridebutton.sip
gui/qgsquerybuilder.sip
gui/qgsrasterformatsaveoptionswidget.sip
gui/qgsrasterlayersaveasdialog.sip

View File

@ -40,18 +40,8 @@ Return correct graphics item type.
{
Fixed,
/**
* A
* the
* \see
* \note
*/
Predefined,
/** The
* A
* \note
*/
Auto
};

View File

@ -1,7 +1,28 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsproperty.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsPropertyDefinition
{
%Docstring
Definition for a property.
QgsPropertyDefinition defines the type of values allowed for a property, and
handles descriptive names and help text for using the property. Definitions
can use one of the predefined standard templates to simplify definition of
commonly used property types, such as colors and blend modes.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include <qgsproperty.h>
#include "qgsproperty.h"
%End
public:
@ -38,107 +59,383 @@ class QgsPropertyDefinition
enum DataType
{
DataTypeString,
DataTypeNumeric,
DataTypeBoolean,
};
QgsPropertyDefinition();
%Docstring
Constructs an empty property.
%End
QgsPropertyDefinition( const QString &name, const QString &description, StandardPropertyTemplate type );
%Docstring
Constructor for QgsPropertyDefinition, using a standard property template.
\param name is used internally and should be a unique, alphanumeric string.
\param description can be any localised string describing what the property is used for.
\param type one of the predefined standard property template
%End
QgsPropertyDefinition( const QString &name, DataType dataTypes, const QString &description, const QString &helpText );
QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText );
%Docstring
Constructor for custom QgsPropertyDefinitions.
\param name is used internally and should be a unique, alphanumeric string.
\param dataType the data type for the property
\param description can be any localised string describing what the property is used for.
\param helpText parameter should specify a descriptive string for users outlining the types
of value acceptable by the property (eg 'dashed' or 'solid' for a line style property).
%End
QString name() const;
%Docstring
Returns the name of the property. This is used internally and should be a unique, alphanumeric string.
:rtype: str
%End
QString description() const;
%Docstring
Descriptive name of the property.
:rtype: str
%End
QString helpText() const;
%Docstring
Helper text for using the property, including a description of the valid values for the property.
:rtype: str
%End
DataType dataType() const;
%Docstring
Returns the allowable field/value data type for the property.
:rtype: DataType
%End
StandardPropertyTemplate standardTemplate() const;
%Docstring
Returns the property's standard template, if applicable. Non standard
types will return the Custom template.
:rtype: StandardPropertyTemplate
%End
bool supportsAssistant() const;
%Docstring
Returns true if the property is of a type which is compatible with property
override assistants.
:rtype: bool
%End
};
class QgsProperty
{
%TypeHeaderCode
#include <qgsproperty.h>
%Docstring
A store for object properties.
QgsProperty objects are used for storing properties for objects, which can then be transformed to
a QVariant value by evaluating them against a supplied QgsExpressionContext. Multiple QgsProperty objects
can be grouped using a QgsPropertyCollection for easier bulk storage, retrieval and evaluation.
QgsProperty objects are implicitly shared and can be inexpensively copied.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsproperty.h"
%End
public:
//! Property types
enum Type
{
InvalidProperty, //! Invalid (not set) property
StaticProperty, //!< Static property (QgsStaticProperty)
FieldBasedProperty, //!< Field based property (QgsFieldBasedProperty)
ExpressionBasedProperty, //!< Expression based property (QgsExpressionBasedProperty)
InvalidProperty,
StaticProperty,
FieldBasedProperty,
ExpressionBasedProperty,
};
QgsProperty();
%Docstring
Constructor for a QgsAbstractProperty. The property will be set to an InvalidProperty type.
%End
virtual ~QgsProperty();
static QgsProperty fromExpression( const QString &expression, bool isActive = true );
%Docstring
Returns a new ExpressionBasedProperty created from the specified expression.
:rtype: QgsProperty
%End
static QgsProperty fromField( const QString &fieldName, bool isActive = true );
%Docstring
Returns a new FieldBasedProperty created from the specified field name.
:rtype: QgsProperty
%End
static QgsProperty fromValue( const QVariant &value, bool isActive = true );
%Docstring
Returns a new StaticProperty created from the specified value.
:rtype: QgsProperty
%End
QgsProperty( const QgsProperty &other );
%Docstring
Copy constructor
%End
operator bool() const;
%Docstring
Returns true if the property is not an invalid type.
%End
bool operator==( const QgsProperty &other ) const;
%Docstring
:rtype: bool
%End
bool operator!=( const QgsProperty &other ) const;
%Docstring
:rtype: bool
%End
Type propertyType() const;
%Docstring
Returns the property type.
:rtype: Type
%End
bool isActive() const;
%Docstring
Returns whether the property is currently active.
.. seealso:: setActive()
:rtype: bool
%End
void setActive( bool active );
%Docstring
Sets whether the property is currently active.
.. seealso:: isActive()
%End
void setStaticValue( const QVariant &value );
%Docstring
Sets the static value for the property. Calling this will
transform the property into an StaticProperty.
.. seealso:: staticValue()
%End
QVariant staticValue() const;
%Docstring
Returns the current static value for the property. If the property
is not a StaticProperty this will return an invalid variant.
.. seealso:: setStaticValue()
:rtype: QVariant
%End
void setField( const QString &field );
%Docstring
Sets the field name the property references. Calling this will
transform the property into an FieldBasedProperty.
.. seealso:: field()
%End
QString field() const;
%Docstring
Returns the current field name the property references. If the property
is not a FieldBasedProperty this will return an empty string.
.. seealso:: setField()
:rtype: str
%End
void setExpressionString( const QString &expression );
%Docstring
Sets the expression to use for the property value. Calling this will
transform the property into an ExpressionBasedProperty.
.. seealso:: expressionString()
%End
QString expressionString() const;
%Docstring
Returns the expression used for the property value. If the property
is not a ExpressionBasedProperty this will return an empty string.
.. seealso:: setExpressionString()
:rtype: str
%End
virtual QString asExpression() const;
QString asExpression() const;
%Docstring
Returns an expression string representing the state of the property, or an empty
string if the property could not be converted to an expression
:rtype: str
%End
virtual bool prepare( const QgsExpressionContext &context = QgsExpressionContext() ) const;
bool prepare( const QgsExpressionContext &context = QgsExpressionContext() ) const;
%Docstring
Prepares the property against a specified expression context. Calling prepare before evaluating the
property multiple times allows precalculation of expensive setup tasks such as parsing expressions.
Returns true if preparation was successful.
:rtype: bool
%End
virtual QSet< QString > referencedFields( const QgsExpressionContext &context = QgsExpressionContext() ) const;
QSet< QString > referencedFields( const QgsExpressionContext &context = QgsExpressionContext() ) const;
%Docstring
Returns the set of any fields referenced by the property for a specified
expression context.
:rtype: set of str
%End
QVariant value( const QgsExpressionContext &context, const QVariant &defaultValue = QVariant(), bool *ok /Out/ = 0 ) const;
QVariant value( const QgsExpressionContext &context, const QVariant &defaultValue = QVariant(), bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property, including any transforms which are set for the property
\param context QgsExpressionContext to evaluate the property for. The variables and functions contained
in the expression context can be used to alter the calculated value for the property, so that a property
is able to respond to the current environment, layers and features within QGIS.
\param defaultValue default value to return if the property is not active or cannot be calculated
\param ok if specified, will be set to true if conversion was successful
:return: calculated value for property
.. seealso:: valueAsString()
.. seealso:: valueAsColor()
.. seealso:: valueAsDouble()
.. seealso:: valueAsInt()
.. seealso:: valueAsBool()
:rtype: QVariant
%End
QString valueAsString( const QgsExpressionContext &context, const QString &defaultString = QString(), bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property and interprets it as a string.
\param context QgsExpressionContext to evaluate the property for.
\param defaultString default string to return if the property cannot be calculated as a string
\param ok if specified, will be set to true if conversion was successful
:return: value parsed to string
.. seealso:: value()
.. seealso:: valueAsColor()
.. seealso:: valueAsDouble()
.. seealso:: valueAsInt()
.. seealso:: valueAsBool()
:rtype: str
%End
QColor valueAsColor( const QgsExpressionContext &context, const QColor &defaultColor = QColor(), bool *ok /Out/ = 0 ) const;
QColor valueAsColor( const QgsExpressionContext &context, const QColor &defaultColor = QColor(), bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property and interprets it as a color.
\param context QgsExpressionContext to evaluate the property for.
\param defaultColor default color to return if the property cannot be calculated as a color
\param ok if specified, will be set to true if conversion was successful
:return: value parsed to color
.. seealso:: value()
.. seealso:: valueAsString()
.. seealso:: valueAsDouble()
.. seealso:: valueAsInt()
.. seealso:: valueAsBool()
:rtype: QColor
%End
double valueAsDouble( const QgsExpressionContext &context, double defaultValue = 0.0, bool *ok /Out/ = 0 ) const;
double valueAsDouble( const QgsExpressionContext &context, double defaultValue = 0.0, bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property and interprets it as a double.
\param context QgsExpressionContext to evaluate the property for.
\param defaultValue default double to return if the property cannot be calculated as a double
\param ok if specified, will be set to true if conversion was successful
:return: value parsed to double
.. seealso:: value()
.. seealso:: valueAsString()
.. seealso:: valueAsColor()
.. seealso:: valueAsInt()
.. seealso:: valueAsBool()
:rtype: float
%End
int valueAsInt( const QgsExpressionContext &context, int defaultValue = 0, bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property and interprets it as an integer.
\param context QgsExpressionContext to evaluate the property for.
\param defaultValue default integer to return if the property cannot be calculated as an integer
\param ok if specified, will be set to true if conversion was successful
:return: value parsed to integer
.. seealso:: value()
.. seealso:: valueAsString()
.. seealso:: valueAsColor()
.. seealso:: valueAsDouble()
.. seealso:: valueAsBool()
:rtype: int
%End
bool valueAsBool( const QgsExpressionContext &context, bool defaultValue = false, bool *ok /Out/ = 0 ) const;
%Docstring
Calculates the current value of the property and interprets it as an boolean.
\param context QgsExpressionContext to evaluate the property for.
\param defaultValue default boolean to return if the property cannot be calculated as an boolean
\param ok if specified, will be set to true if conversion was successful
:return: value parsed to boolean
.. seealso:: value()
.. seealso:: valueAsString()
.. seealso:: valueAsColor()
.. seealso:: valueAsDouble()
.. seealso:: valueAsInt()
:rtype: bool
%End
QVariant toVariant() const;
%Docstring
Saves this property to a QVariantMap, wrapped in a QVariant.
You can use QgsXmlUtils.writeVariant to save it to an XML document.
.. seealso:: loadVariant()
:rtype: QVariant
%End
bool loadVariant( const QVariant &property );
%Docstring
Loads this property from a QVariantMap, wrapped in a QVariant.
You can use QgsXmlUtils.readVariant to load it from an XML document.
.. seealso:: toVariant()
:rtype: bool
%End
void setTransformer( QgsPropertyTransformer *transformer /Transfer/ );
%Docstring
Sets an optional transformer to use for manipulating the calculated values for the property.
\param transformer transformer to install. Ownership is transferred to the property, and any
existing transformer will be deleted. Set to null to remove an existing transformer.
.. seealso:: transformer()
%End
const QgsPropertyTransformer *transformer() const;
%Docstring
Returns the existing transformer used for manipulating the calculated values for the property, if set.
.. seealso:: setTransformer()
:rtype: QgsPropertyTransformer
%End
bool convertToTransformer();
%Docstring
Attempts to convert an existing expression based property to a base expression with
corresponding transformer. Returns true if conversion was successful. Note that
calling this method requires multiple parsing of expressions, so it should only
be called in non-performance critical code.
:rtype: bool
%End
operator QVariant() const;
%Docstring
Allows direct construction of QVariants from properties.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsproperty.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -46,6 +46,7 @@ class QgsWidgetWrapper : QObject
enum Property
{
RootPath,
DocumentViewerContent
};
static const QgsPropertiesDefinition &propertyDefinitions();

View File

@ -1,58 +1,208 @@
class QgsPropertyOverrideButton : QToolButton
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgspropertyoverridebutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsPropertyOverrideButton: QToolButton
{
%Docstring
A button for controlling property overrides which may apply to a widget.
QgsPropertyOverrideButton is designed to be used alongside the QGIS
properties framework (QgsProperty, QgsPropertyDefinition
and QgsPropertyCollection).
It allows users to specify field or expression based overrides
which should be applied to a property of an object. Eg, this widget
is used for controlling data defined overrides in symbology, labeling
and composer.
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include <qgspropertyoverridebutton.h>
#include "qgspropertyoverridebutton.h"
%End
public:
QgsPropertyOverrideButton( QWidget* parent /TransferThis/ = 0,
const QgsVectorLayer *layer = 0 );
QgsPropertyOverrideButton( QWidget *parent /TransferThis/ = 0,
const QgsVectorLayer *layer = 0 );
%Docstring
Constructor for QgsPropertyOverrideButton.
\param parent parent widget
\param layer associated vector layer
%End
void init( int propertyKey,
const QgsProperty& property,
const QgsPropertiesDefinition& definitions,
const QgsProperty &property,
const QgsPropertiesDefinition &definitions,
const QgsVectorLayer *layer = 0 );
%Docstring
Initialize a newly constructed property button (useful if button was included in a UI layout).
\param propertyKey key for corresponding property
\param property initial value of associated property to show in widget
\param definitions properties definitions for corresponding collection
\param layer associated vector layer
%End
void init( int propertyKey,
const QgsAbstractPropertyCollection& collection,
const QgsPropertiesDefinition& definitions,
const QgsAbstractPropertyCollection &collection,
const QgsPropertiesDefinition &definitions,
const QgsVectorLayer *layer = 0 );
%Docstring
Initialize a newly constructed property button (useful if button was included in a UI layout).
\param propertyKey key for corresponding property
\param collection associated property collection
\param definitions properties definitions for collection
\param layer associated vector layer
%End
QgsProperty toProperty() const;
%Docstring
Returns a QgsProperty object encapsulating the current state of the
widget.
.. seealso:: setToProperty()
:rtype: QgsProperty
%End
void setToProperty( const QgsProperty &property );
%Docstring
Sets the widget to reflect the current state of a QgsProperty.
%End
int propertyKey() const;
%Docstring
Returns the property key linked to the button.
:rtype: int
%End
bool isActive() const;
%Docstring
Returns true if the button has an active property.
:rtype: bool
%End
QgsPropertyDefinition::DataType validDataType() const;
%Docstring
Returns the data type which the widget will accept. This is used to filter
out fields from the associated vector layer to only show fields which
are compatible with the property.
:rtype: QgsPropertyDefinition.DataType
%End
QString fullDescription() const;
%Docstring
Returns the full definition description and current definition
(internally generated on a contextual basis).
:rtype: str
%End
QString usageInfo() const;
%Docstring
Returns usage information for the property.
.. seealso:: setUsageInfo()
:rtype: str
%End
void setUsageInfo( const QString &info );
%Docstring
Set the usage information for the property.
.. seealso:: usageInfo()
%End
void setVectorLayer( const QgsVectorLayer *layer );
%Docstring
Sets the vector layer associated with the button. This controls which fields are
displayed within the widget's pop up menu.
.. seealso:: vectorLayer()
%End
const QgsVectorLayer *vectorLayer() const;
%Docstring
Returns the vector layer associated with the button. This controls which fields are
displayed within the widget's pop up menu.
.. seealso:: setVectorLayer()
:rtype: QgsVectorLayer
%End
void registerCheckedWidget( QWidget *widget );
void registerCheckedWidget( QWidget *widget, bool natural = true );
%Docstring
Register a sibling ``widget`` that gets checked when the property is active.
if ``natural`` is false, widget gets unchecked when the property is active.
.. note::
this should be called after calling init() to be correctly initialized.
%End
void registerEnabledWidget( QWidget *widget, bool natural = true );
%Docstring
Register a sibling ``widget`` that gets enabled when the property is active, and disabled when the property is inactive.
if ``natural`` is false, widget gets disabled when the property is active, and enabled when the property is inactive.
.. note::
this should be called after calling init() to be correctly initialized.
%End
void registerVisibleWidget( QWidget *widget, bool natural = true );
%Docstring
Register a sibling ``widget`` that gets visible when the property is active, and hidden when the property is inactive.
if ``natural`` is false, widget gets hidden when the property is active, and visible when the property is inactive.
.. note::
this should be called after calling init() to be correctly initialized.
%End
void registerExpressionWidget( QWidget *widget );
%Docstring
Register a sibling ``widget`` (line edit, text edit) that will receive the property as an expression
.. note::
this should be called after calling init() to be correctly initialized.
%End
void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator );
%Docstring
Register an expression context generator class that will be used to retrieve
an expression context for the button when required.
%End
public slots:
void setActive( bool active );
%Docstring
Set whether the current property override definition is to be used
%End
signals:
void changed();
%Docstring
Emitted when property definition changes
%End
void activated( bool isActive );
%Docstring
Emitted when the activated status of the widget changes
%End
protected:
void mouseReleaseEvent( QMouseEvent *event );
virtual void mouseReleaseEvent( QMouseEvent *event );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgspropertyoverridebutton.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -177,6 +177,26 @@ sub fix_annotations(){
$line =~ s/SIP_FORCE//;
}
# detect a comment block, return 1 if found
sub detect_comment_block(){
if ($line =~ m/^\s*\/\*/){
do {no warnings 'uninitialized';
$comment = processDoxygenLine( $line =~ s/^\s*\/\*(\*)?(.*?)\n?$/$2/r );
};
$comment =~ s/^\s*$//;
#$comment =~ s/^(\s*\n)*(.+)/$2/;
while ($line !~ m/\*\/\s*(\/\/.*?)?$/){
$line = $lines[$line_idx];
$line_idx++;
$comment .= processDoxygenLine( $line =~ s/\s*\*?(.*?)(\/)?\n?$/$1/r );
}
$comment =~ s/\n+$//;
#push @output, dbg("XXX").$comment;
return 1;
}
return 0;
}
# main loop
while ($line_idx < $line_count){
@ -342,19 +362,7 @@ while ($line_idx < $line_count){
}
# Detect comment block
if ($line =~ m/^\s*\/\*/){
do {no warnings 'uninitialized';
$comment = processDoxygenLine( $line =~ s/^\s*\/\*(\*)?(.*?)\n?$/$2/r );
};
$comment =~ s/^\s*$//;
#$comment =~ s/^(\s*\n)*(.+)/$2/;
while ($line !~ m/\*\/\s*(\/\/.*?)?$/){
$line = $lines[$line_idx];
$line_idx++;
$comment .= processDoxygenLine( $line =~ s/\s*\*?(.*?)(\/)?\n?$/$1/r );
}
$comment =~ s/\n+$//;
#push @output, dbg("XXX").$comment;
if (detect_comment_block()){
next;
}
@ -499,6 +507,9 @@ while ($line_idx < $line_count){
while ($line_idx < $line_count){
$line = $lines[$line_idx];
$line_idx++;
if (detect_comment_block()){
next;
}
if ($line =~ m/\};/){
last;
}

View File

@ -175,10 +175,10 @@ QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, const QString
}
}
QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, DataType dataTypes, const QString &description, const QString &helpText )
QgsPropertyDefinition::QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText )
: mName( name )
, mDescription( description )
, mTypes( dataTypes )
, mTypes( dataType )
, mHelpText( helpText )
{}

View File

@ -112,19 +112,21 @@ class CORE_EXPORT QgsPropertyDefinition
/**
* Constructor for QgsPropertyDefinition, using a standard property template.
* The name is used internally and should be a unique, alphanumeric string.
* Description can be any localised string describing what the property is used for.
* \param name is used internally and should be a unique, alphanumeric string.
* \param description can be any localised string describing what the property is used for.
* \param type one of the predefined standard property template
*/
QgsPropertyDefinition( const QString &name, const QString &description, StandardPropertyTemplate type );
/**
* Constructor for custom QgsPropertyDefinitions.
* The name is used internally and should be a unique, alphanumeric string.
* Description can be any localised string describing what the property is used for.
* The helpText parameter should specify a descriptive string for users outlining the types
* \param name is used internally and should be a unique, alphanumeric string.
* \param dataType the data type for the property
* \param description can be any localised string describing what the property is used for.
* \param helpText parameter should specify a descriptive string for users outlining the types
* of value acceptable by the property (eg 'dashed' or 'solid' for a line style property).
*/
QgsPropertyDefinition( const QString &name, DataType dataTypes, const QString &description, const QString &helpText );
QgsPropertyDefinition( const QString &name, DataType dataType, const QString &description, const QString &helpText );
/**
* Returns the name of the property. This is used internally and should be a unique, alphanumeric string.

View File

@ -27,7 +27,8 @@ const QgsPropertiesDefinition &QgsWidgetWrapper::propertyDefinitions()
{
properties =
{
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QObject::tr( "string of variable length representing root path to attachment" ) ) }
{ RootPath, QgsPropertyDefinition( "propertyRootPath", QgsPropertyDefinition::DataTypeString, QObject::tr( "Root path" ), QObject::tr( "string of variable length representing root path to attachment" ) ) },
{ DocumentViewerContent, QgsPropertyDefinition( "documentViewerContent", QgsPropertyDefinition::DataTypeString, QObject::tr( "Document viewer content" ), QObject::tr( "string" ) + "<b>NoContent</b>|<b>Image</b>|<b>Web</b>" ) }
};
}
return properties;

View File

@ -69,6 +69,7 @@ class GUI_EXPORT QgsWidgetWrapper : public QObject
enum Property
{
RootPath = 0, //!< Root path for external resource
DocumentViewerContent //!< Document type for external resource
};
/**

View File

@ -43,7 +43,16 @@ QgsExternalResourceConfigDlg::QgsExternalResourceConfigDlg( QgsVectorLayer *vl,
connect( mRootPathButton, &QToolButton::clicked, this, &QgsExternalResourceConfigDlg::chooseDefaultPath );
initializeDataDefinedButton( mRootPathPropertyOverrideButton, QgsEditorWidgetWrapper::RootPath );
connect( mRootPathPropertyOverrideButton, &QgsPropertyOverrideButton::changed, this, &QgsExternalResourceConfigDlg::rootPathPropertyChanged );
mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPathExpression );
mRootPathPropertyOverrideButton->registerExpressionWidget( mRootPathExpression );
mRootPathPropertyOverrideButton->registerVisibleWidget( mRootPath, false );
mRootPathPropertyOverrideButton->registerEnabledWidget( mRootPathButton, false );
initializeDataDefinedButton( mDocumentViewerContentPropertyOverrideButton, QgsEditorWidgetWrapper::DocumentViewerContent );
mDocumentViewerContentPropertyOverrideButton->registerVisibleWidget( mDocumentViewerContentExpression );
mDocumentViewerContentPropertyOverrideButton->registerExpressionWidget( mDocumentViewerContentExpression );
mDocumentViewerContentPropertyOverrideButton->registerEnabledWidget( mDocumentViewerContentComboBox, false );
// Activate Relative Default Path option only if Default Path is set
connect( mRootPath, &QLineEdit::textChanged, this, &QgsExternalResourceConfigDlg::enableRelativeDefault );
@ -97,16 +106,6 @@ void QgsExternalResourceConfigDlg::chooseDefaultPath()
mRootPath->setText( rootName );
}
void QgsExternalResourceConfigDlg::rootPathPropertyChanged()
{
QgsProperty prop = mRootPathPropertyOverrideButton->toProperty();
setRootPathExpression( prop );
mRootPathExpression->setVisible( prop.isActive() );
mRootPath->setVisible( !prop.isActive() );
mRootPathButton->setEnabled( !prop.isActive() );
}
void QgsExternalResourceConfigDlg::enableRelativeDefault()
{
bool relativePathActive = false;
@ -197,11 +196,8 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
mPropertyCollection.loadVariant( config.value( QStringLiteral( "PropertyCollection" ) ), QgsWidgetWrapper::propertyDefinitions() );
updateDataDefinedButtons();
setRootPathExpression( mPropertyCollection.property( QgsWidgetWrapper::RootPath ) );
mRootPath->setText( config.value( QStringLiteral( "DefaultRoot" ) ).toString() );
rootPathPropertyChanged();
// relative storage
if ( config.contains( QStringLiteral( "RelativeStorage" ) ) )
{
@ -243,13 +239,3 @@ void QgsExternalResourceConfigDlg::setConfig( const QVariantMap &config )
}
}
}
void QgsExternalResourceConfigDlg::setRootPathExpression( const QgsProperty &property )
{
mRootPathExpression->setToolTip( property.asExpression() );
QgsExpressionContext ctx = layer()->createExpressionContext();
mRootPathExpression->setText( property.valueAsString( ctx ) );
enableRelativeDefault();
}

View File

@ -42,15 +42,8 @@ class GUI_EXPORT QgsExternalResourceConfigDlg : public QgsEditorConfigWidget, pr
//! Choose a base directory for rootPath
void chooseDefaultPath();
void rootPathPropertyChanged();
//! Modify RelativeDefault according to mRootPath content
void enableRelativeDefault();
private:
void setRootPathExpression( const QgsProperty &property );
};
#endif // QGSEXTERNALRESOURCECONFIGDLG_H

View File

@ -79,15 +79,40 @@ bool QgsExternalResourceWidgetWrapper::valid() const
void QgsExternalResourceWidgetWrapper::setFeature( const QgsFeature &feature )
{
if ( mQgsWidget && mPropertyCollection.isActive( QgsEditorWidgetWrapper::RootPath ) )
if ( mQgsWidget && mPropertyCollection.hasActiveProperties() )
{
QgsExpressionContext expressionContext( QgsExpressionContextUtils::globalProjectLayerScopes( layer() ) );
expressionContext.setFeature( feature );
bool ok = false;
QString path = mPropertyCollection.valueAsString( QgsEditorWidgetWrapper::RootPath, expressionContext, QString(), &ok );
if ( ok )
if ( mPropertyCollection.isActive( QgsEditorWidgetWrapper::RootPath ) )
{
mQgsWidget->setDefaultRoot( path );
QString path = mPropertyCollection.valueAsString( QgsEditorWidgetWrapper::RootPath, expressionContext, QString(), &ok );
if ( ok )
{
mQgsWidget->setDefaultRoot( path );
}
}
if ( mPropertyCollection.isActive( QgsEditorWidgetWrapper::DocumentViewerContent ) )
{
QString dvcString = mPropertyCollection.valueAsString( QgsEditorWidgetWrapper::DocumentViewerContent, expressionContext, "NoContent", &ok );
if ( ok )
{
QgsExternalResourceWidget::DocumentViewerContent dvc;
if ( dvcString.compare( QLatin1String( "image" ), Qt::CaseInsensitive ) == 0 )
{
dvc = QgsExternalResourceWidget::Image;
}
else if ( dvcString.compare( QLatin1String( "web" ), Qt::CaseInsensitive ) == 0 )
{
dvc = QgsExternalResourceWidget::Web;
}
else
{
dvc = QgsExternalResourceWidget::NoContent;
}
mQgsWidget->setDocumentViewerContent( dvc );
}
}
}

View File

@ -43,7 +43,7 @@ QgsPropertyOverrideButton::QgsPropertyOverrideButton( QWidget *parent,
setIconSize( QSize( 24, 24 ) );
setPopupMode( QToolButton::InstantPopup );
connect( this, &QgsPropertyOverrideButton::activated, this, &QgsPropertyOverrideButton::checkCheckedWidgets );
connect( this, &QgsPropertyOverrideButton::activated, this, &QgsPropertyOverrideButton::updateSiblingWidgets );
mDefineMenu = new QMenu( this );
connect( mDefineMenu, &QMenu::aboutToShow, this, &QgsPropertyOverrideButton::aboutToShowMenu );
@ -78,6 +78,7 @@ QgsPropertyOverrideButton::QgsPropertyOverrideButton( QWidget *parent,
mDefineMenu->addAction( mActionAssistant );
}
void QgsPropertyOverrideButton::init( int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer )
{
mVectorLayer = layer;
@ -191,16 +192,51 @@ void QgsPropertyOverrideButton::setVectorLayer( const QgsVectorLayer *layer )
mVectorLayer = layer;
}
void QgsPropertyOverrideButton::registerCheckedWidget( QWidget *widget )
void QgsPropertyOverrideButton::registerCheckedWidget( QWidget *widget, bool natural )
{
Q_FOREACH ( const QPointer<QWidget> &w, mCheckedWidgets )
Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
{
if ( widget == w.data() )
if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingCheckState )
return;
}
mCheckedWidgets.append( QPointer<QWidget>( widget ) );
mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingCheckState, natural ) );
updateSiblingWidgets( isActive() );
}
void QgsPropertyOverrideButton::registerEnabledWidget( QWidget *widget, bool natural )
{
Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
{
if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingEnableState )
return;
}
mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingEnableState, natural ) );
updateSiblingWidgets( isActive() );
}
void QgsPropertyOverrideButton::registerVisibleWidget( QWidget *widget, bool natural )
{
Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
{
if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingVisibility )
return;
}
mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingVisibility, natural ) );
updateSiblingWidgets( isActive() );
}
void QgsPropertyOverrideButton::registerExpressionWidget( QWidget *widget )
{
Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
{
if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingExpressionText )
return;
}
mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingExpressionText ) );
updateSiblingWidgets( isActive() );
}
void QgsPropertyOverrideButton::mouseReleaseEvent( QMouseEvent *event )
{
// Ctrl-click to toggle activated state
@ -246,6 +282,7 @@ void QgsPropertyOverrideButton::setToProperty( const QgsProperty &property )
}
mProperty = property;
setActive( mProperty && mProperty.isActive() );
updateSiblingWidgets( isActive() );
updateGui();
}
@ -434,6 +471,7 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
mProperty.setExpressionString( mExpressionString );
mProperty.setTransformer( nullptr );
setActivePrivate( true );
updateSiblingWidgets( isActive() );
updateGui();
emit changed();
}
@ -450,6 +488,7 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
mProperty.setExpressionString( mExpressionString );
mProperty.setTransformer( nullptr );
setActivePrivate( true );
updateSiblingWidgets( isActive() );
updateGui();
emit changed();
}
@ -460,6 +499,7 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
mProperty.setStaticValue( QVariant() );
mProperty.setTransformer( nullptr );
mExpressionString.clear();
updateSiblingWidgets( isActive() );
updateGui();
emit changed();
}
@ -478,6 +518,7 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
mProperty.setField( mFieldName );
mProperty.setTransformer( nullptr );
setActivePrivate( true );
updateSiblingWidgets( isActive() );
updateGui();
emit changed();
}
@ -491,6 +532,7 @@ void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
mProperty.setExpressionString( mExpressionString );
mProperty.setTransformer( nullptr );
setActivePrivate( true );
updateSiblingWidgets( isActive() );
updateGui();
emit changed();
}
@ -656,30 +698,80 @@ void QgsPropertyOverrideButton::setActivePrivate( bool active )
}
}
void QgsPropertyOverrideButton::checkCheckedWidgets( bool check )
void QgsPropertyOverrideButton::updateSiblingWidgets( bool state )
{
// don't uncheck, only set to checked
if ( !check )
{
return;
}
Q_FOREACH ( const QPointer< QWidget > &w, mCheckedWidgets )
Q_FOREACH ( const SiblingWidget &sw, mSiblingWidgets )
{
QAbstractButton *btn = qobject_cast< QAbstractButton * >( w.data() );
if ( btn && btn->isCheckable() )
switch ( sw.mSiblingType )
{
btn->setChecked( true );
continue;
}
QGroupBox *grpbx = qobject_cast< QGroupBox * >( w.data() );
if ( grpbx && grpbx->isCheckable() )
{
grpbx->setChecked( true );
case SiblingCheckState:
{
// don't uncheck, only set to checked
if ( state )
{
QAbstractButton *btn = qobject_cast< QAbstractButton * >( sw.mWidgetPointer.data() );
if ( btn && btn->isCheckable() )
{
btn->setChecked( sw.mNatural ? state : !state );
}
else
{
QGroupBox *grpbx = qobject_cast< QGroupBox * >( sw.mWidgetPointer.data() );
if ( grpbx && grpbx->isCheckable() )
{
grpbx->setChecked( sw.mNatural ? state : !state );
}
}
}
break;
}
case SiblingEnableState:
{
QLineEdit *le = qobject_cast< QLineEdit * >( sw.mWidgetPointer.data() );
if ( le )
le->setReadOnly( sw.mNatural ? !state : state );
else
sw.mWidgetPointer.data()->setEnabled( sw.mNatural ? state : !state );
break;
}
case SiblingVisibility:
{
sw.mWidgetPointer.data()->setVisible( sw.mNatural ? state : !state );
break;
}
case SiblingExpressionText:
{
QLineEdit *le = qobject_cast<QLineEdit *>( sw.mWidgetPointer.data() );
if ( le )
{
le->setText( mProperty.asExpression() );
}
else
{
QTextEdit *te = qobject_cast<QTextEdit *>( sw.mWidgetPointer.data() );
if ( te )
{
te->setText( mProperty.asExpression() );
}
}
break;
}
default:
break;
}
}
}
void QgsPropertyOverrideButton::setActive( bool active )
{
if ( mProperty.isActive() != active )

View File

@ -58,9 +58,10 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton
* \param parent parent widget
* \param layer associated vector layer
*/
QgsPropertyOverrideButton( QWidget *parent = nullptr,
QgsPropertyOverrideButton( QWidget *parent SIP_TRANSFERTHIS = nullptr,
const QgsVectorLayer *layer = nullptr );
/**
* Initialize a newly constructed property button (useful if button was included in a UI layout).
* \param propertyKey key for corresponding property
@ -105,7 +106,7 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton
/**
* Returns true if the button has an active property.
*/
bool isActive() const { return mProperty.isActive(); }
bool isActive() const { return mProperty && mProperty.isActive(); }
/**
* Returns the data type which the widget will accept. This is used to filter
@ -147,9 +148,31 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton
const QgsVectorLayer *vectorLayer() const { return mVectorLayer; }
/**
* Register a sibling widget that get checked when the property is active.
* Register a sibling \a widget that gets checked when the property is active.
* if \a natural is false, widget gets unchecked when the property is active.
* \note this should be called after calling init() to be correctly initialized.
*/
void registerCheckedWidget( QWidget *widget );
void registerCheckedWidget( QWidget *widget, bool natural = true );
/**
* Register a sibling \a widget that gets enabled when the property is active, and disabled when the property is inactive.
* if \a natural is false, widget gets disabled when the property is active, and enabled when the property is inactive.
* \note this should be called after calling init() to be correctly initialized.
*/
void registerEnabledWidget( QWidget *widget, bool natural = true );
/**
* Register a sibling \a widget that gets visible when the property is active, and hidden when the property is inactive.
* if \a natural is false, widget gets hidden when the property is active, and visible when the property is inactive.
* \note this should be called after calling init() to be correctly initialized.
*/
void registerVisibleWidget( QWidget *widget, bool natural = true );
/**
* Register a sibling \a widget (line edit, text edit) that will receive the property as an expression
* \note this should be called after calling init() to be correctly initialized.
*/
void registerExpressionWidget( QWidget *widget );
/**
* Register an expression context generator class that will be used to retrieve
@ -233,7 +256,25 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton
QgsExpressionContextGenerator *mExpressionContextGenerator = nullptr;
QList< QPointer<QWidget> > mCheckedWidgets;
enum SiblingType
{
SiblingCheckState,
SiblingEnableState,
SiblingVisibility,
SiblingExpressionText,
};
struct SiblingWidget
{
SiblingWidget( QPointer<QWidget> widgetPointer, SiblingType siblingType, bool natural = true )
: mWidgetPointer( widgetPointer )
, mSiblingType( siblingType )
, mNatural( natural )
{}
QPointer<QWidget> mWidgetPointer;
SiblingType mSiblingType;
bool mNatural;
};
QList< SiblingWidget > mSiblingWidgets;
//! Internal property used for storing state of widget
QgsProperty mProperty;
@ -244,7 +285,7 @@ class GUI_EXPORT QgsPropertyOverrideButton: public QToolButton
void aboutToShowMenu();
void menuActionTriggered( QAction *action );
void checkCheckedWidgets( bool checked );
void updateSiblingWidgets( bool state );
};

View File

@ -45,7 +45,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-17</y>
<y>0</y>
<width>467</width>
<height>715</height>
</rect>
@ -103,7 +103,10 @@
<item>
<widget class="QLineEdit" name="mRootPathExpression">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
@ -338,7 +341,7 @@
<item row="0" column="2">
<widget class="QComboBox" name="mDocumentViewerContentComboBox"/>
</item>
<item row="0" column="3">
<item row="0" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -351,7 +354,7 @@
</property>
</spacer>
</item>
<item row="1" column="1" colspan="3">
<item row="1" column="1" colspan="5">
<widget class="QWidget" name="mDocumentViewerContentSettingsWidget" native="true">
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
@ -435,6 +438,23 @@
</layout>
</widget>
</item>
<item row="0" column="4">
<widget class="QgsPropertyOverrideButton" name="mDocumentViewerContentPropertyOverrideButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="mDocumentViewerContentExpression">
<property name="enabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>