File indexing completed on 2024-11-10 05:11:09

0001 /*
0002  * Copyright 2018 by Marco Martin <mart@kde.org>
0003  *
0004  * Licensed under the Apache License, Version 2.0 (the "License");
0005  * you may not use this file except in compliance with the License.
0006  * You may obtain a copy of the License at
0007  *
0008  *    http://www.apache.org/licenses/LICENSE-2.0
0009  *
0010  * Unless required by applicable law or agreed to in writing, software
0011  * distributed under the License is distributed on an "AS IS" BASIS,
0012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013  * See the License for the specific language governing permissions and
0014  * limitations under the License.
0015  *
0016  */
0017 #include "delegatesmodel.h"
0018 #include "abstractdelegate.h"
0019 
0020 #include <QTimer>
0021 #include <QDebug>
0022 
0023 
0024 DelegatesModel::DelegatesModel(QObject *parent)
0025     : QAbstractListModel(parent)
0026 {
0027     m_deleteTimer = new QTimer(this);
0028     m_deleteTimer->setSingleShot(true);
0029     m_deleteTimer->setInterval(2000);
0030 
0031     connect(m_deleteTimer, &QTimer::timeout, this, [this]() {
0032         for (auto d : m_delegateLoadersToDelete) {
0033             d->deleteLater();
0034         }
0035         m_delegateLoadersToDelete.clear();
0036     });
0037 }
0038 
0039 DelegatesModel::~DelegatesModel()
0040 {
0041     //TODO: necessary?
0042     for (auto c : m_delegateLoadersToDelete) {
0043         c->deleteLater();
0044     }
0045     for (auto c : m_delegateLoaders) {
0046         c->deleteLater();
0047     }
0048 }
0049 
0050 void DelegatesModel::insertDelegateLoaders(int position, QList<DelegateLoader *> loaders)
0051 {
0052     if (position < 0 || position > m_delegateLoaders.count()) {
0053         return;
0054     }
0055 
0056     beginInsertRows(QModelIndex(), position, position + loaders.count() - 1);
0057 
0058     int i = 0;
0059     for (auto *loader : loaders) {
0060         m_delegateLoaders.insert(position + i, loader);
0061         if (!loader->delegate()) {
0062             connect(loader, &DelegateLoader::delegateCreated, this, [this, loader]() {
0063                 int row = m_delegateLoaders.indexOf(loader);
0064                 emit dataChanged(index(row, 0), index(row, 0), {DelegateUi});
0065             });
0066         }
0067         connect(loader, &QObject::destroyed, this, [this](QObject *obj) {
0068             const int index = m_delegateLoaders.indexOf(qobject_cast<DelegateLoader *>(obj));
0069             //if the loader is in the list, remove it
0070             if (index > -1) {
0071                 removeRows(index, 1, QModelIndex());
0072             }
0073         });
0074         ++i;
0075     }
0076 
0077     endInsertRows();
0078 
0079     m_currentIndex = m_delegateLoaders.indexOf(loaders.first());
0080     emit currentIndexChanged();
0081 }
0082 
0083 void DelegatesModel::clear()
0084 {
0085     
0086     beginResetModel();
0087     m_delegateLoadersToDelete = m_delegateLoaders;
0088     m_deleteTimer->start();
0089     m_delegateLoaders.clear();
0090     endResetModel();
0091 }
0092 
0093 QList<AbstractDelegate *> DelegatesModel::delegates() const
0094 {
0095     QList<AbstractDelegate *> delegates;
0096 
0097     for (auto c : m_delegateLoaders) {
0098         if (c->delegate()) {
0099             delegates << c->delegate();
0100         }
0101     }
0102 
0103     return delegates;
0104 }
0105 
0106 bool DelegatesModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
0107 {
0108     if (sourceParent.isValid() || destinationParent.isValid()) {
0109         return false;
0110     }
0111 
0112     if (count <= 0 || sourceRow == destinationChild || sourceRow < 0 || sourceRow >= m_delegateLoaders.count() ||
0113         destinationChild < 0 || destinationChild >= m_delegateLoaders.count() || count - destinationChild > m_delegateLoaders.count() - sourceRow) {
0114         return false;
0115     }
0116     const int sourceLast = sourceRow + count - 1;
0117 
0118     //beginMoveRows wants indexes before the source rows are removed from the old order
0119     if (!beginMoveRows(sourceParent, sourceRow, sourceLast, destinationParent, destinationChild)) {
0120         return false;
0121     }
0122 
0123     if (sourceRow < destinationChild) {
0124         for (int i = count - 1; i >= 0; --i) {
0125             m_delegateLoaders.move(sourceRow + i, qMin(destinationChild + i, m_delegateLoaders.count() - 1));
0126         }
0127     } else {
0128         for (int i = 0; i < count; ++i) {
0129             m_delegateLoaders.move(sourceRow + i, destinationChild + i);
0130         }
0131     }
0132 
0133     endMoveRows();
0134     return true;
0135 }
0136 
0137 bool DelegatesModel::removeRows(int row, int count, const QModelIndex &parent)
0138 {
0139     if (row < 0 || count <= 0 || row + count > m_delegateLoaders.count() || parent.isValid()) {
0140         return false;
0141     }
0142 
0143     beginRemoveRows(parent, row, row + count - 1);
0144     std::copy(m_delegateLoaders.begin() + row, m_delegateLoaders.begin() + row + count,
0145               std::back_inserter(m_delegateLoadersToDelete));
0146     m_deleteTimer->start();
0147     m_delegateLoaders.erase(m_delegateLoaders.begin() + row, m_delegateLoaders.begin() + row + count);
0148 
0149     endRemoveRows();
0150     return true;
0151 }
0152 
0153 
0154 int DelegatesModel::rowCount(const QModelIndex &parent) const
0155 {
0156     if (parent.isValid()) {
0157         return 0;
0158     }
0159     return m_delegateLoaders.count();
0160 }
0161 
0162 QVariant DelegatesModel::data(const QModelIndex &index, int role) const
0163 {
0164     if (!index.isValid() || index.parent().isValid()) {
0165         return QVariant();
0166     }
0167     const int row = index.row();
0168 
0169     if (row < 0 || row >= m_delegateLoaders.count() || role != DelegateUi) {
0170         return QVariant();
0171     }
0172 
0173     return QVariant::fromValue(m_delegateLoaders[row]->delegate());
0174 }
0175 
0176 QHash<int, QByteArray> DelegatesModel::roleNames() const
0177 {
0178     return {
0179         {DelegateUi, "delegateUi"}
0180     };
0181 }
0182