18 #include <QPushButton>
20 #include <QHBoxLayout>
40 switch ( p1.first.type() )
42 case QVariant::String:
43 return p1.first.toString() < p2.first.toString();
46 case QVariant::Double:
47 return p1.first.toDouble() < p2.first.toDouble();
51 return p1.first.toInt() < p2.first.toInt();
66 , mMessageBarItem( NULL )
68 , mReferencedAttributeForm( NULL )
69 , mReferencedLayer( NULL )
70 , mReferencingLayer( NULL )
73 , mFeatureListModel( 0 )
74 , mWindowWidget( NULL )
78 , mReadOnlySelector( false )
79 , mAllowMapIdentification( false )
80 , mOrderByValue( false )
81 , mOpenFormButtonVisible( true )
82 , mChainFilters( false )
94 mChooserContainer =
new QWidget;
95 editLayout->
addWidget( mChooserContainer );
100 mFilterContainer =
new QWidget;
101 mFilterContainer->
setLayout( mFilterLayout );
102 mChooserContainer->
setLayout( chooserLayout );
103 chooserLayout->
addWidget( mFilterContainer );
117 mOpenFormButton->
setText(
tr(
"Open related feature form" ) );
118 editLayout->
addWidget( mOpenFormButton );
122 mHighlightFeatureButton->
setPopupMode( QToolButton::MenuButtonPopup );
126 mHighlightFeatureButton->
addAction( mHighlightFeatureAction );
127 mHighlightFeatureButton->
addAction( mScaleHighlightFeatureAction );
128 mHighlightFeatureButton->
addAction( mPanHighlightFeatureAction );
130 editLayout->
addWidget( mHighlightFeatureButton );
133 mMapIdentificationButton =
new QToolButton(
this );
135 mMapIdentificationButton->
setText(
tr(
"Select on map" ) );
137 editLayout->
addWidget( mMapIdentificationButton );
142 mRemoveFKButton->
setText(
tr(
"No selection" ) );
143 editLayout->
addWidget( mRemoveFKButton );
153 mAttributeEditorLayout =
new QVBoxLayout( mAttributeEditorFrame );
154 mAttributeEditorFrame->
setLayout( mAttributeEditorLayout );
155 mAttributeEditorFrame->
setSizePolicy( mAttributeEditorFrame->
sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
156 mTopLayout->
addWidget( mAttributeEditorFrame );
159 mInvalidLabel =
new QLabel(
tr(
"The relation is not valid. Please make sure your relation definitions are ok." ) );
164 mInvalidLabel->
setFont( font );
169 mMapIdentificationButton->
hide();
170 mHighlightFeatureButton->
hide();
171 mAttributeEditorFrame->
hide();
172 mInvalidLabel->
hide();
175 connect( mOpenFormButton, SIGNAL( clicked() ),
this, SLOT(
openForm() ) );
176 connect( mHighlightFeatureButton, SIGNAL( triggered(
QAction* ) ),
this, SLOT( highlightActionTriggered(
QAction* ) ) );
191 mAllowNull = allowNullValue;
192 mRemoveFKButton->
setVisible( allowNullValue && mReadOnlySelector );
196 mInvalidLabel->
hide();
198 mRelation = relation;
200 mRelationName = relation.
name();
208 mAttributeEditorFrame->
setTitle( mReferencedLayer->
name() );
211 mAttributeEditorLayout->
addWidget( mReferencedAttributeForm );
216 mInvalidLabel->
show();
232 mMapIdentificationButton->
setEnabled( editable );
234 mIsEditable = editable;
245 if ( !mReferencedLayer )
249 attrs[mFkeyFieldIdx] = value;
261 mForeignKey = mFeature.
attribute( mFkeyFieldIdx );
263 if ( mReadOnlySelector )
270 context.setFeature( mFeature );
271 QString title = expr.evaluate( &context ).toString();
272 if ( expr.hasEvalError() )
281 if ( i == -1 && mAllowNull )
292 highlightFeature( mFeature );
293 updateAttributeEditorFrame( mFeature );
300 if ( mReadOnlySelector )
305 nullText =
tr(
"%1 (no selection)" ).
arg( nullValue.
toString() );
307 mLineEdit->
setText( nullText );
330 if ( mReferencedLayer )
333 if ( mReadOnlySelector )
348 if ( mReadOnlySelector )
360 return mFeature.
attribute( mFkeyFieldIdx );
367 mEditorContext = context;
369 mMessageBar = messageBar;
374 mMapTool->
setButton( mMapIdentificationButton );
380 mEmbedForm = display;
385 mChooserContainer->
setHidden( readOnly );
387 mRemoveFKButton->
setVisible( mAllowNull && readOnly );
388 mReadOnlySelector = readOnly;
393 mHighlightFeatureButton->
setVisible( allowMapIdentification );
394 mMapIdentificationButton->
setVisible( allowMapIdentification );
405 mFilterFields = filterFields;
410 mOpenFormButton->
setVisible( openFormButtonVisible );
430 if ( !mReadOnlySelector && mComboBox->
count() == 0 && mReferencedLayer )
438 if ( mFilterFields.
size() )
440 Q_FOREACH (
const QString& fieldName, mFilterFields )
442 QVariantList uniqueValues;
446 mFilterComboBoxes << cb;
452 Q_FOREACH (
const QVariant& v, uniqueValues )
457 connect( cb, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT( filterChanged() ) );
460 requestedAttrs << fieldName;
473 for (
int i = 0; i < mFilterComboBoxes.
count() - 1; ++i )
479 mFilterCache[mFilterFields[i]][cf] << nf;
487 requestedAttrs += exp.referencedColumns().toSet();
488 requestedAttrs << mRelation.
fieldPairs().at( 0 ).second;
491 Q_FOREACH (
const QString& attr, requestedAttrs )
507 if ( referencedColumns.
size() > 0 )
510 mFilterModel->
sort( sortIdx );
514 mComboBox->
setModel( mFeatureListModel );
518 if ( mChainFilters && mFeature.
isValid() )
520 for (
int i = 0; i < mFilterFields.
size(); i++ )
524 mFilterComboBoxes[i]->setCurrentIndex( mFilterComboBoxes[i]->findText( f ) );
531 connect( mComboBox, SIGNAL( currentIndexChanged(
int ) ),
this, SLOT( comboReferenceChanged(
int ) ) );
536 void QgsRelationReferenceWidget::highlightActionTriggered(
QAction* action )
538 if ( action == mHighlightFeatureAction )
542 else if ( action == mScaleHighlightFeatureAction )
546 else if ( action == mPanHighlightFeatureAction )
561 attributeDialog.
exec();
564 void QgsRelationReferenceWidget::highlightFeature(
QgsFeature f, CanvasExtent canvasExtent )
584 if ( canvasExtent ==
Scale )
597 else if ( canvasExtent ==
Pan )
608 mHighlight =
new QgsHighlight( mCanvas, f, mReferencedLayer );
624 connect( timer, SIGNAL( timeout() ),
this, SLOT( deleteHighlight() ) );
625 timer->
start( 3000 );
628 void QgsRelationReferenceWidget::deleteHighlight()
640 if ( !mAllowMapIdentification || !mReferencedLayer )
649 mMapTool->
setLayer( mReferencedLayer );
659 connect( mMapTool, SIGNAL( deactivated() ),
this, SLOT( mapToolDeactivated() ) );
664 QString msg =
tr(
"Identify a feature of %1 to be associated. Press <ESC> to cancel." ).
arg( mReferencedLayer->
name() );
666 mMessageBar->
pushItem( mMessageBarItem );
670 void QgsRelationReferenceWidget::comboReferenceChanged(
int index )
674 highlightFeature( mFeature );
675 updateAttributeEditorFrame( mFeature );
679 void QgsRelationReferenceWidget::updateAttributeEditorFrame(
const QgsFeature& feature )
682 if ( mAttributeEditorFrame )
684 if ( mReferencedAttributeForm )
686 mReferencedAttributeForm->
setFeature( feature );
691 void QgsRelationReferenceWidget::featureIdentified(
const QgsFeature& feature )
693 if ( mReadOnlySelector )
700 context.setFeature( feature );
701 QString title = expr.evaluate( &context ).toString();
702 if ( expr.hasEvalError() )
707 mForeignKey = feature.
attribute( mFkeyFieldIdx );
717 highlightFeature( feature );
718 updateAttributeEditorFrame( feature );
724 void QgsRelationReferenceWidget::unsetMapTool()
727 if ( mCanvas && mMapTool )
734 void QgsRelationReferenceWidget::mapToolDeactivated()
738 mWindowWidget->
raise();
742 if ( mMessageBar && mMessageBarItem )
744 mMessageBar->
popWidget( mMessageBarItem );
746 mMessageBarItem = NULL;
749 void QgsRelationReferenceWidget::filterChanged()
763 Q_FOREACH (
QComboBox* cb, mFilterComboBoxes )
802 Q_FOREACH (
QComboBox* cb, mFilterComboBoxes )
810 filters <<
QString(
"\"%1\" IS NULL" ).
arg( fieldName );
814 if ( mReferencedLayer->
fields().
field( fieldName ).
type() == QVariant::String )
827 QString filterExpression = filters.
join(
" AND " );
834 while ( it.nextFeature( f ) )
836 featureIds << f.id();
void unsetMapTool(QgsMapTool *mapTool)
Unset the current map tool or last non zoom tool.
QgsFeatureId id() const
Get the feature ID for this feature.
When showing a single feature (e.g. district information when looking at the form of a house) ...
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
Class for parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool isValid() const
Returns the validity of this relation.
static double DEFAULT_HIGHLIGHT_BUFFER_MM
Default highlight buffer in mm.
A rectangle specified with double values.
static const QColor DEFAULT_HIGHLIGHT_COLOR
Default highlight color.
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from layer's CRS to output CRS
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
void setContentsMargins(int left, int top, int right, int bottom)
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
void zoomByFactor(double scaleFactor, const QgsPoint *center=0)
Zoom with the factor supplied.
bool isValid() const
Returns the validity of this feature.
bool setDisplayExpression(const QString &expression)
A form was opened as a new dialog.
void setText(const QString &)
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
QgsFields fields() const
Returns the list of fields of this layer.
This class contains context information for attribute editor widgets.
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void setExtent(const QgsRectangle &r)
Set the extent of the map canvas.
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
void setFillColor(const QColor &fillColor)
Set polygons fill color.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
A bar for displaying non-blocking messages to the user.
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
QgsVectorLayer * referencedLayer() const
Access the referenced (parent) layer.
void refresh()
Repaints the canvas map.
A geometry is the spatial representation of a feature.
QString join(const QString &separator) const
QString name() const
Returns a human readable name for this relation.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
const QString displayExpression()
Get the preview expression, used to create a human readable preview string.
QgsFeatureRequest getReferencedFeatureRequest(const QgsAttributes &attributes) const
Creates a request to return the feature on the referenced (parent) layer which is referenced by the p...
QString tr(const char *sourceText, const char *disambiguation, int n)
Map canvas is a class for displaying all GIS data types on a canvas.
void setCacheSubsetOfAttributes(const QgsAttributeList &attributes)
Set the subset of attributes to be cached.
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
void addItem(const QString &text, const QVariant &userData)
void setMapTool(QgsMapTool *mapTool)
Sets the map tool currently being used on the canvas.
void setBuffer(double buffer)
Set line / outline buffer in millimeters.
const QString & name() const
Get the display name of the layer.
int count(const T &value) const
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QVariant property(const char *name) const
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=0)
make out a widget containing a message to be displayed on the bar
int toInt(bool *ok) const
bool popWidget(QgsMessageBarItem *item)
Remove the passed widget from the bar (if previously added), then display the next one in the stack i...
QgsVectorLayer * referencingLayer() const
Access the referencing (child) layer This is the layer which has the field(s) which point to another ...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void addItem(QLayoutItem *item)
A class for highlight features on the map.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setOverrideCursor(const QCursor &cursor)
void restoreOverrideCursor()
int count() const
Return number of items.
QgsGeometry * centroid() const
Returns the center of mass of a geometry.
QString attributeAlias(int attributeIndex) const
Returns the alias of an attribute name or an empty string if there is no alias.
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
A class to represent a point.
QVariant itemData(int index, int role) const
bool blockSignals(bool block)
This class caches features of a given QgsVectorLayer.
void setItalic(bool enable)
void setValid(bool validity)
Sets the validity of the feature.
bool setAlignment(QWidget *w, QFlags< Qt::AlignmentFlag > alignment)
QVariant value(const QString &key, const QVariant &defaultValue) const
void pushItem(QgsMessageBarItem *item)
Display a message item on the bar after hiding the currently visible one and putting it in a stack...
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
int findData(const QVariant &data, int role, QFlags< Qt::MatchFlag > flags) const
void setColor(const QColor &color)
Set line/outline to color, polygon fill to color with alpha = 63.
void setModel(QAbstractItemModel *model)
virtual void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
void setTitle(const QString &title)
const QgsVectorLayerTools * vectorLayerTools() const
void setCurrentIndex(int index)
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
QList< FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names f...
void setText(const QString &text)
double toDouble(bool *ok) const
bool setProperty(const char *name, const QVariant &value)
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
void setInjectNull(bool injectNull)
If true is specified, a NULL value will be injected.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsPoint asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
static double DEFAULT_HIGHLIGHT_MIN_WIDTH_MM
Default highlight line/outline minimum width in mm.
void setWordWrap(bool on)
void setSpacing(int spacing)
A form was embedded as a widget on another form.
char * toString(const QLatin1String &string)
void addLayout(QLayout *layout, int stretch)
void setMinWidth(double width)
Set minimum line / outline width in millimeters.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
void setSingleShot(bool singleShot)
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.