QGIS API Documentation  2.14.0-Essen
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 QIcon QgsVariableEditorTree::mExpandIcon;
251 
252 QgsVariableEditorTree::QgsVariableEditorTree( QWidget *parent )
253  : QTreeWidget( parent )
254  , mEditorDelegate( nullptr )
255  , mEditableScopeIndex( -1 )
256  , mContext( nullptr )
257 {
258  // init icons
259  if ( mExpandIcon.isNull() )
260  {
261  QPixmap pix( 14, 14 );
262  pix.fill( Qt::transparent );
263  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconExpandSmall.svg" ).pixmap( 14, 14 ), QIcon::Normal, QIcon::Off );
264  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconExpandSmall.svg" ).pixmap( 14, 14 ), QIcon::Selected, QIcon::Off );
265  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconCollapseSmall.svg" ).pixmap( 14, 14 ), QIcon::Normal, QIcon::On );
266  mExpandIcon.addPixmap( QgsApplication::getThemeIcon( "/mIconCollapseSmall.svg" ).pixmap( 14, 14 ), QIcon::Selected, QIcon::On );
267  }
268 
269  setIconSize( QSize( 18, 18 ) );
270  setColumnCount( 2 );
271  setHeaderLabels( QStringList() << tr( "Variable" ) << tr( "Value" ) );
272  setAlternatingRowColors( true );
273  setEditTriggers( QAbstractItemView::AllEditTriggers );
274  setRootIsDecorated( false );
275  header()->setMovable( false );
276  header()->setResizeMode( QHeaderView::Interactive );
277 
278  mEditorDelegate = new VariableEditorDelegate( this, this );
279  setItemDelegate( mEditorDelegate );
280 }
281 
282 QgsExpressionContextScope* QgsVariableEditorTree::scopeFromItem( QTreeWidgetItem *item ) const
283 {
284  if ( !item )
285  return nullptr;
286 
287  bool ok;
288  int contextIndex = item->data( 0, ContextIndex ).toInt( &ok );
289  if ( !ok )
290  return nullptr;
291 
292  if ( !mContext )
293  {
294  return nullptr;
295  }
296  else if ( mContext->scopeCount() > contextIndex )
297  {
298  return mContext->scope( contextIndex );
299  }
300  else
301  {
302  return nullptr;
303  }
304 }
305 
306 QTreeWidgetItem* QgsVariableEditorTree::itemFromVariable( QgsExpressionContextScope *scope, const QString &name ) const
307 {
308  int contextIndex = mContext ? mContext->indexOfScope( scope ) : 0;
309  if ( contextIndex < 0 )
310  return nullptr;
311  return mVariableToItem.value( qMakePair( contextIndex, name ) );
312 }
313 
314 QgsExpressionContextScope* QgsVariableEditorTree::editableScope()
315 {
316  if ( !mContext || mEditableScopeIndex < 0 || mEditableScopeIndex >= mContext->scopeCount() )
317  {
318  return nullptr;
319  }
320 
321  return mContext->scope( mEditableScopeIndex );
322 }
323 
324 void QgsVariableEditorTree::refreshTree()
325 {
326  if ( !mContext || mEditableScopeIndex < 0 )
327  {
328  clear();
329  return;
330  }
331 
332  //add all scopes from the context
333  int scopeIndex = 0;
334  Q_FOREACH ( QgsExpressionContextScope* scope, mContext->scopes() )
335  {
336  refreshScopeItems( scope, scopeIndex );
337  scopeIndex++;
338  }
339 }
340 
341 void QgsVariableEditorTree::refreshScopeVariables( QgsExpressionContextScope* scope, int scopeIndex )
342 {
343  QColor baseColor = rowColor( scopeIndex );
344  bool isCurrent = scopeIndex == mEditableScopeIndex;
345  QTreeWidgetItem* scopeItem = mScopeToItem.value( scopeIndex );
346 
347  Q_FOREACH ( const QString& name, scope->filteredVariableNames() )
348  {
349  QTreeWidgetItem* item;
350  if ( mVariableToItem.contains( qMakePair( scopeIndex, name ) ) )
351  {
352  item = mVariableToItem.value( qMakePair( scopeIndex, name ) );
353  }
354  else
355  {
356  item = new QTreeWidgetItem( scopeItem );
357  mVariableToItem.insert( qMakePair( scopeIndex, name ), item );
358  }
359 
360  bool readOnly = scope->isReadOnly( name );
361  bool isActive = true;
362  QgsExpressionContextScope* activeScope = nullptr;
363  if ( mContext )
364  {
365  activeScope = mContext->activeScopeForVariable( name );
366  isActive = activeScope == scope;
367  }
368 
369  item->setFlags( item->flags() | Qt::ItemIsEnabled );
370  item->setText( 0, name );
371  QString value = scope->variable( name ).toString();
372  item->setText( 1, value );
373  QFont font = item->font( 0 );
374  if ( readOnly || !isCurrent )
375  {
376  font.setItalic( true );
377  item->setFlags( item->flags() ^ Qt::ItemIsEditable );
378  }
379  else
380  {
381  font.setItalic( false );
382  item->setFlags( item->flags() | Qt::ItemIsEditable );
383  }
384  if ( !isActive )
385  {
386  //overridden
387  font.setStrikeOut( true );
388  QString toolTip = tr( "Overridden by value from %1" ).arg( activeScope->name() );
389  item->setToolTip( 0, toolTip );
390  item->setToolTip( 1, toolTip );
391  }
392  else
393  {
394  font.setStrikeOut( false );
395  item->setToolTip( 0, name );
396  item->setToolTip( 1, value );
397  }
398  item->setFont( 0, font );
399  item->setFont( 1, font );
400  item->setData( 0, RowBaseColor, baseColor );
401  item->setData( 0, ContextIndex, scopeIndex );
402  item->setFirstColumnSpanned( false );
403  }
404 }
405 
406 void QgsVariableEditorTree::refreshScopeItems( QgsExpressionContextScope* scope, int scopeIndex )
407 {
408  QSettings settings;
409 
410  //add top level item
411  bool isCurrent = scopeIndex == mEditableScopeIndex;
412 
413  QTreeWidgetItem* scopeItem;
414  if ( mScopeToItem.contains( scopeIndex ) )
415  {
416  //retrieve existing item
417  scopeItem = mScopeToItem.value( scopeIndex );
418  }
419  else
420  {
421  //create new top-level item
422  scopeItem = new QTreeWidgetItem();
423  mScopeToItem.insert( scopeIndex, scopeItem );
424  scopeItem->setFlags( scopeItem->flags() | Qt::ItemIsEnabled );
425  scopeItem->setText( 0, scope->name() );
426  scopeItem->setFlags( scopeItem->flags() ^ Qt::ItemIsEditable );
427  scopeItem->setFirstColumnSpanned( true );
428  QFont scopeFont = scopeItem->font( 0 );
429  scopeFont .setBold( true );
430  scopeItem->setFont( 0, scopeFont );
431  scopeItem->setFirstColumnSpanned( true );
432 
433  addTopLevelItem( scopeItem );
434 
435  //expand by default if current context or context was previously expanded
436  if ( isCurrent || settings.value( "QgsVariableEditor/" + scopeItem->text( 0 ) + "/expanded" ).toBool() )
437  scopeItem->setExpanded( true );
438 
439  scopeItem->setIcon( 0, mExpandIcon );
440  }
441 
442  refreshScopeVariables( scope, scopeIndex );
443 }
444 
445 void QgsVariableEditorTree::removeItem( QTreeWidgetItem *item )
446 {
447  if ( !item )
448  return;
449 
450  mVariableToItem.remove( mVariableToItem.key( item ) );
451  item->parent()->takeChild( item->parent()->indexOfChild( item ) );
452 
453  emit scopeChanged();
454 }
455 
456 void QgsVariableEditorTree::renameItem( QTreeWidgetItem *item, const QString& name )
457 {
458  if ( !item )
459  return;
460 
461  int contextIndex = mVariableToItem.key( item ).first;
462  mVariableToItem.remove( mVariableToItem.key( item ) );
463  mVariableToItem.insert( qMakePair( contextIndex, name ), item );
464  item->setText( 0, name );
465 
466  emit scopeChanged();
467 }
468 
469 void QgsVariableEditorTree::resetTree()
470 {
471  mVariableToItem.clear();
472  mScopeToItem.clear();
473  clear();
474 }
475 
476 void QgsVariableEditorTree::emitChanged()
477 {
478  emit scopeChanged();
479 }
480 
481 void QgsVariableEditorTree::drawRow( QPainter* painter, const QStyleOptionViewItem& option,
482  const QModelIndex& index ) const
483 {
484  QStyleOptionViewItemV3 opt = option;
485  QTreeWidgetItem* item = itemFromIndex( index );
486  if ( index.parent().isValid() )
487  {
488  //not a top-level item, so shade row background by context
489  const QColor baseColor = item->data( 0, RowBaseColor ).value<QColor>();
490  painter->fillRect( option.rect, baseColor );
491  opt.palette.setColor( QPalette::AlternateBase, baseColor.lighter( 110 ) );
492  }
493  QTreeWidget::drawRow( painter, opt, index );
494  QColor color = static_cast<QRgb>( QApplication::style()->styleHint( QStyle::SH_Table_GridLineColor, &opt ) );
495  painter->save();
496  painter->setPen( QPen( color ) );
497  painter->drawLine( opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom() );
498  painter->restore();
499 }
500 
501 QColor QgsVariableEditorTree::rowColor( int index ) const
502 {
503  //return some nice (inspired by Qt Designer) background row colors
504  int colorIdx = index % 6;
505  switch ( colorIdx )
506  {
507  case 0:
508  return QColor( 255, 220, 167 );
509  case 1:
510  return QColor( 255, 255, 191 );
511  case 2:
512  return QColor( 191, 255, 191 );
513  case 3:
514  return QColor( 199, 255, 255 );
515  case 4:
516  return QColor( 234, 191, 255 );
517  case 5:
518  default:
519  return QColor( 255, 191, 239 );
520  }
521 }
522 
523 void QgsVariableEditorTree::toggleContextExpanded( QTreeWidgetItem* item )
524 {
525  if ( !item )
526  return;
527 
528  item->setExpanded( !item->isExpanded() );
529 
530  //save expanded state
531  QSettings settings;
532  settings.setValue( "QgsVariableEditor/" + item->text( 0 ) + "/expanded", item->isExpanded() );
533 }
534 
535 void QgsVariableEditorTree::editNext( const QModelIndex& index )
536 {
537  if ( !index.isValid() )
538  return;
539 
540  if ( index.column() == 0 )
541  {
542  //switch to next column
543  QModelIndex nextIndex = index.sibling( index.row(), 1 );
544  if ( nextIndex.isValid() )
545  {
546  setCurrentIndex( nextIndex );
547  edit( nextIndex );
548  }
549  }
550  else
551  {
552  QModelIndex nextIndex = model()->index( index.row() + 1, 0, index.parent() );
553  if ( nextIndex.isValid() )
554  {
555  //start editing next row
556  setCurrentIndex( nextIndex );
557  edit( nextIndex );
558  }
559  else
560  {
561  edit( index );
562  }
563  }
564 }
565 
566 QModelIndex QgsVariableEditorTree::moveCursor( QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers )
567 {
568  if ( cursorAction == QAbstractItemView::MoveNext )
569  {
570  QModelIndex index = currentIndex();
571  if ( index.isValid() )
572  {
573  if ( index.column() + 1 < model()->columnCount() )
574  return index.sibling( index.row(), index.column() + 1 );
575  else if ( index.row() + 1 < model()->rowCount( index.parent() ) )
576  return index.sibling( index.row() + 1, 0 );
577  else
578  return QModelIndex();
579  }
580  }
581  else if ( cursorAction == QAbstractItemView::MovePrevious )
582  {
583  QModelIndex index = currentIndex();
584  if ( index.isValid() )
585  {
586  if ( index.column() >= 1 )
587  return index.sibling( index.row(), index.column() - 1 );
588  else if ( index.row() >= 1 )
589  return index.sibling( index.row() - 1, model()->columnCount() - 1 );
590  else
591  return QModelIndex();
592  }
593  }
594 
595  return QTreeWidget::moveCursor( cursorAction, modifiers );
596 }
597 
598 void QgsVariableEditorTree::keyPressEvent( QKeyEvent *event )
599 {
600  switch ( event->key() )
601  {
602  case Qt::Key_Return:
603  case Qt::Key_Enter:
604  case Qt::Key_Space:
605  {
606  QTreeWidgetItem *item = currentItem();
607  if ( item && !item->parent() )
608  {
609  event->accept();
610  toggleContextExpanded( item );
611  return;
612  }
613  else if ( item && ( item->flags() & Qt::ItemIsEditable ) )
614  {
615  event->accept();
616  editNext( currentIndex() );
617  return;
618  }
619  break;
620  }
621  default:
622  break;
623  }
625 }
626 
627 void QgsVariableEditorTree::mousePressEvent( QMouseEvent *event )
628 {
630  QTreeWidgetItem* item = itemAt( event->pos() );
631  if ( !item )
632  return;
633 
634  if ( item->parent() )
635  {
636  //not a top-level item
637  return;
638  }
639 
640  if ( event->pos().x() + header()->offset() > 20 )
641  {
642  //not clicking on expand icon
643  return;
644  }
645 
646  if ( event->modifiers() & Qt::ShiftModifier )
647  {
648  //shift modifier expands all
649  if ( !item->isExpanded() )
650  {
651  expandAll();
652  }
653  else
654  {
655  collapseAll();
656  }
657  }
658  else
659  {
660  toggleContextExpanded( item );
661  }
662 }
663 
664 //
665 // VariableEditorDelegate
666 //
667 
668 QWidget* VariableEditorDelegate::createEditor( QWidget *parent,
669  const QStyleOptionViewItem&,
670  const QModelIndex &index ) const
671 {
672  if ( !mParentTree )
673  return nullptr;
674 
675  //no editing for top level items
676  if ( !index.parent().isValid() )
677  return nullptr;
678 
679  QTreeWidgetItem *item = mParentTree->indexToItem( index );
680  QgsExpressionContextScope* scope = mParentTree->scopeFromItem( item );
681  if ( !item || !scope )
682  return nullptr;
683 
684  QString variableName = mParentTree->variableNameFromIndex( index );
685 
686  //no editing inherited or read-only variables
687  if ( scope != mParentTree->editableScope() || scope->isReadOnly( variableName ) )
688  return nullptr;
689 
690  QLineEdit *lineEdit = new QLineEdit( parent );
691  lineEdit->setText( index.column() == 0 ? variableName : mParentTree->editableScope()->variable( variableName ).toString() );
692  lineEdit->setAutoFillBackground( true );
693  return lineEdit;
694 }
695 
696 void VariableEditorDelegate::updateEditorGeometry( QWidget *editor,
697  const QStyleOptionViewItem &option,
698  const QModelIndex & ) const
699 {
700  editor->setGeometry( option.rect.adjusted( 0, 0, 0, -1 ) );
701 }
702 
703 QSize VariableEditorDelegate::sizeHint( const QStyleOptionViewItem &option,
704  const QModelIndex &index ) const
705 {
706  return QItemDelegate::sizeHint( option, index ) + QSize( 3, 4 );
707 }
708 
709 void VariableEditorDelegate::setModelData( QWidget* widget, QAbstractItemModel *model,
710  const QModelIndex& index ) const
711 {
712  Q_UNUSED( model );
713 
714  if ( !mParentTree )
715  return;
716 
717  QTreeWidgetItem *item = mParentTree->indexToItem( index );
718  QgsExpressionContextScope *scope = mParentTree->scopeFromItem( item );
719  if ( !item || !scope )
720  return;
721 
722  QLineEdit* lineEdit = qobject_cast< QLineEdit* >( widget );
723  if ( !lineEdit )
724  return;
725 
726  QString variableName = mParentTree->variableNameFromIndex( index );
727  if ( index.column() == 0 )
728  {
729  //edited variable name
730  QString newName = lineEdit->text();
731 
732  //test for validity
733  if ( newName == variableName )
734  {
735  return;
736  }
737  if ( scope->hasVariable( newName ) )
738  {
739  //existing name
740  QMessageBox::warning( mParentTree, tr( "Rename variable" ), tr( "A variable with the name \"%1\" already exists in this context." ).arg( newName ) );
741  newName.append( "_1" );
742  }
743 
744  QString value = scope->variable( variableName ).toString();
745  mParentTree->renameItem( item, newName );
746  scope->removeVariable( variableName );
747  scope->setVariable( newName, value );
748  mParentTree->emitChanged();
749  }
750  else if ( index.column() == 1 )
751  {
752  //edited variable value
753  QString value = lineEdit->text();
754  if ( scope->variable( variableName ).toString() == value )
755  {
756  return;
757  }
758  scope->setVariable( variableName, value );
759  mParentTree->emitChanged();
760  }
761  mParentTree->refreshTree();
762 }
763 
void setEditableScopeIndex(int scopeIndex)
Sets the editable scope 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)
QgsExpressionContext * context() const
Returns the current expression context for the widget.
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.
void setIcon(int column, const QIcon &icon)
void save()
T value() const
void setFirstColumnSpanned(bool span)
virtual void setData(int column, int role, const QVariant &value)
bool hasVariable(const QString &name) const
Tests whether a variable with the specified name exists in the scope.
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.
QString name() const
Returns the friendly display name of the context scope.
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)
QStringList filteredVariableNames() const
Returns a fitlered and sorted list of variable names contained within the scope.
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
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
QVariant variable(const QString &name) const
Retrieves a variable&#39;s value from the scope.
Qt::KeyboardModifiers modifiers() const
T * data() const
int key() const
QgsStringMap variablesInActiveScope() const
Returns a map variables set within the editable scope.
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
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
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
bool isReadOnly(const QString &name) const
Tests whether the specified variable is read only and should not be editable by users.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
virtual bool event(QEvent *event)
QString text(int column) const
void setSpacing(int spacing)
virtual void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
QgsExpressionContextScope * editableScope() const
Returns the current editable scope for the widget.
QStringList variableNames() const
Returns a list of variable names contained within the scope.
void addLayout(QLayout *layout, int stretch)
QTreeWidgetItem * takeChild(int index)
typedef KeyboardModifiers