From aa414c9bb7a4c65d0722b974c65698a7a1dc7e93 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 71e887fbcd6a..b6338120907b 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 8af20e0eb185..d09940395fd3 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 3bafeb2b6c2da422e9bbc98250423d23004c2146 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 3872092a1922..d7b254af3c1d 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 b6338120907b..e7c310cfe367 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 d09940395fd3..0854368906f9 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 fb5ecd4fab069f66e088322fd10bf6a1df76868b 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 d7b254af3c1d..60e86dfe8f69 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 e7c310cfe367..bbdc99ca359e 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 0854368906f9..b6743d9f8383 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 c3cd89f1fb38cd1fe04aac5147dbd19369bf6d21 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 60e86dfe8f69..864adf01a6af 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 e2eae7e001b41abe9f838224edb53fdafad494b3 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 bbdc99ca359e..a1855d1e2ee0 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 b6743d9f8383..62568868bd7f 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;