Fri, 10 Feb 2023 10:09:37 +0100
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.
--- 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>