Ustawienia środowiska i pierwsze kroki

Przygotowywanie się do stworzenia naszej pierwszej aplikacji Kirigami

Wgrywanie potrzebnych pakietów

Zanim zaczniemy, musimy wgrać kilka rzeczy. Potrzebujemy kompilatora C++, pakietów programistycznych Qt oraz Kirigami.

Na Ubuntu, Debianie oraz Neonie możemy je wgrać, używając APT:

sudo apt install build-essential extra-cmake-modules cmake qtbase5-dev qtdeclarative5-dev libqt5svg5-dev qtquickcontrols2-5-dev qml-module-org-kde-kirigami2 kirigami2-dev libkf5i18n-dev gettext libkf5coreaddons-dev qml-module-qtquick-layouts

Na dystrybucjach opartych na Archu (takich jak Manjaro) możemy skorzystać z Pacmana:

sudo pacman -Syu base-devel extra-cmake-modules cmake kirigami2 kde-sdk-meta gettext

Na Fedorze, użyjemy DNF:

sudo dnf groupinstall "Development Tools" "Development Libraries"
sudo dnf install extra-cmake-modules cmake qt5-qtbase-devel qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel kf5-kirigami2 kf5-kirigami2-devel kf5-ki18n-devel kf5-kcoreaddons-devel gettext

Dalsze szczegóły dla innych dystrybucji można znaleźć tutaj.

Struktura projektu

Mimo że istnieją narzędzia, które umożliwiają łatwe stworzenie tych plików, to my stworzymy je ręcznie. Ułatwi nam to zrozumienie części, które będą się składać na nasza nową aplikację.

Najpierw tworzymy katalog naszego projektu. Nazwiemy go ‘helloworld’.

helloworld
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── contents
    │   └── ui
    │       └── main.qml
    ├── main.cpp
    └── resources.qrc

W tym katalogu stworzymy katalog src oraz CMakeLists.txt. Ogólnym zwyczajem jest umieszczanie wszystkich plików naszego głównego kodu w katalogu src. Nasz katalog src będzie zawierał katalog o nazwie contents, który będzie zawierał katalog o nazwie ui. To tutaj, gdzie utworzymy nasze pliki QML.

Jest to zwyczaj KDE, lecz nie wszystkie projekty KDE przestrzegają tej struktury. Masz dowolność w ustawieniu rzeczy inaczej, lecz będziesz musiał to uwzględnić podczas tworzenia swoich plików CMakeLists.txt oraz resources.qrc.

main.qml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Includes relevant modules used by the QML
import QtQuick 2.6
import QtQuick.Controls 2.0 as Controls
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.13 as Kirigami

// Base element, provides basic features needed for all kirigami applications
Kirigami.ApplicationWindow {
    // ID provides unique identifier to reference this element
    id: root

    // Window title
    // i18nc is useful for adding context for translators, also lets strings be changed for different languages
    title: i18nc("@title:window", "Hello World")

    // Initial page to be loaded on app load
    pageStack.initialPage: Kirigami.Page {

        Controls.Label {
            // Center label horizontally and vertically within parent element
            anchors.centerIn: parent
            text: i18n("Hello World!")
        }
    }
}

To miejsce, w którym będziemy obsługiwać przód naszej aplikacji.

Jeśli znacz trochę Javascriptu, to większość QML będzie dla ciebie znajoma (mimo tego ma on swoje osobliwości). Dokumentacja Qt zawiera wiele treści na temat tego języka, jeśli chciałbyś spróbować czego samemu. Na przestrzeni tych samouczków, będziemy skupiać nasza uwagę na kodzie QML, dzięki któremu możemy wydobyć najwięcej z Kirigami.

Na teraz, skupmy się na main.qml. Najpierw importujemy kilka ważnych modułów:

  • QtQuick, standardowa biblioteka używana w aplikacjach QML.
  • QtQuick Controls, który daje kilka standardowych rzeczy sterujących, których możemy użyć, aby umożliwić oddziaływanie z naszą aplikacją.
  • Układy QtQuick, które zapewniają narzędzia do umieszczania składników wewnątrz okna aplikacji.
  • Kirigami, który dostarcza kilka składników nadających się do tworzenia aplikacji, które działają na urządzeniach o różnych kształtach i rozmiarach.

Dochodzimy wtedy do naszej rzeczy głównej, Kirigami.ApplicationWindow która daje podstawowe możliwości, potrzebne każdej aplikacji Kirigami. To jest okno, które będzie zawierało każdą z naszych stron oraz główne obszary naszego interfejsu.

Następnie ustawiamy właściwość id rzeczy Kirigami.ApplicationWindow na ‘root’. Identyfikatory są użyteczne, bo umożliwiają odnoszenie się do składnika w niepowtarzalny sposób, nawet gdy mamy kilka tego samego rodzaju.

Ustawiamy także własność okna title na ‘Hello World’. Możesz zauważyć, że otoczyliśmy nasz ciąg znaków “Hello World” funkcją o nazwie i18nc, w której opisujemy zarówno kontekst ciągu znaków jak i sam ciąg znaków.

Następnie ustawiamy pierwszą stronę naszego stosu stron. Większość aplikacji Kirigami jest zorganizowanych jako stosy stron, gdzie każda strona zawiera składniki odpowiednie danemu zadaniu. Na tę chwilę, chcemy prostoty, więc trzymamy się pojedynczej strony. Poprzez pageStack.initialPage: Kirigami.Page{...} ustawiamy pierwszą stronę przedstawianą podczas wczytywania aplikacji do Kirigami.Page, która będzie zawierać całą naszą zawartość.

Na końcu, dodajemy do naszej strony Controls.Label, która umożliwia nam umieszczenie tekstu na naszej stronie. Używamy anchors.centerIn: parent do wyśrodkowania etykiety w poziomie i pionie wewnątrz naszej nadrzędnej rzeczy. W tym przypadku nadrzędnym składnikiem Controls.Label jest Kirigami.Page. Ostatnią rzeczą jaką musimy zrobić, to ustawienie tekstu: text: i18n("Hello World!").

main.cpp

main.cpp obsługuje ‘logikę biznesową’ naszej aplikacji. C++ jest użyteczny, bo jest elastyczny i szybki, nawet gdy jest bardziej zawiły niż inne języki programowania.

main.cpp jest także punktem wejściowym twojej aplikacji. Dwie części naszego projektu, silnik oraz interfejs użytkownika są tutaj przygotowywane i uruchamiane.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QUrl>
#include <KLocalizedContext>
#include <KLocalizedString>

int main(int argc, char *argv[])
{
    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);
    KLocalizedString::setApplicationDomain(QStringLiteral("helloworld"));
    QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
    QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
    QCoreApplication::setApplicationName(QStringLiteral("Hello World"));

    QQmlApplicationEngine engine;

    engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    if (engine.rootObjects().isEmpty()) {
        return -1;
    }

    return app.exec();
}

Na razie nie musimy zagłębiać się w to, co nasz kod main.cpp robi, lecz jego rola urośnie znacząco, gdy dodamy bardziej złożone możliwości do naszej aplikacji w przyszłości. Jeśli chcesz więcej o tym jak działa main.cpp, to przeczytaj o tym na tej stronie.

resources.qrc

resources.qrc zawiera listę wszystkich plików QML, a także inne pliki (takie jak własne ikony) które będą umieszczone w pliku wykonywalnym.

1
2
3
4
5
<RCC>
    <qresource prefix="/">
        <file alias="main.qml">contents/ui/main.qml</file>
    </qresource>
</RCC>

Zwróć uwagę na wiersz <file alias="main.qml">contents/ui/main.qml</file>. Określa pliki QML, które zostaną dołączone podczas budowania. W naszym przypadku używamy tylko main.qml, lecz gdybyśmy chcieli dodać więcej plików QML do naszego kodu, to musielibyśmy załączyć je do pliku resources.qrc, dodają kolejne wiersze takie jak ten.

Więcej o tym jak działa system zasobów Qt możesz przeczytać w dokumentacji Qt.

CMakeLists.txt

CMakeLists.txt są potrzebne do używania systemu budowania wybranego przez KDE, CMake. Plik CMakeLists.txt w naszym głównym katalogu określi pewne szczegóły naszej aplikacji. Zawiera także niektóre z zależności, wymagane do jej zbudowania.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cmake_minimum_required(VERSION 3.16)
project(helloworld)

set(KF_MIN_VERSION "5.68.0")
set(QT_MIN_VERSION "5.12.0")

find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)

set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})

include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)

find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui QuickControls2 Widgets)
find_package(KF5 ${KF_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 I18n CoreAddons)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_subdirectory(src)

feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)

CMakeLists.txt określa sposób budowania naszego projektu. Większość z treści tutaj jest tylko po to, aby stworzyć zalążek naszego projektu. Możesz przeczytać wiersz po wierszu, nasze szczegółowe wyjaśnienie tego, co robi plik CMakeLists tutaj.

Najważniejsze do zapamiętania jest to, że zależności Qt i Szkieletów KDE są zarządzane przez find_package. Będziesz musiał zmienić te wiersze i dołączyć dowolne dodatkowe składniki, których postanowisz użyć podczas tworzenia swojej aplikacji.

Ostatni wiersz, add_subdirectory(src), wskazuje CMake na katalog ‘src’, gdzie znajduje się nasz kod źródłowy. Zagłębmy się tutaj w plik CMakeLists.txt.

1
2
add_executable(helloworld main.cpp resources.qrc)
target_link_libraries(helloworld Qt5::Quick Qt5::Qml Qt5::Gui Qt5::QuickControls2 Qt5::Widgets KF5::Kirigami2 KF5::I18n)

Ten jest dużo krótszy! Spójrzmy po kolei, co on robi:

  • add_executable tworzy plik wykonywalny z danych plików źródłowych.
  • target_link_libraries dowiązuje biblioteki użyte w naszym kodzie do naszego pliku wykonywalnego.

Teraz zajęliśmy się CMake, więc spójrzmy na pliki, nad którymi będziemy pracować przez większość czasu.

Kompilowanie i uruchamianie aplikacji

Już prawie jesteśmy na mecie. Ostatnią rzeczą jaką musimy zrobić to zbudować naszą aplikację. Aby to zrobić, musimy wpisać katalog ‘helloworld’ do naszego terminala i wykonać następujące polecenie:

cmake -B build/ . && cmake --build build/

I uruchom poprzez

./build/bin/<project_name>

Voila! Teraz możesz zobaczyć swoją pierwszą aplikację Kirigami na własne oczy.

Zrzut ekranu wytworzonej aplikacji Kirigami