Mastering MVC
Now that our solution structure is in place, we’ll get started on the MVC implementation. As you’ll see, it is very minimal and incredibly easy to set up.
First, expand cm-ui > Resources > views.qrc > / > views, right-click on main.qml, select Rename, and rename the file as MasterView.qml. If you get a message about project editing, just select Yes to continue anyway:
If you do get the error message, the file will still appear as main.qml in the Projects pane, but the file will have been renamed in the filesystem.
Next, edit views.qrc (right-click on it and select Open With > Plain Text Editor). Replace the content as follows:
<RCC> <qresource prefix="/views"> <file alias="MasterView.qml">views/MasterView.qml</file> </qresource> </RCC>
If you recall how we load this QML file in main.cpp, the syntax is qrc:<prefix><filename>. We previously had a / prefix and a views/main.qml relative filename. This gave us qrc:/views/main.qml.
A prefix of / isn’t terribly descriptive. As you add more and more QML files, it’s really helpful to organize them into blocks with meaningful prefixes. Having unstructured resource blocks also makes the Projects pane ugly and more difficult to navigate, as you just saw when you had to drill down through views.qrc > / > views. So, the first step is to rename the prefix from / to /views.
However, with a prefix of /views and a relative filename of views/main.qml, our URL is now qrc:/views/views/main.qml.
This is worse than it was before, and we still have a deep folder structure in views.qrc. Fortunately, we can add an alias for our file to make both of these problems go away. You can use the alias of a resource in place of the relative path, so if we assign an alias of main.qml, we can replace views/main.qml with simply main.qml, giving us qrc:/views/main.qml.
That’s concise and descriptive, and our Projects pane is neater too.
So, going back to our updated version of views.qrc, we have simply updated the name of the file from main.qml to MasterView.qml, consistent with the file rename we performed, and we have also provided a shortcut alias, so we don't have to specify views twice.
We now need to update our code in main.cpp to reflect these changes:
engine.load(QUrl(QStringLiteral("qrc:/views/MasterView.qml")));
You should be able to run qmake, and build and run to verify that nothing has broken.
Next, we’ll create a MasterController class, so right-click on the cm-lib project and select Add New… > C++ > C++ Class > Choose…:
Use the Browse… button to create the source/controllers subfolder.
By selecting QObject as the base class and including it, Qt Creator will write some of the boilerplate code for us. You can always add it yourself later, so don’t feel like it’s a necessary part of creating a new class.
Once you’ve skipped version control and created the class, declare and define it as follows. Our MasterController doesn’t do anything particularly exciting just yet, we’re just doing the groundwork.
Here's master-controller.h:
#ifndef MASTERCONTROLLER_H #define MASTERCONTROLLER_H
#include <QObject> #include <cm-lib_global.h>
namespace cm { namespace controllers {
class CMLIBSHARED_EXPORT MasterController : public QObject { Q_OBJECT
public: explicit MasterController(QObject* parent = nullptr); };
}}
#endif
All we’ve really added to the default implementation Qt Creator gave us is the CMLIBSHARED_EXPORT macro Qt Creator wrote for us in cm-lib_global.h to take care of our shared library exports, and to put the class inside a namespace.
This is master-controller.cpp:
#include "master-controller.h" namespace cm { namespace controllers {
MasterController::MasterController(QObject* parent) : QObject(parent) { }
}}