File indexing completed on 2024-04-28 04:41:47

0001 /***************************************************************************
0002  *   Copyright (C) 2017 by Emmanuel Lepage Vallee                          *
0003  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@kde.org>             *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 3 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0017  **************************************************************************/
0018 #include "abstractitemadapter.h"
0019 
0020 // libstdc++
0021 #include <atomic>
0022 
0023 // Qt
0024 #include <QtCore/QTimer>
0025 #include <QQmlContext>
0026 #include <QQuickItem>
0027 #include <QQmlEngine>
0028 
0029 // KQuickItemViews
0030 #include "private/statetracker/viewitem_p.h"
0031 #include "adapters/selectionadapter.h"
0032 #include "adapters/geometryadapter.h"
0033 #include "private/selectionadapter_p.h"
0034 #include "private/geostrategyselector_p.h"
0035 #include "viewport.h"
0036 #include "private/indexmetadata_p.h"
0037 #include "private/viewport_p.h"
0038 #include "modeladapter.h"
0039 #include "private/statetracker/index_p.h"
0040 #include "viewbase.h"
0041 #include "contextadapterfactory.h"
0042 #include "contextadapter.h"
0043 
0044 class AbstractItemAdapterPrivate : public QObject
0045 {
0046     Q_OBJECT
0047 public:
0048     typedef bool(AbstractItemAdapterPrivate::*StateF)();
0049 
0050     // Helpers
0051     inline void load();
0052 
0053     // Actions
0054     bool attach ();
0055     bool refresh();
0056     bool move   ();
0057     bool flush  ();
0058     bool remove ();
0059     bool nothing();
0060     bool error  ();
0061     bool destroy();
0062     bool detach ();
0063     bool hide   ();
0064 
0065     static const StateTracker::ViewItem::State  m_fStateMap    [7][7];
0066     static const StateF                 m_fStateMachine[7][7];
0067 
0068     mutable QSharedPointer<AbstractItemAdapter::SelectionLocker> m_pLocker;
0069 
0070     mutable QQuickItem  *m_pContainer {nullptr};
0071     mutable QQuickItem  *m_pContent   {nullptr};
0072     mutable QQmlContext *m_pContext   {nullptr};
0073 
0074     // Helpers
0075     bool loadDelegate(QQuickItem* parentI) const;
0076 
0077     // Attributes
0078     AbstractItemAdapter* q_ptr;
0079 
0080 public Q_SLOTS:
0081     void slotDestroyed();
0082 };
0083 
0084 /*
0085  * The visual elements state changes.
0086  *
0087  * Note that the ::FAILED elements will always try to self-heal themselves and
0088  * go back into FAILED once the self-healing itself failed.
0089  */
0090 #define S StateTracker::ViewItem::State::
0091 const StateTracker::ViewItem::State AbstractItemAdapterPrivate::m_fStateMap[7][7] = {
0092 /*              ATTACH ENTER_BUFFER ENTER_VIEW UPDATE     MOVE   LEAVE_BUFFER   DETACH  */
0093 /*POOLING */ { S POOLING, S BUFFER, S ERROR , S ERROR , S ERROR , S ERROR  , S POOLED   },
0094 /*POOLED  */ { S POOLED , S BUFFER, S ACTIVE, S ERROR , S ERROR , S ERROR  , S DANGLING },
0095 /*BUFFER  */ { S ERROR  , S ERROR , S ACTIVE, S BUFFER, S ERROR , S POOLING, S DANGLING },
0096 /*ACTIVE  */ { S ERROR  , S BUFFER, S ERROR , S ACTIVE, S ACTIVE, S BUFFER , S POOLING  },
0097 /*FAILED  */ { S ERROR  , S BUFFER, S ACTIVE, S ACTIVE, S ACTIVE, S POOLED , S DANGLING },
0098 /*DANGLING*/ { S ERROR  , S ERROR , S ERROR , S ERROR , S ERROR , S ERROR  , S DANGLING },
0099 /*ERROR   */ { S ERROR  , S ERROR , S ERROR , S ERROR , S ERROR , S ERROR  , S DANGLING },
0100 };
0101 #undef S
0102 
0103 #define A &AbstractItemAdapterPrivate::
0104 const AbstractItemAdapterPrivate::StateF AbstractItemAdapterPrivate::m_fStateMachine[7][7] = {
0105 /*             ATTACH  ENTER_BUFFER  ENTER_VIEW   UPDATE     MOVE   LEAVE_BUFFER  DETACH  */
0106 /*POOLING */ { A error  , A error  , A error  , A error  , A error  , A error  , A nothing },
0107 /*POOLED  */ { A nothing, A attach , A move   , A error  , A error  , A error  , A destroy },
0108 /*BUFFER  */ { A error  , A error  , A move   , A refresh, A error  , A detach , A destroy },
0109 /*ACTIVE  */ { A error  , A nothing, A nothing, A refresh, A move   , A hide   , A detach  },
0110 /*FAILED  */ { A error  , A nothing, A nothing, A nothing, A nothing, A nothing, A destroy },
0111 /*DANGLING*/ { A error  , A error  , A error  , A error  , A error  , A error  , A destroy },
0112 /*error   */ { A error  , A error  , A error  , A error  , A error  , A error  , A destroy },
0113 };
0114 #undef A
0115 
0116 AbstractItemAdapter::AbstractItemAdapter(Viewport* r) :
0117     s_ptr(new StateTracker::ViewItem(r)), d_ptr(new AbstractItemAdapterPrivate)
0118 {
0119     d_ptr->q_ptr = this;
0120     s_ptr->d_ptr = this;
0121 }
0122 
0123 AbstractItemAdapter::~AbstractItemAdapter()
0124 {
0125     if (d_ptr->m_pContainer)
0126         delete d_ptr->m_pContainer;
0127 
0128     if (d_ptr->m_pContext)
0129         delete d_ptr->m_pContext;
0130 
0131     delete d_ptr;
0132 }
0133 
0134 ViewBase* AbstractItemAdapter::view() const
0135 {
0136     return s_ptr->m_pViewport->modelAdapter()->view();
0137 }
0138 
0139 void AbstractItemAdapter::resetPosition()
0140 {
0141     //
0142 }
0143 
0144 int AbstractItemAdapter::row() const
0145 {
0146     return s_ptr->row();
0147 }
0148 
0149 int AbstractItemAdapter::column() const
0150 {
0151     return s_ptr->column();
0152 }
0153 
0154 QPersistentModelIndex AbstractItemAdapter::index() const
0155 {
0156     return s_ptr->index();
0157 }
0158 
0159 AbstractItemAdapter *AbstractItemAdapter::next(Qt::Edge e) const
0160 {
0161     const auto i = s_ptr->next(e);
0162     return i ? i->d_ptr : nullptr;
0163 }
0164 
0165 AbstractItemAdapter* AbstractItemAdapter::parent() const
0166 {
0167     return nullptr;
0168 }
0169 
0170 void AbstractItemAdapter::updateGeometry()
0171 {
0172     s_ptr->updateGeometry();
0173 }
0174 
0175 void StateTracker::ViewItem::setSelected(bool v)
0176 {
0177     d_ptr->setSelected(v);
0178 }
0179 
0180 QRectF StateTracker::ViewItem::currentGeometry() const
0181 {
0182     return d_ptr->geometry();
0183 }
0184 
0185 QQuickItem* StateTracker::ViewItem::item() const
0186 {
0187     return d_ptr->container();
0188 }
0189 
0190 bool AbstractItemAdapterPrivate::attach()
0191 {
0192     if (m_pContainer)
0193         m_pContainer->setVisible(true);
0194 
0195     return q_ptr->attach();
0196 }
0197 
0198 bool AbstractItemAdapterPrivate::refresh()
0199 {
0200     return q_ptr->refresh();
0201 }
0202 
0203 bool AbstractItemAdapterPrivate::move()
0204 {
0205     const bool ret = q_ptr->move();
0206 
0207     // Views should apply the geometry they have been told to apply. Otherwise
0208     // all optimizations brakes.
0209 //     Q_ASSERT((!ret) || q_ptr->s_ptr->m_pMetadata->isInSync());
0210 
0211     return ret;
0212 }
0213 
0214 bool AbstractItemAdapterPrivate::flush()
0215 {
0216     return q_ptr->flush();
0217 }
0218 
0219 bool AbstractItemAdapterPrivate::remove()
0220 {
0221     bool ret = q_ptr->remove();
0222 
0223     m_pContainer->setParentItem(nullptr);
0224     q_ptr->s_ptr->m_pMetadata = nullptr;
0225 
0226     return ret;
0227 }
0228 
0229 bool AbstractItemAdapterPrivate::hide()
0230 {
0231     Q_ASSERT(m_pContainer);
0232     if (!m_pContainer)
0233         return false;
0234 
0235     m_pContainer->setVisible(false);
0236 
0237     return true;
0238 }
0239 
0240 // This methodwrap the removal of the element from the view
0241 bool AbstractItemAdapterPrivate::detach()
0242 {
0243     m_pContainer->setParentItem(nullptr);
0244     remove();
0245 
0246     //FIXME
0247     q_ptr->s_ptr->m_pMetadata << IndexMetadata::ViewAction::DETACH;
0248     Q_ASSERT(q_ptr->s_ptr->state() == StateTracker::ViewItem::State::POOLED);
0249 
0250     return true;
0251 }
0252 
0253 bool AbstractItemAdapterPrivate::nothing()
0254 {
0255     return true;
0256 }
0257 
0258 #pragma GCC diagnostic push
0259 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
0260 bool AbstractItemAdapterPrivate::error()
0261 {
0262     Q_ASSERT(false);
0263     return true;
0264 }
0265 #pragma GCC diagnostic pop
0266 
0267 bool AbstractItemAdapterPrivate::destroy()
0268 {
0269     auto ptrCopy = m_pLocker;
0270 
0271     //FIXME manage to add to the pool without a SEGFAULT
0272     if (m_pContainer) {
0273         m_pContainer->setParentItem(nullptr);
0274         delete m_pContainer;
0275     }
0276 
0277     m_pContainer = nullptr;
0278     m_pContent   = nullptr;
0279 
0280     if (ptrCopy) {
0281         QTimer::singleShot(0,[this, ptrCopy]() {
0282             if (!ptrCopy)
0283             // else the reference will be dropped and the destructor called
0284                 delete q_ptr;
0285         });
0286         if (m_pLocker)
0287             m_pLocker.clear();
0288     }
0289     else {
0290         delete q_ptr;
0291     }
0292 
0293     return true;
0294 }
0295 
0296 bool StateTracker::ViewItem::performAction(IndexMetadata::ViewAction a)
0297 {
0298     const int s = (int)m_State;
0299 
0300     m_State     = d_ptr->d_ptr->m_fStateMap [s][(int)a];
0301     Q_ASSERT(m_State != StateTracker::ViewItem::State::ERROR);
0302 
0303     return (d_ptr->d_ptr ->* d_ptr->d_ptr->m_fStateMachine[s][(int)a])();
0304 }
0305 
0306 int StateTracker::ViewItem::depth() const
0307 {
0308     return m_pMetadata->indexTracker()->depth();
0309 }
0310 
0311 QPair<QWeakPointer<AbstractItemAdapter::SelectionLocker>, AbstractItemAdapter*>
0312 AbstractItemAdapter::weakReference() const
0313 {
0314     if (d_ptr->m_pLocker)
0315         return {d_ptr->m_pLocker, const_cast<AbstractItemAdapter*>(this)};
0316 
0317     d_ptr->m_pLocker = QSharedPointer<SelectionLocker>(new SelectionLocker());
0318 
0319 
0320     return {d_ptr->m_pLocker, const_cast<AbstractItemAdapter*>(this)};
0321 }
0322 
0323 void AbstractItemAdapterPrivate::load()
0324 {
0325     if (m_pContext || m_pContainer)
0326         return;
0327 
0328     // Usually if we get here something already failed
0329     if (!q_ptr->s_ptr->m_pViewport->modelAdapter()->delegate()) {
0330         Q_ASSERT(false);
0331         qDebug() << "Cannot attach, there is no delegate";
0332         return;
0333     }
0334 
0335     loadDelegate(q_ptr->view()->contentItem());
0336 
0337     if (!m_pContainer) {
0338         qDebug() << "Item failed to load" << q_ptr->index().data();
0339         return;
0340     }
0341 
0342     if (!m_pContainer->z())
0343         m_pContainer->setZ(1);
0344 
0345     /*d()->m_DepthChart[depth()] = std::max(
0346         d()->m_DepthChart[depth()],
0347         pair.first->height()
0348     );*/
0349 
0350     // QtQuick can decide to destroy it even with C++ ownership, so be it
0351     connect(m_pContainer, &QObject::destroyed, this, &AbstractItemAdapterPrivate::slotDestroyed);
0352 
0353     Q_ASSERT(q_ptr->s_ptr->m_pMetadata);
0354 
0355     q_ptr->s_ptr->m_pMetadata->contextAdapter()->context();
0356 
0357     Q_ASSERT(q_ptr->s_ptr->m_pMetadata->contextAdapter()->context() == m_pContext);
0358 
0359     if (q_ptr->s_ptr->m_pViewport->s_ptr->m_pGeoAdapter->capabilities() & GeometryAdapter::Capabilities::HAS_AHEAD_OF_TIME) {
0360         q_ptr->s_ptr->m_pMetadata->performAction(
0361             IndexMetadata::GeometryAction::MODIFY
0362         );
0363     }
0364     else {
0365         //TODO it should still call the GeometryAdapter, but most of them are
0366         // currently too buggy for that to help.
0367         q_ptr->s_ptr->m_pMetadata->setSize(
0368             QSizeF(m_pContainer->width(), m_pContainer->height())
0369         );
0370     }
0371 
0372     Q_ASSERT(q_ptr->s_ptr->m_pMetadata->geometryTracker()->state() != StateTracker::Geometry::State::INIT);
0373 }
0374 
0375 QQmlContext *AbstractItemAdapter::context() const
0376 {
0377     d_ptr->load();
0378     return d_ptr->m_pContext;
0379 }
0380 
0381 QQuickItem *AbstractItemAdapter::container() const
0382 {
0383     d_ptr->load();
0384     return d_ptr->m_pContainer;
0385 }
0386 
0387 QQuickItem *AbstractItemAdapter::content() const
0388 {
0389     d_ptr->load();
0390     return d_ptr->m_pContent;
0391 }
0392 
0393 Viewport *AbstractItemAdapter::viewport() const
0394 {
0395     return s_ptr->m_pViewport;
0396 }
0397 
0398 QRectF AbstractItemAdapter::geometry() const
0399 {
0400     if (!d_ptr->m_pContainer)
0401         return {};
0402 
0403     const QPointF p = container()->mapFromItem(view()->contentItem(), {0,0});
0404     return {
0405         -p.x(),
0406         -p.y(),
0407         container()->width(),
0408         container()->height()
0409     };
0410 }
0411 
0412 QRectF AbstractItemAdapter::decoratedGeometry() const
0413 {
0414     return s_ptr->m_pMetadata->decoratedGeometry();
0415 }
0416 
0417 qreal AbstractItemAdapter::borderDecoration(Qt::Edge e) const
0418 {
0419     return s_ptr->m_pMetadata->borderDecoration(e);
0420 }
0421 
0422 void AbstractItemAdapter::setBorderDecoration(Qt::Edge e, qreal r)
0423 {
0424     s_ptr->m_pMetadata->setBorderDecoration(e, r);
0425 }
0426 
0427 bool AbstractItemAdapter::refresh()
0428 {
0429     return true;
0430 }
0431 
0432 bool AbstractItemAdapter::remove()
0433 {
0434     return true;
0435 }
0436 
0437 bool AbstractItemAdapter::move()
0438 {
0439     using Cap = GeometryAdapter::Capabilities;
0440     const auto a = s_ptr->m_pViewport->geometryAdapter();
0441     Q_ASSERT(a);
0442 
0443     const auto size = a->sizeHint(index(), this);
0444 
0445     if (content() && a->capabilities() & Cap::FORCE_DELEGATE_SIZE) {
0446         content()->setSize(size);
0447     }
0448 
0449     const auto pos = a->positionHint(index(), this);
0450     container()->setSize(size);
0451 
0452     container()->setX(pos.x());
0453     container()->setY(pos.y());
0454 
0455     return true;
0456 }
0457 
0458 bool AbstractItemAdapter::attach()
0459 {
0460     Q_ASSERT(index().isValid());
0461 
0462     return container();// && move();
0463 }
0464 
0465 bool AbstractItemAdapter::flush()
0466 {
0467     return true;
0468 }
0469 
0470 void AbstractItemAdapter::setSelected(bool /*s*/)
0471 {}
0472 
0473 bool AbstractItemAdapterPrivate::loadDelegate(QQuickItem* parentI) const
0474 {
0475     const auto delegate = q_ptr->s_ptr->m_pViewport->modelAdapter()->delegate();
0476     if (!delegate) {
0477         qWarning() << "No delegate is set";
0478         return false;
0479     }
0480 
0481     const auto engine = q_ptr->s_ptr->m_pViewport->s_ptr->engine();
0482 
0483     auto pctx = q_ptr->s_ptr->m_pMetadata->contextAdapter()->context();
0484 
0485     // Create a parent item to hold the delegate and all children
0486     auto container = qobject_cast<QQuickItem *>(q_ptr->s_ptr->m_pViewport->s_ptr->component()->create(pctx));
0487     container->setWidth(q_ptr->view()->width());
0488     engine->setObjectOwnership(container, QQmlEngine::CppOwnership);
0489     container->setParentItem(parentI);
0490 
0491     m_pContext   = pctx;
0492     m_pContainer = container;
0493 
0494     // Create a context with all the tree roles
0495     auto ctx = new QQmlContext(pctx);
0496 
0497     // Create the delegate
0498     m_pContent = qobject_cast<QQuickItem *>(delegate->create(ctx));
0499 
0500     // It allows the children to be added anyway
0501     if(!m_pContent) {
0502         if (!delegate->errorString().isEmpty())
0503             qWarning() << delegate->errorString();
0504 
0505         return true;
0506     }
0507 
0508     engine->setObjectOwnership(m_pContent, QQmlEngine::CppOwnership);
0509 
0510     m_pContent->setWidth(q_ptr->view()->width());
0511     m_pContent->setParentItem(container);
0512 
0513     const auto a = q_ptr->s_ptr->m_pViewport->geometryAdapter();
0514 
0515     // Resize the container
0516     if (!(a->capabilities() & GeometryAdapter::Capabilities::FORCE_DELEGATE_SIZE))
0517         container->setHeight(m_pContent->height());
0518 
0519     // Make sure it can be resized dynamically
0520     QObject::connect(m_pContent, &QQuickItem::heightChanged, container, [container, this]() {
0521         const auto a = q_ptr->s_ptr->m_pViewport->geometryAdapter();
0522         if (!(a->capabilities() & GeometryAdapter::Capabilities::FORCE_DELEGATE_SIZE))
0523             container->setHeight(m_pContent->height());
0524     });
0525 
0526     return true;
0527 }
0528 
0529 void StateTracker::ViewItem::updateGeometry()
0530 {
0531     const auto sm = m_pViewport->modelAdapter()->selectionAdapter();
0532 
0533     if (sm && sm->selectionModel() && sm->selectionModel()->currentIndex() == index())
0534         sm->s_ptr->updateSelection(index());
0535 
0536     m_pViewport->s_ptr->geometryUpdated(m_pMetadata);
0537 }
0538 
0539 QQmlContext *StateTracker::ViewItem::context() const
0540 {
0541     return d_ptr->d_ptr->m_pContext;
0542 }
0543 
0544 void AbstractItemAdapter::setCollapsed(bool v)
0545 {
0546     s_ptr->setCollapsed(v);
0547 }
0548 
0549 bool AbstractItemAdapter::isCollapsed() const
0550 {
0551     return s_ptr->isCollapsed();
0552 }
0553 
0554 QSizeF AbstractItemAdapter::sizeHint() const
0555 {
0556     return s_ptr->m_pMetadata->sizeHint();
0557 }
0558 
0559 QPersistentModelIndex StateTracker::ViewItem::index() const
0560 {
0561     return QModelIndex(m_pMetadata->indexTracker()->index());
0562 }
0563 
0564 /**
0565  * Flatten the tree as a linked list.
0566  *
0567  * Returns the previous non-failed item.
0568  */
0569 StateTracker::ViewItem* StateTracker::ViewItem::up() const
0570 {
0571     Q_ASSERT(m_State == State::ACTIVE
0572         || m_State == State::BUFFER
0573         || m_State == State::FAILED
0574         || m_State == State::POOLING
0575         || m_State == State::DANGLING //FIXME add a new state for
0576         // "deletion in progress" or swap the f call and set state
0577     );
0578 
0579     auto ret = m_pMetadata->indexTracker()->up();
0580     //TODO support collapsed nodes
0581 
0582     // Linearly look for a valid element. Doing this here allows the views
0583     // that implement this (abstract) class to work without having to always
0584     // check if some of their item failed to load. This is non-fatal in the
0585     // other Qt views, so it isn't fatal here either.
0586     while (ret && !ret->metadata()->viewTracker())
0587         ret = ret->up();
0588 
0589     if (ret && ret->metadata()->viewTracker())
0590         Q_ASSERT(ret->metadata()->viewTracker()->m_State != State::POOLING && ret->metadata()->viewTracker()->m_State != State::DANGLING);
0591 
0592     auto vi = ret ? ret->metadata()->viewTracker() : nullptr;
0593 
0594     // Do not allow navigating past the loaded edges
0595     if (vi && (vi->m_State == State::POOLING || vi->m_State == State::POOLED))
0596         return nullptr;
0597 
0598     return vi;
0599 }
0600 
0601 /**
0602  * Flatten the tree as a linked list.
0603  *
0604  * Returns the next non-failed item.
0605  */
0606 StateTracker::ViewItem* StateTracker::ViewItem::down() const
0607 {
0608     Q_ASSERT(m_State == State::ACTIVE
0609         || m_State == State::BUFFER
0610         || m_State == State::FAILED
0611         || m_State == State::POOLING
0612         || m_State == State::DANGLING //FIXME add a new state for
0613         // "deletion in progress" or swap the f call and set state
0614     );
0615 
0616     auto ret = m_pMetadata->indexTracker();
0617     //TODO support collapsed entries
0618 
0619     // Recursively look for a valid element. Doing this here allows the views
0620     // that implement this (abstract) class to work without having to always
0621     // check if some of their item failed to load. This is non-fatal in the
0622     // other Qt views, so it isn't fatal here either.
0623     while (ret && !ret->metadata()->viewTracker())
0624         ret = ret->down();
0625 
0626     auto vi = ret ? ret->metadata()->viewTracker() : nullptr;
0627 
0628     // Do not allow navigating past the loaded edges
0629     if (vi && (vi->m_State == State::POOLING || vi->m_State == State::POOLED))
0630         return nullptr;
0631 
0632     return vi;
0633 }
0634 
0635 StateTracker::ViewItem *StateTracker::ViewItem::next(Qt::Edge e) const
0636 {
0637     switch (e) {
0638         case Qt::TopEdge:
0639             return up();
0640         case Qt::BottomEdge:
0641             return down();
0642         case Qt::LeftEdge:
0643             return left();
0644         case Qt::RightEdge:
0645             return right();
0646     }
0647 
0648     Q_ASSERT(false);
0649     return {};
0650 }
0651 
0652 int StateTracker::ViewItem::row() const
0653 {
0654     return m_pMetadata->indexTracker()->effectiveRow();
0655 }
0656 
0657 int StateTracker::ViewItem::column() const
0658 {
0659     return m_pMetadata->indexTracker()->effectiveColumn();
0660 }
0661 
0662 void StateTracker::ViewItem::setCollapsed(bool v)
0663 {
0664     m_pMetadata->setCollapsed(v);
0665 }
0666 
0667 bool StateTracker::ViewItem::isCollapsed() const
0668 {
0669     return m_pMetadata->isCollapsed();
0670 }
0671 
0672 StateTracker::ViewItem::State StateTracker::ViewItem::state() const
0673 {
0674     return m_State;
0675 }
0676 
0677 void AbstractItemAdapterPrivate::slotDestroyed()
0678 {
0679     m_pContainer = nullptr;
0680     m_pContent   = nullptr;
0681 }
0682 
0683 #include <abstractitemadapter.moc>