33 #include <QItemSelectionRange> 63 for (
int i = 0, size = c.size (); i < size; ++i)
64 if (c.at (i).get () ==
this)
73 return static_cast<FlatTreeItem*
> (idx.internalPointer ());
79 : QAbstractItemModel {
parent }
81 , Root_ { std::make_shared<FlatTreeItem> () }
89 SourceModel_->columnCount (QModelIndex ()) :
98 QModelIndex source = fti->
Index_;
99 return source.sibling (source.row (),
index.column ()).
data (role);
102 index.column () == 0)
104 if (role == Qt::DisplayRole)
106 if (fti->
Tag_.isEmpty ())
107 return tr (
"untagged");
111 return tr (
"<unknown tag>");
125 Qt::Orientation orient,
int role)
const 128 return SourceModel_->headerData (section, orient, role);
137 return fti->Index_.flags ();
139 return Qt::ItemIsSelectable |
141 Qt::ItemIsDragEnabled |
142 Qt::ItemIsDropEnabled;
146 const QModelIndex& parent)
const 148 if (!hasIndex (row, column,
parent))
149 return QModelIndex ();
158 return QModelIndex ();
160 return createIndex (row, column, fti->
C_.at (row).get ());
166 if (
index.isValid ())
178 return QModelIndex ();
183 if (
index.isValid ())
186 return Root_->C_.size ();
191 return SourceModel_ ?
192 SourceModel_->supportedDropActions () :
193 QAbstractItemModel::supportedDropActions ();
198 return SourceModel_ ?
199 SourceModel_->mimeTypes () :
200 QAbstractItemModel::mimeTypes ();
206 return QAbstractItemModel::mimeData (indexes);
208 QModelIndexList sourceIdxs;
209 for (
const auto&
index : indexes)
218 for (
const auto& subItem : item->C_)
219 sourceIdxs << subItem->Index_;
226 return SourceModel_->mimeData (sourceIdxs);
235 for (
const auto& format :
data->formats ())
236 modified.setData (format,
data->data (format));
238 if (
auto ptr = static_cast<FlatTreeItem*> (
parent.internalPointer ()))
244 modified.setData (
"x-leechcraft/tag", ptr->Tag_.toLatin1 ());
251 return SourceModel_->dropMimeData (&modified, action, -1, -1, QModelIndex ());
257 disconnect (SourceModel_,
262 SourceModel_ = model;
269 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)),
271 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)));
273 SIGNAL (dataChanged (
const QModelIndex&,
const QModelIndex&)),
275 SLOT (handleDataChanged (
const QModelIndex&,
const QModelIndex&)));
277 SIGNAL (layoutAboutToBeChanged ()),
279 SIGNAL (layoutAboutToBeChanged ()));
281 SIGNAL (layoutChanged ()),
283 SIGNAL (layoutChanged ()));
285 SIGNAL (modelReset ()),
287 SLOT (handleModelReset ()));
289 SIGNAL (rowsInserted (
const QModelIndex&,
292 SLOT (handleRowsInserted (
const QModelIndex&,
295 SIGNAL (rowsAboutToBeRemoved (
const QModelIndex&,
298 SLOT (handleRowsAboutToBeRemoved (
const QModelIndex&,
315 if (!proxy.isValid ())
318 const auto item =
ToFlat (proxy);
328 auto tags = source.data (
RoleTags).toStringList ();
333 for (
const auto& tag : tags)
335 const auto& folder = FindFolder (tag);
338 qWarning () << Q_FUNC_INFO
339 <<
"could not find folder for tag" 345 const auto& folderIdx =
index (folder->Row (), 0, {});
347 for (
int i = 0; i < folder->C_.size (); ++i)
349 const auto& child = folder->C_.at (i);
350 if (child->Index_ != source)
353 result <<
index (i, 0, folderIdx);
360 FlatTreeItem_ptr FlatToFoldersProxyModel::FindFolder (
const QString& tag)
const 362 for (
const auto& item : Root_->C_)
363 if (item->Tag_ == tag)
372 for (
const auto& item : c)
373 if (item->Tag_ == tag)
376 const auto& item = std::make_shared<FlatTreeItem> ();
379 item->Parent_ = Root_;
381 int size = c.size ();
382 beginInsertRows (QModelIndex (), size, size);
389 void FlatToFoldersProxyModel::HandleRowInserted (
int i)
391 QModelIndex idx = SourceModel_->index (i, 0);
393 QStringList tags = idx.data (
RoleTags).toStringList ();
398 QPersistentModelIndex pidx (idx);
400 for (
auto tag : tags)
401 AddForTag (tag, pidx);
404 void FlatToFoldersProxyModel::HandleRowRemoved (
int i)
406 QAbstractItemModel *model = SourceModel_;
407 QModelIndex idx = model->index (i, 0);
409 QStringList tags = idx.data (
RoleTags).toStringList ();
414 QPersistentModelIndex pidx (idx);
416 for (
const auto& tag : tags)
417 RemoveFromTag (tag, pidx);
420 void FlatToFoldersProxyModel::AddForTag (
const QString& tag,
421 const QPersistentModelIndex& pidx)
425 const auto& item = std::make_shared<FlatTreeItem> ();
428 item->Parent_ = folder;
431 int size = folder->C_.size ();
432 QModelIndex iidx =
index (Root_->C_.indexOf (folder), 0);
433 beginInsertRows (iidx, size, size);
434 folder->C_.append (item);
435 Items_.insert (pidx, item);
439 void FlatToFoldersProxyModel::RemoveFromTag (
const QString& tag,
440 const QPersistentModelIndex& pidx)
442 const auto& folder = GetFolder (tag);
443 auto& c = folder->C_;
444 int findex = Root_->C_.indexOf (folder);
445 for (
int i = 0, size = c.size ();
448 if (c.at (i)->Index_ != pidx)
451 beginRemoveRows (
index (findex, 0), i, i);
452 Items_.remove (pidx, c.at (i));
460 beginRemoveRows (QModelIndex (), findex, findex);
461 Root_->C_.removeAt (findex);
466 void FlatToFoldersProxyModel::HandleChanged (
const QModelIndex& idx)
469 if (newTags.isEmpty ())
470 newTags << QString {};
472 QPersistentModelIndex pidx (idx);
474 const auto& oldTags = Util::MapAs<QSet> (Items_.values (pidx), [] (
const auto& item) {
return item->Tag_; });
476 const auto added = QSet<QString> (newTags).subtract (oldTags);
477 const auto removed = QSet<QString> (oldTags).subtract (newTags);
478 const auto changed = QSet<QString> (newTags).intersect (oldTags);
480 for (
const auto& ch : changed)
485 int findex = Root_->C_.indexOf (folder);
486 QModelIndex fmi =
index (findex, 0);
487 for (
int i = 0, size = c.size ();
490 if (c.at (i)->Index_ != pidx)
493 emit dataChanged (
index (i, 0, fmi),
499 for (
const auto& rem : removed)
500 RemoveFromTag (rem, pidx);
502 for (
const auto& add : added)
503 AddForTag (add, pidx);
506 void FlatToFoldersProxyModel::handleDataChanged (
const QModelIndex& topLeft,
507 const QModelIndex& bottomRight)
509 QItemSelectionRange range (topLeft.sibling (topLeft.row (), 0),
510 bottomRight.sibling (bottomRight.row (), 0));
511 QModelIndexList indexes = range.indexes ();
512 for (
int i = 0, size = indexes.size ();
514 HandleChanged (indexes.at (i));
517 void FlatToFoldersProxyModel::handleModelReset ()
519 if (
const int size = Root_->C_.size ())
521 beginRemoveRows (QModelIndex (), 0, size - 1);
529 for (
int i = 0, size = SourceModel_->rowCount ();
531 HandleRowInserted (i);
535 void FlatToFoldersProxyModel::handleRowsInserted (
const QModelIndex&,
538 for (
int i = start; i <= end; ++i)
539 HandleRowInserted (i);
542 void FlatToFoldersProxyModel::handleRowsAboutToBeRemoved (
const QModelIndex&,
545 for (
int i = start; i <= end; ++i)
546 HandleRowRemoved (i);
QVariant headerData(int, Qt::Orientation, int) const override
std::shared_ptr< FlatTreeItem > FlatTreeItem_ptr
QStringList mimeTypes() const override
QAbstractItemModel * GetSourceModel() const
QModelIndex parent(const QModelIndex &) const override
QModelIndex index(int, int, const QModelIndex &={}) const override
auto AsSet(const T &cont)
void SetSourceModel(QAbstractItemModel *)
QList< FlatTreeItem_ptr > C_
FlatTreeItem * ToFlat(const QModelIndex &idx)
QPersistentModelIndex Index_
QVariant data(const QModelIndex &, int=Qt::DisplayRole) const override
FlatToFoldersProxyModel(const ITagsManager *, QObject *=nullptr)
int columnCount(const QModelIndex &={}) const override
QModelIndex MapToSource(const QModelIndex &) const
Qt::ItemFlags flags(const QModelIndex &) const override
Qt::DropActions supportedDropActions() const override
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
int rowCount(const QModelIndex &={}) const override
QMimeData * mimeData(const QModelIndexList &indexes) const override
QList< QModelIndex > MapFromSource(const QModelIndex &) const