0

I want to create an object list model like in this example: http://doc.qt.io/qt-5/qtquick-models-objectlistmodel-example.html

To use it in QML I need to set the context property

ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));

In the above example, this is done in the main.cpp, however, I would like to do this in the constructor of the class which defines the model. Is there a way to get the context in my class definition? If not, what is the best practice to set the context?

Edit: Some more context: I am doing a QQuickItem which should plot a line. This model I wanted to use to hold the properties of the ticks, namely pixel position and string label, therefore it does not need to be editable, and if the zoom changes all values will need to change. The ticks I then wanted to draw using a ListView with a custom delegate. Therefore, ideally I wanted to define my model inside the QQuickItem, which is then created in QML.

numberCruncher
  • 595
  • 1
  • 6
  • 25
  • A list of `QObejct`s and a `ListView` for some ticks sounds like a gigantic waste of resources. – dtech Mar 29 '18 at 15:04
  • And I thought I am following your suggestions :-) https://stackoverflow.com/questions/49150374/text-in-custom-qquickitem I am happy to describe it better in a chat, if you want. – numberCruncher Mar 29 '18 at 15:07
  • The text label itself won't be an issue unless you are drawing hundreds. Bug it is puzzling as to why you need the `QObject`s part. – dtech Mar 29 '18 at 15:09
  • Basically what I want: In my c++ QQuickItem I have a function which will give me a list of tick positions. These need to be drawn then. I just do not know what the best way is to get the c++ list into QML and then draw it – numberCruncher Mar 29 '18 at 15:11
  • Note that in that linked question you were taking about creating your own discrete text element, which couldn't possibly have been more efficient than simply using the QML `Text`. This is different from say if you draw the text as a part of the plot, without instantiating a bunch of text elements for each label. – dtech Mar 29 '18 at 15:11
  • Well, you can also pass a list or vector of ints. Or you could calculate those in JS from some base unit value just as well. Having a list of 160 byte objects just to represent 8 bytes of data each is a huge waste in my book. – dtech Mar 29 '18 at 15:12
  • It would be helpful to see exactly what kind of charts you are trying to draw. – dtech Mar 29 '18 at 15:15
  • Standard x vs y line plots. So I make a function which will return the list of pixel positions, and then use a Repeater? Or can I use this list directly as model of ListView? – numberCruncher Mar 29 '18 at 15:15
  • I don't recall seeing a plot where the ticks are not equally spaced. And if they are equally spaced, all you need is the spacing, you absolutely do not need an individual position for each one. That stuff will be automatically done for you. You can even do non-linear spacing. – dtech Mar 29 '18 at 15:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/167822/discussion-between-numbercruncher-and-dtech). – numberCruncher Mar 29 '18 at 15:25

1 Answers1

1

Is there a way to get the context in my class definition?

Passing it as a constructor parameter should do the trick ;)

However, I would not recommend using such an object as a model. It is quick and dirty, emphasis on dirty. It is very inefficient when the model changes, because the view has to recreate everything, whereas a full fledged model will only reflect the actual changes.

Check this implementation out.

EDIT: After your clarifications, consider the following bit of documentation:

Certain C++ sequence types are supported transparently in QML as JavaScript Array types.

In particular, QML currently supports:

QList<int>
QList<qreal>
QList<bool>
QList<QString> and QStringList
QVector<QString>
std::vector<QString>
QList<QUrl>
QVector<QUrl>
std::vector<QUrl>
QVector<int>
QVector<qreal>
QVector<bool>
std::vector<int>
std::vector<qreal>
std::vector<bool>

All those are implicitly converted to JS arrays, and you can use JS arrays as model data directly.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Thanks for the link, I will need more time to understand it. The problem is, that I create the object in qml, so I cannot pass it as constructor parameter (I suppose). – numberCruncher Mar 29 '18 at 14:58
  • If you create it in QML there is no need to expose it from C++ to QML. Just assign it to a property or whatever. – dtech Mar 29 '18 at 14:59
  • Sorry, I did not write it very clearly. The dataList which is a QList which I would have liked to be simply a member variable of my QQuickItem (the plot component). The QQuickItem is then created in QML. How would I then access dataList from QML? As simple as plot.dataList? – numberCruncher Mar 29 '18 at 15:04
  • Well sure, you only need to expose things to QML if they are not already accessible from there. But again, this is quite a waste, considering each empty `QObject` is like 160 bytes. – dtech Mar 29 '18 at 15:06
  • A further question: If I have e.g. a QList defined in my QQuickItem derived c++ class as a property, do I still need to set the context or is it automatically available? – numberCruncher Mar 29 '18 at 19:57
  • Properties just work in QML, as long as the type is supported. I am not sure whether the implicit conversion to a JS array will kick in if it is not a value returned from a C++ function tho. But if you write a property getter that should essentially happen anyway. – dtech Mar 29 '18 at 20:01