QGIS API Documentation 3.41.0-Master (3440c17df1d)
Loading...
Searching...
No Matches
qgsfieldvalueslineedit.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfieldvalueslineedit.cpp
3 -------------------------
4 Date : 20-08-2016
5 Copyright : (C) 2016 by 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
17#include "qgsvectorlayer.h"
18#include "qgsfloatingwidget.h"
19#include "moc_qgsfieldvalueslineedit.cpp"
20
21#include <QCompleter>
22#include <QStringListModel>
23#include <QTimer>
24#include <QHBoxLayout>
25
27 : QgsFilterLineEdit( parent )
28{
29 QCompleter *c = new QCompleter( this );
30 c->setCaseSensitivity( Qt::CaseInsensitive );
31 c->setFilterMode( Qt::MatchContains );
32 c->setCompletionMode( QCompleter::UnfilteredPopupCompletion );
33 setCompleter( c );
34 connect( this, &QgsFieldValuesLineEdit::textEdited, this, &QgsFieldValuesLineEdit::requestCompleterUpdate );
35 mShowPopupTimer.setSingleShot( true );
36 mShowPopupTimer.setInterval( 100 );
37 connect( &mShowPopupTimer, &QTimer::timeout, this, &QgsFieldValuesLineEdit::triggerCompleterUpdate );
38}
39
41{
42 if ( mGatherer )
43 {
44 mGatherer->stop();
45 mGatherer->wait(); // mGatherer is deleted when wait completes
46 }
47}
48
50{
51 if ( mLayer == layer )
52 return;
53
54 mLayer = layer;
55 emit layerChanged( layer );
56}
57
59{
60 if ( mAttributeIndex == index )
61 return;
62
63 mAttributeIndex = index;
64 emit attributeIndexChanged( index );
65}
66
67void QgsFieldValuesLineEdit::requestCompleterUpdate()
68{
69 mUpdateRequested = true;
70 mShowPopupTimer.start();
71}
72
73void QgsFieldValuesLineEdit::triggerCompleterUpdate()
74{
75 mShowPopupTimer.stop();
76 const QString currentText = text();
77
78 if ( currentText.isEmpty() )
79 {
80 if ( mGatherer )
81 mGatherer->stop();
82 return;
83 }
84
85 updateCompletionList( currentText );
86}
87
88void QgsFieldValuesLineEdit::updateCompletionList( const QString &text )
89{
90 if ( text.isEmpty() )
91 {
92 if ( mGatherer )
93 mGatherer->stop();
94 return;
95 }
96
97 mUpdateRequested = true;
98 if ( mGatherer )
99 {
100 mRequestedCompletionText = text;
101 mGatherer->stop();
102 return;
103 }
104
105 mGatherer = new QgsFieldValuesLineEditValuesGatherer( mLayer, mAttributeIndex );
106 mGatherer->setSubstring( text );
107
108 connect( mGatherer, &QgsFieldValuesLineEditValuesGatherer::collectedValues, this, &QgsFieldValuesLineEdit::updateCompleter );
109 connect( mGatherer, &QgsFieldValuesLineEditValuesGatherer::finished, this, &QgsFieldValuesLineEdit::gathererThreadFinished );
110
111 mGatherer->start();
112}
113
114void QgsFieldValuesLineEdit::gathererThreadFinished()
115{
116 const bool wasCanceled = mGatherer->wasCanceled();
117
118 delete mGatherer;
119 mGatherer = nullptr;
120
121 if ( wasCanceled )
122 {
123 const QString text = mRequestedCompletionText;
124 mRequestedCompletionText.clear();
125 updateCompletionList( text );
126 return;
127 }
128}
129
130void QgsFieldValuesLineEdit::updateCompleter( const QStringList &values )
131{
132 mUpdateRequested = false;
133 completer()->setModel( new QStringListModel( values ) );
134 completer()->complete();
135}
136
137
138// just internal guff - definitely not for exposing to public API!
140
141void QgsFieldValuesLineEditValuesGatherer::run()
142{
143 mWasCanceled = false;
144 if ( mSubstring.isEmpty() )
145 {
146 emit collectedValues( QStringList() );
147 return;
148 }
149
150 // allow responsive cancellation
151 mFeedback = new QgsFeedback();
152 // just get 100 values... maybe less/more would be useful?
153 mValues = mLayer->uniqueStringsMatching( mAttributeIndex, mSubstring, 100, mFeedback );
154
155 // be overly cautious - it's *possible* stop() might be called between deleting mFeedback and nulling it
156 mFeedbackMutex.lock();
157 delete mFeedback;
158 mFeedback = nullptr;
159 mFeedbackMutex.unlock();
160
161 emit collectedValues( mValues );
162}
163
164void QgsFieldValuesLineEditValuesGatherer::stop()
165{
166 // be cautious, in case gatherer stops naturally just as we are canceling it and mFeedback gets deleted
167 mFeedbackMutex.lock();
168 if ( mFeedback )
169 mFeedback->cancel();
170 mFeedbackMutex.unlock();
171
172 mWasCanceled = true;
173}
174
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
void attributeIndexChanged(int index)
Emitted when the field associated with the widget changes.
QgsFieldValuesLineEdit(QWidget *parent=nullptr)
Constructor for QgsFieldValuesLineEdit.
void setLayer(QgsVectorLayer *layer)
Sets the layer containing the field that values will be shown from.
void layerChanged(QgsVectorLayer *layer)
Emitted when the layer associated with the widget changes.
void setAttributeIndex(int index)
Sets the attribute index for the field containing values to show in the widget.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
Represents a vector layer which manages a vector based data sets.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c