Fermenter charts, only draw lines that are really used. Better auto scaling, not using the internal version. If only a air line is to be shown, make it fat. Save the path to download the image in the settings file.

Fri, 10 Feb 2023 10:09:37 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Fri, 10 Feb 2023 10:09:37 +0100
changeset 490
b67fb2e5bb41
parent 489
4db768aea3df
child 491
76f3a96e82b5

Fermenter charts, only draw lines that are really used. Better auto scaling, not using the internal version. If only a air line is to be shown, make it fat. Save the path to download the image in the settings file.

src/ChartFermenter.cpp file | annotate | diff | comparison | revisions
translations/bmsapp_en.ts file | annotate | diff | comparison | revisions
translations/bmsapp_nl.ts file | annotate | diff | comparison | revisions
--- a/src/ChartFermenter.cpp	Thu Feb 09 12:53:21 2023 +0100
+++ b/src/ChartFermenter.cpp	Fri Feb 10 10:09:37 2023 +0100
@@ -23,9 +23,43 @@
 {
     QSqlQuery query;
     double timestamp;
+    bool use_air = false, use_beer=false, use_chiller = false, use_room = false;
+    bool use_sp_low = false, use_sp_high = false, use_heater = false, use_cooler = false;
+    QAreaSeries *pwr_cool, *pwr_heat;
+    QLineSeries *pv_air, *pv_beer, *pv_chiller;
+    QLineSeries *pwr_cool1, *pwr_cool0, *pwr_heat1, *pwr_heat0;
+    int	min = 100, max = 0;
 
     qDebug() << "ChartFermenter:" << code << name;
 
+    /*
+     * First see which values are really used in the logfile.
+     */
+    query.prepare("SELECT * FROM log_fermenter WHERE code=:code ORDER BY datetime");
+    query.bindValue(":code", code);
+    query.exec();
+    while (query.next()) {
+	if (query.value("temp_air").toDouble() > 0)
+	    use_air = true;
+	if (query.value("temp_beer").toDouble() > 0)
+	    use_beer = true;
+	if (query.value("temp_chiller").toDouble() > 0)
+	    use_chiller = true;
+	if (query.value("temp_room").toDouble() > 0)
+	    use_room = true;
+	if (query.value("sp_low").toDouble() > 0)
+	    use_sp_low = true;
+	if (query.value("sp_high").toDouble() > 0)
+	    use_sp_high = true;
+	if (query.value("heater_power").toDouble() > 0)
+	    use_heater = true;
+	if (query.value("cooler_power").toDouble() > 0)
+	    use_cooler = true;
+	if (use_air && use_beer && use_chiller && use_room && use_sp_low && use_sp_high && use_heater && use_cooler)
+	    break;
+    }
+//    qDebug() << "use" << use_air << use_beer << use_chiller << use_room << use_sp_low << use_sp_high << use_heater << use_cooler;
+
     QDialog* dialog = new QDialog(parent);
     dialog->setWindowTitle(tr("BMSapp - Fermenter log ") + "\"" + name + "\"");
     dialog->setObjectName(QString::fromUtf8("ChartFermenter"));
@@ -44,55 +78,117 @@
     buttonBox->setStandardButtons(QDialogButtonBox::Ok);
     buttonBox->addButton(saveButton,QDialogButtonBox::ActionRole);
 
-    QLineSeries *pv_air = new QLineSeries();
-    QLineSeries *pv_beer = new QLineSeries();
-    QLineSeries *pv_chiller = new QLineSeries();
-    QLineSeries *pwr_cool1 = new QLineSeries();
-    QLineSeries *pwr_cool0 = new QLineSeries();
-    QLineSeries *pwr_heat1 = new QLineSeries();	// Top side of area
-    QLineSeries *pwr_heat0 = new QLineSeries();	// Bottom side of area
+    if (use_air)
+	pv_air = new QLineSeries();
+    if (use_beer)
+	pv_beer = new QLineSeries();
+    if (use_chiller)
+	pv_chiller = new QLineSeries();
+    if (use_cooler) {
+	pwr_cool1 = new QLineSeries();
+	pwr_cool0 = new QLineSeries();
+    }
+    if (use_heater) {
+	pwr_heat1 = new QLineSeries();	// Top side of area
+	pwr_heat0 = new QLineSeries();	// Bottom side of area
+    }
 
     query.prepare("SELECT * FROM log_fermenter WHERE code=:code ORDER BY datetime");
     query.bindValue(":code", code);
     query.exec();
     while (query.next()) {
         timestamp = query.value("datetime").toDateTime().toSecsSinceEpoch() * 1000;
-        pv_air->append(timestamp, query.value("temp_air").toDouble());
-        pv_beer->append(timestamp, query.value("temp_beer").toDouble());
-        if (query.value("temp_chiller").toDouble() > 0)
+	if (use_air) {
+            pv_air->append(timestamp, query.value("temp_air").toDouble());
+	    if (ceil(query.value("temp_air").toDouble()) > max)
+		max = ceil(query.value("temp_air").toDouble());
+	    if (floor(query.value("temp_air").toDouble()) < min)
+		min = floor(query.value("temp_air").toDouble());
+	}
+	if (use_beer) {
+            pv_beer->append(timestamp, query.value("temp_beer").toDouble());
+	    if (ceil(query.value("temp_beer").toDouble()) > max)
+                max = ceil(query.value("temp_beer").toDouble());
+            if (floor(query.value("temp_beer").toDouble()) < min)
+                min = floor(query.value("temp_beer").toDouble());
+	}
+        if (use_chiller && query.value("temp_chiller").toDouble() > 0) {
             pv_chiller->append(timestamp, query.value("temp_chiller").toDouble());
-	pwr_cool0->append(timestamp, 0);
-        pwr_cool1->append(timestamp, query.value("cooler_power").toInt());
-	pwr_heat0->append(timestamp, 0);
-        pwr_heat1->append(timestamp, query.value("heater_power").toInt());
+//	    if (ceil(query.value("temp_chiller").toDouble()) > max)
+//                max = ceil(query.value("temp_chiller").toDouble());
+//            if (floor(query.value("temp_chiller").toDouble()) < min)
+//                min = floor(query.value("temp_chiller").toDouble());
+	}
+	if (use_cooler) {
+	    pwr_cool0->append(timestamp, 0);
+            pwr_cool1->append(timestamp, query.value("cooler_power").toInt());
+	}
+	if (use_heater) {
+	    pwr_heat0->append(timestamp, 0);
+            pwr_heat1->append(timestamp, query.value("heater_power").toInt());
+	}
+    }
+//    qDebug() << "min" << min << "max" << max << "ticks" << max-min+1;
+
+    /*
+     * If the range is small, increase it.
+     */
+    if ((max - min) < 5) {
+	min = max - 5;
+    } else if ((max - min) < 10) {
+	min = max - 10;
     }
 
-    pv_air->setName(tr("Air"));
-    pv_air->setColor(QColorConstants::Svg::lightgreen);
-    pv_beer->setName(tr("Beer"));
-    QPen pen(QColorConstants::Svg::navy);
-    pen.setWidth(2);
-    pv_beer->setPen(pen);
-    pv_chiller->setName(tr("Chiller"));
-    pv_chiller->setColor(QColorConstants::Svg::lightsalmon);
-    pv_chiller->setOpacity(0.75);
+    if (use_air) {
+	pv_air->setName(tr("Air"));
+	if (use_beer) {
+	    pv_air->setColor(QColorConstants::Svg::lightgreen);
+	} else {
+	    /*
+	     * If there is no beer line, then make this one fat.
+	     */
+	    QPen pen(QColorConstants::Svg::lightgreen);
+	    pen.setWidth(2);
+            pv_air->setPen(pen);
+	}
+    }
+    if (use_beer) {
+	pv_beer->setName(tr("Beer"));
+	QPen pen(QColorConstants::Svg::navy);
+	pen.setWidth(2);
+	pv_beer->setPen(pen);
+    }
+    if (use_chiller) {
+	pv_chiller->setName(tr("Chiller"));
+	pv_chiller->setColor(QColorConstants::Svg::lightsalmon);
+	pv_chiller->setOpacity(0.75);
+    }
 
-    QAreaSeries *pwr_cool = new QAreaSeries(pwr_cool0, pwr_cool1);
-    pwr_cool->setName("Cool %");
-    pwr_cool->setOpacity(0.50);
-    pwr_cool->setColor(QColorConstants::Blue);
-    QAreaSeries *pwr_heat = new QAreaSeries(pwr_heat0, pwr_heat1);
-    pwr_heat->setName("Heat %");
-    pwr_heat->setOpacity(0.50);
-    pwr_heat->setColor(QColorConstants::Red);
+    if (use_cooler) {
+	pwr_cool = new QAreaSeries(pwr_cool0, pwr_cool1);
+	pwr_cool->setName("Cool %");
+	pwr_cool->setOpacity(0.50);
+	pwr_cool->setColor(QColorConstants::Blue);
+    }
+    if (use_heater) {
+	pwr_heat = new QAreaSeries(pwr_heat0, pwr_heat1);
+	pwr_heat->setName("Heat %");
+	pwr_heat->setOpacity(0.50);
+	pwr_heat->setColor(QColorConstants::Red);
+    }
 
     chart = new QChart();
     chart->setTitle(QString("%1 \"%2\"").arg(code).arg(name));
-    chart->addSeries(pwr_cool);		// Order is important, first drawn is lowest layer.
-    chart->addSeries(pwr_heat);
-    chart->addSeries(pv_chiller);
-    chart->addSeries(pv_air);
-    chart->addSeries(pv_beer);		// Top layer
+    if (use_cooler)
+	chart->addSeries(pwr_cool);	// Order is important, first drawn is lowest layer.
+    if (use_heater)
+	chart->addSeries(pwr_heat);
+    if (use_chiller)
+	chart->addSeries(pv_chiller);
+    if (use_air)
+	chart->addSeries(pv_air);
+    if (use_beer)
+	chart->addSeries(pv_beer);	// Top layer
 
     QDateTimeAxis *axisX = new QDateTimeAxis;
     axisX->setTickCount(10);
@@ -100,34 +196,48 @@
     axisX->setTitleText(tr("Date"));
     axisX->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
     chart->addAxis(axisX, Qt::AlignBottom);
-    pv_air->attachAxis(axisX);
-    pv_beer->attachAxis(axisX);
-    pv_chiller->attachAxis(axisX);
+    if (use_air)
+	pv_air->attachAxis(axisX);
+    if (use_beer)
+	pv_beer->attachAxis(axisX);
+    if (use_chiller)
+	pv_chiller->attachAxis(axisX);
 
     QValueAxis *axisY = new QValueAxis;
-    axisY->setTickCount(11);
+    axisY->setRange(min, max);
+    axisY->setTickCount(max-min+1);
     axisY->setMinorTickCount(1);
-    axisY->setLabelFormat("%i");
+    axisY->setLabelFormat("%.1f");
     axisY->setTitleText(tr("Temp °C"));
     axisY->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
     chart->addAxis(axisY, Qt::AlignLeft);
-    pv_air->attachAxis(axisY);
-    pv_beer->attachAxis(axisY);
-    pv_chiller->attachAxis(axisY);
+    if (use_air)
+	pv_air->attachAxis(axisY);
+    if (use_beer)
+	pv_beer->attachAxis(axisY);
+    if (use_chiller)
+	pv_chiller->attachAxis(axisY);
 
-    QValueAxis *axisYR = new QValueAxis;
-    axisYR->setRange(0, 100);
-    axisYR->setTickCount(11);
-    axisYR->setLabelFormat("%i");
-    axisYR->setTitleText(tr("Power %"));
-    axisYR->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
-    chart->addAxis(axisYR, Qt::AlignRight);
-    pwr_cool->attachAxis(axisYR);
-    pwr_heat->attachAxis(axisYR);
+    if (use_heater || use_cooler) {
+	QValueAxis *axisYR = new QValueAxis;
+	axisYR->setRange(0, 100);
+	axisYR->setTickCount(11);
+	axisYR->setLabelFormat("%i");
+	axisYR->setTitleText(tr("Power %"));
+	axisYR->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
+	chart->addAxis(axisYR, Qt::AlignRight);
+	if (use_cooler)
+	    pwr_cool->attachAxis(axisYR);
+	if (use_heater)
+	    pwr_heat->attachAxis(axisYR);
+    }
 
-    connect(pv_air, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
-    connect(pv_beer, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
-    connect(pv_chiller, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
+    if (use_air)
+	connect(pv_air, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
+    if (use_beer)
+	connect(pv_beer, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
+    if (use_chiller)
+	connect(pv_chiller, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
 
     chartView = new QChartView(chart);
     chartView->setRenderHint(QPainter::Antialiasing);
@@ -149,12 +259,30 @@
 
 void ChartFermenter::savePNG()
 {
-    QString path = QFileDialog::getSaveFileName(this, tr("Save Image"), QDir::homePath() + "/fermenter.png", tr("Image (*.png)"));
+    QSettings settings(QSettings::IniFormat, QSettings::UserScope, "mbse", "bmsapp");
+    QString dirName;
+
+    /*
+     * First check if the directory stored in the settings file exists.
+     * It might be on a removable media that was last used ...
+     * If so, fallback to the user's home directory.
+     */
+    dirName = settings.value("paths/download").toString();
+    if (! QDir(dirName).exists()) {
+        dirName = QDir::homePath();
+    }
+
+    QString path = QFileDialog::getSaveFileName(this, tr("Save Image"), dirName + "/fermenter.png", tr("Image (*.png)"));
     if (path.isEmpty()) {
 	QMessageBox::warning(this, tr("Save File"), tr("No image file selected."));
 	return;
     }
 
+    /*
+     * Update to current selected path
+     */
+    settings.setValue("paths/download", QFileInfo(path).absolutePath());
+
     QImage img((chartView->size()), QImage::Format_ARGB32);
     QPainter painter;
     painter.begin(&img);
--- a/translations/bmsapp_en.ts	Thu Feb 09 12:53:21 2023 +0100
+++ b/translations/bmsapp_en.ts	Fri Feb 10 10:09:37 2023 +0100
@@ -100,62 +100,62 @@
 <context>
     <name>ChartFermenter</name>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="30"/>
+        <location filename="../src/ChartFermenter.cpp" line="64"/>
         <source>BMSapp - Fermenter log </source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="35"/>
+        <location filename="../src/ChartFermenter.cpp" line="69"/>
         <source>Save</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="70"/>
+        <location filename="../src/ChartFermenter.cpp" line="143"/>
         <source>Air</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="72"/>
+        <location filename="../src/ChartFermenter.cpp" line="153"/>
         <source>Beer</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="76"/>
+        <location filename="../src/ChartFermenter.cpp" line="159"/>
         <source>Chiller</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="100"/>
+        <location filename="../src/ChartFermenter.cpp" line="193"/>
         <source>Date</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="111"/>
+        <location filename="../src/ChartFermenter.cpp" line="208"/>
         <source>Temp °C</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="122"/>
+        <location filename="../src/ChartFermenter.cpp" line="223"/>
         <source>Power %</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="152"/>
+        <location filename="../src/ChartFermenter.cpp" line="272"/>
         <source>Save Image</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="152"/>
+        <location filename="../src/ChartFermenter.cpp" line="272"/>
         <source>Image (*.png)</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="154"/>
+        <location filename="../src/ChartFermenter.cpp" line="274"/>
         <source>Save File</source>
         <translation type="unfinished"></translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="154"/>
+        <location filename="../src/ChartFermenter.cpp" line="274"/>
         <source>No image file selected.</source>
         <translation type="unfinished"></translation>
     </message>
--- a/translations/bmsapp_nl.ts	Thu Feb 09 12:53:21 2023 +0100
+++ b/translations/bmsapp_nl.ts	Fri Feb 10 10:09:37 2023 +0100
@@ -130,62 +130,62 @@
 <context>
     <name>ChartFermenter</name>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="30"/>
+        <location filename="../src/ChartFermenter.cpp" line="64"/>
         <source>BMSapp - Fermenter log </source>
         <translation>BMSapp - Klimaatkast log </translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="35"/>
+        <location filename="../src/ChartFermenter.cpp" line="69"/>
         <source>Save</source>
         <translation>Bewaar</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="70"/>
+        <location filename="../src/ChartFermenter.cpp" line="143"/>
         <source>Air</source>
         <translation>Lucht</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="72"/>
+        <location filename="../src/ChartFermenter.cpp" line="153"/>
         <source>Beer</source>
         <translation>Bier</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="76"/>
+        <location filename="../src/ChartFermenter.cpp" line="159"/>
         <source>Chiller</source>
         <translation>Koeler</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="100"/>
+        <location filename="../src/ChartFermenter.cpp" line="193"/>
         <source>Date</source>
         <translation>Datum</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="111"/>
+        <location filename="../src/ChartFermenter.cpp" line="208"/>
         <source>Temp °C</source>
         <translation>Temp °C</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="122"/>
+        <location filename="../src/ChartFermenter.cpp" line="223"/>
         <source>Power %</source>
         <translation>Power %</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="152"/>
+        <location filename="../src/ChartFermenter.cpp" line="272"/>
         <source>Save Image</source>
         <translation>Opslaan plaatje</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="152"/>
+        <location filename="../src/ChartFermenter.cpp" line="272"/>
         <source>Image (*.png)</source>
         <translation>Plaatje (*.png)</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="154"/>
+        <location filename="../src/ChartFermenter.cpp" line="274"/>
         <source>Save File</source>
         <translation>Bestand opslaan</translation>
     </message>
     <message>
-        <location filename="../src/ChartFermenter.cpp" line="154"/>
+        <location filename="../src/ChartFermenter.cpp" line="274"/>
         <source>No image file selected.</source>
         <translation>Geen plaatjes bestand gekozen.</translation>
     </message>

mercurial