Skip to content

Commit 026e352

Browse files
committedMay 23, 2016
[FEATURE] Add a search widget wrapper for datetime widgets
1 parent 6d86859 commit 026e352

10 files changed

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

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@
254254
%Include editorwidgets/core/qgswidgetwrapper.sip
255255
%Include editorwidgets/qgscheckboxsearchwidgetwrapper.sip
256256
%Include editorwidgets/qgsdatetimeedit.sip
257+
%Include editorwidgets/qgsdatetimesearchwidgetwrapper.sip
257258
%Include editorwidgets/qgsdefaultsearchwidgetwrapper.sip
258259
%Include editorwidgets/qgsdoublespinbox.sip
259260
%Include editorwidgets/qgsmultiedittoolbutton.sip

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ SET(QGIS_GUI_SRCS
105105
editorwidgets/qgsdatetimeeditfactory.cpp
106106
editorwidgets/qgsdatetimeeditconfig.cpp
107107
editorwidgets/qgsdatetimeeditwrapper.cpp
108+
editorwidgets/qgsdatetimesearchwidgetwrapper.cpp
108109
editorwidgets/qgsdefaultsearchwidgetwrapper.cpp
109110
editorwidgets/qgsdoublespinbox.cpp
110111
editorwidgets/qgsdummyconfigdlg.cpp
@@ -530,6 +531,7 @@ SET(QGIS_GUI_MOC_HDRS
530531
editorwidgets/qgscolorwidgetwrapper.h
531532
editorwidgets/qgsdatetimeedit.h
532533
editorwidgets/qgsdatetimeeditconfig.h
534+
editorwidgets/qgsdatetimesearchwidgetwrapper.h
533535
editorwidgets/qgsdatetimeeditwrapper.h
534536
editorwidgets/qgsdefaultsearchwidgetwrapper.h
535537
editorwidgets/qgsdoublespinbox.h

‎src/gui/editorwidgets/qgsdatetimeeditfactory.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "qgsdatetimeeditfactory.h"
1717
#include "qgsdatetimeeditconfig.h"
1818
#include "qgsdatetimeeditwrapper.h"
19+
#include "qgsdatetimesearchwidgetwrapper.h"
1920

2021
#include <QSettings>
2122

@@ -29,6 +30,11 @@ QgsEditorWidgetWrapper *QgsDateTimeEditFactory::create( QgsVectorLayer *vl, int
2930
return new QgsDateTimeEditWrapper( vl, fieldIdx, editor, parent );
3031
}
3132

33+
QgsSearchWidgetWrapper* QgsDateTimeEditFactory::createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const
34+
{
35+
return new QgsDateTimeSearchWidgetWrapper( vl, fieldIdx, parent );
36+
}
37+
3238
QgsEditorConfigWidget *QgsDateTimeEditFactory::configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const
3339
{
3440
return new QgsDateTimeEditConfig( vl, fieldIdx, parent );

‎src/gui/editorwidgets/qgsdatetimeeditfactory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class GUI_EXPORT QgsDateTimeEditFactory : public QgsEditorWidgetFactory
3434
// QgsEditorWidgetFactory interface
3535
public:
3636
QgsEditorWidgetWrapper* create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const override;
37+
QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
3738
QgsEditorConfigWidget* configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const override;
3839
QgsEditorWidgetConfig readConfig( const QDomElement &configElement, QgsVectorLayer *layer, int fieldIdx ) override;
3940
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;

‎src/gui/editorwidgets/qgsdatetimeeditwrapper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ bool QgsDateTimeEditWrapper::valid() const
101101
return mQgsDateTimeEdit || mQDateTimeEdit;
102102
}
103103

104+
void QgsDateTimeEditWrapper::showIndeterminateState()
105+
{
106+
if ( mQgsDateTimeEdit )
107+
mQgsDateTimeEdit->setEmpty();
108+
}
109+
104110
void QgsDateTimeEditWrapper::dateTimeChanged( const QDateTime& dateTime )
105111
{
106112
const QString fieldFormat = config( "field_format", QGSDATETIMEEDIT_DATEFORMAT ).toString();

‎src/gui/editorwidgets/qgsdatetimeeditwrapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class GUI_EXPORT QgsDateTimeEditWrapper : public QgsEditorWidgetWrapper
5555
QWidget *createWidget( QWidget *parent ) override;
5656
void initWidget( QWidget *editor ) override;
5757
bool valid() const override;
58+
virtual void showIndeterminateState() override;
5859

5960
public slots:
6061
void setValue( const QVariant &value ) override;
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/***************************************************************************
2+
qgsdatetimesearchwidgetwrapper.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 "qgsdatetimesearchwidgetwrapper.h"
17+
18+
#include "qgsfield.h"
19+
#include "qgsdatetimeeditfactory.h"
20+
#include "qgsvectorlayer.h"
21+
#include "qgsdatetimeedit.h"
22+
#include "qcalendarwidget.h"
23+
24+
#include <QSettings>
25+
26+
QgsDateTimeSearchWidgetWrapper::QgsDateTimeSearchWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
27+
: QgsSearchWidgetWrapper( vl, fieldIdx, parent )
28+
, mDateTimeEdit( nullptr )
29+
, mLayer( nullptr )
30+
{
31+
}
32+
33+
bool QgsDateTimeSearchWidgetWrapper::applyDirectly()
34+
{
35+
return true;
36+
}
37+
38+
QString QgsDateTimeSearchWidgetWrapper::expression()
39+
{
40+
return mExpression;
41+
}
42+
43+
QVariant QgsDateTimeSearchWidgetWrapper::value() const
44+
{
45+
if ( ! mDateTimeEdit )
46+
return QDateTime();
47+
48+
const QString fieldFormat = config( "field_format", QGSDATETIMEEDIT_DATEFORMAT ).toString();
49+
return mDateTimeEdit->dateTime().toString( fieldFormat );
50+
}
51+
52+
QgsSearchWidgetWrapper::FilterFlags QgsDateTimeSearchWidgetWrapper::supportedFlags() const
53+
{
54+
return EqualTo | NotEqualTo | GreaterThan | LessThan | GreaterThanOrEqualTo | LessThanOrEqualTo | IsNull;
55+
}
56+
57+
QgsSearchWidgetWrapper::FilterFlags QgsDateTimeSearchWidgetWrapper::defaultFlags() const
58+
{
59+
return EqualTo;
60+
}
61+
62+
QString QgsDateTimeSearchWidgetWrapper::createExpression( QgsSearchWidgetWrapper::FilterFlags flags ) const
63+
{
64+
QString fieldName = QgsExpression::quotedColumnRef( layer()->fields().at( mFieldIdx ).name() );
65+
66+
//clear any unsupported flags
67+
flags &= supportedFlags();
68+
if ( flags & IsNull )
69+
return fieldName + " IS NULL";
70+
71+
QVariant v = value();
72+
if ( !v.isValid() )
73+
return QString();
74+
75+
if ( flags & EqualTo )
76+
return fieldName + "='" + v.toString() + '\'';
77+
else if ( flags & NotEqualTo )
78+
return fieldName + "<>'" + v.toString() + '\'';
79+
else if ( flags & GreaterThan )
80+
return fieldName + ">'" + v.toString() + '\'';
81+
else if ( flags & LessThan )
82+
return fieldName + "<'" + v.toString() + '\'';
83+
else if ( flags & GreaterThanOrEqualTo )
84+
return fieldName + ">='" + v.toString() + '\'';
85+
else if ( flags & LessThanOrEqualTo )
86+
return fieldName + "<='" + v.toString() + '\'';
87+
88+
return QString();
89+
}
90+
91+
void QgsDateTimeSearchWidgetWrapper::clearWidget()
92+
{
93+
if ( mDateTimeEdit )
94+
{
95+
mDateTimeEdit->setEmpty();
96+
}
97+
}
98+
99+
void QgsDateTimeSearchWidgetWrapper::setEnabled( bool enabled )
100+
{
101+
if ( mDateTimeEdit )
102+
{
103+
mDateTimeEdit->setEnabled( enabled );
104+
}
105+
}
106+
107+
bool QgsDateTimeSearchWidgetWrapper::valid() const
108+
{
109+
return true;
110+
}
111+
112+
void QgsDateTimeSearchWidgetWrapper::setExpression( QString exp )
113+
{
114+
QString fieldName = layer()->fields().at( mFieldIdx ).name();
115+
116+
QString str = QString( "%1 = '%3'" )
117+
.arg( QgsExpression::quotedColumnRef( fieldName ),
118+
exp.replace( '\'', "''" )
119+
);
120+
mExpression = str;
121+
}
122+
123+
void QgsDateTimeSearchWidgetWrapper::dateTimeChanged( const QDateTime& dt )
124+
{
125+
if ( mDateTimeEdit )
126+
{
127+
QString exp = value().toString();
128+
setExpression( exp );
129+
if ( dt.isValid() && !dt.isNull() )
130+
emit valueChanged();
131+
else
132+
emit valueCleared();
133+
emit expressionChanged( mExpression );
134+
}
135+
}
136+
137+
QWidget* QgsDateTimeSearchWidgetWrapper::createWidget( QWidget* parent )
138+
{
139+
QgsDateTimeEdit* widget = new QgsDateTimeEdit( parent );
140+
widget->setEmpty();
141+
return widget;
142+
}
143+
144+
void QgsDateTimeSearchWidgetWrapper::initWidget( QWidget* editor )
145+
{
146+
mDateTimeEdit = qobject_cast<QgsDateTimeEdit*>( editor );
147+
148+
if ( mDateTimeEdit )
149+
{
150+
mDateTimeEdit->setAllowNull( false );
151+
152+
const QString displayFormat = config( "display_format", QGSDATETIMEEDIT_DATEFORMAT ).toString();
153+
mDateTimeEdit->setDisplayFormat( displayFormat );
154+
155+
const bool calendar = config( "calendar_popup", false ).toBool();
156+
mDateTimeEdit->setCalendarPopup( calendar );
157+
if ( calendar )
158+
{
159+
// highlight today's date
160+
QTextCharFormat todayFormat;
161+
todayFormat.setBackground( QColor( 160, 180, 200 ) );
162+
mDateTimeEdit->calendarWidget()->setDateTextFormat( QDate::currentDate(), todayFormat );
163+
}
164+
165+
mDateTimeEdit->setEmpty();
166+
167+
connect( mDateTimeEdit, SIGNAL( dateTimeChanged( QDateTime ) ), this, SLOT( dateTimeChanged( QDateTime ) ) );
168+
}
169+
}
170+
171+
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/***************************************************************************
2+
qgsdatetimesearchwidgetwrapper.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 QGSDATETIMESEARCHWIDGETWRAPPER_H
17+
#define QGSDATETIMESEARCHWIDGETWRAPPER_H
18+
19+
#include "qgssearchwidgetwrapper.h"
20+
#include "qgsdatetimeeditwrapper.h"
21+
22+
#include <QComboBox>
23+
#include <QListWidget>
24+
#include <QLineEdit>
25+
26+
class QgsDateTimeEditFactory;
27+
28+
/**
29+
* Wraps a date time search widget.
30+
*/
31+
class GUI_EXPORT QgsDateTimeSearchWidgetWrapper : public QgsSearchWidgetWrapper
32+
{
33+
Q_OBJECT
34+
35+
public:
36+
explicit QgsDateTimeSearchWidgetWrapper( 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 dateTimeChanged( const QDateTime &date );
59+
60+
private:
61+
QgsDateTimeEdit* mDateTimeEdit;
62+
QgsVectorLayer* mLayer;
63+
64+
friend class QgsDateTimeEditFactory;
65+
};
66+
67+
#endif // QGSDATETIMESEARCHWIDGETWRAPPER_H

‎tests/src/python/test_qgssearchwidgetwrapper.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
QgsDefaultSearchWidgetWrapper,
1919
QgsValueMapSearchWidgetWrapper,
2020
QgsValueRelationSearchWidgetWrapper,
21-
QgsCheckboxSearchWidgetWrapper)
21+
QgsCheckboxSearchWidgetWrapper,
22+
QgsDateTimeSearchWidgetWrapper)
2223
from qgis.core import (QgsVectorLayer,
2324
QgsFeature,
2425
QgsMapLayerRegistry,
2526
)
27+
from qgis.PyQt.QtCore import QDateTime, QDate, QTime
2628
from qgis.PyQt.QtWidgets import QWidget
2729

2830
from qgis.testing import start_app, unittest
@@ -259,5 +261,61 @@ def testCreateExpression(self):
259261
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL')
260262
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=9')
261263

264+
265+
class PyQgsDateTimeSearchWidgetWrapper(unittest.TestCase):
266+
267+
def testCreateExpression(self):
268+
""" Test creating an expression using the widget"""
269+
layer = QgsVectorLayer("Point?field=date:date&field=time:time&field=datetime:datetime", "test", "memory")
270+
271+
w = QgsDateTimeSearchWidgetWrapper(layer, 0)
272+
config = {"field_format": 'yyyy-MM-dd',
273+
"display_format": 'yyyy-MM-dd'}
274+
w.setConfig(config)
275+
c = w.widget()
276+
277+
# first check with date field type
278+
c.setDateTime(QDateTime(QDate(2013, 4, 5), QTime()))
279+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"date" IS NULL')
280+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"date"=\'2013-04-05\'')
281+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"date"<>\'2013-04-05\'')
282+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThan), '"date">\'2013-04-05\'')
283+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThan), '"date"<\'2013-04-05\'')
284+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThanOrEqualTo), '"date">=\'2013-04-05\'')
285+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThanOrEqualTo), '"date"<=\'2013-04-05\'')
286+
287+
# time field type
288+
w = QgsDateTimeSearchWidgetWrapper(layer, 1)
289+
config = {"field_format": 'HH:mm:ss',
290+
"display_format": 'HH:mm:ss'}
291+
w.setConfig(config)
292+
c = w.widget()
293+
294+
c.setDateTime(QDateTime(QDate(2013, 4, 5), QTime(13, 14, 15)))
295+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"time" IS NULL')
296+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"time"=\'13:14:15\'')
297+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"time"<>\'13:14:15\'')
298+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThan), '"time">\'13:14:15\'')
299+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThan), '"time"<\'13:14:15\'')
300+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThanOrEqualTo), '"time">=\'13:14:15\'')
301+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThanOrEqualTo), '"time"<=\'13:14:15\'')
302+
303+
# datetime field type
304+
w = QgsDateTimeSearchWidgetWrapper(layer, 2)
305+
config = {"field_format": 'yyyy-MM-dd HH:mm:ss',
306+
"display_format": 'yyyy-MM-dd HH:mm:ss'}
307+
w.setConfig(config)
308+
c = w.widget()
309+
310+
c.setDateTime(QDateTime(QDate(2013, 4, 5), QTime(13, 14, 15)))
311+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"datetime" IS NULL')
312+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"datetime"=\'2013-04-05 13:14:15\'')
313+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"datetime"<>\'2013-04-05 13:14:15\'')
314+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThan), '"datetime">\'2013-04-05 13:14:15\'')
315+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThan), '"datetime"<\'2013-04-05 13:14:15\'')
316+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.GreaterThanOrEqualTo), '"datetime">=\'2013-04-05 13:14:15\'')
317+
self.assertEquals(w.createExpression(QgsSearchWidgetWrapper.LessThanOrEqualTo), '"datetime"<=\'2013-04-05 13:14:15\'')
318+
319+
262320
if __name__ == '__main__':
263321
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.