File indexing completed on 2024-06-16 04:12:34

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KIS_MEMENTO_ITEM_H_
0008 #define KIS_MEMENTO_ITEM_H_
0009 
0010 #include <kis_shared.h>
0011 #include <kis_shared_ptr.h>
0012 #include "kis_tile.h"
0013 
0014 
0015 class KisMementoItem;
0016 typedef KisSharedPtr<KisMementoItem> KisMementoItemSP;
0017 
0018 class KisMementoItem : public KisShared
0019 {
0020 public:
0021     enum enumType {
0022         CHANGED  = 0x0,
0023         DELETED  = 0x1
0024     };
0025 
0026 public:
0027     KisMementoItem()
0028             : m_tileData(0), m_committedFlag(false) {
0029     }
0030 
0031     KisMementoItem(const KisMementoItem& rhs)
0032             : KisShared(),
0033             m_tileData(rhs.m_tileData),
0034             m_committedFlag(rhs.m_committedFlag),
0035             m_type(rhs.m_type),
0036             m_col(rhs.m_col),
0037             m_row(rhs.m_row),
0038             m_next(0),
0039             m_parent(0) {
0040         if (m_tileData) {
0041             if (m_committedFlag)
0042                 m_tileData->acquire();
0043             else
0044                 m_tileData->ref();
0045         }
0046     }
0047 
0048     /**
0049      * Automatically called by Kis..HashTable. It means that
0050      * this mementoItem is a root item of parental hierarchy.
0051      * So m_parent should be NULL. Taking into account the tile
0052      * was not present before, the status of the item
0053      * should be 'DELETED'.
0054      * This memento item is considered as committed, so we acquire
0055      * the tile data right at the beginning.
0056      */
0057     KisMementoItem(qint32 col, qint32 row, KisTileData* defaultTileData, KisMementoManager *mm) {
0058         Q_UNUSED(mm);
0059         m_tileData = defaultTileData;
0060         /* acquire the tileData deliberately and completely */
0061         m_tileData->acquire();
0062         m_col = col;
0063         m_row = row;
0064         m_type = DELETED;
0065         m_parent = 0;
0066         m_committedFlag = true; /* yes, we've committed it */
0067     }
0068 
0069     /**
0070      * FIXME: Not sure this function has any particular usecase.
0071      * Just leave it for compatibility with a hash table
0072      */
0073     KisMementoItem(const KisMementoItem &rhs, KisMementoManager *mm) {
0074         Q_UNUSED(mm);
0075         m_tileData = rhs.m_tileData;
0076         /* Setting counter: m_refCount++ */
0077         m_tileData->ref();
0078         m_col = rhs.m_col;
0079         m_row = rhs.m_row;
0080         m_type = CHANGED;
0081         m_parent = 0;
0082         m_committedFlag = false;
0083     }
0084 
0085     ~KisMementoItem() {
0086         releaseTileData();
0087     }
0088 
0089     void notifyDetachedFromDataManager() {
0090         // just to resemble KisTile...
0091     }
0092 
0093     void notifyDeadWithoutDetaching() {
0094         // just to resemble KisTile...
0095     }
0096 
0097     void notifyAttachedToDataManager(KisMementoManager *mm) {
0098         Q_UNUSED(mm);
0099         // just to resemble KisTile...
0100     }
0101 
0102 
0103     void reset() {
0104         releaseTileData();
0105         m_tileData = 0;
0106         m_committedFlag = false;
0107     }
0108 
0109     void deleteTile(KisTile* tile, KisTileData* defaultTileData) {
0110         m_tileData = defaultTileData;
0111         /* Setting counter: m_refCount++ */
0112         m_tileData->ref();
0113 
0114         m_col = tile->col();
0115         m_row = tile->row();
0116         m_type = DELETED;
0117     }
0118 
0119     void changeTile(KisTile* tile) {
0120         m_tileData = tile->tileData();
0121         /* Setting counter: m_refCount++ */
0122         m_tileData->ref();
0123         m_col = tile->col();
0124         m_row = tile->row();
0125         m_type = CHANGED;
0126     }
0127 
0128     void commit() {
0129         if (m_committedFlag) return;
0130         if (m_tileData) {
0131             /**
0132              * Setting counters to proper values:
0133              * m_refCount++, m_usersCount++;
0134              * m_refCount--
0135              */
0136             m_tileData->acquire();
0137             m_tileData->deref();
0138 
0139             m_tileData->setMementoed(true);
0140         }
0141         m_committedFlag = true;
0142     }
0143 
0144     inline KisTileSP tile(KisMementoManager *mm) {
0145         Q_ASSERT(m_tileData);
0146         return KisTileSP(new KisTile(m_col, m_row, m_tileData, mm));
0147     }
0148 
0149     inline enumType type() {
0150         return m_type;
0151     }
0152 
0153     inline void setParent(KisMementoItemSP parent) {
0154         m_parent = parent;
0155     }
0156     inline KisMementoItemSP parent() {
0157         return m_parent;
0158     }
0159 
0160     // Stuff for Kis..HashTable
0161     inline void setNext(KisMementoItemSP next) {
0162         m_next = next;
0163     }
0164     inline KisMementoItemSP next() const {
0165         return m_next;
0166     }
0167     inline qint32 col() const {
0168         return m_col;
0169     }
0170     inline qint32 row() const {
0171         return m_row;
0172     }
0173     inline KisTileData* tileData() const {
0174         return m_tileData;
0175     }
0176 
0177     void debugPrintInfo() {
0178         QString s = QString("------\n"
0179                    "Memento item:\t\t0x%1 (0x%2)\n"
0180                    "   status:\t(%3,%4) %5%6\n"
0181                    "   parent:\t0x%7 (0x%8)\n"
0182                    "   next:\t0x%9 (0x%10)\n")
0183                 .arg((quintptr)this)
0184                 .arg((quintptr)m_tileData)
0185                 .arg(m_col)
0186                 .arg(m_row)
0187                 .arg((m_type == CHANGED) ? 'W' : 'D')
0188                 .arg(m_committedFlag ? 'C' : '-')
0189                 .arg((quintptr)m_parent.data())
0190                 .arg(m_parent ? (quintptr)m_parent->m_tileData : 0)
0191                 .arg((quintptr)m_next.data())
0192                 .arg(m_next ? (quintptr)m_next->m_tileData : 0);
0193         dbgKrita << s;
0194     }
0195 
0196 protected:
0197     void releaseTileData() {
0198         if (m_tileData) {
0199             if (m_committedFlag) {
0200                 m_tileData->setMementoed(false);
0201                 m_tileData->release();
0202             }
0203             else {
0204                 m_tileData->deref();
0205             }
0206         }
0207     }
0208 
0209 protected:
0210     KisTileData *m_tileData {0};
0211     bool m_committedFlag {false};
0212     enumType m_type {CHANGED};
0213 
0214     qint32 m_col {0};
0215     qint32 m_row {0};
0216 
0217     KisMementoItemSP m_next;
0218     KisMementoItemSP m_parent;
0219 private:
0220 };
0221 
0222 
0223 #endif /* KIS_MEMENTO_ITEM_H_ */
0224