File indexing completed on 2024-04-28 08:33:11
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 "viewbase.h" 0019 0020 // Qt 0021 #include <QtCore/QTimer> 0022 #include <QQmlContext> 0023 0024 // LibStdC++ 0025 #include <functional> 0026 0027 // KQuickItemViews 0028 #include "private/statetracker/viewitem_p.h" 0029 #include "adapters/abstractitemadapter.h" 0030 #include "adapters/selectionadapter.h" 0031 #include "private/statetracker/content_p.h" 0032 #include "viewport.h" 0033 #include "contextadapterfactory.h" 0034 #include "adapters/contextadapter.h" 0035 #include "adapters/modeladapter.h" 0036 #include "private/selectionadapter_p.h" 0037 #include "extensions/contextextension.h" 0038 0039 class ViewBasePrivate final : public QObject 0040 { 0041 Q_OBJECT 0042 public: 0043 0044 enum class State { 0045 UNFILLED, /*!< There is less items that the space available */ 0046 ANCHORED, /*!< Some items are out of view, but it's at the beginning */ 0047 SCROLLED, /*!< It's scrolled to a random point */ 0048 AT_END , /*!< It's at the end of the items */ 0049 ERROR , /*!< Something went wrong */ 0050 }; 0051 0052 enum class Action { 0053 INSERTION = 0, 0054 REMOVAL = 1, 0055 MOVE = 2, 0056 RESET_SCROLL = 3, 0057 SCROLL = 4, 0058 }; 0059 0060 typedef bool(ViewBasePrivate::*StateF)(); 0061 0062 static const State m_fStateMap [5][5]; 0063 static const StateF m_fStateMachine[5][5]; 0064 0065 QQmlEngine *m_pEngine { nullptr }; 0066 Qt::Corner m_Corner {Qt::TopLeftCorner}; 0067 0068 QVector<ModelAdapter*> m_lAdapters; 0069 0070 State m_State {State::UNFILLED}; 0071 0072 ViewBase* q_ptr; 0073 0074 private: 0075 bool nothing (); 0076 bool resetScoll (); 0077 bool refresh (); 0078 bool refreshFront(); 0079 bool refreshBack (); 0080 bool error (); 0081 0082 public Q_SLOTS: 0083 void slotContentChanged(); 0084 }; 0085 0086 /// Add the same property as the QtQuick.ListView 0087 class ModelIndexGroup final : public ContextExtension 0088 { 0089 public: 0090 virtual ~ModelIndexGroup() {} 0091 virtual QVector<QByteArray>& propertyNames() const override; 0092 virtual QVariant getProperty(AbstractItemAdapter* item, uint id, const QModelIndex& index) const override; 0093 }; 0094 0095 #define S ViewBasePrivate::State:: 0096 const ViewBasePrivate::State ViewBasePrivate::m_fStateMap[5][5] = { 0097 /* INSERTION REMOVAL MOVE RESET_SCROLL SCROLL */ 0098 /*UNFILLED */ { S ANCHORED, S UNFILLED , S UNFILLED , S UNFILLED, S UNFILLED }, 0099 /*ANCHORED */ { S ANCHORED, S ANCHORED , S ANCHORED , S ANCHORED, S SCROLLED }, 0100 /*SCROLLED */ { S SCROLLED, S SCROLLED , S SCROLLED , S ANCHORED, S SCROLLED }, 0101 /*AT_END */ { S AT_END , S AT_END , S AT_END , S ANCHORED, S SCROLLED }, 0102 /*ERROR */ { S ERROR , S ERROR , S ERROR , S ERROR , S ERROR }, 0103 }; 0104 #undef S 0105 0106 #define A &ViewBasePrivate:: 0107 const ViewBasePrivate::StateF ViewBasePrivate::m_fStateMachine[5][5] = { 0108 /* INSERTION REMOVAL MOVE RESET_SCROLL SCROLL */ 0109 /*UNFILLED*/ { A refreshFront, A refreshFront , A refreshFront , A nothing , A nothing }, 0110 /*ANCHORED*/ { A refreshFront, A refreshFront , A refreshFront , A nothing , A refresh }, 0111 /*SCROLLED*/ { A refresh , A refresh , A refresh , A resetScoll, A refresh }, 0112 /*AT_END */ { A refreshBack , A refreshBack , A refreshBack , A resetScoll, A refresh }, 0113 /*ERROR */ { A error , A error , A error , A error , A error }, 0114 }; 0115 #undef A 0116 0117 ViewBase::ViewBase(QQuickItem* parent) : Flickable(parent), d_ptr(new ViewBasePrivate()) 0118 { 0119 d_ptr->q_ptr = this; 0120 } 0121 0122 ViewBase::~ViewBase() 0123 { 0124 delete d_ptr; 0125 } 0126 0127 void ViewBase::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) 0128 { 0129 Q_UNUSED(oldGeometry) 0130 contentItem()->setWidth(newGeometry.width()); 0131 0132 // Resize the viewport(s) 0133 for (auto ma : qAsConst(d_ptr->m_lAdapters)) { 0134 const auto vps = ma->viewports(); 0135 for (auto vp : qAsConst(vps)) 0136 vp->resize( 0137 QRectF {0.0, 0.0, newGeometry.width(), newGeometry.height()} 0138 ); 0139 } 0140 } 0141 0142 void ViewBase::reload() 0143 { 0144 Q_ASSERT(false); 0145 } 0146 0147 void ViewBasePrivate::slotContentChanged() 0148 { 0149 emit q_ptr->contentChanged(); 0150 } 0151 0152 bool ViewBasePrivate::nothing() 0153 { return true; } 0154 0155 bool ViewBasePrivate::resetScoll() 0156 { 0157 return true; 0158 } 0159 0160 bool ViewBasePrivate::refresh() 0161 { 0162 return true; 0163 } 0164 0165 bool ViewBasePrivate::refreshFront() 0166 { 0167 return true; 0168 } 0169 0170 bool ViewBasePrivate::refreshBack() 0171 { 0172 return true; 0173 } 0174 0175 bool ViewBasePrivate::error() 0176 { 0177 Q_ASSERT(false); 0178 return true; 0179 } 0180 0181 void ViewBase::refresh() 0182 { 0183 //TODO 0184 } 0185 0186 QVector<QByteArray>& ModelIndexGroup::propertyNames() const 0187 { 0188 static QVector<QByteArray> ret { 0189 "index" , 0190 "rootIndex" , 0191 "rowCount" , 0192 }; 0193 0194 return ret; 0195 } 0196 0197 QVariant ModelIndexGroup::getProperty(AbstractItemAdapter* item, uint id, const QModelIndex& index) const 0198 { 0199 switch(id) { 0200 case 0 /*index*/: 0201 return index.row(); 0202 case 1 /*rootIndex*/: 0203 return item->index(); // That's a QPersistentModelIndex and is a better fit 0204 case 2 /*rowCount*/: 0205 return index.model()->rowCount(index); 0206 //FIXME add parent index 0207 //FIXME add parent item? 0208 //FIXME depth 0209 } 0210 0211 Q_ASSERT(false); 0212 return {}; 0213 } 0214 0215 void ViewBase::addModelAdapter(ModelAdapter* a) 0216 { 0217 connect(a, &ModelAdapter::contentChanged, 0218 d_ptr, &ViewBasePrivate::slotContentChanged); 0219 0220 a->contextAdapterFactory()->addContextExtension(new ModelIndexGroup()); 0221 0222 d_ptr->m_lAdapters << a; 0223 } 0224 0225 void ViewBase::removeModelAdapter(ModelAdapter* a) 0226 { 0227 Q_ASSERT(false); //TODO 0228 d_ptr->m_lAdapters.removeAll(a); 0229 } 0230 0231 QVector<ModelAdapter*> ViewBase::modelAdapters() const 0232 { 0233 return d_ptr->m_lAdapters; 0234 } 0235 0236 bool ViewBase::isEmpty() const 0237 { 0238 for (auto a : qAsConst(d_ptr->m_lAdapters)) { 0239 if (!a->isEmpty()) 0240 return false; 0241 } 0242 0243 return true; 0244 } 0245 0246 Qt::Corner ViewBase::gravity() const 0247 { 0248 return d_ptr->m_Corner; 0249 } 0250 0251 void ViewBase::setGravity(Qt::Corner g) 0252 { 0253 d_ptr->m_Corner = g; 0254 refresh(); 0255 } 0256 0257 #include <viewbase.moc>