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)