19#include "moc_qgslayoutmodel.cpp"
24#include <QApplication>
25#include <QGraphicsItem>
26#include <QDomDocument>
34 : QAbstractItemModel( parent )
53 const QModelIndex &parent )
const
61 if ( !
parent.isValid() && row == 0 )
63 return createIndex( row, column,
nullptr );
65 else if ( !
parent.isValid() && row >= 1 && row < mItemsInScene.size() + 1 )
68 return createIndex( row, column, mItemsInScene.at( row - 1 ) );
75void QgsLayoutModel::refreshItemsInScene()
77 mItemsInScene.clear();
79 const QList< QGraphicsItem * > items = mLayout->items();
86 mItemsInScene.push_back( item );
103 return mItemsInScene.size() + 1;
128 if ( !
index.isValid() )
139 case Qt::DisplayRole:
149 case Qt::DecorationRole:
174 return QVariant::fromValue( qobject_cast<QObject *>( item ) );
176 case Qt::TextAlignmentRole:
177 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft & Qt::AlignVCenter );
179 case Qt::CheckStateRole:
180 switch (
index.column() )
184 return item->isVisible() ? Qt::Checked : Qt::Unchecked;
187 return item->
isLocked() ? Qt::Checked : Qt::Unchecked;
201 if ( !
index.isValid() )
210 switch (
index.column() )
224 item->
setId( value.toString() );
235 case Qt::DisplayRole:
244 case Qt::DecorationRole:
258 case Qt::TextAlignmentRole:
259 return static_cast<Qt::Alignment::Int
>( Qt::AlignLeft & Qt::AlignVCenter );
262 return QAbstractItemModel::headerData( section, orientation, role );
269 return Qt::MoveAction;
275 types << QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" );
281 QMimeData *
mimeData =
new QMimeData();
282 QByteArray encodedData;
284 QDataStream stream( &encodedData, QIODevice::WriteOnly );
286 for (
const QModelIndex &
index : indexes )
295 QString text = item->
uuid();
300 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ), encodedData );
306 return item1->zValue() > item2->zValue();
310 Qt::DropAction action,
int row,
int column,
const QModelIndex &parent )
312 if ( column !=
ItemId && column != -1 )
317 if ( action == Qt::IgnoreAction )
322 if ( !
data->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) ) )
332 int beginRow = row != -1 ? row :
rowCount( QModelIndex() );
334 QByteArray encodedData =
data->data( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) );
335 QDataStream stream( &encodedData, QIODevice::ReadOnly );
336 QList<QgsLayoutItem *> droppedItems;
338 while ( !stream.atEnd() )
345 droppedItems << item;
349 if ( droppedItems.empty() )
364 QgsLayoutItem *itemBefore = mItemsInScene.at( beginRow - 1 );
365 destPos = mItemZList.indexOf( itemBefore );
370 destPos = mItemZList.size();
374 int insertPos = destPos;
377 int listPos = mItemZList.indexOf( item );
384 if ( listPos < destPos )
391 auto itemIt = droppedItems.begin();
392 for ( ; itemIt != droppedItems.end(); ++itemIt )
394 mItemZList.removeOne( *itemIt );
398 itemIt = droppedItems.begin();
399 for ( ; itemIt != droppedItems.end(); ++itemIt )
401 mItemZList.insert( insertPos, *itemIt );
405 rebuildSceneItemList();
430void QgsLayoutModel::clear()
435 refreshItemsInScene();
439int QgsLayoutModel::zOrderListSize()
const
441 return mItemZList.size();
444void QgsLayoutModel::rebuildZList()
446 QList<QgsLayoutItem *> sortedList;
450 const QList<QGraphicsItem *> itemList = mLayout->items( Qt::DescendingOrder );
451 for ( QGraphicsItem *item : itemList )
457 sortedList.append( layoutItem );
462 mItemZList = sortedList;
463 rebuildSceneItemList();
467void QgsLayoutModel::rebuildSceneItemList()
472 const QList< QGraphicsItem * > items = mLayout->items();
481 int sceneListPos = mItemsInScene.indexOf( item );
482 if ( sceneListPos == row )
487 else if ( sceneListPos != -1 )
490 beginMoveRows( QModelIndex(), sceneListPos + 1, sceneListPos + 1, QModelIndex(), row + 1 );
491 mItemsInScene.removeAt( sceneListPos );
492 mItemsInScene.insert( row, item );
498 beginInsertRows( QModelIndex(), row + 1, row + 1 );
499 mItemsInScene.insert( row, item );
508 mItemZList.push_front( item );
509 refreshItemsInScene();
510 item->setZValue( mItemZList.size() );
521 int pos = mItemZList.indexOf( item );
530 if ( !itemIndex.isValid() )
535 mItemZList.removeAt( pos );
536 refreshItemsInScene();
541 int row = itemIndex.row();
542 beginRemoveRows( QModelIndex(), row, row );
543 mItemZList.removeAt( pos );
544 refreshItemsInScene();
556 int pos = mItemZList.indexOf( item );
565 if ( !itemIndex.isValid() )
571 int row = itemIndex.row();
572 beginRemoveRows( QModelIndex(), row, row );
573 mLayout->removeItem( item );
574 refreshItemsInScene();
578void QgsLayoutModel::updateItemDisplayName(
QgsLayoutItem *item )
588 if ( !itemIndex.isValid() )
594 emit dataChanged( itemIndex, itemIndex );
597void QgsLayoutModel::updateItemLockStatus(
QgsLayoutItem *item )
607 if ( !itemIndex.isValid() )
613 emit dataChanged( itemIndex, itemIndex );
616void QgsLayoutModel::updateItemVisibility(
QgsLayoutItem *item )
626 if ( !itemIndex.isValid() )
632 emit dataChanged( itemIndex, itemIndex );
635void QgsLayoutModel::updateItemSelectStatus(
QgsLayoutItem *item )
645 if ( !itemIndex.isValid() )
651 emit dataChanged( itemIndex, itemIndex );
661 if ( mItemsInScene.at( 0 ) == item )
668 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
669 if ( ! it.findNext( item ) )
675 const QList< QGraphicsItem * > sceneItems = mLayout->items();
678 while ( it.hasPrevious() )
682 if ( it.value() && sceneItems.contains( it.value() ) )
691 if ( !itemIndex.isValid() )
697 int row = itemIndex.row();
698 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row - 1 );
699 refreshItemsInScene();
711 if ( mItemsInScene.last() == item )
718 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
719 if ( ! it.findNext( item ) )
725 const QList< QGraphicsItem * > sceneItems = mLayout->items();
727 while ( it.hasNext() )
733 if ( it.value() && sceneItems.contains( it.value() ) )
742 if ( !itemIndex.isValid() )
748 int row = itemIndex.row();
749 beginMoveRows( QModelIndex(), row, row, QModelIndex(), row + 2 );
750 refreshItemsInScene();
757 if ( !item || !mItemsInScene.contains( item ) )
762 if ( mItemsInScene.at( 0 ) == item )
769 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
770 if ( it.findNext( item ) )
774 mItemZList.push_front( item );
778 if ( !itemIndex.isValid() )
784 int row = itemIndex.row();
785 beginMoveRows( QModelIndex(), row, row, QModelIndex(), 1 );
786 refreshItemsInScene();
791bool QgsLayoutModel::reorderItemToBottom(
QgsLayoutItem *item )
793 if ( !item || !mItemsInScene.contains( item ) )
798 if ( mItemsInScene.last() == item )
805 QMutableListIterator<QgsLayoutItem *> it( mItemZList );
806 if ( it.findNext( item ) )
810 mItemZList.push_back( item );
814 if ( !itemIndex.isValid() )
820 int row = itemIndex.row();
821 beginMoveRows( QModelIndex(), row, row, QModelIndex(),
rowCount() );
822 refreshItemsInScene();
830 QListIterator<QgsLayoutItem *> it( mItemZList );
832 if ( it.findPrevious( item ) )
835 while ( it.hasPrevious() )
838 if ( it.hasPrevious() && !it.peekPrevious()->isGroupMember() )
840 return it.previous();
851 QListIterator<QgsLayoutItem *> it( mItemZList );
852 if ( it.findNext( item ) )
855 while ( it.hasNext() )
857 if ( !it.peekNext()->isGroupMember() )
867QList<QgsLayoutItem *> &QgsLayoutModel::zOrderList()
876 Qt::ItemFlags
flags = QAbstractItemModel::flags(
index );
878 if ( !
index.isValid() )
880 return flags | Qt::ItemIsDropEnabled;
883 if (
index.row() == 0 )
885 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
889 switch (
index.column() )
893 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
895 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
897 return flags | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
906 return QModelIndex();
909 int row = mItemsInScene.indexOf( item );
913 return QModelIndex();
916 return index( row + 1, column );
920void QgsLayoutModel::setSelected(
const QModelIndex &index )
938 if ( group && group != item )
948 : QSortFilterProxyModel( parent )
955 setDynamicSortFilter(
true );
956 setSortLocaleAware(
true );
962 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
963 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
964 if ( leftText.isEmpty() )
966 if ( rightText.isEmpty() )
987 QVariant itemAsVariant = sourceModel()->data( sourceIndex, Qt::UserRole + 1 );
988 return qobject_cast<QgsLayoutItem *>( itemAsVariant.value<QObject *>() );
993 mAllowEmpty = allowEmpty;
1015 mItemTypeFilter = filter;
1021 if ( mExceptedList == items )
1024 mExceptedList = items;
1031 QModelIndex index = sourceModel()->index( sourceRow, 0, sourceParent );
1038 if ( mExceptedList.contains( item ) )
1045 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)