From 53476114df64ee419583c5504d038c2f03f32029 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 27 Mar 2024 10:20:27 +1000 Subject: [PATCH] Nicer approach to removing rows in expansion table --- .../qgssensorthingssourcewidget.cpp | 93 +++++++++++++++++-- .../qgssensorthingssourcewidget.h | 21 ++++- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/src/gui/providers/sensorthings/qgssensorthingssourcewidget.cpp b/src/gui/providers/sensorthings/qgssensorthingssourcewidget.cpp index fa51f35ebabb..eed15ec3ac03 100644 --- a/src/gui/providers/sensorthings/qgssensorthingssourcewidget.cpp +++ b/src/gui/providers/sensorthings/qgssensorthingssourcewidget.cpp @@ -444,7 +444,7 @@ QgsSensorThingsExpansionsModel::QgsSensorThingsExpansionsModel( QObject *parent int QgsSensorThingsExpansionsModel::columnCount( const QModelIndex & ) const { - return 4; + return 5; } int QgsSensorThingsExpansionsModel::rowCount( const QModelIndex &parent ) const @@ -485,6 +485,8 @@ Qt::ItemFlags QgsSensorThingsExpansionsModel::flags( const QModelIndex &index ) case Column::OrderBy: case Column::SortOrder: return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsSelectable; + case Column::Actions: + return Qt::ItemFlag::ItemIsEnabled; default: break; } @@ -521,6 +523,9 @@ QVariant QgsSensorThingsExpansionsModel::data( const QModelIndex &index, int rol case Column::SortOrder: return !expansion.isValid() ? QVariant() : ( expansion.sortOrder() == Qt::SortOrder::AscendingOrder ? tr( "Ascending" ) : tr( "Descending" ) ); + case Column::Actions: + return role == Qt::ToolTipRole ? tr( "Remove expansion" ) : QString(); + default: break; } @@ -586,6 +591,8 @@ QVariant QgsSensorThingsExpansionsModel::headerData( int section, Qt::Orientatio return tr( "Order By" ); case Column::SortOrder: return tr( "Sort Order" ); + case Column::Actions: + return QString(); default: break; } @@ -616,12 +623,6 @@ bool QgsSensorThingsExpansionsModel::setData( const QModelIndex &index, const QV { if ( wasInvalid ) break; - - // entity type cleared, remove row, and all subsequent ones - beginRemoveRows( QModelIndex(), index.row() + 1, mExpansions.size() - 1 ); - mExpansions = mExpansions.mid( 0, index.row() ); - mExpansions.append( QgsSensorThingsExpansionDefinition() ); - endRemoveRows(); } else { @@ -695,6 +696,13 @@ bool QgsSensorThingsExpansionsModel::removeRows( int position, int rows, const Q for ( int i = 0; i < rows; ++i ) mExpansions.removeAt( position ); endRemoveRows(); + + if ( mExpansions.empty() ) + { + beginInsertRows( QModelIndex(), 0, 0 ); + mExpansions.append( QgsSensorThingsExpansionDefinition() ); + endInsertRows(); + } return true; } @@ -733,6 +741,18 @@ QgsSensorThingsConfigureExpansionsDialog::QgsSensorThingsConfigureExpansionsDial mTable->setItemDelegateForColumn( 1, tableDelegate ); mTable->setItemDelegateForColumn( 2, tableDelegate ); mTable->setItemDelegateForColumn( 3, tableDelegate ); + + QgsSensorThingsRemoveExpansionDelegate *removeDelegate = new QgsSensorThingsRemoveExpansionDelegate( mTable ); + mTable->setItemDelegateForColumn( 4, removeDelegate ); + mTable->viewport()->installEventFilter( removeDelegate ); + connect( mTable, &QTableView::clicked, this, [this]( const QModelIndex & index ) + { + if ( index.column() == QgsSensorThingsExpansionsModel::Column::Actions ) + { + mModel->removeRows( index.row(), 1 ); + } + } ); + mTable->setEditTriggers( QAbstractItemView::AllEditTriggers ); mTable->verticalHeader()->hide(); const QFontMetrics fm( font() ); @@ -740,6 +760,7 @@ QgsSensorThingsConfigureExpansionsDialog::QgsSensorThingsConfigureExpansionsDial mTable->horizontalHeader()->resizeSection( QgsSensorThingsExpansionsModel::Column::Limit, fm.horizontalAdvance( '0' ) * 15 ); mTable->horizontalHeader()->resizeSection( QgsSensorThingsExpansionsModel::Column::OrderBy, fm.horizontalAdvance( '0' ) * 30 ); mTable->horizontalHeader()->resizeSection( QgsSensorThingsExpansionsModel::Column::SortOrder, fm.horizontalAdvance( '0' ) * 15 ); + mTable->horizontalHeader()->resizeSection( QgsSensorThingsExpansionsModel::Column::Actions, fm.horizontalAdvance( '0' ) * 5 ); hLayout->addWidget( mTable, 1 ); @@ -793,7 +814,6 @@ QWidget *QgsSensorThingsExpansionsDelegate::createEditor( QWidget *parent, const } QComboBox *combo = new QComboBox( parent ); - combo->addItem( QString() ); for ( Qgis::SensorThingsEntity type : compatibleEntities ) { combo->addItem( QgsSensorThingsUtils::displayString( type, true ), QVariant::fromValue( type ) ); @@ -904,4 +924,61 @@ void QgsSensorThingsExpansionsDelegate::setModelData( QWidget *editor, QAbstract } } + +// +// QgsSensorThingsRemoveExpansionDelegate +// + +QgsSensorThingsRemoveExpansionDelegate::QgsSensorThingsRemoveExpansionDelegate( QObject *parent ) + : QStyledItemDelegate( parent ) +{ + +} + +bool QgsSensorThingsRemoveExpansionDelegate::eventFilter( QObject *obj, QEvent *event ) +{ + if ( event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove ) + { + QHoverEvent *hoverEvent = static_cast( event ); + if ( QAbstractItemView *view = qobject_cast( obj->parent() ) ) + { + const QModelIndex indexUnderMouse = view->indexAt( hoverEvent->pos() ); + setHoveredIndex( indexUnderMouse ); + view->viewport()->update(); + } + } + else if ( event->type() == QEvent::HoverLeave ) + { + setHoveredIndex( QModelIndex() ); + qobject_cast< QWidget * >( obj )->update(); + } + return QStyledItemDelegate::eventFilter( obj, event ); +} + +void QgsSensorThingsRemoveExpansionDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + QStyledItemDelegate::paint( painter, option, index ); + + if ( index == mHoveredIndex ) + { + QStyleOptionButton buttonOption; + buttonOption.initFrom( option.widget ); + buttonOption.rect = option.rect; + + option.widget->style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter ); + } + + const QIcon icon = QgsApplication::getThemeIcon( "/mIconClearItem.svg" ); + const QRect iconRect( option.rect.left() + ( option.rect.width() - 16 ) / 2, + option.rect.top() + ( option.rect.height() - 16 ) / 2, + 16, 16 ); + + icon.paint( painter, iconRect ); +} + +void QgsSensorThingsRemoveExpansionDelegate::setHoveredIndex( const QModelIndex &index ) +{ + mHoveredIndex = index; +} + ///@endcond diff --git a/src/gui/providers/sensorthings/qgssensorthingssourcewidget.h b/src/gui/providers/sensorthings/qgssensorthingssourcewidget.h index fee5e6893755..388bb8326032 100644 --- a/src/gui/providers/sensorthings/qgssensorthingssourcewidget.h +++ b/src/gui/providers/sensorthings/qgssensorthingssourcewidget.h @@ -45,7 +45,8 @@ class QgsSensorThingsExpansionsModel : public QAbstractItemModel Entity = 0, Limit = 1, OrderBy = 2, - SortOrder = 3 + SortOrder = 3, + Actions = 4, }; QgsSensorThingsExpansionsModel( QObject *parent ); @@ -86,6 +87,24 @@ class QgsSensorThingsExpansionsDelegate : public QStyledItemDelegate Qgis::SensorThingsEntity mBaseEntityType = Qgis::SensorThingsEntity::Invalid; }; + +class QgsSensorThingsRemoveExpansionDelegate : public QStyledItemDelegate SIP_SKIP +{ + Q_OBJECT + + public: + QgsSensorThingsRemoveExpansionDelegate( QObject *parent ); + bool eventFilter( QObject *obj, QEvent *event ) override; + protected: + void paint( QPainter *painter, + const QStyleOptionViewItem &option, const QModelIndex &index ) const override; + private: + void setHoveredIndex( const QModelIndex &index ); + + QModelIndex mHoveredIndex; +}; + + class QgsSensorThingsConfigureExpansionsDialog : public QDialog { Q_OBJECT