From 809bdd4270f5c67c96e16e9e7c88e5ab3350e4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Tue, 11 Feb 2025 21:37:15 +0100 Subject: [PATCH 1/5] [ux] In graduated and categorized symbol lists, make sure we don't append to the end when dropping an item between other items (fix #50823) --- src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp | 7 ++++--- src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index df461a52d892..fd259ab4fd95 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -113,7 +113,7 @@ Qt::ItemFlags QgsCategorizedSymbolRendererModel::flags( const QModelIndex &index return Qt::ItemIsDropEnabled; } - Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable; + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable; if ( index.column() == 1 ) { const QgsRendererCategory category = mRenderer->categories().value( index.row() ); @@ -398,8 +398,8 @@ QMimeData *QgsCategorizedSymbolRendererModel::mimeData( const QModelIndexList &i bool QgsCategorizedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { - Q_UNUSED( row ) Q_UNUSED( column ) + Q_UNUSED( parent ) if ( action != Qt::MoveAction ) return true; @@ -417,7 +417,8 @@ bool QgsCategorizedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt: rows.append( r ); } - int to = parent.row(); + int to = row; + // to is -1 if dragged outside items, i.e. below any item, // then move to the last position if ( to == -1 ) diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index e9c030725a75..f2bef4b95e26 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -139,7 +139,7 @@ Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags( const QModelIndex &index ) return Qt::ItemIsDropEnabled; } - Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable; + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable; if ( index.column() == 2 ) { @@ -306,8 +306,8 @@ QMimeData *QgsGraduatedSymbolRendererModel::mimeData( const QModelIndexList &ind bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { - Q_UNUSED( row ) Q_UNUSED( column ) + Q_UNUSED( parent ) if ( action != Qt::MoveAction ) return true; @@ -325,7 +325,8 @@ bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::D rows.append( r ); } - int to = parent.row(); + int to = row; + // to is -1 if dragged outside items, i.e. below any item, // then move to the last position if ( to == -1 ) From a37bc82e9fbc98f990a8fc54906dd01360151b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Wed, 12 Feb 2025 09:25:20 +0100 Subject: [PATCH 2/5] [ux] In Point cloud classification list, make sure we don't append to the end when dropping an item between other items (fix qgis#60559) --- .../pointcloud/qgspointcloudclassifiedrendererwidget.cpp | 6 +++--- src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp | 2 +- src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp index e03d76a97dc9..2557c674ef70 100644 --- a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp +++ b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp @@ -83,7 +83,7 @@ Qt::ItemFlags QgsPointCloudClassifiedRendererModel::flags( const QModelIndex &in return Qt::ItemIsDropEnabled; } - Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable; + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable; if ( index.column() == 1 || index.column() == 2 || index.column() == 3 ) { flags |= Qt::ItemIsEditable; @@ -292,8 +292,8 @@ QMimeData *QgsPointCloudClassifiedRendererModel::mimeData( const QModelIndexList bool QgsPointCloudClassifiedRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { - Q_UNUSED( row ) Q_UNUSED( column ) + Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true; @@ -311,7 +311,7 @@ bool QgsPointCloudClassifiedRendererModel::dropMimeData( const QMimeData *data, rows.append( r ); } - int to = parent.row(); + int to = row; // to is -1 if dragged outside items, i.e. below any item, // then move to the last position if ( to == -1 ) diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index fd259ab4fd95..08b4121ecb5c 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -399,7 +399,7 @@ QMimeData *QgsCategorizedSymbolRendererModel::mimeData( const QModelIndexList &i bool QgsCategorizedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { Q_UNUSED( column ) - Q_UNUSED( parent ) + Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true; diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index f2bef4b95e26..8e0806c52e87 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -307,7 +307,7 @@ QMimeData *QgsGraduatedSymbolRendererModel::mimeData( const QModelIndexList &ind bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { Q_UNUSED( column ) - Q_UNUSED( parent ) + Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true; From 4d9a55342cec7c4d19d215cb77cfa840fdbe6833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Mon, 17 Feb 2025 09:26:29 +0100 Subject: [PATCH 3/5] [ux] Symbology drag'n'drop harmonization: Make sure symbology items being dragged are properly sorted to guarantee that they keep the same relative order when dropped (i.e., higher items before being dragged, will remain higher with respect to other dragged items after the drop). --- src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp | 3 +++ src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp | 3 +++ src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp index 2557c674ef70..0d630ca66936 100644 --- a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp +++ b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp @@ -311,6 +311,9 @@ bool QgsPointCloudClassifiedRendererModel::dropMimeData( const QMimeData *data, rows.append( r ); } + // Items may come unsorted depending on selecion order + std::sort( rows.begin(), rows.end() ); + int to = row; // to is -1 if dragged outside items, i.e. below any item, // then move to the last position diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index 08b4121ecb5c..be085f56e54a 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -417,6 +417,9 @@ bool QgsCategorizedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt: rows.append( r ); } + // Items may come unsorted depending on selecion order + std::sort( rows.begin(), rows.end() ); + int to = row; // to is -1 if dragged outside items, i.e. below any item, diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index 8e0806c52e87..12772ec4c89e 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -325,6 +325,9 @@ bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::D rows.append( r ); } + // Items may come unsorted depending on selecion order + std::sort( rows.begin(), rows.end() ); + int to = row; // to is -1 if dragged outside items, i.e. below any item, From 11348b8407f496245b59f50d9655d84c9688f333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Thu, 20 Feb 2025 16:17:54 +0100 Subject: [PATCH 4/5] [ux] Symbology drag'n'drop harmonization: Once items are drag'n'dropped in Point Cloud classification list, clear item selection. --- .../qgspointcloudclassifiedrendererwidget.cpp | 10 +++++++++- .../pointcloud/qgspointcloudclassifiedrendererwidget.h | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp index 0d630ca66936..1af671b435f6 100644 --- a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp +++ b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.cpp @@ -78,6 +78,7 @@ QgsPointCloudCategory QgsPointCloudClassifiedRendererModel::category( const QMod Qt::ItemFlags QgsPointCloudClassifiedRendererModel::flags( const QModelIndex &index ) const { + // Flat list, to ease drop handling valid indexes are not dropEnabled if ( !index.isValid() || mCategories.empty() ) { return Qt::ItemIsDropEnabled; @@ -293,7 +294,7 @@ QMimeData *QgsPointCloudClassifiedRendererModel::mimeData( const QModelIndexList bool QgsPointCloudClassifiedRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { Q_UNUSED( column ) - Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled + Q_UNUSED( parent ) // Unused because only invalid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true; @@ -342,6 +343,7 @@ bool QgsPointCloudClassifiedRendererModel::dropMimeData( const QMimeData *data, } emit dataChanged( createIndex( 0, 0 ), createIndex( mCategories.size(), 0 ) ); emit categoriesChanged(); + emit rowsMoved(); return false; } @@ -428,6 +430,7 @@ QgsPointCloudClassifiedRendererWidget::QgsPointCloudClassifiedRendererWidget( Qg connect( mAttributeComboBox, &QgsPointCloudAttributeComboBox::attributeChanged, this, &QgsPointCloudClassifiedRendererWidget::attributeChanged ); connect( mModel, &QgsPointCloudClassifiedRendererModel::categoriesChanged, this, &QgsPointCloudClassifiedRendererWidget::emitWidgetChanged ); + connect( mModel, &QgsPointCloudClassifiedRendererModel::rowsMoved, this, &QgsPointCloudClassifiedRendererWidget::rowsMoved ); connect( viewCategories, &QAbstractItemView::doubleClicked, this, &QgsPointCloudClassifiedRendererWidget::categoriesDoubleClicked ); connect( btnAddCategories, &QAbstractButton::clicked, this, &QgsPointCloudClassifiedRendererWidget::addCategories ); @@ -709,6 +712,11 @@ void QgsPointCloudClassifiedRendererWidget::changeCategoryPointSize() } } +void QgsPointCloudClassifiedRendererWidget::rowsMoved() +{ + viewCategories->selectionModel()->clear(); +} + QList QgsPointCloudClassifiedRendererWidget::selectedCategories() { QList rows; diff --git a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.h b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.h index cdaedb1449c0..10d30854d4be 100644 --- a/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.h +++ b/src/gui/pointcloud/qgspointcloudclassifiedrendererwidget.h @@ -70,6 +70,9 @@ class GUI_EXPORT QgsPointCloudClassifiedRendererModel : public QAbstractItemMode signals: void categoriesChanged(); + //! Informs views that categories were moved (e.g., via mCategories.move()) in the model. + void rowsMoved(); + private: QgsPointCloudCategoryList mCategories; QMap mPercentages; @@ -126,6 +129,7 @@ class GUI_EXPORT QgsPointCloudClassifiedRendererWidget : public QgsPointCloudRen void changeCategoryColor(); void changeCategoryOpacity(); void changeCategoryPointSize(); + void rowsMoved(); private: //! Sets default category and available classes From e5b242dabab8dcdd7c108adc0c678b9ec324c9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Carrillo?= Date: Thu, 20 Feb 2025 16:19:13 +0100 Subject: [PATCH 5/5] [ux] Symbology, drag and drop on flat lists: Add comments to clarify the approach and perhaps avoid eventual regressions later --- src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp | 3 ++- src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index be085f56e54a..c67b657841cb 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -108,6 +108,7 @@ QgsRendererCategory QgsCategorizedSymbolRendererModel::category( const QModelInd Qt::ItemFlags QgsCategorizedSymbolRendererModel::flags( const QModelIndex &index ) const { + // Flat list, to ease drop handling valid indexes are not dropEnabled if ( !index.isValid() || !mRenderer ) { return Qt::ItemIsDropEnabled; @@ -399,7 +400,7 @@ QMimeData *QgsCategorizedSymbolRendererModel::mimeData( const QModelIndexList &i bool QgsCategorizedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { Q_UNUSED( column ) - Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled + Q_UNUSED( parent ) // Unused because only invalid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true; diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index 12772ec4c89e..605e54c5624b 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -134,6 +134,7 @@ QgsRendererRange QgsGraduatedSymbolRendererModel::rendererRange( const QModelInd Qt::ItemFlags QgsGraduatedSymbolRendererModel::flags( const QModelIndex &index ) const { + // Flat list, to ease drop handling valid indexes are not dropEnabled if ( !index.isValid() ) { return Qt::ItemIsDropEnabled; @@ -307,7 +308,7 @@ QMimeData *QgsGraduatedSymbolRendererModel::mimeData( const QModelIndexList &ind bool QgsGraduatedSymbolRendererModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { Q_UNUSED( column ) - Q_UNUSED( parent ) // Unused because only valid indexes have Qt::ItemIsDropEnabled + Q_UNUSED( parent ) // Unused because only invalid indexes have Qt::ItemIsDropEnabled if ( action != Qt::MoveAction ) return true;