12 #include <QItemSelectionRange>
42 for (
int i = 0, size = c.size (); i < size; ++i)
43 if (c.at (i).get () ==
this)
52 return static_cast<FlatTreeItem*
> (idx.internalPointer ());
56 : QAbstractItemModel { parent }
58 , Root_ { std::make_shared<FlatTreeItem> () }
65 SourceModel_->columnCount ({}) :
75 const auto& source = fti->Index_;
76 return source.sibling (source.row (),
index.column ()).data (role);
85 if (fti->Tag_.isEmpty ())
86 return tr (
"untagged");
88 const auto& ut = TM_->
GetTag (fti->Tag_);
89 return ut.isEmpty () ? tr (
"<unknown tag>") : ut;
106 return SourceModel_->headerData (section, orient, role);
113 return fti->Index_.flags ();
115 return Qt::ItemIsSelectable |
117 Qt::ItemIsDragEnabled |
118 Qt::ItemIsDropEnabled;
123 if (!hasIndex (row, column,
parent))
126 const auto& fti = ToFlatOrRoot (
parent);
129 createIndex (row, column, fti.C_.at (row).get ());
143 return ToFlatOrRoot (
index).
C_.size ();
148 return SourceModel_ ?
149 SourceModel_->supportedDropActions () :
150 QAbstractItemModel::supportedDropActions ();
155 return SourceModel_ ?
156 SourceModel_->mimeTypes () :
157 QAbstractItemModel::mimeTypes ();
163 return QAbstractItemModel::mimeData (indexes);
165 QModelIndexList sourceIdxs;
175 for (
const auto& subItem : item->C_)
176 sourceIdxs << subItem->Index_;
183 return SourceModel_->mimeData (sourceIdxs);
192 for (
const auto& format :
data->formats ())
193 modified.setData (format,
data->data (format));
200 modified.setData (QStringLiteral (
"x-leechcraft/tag"), ptr->Tag_.toLatin1 ());
206 return SourceModel_->dropMimeData (&modified, action, -1, -1, QModelIndex ());
212 disconnect (SourceModel_,
217 SourceModel_ = model;
224 &QAbstractItemModel::headerDataChanged,
226 &QAbstractItemModel::headerDataChanged);
228 &QAbstractItemModel::dataChanged,
230 &FlatToFoldersProxyModel::HandleDataChanged);
232 &QAbstractItemModel::layoutAboutToBeChanged,
234 &QAbstractItemModel::layoutAboutToBeChanged);
236 &QAbstractItemModel::layoutChanged,
238 &QAbstractItemModel::layoutChanged);
240 &QAbstractItemModel::modelReset,
242 &FlatToFoldersProxyModel::HandleModelReset);
244 &QAbstractItemModel::rowsInserted,
246 &FlatToFoldersProxyModel::HandleRowsInserted);
248 &QAbstractItemModel::rowsAboutToBeRemoved,
250 &FlatToFoldersProxyModel::HandleRowsAboutToBeRemoved);
266 if (!proxy.isValid ())
269 const auto item =
ToFlat (proxy);
279 auto tags = source.data (
RoleTags).toStringList ();
284 for (
const auto& tag : tags)
286 const auto& folder = FindFolder (tag);
289 qWarning () << Q_FUNC_INFO
290 <<
"could not find folder for tag"
296 const auto& folderIdx =
index (folder->Row (), 0, {});
298 for (
int i = 0; i < folder->C_.size (); ++i)
300 const auto& child = folder->C_.at (i);
301 if (child->Index_ != source)
304 result <<
index (i, 0, folderIdx);
311 FlatTreeItem_ptr FlatToFoldersProxyModel::FindFolder (
const QString& tag)
const
313 for (
const auto& item : Root_->C_)
314 if (item->Tag_ == tag)
323 for (
const auto& item : c)
324 if (item->Tag_ == tag)
327 const auto& item = std::make_shared<FlatTreeItem> ();
330 item->Parent_ = Root_;
332 int size = c.size ();
333 beginInsertRows (QModelIndex (), size, size);
340 const FlatTreeItem& FlatToFoldersProxyModel::ToFlatOrRoot (
const QModelIndex& idx)
const
342 return idx.isValid () ? *
ToFlat (idx) : *Root_;
345 void FlatToFoldersProxyModel::HandleRowInserted (
int i)
347 const auto& idx = SourceModel_->index (i, 0);
349 auto tags = idx.data (
RoleTags).toStringList ();
354 QPersistentModelIndex pidx (idx);
356 for (
const auto& tag : qAsConst (tags))
357 AddForTag (tag, pidx);
360 void FlatToFoldersProxyModel::HandleRowRemoved (
int i)
362 QAbstractItemModel *model = SourceModel_;
363 QModelIndex idx = model->index (i, 0);
365 QStringList tags = idx.data (
RoleTags).toStringList ();
370 QPersistentModelIndex pidx (idx);
372 for (
const auto& tag : tags)
373 RemoveFromTag (tag, pidx);
376 void FlatToFoldersProxyModel::AddForTag (
const QString& tag,
377 const QPersistentModelIndex& pidx)
381 const auto& item = std::make_shared<FlatTreeItem> ();
384 item->Parent_ = folder;
387 int size = folder->C_.size ();
388 QModelIndex iidx =
index (Root_->C_.indexOf (folder), 0);
389 beginInsertRows (iidx, size, size);
390 folder->C_.append (item);
391 Items_.insert (pidx, item);
395 void FlatToFoldersProxyModel::RemoveFromTag (
const QString& tag,
396 const QPersistentModelIndex& pidx)
398 const auto& folder = GetFolder (tag);
399 auto& c = folder->C_;
400 int findex = Root_->C_.indexOf (folder);
401 for (
int i = 0, size = c.size ();
404 if (c.at (i)->Index_ != pidx)
407 beginRemoveRows (
index (findex, 0), i, i);
408 Items_.remove (pidx, c.at (i));
416 beginRemoveRows (QModelIndex (), findex, findex);
417 Root_->C_.removeAt (findex);
422 void FlatToFoldersProxyModel::HandleChanged (
const QModelIndex& idx)
425 if (newTags.isEmpty ())
426 newTags << QString {};
428 QPersistentModelIndex pidx (idx);
430 const auto& oldTags = Util::MapAs<QSet> (Items_.values (pidx), [] (
const auto& item) { return item->Tag_; });
432 const auto added = QSet<QString> (newTags).subtract (oldTags);
433 const auto removed = QSet<QString> (oldTags).subtract (newTags);
434 const auto changed = QSet<QString> (newTags).intersect (oldTags);
436 for (
const auto& ch : changed)
441 int findex = Root_->C_.indexOf (folder);
442 QModelIndex fmi =
index (findex, 0);
443 for (
int i = 0, size = c.size ();
446 if (c.at (i)->Index_ != pidx)
449 emit dataChanged (
index (i, 0, fmi),
455 for (
const auto& rem : removed)
456 RemoveFromTag (rem, pidx);
458 for (
const auto& add : added)
459 AddForTag (add, pidx);
462 void FlatToFoldersProxyModel::HandleDataChanged (
const QModelIndex& topLeft,
const QModelIndex& bottomRight)
464 const QItemSelectionRange range
466 topLeft.sibling (topLeft.row (), 0),
467 bottomRight.sibling (bottomRight.row (), 0)
469 for (
const auto&
index : range.indexes ())
470 HandleChanged (
index);
473 void FlatToFoldersProxyModel::HandleModelReset ()
475 if (
const int size = Root_->C_.size ())
477 beginRemoveRows (QModelIndex (), 0, size - 1);
484 for (
int i = 0, size = SourceModel_->rowCount (); i < size; ++i)
485 HandleRowInserted (i);
488 void FlatToFoldersProxyModel::HandleRowsInserted (
const QModelIndex&,
int start,
int end)
490 for (
int i = start; i <= end; ++i)
491 HandleRowInserted (i);
494 void FlatToFoldersProxyModel::HandleRowsAboutToBeRemoved (
const QModelIndex&,
int start,
int end)
496 for (
int i = start; i <= end; ++i)
497 HandleRowRemoved (i);