My application is a tool library manager. It has a treeview containing a list of lists and tools. It also has a tableview showing a list of tools.
When I click on a list in the treeview, I want to show the tableview with the list of children. When I click on a single tool in the tree, I switch widgets and display the editform for the tool.
How do I limit the tableview to only the children of the selected node in the treeview?
My data model is a custom qAbstractItemModel.
I have a similar situation (not quite the same!) as yours. Before I share my experience, my assumption is that you have a database of sorts which consists of the items that make up your lists/tools.
One possible solution is to create two custom models, one for the tree view (say, MyTreeViewModel -> QAbstractItemModel, associated with QTreeView) and one for the table view (MyTableViewModel -> QAbstractItemModel, associated with QTableView).
The two custom models should be fed by the same agent working with the database. The key difference is that the tree view model works with the entire database, and the table view model with only a subset, that is, the children of the chosen item in the main list. Think of it as full mapping v. partial mapping of the database.
When the user clicks on the top list of nodes in the tree view, you can emit a signal which could be picked up by MyTableViewModel, populates with only the children, and is displayed by QTableView.
Because the same agent serves both models, you should be able to maintain data integrity, in the sense changes to the underlying data by one model should be reflected in the other model. This solution has worked out really well for my application. Hope this works for you too!
I'm not sure if this is a complete answer to my own question but I'm much closer. On the tableview I can call setRootIndex() and pass in the current item from the qTreeView. This works to show only the children of the current tree item in the table list.
For me, it still shows both tools and child lists, which I want to filter, but I think that's a different issue.
Related
I'm learning the Model/View paradigm of Qt because it seems very well suited to edit the data structures I have to deal with, such as this one:
Addition
|_QuadraticFunction
| |_intercept=0.2
| |_slope=0.0
| |_quadratic=1.2
|_Multiplication
|_LinearFunction
| |_intercept=0.0
| |_slope=-8.9
|_Gaussian
|_center=0.6
|_sigma=0.4
My data structure is made up of a combination of functions, each function has its own properties. However, I don't want to display the whole data structure in a single TreeView because it can get too long for complicated structures. Instead, I want to show one view including only the function names, and other view showing only the properties of the function selected in the previous view by the user with a click of the mouse, like this:
(FunctionsView, the first View)
Addition
|_QuadraticFunction
|_Multiplication
|_**LinearFunction**
|_Gaussian
(selectedFunctionView, the second View)
intercept 0.0
slope -8.9
In this example, the user clicked on LinearFunction in the first View, and the second View automatically showed its properties.
My question is: can I hold all my data structure (function names and function properties) under a single model and then have two Views that display only parts of the model like above? If not, do I have to create one model for each partial View, each model indexing different parts of the data structure? Please help, I'm inexperienced with this.
.Jose
Yes, you can absolutely keep it all in one model with two different views. You'll probably want to look into a QSortFilterProxyModel; you would have one of these for each view. The proxy applies sorting and filtering--and filtering is what you're doing here--to a more complete model. When you select something in the main view, you'll want to issue a signal that's picked up by the other proxy model (or the other view and passed to its proxy), and then refilter based on the newly selected item. It's actually very easy to use overall. The easiest mistake to make is getting confused over which model index to use because you'll have model indexes for the proxies, and model indexes for the complete model, and sometimes you have to convert between the two. The documentation is pretty clear on where that's necessary, but it helps to be extra aware of it.
Take a look at the documentation and if you have more questions, please ask.
I'm currently building a model view architecture and came across an issue I can't find information on across the internet.
I have one set of complex data, that I want to show to the user in two (or more) different fashions :
full data is shown
only selected (partial) information in shown
The way this data is printed is to me irrelevant, but if this help it's either in a table view (basic information) or a column view (full information). those two clases comes from QT model / view framework.
Now I though about two option to implement this and wonder the one I should use
Option 1
I build my data structure,
include it in a custom model
specialize (subclass) view classes in order to only print what I'm interrested in.
Option 2
I build my data structure,
specialize my models to only provide access to relevant data
use standart view to print it on screen.
I would honestly go for option 2, but seeing the amount of case over the internet where option 1 is used I started to wonder if I'm doing it right. (I never found any example of dual model of a data when multiple view of a model appears to be quite frequent)
Placing data relevant handling inside view classes seem wrong to me, but duplicating models of a data leads to either duplicated data (which also seems wrong) or shared data (and then model no longer 'hold' the data)
I also had a look on QT delegates, but those class are mostly meant to change the appearence of data. I didn't find a way using delegates to ignore the data that is not relevant for one view.
You are completely right thinking that it's wrong to use views for filtering data. The only reasons for reimplementing a view is to have a different view of the same data or special processing of user events.
So there are two ways to filter out a data:
1.Create two models which will share the data. It's a standard recommended approach - not to keep data in models.
2.Create one model providing all the data and create a proxy model inherited from QSortFilterProxyModel to filter out the data.
You will need to reimplement filterAcceptsColumn method to filter out columns and filterAcceptsRow to filter out rows.
Then use View-Model to show all the data or View-Proxy-Model to show some data.
I am just starting out with mobile development and the data handling for Flex mobile applications seem to be plain horror. I have spent two days on it, tried about 10 different approaches and still can't find a clen working solution.
So i have a TabbedViewNavigatorApplication with many views and subviews. All of them should be able to access the same data that i want to store in a model (so basically they need to access the same model class to add, edit and retrieve some data from there).
I create one instance of a model, pass it as data to all view stacks
If i change something in one view stack and switch to another one, i see the changes and all is fine.
But if I change the model data in one view and restart the application, I see changed data in that view but if i switch to another view, it has the old (unmodified) model. I would assume that the model would be the same instance but apparently each view has its own "model" when saving persistance data.
So how do you manage shared model over all views ? Ideally i would create it once on the first app launch, and then just add / remove items from any view or subview.
Or do i need to use the SQLite for that ? In this case it seems i would need to fetch the data for each view each time a view changes to stay up-to-date with the current data in the database ?
Please help :)
I am trying to drag and drop hierarchical data in the same advanced data grid, and I would like the data provider to updated when the ADG is updated. (I want to be able to save and load this tree, so it is important that drags and drops are saved.)
I have a sample application (with view source enabled) posted here: www.crcarlson.com/adg/AdvancedDataGridDragAndDrop.swf
The sample app has an ADG showing hierarchical data as well as flat data. The first column of each datagrid shows the rowindex of the underlying data.
If you rearrange the items on the left ADG, the row indexes become unordered. If you click traceTree you see that the data provider is not in order.
On the other hand if you do the same on the right, the row numbers stay ordered even when the objects move around and if you click traceFlat, the data provider is in the order shown on ADG
My goal is to have the data provider order match the ADG order for the left grid which is displaying hierarchical data.
I would appreciate any advice on this, including "you can't get there from here, do it this way."
I noticed a few things while perusing your code and using the app:
Use an ArrayCollection instead of Array as the dataProvider for a view component whose data changes. This might solve your update problems.
If implementing an ArrayCollection doesn't completely solve your update problems, add the necessary logic to a dragDrop or dragComplete event handler.
I get a runtime error every time I drag an item from adg to adgFlat.
Here's Adobe's take on Using Drag and Drop. Specifically check out the last page titled "Moving and copying data". Good luck to you.
What I'm trying to do is have a 3 state tree expansion.
I have three different icons for "expand" "collapse" "semi-expanded" which I want to use to show a partially populated tree control with all nodes initialized to semi-expanded state and then on clicking the "semi-expanded" icon it gets data from server and populates the tree and open that branch with "expanded" icon.
I tried looking for it but couldn't find anything close to it except the 3-state checkbox but don't know how to use it on 3 state icon when tree would only maintain 2 states.
Thanks in advance.
I think what you are looking for is called a lazy-loading tree. There are lots of examples your can google for, but here is a great example.
As far as the visual part of your request goes (3 different icons to show that state of the branch or node) - you could easily handle that with a custom renderer, by looking at a flag on the node for it's load status.
Does that help?
A 3-State tree control is a bit uncommon and might therefore be a bit confusing; consider that even simple 3-state checkboxes are relatively rare and users may not be accustomed to them. Maybe that's why you didn't find such a tree control.
Thus, maybe you should consider using an alternate design that doesn't require 3-state controls.
For example, the node could start in collapsed node. If the user expands it, and there is no data yet, show a single sub node with the text "retrieving data..." (and a progress wheel or other progress indicator, if you can) and start data retrieval. When the data arrives, replace this sub node with the actual data.