3#include <QLoggingCategory>
4#include "FavoriteModel.h"
6static Q_LOGGING_CATEGORY(log,
"App.Favorite.Model")
8 : QAbstractItemModel(parent)
9 , m_pDatabase(pDatabase)
15 m_pRoot->item.type = TreeItem::TYPE::Node;
17 m_pRoot->item.szName =
"Root";
18 m_Folders[0] = m_pRoot;
22CFavoriteModel::~CFavoriteModel()
30QModelIndex CFavoriteModel::index(
int row,
int column,
const QModelIndex &parent)
const
33 if(!hasIndex(row, column, parent))
return QModelIndex();
34 if(0 > row || 0 != column)
return QModelIndex();
36 tree* parentItem =
nullptr;
38 parentItem = (tree*)parent.internalPointer();
43 if(row < parentItem->children.size()) {
44 return CreateIndex(parentItem->children[row]);
51QModelIndex CFavoriteModel::parent(
const QModelIndex &index)
const
54 if(!index.isValid())
return QModelIndex();
55 if(0 != index.column())
return QModelIndex();
56 tree* item = (tree*)index.internalPointer();
57 if(!item)
return QModelIndex();
58 return CreateIndex(item->parent);
66int CFavoriteModel::rowCount(
const QModelIndex &parent)
const
68 if(!m_pDatabase)
return 0;
70 if (parent.isValid()) {
71 if(parent.column() != 0)
return 0;
72 item = (tree*)parent.internalPointer();
79 if(item->item.isFavorite())
return 0;
80 if(item->children.size())
81 return item->children.size();
82 return m_pDatabase->
GetCount(item->item.id);
85int CFavoriteModel::columnCount(
const QModelIndex &parent)
const
90bool CFavoriteModel::canFetchMore(
const QModelIndex &parent)
const
93 if(!m_pDatabase)
return false;
95 if (parent.isValid()) {
96 if(0 != parent.column())
return false;
97 tree* parentItem =
static_cast<tree*
>(parent.internalPointer());
100 if(parentItem->item.isFavorite())
102 parentId = parentItem->item.id;
103 if(parentItem->children.isEmpty())
104 return m_pDatabase->
GetCount(parentId) > 0;
111void CFavoriteModel::fetchMore(
const QModelIndex &parent)
114 if(!m_pDatabase)
return;
115 tree* parentItem =
nullptr;
117 parentItem =
static_cast<tree*
>(parent.internalPointer());
120 m_pRoot =
new tree();
122 m_pRoot->item.type = TreeItem::Node;
123 m_Folders[0] = m_pRoot;
126 parentItem = m_pRoot;
128 if(!parentItem)
return;
129 if(parentItem->item.isFavorite())
return;
130 if(!parentItem->children.isEmpty())
return;
132 auto Nodes = m_pDatabase->GetChildren(parentItem->item.id);
133 if(Nodes.isEmpty())
return;
135 beginInsertRows(parent, 0, Nodes.size() - 1);
136 foreach(
auto n, Nodes) {
137 tree* pTree =
new tree();
138 pTree->parent = parentItem;
139 pTree->SetRow(row++);
142 m_Folders[n.id] = pTree;
143 parentItem->children.append(pTree);
148QVariant CFavoriteModel::data(
const QModelIndex &index,
int role)
const
151 if (!index.isValid())
153 if(0 != index.column())
return QVariant();
154 tree* ip =
static_cast<tree*
>(index.internalPointer());
155 if(!ip)
return QVariant();
156 auto item = ip->item;
158 case Qt::DecorationRole:
159 return item.GetIcon();
160 case Qt::DisplayRole:
162 case Qt::ToolTipRole:
163 return item.szDescription;
164 case CFavoriteModel::RoleFile:
169 return QVariant::fromValue(item);
177bool CFavoriteModel::setData(
const QModelIndex &index,
const QVariant &value,
int role)
179 if(!index.isValid())
return false;
180 if(0 != index.column())
return false;
181 if (data(index, role) != value) {
182 if(Qt::EditRole == role) {
183 tree* ip = (tree*)index.internalPointer();
184 if(!ip)
return false;
185 if(ip->item.isFavorite())
186 m_pDatabase->UpdateFavorite(ip->item.id, value.toString());
188 m_pDatabase->RenameNode(ip->item.id, value.toString());
189 ip->item.szName = value.toString();
191 emit dataChanged(index, index, {role});
197Qt::ItemFlags CFavoriteModel::flags(
const QModelIndex &index)
const
199 if (!index.isValid())
200 return Qt::NoItemFlags;
202 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
205bool CFavoriteModel::removeRows(
int row,
int count,
const QModelIndex &parent)
207 tree* pItem = GetTree(parent);
208 if(!pItem || 0 > row || row + count > pItem->ChildCount())
211 beginRemoveRows(parent, row, row + count - 1);
212 for(
int i = row; i < row + count; i++) {
213 auto t = pItem->children[i];
215 if(t->item.isFolder()) {
216 m_pDatabase->DeleteNode(t->item.id,
true);
217 m_Folders.remove(t->item.id);
219 m_pDatabase->Delete(t->item.id,
true);
221 pItem->RemoveChild(t);
225 emit dataChanged(parent, parent);
229bool CFavoriteModel::AddFavorite(
230 const QString &szFile,
const QString& szName,
const QIcon &icon,
231 const QString szDescription,
int parentId)
233 if(!m_pDatabase || !m_Folders.contains(parentId))
return false;
237 auto items = m_pDatabase->GetFavorite(szFile);
238 if(items.isEmpty()) {
240 id = m_pDatabase->AddFavorite(szFile, szName, icon, szDescription, parentId);
241 if(
id <= 0 )
return false;
244 item.parentId = parentId;
245 item.szName = szName;
246 item.szFile = szFile;
248 item.szDescription = szDescription;
249 AddTree(item, parentId);
252 auto it = items.at(0);
253 if(it.id <= 0)
return false;
254 bool ok = MoveTree(it, parentId);
255 if(!ok)
return false;
256 m_pDatabase->Move(it.id, parentId);
262bool CFavoriteModel::UpdateFavorite(
263 const QString &szFile,
const QString &szName,
264 const QString &szDescription,
const QIcon &icon)
266 if(!m_pDatabase)
return false;
267 m_pDatabase->UpdateFavorite(szFile, szName, icon, szDescription);
272bool CFavoriteModel::Move(QModelIndex index, QModelIndex parentIndex)
274 if(!index.isValid())
return false;
275 tree* ip = GetTree(index);
276 if(!ip)
return false;
277 tree* ipParent = GetTree(parentIndex);
278 if(!ipParent || ipParent->item.isFavorite())
return false;
279 int nParentId = ipParent->item.id;
280 auto& item = ip->item;
282 if(item.isFavorite())
283 bRet = m_pDatabase->Move(item.id, nParentId);
285 if(item.id != nParentId && ip->FindRecursive(ipParent->item).isEmpty())
286 bRet = m_pDatabase->MoveNode(item.id, nParentId);
288 if(item.id == nParentId)
289 qWarning(log) <<
"The same node:" << item.id;
291 qWarning(log) <<
"The destination node is a child node of this node."
292 << item.id << ipParent->item.id;
296 bRet = MoveTree(ip->item, ipParent->item.id);
301bool CFavoriteModel::Copy(QModelIndex index, QModelIndex parentIndex)
304 if(!index.isValid())
return false;
305 tree* ip = GetTree(index);
306 if(!ip)
return false;
307 tree* ipParent = GetTree(parentIndex);
308 if(!ipParent || ipParent->item.isFavorite())
return false;
309 int nParentId = ipParent->item.id;
310 auto& item = ip->item;
311 if(item.isFavorite())
312 bRet = AddFavorite(item.szFile, item.szName, item.GetIcon(),
313 item.szDescription, nParentId);
315 if(item.id != nParentId)
316 bRet = m_pDatabase->AddNode(item.szName, nParentId);
318 bRet = AddTree(item, nParentId);
326 if(!m_pDatabase)
return item;
327 auto items = m_pDatabase->GetFavorite(szFile);
328 if(!items.isEmpty()) {
334void CFavoriteModel::Refresh()
342bool CFavoriteModel::AddNode(
const QString& szName,
int parentId)
344 if(!m_pDatabase || !m_Folders.contains(parentId))
return false;
346 int id = m_pDatabase->AddNode(szName, parentId);
348 auto item = m_pDatabase->GetGroup(
id);
349 auto parent = GetTree(parentId);
350 if(!parent)
return false;
355 QModelIndex index = CreateIndex(parent);
357 int pos = parent->GetInserIndex(t);
358 beginInsertRows(index, pos, pos);
359 parent->InsertChild(pos, t);
362 emit dataChanged(index, index);
367void CFavoriteModel::ClearTree(tree* node)
370 if(node->item.isFolder()) {
371 foreach(
auto child, node->children) {
374 m_Folders.remove(node->item.id);
381 if(0 ==
id)
return m_pRoot;
382 if(m_Folders.contains(
id))
383 return m_Folders[id];
391 ip =
static_cast<tree*
>(index.internalPointer());
397QModelIndex CFavoriteModel::CreateIndex(tree* t)
const
400 return QModelIndex();
404 return QModelIndex();
408 return QModelIndex();
410 return createIndex(t->GetRow(), 0, t);
415 if (item.id == 0)
return false;
417 auto parent = GetTree(parentId);
419 qCritical(log) << QString(
"m_Folders[%1] is nullptr").arg(parentId);
423 auto t =
new tree(item);
425 qCritical(log) <<
"Failed to allocate memory for tree node";
429 int pos = parent->GetInserIndex(t);
431 QModelIndex parentIndex = CreateIndex(parent);
433 beginInsertRows(parentIndex, pos, pos);
435 parent->InsertChild(pos, t);
437 if (item.isFolder()) {
438 m_Folders[item.id] = t;
443 emit dataChanged(parentIndex, parentIndex);
448bool CFavoriteModel::UpdateTree(
const QString &szFile)
450 auto items = m_pDatabase->GetFavorite(szFile);
451 foreach(
auto it, items) {
452 if(it.id <= 0)
continue;
453 tree* parent = GetTree(it.parentId);
454 if(!parent)
continue;
455 QList<tree*> children = parent->FindChild(it);
456 if(children.isEmpty())
continue;
457 foreach(
auto c, children) {
459 QModelIndex changedIndex = CreateIndex(parent);
460 if (changedIndex.isValid()) {
461 emit dataChanged(changedIndex, changedIndex);
473 int parentId = item.parentId;
474 if(parentId == newParentId)
477 if(item.isFolder() && item.id == newParentId)
480 tree* parent = GetTree(parentId);
481 if(!parent)
return false;
483 tree* newParent = GetTree(newParentId);
484 if(!newParent)
return false;
486 auto children = parent->FindChild(item);
487 foreach(
auto cur, children) {
488 int sourcePos = parent->children.indexOf(cur);
491 int desPos = newParent->GetInserIndex(cur);
492 QModelIndex index = CreateIndex(parent);
493 QModelIndex newIndex = CreateIndex(newParent);
494 beginMoveRows(index, sourcePos, sourcePos, newIndex, desPos);
495 parent->RemoveChild(cur);
496 newParent->AddChild(cur);
502CFavoriteModel::tree::tree(): item(
TreeItem::TYPE::Node)
509CFavoriteModel::tree::~tree()
513int CFavoriteModel::tree::GetRow()
const
518void CFavoriteModel::tree::SetRow(
int r)
523bool CFavoriteModel::tree::IsFolder()
const
525 return item.isFolder();
528bool CFavoriteModel::tree::IsFavorite()
const
530 return item.isFavorite();
533int CFavoriteModel::tree::ChildCount()
const
535 return children.size();
540 if (index < 0 || index >= children.size()) {
543 return children[index];
546int CFavoriteModel::tree::GetInserIndex(tree *child)
550 if(child->IsFavorite()) {
551 index = children.size();
553 foreach (
const auto &c, children) {
554 if (c && c->item.isFolder()) {
562bool CFavoriteModel::tree::AddChild(tree *child)
564 if (!child)
return false;
565 child->parent =
this;
566 return InsertChild(GetInserIndex(child), child);
569bool CFavoriteModel::tree::InsertChild(
int index, tree *child)
571 if(0 > index || ChildCount() < index || !child)
573 children.insert(index, child);
574 child->parent =
this;
576 for (
int i = index; i < ChildCount(); ++i) {
577 children[i]->SetRow(i);
582bool CFavoriteModel::tree::RemoveChild(tree *child)
584 if (!child)
return false;
586 int index = children.indexOf(child);
587 if (index == -1)
return false;
589 children.remove(index);
592 for (
int i = index; i < children.size(); ++i) {
593 children[i]->SetRow(i);
601 QList<tree*> lstChildren;
602 for (
auto child : children) {
603 if (child->item.id == item.id && child->item.type == item.type) {
604 lstChildren << child;
612 QList<tree*> lstChildren;
613 if (item.id == this->item.id && item.type == this->item.type) {
614 lstChildren << const_cast<tree*>(
this);
617 for (
auto child : children) {
618 QList<tree*> found = child->FindRecursive(item);
619 if (!found.isEmpty()) {
620 lstChildren << found;
int GetCount(int parentId=0)
得到指定id节点下的所有节点和叶子数。不递归。
The CFavoriteDatabase class