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;
337 while ( !stream.atEnd() )
344 droppedItems << item;
348 if ( droppedItems.empty() )
363 QgsLayoutItem *itemBefore = mItemsInScene.at( beginRow - 1 );
364 destPos = mItemZList.indexOf( itemBefore );
369 destPos = mItemZList.size();
373 int insertPos = destPos;
376 int listPos = mItemZList.indexOf( item );
383 if ( listPos < destPos )
390 auto itemIt = droppedItems.begin();
391 for ( ; itemIt != droppedItems.end(); ++itemIt )
393 mItemZList.removeOne( *itemIt );
397 itemIt = droppedItems.begin();
398 for ( ; itemIt != droppedItems.end(); ++itemIt )
400 mItemZList.insert( insertPos, *itemIt );
404 rebuildSceneItemList();
429void QgsLayoutModel::clear()
434 refreshItemsInScene();
438int QgsLayoutModel::zOrderListSize()
const
440 return mItemZList.size();
443void QgsLayoutModel::rebuildZList()
445 QList<QgsLayoutItem *> sortedList;
449 const QList<QGraphicsItem *> itemList = mLayout->items( Qt::DescendingOrder );
450 for ( QGraphicsItem *item : itemList )
456 sortedList.append( layoutItem );
461 mItemZList = sortedList;
462 rebuildSceneItemList();
466void QgsLayoutModel::rebuildSceneItemList()
471 const QList< QGraphicsItem * > items = mLayout->items();
480 int sceneListPos = mItemsInScene.indexOf( item );
481 if ( sceneListPos == row )
486 else if ( sceneListPos != -1 )
489 beginMoveRows( QModelIndex(), sceneListPos + 1, sceneListPos + 1, QModelIndex(), row + 1 );
490 mItemsInScene.removeAt( sceneListPos );
491 mItemsInScene.insert( row, item );
497 beginInsertRows( QModelIndex(), row + 1, row + 1 );
498 mItemsInScene.insert( row, item );
507 mItemZList.push_front( item );
508 refreshItemsInScene();
509 item->setZValue( mItemZList.size() );
520 int pos = mItemZList.indexOf( item );
529 if ( !itemIndex.isValid() )
534 mItemZList.removeAt( pos );
535 refreshItemsInScene();
540 int row = itemIndex.row();
541 beginRemoveRows( QModelIndex(), row, row );
542 mItemZList.removeAt( pos );
543 refreshItemsInScene();
555 int pos = mItemZList.indexOf( item );
564 if ( !itemIndex.isValid() )
570 int row = itemIndex.row();
571 beginRemoveRows( QModelIndex(), row, row );
572 mLayout->removeItem( item );
573 refreshItemsInScene();
577void QgsLayoutModel::updateItemDisplayName(
QgsLayoutItem *item )
587 if ( !itemIndex.isValid() )
593 emit dataChanged( itemIndex, itemIndex );
596void QgsLayoutModel::updateItemLockStatus(
QgsLayoutItem *item )
606 if ( !itemIndex.isValid() )
612 emit dataChanged( itemIndex, itemIndex );
615void QgsLayoutModel::updateItemVisibility(
QgsLayoutItem *item )
625 if ( !itemIndex.isValid() )
631 emit dataChanged( itemIndex, itemIndex );
634void QgsLayoutModel::updateItemSelectStatus(
QgsLayoutItem *item )
644 if ( !itemIndex.isValid() )
650 emit dataChanged( itemIndex, itemIndex );
660 if ( mItemsInScene.at( 0 ) == item )
667 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
668 if ( ! it.findNext( item ) )
674 const QList< QGraphicsItem * > sceneItems = mLayout->items();
677 while ( it.hasPrevious() )
681 if ( it.value() && sceneItems.contains( it.value() ) )
690 if ( !itemIndex.isValid() )
696 int row = itemIndex.row();
697 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row - 1 );
698 refreshItemsInScene();
710 if ( mItemsInScene.last() == item )
717 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
718 if ( ! it.findNext( item ) )
724 const QList< QGraphicsItem * > sceneItems = mLayout->items();
726 while ( it.hasNext() )
732 if ( it.value() && sceneItems.contains( it.value() ) )
741 if ( !itemIndex.isValid() )
747 int row = itemIndex.row();
748 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row + 2 );
749 refreshItemsInScene();
756 if ( !item || !mItemsInScene.contains( item ) )
761 if ( mItemsInScene.at( 0 ) == item )
768 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
769 if ( it.findNext( item ) )
773 mItemZList.push_front( item );
777 if ( !itemIndex.isValid() )
783 int row = itemIndex.row();
784 beginMoveRows( QModelIndex(), row, row, QModelIndex(), 1 );
785 refreshItemsInScene();
790bool QgsLayoutModel::reorderItemToBottom(
QgsLayoutItem *item )
792 if ( !item || !mItemsInScene.contains( item ) )
797 if ( mItemsInScene.last() == item )
804 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
805 if ( it.findNext( item ) )
809 mItemZList.push_back( item );
813 if ( !itemIndex.isValid() )
819 int row = itemIndex.row();
820 beginMoveRows( QModelIndex(), row, row, QModelIndex(),
rowCount() );
821 refreshItemsInScene();
829 QListIterator<QgsLayoutItem *> it( mItemZList );
831 if ( it.findPrevious( item ) )
834 while ( it.hasPrevious() )
837 if ( it.hasPrevious() && !it.peekPrevious()->isGroupMember() )
839 return it.previous();
850 QListIterator<QgsLayoutItem *> it( mItemZList );
851 if ( it.findNext( item ) )
854 while ( it.hasNext() )
856 if ( !it.peekNext()->isGroupMember() )
866QList<QgsLayoutItem *> &QgsLayoutModel::zOrderList()
875 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
877 if ( !
index.isValid() )
879 return flags | Qt::ItemIsDropEnabled;
882 if (
index.row() == 0 )
884 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
888 switch (
index.column() )
892 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
894 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
896 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
905 return QModelIndex();
908 int row = mItemsInScene.indexOf( item );
912 return QModelIndex();
915 return index( row + 1, column );
919void QgsLayoutModel::setSelected(
const QModelIndex &index )
937 if ( group && group != item )
947 : QSortFilterProxyModel( parent )
954 setDynamicSortFilter(
true );
955 setSortLocaleAware(
true );
961 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
962 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
963 if ( leftText.isEmpty() )
965 if ( rightText.isEmpty() )
986 QVariant itemAsVariant = sourceModel()->data( sourceIndex, Qt::UserRole + 1 );
987 return qobject_cast<QgsLayoutItem *>( itemAsVariant.value<QObject *>() );
992 mAllowEmpty = allowEmpty;
1014 mItemTypeFilter = filter;
1020 if ( mExceptedList == items )
1023 mExceptedList = items;
1030 QModelIndex index = sourceModel()->index( sourceRow, 0, sourceParent );
1037 if ( mExceptedList.contains( item ) )
1044 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.
virtual QIcon icon() const
Returns the item's icon.
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 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)