QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsvariableeditorwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvariableeditorwidget.cpp
3  ---------------------------
4  Date : April 2015
5  Copyright : (C) 2015 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 "qgsexpressioncontext.h"
18 #include "qgsfeature.h"
19 #include "qgsapplication.h"
20 #include <QVBoxLayout>
21 #include <QTreeWidget>
22 #include <QPainter>
23 #include <QKeyEvent>
24 #include <QMouseEvent>
25 #include <QLineEdit>
26 #include <QPushButton>
27 #include <QHeaderView>
28 #include <QMessageBox>
29 #include <QSettings>
30 
31 
32 //
33 // QgsVariableEditorWidget
34 //
35 
37  : QWidget( parent )
38  , mContext( nullptr )
39  , mEditableScopeIndex( -1 )
40  , mShown( false )
41 {
42  QVBoxLayout* verticalLayout = new QVBoxLayout( this );
43  verticalLayout->setSpacing( 3 );
44  verticalLayout->setContentsMargins( 3, 3, 3, 3 );
45  mTreeWidget = new QgsVariableEditorTree( this );
46  mTreeWidget->setSelectionMode( QAbstractItemView::SingleSelection );
47  verticalLayout->addWidget( mTreeWidget );
48  QHBoxLayout* horizontalLayout = new QHBoxLayout();
49  horizontalLayout->setSpacing( 6 );
50  QSpacerItem* horizontalSpacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
51  horizontalLayout->addItem( horizontalSpacer );
52  mAddButton = new QPushButton();
53  mAddButton->setIcon( QgsApplication::getThemeIcon( "/symbologyAdd.svg" ) );
54  mAddButton->setEnabled( false );
55  horizontalLayout->addWidget( mAddButton );
56  mRemoveButton = new QPushButton();
57  mRemoveButton->setIcon( QgsApplication::getThemeIcon( "/symbologyRemove.svg" ) );
58  mRemoveButton->setEnabled( false );
59  horizontalLayout->addWidget( mRemoveButton );
60  verticalLayout->addLayout( horizontalLayout );
61  connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( on_mRemoveButton_clicked() ) );
62  connect( mAddButton, SIGNAL( clicked() ), this, SLOT( on_mAddButton_clicked() ) );
63  connect( mTreeWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( selectionChanged() ) );
64  connect( mTreeWidget, SIGNAL( scopeChanged() ), this, SIGNAL( scopeChanged() ) );
65 
66  //setContext clones context
68  setContext( context );
69  delete context;
70 }
71 
73 {
74  QSettings settings;
75  settings.setValue( saveKey() + "column0width", mTreeWidget->header()->sectionSize( 0 ) );
76 }
77 
79 {
80  // initialise widget on first show event only
81  if ( mShown )
82  {
83  event->accept();
84  return;
85  }
86 
87  //restore split size
88  QSettings settings;
89  QVariant val;
90  val = settings.value( saveKey() + "column0width" );
91  bool ok;
92  int sectionSize = val.toInt( &ok );
93  if ( ok )
94  {
95  mTreeWidget->header()->resizeSection( 0, sectionSize );
96  }
97  mShown = true;
98 
99  QWidget::showEvent( event );
100 }
101 
103 {
104  mContext.reset( new QgsExpressionContext( *context ) );
105  reloadContext();
106 }
107 
109 {
110  mTreeWidget->resetTree();
111  mTreeWidget->setContext( mContext.data() );
112  mTreeWidget->refreshTree();
113 }
114 
116 {
117  mEditableScopeIndex = scopeIndex;
118  if ( mEditableScopeIndex >= 0 )
119  {
120  mAddButton->setEnabled( true );
121  }
122  mTreeWidget->setEditableScopeIndex( scopeIndex );
123  mTreeWidget->refreshTree();
124 }
125 
127 {
128  if ( !mContext || mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
129  {
130  return nullptr;
131  }
132  return mContext->scope( mEditableScopeIndex );
133 }
134 
136 {
137  QgsStringMap variables;
138  if ( !mContext || mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
139  {
140  return variables;
141  }
142 
143  QgsExpressionContextScope* scope = mContext->scope( mEditableScopeIndex );
144  Q_FOREACH ( const QString& variable, scope->variableNames() )
145  {
146  if ( scope->isReadOnly( variable ) )
147  continue;
148 
149  variables.insert( variable, scope->variable( variable ).toString() );
150  }
151 
152  return variables;
153 }
154 
155 QString QgsVariableEditorWidget::saveKey() const
156 {
157  // save key for load/save state
158  // currently QgsVariableEditorTree/window()/object
159  QString setGroup = mSettingGroup.isEmpty() ? objectName() : mSettingGroup;
160  QString saveKey = "/QgsVariableEditorTree/" + setGroup + '/';
161  return saveKey;
162 }
163 
164 void QgsVariableEditorWidget::on_mAddButton_clicked()
165 {
166  if ( mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
167  return;
168 
169  QgsExpressionContextScope* scope = mContext->scope( mEditableScopeIndex );
170  scope->setVariable( "new_variable", QVariant() );
171  mTreeWidget->refreshTree();
172  QTreeWidgetItem* item = mTreeWidget->itemFromVariable( scope, "new_variable" );
173  QModelIndex index = mTreeWidget->itemToIndex( item );
174  mTreeWidget->selectionModel()->select( index, QItemSelectionModel::ClearAndSelect );
175  mTreeWidget->editItem( item, 0 );
176 
177  emit scopeChanged();
178 }
179 
180 void QgsVariableEditorWidget::on_mRemoveButton_clicked()
181 {
182  if ( mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
183  return;
184 
185  QgsExpressionContextScope* editableScope = mContext->scope( mEditableScopeIndex );
186  QList<QTreeWidgetItem*> selectedItems = mTreeWidget->selectedItems();
187 
188  Q_FOREACH ( QTreeWidgetItem* item, selectedItems )
189  {
190  if ( !( item->flags() & Qt::ItemIsEditable ) )
191  continue;
192 
193  QString name = item->text( 0 );
194  QgsExpressionContextScope* itemScope = mTreeWidget->scopeFromItem( item );
195  if ( itemScope != editableScope )
196  continue;
197 
198  if ( itemScope->isReadOnly( name ) )
199  continue;
200 
201  itemScope->removeVariable( name );
202  mTreeWidget->removeItem( item );
203  }
204  mTreeWidget->refreshTree();
205 }
206 
207 void QgsVariableEditorWidget::selectionChanged()
208 {
209  if ( mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
210  {
211  mRemoveButton->setEnabled( false );
212  return;
213  }
214 
215  QgsExpressionContextScope* editableScope = mContext->scope( mEditableScopeIndex );
216  QList<QTreeWidgetItem*> selectedItems = mTreeWidget->selectedItems();
217 
218  bool removeEnabled = true;
219  Q_FOREACH ( QTreeWidgetItem* item, selectedItems )
220  {
221  if ( !( item->flags() & Qt::ItemIsEditable ) )
222  {
223  removeEnabled = false;
224  break;
225  }
226 
227  QString name = item->text( 0 );
228  QgsExpressionContextScope* itemScope = mTreeWidget->scopeFromItem( item );
229  if ( itemScope != editableScope )
230  {
231  removeEnabled = false;
232  break;
233  }
234 
235  if ( editableScope->isReadOnly( name ) )
236  {
237  removeEnabled = false;
238  break;
239  }
240  }
241  mRemoveButton->setEnabled( removeEnabled );
242 }
243 
244 
246 //
247 // VariableEditorTree
248 //
249 
250 QgsVariableEditorTree::QgsVariableEditorTree( QWidget *parent )
251  : QTreeWidget( parent )
252  , mEditorDelegate( nullptr )
253  , mEditableScopeIndex( -1 )
254  , mContext( nullptr )
255 {
256  // init icons
257  if ( mExpandIcon.isNull() )
258  {
259  QPixmap pix( 14, 14 );
260  pix.fill( Qt::transparent );
261  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconExpandSmall.svg" ).pixmap( 14, 14 ), QIcon::Normal, QIcon::Off );
262  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconExpandSmall.svg" ).pixmap( 14, 14 ), QIcon::Selected, QIcon::Off );
263  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconCollapseSmall.svg" ).pixmap( 14, 14 ), QIcon::Normal, QIcon::On );
264  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconCollapseSmall.svg" ).pixmap( 14, 14 ), QIcon::Selected, QIcon::On );
265  }
266 
267  setIconSize( QSize( 18, 18 ) );
268  setColumnCount( 2 );
269  setHeaderLabels( QStringList() << tr( "Variable" ) << tr( "Value" ) );
270  setAlternatingRowColors( true );
271  setEditTriggers( QAbstractItemView::AllEditTriggers );
272  setRootIsDecorated( false );
273  header()->setMovable( false );
274  header()->setResizeMode( QHeaderView::Interactive );
275 
276  mEditorDelegate = new VariableEditorDelegate( this, this );
277  setItemDelegate( mEditorDelegate );
278 }
279 
280 QgsExpressionContextScope* QgsVariableEditorTree::scopeFromItem( QTreeWidgetItem *item ) const
281 {
282  if ( !item )
283  return nullptr;
284 
285  bool ok;
286  int contextIndex = item->data( 0, ContextIndex ).toInt( &ok );
287  if ( !ok )
288  return nullptr;
289 
290  if ( !mContext )
291  {
292  return nullptr;
293  }
294  else if ( mContext->scopeCount() > contextIndex )
295  {
296  return mContext->scope( contextIndex );
297  }
298  else
299  {
300  return nullptr;
301  }
302 }
303 
304 QTreeWidgetItem* QgsVariableEditorTree::itemFromVariable( QgsExpressionContextScope *scope, const QString &name ) const
305 {
306  int contextIndex = mContext ? mContext->indexOfScope( scope ) : 0;
307  if ( contextIndex < 0 )
308  return nullptr;
309  return mVariableToItem.value( qMakePair( contextIndex, name ) );
310 }
311 
312 QgsExpressionContextScope* QgsVariableEditorTree::editableScope()
313 {
314  if ( !mContext || mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
315  {
316  return nullptr;
317  }
318 
319  return mContext->scope( mEditableScopeIndex );
320 }
321 
322 void QgsVariableEditorTree::refreshTree()
323 {
324  if ( !mContext || mEditableScopeIndex < 0 )
325  {
326  clear();
327  return;
328  }
329 
330  //add all scopes from the context
331  int scopeIndex = 0;
332  Q_FOREACH ( QgsExpressionContextScope* scope, mContext->scopes() )
333  {
334  refreshScopeItems( scope, scopeIndex );
335  scopeIndex++;
336  }
337 }
338 
339 void QgsVariableEditorTree::refreshScopeVariables( QgsExpressionContextScope* scope, int scopeIndex )
340 {
341  QColor baseColor = rowColor( scopeIndex );
342  bool isCurrent = scopeIndex == mEditableScopeIndex;
343  QTreeWidgetItem* scopeItem = mScopeToItem.value( scopeIndex );
344 
345  Q_FOREACH ( const QString& name, scope->filteredVariableNames() )
346  {
347  QTreeWidgetItem* item;
348  if ( mVariableToItem.contains( qMakePair( scopeIndex, name ) ) )
349  {
350  item = mVariableToItem.value( qMakePair( scopeIndex, name ) );
351  }
352  else
353  {
354  item = new QTreeWidgetItem( scopeItem );
355  mVariableToItem.insert( qMakePair( scopeIndex, name ), item );
356  }
357 
358  bool readOnly = scope->isReadOnly( name );
359  bool isActive = true;
360  QgsExpressionContextScope* activeScope = nullptr;
361  if ( mContext )
362  {
363  activeScope = mContext->activeScopeForVariable( name );
364  isActive = activeScope == scope;
365  }
366 
367  item->setFlags( item->flags() | Qt::ItemIsEnabled );
368  item->setText( 0, name );
369  QString value = scope->variable( name ).toString();
370  item->setText( 1, value );
371  QFont font = item->font( 0 );
372  if ( readOnly || !isCurrent )
373  {
374  font.setItalic( true );
375  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
376  }
377  else
378  {
379  font.setItalic( false );
380  item->setFlags( item->flags() | Qt::ItemIsEditable );
381  }
382  if ( !isActive )
383  {
384  //overridden
385  font.setStrikeOut( true );
386  QString toolTip = tr( "Overridden by value from %1" ).arg( activeScope->name() );
387  item->setToolTip( 0, toolTip );
388  item->setToolTip( 1, toolTip );
389  }
390  else
391  {
392  font.setStrikeOut( false );
393  item->setToolTip( 0, name );
394  item->setToolTip( 1, value );
395  }
396  item->setFont( 0, font );
397  item->setFont( 1, font );
398  item->setData( 0, RowBaseColor, baseColor );
399  item->setData( 0, ContextIndex, scopeIndex );
400  item->setFirstColumnSpanned( false );
401  }
402 }
403 
404 void QgsVariableEditorTree::refreshScopeItems( QgsExpressionContextScope* scope, int scopeIndex )
405 {
406  QSettings settings;
407 
408  //add top level item
409  bool isCurrent = scopeIndex == mEditableScopeIndex;
410 
411  QTreeWidgetItem* scopeItem;
412  if ( mScopeToItem.contains( scopeIndex ) )
413  {
414  //retrieve existing item
415  scopeItem = mScopeToItem.value( scopeIndex );
416  }
417  else
418  {
419  //create new top-level item
420  scopeItem = new QTreeWidgetItem();
421  mScopeToItem.insert( scopeIndex, scopeItem );
422  scopeItem->setFlags( scopeItem->flags() | Qt::ItemIsEnabled );
423  scopeItem->setText( 0, scope->name() );
424  scopeItem->setFlags( scopeItem->flags() ^ Qt::ItemIsEditable );
425  scopeItem->setFirstColumnSpanned( true );
426  QFont scopeFont = scopeItem->font( 0 );
427  scopeFont .setBold( true );
428  scopeItem->setFont( 0, scopeFont );
429  scopeItem->setFirstColumnSpanned( true );
430 
431  addTopLevelItem( scopeItem );
432 
433  //expand by default if current context or context was previously expanded
434  if ( isCurrent || settings.value( "QgsVariableEditor/" + scopeItem->text( 0 ) + "/expanded" ).toBool() )
435  scopeItem->setExpanded( true );
436 
437  scopeItem->setIcon( 0, mExpandIcon );
438  }
439 
440  refreshScopeVariables( scope, scopeIndex );
441 }
442 
443 void QgsVariableEditorTree::removeItem( QTreeWidgetItem *item )
444 {
445  if ( !item )
446  return;
447 
448  mVariableToItem.remove( mVariableToItem.key( item ) );
449  item->parent()->takeChild( item->parent()->indexOfChild( item ) );
450 
451  emit scopeChanged();
452 }
453 
454 void QgsVariableEditorTree::renameItem( QTreeWidgetItem *item, const QString& name )
455 {
456  if ( !item )
457  return;
458 
459  int contextIndex = mVariableToItem.key( item ).first;
460  mVariableToItem.remove( mVariableToItem.key( item ) );
461  mVariableToItem.insert( qMakePair( contextIndex, name ), item );
462  item->setText( 0, name );
463 
464  emit scopeChanged();
465 }
466 
467 void QgsVariableEditorTree::resetTree()
468 {
469  mVariableToItem.clear();
470  mScopeToItem.clear();
471  clear();
472 }
473 
474 void QgsVariableEditorTree::emitChanged()
475 {
476  emit scopeChanged();
477 }
478 
479 void QgsVariableEditorTree::drawRow( QPainter* painter, const QStyleOptionViewItem& option,
480  const QModelIndex& index ) const
481 {
482  QStyleOptionViewItemV3 opt = option;
483  QTreeWidgetItem* item = itemFromIndex( index );
484  if ( index.parent().isValid() )
485  {
486  //not a top-level item, so shade row background by context
487  const QColor baseColor = item->data( 0, RowBaseColor ).value<QColor>();
488  painter->fillRect( option.rect, baseColor );
489  opt.palette.setColor( QPalette::AlternateBase, baseColor.lighter( 110 ) );
490  }
491  QTreeWidget::drawRow( painter, opt, index );
492  QColor color = static_cast<QRgb>( QApplication::style()->styleHint( QStyle::SH_Table_GridLineColor, &opt ) );
493  painter->save();
494  painter->setPen( QPen( color ) );
495  painter->drawLine( opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom() );
496  painter->restore();
497 }
498 
499 QColor QgsVariableEditorTree::rowColor( int index ) const
500 {
501  //return some nice (inspired by Qt Designer) background row colors
502  int colorIdx = index % 6;
503  switch ( colorIdx )
504  {
505  case 0:
506  return QColor( 255, 220, 167 );
507  case 1:
508  return QColor( 255, 255, 191 );
509  case 2:
510  return QColor( 191, 255, 191 );
511  case 3:
512  return QColor( 199, 255, 255 );
513  case 4:
514  return QColor( 234, 191, 255 );
515  case 5:
516  default:
517  return QColor( 255, 191, 239 );
518  }
519 }
520 
521 void QgsVariableEditorTree::toggleContextExpanded( QTreeWidgetItem* item )
522 {
523  if ( !item )
524  return;
525 
526  item->setExpanded( !item->isExpanded() );
527 
528  //save expanded state
529  QSettings settings;
530  settings.setValue( "QgsVariableEditor/" + item->text( 0 ) + "/expanded", item->isExpanded() );
531 }
532 
533 void QgsVariableEditorTree::editNext( const QModelIndex& index )
534 {
535  if ( !index.isValid() )
536  return;
537 
538  if ( index.column() == 0 )
539  {
540  //switch to next column
541  QModelIndex nextIndex = index.sibling( index.row(), 1 );
542  if ( nextIndex.isValid() )
543  {
544  setCurrentIndex( nextIndex );
545  edit( nextIndex );
546  }
547  }
548  else
549  {
550  QModelIndex nextIndex = model()->index( index.row() + 1, 0, index.parent() );
551  if ( nextIndex.isValid() )
552  {
553  //start editing next row
554  setCurrentIndex( nextIndex );
555  edit( nextIndex );
556  }
557  else
558  {
559  edit( index );
560  }
561  }
562 }
563 
564 QModelIndex QgsVariableEditorTree::moveCursor( QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers )
565 {
566  if ( cursorAction == QAbstractItemView::MoveNext )
567  {
568  QModelIndex index = currentIndex();
569  if ( index.isValid() )
570  {
571  if ( index.column() + 1 < model()->columnCount() )
572  return index.sibling( index.row(), index.column() + 1 );
573  else if ( index.row() + 1 < model()->rowCount( index.parent() ) )
574  return index.sibling( index.row() + 1, 0 );
575  else
576  return QModelIndex();
577  }
578  }
579  else if ( cursorAction == QAbstractItemView::MovePrevious )
580  {
581  QModelIndex index = currentIndex();
582  if ( index.isValid() )
583  {
584  if ( index.column() >= 1 )
585  return index.sibling( index.row(), index.column() - 1 );
586  else if ( index.row() >= 1 )
587  return index.sibling( index.row() - 1, model()->columnCount() - 1 );
588  else
589  return QModelIndex();
590  }
591  }
592 
593  return QTreeWidget::moveCursor( cursorAction, modifiers );
594 }
595 
596 void QgsVariableEditorTree::keyPressEvent( QKeyEvent *event )
597 {
598  switch ( event->key() )
599  {
600  case Qt::Key_Return:
601  case Qt::Key_Enter:
602  case Qt::Key_Space:
603  {
604  QTreeWidgetItem *item = currentItem();
605  if ( item && !item->parent() )
606  {
607  event->accept();
608  toggleContextExpanded( item );
609  return;
610  }
611  else if ( item && ( item->flags() & Qt::ItemIsEditable ) )
612  {
613  event->accept();
614  editNext( currentIndex() );
615  return;
616  }
617  break;
618  }
619  default:
620  break;
621  }
623 }
624 
625 void QgsVariableEditorTree::mousePressEvent( QMouseEvent *event )
626 {
628  QTreeWidgetItem* item = itemAt( event->pos() );
629  if ( !item )
630  return;
631 
632  if ( item->parent() )
633  {
634  //not a top-level item
635  return;
636  }
637 
638  if ( event->pos().x() + header()->offset() > 20 )
639  {
640  //not clicking on expand icon
641  return;
642  }
643 
644  if ( event->modifiers() & Qt::ShiftModifier )
645  {
646  //shift modifier expands all
647  if ( !item->isExpanded() )
648  {
649  expandAll();
650  }
651  else
652  {
653  collapseAll();
654  }
655  }
656  else
657  {
658  toggleContextExpanded( item );
659  }
660 }
661 
662 //
663 // VariableEditorDelegate
664 //
665 
666 QWidget* VariableEditorDelegate::createEditor( QWidget *parent,
667  const QStyleOptionViewItem&,
668  const QModelIndex &index ) const
669 {
670  if ( !mParentTree )
671  return nullptr;
672 
673  //no editing for top level items
674  if ( !index.parent().isValid() )
675  return nullptr;
676 
677  QTreeWidgetItem *item = mParentTree->indexToItem( index );
678  QgsExpressionContextScope* scope = mParentTree->scopeFromItem( item );
679  if ( !item || !scope )
680  return nullptr;
681 
682  QString variableName = mParentTree->variableNameFromIndex( index );
683 
684  //no editing inherited or read-only variables
685  if ( scope != mParentTree->editableScope() || scope->isReadOnly( variableName ) )
686  return nullptr;
687 
688  QLineEdit *lineEdit = new QLineEdit( parent );
689  lineEdit->setText( index.column() == 0 ? variableName : mParentTree->editableScope()->variable( variableName ).toString() );
690  lineEdit->setAutoFillBackground( true );
691  return lineEdit;
692 }
693 
694 void VariableEditorDelegate::updateEditorGeometry( QWidget *editor,
695  const QStyleOptionViewItem &option,
696  const QModelIndex & ) const
697 {
698  editor->setGeometry( option.rect.adjusted( 0, 0, 0, -1 ) );
699 }
700 
701 QSize VariableEditorDelegate::sizeHint( const QStyleOptionViewItem &option,
702  const QModelIndex &index ) const
703 {
704  return QItemDelegate::sizeHint( option, index ) + QSize( 3, 4 );
705 }
706 
707 void VariableEditorDelegate::setModelData( QWidget* widget, QAbstractItemModel *model,
708  const QModelIndex& index ) const
709 {
710  Q_UNUSED( model );
711 
712  if ( !mParentTree )
713  return;
714 
715  QTreeWidgetItem *item = mParentTree->indexToItem( index );
716  QgsExpressionContextScope *scope = mParentTree->scopeFromItem( item );
717  if ( !item || !scope )
718  return;
719 
720  QLineEdit* lineEdit = qobject_cast< QLineEdit* >( widget );
721  if ( !lineEdit )
722  return;
723 
724  QString variableName = mParentTree->variableNameFromIndex( index );
725  if ( index.column() == 0 )
726  {
727  //edited variable name
728  QString newName = lineEdit->text();
729 
730  //test for validity
731  if ( newName == variableName )
732  {
733  return;
734  }
735  if ( scope->hasVariable( newName ) )
736  {
737  //existing name
738  QMessageBox::warning( mParentTree, tr( "Rename variable" ), tr( "A variable with the name \"%1\" already exists in this context." ).arg( newName ) );
739  newName.append( "_1" );
740  }
741 
742  QString value = scope->variable( variableName ).toString();
743  mParentTree->renameItem( item, newName );
744  scope->removeVariable( variableName );
745  scope->setVariable( newName, value );
746  mParentTree->emitChanged();
747  }
748  else if ( index.column() == 1 )
749  {
750  //edited variable value
751  QString value = lineEdit->text();
752  if ( scope->variable( variableName ).toString() == value )
753  {
754  return;
755  }
756  scope->setVariable( variableName, value );
757  mParentTree->emitChanged();
758  }
759  mParentTree->refreshTree();
760 }
761 
void setEditableScopeIndex(int scopeIndex)
Sets the editable scope for the widget.
bool hasVariable(const QString &name) const
Tests whether a variable with the specified name exists in the scope.
QgsExpressionContext * context() const
Returns the current expression context for the widget.
static unsigned index
void showEvent(QShowEvent *event) override
QString & append(QChar ch)
void setContentsMargins(int left, int top, int right, int bottom)
void fillRect(const QRectF &rectangle, const QBrush &brush)
void fill(const QColor &color)
virtual QModelIndex moveCursor(CursorAction cursorAction, QFlags< Qt::KeyboardModifier > modifiers)
void setText(const QString &)
void setToolTip(int column, const QString &toolTip)
void setFont(int column, const QFont &font)
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
void setIcon(int column, const QIcon &icon)
bool isReadOnly(const QString &name) const
Tests whether the specified variable is read only and should not be editable by users.
void save()
T value() const
void setFirstColumnSpanned(bool span)
virtual void setData(int column, int role, const QVariant &value)
QgsExpressionContextScope * editableScope() const
Returns the current editable scope for the widget.
void drawLine(const QLineF &line)
virtual QVariant data(int column, int role) const
bool isExpanded() const
void setIcon(const QIcon &icon)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setVariable(const QString &name, const QVariant &value)
Convenience method for setting a variable in the context scope by name and value. ...
int x() const
void setGeometry(int x, int y, int w, int h)
void reset(T *other)
QgsVariableEditorWidget(QWidget *parent=nullptr)
Constructor for QgsVariableEditorWidget.
void setBold(bool enable)
void scopeChanged()
Emitted when the user has modified a scope using the widget.
void setValue(const QString &key, const QVariant &value)
void setFlags(QFlags< Qt::ItemFlag > flags)
const char * name() const
bool isValid() const
bool removeVariable(const QString &name)
Removes a variable from the context scope, if found.
void setEnabled(bool)
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
virtual void showEvent(QShowEvent *event)
int toInt(bool *ok) const
void setPen(const QColor &color)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void addItem(QLayoutItem *item)
QString objectName() const
bool isEmpty() const
virtual int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const=0
int row() const
QFont font(int column) const
QVariant variable(const QString &name) const
Retrieves a variable&#39;s value from the scope.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Single scope for storing variables and functions for use within a QgsExpressionContext.
QModelIndex parent() const
Qt::KeyboardModifiers modifiers() const
T * data() const
int key() const
const QFont & font() const
QColor lighter(int factor) const
QTreeWidgetItem * parent() const
void setItalic(bool enable)
int indexOfChild(QTreeWidgetItem *child) const
void restore()
QVariant value(const QString &key, const QVariant &defaultValue) const
void setExpanded(bool expand)
Qt::ItemFlags flags() const
void reloadContext()
Reloads all scopes from the editor&#39;s current context.
QStyle * style()
QModelIndex sibling(int row, int column) const
QgsStringMap variablesInActiveScope() const
Returns a map variables set within the editable scope.
void setText(int column, const QString &text)
void setContext(QgsExpressionContext *context)
Overwrites the QgsExpressionContext for the widget.
int column() const
void setStrikeOut(bool enable)
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
virtual void mousePressEvent(QMouseEvent *event)
iterator insert(const Key &key, const T &value)
void setAutoFillBackground(bool enabled)
const QPoint & pos() const
QString toolTip() const
QString name() const
Returns the friendly display name of the context scope.
virtual void keyPressEvent(QKeyEvent *event)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
virtual bool event(QEvent *event)
QStringList filteredVariableNames() const
Returns a fitlered and sorted list of variable names contained within the scope.
QString text(int column) const
void setSpacing(int spacing)
virtual void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
void addLayout(QLayout *layout, int stretch)
QTreeWidgetItem * takeChild(int index)
typedef KeyboardModifiers