Import brew logs added.

Tue, 02 Aug 2022 20:18:05 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 02 Aug 2022 20:18:05 +0200
changeset 387
7945bf3be1f9
parent 386
2e30c9c20d22
child 388
5eea69925634

Import brew logs added.

CMakeLists.txt file | annotate | diff | comparison | revisions
src/ImportBrew.cpp file | annotate | diff | comparison | revisions
src/ImportBrew.h file | annotate | diff | comparison | revisions
src/MainWindow.cpp file | annotate | diff | comparison | revisions
src/MainWindow.h file | annotate | diff | comparison | revisions
translations/bmsapp_en.ts file | annotate | diff | comparison | revisions
translations/bmsapp_nl.ts file | annotate | diff | comparison | revisions
ui/ImportBrew.ui file | annotate | diff | comparison | revisions
ui/MainWindow.ui file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Mon Aug 01 21:49:57 2022 +0200
+++ b/CMakeLists.txt	Tue Aug 02 20:18:05 2022 +0200
@@ -230,6 +230,7 @@
     ${SRCDIR}/ChartiSpindel.cpp
     ${SRCDIR}/EditProduct.cpp
     ${SRCDIR}/ImportXML.cpp
+    ${SRCDIR}/ImportBrew.cpp
     ${SRCDIR}/Setup.cpp
     ${SRCDIR}/Utils.cpp
     ${SRCDIR}/PrinterDialog.cpp
@@ -294,6 +295,7 @@
     ${SRCDIR}/ChartiSpindel.h
     ${SRCDIR}/EditProduct.h
     ${SRCDIR}/ImportXML.h
+    ${SRCDIR}/ImportBrew.h
     ${SRCDIR}/Setup.h
     ${SRCDIR}/Utils.h
     ${SRCDIR}/PrinterDialog.h
@@ -334,6 +336,7 @@
     ${UIDIR}/DetailCO2meter.ui
     ${UIDIR}/DetailiSpindel.ui
     ${UIDIR}/ImportXML.ui
+    ${UIDIR}/ImportBrew.ui
     ${UIDIR}/MainWindow.ui
   )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ImportBrew.cpp	Tue Aug 02 20:18:05 2022 +0200
@@ -0,0 +1,208 @@
+/**
+ * ImportBrew.cpp is part of bmsapp.
+ *
+ * bmsapp is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * bmsapp is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "ImportBrew.h"
+#include "../ui/ui_ImportBrew.h"
+#include "global.h"
+#include "Utils.h"
+#include "database/db_product.h"
+#include "MainWindow.h"
+
+
+ImportBrew::ImportBrew(QWidget *parent) : QDialog(parent), ui(new Ui::ImportBrew)
+{
+    qDebug() << "ImportBrew start";
+    ui->setupUi(this);
+    WindowTitle();
+    ui->progressBar->setValue(0);
+    connect(ui->quitButton, SIGNAL(clicked()), parent, SLOT(fromImportBrew()));
+}
+
+
+ImportBrew::~ImportBrew()
+{
+    qDebug() << "ImportBrew done";
+    delete ui;
+}
+
+
+void ImportBrew::WindowTitle()
+{
+    QString txt = QString(tr("BMSapp - Import Brewlog"));
+    setWindowTitle(txt);
+}
+
+
+void ImportBrew::on_openButton_clicked()
+{
+    QSqlQuery query;
+    QString   log, sql, code, name, uuid;
+    int total = 0, errors = 0, updates = 0;
+
+    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::homePath() + "/*.json", tr("Files (*.json)"));
+    if (fileName == 0) {
+        QMessageBox::warning(this, tr("Open File"), tr("No Brewlog JSON file selected."));
+        return;
+    }
+    ui->fileEdit->setText(fileName);
+
+    QFile file(fileName);
+    qint64 fsize = file.size();
+
+    log = "Import Brewlog file `" + fileName + "`\n\n"; 
+    qInfo() << "Import Brewlog" << fileName << "length" << fsize << "bytes";
+
+    file.open(QIODevice::ReadOnly);
+    QByteArray val = file.readAll();
+    file.close();
+
+    QJsonParseError parseError;
+    QJsonDocument brewlog = QJsonDocument::fromJson(val, &parseError);
+    if (parseError.error != QJsonParseError::NoError) {
+	qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
+    } else {
+	QJsonObject root = brewlog.object();
+	QJsonValue value = root.value(QString("brew"));
+
+	/*
+	 * The logfile is a array with just 1 item.
+	 */
+	QJsonArray array = value.toArray();
+	foreach (const QJsonValue & v, array) {
+	    /*
+	     * 4 items in a object is a complete brewlog.
+	     */
+	    QString Recipe = v.toObject().value("Recipe").toString();
+	    QDateTime Date = QDateTime::fromString(v.toObject().value("Date").toString());
+	    QJsonArray data = v.toObject().value("brewdata").toArray();
+	    QJsonArray events = v.toObject().value("annotations").toArray();
+	    qDebug() << Recipe << Date << data.size() << events.size();
+	    code = Recipe.split(" ").at(0);
+	    name = Recipe.remove(0, code.size() + 1);
+	    log.append(QString(tr("Brew: ") + code + " " + name + "\n"));
+
+	    sql = "SELECT uuid FROM products WHERE code='" + code + "'";
+	    query.exec(sql);
+	    if (query.first()) {
+		uuid = query.value(0).toString();
+		qDebug() << uuid;
+	    } else {
+		uuid = "";
+		errors++;
+		qWarning() << "ImportBrew" << code << "product not found";
+		continue;
+	    }
+
+	    sql = "DELETE FROM log_brews WHERE code='" + code + "'";
+	    query.exec(sql);
+	    if (query.numRowsAffected() > 0) {
+		log.append(QString(tr("Deleted %1 old records\n")).arg(query.numRowsAffected()));
+	    	qDebug() << "ImportBrew deleted" << query.numRowsAffected();
+	    }
+
+	    for (int j = 0; j < data.size(); j++) {
+		
+		QJsonObject obj = data.at(j).toObject();
+
+		/*
+		 * It's fucking crazy that despite all Googling this cannot be
+		 * done with an internal function. All examples are not working
+		 * for this very very simple problem, add the time string converted
+		 * to QTime to a QDateTime.
+		 *
+		 * Solution that always works, split the string, and do the math.
+		 */
+		QStringList Times = obj["Label"].toString().split(":");
+		int seconds = Times[0].toInt() * 3600 + Times[1].toInt() * 60;
+		QDateTime logDate = Date.addSecs(seconds);
+		QString dt = logDate.toString("yyyy-MM-dd HH:mm:ss");
+
+		sql = "INSERT INTO log_brews SET version='2', datetime='" + dt + "'";
+		sql.append(", uuid='" + uuid + "'");
+		sql.append(", code='" + code + "'");
+		sql.append(", name='" + name + "'");
+		sql.append(", pv_mlt='" + obj["MLT_pv"].toString() + "'");
+		sql.append(", sp_mlt='" + obj["MLT_sp"].toString() + "'");
+		sql.append(", pwm_mlt='" + obj["MLT_pwm"].toString() + "'");
+		if (obj["HLT_pv"].toString().size()) {
+		    sql.append(", pv_hlt='" + obj["HLT_pv"].toString() + "'");
+		    sql.append(", sp_hlt='" + obj["HLT_sp"].toString() + "'");
+		    sql.append(", pwm_hlt='" + obj["HLT_pwm"].toString() + "'");
+		}
+		//qDebug() << sql;
+
+		query.exec(sql);
+		if (query.lastError().isValid()) {
+        	    qWarning() << "ImportBrew" << query.lastError();
+		    errors++;
+		}
+		total++;
+
+		/*
+		 * The first 90% is for the normal data
+		 */
+		ui->progressBar->setValue((total * 90) / data.size());
+	    }
+	    log.append(QString(tr("Inserted %1 new records\n")).arg(total - errors));
+
+	    /*
+	     * Update events, they are annotations in the json file.
+	     */
+	    for (int j = 0; j < events.size(); j++) {
+
+                QJsonObject obj = events.at(j).toObject();
+
+		QStringList Times = obj["value"].toString().split(":");
+                int seconds = Times[0].toInt() * 3600 + Times[1].toInt() * 60;
+                QDateTime logDate = Date.addSecs(seconds);
+                QString dt = logDate.toString("yyyy-MM-dd HH:mm:ss");
+		QJsonObject label = obj["label"].toObject();
+		QString evt = label["content"].toString();
+
+		sql = "UPDATE log_brews SET event='" + evt + "' WHERE datetime='" + dt + "' AND uuid='" + uuid + "'";
+		//qDebug() << sql;
+		query.exec(sql);
+                if (query.lastError().isValid()) {
+                    qWarning() << "ImportBrew" << query.lastError();
+                    errors++;
+                } else {
+		    updates++;
+		}
+
+		/*
+		 * The last 10% is for the updates.
+		 */
+		ui->progressBar->setValue(((updates * 10) / events.size()) + 90);
+	    }
+	    log.append(QString(tr("Updated %1 records with events\n")).arg(updates));
+
+	    if (errors == 0) {
+		sql = "UPDATE products SET log_brew=1 WHERE code='" + code + "'";
+		query.exec(sql);
+		if (query.numRowsAffected())
+		    log.append(QString(tr("Marked brew graph available in product\n")));
+	    }
+	}
+
+    }
+
+    ui->logEdit->setPlainText(log);
+    qInfo() << "Import" << total << "records, " << total - errors << "ok, " << errors << "errors";
+
+    ui->progressBar->setValue(100);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ImportBrew.h	Tue Aug 02 20:18:05 2022 +0200
@@ -0,0 +1,28 @@
+#ifndef _IMPORTBREW_H
+#define _IMPORTBREW_H
+
+#include <QDialog>
+#include <QJsonDocument>
+
+namespace Ui {
+class ImportBrew;
+}
+
+class ImportBrew : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit ImportBrew(QWidget *parent = 0);
+    ~ImportBrew();
+
+private slots:
+    void on_openButton_clicked();
+
+private:
+    Ui::ImportBrew *ui;
+
+    void WindowTitle();
+};
+
+#endif
--- a/src/MainWindow.cpp	Mon Aug 01 21:49:57 2022 +0200
+++ b/src/MainWindow.cpp	Tue Aug 02 20:18:05 2022 +0200
@@ -38,6 +38,7 @@
 #include "MonCO2meters.h"
 #include "MoniSpindels.h"
 #include "ImportXML.h"
+#include "ImportBrew.h"
 #include "Setup.h"
 #include "PrinterDialog.h"
 #include "../ui/ui_MainWindow.h"
@@ -413,6 +414,27 @@
 }
 
 
+void MainWindow::fromImportBrew()
+{
+    ui->mainStack->setCurrentIndex(-1);
+    ui->mainStack->removeWidget(ImportBrewWindow);
+    delete ImportBrewWindow;
+    setWindowTitle( QString("BMSapp - %1").arg(VERSIONSTRING) );
+    ui->menuBar->setVisible(true);
+}
+
+
+void MainWindow::on_actionImport_Brew_triggered()
+{
+    ImportBrewWindow = new ImportBrew(this);
+    int index = ui->mainStack->count();
+    ui->mainStack->addWidget(ImportBrewWindow);
+    ui->mainStack->setCurrentIndex(index);
+    setWindowTitle( QString("BMSapp - %1 - Import Brewlog").arg(VERSIONSTRING));
+    ui->menuBar->setVisible(false);
+}
+
+
 void MainWindow::fromMonNodes()
 {
     ui->mainStack->setCurrentIndex(-1);
--- a/src/MainWindow.h	Mon Aug 01 21:49:57 2022 +0200
+++ b/src/MainWindow.h	Tue Aug 02 20:18:05 2022 +0200
@@ -23,6 +23,7 @@
 #include "MonCO2meters.h"
 #include "MoniSpindels.h"
 #include "ImportXML.h"
+#include "ImportBrew.h"
 #include "Setup.h"
 
 #include <QMainWindow>
@@ -133,6 +134,7 @@
     MonCO2meters *MonCO2metersWindow;
     MoniSpindels *MoniSpindelsWindow;
     ImportXML *ImportXMLWindow;
+    ImportBrew *ImportBrewWindow;
     Setup *SetupWindow;
 
 signals:
@@ -143,6 +145,7 @@
 
 private slots:
     void on_actionImport_XML_triggered();
+    void on_actionImport_Brew_triggered();
     void on_actionExit_triggered();
     void on_actionMon_Nodes_triggered();
     void on_actionMon_Fermenters_triggered();
@@ -175,6 +178,7 @@
 
 public slots:
     void fromImportXML();
+    void fromImportBrew();
     void fromMonNodes();
     void fromMonFermenters();
     void fromMonCO2meters();
--- a/translations/bmsapp_en.ts	Mon Aug 01 21:49:57 2022 +0200
+++ b/translations/bmsapp_en.ts	Tue Aug 02 20:18:05 2022 +0200
@@ -8080,6 +8080,84 @@
     </message>
 </context>
 <context>
+    <name>ImportBrew</name>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="14"/>
+        <source>Dialog</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="29"/>
+        <source>Brew logfile:</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="64"/>
+        <source>Quit</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="84"/>
+        <source>Open</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="101"/>
+        <source>Results</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="44"/>
+        <source>BMSapp - Import Brewlog</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="55"/>
+        <location filename="../src/ImportBrew.cpp" line="57"/>
+        <source>Open File</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="55"/>
+        <source>Files (*.json)</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="57"/>
+        <source>No Brewlog JSON file selected.</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="95"/>
+        <source>Brew: </source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="112"/>
+        <source>Deleted %1 old records
+</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="159"/>
+        <source>Inserted %1 new records
+</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="190"/>
+        <source>Updated %1 records with events
+</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="196"/>
+        <source>Marked brew graph available in product
+</source>
+        <translation type="unfinished"></translation>
+    </message>
+</context>
+<context>
     <name>ImportXML</name>
     <message>
         <location filename="../ui/ImportXML.ui" line="14"/>
@@ -8721,218 +8799,223 @@
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="55"/>
+        <location filename="../ui/MainWindow.ui" line="56"/>
         <source>Help</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="61"/>
+        <location filename="../ui/MainWindow.ui" line="62"/>
         <source>Settings</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="72"/>
+        <location filename="../ui/MainWindow.ui" line="73"/>
         <source>Inventory</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="88"/>
+        <location filename="../ui/MainWindow.ui" line="89"/>
         <source>Monitor</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="99"/>
+        <location filename="../ui/MainWindow.ui" line="100"/>
         <source>Products</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="103"/>
-        <location filename="../ui/MainWindow.ui" line="362"/>
+        <location filename="../ui/MainWindow.ui" line="104"/>
+        <location filename="../ui/MainWindow.ui" line="363"/>
         <source>Archive</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="132"/>
-        <location filename="../ui/MainWindow.ui" line="335"/>
+        <location filename="../ui/MainWindow.ui" line="133"/>
+        <location filename="../ui/MainWindow.ui" line="336"/>
         <source>Recipes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="155"/>
+        <location filename="../ui/MainWindow.ui" line="156"/>
         <source>Exit</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="164"/>
+        <location filename="../ui/MainWindow.ui" line="165"/>
         <source>About</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="450"/>
+        <location filename="../ui/MainWindow.ui" line="451"/>
         <source>Fermenters</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="468"/>
+        <location filename="../ui/MainWindow.ui" line="469"/>
         <source>iSpindels</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="173"/>
+        <location filename="../ui/MainWindow.ui" line="174"/>
         <source>Suppliers</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="116"/>
+        <location filename="../ui/MainWindow.ui" line="117"/>
         <source>Reports</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="185"/>
+        <location filename="../ui/MainWindow.ui" line="186"/>
         <source>Fermentables</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="197"/>
+        <location filename="../ui/MainWindow.ui" line="198"/>
         <source>Hops</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="209"/>
+        <location filename="../ui/MainWindow.ui" line="210"/>
         <source>Yeasts</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="221"/>
+        <location filename="../ui/MainWindow.ui" line="222"/>
         <source>Miscs</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="233"/>
+        <location filename="../ui/MainWindow.ui" line="234"/>
         <source>Waters</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="245"/>
+        <location filename="../ui/MainWindow.ui" line="246"/>
         <source>Equipments</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="257"/>
+        <location filename="../ui/MainWindow.ui" line="258"/>
         <source>Supplies list</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="269"/>
+        <location filename="../ui/MainWindow.ui" line="270"/>
         <source>Yeast bank</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="281"/>
+        <location filename="../ui/MainWindow.ui" line="282"/>
         <source>Water profiles</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="293"/>
+        <location filename="../ui/MainWindow.ui" line="294"/>
         <source>Mash schedules</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="305"/>
+        <location filename="../ui/MainWindow.ui" line="306"/>
         <source>Beer styles</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="317"/>
+        <location filename="../ui/MainWindow.ui" line="318"/>
         <source>Fermentation schedules</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="326"/>
+        <location filename="../ui/MainWindow.ui" line="327"/>
         <source>Global settings</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="344"/>
+        <location filename="../ui/MainWindow.ui" line="345"/>
         <source>Import beerxml</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="353"/>
+        <location filename="../ui/MainWindow.ui" line="354"/>
         <source>In Production</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="371"/>
+        <location filename="../ui/MainWindow.ui" line="372"/>
         <source>On Name</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="380"/>
+        <location filename="../ui/MainWindow.ui" line="381"/>
         <source>On Code</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="389"/>
+        <location filename="../ui/MainWindow.ui" line="390"/>
         <source>On Date</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="398"/>
+        <location filename="../ui/MainWindow.ui" line="399"/>
         <source>On Beerstyle</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="407"/>
+        <location filename="../ui/MainWindow.ui" line="408"/>
         <source>Import beerXML</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="412"/>
+        <location filename="../ui/MainWindow.ui" line="413"/>
         <source>dummy</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="417"/>
+        <location filename="../ui/MainWindow.ui" line="418"/>
         <source>hh</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="422"/>
+        <location filename="../ui/MainWindow.ui" line="423"/>
         <source>hj</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="427"/>
+        <location filename="../ui/MainWindow.ui" line="428"/>
         <source>ll</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="432"/>
-        <location filename="../ui/MainWindow.ui" line="441"/>
+        <location filename="../ui/MainWindow.ui" line="433"/>
+        <location filename="../ui/MainWindow.ui" line="442"/>
         <source>Nodes</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="459"/>
+        <location filename="../ui/MainWindow.ui" line="460"/>
         <source>Carbonation</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="477"/>
+        <location filename="../ui/MainWindow.ui" line="478"/>
         <source>Total Production</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="486"/>
+        <location filename="../ui/MainWindow.ui" line="487"/>
         <source>Efficiency</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="495"/>
+        <location filename="../ui/MainWindow.ui" line="496"/>
         <source>Fermentation</source>
         <translation type="unfinished"></translation>
     </message>
+    <message>
+        <location filename="../ui/MainWindow.ui" line="505"/>
+        <source>Import brew log</source>
+        <translation type="unfinished"></translation>
+    </message>
 </context>
 <context>
     <name>ManoMeter</name>
--- a/translations/bmsapp_nl.ts	Mon Aug 01 21:49:57 2022 +0200
+++ b/translations/bmsapp_nl.ts	Tue Aug 02 20:18:05 2022 +0200
@@ -8635,6 +8635,88 @@
     </message>
 </context>
 <context>
+    <name>ImportBrew</name>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="14"/>
+        <source>Dialog</source>
+        <translation>Dialog</translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="29"/>
+        <source>Brew logfile:</source>
+        <translation>Brouw logbestand:</translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="64"/>
+        <source>Quit</source>
+        <translation>Terug</translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="84"/>
+        <source>Open</source>
+        <translation>Open</translation>
+    </message>
+    <message>
+        <location filename="../ui/ImportBrew.ui" line="101"/>
+        <source>Results</source>
+        <translation>Resultaat</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="44"/>
+        <source>BMSapp - Import Brewlog</source>
+        <translation>BMSapp - importeer brouwlog</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="55"/>
+        <location filename="../src/ImportBrew.cpp" line="57"/>
+        <source>Open File</source>
+        <translation>Open bestand</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="55"/>
+        <source>Files (*.json)</source>
+        <translation>Bestanden (*.json)</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="57"/>
+        <source>No Brewlog JSON file selected.</source>
+        <translation>Geen brouwlog JSON bestand gekozen.</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="95"/>
+        <source>Brew: </source>
+        <translation>Brouw: </translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="112"/>
+        <source>Deleted %1 old records
+</source>
+        <translation>%1 oude records verwijderd
+</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="159"/>
+        <source>Inserted %1 new records
+</source>
+        <translation>%1 nieuwe records ingevoegd
+</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="190"/>
+        <source>Updated %1 records with events
+</source>
+        <translation>%1 records bijgewerkt met events
+</translation>
+    </message>
+    <message>
+        <location filename="../src/ImportBrew.cpp" line="196"/>
+        <source>Marked brew graph available in product
+</source>
+        <translation>Brouw grafiek beschikbaar gezet in product
+</translation>
+    </message>
+</context>
+<context>
     <name>ImportXML</name>
     <message>
         <location filename="../ui/ImportXML.ui" line="14"/>
@@ -9488,49 +9570,49 @@
         <translation>Bestand</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="55"/>
+        <location filename="../ui/MainWindow.ui" line="56"/>
         <source>Help</source>
         <translation>Hulp</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="61"/>
+        <location filename="../ui/MainWindow.ui" line="62"/>
         <source>Settings</source>
         <translation>Instellingen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="72"/>
+        <location filename="../ui/MainWindow.ui" line="73"/>
         <source>Inventory</source>
         <translation>Inventaris</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="88"/>
+        <location filename="../ui/MainWindow.ui" line="89"/>
         <source>Monitor</source>
         <translation>Monitoren</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="99"/>
+        <location filename="../ui/MainWindow.ui" line="100"/>
         <source>Products</source>
         <translation>Productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="103"/>
-        <location filename="../ui/MainWindow.ui" line="362"/>
+        <location filename="../ui/MainWindow.ui" line="104"/>
+        <location filename="../ui/MainWindow.ui" line="363"/>
         <source>Archive</source>
         <translation>Archief</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="132"/>
-        <location filename="../ui/MainWindow.ui" line="335"/>
+        <location filename="../ui/MainWindow.ui" line="133"/>
+        <location filename="../ui/MainWindow.ui" line="336"/>
         <source>Recipes</source>
         <translation>Recepten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="155"/>
+        <location filename="../ui/MainWindow.ui" line="156"/>
         <source>Exit</source>
         <translation>Afsluiten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="164"/>
+        <location filename="../ui/MainWindow.ui" line="165"/>
         <source>About</source>
         <translation>Over</translation>
     </message>
@@ -9539,7 +9621,7 @@
         <translation type="vanished">Systemen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="450"/>
+        <location filename="../ui/MainWindow.ui" line="451"/>
         <source>Fermenters</source>
         <translation>Vergisting</translation>
     </message>
@@ -9548,166 +9630,171 @@
         <translation type="vanished">CO2 meters</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="468"/>
+        <location filename="../ui/MainWindow.ui" line="469"/>
         <source>iSpindels</source>
         <translation>iSpindels</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="173"/>
+        <location filename="../ui/MainWindow.ui" line="174"/>
         <source>Suppliers</source>
         <translation>Leveranciers</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="116"/>
+        <location filename="../ui/MainWindow.ui" line="117"/>
         <source>Reports</source>
         <translation>Rapporten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="185"/>
+        <location filename="../ui/MainWindow.ui" line="186"/>
         <source>Fermentables</source>
         <translation>Vergistbare ingredienten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="197"/>
+        <location filename="../ui/MainWindow.ui" line="198"/>
         <source>Hops</source>
         <translation>Hoppen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="209"/>
+        <location filename="../ui/MainWindow.ui" line="210"/>
         <source>Yeasts</source>
         <translation>Gisten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="221"/>
+        <location filename="../ui/MainWindow.ui" line="222"/>
         <source>Miscs</source>
         <translation>Overige ingredienten</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="233"/>
+        <location filename="../ui/MainWindow.ui" line="234"/>
         <source>Waters</source>
         <translation>Water</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="245"/>
+        <location filename="../ui/MainWindow.ui" line="246"/>
         <source>Equipments</source>
         <translation>Brouw apparatuur</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="257"/>
+        <location filename="../ui/MainWindow.ui" line="258"/>
         <source>Supplies list</source>
         <translation>Voorraad lijst</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="269"/>
+        <location filename="../ui/MainWindow.ui" line="270"/>
         <source>Yeast bank</source>
         <translation>Gistbank lijst</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="281"/>
+        <location filename="../ui/MainWindow.ui" line="282"/>
         <source>Water profiles</source>
         <translation>Water profielen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="293"/>
+        <location filename="../ui/MainWindow.ui" line="294"/>
         <source>Mash schedules</source>
         <translation>Maisch schemas</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="305"/>
+        <location filename="../ui/MainWindow.ui" line="306"/>
         <source>Beer styles</source>
         <translation>Bierstijlen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="317"/>
+        <location filename="../ui/MainWindow.ui" line="318"/>
         <source>Fermentation schedules</source>
         <translation>Vergisting profielen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="326"/>
+        <location filename="../ui/MainWindow.ui" line="327"/>
         <source>Global settings</source>
         <translation>Instellingen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="344"/>
+        <location filename="../ui/MainWindow.ui" line="345"/>
         <source>Import beerxml</source>
         <translation>Importeer beerxml</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="353"/>
+        <location filename="../ui/MainWindow.ui" line="354"/>
         <source>In Production</source>
         <translation>In Productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="371"/>
+        <location filename="../ui/MainWindow.ui" line="372"/>
         <source>On Name</source>
         <translation>Op naam</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="380"/>
+        <location filename="../ui/MainWindow.ui" line="381"/>
         <source>On Code</source>
         <translation>Op code</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="389"/>
+        <location filename="../ui/MainWindow.ui" line="390"/>
         <source>On Date</source>
         <translation>Op datum</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="398"/>
+        <location filename="../ui/MainWindow.ui" line="399"/>
         <source>On Beerstyle</source>
         <translation>Op bierstijl</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="407"/>
+        <location filename="../ui/MainWindow.ui" line="408"/>
         <source>Import beerXML</source>
         <translation>Importeer beerXML</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="412"/>
+        <location filename="../ui/MainWindow.ui" line="413"/>
         <source>dummy</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="417"/>
+        <location filename="../ui/MainWindow.ui" line="418"/>
         <source>hh</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="422"/>
+        <location filename="../ui/MainWindow.ui" line="423"/>
         <source>hj</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="427"/>
+        <location filename="../ui/MainWindow.ui" line="428"/>
         <source>ll</source>
         <translation></translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="432"/>
-        <location filename="../ui/MainWindow.ui" line="441"/>
+        <location filename="../ui/MainWindow.ui" line="433"/>
+        <location filename="../ui/MainWindow.ui" line="442"/>
         <source>Nodes</source>
         <translation>Systemen</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="459"/>
+        <location filename="../ui/MainWindow.ui" line="460"/>
         <source>Carbonation</source>
         <translation>Carbonatie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="477"/>
+        <location filename="../ui/MainWindow.ui" line="478"/>
         <source>Total Production</source>
         <translation>Totaal productie</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="486"/>
+        <location filename="../ui/MainWindow.ui" line="487"/>
         <source>Efficiency</source>
         <translation>Rendement</translation>
     </message>
     <message>
-        <location filename="../ui/MainWindow.ui" line="495"/>
+        <location filename="../ui/MainWindow.ui" line="496"/>
         <source>Fermentation</source>
         <translation>Vergisting</translation>
     </message>
+    <message>
+        <location filename="../ui/MainWindow.ui" line="505"/>
+        <source>Import brew log</source>
+        <translation>Importeer brouwlog</translation>
+    </message>
 </context>
 <context>
     <name>ManoMeter</name>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/ImportBrew.ui	Tue Aug 02 20:18:05 2022 +0200
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ImportBrew</class>
+ <widget class="QDialog" name="ImportBrew">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>1280</width>
+    <height>640</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QWidget" name="topWidget" native="true">
+     <widget class="QLabel" name="fileLabel">
+      <property name="geometry">
+       <rect>
+        <x>170</x>
+        <y>20</y>
+        <width>121</width>
+        <height>20</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Brew logfile:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QLineEdit" name="fileEdit">
+      <property name="geometry">
+       <rect>
+        <x>310</x>
+        <y>20</y>
+        <width>661</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="maxLength">
+       <number>128</number>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="quitButton">
+      <property name="geometry">
+       <rect>
+        <x>600</x>
+        <y>540</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="text">
+       <string>Quit</string>
+      </property>
+      <property name="icon">
+       <iconset>
+        <normaloff>:icons/silk/door_out.png</normaloff>:icons/silk/door_out.png</iconset>
+      </property>
+     </widget>
+     <widget class="QPushButton" name="openButton">
+      <property name="enabled">
+       <bool>true</bool>
+      </property>
+      <property name="geometry">
+       <rect>
+        <x>1000</x>
+        <y>20</y>
+        <width>80</width>
+        <height>23</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Open</string>
+      </property>
+      <property name="icon">
+       <iconset resource="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc">
+        <normaloff>:/icons/silk/application_form_add.png</normaloff>:/icons/silk/application_form_add.png</iconset>
+      </property>
+     </widget>
+     <widget class="QGroupBox" name="groupBox">
+      <property name="geometry">
+       <rect>
+        <x>200</x>
+        <y>80</y>
+        <width>881</width>
+        <height>431</height>
+       </rect>
+      </property>
+      <property name="title">
+       <string>Results</string>
+      </property>
+      <widget class="QPlainTextEdit" name="logEdit">
+       <property name="geometry">
+        <rect>
+         <x>30</x>
+         <y>90</y>
+         <width>821</width>
+         <height>311</height>
+        </rect>
+       </property>
+       <property name="font">
+        <font>
+         <family>Courier 10 Pitch</family>
+        </font>
+       </property>
+      </widget>
+      <widget class="QProgressBar" name="progressBar">
+       <property name="geometry">
+        <rect>
+         <x>30</x>
+         <y>40</y>
+         <width>821</width>
+         <height>23</height>
+        </rect>
+       </property>
+       <property name="value">
+        <number>24</number>
+       </property>
+      </widget>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>fileEdit</tabstop>
+  <tabstop>quitButton</tabstop>
+  <tabstop>openButton</tabstop>
+ </tabstops>
+ <resources>
+  <include location="../../../../../../home/mbroek/MyProjects/bmsapp/resources/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
--- a/ui/MainWindow.ui	Mon Aug 01 21:49:57 2022 +0200
+++ b/ui/MainWindow.ui	Tue Aug 02 20:18:05 2022 +0200
@@ -48,6 +48,7 @@
      <string>File</string>
     </property>
     <addaction name="actionImport_XML"/>
+    <addaction name="actionImport_Brew"/>
     <addaction name="actionExit"/>
    </widget>
    <widget class="QMenu" name="menuHelp">
@@ -495,6 +496,15 @@
     <string>Fermentation</string>
    </property>
   </action>
+  <action name="actionImport_Brew">
+   <property name="icon">
+    <iconset resource="../resources/icons.qrc">
+     <normaloff>:/icons/silk/chart_line_add.png</normaloff>:/icons/silk/chart_line_add.png</iconset>
+   </property>
+   <property name="text">
+    <string>Import brew log</string>
+   </property>
+  </action>
  </widget>
  <layoutdefault spacing="6" margin="11"/>
  <resources>

mercurial