The document discusses applying the presentation model design pattern in Qt style. It describes the challenges of complex user interfaces that mix C++, QML, and JavaScript. It proposes using the presentation model pattern to separate the presentation logic from the view and business logic. The presentation model would be defined in QML to take advantage of its declarative nature, while synchronizing with the C++ business logic using signals and slots. This allows pulling functionality out of the view while still leveraging QML/JavaScript expressiveness. An example log viewer application is presented to illustrate how this pattern can be implemented.
If we go out to the street and ask what’s makes an application really awesome, I’m sure most of the answer we get refer to the graphical interface: how fancy it is, colors? Touch, multi-touch? It’s fast or slow?
That’s because the interface is the part of the software we see and touch. Software is immaterial, but the interface give us the possibility of trespassing that border and interact with devices.
So, if we say the interface is was makes an application awesome, here is the next question: What makes a graphical interface awesome?
If we go to the books (or wikipedia) we can see there is some guidelines about how a user interface should be.
I would summarize it saying it has to be: Functional, easy to use and pretty.
So that’s it!
Well,.. It’s not that easy.
All of us that had ever deal with the problem of programming a professional user interface have come across a bunch of technical problems:
If we are developing in Qt – and most of us do, or we wouldn’t be here now- we have to deal with different languages, like C++ and QML. That’s not a problem by itself. On the contrary, it give us great flexibility. But there is some issues we can run into:
Where to place common functionality? How to keep a clean separation between widgets (or QML component ) and our business logic?
What we see in the slide is a classical architecture in layers of a application. It contains some infrastructure functionality in the lower layer. Here is the logic responsible for thing like persistence, networking, an so forth.
In the middle we have the business logic. Here is where we place the internal data structures and the algorithms. Where we keep the consistency of the data. If a Model Driven Development, here is where we place the model.
On top of that, the views. That’s the visible part. Where we display information and react to user actions.
In those applications were the user interface plays a central role, the amount of code we need for fancy animations AND color transitions AND scrolling list AND transforming data for better display, etc., can lead to big, messy overweight views.
Fortunately, there is a solution for this that has been around for a while: the Presentation Model
The idea of the presentation model is adding a layer between views and business model and pull information out of the view in order to keep them thin and tidy.
What can we move out of the view? Well basically the state and the routines for data manipulation.
Advantages
The model can be shared between several views.
Common place for shared functionality.
Models are usually easier to unit-test than views.
Pull the state out of the widgets. Stateless views are easy to maintain. Let the model make the decision based on the state.
But it also have disadvantages : We’re adding another level of indirection, which means more complexity. We need a way to keep the layers synchronized.
Fortunately, there are some features in Qt we can use to make our live easier:
We’ll keep the business logic in C++ and code the model in QML, because the model is closer to the views than to the layer underneath. However, we’ll use the Qt signals and slots as well as property binding to synchronize between layers.
This is an example of a log viewer. The idea is quite simple: The window pops up and shows a list with the latest logs from the system. We have two kind of logs, critical –marked in red- and non-critical –in blue-. At the top we can choose to display all the logs, or just the critical ones. The amount of logs currently displayed is part of the main window’s title.
A simple implementation could be having a main window with a ListView and getting the log from the system by asking the C++ classes in the business logic directly. Then, is up to the View to decide whether to show all the logs or just the critical ones, based on the status of the filter.
For this simple application, that’s definitely good enough. But imagine a more complex context. Imagine the want to enable some functionality if critical logs are present. A view to report an incident, for instance. This second view must be aware of the filter status and have access to the logs in the ListView to in order to get the information to make the report.
As you see, we can end up with high coupling between views. And that’s not a good design.
Applying the Presentation Model to this problem can be something like this: We create 2 different QML components. The one in the left still has a ListView and a couple of buttons, but the state of the filter and what should be displayed whenever the filter changes, is up to the component in the right, which is the model.
Basically we divide the responsibilities: The model decides the “what” to display, and the view the “how”.
In this example, each time the model get new logs from the system emits a signal “Model Changed” and the view updates. In the other ways, when the filter changes the view updates the filter state in the model and retrieves the logs to display. The amount of logs displayed is a property of the model, and bound to the Main windows’ s title. So the QML engine takes care of the synchronization for us.