20 : QAbstractItemModel (parent)
21 , Headers_ (
std::move (headers))
28 if (!
index.isValid ())
29 return Headers_.size ();
31 return mapped.model ()->columnCount (mapped);
36 if (orient != Qt::Horizontal || role != Qt::DisplayRole)
39 return Headers_.at (column);
44 if (!
index.isValid ())
51 catch (
const std::exception& e)
53 qWarning () << Q_FUNC_INFO
65 catch (
const std::exception& e)
67 qWarning () << Q_FUNC_INFO
75 if (!hasIndex (row, column,
parent))
78 auto parentItem =
parent.isValid () ?
82 return createIndex (row, column, parentItem->EnsureChild (row));
87 if (!
index.isValid () ||
index.internalPointer () == Root_.get ())
95 return createIndex (
parent->GetRow (), 0,
parent.get ());
101 return Root_->GetRowCount ();
104 return item->
GetModel ()->rowCount (item->GetIndex ());
111 for (
const auto& type : model->mimeTypes ())
112 if (!result.contains (type))
119 void Merge (QMimeData& out,
const QMimeData& sub)
121 for (
const auto& format : sub.formats ())
122 if (format !=
"text/uri-list"_ql && !out.hasFormat (format))
123 out.setData (format, sub.data (format));
125 out.setUrls (out.urls () + sub.urls ());
131 std::unique_ptr<QMimeData> result;
133 for (
const auto&
index : indexes)
137 std::unique_ptr<QMimeData> subresult { src.model ()->mimeData ({ src }) };
142 result = std::move (subresult);
144 Merge (*result, *subresult);
147 return result.release ();
152 if (!sourceIndex.isValid ())
156 auto parent = sourceIndex;
163 auto currentItem = Root_;
164 for (
const auto& idx : hier)
166 currentItem = currentItem->FindChild (idx);
169 qWarning () << Q_FUNC_INFO
170 <<
"no next item for"
177 return createIndex (currentItem->GetRow (), sourceIndex.column (), currentItem.get ());
182 const auto item = proxyIndex.isValid () ?
183 static_cast<ModelItem*
> (proxyIndex.internalPointer ()) :
186 const auto& srcIdx = item->GetIndex ();
187 return srcIdx.sibling (srcIdx.row (), proxyIndex.column ());
192 throw std::runtime_error (
"You should not set source model via setSourceModel()");
207 auto withModel = [
this, model]<
typename... Args> (void (
MergeModel::*method) (QAbstractItemModel*, Args...))
209 return [
this, model, method] (Args... args) { (this->*method) (model, args...); };
213 &QAbstractItemModel::dataChanged,
215 [
this] (
const QModelIndex& topLeft,
const QModelIndex& bottomRight)
220 &QAbstractItemModel::layoutAboutToBeChanged,
224 &QAbstractItemModel::layoutChanged,
228 &QAbstractItemModel::modelAboutToBeReset,
232 &QAbstractItemModel::modelReset,
236 &QAbstractItemModel::rowsAboutToBeInserted,
240 &QAbstractItemModel::rowsAboutToBeRemoved,
244 &QAbstractItemModel::rowsInserted,
248 &QAbstractItemModel::rowsRemoved,
252 if (
const auto rc = model->rowCount ())
256 for (
auto i = 0; i < rc; ++i)
257 Root_->AppendChild (model, model->index (i, 0), Root_);
279 qWarning () << Q_FUNC_INFO <<
"not found model" << model;
283 for (
auto r = Root_->begin (); r != Root_->end (); )
284 if ((*r)->GetModel () == model)
286 const auto idx =
static_cast<int> (std::distance (Root_->begin (), r));
288 beginRemoveRows ({}, idx, idx);
289 r = Root_->EraseChild (r);
306 for (
auto i =
Models_.begin (); i != it; ++i)
307 result += (*i)->rowCount ({});
314 for (
auto i =
Models_.begin (); i != it; ++i)
315 result += (*i)->rowCount ({});
321 const auto child = Root_->GetChild (row);
322 const auto it =
FindModel (child->GetModel ());
332 const auto child = Root_->GetChild (row);
333 const auto it =
FindModel (child->GetModel ());
352 const auto startingRow =
parent.isValid () ?
356 first + startingRow, last + startingRow);
361 const auto startingRow =
parent.isValid () ?
365 beginRemoveRows (mergedParent, first + startingRow, last + startingRow);
367 const auto rawItem =
parent.isValid () ?
368 static_cast<ModelItem*
> (mergedParent.internalPointer ()) :
370 const auto& item = rawItem->shared_from_this ();
372 auto it = item->EraseChildren (item->begin () + startingRow + first,
373 item->begin () + startingRow + last + 1);
375 RemovalRefreshers_.push ([=] ()
mutable
377 for ( ; it != item->end () && (*it)->GetModel () == model; ++it)
378 (*it)->RefreshIndex (startingRow);
384 const auto startingRow =
parent.isValid () ?
388 const auto rawItem =
parent.isValid () ?
391 const auto& item = rawItem->shared_from_this ();
393 for ( ; first <= last; ++first)
395 const auto& srcIdx = model->index (first, 0,
parent);
396 item->InsertChild (startingRow + first, model, srcIdx, item);
402 for (
int rc = item->GetRowCount (); last < rc; ++last)
404 const auto child = item->GetChild (last);
405 if (child->GetModel () != model)
408 child->RefreshIndex (startingRow);
416 RemovalRefreshers_.pop () ();
422 if (
const auto rc = model->rowCount ())
425 beginRemoveRows ({}, startingRow, rc + startingRow - 1);
426 Root_->EraseChildren (Root_->begin () + startingRow, Root_->begin () + startingRow + rc);
433 if (
const auto rc = model->rowCount ())
437 beginInsertRows ({}, startingRow, rc + startingRow - 1);
439 for (
int i = 0; i < rc; ++i)
440 Root_->InsertChild (startingRow + i, model, model->index (i, 0, {}), Root_);
448 DefaultAcceptsRowImpl_ =
true;
452 int MergeModel::RowCount (QAbstractItemModel *model)
const
457 int orig = model->rowCount ();
458 if (DefaultAcceptsRowImpl_)
462 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
T_ptr GetParent() const
Returns the pointer to the parent item.
Provides a proxying API on top of an QAbstractItemModel.
QAbstractItemModel * GetModel() const
Returns the wrapped model.