[FEATURE] Add search widget wrapper for check box widget

This commit is contained in:
Nyall Dawson 2016-05-23 02:35:42 +10:00
parent ca5c7e2cd4
commit 195b4dee5a
10 changed files with 314 additions and 2 deletions

View File

@ -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 );
};

View File

@ -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

View File

@ -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
@ -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

View File

@ -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;
}
}

View File

@ -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 ) ) );
}
}

View File

@ -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

View File

@ -14,7 +14,7 @@
***************************************************************************/
#include "qgscheckboxwidgetfactory.h"
#include "qgscheckboxsearchwidgetwrapper.h"
#include "qgscheckboxwidgetwrapper.h"
#include "qgscheckboxconfigdlg.h"
@ -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 );

View File

@ -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;

View File

@ -125,6 +125,8 @@ void QgsAttributeFormEditorWidget::changesCommitted()
void QgsAttributeFormEditorWidget::resetSearch()
{
mSearchWidgetToolButton->setInactive();
if ( mSearchWidget )
mSearchWidget->clearWidget();
}
void QgsAttributeFormEditorWidget::initialize( const QVariant& initialValue, bool mixedValues )

View File

@ -17,7 +17,8 @@ import qgis # NOQA
from qgis.gui import (QgsSearchWidgetWrapper,
QgsDefaultSearchWidgetWrapper,
QgsValueMapSearchWidgetWrapper,
QgsValueRelationSearchWidgetWrapper)
QgsValueRelationSearchWidgetWrapper,
QgsCheckboxSearchWidgetWrapper)
from qgis.core import (QgsVectorLayer,
QgsFeature,
QgsMapLayerRegistry,
@ -226,5 +227,37 @@ class PyQgsValueRelationSearchWidgetWrapper(unittest.TestCase):
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()