Skip to content

Commit

Permalink
Merge pull request #2059 from carolinux/search-widgets
Browse files Browse the repository at this point in the history
[FEATURE] Search widgets

Makes it easier to filter the attribute table if there are attribute domains attached
  • Loading branch information
m-kuhn committed May 26, 2015
2 parents b5801af + e015a7e commit 95a7408
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 13 deletions.
47 changes: 41 additions & 6 deletions src/app/qgsattributetabledialog.cpp
Expand Up @@ -42,6 +42,8 @@
#include "qgsexpressionselectiondialog.h"
#include "qgsfeaturelistmodel.h"
#include "qgsrubberband.h"
#include "qgsfield.h"
#include "qgseditorwidgetregistry.h"

class QgsAttributeTableDock : public QDockWidget
{
Expand All @@ -64,6 +66,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
, mDock( 0 )
, mLayer( theLayer )
, mRubberBand( 0 )
, mCurrentSearchWidgetWrapper( 0 )
{
setupUi( this );

Expand Down Expand Up @@ -402,12 +405,37 @@ void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, QStrin
mLayer->endEditCommand();
}

void QgsAttributeTableDialog::replaceSearchWidget(QWidget* oldw, QWidget* neww)
{
mFilterLayout->removeWidget(oldw);
oldw->setVisible(false);
mFilterLayout->addWidget(neww,0,0,0);
neww->setVisible(true);
}

void QgsAttributeTableDialog::filterColumnChanged( QObject* filterAction )
{
mFilterButton->setDefaultAction( qobject_cast<QAction *>( filterAction ) );
mFilterButton->setPopupMode( QToolButton::InstantPopup );
mCbxCaseSensitive->setVisible( true );
mFilterQuery->setVisible( true );
// replace the search line edit with a search widget that is suited to the selected field
// delete previous widget
if ( mCurrentSearchWidgetWrapper != 0 )
{
delete mCurrentSearchWidgetWrapper;
}
QString fieldName = mFilterButton->defaultAction()->text();
// get the search widget
int fldIdx = mLayer->fieldNameIndex( fieldName );
if ( fldIdx < 0 )
return;
const QString widgetType = mLayer->editorWidgetV2( fldIdx );
const QgsEditorWidgetConfig widgetConfig = mLayer->editorWidgetV2Config( fldIdx );
mCurrentSearchWidgetWrapper= QgsEditorWidgetRegistry::instance()->
createSearchWidget(widgetType, mLayer, fldIdx, widgetConfig, mFilterContainer);

replaceSearchWidget(mFilterQuery, mCurrentSearchWidgetWrapper->widget());

mApplyFilterButton->setVisible( true );
}

Expand Down Expand Up @@ -677,7 +705,6 @@ void QgsAttributeTableDialog::filterQueryChanged( const QString& query )
else
{
QString fieldName = mFilterButton->defaultAction()->text();

const QgsFields& flds = mLayer->pendingFields();
int fldIndex = mLayer->fieldNameIndex( fieldName );
if ( fldIndex < 0 )
Expand All @@ -694,8 +721,9 @@ void QgsAttributeTableDialog::filterQueryChanged( const QString& query )

QSettings settings;
QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
QString value = mCurrentSearchWidgetWrapper->value().toString();

if ( mFilterQuery->displayText() == nullValue )
if ( value == nullValue )
{
str = QString( "%1 IS NULL" ).arg( QgsExpression::quotedColumnRef( fieldName ) );
}
Expand All @@ -705,9 +733,9 @@ void QgsAttributeTableDialog::filterQueryChanged( const QString& query )
.arg( QgsExpression::quotedColumnRef( fieldName ) )
.arg( numeric ? "=" : sensString )
.arg( numeric
? mFilterQuery->displayText().replace( "'", "''" )
? value.replace( "'", "''" )
:
"%" + mFilterQuery->displayText().replace( "'", "''" ) + "%" ); // escape quotes
"%" + value.replace( "'", "''" ) + "%" ); // escape quotes
}
}

Expand All @@ -717,7 +745,9 @@ void QgsAttributeTableDialog::filterQueryChanged( const QString& query )

void QgsAttributeTableDialog::filterQueryAccepted()
{
if ( mFilterQuery->text().isEmpty() )
if ( (mFilterQuery->isVisible() && mFilterQuery->text().isEmpty()) ||
(mCurrentSearchWidgetWrapper!=0 && mCurrentSearchWidgetWrapper->widget()->isVisible()
&& mCurrentSearchWidgetWrapper->value().toString().isEmpty() ))
{
filterShowAll();
return;
Expand All @@ -731,7 +761,12 @@ void QgsAttributeTableDialog::setFilterExpression( QString filterString )
mFilterButton->setDefaultAction( mActionAdvancedFilter );
mFilterButton->setPopupMode( QToolButton::MenuButtonPopup );
mCbxCaseSensitive->setVisible( false );

mFilterQuery->setVisible( true );
if ( mCurrentSearchWidgetWrapper != 0 )
{
replaceSearchWidget(mCurrentSearchWidgetWrapper->widget(),mFilterQuery);
}
mApplyFilterButton->setVisible( true );
mMainView->setFilterMode( QgsAttributeTableFilterModel::ShowFilteredList );

Expand Down
8 changes: 7 additions & 1 deletion src/app/qgsattributetabledialog.h
Expand Up @@ -29,6 +29,7 @@
#include "qgsattributedialog.h"
#include "qgsvectorlayer.h" //QgsFeatureIds
#include "qgsfieldmodel.h"
#include "qgseditorwidgetwrapper.h"

class QDialogButtonBox;
class QPushButton;
Expand Down Expand Up @@ -158,6 +159,10 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
void updateTitle();

void updateButtonStatus( QString fieldName, bool isValid );

/* replace the search widget with a new one */
void replaceSearchWidget(QWidget* oldw, QWidget* neww);

signals:
/**
* Informs that editing mode has been toggled
Expand Down Expand Up @@ -207,7 +212,8 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
QgsVectorLayer* mLayer;
QgsFieldModel* mFieldModel;

QgsRubberBand *mRubberBand;
QgsRubberBand* mRubberBand;
QgsEditorWidgetWrapper* mCurrentSearchWidgetWrapper;
};

#endif
4 changes: 4 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -60,6 +60,7 @@ attributetable/qgsfeatureselectionmodel.cpp
attributetable/qgsgenericfeatureselectionmanager.cpp
attributetable/qgsvectorlayerselectionmanager.cpp

editorwidgets/core/qgsdefaultsearchwidgetwrapper.cpp
editorwidgets/core/qgseditorconfigwidget.cpp
editorwidgets/core/qgseditorwidgetfactory.cpp
editorwidgets/core/qgseditorwidgetregistry.cpp
Expand Down Expand Up @@ -407,6 +408,9 @@ SET(QGIS_GUI_MOC_HDRS
effects/qgspainteffectwidget.h
effects/qgseffectstackpropertieswidget.h

editorwidgets/core/qgsdefaultsearchwidgetwrapper.h
editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorconfigwidget.h
editorwidgets/core/qgseditorwidgetregistry.h
editorwidgets/core/qgseditorwidgetwrapper.h
Expand Down
59 changes: 59 additions & 0 deletions src/gui/editorwidgets/core/qgsdefaultsearchwidgetwrapper.cpp
@@ -0,0 +1,59 @@
/***************************************************************************
qgstexteditwrapper.cpp
--------------------------------------
Date : 5.1.2014
Copyright : (C) 2014 Matthias Kuhn
Email : matthias dot kuhn at gmx dot 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 "qgsdefaultsearchwidgetwrapper.h"

#include "qgsfield.h"
#include "qgsfieldvalidator.h"

#include <QSettings>
#include <QSizePolicy>

QgsDefaultSearchWidgetWrapper::QgsDefaultSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent )
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
, mLineEdit( NULL )
{
}

QVariant QgsDefaultSearchWidgetWrapper::value()
{
return mLineEdit->text();
}

QWidget* QgsDefaultSearchWidgetWrapper::createWidget( QWidget* parent )
{
return new QgsFilterLineEdit( parent );
}

void QgsDefaultSearchWidgetWrapper::initWidget( QWidget* widget )
{
mLineEdit = qobject_cast<QgsFilterLineEdit*>( widget );
mLineEdit->setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Fixed );
connect( widget, SIGNAL( textChanged( QString ) ), this, SLOT( valueChanged( QString ) ) );
}

void QgsDefaultSearchWidgetWrapper::setValue( const QVariant& value )
{
mLineEdit->setText( value.toString() ); //FIXME no null check :(
}

void QgsDefaultSearchWidgetWrapper::setEnabled( bool enabled )
{
mLineEdit->setReadOnly( !enabled );
//if ( enabled )
//mLineEdit->setPalette( mWritablePalette );
//else
//mLineEdit->setPalette( mReadOnlyPalette );
}
50 changes: 50 additions & 0 deletions src/gui/editorwidgets/core/qgsdefaultsearchwidgetwrapper.h
@@ -0,0 +1,50 @@
/***************************************************************************
qgsdefaultsearchwidgetwrapper.h
--------------------------------------
Date : 21.5.2015
Copyright : (C) 2015 Karolina Alexiou
Email : carolinegr 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. *
* *
***************************************************************************/

#ifndef QGSDEFAULTSEARCHWIDGETWRAPPER_H
#define QGSDEFAULTSEARCHWIDGETWRAPPER_H

#include "qgseditorwidgetwrapper.h"
#include <qgsfilterlineedit.h>


/**
* Wraps a search widget. Default form is just a QgsLineFilterEdit
*
*/

class GUI_EXPORT QgsDefaultSearchWidgetWrapper : public QgsEditorWidgetWrapper
{
Q_OBJECT
public:
explicit QgsDefaultSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor = 0, QWidget* parent = 0 );

// QgsEditorWidgetWrapper interface
public:
QVariant value() override;

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

public slots:
void setValue( const QVariant& value ) override;
void setEnabled( bool enabled ) override;

private:
QgsFilterLineEdit* mLineEdit;
};

#endif // QGSDEFAULTSEARCHWIDGETWRAPPER_H
12 changes: 12 additions & 0 deletions src/gui/editorwidgets/core/qgseditorwidgetfactory.cpp
Expand Up @@ -14,9 +14,12 @@
***************************************************************************/

#include "qgseditorwidgetfactory.h"
#include "qgsdefaultsearchwidgetwrapper.h"

#include <QSettings>

class QgsDefaultSearchWidgetWrapper;

QgsEditorWidgetFactory::QgsEditorWidgetFactory( const QString& name )
: mName( name )
{
Expand All @@ -26,6 +29,15 @@ QgsEditorWidgetFactory::~QgsEditorWidgetFactory()
{
}

/** Override in own factory to get something different than the default (a simple QgsFilterLineEdit)
*
*/
QgsEditorWidgetWrapper* QgsEditorWidgetFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
{

return new QgsDefaultSearchWidgetWrapper(vl, fieldIdx, 0, parent);
}

QString QgsEditorWidgetFactory::name()
{
return mName;
Expand Down
3 changes: 3 additions & 0 deletions src/gui/editorwidgets/core/qgseditorwidgetfactory.h
Expand Up @@ -18,6 +18,7 @@

#include "qgseditorwidgetwrapper.h"
#include "qgsapplication.h"
#include "qgsdefaultsearchwidgetwrapper.h"

#include <QDomNode>
#include <QMap>
Expand Down Expand Up @@ -60,6 +61,8 @@ class GUI_EXPORT QgsEditorWidgetFactory
*/
virtual QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const = 0;

virtual QgsEditorWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent );

/**
* Return The human readable identifier name of this widget type
*
Expand Down
21 changes: 20 additions & 1 deletion src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
Expand Up @@ -16,7 +16,7 @@
#include "qgseditorwidgetregistry.h"

#include "qgsattributeeditorcontext.h"
#include "qgseditorwidgetfactory.h"
//#include "qgseditorwidgetfactory.h"
#include "qgslegacyhelpers.h"
#include "qgsmessagelog.h"
#include "qgsproject.h"
Expand Down Expand Up @@ -102,6 +102,25 @@ QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId
return 0;
}

QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::createSearchWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, QWidget* parent, const QgsAttributeEditorContext &context )
{
if ( mWidgetFactories.contains( widgetId ) )
{
QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->createSearchWidget( vl, fieldIdx, parent );

if ( ww )
{
ww->setConfig( config );
ww->setContext( context );
// Make sure that there is a widget created at this point
// so setValue() et al won't crash
ww->widget();
return ww;
}
}
return 0;
}

QgsEditorConfigWidget* QgsEditorWidgetRegistry::createConfigWidget( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
{
if ( mWidgetFactories.contains( widgetId ) )
Expand Down
7 changes: 7 additions & 0 deletions src/gui/editorwidgets/core/qgseditorwidgetregistry.h
Expand Up @@ -83,6 +83,13 @@ class GUI_EXPORT QgsEditorWidgetRegistry : public QObject
QWidget* parent,
const QgsAttributeEditorContext& context = QgsAttributeEditorContext() );

QgsEditorWidgetWrapper* createSearchWidget( const QString& widgetId,
QgsVectorLayer* vl,
int fieldIdx,
const QgsEditorWidgetConfig& config,
QWidget* parent,
const QgsAttributeEditorContext& context = QgsAttributeEditorContext() );

/**
* Creates a configuration widget
*
Expand Down
6 changes: 6 additions & 0 deletions src/gui/editorwidgets/qgsvaluemapwidgetfactory.cpp
Expand Up @@ -29,6 +29,12 @@ QgsEditorWidgetWrapper* QgsValueMapWidgetFactory::create( QgsVectorLayer* vl, in
return new QgsValueMapWidgetWrapper( vl, fieldIdx, editor, parent );
}


QgsEditorWidgetWrapper* QgsValueMapWidgetFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
{
return new QgsValueMapWidgetWrapper( vl, fieldIdx, 0, parent );
}

QgsEditorConfigWidget* QgsValueMapWidgetFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsValueMapConfigDlg( vl, fieldIdx, parent );
Expand Down
1 change: 1 addition & 0 deletions src/gui/editorwidgets/qgsvaluemapwidgetfactory.h
Expand Up @@ -26,6 +26,7 @@ class GUI_EXPORT QgsValueMapWidgetFactory : public QgsEditorWidgetFactory
// QgsEditorWidgetFactory interface
public:
QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const override;
QgsEditorWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) override;
QgsEditorConfigWidget* configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ) override;
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
Expand Down

0 comments on commit 95a7408

Please sign in to comment.