21 : QAbstractItemModel (
parent)
22 , Headers_ (std::move (headers))
30 if (!
index.isValid ())
31 return Headers_.size ();
33 return mapped.model ()->columnCount (mapped);
38 if (orient != Qt::Horizontal || role != Qt::DisplayRole)
41 return Headers_.at (column);
46 if (!
index.isValid ())
53 catch (
const std::exception& e)
55 qWarning () << Q_FUNC_INFO
67 catch (
const std::exception& e)
69 qWarning () << Q_FUNC_INFO
77 if (!hasIndex (row, column,
parent))
80 auto parentItem =
parent.isValid () ?
84 return createIndex (row, column, parentItem->EnsureChild (row));
89 if (!
index.isValid () ||
index.internalPointer () == Root_.get ())
93 auto parent = item->GetParent ();
97 return createIndex (
parent->GetRow (), 0,
parent.get ());
103 return Root_->GetRowCount ();
106 return item->
GetModel ()->rowCount (item->GetIndex ());
113 for (
const auto& type : model->mimeTypes ())
114 if (!result.contains (type))
121 void Merge (QMimeData& out,
const QMimeData& sub)
123 for (
const auto& format : sub.formats ())
124 if (format !=
"text/uri-list"_ql && !out.hasFormat (format))
125 out.setData (format, sub.data (format));
127 out.setUrls (out.urls () + sub.urls ());
133 std::unique_ptr<QMimeData> result;
135 for (
const auto&
index : indexes)
139 std::unique_ptr<QMimeData> subresult { src.model ()->mimeData ({ src }) };
144 result = std::move (subresult);
146 Merge (*result, *subresult);
149 return result.release ();
154 if (!sourceIndex.isValid ())
158 auto parent = sourceIndex;
165 auto currentItem = Root_;
166 for (
const auto& idx : hier)
168 currentItem = currentItem->FindChild (idx);
171 qWarning () << Q_FUNC_INFO
172 <<
"no next item for"
179 return createIndex (currentItem->GetRow (), sourceIndex.column (), currentItem.get ());
184 const auto item = proxyIndex.isValid () ?
185 static_cast<ModelItem*
> (proxyIndex.internalPointer ()) :
188 const auto& srcIdx = item->
GetIndex ();
189 return srcIdx.sibling (srcIdx.row (), proxyIndex.column ());
194 throw std::runtime_error (
"You should not set source model via setSourceModel()");
208 qFatal () << Q_FUNC_INFO <<
"model already added:" << model;
212 auto withModel = [
this, model]<
typename... Args> (void (
MergeModel::*method) (QAbstractItemModel*, Args...))
214 return [
this, model, method] (Args... args) { (this->*method) (model, args...); };
218 &QAbstractItemModel::dataChanged,
220 [
this] (
const QModelIndex& topLeft,
const QModelIndex& bottomRight)
225 &QAbstractItemModel::layoutAboutToBeChanged,
229 &QAbstractItemModel::layoutChanged,
233 &QAbstractItemModel::modelAboutToBeReset,
237 &QAbstractItemModel::modelReset,
241 &QAbstractItemModel::rowsAboutToBeInserted,
245 &QAbstractItemModel::rowsAboutToBeRemoved,
249 &QAbstractItemModel::rowsInserted,
253 &QAbstractItemModel::rowsRemoved,
257 if (
const auto rc = model->rowCount ())
261 for (
auto i = 0; i < rc; ++i)
262 Root_->AppendChild (model, model->index (i, 0), Root_);
284 qWarning () << Q_FUNC_INFO <<
"not found model" << model;
288 for (
auto r = Root_->begin (); r != Root_->end (); )
289 if ((*r)->GetModel () == model)
291 const auto idx =
static_cast<int> (std::distance (Root_->begin (), r));
293 beginRemoveRows ({}, idx, idx);
294 r = Root_->EraseChild (r);
311 for (
auto i =
Models_.begin (); i != it; ++i)
312 result += (*i)->rowCount ({});
319 for (
auto i =
Models_.begin (); i != it; ++i)
320 result += (*i)->rowCount ({});
326 const auto child = Root_->GetChild (row);
327 const auto it =
FindModel (child->GetModel ());
337 const auto child = Root_->GetChild (row);
338 const auto it =
FindModel (child->GetModel ());
357 const auto startingRow =
parent.isValid () ?
361 first + startingRow, last + startingRow);
366 const auto startingRow =
parent.isValid () ?
370 beginRemoveRows (mergedParent, first + startingRow, last + startingRow);
372 const auto rawItem =
parent.isValid () ?
373 static_cast<ModelItem*
> (mergedParent.internalPointer ()) :
375 const auto& item = rawItem->shared_from_this ();
377 auto it = item->
EraseChildren (item->begin () + startingRow + first,
378 item->begin () + startingRow + last + 1);
380 RemovalRefreshers_.push ([=] ()
mutable
382 for ( ; it != item->end () && (*it)->GetModel () == model; ++it)
383 (*it)->RefreshIndex (startingRow);
389 const auto startingRow =
parent.isValid () ?
393 const auto rawItem =
parent.isValid () ?
396 const auto& item = rawItem->shared_from_this ();
398 for ( ; first <= last; ++first)
400 const auto& srcIdx = model->index (first, 0,
parent);
401 item->InsertChild (startingRow + first, model, srcIdx, item);
407 for (
int rc = item->GetRowCount (); last < rc; ++last)
409 const auto child = item->GetChild (last);
410 if (child->GetModel () != model)
413 child->RefreshIndex (startingRow);
421 RemovalRefreshers_.pop () ();
427 if (
const auto rc = model->rowCount ())
430 beginRemoveRows ({}, startingRow, rc + startingRow - 1);
431 Root_->EraseChildren (Root_->begin () + startingRow, Root_->begin () + startingRow + rc);
438 if (
const auto rc = model->rowCount ())
442 beginInsertRows ({}, startingRow, rc + startingRow - 1);
444 for (
int i = 0; i < rc; ++i)
445 Root_->InsertChild (startingRow + i, model, model->index (i, 0, {}), Root_);
453 DefaultAcceptsRowImpl_ =
true;
457 int MergeModel::RowCount (QAbstractItemModel *model)
const
462 int orig = model->rowCount ();
463 if (DefaultAcceptsRowImpl_)
467 for (
int i = 0; i < orig; ++i)
QList< QAbstractItemModel * > GetAllModels() const
Returns all models intalled into this one.
QModelIndex index(int, int, const QModelIndex &=QModelIndex()) const override
const_iterator FindModel(const QAbstractItemModel *model) const
Returns a const_iterator corresponding to the passed model, or one-past-end if no such model is found...
virtual bool AcceptsRow(QAbstractItemModel *model, int row) const
Allows to filter rows from the resulting model.
const_iterator GetModelForRow(int row, int *starting=nullptr) const
Returns the model for the given row.
virtual void HandleRowsAboutToBeInserted(QAbstractItemModel *, const QModelIndex &, int, int)
void AddModel(QAbstractItemModel *model)
Adds a model to the list of source models.
QMimeData * mimeData(const QModelIndexList &indices) const override
Returns the MIME data for the given indices.
virtual void HandleModelReset(QAbstractItemModel *)
size_t Size() const
Returns the number of child models in the merger.
virtual void HandleModelAboutToBeReset(QAbstractItemModel *)
virtual void setSourceModel(QAbstractItemModel *)
int GetStartingRow(const_iterator it) const
Finds starting row for the model pointed by it.
virtual void HandleRowsAboutToBeRemoved(QAbstractItemModel *, const QModelIndex &, int, int)
QModelIndex parent(const QModelIndex &) const override
virtual void HandleRowsRemoved(QAbstractItemModel *, const QModelIndex &, int, int)
virtual QModelIndex mapToSource(const QModelIndex &index) const
Returns the source model index corresponding to the given index from the sorting filter model.
void RemoveModel(QAbstractItemModel *model)
Removes a model from the list of source models.
int columnCount(const QModelIndex &=QModelIndex()) const override
int rowCount(const QModelIndex &=QModelIndex()) const override
void SetHeaders(const QStringList &headers)
Sets the new headers for this model.
Qt::ItemFlags flags(const QModelIndex &) const override
models_t::const_iterator const_iterator
virtual QModelIndex mapFromSource(const QModelIndex &index) const
Returns the model index in the MergeModel given the index from the source model.
QStringList mimeTypes() const override
Returns the union of MIME types of the models.
models_t::iterator iterator
QVariant data(const QModelIndex &, int=Qt::DisplayRole) const override
MergeModel(QStringList headers, QObject *parent=nullptr)
Constructs the merge model.
virtual void HandleRowsInserted(QAbstractItemModel *, const QModelIndex &, int, int)
QVariant headerData(int, Qt::Orientation, int=Qt::DisplayRole) const override
iterator EraseChildren(iterator begin, iterator end)
Erases all child items in the given range.
Provides a proxying API on top of an QAbstractItemModel.
QAbstractItemModel * GetModel() const
Returns the wrapped model.
const QModelIndex & GetIndex() const
Returns the index this ModelItem instance wraps.
void InstallModelSanitizer(QAbstractItemModel &model)