Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.8
-
None
Description
Each call to `QAbstractItemModel::beginInsertRow` has to have a subsequent `QAbstractItemModel::endInsertRow` call.
Same for the other `AbstractItemModel::{begin,end}*` method pairs.
Most of the time, it's trivial to match them, but there are situations where it's difficult to get this right.
There is a C++-Idiom "RAII" which helps in this situation.
Ideally, there would be a class hierarchy with an abstract base class (e.g., `AbstractModelManipulator`) and a derived class for each begin/end operation (e.g., `ModelInsertManipulator`, `ModelRemoveManipulator`, `ModelMoveManipulator`, etc.).
That would allow to create a unique_ptr of `AbstractModelManipulator` without needing to know what it actually does, which can be super helpful in complex routines which can e.g., both insert or remove rows.
RAII has more advantages, e.g., it would also be exception-safe.
Users cannot create such a class themselves because the `begin*`/`end*` methods are protected.
See https://stackoverflow.com/questions/15277447/modelresetter-raii-object
class AbstractModelManipulator { public: explicit AbstractModelManipulator(QAbstractItemModel& model) : model(model) {} virtual ~AbstractModelManipulator() = default; protected: QAbstractItemModel& model; }; class InsertModelManipulator { public: explicit InsertRowsModelManipulator(QAbstractItemModel& model, const QModelIndex &parent, const int first, const int last) : AbstractModelManipulator(model) { model.beginInsertRows(parent, first, last) } ~InsertRowsModelManipulator() override { model.endInsertRows() } };