Update packaging and use KF5 for about screen. Implement basic notifications for error messages. Use icon for app icon.
This commit is contained in:
@@ -30,6 +30,7 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
|
|||||||
|
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2 Bluetooth Charts)
|
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2 Bluetooth Charts)
|
||||||
find_package(KF5Kirigami2 ${KF5_MIN_VERSION} REQUIRED)
|
find_package(KF5Kirigami2 ${KF5_MIN_VERSION} REQUIRED)
|
||||||
|
find_package(KF5CoreAddons ${KF5_MIN_VERSION} REQUIRED)
|
||||||
|
|
||||||
################# Enable C++11 features for clang and gcc #################
|
################# Enable C++11 features for clang and gcc #################
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
<project_license>GPL-3.0-or-later</project_license>
|
<project_license>GPL-3.0-or-later</project_license>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
<url type="homepage">https://git.eyecreate.org/eyecreate/qiflora</url>
|
<url type="homepage">https://git.eyecreate.org/eyecreate/qiflora</url>
|
||||||
|
<url type="contact">mailto:eyecreate@eyecreate.org</url>
|
||||||
|
<url type="donation">monero:49DAuwzCytB8cWVA8RXGcv1cviG2QRtZWW4U7KeX9mAtLfAewk8LAAwAUhwCRXD9tz8LESmgaAPrjZ62G8Z6JrdhRmLx2kY?tx_description=donation</url>
|
||||||
<developer_name>eyecreate</developer_name>
|
<developer_name>eyecreate</developer_name>
|
||||||
<description>
|
<description>
|
||||||
<p>Mobile friendly application to monitor Mi Flora devices.</p>
|
<p>Mobile friendly application to monitor Mi Flora devices.</p>
|
||||||
@@ -14,10 +16,15 @@
|
|||||||
</description>
|
</description>
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<image type="source">https://git.eyecreate.org/eyecreate/qiflora/raw/v1.0/packaging/main_window.png</image>
|
<image type="source">https://git.eyecreate.org/eyecreate/qiflora/raw/v1.1/packaging/main_window.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<releases>
|
<releases>
|
||||||
<release version="1.0" date="2019-11-8" type="stable"/>
|
<release version="1.0" date="2019-11-8" type="stable"/>
|
||||||
|
<release version="1.1" date="2019-11-13" type="stable">
|
||||||
|
<description>
|
||||||
|
<p>This release adds history graph for the last 48 hours.</p>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
</releases>
|
</releases>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=QiFlora
|
Name=QiFlora
|
||||||
Comment=Monitor plants with Mi Flora sensors.
|
Comment=Monitor plants with Mi Flora sensors.
|
||||||
Version=1.0
|
Version=1.1
|
||||||
Exec=qiflora
|
Exec=qiflora
|
||||||
MimeType=application/x-qiflora;
|
MimeType=application/x-qiflora;
|
||||||
Icon=org.eyecreate.qiflora
|
Icon=org.eyecreate.qiflora
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.eyecreate.org/eyecreate/qiflora.git",
|
"url": "https://git.eyecreate.org/eyecreate/qiflora.git",
|
||||||
"tag": "v1.0",
|
"tag": "v1.1",
|
||||||
"commit": "bcdf831d0c64f84642f53a4f8376a26df412b819"
|
"commit": "bcdf831d0c64f84642f53a4f8376a26df412b819"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ set(qiflora_SRCS
|
|||||||
|
|
||||||
qt5_add_resources(RESOURCES resources.qrc)
|
qt5_add_resources(RESOURCES resources.qrc)
|
||||||
add_executable(qiflora ${qiflora_SRCS} ${RESOURCES})
|
add_executable(qiflora ${qiflora_SRCS} ${RESOURCES})
|
||||||
target_link_libraries(qiflora Qt5::Core Qt5::Qml Qt5::Quick Qt5::Svg Qt5::Bluetooth Qt5::Charts)
|
target_link_libraries(qiflora Qt5::Core Qt5::Qml Qt5::Quick Qt5::Svg Qt5::Bluetooth Qt5::Charts KF5::CoreAddons)
|
||||||
install(TARGETS qiflora ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
|
install(TARGETS qiflora ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import org.kde.kirigami 2.4 as Kirigami
|
import org.kde.kirigami 2.6 as Kirigami
|
||||||
import QtQuick.Controls 2.0 as Controls
|
import QtQuick.Controls 2.0 as Controls
|
||||||
import QtQuick.Layouts 1.12 as Layouts
|
import QtQuick.Layouts 1.12 as Layouts
|
||||||
import QtCharts 2.3 as Charts
|
import QtCharts 2.3 as Charts
|
||||||
@@ -12,6 +12,7 @@ Kirigami.ApplicationWindow {
|
|||||||
|
|
||||||
|
|
||||||
pageStack.initialPage: mainPageComponent
|
pageStack.initialPage: mainPageComponent
|
||||||
|
contextDrawer: Kirigami.ContextDrawer {}
|
||||||
|
|
||||||
QiFlora {
|
QiFlora {
|
||||||
id: qiflora
|
id: qiflora
|
||||||
@@ -20,7 +21,8 @@ Kirigami.ApplicationWindow {
|
|||||||
Component {
|
Component {
|
||||||
id: mainPageComponent
|
id: mainPageComponent
|
||||||
|
|
||||||
Kirigami.ScrollablePage {
|
Kirigami.Page {
|
||||||
|
id: mainPage
|
||||||
mainAction: Kirigami.Action {
|
mainAction: Kirigami.Action {
|
||||||
iconName: "view-refresh"
|
iconName: "view-refresh"
|
||||||
text: i18n("Query Device")
|
text: i18n("Query Device")
|
||||||
@@ -28,131 +30,165 @@ Kirigami.ApplicationWindow {
|
|||||||
deviceSelect.open();
|
deviceSelect.open();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
contextualActions: [
|
||||||
|
Kirigami.Action {
|
||||||
|
iconName: "help-about"
|
||||||
|
text: i18n("About")
|
||||||
|
onTriggered: {
|
||||||
|
pageStack.replace(aboutPageComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
title: "Monitor"
|
title: "Monitor"
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
|
||||||
Kirigami.CardsListView {
|
Layouts.ColumnLayout {
|
||||||
id: monitorView
|
anchors.fill: parent
|
||||||
model: ListModel {
|
Kirigami.InlineMessage {
|
||||||
id: monitorTypes
|
Layouts.Layout.fillWidth: true
|
||||||
ListElement{
|
Layouts.Layout.leftMargin: 10
|
||||||
chartType: "temperature"
|
Layouts.Layout.rightMargin: 10
|
||||||
title: "Temperature"
|
z: 9997
|
||||||
icon: "filename-bpm-amarok"
|
type: Kirigami.MessageType.Error
|
||||||
lineColor: "red"
|
id: errorMessage
|
||||||
yMin: -20
|
showCloseButton: true
|
||||||
yMax: 40
|
Connections {
|
||||||
modelCol: 1
|
target: qiflora
|
||||||
}
|
onErrorHappened: {
|
||||||
ListElement{
|
errorMessage.text = description;
|
||||||
chartType: "moisture"
|
errorMessage.visible = true;
|
||||||
title: "Moisture"
|
}
|
||||||
icon: "colors-chromablue"
|
|
||||||
lineColor: "cyan"
|
|
||||||
yMin: 0
|
|
||||||
yMax: 75
|
|
||||||
modelCol: 3
|
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
chartType: "conductivity"
|
|
||||||
title: "Conductivity"
|
|
||||||
icon: "quickopen"
|
|
||||||
lineColor: "gold"
|
|
||||||
yMin: 0
|
|
||||||
yMax: 6000
|
|
||||||
modelCol: 4
|
|
||||||
}
|
|
||||||
ListElement{
|
|
||||||
chartType: "brightness"
|
|
||||||
title: "Brightness"
|
|
||||||
icon: "contrast"
|
|
||||||
lineColor: "orange"
|
|
||||||
yMin: 0
|
|
||||||
yMax: 30000
|
|
||||||
modelCol: 2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Kirigami.Card {
|
Kirigami.CardsListView {
|
||||||
id: card
|
Layouts.Layout.fillWidth: true
|
||||||
banner {
|
Layouts.Layout.fillHeight: true
|
||||||
title: i18n(model.title)
|
id: monitorView
|
||||||
titleIcon: model.icon
|
model: ListModel {
|
||||||
titleLevel: 2
|
id: monitorTypes
|
||||||
|
ListElement{
|
||||||
|
chartType: "temperature"
|
||||||
|
title: "Temperature"
|
||||||
|
icon: "filename-bpm-amarok"
|
||||||
|
lineColor: "red"
|
||||||
|
yMin: -20
|
||||||
|
yMax: 40
|
||||||
|
modelCol: 1
|
||||||
|
}
|
||||||
|
ListElement{
|
||||||
|
chartType: "moisture"
|
||||||
|
title: "Moisture"
|
||||||
|
icon: "colors-chromablue"
|
||||||
|
lineColor: "cyan"
|
||||||
|
yMin: 0
|
||||||
|
yMax: 75
|
||||||
|
modelCol: 3
|
||||||
|
}
|
||||||
|
ListElement{
|
||||||
|
chartType: "conductivity"
|
||||||
|
title: "Conductivity"
|
||||||
|
icon: "quickopen"
|
||||||
|
lineColor: "gold"
|
||||||
|
yMin: 0
|
||||||
|
yMax: 6000
|
||||||
|
modelCol: 4
|
||||||
|
}
|
||||||
|
ListElement{
|
||||||
|
chartType: "brightness"
|
||||||
|
title: "Brightness"
|
||||||
|
icon: "contrast"
|
||||||
|
lineColor: "orange"
|
||||||
|
yMin: 0
|
||||||
|
yMax: 30000
|
||||||
|
modelCol: 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
header: Row {
|
|
||||||
layoutDirection: Qt.RightToLeft
|
delegate: Kirigami.Card {
|
||||||
topPadding: 10.0
|
id: card
|
||||||
rightPadding: 10.0
|
banner {
|
||||||
Layouts.ColumnLayout {
|
title: i18n(model.title)
|
||||||
Kirigami.Heading {
|
titleIcon: model.icon
|
||||||
Layouts.Layout.alignment: Qt.AlignCenter
|
titleLevel: 2
|
||||||
level: 4
|
}
|
||||||
text: i18n("Last Measured")
|
header: Row {
|
||||||
}
|
layoutDirection: Qt.RightToLeft
|
||||||
Kirigami.Heading {
|
topPadding: 10.0
|
||||||
Layouts.Layout.alignment: Qt.AlignCenter
|
rightPadding: 10.0
|
||||||
level: 3
|
Layouts.ColumnLayout {
|
||||||
text: {
|
Kirigami.Heading {
|
||||||
if(model.chartType == "temperature") qiflora.temperature + "°C\n" + (qiflora.temperature*1.8+32) + "°F"
|
Layouts.Layout.alignment: Qt.AlignCenter
|
||||||
else if(model.chartType == "moisture") qiflora.moisture + "%"
|
level: 4
|
||||||
else if(model.chartType == "conductivity") qiflora.conduction + " µS/cm"
|
text: i18n("Last Measured")
|
||||||
else if(model.chartType == "brightness") qiflora.brightness + " lux"
|
}
|
||||||
|
Kirigami.Heading {
|
||||||
|
Layouts.Layout.alignment: Qt.AlignCenter
|
||||||
|
level: 3
|
||||||
|
text: {
|
||||||
|
if(model.chartType == "temperature") qiflora.temperature + "°C\n" + (qiflora.temperature*1.8+32) + "°F"
|
||||||
|
else if(model.chartType == "moisture") qiflora.moisture + "%"
|
||||||
|
else if(model.chartType == "conductivity") qiflora.conduction + " µS/cm"
|
||||||
|
else if(model.chartType == "brightness") qiflora.brightness + " lux"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
contentItem: Item {
|
||||||
contentItem: Item {
|
implicitWidth: 300
|
||||||
implicitWidth: 300
|
implicitHeight: 200
|
||||||
implicitHeight: 200
|
Charts.ChartView {
|
||||||
Charts.ChartView {
|
id: chart
|
||||||
id: chart
|
antialiasing: true
|
||||||
antialiasing: true
|
backgroundColor: Kirigami.Theme.buttonBackgroundColor
|
||||||
backgroundColor: Kirigami.Theme.buttonBackgroundColor
|
titleColor: Kirigami.Theme.textColor
|
||||||
titleColor: Kirigami.Theme.textColor
|
legend.visible: false
|
||||||
legend.visible: false
|
anchors.fill: parent
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Charts.LineSeries {
|
Charts.LineSeries {
|
||||||
id: series
|
id: series
|
||||||
axisX: Charts.DateTimeAxis {
|
axisX: Charts.DateTimeAxis {
|
||||||
id: dateAx
|
id: dateAx
|
||||||
labelsColor: Kirigami.Theme.textColor
|
labelsColor: Kirigami.Theme.textColor
|
||||||
format: "MMM d yyyy ha"
|
format: "MMM d yyyy ha"
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
//On load, change date span to last 24 to remove awkward 1969 empty dates.
|
||||||
|
var yesterday = new Date();
|
||||||
|
yesterday.setDate(yesterday.getDate() -1);
|
||||||
|
dateAx.min = yesterday;
|
||||||
|
dateAx.max = new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axisY: Charts.ValueAxis {
|
||||||
|
id: valueAx
|
||||||
|
labelsColor: Kirigami.Theme.textColor
|
||||||
|
min: yMin
|
||||||
|
max: yMax
|
||||||
|
}
|
||||||
|
color: model.lineColor
|
||||||
|
name: model.title
|
||||||
|
|
||||||
|
Charts.VXYModelMapper {
|
||||||
|
model: qiflora.model
|
||||||
|
xColumn: 0
|
||||||
|
yColumn: modelCol
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
//On load, change date span to last 24 to remove awkward 1969 empty dates.
|
|
||||||
var yesterday = new Date();
|
|
||||||
yesterday.setDate(yesterday.getDate() -1);
|
|
||||||
dateAx.min = yesterday;
|
|
||||||
dateAx.max = new Date();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
axisY: Charts.ValueAxis {
|
Connections {
|
||||||
id: valueAx
|
target: qiflora.model
|
||||||
labelsColor: Kirigami.Theme.textColor
|
onRowsInserted: {
|
||||||
min: yMin
|
//Readjust graphs to show date range from earliest item.
|
||||||
max: yMax
|
dateAx.max = new Date();
|
||||||
|
dateAx.min = qiflora.model.data(qiflora.model.index(0,0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
color: model.lineColor
|
}
|
||||||
name: model.title
|
|
||||||
|
|
||||||
Charts.VXYModelMapper {
|
|
||||||
model: qiflora.model
|
|
||||||
xColumn: 0
|
|
||||||
yColumn: modelCol
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Connections {
|
|
||||||
target: qiflora.model
|
|
||||||
onRowsInserted: {
|
|
||||||
//Readjust graphs to show date range from earliest item.
|
|
||||||
dateAx.max = new Date();
|
|
||||||
dateAx.min = qiflora.model.data(qiflora.model.index(0,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Controls.ScrollBar.vertical: Controls.ScrollBar {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,4 +238,20 @@ Kirigami.ApplicationWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id:aboutPageComponent
|
||||||
|
Kirigami.AboutPage {
|
||||||
|
id: aboutPage
|
||||||
|
actions.main: Kirigami.Action {
|
||||||
|
iconName: "window-close"
|
||||||
|
text: "Close"
|
||||||
|
onTriggered: {
|
||||||
|
pageStack.clear();
|
||||||
|
pageStack.push(mainPageComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aboutData: appAboutData
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/main.cpp
13
src/main.cpp
@@ -4,19 +4,30 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include "miflora/miflora.h"
|
#include "miflora/miflora.h"
|
||||||
#include "miflora/bluetoothdevices.h"
|
#include "miflora/bluetoothdevices.h"
|
||||||
|
#include <KAboutData>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
Q_DECL_EXPORT int main(int argc, char *argv[])
|
Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
KAboutData aboutData("org.eyecreate.qiflora", "QiFlora", "1.1", "Mobile friendly application to monitor Mi Flora devices.",KAboutLicense::GPL_V3);//TODO:i18n
|
||||||
|
aboutData.setProductName("qiflora");
|
||||||
|
aboutData.addAuthor("Kevin Whitaker",QString(),"eyecreate@eyecreate.org","https://www.eyecreate.org");
|
||||||
|
aboutData.setDesktopFileName("org.eyecreate.qiflora");
|
||||||
|
|
||||||
QCoreApplication::setOrganizationName("eyecreate");
|
QCoreApplication::setOrganizationName("eyecreate");
|
||||||
QCoreApplication::setOrganizationDomain("eyecreate.org");
|
QCoreApplication::setOrganizationDomain("eyecreate.org");
|
||||||
QCoreApplication::setApplicationName("qiflora");
|
QCoreApplication::setApplicationName(aboutData.productName());
|
||||||
|
QCoreApplication::setApplicationVersion(aboutData.version());
|
||||||
|
app.setWindowIcon(QIcon::fromTheme("org.eyecreate.qiflora"));
|
||||||
|
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
qmlRegisterType<BluetoothDevices>();
|
qmlRegisterType<BluetoothDevices>();
|
||||||
qmlRegisterType<MiFlora>("org.eyecreate.qiflora",1,0,"QiFlora");
|
qmlRegisterType<MiFlora>("org.eyecreate.qiflora",1,0,"QiFlora");
|
||||||
|
engine.rootContext()->setContextProperty(QStringLiteral("appAboutData"), QVariant::fromValue(aboutData));
|
||||||
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
||||||
|
|
||||||
if (engine.rootObjects().isEmpty()) {
|
if (engine.rootObjects().isEmpty()) {
|
||||||
|
|||||||
@@ -77,11 +77,13 @@ QQmlListProperty<BluetoothDevices> MiFlora::getDeviceList()
|
|||||||
void MiFlora::logControllerError ( QLowEnergyController::Error err )
|
void MiFlora::logControllerError ( QLowEnergyController::Error err )
|
||||||
{
|
{
|
||||||
qDebug() << "Error:" << err;
|
qDebug() << "Error:" << err;
|
||||||
|
emit errorHappened(currentController->errorString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiFlora::logServiceError(QLowEnergyService::ServiceError err)
|
void MiFlora::logServiceError(QLowEnergyService::ServiceError err)
|
||||||
{
|
{
|
||||||
qDebug() << "Service Error:" << err;
|
qDebug() << "Service Error:" << err;
|
||||||
|
emit errorHappened("Possible Read/Write error!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void newDeviceFound();
|
void newDeviceFound();
|
||||||
void modelUpdated();
|
void modelUpdated();
|
||||||
|
void errorHappened(QString description);
|
||||||
void temperatureChanged(float temperature);
|
void temperatureChanged(float temperature);
|
||||||
void brightnessChanged(quint32 brightness);
|
void brightnessChanged(quint32 brightness);
|
||||||
void moistureChanged(quint8 moisture);
|
void moistureChanged(quint8 moisture);
|
||||||
|
|||||||
Reference in New Issue
Block a user