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;
236 item.type = TreeItem::Leaf;
238 auto items = m_pDatabase->GetFavorite(szFile);
239 if(items.isEmpty()) {
241 id = m_pDatabase->AddFavorite(szFile, szName, icon, szDescription, parentId);
242 if(
id <= 0 )
return false;
245 item.parentId = parentId;
246 item.szName = szName;
247 item.szFile = szFile;
249 item.szDescription = szDescription;
250 AddTree(item, parentId);
253 auto it = items.at(0);
254 if(it.id <= 0)
return false;
255 bool ok = MoveTree(it.id, parentId);
256 if(!ok)
return false;
257 m_pDatabase->Move(it.id, parentId);
263bool CFavoriteModel::UpdateFavorite(
264 const QString &szFile,
const QString &szName,
265 const QString &szDescription,
const QIcon &icon)
267 if(!m_pDatabase)
return false;
268 m_pDatabase->UpdateFavorite(szFile, szName, icon, szDescription);
276 if(!m_pDatabase)
return item;
277 auto items = m_pDatabase->GetFavorite(szFile);
278 if(!items.isEmpty()) {
284void CFavoriteModel::Refresh()
292bool CFavoriteModel::AddNode(
const QString& szName,
int parentId)
294 if(!m_pDatabase || !m_Folders.contains(parentId))
return false;
296 int id = m_pDatabase->AddNode(szName, parentId);
298 auto item = m_pDatabase->GetGroup(
id);
299 auto parent = GetTree(parentId);
300 if(!parent)
return false;
305 QModelIndex index = CreateIndex(parent);
307 int pos = parent->GetInserIndex(t);
308 beginInsertRows(index, pos, pos);
309 parent->InsertChild(pos, t);
312 emit dataChanged(index, index);
317void CFavoriteModel::ClearTree(tree* node)
320 if(node->item.isFolder()) {
321 foreach(
auto child, node->children) {
324 m_Folders.remove(node->item.id);
331 if(0 ==
id)
return m_pRoot;
332 if(m_Folders.contains(
id))
333 return m_Folders[id];
341 ip =
static_cast<tree*
>(index.internalPointer());
347QModelIndex CFavoriteModel::CreateIndex(tree* t)
const
350 return QModelIndex();
354 return QModelIndex();
358 return QModelIndex();
360 return createIndex(t->GetRow(), 0, t);
365 if (item.id == 0)
return false;
367 auto parent = GetTree(parentId);
369 qCritical(log) << QString(
"m_Folders[%1] is nullptr").arg(parentId);
373 auto t =
new tree(item);
375 qCritical(log) <<
"Failed to allocate memory for tree node";
379 int pos = parent->GetInserIndex(t);
381 QModelIndex parentIndex = CreateIndex(parent);
383 beginInsertRows(parentIndex, pos, pos);
385 parent->InsertChild(pos, t);
387 if (item.isFolder()) {
388 m_Folders[item.id] = t;
393 emit dataChanged(parentIndex, parentIndex);
398bool CFavoriteModel::UpdateTree(
const QString &szFile)
400 auto items = m_pDatabase->GetFavorite(szFile);
401 foreach(
auto it, items) {
402 if(it.id <= 0)
continue;
403 auto leaf = m_pDatabase->GetLeaf(it.id);
404 if(leaf.GetId() == 0)
406 int parentId = leaf.GetParentId();
407 tree* parent = GetTree(parentId);
408 if(!parent)
continue;
409 auto c = parent->FindChild(it.id);
412 QModelIndex changedIndex = CreateIndex(parent);
413 if (changedIndex.isValid()) {
414 emit dataChanged(changedIndex, changedIndex);
420bool CFavoriteModel::MoveTree(
int id,
int newParentId)
422 auto leaf = m_pDatabase->GetLeaf(
id);
423 if(leaf.GetId() == 0)
426 int parentId = leaf.GetParentId();
427 if(parentId == newParentId)
430 tree* parent = GetTree(parentId);
431 if(!parent)
return false;
433 tree* newParent = GetTree(newParentId);
434 if(!newParent)
return false;
436 tree* cur = parent->FindChild(
id);
437 int sourcePos = parent->children.indexOf(cur);
440 int desPos = parent->GetInserIndex(cur);
441 QModelIndex index = CreateIndex(parent);
442 QModelIndex newIndex = CreateIndex(newParent);
443 beginMoveRows(index, sourcePos, sourcePos, newIndex, desPos);
444 parent->RemoveChild(cur);
445 newParent->AddChild(cur);
450CFavoriteModel::tree::tree()
457CFavoriteModel::tree::~tree()
461int CFavoriteModel::tree::GetRow()
const
466void CFavoriteModel::tree::SetRow(
int r)
471bool CFavoriteModel::tree::IsFolder()
const
473 return item.isFolder();
476bool CFavoriteModel::tree::IsFavorite()
const
478 return item.isFavorite();
481int CFavoriteModel::tree::ChildCount()
const
483 return children.size();
488 if (index < 0 || index >= children.size()) {
491 return children[index];
494int CFavoriteModel::tree::GetInserIndex(tree *child)
498 if(child->IsFavorite()) {
499 index = children.size();
501 foreach (
const auto &c, children) {
502 if (c && c->item.isFolder()) {
510bool CFavoriteModel::tree::AddChild(tree *child)
512 if (!child)
return false;
513 child->parent =
this;
514 return InsertChild(GetInserIndex(child), child);
517bool CFavoriteModel::tree::InsertChild(
int index, tree *child)
519 if(0 > index || ChildCount() < index || !child)
521 children.insert(index, child);
522 child->parent =
this;
524 for (
int i = index; i < ChildCount(); ++i) {
525 children[i]->SetRow(i);
530bool CFavoriteModel::tree::RemoveChild(tree *child)
532 if (!child)
return false;
534 int index = children.indexOf(child);
535 if (index == -1)
return false;
537 children.remove(index);
540 for (
int i = index; i < children.size(); ++i) {
541 children[i]->SetRow(i);
549 for (
auto child : children) {
550 if (child->item.id ==
id) {
560 return const_cast<tree*
>(
this);
563 for (
auto child : children) {
564 tree* found = child->FindRecursive(
id);
int GetCount(int parentId=0)
得到指定id节点下的所有节点和叶子数。不递归。