diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6655cd8..8d9c235 100644
--- a/CMakeLists.txt
+++ b/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)
diff --git a/beerlog_ru_RU.ts b/beerlog_ru_RU.ts
index 4c056ff..2dd95d2 100644
--- a/beerlog_ru_RU.ts
+++ b/beerlog_ru_RU.ts
@@ -4,9 +4,32 @@
MainMenu
-
- BeerLog v0.1
-
+
+ Online
+ В сети
+
+
+
+ Offline
+ Не в сети
+
+
+
+ SettingsView
+
+
+ Settings
+ Настройки
+
+
+
+ BeerLog service address
+ Адрес сервиса BeerLog
+
+
+
+ Selected user id
+ Выбранный пользователь
@@ -17,24 +40,24 @@
-
+
BeerLog v0.1
BeerLog v1.0.0
-
+
Settings
Настройки
-
-
+
+
Quit
Выход
-
+
Realy quit the application?
Действительно выйти из приложения?
diff --git a/main.cpp b/main.cpp
index 0cc090e..d0be815 100644
--- a/main.cpp
+++ b/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("ru.ded.beerlog", 1, 0, "UsersViewModel");
engine.load(url);
diff --git a/models/usersmodel.h b/models/usersmodel.h
index 728c333..382de44 100644
--- a/models/usersmodel.h
+++ b/models/usersmodel.h
@@ -4,7 +4,6 @@
#include
#include
-#include "services/settingsservice.h"
#include "models/abstractmodel.h"
class UsersModel : public AbstractModel
diff --git a/qml/Components/MainMenu.qml b/qml/Components/MainMenu.qml
index b962e26..5346d01 100644
--- a/qml/Components/MainMenu.qml
+++ b/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"
+ }
}
}
diff --git a/qml/Components/SubtitledItemDelegate.qml b/qml/Components/SubtitledItemDelegate.qml
new file mode 100644
index 0000000..df5d8d0
--- /dev/null
+++ b/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
+ }
+ }
+}
diff --git a/qml/Components/qmldir b/qml/Components/qmldir
new file mode 100644
index 0000000..5c956d0
--- /dev/null
+++ b/qml/Components/qmldir
@@ -0,0 +1,5 @@
+module Components
+
+MainMenu 1.0 MainMenu.qml
+MenuBackButton 1.0 MenuBackButton.qml
+SubtitledItemDelegate 1.0 SubtitledItemDelegate.qml
diff --git a/qml/Views/SettingsView.qml b/qml/Views/SettingsView.qml
index ed62c36..ff23454 100644
--- a/qml/Views/SettingsView.qml
+++ b/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
+ }
+ }
}
diff --git a/qml/main.qml b/qml/main.qml
index 5e094a7..a273d35 100644
--- a/qml/main.qml
+++ b/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 {
diff --git a/qml/qml.qrc b/qml/qml.qrc
index c5d13fd..ca1e243 100644
--- a/qml/qml.qrc
+++ b/qml/qml.qrc
@@ -8,5 +8,8 @@
Components/MainMenu.qml
Views/OrdersView.qml
Views/SettingsView.qml
+ Components/SubtitledItemDelegate.qml
+ Components/qmldir
+ qt_ru.qm
diff --git a/services/beerservice.cpp b/services/beerservice.cpp
index 741e5bc..823fcbb 100644
--- a/services/beerservice.cpp
+++ b/services/beerservice.cpp
@@ -7,6 +7,8 @@
#include
#include
+#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();
+}
diff --git a/services/beerservice.h b/services/beerservice.h
index d18a712..6eb506f 100644
--- a/services/beerservice.h
+++ b/services/beerservice.h
@@ -4,10 +4,13 @@
#include
#include
+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 m_listeners;
diff --git a/services/settingsservice.cpp b/services/settingsservice.cpp
index 194953f..f0ba617 100644
--- a/services/settingsservice.cpp
+++ b/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();
}
diff --git a/services/settingsservice.h b/services/settingsservice.h
index bbc3015..b0eac76 100644
--- a/services/settingsservice.h
+++ b/services/settingsservice.h
@@ -1,18 +1,40 @@
#ifndef SETTINGSSERVICE_H
#define SETTINGSSERVICE_H
+#include
#include
-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");
};
diff --git a/viewmodels/usersviewmodel.cpp b/viewmodels/usersviewmodel.cpp
index 0bb98ff..4eabb6a 100644
--- a/viewmodels/usersviewmodel.cpp
+++ b/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();
}
diff --git a/viewmodels/usersviewmodel.h b/viewmodels/usersviewmodel.h
index 892807f..d6edded 100644
--- a/viewmodels/usersviewmodel.h
+++ b/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