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.
Related
I need to write a QAbstractItemModel class that represents a hierarchy of different object types. I want to be able at some point, show a table/list containing only level 1 elements, only level 2, and so on.
I am working on a network protocol analyzer tool, something like wireshark. I am capturing socket.recv and socket.send events from a process. In my model those events are called NetworkEvent. Each network event may contain one or more Packet. Each packet has one or more Message, where a message, based on its code, is parsed as a defined struct.
Here is an image of the program class hierarchy:
The main window has a list and a tree. I expect to be able to show:
a table/list containing only network events including its attributes.
a table/list containing only packets including its attributes.
a table/list containing only packets based on a network event.
a tree containing a packet/message hierarchy (with fields and sub structures)
a table/list containing only messages
a table/list containing only messages based on a packet
a tree containing a message hierarchy (with fields and sub structures).
So I thought the best idea was to model the QAbstractItemModel as a tree. First problem I encountered is that while each class has the concept of "children", each one has a different field that represents childrens, so I have to take care of that inside the QAbstractItemModel.
Also, because a table/list of EventNetworkdoesn't have same columns as table/list of Packet, nor Message, I can't properly use the same model to define all possible ways to show the data. I suppose the correct way to do this would be defining proxy models for each kind of view.
Is there any better or easy way to approach this? Or is this the way to go?
So you create a common base family of polymorphic classes, and use a base pointer as the data source for the model. One single role - the data object, from then individual delegates can access their specific data fields without having to bother implementing everything using roles. The role-centric use-case is really only applicable for isomorphic data sets.
Then you can customize the visual representation based on the actual individual object and view type.
I wouldn't marry to any particular representation. I'd only implement a list interface, this gives more flexibility how to represent the structure, you can draw simple lists as list view or table view, and you can also have tables or trees that are made of lists of lists.
In programming, it is always a tree, which is very obvious if you structure your application well, so it is a simple manner of choosing how you visualize each node and its contents. It is common to even have different ways of visualizing the same data, both in terms of visual structure and actual delegates.
You will have a tremendously easier time implementing this in QML, especially the actual visual representation, using the generic object model outlined here. Although if your object count is very high, you might want to implement it as a single abstract item model rather than have every object be a list model to avoid the overhead. But unless you deal with millions and millions of items, the overhead is well worth the return.
I think you are on the right course with thinking of using multiple proxy models, one for each table. I would suggest starting with QSortFilterProxyModel and implement your own filtering algorithm.
I will also suggest you might want to identify the type of data with using custom Qt::ItemDataRole enumerations, one for each type. I think it will make the filtering easier.
You may want to experiment with List, Table, and Tree Views to see which suits your purpose the best. The beauty of the Model-View system is you can easily change the View once you have the model(s) down.
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 am building a Custom SSIS data flow control which will provide three out put flow based on some rules validation. Please help me what exactly I need to implement in ProcessInput method to redirect data in these three output based on the some logic applied on the input
If I understand correctly, I think you want to route each 1 of the 3 outputs from the Custom Control component shown in your data flow, to various different destinations based on conditions. For that, you could use a CONDITIONAL SPLIT Component as shown below.
You can split the input into 2 or more row streams by giving the CONDITIONAL SPLIT various conditions that look at column values etc.
If my understanding is incorrect, then please update your question with more details on your situation.
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 :)
Here's my use case (very simplified).
I have some data from DB in QSQLTableModel and I need to transform it: merge few fields into one (and display as such) or split one field into few. How and where this should be done in Model/View?
Notes:
I tried using AbstractProxyModel to do this, but I guess, it's suitable only for filtering or sorting. I could allocate new data and return QModelIndex (which carries the pointer to the data) but which object should deallocate the data later?
Modifying the View object also wouldn't help because it processes every table cell separately.
Mind that I can't alter database in any way.
How to do this in Qt? I already spend two whole days on this only to run into one wall after another.
Using QAbstractProxyModel isn't the wrong approach, you can use it to map any kind of source model to restructure the data. But it will be a lot of work, you have to re-implement several methods, including columnCount, data, flags, index, and more. In effect, you have to make sure that the indexes of this model map to the correct data of the source model. Also, if you have a dynamic model, then you will want to handle signals coming from the source model, modify the values and re-emit them. If you want the view to edit the data as well, then you'll have to re-implement setData, etc.
For example, if you have a column that has two values appended, and you want to display them in two separate columns, then columnCount should return one extra, data should retrieve the original data and return only one part based on the column in the index, index must be modified to check the new bounds of this model, etc.
If you want more specific help with this, then please post some example code.