Skip to content

Commit

Permalink
[FEATURE] Add search widget wrapper for check box widget
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed May 23, 2016
1 parent ca5c7e2 commit 195b4de
Show file tree
Hide file tree
Showing 10 changed files with 314 additions and 2 deletions.
34 changes: 34 additions & 0 deletions python/gui/editorwidgets/qgscheckboxsearchwidgetwrapper.sip
@@ -0,0 +1,34 @@
/**
* Wraps a checkbox search widget.
*/
class QgsCheckboxSearchWidgetWrapper : QgsSearchWidgetWrapper
{
%TypeHeaderCode
#include <qgscheckboxsearchwidgetwrapper.h>
%End
public:

explicit QgsCheckboxSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent /TransferThis/ = nullptr );

// QgsSearchWidgetWrapper interface
public:
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 );

protected slots:
void setExpression( QString exp );
};
1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -252,6 +252,7 @@
%Include editorwidgets/core/qgseditorwidgetwrapper.sip
%Include editorwidgets/core/qgssearchwidgetwrapper.sip
%Include editorwidgets/core/qgswidgetwrapper.sip
%Include editorwidgets/qgscheckboxsearchwidgetwrapper.sip
%Include editorwidgets/qgsdatetimeedit.sip
%Include editorwidgets/qgsdefaultsearchwidgetwrapper.sip
%Include editorwidgets/qgsdoublespinbox.sip
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -94,6 +94,7 @@ SET(QGIS_GUI_SRCS
editorwidgets/core/qgswidgetwrapper.cpp

editorwidgets/qgscheckboxconfigdlg.cpp
editorwidgets/qgscheckboxsearchwidgetwrapper.cpp
editorwidgets/qgscheckboxwidgetwrapper.cpp
editorwidgets/qgscheckboxwidgetfactory.cpp
editorwidgets/qgsclassificationwidgetwrapper.cpp
Expand Down Expand Up @@ -523,6 +524,7 @@ SET(QGIS_GUI_MOC_HDRS
editorwidgets/core/qgswidgetwrapper.h

editorwidgets/qgscheckboxconfigdlg.h
editorwidgets/qgscheckboxsearchwidgetwrapper.h
editorwidgets/qgscheckboxwidgetwrapper.h
editorwidgets/qgsclassificationwidgetwrapper.h
editorwidgets/qgscolorwidgetwrapper.h
Expand Down
1 change: 1 addition & 0 deletions src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
Expand Up @@ -131,6 +131,7 @@ QgsSearchWidgetWrapper* QgsEditorWidgetRegistry::createSearchWidget( const QStri
// Make sure that there is a widget created at this point
// so setValue() et al won't crash
ww->widget();
ww->clearWidget();
return ww;
}
}
Expand Down
166 changes: 166 additions & 0 deletions src/gui/editorwidgets/qgscheckboxsearchwidgetwrapper.cpp
@@ -0,0 +1,166 @@
/***************************************************************************
qgscheckboxsearchwidgetwrapper.cpp
---------------------------------
Date : 2016-05-23
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 "qgscheckboxsearchwidgetwrapper.h"

#include "qgsfield.h"
#include "qgscheckboxwidgetfactory.h"
#include "qgsvectorlayer.h"

#include <QSettings>
#include <QCheckBox>

QgsCheckboxSearchWidgetWrapper::QgsCheckboxSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
: QgsSearchWidgetWrapper( vl, fieldIdx, parent )
, mCheckBox( nullptr )
, mLayer( nullptr )
{
}

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

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

QVariant QgsCheckboxSearchWidgetWrapper::value() const
{
QVariant v;

if ( mCheckBox )
v = mCheckBox->isChecked() ? config( "CheckedState" ) : config( "UncheckedState" );

return v;
}

QgsSearchWidgetWrapper::FilterFlags QgsCheckboxSearchWidgetWrapper::supportedFlags() const
{
return EqualTo | IsNull;
}

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

QString QgsCheckboxSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
{
QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );

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

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

switch ( fldType )
{
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 QgsCheckboxSearchWidgetWrapper::clearWidget()
{
if ( mCheckBox )
{
whileBlocking( mCheckBox )->setCheckState( Qt::PartiallyChecked );
}
}

void QgsCheckboxSearchWidgetWrapper::setEnabled( bool enabled )
{
if ( mCheckBox )
{
mCheckBox->setEnabled( enabled );
}
}

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

void QgsCheckboxSearchWidgetWrapper::setExpression( QString exp )
{
QString fieldName = layer()->fields().at( mFieldIdx ).name();

QString str = QString( "%1 = '%3'" )
.arg( QgsExpression::quotedColumnRef( fieldName ),
exp.replace( '\'', "''" )
);
mExpression = str;
}

void QgsCheckboxSearchWidgetWrapper::stateChanged( int )
{
if ( mCheckBox )
{
mCheckBox->setTristate( false );
QString exp = value().toString();
setExpression( exp );
emit valueChanged();
emit expressionChanged( mExpression );
}
}

QWidget* QgsCheckboxSearchWidgetWrapper::createWidget( QWidget* parent )
{
QCheckBox* c = new QCheckBox( parent );
c->setChecked( Qt::PartiallyChecked );
return c;
}

void QgsCheckboxSearchWidgetWrapper::initWidget( QWidget* editor )
{
mCheckBox = qobject_cast<QCheckBox*>( editor );

if ( mCheckBox )
{
mCheckBox->setChecked( Qt::PartiallyChecked );
connect( mCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( stateChanged( int ) ) );
}
}


67 changes: 67 additions & 0 deletions src/gui/editorwidgets/qgscheckboxsearchwidgetwrapper.h
@@ -0,0 +1,67 @@
/***************************************************************************
qgscheckboxsearchwidgetwrapper.h
-------------------------------
Date : 2016-05-23
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. *
* *
***************************************************************************/

#ifndef QGSCHECKBOXSEARCHWIDGETWRAPPER_H
#define QGSCHECKBOXSEARCHWIDGETWRAPPER_H

#include "qgssearchwidgetwrapper.h"
#include "qgscheckboxwidgetwrapper.h"

#include <QComboBox>
#include <QListWidget>
#include <QLineEdit>

class QgsCheckboxWidgetFactory;

/**
* Wraps a checkbox search widget.
*/
class GUI_EXPORT QgsCheckboxSearchWidgetWrapper : public QgsSearchWidgetWrapper
{
Q_OBJECT

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

public slots:

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

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

protected slots:
void setExpression( QString exp ) override;

private slots:
void stateChanged( int state );

private:
QCheckBox* mCheckBox;
QgsVectorLayer* mLayer;

friend class QgsCheckboxWidgetFactory;
};

#endif // QGSCHECKBOXSEARCHWIDGETWRAPPER_H
7 changes: 6 additions & 1 deletion src/gui/editorwidgets/qgscheckboxwidgetfactory.cpp
Expand Up @@ -14,7 +14,7 @@
***************************************************************************/

#include "qgscheckboxwidgetfactory.h"

#include "qgscheckboxsearchwidgetwrapper.h"
#include "qgscheckboxwidgetwrapper.h"
#include "qgscheckboxconfigdlg.h"

Expand All @@ -28,6 +28,11 @@ QgsEditorWidgetWrapper* QgsCheckboxWidgetFactory::create( QgsVectorLayer* vl, in
return new QgsCheckboxWidgetWrapper( vl, fieldIdx, editor, parent );
}

QgsSearchWidgetWrapper*QgsCheckboxWidgetFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsCheckboxSearchWidgetWrapper( vl, fieldIdx, parent );
}

QgsEditorConfigWidget* QgsCheckboxWidgetFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
{
return new QgsCheckBoxConfigDlg( vl, fieldIdx, parent );
Expand Down
1 change: 1 addition & 0 deletions src/gui/editorwidgets/qgscheckboxwidgetfactory.h
Expand Up @@ -30,6 +30,7 @@ class GUI_EXPORT QgsCheckboxWidgetFactory : public QgsEditorWidgetFactory
// QgsEditorWidgetFactory interface
public:
QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const override;
QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const 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
2 changes: 2 additions & 0 deletions src/gui/qgsattributeformeditorwidget.cpp
Expand Up @@ -125,6 +125,8 @@ void QgsAttributeFormEditorWidget::changesCommitted()
void QgsAttributeFormEditorWidget::resetSearch()
{
mSearchWidgetToolButton->setInactive();
if ( mSearchWidget )
mSearchWidget->clearWidget();
}

void QgsAttributeFormEditorWidget::initialize( const QVariant& initialValue, bool mixedValues )
Expand Down
35 changes: 34 additions & 1 deletion tests/src/python/test_qgssearchwidgetwrapper.py
Expand Up @@ -17,7 +17,8 @@
from qgis.gui import (QgsSearchWidgetWrapper,
QgsDefaultSearchWidgetWrapper,
QgsValueMapSearchWidgetWrapper,
QgsValueRelationSearchWidgetWrapper)
QgsValueRelationSearchWidgetWrapper,
QgsCheckboxSearchWidgetWrapper)
from qgis.core import (QgsVectorLayer,
QgsFeature,
QgsMapLayerRegistry,
Expand Down Expand Up @@ -226,5 +227,37 @@ def testCreateExpression(self):
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=2')
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>2')


class PyQgsCheckboxSearchWidgetWrapper(unittest.TestCase):

def testCreateExpression(self):
""" Test creating an expression using the widget"""
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "test", "memory")

w = QgsCheckboxSearchWidgetWrapper(layer, 0)
config = {"CheckedState": 5,
"UncheckedState": 9}
w.setConfig(config)
c = w.widget()

# first check with string field type
c.setChecked(True)
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL')
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'5\'')
c.setChecked(False)
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL')
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'9\'')

# try with numeric field
w = QgsCheckboxSearchWidgetWrapper(layer, 1)
w.setConfig(config)
c = w.widget()
c.setChecked(True)
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL')
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=5')
c.setChecked(False)
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL')
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=9')

if __name__ == '__main__':
unittest.main()

0 comments on commit 195b4de

Please sign in to comment.