22 #include <QApplication> 23 #include <QGraphicsItem> 24 #include <QDomDocument> 25 #include <QDomElement> 28 #include <QMessageBox> 32 : QAbstractItemModel( parent )
41 if ( !index.isValid() || index.row() == 0 )
51 const QModelIndex &
parent )
const 59 if ( !parent.isValid() && row == 0 )
61 return createIndex( row, column,
nullptr );
63 else if ( !parent.isValid() && row >= 1 && row < mItemsInScene.size() + 1 )
66 return createIndex( row, column, mItemsInScene.at( row - 1 ) );
73 void QgsLayoutModel::refreshItemsInScene()
75 mItemsInScene.clear();
77 const QList< QGraphicsItem * > items = mLayout->items();
84 mItemsInScene.push_back( item );
99 if ( !parent.isValid() )
101 return mItemsInScene.size() + 1;
108 return mItemsInScene.size() + 1;
125 if ( !index.isValid() )
136 case Qt::DisplayRole:
137 if ( index.column() ==
ItemId )
146 case Qt::DecorationRole:
147 if ( index.column() ==
ItemId )
157 if ( index.column() ==
ItemId )
171 return qVariantFromValue( qobject_cast<QObject *>( item ) );
173 case Qt::TextAlignmentRole:
174 return Qt::AlignLeft & Qt::AlignVCenter;
176 case Qt::CheckStateRole:
177 switch ( index.column() )
181 return item->isVisible() ? Qt::Checked : Qt::Unchecked;
184 return item->
isLocked() ? Qt::Checked : Qt::Unchecked;
198 if ( !index.isValid() )
207 switch ( index.column() )
221 item->
setId( value.toString() );
232 case Qt::DisplayRole:
241 case Qt::DecorationRole:
255 case Qt::TextAlignmentRole:
256 return Qt::AlignLeft & Qt::AlignVCenter;
259 return QAbstractItemModel::headerData( section, orientation, role );
266 return Qt::MoveAction;
272 types << QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" );
278 QMimeData *
mimeData =
new QMimeData();
279 QByteArray encodedData;
281 QDataStream stream( &encodedData, QIODevice::WriteOnly );
283 for (
const QModelIndex &
index : indexes )
292 QString text = item->
uuid();
297 mimeData->setData( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ), encodedData );
303 return item1->zValue() > item2->zValue();
307 Qt::DropAction action,
int row,
int column,
const QModelIndex &
parent )
314 if ( action == Qt::IgnoreAction )
319 if ( !data->hasFormat( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) ) )
324 if ( parent.isValid() )
329 int beginRow = row != -1 ? row :
rowCount( QModelIndex() );
331 QByteArray encodedData = data->data( QStringLiteral(
"application/x-vnd.qgis.qgis.composeritemid" ) );
332 QDataStream stream( &encodedData, QIODevice::ReadOnly );
333 QList<QgsLayoutItem *> droppedItems;
336 while ( !stream.atEnd() )
343 droppedItems << item;
348 if ( droppedItems.empty() )
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();
414 if ( parent.isValid() )
429 void QgsLayoutModel::clear()
434 refreshItemsInScene();
438 int QgsLayoutModel::zOrderListSize()
const 440 return mItemZList.size();
443 void QgsLayoutModel::rebuildZList()
445 QList<QgsLayoutItem *> sortedList;
449 const QList<QGraphicsItem *> itemList = mLayout->items( Qt::DescendingOrder );
450 for ( QGraphicsItem *item : itemList )
452 if (
QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item ) )
456 sortedList.append( layoutItem );
461 mItemZList = sortedList;
462 rebuildSceneItemList();
466 void 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();
577 void QgsLayoutModel::updateItemDisplayName(
QgsLayoutItem *item )
587 if ( !itemIndex.isValid() )
593 emit dataChanged( itemIndex, itemIndex );
596 void QgsLayoutModel::updateItemLockStatus(
QgsLayoutItem *item )
606 if ( !itemIndex.isValid() )
612 emit dataChanged( itemIndex, itemIndex );
615 void QgsLayoutModel::updateItemVisibility(
QgsLayoutItem *item )
625 if ( !itemIndex.isValid() )
631 emit dataChanged( itemIndex, itemIndex );
634 void 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();
790 bool 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() )
866 QList<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 );
919 void QgsLayoutModel::setSelected(
const QModelIndex &
index )
936 : QSortFilterProxyModel( parent )
943 setDynamicSortFilter(
true );
944 setSortLocaleAware(
true );
950 const QString leftText = sourceModel()->data( left, Qt::DisplayRole ).toString();
951 const QString rightText = sourceModel()->data( right, Qt::DisplayRole ).toString();
952 if ( leftText.isEmpty() )
954 if ( rightText.isEmpty() )
975 QVariant itemAsVariant = sourceModel()->data( sourceIndex, Qt::UserRole + 1 );
976 return qobject_cast<
QgsLayoutItem *>( itemAsVariant.value<QObject *>() );
981 mAllowEmpty = allowEmpty;
992 mItemTypeFilter = filter;
998 if ( mExceptedList == items )
1001 mExceptedList = items;
1008 QModelIndex index = sourceModel()->index( sourceRow, 0, sourceParent );
1015 if ( mExceptedList.contains( item ) )
QgsLayoutProxyModel(QgsLayout *layout, QObject *parent=nullptr)
Constructor for QgsLayoutProxyModelm, attached to the specified layout.
virtual QIcon icon() const
Returns the item's icon.
bool setData(const QModelIndex &index, const QVariant &value, int role) override
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QgsLayoutItem * itemFromIndex(const QModelIndex &index) const
Returns the QgsLayoutItem corresponding to a QModelIndex index, if possible.
Base class for graphical items within a QgsLayout.
int type() const override
Returns a unique graphics item type identifier.
QVariant data(const QModelIndex &index, int role) const override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
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...
int columnCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex indexForItem(QgsLayoutItem *item, int column=0)
Returns the QModelIndex corresponding to a QgsLayoutItem item and column, if possible.
Qt::ItemFlags flags(const QModelIndex &index) const override
void setAllowEmptyItem(bool allowEmpty)
Sets whether an optional empty layout item is present in the model.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Qt::DropActions supportedDropActions() const override
void setExceptedItemList(const QList< QgsLayoutItem * > &items)
Sets a list of specific items to exclude from the model.
QMimeData * mimeData(const QModelIndexList &indexes) const override
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
void updateZValues(bool addUndoCommands=true)
Resets the z-values of items based on their position in the internal z order list.
virtual void setId(const QString &id)
Set the item's id name.
QStringList mimeTypes() const override
void setLocked(bool locked)
Sets whether the item is locked, preventing mouse interactions with the item.
Item visibility checkbox.
bool zOrderDescending(QgsLayoutItem *item1, QgsLayoutItem *item2)
QString id() const
Returns the item's ID name.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
void setFilterType(QgsLayoutItemRegistry::ItemType filter)
Sets the item type filter.
virtual void setVisibility(bool visible)
Sets whether the item is visible.
Item lock status checkbox.
QgsLayoutItem * itemFromSourceIndex(const QModelIndex &sourceIndex) const
Returns the QgsLayoutItem corresponding to an index from the source QgsLayoutModel model...
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
virtual QString displayName() const
Gets item display name.
QModelIndex parent(const QModelIndex &index) const override
QgsLayoutModel(QgsLayout *layout, QObject *parent=nullptr)
Constructor for a QgsLayoutModel attached to the specified layout.
Registry of available layout item types.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
virtual QString uuid() const
Returns the item identification string.
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
bool allowEmptyItem() const
Returns true if the model includes the empty item choice.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override