File indexing completed on 2025-01-05 04:59:44
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Mario Bensi <mbensi@ipsquad.net> 0003 * SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org> 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 0008 #include "querytreemodelbase.h" 0009 0010 #include <QMimeData> 0011 #include <QStringList> 0012 0013 #include <algorithm> 0014 0015 using namespace Presentation; 0016 0017 QueryTreeNodeBase::QueryTreeNodeBase(QueryTreeNodeBase *parent, QueryTreeModelBase *model) 0018 : m_parent(parent), 0019 m_model(model) 0020 { 0021 } 0022 0023 QueryTreeNodeBase::~QueryTreeNodeBase() 0024 { 0025 qDeleteAll(m_childNode); 0026 } 0027 0028 int QueryTreeNodeBase::row() 0029 { 0030 return m_parent ? m_parent->m_childNode.indexOf(this) : -1; 0031 } 0032 0033 QueryTreeNodeBase *QueryTreeNodeBase::parent() const 0034 { 0035 return m_parent; 0036 } 0037 0038 QueryTreeNodeBase *QueryTreeNodeBase::child(int row) const 0039 { 0040 if (row >= 0 && row < m_childNode.size()) 0041 return m_childNode.value(row); 0042 else 0043 return nullptr; 0044 } 0045 0046 void QueryTreeNodeBase::insertChild(int row, QueryTreeNodeBase *node) 0047 { 0048 m_childNode.insert(row, node); 0049 } 0050 0051 void QueryTreeNodeBase::appendChild(QueryTreeNodeBase *node) 0052 { 0053 m_childNode.append(node); 0054 } 0055 0056 void QueryTreeNodeBase::removeChildAt(int row) 0057 { 0058 delete m_childNode.takeAt(row); 0059 } 0060 0061 int QueryTreeNodeBase::childCount() const 0062 { 0063 return m_childNode.size(); 0064 } 0065 0066 QModelIndex QueryTreeNodeBase::index(int row, int column, const QModelIndex &parent) const 0067 { 0068 return m_model->index(row, column, parent); 0069 } 0070 0071 QModelIndex QueryTreeNodeBase::createIndex(int row, int column, void *data) const 0072 { 0073 return m_model->createIndex(row, column, data); 0074 } 0075 0076 void QueryTreeNodeBase::beginInsertRows(const QModelIndex &parent, int first, int last) 0077 { 0078 m_model->beginInsertRows(parent, first, last); 0079 } 0080 0081 void QueryTreeNodeBase::endInsertRows() 0082 { 0083 m_model->endInsertRows(); 0084 } 0085 0086 void QueryTreeNodeBase::beginRemoveRows(const QModelIndex &parent, int first, int last) 0087 { 0088 m_model->beginRemoveRows(parent, first, last); 0089 } 0090 0091 void QueryTreeNodeBase::endRemoveRows() 0092 { 0093 m_model->endRemoveRows(); 0094 } 0095 0096 void QueryTreeNodeBase::emitDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) 0097 { 0098 emit m_model->dataChanged(topLeft, bottomRight); 0099 } 0100 0101 QueryTreeModelBase::QueryTreeModelBase(QueryTreeNodeBase *rootNode, QObject *parent) 0102 : QAbstractItemModel(parent), 0103 m_rootIndexFlag(Qt::ItemIsDropEnabled), 0104 m_rootNode(rootNode) 0105 { 0106 } 0107 0108 QueryTreeModelBase::~QueryTreeModelBase() 0109 { 0110 delete m_rootNode; 0111 } 0112 0113 QHash<int, QByteArray> QueryTreeModelBase::roleNames() const 0114 { 0115 auto roles = QAbstractItemModel::roleNames(); 0116 roles.insert(ObjectRole, "object"); 0117 roles.insert(IconNameRole, "icon"); 0118 roles.insert(IsDefaultRole, "default"); 0119 return roles; 0120 } 0121 0122 Qt::ItemFlags QueryTreeModelBase::flags(const QModelIndex &index) const 0123 { 0124 if (!isModelIndexValid(index)) 0125 return m_rootIndexFlag; 0126 0127 return nodeFromIndex(index)->flags(); 0128 } 0129 0130 QModelIndex QueryTreeModelBase::index(int row, int column, const QModelIndex &parent) const 0131 { 0132 if (row < 0 || column != 0) 0133 return QModelIndex(); 0134 0135 const QueryTreeNodeBase *parentNode = nodeFromIndex(parent); 0136 0137 if (row < parentNode->childCount()) { 0138 QueryTreeNodeBase *node = parentNode->child(row); 0139 return createIndex(row, column, node); 0140 } else { 0141 return QModelIndex(); 0142 } 0143 } 0144 0145 QModelIndex QueryTreeModelBase::parent(const QModelIndex &index) const 0146 { 0147 QueryTreeNodeBase *node = nodeFromIndex(index); 0148 if (!node->parent() || node->parent() == m_rootNode) 0149 return QModelIndex(); 0150 else 0151 return createIndex(node->parent()->row(), 0, node->parent()); 0152 } 0153 0154 int QueryTreeModelBase::rowCount(const QModelIndex &index) const 0155 { 0156 return nodeFromIndex(index)->childCount(); 0157 } 0158 0159 int QueryTreeModelBase::columnCount(const QModelIndex &) const 0160 { 0161 return 1; 0162 } 0163 0164 QVariant QueryTreeModelBase::data(const QModelIndex &index, int role) const 0165 { 0166 if (!isModelIndexValid(index)) { 0167 return QVariant(); 0168 } 0169 0170 const_cast<QueryTreeModelBase *>(this)->fetchAdditionalInfo(index); 0171 0172 return nodeFromIndex(index)->data(role); 0173 } 0174 0175 bool QueryTreeModelBase::setData(const QModelIndex &index, const QVariant &value, int role) 0176 { 0177 if (!isModelIndexValid(index)) { 0178 return false; 0179 } 0180 0181 return nodeFromIndex(index)->setData(value, role); 0182 } 0183 0184 bool QueryTreeModelBase::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) 0185 { 0186 Q_UNUSED(row); 0187 Q_UNUSED(column); 0188 0189 // If that's not holding that mime type we can't do the cycle checking 0190 // this is relevant only for internal drag and drop anyway 0191 if (data->hasFormat(QStringLiteral("application/x-zanshin-indexes"))) { 0192 const auto indexes = data->property("indexes").value<QModelIndexList>(); 0193 foreach (const auto &index, indexes) { 0194 auto p = parent; 0195 while (p.isValid()) { 0196 if (p == index) // Oops, we found a cycle (one of the indexes is parent of the drop point) 0197 return false; 0198 p = p.parent(); 0199 } 0200 } 0201 } 0202 0203 return nodeFromIndex(parent)->dropMimeData(data, action); 0204 } 0205 0206 QMimeData *QueryTreeModelBase::mimeData(const QModelIndexList &indexes) const 0207 { 0208 if (indexes.isEmpty()) 0209 return nullptr; 0210 0211 auto data = createMimeData(indexes); 0212 data->setData(QStringLiteral("application/x-zanshin-indexes"), "indexes"); 0213 data->setProperty("indexes", QVariant::fromValue(indexes)); 0214 return data; 0215 } 0216 0217 QStringList QueryTreeModelBase::mimeTypes() const 0218 { 0219 return QAbstractItemModel::mimeTypes() << QStringLiteral("application/x-zanshin-object") 0220 << QStringLiteral("application/x-zanshin-indexes"); 0221 } 0222 0223 Qt::DropActions QueryTreeModelBase::supportedDragActions() const 0224 { 0225 return Qt::MoveAction; 0226 } 0227 0228 Qt::DropActions QueryTreeModelBase::supportedDropActions() const 0229 { 0230 return Qt::MoveAction; 0231 } 0232 0233 QueryTreeNodeBase *QueryTreeModelBase::nodeFromIndex(const QModelIndex &index) const 0234 { 0235 return index.isValid() ? static_cast<QueryTreeNodeBase*>(index.internalPointer()) : m_rootNode; 0236 } 0237 0238 void QueryTreeModelBase::setRootIndexFlag(Qt::ItemFlags flags) 0239 { 0240 m_rootIndexFlag = flags; 0241 } 0242 0243 bool QueryTreeModelBase::isModelIndexValid(const QModelIndex &index) const 0244 { 0245 bool valid = index.isValid() 0246 && index.column() == 0 0247 && index.row() >= 0; 0248 0249 if (!valid) 0250 return false; 0251 0252 const QueryTreeNodeBase *parentNode = nodeFromIndex(index.parent()); 0253 const int count = parentNode->childCount(); 0254 return index.row() < count; 0255 } 0256 0257 #include "moc_querytreemodelbase.cpp"