[Qt5-feedback] Add internalVariant to QModelIndex

Charley Bay charleyb123 at gmail.com
Fri Jul 15 22:35:36 CEST 2011


>
> > A "summary statement" is that I'd like to merely expose my (fairly
> > common-and-typical) model-of-containment-of-different-types to the GUI,
> > not write an adapter infrastructure that I can "mount" my model into, for
> > the purpose of exposing to the GUI.
>
> > class MyBookNode {
> >   public:
> >     void* book_or_chapter_or_paragraph_;
> >     enum { BOOK, CHAPTER, PARAGRAPH } enum_type_;
> > };
>
> >> What is the actual problem you're trying to solve?
> > Goal:  Containment models can be *exposed* to the model/view
> > infrastructure
> > without requiring an adapter (synchronization) layer.  I assert this is a
> > "common" case.  IMHO, that adapter/synchronization layer is prohibitively
> > expensive (we don't use Qt model/view unless we absolutely must, because
> > the cost is so high).
>
> > For my specific concerns, it's too hard to maintain the synchronization
> > layer (lots of code, tedious to synchronize).
>

> So the main problem is that you consider it prohibitively expensive in
> developmer and maintiner time to implement the adapter pattern using a Node
> of some sort.
>

Yes, but more specifically:

(1) Writing a custom "Node" class is fine (trivial effort)

(2) The current Qt model/view provides no mechanism to permit a custom
"Node" instance life-cycle to match the QModelIndex life-cycle.  Thus, a
(persistent and synchronized) "adapter-tree-model-of-Node-instances" is
required (huge effort).

(3) The only reason a "Node" class is considered is because no application
can implement a model (derive from a QAbstractItemModel) unless all
instances in that model are the same type.  (Only QModelIndex is the "weak
link" because a "void*" provides insufficient information to know what is
being referenced.  The rest of the Qt model/view API/infrastructure is
fine.)

I don't agree, and it seems to me that the whole point of QAIM is to define
> an interface for that adapter so that your model can be used with the rest
> of Qt (in views, comboboxes etc). You're trying to avoid doing exactly what
> the class is supposed to be doing, which is implementing the adapter.
>

Ah!  I didn't speak clearly:  I see my "tree-of-nodes" as the painfully
expensive "adapter" that I don't want to code-and-synchronize, not the
interface that QAbstactItemModel defines.  So:

(a) I derive from QAbstractItemModel.  That's fine -- that's how you use the
system.

(b) The complaint is that no application *can* implement their own
MyItemModel (derived from QAbstractItemModel) unless all the instances in
the model are of the same type (or share a common base class).

In my case, I must *first* implement a "synchronized-node-tree" to reflect
my *real* "model-of-containment", and *then* derive from QAbstractItemModel
(which indexes into that "synchronized-node-tree").  I'm only complaining
about implementing the "synchronized-node-tree".

The only reason a "void*" is considered reasonable as the sole application
state within a QModelIndex() is because the type is *assumed* to be "known",
so the implementation in the QAbstractItemModel-derived can merely cast it
to some "well-known" type.  I assert the "common case" is that the model has
heterogeneous types, so the "void*" is insufficient.

I agree it's not perfect, but adding an enum isn't the right fix. There are
> several model-related efforts underway in Qt (eg in QML) or abandoned
> (itemviews-ng). I suggest to seek them out and see if they solve the
> problem
> better for you and work on making it 'the new way' if possible.
>

If the constraints are speed-and-size of QModelIndex (and I accept those as
constraints), then IMHO an enum (or int) is *exactly* the right fix.  It's
fast, and trivial (plain-old-data), and provides all the context ever needed
to implement a QAbstractItemModel-derived class when you want to violate the
current design assumption that the model is composed of only a single
well-known type.

> For the API, we would add one (overloaded) function where we could create
> > a QModelIndex with *both* the void* and the enum:
> >
> > QModelIndex QAbstractItemModel::createIndex(int row, int column, void*
> > ptr, quint32 user_num);
>
> That also would mean that tables would have to do something like
>
> createIndex(row, column, 0, MyBookType);
>
> That 0 is not nice and can't be overloaded away.
>

IMHO, that represents a detail only relevant to the implementer of the
QAbstractItemModel-derived class.  That's already a very non-trivial effort
with many details that programmer must already know (so I don't think it
prohibitive, given the design assumption it removes).


> > Performance should be pretty much the same (copy construction is copying
> > void* and int, rather than just void*).
>
> I don't know that it ould be the same... There is also a concern of
> additional memory needs. How much extra would this cost on a 64 bit system?
> Is there padding? (I don't know).
>

I seriously doubt any measurable performance hits (it's just the
smallest-possible chunk of plain-old-data). I'd assume the size hit is
similarly small or insignificant, since a QModelIndex() already has stuff in
it beyond its current "void*" (but we agree we want it fast-and-small).

You would need to create benchmarks, but really I don't see this happening
> anyway in Qt5 to be honest. Apart from the QStandardItem-like API which you
> could implement as described below, you could look into itemviews-ng which
> is C++ template and iterator based. You could try to revive it and make it
> the new way of doing models.
>

I appreciate the thoughts.  I'll look into the QStandardItem API.

However, IMHO, this represents a serious design issue (and my only real
issue) with the Qt model/view infrastructure.  If it's not done in Qt5 (I
know there's already a lot going on, and not enough resources), then I'll
just assume it's not going to happen.

Our (irrelevant) response is that we'll continue doing-what-we're-doing:  We
don't use Qt's model/view unless we absolutely *must*.  The
"homogenous-type-in-model" design assumption is too costly.  This is one of
the reasons we have interest in QML, where we hope to dynamically present
very large amounts of (heterogenous) state.  In that respect, the Qt
model/view is the wrong answer for our problem.  It would be the correct
design for an application that presented records from a phone book (e.g., a
single record type).

A bummer, because the only limiting factor I see with any of those classes
in that design is the QModelIndex assumption of a single instance type for
items in the model.

>> It sounds like the QStandardItem API would suit you better. <snip>,
>
> > <snip, Charley misunderstands>
>


> No, QVariant::type() is exactly what you want for your enum.
> QVariant::value() is your data.
>

Ah, very good.  I'll look into that.

In that case, I'll merely instantiate a QStandardItemModel to mirror my
"real" model, and synchronize that model the same way I'm synchronizing with
MyNodeTree now.  It's *some* less code.  But, IMHO, it is still a
significant adapter to tediously synchronize during system run.  (We already
implemented a MyTree<> template that did all the work before realizing
QStandardItemModel might do what our tree does.)

Thanks for your help!

--charley
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt.nokia.com/pipermail/qt5-feedback/attachments/20110715/41a477a4/attachment-0001.html 


More information about the Qt5-feedback mailing list