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.
Related
I see references to "best practice", but why is it better to use a ViewBag object versus an Application object when accessing static data in the view?
Both are possible. Suppose you want to add an object to every view but not necessarily pass it to view the model (since there may not even be a model for a given view)?
This could be done several ways, like with a global filter, but accessing an application variable is much more convenient.
Both are nasty workarounds that bypass everything that MVC stands for.
In the Model-View-Controller pattern, your Controller prepares a Model containing all values necessary to populate the View, and the View in turn displays the Model properties the way it's intended to.
Any way you use to circumvent that pattern, like ViewBag, Session or Application variables, are anti-patterns that defeat the MVC way - as long as you access those variables directly from the View.
See also Pass data to layout that are common to all pages and Create ViewModel for Navigation: if you need certain values on all pages, consider using a base viewmodel or partial views.
And yes, this discussion borders on pragmatic/purist. If you for example have a menu that's the same for every user, but which is loaded from a database, then sure, go ahead and store it in an Application variable for caching purposes to load it once per AppDomain. But then still use a base ViewModel or Partial to render that menu.
I wouldn't say putting data in a view bag is a best practice. I would say using a view model is a best practice.
Suppose you want to add object to every view but not necessarily pass
it to view the model (since there may not even be a model for a given
view).
Even if you haven't define a view model, conceptually there is a model is you are passing data to the view.
See Why do we use ViewModels?
If the data is on every view, you could create a base view model that every model inherits from that contains the universal data.
you could also create a partial view with its own view model that is then applied to each page.
Normally I design ViewModels taking in consideration the business or functional concepts of the application.
For example, if you are displaying an invoice, the view model should contain all the properties related to invoices that needs to be displayed on that specific view. I wouldn't use ViewBags/ViewData for this purposes.
On the ViewBag I normally put other and "more ancillary" properties like, for example, a boolean for showing/hiding some part of the view, or maybe for some other "not business relevant" properties.
Of course some people could disagree with this and would put everything on the Viewmodels, some others not. This is a decision you must take at the beginning so you can be consistent in the way you design across the application.
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.
I have a checkbox in a Flex DataGrid, and when I scroll, other rows are randomly checked/unchecked.
After reading over: Creating a column of RadioButtons in Adobe Flex
it's clear that the itemRenderers are getting recycled, but the problem I have with the solution presented there is it moves info about the view into the model.
Does anyone have a better way of solving it, that doesn't force me to put information for the UI into my actionscript model classes? (in my case, I am converting incoming XML data to actionscript classes, and these are getting bound to my datagrid).
Thanks for the help.
thanks everyone. great tips. unfortunately it was becoming too much overhead to keep the model pure, so i just polluted the model like the link in my original post. :( at least it works.
Chetan, neat idea.. i tried working with this for almost an entire day with no luck though.
brd6644, good thoughts on separating the two model classes.. i might go back and do this later.
You could create a subclass of DataGrid that internally stores what rows are checked/unchecked (Array/Collection of Boolean) but you would have a devil of a time keeping that in sync with the dataProvider when it is sorted or filtered. I suppose you could use a Dictionary that is keyed by the object in each index of the dataProvider and valued with a Boolean to indicate whether it's selected. That would at least isolate you from the sorting / filtering issues. This will not work if you have duplicate references in your dataProvider.
Alternatively, you could create a subclass of your ActionScript model class and add the "selected" property to it, then write some simple utility methods to "convert" between the two. That way your View deals only with the "ViewModel" class and other layers (especially the server side) deals only with the real "Model" class.
Adding to what cliff.meyers said, there is a third option of creating a custom IList class as described in this blog post by Alex Harui. It is pretty clever actually, and is cleaner as it doesn't require subclassing the component or polluting your model classes.
I was wondering best practices for views of inherited classes in PureMVC in this situation:
Multiple classes inherit a BaseClass (lets say InheritedClass1 and InheritedClass2)
Each InheritedClass has a respective view (derived from a base view class, but each unique)
With a given dataset (lets say ArrayCollection of InheritedClass1/2 Objects), the respective views need to be dynamically loaded.
The dataset is relatively large, so a TileList would be nice (since it only instantiates objects which are currently displayed)
I can think of a couple solutions, but I find them to be too "hackish" to be the best solution:
In View: Repeater over a BaseClassView which attributes a view to a State (set to the "InheritedClass1" state to add a InheritedClass1 object)
Pros: No unneeded memory increase (States' objects are instantiated when needed)
Cons: View is dependent on the data types, so adds coupling
In Mediator: Loop over the ArrayCollection and addChild() the views based on data type
Pros: Works.
Cons: Mediator is adding things to the View, which defeats the point of the separation of Mediator and View. Slower than a Repeater.
Any comments or other suggestions would be appreciated. Thanks!
The answer is simple if you like the first example. Why not have a map (Object()) on the mediator that assigns datatype to view component (or states). e.g.:
private static var map:Object = {"ic_oneType": "ic_oneState",
"ic_twoType": "ic_twoState"}
And the mediator can assign that map to the BaseClassView.
I'm likely to agree with the idea that you need some form of viewProxy that renders all your inherited views based on data fed to it from the mediator (e.g., first example). Can confirm or deny whether states is the best course of action in your UI though without more concrete examples.
Mediators are part of the View. How would you separate them from the View is beyond me.
I'd got with option 2.
Here's a topic from the pureMVC forum: Dynamically adding View components: where should I do it?.
The post by "pureMVC" should be of interest to you.
Also, the size of the dataset can be problematic. If it's really large you should consider using a List with renderers instead of adding a component for each item (repeaters do that). Which would further complicate things a bit because you'll have to wrap your data to keep the main component decoupled of the Model.
Cons: View is dependent on the data
types, so adds coupling
Typically, a view component has no other purpose than to display the domain data and possibly allow the user to interact with it. It is a given that the view component will need to have some understanding of the domain data.
So feeding a collection of VOs to your view component doesn't add a 'bad' coupling. A 'bad' coupling is when the view component knows about how to reach into the Model tier and manipulate the Proxy that holds the data. Or when the Proxies in the Model tier know how to get their hands on the view components or their Mediators to poke data into them.
Mediator is adding things to the View,
which defeats the point of the
separation of Mediator and View.
As Coded Signal pointed out, we're not trying to separate the Mediator from the View component. The Mediator is the one actor in the PureMVC system that should know the view component, and mediate the communications between it and the rest of the system. The Mediator is the most critical actor in the system with regard to loosening the coupling between the View tier and the Model tier.
To communicate with the view component, other actors send notifications, which the Mediator hears and responds to by manipulating the view component's exposed API; spoonfeeding it data or invoking methods on it. This effectively keeps the rest of the app from needing to know anything about the component.
The Mediator also listens to the component for events and acts on its behalf, retrieving data from the Model tier, or sending notes to to other Mediators or to trigger Commands in the Controller tier. This keeps the component from having to know anything about the system it is connected to. It simply exposes an API of properties and methods, encapsulates its own behavior and sends events when things happen that the system should know about.
So together, the Mediators and View components make up the View Tier of the application.
-=Cliff>
Cons: Mediator is adding things to the View, which defeats the point of the separation of Mediator and View
Not really: they're what the documentation refers to as a collaboration pair and should be treated as such.