Răsfoiți Sursa

Settings page was added

Denis V. Dedkov 2 ani în urmă
părinte
comite
25e8a3ea79

+ 0 - 4
CMakeLists.txt

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

+ 31 - 8
beerlog_ru_RU.ts

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

+ 10 - 0
main.cpp

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

+ 0 - 1
models/usersmodel.h

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

+ 17 - 5
qml/Components/MainMenu.qml

@@ -5,6 +5,7 @@ Drawer {
     property alias logo: logoImage.source
     property alias appName: appNameLabel.text
     property alias model: menuRepeater.model
+    property alias connected: connectionLabel.connected
 
     signal actionSelected(var action)
 
@@ -26,12 +27,23 @@ Drawer {
                 anchors.margins: 10
             }
 
-            Label {
-                id: appNameLabel
-
+            Column {
                 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"
+                }
             }
         }
 

+ 24 - 0
qml/Components/SubtitledItemDelegate.qml

@@ -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 - 0
qml/Components/qmldir

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

+ 66 - 3
qml/Views/SettingsView.qml

@@ -1,11 +1,74 @@
 import QtQuick 2.15
 import QtQuick.Controls 2.15
+import Components 1.0
 
 Page {
+    id: root
 
-    Label {
-        anchors.centerIn: parent
-        text: "Settings"
+    title: qsTr("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
+        }
+    }
 }

+ 13 - 4
qml/main.qml

@@ -5,7 +5,7 @@ import QtQuick.Layouts 1.15
 import QtWebSockets
 
 import ru.ded.beerlog 1.0
-import "Components"
+import Components 1.0
 
 ApplicationWindow {
     width: 640
@@ -16,15 +16,23 @@ ApplicationWindow {
     header: ToolBar {
         RowLayout {
             anchors.fill: parent
+
             MenuBackButton {
                 state: stackView.depth > 1 ? "back" : "menu"
                 onClicked: mainMenu.open()
                 onBack: stackView.pop()
             }
-            ToolButton {
-                text: usersModel.selectedUserName
+
+            Label {
+                text: stackView.currentItem.title || usersModel.selectedUserName
                 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"
         appName: qsTr("BeerLog v0.1")
+        connected: beerService.connected
 
         model: ListModel {
             ListElement {

+ 3 - 0
qml/qml.qrc

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

+ 32 - 9
services/beerservice.cpp

@@ -7,6 +7,8 @@
 #include <QFile>
 #include <QDebug>
 
+#include "settingsservice.h"
+
 BeerService::BeerService()
     : QObject{nullptr}
 {
@@ -38,6 +40,13 @@ BeerService::BeerService()
             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()
@@ -46,15 +55,9 @@ BeerService::~BeerService()
     m_socket.close();
 }
 
-void BeerService::connectSrv(const QString &userId)
+SettingsService *BeerService::settings() const
 {
-    if (QAbstractSocket::ConnectedState == m_socket.state()) {
-        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);
+    return SettingsService::instance();
 }
 
 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)
 {
-    if (QAbstractSocket::ConnectedState == m_socket.state()) {
+    if (connected()) {
         QJsonDocument doc = QJsonDocument::fromVariant(command);
         m_socket.sendTextMessage(doc.toJson(QJsonDocument::Compact));
     } else {
         m_commandStash << command;
     }
 }
+
+bool BeerService::connected() const
+{
+    return QAbstractSocket::ConnectedState == m_socket.state();
+}

+ 11 - 2
services/beerservice.h

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

+ 22 - 2
services/settingsservice.cpp

@@ -3,6 +3,14 @@
 namespace Defaults {
 
 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);
 }
 
+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
 {
-    return m_settings.value("selected_user", Defaults::GuestUserId).toString();
+    return m_settings.value(Keys::SelectedUser, Defaults::GuestUserId).toString();
 }
 
 void SettingsService::setSelectedUserId(const QString &userId)
 {
-    m_settings.setValue("selected_user", userId);
+    m_settings.setValue(Keys::SelectedUser, userId);
+    emit selectedUserIdChanged();
 }

+ 23 - 1
services/settingsservice.h

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

+ 13 - 14
viewmodels/usersviewmodel.cpp

@@ -1,18 +1,15 @@
 #include "usersviewmodel.h"
 
-#include "services/beerservice.h"
+#include "services/settingsservice.h"
 
 UsersViewModel::UsersViewModel(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::selectedUserNameChanged);
+
+    connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserChanged);
+    connect(settings(), &SettingsService::selectedUserIdChanged, this, &UsersViewModel::selectedUserNameChanged);
 }
 
 QVariantList UsersViewModel::users() const
@@ -22,22 +19,24 @@ QVariantList UsersViewModel::users() const
 
 QString UsersViewModel::selectedUser() const
 {
-    return m_selectedUser;
+    return settings()->selectedUserId();
 }
 
 void UsersViewModel::setSelectedUser(const QString &newSelectedUser)
 {
-    if (m_selectedUser == newSelectedUser) {
+    if (selectedUser() == newSelectedUser) {
         return;
     }
 
-    m_selectedUser = newSelectedUser;
-    m_settings.setSelectedUserId(m_selectedUser);
-    emit selectedUserChanged();
-    emit selectedUserNameChanged();
+    settings()->setSelectedUserId(newSelectedUser);
 }
 
 QString UsersViewModel::selectedUserName() const
 {
-    return m_usersModel.userName(m_selectedUser);
+    return m_usersModel.userName(selectedUser());
+}
+
+SettingsService *UsersViewModel::settings() const
+{
+    return SettingsService::instance();
 }

+ 2 - 2
viewmodels/usersviewmodel.h

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