Use database “advanced options” and persist them

I only want to store these options if the connection to the database is
established, to avoid saving incorrect values by error. I, then, did not
use property alias, as the documentation reccomends, and instead have a
function to save the parameters when the application sees the database
open.

I have to use the function because a Connections inside LoginPage gets
called _after_ the Connections in Main, meaning that i would get deleted
before it has the chance to save the settings.

Now i can’t assume connect options will include search_path, as it is
unreasonable to request people to know the internal schemas of the
application.
This commit is contained in:
jordi fita mas 2024-12-23 20:54:04 +01:00
parent dd2beba676
commit 7eeccbb033
4 changed files with 75 additions and 23 deletions

View File

@ -1,4 +1,5 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtCore
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
@ -6,6 +7,14 @@ import QtQuick.Layouts
Page { Page {
id: page id: page
function saveSettings() {
settings.connectOptions = connectOptions.text;
settings.databaseName = databaseName.text;
settings.hostName = hostName.text;
settings.port = port.value;
settings.usePort = usePort.checked;
}
title: qsTr("Login") title: qsTr("Login")
ColumnLayout { ColumnLayout {
@ -63,33 +72,36 @@ Page {
id: hostName id: hostName
Layout.fillWidth: true Layout.fillWidth: true
text: settings.hostName
onAccepted: loginAction.trigger() onAccepted: loginAction.trigger()
} }
CheckBox { CheckBox {
id: port id: usePort
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
Mnemonic.label: qsTr("Por&t:") Mnemonic.label: qsTr("Por&t:")
checked: settings.usePort
text: Mnemonic.richTextLabel text: Mnemonic.richTextLabel
Shortcut { Shortcut {
sequence: port.Mnemonic.sequence sequence: usePort.Mnemonic.sequence
onActivated: port.click() onActivated: usePort.click()
} }
} }
SpinBox { SpinBox {
id: portNumber id: port
Accessible.name: qsTr("Port number") Accessible.name: qsTr("Port number")
Layout.fillWidth: true Layout.fillWidth: true
editable: true editable: true
enabled: port.checked enabled: usePort.checked
from: 1 from: 1
to: 65535 to: 65535
value: settings.port
} }
MnemonicLabel { MnemonicLabel {
@ -102,6 +114,7 @@ Page {
id: databaseName id: databaseName
Layout.fillWidth: true Layout.fillWidth: true
text: settings.databaseName
onAccepted: loginAction.trigger() onAccepted: loginAction.trigger()
} }
@ -116,6 +129,7 @@ Page {
id: connectOptions id: connectOptions
Layout.fillWidth: true Layout.fillWidth: true
text: settings.connectOptions
onAccepted: loginAction.trigger() onAccepted: loginAction.trigger()
} }
@ -128,13 +142,25 @@ Page {
} }
} }
Settings {
id: settings
property string connectOptions: ""
property string databaseName: ""
property string hostName: ""
property int port: 5432
property bool usePort: false
category: "database"
}
MnemonicAction { MnemonicAction {
id: loginAction id: loginAction
mnemonic: qsTr("Log &in") mnemonic: qsTr("Log &in")
onTriggered: function () { onTriggered: function () {
Database.open(user.text, password.text); Database.open(user.text.trim(), password.text.trim(), hostName.text.trim(), usePort.checked, port.value, databaseName.text.trim(), connectOptions.text.trim());
} }
} }
} }

View File

@ -55,6 +55,7 @@ ApplicationWindow {
} }
function onOpened() { function onOpened() {
(pageStack.currentItem as LoginPage)?.saveSettings();
pageStack.replace(reservationsPage); pageStack.replace(reservationsPage);
} }

View File

@ -1,6 +1,7 @@
#include "database.h" #include "database.h"
#include <QSqlDatabase> #include <QSqlDatabase>
#include <QSqlError> #include <QSqlError>
#include <QSqlQuery>
#include <QtConcurrent> #include <QtConcurrent>
Database::Database(QObject *parent) Database::Database(QObject *parent)
@ -11,24 +12,42 @@ Database::Database(QObject *parent)
m_pool.setExpiryTimeout(-1); m_pool.setExpiryTimeout(-1);
} }
QFuture<void> Database::open(const QString &user, const QString &password) QFuture<void> Database::open(const QString &user,
const QString &password,
const QString &hostName,
bool usePort,
int portNumber,
const QString &databaseName,
const QString &connectOptions)
{ {
return QtConcurrent::run(&m_pool, [this, user, password]() { return QtConcurrent::run(
QString errorMessage; &m_pool,
QString connectionName; [this, user, password, hostName, usePort, portNumber, databaseName, connectOptions]() {
{ QString errorMessage;
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); QString connectionName;
db.setConnectOptions("service=camper; options=-csearch_path=camper,public"); {
if (db.open(user, password)) { QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
emit opened(); db.setHostName(hostName);
return; if (usePort) {
db.setPort(portNumber);
}
db.setDatabaseName(databaseName);
db.setConnectOptions(connectOptions);
if (db.open(user, password)) {
QSqlQuery q(db);
if (q.exec("SET search_path TO camper, public")) {
emit opened();
return;
}
errorMessage = q.lastError().text();
} else {
errorMessage = db.lastError().text();
}
connectionName = db.connectionName();
} }
errorMessage = db.lastError().text(); QSqlDatabase::removeDatabase(connectionName);
connectionName = db.connectionName(); emit errorOcurred(errorMessage);
} });
QSqlDatabase::removeDatabase(connectionName);
emit errorOcurred(errorMessage);
});
} }
QFuture<void> Database::close() QFuture<void> Database::close()

View File

@ -15,7 +15,13 @@ class Database : public QObject
public: public:
explicit Database(QObject *parent = nullptr); explicit Database(QObject *parent = nullptr);
Q_INVOKABLE QFuture<void> open(const QString &user, const QString &password); Q_INVOKABLE QFuture<void> open(const QString &user,
const QString &password,
const QString &hostName,
bool usePort,
int portNumber,
const QString &databaseName,
const QString &connectOptions);
Q_INVOKABLE QFuture<void> close(); Q_INVOKABLE QFuture<void> close();
signals: signals: