From 7343174056948ee45f2ed08692c8556e5f16a01a Mon Sep 17 00:00:00 2001 From: jordi fita mas Date: Thu, 19 Dec 2024 01:53:12 +0100 Subject: [PATCH] Add login and reservations page in a StackView --- src/CMakeLists.txt | 2 ++ src/LoginPage.qml | 59 ++++++++++++++++++++++++++++++++ src/Main.qml | 72 +++++++++++++++------------------------- src/ReservationsPage.qml | 23 +++++++++++++ src/database.cpp | 23 ++++++++++--- src/database.h | 4 +++ 6 files changed, 134 insertions(+), 49 deletions(-) create mode 100644 src/LoginPage.qml create mode 100644 src/ReservationsPage.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7fb64e..6ea5db8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,9 @@ qt_add_qml_module(${PROJECT_NAME} database.cpp database.h QML_FILES ErrorNotification.qml + LoginPage.qml Main.qml + ReservationsPage.qml SelectableLabel.qml ) diff --git a/src/LoginPage.qml b/src/LoginPage.qml new file mode 100644 index 0000000..1bc4ff6 --- /dev/null +++ b/src/LoginPage.qml @@ -0,0 +1,59 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Page { + id: page + + title: qsTr("Login") + + ColumnLayout { + Label { + text: qsTr("&User:") + } + + TextField { + id: user + + focus: true + + validator: RegularExpressionValidator { + regularExpression: /[^s].*/ + } + + onAccepted: function () { + loginAction.trigger(); + } + } + + Label { + text: qsTr("&Password:") + } + + TextField { + id: password + + echoMode: TextInput.Password + + onAccepted: function () { + loginAction.trigger(); + } + } + + Button { + action: loginAction + } + } + + Action { + id: loginAction + + enabled: user.acceptableInput + text: "&Login" + + onTriggered: function () { + Database.open(user.text, password.text); + } + } +} diff --git a/src/Main.qml b/src/Main.qml index b801cbb..8e131ac 100644 --- a/src/Main.qml +++ b/src/Main.qml @@ -1,50 +1,35 @@ pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls -import QtQuick.Layouts import Camper ApplicationWindow { height: 480 - title: qsTr("Camper") + title: pageStack.title ? qsTr("%1 — Camper").arg(pageStack.title) : qsTr("Camper") visible: true width: 640 - ColumnLayout { - Label { - text: qsTr("&User:") + StackView { + id: pageStack + + property string title: (currentItem as Page)?.title ?? "" + + anchors.fill: parent + focus: true + initialItem: loginPage + } + + Component { + id: loginPage + + LoginPage { } + } - TextField { - id: user + Component { + id: reservationsPage - focus: true - - validator: RegularExpressionValidator { - regularExpression: /[^s].*/ - } - - onAccepted: function () { - loginAction.trigger(); - } - } - - Label { - text: qsTr("&Password:") - } - - TextField { - id: password - - echoMode: TextInput.Password - - onAccepted: function () { - loginAction.trigger(); - } - } - - Button { - action: loginAction + ReservationsPage { } } @@ -60,22 +45,19 @@ ApplicationWindow { } } - Action { - id: loginAction - - enabled: user.acceptableInput - text: "&Login" - - onTriggered: function () { - Database.open(user.text, password.text); - } - } - Connections { + function onClosed() { + pageStack.replace(null, loginPage); + } + function onErrorOcurred(errorMessage) { errorNotification.show(errorMessage); } + function onOpened() { + pageStack.replace(reservationsPage); + } + target: Database } } diff --git a/src/ReservationsPage.qml b/src/ReservationsPage.qml new file mode 100644 index 0000000..0226768 --- /dev/null +++ b/src/ReservationsPage.qml @@ -0,0 +1,23 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls + +Page { + title: qsTr("Reservations") + + Button { + action: logoutAction + } + + Action { + id: logoutAction + + icon.name: "system-log-out" + shortcut: "Ctrl+L" + text: qsTr("&Log out") + + onTriggered: function () { + Database.close(); + } + } +} diff --git a/src/database.cpp b/src/database.cpp index 71620dd..56f2812 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -6,6 +6,7 @@ Database::Database(QObject *parent) : QObject{parent} , m_pool{} + , m_connectionName{"main"} { m_pool.setMaxThreadCount(1); m_pool.setExpiryTimeout(-1); @@ -14,16 +15,30 @@ Database::Database(QObject *parent) QFuture Database::open(const QString &user, const QString &password) { return QtConcurrent::run(&m_pool, [this, user, password]() { - QString connectionName("main"); - QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL", connectionName); + QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL", m_connectionName); db.setConnectOptions("service=camper; options=-csearch_path=camper,public"); - if (!db.open(user, password)) { + if (db.open(user, password)) { + emit opened(); + } else { const QString errorMessage(db.lastError().text()); db = QSqlDatabase(); // Otherwise removeDatabase complains is still being used. - QSqlDatabase::removeDatabase(connectionName); + QSqlDatabase::removeDatabase(m_connectionName); emit errorOcurred(errorMessage); } }); } +QFuture Database::close() +{ + return QtConcurrent::run(&m_pool, [this]() { + QSqlDatabase db = QSqlDatabase::database(m_connectionName); + if (!db.isValid()) { + return; + } + db.close(); + QSqlDatabase::removeDatabase(m_connectionName); + emit closed(); + }); +} + #include "moc_database.cpp" diff --git a/src/database.h b/src/database.h index 1c6b5b5..eb53aab 100644 --- a/src/database.h +++ b/src/database.h @@ -16,12 +16,16 @@ public: explicit Database(QObject *parent = nullptr); Q_INVOKABLE QFuture open(const QString &user, const QString &password); + Q_INVOKABLE QFuture close(); signals: + void closed(); void errorOcurred(const QString &errorMessage); + void opened(); private: QThreadPool m_pool; + QString m_connectionName; }; #endif // DATABASE_H