diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cfe33175ba474f99167413f36ffd93f5e768b69..86d0849f8f871d08c806daa3836881082a08dd61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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(KF5Kirigami2 ${KF5_MIN_VERSION} REQUIRED) +find_package(KF5CoreAddons ${KF5_MIN_VERSION} REQUIRED) ################# Enable C++11 features for clang and gcc ################# diff --git a/packaging/org.eyecreate.qiflora.appdata.xml b/packaging/org.eyecreate.qiflora.appdata.xml index 88a638a8574a68bec51f81cdf557c75104e20648..46374aa5cdae9eed111e105c1cf9822edc001179 100644 --- a/packaging/org.eyecreate.qiflora.appdata.xml +++ b/packaging/org.eyecreate.qiflora.appdata.xml @@ -7,6 +7,8 @@ GPL-3.0-or-later https://git.eyecreate.org/eyecreate/qiflora + mailto:eyecreate@eyecreate.org + monero:49DAuwzCytB8cWVA8RXGcv1cviG2QRtZWW4U7KeX9mAtLfAewk8LAAwAUhwCRXD9tz8LESmgaAPrjZ62G8Z6JrdhRmLx2kY?tx_description=donation eyecreate

Mobile friendly application to monitor Mi Flora devices.

@@ -14,10 +16,15 @@
- https://git.eyecreate.org/eyecreate/qiflora/raw/v1.0/packaging/main_window.png + https://git.eyecreate.org/eyecreate/qiflora/raw/v1.1/packaging/main_window.png + + +

This release adds history graph for the last 48 hours.

+
+
diff --git a/packaging/org.eyecreate.qiflora.desktop b/packaging/org.eyecreate.qiflora.desktop index b57b8f64c0290a46c9f9e389a7fd70326145f314..8a66505afbc936de024e57e717830147637901a9 100755 --- a/packaging/org.eyecreate.qiflora.desktop +++ b/packaging/org.eyecreate.qiflora.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Name=QiFlora Comment=Monitor plants with Mi Flora sensors. -Version=1.0 +Version=1.1 Exec=qiflora MimeType=application/x-qiflora; Icon=org.eyecreate.qiflora diff --git a/packaging/org.eyecreate.qiflora.json b/packaging/org.eyecreate.qiflora.json index 4985978a376851b8be93a24c9aaa3b4d0610a1c4..9a47a2ff4171ec29f443ca237023f8a267278b2e 100644 --- a/packaging/org.eyecreate.qiflora.json +++ b/packaging/org.eyecreate.qiflora.json @@ -87,7 +87,7 @@ { "type": "git", "url": "https://git.eyecreate.org/eyecreate/qiflora.git", - "tag": "v1.0", + "tag": "v1.1", "commit": "bcdf831d0c64f84642f53a4f8376a26df412b819" } ] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a6b988838a99da639372fa0e0c68a512898095b..62d1271c389fb9422cd4726fdc4198209b768fde 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,5 +8,5 @@ set(qiflora_SRCS qt5_add_resources(RESOURCES resources.qrc) 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}) diff --git a/src/contents/ui/main.qml b/src/contents/ui/main.qml index dc25b93722eeb5302fd1f9ce724a93a036507714..2e6225d271d3621660bbbda66c831ae461d99ae1 100644 --- a/src/contents/ui/main.qml +++ b/src/contents/ui/main.qml @@ -1,5 +1,5 @@ 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.Layouts 1.12 as Layouts import QtCharts 2.3 as Charts @@ -12,6 +12,7 @@ Kirigami.ApplicationWindow { pageStack.initialPage: mainPageComponent + contextDrawer: Kirigami.ContextDrawer {} QiFlora { id: qiflora @@ -20,7 +21,8 @@ Kirigami.ApplicationWindow { Component { id: mainPageComponent - Kirigami.ScrollablePage { + Kirigami.Page { + id: mainPage mainAction: Kirigami.Action { iconName: "view-refresh" text: i18n("Query Device") @@ -28,131 +30,165 @@ Kirigami.ApplicationWindow { deviceSelect.open(); } } + contextualActions: [ + Kirigami.Action { + iconName: "help-about" + text: i18n("About") + onTriggered: { + pageStack.replace(aboutPageComponent); + } + } + ] title: "Monitor" + leftPadding: 0 + rightPadding: 0 - Kirigami.CardsListView { - id: monitorView - model: ListModel { - 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 + Layouts.ColumnLayout { + anchors.fill: parent + Kirigami.InlineMessage { + Layouts.Layout.fillWidth: true + Layouts.Layout.leftMargin: 10 + Layouts.Layout.rightMargin: 10 + z: 9997 + type: Kirigami.MessageType.Error + id: errorMessage + showCloseButton: true + Connections { + target: qiflora + onErrorHappened: { + errorMessage.text = description; + errorMessage.visible = true; + } } } - delegate: Kirigami.Card { - id: card - banner { - title: i18n(model.title) - titleIcon: model.icon - titleLevel: 2 - } - header: Row { - layoutDirection: Qt.RightToLeft - topPadding: 10.0 - rightPadding: 10.0 - Layouts.ColumnLayout { - Kirigami.Heading { - Layouts.Layout.alignment: Qt.AlignCenter - level: 4 - text: i18n("Last Measured") - } - 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" + Kirigami.CardsListView { + Layouts.Layout.fillWidth: true + Layouts.Layout.fillHeight: true + id: monitorView + model: ListModel { + 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 + } + } + + delegate: Kirigami.Card { + id: card + banner { + title: i18n(model.title) + titleIcon: model.icon + titleLevel: 2 + } + header: Row { + layoutDirection: Qt.RightToLeft + topPadding: 10.0 + rightPadding: 10.0 + Layouts.ColumnLayout { + Kirigami.Heading { + Layouts.Layout.alignment: Qt.AlignCenter + level: 4 + text: i18n("Last Measured") + } + 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 { - implicitWidth: 300 - implicitHeight: 200 - Charts.ChartView { - id: chart - antialiasing: true - backgroundColor: Kirigami.Theme.buttonBackgroundColor - titleColor: Kirigami.Theme.textColor - legend.visible: false - anchors.fill: parent - - Charts.LineSeries { - id: series - axisX: Charts.DateTimeAxis { - id: dateAx - labelsColor: Kirigami.Theme.textColor - 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 + contentItem: Item { + implicitWidth: 300 + implicitHeight: 200 + Charts.ChartView { + id: chart + antialiasing: true + backgroundColor: Kirigami.Theme.buttonBackgroundColor + titleColor: Kirigami.Theme.textColor + legend.visible: false + anchors.fill: parent - Charts.VXYModelMapper { - model: qiflora.model - xColumn: 0 - yColumn: modelCol + Charts.LineSeries { + id: series + axisX: Charts.DateTimeAxis { + id: dateAx + labelsColor: Kirigami.Theme.textColor + 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 + + } } - } - 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)); + 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 + } + } } diff --git a/src/main.cpp b/src/main.cpp index bb86898201983567899aec3a9e518db898e31337..b1f57fa11b52e6a39d9c0d6709619ff396daf5b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,19 +4,30 @@ #include #include "miflora/miflora.h" #include "miflora/bluetoothdevices.h" +#include +#include Q_DECL_EXPORT int main(int argc, char *argv[]) { QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 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::setOrganizationDomain("eyecreate.org"); - QCoreApplication::setApplicationName("qiflora"); + QCoreApplication::setApplicationName(aboutData.productName()); + QCoreApplication::setApplicationVersion(aboutData.version()); + app.setWindowIcon(QIcon::fromTheme("org.eyecreate.qiflora")); QQmlApplicationEngine engine; qmlRegisterType(); qmlRegisterType("org.eyecreate.qiflora",1,0,"QiFlora"); + engine.rootContext()->setContextProperty(QStringLiteral("appAboutData"), QVariant::fromValue(aboutData)); engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); if (engine.rootObjects().isEmpty()) { diff --git a/src/miflora/miflora.cpp b/src/miflora/miflora.cpp index 06f4a1e32ae08bd17aab4a557f4c938e75575daa..40f7c3961772d8291e982f3efd03e4ceff6c1454 100644 --- a/src/miflora/miflora.cpp +++ b/src/miflora/miflora.cpp @@ -77,11 +77,13 @@ QQmlListProperty MiFlora::getDeviceList() void MiFlora::logControllerError ( QLowEnergyController::Error err ) { qDebug() << "Error:" << err; + emit errorHappened(currentController->errorString()); } void MiFlora::logServiceError(QLowEnergyService::ServiceError err) { qDebug() << "Service Error:" << err; + emit errorHappened("Possible Read/Write error!"); } diff --git a/src/miflora/miflora.h b/src/miflora/miflora.h index 3bc910256f43b492d2ba7d3ee642759b680dd8d0..a7aea5bb54895e80b17b869553666018a567d28e 100644 --- a/src/miflora/miflora.h +++ b/src/miflora/miflora.h @@ -57,6 +57,7 @@ public: signals: void newDeviceFound(); void modelUpdated(); + void errorHappened(QString description); void temperatureChanged(float temperature); void brightnessChanged(quint32 brightness); void moistureChanged(quint8 moisture);