Settings page was added

This commit is contained in:
2023-03-30 20:06:03 +02:00
parent 31cb989f67
commit 25e8a3ea79
16 changed files with 272 additions and 55 deletions

View File

@@ -68,10 +68,6 @@ set_target_properties(beerlog PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
) )
#install(TARGETS beerlog
# BUNDLE DESTINATION .
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(QT_VERSION_MAJOR EQUAL 6) if(QT_VERSION_MAJOR EQUAL 6)
qt_import_qml_plugins(beerlog) qt_import_qml_plugins(beerlog)
qt_finalize_executable(beerlog) qt_finalize_executable(beerlog)

View File

@@ -4,9 +4,32 @@
<context> <context>
<name>MainMenu</name> <name>MainMenu</name>
<message> <message>
<location filename="qml/Components/MainMenu.qml" line="34"/> <location filename="qml/Components/MainMenu.qml" line="44"/>
<source>BeerLog v0.1</source> <source>Online</source>
<translation></translation> <translation>В сети</translation>
</message>
<message>
<location filename="qml/Components/MainMenu.qml" line="44"/>
<source>Offline</source>
<translation>Не в сети</translation>
</message>
</context>
<context>
<name>SettingsView</name>
<message>
<location filename="qml/Views/SettingsView.qml" line="8"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="qml/Views/SettingsView.qml" line="14"/>
<source>BeerLog service address</source>
<translation>Адрес сервиса BeerLog</translation>
</message>
<message>
<location filename="qml/Views/SettingsView.qml" line="19"/>
<source>Selected user id</source>
<translation>Выбранный пользователь</translation>
</message> </message>
</context> </context>
<context> <context>
@@ -17,24 +40,24 @@
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="qml/main.qml" line="64"/> <location filename="qml/main.qml" line="72"/>
<source>BeerLog v0.1</source> <source>BeerLog v0.1</source>
<oldsource>BeerLog v1.0.0</oldsource> <oldsource>BeerLog v1.0.0</oldsource>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="qml/main.qml" line="68"/> <location filename="qml/main.qml" line="77"/>
<source>Settings</source> <source>Settings</source>
<translation>Настройки</translation> <translation>Настройки</translation>
</message> </message>
<message> <message>
<location filename="qml/main.qml" line="72"/> <location filename="qml/main.qml" line="81"/>
<location filename="qml/main.qml" line="108"/> <location filename="qml/main.qml" line="117"/>
<source>Quit</source> <source>Quit</source>
<translation>Выход</translation> <translation>Выход</translation>
</message> </message>
<message> <message>
<location filename="qml/main.qml" line="112"/> <location filename="qml/main.qml" line="121"/>
<source>Realy quit the application?</source> <source>Realy quit the application?</source>
<translation>Действительно выйти из приложения?</translation> <translation>Действительно выйти из приложения?</translation>
</message> </message>

View File

@@ -7,6 +7,7 @@
#include "viewmodels/usersviewmodel.h" #include "viewmodels/usersviewmodel.h"
#include "services/beerservice.h" #include "services/beerservice.h"
#include "services/settingsservice.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@@ -16,6 +17,11 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QTranslator translator; QTranslator translator;
if (!translator.load("qt_ru.qm", "qrc:/")) {
qWarning() << "Cant load";
}
const QStringList uiLanguages = QLocale::system().uiLanguages(); const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) { for (const QString &locale : uiLanguages) {
const QString baseName = "beerlog_" + QLocale(locale).name(); const QString baseName = "beerlog_" + QLocale(locale).name();
@@ -33,7 +39,11 @@ int main(int argc, char *argv[])
QCoreApplication::exit(-1); QCoreApplication::exit(-1);
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
engine.addImportPath("qrc:/");
engine.rootContext()->setContextProperty("beerService", BeerService::instance()); engine.rootContext()->setContextProperty("beerService", BeerService::instance());
engine.rootContext()->setContextProperty("settingsService", SettingsService::instance());
qmlRegisterType<UsersViewModel>("ru.ded.beerlog", 1, 0, "UsersViewModel"); qmlRegisterType<UsersViewModel>("ru.ded.beerlog", 1, 0, "UsersViewModel");
engine.load(url); engine.load(url);

View File

@@ -4,7 +4,6 @@
#include <QObject> #include <QObject>
#include <QVariantMap> #include <QVariantMap>
#include "services/settingsservice.h"
#include "models/abstractmodel.h" #include "models/abstractmodel.h"
class UsersModel : public AbstractModel class UsersModel : public AbstractModel

View File

@@ -5,6 +5,7 @@ Drawer {
property alias logo: logoImage.source property alias logo: logoImage.source
property alias appName: appNameLabel.text property alias appName: appNameLabel.text
property alias model: menuRepeater.model property alias model: menuRepeater.model
property alias connected: connectionLabel.connected
signal actionSelected(var action) signal actionSelected(var action)
@@ -26,12 +27,23 @@ Drawer {
anchors.margins: 10 anchors.margins: 10
} }
Label { Column {
id: appNameLabel
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pointSize: 20
text: qsTr("BeerLog v0.1") Label {
id: appNameLabel
font.pointSize: 20
}
Label {
id: connectionLabel
property bool connected: false
text: connected ? qsTr("Online") : qsTr("Offline")
color: connected ? "green" : "red"
}
} }
} }

View File

@@ -0,0 +1,24 @@
import QtQuick 2.0
import QtQuick.Controls 2.2
ItemDelegate {
id: root
property string subtitle: ""
contentItem: Column {
Label {
id: titleLabel
width: parent.width
text: root.text
}
Label {
width: parent.width
font.pixelSize: titleLabel.font.pixelSize - 2
text: root.subtitle
opacity: 0.8
}
}
}

5
qml/Components/qmldir Normal file
View File

@@ -0,0 +1,5 @@
module Components
MainMenu 1.0 MainMenu.qml
MenuBackButton 1.0 MenuBackButton.qml
SubtitledItemDelegate 1.0 SubtitledItemDelegate.qml

View File

@@ -1,11 +1,74 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import Components 1.0
Page { Page {
id: root
Label { title: qsTr("Settings")
anchors.centerIn: parent
text: "Settings" ListModel {
id: settingsModel
ListElement {
title: qsTr("BeerLog service address")
name: "serverAddress"
}
ListElement {
title: qsTr("Selected user id")
name: "selectedUserId"
}
} }
ListView {
anchors.fill: parent
model: settingsModel
delegate: SubtitledItemDelegate {
width: parent.width
text: model.title
subtitle: settingsService[model.name]
onClicked: {
inputDialog.title = model.title
inputDialog.name = model.name
inputDialog.open()
}
}
}
Dialog {
id: inputDialog
property string name: ""
width: root.width * 0.8
anchors.centerIn: parent
parent: ApplicationWindow.overlay
modal: true
standardButtons: Dialog.Ok | Dialog.Cancel
Column {
spacing: 20
anchors.fill: parent
TextField {
id: textField
width: parent.width
inputMethodHints: Qt.ImhNoAutoUppercase
placeholderText: inputDialog.title
text: settingsService[inputDialog.name] || ""
}
}
onAccepted: {
settingsService[inputDialog.name] = textField.text
}
}
} }

View File

@@ -5,7 +5,7 @@ import QtQuick.Layouts 1.15
import QtWebSockets import QtWebSockets
import ru.ded.beerlog 1.0 import ru.ded.beerlog 1.0
import "Components" import Components 1.0
ApplicationWindow { ApplicationWindow {
width: 640 width: 640
@@ -16,15 +16,23 @@ ApplicationWindow {
header: ToolBar { header: ToolBar {
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
MenuBackButton { MenuBackButton {
state: stackView.depth > 1 ? "back" : "menu" state: stackView.depth > 1 ? "back" : "menu"
onClicked: mainMenu.open() onClicked: mainMenu.open()
onBack: stackView.pop() onBack: stackView.pop()
} }
ToolButton {
text: usersModel.selectedUserName Label {
text: stackView.currentItem.title || usersModel.selectedUserName
Layout.fillWidth: true Layout.fillWidth: true
onClicked: usersMenu.open() horizontalAlignment: Qt.AlignCenter
MouseArea {
anchors.fill: parent
enabled: stackView.depth === 1
onClicked: usersMenu.open()
}
} }
} }
@@ -62,6 +70,7 @@ ApplicationWindow {
logo: "qrc:/logo.png" logo: "qrc:/logo.png"
appName: qsTr("BeerLog v0.1") appName: qsTr("BeerLog v0.1")
connected: beerService.connected
model: ListModel { model: ListModel {
ListElement { ListElement {

View File

@@ -8,5 +8,8 @@
<file>Components/MainMenu.qml</file> <file>Components/MainMenu.qml</file>
<file>Views/OrdersView.qml</file> <file>Views/OrdersView.qml</file>
<file>Views/SettingsView.qml</file> <file>Views/SettingsView.qml</file>
<file>Components/SubtitledItemDelegate.qml</file>
<file>Components/qmldir</file>
<file>qt_ru.qm</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -7,6 +7,8 @@
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
#include "settingsservice.h"
BeerService::BeerService() BeerService::BeerService()
: QObject{nullptr} : QObject{nullptr}
{ {
@@ -38,6 +40,13 @@ BeerService::BeerService()
sendCommand(m_commandStash.takeFirst().toMap()); sendCommand(m_commandStash.takeFirst().toMap());
} }
}); });
connect(&m_socket, &QWebSocket::stateChanged, this, &BeerService::connectedChanged);
connect(settings(), &SettingsService::serverAddressChanged, this, &BeerService::reconnect);
connect(settings(), &SettingsService::selectedUserIdChanged, this, &BeerService::reconnect);
reconnect();
} }
BeerService::~BeerService() BeerService::~BeerService()
@@ -46,15 +55,9 @@ BeerService::~BeerService()
m_socket.close(); m_socket.close();
} }
void BeerService::connectSrv(const QString &userId) SettingsService *BeerService::settings() const
{ {
if (QAbstractSocket::ConnectedState == m_socket.state()) { return SettingsService::instance();
m_socket.close();
}
QNetworkRequest request(QUrl("ws://195.133.196.161:8000"));
request.setRawHeader("Authorization", "Basic " + QString("%1:pass").arg(userId).toLatin1().toBase64());
m_socket.open(request);
} }
void BeerService::sendCommand(const QString &entity, const QString &action, const QVariantMap &data) void BeerService::sendCommand(const QString &entity, const QString &action, const QVariantMap &data)
@@ -104,12 +107,32 @@ void BeerService::restoreStash()
} }
} }
void BeerService::reconnect()
{
if (connected()) {
m_socket.close();
}
QString userId = settings()->selectedUserId();
QUrl serverUrl(QString("ws://%1").arg(settings()->serverAddress()));
QNetworkRequest request(serverUrl);
request.setRawHeader("Authorization", "Basic " + QString("%1:pass").arg(userId).toLatin1().toBase64());
m_socket.open(request);
}
void BeerService::sendCommand(const QVariantMap &command) void BeerService::sendCommand(const QVariantMap &command)
{ {
if (QAbstractSocket::ConnectedState == m_socket.state()) { if (connected()) {
QJsonDocument doc = QJsonDocument::fromVariant(command); QJsonDocument doc = QJsonDocument::fromVariant(command);
m_socket.sendTextMessage(doc.toJson(QJsonDocument::Compact)); m_socket.sendTextMessage(doc.toJson(QJsonDocument::Compact));
} else { } else {
m_commandStash << command; m_commandStash << command;
} }
} }
bool BeerService::connected() const
{
return QAbstractSocket::ConnectedState == m_socket.state();
}

View File

@@ -4,10 +4,13 @@
#include <QObject> #include <QObject>
#include <QtWebSockets/QWebSocket> #include <QtWebSockets/QWebSocket>
class SettingsService;
class BeerService : public QObject class BeerService : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
public: public:
static BeerService *instance() static BeerService *instance()
{ {
@@ -15,19 +18,25 @@ public:
return &i; return &i;
} }
Q_INVOKABLE void connectSrv(const QString &userId = QString());
void sendCommand(const QString &entity, const QString &action, const QVariantMap &data = QVariantMap()); void sendCommand(const QString &entity, const QString &action, const QVariantMap &data = QVariantMap());
void connectListener(QObject *listener); void connectListener(QObject *listener);
signals:
void connectedChanged();
private: private:
BeerService(); BeerService();
~BeerService(); ~BeerService();
SettingsService *settings() const;
QString stashFileName() const; QString stashFileName() const;
void saveStash() const; void saveStash() const;
void restoreStash(); void restoreStash();
void reconnect();
void sendCommand(const QVariantMap &command); void sendCommand(const QVariantMap &command);
bool connected() const;
QMultiMap<QString, QObject *> m_listeners; QMultiMap<QString, QObject *> m_listeners;

View File

@@ -3,6 +3,14 @@
namespace Defaults { namespace Defaults {
constexpr auto GuestUserId = "2641ffe8cd4311eda27f0242ac120002"; constexpr auto GuestUserId = "2641ffe8cd4311eda27f0242ac120002";
constexpr auto ServerAddress = "195.133.196.161:8000";
}
namespace Keys {
constexpr auto ServerAddress = "server_address";
constexpr auto SelectedUser = "selected_user";
} }
@@ -16,12 +24,24 @@ void SettingsService::setValue(const QString &key, const QVariant &value)
m_settings.setValue(key, value); m_settings.setValue(key, value);
} }
QString SettingsService::serverAddress() const
{
return m_settings.value(Keys::ServerAddress, Defaults::ServerAddress).toString();
}
void SettingsService::setServerAddress(const QString &address)
{
m_settings.setValue(Keys::ServerAddress, address);
emit serverAddressChanged();
}
QString SettingsService::selectedUserId() const QString SettingsService::selectedUserId() const
{ {
return m_settings.value("selected_user", Defaults::GuestUserId).toString(); return m_settings.value(Keys::SelectedUser, Defaults::GuestUserId).toString();
} }
void SettingsService::setSelectedUserId(const QString &userId) void SettingsService::setSelectedUserId(const QString &userId)
{ {
m_settings.setValue("selected_user", userId); m_settings.setValue(Keys::SelectedUser, userId);
emit selectedUserIdChanged();
} }

View File

@@ -1,18 +1,40 @@
#ifndef SETTINGSSERVICE_H #ifndef SETTINGSSERVICE_H
#define SETTINGSSERVICE_H #define SETTINGSSERVICE_H
#include <QObject>
#include <QSettings> #include <QSettings>
class SettingsService class SettingsService : public QObject
{ {
Q_OBJECT
Q_PROPERTY(QString serverAddress READ serverAddress WRITE setServerAddress NOTIFY serverAddressChanged)
Q_PROPERTY(QString selectedUserId READ selectedUserId WRITE setSelectedUserId NOTIFY selectedUserIdChanged)
public: public:
static SettingsService *instance()
{
static SettingsService i;
return &i;
}
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
void setValue(const QString &key, const QVariant &value); void setValue(const QString &key, const QVariant &value);
QString serverAddress() const;
void setServerAddress(const QString &address);
QString selectedUserId() const; QString selectedUserId() const;
void setSelectedUserId(const QString &userId); void setSelectedUserId(const QString &userId);
signals:
void serverAddressChanged();
void selectedUserIdChanged();
private: private:
SettingsService() = default;
~SettingsService() = default;
QSettings m_settings = QSettings("DedSoft", "BeerLog"); QSettings m_settings = QSettings("DedSoft", "BeerLog");
}; };

View File

@@ -1,18 +1,15 @@
#include "usersviewmodel.h" #include "usersviewmodel.h"
#include "services/beerservice.h" #include "services/settingsservice.h"
UsersViewModel::UsersViewModel(QObject *parent) UsersViewModel::UsersViewModel(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
connect(this, &UsersViewModel::selectedUserChanged, this, [this]() {
BeerService::instance()->connectSrv(m_selectedUser);
});
setSelectedUser(m_settings.selectedUserId());
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::usersChanged); connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::usersChanged);
connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged); connect(&m_usersModel, &AbstractModel::dataChanged, this, &UsersViewModel::selectedUserNameChanged);
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserChanged);
connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserNameChanged);
} }
QVariantList UsersViewModel::users() const QVariantList UsersViewModel::users() const
@@ -22,22 +19,24 @@ QVariantList UsersViewModel::users() const
QString UsersViewModel::selectedUser() const QString UsersViewModel::selectedUser() const
{ {
return m_selectedUser; return settings()->selectedUserId();
} }
void UsersViewModel::setSelectedUser(const QString &newSelectedUser) void UsersViewModel::setSelectedUser(const QString &newSelectedUser)
{ {
if (m_selectedUser == newSelectedUser) { if (selectedUser() == newSelectedUser) {
return; return;
} }
m_selectedUser = newSelectedUser; settings()->setSelectedUserId(newSelectedUser);
m_settings.setSelectedUserId(m_selectedUser);
emit selectedUserChanged();
emit selectedUserNameChanged();
} }
QString UsersViewModel::selectedUserName() const QString UsersViewModel::selectedUserName() const
{ {
return m_usersModel.userName(m_selectedUser); return m_usersModel.userName(selectedUser());
}
SettingsService *UsersViewModel::settings() const
{
return SettingsService::instance();
} }

View File

@@ -5,6 +5,7 @@
#include "models/usersmodel.h" #include "models/usersmodel.h"
class SettingsService;
class UsersViewModel : public QObject class UsersViewModel : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -27,10 +28,9 @@ signals:
void selectedUserNameChanged(); void selectedUserNameChanged();
private: private:
QString m_selectedUser; SettingsService *settings() const;
UsersModel m_usersModel; UsersModel m_usersModel;
SettingsService m_settings;
}; };
#endif // USERSVIEWMODEL_H #endif // USERSVIEWMODEL_H