Skip to content

Commit d493a69

Browse files
committedSep 25, 2015
[FEATURE] allow filtering for field values in expression widget
1 parent e655c26 commit d493a69

File tree

4 files changed

+107
-139
lines changed

4 files changed

+107
-139
lines changed
 

‎python/gui/qgsexpressionbuilderwidget.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ class QgsExpressionBuilderWidget : QWidget
173173
void on_expressionTree_doubleClicked( const QModelIndex &index );
174174
void on_txtExpressionString_textChanged();
175175
void on_txtSearchEdit_textChanged();
176+
void on_txtSearchEditValues_textChanged();
176177
void on_lblPreview_linkActivated( QString link );
177-
void on_mValueListWidget_itemDoubleClicked( QListWidgetItem* item );
178+
void on_mValuesListView_doubleClicked( const QModelIndex &index );
178179
void operatorButtonClicked();
179180
void showContextMenu( const QPoint & );
180181
void loadSampleValues();

‎src/gui/qgsexpressionbuilderwidget.cpp

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,19 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
5858
connect( btnLoadAll, SIGNAL( pressed() ), this, SLOT( loadAllValues() ) );
5959
connect( btnLoadSample, SIGNAL( pressed() ), this, SLOT( loadSampleValues() ) );
6060

61-
Q_FOREACH ( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
61+
Q_FOREACH( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
6262
{
6363
connect( button, SIGNAL( pressed() ), this, SLOT( operatorButtonClicked() ) );
6464
}
6565

6666
txtSearchEdit->setPlaceholderText( tr( "Search" ) );
6767

68+
mValuesModel = new QStringListModel();
69+
mProxyValues = new QSortFilterProxyModel();
70+
mProxyValues->setSourceModel( mValuesModel );
71+
mValuesListView->setModel( mProxyValues );
72+
txtSearchEditValues->setPlaceholderText( tr( "Search" ) );
73+
6874
QSettings settings;
6975
splitter->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/splitter" ).toByteArray() );
7076
functionsplit->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/functionsplitter" ).toByteArray() );
@@ -101,6 +107,8 @@ QgsExpressionBuilderWidget::~QgsExpressionBuilderWidget()
101107

102108
delete mModel;
103109
delete mProxyModel;
110+
delete mValuesModel;
111+
delete mProxyValues;
104112
}
105113

106114
void QgsExpressionBuilderWidget::setLayer( QgsVectorLayer *layer )
@@ -115,25 +123,22 @@ void QgsExpressionBuilderWidget::setLayer( QgsVectorLayer *layer )
115123

116124
void QgsExpressionBuilderWidget::currentChanged( const QModelIndex &index, const QModelIndex & )
117125
{
126+
txtSearchEditValues->setText( QString( "" ) );
127+
118128
// Get the item
119129
QModelIndex idx = mProxyModel->mapToSource( index );
120130
QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
121131
if ( !item )
122132
return;
123133

124-
mValueListWidget->clear();
125134
if ( item->getItemType() == QgsExpressionItem::Field && mFieldValues.contains( item->text() ) )
126135
{
127136
const QStringList& values = mFieldValues[item->text()];
128-
mValueListWidget->setUpdatesEnabled( false );
129-
mValueListWidget->blockSignals( true );
130-
mValueListWidget->addItems( values );
131-
mValueListWidget->setUpdatesEnabled( true );
132-
mValueListWidget->blockSignals( false );
137+
mValuesModel->setStringList( values );
133138
}
134139

135140
mLoadGroupBox->setVisible( item->getItemType() == QgsExpressionItem::Field && mLayer );
136-
mValueGroupBox->setVisible(( item->getItemType() == QgsExpressionItem::Field && mLayer ) || mValueListWidget->count() > 0 );
141+
mValueGroupBox->setVisible( ( item->getItemType() == QgsExpressionItem::Field && mLayer ) || mValuesListView->model()->rowCount() > 0 );
137142

138143
// Show the help for the current item.
139144
QString help = loadFunctionHelp( item );
@@ -188,7 +193,7 @@ void QgsExpressionBuilderWidget::updateFunctionFileList( QString path )
188193
dir.setNameFilters( QStringList() << "*.py" );
189194
QStringList files = dir.entryList( QDir::Files );
190195
cmbFileNames->clear();
191-
Q_FOREACH ( const QString& name, files )
196+
Q_FOREACH( const QString& name, files )
192197
{
193198
QFileInfo info( mFunctionsPath + QDir::separator() + name );
194199
if ( info.baseName() == "__init__" ) continue;
@@ -292,7 +297,7 @@ void QgsExpressionBuilderWidget::loadFieldNames( const QgsFields& fields )
292297
void QgsExpressionBuilderWidget::loadFieldsAndValues( const QMap<QString, QStringList> &fieldValues )
293298
{
294299
QgsFields fields;
295-
Q_FOREACH ( const QString& fieldName, fieldValues.keys() )
300+
Q_FOREACH( const QString& fieldName, fieldValues.keys() )
296301
{
297302
fields.append( QgsField( fieldName ) );
298303
}
@@ -308,20 +313,16 @@ void QgsExpressionBuilderWidget::fillFieldValues( const QString& fieldName, int
308313
return;
309314

310315
// TODO We should thread this so that we don't hold the user up if the layer is massive.
311-
mValueListWidget->clear();
312316

313317
int fieldIndex = mLayer->fieldNameIndex( fieldName );
314318

315319
if ( fieldIndex < 0 )
316320
return;
317321

318-
mValueListWidget->setUpdatesEnabled( false );
319-
mValueListWidget->blockSignals( true );
320-
321322
QList<QVariant> values;
322323
QStringList strValues;
323324
mLayer->uniqueValues( fieldIndex, values, countLimit );
324-
Q_FOREACH ( const QVariant& value, values )
325+
Q_FOREACH( const QVariant& value, values )
325326
{
326327
QString strValue;
327328
if ( value.isNull() )
@@ -330,13 +331,10 @@ void QgsExpressionBuilderWidget::fillFieldValues( const QString& fieldName, int
330331
strValue = value.toString();
331332
else
332333
strValue = "'" + value.toString().replace( "'", "''" ) + "'";
333-
mValueListWidget->addItem( strValue );
334334
strValues.append( strValue );
335335
}
336+
mValuesModel->setStringList( strValues );
336337
mFieldValues[fieldName] = strValues;
337-
338-
mValueListWidget->setUpdatesEnabled( true );
339-
mValueListWidget->blockSignals( false );
340338
}
341339

342340
void QgsExpressionBuilderWidget::registerItem( QString group,
@@ -417,7 +415,7 @@ void QgsExpressionBuilderWidget::loadRecent( QString key )
417415
QSettings settings;
418416
QString location = QString( "/expressions/recent/%1" ).arg( key );
419417
QStringList expressions = settings.value( location ).toStringList();
420-
Q_FOREACH ( const QString& expression, expressions )
418+
Q_FOREACH( const QString& expression, expressions )
421419
{
422420
this->registerItem( name, expression, expression, expression );
423421
}
@@ -598,7 +596,7 @@ QString QgsExpressionBuilderWidget::formatPreviewString( const QString& previewS
598596
void QgsExpressionBuilderWidget::loadExpressionContext()
599597
{
600598
QStringList variableNames = mExpressionContext.filteredVariableNames();
601-
Q_FOREACH ( const QString& variable, variableNames )
599+
Q_FOREACH( const QString& variable, variableNames )
602600
{
603601
registerItem( "Variables", variable, " @" + variable + " ",
604602
QgsExpression::variableHelpText( variable, true, mExpressionContext.variable( variable ) ),
@@ -608,7 +606,7 @@ void QgsExpressionBuilderWidget::loadExpressionContext()
608606

609607
// Load the functions from the expression context
610608
QStringList contextFunctions = mExpressionContext.functionNames();
611-
Q_FOREACH ( const QString& functionName, contextFunctions )
609+
Q_FOREACH( const QString& functionName, contextFunctions )
612610
{
613611
QgsExpression::Function* func = mExpressionContext.function( functionName );
614612
QString name = func->name();
@@ -629,6 +627,12 @@ void QgsExpressionBuilderWidget::on_txtSearchEdit_textChanged()
629627
expressionTree->expandAll();
630628
}
631629

630+
void QgsExpressionBuilderWidget::on_txtSearchEditValues_textChanged()
631+
{
632+
mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
633+
mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
634+
}
635+
632636
void QgsExpressionBuilderWidget::on_lblPreview_linkActivated( QString link )
633637
{
634638
Q_UNUSED( link );
@@ -638,10 +642,10 @@ void QgsExpressionBuilderWidget::on_lblPreview_linkActivated( QString link )
638642
mv->exec();
639643
}
640644

641-
void QgsExpressionBuilderWidget::on_mValueListWidget_itemDoubleClicked( QListWidgetItem *item )
645+
void QgsExpressionBuilderWidget::on_mValuesListView_doubleClicked( const QModelIndex &index )
642646
{
643647
// Insert the item text or replace selected text
644-
txtExpressionString->insertText( " " + item->text() + " " );
648+
txtExpressionString->insertText( " " + index.data( Qt::DisplayRole ).toString() + " " );
645649
txtExpressionString->setFocus();
646650
}
647651

‎src/gui/qgsexpressionbuilderwidget.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "QStandardItemModel"
2626
#include "QStandardItem"
2727
#include "QSortFilterProxyModel"
28+
#include "QStringListModel"
2829

2930
/** An expression item that can be used in the QgsExpressionBuilderWidget tree.
3031
*/
@@ -136,6 +137,7 @@ class QgsExpressionItemSearchProxy : public QSortFilterProxyModel
136137
}
137138
};
138139

140+
139141
/** A reusable widget that can be used to build a expression string.
140142
* See QgsExpressionBuilderDialog for exmaple of usage.
141143
*/
@@ -238,8 +240,9 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
238240
void on_expressionTree_doubleClicked( const QModelIndex &index );
239241
void on_txtExpressionString_textChanged();
240242
void on_txtSearchEdit_textChanged();
243+
void on_txtSearchEditValues_textChanged();
241244
void on_lblPreview_linkActivated( QString link );
242-
void on_mValueListWidget_itemDoubleClicked( QListWidgetItem* item );
245+
void on_mValuesListView_doubleClicked( const QModelIndex &index );
243246
void operatorButtonClicked();
244247
void showContextMenu( const QPoint & );
245248
void loadSampleValues();
@@ -274,6 +277,8 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
274277
QString mFunctionsPath;
275278
QgsVectorLayer *mLayer;
276279
QStandardItemModel *mModel;
280+
QStringListModel *mValuesModel;
281+
QSortFilterProxyModel *mProxyValues;
277282
QgsExpressionItemSearchProxy *mProxyModel;
278283
QMap<QString, QgsExpressionItem*> mExpressionGroups;
279284
QgsFeature mFeature;

‎src/ui/qgsexpressionbuilder.ui

Lines changed: 71 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -321,15 +321,12 @@
321321
</layout>
322322
</widget>
323323
<widget class="QFrame" name="moperationListGroup">
324-
<layout class="QGridLayout" name="gridLayout_5">
324+
<layout class="QGridLayout" name="gridLayout_6">
325325
<item row="0" column="0">
326326
<widget class="QSplitter" name="functionsplit">
327327
<property name="orientation">
328328
<enum>Qt::Horizontal</enum>
329329
</property>
330-
<property name="opaqueResize">
331-
<bool>false</bool>
332-
</property>
333330
<widget class="QWidget" name="layoutWidget">
334331
<layout class="QVBoxLayout" name="verticalLayout_4">
335332
<item>
@@ -366,8 +363,8 @@
366363
</item>
367364
</layout>
368365
</widget>
369-
<widget class="QWidget" name="layoutWidget2">
370-
<layout class="QVBoxLayout" name="verticalLayout_3">
366+
<widget class="QWidget" name="">
367+
<layout class="QVBoxLayout" name="verticalLayout_2">
371368
<item>
372369
<widget class="QTextEdit" name="txtHelpText">
373370
<property name="readOnly">
@@ -376,116 +373,77 @@
376373
</widget>
377374
</item>
378375
<item>
379-
<layout class="QVBoxLayout" name="verticalLayout_2">
380-
<property name="spacing">
381-
<number>0</number>
382-
</property>
383-
<property name="sizeConstraint">
384-
<enum>QLayout::SetDefaultConstraint</enum>
385-
</property>
386-
<property name="topMargin">
387-
<number>0</number>
388-
</property>
389-
<property name="rightMargin">
390-
<number>0</number>
391-
</property>
392-
<property name="bottomMargin">
393-
<number>0</number>
394-
</property>
395-
<item>
396-
<widget class="QFrame" name="mValueGroupBox">
397-
<layout class="QGridLayout" name="gridLayout_7">
398-
<property name="margin">
399-
<number>0</number>
376+
<widget class="QFrame" name="mValueGroupBox">
377+
<layout class="QGridLayout" name="gridLayout_5">
378+
<property name="margin">
379+
<number>0</number>
380+
</property>
381+
<item row="0" column="0">
382+
<widget class="QLabel" name="label_4">
383+
<property name="text">
384+
<string>Values</string>
400385
</property>
401-
<property name="spacing">
402-
<number>0</number>
386+
</widget>
387+
</item>
388+
<item row="0" column="1">
389+
<widget class="QgsFilterLineEdit" name="txtSearchEditValues">
390+
<property name="enabled">
391+
<bool>true</bool>
403392
</property>
404-
<item row="1" column="0" colspan="2">
405-
<widget class="QListWidget" name="mValueListWidget">
406-
<property name="sizePolicy">
407-
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
408-
<horstretch>0</horstretch>
409-
<verstretch>0</verstretch>
410-
</sizepolicy>
411-
</property>
412-
<property name="maximumSize">
413-
<size>
414-
<width>16777215</width>
415-
<height>16777215</height>
416-
</size>
417-
</property>
418-
<property name="autoFillBackground">
419-
<bool>false</bool>
420-
</property>
421-
<property name="editTriggers">
422-
<set>QAbstractItemView::NoEditTriggers</set>
423-
</property>
424-
<property name="showDropIndicator" stdset="0">
425-
<bool>false</bool>
426-
</property>
427-
<property name="alternatingRowColors">
428-
<bool>true</bool>
429-
</property>
430-
<property name="viewMode">
431-
<enum>QListView::ListMode</enum>
432-
</property>
433-
</widget>
434-
</item>
435-
<item row="0" column="0">
436-
<widget class="QLabel" name="label_4">
437-
<property name="text">
438-
<string>Values</string>
439-
</property>
440-
</widget>
441-
</item>
442-
</layout>
443-
</widget>
444-
</item>
445-
<item>
446-
<widget class="QWidget" name="mLoadGroupBox" native="true">
447-
<layout class="QHBoxLayout" name="horizontalLayout">
448-
<property name="margin">
449-
<number>0</number>
393+
</widget>
394+
</item>
395+
<item row="1" column="0" colspan="2">
396+
<widget class="QListView" name="mValuesListView">
397+
<property name="editTriggers">
398+
<set>QAbstractItemView::NoEditTriggers</set>
450399
</property>
451-
<item>
452-
<spacer name="horizontalSpacer">
453-
<property name="orientation">
454-
<enum>Qt::Horizontal</enum>
455-
</property>
456-
<property name="sizeHint" stdset="0">
457-
<size>
458-
<width>5</width>
459-
<height>20</height>
460-
</size>
461-
</property>
462-
</spacer>
463-
</item>
464-
<item>
465-
<widget class="QLabel" name="lblLoad">
466-
<property name="text">
467-
<string>Load values</string>
468-
</property>
469-
</widget>
470-
</item>
471-
<item>
472-
<widget class="QPushButton" name="btnLoadAll">
473-
<property name="text">
474-
<string>all unique</string>
475-
</property>
476-
</widget>
477-
</item>
478-
<item>
479-
<widget class="QPushButton" name="btnLoadSample">
480-
<property name="text">
481-
<string>10 samples</string>
482-
</property>
483-
</widget>
484-
</item>
485-
</layout>
486-
</widget>
487-
</item>
488-
</layout>
400+
</widget>
401+
</item>
402+
</layout>
403+
</widget>
404+
</item>
405+
<item>
406+
<widget class="QWidget" name="mLoadGroupBox" native="true">
407+
<layout class="QHBoxLayout" name="horizontalLayout">
408+
<property name="margin">
409+
<number>0</number>
410+
</property>
411+
<item>
412+
<spacer name="horizontalSpacer">
413+
<property name="orientation">
414+
<enum>Qt::Horizontal</enum>
415+
</property>
416+
<property name="sizeHint" stdset="0">
417+
<size>
418+
<width>5</width>
419+
<height>20</height>
420+
</size>
421+
</property>
422+
</spacer>
423+
</item>
424+
<item>
425+
<widget class="QLabel" name="lblLoad">
426+
<property name="text">
427+
<string>Load values</string>
428+
</property>
429+
</widget>
430+
</item>
431+
<item>
432+
<widget class="QPushButton" name="btnLoadAll">
433+
<property name="text">
434+
<string>all unique</string>
435+
</property>
436+
</widget>
437+
</item>
438+
<item>
439+
<widget class="QPushButton" name="btnLoadSample">
440+
<property name="text">
441+
<string>10 samples</string>
442+
</property>
443+
</widget>
444+
</item>
445+
</layout>
446+
</widget>
489447
</item>
490448
</layout>
491449
</widget>

0 commit comments

Comments
 (0)
Please sign in to comment.