Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayoutmodel.h 3 : : ---------------- 4 : : begin : October 2017 5 : : copyright : (C) 2017 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #ifndef QGSLAYOUTMODEL_H 19 : : #define QGSLAYOUTMODEL_H 20 : : 21 : : #include "qgis_core.h" 22 : : #include "qgis_sip.h" 23 : : #include "qgslayoutitemregistry.h" 24 : : 25 : : #include <QAbstractItemModel> 26 : : #include <QSortFilterProxyModel> 27 : : #include <QStringList> 28 : : #include <QSet> 29 : : 30 : : class QgsLayout; 31 : : class QGraphicsItem; 32 : : class QgsLayoutItem; 33 : : 34 : : /** 35 : : * \class QgsLayoutModel 36 : : * \ingroup core 37 : : * 38 : : * \brief A model for items attached to a layout. The model also maintains the z-order for the 39 : : * layout, and must be notified whenever item stacking changes. 40 : : * 41 : : * Internally, QgsLayoutModel maintains two lists. One contains a complete list of all items for 42 : : * the layout, ordered by their position within the z-order stack. 43 : : * 44 : : * The second list contains only items which are currently displayed in the layout's scene. 45 : : * It is used as a cache of the last known stacking order, so that the model can compare the current 46 : : * stacking of items in the layout to the last known state, and emit the corresponding signals 47 : : * as required. 48 : : * 49 : : * \since QGIS 3.0 50 : : */ 51 : : 52 : : class CORE_EXPORT QgsLayoutModel: public QAbstractItemModel 53 : : { 54 : 0 : Q_OBJECT 55 : : 56 : : public: 57 : : 58 : : //! Columns returned by the model 59 : : enum Columns 60 : : { 61 : : Visibility = 0, //!< Item visibility checkbox 62 : : LockStatus, //!< Item lock status checkbox 63 : : ItemId, //!< Item ID 64 : : }; 65 : : 66 : : /** 67 : : * Constructor for a QgsLayoutModel attached to the specified \a layout. 68 : : */ 69 : : explicit QgsLayoutModel( QgsLayout *layout, QObject *parent SIP_TRANSFERTHIS = nullptr ); 70 : : 71 : : //reimplemented QAbstractItemModel methods 72 : : QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override; 73 : : QModelIndex parent( const QModelIndex &index ) const override; 74 : : int rowCount( const QModelIndex &parent = QModelIndex() ) const override; 75 : : int columnCount( const QModelIndex &parent = QModelIndex() ) const override; 76 : : QVariant data( const QModelIndex &index, int role ) const override; 77 : : Qt::ItemFlags flags( const QModelIndex &index ) const override; 78 : : bool setData( const QModelIndex &index, const QVariant &value, int role ) override; 79 : : QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; 80 : : Qt::DropActions supportedDropActions() const override; 81 : : QStringList mimeTypes() const override; 82 : : QMimeData *mimeData( const QModelIndexList &indexes ) const override; 83 : : bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override; 84 : : bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override; 85 : : 86 : : ///@cond PRIVATE 87 : : #ifndef SIP_RUN 88 : : 89 : : /** 90 : : * Clears all items from z-order list and resets the model 91 : : */ 92 : : void clear(); 93 : : 94 : : /** 95 : : * Returns the size of the z-order list. 96 : : */ 97 : : int zOrderListSize() const; 98 : : 99 : : /** 100 : : * Rebuilds the z-order list, based on the current stacking of items in the layout. 101 : : * This method should be called after adding multiple items to the layout. 102 : : */ 103 : : void rebuildZList(); 104 : : 105 : : /** 106 : : * Adds an \a item to the top of the layout z stack. The item must not already exist in the z-order list. 107 : : * \see reorderItemToTop() 108 : : */ 109 : : void addItemAtTop( QgsLayoutItem *item ); 110 : : 111 : : /** 112 : : * Removes an \a item from the z-order list. 113 : : */ 114 : : void removeItem( QgsLayoutItem *item ); 115 : : 116 : : /** 117 : : * Moves an \a item up the z-order list. 118 : : * 119 : : * Returns TRUE if \a item was moved. Returns FALSE if \a item was not found 120 : : * in z-order list or was already at the top of the z-order list. 121 : : * 122 : : * \see reorderItemDown() 123 : : * \see reorderItemToTop() 124 : : * \see reorderItemToBottom() 125 : : */ 126 : : bool reorderItemUp( QgsLayoutItem *item ); 127 : : 128 : : /** 129 : : * Moves an \a item down the z-order list. 130 : : * 131 : : * Returns TRUE if \a item was moved. Returns FALSE if \a item was not found 132 : : * in z-order list or was already at the bottom of the z-order list. 133 : : * 134 : : * \see reorderItemUp() 135 : : * \see reorderItemToTop() 136 : : * \see reorderItemToBottom() 137 : : */ 138 : : bool reorderItemDown( QgsLayoutItem *item ); 139 : : 140 : : /** 141 : : * Moves an \a item to the top of the z-order list. 142 : : * 143 : : * Returns TRUE if \a item was moved. Returns FALSE if \a item was not found 144 : : * in z-order list or was already at the top of the z-order list. 145 : : * 146 : : * \see reorderItemUp() 147 : : * \see reorderItemDown() 148 : : * \see reorderItemToBottom() 149 : : */ 150 : : bool reorderItemToTop( QgsLayoutItem *item ); 151 : : 152 : : /** 153 : : * Moves an \a item to the bottom of the z-order list. 154 : : * 155 : : * Returns TRUE if \a item was moved. Returns FALSE if \a item was not found 156 : : * in z-order list or was already at the bottom of the z-order list. 157 : : * 158 : : * \see reorderItemUp() 159 : : * \see reorderItemDown() 160 : : * \see reorderItemToTop() 161 : : */ 162 : : bool reorderItemToBottom( QgsLayoutItem *item ); 163 : : 164 : : /** 165 : : * Finds the next layout item above an \a item, where \a item is 166 : : * the item to search above. 167 : : * 168 : : * If no items were found, NULLPTR will be returned. 169 : : * 170 : : * \see findItemBelow() 171 : : */ 172 : : QgsLayoutItem *findItemAbove( QgsLayoutItem *item ) const; 173 : : 174 : : /** 175 : : * Finds the next layout item below an \a item, where \a item 176 : : * is the item to search below. 177 : : * 178 : : * If no items were found, NULLPTR will be returned. 179 : : 180 : : * \see findItemAbove() 181 : : */ 182 : : QgsLayoutItem *findItemBelow( QgsLayoutItem *item ) const; 183 : : 184 : : /** 185 : : * Returns the item z-order list. 186 : : */ 187 : : QList<QgsLayoutItem *> &zOrderList(); 188 : : 189 : : /** 190 : : * Marks an \a item as removed from the layout. This must be called whenever an item 191 : : * is about to be removed from the layout. 192 : : */ 193 : : void setItemRemoved( QgsLayoutItem *item ); 194 : : 195 : : #if 0 196 : : 197 : : /** 198 : : * Restores an item to the composition. This must be called whenever an item removed 199 : : * from the composition is restored to the composition. 200 : : * \param item to mark as restored to the composition 201 : : * \see setItemRemoved 202 : : * \since QGIS 2.5 203 : : */ 204 : : void setItemRestored( QgsComposerItem *item ); 205 : : #endif 206 : : 207 : : /** 208 : : * Must be called when an \a item's display name is modified. 209 : : * 210 : : * \see updateItemLockStatus() 211 : : * \see updateItemVisibility() 212 : : * \see updateItemSelectStatus() 213 : : */ 214 : : void updateItemDisplayName( QgsLayoutItem *item ); 215 : : 216 : : /** 217 : : * Must be called when an \a item's lock status changes. 218 : : * \see updateItemDisplayName() 219 : : * \see updateItemVisibility() 220 : : * \see updateItemSelectStatus() 221 : : */ 222 : : void updateItemLockStatus( QgsLayoutItem *item ); 223 : : 224 : : /** 225 : : * Must be called when an \a item's visibility changes. 226 : : * \see updateItemDisplayName() 227 : : * \see updateItemLockStatus() 228 : : * \see updateItemSelectStatus() 229 : : */ 230 : : void updateItemVisibility( QgsLayoutItem *item ); 231 : : 232 : : /** 233 : : * Must be called when an \a item's selection status changes. 234 : : * \see updateItemDisplayName() 235 : : * \see updateItemVisibility() 236 : : * \see updateItemLockStatus() 237 : : */ 238 : : void updateItemSelectStatus( QgsLayoutItem *item ); 239 : : #endif 240 : : ///@endcond 241 : : 242 : : /** 243 : : * Returns the QgsLayoutItem corresponding to a QModelIndex \a index, if possible. 244 : : * \see indexForItem() 245 : : */ 246 : : QgsLayoutItem *itemFromIndex( const QModelIndex &index ) const; 247 : : 248 : : /** 249 : : * Returns the QModelIndex corresponding to a QgsLayoutItem \a item and \a column, if possible. 250 : : * \see itemFromIndex() 251 : : */ 252 : : QModelIndex indexForItem( QgsLayoutItem *item, int column = 0 ); 253 : : 254 : : public slots: 255 : : 256 : : ///@cond PRIVATE 257 : : #ifndef SIP_RUN 258 : : 259 : : /** 260 : : * Sets an item as the current selection from a QModelIndex \a index. 261 : : */ 262 : : void setSelected( const QModelIndex &index ); 263 : : #endif 264 : : ///@endcond 265 : : 266 : : private: 267 : : 268 : : //! Maintains z-Order of items. Starts with item at position 1 (position 0 is always paper item) 269 : : QList<QgsLayoutItem *> mItemZList; 270 : : 271 : : //! Cached list of items from mItemZList which are currently in the scene 272 : : QList<QgsLayoutItem *> mItemsInScene; 273 : : 274 : : //! Parent layout 275 : : QgsLayout *mLayout = nullptr; 276 : : 277 : : /** 278 : : * Rebuilds the list of all layout items which are present in the layout. This is 279 : : * called when the stacking of order changes or when items are removed/restored to the 280 : : * layout. Unlike rebuildSceneItemList, this method clears the existing scene item 281 : : * list and does not emit QAbstractItemModel signals. Accordingly, this method should 282 : : * only be called when changes to the z-order list are known and QAbstractItemModel begin 283 : : * signals have already been called. 284 : : * \see rebuildSceneItemList() 285 : : */ 286 : : void refreshItemsInScene(); 287 : : 288 : : /** 289 : : * Steps through the item z-order list and rebuilds the items in layout list, 290 : : * emitting QAbstractItemModel signals as required. 291 : : * \see refreshItemsInScene() 292 : : */ 293 : : void rebuildSceneItemList(); 294 : : 295 : : friend class TestQgsLayoutModel; 296 : : friend class TestQgsLayoutGui; 297 : : }; 298 : : 299 : : 300 : : /** 301 : : * \class QgsLayoutProxyModel 302 : : * \ingroup core 303 : : * \brief Allows for filtering a QgsLayoutModel by item type. 304 : : * \since QGIS 3.0 305 : : */ 306 : : class CORE_EXPORT QgsLayoutProxyModel: public QSortFilterProxyModel 307 : : { 308 : : Q_OBJECT 309 : : 310 : : public: 311 : : 312 : : /** 313 : : * Constructor for QgsLayoutProxyModelm, attached to the specified \a layout. 314 : : */ 315 : : QgsLayoutProxyModel( QgsLayout *layout, QObject *parent SIP_TRANSFERTHIS = nullptr ); 316 : : 317 : : /** 318 : : * Returns the current item type filter, or QgsLayoutItemRegistry::LayoutItem if no 319 : : * item type filter is set. 320 : : * \see setFilterType() 321 : : */ 322 : : QgsLayoutItemRegistry::ItemType filterType() const { return mItemTypeFilter; } 323 : : 324 : : /** 325 : : * Sets the item type \a filter. Only matching item types will be shown. 326 : : * Set \a filter to QgsLayoutItemRegistry::LayoutItem to show all 327 : : * item types. 328 : : * \see filterType() 329 : : */ 330 : : void setFilterType( QgsLayoutItemRegistry::ItemType filter ); 331 : : 332 : : /** 333 : : * Sets a list of specific \a items to exclude from the model. 334 : : * \see exceptedItemList() 335 : : */ 336 : : void setExceptedItemList( const QList< QgsLayoutItem * > &items ); 337 : : 338 : : /** 339 : : * Returns the list of specific items excluded from the model. 340 : : * \see setExceptedItemList() 341 : : */ 342 : : QList< QgsLayoutItem * > exceptedItemList() const { return mExceptedList; } 343 : : 344 : : /** 345 : : * Returns the QgsLayoutModel used in this proxy model. 346 : : */ 347 : : QgsLayoutModel *sourceLayerModel() const { return static_cast< QgsLayoutModel * >( sourceModel() ); } 348 : : 349 : : /** 350 : : * Returns the QgsLayoutItem corresponding to an index from the source 351 : : * QgsLayoutModel model. 352 : : */ 353 : : QgsLayoutItem *itemFromSourceIndex( const QModelIndex &sourceIndex ) const; 354 : : 355 : : /** 356 : : * Returns the associated layout. 357 : : * \since QGIS 3.8 358 : : */ 359 : : QgsLayout *layout() { return mLayout; } 360 : : 361 : : /** 362 : : * Sets whether an optional empty layout item is present in the model. 363 : : * \see allowEmptyItem() 364 : : * \since QGIS 3.8 365 : : */ 366 : : void setAllowEmptyItem( bool allowEmpty ); 367 : : 368 : : /** 369 : : * Returns TRUE if the model includes the empty item choice. 370 : : * \see setAllowEmptyItem() 371 : : * \since QGIS 3.8 372 : : */ 373 : : bool allowEmptyItem() const; 374 : : 375 : : /** 376 : : * Sets layout item flags to use for filtering the available items. 377 : : * 378 : : * Set \a flags to NULLPTR to clear the flag based filtering. 379 : : * 380 : : * \see itemFlags() 381 : : * \since QGIS 3.16 382 : : */ 383 : : void setItemFlags( QgsLayoutItem::Flags flags ); 384 : : 385 : : /** 386 : : * Returns the layout item flags used for filtering the available items. 387 : : * 388 : : * Returns NULLPTR if no flag based filtering is occurring. 389 : : * 390 : : * \see setItemFlags() 391 : : * \since QGIS 3.16 392 : : */ 393 : : QgsLayoutItem::Flags itemFlags() const; 394 : : 395 : : protected: 396 : : bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override; 397 : : bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; 398 : : 399 : : private: 400 : : QgsLayout *mLayout = nullptr; 401 : : QgsLayoutItemRegistry::ItemType mItemTypeFilter; 402 : : QList< QgsLayoutItem * > mExceptedList; 403 : : bool mAllowEmpty = false; 404 : : QgsLayoutItem::Flags mItemFlags = QgsLayoutItem::Flags(); 405 : : 406 : : }; 407 : : 408 : : 409 : : 410 : : #endif //QGSLAYOUTMODEL_H