915 changes: 915 additions & 0 deletions images/themes/gis/mIconDeselected.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
915 changes: 915 additions & 0 deletions images/themes/gis/mIconSelected.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 10 additions & 15 deletions src/app/qgsattributetabledialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
connect( mLayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) );
connect( mLayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( close() ) );
connect( mLayer, SIGNAL( selectionChanged() ), this, SLOT( updateTitle() ) );
connect( mLayer, SIGNAL( attributeAdded(int) ), this, SLOT( columnBoxInit() ) );
connect( mLayer, SIGNAL( attributeDeleted(int) ), this, SLOT( columnBoxInit() ) );

// connect table info to window
connect( mMainView, SIGNAL( filterChanged() ), this, SLOT( updateTitle() ) );

// info from table to application
connect( this, SIGNAL( saveEdits( QgsMapLayer * ) ), QgisApp::instance(), SLOT( saveEdits( QgsMapLayer * ) ) );
Expand Down Expand Up @@ -193,12 +199,11 @@ QgsAttributeTableDialog::~QgsAttributeTableDialog()
void QgsAttributeTableDialog::updateTitle()
{
QWidget *w = mDock ? qobject_cast<QWidget*>( mDock ) : qobject_cast<QWidget*>( this );
w->setWindowTitle( tr( "Attribute table - %1 :: %n / %2 feature(s) filtered",
"feature count",
mMainView->filteredFeatureCount()
)
w->setWindowTitle( tr( "Attribute table - %1 :: Features total: %2, filtered: %3, selected: %4" )
.arg( mLayer->name() )
.arg( mMainView->featureCount() )
.arg( mMainView->filteredFeatureCount() )
.arg( mLayer->selectedFeatureCount() )
);
}

Expand All @@ -219,6 +224,7 @@ void QgsAttributeTableDialog::columnBoxInit()
{
mFilterColumnsMenu->removeAction( a );
mFilterActionMapper->removeMappings( a );
mFilterButton->removeAction( a );
delete a;
}

Expand Down Expand Up @@ -345,7 +351,6 @@ void QgsAttributeTableDialog::on_mOpenFieldCalculator_clicked()
if ( col >= 0 )
{
masterModel->reload( masterModel->index( 0, col ), masterModel->index( masterModel->rowCount() - 1, col ) );
columnBoxInit();
}
}
}
Expand Down Expand Up @@ -610,14 +615,4 @@ void QgsAttributeTableDialog::setFilterExpression( QString filterString )
QgisApp::instance()->messageBar()->pushMessage( tr( "Error filtering" ), filterExpression.evalErrorString(), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() );
return;
}

QWidget *w = mDock ? qobject_cast<QWidget*>( mDock ) : qobject_cast<QWidget*>( this );
if ( mMainView->filteredFeatureCount() )
{
w->setWindowTitle( tr( "Attribute table - %1 (%n matching features)", "matching features", mMainView->filteredFeatureCount() ).arg( mMainView->filteredFeatureCount() ) );
}
else
{
w->setWindowTitle( tr( "Attribute table - %1 (No matching features)" ).arg( mLayer->name() ) );
}
}
13 changes: 7 additions & 6 deletions src/app/qgsattributetabledialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ class QgsAttributeTableDialog : public QDialog, private Ui::QgsAttributeTableDia
void filterQueryChanged( const QString& query );
void filterQueryAccepted();

/**
* update window title
*/
void updateTitle();

signals:
/**
* Informs that editing mode has been toggled
Expand All @@ -158,17 +163,13 @@ class QgsAttributeTableDialog : public QDialog, private Ui::QgsAttributeTableDia
*/
void closeEvent( QCloseEvent* event );

private:
private slots:
/**
* Initialize column box
*/
void columnBoxInit();

/**
* update window title
*/
void updateTitle();

private:
QMenu* mMenuActions;
QAction* mActionToggleEditing;

Expand Down
28 changes: 28 additions & 0 deletions src/core/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1511,6 +1511,18 @@ bool QgsVectorLayer::readXml( const QDomNode& layer_node )
updateFields();
connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( checkJoinLayerRemove( QString ) ) );

QDomNode prevExpNode = layer_node.namedItem( "previewExpression" );

if( prevExpNode.isNull() )
{
mDisplayExpression = "";
}
else
{
QDomElement prevExpElem = prevExpNode.toElement();
mDisplayExpression = prevExpElem.text();
}

QString errorMsg;
if ( !readSymbology( layer_node, errorMsg ) )
{
Expand Down Expand Up @@ -1658,6 +1670,12 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
layer_node.appendChild( provider );
}

// save preview expression
QDomElement prevExpElem = document.createElement( "previewExpression" );
QDomText prevExpText = document.createTextNode( mDisplayExpression );
prevExpElem.appendChild( prevExpText );
layer_node.appendChild( prevExpElem );

//save joins
mJoinBuffer->writeXml( layer_node, document );

Expand Down Expand Up @@ -2790,6 +2808,16 @@ const QString QgsVectorLayer::displayField() const
return mDisplayField;
}

void QgsVectorLayer::setDisplayExpression( const QString displayExpression )
{
mDisplayExpression = displayExpression;
}

const QString QgsVectorLayer::displayExpression()
{
return mDisplayExpression;
}

bool QgsVectorLayer::isEditable() const
{
return ( mEditBuffer && mDataProvider );
Expand Down
21 changes: 21 additions & 0 deletions src/core/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,24 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Returns the primary display field name used in the identify results dialog */
const QString displayField() const;

/** Set the preview expression, used to create a human readable preview string.
* Used e.g. in the attribute table feature list. Uses @link {QgsExpression}.
*
* @param previewExpression The expression which will be used to preview features
* for this layer
* @note added in 2.0
*/
void setDisplayExpression( const QString displayExpression );

/**
* Get the preview expression, used to create a human readable preview string.
* Uses @link {QgsExpression}.
*
* @return The expression which will be used to preview features for this layer
* @note added in 2.0
*/
const QString displayExpression();

/** Returns the data provider */
QgsVectorDataProvider* dataProvider();

Expand Down Expand Up @@ -973,6 +991,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** index of the primary label field */
QString mDisplayField;

/** the preview expression used to generate a human readable preview string for features */
QString mDisplayExpression;

/** Data provider key */
QString mProviderKey;

Expand Down
16 changes: 15 additions & 1 deletion src/gui/attributetable/qgsattributetablefiltermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ void QgsAttributeTableFilterModel::masterSelectionChanged( const QItemSelection
}

// Now emit the signal
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
if ( mSyncSelection )
{
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
}

connect( layer(), SIGNAL( selectionChanged() ), this, SLOT( selectionChanged() ) );
}
Expand Down Expand Up @@ -321,6 +324,17 @@ QItemSelectionModel* QgsAttributeTableFilterModel::masterSelection()
return mMasterSelection;
}

void QgsAttributeTableFilterModel::disableSelectionSync()
{
mSyncSelection = false;
}

void QgsAttributeTableFilterModel::enableSelectionSync()
{
mSyncSelection = true;
layer()->setSelectedFeatures( layer()->selectedFeaturesIds() );
}

QModelIndex QgsAttributeTableFilterModel::mapToMaster( const QModelIndex &proxyIndex ) const
{
// Master is source
Expand Down
21 changes: 21 additions & 0 deletions src/gui/attributetable/qgsattributetablefiltermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
*/
inline QgsVectorLayer *layer() const { return masterModel()->layer(); }

/**
* Returns the layerCache this filter acts on.
*
* @return The layer cache
*/
inline QgsVectorLayerCache *layerCache() const { return masterModel()->layerCache(); }

/**
Expand Down Expand Up @@ -120,6 +125,21 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
*/
QItemSelectionModel* masterSelection();

/**
* Disables selection synchronisation with the map canvas. Changes to the selection in the master
* model are propagated to the layer, but no redraw is requested until @link{enableSelectionSync()}
* is called.
*/
void disableSelectionSync();

/**
* Enables selection synchronisation with the map canvas. Changes to the selection in the master
* are propagated and upon every change, a redraw will be requested. This method will update the
* selection to account for any cached selection change since @link{disableSelectionSync()} was
* called.
*/
void enableSelectionSync();

virtual QModelIndex mapToMaster( const QModelIndex &proxyIndex ) const;

virtual QModelIndex mapFromMaster( const QModelIndex &sourceIndex ) const;
Expand Down Expand Up @@ -194,6 +214,7 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel
bool mSelectedOnTop;
QItemSelectionModel* mMasterSelection;
QgsAttributeTableModel* mTableModel;
bool mSyncSelection;
};

#endif
6 changes: 5 additions & 1 deletion src/gui/attributetable/qgsattributetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ void QgsAttributeTableModel::layerDeleted()

void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
{
if ( fid == mFeat.id() )
{
mFeat.setValid( false );
}
setData( index( idToRow( fid ), fieldCol( idx ) ), value, Qt::EditRole );
}

Expand Down Expand Up @@ -469,7 +473,7 @@ QVariant QgsAttributeTableModel::data( const QModelIndex &index, int role ) cons
}

// if we don't have the row in current cache, load it from layer first
if ( mFeat.id() != rowId )
if ( mFeat.id() != rowId || !mFeat.isValid() )
{
if ( !loadFeatureAtId( rowId ) )
return QVariant( "ERROR" );
Expand Down
39 changes: 22 additions & 17 deletions src/gui/attributetable/qgsattributetableview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ QgsAttributeTableView::QgsAttributeTableView( QWidget *parent )
setSelectionMode( QAbstractItemView::ExtendedSelection );
setSortingEnabled( true );

connect( verticalHeader(), SIGNAL( sectionClicked( int ) ), SLOT( onVerticalHeaderSectionClicked( int ) ) );
verticalHeader()->viewport()->installEventFilter( this );
}

QgsAttributeTableView::~QgsAttributeTableView()
Expand Down Expand Up @@ -75,6 +75,27 @@ void QgsAttributeTableView::setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVec
delete filterModel;
}

bool QgsAttributeTableView::eventFilter(QObject *object, QEvent *event)
{
if ( object == verticalHeader()->viewport() )
{
switch ( event->type() )
{
case QEvent::MouseButtonPress:
mFilterModel->disableSelectionSync();
break;

case QEvent::MouseButtonRelease:
mFilterModel->enableSelectionSync();
break;

default:
break;
}
}
return false;
}

void QgsAttributeTableView::setModel( QgsAttributeTableFilterModel* filterModel )
{
if ( mFilterModel )
Expand Down Expand Up @@ -158,22 +179,6 @@ void QgsAttributeTableView::keyPressEvent( QKeyEvent *event )
}
}

void QgsAttributeTableView::onVerticalHeaderSectionClicked( int logicalIndex )
{
Q_UNUSED( logicalIndex )

QgsFeatureIds selectedFeatures;

QModelIndexList selectedRows = selectionModel()->selectedRows();

foreach ( QModelIndex row, selectedRows )
{
selectedFeatures.insert( mFilterModel->rowToId( row ) );
}

emit selectionChangeFinished( selectedFeatures );
}

void QgsAttributeTableView::onFilterAboutToBeInvalidated()
{
disconnect( selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SLOT( onSelectionChanged( QItemSelection, QItemSelection ) ) );
Expand Down
28 changes: 12 additions & 16 deletions src/gui/attributetable/qgsattributetableview.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView
*/
void setCanvasAndLayerCache( QgsMapCanvas *canvas, QgsVectorLayerCache *layerCache );

/**
* This event filter is installed on the verticalHeader to intercept mouse press and release
* events. These are used to disable / enable live synchronisation with the map canvas selection
* which can be slow due to recurring canvas repaints. Updating the
*
* @param object The object which is the target of the event.
* @param event The intercepted event
*
* @return Returns always false, so the event gets processed
*/
virtual bool eventFilter( QObject* object, QEvent* event );

protected:
/**
* Called for mouse press events on a table cell.
Expand Down Expand Up @@ -124,23 +136,7 @@ class GUI_EXPORT QgsAttributeTableView : public QTableView

void finished();

/**
* @brief
* Is emitted, after the selection has been changed.
*
* @param selectedFeatures A list of currently selected features.
*/
void selectionChangeFinished( const QgsFeatureIds &selectedFeatures );

public slots:
/**
* Is triggered after a mouse release event on the vertical header.
* Emits a selectionChangeFinished() signal, so the underlying sort filter
* can adapt to the current selection without disturbing the users current interaction.
*
* @param logicalIndex The section's logical index
*/
void onVerticalHeaderSectionClicked( int logicalIndex );
void onFilterAboutToBeInvalidated();
void onFilterInvalidated();
void onSelectionChanged( const QItemSelection& selected, const QItemSelection& deselected );
Expand Down
101 changes: 66 additions & 35 deletions src/gui/attributetable/qgsdualview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ QgsDualView::QgsDualView( QWidget* parent )
// Connect layer list preview signals
connect( mActionExpressionPreview, SIGNAL( triggered() ), SLOT( previewExpressionBuilder() ) );
connect( mPreviewActionMapper, SIGNAL( mapped( QObject* ) ), SLOT( previewColumnChanged( QObject* ) ) );
connect( mFeatureList, SIGNAL( displayExpressionChanged(QString) ), this, SLOT( previewExpressionChanged(QString) ) );
}

QgsDualView::~QgsDualView()
Expand Down Expand Up @@ -76,6 +77,54 @@ void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QgsDista

void QgsDualView::columnBoxInit()
{
// load fields
QList<QgsField> fields = mLayerCache->layer()->pendingFields().toList();

// default expression: saved value
QString displayExpression = mLayerCache->layer()->displayExpression();

// if no display expression is saved: use display field instead
if ( displayExpression == "" )
{
displayExpression = mLayerCache->layer()->displayField();
}

// if neither diaplay expression nor display field is saved...
if ( displayExpression == "" )
{
QgsAttributeList pkAttrs = mLayerCache->layer()->pendingPkAttributesList();

if ( pkAttrs.size() > 0 )
{
// ... If there are primary key(s) defined
QStringList pkFields;

foreach ( int attr, pkAttrs )
{
pkFields.append( "\"" + fields[attr].name() + "\"" );
}

displayExpression = pkFields.join( "||', '||" );
}
else if ( fields.size() > 0 )
{
// ... concat all fields
QStringList fieldNames;
foreach ( QgsField field, fields )
{
fieldNames.append( "\"" + field.name() + "\"" );
}

displayExpression = fieldNames.join( "||', '||" );
}
else
{
// ... there isn't really much to display
displayExpression = "[Please define preview text]";
}
}

// now initialise the menu
QList< QAction* > previewActions = mFeatureListPreviewButton->actions();
foreach ( QAction* a, previewActions )
{
Expand All @@ -89,8 +138,6 @@ void QgsDualView::columnBoxInit()
mFeatureListPreviewButton->addAction( mActionExpressionPreview );
mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );

QList<QgsField> fields = mLayerCache->layer()->pendingFields().toList();

foreach ( const QgsField field, fields )
{
if ( mLayerCache->layer()->editType( mLayerCache->layer()->fieldNameIndex( field.name() ) ) != QgsVectorLayer::Hidden )
Expand All @@ -104,45 +151,18 @@ void QgsDualView::columnBoxInit()
connect( previewAction, SIGNAL( triggered() ), mPreviewActionMapper, SLOT( map() ) );
mPreviewColumnsMenu->addAction( previewAction );

if ( text == mLayerCache->layer()->displayField() )
if ( text == displayExpression )
{
mFeatureListPreviewButton->setDefaultAction( previewAction );
}
}
}

// Most likely no displayField is defined
// Join primary key fields
// If there is no single field found as preview
if ( !mFeatureListPreviewButton->defaultAction() )
{
mFeatureList->setDisplayExpression( displayExpression );
mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
QgsAttributeList pkAttrs = mLayerCache->layer()->pendingPkAttributesList();
// If there is a primary key defined
if ( pkAttrs.size() > 0 )
{
QStringList pkFields;

foreach ( int attr, pkAttrs )
{
pkFields.append( "\"" + fields[attr].name() + "\"" );
}

mFeatureList->setDisplayExpression( pkFields.join( "||', '||" ) );
}
else if ( fields.size() > 0 )
{
QStringList fieldNames;
foreach ( QgsField field, fields )
{
fieldNames.append( "\"" + field.name() + "\"" );
}

mFeatureList->setDisplayExpression( fieldNames.join( "||', '||" ) );
}
else
{
mFeatureList->setDisplayExpression( "[Please define preview text]" );
}
}
else
{
Expand Down Expand Up @@ -191,6 +211,10 @@ void QgsDualView::initModels( QgsMapCanvas* mapCanvas )
mMasterModel->loadLayer();

mFilterModel = new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );

connect( mFilterModel, SIGNAL( filterInvalidated() ), this, SIGNAL( filterChanged() ) );
connect( mFeatureList, SIGNAL( displayExpressionChanged(QString) ), this, SIGNAL( displayExpressionChanged(QString) ) );

mFeatureListModel = new QgsFeatureListModel( mFilterModel, mFilterModel );
}

Expand Down Expand Up @@ -272,9 +296,11 @@ void QgsDualView::previewColumnChanged( QObject* action )
.arg( mFeatureList->parserErrorString() )
);
}

mFeatureListPreviewButton->setDefaultAction( previewAction );
mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
else
{
mFeatureListPreviewButton->setDefaultAction( previewAction );
mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
}
}

Q_ASSERT( previewAction );
Expand Down Expand Up @@ -325,6 +351,11 @@ void QgsDualView::viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex )
menu->addAction( tr( "Open form" ), a, SLOT( featureForm() ) );
}

void QgsDualView::previewExpressionChanged( const QString expression )
{
mLayerCache->layer()->setDisplayExpression( expression );
}

void QgsDualView::setFilteredFeatures( QgsFeatureIds filteredFeatures )
{
mFilterModel->setFilteredFeatures( filteredFeatures );
Expand Down
12 changes: 12 additions & 0 deletions src/gui/attributetable/qgsdualview.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
void setCurrentEditSelection( const QgsFeatureIds& fids );

signals:
/**
* Is emitted, whenever the display expression is successfully changed
* @param The expression that was applied
*/
void displayExpressionChanged( const QString expression );

/**
* Is emitted, whenever the filter changes
*/
void filterChanged();

private slots:
/**
Expand All @@ -113,6 +123,8 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas

void viewWillShowContextMenu( QMenu* menu, QModelIndex atIndex );

void previewExpressionChanged( const QString expression );

/**
* Will be called periodically, when loading layers from slow data providers.
*
Expand Down
10 changes: 10 additions & 0 deletions src/gui/attributetable/qgsfeaturelistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,13 @@ int QgsFeatureListModel::rowCount( const QModelIndex& parent ) const
Q_UNUSED( parent )
return sourceModel()->rowCount();
}

void QgsFeatureListModel::disableSelectionSync()
{
mFilterModel->disableSelectionSync();
}

void QgsFeatureListModel::enableSelectionSync()
{
mFilterModel->enableSelectionSync();
}
15 changes: 15 additions & 0 deletions src/gui/attributetable/qgsfeaturelistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ class QgsFeatureListModel : public QAbstractProxyModel
virtual int columnCount( const QModelIndex&parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;

/**
* Disables selection synchronisation with the map canvas. Changes to the selection in the master
* model are propagated to the layer, but no redraw is requested until @link{enableSelectionSync()}
* is called.
*/
void disableSelectionSync();

/**
* Enables selection synchronisation with the map canvas. Changes to the selection in the master
* are propagated and upon every change, a redraw will be requested. This method will update the
* selection to account for any cached selection change since @link{disableSelectionSync()} was
* called.
*/
void enableSelectionSync();

public slots:
void onBeginRemoveRows( const QModelIndex& parent, int first, int last );
void onEndRemoveRows( const QModelIndex& parent, int first, int last );
Expand Down
25 changes: 20 additions & 5 deletions src/gui/attributetable/qgsfeaturelistview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,15 @@ void QgsFeatureListView::setModel( QgsFeatureListModel* featureListModel )

bool QgsFeatureListView::setDisplayExpression( const QString expression )
{
return mModel->setDisplayExpression( expression );
if ( mModel->setDisplayExpression( expression ) )
{
emit displayExpressionChanged( expression );
return true;
}
else
{
return false;
}
}

const QString& QgsFeatureListView::displayExpression() const
Expand Down Expand Up @@ -106,7 +114,7 @@ void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
{
QPoint pos = event->pos();

if ( QgsFeatureListViewDelegate::EditButtonElement == mItemDelegate->positionToElement( event->pos() ) )
if ( QgsFeatureListViewDelegate::EditElement == mItemDelegate->positionToElement( event->pos() ) )
{
mEditSelectionDrag = true;
QModelIndex index = mModel->mapToMaster( indexAt( pos ) );
Expand All @@ -115,15 +123,22 @@ void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
}
else
{
mModel->disableSelectionSync();
QListView::mousePressEvent( event );
}
}

void QgsFeatureListView::mouseReleaseEvent( QMouseEvent *event )
{
mEditSelectionDrag = false;

QListView::mouseReleaseEvent( event );
if ( mEditSelectionDrag )
{
mEditSelectionDrag = false;
}
else
{
QListView::mouseReleaseEvent( event );
mModel->enableSelectionSync();
}
}

void QgsFeatureListView::editSelectionChanged( QItemSelection deselected, QItemSelection selected )
Expand Down
6 changes: 6 additions & 0 deletions src/gui/attributetable/qgsfeaturelistview.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ class GUI_EXPORT QgsFeatureListView : public QListView
*/
void currentEditSelectionChanged( QgsFeature &feat );

/**
* Is emitted, whenever the display expression is successfully changed
* @param The expression that was applied
*/
void displayExpressionChanged( const QString expression );

public slots:
/**
* Set the feature(s) to be edited
Expand Down
44 changes: 23 additions & 21 deletions src/gui/attributetable/qgsfeaturelistviewdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ QgsFeatureListViewDelegate::QgsFeatureListViewDelegate( QgsFeatureListModel *lis

QgsFeatureListViewDelegate::Element QgsFeatureListViewDelegate::positionToElement( const QPoint &pos )
{
if ( pos.x() < sIconSize )
if ( pos.x() > sIconSize )
{
return EditButtonElement;
return EditElement;
}
else
{
return TextElement;
return SelectionElement;
}
}

Expand All @@ -45,46 +45,48 @@ void QgsFeatureListViewDelegate::paint( QPainter *painter, const QStyleOptionVie
{
QString text = index.model()->data( index, Qt::EditRole ).toString();
QgsFeatureListModel::FeatureInfo featInfo = index.model()->data( index, Qt::UserRole ).value<QgsFeatureListModel::FeatureInfo>();
bool isEdited = mEditSelectionModel->isSelected( mListModel->mapToMaster( index ) );

// Edit button state
bool checked = mEditSelectionModel->isSelected( mListModel->mapToMaster( index ) );
// Icon layout options
QStyleOptionViewItem iconOption;

QStyleOptionButton pbn1Opts;
QRect iconLayoutBounds( option.rect.x(), option.rect.y(), option.rect.height(), option.rect.height() );

pbn1Opts.iconSize = QSize( sIconSize, sIconSize );
QPixmap icon;

pbn1Opts.state |= QStyle::State_Enabled;
if ( checked )
if ( option.state.testFlag( QStyle::State_Selected ) )
{
pbn1Opts.icon = QgsApplication::getThemeIcon( "/mIconEditableEdits.png" );
pbn1Opts.state |= QStyle::State_On;
// Item is selected
icon = QgsApplication::getThemePixmap( "/mIconSelected.svg" );
}
else
{
pbn1Opts.icon = QgsApplication::getThemeIcon( "/mIconEditable.png" );
pbn1Opts.state |= QStyle::State_Off;
icon = QgsApplication::getThemePixmap( "/mIconDeselected.svg" );
}

QRect pbn1Rect( option.rect.x(), option.rect.y(), option.rect.height(), option.rect.height() );
pbn1Opts.rect = pbn1Rect;
// Text layout options
QRect textLayoutBounds( iconLayoutBounds.x() + iconLayoutBounds.width(), option.rect.y(), option.rect.width() - ( iconLayoutBounds.x() + iconLayoutBounds.width() ), option.rect.height() );

QApplication::style()->drawControl( QStyle::CE_PushButton, &pbn1Opts, painter );

QRect textLayoutBounds( pbn1Rect.x() + pbn1Rect.width(), option.rect.y(), option.rect.width() - ( pbn1Rect.x() + pbn1Rect.width() ), option.rect.height() );

QStyleOptionViewItem textOption = option;
QStyleOptionViewItem textOption;
textOption.state |= QStyle::State_Enabled;
if ( isEdited )
{
textOption.state |= QStyle::State_Selected;
}

if ( featInfo.isNew )
{
textOption.font.setStyle( QFont::StyleItalic );
textOption.palette.setColor( QPalette::Text, Qt::darkGreen );
textOption.palette.setColor( QPalette::HighlightedText, Qt::darkGreen );
}
else if ( featInfo.isEdited || checked )
else if ( featInfo.isEdited || isEdited )
{
textOption.font.setStyle( QFont::StyleItalic );
textOption.palette.setColor( QPalette::Text, Qt::red );
textOption.palette.setColor( QPalette::HighlightedText, Qt::red );
}

drawDisplay( painter, textOption, textLayoutBounds, text );
drawDecoration( painter, iconOption, iconLayoutBounds, icon );
}
4 changes: 2 additions & 2 deletions src/gui/attributetable/qgsfeaturelistviewdelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class QgsFeatureListViewDelegate : public QItemDelegate

enum Element
{
EditButtonElement,
TextElement
EditElement,
SelectionElement
};

explicit QgsFeatureListViewDelegate( QgsFeatureListModel* listModel, QObject *parent = 0 );
Expand Down