23#include <QApplication>
24#include <QGraphicsItem>
25#include <QDomDocument>
33 : QAbstractItemModel( parent )
52 const QModelIndex &parent )
const
60 if ( !
parent.isValid() && row == 0 )
62 return createIndex( row, column,
nullptr );
64 else if ( !
parent.isValid() && row >= 1 && row < mItemsInScene.size() + 1 )
67 return createIndex( row, column, mItemsInScene.at( row - 1 ) );
74void QgsLayoutModel::refreshItemsInScene()
76 mItemsInScene.clear();
78 const QList< QGraphicsItem * > items = mLayout->items();
85 mItemsInScene.push_back( item );
102 return mItemsInScene.size() + 1;
127 if ( !
index.isValid() )
138 case Qt::DisplayRole:
148 case Qt::DecorationRole:
173 return QVariant::fromValue( qobject_cast<QObject *>( item ) );
175 case Qt::TextAlignmentRole:
176 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft & Qt::AlignVCenter );
178 case Qt::CheckStateRole:
179 switch (
index.column() )
183 return item->isVisible() ? Qt::Checked : Qt::Unchecked;
186 return item->
isLocked() ? Qt::Checked : Qt::Unchecked;
200 if ( !
index.isValid() )
209 switch (
index.column() )
223 item->
setId( value.toString() );
234 case Qt::DisplayRole:
243 case Qt::DecorationRole:
257 case Qt::TextAlignmentRole:
258 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft & Qt::AlignVCenter );
261 return QAbstractItemModel::headerData( section, orientation, role );
268 return Qt::MoveAction;
274 types << QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" );
280 QMimeData *
mimeData =
new QMimeData();
281 QByteArray encodedData;
283 QDataStream stream( &encodedData, QIODevice::WriteOnly );
285 for (
const QModelIndex &
index : indexes )
294 QString text = item->
uuid();
299 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ), encodedData );
305 return item1->zValue() > item2->zValue();
309 Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
311 if ( column !=
ItemId && column != -1 )
316 if ( action == Qt::IgnoreAction )
321 if ( !
data->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) ) )
331 int beginRow = row != -1 ? row :
rowCount( QModelIndex() );
333 QByteArray encodedData =
data->data( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) );
334 QDataStream stream( &encodedData, QIODevice::ReadOnly );
335 QList<QgsLayoutItem *> droppedItems;
338 while ( !stream.atEnd() )
345 droppedItems << item;
350 if ( droppedItems.empty() )
365 QgsLayoutItem *itemBefore = mItemsInScene.at( beginRow - 1 );
366 destPos = mItemZList.indexOf( itemBefore );
371 destPos = mItemZList.size();
375 int insertPos = destPos;
378 int listPos = mItemZList.indexOf( item );
385 if ( listPos < destPos )
392 auto itemIt = droppedItems.begin();
393 for ( ; itemIt != droppedItems.end(); ++itemIt )
395 mItemZList.removeOne( *itemIt );
399 itemIt = droppedItems.begin();
400 for ( ; itemIt != droppedItems.end(); ++itemIt )
402 mItemZList.insert( insertPos, *itemIt );
406 rebuildSceneItemList();
431void QgsLayoutModel::clear()
436 refreshItemsInScene();
440int QgsLayoutModel::zOrderListSize()
const
442 return mItemZList.size();
445void QgsLayoutModel::rebuildZList()
447 QList<QgsLayoutItem *> sortedList;
451 const QList<QGraphicsItem *> itemList = mLayout->items( Qt::DescendingOrder );
452 for ( QGraphicsItem *item : itemList )
458 sortedList.append( layoutItem );
463 mItemZList = sortedList;
464 rebuildSceneItemList();
468void QgsLayoutModel::rebuildSceneItemList()
473 const QList< QGraphicsItem * > items = mLayout->items();
482 int sceneListPos = mItemsInScene.indexOf( item );
483 if ( sceneListPos == row )
488 else if ( sceneListPos != -1 )
491 beginMoveRows( QModelIndex(), sceneListPos + 1, sceneListPos + 1, QModelIndex(), row + 1 );
492 mItemsInScene.removeAt( sceneListPos );
493 mItemsInScene.insert( row, item );
499 beginInsertRows( QModelIndex(), row + 1, row + 1 );
500 mItemsInScene.insert( row, item );
509 mItemZList.push_front( item );
510 refreshItemsInScene();
511 item->setZValue( mItemZList.size() );
522 int pos = mItemZList.indexOf( item );
531 if ( !itemIndex.isValid() )
536 mItemZList.removeAt( pos );
537 refreshItemsInScene();
542 int row = itemIndex.row();
543 beginRemoveRows( QModelIndex(), row, row );
544 mItemZList.removeAt( pos );
545 refreshItemsInScene();
557 int pos = mItemZList.indexOf( item );
566 if ( !itemIndex.isValid() )
572 int row = itemIndex.row();
573 beginRemoveRows( QModelIndex(), row, row );
574 mLayout->removeItem( item );
575 refreshItemsInScene();
579void QgsLayoutModel::updateItemDisplayName(
QgsLayoutItem *item )
589 if ( !itemIndex.isValid() )
595 emit dataChanged( itemIndex, itemIndex );
598void QgsLayoutModel::updateItemLockStatus(
QgsLayoutItem *item )
608 if ( !itemIndex.isValid() )
614 emit dataChanged( itemIndex, itemIndex );
617void QgsLayoutModel::updateItemVisibility(
QgsLayoutItem *item )
627 if ( !itemIndex.isValid() )
633 emit dataChanged( itemIndex, itemIndex );
636void QgsLayoutModel::updateItemSelectStatus(
QgsLayoutItem *item )
646 if ( !itemIndex.isValid() )
652 emit dataChanged( itemIndex, itemIndex );
662 if ( mItemsInScene.at( 0 ) == item )
669 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
670 if ( ! it.findNext( item ) )
676 const QList< QGraphicsItem * > sceneItems = mLayout->items();
679 while ( it.hasPrevious() )
683 if ( it.value() && sceneItems.contains( it.value() ) )
692 if ( !itemIndex.isValid() )
698 int row = itemIndex.row();
699 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row - 1 );
700 refreshItemsInScene();
712 if ( mItemsInScene.last() == item )
719 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
720 if ( ! it.findNext( item ) )
726 const QList< QGraphicsItem * > sceneItems = mLayout->items();
728 while ( it.hasNext() )
734 if ( it.value() && sceneItems.contains( it.value() ) )
743 if ( !itemIndex.isValid() )
749 int row = itemIndex.row();
750 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row + 2 );
751 refreshItemsInScene();
758 if ( !item || !mItemsInScene.contains( item ) )
763 if ( mItemsInScene.at( 0 ) == item )
770 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
771 if ( it.findNext( item ) )
775 mItemZList.push_front( item );
779 if ( !itemIndex.isValid() )
785 int row = itemIndex.row();
786 beginMoveRows( QModelIndex(), row, row, QModelIndex(), 1 );
787 refreshItemsInScene();
792bool QgsLayoutModel::reorderItemToBottom(
QgsLayoutItem *item )
794 if ( !item || !mItemsInScene.contains( item ) )
799 if ( mItemsInScene.last() == item )
806 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
807 if ( it.findNext( item ) )
811 mItemZList.push_back( item );
815 if ( !itemIndex.isValid() )
821 int row = itemIndex.row();
822 beginMoveRows( QModelIndex(), row, row, QModelIndex(),
rowCount() );
823 refreshItemsInScene();
831 QListIterator<QgsLayoutItem *> it( mItemZList );
833 if ( it.findPrevious( item ) )
836 while ( it.hasPrevious() )
839 if ( it.hasPrevious() && !it.peekPrevious()->isGroupMember() )
841 return it.previous();
852 QListIterator<QgsLayoutItem *> it( mItemZList );
853 if ( it.findNext( item ) )
856 while ( it.hasNext() )
858 if ( !it.peekNext()->isGroupMember() )
868QList<QgsLayoutItem *> &QgsLayoutModel::zOrderList()
877 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
879 if ( !
index.isValid() )
881 return flags | Qt::ItemIsDropEnabled;
884 if (
index.row() == 0 )
886 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
890 switch (
index.column() )
894 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
896 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
898 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
907 return QModelIndex();
910 int row = mItemsInScene.indexOf( item );
914 return QModelIndex();
917 return index( row + 1, column );
921void QgsLayoutModel::setSelected(
const QModelIndex &index )
939 if ( group && group != item )
949 : QSortFilterProxyModel( parent )
956 setDynamicSortFilter(
true );
957 setSortLocaleAware(
true );
963 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
964 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
965 if ( leftText.isEmpty() )
967 if ( rightText.isEmpty() )
988 QVariant itemAsVariant = sourceModel()->data( sourceIndex, Qt::UserRole + 1 );
989 return qobject_cast<QgsLayoutItem *>( itemAsVariant.value<QObject *>() );
994 mAllowEmpty = allowEmpty;
1016 mItemTypeFilter = filter;
1022 if ( mExceptedList == items )
1025 mExceptedList = items;
1032 QModelIndex index = sourceModel()->index( sourceRow, 0, sourceParent );
1039 if ( mExceptedList.contains( item ) )
1046 if ( mItemFlags && !( item->
itemFlags() & mItemFlags ) )
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A container for grouping several QgsLayoutItems.
Registry of available layout item types.
@ LayoutItem
Base class for items.
Base class for graphical items within a QgsLayout.
QgsLayoutItemGroup * parentGroup() const
Returns the item's parent group, if the item is part of a QgsLayoutItemGroup group.
virtual void setSelected(bool selected)
Sets whether the item should be selected.
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
virtual void setVisibility(bool visible)
Sets whether the item is visible.
virtual void setId(const QString &id)
Set the item's id name.
void setLocked(bool locked)
Sets whether the item is locked, preventing mouse interactions with the item.
int type() const override
Returns a unique graphics item type identifier.
virtual QString displayName() const
Gets item display name.
virtual QString uuid() const
Returns the item identification string.
QString id() const
Returns the item's ID name.
virtual QIcon icon() const
Returns the item's icon.
virtual Flags itemFlags() const
Returns the item's flags, which indicate how the item behaves.
QMimeData * mimeData(const QModelIndexList &indexes) const override
QModelIndex parent(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QVariant data(const QModelIndex &index, int role) const override
QgsLayoutModel(QgsLayout *layout, QObject *parent=nullptr)
Constructor for a QgsLayoutModel attached to the specified layout.
QgsLayoutItem * itemFromIndex(const QModelIndex &index) const
Returns the QgsLayoutItem corresponding to a QModelIndex index, if possible.
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
Qt::DropActions supportedDropActions() const override
@ Visibility
Item visibility checkbox.
@ LockStatus
Item lock status checkbox.
QModelIndex indexForItem(QgsLayoutItem *item, int column=0)
Returns the QModelIndex corresponding to a QgsLayoutItem item and column, if possible.
QStringList mimeTypes() const override
Qt::ItemFlags flags(const QModelIndex &index) const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
void setExceptedItemList(const QList< QgsLayoutItem * > &items)
Sets a list of specific items to exclude from the model.
QgsLayoutItem::Flags itemFlags() const
Returns the layout item flags used for filtering the available items.
void setFilterType(QgsLayoutItemRegistry::ItemType filter)
Sets the item type filter.
bool allowEmptyItem() const
Returns true if the model includes the empty item choice.
void setItemFlags(QgsLayoutItem::Flags flags)
Sets layout item flags to use for filtering the available items.
void setAllowEmptyItem(bool allowEmpty)
Sets whether an optional empty layout item is present in the model.
QgsLayoutItem * itemFromSourceIndex(const QModelIndex &sourceIndex) const
Returns the QgsLayoutItem corresponding to an index from the source QgsLayoutModel model.
QgsLayoutProxyModel(QgsLayout *layout, QObject *parent=nullptr)
Constructor for QgsLayoutProxyModelm, attached to the specified layout.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
QgsLayoutItem * itemByUuid(const QString &uuid, bool includeTemplateUuids=false) const
Returns the layout item with matching uuid unique identifier, or nullptr if a matching item could not...
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
void updateZValues(bool addUndoCommands=true)
Resets the z-values of items based on their position in the internal z order list.
bool zOrderDescending(QgsLayoutItem *item1, QgsLayoutItem *item2)