QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsattributeeditor.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsattributeeditor.cpp - description
3  -------------------
4  begin : July 2009
5  copyright : (C) 2009 by J├╝rgen E. Fischer
6  email : jef@norbit.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
19 #include "qgseditorwidgetfactory.h"
20 #include "qgseditorwidgetregistry.h"
21 #include "qgseditorwidgetwrapper.h"
22 
23 #include "qgsattributedialog.h"
24 #include "qgsattributeeditor.h"
27 #include "qgscolorbutton.h"
28 #include "qgsexpression.h"
29 #include "qgsfieldvalidator.h"
30 #include "qgsfilterlineedit.h"
31 #include "qgslogger.h"
32 #include "qgslonglongvalidator.h"
33 #include "qgsmaplayerregistry.h"
35 #include "qgsrelationeditor.h"
36 #include "qgsrelationmanager.h"
37 #include "qgsvectordataprovider.h"
38 #include "qgsvectorlayer.h"
39 
40 #include <QScrollArea>
41 #include <QPushButton>
42 #include <QLineEdit>
43 #include <QTextEdit>
44 #include <QFileDialog>
45 #include <QComboBox>
46 #include <QListWidget>
47 #include <QCheckBox>
48 #include <QSpinBox>
49 #include <QCompleter>
50 #include <QHBoxLayout>
51 #include <QPlainTextEdit>
52 #include <QDial>
53 #include <QCalendarWidget>
54 #include <QDialogButtonBox>
55 #include <QSettings>
56 #include <QDir>
57 #include <QUuid>
58 #include <QGroupBox>
59 #include <QLabel>
60 #include <QWebView>
61 #include <QDesktopServices>
62 
64 {
65  QPushButton *pb = qobject_cast<QPushButton *>( sender() );
66  if ( !pb )
67  return;
68 
69  QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
70  if ( !hbox )
71  return;
72 
73  QLineEdit *le = hbox->findChild<QLineEdit *>();
74  if ( !le )
75  return;
76 
77  QString fileName = QFileDialog::getOpenFileName( 0 , tr( "Select a file" ), QFileInfo( le->text() ).absolutePath() );
78  if ( fileName.isNull() )
79  return;
80 
81  le->setText( QDir::toNativeSeparators( fileName ) );
82 }
83 
85 {
86  QPushButton *pb = qobject_cast<QPushButton *>( sender() );
87  if ( !pb )
88  return;
89 
90  QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
91  if ( !hbox )
92  return;
93 
94  QLineEdit *le = hbox->findChild<QLineEdit *>();
95  if ( !le )
96  return;
97 
98  QDialog *dlg = new QDialog();
99  dlg->setWindowTitle( tr( "Select a date" ) );
100  QVBoxLayout *vl = new QVBoxLayout( dlg );
101 
102  const QgsFieldValidator *v = dynamic_cast<const QgsFieldValidator *>( le->validator() );
103  QString dateFormat = v ? v->dateFormat() : "yyyy-MM-dd";
104 
105  QCalendarWidget *cw = new QCalendarWidget( dlg );
106  QString prevValue = le->text();
107  cw->setSelectedDate( QDate::fromString( prevValue, dateFormat ) );
108  vl->addWidget( cw );
109 
110  QDialogButtonBox *buttonBox = new QDialogButtonBox( dlg );
111  buttonBox->addButton( QDialogButtonBox::Ok );
112  buttonBox->addButton( QDialogButtonBox::Cancel );
113  vl->addWidget( buttonBox );
114 
115  connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
116  connect( buttonBox, SIGNAL( rejected() ), dlg, SLOT( reject() ) );
117 
118  if ( dlg->exec() == QDialog::Accepted )
119  {
120  QString newValue = cw->selectedDate().toString( dateFormat );
121  le->setText( newValue );
122  le->setModified( newValue != prevValue );
123  }
124 }
125 
126 void QgsAttributeEditor::loadUrl( const QString &url )
127 {
128  QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
129  if ( !le )
130  return;
131 
132  QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
133  if ( !hbox )
134  return;
135 
136  QWebView *ww = hbox->findChild<QWebView *>();
137  if ( !ww )
138  return;
139 
140  ww->load( url );
141 }
142 
143 void QgsAttributeEditor::loadPixmap( const QString &name )
144 {
145  QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
146  if ( !le )
147  return;
148 
149  QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
150  if ( !hbox )
151  return;
152 
153  QLabel *lw = hbox->findChild<QLabel *>();
154  if ( !lw )
155  return;
156 
157  QPixmap pm( name );
158  if ( pm.isNull() )
159  return;
160 
161  QSize size( mLayer->widgetSize( mIdx ) );
162  if ( size.width() == 0 && size.height() > 0 )
163  {
164  size.setWidth( size.height() * pm.size().width() / pm.size().height() );
165  }
166  else if ( size.width() > 0 && size.height() == 0 )
167  {
168  size.setHeight( size.width() * pm.size().height() / pm.size().width() );
169  }
170 
171  pm = pm.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
172 
173  lw->setPixmap( pm );
174  lw->setMinimumSize( size );
175 }
176 
178 {
179  QPushButton *pb = qobject_cast<QPushButton *>( sender() );
180  if ( !pb )
181  return;
182 
183  QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
184  if ( !hbox )
185  return;
186 
187  QWebView *ww = hbox->findChild<QWebView *>();
188  if ( !ww )
189  return;
190 
191  QLineEdit *le = hbox->findChild<QLineEdit *>();
192  if ( !le )
193  return;
194 
195  le->blockSignals( true );
196  le->setText( ww->url().toString() );
197  le->blockSignals( false );
198 }
199 
201 {
202  QPushButton *pb = qobject_cast<QPushButton *>( sender() );
203  if ( !pb )
204  return;
205 
206  QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
207  if ( !hbox )
208  return;
209 
210  QWebView *ww = hbox->findChild<QWebView *>();
211  if ( !ww )
212  return;
213 
214  QDesktopServices::openUrl( ww->url().toString() );
215 }
216 
218 {
219  QString color;
220  QgsColorButton *scb = qobject_cast<QgsColorButton *>( sender() );
221  QLineEdit *sle = qobject_cast<QLineEdit *>( sender() );
222 
223  if ( !scb && !sle )
224  return;
225 
226  QWidget *hbox = qobject_cast<QWidget *>( sender()->parent() );
227  if ( !hbox )
228  return;
229 
230  QgsColorButton *cb = hbox->findChild<QgsColorButton *>();
231  if ( !cb )
232  return;
233 
234  QLineEdit *le = hbox->findChild<QLineEdit *>();
235  if ( !le )
236  return;
237 
238  if ( scb )
239  {
240  le->blockSignals( true );
241  le->setText( scb->color().name() );
242  le->blockSignals( false );
243  }
244 
245  if ( sle )
246  {
247  cb->blockSignals( true );
248  cb->setColor( QColor( sle->text() ) );
249  cb->blockSignals( false );
250  }
251 }
252 
253 QComboBox *QgsAttributeEditor::comboBox( QWidget *editor, QWidget *parent )
254 {
255  QComboBox *cb = 0;
256  if ( editor )
257  cb = qobject_cast<QComboBox *>( editor );
258  else
259  cb = new QComboBox( parent );
260 
261  return cb;
262 }
263 
264 QListWidget *QgsAttributeEditor::listWidget( QWidget *editor, QWidget *parent )
265 {
266  QListWidget *lw = 0;
267  if ( editor )
268  lw = qobject_cast<QListWidget *>( editor );
269  else
270  lw = new QListWidget( parent );
271 
272  return lw;
273 }
274 
275 QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
276 {
278  context.addProxyWidgets( vl, QMap<int, QWidget*>() );
279 
280  return createAttributeEditor( parent, editor, vl, idx, value, context );
281 }
282 
283 QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value, QMap<int, QWidget*> &proxyWidgets )
284 {
286  context.addProxyWidgets( vl, proxyWidgets );
287 
288  return createAttributeEditor( parent, editor, vl, idx, value, context );
289 }
290 
291 QWidget* QgsAttributeEditor::createAttributeEditor( QWidget* parent, QWidget* editor, QgsVectorLayer* vl, int idx, const QVariant& value, QgsAttributeEditorContext& context )
292 {
293  if ( !vl )
294  return 0;
295 
296  QWidget *myWidget = 0;
297  QgsVectorLayer::EditType editType = vl->editType( idx );
298  const QgsField &field = vl->pendingFields()[idx];
299  QVariant::Type myFieldType = field.type();
300 
301  bool synchronized = false;
302 
303  switch ( editType )
304  {
306  {
307  QList<QVariant> values;
308  vl->dataProvider()->uniqueValues( idx, values );
309 
310  QComboBox *cb = comboBox( editor, parent );
311  if ( cb )
312  {
313  cb->setEditable( false );
314 
315  for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); ++it )
316  cb->addItem( it->toString(), it->toString() );
317 
318  myWidget = cb;
319  }
320 
321  }
322  break;
323 
325  {
326  QStringList enumValues;
327  vl->dataProvider()->enumValues( idx, enumValues );
328 
329  QComboBox *cb = comboBox( editor, parent );
330  if ( cb )
331  {
332  QStringList::const_iterator s_it = enumValues.constBegin();
333  for ( ; s_it != enumValues.constEnd(); ++s_it )
334  {
335  cb->addItem( *s_it, *s_it );
336  }
337 
338  myWidget = cb;
339  }
340  }
341  break;
342 
344  {
345  const QMap<QString, QVariant> &map = vl->valueMap( idx );
346 
347  QComboBox *cb = comboBox( editor, parent );
348  if ( cb )
349  {
350  for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); ++it )
351  {
352  cb->addItem( it.key(), it.value() );
353  }
354 
355  myWidget = cb;
356  }
357  }
358  break;
359 
361  {
362  const QgsVectorLayer::ValueRelationData &data = vl->valueRelation( idx );
363 
364  QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) );
365  QMap< QString, QString > map;
366 
367  if ( layer )
368  {
369  int ki = layer->fieldNameIndex( data.mOrderByValue ? data.mValue : data.mKey );
370  int vi = layer->fieldNameIndex( data.mOrderByValue ? data.mKey : data.mValue );
371 
372  QgsExpression *e = 0;
373  if ( !data.mFilterExpression.isEmpty() )
374  {
375  e = new QgsExpression( data.mFilterExpression );
376  if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
377  ki = -1;
378  }
379 
380  if ( ki >= 0 && vi >= 0 )
381  {
382  QSet<int> attributes;
383  attributes << ki << vi;
384 
386 
387  if ( e )
388  {
389  if ( e->needsGeometry() )
391 
392  foreach ( const QString &field, e->referencedColumns() )
393  {
394  int idx = layer->fieldNameIndex( field );
395  if ( idx < 0 )
396  continue;
397  attributes << idx;
398  }
399  }
400 
401  QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFlags( flags ).setSubsetOfAttributes( attributes.toList() ) );
402  QgsFeature f;
403  while ( fit.nextFeature( f ) )
404  {
405  if ( e && !e->evaluate( &f ).toBool() )
406  continue;
407 
408  map.insert( f.attribute( ki ).toString(), f.attribute( vi ).toString() );
409  }
410  }
411  }
412 
413  if ( !data.mAllowMulti )
414  {
415  QComboBox *cb = comboBox( editor, parent );
416  if ( cb )
417  {
418  if ( data.mAllowNull )
419  {
420  QSettings settings;
421  cb->addItem( tr( "(no selection)" ), settings.value( "qgis/nullValue", "NULL" ).toString() );
422  }
423 
424  for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); ++it )
425  {
426  if ( data.mOrderByValue )
427  cb->addItem( it.key(), it.value() );
428  else
429  cb->addItem( it.value(), it.key() );
430  }
431 
432  myWidget = cb;
433  }
434  }
435  else
436  {
437  QListWidget *lw = listWidget( editor, parent );
438  if ( lw )
439  {
440  QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," );
441 
442  for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); ++it )
443  {
444  QListWidgetItem *item;
445  if ( data.mOrderByValue )
446  {
447  item = new QListWidgetItem( it.key() );
448  item->setData( Qt::UserRole, it.value() );
449  item->setCheckState( checkList.contains( it.value() ) ? Qt::Checked : Qt::Unchecked );
450  }
451  else
452  {
453  item = new QListWidgetItem( it.value() );
454  item->setData( Qt::UserRole, it.key() );
455  item->setCheckState( checkList.contains( it.key() ) ? Qt::Checked : Qt::Unchecked );
456  }
457  lw->addItem( item );
458  }
459 
460  myWidget = lw;
461  }
462  }
463  }
464  break;
465 
467  {
468  const QString& widgetType = vl->editorWidgetV2( idx );
469  const QgsEditorWidgetConfig widgetConfig = vl->editorWidgetV2Config( idx );
470 
471  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, vl, idx, widgetConfig, editor, parent );
472 
473  if ( eww )
474  myWidget = eww->widget();
475  }
476  break;
477 
479  {
480  QMap<QString, QString> classes;
481 
482  const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() );
483  if ( csr )
484  {
485  const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories(); // FIXME: QgsCategorizedSymbolRendererV2::categories() should be const
486  for ( int i = 0; i < categories.size(); i++ )
487  {
488  QString label = categories[i].label();
489  QString value = categories[i].value().toString();
490  if ( label.isEmpty() )
491  label = value;
492  classes.insert( value, label );
493  }
494  }
495 
496  QComboBox *cb = comboBox( editor, parent );
497  if ( cb )
498  {
499  for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); ++it )
500  {
501  cb->addItem( it.value(), it.key() );
502  }
503 
504  myWidget = cb;
505  }
506  }
507  break;
508 
512  {
513  if ( myFieldType == QVariant::Int || myFieldType == QVariant::LongLong )
514  {
515  int min = vl->range( idx ).mMin.toInt();
516  int max = vl->range( idx ).mMax.toInt();
517  int step = vl->range( idx ).mStep.toInt();
518 
519  if ( editType == QgsVectorLayer::EditRange )
520  {
521  QSpinBox *sb = 0;
522 
523  if ( editor )
524  sb = qobject_cast<QSpinBox *>( editor );
525  else
526  sb = new QSpinBox( parent );
527 
528  if ( sb )
529  {
530  sb->setRange( min, max );
531  sb->setSingleStep( step );
532 
533  myWidget = sb;
534  }
535  }
536  else
537  {
538  QAbstractSlider *sl = 0;
539 
540  if ( editor )
541  {
542  sl = qobject_cast<QAbstractSlider*>( editor );
543  }
544  else if ( editType == QgsVectorLayer::DialRange )
545  {
546  sl = new QDial( parent );
547  }
548  else
549  {
550  sl = new QSlider( Qt::Horizontal, parent );
551  }
552 
553  if ( sl )
554  {
555  sl->setRange( min, max );
556  sl->setSingleStep( step );
557 
558  myWidget = sl;
559  }
560  }
561  break;
562  }
563  else if ( myFieldType == QVariant::Double )
564  {
565  QDoubleSpinBox *dsb = 0;
566  if ( editor )
567  dsb = qobject_cast<QDoubleSpinBox*>( editor );
568  else
569  dsb = new QDoubleSpinBox( parent );
570 
571  if ( dsb )
572  {
573  double min = vl->range( idx ).mMin.toDouble();
574  double max = vl->range( idx ).mMax.toDouble();
575  double step = vl->range( idx ).mStep.toDouble();
576 
577  dsb->setRange( min, max );
578  dsb->setSingleStep( step );
579 
580  myWidget = dsb;
581  }
582  break;
583  }
584  }
585 
587  {
588  QCheckBox *cb = 0;
589  QGroupBox *gb = 0;
590  if ( editor )
591  {
592  gb = qobject_cast<QGroupBox *>( editor );
593  cb = qobject_cast<QCheckBox*>( editor );
594  }
595  else
596  cb = new QCheckBox( parent );
597 
598  if ( cb )
599  {
600  myWidget = cb;
601  break;
602  }
603  else if ( gb )
604  {
605  myWidget = gb;
606  break;
607  }
608  }
609 
610  // fall-through
611 
617  {
618  QLineEdit *le = 0;
619  QTextEdit *te = 0;
620  QPlainTextEdit *pte = 0;
621  QComboBox * cb = 0;
622 
623  if ( editor )
624  {
625  le = qobject_cast<QLineEdit *>( editor );
626  te = qobject_cast<QTextEdit *>( editor );
627  pte = qobject_cast<QPlainTextEdit *>( editor );
628  cb = qobject_cast<QComboBox *>( editor );
629  }
630  else if ( editType == QgsVectorLayer::TextEdit )
631  {
632  pte = new QPlainTextEdit( parent );
633  }
634  else
635  {
636  le = new QgsFilterLineEdit( parent );
637  }
638 
639  if ( le )
640  {
641  if ( editType == QgsVectorLayer::UniqueValuesEditable )
642  {
643  QList<QVariant> values;
644  vl->dataProvider()->uniqueValues( idx, values );
645 
646  QStringList svalues;
647  for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); ++it )
648  svalues << it->toString();
649 
650  QCompleter *c = new QCompleter( svalues );
651  c->setCompletionMode( QCompleter::PopupCompletion );
652  le->setCompleter( c );
653  }
654 
655  if ( editType == QgsVectorLayer::UuidGenerator )
656  {
657  le->setReadOnly( true );
658  }
659 
660  le->setValidator( new QgsFieldValidator( le, field, vl->dateFormat( idx ) ) );
661 
662  myWidget = le;
663  }
664 
665  if ( te )
666  {
667  te->setAcceptRichText( true );
668  myWidget = te;
669  }
670 
671  if ( pte )
672  {
673  myWidget = pte;
674  }
675 
676  if ( cb )
677  {
678  if ( cb->isEditable() )
679  cb->setValidator( new QgsFieldValidator( cb, field, vl->dateFormat( idx ) ) );
680  myWidget = cb;
681  }
682 
683  if ( myWidget )
684  {
685  if ( editType == QgsVectorLayer::Immutable )
686  {
687  myWidget->setDisabled( true );
688  }
689 
690  QgsStringRelay* relay = NULL;
691 
692  QWidget* pwdg = context.proxyWidget( vl, idx );
693  if ( pwdg )
694  {
695  relay = pwdg->property( "QgisAttrEditProxy" ).value<QgsStringRelay*>();
696  }
697  else
698  {
699  relay = new QgsStringRelay( myWidget );
700  }
701 
702  const char* rSlot = SLOT( changeText( QString ) );
703  const char* rSig = SIGNAL( textChanged( QString ) );
704  const char* wSlot = SLOT( setText( QString ) );
705  const char* wSig = SIGNAL( textChanged( QString ) );
706  if ( te || pte )
707  {
708  rSlot = SLOT( changeText() );
709  wSig = SIGNAL( textChanged() );
710  }
711  if ( pte )
712  {
713  wSlot = SLOT( setPlainText( QString ) );
714  }
715  if ( cb && cb->isEditable() )
716  {
717  wSlot = SLOT( setEditText( QString ) );
718  wSig = SIGNAL( editTextChanged( QString ) );
719  }
720 
721  synchronized = connect( relay, rSig, myWidget, wSlot );
722  synchronized &= connect( myWidget, wSig, relay, rSlot );
723 
724  // store list of proxies in relay
725  relay->appendProxy( myWidget );
726 
727  if ( !cb || cb->isEditable() )
728  {
729  myWidget->setProperty( "QgisAttrEditSlot", QVariant( QByteArray( wSlot ) ) );
730  myWidget->setProperty( "QgisAttrEditProxy", QVariant::fromValue<QgsStringRelay*>( relay ) );
731  }
732  }
733  }
734  break;
735 
737  myWidget = 0;
738  break;
739 
745  {
746  QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
747  if ( cw )
748  {
749  myWidget = cw;
750  break;
751  }
752 
753  QWebView *ww = qobject_cast<QWebView *>( editor );
754  if ( ww )
755  {
756  ww->page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
757  // ww->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
758  ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
759  ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows, true );
760 #ifdef QGISDEBUG
761  ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
762 #endif
763 
764  QSize size( vl->widgetSize( idx ) );
765  if ( size.width() > 0 || size.height() > 0 )
766  {
767  if ( size.width() == 0 )
768  size.setWidth( 1 );
769  if ( size.height() == 0 )
770  size.setHeight( 1 );
771  ww->setMinimumSize( size );
772  }
773 
774  myWidget = ww;
775  break;
776  }
777 
778  QLabel *lw = qobject_cast<QLabel *>( editor );
779  if ( lw )
780  {
781  myWidget = lw;
782  break;
783  }
784 
785  QgsColorButton *cb = qobject_cast<QgsColorButton *>( editor );
786  if ( cb )
787  {
788  myWidget = cb;
789  break;
790  }
791 
792  QPushButton *pb0 = 0;
793  QPushButton *pb1 = 0;
794  QLineEdit *le = qobject_cast<QLineEdit *>( editor );
795  if ( le )
796  {
797  if ( le )
798  myWidget = le;
799 
800  if ( editor->parent() )
801  {
802  pb0 = editor->parent()->findChild<QPushButton *>();
803  }
804  }
805  else
806  {
807  myWidget = new QWidget( parent );
808  myWidget->setBackgroundRole( QPalette::Window );
809  myWidget->setAutoFillBackground( true );
810 
811  le = new QgsFilterLineEdit( myWidget );
812  switch ( editType )
813  {
817  pb0 = new QPushButton( tr( "..." ), myWidget );
818  break;
819 
821  pb0 = new QPushButton( tr( "<" ), myWidget );
822  pb0->setObjectName( "saveUrl" );
823  pb1 = new QPushButton( tr( "..." ), myWidget );
824  pb1->setObjectName( "openUrl" );
825  break;
826 
828  pb0 = new QgsColorButton( myWidget );
829  break;
830 
831  default:
832  break;
833  }
834 
835 
836  int row = 0;
837  QGridLayout *layout = new QGridLayout( myWidget );
838  if ( editType == QgsVectorLayer::Photo )
839  {
840  lw = new QLabel( myWidget );
841  layout->addWidget( lw, 0, 0, 1, 2 );
842  row++;
843  }
844  else if ( editType == QgsVectorLayer::WebView )
845  {
846  ww = new QWebView( myWidget );
847  ww->setObjectName( "webview" );
848  ww->page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
849  // ww->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
850  ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
851  ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows, true );
852 #ifdef QGISDEBUG
853  ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
854 #endif
855 
856  QSize size( vl->widgetSize( idx ) );
857  if ( size.width() > 0 || size.height() > 0 )
858  {
859  if ( size.width() == 0 )
860  size.setWidth( 1 );
861  if ( size.height() == 0 )
862  size.setHeight( 1 );
863  ww->setMinimumSize( size );
864  }
865 
866  layout->addWidget( ww, 0, 0, 1, 2 );
867  row++;
868  }
869 
870  layout->addWidget( le, row, 0 );
871  layout->addWidget( pb0, row, 1 );
872  if ( pb1 )
873  layout->addWidget( pb1, row, 2 );
874 
875  myWidget->setLayout( layout );
876  }
877 
878  if ( le )
879  {
880  le->setValidator( new QgsFieldValidator( le, field, vl->dateFormat( idx ) ) );
881 
882  if ( ww )
883  connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le, vl, idx ), SLOT( loadUrl( const QString & ) ) );
884  if ( lw )
885  connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le, vl, idx ), SLOT( loadPixmap( const QString & ) ) );
886  if ( editType == QgsVectorLayer::Color )
887  connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le ), SLOT( updateColor() ) );
888  }
889 
890  if ( pb0 )
891  {
892  if ( editType == QgsVectorLayer::FileName || editType == QgsVectorLayer::Photo )
893  {
894  connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( selectFileName() ) );
895  pb0->setToolTip( tr( "Select filename..." ) );
896  }
897  if ( editType == QgsVectorLayer::WebView )
898  {
899  connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( updateUrl() ) );
900  pb0->setToolTip( tr( "Save current page url in attribute" ) );
901  }
902  if ( editType == QgsVectorLayer::Calendar )
903  {
904  connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( selectDate() ) );
905  pb0->setToolTip( tr( "Select date in calendar" ) );
906  }
907  if ( editType == QgsVectorLayer::Color )
908  {
909  connect( pb0, SIGNAL( colorChanged( const QColor & ) ), new QgsAttributeEditor( pb0 ), SLOT( updateColor() ) );
910  pb0->setToolTip( tr( "Select color in browser" ) );
911  }
912  }
913 
914  if ( pb1 )
915  {
916  if ( editType == QgsVectorLayer::WebView )
917  {
918  connect( pb1, SIGNAL( clicked() ), new QgsAttributeEditor( pb1 ), SLOT( openUrl() ) );
919  pb1->setToolTip( tr( "Open current page in default browser" ) );
920  }
921  }
922  }
923  break;
924  }
925 
926  if ( context.proxyWidget( vl, idx ) )
927  {
928  if ( !synchronized )
929  {
930  myWidget->setEnabled( false );
931  }
932  }
933  else
934  {
935  context.addProxyWidget( vl, idx, myWidget );
936  }
937 
938  setValue( myWidget, vl, idx, value );
939 
940  return myWidget;
941 }
942 
943 bool QgsAttributeEditor::retrieveValue( QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value )
944 {
945  if ( !widget )
946  return false;
947 
948  QgsEditorWidgetWrapper* wrapper = QgsEditorWidgetWrapper::fromWidget( widget );
949 
950  if ( wrapper )
951  {
952  value = wrapper->value();
953  return true;
954  }
955 
956  const QgsField &theField = vl->pendingFields()[idx];
957  QgsVectorLayer::EditType editType = vl->editType( idx );
958  bool modified = false;
959  QString text;
960 
961  QSettings settings;
962  QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
963 
964  QLineEdit *le = qobject_cast<QLineEdit *>( widget );
965  if ( le )
966  {
967  text = le->text();
968  modified = le->isModified();
969  if ( text == nullValue )
970  {
971  text = QString::null;
972  }
973  }
974 
975  QTextEdit *te = qobject_cast<QTextEdit *>( widget );
976  if ( te )
977  {
978  text = te->toHtml();
979  modified = te->document()->isModified();
980  if ( text == nullValue )
981  {
982  text = QString::null;
983  }
984  }
985 
986  QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
987  if ( pte )
988  {
989  text = pte->toPlainText();
990  modified = pte->document()->isModified();
991  if ( text == nullValue )
992  {
993  text = QString::null;
994  }
995  }
996 
997  QComboBox *cb = qobject_cast<QComboBox *>( widget );
998  if ( cb )
999  {
1000  if ( editType == QgsVectorLayer::UniqueValues ||
1001  editType == QgsVectorLayer::ValueMap ||
1002  editType == QgsVectorLayer::Classification ||
1003  editType == QgsVectorLayer::ValueRelation )
1004  {
1005  text = cb->itemData( cb->currentIndex() ).toString();
1006  if ( text == nullValue )
1007  {
1008  text = QString::null;
1009  }
1010  }
1011  else
1012  {
1013  text = cb->currentText();
1014  }
1015  modified = true;
1016  }
1017 
1018  QListWidget *lw = qobject_cast<QListWidget *>( widget );
1019  if ( lw )
1020  {
1021  if ( editType == QgsVectorLayer::ValueRelation )
1022  {
1023  text = '{';
1024  for ( int i = 0, n = 0; i < lw->count(); i++ )
1025  {
1026  if ( lw->item( i )->checkState() == Qt::Checked )
1027  {
1028  if ( n > 0 )
1029  {
1030  text.append( ',' );
1031  }
1032  text.append( lw->item( i )->data( Qt::UserRole ).toString() );
1033  n++;
1034  }
1035  }
1036  text.append( '}' );
1037  }
1038  else
1039  {
1040  text = QString::null;
1041  }
1042  modified = true;
1043  }
1044 
1045  QSpinBox *sb = qobject_cast<QSpinBox *>( widget );
1046  if ( sb )
1047  {
1048  text = QString::number( sb->value() );
1049  }
1050 
1051  QAbstractSlider *slider = qobject_cast<QAbstractSlider *>( widget );
1052  if ( slider )
1053  {
1054  text = QString::number( slider->value() );
1055  }
1056 
1057  QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
1058  if ( dsb )
1059  {
1060  text = QString::number( dsb->value() );
1061  }
1062 
1063  QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
1064  if ( ckb )
1065  {
1066  QPair<QString, QString> states = vl->checkedState( idx );
1067  text = ckb->isChecked() ? states.first : states.second;
1068  }
1069 
1070  QGroupBox *gb = qobject_cast<QGroupBox *>( widget );
1071  if ( gb )
1072  {
1073  QPair<QString, QString> states = vl->checkedState( idx );
1074  text = gb->isChecked() ? states.first : states.second;
1075  }
1076 
1077  QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( widget );
1078  if ( cw )
1079  {
1080  text = cw->selectedDate().toString( vl->dateFormat( idx ) );
1081  }
1082 
1083  le = widget->findChild<QLineEdit *>();
1084  // QCalendarWidget and QGroupBox have an internal QLineEdit which returns the year
1085  // part of the date so we need to skip this if we have a QCalendarWidget
1086  if ( !cw && !gb && le )
1087  {
1088  text = le->text();
1089  modified = le->isModified();
1090  if ( text == nullValue )
1091  {
1092  text = QString::null;
1093  }
1094  }
1095 
1096  switch ( theField.type() )
1097  {
1098  case QVariant::Int:
1099  {
1100  bool ok;
1101  int myIntValue = text.toInt( &ok );
1102  if ( ok && !text.isEmpty() )
1103  {
1104  value = QVariant( myIntValue );
1105  modified = true;
1106  }
1107  else if ( modified )
1108  {
1109  value = QVariant();
1110  }
1111  }
1112  break;
1113  case QVariant::LongLong:
1114  {
1115  bool ok;
1116  qlonglong myLongValue = text.toLong( &ok );
1117  if ( ok && !text.isEmpty() )
1118  {
1119  value = QVariant( myLongValue );
1120  modified = true;
1121  }
1122  else if ( modified )
1123  {
1124  value = QVariant();
1125  }
1126  }
1127  case QVariant::Double:
1128  {
1129  bool ok;
1130  double myDblValue = text.toDouble( &ok );
1131  if ( ok && !text.isEmpty() )
1132  {
1133  value = QVariant( myDblValue );
1134  modified = true;
1135  }
1136  else if ( modified )
1137  {
1138  value = QVariant();
1139  }
1140  }
1141  break;
1142  case QVariant::Date:
1143  {
1144  QDate myDateValue = QDate::fromString( text, vl->dateFormat( idx ) );
1145  if ( myDateValue.isValid() && !text.isEmpty() )
1146  {
1147  value = myDateValue;
1148  modified = true;
1149  }
1150  else if ( modified )
1151  {
1152  value = QVariant();
1153  }
1154  }
1155  break;
1156  default: //string
1157  modified = true;
1158  if ( text.isNull() )
1159  value = QVariant( theField.type() );
1160  else
1161  value = QVariant( text );
1162  break;
1163  }
1164 
1165  return modified;
1166 }
1167 
1168 bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
1169 {
1170  if ( !editor )
1171  return false;
1172 
1173  QgsVectorLayer::EditType editType = vl->editType( idx );
1174  const QgsField &field = vl->pendingFields()[idx];
1175  QVariant::Type myFieldType = field.type();
1176 
1177  QSettings settings;
1178  QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
1179 
1180  switch ( editType )
1181  {
1187  {
1188  QVariant v = value;
1189  QComboBox *cb = qobject_cast<QComboBox *>( editor );
1190  if ( !cb )
1191  return false;
1192 
1193  if ( v.isNull() )
1194  {
1195  v = nullValue;
1196  }
1197 
1198  int idx = cb->findData( v );
1199  if ( idx < 0 )
1200  return false;
1201 
1202  cb->setCurrentIndex( idx );
1203  }
1204  break;
1205 
1209  {
1210  if ( myFieldType == QVariant::Int || myFieldType == QVariant::LongLong )
1211  {
1212  if ( editType == QgsVectorLayer::EditRange )
1213  {
1214  QSpinBox *sb = qobject_cast<QSpinBox *>( editor );
1215  if ( !sb )
1216  return false;
1217  sb->setValue( value.toInt() );
1218  }
1219  else
1220  {
1221  QAbstractSlider *sl = qobject_cast<QAbstractSlider *>( editor );
1222  if ( !sl )
1223  return false;
1224  sl->setValue( value.toInt() );
1225  }
1226  break;
1227  }
1228  else if ( myFieldType == QVariant::Double )
1229  {
1230  QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( editor );
1231  if ( !dsb )
1232  return false;
1233  dsb->setValue( value.toDouble() );
1234  }
1235  }
1236 
1238  {
1239  QGroupBox *gb = qobject_cast<QGroupBox *>( editor );
1240  if ( gb )
1241  {
1242  QPair<QString, QString> states = vl->checkedState( idx );
1243  gb->setChecked( value == states.first );
1244  break;
1245  }
1246 
1247  QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
1248  if ( cb )
1249  {
1250  QPair<QString, QString> states = vl->checkedState( idx );
1251  cb->setChecked( value == states.first );
1252  break;
1253  }
1254  }
1255 
1256  // fall-through
1257 
1263  {
1264  QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit *>( editor );
1265  QLineEdit *le = qobject_cast<QLineEdit *>( editor );
1266  QComboBox *cb = qobject_cast<QComboBox *>( editor );
1267  QTextEdit *te = qobject_cast<QTextEdit *>( editor );
1268  QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
1269  if ( !le && ! cb && !te && !pte )
1270  return false;
1271 
1272  if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
1273  {
1274  fle->setNullValue( nullValue );
1275  }
1276 
1277  QString text;
1278  if ( value.isNull() )
1279  {
1280  if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
1281  text = "";
1282  else if ( editType == QgsVectorLayer::UuidGenerator )
1283  text = QUuid::createUuid().toString();
1284  else
1285  text = nullValue;
1286  }
1287  else
1288  {
1289  text = field.displayString( value );
1290  }
1291 
1292  if ( le )
1293  le->setText( text );
1294  if ( cb && cb->isEditable() )
1295  cb->setEditText( text );
1296  if ( te )
1297  te->setHtml( text );
1298  if ( pte )
1299  pte->setPlainText( text );
1300  }
1301  break;
1302 
1305  case QgsVectorLayer::Photo:
1307  case QgsVectorLayer::Color:
1308  {
1309  QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
1310  if ( cw )
1311  {
1312  cw->setSelectedDate( value.toDate() );
1313  break;
1314  }
1315 
1316  QWebView *ww = qobject_cast<QWebView *>( editor );
1317  if ( ww )
1318  {
1319  ww->load( value.toString() );
1320  break;
1321  }
1322 
1323  QLabel *lw = qobject_cast<QLabel *>( editor );
1324  if ( lw )
1325  break;
1326 
1327  QgsColorButton *cb = qobject_cast<QgsColorButton *>( editor );
1328  if ( cb )
1329  {
1330  cb->setColor( QColor( value.toString() ) );
1331  break;
1332  }
1333 
1334  QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit*>( editor );
1335  QLineEdit *le = qobject_cast<QLineEdit*>( editor );
1336  if ( !le )
1337  {
1338  le = editor->findChild<QLineEdit *>();
1339  fle = qobject_cast<QgsFilterLineEdit *>( le );
1340  }
1341  if ( !le )
1342  return false;
1343 
1344  if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
1345  {
1346  fle->setNullValue( nullValue );
1347  }
1348 
1349  QString text;
1350  if ( value.isNull() )
1351  {
1352  if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
1353  text = "";
1354  else
1355  text = nullValue;
1356  }
1357  else if ( editType == QgsVectorLayer::Calendar && value.canConvert( QVariant::Date ) )
1358  {
1359  text = value.toDate().toString( vl->dateFormat( idx ) );
1360  }
1361  else
1362  {
1363  text = value.toString();
1364  }
1365 
1366  le->setText( text );
1367  }
1368  break;
1369 
1371  break;
1372 
1374  QgsEditorWidgetWrapper* wrapper = QgsEditorWidgetWrapper::fromWidget( editor );
1375  if ( wrapper )
1376  {
1377  wrapper->setValue( value );
1378  }
1379  break;
1380  }
1381 
1382  return true;
1383 }
1384 
1385 QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElement* widgetDef, QWidget* parent, QgsVectorLayer* vl, const QgsFeature& feat, QgsAttributeEditorContext& context, QString& labelText, bool& labelOnTop )
1386 {
1387  QWidget *newWidget = 0;
1388 
1389  switch ( widgetDef->type() )
1390  {
1392  {
1393  const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
1394  int fldIdx = fieldDef->idx();
1395  if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
1396  {
1397  newWidget = createAttributeEditor( parent, 0, vl, fldIdx, feat.attributes().value( fldIdx, QVariant() ), context );
1398 
1399  if ( newWidget )
1400  {
1401  if ( vl->editType( fldIdx ) != QgsVectorLayer::Immutable )
1402  {
1403  if ( newWidget->isEnabled() && vl->isEditable() && vl->fieldEditable( fldIdx ) )
1404  {
1405  newWidget->setEnabled( true );
1406  }
1407  else if ( vl->editType( fldIdx ) == QgsVectorLayer::Photo )
1408  {
1409  foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
1410  {
1411  w->setEnabled( qobject_cast<QLabel *>( w ) ? true : false );
1412  }
1413  }
1414  else if ( vl->editType( fldIdx ) == QgsVectorLayer::WebView )
1415  {
1416  foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
1417  {
1418  if ( qobject_cast<QWebView *>( w ) )
1419  w->setEnabled( true );
1420  else if ( qobject_cast<QPushButton *>( w ) && w->objectName() == "openUrl" )
1421  w->setEnabled( true );
1422  else
1423  w->setEnabled( false );
1424  }
1425  }
1426  else
1427  {
1428  newWidget->setEnabled( false );
1429  }
1430  }
1431  }
1432  }
1433  else
1434  {
1435  newWidget = new QLabel( tr( "<i>Error: Field does not exist in datasource</i>" ), parent );
1436  }
1437  labelOnTop = vl->labelOnTop( fieldDef->idx() );
1438  labelText = vl->attributeDisplayName( fieldDef->idx() );
1439  break;
1440  }
1441 
1443  {
1444  const QgsAttributeEditorRelation* relDef = dynamic_cast<const QgsAttributeEditorRelation*>( widgetDef );
1445 
1446  newWidget = QgsRelationEditorWidget::createRelationEditor( relDef->relation(), feat, context );
1447  labelText = QString::null;
1448  labelOnTop = true;
1449  break;
1450  }
1451 
1453  {
1454  const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
1455  QWidget* myContainer;
1456 
1457  if ( container->isGroupBox() )
1458  {
1459  QGroupBox* groupBox = new QGroupBox( parent );
1460  groupBox->setTitle( container->name() );
1461  myContainer = groupBox;
1462  newWidget = myContainer;
1463  }
1464  else
1465  {
1466  QScrollArea *scrollArea = new QScrollArea( parent );
1467 
1468  myContainer = new QWidget( scrollArea );
1469 
1470  scrollArea->setWidget( myContainer );
1471  scrollArea->setWidgetResizable( true );
1472  scrollArea->setFrameShape( QFrame::NoFrame );
1473 
1474  newWidget = scrollArea;
1475  }
1476 
1477  QGridLayout* gbLayout = new QGridLayout( myContainer );
1478  myContainer->setLayout( gbLayout );
1479 
1480  int index = 0;
1481 
1482  QList<QgsAttributeEditorElement*> children = container->children();
1483 
1484  Q_FOREACH( QgsAttributeEditorElement* childDef, children )
1485  {
1486  QString labelText;
1487  bool labelOnTop;
1488  QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, feat, context, labelText, labelOnTop );
1489 
1490  if ( labelText == QString::null )
1491  {
1492  gbLayout->addWidget( editor, index, 0, 1, 2 );
1493  }
1494  else
1495  {
1496  QLabel* mypLabel = new QLabel( labelText );
1497  if ( labelOnTop )
1498  {
1499  gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
1500  ++index;
1501  gbLayout->addWidget( editor, index, 0, 1 , 2 );
1502  }
1503  else
1504  {
1505  gbLayout->addWidget( mypLabel, index, 0 );
1506  gbLayout->addWidget( editor, index, 1 );
1507  }
1508  }
1509 
1510  ++index;
1511  }
1512  gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
1513 
1514  labelText = QString::null;
1515  labelOnTop = true;
1516  break;
1517  }
1518 
1519  default:
1520  QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
1521  break;
1522  }
1523 
1524  return newWidget;
1525 }
1526 
1528 {
1529  QObject* sObj = QObject::sender();
1530  QTextEdit *te = qobject_cast<QTextEdit *>( sObj );
1531  QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( sObj );
1532 
1533  if ( te )
1534  changeText( te->toPlainText() );
1535  if ( pte )
1536  changeText( pte->toPlainText() );
1537 }
1538 
1539 void QgsStringRelay::changeText( QString str )
1540 {
1541  QObject* sObj = QObject::sender();
1542  const char* sSlot = sObj->property( "QgisAttrEditSlot" ).toByteArray().constData();
1543 
1544  // disconnect widget being edited from relay's signal
1545  disconnect( this, SIGNAL( textChanged( QString ) ), sObj, sSlot );
1546 
1547  // block all proxies' signals
1548  QList<bool> oldBlockSigs;
1549  for ( int i = 0; i < mProxyList.size(); ++i )
1550  {
1551  oldBlockSigs << ( mProxyList[i] )->blockSignals( true );
1552  }
1553 
1554  // update all proxies not being edited without creating cyclical signals/slots
1555  emit textChanged( str );
1556 
1557  // reconnect widget being edited and reset blockSignals state
1558  connect( this, SIGNAL( textChanged( QString ) ), sObj, sSlot );
1559  for ( int i = 0; i < mProxyList.size(); ++i )
1560  {
1561  mProxyList[i]->blockSignals( oldBlockSigs[i] );
1562  }
1563 }
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
QMap< QString, QVariant > & valueMap(int idx)
access value map
Wrapper for iterator of features from vector data provider or vector layer.
void appendProxy(QWidget *proxy)
void addProxyWidget(QgsVectorLayer *vl, int idx, QWidget *widget)
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static unsigned index
bool fieldEditable(int idx)
is edit widget editable
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:96
QWidget * proxyWidget(QgsVectorLayer *vl, int fieldIdx)
QList< QWidget * > mProxyList
virtual bool isGroupBox() const
RangeData & range(int idx)
access range
static bool retrieveValue(QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value)
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
virtual void enumValues(int index, QStringList &enumList)
Returns the possible enum values of an attribute.
bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:114
The attribute value should not be changed in the attribute form.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
This class contains context information for attribute editor widgets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
void textChanged(QString)
static QListWidget * listWidget(QWidget *editor, QWidget *parent)
QgsAttributeEditor(QObject *parent, QgsVectorLayer *vl=0, int idx=-1)
A cross platform button subclass for selecting colors. Will open a color chooser dialog when clicked...
virtual void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Return unique values of an attribute.
QColor color() const
Return the currently selected color.
const QgsRelation & relation() const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:114
static QWidget * createWidgetFromDef(const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, const QgsFeature &feat, QgsAttributeEditorContext &context, QString &labelText, bool &labelOnTop)
Creates a widget form a QgsAttributeEditorElement definition.
QgsVectorLayer * mLayer
const QgsEditorWidgetConfig editorWidgetV2Config(int fieldIdx)
Get the configuration for the editor widget used to represent the field at the given index...
double ANALYSIS_EXPORT max(double x, double y)
returns the maximum of two doubles or the first argument if both are equal
QList< QgsRendererCategoryV2 > QgsCategoryList
QSize & widgetSize(int idx)
access widget size for photo and webview widget
static QgsRelationEditorWidget * createRelationEditor(const QgsRelation &relation, const QgsFeature &feature, QgsAttributeEditorContext context, QWidget *parent=NULL)
QString dateFormat() const
QString attributeDisplayName(int attributeIndex) const
Convenience function that returns the attribute alias if defined or the field name else...
The attribute value should not be shown in the attribute form.
EditType editType(int idx)
get edit type
QStringList referencedColumns()
Get list of columns referenced by the expression.
static bool setValue(QWidget *widget, QgsVectorLayer *vl, int idx, const QVariant &value)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
AttributeEditorType type() const
QString & dateFormat(int idx)
access date format
const QgsAttributes & attributes() const
Definition: qgsfeature.h:143
Lineedit with builtin clear button.
QPair< QString, QString > checkedState(int idx)
return string representing 'true' for a checkbox (added in 1.4)
static QComboBox * comboBox(QWidget *editor, QWidget *parent)
void setNullValue(QString nullValue)
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:31
ValueRelationData & valueRelation(int idx)
access relations
void loadPixmap(const QString &)
bool labelOnTop(int idx)
label widget on top
QList< QgsAttributeEditorElement * > children() const
bool needsGeometry()
Returns true if the expression uses feature geometry for some computation.
uuid generator - readonly and automatically intialized
static QWidget * createAttributeEditor(QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value, QMap< int, QWidget * > &proxyWidgets)
Creates or prepares a attribute editor widget.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
static QgsNetworkAccessManager * instance()
returns a pointer to the single instance
const QString editorWidgetV2(int fieldIdx)
Get the id for the editor widget used to represent the field at the given index.
void setColor(const QColor &color)
Specify the current color.
QMap< QString, QVariant > QgsEditorWidgetConfig
Holds a set of configuration parameters for a editor widget wrapper.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
void addProxyWidgets(QgsVectorLayer *vl, QMap< int, QWidget * > proxyWidgets)
QgsVectorDataProvider * dataProvider()
Returns the data provider.
double ANALYSIS_EXPORT min(double x, double y)
returns the minimum of two doubles or the first argument if both are equal
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
virtual bool isEditable() const
Returns true if the provider is in editing mode.
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
double size
Definition: qgssvgcache.cpp:77
modularized edit widgets
void loadUrl(const QString &)
value map from an table
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:60
#define tr(sourceText)