Skip to content

Commit 195b4de

Browse files
committed
[FEATURE] Add search widget wrapper for check box widget
1 parent ca5c7e2 commit 195b4de

10 files changed

+314
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* Wraps a checkbox search widget.
3+
*/
4+
class QgsCheckboxSearchWidgetWrapper : QgsSearchWidgetWrapper
5+
{
6+
%TypeHeaderCode
7+
#include <qgscheckboxsearchwidgetwrapper.h>
8+
%End
9+
public:
10+
11+
explicit QgsCheckboxSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent /TransferThis/ = nullptr );
12+
13+
// QgsSearchWidgetWrapper interface
14+
public:
15+
bool applyDirectly();
16+
QString expression();
17+
bool valid() const;
18+
QVariant value() const;
19+
FilterFlags supportedFlags() const;
20+
FilterFlags defaultFlags() const;
21+
virtual QString createExpression( FilterFlags flags ) const;
22+
23+
public slots:
24+
25+
virtual void clearWidget();
26+
virtual void setEnabled( bool enabled );
27+
28+
protected:
29+
QWidget* createWidget( QWidget* parent );
30+
void initWidget( QWidget* editor );
31+
32+
protected slots:
33+
void setExpression( QString exp );
34+
};

python/gui/gui.sip

+1
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
%Include editorwidgets/core/qgseditorwidgetwrapper.sip
253253
%Include editorwidgets/core/qgssearchwidgetwrapper.sip
254254
%Include editorwidgets/core/qgswidgetwrapper.sip
255+
%Include editorwidgets/qgscheckboxsearchwidgetwrapper.sip
255256
%Include editorwidgets/qgsdatetimeedit.sip
256257
%Include editorwidgets/qgsdefaultsearchwidgetwrapper.sip
257258
%Include editorwidgets/qgsdoublespinbox.sip

src/gui/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ SET(QGIS_GUI_SRCS
9494
editorwidgets/core/qgswidgetwrapper.cpp
9595

9696
editorwidgets/qgscheckboxconfigdlg.cpp
97+
editorwidgets/qgscheckboxsearchwidgetwrapper.cpp
9798
editorwidgets/qgscheckboxwidgetwrapper.cpp
9899
editorwidgets/qgscheckboxwidgetfactory.cpp
99100
editorwidgets/qgsclassificationwidgetwrapper.cpp
@@ -523,6 +524,7 @@ SET(QGIS_GUI_MOC_HDRS
523524
editorwidgets/core/qgswidgetwrapper.h
524525

525526
editorwidgets/qgscheckboxconfigdlg.h
527+
editorwidgets/qgscheckboxsearchwidgetwrapper.h
526528
editorwidgets/qgscheckboxwidgetwrapper.h
527529
editorwidgets/qgsclassificationwidgetwrapper.h
528530
editorwidgets/qgscolorwidgetwrapper.h

src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ QgsSearchWidgetWrapper* QgsEditorWidgetRegistry::createSearchWidget( const QStri
131131
// Make sure that there is a widget created at this point
132132
// so setValue() et al won't crash
133133
ww->widget();
134+
ww->clearWidget();
134135
return ww;
135136
}
136137
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/***************************************************************************
2+
qgscheckboxsearchwidgetwrapper.cpp
3+
---------------------------------
4+
Date : 2016-05-23
5+
Copyright : (C) 2016 Nyall Dawson
6+
Email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgscheckboxsearchwidgetwrapper.h"
17+
18+
#include "qgsfield.h"
19+
#include "qgscheckboxwidgetfactory.h"
20+
#include "qgsvectorlayer.h"
21+
22+
#include <QSettings>
23+
#include <QCheckBox>
24+
25+
QgsCheckboxSearchWidgetWrapper::QgsCheckboxSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
26+
: QgsSearchWidgetWrapper( vl, fieldIdx, parent )
27+
, mCheckBox( nullptr )
28+
, mLayer( nullptr )
29+
{
30+
}
31+
32+
bool QgsCheckboxSearchWidgetWrapper::applyDirectly()
33+
{
34+
return true;
35+
}
36+
37+
QString QgsCheckboxSearchWidgetWrapper::expression()
38+
{
39+
return mExpression;
40+
}
41+
42+
QVariant QgsCheckboxSearchWidgetWrapper::value() const
43+
{
44+
QVariant v;
45+
46+
if ( mCheckBox )
47+
v = mCheckBox->isChecked() ? config( "CheckedState" ) : config( "UncheckedState" );
48+
49+
return v;
50+
}
51+
52+
QgsSearchWidgetWrapper::FilterFlags QgsCheckboxSearchWidgetWrapper::supportedFlags() const
53+
{
54+
return EqualTo | IsNull;
55+
}
56+
57+
QgsSearchWidgetWrapper::FilterFlags QgsCheckboxSearchWidgetWrapper::defaultFlags() const
58+
{
59+
return EqualTo;
60+
}
61+
62+
QString QgsCheckboxSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
63+
{
64+
QVariant::Type fldType = layer()->fields().at( mFieldIdx ).type();
65+
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
66+
67+
//clear any unsupported flags
68+
flags &= supportedFlags();
69+
if ( flags & IsNull )
70+
return fieldName + " IS NULL";
71+
72+
QVariant v = value();
73+
if ( !v.isValid() )
74+
return QString();
75+
76+
switch ( fldType )
77+
{
78+
case QVariant::Int:
79+
case QVariant::UInt:
80+
case QVariant::Double:
81+
case QVariant::LongLong:
82+
case QVariant::ULongLong:
83+
{
84+
if ( flags & EqualTo )
85+
return fieldName + '=' + v.toString();
86+
else if ( flags & NotEqualTo )
87+
return fieldName + "<>" + v.toString();
88+
break;
89+
}
90+
91+
default:
92+
{
93+
if ( flags & EqualTo )
94+
return fieldName + "='" + v.toString() + '\'';
95+
else if ( flags & NotEqualTo )
96+
return fieldName + "<>'" + v.toString() + '\'';
97+
break;
98+
}
99+
}
100+
101+
return QString();
102+
}
103+
104+
void QgsCheckboxSearchWidgetWrapper::clearWidget()
105+
{
106+
if ( mCheckBox )
107+
{
108+
whileBlocking( mCheckBox )->setCheckState( Qt::PartiallyChecked );
109+
}
110+
}
111+
112+
void QgsCheckboxSearchWidgetWrapper::setEnabled( bool enabled )
113+
{
114+
if ( mCheckBox )
115+
{
116+
mCheckBox->setEnabled( enabled );
117+
}
118+
}
119+
120+
bool QgsCheckboxSearchWidgetWrapper::valid() const
121+
{
122+
return true;
123+
}
124+
125+
void QgsCheckboxSearchWidgetWrapper::setExpression( QString exp )
126+
{
127+
QString fieldName = layer()->fields().at( mFieldIdx ).name();
128+
129+
QString str = QString( "%1 = '%3'" )
130+
.arg( QgsExpression::quotedColumnRef( fieldName ),
131+
exp.replace( '\'', "''" )
132+
);
133+
mExpression = str;
134+
}
135+
136+
void QgsCheckboxSearchWidgetWrapper::stateChanged( int )
137+
{
138+
if ( mCheckBox )
139+
{
140+
mCheckBox->setTristate( false );
141+
QString exp = value().toString();
142+
setExpression( exp );
143+
emit valueChanged();
144+
emit expressionChanged( mExpression );
145+
}
146+
}
147+
148+
QWidget* QgsCheckboxSearchWidgetWrapper::createWidget( QWidget* parent )
149+
{
150+
QCheckBox* c = new QCheckBox( parent );
151+
c->setChecked( Qt::PartiallyChecked );
152+
return c;
153+
}
154+
155+
void QgsCheckboxSearchWidgetWrapper::initWidget( QWidget* editor )
156+
{
157+
mCheckBox = qobject_cast<QCheckBox*>( editor );
158+
159+
if ( mCheckBox )
160+
{
161+
mCheckBox->setChecked( Qt::PartiallyChecked );
162+
connect( mCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( stateChanged( int ) ) );
163+
}
164+
}
165+
166+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/***************************************************************************
2+
qgscheckboxsearchwidgetwrapper.h
3+
-------------------------------
4+
Date : 2016-05-23
5+
Copyright : (C) 2016 Nyall Dawson
6+
Email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSCHECKBOXSEARCHWIDGETWRAPPER_H
17+
#define QGSCHECKBOXSEARCHWIDGETWRAPPER_H
18+
19+
#include "qgssearchwidgetwrapper.h"
20+
#include "qgscheckboxwidgetwrapper.h"
21+
22+
#include <QComboBox>
23+
#include <QListWidget>
24+
#include <QLineEdit>
25+
26+
class QgsCheckboxWidgetFactory;
27+
28+
/**
29+
* Wraps a checkbox search widget.
30+
*/
31+
class GUI_EXPORT QgsCheckboxSearchWidgetWrapper : public QgsSearchWidgetWrapper
32+
{
33+
Q_OBJECT
34+
35+
public:
36+
explicit QgsCheckboxSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent = nullptr );
37+
bool applyDirectly() override;
38+
QString expression() override;
39+
bool valid() const override;
40+
QVariant value() const;
41+
FilterFlags supportedFlags() const override;
42+
FilterFlags defaultFlags() const override;
43+
virtual QString createExpression( FilterFlags flags ) const override;
44+
45+
public slots:
46+
47+
virtual void clearWidget() override;
48+
virtual void setEnabled( bool enabled ) override;
49+
50+
protected:
51+
QWidget* createWidget( QWidget* parent ) override;
52+
void initWidget( QWidget* editor ) override;
53+
54+
protected slots:
55+
void setExpression( QString exp ) override;
56+
57+
private slots:
58+
void stateChanged( int state );
59+
60+
private:
61+
QCheckBox* mCheckBox;
62+
QgsVectorLayer* mLayer;
63+
64+
friend class QgsCheckboxWidgetFactory;
65+
};
66+
67+
#endif // QGSCHECKBOXSEARCHWIDGETWRAPPER_H

src/gui/editorwidgets/qgscheckboxwidgetfactory.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
***************************************************************************/
1515

1616
#include "qgscheckboxwidgetfactory.h"
17-
17+
#include "qgscheckboxsearchwidgetwrapper.h"
1818
#include "qgscheckboxwidgetwrapper.h"
1919
#include "qgscheckboxconfigdlg.h"
2020

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

31+
QgsSearchWidgetWrapper*QgsCheckboxWidgetFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
32+
{
33+
return new QgsCheckboxSearchWidgetWrapper( vl, fieldIdx, parent );
34+
}
35+
3136
QgsEditorConfigWidget* QgsCheckboxWidgetFactory::configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
3237
{
3338
return new QgsCheckBoxConfigDlg( vl, fieldIdx, parent );

src/gui/editorwidgets/qgscheckboxwidgetfactory.h

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class GUI_EXPORT QgsCheckboxWidgetFactory : public QgsEditorWidgetFactory
3030
// QgsEditorWidgetFactory interface
3131
public:
3232
QgsEditorWidgetWrapper* create( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ) const override;
33+
QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
3334
QgsEditorConfigWidget* configWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
3435
QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ) override;
3536
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;

src/gui/qgsattributeformeditorwidget.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ void QgsAttributeFormEditorWidget::changesCommitted()
125125
void QgsAttributeFormEditorWidget::resetSearch()
126126
{
127127
mSearchWidgetToolButton->setInactive();
128+
if ( mSearchWidget )
129+
mSearchWidget->clearWidget();
128130
}
129131

130132
void QgsAttributeFormEditorWidget::initialize( const QVariant& initialValue, bool mixedValues )

tests/src/python/test_qgssearchwidgetwrapper.py

+34-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
from qgis.gui import (QgsSearchWidgetWrapper,
1818
QgsDefaultSearchWidgetWrapper,
1919
QgsValueMapSearchWidgetWrapper,
20-
QgsValueRelationSearchWidgetWrapper)
20+
QgsValueRelationSearchWidgetWrapper,
21+
QgsCheckboxSearchWidgetWrapper)
2122
from qgis.core import (QgsVectorLayer,
2223
QgsFeature,
2324
QgsMapLayerRegistry,
@@ -226,5 +227,37 @@ def testCreateExpression(self):
226227
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=2')
227228
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>2')
228229

230+
231+
class PyQgsCheckboxSearchWidgetWrapper(unittest.TestCase):
232+
233+
def testCreateExpression(self):
234+
""" Test creating an expression using the widget"""
235+
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "test", "memory")
236+
237+
w = QgsCheckboxSearchWidgetWrapper(layer, 0)
238+
config = {"CheckedState": 5,
239+
"UncheckedState": 9}
240+
w.setConfig(config)
241+
c = w.widget()
242+
243+
# first check with string field type
244+
c.setChecked(True)
245+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL')
246+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'5\'')
247+
c.setChecked(False)
248+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL')
249+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'9\'')
250+
251+
# try with numeric field
252+
w = QgsCheckboxSearchWidgetWrapper(layer, 1)
253+
w.setConfig(config)
254+
c = w.widget()
255+
c.setChecked(True)
256+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL')
257+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=5')
258+
c.setChecked(False)
259+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL')
260+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=9')
261+
229262
if __name__ == '__main__':
230263
unittest.main()

0 commit comments

Comments
 (0)