I'm a (Py)Qt newbie, porting C# GUI code to Qt for a couple of days now. One question that I keep asking myself is why are QAbstractItemModel subclasses required to supply a parent() method, and why are they required to supply, in the resulting QModelIndex, the row of a child in the parent?
This requirement forces me to add another layer over my tree data (because I don't want to call indexOf(item) in parent(), it wouldn't be very efficient) that remembers row indexes.
I ask this because it's the first time I see a model based view require this. For example, NSOutlineViewDataSource in Cocoa doesn't require this.
Trolltech devs are smart people, so I'm sure there's a good reason for this, I just want to know what reason.
The quick answer is, "they thought it best at the time." The Qt developers are people just like you and me -- they aren't perfect and they do make mistakes. They have learned from that experience and the result is in the works in the form of Itemviews-NG.
In their own words from the link above:
Let’s just say that there is room for improvement, lots of room!
By providing a parent that contains a row and column index, they provide one possible way to implement trees and support navigation. They could just as easily have used a more obvious graph implementation.
The requirement is primarily to support trees. I couldn't tell you the reason, since I'm not a Qt dev... I only use the stuff. However, if you aren't doing trees, you could probably use one of the more-tuned model classes and not have to deal with the overhead of supplying a parent. I believe that both QAbstractListModel and QAbstractTableModel handle the parent portion themselves, leaving you free to just worry about the data you want.
For trees, I suspect that one of the reasons they need the parent is that they try to keep to only asking for the information they need to draw. Without knowing all of the items in a tree (if it wasn't expanded, for example), it becomes much harder to provide an absolute position of a given item in a tree.
As for the quandry of using indexOf(item) in the parent function, have you considered using QModelIndex's internalId or internalPointer? I'm assuming they are available in PyQt... they can be used by your model to track things about the index. You might be able to use that to shortcut the effort of finding the parent's index.
Related
I am trying to understand how one would choose whether to use a QAbstractListModel or a QObject with a QQmlListProperty.
Given that the QQmlListProperty handles the "roles" functionality that would have to be written using the QAbstractListModel, it seems like the less tedious route.
I can't tell if most people suggest using QAbstractListModel simply because it has been around longer or if it is the better choice for some reason.
Nor have I been able to find any discussion of the trade-offs between the two options. This question was brought up during a Qt Developer Days talk discussing QAbstractListModel, but the answer was along the lines of "that would also work".
A model implementation will generally be more efficient to work with a view. When you expose a "dumb list" to use a model, every time the model changes the whole view is reconstructed, whereas with a model only the changes are updated. If you have a lot of items there will be tangible performance overhead.
You could use a list for a model, and you could use a model for a list, but when you want optimal performance, you should use a list for a list, and a model for a model.
I want to implement in my program a tree with nested sub-levels, and I'm looking for which of those two kind(View/Widget) is best suited for my goal.
I have a list of days with task that are either done/missed/failed, each task has a count of how many times it was done/missed/failed and lastly a score for that day.
I want to display them like so:
I made this example in QtCreator using a QTreeWidget, but I'm worried that it would be hard to modify the elements since they are stored somewhere else.
Are my worries rational and should I go to the model/view structure, or can I easily get going with the QTreeWidget? The tree will be logging the task and thus will be constantly changing. Elements will only be added to it, not removed. And the days will be sorted from highest-lowest(day 2 is first, then day 1)
If your data is stored in a database model or if you want to have a single data model and show it in some views in different ways, then you are definitely better to go with QTreeView.
But QTreeWidget has it's internal model in some way along with the methods to deal with model in context of indexes. In general if you just want something that is simple to work, you can use the widget way.
But the Model/View approach is more general and flexible IMO. You can create your own subclasses of model and view which enables you to do whatever you like.
I was reading http://www.infoq.com/interviews/trelford-functional and trying to understand the alternative approach to OO.
Q I see you’re doing a talk here at GOTOCon on functional
architecture, what is that? I thought all architectures were object
oriented?
A Well, they’re not; I wanted to highlight the idea that your choice
of language and platform does affect your architecture in the way you
think; how picking a functional language or architecture can really
benefit the system.
If I just take a simple example say we write a retail application, if
you think just about objects and mutation, then you would think when
you’re constructing a basket of items, as you add an item you'd
increase the quantity and if somebody returns an item or cancels an
item, you'd decrease the quantity, you’d be doing it wrong.
With retail system, you need to track what’s actually been done so you
can detect fraud, it’s one of the key elements of the system; so you
actually add new values each this time, you never mutate.
So just from one of the most basic systems that we interact with
everyday, functional immutable style is actually close to the
architecture you want.
If you were to adopt a more functional style wrt a shopping basket app, how would you be thinking about the problem? eg Would you still have a shopping basket object and rather than mutate its contents you'd create a new one or something?
Many thx
It would be a container data structure who's invariants modelled those of a basket (e.g. a bag -like data type). The container would be persistent, so you could transparently roll back to older versions (to allow the user to undo actions, or save for a later visit).
By not destructively updating the basket, you get rollback, undo and persistence for free.
By using a richer data type, there is less book keeping to do, and thus less chance of bugs.
I have a simple list:
mylist = ["foo", "bar", "baz"]
and a QtTableWidget with 1 column. I would like to keep the data in mylist in sync with that in the QtTableWidget, including allowing drag-and-drop reordering (i.e., the user can do that, and mylist gets updated) and programmatic changes (i.e., I update mylist and the table gets updated).
What is the right way to do this?
Note that in general there's no way in Qt/C++ proper to link a generic data structure with a view. Models are such instrumented data structures that allow trivial linking with views -- generic lists, like say QStringList can't be used like that.
In Python it should be possible to inject attributes into an existing instance of any list to turn it into a model that notifies its views of changes done to it. I don't know if any Qt-to-Python bridges do that sort of a thing, I can only give C++ perspective on this. Someone who knows PyQt or PySide is welcome to chime in and edit as appropriate.
Use a QStringListModel for the model. Enable drag-drop reordering on the view as follows:
view.setDragEnabled(true);
view.setDropIndicatorShown(true);
view.setDragDropMode(QAbstractItemView::InternalMove);
My other answer has a full example that uses the convenience widget QListWidget with its buit-in model. That may be better as a starting point, and for lists that can be reasonably manipulated with a mouse, it's a good choice. Generally if a model has 100s of items, it can't be readily manipulated with just a mouse without a way of doing real-time finds or pruning of some sort -- scrolling so many items is a usability nightmare. So don't do it.
Qt's documentation would be a good plate to start learning. Read about the model/view framework. Then look at QStringListModel and your chosen view, say QTableView or QListView.
Qt's QList class provides several methods for getting the number of items in the list - count, length, and size. As we all know, consistency is important, so which should be the canonical/preferred method to use of those 3?
I agree with everything #Cogwheel said, but in all honesty I would just pick one and stick with it. I think good style would dictate that if "size" sounds the best to you, then use "size" everywhere...don't alternate between "count", "length" and "size" haphazardly. That will lead to potential confusion or a lot of unnecessary trips to documentation pages.
You could try to come up with some other kind of rationale, but the language itself isn't even consistent. All the STL containers (e.g. list, vector) only provide "size", the string class provides "size" and "length", etc.
Pick your favorite (or if you have multiple developers, you should all agree on a favorite) and just stick with it.
The consistency you should work towards is within your project. You're not really going to gain anything by trying to be consistent with everyone else, unless there's some way they'd be incompatible.
That being said, there are subtle semantic differences (in English, not C++) between the names of the functions. If you can make your code clearer by taking advantage of the differences, then consistency may actually work against you.
IMHO, Any one of those. Since even different developers follow different functions within your project, the function names are quite self documented, in the sense that other developers can easily understand what the function is meant to.
I usually go with "size." Ultimately, it is a bit arbitrary, but Qt containers and STL containers both generally have a size, so it is easy to stay consistent between the two types. It's also the shortest. Whenever several solutions are basically equivalent, I always go with whichever results in the least amount of typing. It's a simple rule of thumb, so everybody on the project can usually remember it.