QGIS API Documentation  2.99.0-Master (0cba29c)
qgsattributetabledelegate.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsAttributeTableDelegate.cpp
3  --------------------------------------
4  Date : Feb 2009
5  Copyright : (C) 2009 Vita Cizek
6  Email : weetya (at) gmail.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 
16 #include <QItemDelegate>
17 #include <QLineEdit>
18 #include <QComboBox>
19 #include <QPainter>
20 #include <QToolButton>
21 
24 #include "qgsattributetablemodel.h"
25 #include "qgsattributetableview.h"
27 #include "qgseditorwidgetwrapper.h"
29 #include "qgslogger.h"
30 #include "qgsvectordataprovider.h"
31 #include "qgsactionmanager.h"
32 #include "qgsgui.h"
33 
34 QgsVectorLayer *QgsAttributeTableDelegate::layer( const QAbstractItemModel *model )
35 {
36  const QgsAttributeTableModel *tm = qobject_cast<const QgsAttributeTableModel *>( model );
37  if ( tm )
38  return tm->layer();
39 
40  const QgsAttributeTableFilterModel *fm = qobject_cast<const QgsAttributeTableFilterModel *>( model );
41  if ( fm )
42  return fm->layer();
43 
44  return nullptr;
45 }
46 
47 const QgsAttributeTableModel *QgsAttributeTableDelegate::masterModel( const QAbstractItemModel *model )
48 {
49  const QgsAttributeTableModel *tm = qobject_cast<const QgsAttributeTableModel *>( model );
50  if ( tm )
51  return tm;
52 
53  const QgsAttributeTableFilterModel *fm = qobject_cast<const QgsAttributeTableFilterModel *>( model );
54  if ( fm )
55  return fm->masterModel();
56 
57  return nullptr;
58 }
59 
60 QWidget *QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
61 {
62  Q_UNUSED( option );
63  QgsVectorLayer *vl = layer( index.model() );
64  if ( !vl )
65  return nullptr;
66 
67  int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();
68 
69  QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup );
70  QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vl, fieldIdx, nullptr, parent, context );
71  QWidget *w = eww->widget();
72 
73  w->setAutoFillBackground( true );
74  w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget
75 
76  eww->setEnabled( !vl->editFormConfig().readOnly( fieldIdx ) );
77 
78  return w;
79 }
80 
81 void QgsAttributeTableDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
82 {
83  QgsVectorLayer *vl = layer( model );
84  if ( !vl )
85  return;
86 
87  int fieldIdx = model->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();
88  QgsFeatureId fid = model->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
89  QVariant oldValue = model->data( index, Qt::EditRole );
90 
91  QVariant newValue;
93  if ( !eww )
94  return;
95 
96  newValue = eww->value();
97 
98  if ( ( oldValue != newValue && newValue.isValid() ) || oldValue.isNull() != newValue.isNull() )
99  {
100  // This fixes https://issues.qgis.org/issues/16492
101  QgsFeatureRequest request( fid );
104  QgsFeature feature;
105  vl->getFeatures( request ).nextFeature( feature );
106  if ( feature.isValid() )
107  {
108  vl->beginEditCommand( tr( "Attribute changed" ) );
109  vl->changeAttributeValue( fid, fieldIdx, newValue, oldValue );
110  vl->endEditCommand();
111  }
112  }
113 }
114 
115 void QgsAttributeTableDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
116 {
118  if ( !eww )
119  return;
120 
121  eww->setValue( index.model()->data( index, Qt::EditRole ) );
122 }
123 
125 {
126  mFeatureSelectionModel = featureSelectionModel;
127 }
128 
129 void QgsAttributeTableDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
130 {
132 
134  {
135  emit actionColumnItemPainted( index );
136  }
137  else
138  {
139  QgsFeatureId fid = index.model()->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
140 
141  QStyleOptionViewItem myOpt = option;
142 
143  if ( index.model()->data( index, Qt::EditRole ).isNull() )
144  {
145  myOpt.font.setItalic( true );
146  myOpt.palette.setColor( QPalette::Text, QColor( "gray" ) );
147  }
148 
149  if ( mFeatureSelectionModel && mFeatureSelectionModel->isSelected( fid ) )
150  myOpt.state |= QStyle::State_Selected;
151 
152  QItemDelegate::paint( painter, myOpt, index );
153 
154  if ( option.state & QStyle::State_HasFocus )
155  {
156  QRect r = option.rect.adjusted( 1, 1, -1, -1 );
157  QPen p( QBrush( QColor( 0, 255, 127 ) ), 2 );
158  painter->save();
159  painter->setPen( p );
160  painter->drawRect( r );
161  painter->restore();
162  }
163  }
164 }
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:176
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
virtual bool isSelected(QgsFeatureId fid)
Returns the selection status of a given feature id.
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Overloads the paint method form the QItemDelegate base class.
Get the field index of this column.
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
This class contains context information for attribute editor widgets.
Manages an editor widget Widget and wrapper share the same parent.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:61
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
void actionColumnItemPainted(const QModelIndex &index) const
Is emitted when an action column item is painted.
void setFeatureSelectionModel(QgsFeatureSelectionModel *featureSelectionModel)
Get the feature id of the feature in this row.
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
Used to create an editor for when the user tries to change the contents of a cell.
A widget was opened as a popup (e.g. attribute table editor widget)
void setEditorData(QWidget *editor, const QModelIndex &index) const override
Sets data from model into the editor.
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories...
Definition: qgsgui.cpp:43
static QgsEditorWidgetWrapper * fromWidget(QWidget *widget)
Will return a wrapper for a given widget.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
virtual void setValue(const QVariant &value)=0
Is called, when the value of the widget needs to be changed.
QgsEditFormConfig editFormConfig
void endEditCommand()
Finish edit command and add it to undo/redo stack.
QgsEditorWidgetWrapper * create(const QString &widgetId, QgsVectorLayer *vl, int fieldIdx, const QVariantMap &config, QWidget *editor, QWidget *parent, const QgsAttributeEditorContext &context=QgsAttributeEditorContext())
Create an attribute editor widget wrapper of a given type for a given field.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changes an attribute value (but does not commit it)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
Sets data from editor back to model.
virtual QVariant value() const =0
Will be used to access the widget&#39;s value.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
QWidget * widget()
Access the widget managed by this wrapper.
bool readOnly(int idx) const
This returns true if the field is manually set to read only or if the field does not support editing ...
QList< int > QgsAttributeList
Definition: qgsfield.h:27
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Set flags that affect how features will be fetched.