23 #include <QApplication> 
   24 #include <QGraphicsItem> 
   25 #include <QDomDocument> 
   26 #include <QDomElement> 
   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 ) );
 
   74 void 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();
 
  431 void QgsLayoutModel::clear()
 
  436   refreshItemsInScene();
 
  440 int QgsLayoutModel::zOrderListSize()
 const 
  442   return mItemZList.size();
 
  445 void 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();
 
  468 void 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();
 
  579 void QgsLayoutModel::updateItemDisplayName( 
QgsLayoutItem *item )
 
  589   if ( !itemIndex.isValid() )
 
  595   emit dataChanged( itemIndex, itemIndex );
 
  598 void QgsLayoutModel::updateItemLockStatus( 
QgsLayoutItem *item )
 
  608   if ( !itemIndex.isValid() )
 
  614   emit dataChanged( itemIndex, itemIndex );
 
  617 void QgsLayoutModel::updateItemVisibility( 
QgsLayoutItem *item )
 
  627   if ( !itemIndex.isValid() )
 
  633   emit dataChanged( itemIndex, itemIndex );
 
  636 void 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();
 
  792 bool 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() )
 
  868 QList<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 );
 
  921 void 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)