33 #include <QItemSelectionRange> 62 for (
int i = 0, size = c.size (); i < size; ++i)
63 if (c.at (i).get () ==
this)
72 return static_cast<FlatTreeItem*
> (idx.internalPointer ());
78 : QAbstractItemModel {
parent }
79 , Root_ { std::make_shared<FlatTreeItem> () }
94 SourceModel_->columnCount (QModelIndex ()) :
103 QModelIndex source = fti->
Index_;
104 return source.sibling (source.row (),
index.column ()).
data (role);
107 index.column () == 0)
109 if (role == Qt::DisplayRole)
111 if (fti->
Tag_.isEmpty ())
112 return tr (
"untagged");
116 return tr (
"<unknown tag>");
130 Qt::Orientation orient,
int role)
const 133 return SourceModel_->headerData (section, orient, role);
142 return fti->Index_.flags ();
144 return Qt::ItemIsSelectable |
146 Qt::ItemIsDragEnabled |
147 Qt::ItemIsDropEnabled;
151 const QModelIndex& parent)
const 153 if (!hasIndex (row, column,
parent))
154 return QModelIndex ();
163 return QModelIndex ();
165 return createIndex (row, column, fti->
C_.at (row).get ());
171 if (
index.isValid ())
183 return QModelIndex ();
188 if (
index.isValid ())
191 return Root_->C_.size ();
196 return SourceModel_ ?
197 SourceModel_->supportedDropActions () :
198 QAbstractItemModel::supportedDropActions ();
203 return SourceModel_ ?
204 SourceModel_->mimeTypes () :
205 QAbstractItemModel::mimeTypes ();
211 return QAbstractItemModel::mimeData (indexes);
213 QModelIndexList sourceIdxs;
214 for (
const auto&
index : indexes)
223 for (
const auto& subItem : item->C_)
224 sourceIdxs << subItem->Index_;
231 return SourceModel_->mimeData (sourceIdxs);
240 for (
const auto& format :
data->formats ())
241 modified.setData (format,
data->data (format));
243 if (
auto ptr = static_cast<FlatTreeItem*> (
parent.internalPointer ()))
249 modified.setData (
"x-leechcraft/tag", ptr->Tag_.toLatin1 ());
256 return SourceModel_->dropMimeData (&modified, action, -1, -1, QModelIndex ());
262 disconnect (SourceModel_,
267 SourceModel_ = model;
274 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)),
276 SIGNAL (headerDataChanged (Qt::Orientation,
int,
int)));
278 SIGNAL (dataChanged (
const QModelIndex&,
const QModelIndex&)),
280 SLOT (handleDataChanged (
const QModelIndex&,
const QModelIndex&)));
282 SIGNAL (layoutAboutToBeChanged ()),
284 SIGNAL (layoutAboutToBeChanged ()));
286 SIGNAL (layoutChanged ()),
288 SIGNAL (layoutChanged ()));
290 SIGNAL (modelReset ()),
292 SLOT (handleModelReset ()));
294 SIGNAL (rowsInserted (
const QModelIndex&,
297 SLOT (handleRowsInserted (
const QModelIndex&,
300 SIGNAL (rowsAboutToBeRemoved (
const QModelIndex&,
303 SLOT (handleRowsAboutToBeRemoved (
const QModelIndex&,
320 if (!proxy.isValid ())
323 const auto item =
ToFlat (proxy);
333 auto tags = source.data (
RoleTags).toStringList ();
338 for (
const auto& tag : tags)
340 const auto& folder = FindFolder (tag);
343 qWarning () << Q_FUNC_INFO
344 <<
"could not find folder for tag" 350 const auto& folderIdx =
index (folder->Row (), 0, {});
352 for (
int i = 0; i < folder->C_.size (); ++i)
354 const auto& child = folder->C_.at (i);
355 if (child->Index_ != source)
358 result <<
index (i, 0, folderIdx);
365 FlatTreeItem_ptr FlatToFoldersProxyModel::FindFolder (
const QString& tag)
const 367 for (
const auto& item : Root_->C_)
368 if (item->Tag_ == tag)
377 for (
const auto& item : c)
378 if (item->Tag_ == tag)
381 const auto& item = std::make_shared<FlatTreeItem> ();
384 item->Parent_ = Root_;
386 int size = c.size ();
387 beginInsertRows (QModelIndex (), size, size);
394 void FlatToFoldersProxyModel::HandleRowInserted (
int i)
396 QModelIndex idx = SourceModel_->index (i, 0);
398 QStringList tags = idx.data (
RoleTags).toStringList ();
403 QPersistentModelIndex pidx (idx);
405 for (
auto tag : tags)
406 AddForTag (tag, pidx);
409 void FlatToFoldersProxyModel::HandleRowRemoved (
int i)
411 QAbstractItemModel *model = SourceModel_;
412 QModelIndex idx = model->index (i, 0);
414 QStringList tags = idx.data (
RoleTags).toStringList ();
419 QPersistentModelIndex pidx (idx);
421 for (
const auto tag : tags)
422 RemoveFromTag (tag, pidx);
425 void FlatToFoldersProxyModel::AddForTag (
const QString& tag,
426 const QPersistentModelIndex& pidx)
430 const auto& item = std::make_shared<FlatTreeItem> ();
433 item->Parent_ = folder;
436 int size = folder->C_.size ();
437 QModelIndex iidx =
index (Root_->C_.indexOf (folder), 0);
438 beginInsertRows (iidx, size, size);
439 folder->C_.append (item);
440 Items_.insert (pidx, item);
444 void FlatToFoldersProxyModel::RemoveFromTag (
const QString& tag,
445 const QPersistentModelIndex& pidx)
447 const auto& folder = GetFolder (tag);
448 auto& c = folder->C_;
449 int findex = Root_->C_.indexOf (folder);
450 for (
int i = 0, size = c.size ();
453 if (c.at (i)->Index_ != pidx)
456 beginRemoveRows (
index (findex, 0), i, i);
457 Items_.remove (pidx, c.at (i));
465 beginRemoveRows (QModelIndex (), findex, findex);
466 Root_->C_.removeAt (findex);
471 void FlatToFoldersProxyModel::HandleChanged (
const QModelIndex& idx)
473 QSet<QString> newTags = QSet<QString>::fromList (idx.data (
RoleTags).toStringList ());
474 if (newTags.isEmpty ())
475 newTags << QString ();
477 QPersistentModelIndex pidx (idx);
479 const auto& oldTags = Util::MapAs<QSet> (Items_.values (pidx), [] (
const auto& item) {
return item->Tag_; });
481 const auto added = QSet<QString> (newTags).subtract (oldTags);
482 const auto removed = QSet<QString> (oldTags).subtract (newTags);
483 const auto changed = QSet<QString> (newTags).intersect (oldTags);
485 for (
const auto& ch : changed)
490 int findex = Root_->C_.indexOf (folder);
491 QModelIndex fmi =
index (findex, 0);
492 for (
int i = 0, size = c.size ();
495 if (c.at (i)->Index_ != pidx)
498 emit dataChanged (
index (i, 0, fmi),
504 for (
const auto& rem : removed)
505 RemoveFromTag (rem, pidx);
507 for (
const auto& add : added)
508 AddForTag (add, pidx);
511 void FlatToFoldersProxyModel::handleDataChanged (
const QModelIndex& topLeft,
512 const QModelIndex& bottomRight)
514 QItemSelectionRange range (topLeft.sibling (topLeft.row (), 0),
515 bottomRight.sibling (bottomRight.row (), 0));
516 QModelIndexList indexes = range.indexes ();
517 for (
int i = 0, size = indexes.size ();
519 HandleChanged (indexes.at (i));
522 void FlatToFoldersProxyModel::handleModelReset ()
524 if (
const int size = Root_->C_.size ())
526 beginRemoveRows (QModelIndex (), 0, size - 1);
534 for (
int i = 0, size = SourceModel_->rowCount ();
536 HandleRowInserted (i);
540 void FlatToFoldersProxyModel::handleRowsInserted (
const QModelIndex&,
543 for (
int i = start; i <= end; ++i)
544 HandleRowInserted (i);
547 void FlatToFoldersProxyModel::handleRowsAboutToBeRemoved (
const QModelIndex&,
550 for (
int i = start; i <= end; ++i)
551 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