QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgstexteditwrapper.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstexteditwrapper.cpp
3  --------------------------------------
4  Date : 5.1.2014
5  Copyright : (C) 2014 Matthias Kuhn
6  Email : matthias at opengis dot ch
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 "qgstexteditwrapper.h"
17 
18 #include "qgsfields.h"
19 #include "qgsfieldvalidator.h"
20 #include "qgsfilterlineedit.h"
21 
22 #include <QSettings>
23 
24 QgsTextEditWrapper::QgsTextEditWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent )
25  : QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
26 
27 {
28 }
29 
30 QVariant QgsTextEditWrapper::value() const
31 {
32  QString v;
33 
34  if ( mTextEdit )
35  {
36  if ( config( QStringLiteral( "UseHtml" ) ).toBool() )
37  {
38  v = mTextEdit->toHtml();
39  }
40  else
41  {
42  v = mTextEdit->toPlainText();
43  }
44  }
45 
46  if ( mPlainTextEdit )
47  {
48  v = mPlainTextEdit->toPlainText();
49  }
50 
51  if ( mLineEdit )
52  {
53  v = mLineEdit->text();
54  }
55 
56  if ( ( v.isEmpty() && ( field().type() == QVariant::Int || field().type() == QVariant::Double || field().type() == QVariant::LongLong || field().type() == QVariant::Date ) ) ||
58  return QVariant( field().type() );
59 
60  if ( !defaultValue().isNull() && v == defaultValue().toString() )
61  {
62  return defaultValue();
63  }
64 
65  QVariant res( v );
66  if ( field().convertCompatible( res ) )
67  {
68  return res;
69  }
70  else if ( field().type() == QVariant::String && field().length() > 0 )
71  {
72  // for string fields convertCompatible may return false due to field length limit - in this case just truncate
73  // input rather then discarding it entirely
74  return QVariant( v.left( field().length() ) );
75  }
76  else
77  {
78  return QVariant( field().type() );
79  }
80 }
81 
82 QWidget *QgsTextEditWrapper::createWidget( QWidget *parent )
83 {
84  if ( config( QStringLiteral( "IsMultiline" ) ).toBool() )
85  {
86  if ( config( QStringLiteral( "UseHtml" ) ).toBool() )
87  {
88  return new QTextBrowser( parent );
89  }
90  else
91  {
92  return new QPlainTextEdit( parent );
93  }
94  }
95  else
96  {
97  return new QgsFilterLineEdit( parent );
98  }
99 }
100 
101 void QgsTextEditWrapper::initWidget( QWidget *editor )
102 {
103  mTextBrowser = qobject_cast<QTextBrowser *>( editor );
104  mTextEdit = qobject_cast<QTextEdit *>( editor );
105  mPlainTextEdit = qobject_cast<QPlainTextEdit *>( editor );
106  mLineEdit = qobject_cast<QLineEdit *>( editor );
107 
108  if ( mTextEdit )
109  connect( mTextEdit, &QTextEdit::textChanged, this, &QgsEditorWidgetWrapper::emitValueChanged );
110 
111  if ( mPlainTextEdit )
112  connect( mPlainTextEdit, &QPlainTextEdit::textChanged, this, &QgsEditorWidgetWrapper::emitValueChanged );
113 
114  if ( mLineEdit )
115  {
116  mLineEdit->setValidator( new QgsFieldValidator( mLineEdit, field(), defaultValue().toString() ) );
117 
118  QVariant defVal = defaultValue();
119  if ( defVal.isNull() )
120  {
122  }
123 
124  QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit *>( mLineEdit );
125  if ( field().type() == QVariant::Int || field().type() == QVariant::Double || field().type() == QVariant::LongLong || field().type() == QVariant::Date )
126  {
127  mPlaceholderText = defVal.toString();
128  mLineEdit->setPlaceholderText( mPlaceholderText );
129  }
130  else if ( fle )
131  {
132  fle->setNullValue( defVal.toString() );
133  }
134 
135  connect( mLineEdit, &QLineEdit::textChanged, this, [ = ]( const QString & value ) { emit valueChanged( value ); } );
136  connect( mLineEdit, &QLineEdit::textChanged, this, &QgsTextEditWrapper::textChanged );
137 
138  mWritablePalette = mLineEdit->palette();
139  mReadOnlyPalette = mLineEdit->palette();
140  }
141 }
142 
144 {
145  return mLineEdit || mTextEdit || mPlainTextEdit;
146 }
147 
149 {
150  //note - this is deliberately a zero length string, not a null string!
151  if ( mTextEdit )
152  mTextEdit->blockSignals( true );
153  if ( mPlainTextEdit )
154  mPlainTextEdit->blockSignals( true );
155  if ( mLineEdit )
156  {
157  mLineEdit->blockSignals( true );
158  // for interdeminate state we need to clear the placeholder text - we want an empty line edit, not
159  // one showing the default value (e.g., "NULL")
160  mLineEdit->setPlaceholderText( QString() );
161  }
162 
163  setWidgetValue( QString() );
164 
165  if ( mTextEdit )
166  mTextEdit->blockSignals( false );
167  if ( mPlainTextEdit )
168  mPlainTextEdit->blockSignals( false );
169  if ( mLineEdit )
170  mLineEdit->blockSignals( false );
171 }
172 
173 void QgsTextEditWrapper::setValue( const QVariant &val )
174 {
175  if ( mLineEdit )
176  {
177  //restore placeholder text, which may have been removed by showIndeterminateState()
178  mLineEdit->setPlaceholderText( mPlaceholderText );
179  }
180  setWidgetValue( val );
181 }
182 
183 void QgsTextEditWrapper::setEnabled( bool enabled )
184 {
185  if ( mTextEdit )
186  mTextEdit->setReadOnly( !enabled );
187 
188  if ( mPlainTextEdit )
189  mPlainTextEdit->setReadOnly( !enabled );
190 
191  if ( mLineEdit )
192  {
193  mLineEdit->setReadOnly( !enabled );
194  if ( enabled )
195  mLineEdit->setPalette( mWritablePalette );
196  else
197  {
198  mLineEdit->setPalette( mReadOnlyPalette );
199  // removing frame + setting transparent background to distinguish the readonly lineEdit from a normal one
200  // did not get this working via the Palette:
201  mLineEdit->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 75%);" ) );
202  }
203  mLineEdit->setFrame( enabled );
204  }
205 }
206 
207 void QgsTextEditWrapper::textChanged( const QString & )
208 {
209  if ( mLineEdit )
210  {
211  //restore placeholder text, which may have been removed by showIndeterminateState()
212  mLineEdit->setPlaceholderText( mPlaceholderText );
213  }
214 }
215 
216 void QgsTextEditWrapper::setWidgetValue( const QVariant &val )
217 {
218  QString v;
219  if ( val.isNull() )
220  {
221  if ( !( field().type() == QVariant::Int || field().type() == QVariant::Double || field().type() == QVariant::LongLong || field().type() == QVariant::Date ) )
223  }
224  else
225  {
226  v = field().displayString( val );
227  }
228 
229  // For numbers, remove the group separator that might cause validation errors
230  // when the user is editing the field value.
231  // We are checking for editable layer because in the form field context we do not
232  // want to strip the separator unless the layer is editable.
233  // Also check that we have something like a number in the value to avoid
234  // stripping out dots from nextval when we have a schema: see https://issues.qgis.org/issues/20200
235  // "Wrong sequence detection with Postgres"
236  bool canConvertToDouble;
237  QLocale().toDouble( v, &canConvertToDouble );
238  if ( canConvertToDouble && layer() && layer()->isEditable() && ! QLocale().groupSeparator().isNull() && field().isNumeric() )
239  {
240  v = v.remove( QLocale().groupSeparator() );
241  }
242 
243  if ( mTextEdit )
244  {
245  if ( val != value() )
246  {
247  if ( config( QStringLiteral( "UseHtml" ) ).toBool() )
248  {
249  mTextEdit->setHtml( v );
250  if ( mTextBrowser )
251  {
252  mTextBrowser->setTextInteractionFlags( Qt::LinksAccessibleByMouse );
253  mTextBrowser->setOpenExternalLinks( true );
254  }
255  }
256  else
257  mTextEdit->setPlainText( v );
258  }
259  }
260 
261  if ( mPlainTextEdit )
262  {
263  if ( val != value() )
264  mPlainTextEdit->setPlainText( v );
265  }
266 
267  if ( mLineEdit )
268  mLineEdit->setText( v );
269 }
270 
271 void QgsTextEditWrapper::setHint( const QString &hintText )
272 {
273  if ( hintText.isNull() )
274  mPlaceholderText = mPlaceholderTextBackup;
275  else
276  {
277  mPlaceholderTextBackup = mPlaceholderText;
278  mPlaceholderText = hintText;
279  }
280 
281  mLineEdit->setPlaceholderText( mPlaceholderText );
282 }
void setEnabled(bool enabled) override
void emitValueChanged()
Will call the value() method to determine the emitted value.
QVariantMap config() const
Returns the whole config.
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:206
Manages an editor widget Widget and wrapper share the same parent.
QgsField field() const
Access the field.
void showIndeterminateState() override
Sets the widget to display in an indeterminate "mixed value" state.
QVariant value() const override
Will be used to access the widget&#39;s value.
void initWidget(QWidget *editor) override
This method should initialize the editor widget with runtime data.
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
QgsTextEditWrapper(QgsVectorLayer *vl, int fieldIdx, QWidget *editor=nullptr, QWidget *parent=nullptr)
bool valid() const override
Returns true if the widget has been properly initialized.
QWidget * createWidget(QWidget *parent) override
This method should create a new widget with the provided parent.
QVariant defaultValue() const
Access the default value of the field.
void setValue(const QVariant &value) override
void valueChanged(const QVariant &value)
Emit this signal, whenever the value changed.
QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
void setNullValue(const QString &nullValue)
Sets the string representation for null values in the widget.
Represents a vector layer which manages a vector based data sets.
QVariant::Type type
Definition: qgsfield.h:55
void setHint(const QString &hintText) override
Add a hint text on the widget.