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();
498 void QgsRelationReferenceWidget::highlightFeature(
QgsFeature f, CanvasExtent canvasExtent )
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;