I've a simple question regarding the update of a QTreeView (or any subclass of QAbstractItemView) when a model object changes externally. Let's say that a list shows a subclass of QAbstractItemModel, and an item of that model gets changed outside of the list window, and we would like to update the list with the change. What is the usual strategy to achieve something like this ? I've looked at the Qt documentation of QAbstractItemModel and there is a signal named 'dataChanged' that is (or should be) emited when data from the model changes. But since this signal (as all QAbstractItemModel functions/signals/slots) work with a QModelIndex, which is not persistent as the documentation clearly says, am i supposed to store somehow a mapping of my data to QPersistentModelIndex(es), so when my data change i will be able to find the corresponding QPersistenModelIndex and use that as argument to the various QAbstractItemModel functions ? Is that what QPersistentModelIndex(es) are used for ? Or am i missing something ?
Thank you.
ps: I guess i could just reload the QTreeView, but then i wouldn't know which items were expanded or which were selected. Is there an strategy to overcome this problem and just reload the list ?
QTreeView already handles the case in which the underlying model's data changed (i.e. the model has emitted the dataChanged() signal). That means you don't need to do any additional work on the view.
If you're implementing your own model (a derived class of QAbstractItemView), and you're making a change to the contents of the model, you simply need to emit the dataChanged() signal when your change is complete. The signal/slot mechanism will automatically inform the view using that signal.
Related
I am trying to do the following in QT, but I'm unsure of how to do it, or even do it efficiently.
Any input would be greatly appreciated.
I have a QListView and an underlying model that I implemented myself.
The rows of the model include another class "CJTAGPin" which determine the data.
In the rows of the ListView I only need to display certain elements of this class, which works just fine.
In the same window, I have a QTableWidget, where i want rows of the Listview to be allowed to dropped.
But in this Widget, the name displayed in the List ist not enough,
and I would need the instances of "CJJTAGPin" accessible (when pressing a button accessing the cells where Objects were dropped and knowing which instance of CJTAGPin it is).
How can this be achieved?
I already did some research and found that subclassing QMimeData would be an option, but I'm not quite sure which Class I would need to be subclassing and how to rewrite hasFormat(), formats(), and retrieveData().
Im developing a Qt GUI application, with multiple QDialog's open at any given time.
These dialogs need to communicate and notify with each other when special data is received on a separate network thread.
Usually a dialog will hold a reference to at least one other dialog, and thus can communicate using this.
My question is whether to use this reference to call a function in a another dialog, or emit a signal and absorb that signal in a slot in another dialog? Im aware that this might be a preference - but I would still like to get some input on this.
I suggest you start by looking at Qt's Model View Programming. Based on the Model View Controller design pattern, you would be better off separating data (the model) and the view of that data.
If you follow Qt's Model View Programming, you'll find that when the model containing your data changes, the view(s) are notified and react accordingly. You shouldn't need to message from one dialog to another.
I have a Qt C++ application that uses several different models (ultimately) based on QAbstractItemModel.
Several of the items in these models use a custom Delegate to render them properly, these work well.
However, I'm not sure how best to specify which of these Delegate classes should be used to render the data.
At present, I'm calling QAbstractItemView::setItemDelegateForColumn() in each of the forms that contain a view.
This feels very clumsy, because it relies on the form classes knowing which delegate should be used for each column in every model - and if that changes in the future, I have to update every form.
Furthermore, in some cases a View is switching between two different models that require different Delegates, so for these the form class has to handle that switch as well.
Is there a better way to do this?
The model must not know about representation, so you should deal with the view. You can subclass involved view class (e.g. QTableView) and reimplement setModel virtual method. In your implementation call the parent class implementation and adjust item delegates based on specified model. Put objects of this class inside all your forms. So forms will not know about delegates. I think this approach agrees with the Model-View conception.
AFAIK, there's no better way.
However, instead of updating manually every form, i used to have an enum which holds the columns index, which is used both in the model and in the view to retrieve data and apply delegates.
I just read the Model/View documentation for Qt 4.8. I believe to understand how the Model/View (Delegates/SelectionModel) work. One thing that I'm unsure about is how to manipulate data when I have a for example a TreeView.
Imagine having a TreeView to display a list and buttons to remove elements from this list when an item/row is selected. I see two approaches here
1) In the slot of the PushButton I retrieve the SelectionModel and the ItemModel of the TreeView and call model->removeRow(index.row ...). This way the model (that i subclassed from QAbstractItemModel) manipulates the data that it is supposed to represent.
2) In the slot of the PushButton I remove the item directly from the data source, that the TreeView's model represents. Then I can link the data with the model via signals/slot, such that the model can then tell the TreeView that the underlying data has changed.
The same scenario can be imagined with adding elements. Should I add the new element to the data which signals its changed state to the ItemModel which the informs the TreeView, or should I add the new item through the ItemMode?
I haven't found any Best Practices documentation on this. The two approaches differ strongly, such I would like to know in advanced which one is preferable.
Does anybody have a suggestion which path to follow?
Thanks
1) is preferable - you should probably avoid manipulating your data source directly from the UI code - your life will be better if you go through the model. At the very least add a method to your model to do the data manipulation, and call that method from your UI code.
You will find that some of Qt's methods are protected such that they can only be called from the model itself (e.g. endInsertRows etc.)
I've been learning about subclassing and widget promotion in Qt Designer and I've promoted some QPushButtons. My promoted class represents the number keys on a calculator, and takes a parameter in the constructor. The parameter given is the number of the button and it is passed in as an int.
Is there a way to tell Qt Designer how to construct each button? The constructor needs the numbers 0-9 passed to it. If I manually modify the generated code it works; however, each time it generates the form, I have to manually edit it.
There is no simple way to achieve this while keeping your argument in the constructor I'm afraid (read this page in the docs to how you might go about it).
I think your best solution is to keep the constructor mirroring that of QPushButton (i.e. just passing a parent QWidget) and set your custom data by calling a function afterwards.