18 #include <QPushButton> 20 #include <QHBoxLayout> 39 switch ( p1.first.type() )
41 case QVariant::String:
42 return p1.first.toString() < p2.first.toString();
45 case QVariant::Double:
46 return p1.first.toDouble() < p2.first.toDouble();
50 return p1.first.toInt() < p2.first.toInt();
60 , mForeignKey( QVariant() )
66 , mMessageBarItem( NULL )
68 , mReferencedAttributeForm( NULL )
69 , mReferencedLayer( NULL )
70 , mReferencingLayer( NULL )
71 , mWindowWidget( NULL )
75 , mReadOnlySelector( false )
76 , mAllowMapIdentification( false )
77 , mOrderByValue( false )
78 , mOpenFormButtonVisible( true )
80 mTopLayout =
new QVBoxLayout(
this );
81 mTopLayout->setContentsMargins( 0, 0, 0, 0 );
82 mTopLayout->setAlignment( Qt::AlignTop );
83 setLayout( mTopLayout );
85 QHBoxLayout* editLayout =
new QHBoxLayout();
86 editLayout->setContentsMargins( 0, 0, 0, 0 );
87 editLayout->setSpacing( 2 );
90 mComboBox =
new QComboBox(
this );
91 editLayout->addWidget( mComboBox );
94 mLineEdit =
new QLineEdit(
this );
95 mLineEdit->setReadOnly(
true );
96 editLayout->addWidget( mLineEdit );
99 mOpenFormButton =
new QToolButton(
this );
101 mOpenFormButton->setText(
tr(
"Open related feature form" ) );
102 editLayout->addWidget( mOpenFormButton );
105 mHighlightFeatureButton =
new QToolButton(
this );
106 mHighlightFeatureButton->setPopupMode( QToolButton::MenuButtonPopup );
108 mScaleHighlightFeatureAction =
new QAction(
QgsApplication::getThemeIcon(
"/mActionScaleHighlightFeature.svg" ),
tr(
"Scale and highlight feature" ),
this );
109 mPanHighlightFeatureAction =
new QAction(
QgsApplication::getThemeIcon(
"/mActionPanHighlightFeature.svg" ),
tr(
"Pan and highlight feature" ),
this );
110 mHighlightFeatureButton->addAction( mHighlightFeatureAction );
111 mHighlightFeatureButton->addAction( mScaleHighlightFeatureAction );
112 mHighlightFeatureButton->addAction( mPanHighlightFeatureAction );
113 mHighlightFeatureButton->setDefaultAction( mHighlightFeatureAction );
114 editLayout->addWidget( mHighlightFeatureButton );
117 mMapIdentificationButton =
new QToolButton(
this );
119 mMapIdentificationButton->setText(
tr(
"Select on map" ) );
120 mMapIdentificationButton->setCheckable(
true );
121 editLayout->addWidget( mMapIdentificationButton );
124 mRemoveFKButton =
new QToolButton(
this );
126 mRemoveFKButton->setText(
tr(
"No selection" ) );
127 editLayout->addWidget( mRemoveFKButton );
130 editLayout->addItem(
new QSpacerItem( 0, 0, QSizePolicy::Expanding ) );
133 mTopLayout->addLayout( editLayout );
137 mAttributeEditorLayout =
new QVBoxLayout( mAttributeEditorFrame );
138 mAttributeEditorFrame->setLayout( mAttributeEditorLayout );
139 mAttributeEditorFrame->setSizePolicy( mAttributeEditorFrame->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding );
140 mTopLayout->addWidget( mAttributeEditorFrame );
143 mInvalidLabel =
new QLabel(
tr(
"The relation is not valid. Please make sure your relation definitions are ok." ) );
144 mInvalidLabel->setWordWrap(
true );
145 QFont font = mInvalidLabel->font();
146 font.setItalic(
true );
147 mInvalidLabel->setStyleSheet(
"QLabel { color: red; } " );
148 mInvalidLabel->setFont( font );
149 mTopLayout->addWidget( mInvalidLabel );
153 mMapIdentificationButton->hide();
154 mHighlightFeatureButton->hide();
155 mAttributeEditorFrame->hide();
156 mInvalidLabel->hide();
159 connect( mOpenFormButton, SIGNAL( clicked() ),
this, SLOT(
openForm() ) );
160 connect( mHighlightFeatureButton, SIGNAL( triggered( QAction* ) ),
this, SLOT( highlightActionTriggered( QAction* ) ) );
161 connect( mMapIdentificationButton, SIGNAL( clicked() ),
this, SLOT(
mapIdentification() ) );
162 connect( mRemoveFKButton, SIGNAL( clicked() ),
this, SLOT(
deleteForeignKey() ) );
175 mAllowNull = allowNullValue;
176 mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector );
180 mInvalidLabel->hide();
182 mRelation = relation;
184 mRelationName = relation.
name();
192 mAttributeEditorFrame->setTitle( mReferencedLayer->
name() );
195 mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
200 mInvalidLabel->show();
203 if ( mShown && isVisible() )
214 mComboBox->setEnabled( editable );
215 mMapIdentificationButton->setEnabled( editable );
216 mRemoveFKButton->setEnabled( editable );
217 mIsEditable = editable;
222 if ( !value.isValid() || value.isNull() )
229 if ( !mReferencedLayer )
236 if ( f.
attribute( mFkeyFieldIdx ) == value )
248 mForeignKey = f.
attribute( mFkeyFieldIdx );
250 if ( mReadOnlySelector )
253 QString title = expr.
evaluate( &f ).toString();
254 if ( expr.hasEvalError() )
256 title = f.
attribute( mFkeyFieldIdx ).toString();
258 mLineEdit->setText( title );
263 int i = mComboBox->findData( value );
264 if ( i == -1 && mAllowNull )
266 mComboBox->setCurrentIndex( 0 );
270 mComboBox->setCurrentIndex( i );
274 mRemoveFKButton->setEnabled( mIsEditable );
275 highlightFeature( f );
276 updateAttributeEditorFrame( f );
282 QVariant nullValue = QSettings().value(
"qgis/nullValue",
"NULL" );
283 if ( mReadOnlySelector )
285 QString nullText =
"";
288 nullText =
tr(
"%1 (no selection)" ).arg( nullValue.toString() );
290 mLineEdit->setText( nullText );
291 mForeignKey = QVariant();
298 mComboBox->setCurrentIndex( 0 );
302 mComboBox->setCurrentIndex( -1 );
305 mRemoveFKButton->setEnabled(
false );
313 if ( mReferencedLayer )
316 if ( mReadOnlySelector )
322 fid = mComboBox->itemData( mComboBox->currentIndex() ).value<QgsFeatureId>();
331 if ( mReadOnlySelector )
337 QVariant varFid = mComboBox->itemData( mComboBox->currentIndex() );
338 if ( varFid.isNull() )
351 mEditorContext = context;
353 mMessageBar = messageBar;
358 mMapTool->
setAction( mMapIdentificationButton->defaultAction() );
363 mAttributeEditorFrame->setVisible( display );
364 mEmbedForm = display;
369 mComboBox->setHidden( readOnly );
370 mLineEdit->setVisible( readOnly );
371 mRemoveFKButton->setVisible( mAllowNull && readOnly );
372 mReadOnlySelector = readOnly;
377 mHighlightFeatureButton->setVisible( allowMapIdentification );
378 mMapIdentificationButton->setVisible( allowMapIdentification );
389 mOpenFormButton->setVisible( openFormButtonVisible );
404 if ( !mReadOnlySelector && mComboBox->count() == 0 && mReferencedLayer )
406 QApplication::setOverrideCursor( Qt::WaitCursor );
409 const QString nullValue = QSettings().value(
"qgis/nullValue",
"NULL" ).toString();
411 mComboBox->addItem(
tr(
"%1 (no selection)" ).arg( nullValue ), QVariant( QVariant::Int ) );
412 mComboBox->setItemData( 0, QColor( Qt::gray ), Qt::ForegroundRole );
418 attrs << mRelation.
fieldPairs().first().second;
433 QVariant val = exp.evaluate( &f );
434 cache.append( qMakePair( val, f.
id() ) );
435 mFidFkMap.insert( f.
id(), f.
attribute( mFkeyFieldIdx ) );
436 if ( f.
attribute( mFkeyFieldIdx ) == mForeignKey )
437 currentSelection = f.
id();
444 mComboBox->addItem( item.first.toString(), item.second );
446 if ( currentSelection == item.second )
447 mComboBox->setCurrentIndex( mComboBox->count() - 1 );
454 QString txt = exp.evaluate( &f ).toString();
455 mComboBox->addItem( txt, f.
id() );
457 if ( f.
attribute( mFkeyFieldIdx ) == mForeignKey )
458 mComboBox->setCurrentIndex( mComboBox->count() - 1 );
460 mFidFkMap.insert( f.
id(), f.
attribute( mFkeyFieldIdx ) );
465 connect( mComboBox, SIGNAL( activated(
int ) ),
this, SLOT( comboReferenceChanged(
int ) ) );
466 QApplication::restoreOverrideCursor();
470 void QgsRelationReferenceWidget::highlightActionTriggered( QAction* action )
472 if ( action == mHighlightFeatureAction )
476 else if ( action == mScaleHighlightFeatureAction )
480 else if ( action == mPanHighlightFeatureAction )
495 attributeDialog.exec();
517 if ( canvasExtent ==
Scale )
530 else if ( canvasExtent ==
Pan )
541 mHighlight =
new QgsHighlight( mCanvas, f, mReferencedLayer );
549 color.setAlpha( alpha );
555 QTimer* timer =
new QTimer(
this );
556 timer->setSingleShot(
true );
557 connect( timer, SIGNAL( timeout() ),
this, SLOT( deleteHighlight() ) );
558 timer->start( 3000 );
561 void QgsRelationReferenceWidget::deleteHighlight()
573 if ( !mAllowMapIdentification || !mReferencedLayer )
582 mMapTool->
setLayer( mReferencedLayer );
585 mWindowWidget = window();
587 mCanvas->window()->raise();
588 mCanvas->activateWindow();
590 connect( mMapTool, SIGNAL( featureIdentified(
QgsFeature ) ),
this, SLOT( featureIdentified(
const QgsFeature ) ) );
591 connect( mMapTool, SIGNAL( deactivated() ),
this, SLOT( mapToolDeactivated() ) );
595 QString title = QString(
"Relation %1 for %2." ).arg( mRelationName ).arg( mReferencingLayer->
name() );
596 QString msg =
tr(
"Identify a feature of %1 to be associated. Press <ESC> to cancel." ).arg( mReferencedLayer->
name() );
598 mMessageBar->
pushItem( mMessageBarItem );
602 void QgsRelationReferenceWidget::comboReferenceChanged(
int index )
607 highlightFeature( feat );
608 updateAttributeEditorFrame( feat );
612 void QgsRelationReferenceWidget::updateAttributeEditorFrame(
const QgsFeature feature )
615 if ( mAttributeEditorFrame )
617 if ( mReferencedAttributeForm )
619 mReferencedAttributeForm->
setFeature( feature );
624 void QgsRelationReferenceWidget::featureIdentified(
const QgsFeature& feature )
626 if ( mReadOnlySelector )
629 QString title = expr.
evaluate( &feature ).toString();
630 if ( expr.hasEvalError() )
632 title = feature.
attribute( mFkeyFieldIdx ).toString();
634 mLineEdit->setText( title );
635 mForeignKey = feature.
attribute( mFkeyFieldIdx );
636 mFeatureId = feature.
id();
640 mComboBox->setCurrentIndex( mComboBox->findData( feature.
attribute( mFkeyFieldIdx ) ) );
643 mRemoveFKButton->setEnabled( mIsEditable );
644 highlightFeature( feature );
645 updateAttributeEditorFrame( feature );
651 void QgsRelationReferenceWidget::unsetMapTool()
654 if ( mCanvas && mMapTool )
661 void QgsRelationReferenceWidget::mapToolDeactivated()
665 mWindowWidget->raise();
666 mWindowWidget->activateWindow();
669 if ( mMessageBar && mMessageBarItem )
671 mMessageBar->
popWidget( mMessageBarItem );
673 mMessageBarItem = NULL;
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) ...
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.
const QString name() const
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
QStringList referencedColumns() const
Get list of columns referenced by the expression.
void zoomByFactor(double scaleFactor, const QgsPoint *center=0)
Zoom with the factor supplied.
bool isValid() const
Return the validity of this feature.
A form was opened as a new dialog.
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
A groupbox that collapses/expands when toggled and can save its collapsed and checked states...
This class contains context information for attribute editor widgets.
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.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
void setFillColor(const QColor &fillColor)
Set polygons fill color.
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
const QString displayExpression()
Get the preview expression, used to create a human readable preview string.
Map canvas is a class for displaying all GIS data types on a canvas.
QgsGeometry * centroid()
Returns the center of mass of a geometry.
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.
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
static QgsMessageBarItem * createMessage(const QString &text, QWidget *parent=0)
make out a widget containing a message to be displayed on the bar
bool popWidget(QgsMessageBarItem *item)
QgsVectorLayer * referencingLayer() const
Access the referencing (child) layer This is the layer which has the field(s) which point to another ...
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)...
A class to represent a point.
QgsRectangle boundingBox()
Returns the bounding box of this feature.
void pushItem(QgsMessageBarItem *item)
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
void setColor(const QColor &color)
Set line/outline to color, polygon fill to color with alpha = 63.
const QgsVectorLayerTools * vectorLayerTools() const
QList< FieldPair > fieldPairs() const
Returns the field pairs which form this relation The first element of each pair are the field names f...
QgsRectangle extent() const
Returns the current zoom exent of the map canvas.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
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...
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
static double DEFAULT_HIGHLIGHT_MIN_WIDTH_MM
Default highlight line/outline minimum width in mm.
A form was embedded as a widget on another form.
void setMinWidth(double width)
Set minimum line / outline width in millimeters.
void scale(double scaleFactor, const QgsPoint *c=0)
Scale the rectangle around its center point.