diff --git a/README.md b/README.md index e00d9be..aaff763 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,31 @@ ## Introduction -This is minimal program that uses QtQuick library for creating user interface -and using CMake as build system. The application created is simple in design and -consists of sole window. +This guide aims to create a simple Qt application with Qt Quick graphical user +interface. The tutorial uses CMake as the project format and C++ as the language +of source code. The application created is simple in design and consists of sole +window. -## Built With +QtQuick is a user interface library that provides ways to create declarative +user interface separated from the programming logic. It's framework is +implemented as a part of the Qt library set. QML is a user interface +specification and programming language. -Compiling and running the project requires GCC, CMake, GNU Make -and Qt development libraries with Qt Quick enabled. +CMake is the project generator for many platforms and build systems. CMake uses +the unified file format and is able to generate makefiles, Visual Studio +solutions and projects for many other build systems from the same project file. -* [CMake](http://cmake.org/) - Build system (>=2.8 is required). -* [Qt](http://www.qt.io/) - Cross-platform library (>=5.7 is required). +## Prerequisites -## Dependencies +Compiling and running the sample project requires GCC, CMake, GNU Make and Qt +development libraries with Qt Quick enabled. This tutorial specifies the way to +install pre-compiled packages from the standard repositories. -Install the following packages to prepare the build. +## Environment Setup -### Ubuntu & Debian +### Debian-based Systems + +The following instructions are applied to these operating systems: -The following instructions are appliable to: * Ubuntu 16.04 * Debian 9 @@ -32,7 +39,12 @@ sudo apt-get install -y \ qml-module-qtquick-controls ``` -### CentOS 7 +### RedHat-based Systems + +The following instructions are applied to these operating systems: + +* CentOS 7 +* Fedora >=22 ``` sudo yum groupinstall -y "Development Tools" @@ -44,21 +56,240 @@ sudo yum install -y \ qt5-qtquickcontrols2-devel ``` -### Fedora >=22 +## Directory Structure + +The directory of the project is laid out as follows. ``` -sudo dnf groupinstall -y "Development Tools" -sudo dnf install -y \ - cmake \ - qt5-qtbase-devel \ - qt5-qtdeclarative-devel \ - qt5-qtquickcontrols \ - qt5-qtquickcontrols2-devel +$ tree +. +├── CMakeLists.txt +└── src + ├── CMakeLists.txt + ├── main.cpp + ├── main.qml + └── qml.qrc + +1 directory, 5 files ``` -## Build Project +All source files for the project will go in src and main project specifications +in CMake format are in the `CMakeLists.txt` file. Larger projects tend to be +organised in sub-directories for modules, executables and libraries, each with +its individual sub-directory and `CMakeLists.txt` file within. -Call the build of the solution and launch the application: +## Main Window GUI File + +Start with declarative file for user interface that is specified in the file +`src/main.qml`. The code creates a small window without any controls. + +[src/main.qml](https://github.com/apriorit/MinimalQml/blob/master/src/main.qml) + +Necessary modules are imported. The exact version of the `QtQuick` library is not +the same as the version of the Qt framework used. `QtQuick.Controls` library +contains some basic controls for the user interface. + +``` +import QtQuick 2.0 +import QtQuick.Controls 1.0 +``` + +Main application window is represented with the `ApplicationWindow` control in the +Qt Quick library. + +``` +ApplicationWindow +{ +... +} +``` + +There are four attributes of the main window that specify the size and title of +the window. The `visible` attribute is required to specify that the window should +be shown in the screen right after launch. + +``` +visible: true +width: 640 +height: 480 +title: qsTr("Minimal Qml") +``` + +## QML Resource File + +This is the QML resource file for the application that consists of sole QML file +named `main.qml`. The file is XML with `RCC` element as root and `qresource` as +element for group of resources. This project contains only one group that is the +root (i.e. `/`). Larger projects may contain additional qresource elements for +each resource subgroup (e.g. `customControls`, `customWindows`, etc.). + +[src/qml.qrc](https://github.com/apriorit/MinimalQml/blob/master/src/qml.qrc) + +## Application Code + +The main entry point of the application provides the C++ code for displaying Qt +Quick user interface. + +[src/main.qml](https://github.com/apriorit/MinimalQml/blob/master/src/main.cpp) + +Standard object for Qt application is constructed. + +``` +QApplication app(argc, argv); +``` + +Here the QML parsing object is initiated for the application. This object +receives the string with address of the main QML resource as the construction +parameter. In this case `qrc:/main.qml` is the address specified in the `qml.qrc` +file. `qrc:` is the default prefix for the QML resource, `/main.qml` stands for +resource named `main.qml` in the root resource directory (`/`). + +``` +QQmlApplicationEngine engine; +engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); +``` + +The `exec` method starts Qt application. + +``` +return app.exec(); +``` + +## Project Files + +This section shows deployment of Qt Quick application using CMake project +format. + +This is the main project file. The first line sets the minimum version of CMake +for the project. It includes Qt5 framework into the application and concludes +with the further inclusion of the src subdirectory so that CMake would search +for the project file (`CMakeLists.txt`) there. + +[CMakeLists.tst](https://github.com/apriorit/MinimalQml/blob/master/CMakeLists.txt) + +This is the project file for the executable. + +[src/CMakeLists.tst](https://github.com/apriorit/MinimalQml/blob/master/src/CMakeLists.txt) + +The header files of the Qt project should be included into the project so that +makefiles generated will have them specified in the corresponding compilation +commands. There Qt5Widgets stands the header files for the Qt Framework and +QtQml invokes special files for QML functions. + +``` +include_directories(${Qt5Widgets_INCLUDE_DIRS} ${QtQml_INCLUDE_DIRS}) +``` + +The definitions as well as Qt include files should be specified in the makefile +compilation commands. + +``` +add_definitions(${Qt5Widgets_DEFINITIONS} ${QtQml_DEFINITIONS} + ${${Qt5Quick_DEFINITIONS}}) +``` + +The Qt framework requires the code to be created from the Qt resource files. +This is achieved using the special `qt5_add_resources` command. The QML resource +file path relative to this file is passed as an argument here. + +``` +qt5_add_resources(QT_RESOURCES qml.qrc) +``` + +For Qt projects with graphical user interface the compiler should receive +special parameters for compilcation + +``` +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") +``` + +Qt programs require several additional compilation steps for [moc](https://doc.qt.io/qt-5/moc.html), +[rcc](https://doc.qt.io/qt-5/rcc.html) and [uic](https://doc.qt.io/qt-5/uic.html). + +``` +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +``` + +The name of the project that will be used as a name of the compiled executable +is specified using the set command that receives the name of a variable (i.e. +`PROJECT`) and it's value. + +``` +set(PROJECT "MinimalQml") +``` + +The project command sets the current project within the CMake file. It receives +the value of the variable defined above. + +``` +project(${PROJECT}) +``` + +The compiler flags for compiling C++ sources are set below. These flags stands +for very strict compilation rules and help to detect and locate a lot of +potential issues during compilation. + +``` +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++11 + -fstrict-aliasing -pedantic-errors -pedantic -Wno-deprecated-declarations + -Wno-unused-variable") +``` + +There are conditional commands in the CMake project language. The code below +detects if there are `HEADERS` in the project. If the header files were not set +before the `file(GLOB ... .h)` command creates a list of all header files in the +current directory and passes them as header files of the current project. The +same applies to the `.cpp` sources that will be stored in the `SOURCES` variable if +it was not defined. + +``` +if(NOT DEFINED HEADERS) + file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.h) +endif() + +if(NOT DEFINED SOURCES) + file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +endif() +``` + +The `source_group` definition creates a group of files that will be placed in some +build systems (e.g. there will be project sub-directories in Visual Studio +solution). + +``` +source_group("Header Files" FILES ${HEADERS}) +source_group("Source Files" FILES ${SOURCES}) +``` + +This command states an executable file is the result of the project. The first +parameter receives the name of an executable file that is the same as the name +of the project in this case. The rest of the arguments are project sources, +headers and compiled Qt resources. + +``` +add_executable(${PROJECT} ${HEADERS} ${SOURCES} ${QT_RESOURCES}) +``` + +The set of libraries that will be linked with the executable above is set with +the `target_link_libraries` command. Like the command above it receives the name +of project's executable and the list of libraries. In this case the project uses +Qt framework libraries only. + +``` +target_link_libraries(${PROJECT} + Qt5::Widgets + Qt5::Qml + Qt5::Quick + ) +``` + +## Building Project + +The program is build with the commands below. The cmake required the directory +with the main project's `CMakeLists.txt` file as an argument. Then the CMake +creates the build files for the GNU make which builds an executable. ``` cd @@ -67,10 +298,53 @@ cmake .. make ``` -After building the binary `MinimalQml` will end up in `build/src/` +After the successful build the binary `MinimalQml` will end up in `build/src/`. ``` -cd build/src -./MinimalQml +./src/MinimalQml ``` +## Working with Project with Qt Creator + +Go to the *Welcome* tab *(1)* in the main window and select *Open Project* *(2)*. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt101.png]] + +In the opened dialog locate the `CMakeLists.txt` file in the root directory of the +project. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt102.png]] + +After that select the version of the *Qt framework* that will be used for +compiling the project. In case there are multiple frameworks installed in the +system it is possible to select several of them. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt103.png]] + +After opening the project its directory structure will be visible in the *Projects* +panel in Qt Creator. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt104.png]] + +The C++ source files are treated as usual by the editor. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt105.png]] + +QRC resource files are opened as a resource tree. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt106.png]] + +From the resource tree it is possible to open QML files of the project. + +[[https://github.com/apriorit/MinimalQml/blob/master/img/qt107.png]] + +## Links + +* Qt Documentation + * [Qt QML](https://doc.qt.io/qt-5/qtqml-index.html) + * [Qt Quick](https://doc.qt.io/qt-5/qtquick-index.html) + * [QML Applications](https://doc.qt.io/qt-5/qmlapplications.html) +* CMake + * [CMake Documentation](https://cmake.org/documentation/) + * [CMake Tutorial](https://cmake.org/cmake-tutorial/) + diff --git a/img/qt101.png b/img/qt101.png new file mode 100644 index 0000000..63ba07b Binary files /dev/null and b/img/qt101.png differ diff --git a/img/qt102.png b/img/qt102.png new file mode 100644 index 0000000..53ebfdf Binary files /dev/null and b/img/qt102.png differ diff --git a/img/qt103.png b/img/qt103.png new file mode 100644 index 0000000..14b53d8 Binary files /dev/null and b/img/qt103.png differ diff --git a/img/qt104.png b/img/qt104.png new file mode 100644 index 0000000..a3d8d38 Binary files /dev/null and b/img/qt104.png differ diff --git a/img/qt105.png b/img/qt105.png new file mode 100644 index 0000000..ac8df6a Binary files /dev/null and b/img/qt105.png differ diff --git a/img/qt106.png b/img/qt106.png new file mode 100644 index 0000000..54acd13 Binary files /dev/null and b/img/qt106.png differ diff --git a/img/qt107.png b/img/qt107.png new file mode 100644 index 0000000..6165b93 Binary files /dev/null and b/img/qt107.png differ