Skip to content

Commit

Permalink
Recalculate layout when legend item size changes
Browse files Browse the repository at this point in the history
Fixes #38881
  • Loading branch information
m-kuhn authored and nyalldawson committed Sep 20, 2020
1 parent 673d672 commit 2eaf5e6
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 7 deletions.
Expand Up @@ -207,6 +207,13 @@ Draws label on the right side of the item
void dataChanged();
%Docstring
Emitted on internal data change so the layer tree model can forward the signal to views
%End

void sizeChanged();
%Docstring
Emitted when the size of this node changes.

.. versionadded:: 3.16
%End

protected:
Expand Down
12 changes: 12 additions & 0 deletions src/core/layertree/qgslayertreemodel.cpp
Expand Up @@ -868,6 +868,17 @@ void QgsLayerTreeModel::legendNodeDataChanged()
emit dataChanged( index, index );
}

void QgsLayerTreeModel::legendNodeSizeChanged()
{
QgsLayerTreeModelLegendNode *legendNode = qobject_cast<QgsLayerTreeModelLegendNode *>( sender() );
if ( !legendNode )
return;

QModelIndex index = legendNode2index( legendNode );
if ( index.isValid() )
emit dataChanged( index, index, QVector<int> { Qt::SizeHintRole } );
}


void QgsLayerTreeModel::connectToLayer( QgsLayerTreeLayer *nodeLayer )
{
Expand Down Expand Up @@ -1293,6 +1304,7 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer *nodeL )
{
n->setParent( this );
connect( n, &QgsLayerTreeModelLegendNode::dataChanged, this, &QgsLayerTreeModel::legendNodeDataChanged );
connect( n, &QgsLayerTreeModelLegendNode::sizeChanged, this, &QgsLayerTreeModel::legendNodeSizeChanged );
}

// See if we have an embedded node - if we do, we will not use it among active nodes.
Expand Down
3 changes: 3 additions & 0 deletions src/core/layertree/qgslayertreemodel.h
Expand Up @@ -458,6 +458,9 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
double mLegendMapViewScale;
QTimer mDeferLegendInvalidationTimer;

private slots:
void legendNodeSizeChanged();

private:

//! Returns a temporary render context
Expand Down
10 changes: 10 additions & 0 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Expand Up @@ -68,6 +68,15 @@ QSizeF QgsLayerTreeModelLegendNode::userPatchSize() const
return mUserSize;
}

void QgsLayerTreeModelLegendNode::setUserPatchSize( QSizeF size )
{
if ( mUserSize == size )
return;

mUserSize = size;
emit sizeChanged();
}

QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( const QgsLegendSettings &settings, ItemContext *ctx )
{
QFont symbolLabelFont = settings.style( QgsLegendStyle::SymbolLabel ).font();
Expand Down Expand Up @@ -1146,6 +1155,7 @@ void QgsWmsLegendNode::getLegendGraphicFinished( const QImage &image )
if ( image != mImage )
{
mImage = image;
setUserPatchSize( mImage.size() );
emit dataChanged();
}
mValid = true; // only if not null I guess
Expand Down
9 changes: 8 additions & 1 deletion src/core/layertree/qgslayertreemodellegendnode.h
Expand Up @@ -107,7 +107,7 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
* \see userPatchSize()
* \since QGIS 3.14
*/
virtual void setUserPatchSize( QSizeF size ) { mUserSize = size; }
virtual void setUserPatchSize( QSizeF size );

/**
* Sets whether a forced column break should occur before the node.
Expand Down Expand Up @@ -255,6 +255,13 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
//! Emitted on internal data change so the layer tree model can forward the signal to views
void dataChanged();

/**
* Emitted when the size of this node changes.
*
* \since QGIS 3.16
*/
void sizeChanged();

protected:
//! Construct the node with pointer to its parent layer node
explicit QgsLayerTreeModelLegendNode( QgsLayerTreeLayer *nodeL, QObject *parent SIP_TRANSFERTHIS = nullptr );
Expand Down
28 changes: 22 additions & 6 deletions src/gui/layertree/qgslayertreeview.cpp
Expand Up @@ -76,28 +76,31 @@ QgsLayerTreeView::~QgsLayerTreeView()

void QgsLayerTreeView::setModel( QAbstractItemModel *model )
{
if ( !qobject_cast<QgsLayerTreeModel *>( model ) )
QgsLayerTreeModel *layerTreeModel = qobject_cast<QgsLayerTreeModel *>( model );
if ( !layerTreeModel )
return;

connect( model, &QAbstractItemModel::rowsInserted, this, &QgsLayerTreeView::modelRowsInserted );
connect( model, &QAbstractItemModel::rowsRemoved, this, &QgsLayerTreeView::modelRowsRemoved );

if ( mMessageBar )
connect( layerTreeModel(), &QgsLayerTreeModel::messageEmitted,
connect( layerTreeModel, &QgsLayerTreeModel::messageEmitted,
[ = ]( const QString & message, Qgis::MessageLevel level = Qgis::Info, int duration = 5 )
{mMessageBar->pushMessage( message, level, duration );}
);

QTreeView::setModel( model );

connect( layerTreeModel()->rootGroup(), &QgsLayerTreeNode::expandedChanged, this, &QgsLayerTreeView::onExpandedChanged );
connect( layerTreeModel()->rootGroup(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayerTreeView::onCustomPropertyChanged );
connect( layerTreeModel->rootGroup(), &QgsLayerTreeNode::expandedChanged, this, &QgsLayerTreeView::onExpandedChanged );
connect( layerTreeModel->rootGroup(), &QgsLayerTreeNode::customPropertyChanged, this, &QgsLayerTreeView::onCustomPropertyChanged );

connect( selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsLayerTreeView::onCurrentChanged );

connect( layerTreeModel(), &QAbstractItemModel::modelReset, this, &QgsLayerTreeView::onModelReset );
connect( layerTreeModel, &QAbstractItemModel::modelReset, this, &QgsLayerTreeView::onModelReset );

updateExpandedStateFromNode( layerTreeModel()->rootGroup() );
connect( layerTreeModel, &QgsLayerTreeModel::dataChanged, this, &QgsLayerTreeView::onDataChanged );

updateExpandedStateFromNode( layerTreeModel->rootGroup() );
}

QgsLayerTreeModel *QgsLayerTreeView::layerTreeModel() const
Expand Down Expand Up @@ -586,3 +589,16 @@ void QgsLayerTreeView::onHorizontalScroll( int value )
Q_UNUSED( value )
viewport()->update();
}

void QgsLayerTreeView::onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles )
{
Q_UNUSED( topLeft )
Q_UNUSED( bottomRight )

// If an item is resized asynchroneously (e.g. wms legend)
// The items below will need to be shifted vertically.
// This doesn't happen automatically, unless the viewport update is triggered.

if ( roles.contains( Qt::SizeHintRole ) )
viewport()->update();
}
2 changes: 2 additions & 0 deletions src/gui/layertree/qgslayertreeview.h
Expand Up @@ -248,6 +248,8 @@ class GUI_EXPORT QgsLayerTreeView : public QTreeView
//! Handles updating the viewport to avoid flicker
void onHorizontalScroll( int value );

void onDataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles );

protected:
//! helper class with default actions. Lazily initialized.
QgsLayerTreeViewDefaultActions *mDefaultActions = nullptr;
Expand Down

0 comments on commit 2eaf5e6

Please sign in to comment.