mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
[FEATURE] Search widget for relations using aggregates
For each child relations, the subform is visible. Each attribute of the children has a tool button option to define to which aggregate the specified value should be compared. This allows for searching things like * Each city where the highest building is more than 300 m * Each sensor where the median value is lower than 50 ppm * Each feature with a child with a missing value * ...
This commit is contained in:
parent
f5559b5143
commit
fdd00870ee
@ -26,6 +26,13 @@ class QgsAggregateCalculator
|
||||
%End
|
||||
public:
|
||||
|
||||
struct AggregateInfo
|
||||
{
|
||||
QString function;
|
||||
QString name;
|
||||
QSet<QVariant::Type> supportedTypes;
|
||||
};
|
||||
|
||||
enum Aggregate
|
||||
{
|
||||
Count,
|
||||
@ -138,6 +145,11 @@ class QgsAggregateCalculator
|
||||
:rtype: Aggregate
|
||||
%End
|
||||
|
||||
static QList< QgsAggregateCalculator::AggregateInfo > aggregates();
|
||||
%Docstring
|
||||
:rtype: list of QgsAggregateCalculator.AggregateInfo
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -169,6 +169,25 @@ class QgsSearchWidgetWrapper : QgsWidgetWrapper
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
QString createFieldIdentifier() const;
|
||||
%Docstring
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
|
||||
|
||||
QString aggregate() const;
|
||||
%Docstring
|
||||
:rtype: str
|
||||
%End
|
||||
void setAggregate( const QString &aggregate );
|
||||
|
||||
QgsRelation aggregateRelation() const;
|
||||
%Docstring
|
||||
:rtype: QgsRelation
|
||||
%End
|
||||
void setAggregateRelation( const QgsRelation &aggregateRelation );
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void clearWidget();
|
||||
|
@ -0,0 +1,53 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/editorwidgets/qgsrelationaggregatesearchwidgetwrapper.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsRelationAggregateSearchWidgetWrapper : QgsSearchWidgetWrapper
|
||||
{
|
||||
%Docstring
|
||||
*************************************************************************
|
||||
qgsrelationaggregatesearchwidget.h
|
||||
-----------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
**************************************************************************
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify *
|
||||
it under the terms of the GNU General Public License as published by *
|
||||
the Free Software Foundation; either version 2 of the License, or *
|
||||
(at your option) any later version. *
|
||||
*
|
||||
**************************************************************************
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsrelationaggregatesearchwidgetwrapper.h"
|
||||
%End
|
||||
public:
|
||||
explicit QgsRelationAggregateSearchWidgetWrapper( QgsVectorLayer *vl, QgsRelationWidgetWrapper *wrapper, QWidget *parent /TransferThis/ = 0 );
|
||||
|
||||
virtual QString expression() const;
|
||||
|
||||
virtual bool valid() const;
|
||||
virtual QWidget *createWidget( QWidget *parent );
|
||||
virtual bool applyDirectly();
|
||||
virtual void setExpression( const QString &value );
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/editorwidgets/qgsrelationaggregatesearchwidgetwrapper.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -71,6 +71,11 @@ class QgsRelationWidgetWrapper : QgsWidgetWrapper
|
||||
.. versionadded:: 2.18
|
||||
%End
|
||||
|
||||
QgsRelation relation() const;
|
||||
%Docstring
|
||||
:rtype: QgsRelation
|
||||
%End
|
||||
|
||||
protected:
|
||||
virtual QWidget *createWidget( QWidget *parent );
|
||||
|
||||
|
@ -52,9 +52,11 @@
|
||||
%Include qgisinterface.sip
|
||||
%Include qgsactionmenu.sip
|
||||
%Include qgsadvanceddigitizingdockwidget.sip
|
||||
%Include qgsaggregatetoolbutton.sip
|
||||
%Include qgsattributedialog.sip
|
||||
%Include qgsattributeform.sip
|
||||
%Include qgsattributeformeditorwidget.sip
|
||||
%Include qgsattributeformrelationeditorwidget.sip
|
||||
%Include qgsattributeformwidget.sip
|
||||
%Include qgsattributetypeloaddialog.sip
|
||||
%Include qgsblendmodecombobox.sip
|
||||
@ -279,6 +281,7 @@
|
||||
%Include editorwidgets/qgsrelationreferencewidget.sip
|
||||
%Include editorwidgets/qgsrelationreferencewidgetwrapper.sip
|
||||
%Include editorwidgets/qgsrelationwidgetwrapper.sip
|
||||
%Include editorwidgets/qgsrelationaggregatesearchwidgetwrapper.sip
|
||||
%Include editorwidgets/qgssearchwidgettoolbutton.sip
|
||||
%Include editorwidgets/qgsspinbox.sip
|
||||
%Include editorwidgets/qgsvaluemapsearchwidgetwrapper.sip
|
||||
|
68
python/gui/qgsaggregatetoolbutton.sip
Normal file
68
python/gui/qgsaggregatetoolbutton.sip
Normal file
@ -0,0 +1,68 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsaggregatetoolbutton.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAggregateToolButton : QToolButton
|
||||
{
|
||||
%Docstring
|
||||
*************************************************************************
|
||||
qgsaggregatetoolbutton.h
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
**************************************************************************
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify *
|
||||
it under the terms of the GNU General Public License as published by *
|
||||
the Free Software Foundation; either version 2 of the License, or *
|
||||
(at your option) any later version. *
|
||||
*
|
||||
**************************************************************************
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsaggregatetoolbutton.h"
|
||||
%End
|
||||
public:
|
||||
QgsAggregateToolButton();
|
||||
|
||||
void setType( QVariant::Type type );
|
||||
|
||||
QVariant::Type type() const;
|
||||
%Docstring
|
||||
:rtype: QVariant.Type
|
||||
%End
|
||||
|
||||
void setActive( bool active );
|
||||
bool active() const;
|
||||
%Docstring
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
QString aggregate() const;
|
||||
%Docstring
|
||||
:rtype: str
|
||||
%End
|
||||
void setAggregate( const QString &aggregate );
|
||||
|
||||
signals:
|
||||
void aggregateChanged();
|
||||
void activeChanged();
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsaggregatetoolbutton.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -25,6 +25,7 @@ class QgsAttributeForm : QWidget
|
||||
AddFeatureMode,
|
||||
MultiEditMode,
|
||||
SearchMode,
|
||||
AggregateSearchMode,
|
||||
};
|
||||
|
||||
enum FilterType
|
||||
@ -123,6 +124,11 @@ class QgsAttributeForm : QWidget
|
||||
.. versionadded:: 2.16
|
||||
%End
|
||||
|
||||
QString aggregateFilter() const;
|
||||
%Docstring
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void attributeChanged( const QString &attribute, const QVariant &value );
|
||||
|
@ -56,15 +56,6 @@ class QgsAttributeFormEditorWidget : QgsAttributeFormWidget
|
||||
:rtype: QVariant
|
||||
%End
|
||||
|
||||
virtual QString currentFilterExpression() const;
|
||||
|
||||
%Docstring
|
||||
Creates an expression matching the current search filter value and
|
||||
search properties represented in the widget.
|
||||
.. versionadded:: 2.16
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
void setConstraintStatus( const QString &constraint, const QString &description, const QString &err, QgsEditorWidgetWrapper::ConstraintResult result );
|
||||
%Docstring
|
||||
Set the constraint status for this widget.
|
||||
@ -88,11 +79,6 @@ class QgsAttributeFormEditorWidget : QgsAttributeFormWidget
|
||||
Called when field values have been committed;
|
||||
%End
|
||||
|
||||
void resetSearch();
|
||||
%Docstring
|
||||
Resets the search/filter value of the widget.
|
||||
%End
|
||||
|
||||
signals:
|
||||
|
||||
void valueChanged( const QVariant &value );
|
||||
@ -101,55 +87,6 @@ class QgsAttributeFormEditorWidget : QgsAttributeFormWidget
|
||||
\param value new widget value
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
QgsSearchWidgetToolButton *searchWidgetToolButton();
|
||||
%Docstring
|
||||
Returns a pointer to the search widget tool button in the widget.
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
:rtype: QgsSearchWidgetToolButton
|
||||
%End
|
||||
|
||||
void setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
%Docstring
|
||||
Sets the search widget wrapper for the widget used when the form is in
|
||||
search mode.
|
||||
\param wrapper search widget wrapper.
|
||||
.. note::
|
||||
|
||||
the search widget wrapper should be created using searchWidgetFrame()
|
||||
as its parent
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
%End
|
||||
|
||||
QWidget *searchWidgetFrame();
|
||||
%Docstring
|
||||
Returns the widget which should be used as a parent during construction
|
||||
of the search widget wrapper.
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable AP
|
||||
:rtype: QWidget
|
||||
%End
|
||||
|
||||
QList< QgsSearchWidgetWrapper * > searchWidgetWrappers();
|
||||
%Docstring
|
||||
Returns the search widget wrapper used in this widget. The wrapper must
|
||||
first be created using createSearchWidgetWrapper()
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
:rtype: list of QgsSearchWidgetWrapper
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
48
python/gui/qgsattributeformrelationeditorwidget.sip
Normal file
48
python/gui/qgsattributeformrelationeditorwidget.sip
Normal file
@ -0,0 +1,48 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsattributeformrelationeditorwidget.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsAttributeFormRelationEditorWidget : QgsAttributeFormWidget
|
||||
{
|
||||
%Docstring
|
||||
*************************************************************************
|
||||
qgsattributeformrelationeditorwidget.h
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
**************************************************************************
|
||||
*
|
||||
This program is free software; you can redistribute it and/or modify *
|
||||
it under the terms of the GNU General Public License as published by *
|
||||
the Free Software Foundation; either version 2 of the License, or *
|
||||
(at your option) any later version. *
|
||||
*
|
||||
**************************************************************************
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsattributeformrelationeditorwidget.h"
|
||||
%End
|
||||
public:
|
||||
explicit QgsAttributeFormRelationEditorWidget( QgsRelationWidgetWrapper *wrapper, QgsAttributeForm *form );
|
||||
|
||||
virtual void createSearchWidgetWrappers();
|
||||
virtual QString currentFilterExpression() const;
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/gui/qgsattributeformrelationeditorwidget.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -22,6 +22,7 @@ class QgsAttributeFormWidget : QWidget /Abstract/
|
||||
DefaultMode,
|
||||
MultiEditMode,
|
||||
SearchMode,
|
||||
AggregateSearchMode,
|
||||
};
|
||||
|
||||
explicit QgsAttributeFormWidget( QgsWidgetWrapper *widget, QgsAttributeForm *form );
|
||||
@ -34,7 +35,7 @@ class QgsAttributeFormWidget : QWidget /Abstract/
|
||||
\param context editor context (not available in Python bindings)
|
||||
%End
|
||||
|
||||
virtual QString currentFilterExpression() const = 0;
|
||||
virtual QString currentFilterExpression() const;
|
||||
%Docstring
|
||||
Creates an expression matching the current search filter value and
|
||||
search properties represented in the widget.
|
||||
@ -68,6 +69,55 @@ class QgsAttributeFormWidget : QWidget /Abstract/
|
||||
:rtype: QgsAttributeForm
|
||||
%End
|
||||
|
||||
|
||||
|
||||
void setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
%Docstring
|
||||
Sets the search widget wrapper for the widget used when the form is in
|
||||
search mode.
|
||||
\param wrapper search widget wrapper.
|
||||
.. note::
|
||||
|
||||
the search widget wrapper should be created using searchWidgetFrame()
|
||||
as its parent
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
%End
|
||||
|
||||
void addAdditionalSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
|
||||
QList< QgsSearchWidgetWrapper * > searchWidgetWrappers();
|
||||
%Docstring
|
||||
Returns the search widget wrapper used in this widget. The wrapper must
|
||||
first be created using createSearchWidgetWrapper()
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
:rtype: list of QgsSearchWidgetWrapper
|
||||
%End
|
||||
|
||||
void resetSearch();
|
||||
%Docstring
|
||||
Resets the search/filter value of the widget.
|
||||
%End
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
QgsSearchWidgetToolButton *searchWidgetToolButton();
|
||||
%Docstring
|
||||
Returns a pointer to the search widget tool button in the widget.
|
||||
.. note::
|
||||
|
||||
this method is in place for unit testing only, and is not considered
|
||||
stable API
|
||||
:rtype: QgsSearchWidgetToolButton
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -174,6 +174,232 @@ QgsAggregateCalculator::Aggregate QgsAggregateCalculator::stringToAggregate( con
|
||||
return Count;
|
||||
}
|
||||
|
||||
QList<QgsAggregateCalculator::AggregateInfo> QgsAggregateCalculator::aggregates()
|
||||
{
|
||||
QList< AggregateInfo > aggregates;
|
||||
aggregates
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "count" ),
|
||||
QCoreApplication::tr( "Count" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Date
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "count_distinct" ),
|
||||
QCoreApplication::tr( "Count Distinct" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Date
|
||||
<< QVariant::UInt
|
||||
<< QVariant::Int
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "count_missing" ),
|
||||
QCoreApplication::tr( "Count Missing" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Date
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "min" ),
|
||||
QCoreApplication::tr( "Min" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Date
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "max" ),
|
||||
QCoreApplication::tr( "Max" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Date
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "sum" ),
|
||||
QCoreApplication::tr( "Sum" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "mean" ),
|
||||
QCoreApplication::tr( "Mean" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "median" ),
|
||||
QCoreApplication::tr( "Median" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "stdev" ),
|
||||
QCoreApplication::tr( "Stdev" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "stdevsample" ),
|
||||
QCoreApplication::tr( "Stdev Sample" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "range" ),
|
||||
QCoreApplication::tr( "Range" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Date
|
||||
<< QVariant::DateTime
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "minority" ),
|
||||
QCoreApplication::tr( "Minority" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "majority" ),
|
||||
QCoreApplication::tr( "Majority" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "q1" ),
|
||||
QCoreApplication::tr( "Q1" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "q3" ),
|
||||
QCoreApplication::tr( "Q3" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "iqr" ),
|
||||
QCoreApplication::tr( "InterQuartileRange" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::Int
|
||||
<< QVariant::UInt
|
||||
<< QVariant::LongLong
|
||||
<< QVariant::ULongLong
|
||||
<< QVariant::Double
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "min_length" ),
|
||||
QCoreApplication::tr( "Min Length" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "max_length" ),
|
||||
QCoreApplication::tr( "Max Length" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "concatenate" ),
|
||||
QCoreApplication::tr( "Concatenate" ),
|
||||
QSet<QVariant::Type>()
|
||||
<< QVariant::String
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "collect" ),
|
||||
QCoreApplication::tr( "Collect" ),
|
||||
QSet<QVariant::Type>()
|
||||
}
|
||||
<< AggregateInfo
|
||||
{
|
||||
QStringLiteral( "array_agg" ),
|
||||
QCoreApplication::tr( "Array Aggregate" ),
|
||||
QSet<QVariant::Type>()
|
||||
};
|
||||
|
||||
return aggregates;
|
||||
}
|
||||
|
||||
QVariant QgsAggregateCalculator::calculate( QgsAggregateCalculator::Aggregate aggregate, QgsFeatureIterator &fit, QVariant::Type resultType,
|
||||
int attr, QgsExpression *expression, const QString &delimiter, QgsExpressionContext *context, bool *ok )
|
||||
{
|
||||
|
@ -43,6 +43,13 @@ class CORE_EXPORT QgsAggregateCalculator
|
||||
{
|
||||
public:
|
||||
|
||||
struct AggregateInfo
|
||||
{
|
||||
QString function;
|
||||
QString name;
|
||||
QSet<QVariant::Type> supportedTypes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Available aggregates to calculate. Not all aggregates are available for all field
|
||||
* types.
|
||||
@ -155,6 +162,8 @@ class CORE_EXPORT QgsAggregateCalculator
|
||||
*/
|
||||
static Aggregate stringToAggregate( const QString &string, bool *ok = nullptr );
|
||||
|
||||
static QList< QgsAggregateCalculator::AggregateInfo > aggregates();
|
||||
|
||||
private:
|
||||
|
||||
//! Source layer
|
||||
|
@ -125,6 +125,7 @@ SET(QGIS_GUI_SRCS
|
||||
editorwidgets/qgsrangeconfigdlg.cpp
|
||||
editorwidgets/qgsrangewidgetwrapper.cpp
|
||||
editorwidgets/qgsrangewidgetfactory.cpp
|
||||
editorwidgets/qgsrelationaggregatesearchwidgetwrapper.cpp
|
||||
editorwidgets/qgssearchwidgettoolbutton.cpp
|
||||
editorwidgets/qgsspinbox.cpp
|
||||
editorwidgets/qgsrelationwidgetwrapper.cpp
|
||||
@ -191,6 +192,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgsactionmenu.cpp
|
||||
qgsadvanceddigitizingcanvasitem.cpp
|
||||
qgsadvanceddigitizingdockwidget.cpp
|
||||
qgsaggregatetoolbutton.cpp
|
||||
qgsattributedialog.cpp
|
||||
qgsattributeform.cpp
|
||||
qgsattributeformeditorwidget.cpp
|
||||
@ -198,6 +200,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgsattributeformlegacyinterface.cpp
|
||||
qgsattributetypeloaddialog.cpp
|
||||
qgsattributeformwidget.cpp
|
||||
qgsattributeformrelationeditorwidget.cpp
|
||||
qgsblendmodecombobox.cpp
|
||||
qgsbrowsertreeview.cpp
|
||||
qgsbrowserdockwidget.cpp
|
||||
@ -368,9 +371,11 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
qgisinterface.h
|
||||
qgsactionmenu.h
|
||||
qgsadvanceddigitizingdockwidget.h
|
||||
qgsaggregatetoolbutton.h
|
||||
qgsattributedialog.h
|
||||
qgsattributeform.h
|
||||
qgsattributeformeditorwidget.h
|
||||
qgsattributeformrelationeditorwidget.h
|
||||
qgsattributeformwidget.h
|
||||
qgsattributetypeloaddialog.h
|
||||
qgsblendmodecombobox.h
|
||||
@ -647,6 +652,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
editorwidgets/qgsrelationreferencewidget.h
|
||||
editorwidgets/qgsrelationreferencewidgetwrapper.h
|
||||
editorwidgets/qgsrelationwidgetwrapper.h
|
||||
editorwidgets/qgsrelationaggregatesearchwidgetwrapper.h
|
||||
editorwidgets/qgssearchwidgettoolbutton.h
|
||||
editorwidgets/qgsspinbox.h
|
||||
editorwidgets/qgstexteditconfigdlg.h
|
||||
|
@ -100,6 +100,15 @@ QgsSearchWidgetWrapper::FilterFlags QgsSearchWidgetWrapper::defaultFlags() const
|
||||
return FilterFlags();
|
||||
}
|
||||
|
||||
QString QgsSearchWidgetWrapper::createFieldIdentifier() const
|
||||
{
|
||||
QString field = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
if ( mAggregate.isEmpty() )
|
||||
return field;
|
||||
else
|
||||
return QStringLiteral( "relation_aggregate('%1','%2',%3)" ).arg( context().relation().id(), mAggregate, field );
|
||||
}
|
||||
|
||||
void QgsSearchWidgetWrapper::setFeature( const QgsFeature &feature )
|
||||
{
|
||||
Q_UNUSED( feature )
|
||||
@ -110,3 +119,23 @@ void QgsSearchWidgetWrapper::clearExpression()
|
||||
mExpression = QStringLiteral( "TRUE" );
|
||||
}
|
||||
|
||||
QgsRelation QgsSearchWidgetWrapper::aggregateRelation() const
|
||||
{
|
||||
return mAggregateRelation;
|
||||
}
|
||||
|
||||
void QgsSearchWidgetWrapper::setAggregateRelation( const QgsRelation &aggregateRelation )
|
||||
{
|
||||
mAggregateRelation = aggregateRelation;
|
||||
}
|
||||
|
||||
QString QgsSearchWidgetWrapper::aggregate() const
|
||||
{
|
||||
return mAggregate;
|
||||
}
|
||||
|
||||
void QgsSearchWidgetWrapper::setAggregate( const QString &aggregate )
|
||||
{
|
||||
mAggregate = aggregate;
|
||||
}
|
||||
|
||||
|
@ -188,6 +188,16 @@ class GUI_EXPORT QgsSearchWidgetWrapper : public QgsWidgetWrapper
|
||||
// TODO QGIS 3.0 - make pure virtual
|
||||
virtual QString createExpression( FilterFlags flags ) const { Q_UNUSED( flags ); return QStringLiteral( "TRUE" ); }
|
||||
|
||||
QString createFieldIdentifier() const;
|
||||
|
||||
|
||||
|
||||
QString aggregate() const;
|
||||
void setAggregate( const QString &aggregate );
|
||||
|
||||
QgsRelation aggregateRelation() const;
|
||||
void setAggregateRelation( const QgsRelation &aggregateRelation );
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@ -239,6 +249,9 @@ class GUI_EXPORT QgsSearchWidgetWrapper : public QgsWidgetWrapper
|
||||
QString mExpression;
|
||||
int mFieldIdx;
|
||||
|
||||
private:
|
||||
QString mAggregate;
|
||||
QgsRelation mAggregateRelation;
|
||||
};
|
||||
// We'll use this class inside a QVariant in the widgets properties
|
||||
Q_DECLARE_METATYPE( QgsSearchWidgetWrapper * )
|
||||
|
@ -61,7 +61,7 @@ QgsSearchWidgetWrapper::FilterFlags QgsCheckboxSearchWidgetWrapper::defaultFlags
|
||||
QString QgsCheckboxSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
|
||||
{
|
||||
QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
//clear any unsupported flags
|
||||
flags &= supportedFlags();
|
||||
|
@ -62,7 +62,7 @@ QgsSearchWidgetWrapper::FilterFlags QgsDateTimeSearchWidgetWrapper::defaultFlags
|
||||
|
||||
QString QgsDateTimeSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
|
||||
{
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
//clear any unsupported flags
|
||||
flags &= supportedFlags();
|
||||
|
@ -148,7 +148,7 @@ QString QgsDefaultSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper:
|
||||
flags &= supportedFlags();
|
||||
|
||||
QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
if ( flags & IsNull )
|
||||
return fieldName + " IS NULL";
|
||||
|
@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
qgsrelationaggregatesearchwidget.cpp
|
||||
-----------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "qgsrelationaggregatesearchwidgetwrapper.h"
|
||||
#include "qgsattributeform.h"
|
||||
#include "qgsrelationwidgetwrapper.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
QgsRelationAggregateSearchWidgetWrapper::QgsRelationAggregateSearchWidgetWrapper( QgsVectorLayer *vl, QgsRelationWidgetWrapper *wrapper, QWidget *parent )
|
||||
: QgsSearchWidgetWrapper( vl, -1, parent )
|
||||
, mWrapper( wrapper )
|
||||
{
|
||||
setContext( mWrapper->context() );
|
||||
}
|
||||
|
||||
QString QgsRelationAggregateSearchWidgetWrapper::expression() const
|
||||
{
|
||||
QString aggregateFilter = mAttributeForm->aggregateFilter();
|
||||
|
||||
if ( aggregateFilter.isEmpty() )
|
||||
return QStringLiteral( "TRUE" );
|
||||
else
|
||||
return aggregateFilter;
|
||||
}
|
||||
|
||||
bool QgsRelationAggregateSearchWidgetWrapper::valid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QWidget *QgsRelationAggregateSearchWidgetWrapper::createWidget( QWidget *parent )
|
||||
{
|
||||
QgsAttributeEditorContext subContext = QgsAttributeEditorContext( context(), mWrapper->relation(), QgsAttributeEditorContext::Multiple, QgsAttributeEditorContext::Embed );
|
||||
mAttributeForm = new QgsAttributeForm( mWrapper->relation().referencingLayer(), QgsFeature(), subContext, parent );
|
||||
mAttributeForm->setMode( QgsAttributeForm::AggregateSearchMode );
|
||||
return mAttributeForm;
|
||||
}
|
||||
|
||||
bool QgsRelationAggregateSearchWidgetWrapper::applyDirectly()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsRelationAggregateSearchWidgetWrapper::setExpression( const QString &value )
|
||||
{
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
qgsrelationaggregatesearchwidget.h
|
||||
-----------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef QGSRELATIONAGGREGATESEARCHWIDGETWRAPPER_H
|
||||
#define QGSRELATIONAGGREGATESEARCHWIDGETWRAPPER_H
|
||||
|
||||
#include "qgis_gui.h"
|
||||
#include "qgssearchwidgetwrapper.h"
|
||||
#include "qgsattributeform.h"
|
||||
|
||||
class QgsRelationWidgetWrapper;
|
||||
|
||||
class GUI_EXPORT QgsRelationAggregateSearchWidgetWrapper : public QgsSearchWidgetWrapper
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QgsRelationAggregateSearchWidgetWrapper( QgsVectorLayer *vl, QgsRelationWidgetWrapper *wrapper, QWidget *parent SIP_TRANSFERTHIS = 0 );
|
||||
|
||||
virtual QString expression() const override;
|
||||
|
||||
virtual bool valid() const override;
|
||||
virtual QWidget *createWidget( QWidget *parent ) override;
|
||||
virtual bool applyDirectly() override;
|
||||
virtual void setExpression( const QString &value ) override;
|
||||
|
||||
private:
|
||||
QgsRelationWidgetWrapper *mWrapper;
|
||||
QgsAttributeForm *mAttributeForm;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSRELATIONAGGREGATESEARCHWIDGETWRAPPER_H
|
@ -63,7 +63,7 @@ QgsSearchWidgetWrapper::FilterFlags QgsRelationReferenceSearchWidgetWrapper::def
|
||||
|
||||
QString QgsRelationReferenceSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
|
||||
{
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
//clear any unsupported flags
|
||||
flags &= supportedFlags();
|
||||
|
@ -46,6 +46,11 @@ void QgsRelationWidgetWrapper::setVisible( bool visible )
|
||||
mWidget->setVisible( visible );
|
||||
}
|
||||
|
||||
QgsRelation QgsRelationWidgetWrapper::relation() const
|
||||
{
|
||||
return mRelation;
|
||||
}
|
||||
|
||||
bool QgsRelationWidgetWrapper::showUnlinkButton() const
|
||||
{
|
||||
return mWidget->showUnlinkButton();
|
||||
|
@ -79,6 +79,8 @@ class GUI_EXPORT QgsRelationWidgetWrapper : public QgsWidgetWrapper
|
||||
*/
|
||||
void setShowUnlinkButton( bool showUnlinkButton );
|
||||
|
||||
QgsRelation relation() const;
|
||||
|
||||
protected:
|
||||
QWidget *createWidget( QWidget *parent ) override;
|
||||
void initWidget( QWidget *editor ) override;
|
||||
|
@ -88,7 +88,7 @@ QString QgsValueMapSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper
|
||||
flags &= supportedFlags();
|
||||
|
||||
QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
if ( flags & IsNull )
|
||||
return fieldName + " IS NULL";
|
||||
|
@ -94,7 +94,7 @@ QgsSearchWidgetWrapper::FilterFlags QgsValueRelationSearchWidgetWrapper::default
|
||||
|
||||
QString QgsValueRelationSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
|
||||
{
|
||||
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
|
||||
QString fieldName = createFieldIdentifier();
|
||||
|
||||
//clear any unsupported flags
|
||||
flags &= supportedFlags();
|
||||
|
115
src/gui/qgsaggregatetoolbutton.cpp
Normal file
115
src/gui/qgsaggregatetoolbutton.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/***************************************************************************
|
||||
qgsaggregatetoolbutton.cpp
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsaggregatetoolbutton.h"
|
||||
#include "qgsaggregatecalculator.h"
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
QgsAggregateToolButton::QgsAggregateToolButton()
|
||||
{
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
setPopupMode( QToolButton::InstantPopup );
|
||||
|
||||
mMenu = new QMenu( this );
|
||||
connect( mMenu, &QMenu::aboutToShow, this, &QgsAggregateToolButton::aboutToShowMenu );
|
||||
setMenu( mMenu );
|
||||
|
||||
setText( tr( "Exclude" ) );
|
||||
}
|
||||
|
||||
void QgsAggregateToolButton::setType( QVariant::Type type )
|
||||
{
|
||||
if ( mType == type )
|
||||
return;
|
||||
|
||||
mType = type;
|
||||
updateAvailableAggregates();
|
||||
}
|
||||
|
||||
void QgsAggregateToolButton::aboutToShowMenu()
|
||||
{
|
||||
mMenu->clear();
|
||||
|
||||
for ( const auto &aggregate : qgis::as_const( mAvailableAggregates ) )
|
||||
{
|
||||
mMenu->addAction( aggregate.name, this, [ this, aggregate ]
|
||||
{
|
||||
setText( aggregate.name );
|
||||
setAggregate( aggregate.function );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAggregateToolButton::updateAvailableAggregates()
|
||||
{
|
||||
QList<QgsAggregateCalculator::AggregateInfo> aggregates = QgsAggregateCalculator::aggregates();
|
||||
|
||||
for ( const auto &aggregate : aggregates )
|
||||
{
|
||||
if ( aggregate.supportedTypes.contains( mType ) )
|
||||
{
|
||||
mAvailableAggregates.append( aggregate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAggregateToolButton::setActive( bool active )
|
||||
{
|
||||
if ( active == mActive )
|
||||
return;
|
||||
|
||||
mActive = active;
|
||||
|
||||
if ( !active )
|
||||
setText( tr( "Exclude" ) );
|
||||
emit activeChanged();
|
||||
}
|
||||
|
||||
QString QgsAggregateToolButton::aggregate() const
|
||||
{
|
||||
return mAggregate;
|
||||
}
|
||||
|
||||
void QgsAggregateToolButton::setAggregate( const QString &aggregate )
|
||||
{
|
||||
if ( aggregate == mAggregate )
|
||||
return;
|
||||
|
||||
mAggregate = QString();
|
||||
|
||||
for ( const auto &agg : qgis::as_const( mAvailableAggregates ) )
|
||||
{
|
||||
if ( agg.function == aggregate )
|
||||
{
|
||||
mAggregate = aggregate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setActive( !mAggregate.isEmpty() );
|
||||
|
||||
emit aggregateChanged();
|
||||
}
|
||||
|
||||
bool QgsAggregateToolButton::active() const
|
||||
{
|
||||
return mActive;
|
||||
}
|
||||
|
||||
QVariant::Type QgsAggregateToolButton::type() const
|
||||
{
|
||||
return mType;
|
||||
}
|
58
src/gui/qgsaggregatetoolbutton.h
Normal file
58
src/gui/qgsaggregatetoolbutton.h
Normal file
@ -0,0 +1,58 @@
|
||||
/***************************************************************************
|
||||
qgsaggregatetoolbutton.h
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSAGGREGATETOOLBUTTON_H
|
||||
#define QGSAGGREGATETOOLBUTTON_H
|
||||
|
||||
#include <QToolButton>
|
||||
#include <QVariant>
|
||||
|
||||
#include "qgsaggregatecalculator.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
class GUI_EXPORT QgsAggregateToolButton : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsAggregateToolButton();
|
||||
|
||||
void setType( QVariant::Type type );
|
||||
|
||||
QVariant::Type type() const;
|
||||
|
||||
void setActive( bool active );
|
||||
bool active() const;
|
||||
|
||||
QString aggregate() const;
|
||||
void setAggregate( const QString &aggregate );
|
||||
|
||||
signals:
|
||||
void aggregateChanged();
|
||||
void activeChanged();
|
||||
|
||||
private slots:
|
||||
void aboutToShowMenu();
|
||||
|
||||
private:
|
||||
void updateAvailableAggregates();
|
||||
QMenu *mMenu = nullptr;
|
||||
QVariant::Type mType;
|
||||
bool mActive = false;
|
||||
QString mAggregate;
|
||||
QList<QgsAggregateCalculator::AggregateInfo> mAvailableAggregates;
|
||||
};
|
||||
|
||||
#endif // QGSAGGREGATETOOLBUTTON_H
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "qgsattributeforminterface.h"
|
||||
#include "qgsattributeformlegacyinterface.h"
|
||||
#include "qgsattributeformrelationeditorwidget.h"
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
#include "qgsfeatureiterator.h"
|
||||
#include "qgsproject.h"
|
||||
@ -151,7 +152,7 @@ void QgsAttributeForm::setMode( QgsAttributeForm::Mode mode )
|
||||
}
|
||||
|
||||
//update all form editor widget modes to match
|
||||
for ( QgsAttributeFormWidget *w : findChildren< QgsAttributeFormWidget * >() )
|
||||
for ( QgsAttributeFormWidget *w : qgis::as_const( mFormWidgets ) )
|
||||
{
|
||||
switch ( mode )
|
||||
{
|
||||
@ -170,11 +171,15 @@ void QgsAttributeForm::setMode( QgsAttributeForm::Mode mode )
|
||||
case QgsAttributeForm::SearchMode:
|
||||
w->setMode( QgsAttributeFormWidget::SearchMode );
|
||||
break;
|
||||
|
||||
case QgsAttributeForm::AggregateSearchMode:
|
||||
w->setMode( QgsAttributeFormWidget::AggregateSearchMode );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool relationWidgetsVisible = ( mMode == QgsAttributeForm::SingleEditMode || mMode == QgsAttributeForm::AddFeatureMode );
|
||||
Q_FOREACH ( QgsRelationWidgetWrapper *w, findChildren< QgsRelationWidgetWrapper * >() )
|
||||
bool relationWidgetsVisible = ( mMode != QgsAttributeForm::MultiEditMode && mMode != QgsAttributeForm::AggregateSearchMode );
|
||||
for ( QgsAttributeFormRelationEditorWidget *w : findChildren< QgsAttributeFormRelationEditorWidget * >() )
|
||||
{
|
||||
w->setVisible( relationWidgetsVisible );
|
||||
}
|
||||
@ -201,6 +206,11 @@ void QgsAttributeForm::setMode( QgsAttributeForm::Mode mode )
|
||||
mSearchButtonBox->setVisible( true );
|
||||
hideButtonBox();
|
||||
break;
|
||||
|
||||
case QgsAttributeForm::AggregateSearchMode:
|
||||
mSearchButtonBox->setVisible( false );
|
||||
hideButtonBox();
|
||||
break;
|
||||
}
|
||||
|
||||
emit modeChanged( mMode );
|
||||
@ -240,6 +250,7 @@ void QgsAttributeForm::setFeature( const QgsFeature &feature )
|
||||
}
|
||||
case MultiEditMode:
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
{
|
||||
//ignore setFeature
|
||||
break;
|
||||
@ -572,6 +583,7 @@ bool QgsAttributeForm::save()
|
||||
case SingleEditMode:
|
||||
case AddFeatureMode:
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
success = saveEdits();
|
||||
break;
|
||||
|
||||
@ -621,7 +633,7 @@ void QgsAttributeForm::clearMultiEditMessages()
|
||||
QString QgsAttributeForm::createFilterExpression() const
|
||||
{
|
||||
QStringList filters;
|
||||
Q_FOREACH ( QgsAttributeFormEditorWidget *w, findChildren< QgsAttributeFormEditorWidget * >() )
|
||||
for ( QgsAttributeFormWidget *w : qgis::as_const( mFormWidgets ) )
|
||||
{
|
||||
QString filter = w->currentFilterExpression();
|
||||
if ( !filter.isEmpty() )
|
||||
@ -676,6 +688,7 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value )
|
||||
break;
|
||||
}
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
//nothing to do
|
||||
break;
|
||||
}
|
||||
@ -1224,6 +1237,7 @@ void QgsAttributeForm::init()
|
||||
QgsAttributeFormEditorWidget *formWidget = new QgsAttributeFormEditorWidget( eww, widgetSetup.type(), this );
|
||||
w = formWidget;
|
||||
mFormEditorWidgets.insert( idx, formWidget );
|
||||
mFormWidgets.append( formWidget );
|
||||
formWidget->createSearchWidgetWrappers( mContext );
|
||||
|
||||
l->setBuddy( eww->widget() );
|
||||
@ -1264,7 +1278,12 @@ void QgsAttributeForm::init()
|
||||
rww->setConfig( setup.config() );
|
||||
rww->setContext( mContext );
|
||||
gridLayout->addWidget( rww->widget(), row++, 0, 1, 2 );
|
||||
|
||||
QgsAttributeFormRelationEditorWidget *formWidget = new QgsAttributeFormRelationEditorWidget( rww, this );
|
||||
formWidget->createSearchWidgetWrappers( mContext );
|
||||
|
||||
mWidgets.append( rww );
|
||||
mFormWidgets.append( formWidget );
|
||||
}
|
||||
|
||||
if ( QgsProject::instance()->relationManager()->referencedRelations( mLayer ).isEmpty() )
|
||||
@ -1523,12 +1542,13 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
|
||||
const QgsEditorWidgetSetup widgetSetup = QgsGui::editorWidgetRegistry()->findBest( mLayer, fieldDef->name() );
|
||||
|
||||
QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( widgetSetup.type(), mLayer, fldIdx, widgetSetup.config(), nullptr, this, mContext );
|
||||
QgsAttributeFormEditorWidget *w = new QgsAttributeFormEditorWidget( eww, widgetSetup.type(), this );
|
||||
mFormEditorWidgets.insert( fldIdx, w );
|
||||
QgsAttributeFormEditorWidget *formWidget = new QgsAttributeFormEditorWidget( eww, widgetSetup.type(), this );
|
||||
mFormEditorWidgets.insert( fldIdx, formWidget );
|
||||
mFormWidgets.append( formWidget );
|
||||
|
||||
w->createSearchWidgetWrappers( mContext );
|
||||
formWidget->createSearchWidgetWrappers( mContext );
|
||||
|
||||
newWidgetInfo.widget = w;
|
||||
newWidgetInfo.widget = formWidget;
|
||||
addWidgetWrapper( eww );
|
||||
|
||||
newWidgetInfo.widget->setObjectName( fields.at( fldIdx ).name() );
|
||||
@ -1549,11 +1569,17 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
|
||||
QgsRelationWidgetWrapper *rww = new QgsRelationWidgetWrapper( mLayer, relDef->relation(), nullptr, this );
|
||||
rww->setConfig( mLayer->editFormConfig().widgetConfig( relDef->relation().id() ) );
|
||||
rww->setContext( context );
|
||||
newWidgetInfo.widget = rww->widget();
|
||||
rww->setShowLabel( relDef->showLabel() );
|
||||
rww->setShowLinkButton( relDef->showLinkButton() );
|
||||
rww->setShowUnlinkButton( relDef->showUnlinkButton() );
|
||||
|
||||
QgsAttributeFormRelationEditorWidget *formWidget = new QgsAttributeFormRelationEditorWidget( rww, this );
|
||||
formWidget->createSearchWidgetWrappers( mContext );
|
||||
|
||||
mWidgets.append( rww );
|
||||
mFormWidgets.append( formWidget );
|
||||
|
||||
newWidgetInfo.widget = formWidget;
|
||||
newWidgetInfo.labelText = QString();
|
||||
newWidgetInfo.labelOnTop = true;
|
||||
break;
|
||||
@ -1818,6 +1844,7 @@ void QgsAttributeForm::layerSelectionChanged()
|
||||
case SingleEditMode:
|
||||
case AddFeatureMode:
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
break;
|
||||
|
||||
case MultiEditMode:
|
||||
@ -1881,6 +1908,24 @@ void QgsAttributeForm::setMessageBar( QgsMessageBar *messageBar )
|
||||
mMessageBar = messageBar;
|
||||
}
|
||||
|
||||
QString QgsAttributeForm::aggregateFilter() const
|
||||
{
|
||||
if ( mMode != AggregateSearchMode )
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
|
||||
QStringList filters;
|
||||
for ( QgsAttributeFormWidget *widget : mFormWidgets )
|
||||
{
|
||||
QString filter = widget->currentFilterExpression();
|
||||
if ( !filter.isNull() )
|
||||
filters << '(' + filter + ')';
|
||||
}
|
||||
|
||||
return filters.join( QStringLiteral( " AND " ) );
|
||||
}
|
||||
|
||||
int QgsAttributeForm::messageTimeout()
|
||||
{
|
||||
QgsSettings settings;
|
||||
|
@ -54,6 +54,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
|
||||
will add a new feature when the form is accepted. */
|
||||
MultiEditMode, //!< Multi edit mode, for editing fields of multiple features at once
|
||||
SearchMode, //!< Form values are used for searching/filtering the layer
|
||||
AggregateSearchMode,
|
||||
};
|
||||
|
||||
//! Filter types
|
||||
@ -160,6 +161,8 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
|
||||
*/
|
||||
void setMessageBar( QgsMessageBar *messageBar );
|
||||
|
||||
QString aggregateFilter() const;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -351,6 +354,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
|
||||
QWidget *mSearchButtonBox = nullptr;
|
||||
QList<QgsAttributeFormInterface *> mInterfaces;
|
||||
QMap< int, QgsAttributeFormEditorWidget * > mFormEditorWidgets;
|
||||
QList< QgsAttributeFormWidget *> mFormWidgets;
|
||||
QgsExpressionContext mExpressionContext;
|
||||
QMap<const QgsVectorLayerJoinInfo *, QgsFeature> mJoinedFeatures;
|
||||
|
||||
|
@ -21,7 +21,9 @@
|
||||
#include "qgssearchwidgetwrapper.h"
|
||||
#include "qgsattributeeditorcontext.h"
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
#include "qgsaggregatetoolbutton.h"
|
||||
#include "qgsgui.h"
|
||||
|
||||
#include <QLayout>
|
||||
#include <QLabel>
|
||||
#include <QStackedWidget>
|
||||
@ -40,50 +42,18 @@ QgsAttributeFormEditorWidget::QgsAttributeFormEditorWidget( QgsEditorWidgetWrapp
|
||||
mConstraintResultLabel->setObjectName( QStringLiteral( "ConstraintStatus" ) );
|
||||
mConstraintResultLabel->setSizePolicy( QSizePolicy::Fixed, mConstraintResultLabel->sizePolicy().verticalPolicy() );
|
||||
|
||||
mEditPage = new QWidget();
|
||||
QHBoxLayout *l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mEditPage->setLayout( l );
|
||||
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mSearchFrame = new QWidget();
|
||||
mSearchFrame->setLayout( l );
|
||||
|
||||
mSearchPage = new QWidget();
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mSearchPage->setLayout( l );
|
||||
l->addWidget( mSearchFrame, 1 );
|
||||
mSearchWidgetToolButton = new QgsSearchWidgetToolButton();
|
||||
connect( mSearchWidgetToolButton, &QgsSearchWidgetToolButton::activeFlagsChanged,
|
||||
this, &QgsAttributeFormEditorWidget::searchWidgetFlagsChanged );
|
||||
l->addWidget( mSearchWidgetToolButton, 0 );
|
||||
|
||||
|
||||
mStack = new QStackedWidget;
|
||||
mStack->addWidget( mEditPage );
|
||||
mStack->addWidget( mSearchPage );
|
||||
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
setLayout( l );
|
||||
l->addWidget( mStack );
|
||||
|
||||
if ( !mWidget || !mForm )
|
||||
return;
|
||||
|
||||
mEditPage->layout()->addWidget( mWidget->widget() );
|
||||
mMultiEditButton->setField( mWidget->field() );
|
||||
mAggregateButton = new QgsAggregateToolButton();
|
||||
mAggregateButton->setType( editorWidget->field().type() );
|
||||
connect( mAggregateButton, &QgsAggregateToolButton::aggregateChanged, this, &QgsAttributeFormEditorWidget::onAggregateChanged );
|
||||
|
||||
if ( mWidget->widget() )
|
||||
{
|
||||
mWidget->widget()->setObjectName( mWidget->field().name() );
|
||||
}
|
||||
|
||||
connect( mWidget, static_cast<void ( QgsEditorWidgetWrapper::* )( const QVariant &value )>( &QgsEditorWidgetWrapper::valueChanged ), this, &QgsAttributeFormEditorWidget::editorWidgetChanged );
|
||||
|
||||
connect( mMultiEditButton, &QgsMultiEditToolButton::resetFieldValueTriggered, this, &QgsAttributeFormEditorWidget::resetValue );
|
||||
connect( mMultiEditButton, &QgsMultiEditToolButton::setFieldValueTriggered, this, &QgsAttributeFormEditorWidget::setFieldTriggered );
|
||||
|
||||
@ -105,42 +75,19 @@ void QgsAttributeFormEditorWidget::createSearchWidgetWrappers( const QgsAttribut
|
||||
const int fieldIdx = mWidget->fieldIdx();
|
||||
|
||||
QgsSearchWidgetWrapper *sww = QgsGui::editorWidgetRegistry()->createSearchWidget( mWidgetType, layer(), fieldIdx, config,
|
||||
mSearchFrame, context );
|
||||
searchWidgetFrame(), context );
|
||||
setSearchWidgetWrapper( sww );
|
||||
searchWidgetFrame()->layout()->addWidget( mAggregateButton );
|
||||
if ( sww->supportedFlags() & QgsSearchWidgetWrapper::Between ||
|
||||
sww->supportedFlags() & QgsSearchWidgetWrapper::IsNotBetween )
|
||||
{
|
||||
// create secondary widget for between type searches
|
||||
QgsSearchWidgetWrapper *sww2 = QgsGui::editorWidgetRegistry()->createSearchWidget( mWidgetType, layer(), fieldIdx, config,
|
||||
mSearchFrame, context );
|
||||
mSearchWidgets << sww2;
|
||||
mSearchFrame->layout()->addWidget( sww2->widget() );
|
||||
sww2->widget()->hide();
|
||||
searchWidgetFrame(), context );
|
||||
addAdditionalSearchWidgetWrapper( sww2 );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper )
|
||||
{
|
||||
mSearchWidgets.clear();
|
||||
mSearchWidgets << wrapper;
|
||||
mSearchFrame->layout()->addWidget( wrapper->widget() );
|
||||
mSearchWidgetToolButton->setAvailableFlags( wrapper->supportedFlags() );
|
||||
mSearchWidgetToolButton->setActiveFlags( QgsSearchWidgetWrapper::FilterFlags() );
|
||||
mSearchWidgetToolButton->setDefaultFlags( wrapper->defaultFlags() );
|
||||
connect( wrapper, &QgsSearchWidgetWrapper::valueChanged, mSearchWidgetToolButton, &QgsSearchWidgetToolButton::setActive );
|
||||
connect( wrapper, &QgsSearchWidgetWrapper::valueCleared, mSearchWidgetToolButton, &QgsSearchWidgetToolButton::setInactive );
|
||||
}
|
||||
|
||||
QWidget *QgsAttributeFormEditorWidget::searchWidgetFrame()
|
||||
{
|
||||
return mSearchFrame;
|
||||
}
|
||||
|
||||
QList< QgsSearchWidgetWrapper * > QgsAttributeFormEditorWidget::searchWidgetWrappers()
|
||||
{
|
||||
return mSearchWidgets;
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::setConstraintStatus( const QString &constraint, const QString &description, const QString &err, QgsEditorWidgetWrapper::ConstraintResult result )
|
||||
{
|
||||
switch ( result )
|
||||
@ -185,14 +132,7 @@ void QgsAttributeFormEditorWidget::changesCommitted()
|
||||
mIsChanged = false;
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::resetSearch()
|
||||
{
|
||||
mSearchWidgetToolButton->setInactive();
|
||||
Q_FOREACH ( QgsSearchWidgetWrapper *widget, mSearchWidgets )
|
||||
{
|
||||
widget->clearWidget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QgsAttributeFormEditorWidget::initialize( const QVariant &initialValue, bool mixedValues )
|
||||
{
|
||||
@ -213,31 +153,7 @@ QVariant QgsAttributeFormEditorWidget::currentValue() const
|
||||
return mWidget->value();
|
||||
}
|
||||
|
||||
QString QgsAttributeFormEditorWidget::currentFilterExpression() const
|
||||
{
|
||||
if ( mSearchWidgets.isEmpty() )
|
||||
return QString();
|
||||
|
||||
if ( !mSearchWidgetToolButton->isActive() )
|
||||
return QString();
|
||||
|
||||
if ( mSearchWidgetToolButton->activeFlags() & QgsSearchWidgetWrapper::Between )
|
||||
{
|
||||
// special case: Between search
|
||||
QString filter1 = mSearchWidgets.at( 0 )->createExpression( QgsSearchWidgetWrapper::GreaterThanOrEqualTo );
|
||||
QString filter2 = mSearchWidgets.at( 1 )->createExpression( QgsSearchWidgetWrapper::LessThanOrEqualTo );
|
||||
return QStringLiteral( "%1 AND %2" ).arg( filter1, filter2 );
|
||||
}
|
||||
else if ( mSearchWidgetToolButton->activeFlags() & QgsSearchWidgetWrapper::IsNotBetween )
|
||||
{
|
||||
// special case: Is Not Between search
|
||||
QString filter1 = mSearchWidgets.at( 0 )->createExpression( QgsSearchWidgetWrapper::LessThan );
|
||||
QString filter2 = mSearchWidgets.at( 1 )->createExpression( QgsSearchWidgetWrapper::GreaterThan );
|
||||
return QStringLiteral( "%1 OR %2" ).arg( filter1, filter2 );
|
||||
}
|
||||
|
||||
return mSearchWidgets.at( 0 )->createExpression( mSearchWidgetToolButton->activeFlags() );
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::editorWidgetChanged( const QVariant &value )
|
||||
{
|
||||
@ -250,6 +166,7 @@ void QgsAttributeFormEditorWidget::editorWidgetChanged( const QVariant &value )
|
||||
{
|
||||
case DefaultMode:
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
break;
|
||||
case MultiEditMode:
|
||||
mMultiEditButton->setIsChanged( true );
|
||||
@ -270,6 +187,7 @@ void QgsAttributeFormEditorWidget::resetValue()
|
||||
{
|
||||
case DefaultMode:
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
break;
|
||||
case MultiEditMode:
|
||||
{
|
||||
@ -286,41 +204,23 @@ void QgsAttributeFormEditorWidget::setFieldTriggered()
|
||||
mIsChanged = true;
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::searchWidgetFlagsChanged( QgsSearchWidgetWrapper::FilterFlags flags )
|
||||
void QgsAttributeFormEditorWidget::onAggregateChanged()
|
||||
{
|
||||
Q_FOREACH ( QgsSearchWidgetWrapper *widget, mSearchWidgets )
|
||||
{
|
||||
widget->setEnabled( !( flags & QgsSearchWidgetWrapper::IsNull )
|
||||
&& !( flags & QgsSearchWidgetWrapper::IsNotNull ) );
|
||||
if ( !mSearchWidgetToolButton->isActive() )
|
||||
{
|
||||
widget->clearWidget();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mSearchWidgets.count() >= 2 )
|
||||
{
|
||||
mSearchWidgets.at( 1 )->widget()->setVisible( flags & QgsSearchWidgetWrapper::Between ||
|
||||
flags & QgsSearchWidgetWrapper::IsNotBetween );
|
||||
}
|
||||
}
|
||||
|
||||
QgsSearchWidgetToolButton *QgsAttributeFormEditorWidget::searchWidgetToolButton()
|
||||
{
|
||||
return mSearchWidgetToolButton;
|
||||
for ( QgsSearchWidgetWrapper *searchWidget : searchWidgetWrappers() )
|
||||
searchWidget->setAggregate( mAggregateButton->aggregate() );
|
||||
}
|
||||
|
||||
void QgsAttributeFormEditorWidget::updateWidgets()
|
||||
{
|
||||
//first update the tool buttons
|
||||
bool hasMultiEditButton = ( mEditPage->layout()->indexOf( mMultiEditButton ) >= 0 );
|
||||
bool hasMultiEditButton = ( editPage()->layout()->indexOf( mMultiEditButton ) >= 0 );
|
||||
bool fieldReadOnly = layer()->editFormConfig().readOnly( mWidget->fieldIdx() );
|
||||
|
||||
if ( hasMultiEditButton )
|
||||
{
|
||||
if ( mode() != MultiEditMode || fieldReadOnly )
|
||||
{
|
||||
mEditPage->layout()->removeWidget( mMultiEditButton );
|
||||
editPage()->layout()->removeWidget( mMultiEditButton );
|
||||
mMultiEditButton->setParent( nullptr );
|
||||
}
|
||||
}
|
||||
@ -328,7 +228,7 @@ void QgsAttributeFormEditorWidget::updateWidgets()
|
||||
{
|
||||
if ( mode() == MultiEditMode && !fieldReadOnly )
|
||||
{
|
||||
mEditPage->layout()->addWidget( mMultiEditButton );
|
||||
editPage()->layout()->addWidget( mMultiEditButton );
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,16 +237,24 @@ void QgsAttributeFormEditorWidget::updateWidgets()
|
||||
case DefaultMode:
|
||||
case MultiEditMode:
|
||||
{
|
||||
mStack->setCurrentWidget( mEditPage );
|
||||
stack()->setCurrentWidget( editPage() );
|
||||
|
||||
mEditPage->layout()->addWidget( mConstraintResultLabel );
|
||||
editPage()->layout()->addWidget( mConstraintResultLabel );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AggregateSearchMode:
|
||||
{
|
||||
mAggregateButton->setVisible( true );
|
||||
stack()->setCurrentWidget( searchPage() );
|
||||
break;
|
||||
}
|
||||
|
||||
case SearchMode:
|
||||
{
|
||||
mStack->setCurrentWidget( mSearchPage );
|
||||
mAggregateButton->setVisible( true );
|
||||
stack()->setCurrentWidget( searchPage() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ class QgsVectorLayer;
|
||||
class QStackedWidget;
|
||||
class QgsAttributeEditorContext;
|
||||
class QLabel;
|
||||
class QgsAggregateToolButton;
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
@ -74,13 +75,6 @@ class GUI_EXPORT QgsAttributeFormEditorWidget : public QgsAttributeFormWidget
|
||||
*/
|
||||
QVariant currentValue() const;
|
||||
|
||||
/**
|
||||
* Creates an expression matching the current search filter value and
|
||||
* search properties represented in the widget.
|
||||
* \since QGIS 2.16
|
||||
*/
|
||||
QString currentFilterExpression() const override;
|
||||
|
||||
/**
|
||||
* Set the constraint status for this widget.
|
||||
*/
|
||||
@ -104,11 +98,6 @@ class GUI_EXPORT QgsAttributeFormEditorWidget : public QgsAttributeFormWidget
|
||||
*/
|
||||
void changesCommitted();
|
||||
|
||||
/**
|
||||
* Resets the search/filter value of the widget.
|
||||
*/
|
||||
void resetSearch();
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -128,60 +117,16 @@ class GUI_EXPORT QgsAttributeFormEditorWidget : public QgsAttributeFormWidget
|
||||
//! Triggered when the multi edit tool button "set field value" action is selected
|
||||
void setFieldTriggered();
|
||||
|
||||
//! Triggered when search button flags are changed
|
||||
void searchWidgetFlagsChanged( QgsSearchWidgetWrapper::FilterFlags flags );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Returns a pointer to the search widget tool button in the widget.
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
QgsSearchWidgetToolButton *searchWidgetToolButton();
|
||||
|
||||
/**
|
||||
* Sets the search widget wrapper for the widget used when the form is in
|
||||
* search mode.
|
||||
* \param wrapper search widget wrapper.
|
||||
* \note the search widget wrapper should be created using searchWidgetFrame()
|
||||
* as its parent
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
void setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
|
||||
/**
|
||||
* Returns the widget which should be used as a parent during construction
|
||||
* of the search widget wrapper.
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable AP
|
||||
*/
|
||||
QWidget *searchWidgetFrame();
|
||||
|
||||
/**
|
||||
* Returns the search widget wrapper used in this widget. The wrapper must
|
||||
* first be created using createSearchWidgetWrapper()
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
QList< QgsSearchWidgetWrapper * > searchWidgetWrappers();
|
||||
void onAggregateChanged();
|
||||
|
||||
private:
|
||||
|
||||
QWidget *mEditPage = nullptr;
|
||||
QWidget *mSearchPage = nullptr;
|
||||
QStackedWidget *mStack = nullptr;
|
||||
QWidget *mSearchFrame = nullptr;
|
||||
|
||||
QString mWidgetType;
|
||||
QgsEditorWidgetWrapper *mWidget = nullptr;
|
||||
QList< QgsSearchWidgetWrapper * > mSearchWidgets;
|
||||
QgsAttributeForm *mForm = nullptr;
|
||||
QLabel *mConstraintResultLabel = nullptr;
|
||||
|
||||
QgsMultiEditToolButton *mMultiEditButton = nullptr;
|
||||
QgsSearchWidgetToolButton *mSearchWidgetToolButton = nullptr;
|
||||
QgsAggregateToolButton *mAggregateButton = nullptr;
|
||||
QVariant mPreviousValue;
|
||||
bool mBlockValueUpdate;
|
||||
bool mIsMixed;
|
||||
|
38
src/gui/qgsattributeformrelationeditorwidget.cpp
Normal file
38
src/gui/qgsattributeformrelationeditorwidget.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
qgsattributeformrelationeditorwidget.cpp
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsattributeformrelationeditorwidget.h"
|
||||
#include "qgsrelationaggregatesearchwidgetwrapper.h"
|
||||
#include "qgsattributeform.h"
|
||||
|
||||
#include "qgsrelationwidgetwrapper.h"
|
||||
|
||||
QgsAttributeFormRelationEditorWidget::QgsAttributeFormRelationEditorWidget( QgsRelationWidgetWrapper *wrapper, QgsAttributeForm *form )
|
||||
: QgsAttributeFormWidget( wrapper, form )
|
||||
, mWrapper( wrapper )
|
||||
{
|
||||
}
|
||||
|
||||
void QgsAttributeFormRelationEditorWidget::createSearchWidgetWrappers( const QgsAttributeEditorContext &context )
|
||||
{
|
||||
mSearchWidget = new QgsRelationAggregateSearchWidgetWrapper( layer(), mWrapper, form() );
|
||||
|
||||
setSearchWidgetWrapper( mSearchWidget );
|
||||
}
|
||||
|
||||
QString QgsAttributeFormRelationEditorWidget::currentFilterExpression() const
|
||||
{
|
||||
return mSearchWidget->expression();
|
||||
}
|
40
src/gui/qgsattributeformrelationeditorwidget.h
Normal file
40
src/gui/qgsattributeformrelationeditorwidget.h
Normal file
@ -0,0 +1,40 @@
|
||||
/***************************************************************************
|
||||
qgsattributeformrelationeditorwidget.h
|
||||
--------------------------------------
|
||||
Date : Nov 2017
|
||||
Copyright : (C) 2017 Matthias Kuhn
|
||||
Email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSATTRIBUTEFORMRELATIONEDITORWIDGET_H
|
||||
#define QGSATTRIBUTEFORMRELATIONEDITORWIDGET_H
|
||||
|
||||
#include "qgis_gui.h"
|
||||
#include "qgsattributeformwidget.h"
|
||||
|
||||
class QgsRelationWidgetWrapper;
|
||||
class QgsRelationAggregateSearchWidgetWrapper;
|
||||
|
||||
class GUI_EXPORT QgsAttributeFormRelationEditorWidget : public QgsAttributeFormWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QgsAttributeFormRelationEditorWidget( QgsRelationWidgetWrapper *wrapper, QgsAttributeForm *form );
|
||||
|
||||
virtual void createSearchWidgetWrappers( const QgsAttributeEditorContext &context SIP_PYARGREMOVE = QgsAttributeEditorContext() ) override;
|
||||
virtual QString currentFilterExpression() const override;
|
||||
|
||||
private:
|
||||
QgsRelationAggregateSearchWidgetWrapper *mSearchWidget;
|
||||
QgsRelationWidgetWrapper *mWrapper;
|
||||
};
|
||||
|
||||
#endif // QGSATTRIBUTEFORMRELATIONEDITORWIDGET_H
|
@ -1,13 +1,56 @@
|
||||
#include "qgsattributeformwidget.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QStackedWidget>
|
||||
|
||||
#include "qgsattributeform.h"
|
||||
#include "qgssearchwidgettoolbutton.h"
|
||||
|
||||
QgsAttributeFormWidget::QgsAttributeFormWidget( QgsWidgetWrapper *widget, QgsAttributeForm *form )
|
||||
: QWidget( form )
|
||||
, mMode( DefaultMode )
|
||||
, mForm( form )
|
||||
, mWidget( widget )
|
||||
{
|
||||
mEditPage = new QWidget();
|
||||
QHBoxLayout *l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mEditPage->setLayout( l );
|
||||
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mSearchFrame = new QWidget();
|
||||
mSearchFrame->setLayout( l );
|
||||
|
||||
mSearchPage = new QWidget();
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
mSearchPage->setLayout( l );
|
||||
l->addWidget( mSearchFrame, 1 );
|
||||
mSearchWidgetToolButton = new QgsSearchWidgetToolButton();
|
||||
connect( mSearchWidgetToolButton, &QgsSearchWidgetToolButton::activeFlagsChanged,
|
||||
this, &QgsAttributeFormWidget::searchWidgetFlagsChanged );
|
||||
l->addWidget( mSearchWidgetToolButton, 0 );
|
||||
|
||||
|
||||
mStack = new QStackedWidget;
|
||||
mStack->addWidget( mEditPage );
|
||||
mStack->addWidget( mSearchPage );
|
||||
|
||||
l = new QHBoxLayout();
|
||||
l->setMargin( 0 );
|
||||
l->setContentsMargins( 0, 0, 0, 0 );
|
||||
setLayout( l );
|
||||
l->addWidget( mStack );
|
||||
|
||||
if ( !mWidget || !mForm )
|
||||
return;
|
||||
|
||||
mEditPage->layout()->addWidget( mWidget->widget() );
|
||||
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::setMode( QgsAttributeFormWidget::Mode mode )
|
||||
@ -21,8 +64,131 @@ QgsAttributeForm *QgsAttributeFormWidget::form() const
|
||||
return mForm;
|
||||
}
|
||||
|
||||
QWidget *QgsAttributeFormWidget::searchWidgetFrame()
|
||||
{
|
||||
return mSearchFrame;
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper ) SIP_SKIP
|
||||
{
|
||||
mSearchWidgets.clear();
|
||||
mSearchWidgets << wrapper;
|
||||
mSearchFrame->layout()->addWidget( wrapper->widget() );
|
||||
mSearchWidgetToolButton->setAvailableFlags( wrapper->supportedFlags() );
|
||||
mSearchWidgetToolButton->setActiveFlags( QgsSearchWidgetWrapper::FilterFlags() );
|
||||
mSearchWidgetToolButton->setDefaultFlags( wrapper->defaultFlags() );
|
||||
connect( wrapper, &QgsSearchWidgetWrapper::valueChanged, mSearchWidgetToolButton, &QgsSearchWidgetToolButton::setActive );
|
||||
connect( wrapper, &QgsSearchWidgetWrapper::valueCleared, mSearchWidgetToolButton, &QgsSearchWidgetToolButton::setInactive );
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::addAdditionalSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper )
|
||||
{
|
||||
mSearchWidgets << wrapper;
|
||||
|
||||
mSearchFrame->layout()->addWidget( wrapper->widget() );
|
||||
wrapper->widget()->hide();
|
||||
}
|
||||
|
||||
QList<QgsSearchWidgetWrapper *> QgsAttributeFormWidget::searchWidgetWrappers() SIP_SKIP
|
||||
{
|
||||
return mSearchWidgets;
|
||||
}
|
||||
|
||||
QString QgsAttributeFormWidget::currentFilterExpression() const
|
||||
{
|
||||
if ( mSearchWidgets.isEmpty() )
|
||||
return QString();
|
||||
|
||||
if ( !mSearchWidgetToolButton->isActive() )
|
||||
return QString();
|
||||
|
||||
if ( mSearchWidgetToolButton->activeFlags() & QgsSearchWidgetWrapper::Between )
|
||||
{
|
||||
// special case: Between search
|
||||
QString filter1 = mSearchWidgets.at( 0 )->createExpression( QgsSearchWidgetWrapper::GreaterThanOrEqualTo );
|
||||
QString filter2 = mSearchWidgets.at( 1 )->createExpression( QgsSearchWidgetWrapper::LessThanOrEqualTo );
|
||||
return QStringLiteral( "%1 AND %2" ).arg( filter1, filter2 );
|
||||
}
|
||||
else if ( mSearchWidgetToolButton->activeFlags() & QgsSearchWidgetWrapper::IsNotBetween )
|
||||
{
|
||||
// special case: Is Not Between search
|
||||
QString filter1 = mSearchWidgets.at( 0 )->createExpression( QgsSearchWidgetWrapper::LessThan );
|
||||
QString filter2 = mSearchWidgets.at( 1 )->createExpression( QgsSearchWidgetWrapper::GreaterThan );
|
||||
return QStringLiteral( "%1 OR %2" ).arg( filter1, filter2 );
|
||||
}
|
||||
|
||||
return mSearchWidgets.at( 0 )->createExpression( mSearchWidgetToolButton->activeFlags() );
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::resetSearch()
|
||||
{
|
||||
mSearchWidgetToolButton->setInactive();
|
||||
Q_FOREACH ( QgsSearchWidgetWrapper *widget, mSearchWidgets )
|
||||
{
|
||||
widget->clearWidget();
|
||||
}
|
||||
}
|
||||
|
||||
QgsSearchWidgetToolButton *QgsAttributeFormWidget::searchWidgetToolButton() SIP_SKIP
|
||||
{
|
||||
return mSearchWidgetToolButton;
|
||||
}
|
||||
|
||||
QgsVectorLayer *QgsAttributeFormWidget::layer()
|
||||
{
|
||||
QgsAttributeForm *aform = form();
|
||||
return aform ? aform->layer() : nullptr;
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::searchWidgetFlagsChanged( QgsSearchWidgetWrapper::FilterFlags flags )
|
||||
{
|
||||
Q_FOREACH ( QgsSearchWidgetWrapper *widget, mSearchWidgets )
|
||||
{
|
||||
widget->setEnabled( !( flags & QgsSearchWidgetWrapper::IsNull )
|
||||
&& !( flags & QgsSearchWidgetWrapper::IsNotNull ) );
|
||||
if ( !mSearchWidgetToolButton->isActive() )
|
||||
{
|
||||
widget->clearWidget();
|
||||
}
|
||||
}
|
||||
|
||||
if ( mSearchWidgets.count() >= 2 )
|
||||
{
|
||||
mSearchWidgets.at( 1 )->widget()->setVisible( flags & QgsSearchWidgetWrapper::Between ||
|
||||
flags & QgsSearchWidgetWrapper::IsNotBetween );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAttributeFormWidget::updateWidgets()
|
||||
{
|
||||
switch ( mMode )
|
||||
{
|
||||
case DefaultMode:
|
||||
case MultiEditMode:
|
||||
mStack->setCurrentWidget( mEditPage );
|
||||
break;
|
||||
|
||||
case SearchMode:
|
||||
case AggregateSearchMode:
|
||||
{
|
||||
mStack->setCurrentWidget( mSearchPage );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QWidget *QgsAttributeFormWidget::searchPage() const
|
||||
{
|
||||
return mSearchPage;
|
||||
}
|
||||
|
||||
QStackedWidget *QgsAttributeFormWidget::stack() const
|
||||
{
|
||||
return mStack;
|
||||
}
|
||||
|
||||
QWidget *QgsAttributeFormWidget::editPage() const
|
||||
{
|
||||
return mEditPage;
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <QVariant>
|
||||
|
||||
class QgsAttributeForm;
|
||||
class QStackedWidget;
|
||||
class QgsSearchWidgetToolButton;
|
||||
|
||||
class GUI_EXPORT QgsAttributeFormWidget : public QWidget // SIP_ABSTRACT
|
||||
{
|
||||
@ -23,6 +25,7 @@ class GUI_EXPORT QgsAttributeFormWidget : public QWidget // SIP_ABSTRACT
|
||||
DefaultMode, //!< Default mode, only the editor widget is shown
|
||||
MultiEditMode, //!< Multi edit mode, both the editor widget and a QgsMultiEditToolButton is shown
|
||||
SearchMode, //!< Layer search/filter mode
|
||||
AggregateSearchMode,
|
||||
};
|
||||
|
||||
explicit QgsAttributeFormWidget( QgsWidgetWrapper *widget, QgsAttributeForm *form );
|
||||
@ -40,7 +43,7 @@ class GUI_EXPORT QgsAttributeFormWidget : public QWidget // SIP_ABSTRACT
|
||||
* search properties represented in the widget.
|
||||
* \since QGIS 2.16
|
||||
*/
|
||||
virtual QString currentFilterExpression() const = 0;
|
||||
virtual QString currentFilterExpression() const;
|
||||
|
||||
|
||||
/**
|
||||
@ -61,10 +64,72 @@ class GUI_EXPORT QgsAttributeFormWidget : public QWidget // SIP_ABSTRACT
|
||||
|
||||
QgsAttributeForm *form() const;
|
||||
|
||||
/**
|
||||
* Returns the widget which should be used as a parent during construction
|
||||
* of the search widget wrapper.
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
QWidget *searchWidgetFrame() SIP_SKIP;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the search widget wrapper for the widget used when the form is in
|
||||
* search mode.
|
||||
* \param wrapper search widget wrapper.
|
||||
* \note the search widget wrapper should be created using searchWidgetFrame()
|
||||
* as its parent
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
void setSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
|
||||
void addAdditionalSearchWidgetWrapper( QgsSearchWidgetWrapper *wrapper );
|
||||
|
||||
/**
|
||||
* Returns the search widget wrapper used in this widget. The wrapper must
|
||||
* first be created using createSearchWidgetWrapper()
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
QList< QgsSearchWidgetWrapper * > searchWidgetWrappers();
|
||||
|
||||
/**
|
||||
* Resets the search/filter value of the widget.
|
||||
*/
|
||||
void resetSearch();
|
||||
|
||||
protected:
|
||||
QWidget *editPage() const SIP_SKIP;
|
||||
|
||||
QStackedWidget *stack() const SIP_SKIP;
|
||||
|
||||
QWidget *searchPage() const SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the search widget tool button in the widget.
|
||||
* \note this method is in place for unit testing only, and is not considered
|
||||
* stable API
|
||||
*/
|
||||
QgsSearchWidgetToolButton *searchWidgetToolButton();
|
||||
|
||||
private slots:
|
||||
|
||||
//! Triggered when search button flags are changed
|
||||
void searchWidgetFlagsChanged( QgsSearchWidgetWrapper::FilterFlags flags );
|
||||
|
||||
private:
|
||||
virtual void updateWidgets();
|
||||
|
||||
QgsAttributeFormWidget::Mode mMode = DefaultMode;
|
||||
virtual void updateWidgets() = 0;
|
||||
QgsSearchWidgetToolButton *mSearchWidgetToolButton = nullptr;
|
||||
QWidget *mEditPage = nullptr;
|
||||
QWidget *mSearchPage = nullptr;
|
||||
QStackedWidget *mStack = nullptr;
|
||||
QWidget *mSearchFrame = nullptr;
|
||||
QgsAttributeForm *mForm = nullptr;
|
||||
QList< QgsSearchWidgetWrapper * > mSearchWidgets;
|
||||
QgsWidgetWrapper *mWidget = nullptr;
|
||||
};
|
||||
|
||||
#endif // QGSATTRIBUTEFORMWIDGET_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user