Merge pull request #60600 from gacarrillor/dragndrop_stackdiagrams_followup

Fix drag and drop for stacked diagrams (follow-up)
This commit is contained in:
Mathieu Pellerin 2025-03-21 15:14:28 +07:00 committed by GitHub
commit 4d33cac8ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 82 additions and 12 deletions

View File

@ -63,10 +63,14 @@ QgsStackedDiagramProperties::QgsStackedDiagramProperties( QgsVectorLayer *layer,
mModel = new QgsStackedDiagramPropertiesModel();
mSubDiagramsView->setModel( mModel );
mSubDiagramsView->setStyle( new QgsStackedDiagramsViewStyle( mSubDiagramsView ) );
connect( mModel, &QAbstractItemModel::dataChanged, this, &QgsStackedDiagramProperties::widgetChanged );
connect( mModel, &QAbstractItemModel::rowsInserted, this, &QgsStackedDiagramProperties::widgetChanged );
connect( mModel, &QAbstractItemModel::rowsRemoved, this, &QgsStackedDiagramProperties::widgetChanged );
connect( mModel, &QgsStackedDiagramPropertiesModel::subDiagramsMoved, this, &QgsStackedDiagramProperties::clearCurrentIndex );
syncToLayer();
}
@ -86,7 +90,7 @@ void QgsStackedDiagramProperties::addSubDiagramRenderer()
const QModelIndex currentIndex = mSubDiagramsView->selectionModel()->currentIndex();
mModel->insertSubDiagram( currentIndex.row() + 1, renderer.release() );
const QModelIndex newIndex = mModel->index( currentIndex.row() + 1, 0 );
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect );
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
}
else
{
@ -101,7 +105,7 @@ void QgsStackedDiagramProperties::appendSubDiagramRenderer( QgsDiagramRenderer *
const int rows = mModel->rowCount();
mModel->insertSubDiagram( rows, dr ); // Transfers ownership
const QModelIndex newIndex = mModel->index( rows, 0 );
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect );
mSubDiagramsView->selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
}
void QgsStackedDiagramProperties::editSubDiagramRenderer()
@ -169,6 +173,11 @@ void QgsStackedDiagramProperties::removeSubDiagramRenderer()
mSubDiagramsView->selectionModel()->clear();
}
void QgsStackedDiagramProperties::clearCurrentIndex()
{
mSubDiagramsView->selectionModel()->clearCurrentIndex();
}
void QgsStackedDiagramProperties::syncToLayer()
{
const QgsDiagramRenderer *dr = mLayer->diagramRenderer();
@ -197,6 +206,8 @@ void QgsStackedDiagramProperties::syncToLayer()
const QgsDiagramLayerSettings *dls = mLayer->diagramLayerSettings();
mModel->updateDiagramLayerSettings( *dls );
mSubDiagramsView->selectionModel()->clear();
}
}
@ -372,12 +383,16 @@ QgsStackedDiagramPropertiesModel::~QgsStackedDiagramPropertiesModel()
Qt::ItemFlags QgsStackedDiagramPropertiesModel::flags( const QModelIndex &index ) const
{
const Qt::ItemFlag checkable = ( index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags );
// Flat list, to ease drop handling valid indexes are not dropEnabled
if ( !index.isValid() )
return Qt::ItemIsDropEnabled;
// allow drop only at first column
const Qt::ItemFlag drop = ( index.column() == 0 ? Qt::ItemIsDropEnabled : Qt::NoItemFlags );
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | drop | checkable;
if ( index.column() == 0 )
flags |= Qt::ItemIsUserCheckable;
return flags;
}
Qt::DropActions QgsStackedDiagramPropertiesModel::supportedDropActions() const
@ -399,7 +414,11 @@ QMimeData *QgsStackedDiagramPropertiesModel::mimeData( const QModelIndexList &in
QDataStream stream( &encodedData, QIODevice::WriteOnly );
for ( const QModelIndex &index : indexes )
// Sort indexes since their order reflects selection order
QModelIndexList sortedIndexes = indexes;
std::sort( sortedIndexes.begin(), sortedIndexes.end() );
for ( const QModelIndex &index : std::as_const( sortedIndexes ) )
{
// each item consists of several columns - let's add it with just first one
if ( !index.isValid() || index.column() != 0 )
@ -423,6 +442,7 @@ QMimeData *QgsStackedDiagramPropertiesModel::mimeData( const QModelIndexList &in
bool QgsStackedDiagramPropertiesModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
{
Q_UNUSED( column )
Q_UNUSED( parent )
if ( action == Qt::IgnoreAction )
return true;
@ -430,17 +450,14 @@ bool QgsStackedDiagramPropertiesModel::dropMimeData( const QMimeData *data, Qt::
if ( !data->hasFormat( QStringLiteral( "application/vnd.text.list" ) ) )
return false;
if ( parent.column() > 0 )
return false;
QByteArray encodedData = data->data( QStringLiteral( "application/vnd.text.list" ) );
QDataStream stream( &encodedData, QIODevice::ReadOnly );
int rows = 0;
// the item was dropped at parent, we may decide where to put the items
if ( row == -1 )
{
// the item was dropped at a parent - we may decide where to put the items - let's append them
row = rowCount( parent );
row = mRenderers.count(); // let's append them (e.g., drop in empty space)
}
while ( !stream.atEnd() )
@ -480,6 +497,7 @@ bool QgsStackedDiagramPropertiesModel::dropMimeData( const QMimeData *data, Qt::
}
}
emit subDiagramsMoved(); // Let views know they can clean some things up
return true;
}
@ -681,3 +699,24 @@ QgsDiagramLayerSettings QgsStackedDiagramPropertiesModel::diagramLayerSettings()
{
return mDiagramLayerSettings;
}
// ------------------------------ View style --------------------------------
QgsStackedDiagramsViewStyle::QgsStackedDiagramsViewStyle( QWidget *parent )
: QgsProxyStyle( parent )
{}
void QgsStackedDiagramsViewStyle::drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget ) const
{
if ( element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull() )
{
QStyleOption opt( *option );
opt.rect.setLeft( 0 );
// draw always as line above, because we move item to that index
opt.rect.setHeight( 0 );
if ( widget )
opt.rect.setRight( widget->width() );
QProxyStyle::drawPrimitive( element, &opt, painter, widget );
return;
}
QProxyStyle::drawPrimitive( element, option, painter, widget );
}

View File

@ -24,6 +24,7 @@
#include "qgis_gui.h"
#include "qgsdiagramrenderer.h"
#include "ui_qgsstackeddiagrampropertiesbase.h"
#include "qgsproxystyle.h"
#include <QWidget>
#include <QDialog>
@ -88,11 +89,34 @@ class GUI_EXPORT QgsStackedDiagramPropertiesModel : public QAbstractTableModel
*/
void updateDiagramLayerSettings( QgsDiagramLayerSettings dls );
signals:
//! Informs views that subdiagrams were moved in the model.
void subDiagramsMoved();
protected:
QList<QgsDiagramRenderer *> mRenderers;
QgsDiagramLayerSettings mDiagramLayerSettings;
};
/**
* \ingroup gui
* \brief View style which shows drop indicator line between items
*
* \since QGIS 3.40.6
*/
class QgsStackedDiagramsViewStyle : public QgsProxyStyle
{
Q_OBJECT
public:
/**
* Constructor for QgsStackedDiagramsViewStyle
* \param parent parent object
*/
explicit QgsStackedDiagramsViewStyle( QWidget *parent );
void drawPrimitive( PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr ) const override;
};
/**
* \ingroup gui
@ -118,6 +142,13 @@ class GUI_EXPORT QgsStackedDiagramProperties : public QgsPanelWidget, private Ui
public slots:
void apply();
/**
* Clears current item from the view.
*
* \since QGIS 3.40.6
*/
void clearCurrentIndex();
private slots:
/**