Skip to content

Commit

Permalink
Search widget wrapper for relation reference widget
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 25, 2016
1 parent 6837996 commit 9f325df
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 6 deletions.
@@ -0,0 +1,42 @@

/** \ingroup gui
* \class QgsRelationReferenceSearchWidgetWrapper
* Wraps a relation reference search widget.
* \note Added in version 2.16
*/

class QgsRelationReferenceSearchWidgetWrapper : QgsSearchWidgetWrapper
{
%TypeHeaderCode
#include <qgsrelationreferencesearchwidgetwrapper.h>
%End
public:

explicit QgsRelationReferenceSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QgsMapCanvas* canvas, QWidget* parent = nullptr );
bool applyDirectly();
QString expression();
bool valid() const;
QVariant value() const;
FilterFlags supportedFlags() const;
FilterFlags defaultFlags() const;
virtual QString createExpression( FilterFlags flags ) const;

public slots:

virtual void clearWidget();
virtual void setEnabled( bool enabled );

protected:
QWidget* createWidget( QWidget* parent );
void initWidget( QWidget* editor );

public slots:

//! Called when current value of search widget changes
void onValueChanged( QVariant value );

protected slots:
void setExpression( QString exp );

};

1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -258,6 +258,7 @@
%Include editorwidgets/qgsdefaultsearchwidgetwrapper.sip
%Include editorwidgets/qgsdoublespinbox.sip
%Include editorwidgets/qgsmultiedittoolbutton.sip
%Include editorwidgets/qgsrelationreferencesearchwidgetwrapper.sip
%Include editorwidgets/qgsrelationreferencewidget.sip
%Include editorwidgets/qgsrelationreferencewidgetwrapper.sip
%Include editorwidgets/qgsrelationwidgetwrapper.sip
Expand Down
10 changes: 4 additions & 6 deletions src/app/qgsattributetabledialog.cpp
Expand Up @@ -98,16 +98,14 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
// Initialize the window geometry
restoreGeometry( settings.value( "/Windows/BetterAttributeTable/geometry" ).toByteArray() );

QgsAttributeEditorContext context;

myDa = new QgsDistanceArea();

myDa->setSourceCrs( mLayer->crs() );
myDa->setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
myDa->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );

context.setDistanceArea( *myDa );
context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );
mEditorContext.setDistanceArea( *myDa );
mEditorContext.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );

QgsFeatureRequest r;
if ( mLayer->geometryType() != QGis::NoGeometry &&
Expand All @@ -126,7 +124,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
}

// Initialize dual view
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, context );
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext );
mMainView->setAttributeTableConfig( mLayer->attributeTableConfig() );

// Initialize filter gui elements
Expand Down Expand Up @@ -494,7 +492,7 @@ void QgsAttributeTableDialog::filterColumnChanged( QObject* filterAction )
const QString widgetType = mLayer->editFormConfig()->widgetType( fldIdx );
const QgsEditorWidgetConfig widgetConfig = mLayer->editFormConfig()->widgetConfig( fldIdx );
mCurrentSearchWidgetWrapper = QgsEditorWidgetRegistry::instance()->
createSearchWidget( widgetType, mLayer, fldIdx, widgetConfig, mFilterContainer );
createSearchWidget( widgetType, mLayer, fldIdx, widgetConfig, mFilterContainer, mEditorContext );
if ( mCurrentSearchWidgetWrapper->applyDirectly() )
{
connect( mCurrentSearchWidgetWrapper, SIGNAL( expressionChanged( QString ) ), SLOT( filterQueryChanged( QString ) ) );
Expand Down
1 change: 1 addition & 0 deletions src/app/qgsattributetabledialog.h
Expand Up @@ -234,6 +234,7 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
QgsRubberBand* mRubberBand;
QgsSearchWidgetWrapper* mCurrentSearchWidgetWrapper;
QStringList mVisibleFields;
QgsAttributeEditorContext mEditorContext;

void updateMultiEditButtonState();

Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -130,6 +130,7 @@ SET(QGIS_GUI_SRCS
editorwidgets/qgsrelationwidgetwrapper.cpp
editorwidgets/qgsrelationreferenceconfigdlg.cpp
editorwidgets/qgsrelationreferencefactory.cpp
editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp
editorwidgets/qgsrelationreferencewidget.cpp
editorwidgets/qgsrelationreferencewidgetwrapper.cpp
editorwidgets/qgstexteditconfigdlg.cpp
Expand Down Expand Up @@ -548,6 +549,7 @@ SET(QGIS_GUI_MOC_HDRS
editorwidgets/qgsrangeconfigdlg.h
editorwidgets/qgsrangewidgetwrapper.h
editorwidgets/qgsrelationreferenceconfigdlg.h
editorwidgets/qgsrelationreferencesearchwidgetwrapper.h
editorwidgets/qgsrelationreferencewidget.h
editorwidgets/qgsrelationreferencewidgetwrapper.h
editorwidgets/qgsrelationwidgetwrapper.h
Expand Down
6 changes: 6 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencefactory.cpp
Expand Up @@ -18,6 +18,7 @@

#include "qgsrelationreferencewidgetwrapper.h"
#include "qgsrelationreferenceconfigdlg.h"
#include "qgsrelationreferencesearchwidgetwrapper.h"

QgsRelationReferenceFactory::QgsRelationReferenceFactory( const QString& name, QgsMapCanvas* canvas, QgsMessageBar* messageBar )
: QgsEditorWidgetFactory( name )
Expand All @@ -31,6 +32,11 @@ QgsEditorWidgetWrapper* QgsRelationReferenceFactory::create( QgsVectorLayer* vl,
return new QgsRelationReferenceWidgetWrapper( vl, fieldIdx, editor, mCanvas, mMessageBar, parent );
}

QgsSearchWidgetWrapper*QgsRelationReferenceFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsRelationReferenceSearchWidgetWrapper( vl, fieldIdx, mCanvas, parent );
}

QgsEditorConfigWidget* QgsRelationReferenceFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsRelationReferenceConfigDlg( vl, fieldIdx, parent );
Expand Down
2 changes: 2 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencefactory.h
Expand Up @@ -45,6 +45,8 @@ class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory
*/
virtual QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const override;

QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;

/**
* Override this in your implementation.
* Create a new configuration widget for this widget type.
Expand Down
193 changes: 193 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencesearchwidgetwrapper.cpp
@@ -0,0 +1,193 @@
/***************************************************************************
qgsrelationreferencesearchwidgetwrapper.cpp
------------------------------------------
Date : 2016-05-25
Copyright : (C) 2016 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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 "qgsrelationreferencesearchwidgetwrapper.h"

#include "qgsfield.h"
#include "qgsmaplayerregistry.h"
#include "qgsvaluerelationwidgetfactory.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"

#include <QSettings>
#include <QStringListModel>

QgsRelationReferenceSearchWidgetWrapper::QgsRelationReferenceSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QgsMapCanvas* canvas, QWidget* parent )
: QgsSearchWidgetWrapper( vl, fieldIdx, parent )
, mWidget( nullptr )
, mLayer( nullptr )
, mCanvas( canvas )
{

}

bool QgsRelationReferenceSearchWidgetWrapper::applyDirectly()
{
return true;
}

QString QgsRelationReferenceSearchWidgetWrapper::expression()
{
return mExpression;
}

QVariant QgsRelationReferenceSearchWidgetWrapper::value() const
{
if ( mWidget )
{
return mWidget->foreignKey();
}
return QVariant();
}

QgsSearchWidgetWrapper::FilterFlags QgsRelationReferenceSearchWidgetWrapper::supportedFlags() const
{
return EqualTo | NotEqualTo | IsNull | IsNotNull;
}

QgsSearchWidgetWrapper::FilterFlags QgsRelationReferenceSearchWidgetWrapper::defaultFlags() const
{
return EqualTo;
}

QString QgsRelationReferenceSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
{
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );

//clear any unsupported flags
flags &= supportedFlags();
if ( flags & IsNull )
return fieldName + " IS NULL";
if ( flags & IsNotNull )
return fieldName + " IS NOT NULL";

QVariant v = value();
if ( !v.isValid() )
return QString();

switch ( v.type() )
{
case QVariant::Int:
case QVariant::UInt:
case QVariant::Double:
case QVariant::LongLong:
case QVariant::ULongLong:
{
if ( flags & EqualTo )
return fieldName + '=' + v.toString();
else if ( flags & NotEqualTo )
return fieldName + "<>" + v.toString();
break;
}

default:
{
if ( flags & EqualTo )
return fieldName + "='" + v.toString() + '\'';
else if ( flags & NotEqualTo )
return fieldName + "<>'" + v.toString() + '\'';
break;
}
}

return QString();
}

void QgsRelationReferenceSearchWidgetWrapper::clearWidget()
{
if ( mWidget )
{
mWidget->showIndeterminateState();
}
}

void QgsRelationReferenceSearchWidgetWrapper::setEnabled( bool enabled )
{
if ( mWidget )
{
mWidget->setEnabled( enabled );
}
}

bool QgsRelationReferenceSearchWidgetWrapper::valid() const
{
return true;
}

void QgsRelationReferenceSearchWidgetWrapper::onValueChanged( QVariant value )
{
if ( !value.isValid() )
{
clearExpression();
emit valueCleared();
}
else
{
QSettings settings;
setExpression( value.isNull() ? settings.value( "qgis/nullValue", "NULL" ).toString() : value.toString() );
emit valueChanged();
}
emit expressionChanged( mExpression );
}

void QgsRelationReferenceSearchWidgetWrapper::setExpression( QString exp )
{
QSettings settings;
QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
QString fieldName = layer()->fields().at( mFieldIdx ).name();

QString str;
if ( exp == nullValue )
{
str = QString( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
}
else
{
str = QString( "%1 = '%3'" )
.arg( QgsExpression::quotedColumnRef( fieldName ),
exp.replace( '\'', "''" )
);
}
mExpression = str;
}

QWidget* QgsRelationReferenceSearchWidgetWrapper::createWidget( QWidget* parent )
{
return new QgsRelationReferenceWidget( parent );
}

void QgsRelationReferenceSearchWidgetWrapper::initWidget( QWidget* editor )
{
mWidget = qobject_cast<QgsRelationReferenceWidget*>( editor );
if ( !mWidget )
return;

mWidget->setEditorContext( context(), mCanvas, nullptr );

mWidget->setEmbedForm( false );
mWidget->setReadOnlySelector( false );
mWidget->setAllowMapIdentification( config( "MapIdentification", false ).toBool() );
mWidget->setOrderByValue( config( "OrderByValue", false ).toBool() );
mWidget->setAllowAddFeatures( false );
mWidget->setOpenFormButtonVisible( false );

QgsRelation relation = QgsProject::instance()->relationManager()->relation( config( "Relation" ).toString() );
mWidget->setRelation( relation, false );

mWidget->showIndeterminateState();
connect( mWidget, SIGNAL( foreignKeyChanged( QVariant ) ), this, SLOT( onValueChanged( QVariant ) ) );
}


0 comments on commit 9f325df

Please sign in to comment.