33 #include <QItemSelectionRange> 61 for (
int i = 0, size = c.size (); i < size; ++i)
62 if (c.at (i).get () ==
this)
71 return static_cast<FlatTreeItem*
> (idx.internalPointer ());
77 : QAbstractItemModel {
parent }
78 , Root_ { std::make_shared<FlatTreeItem> () }
93 SourceModel_->columnCount (QModelIndex ()) :
102 QModelIndex source = fti->
Index_;
103 return source.sibling (source.row (),
index.column ()).
data (role);
106 index.column () == 0)
108 if (role == Qt::DisplayRole)
110 if (fti->
Tag_.isEmpty ())
111 return tr (
"untagged");
115 return tr (
"<unknown tag>");
129 Qt::Orientation orient,
int role)
const 132 return SourceModel_->headerData (section, orient, role);
141 return fti->Index_.flags ();
143 return Qt::ItemIsSelectable |
145 Qt::ItemIsDragEnabled |
146 Qt::ItemIsDropEnabled;
150 const QModelIndex& parent)
const 152 if (!hasIndex (row, column,
parent))
153 return QModelIndex ();
162 return QModelIndex ();
164 return createIndex (row, column, fti->
C_.at (row).get ());
170 if (
index.isValid ())
182 return QModelIndex ();
187 if (
index.isValid ())
190 return Root_->C_.size ();
195 return SourceModel_ ?
196 SourceModel_->supportedDropActions () :
197 QAbstractItemModel::supportedDropActions ();
202 return SourceModel_ ?
203 SourceModel_->mimeTypes () :
204 QAbstractItemModel::mimeTypes ();
210 return QAbstractItemModel::mimeData (indexes);
212 QModelIndexList sourceIdxs;
213 for (
const auto&
index : indexes)
222 for (
const auto& subItem : item->C_)
223 sourceIdxs << subItem->Index_;
230 return SourceModel_->mimeData (sourceIdxs);
239 for (
const auto& format :
data->formats ())
240 modified.setData (format,
data->data (format));
242 if (
auto ptr = static_cast<FlatTreeItem*> (
parent.internalPointer ()))
248 modified.setData (
"x-leechcraft/tag", ptr->Tag_.toLatin1 ());
255 return SourceModel_->dropMimeData (&modified, action, -1, -1, QModelIndex ());
261 disconnect (SourceModel_,
266 SourceModel_ = model;
273 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)),
275 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)));
277 SIGNAL (dataChanged (
const QModelIndex&,
const QModelIndex&)),
279 SLOT (handleDataChanged (
const QModelIndex&,
const QModelIndex&)));
281 SIGNAL (layoutAboutToBeChanged ()),
283 SIGNAL (layoutAboutToBeChanged ()));
285 SIGNAL (layoutChanged ()),
287 SIGNAL (layoutChanged ()));
289 SIGNAL (modelReset ()),
291 SLOT (handleModelReset ()));
293 SIGNAL (rowsInserted (
const QModelIndex&,
296 SLOT (handleRowsInserted (
const QModelIndex&,
299 SIGNAL (rowsAboutToBeRemoved (
const QModelIndex&,
302 SLOT (handleRowsAboutToBeRemoved (
const QModelIndex&,
319 if (!proxy.isValid ())
322 const auto item =
ToFlat (proxy);
332 auto tags = source.data (
RoleTags).toStringList ();
337 for (
const auto& tag : tags)
339 const auto& folder = FindFolder (tag);
342 qWarning () << Q_FUNC_INFO
343 <<
"could not find folder for tag" 349 const auto& folderIdx =
index (folder->Row (), 0, {});
351 for (
int i = 0; i < folder->C_.size (); ++i)
353 const auto& child = folder->C_.at (i);
354 if (child->Index_ != source)
357 result <<
index (i, 0, folderIdx);
364 FlatTreeItem_ptr FlatToFoldersProxyModel::FindFolder (
const QString& tag)
const 366 for (
const auto& item : Root_->C_)
367 if (item->Tag_ == tag)
376 for (
const auto& item : c)
377 if (item->Tag_ == tag)
380 const auto& item = std::make_shared<FlatTreeItem> ();
383 item->Parent_ = Root_;
385 int size = c.size ();
386 beginInsertRows (QModelIndex (), size, size);
393 void FlatToFoldersProxyModel::HandleRowInserted (
int i)
395 QModelIndex idx = SourceModel_->index (i, 0);
397 QStringList tags = idx.data (
RoleTags).toStringList ();
402 QPersistentModelIndex pidx (idx);
404 Q_FOREACH (QString tag, tags)
405 AddForTag (tag, pidx);
408 void FlatToFoldersProxyModel::HandleRowRemoved (
int i)
410 QAbstractItemModel *model = SourceModel_;
411 QModelIndex idx = model->index (i, 0);
413 QStringList tags = idx.data (
RoleTags).toStringList ();
418 QPersistentModelIndex pidx (idx);
420 Q_FOREACH (QString tag, tags)
421 RemoveFromTag (tag, pidx);
424 void FlatToFoldersProxyModel::AddForTag (
const QString& tag,
425 const QPersistentModelIndex& pidx)
429 const auto& item = std::make_shared<FlatTreeItem> ();
432 item->Parent_ = folder;
435 int size = folder->C_.size ();
436 QModelIndex iidx =
index (Root_->C_.indexOf (folder), 0);
437 beginInsertRows (iidx, size, size);
438 folder->C_.append (item);
439 Items_.insert (pidx, item);
443 void FlatToFoldersProxyModel::RemoveFromTag (
const QString& tag,
444 const QPersistentModelIndex& pidx)
446 const auto& folder = GetFolder (tag);
447 auto& c = folder->C_;
448 int findex = Root_->C_.indexOf (folder);
449 for (
int i = 0, size = c.size ();
452 if (c.at (i)->Index_ != pidx)
455 beginRemoveRows (
index (findex, 0), i, i);
456 Items_.remove (pidx, c.at (i));
464 beginRemoveRows (QModelIndex (), findex, findex);
465 Root_->C_.removeAt (findex);
470 void FlatToFoldersProxyModel::HandleChanged (
const QModelIndex& idx)
472 QSet<QString> newTags = QSet<QString>::fromList (idx.data (
RoleTags).toStringList ());
473 if (newTags.isEmpty ())
474 newTags << QString ();
476 QPersistentModelIndex pidx (idx);
479 QSet<QString> oldTags;
481 oldTags << item->Tag_;
483 QSet<QString> added = QSet<QString> (newTags).subtract (oldTags);
484 QSet<QString> removed = QSet<QString> (oldTags).subtract (newTags);
485 QSet<QString> changed = QSet<QString> (newTags).intersect (oldTags);
487 Q_FOREACH (QString ch, changed)
492 int findex = Root_->C_.indexOf (folder);
493 QModelIndex fmi =
index (findex, 0);
494 for (
int i = 0, size = c.size ();
497 if (c.at (i)->Index_ != pidx)
500 emit dataChanged (
index (i, 0, fmi),
506 Q_FOREACH (QString rem, removed)
507 RemoveFromTag (rem, pidx);
509 Q_FOREACH (QString add, added)
510 AddForTag (add, pidx);
513 void FlatToFoldersProxyModel::handleDataChanged (
const QModelIndex& topLeft,
514 const QModelIndex& bottomRight)
516 QItemSelectionRange range (topLeft.sibling (topLeft.row (), 0),
517 bottomRight.sibling (bottomRight.row (), 0));
518 QModelIndexList indexes = range.indexes ();
519 for (
int i = 0, size = indexes.size ();
521 HandleChanged (indexes.at (i));
524 void FlatToFoldersProxyModel::handleModelReset ()
526 if (
const int size = Root_->C_.size ())
528 beginRemoveRows (QModelIndex (), 0, size - 1);
536 for (
int i = 0, size = SourceModel_->rowCount ();
538 HandleRowInserted (i);
542 void FlatToFoldersProxyModel::handleRowsInserted (
const QModelIndex&,
545 for (
int i = start; i <= end; ++i)
546 HandleRowInserted (i);
549 void FlatToFoldersProxyModel::handleRowsAboutToBeRemoved (
const QModelIndex&,
552 for (
int i = start; i <= end; ++i)
553 HandleRowRemoved (i);
QMimeData * mimeData(const QModelIndexList &indexes) const override
QList< QModelIndex > MapFromSource(const QModelIndex &) const
QVariant headerData(int, Qt::Orientation, int) const override
std::shared_ptr< FlatTreeItem > FlatTreeItem_ptr
FlatToFoldersProxyModel(QObject *=0)
QModelIndex parent(const QModelIndex &) const override
QList< FlatTreeItem_ptr > C_
QPersistentModelIndex Index_
QModelIndex MapToSource(const QModelIndex &) const
QVariant data(const QModelIndex &, int=Qt::DisplayRole) const override
FlatTreeItem * ToFlat(const QModelIndex &idx)
QAbstractItemModel * GetSourceModel() const
int columnCount(const QModelIndex &={}) const override
Qt::ItemFlags flags(const QModelIndex &) const override
Qt::DropActions supportedDropActions() const override
int rowCount(const QModelIndex &={}) const override
QModelIndex index(int, int, const QModelIndex &={}) const override
QStringList mimeTypes() const override
void SetSourceModel(QAbstractItemModel *)
void SetTagsManager(ITagsManager *)
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override