src/ChartFermenter.cpp

changeset 490
b67fb2e5bb41
parent 434
ebf4996ab396
equal deleted inserted replaced
489:4db768aea3df 490:b67fb2e5bb41
21 21
22 ChartFermenter::ChartFermenter(QString code, QString name, QWidget *parent) : QDialog(parent) 22 ChartFermenter::ChartFermenter(QString code, QString name, QWidget *parent) : QDialog(parent)
23 { 23 {
24 QSqlQuery query; 24 QSqlQuery query;
25 double timestamp; 25 double timestamp;
26 bool use_air = false, use_beer=false, use_chiller = false, use_room = false;
27 bool use_sp_low = false, use_sp_high = false, use_heater = false, use_cooler = false;
28 QAreaSeries *pwr_cool, *pwr_heat;
29 QLineSeries *pv_air, *pv_beer, *pv_chiller;
30 QLineSeries *pwr_cool1, *pwr_cool0, *pwr_heat1, *pwr_heat0;
31 int min = 100, max = 0;
26 32
27 qDebug() << "ChartFermenter:" << code << name; 33 qDebug() << "ChartFermenter:" << code << name;
34
35 /*
36 * First see which values are really used in the logfile.
37 */
38 query.prepare("SELECT * FROM log_fermenter WHERE code=:code ORDER BY datetime");
39 query.bindValue(":code", code);
40 query.exec();
41 while (query.next()) {
42 if (query.value("temp_air").toDouble() > 0)
43 use_air = true;
44 if (query.value("temp_beer").toDouble() > 0)
45 use_beer = true;
46 if (query.value("temp_chiller").toDouble() > 0)
47 use_chiller = true;
48 if (query.value("temp_room").toDouble() > 0)
49 use_room = true;
50 if (query.value("sp_low").toDouble() > 0)
51 use_sp_low = true;
52 if (query.value("sp_high").toDouble() > 0)
53 use_sp_high = true;
54 if (query.value("heater_power").toDouble() > 0)
55 use_heater = true;
56 if (query.value("cooler_power").toDouble() > 0)
57 use_cooler = true;
58 if (use_air && use_beer && use_chiller && use_room && use_sp_low && use_sp_high && use_heater && use_cooler)
59 break;
60 }
61 // qDebug() << "use" << use_air << use_beer << use_chiller << use_room << use_sp_low << use_sp_high << use_heater << use_cooler;
28 62
29 QDialog* dialog = new QDialog(parent); 63 QDialog* dialog = new QDialog(parent);
30 dialog->setWindowTitle(tr("BMSapp - Fermenter log ") + "\"" + name + "\""); 64 dialog->setWindowTitle(tr("BMSapp - Fermenter log ") + "\"" + name + "\"");
31 dialog->setObjectName(QString::fromUtf8("ChartFermenter")); 65 dialog->setObjectName(QString::fromUtf8("ChartFermenter"));
32 dialog->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint); 66 dialog->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
42 buttonBox->setObjectName(QString::fromUtf8("buttonBox")); 76 buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
43 buttonBox->setOrientation(Qt::Vertical); 77 buttonBox->setOrientation(Qt::Vertical);
44 buttonBox->setStandardButtons(QDialogButtonBox::Ok); 78 buttonBox->setStandardButtons(QDialogButtonBox::Ok);
45 buttonBox->addButton(saveButton,QDialogButtonBox::ActionRole); 79 buttonBox->addButton(saveButton,QDialogButtonBox::ActionRole);
46 80
47 QLineSeries *pv_air = new QLineSeries(); 81 if (use_air)
48 QLineSeries *pv_beer = new QLineSeries(); 82 pv_air = new QLineSeries();
49 QLineSeries *pv_chiller = new QLineSeries(); 83 if (use_beer)
50 QLineSeries *pwr_cool1 = new QLineSeries(); 84 pv_beer = new QLineSeries();
51 QLineSeries *pwr_cool0 = new QLineSeries(); 85 if (use_chiller)
52 QLineSeries *pwr_heat1 = new QLineSeries(); // Top side of area 86 pv_chiller = new QLineSeries();
53 QLineSeries *pwr_heat0 = new QLineSeries(); // Bottom side of area 87 if (use_cooler) {
88 pwr_cool1 = new QLineSeries();
89 pwr_cool0 = new QLineSeries();
90 }
91 if (use_heater) {
92 pwr_heat1 = new QLineSeries(); // Top side of area
93 pwr_heat0 = new QLineSeries(); // Bottom side of area
94 }
54 95
55 query.prepare("SELECT * FROM log_fermenter WHERE code=:code ORDER BY datetime"); 96 query.prepare("SELECT * FROM log_fermenter WHERE code=:code ORDER BY datetime");
56 query.bindValue(":code", code); 97 query.bindValue(":code", code);
57 query.exec(); 98 query.exec();
58 while (query.next()) { 99 while (query.next()) {
59 timestamp = query.value("datetime").toDateTime().toSecsSinceEpoch() * 1000; 100 timestamp = query.value("datetime").toDateTime().toSecsSinceEpoch() * 1000;
60 pv_air->append(timestamp, query.value("temp_air").toDouble()); 101 if (use_air) {
61 pv_beer->append(timestamp, query.value("temp_beer").toDouble()); 102 pv_air->append(timestamp, query.value("temp_air").toDouble());
62 if (query.value("temp_chiller").toDouble() > 0) 103 if (ceil(query.value("temp_air").toDouble()) > max)
104 max = ceil(query.value("temp_air").toDouble());
105 if (floor(query.value("temp_air").toDouble()) < min)
106 min = floor(query.value("temp_air").toDouble());
107 }
108 if (use_beer) {
109 pv_beer->append(timestamp, query.value("temp_beer").toDouble());
110 if (ceil(query.value("temp_beer").toDouble()) > max)
111 max = ceil(query.value("temp_beer").toDouble());
112 if (floor(query.value("temp_beer").toDouble()) < min)
113 min = floor(query.value("temp_beer").toDouble());
114 }
115 if (use_chiller && query.value("temp_chiller").toDouble() > 0) {
63 pv_chiller->append(timestamp, query.value("temp_chiller").toDouble()); 116 pv_chiller->append(timestamp, query.value("temp_chiller").toDouble());
64 pwr_cool0->append(timestamp, 0); 117 // if (ceil(query.value("temp_chiller").toDouble()) > max)
65 pwr_cool1->append(timestamp, query.value("cooler_power").toInt()); 118 // max = ceil(query.value("temp_chiller").toDouble());
66 pwr_heat0->append(timestamp, 0); 119 // if (floor(query.value("temp_chiller").toDouble()) < min)
67 pwr_heat1->append(timestamp, query.value("heater_power").toInt()); 120 // min = floor(query.value("temp_chiller").toDouble());
68 } 121 }
69 122 if (use_cooler) {
70 pv_air->setName(tr("Air")); 123 pwr_cool0->append(timestamp, 0);
71 pv_air->setColor(QColorConstants::Svg::lightgreen); 124 pwr_cool1->append(timestamp, query.value("cooler_power").toInt());
72 pv_beer->setName(tr("Beer")); 125 }
73 QPen pen(QColorConstants::Svg::navy); 126 if (use_heater) {
74 pen.setWidth(2); 127 pwr_heat0->append(timestamp, 0);
75 pv_beer->setPen(pen); 128 pwr_heat1->append(timestamp, query.value("heater_power").toInt());
76 pv_chiller->setName(tr("Chiller")); 129 }
77 pv_chiller->setColor(QColorConstants::Svg::lightsalmon); 130 }
78 pv_chiller->setOpacity(0.75); 131 // qDebug() << "min" << min << "max" << max << "ticks" << max-min+1;
79 132
80 QAreaSeries *pwr_cool = new QAreaSeries(pwr_cool0, pwr_cool1); 133 /*
81 pwr_cool->setName("Cool %"); 134 * If the range is small, increase it.
82 pwr_cool->setOpacity(0.50); 135 */
83 pwr_cool->setColor(QColorConstants::Blue); 136 if ((max - min) < 5) {
84 QAreaSeries *pwr_heat = new QAreaSeries(pwr_heat0, pwr_heat1); 137 min = max - 5;
85 pwr_heat->setName("Heat %"); 138 } else if ((max - min) < 10) {
86 pwr_heat->setOpacity(0.50); 139 min = max - 10;
87 pwr_heat->setColor(QColorConstants::Red); 140 }
141
142 if (use_air) {
143 pv_air->setName(tr("Air"));
144 if (use_beer) {
145 pv_air->setColor(QColorConstants::Svg::lightgreen);
146 } else {
147 /*
148 * If there is no beer line, then make this one fat.
149 */
150 QPen pen(QColorConstants::Svg::lightgreen);
151 pen.setWidth(2);
152 pv_air->setPen(pen);
153 }
154 }
155 if (use_beer) {
156 pv_beer->setName(tr("Beer"));
157 QPen pen(QColorConstants::Svg::navy);
158 pen.setWidth(2);
159 pv_beer->setPen(pen);
160 }
161 if (use_chiller) {
162 pv_chiller->setName(tr("Chiller"));
163 pv_chiller->setColor(QColorConstants::Svg::lightsalmon);
164 pv_chiller->setOpacity(0.75);
165 }
166
167 if (use_cooler) {
168 pwr_cool = new QAreaSeries(pwr_cool0, pwr_cool1);
169 pwr_cool->setName("Cool %");
170 pwr_cool->setOpacity(0.50);
171 pwr_cool->setColor(QColorConstants::Blue);
172 }
173 if (use_heater) {
174 pwr_heat = new QAreaSeries(pwr_heat0, pwr_heat1);
175 pwr_heat->setName("Heat %");
176 pwr_heat->setOpacity(0.50);
177 pwr_heat->setColor(QColorConstants::Red);
178 }
88 179
89 chart = new QChart(); 180 chart = new QChart();
90 chart->setTitle(QString("%1 \"%2\"").arg(code).arg(name)); 181 chart->setTitle(QString("%1 \"%2\"").arg(code).arg(name));
91 chart->addSeries(pwr_cool); // Order is important, first drawn is lowest layer. 182 if (use_cooler)
92 chart->addSeries(pwr_heat); 183 chart->addSeries(pwr_cool); // Order is important, first drawn is lowest layer.
93 chart->addSeries(pv_chiller); 184 if (use_heater)
94 chart->addSeries(pv_air); 185 chart->addSeries(pwr_heat);
95 chart->addSeries(pv_beer); // Top layer 186 if (use_chiller)
187 chart->addSeries(pv_chiller);
188 if (use_air)
189 chart->addSeries(pv_air);
190 if (use_beer)
191 chart->addSeries(pv_beer); // Top layer
96 192
97 QDateTimeAxis *axisX = new QDateTimeAxis; 193 QDateTimeAxis *axisX = new QDateTimeAxis;
98 axisX->setTickCount(10); 194 axisX->setTickCount(10);
99 axisX->setFormat("dd MMM"); 195 axisX->setFormat("dd MMM");
100 axisX->setTitleText(tr("Date")); 196 axisX->setTitleText(tr("Date"));
101 axisX->setLabelsFont(QFont("Helvetica", 8, QFont::Normal)); 197 axisX->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
102 chart->addAxis(axisX, Qt::AlignBottom); 198 chart->addAxis(axisX, Qt::AlignBottom);
103 pv_air->attachAxis(axisX); 199 if (use_air)
104 pv_beer->attachAxis(axisX); 200 pv_air->attachAxis(axisX);
105 pv_chiller->attachAxis(axisX); 201 if (use_beer)
202 pv_beer->attachAxis(axisX);
203 if (use_chiller)
204 pv_chiller->attachAxis(axisX);
106 205
107 QValueAxis *axisY = new QValueAxis; 206 QValueAxis *axisY = new QValueAxis;
108 axisY->setTickCount(11); 207 axisY->setRange(min, max);
208 axisY->setTickCount(max-min+1);
109 axisY->setMinorTickCount(1); 209 axisY->setMinorTickCount(1);
110 axisY->setLabelFormat("%i"); 210 axisY->setLabelFormat("%.1f");
111 axisY->setTitleText(tr("Temp °C")); 211 axisY->setTitleText(tr("Temp °C"));
112 axisY->setLabelsFont(QFont("Helvetica", 8, QFont::Normal)); 212 axisY->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
113 chart->addAxis(axisY, Qt::AlignLeft); 213 chart->addAxis(axisY, Qt::AlignLeft);
114 pv_air->attachAxis(axisY); 214 if (use_air)
115 pv_beer->attachAxis(axisY); 215 pv_air->attachAxis(axisY);
116 pv_chiller->attachAxis(axisY); 216 if (use_beer)
117 217 pv_beer->attachAxis(axisY);
118 QValueAxis *axisYR = new QValueAxis; 218 if (use_chiller)
119 axisYR->setRange(0, 100); 219 pv_chiller->attachAxis(axisY);
120 axisYR->setTickCount(11); 220
121 axisYR->setLabelFormat("%i"); 221 if (use_heater || use_cooler) {
122 axisYR->setTitleText(tr("Power %")); 222 QValueAxis *axisYR = new QValueAxis;
123 axisYR->setLabelsFont(QFont("Helvetica", 8, QFont::Normal)); 223 axisYR->setRange(0, 100);
124 chart->addAxis(axisYR, Qt::AlignRight); 224 axisYR->setTickCount(11);
125 pwr_cool->attachAxis(axisYR); 225 axisYR->setLabelFormat("%i");
126 pwr_heat->attachAxis(axisYR); 226 axisYR->setTitleText(tr("Power %"));
127 227 axisYR->setLabelsFont(QFont("Helvetica", 8, QFont::Normal));
128 connect(pv_air, &QLineSeries::hovered, this, &ChartFermenter::tooltip); 228 chart->addAxis(axisYR, Qt::AlignRight);
129 connect(pv_beer, &QLineSeries::hovered, this, &ChartFermenter::tooltip); 229 if (use_cooler)
130 connect(pv_chiller, &QLineSeries::hovered, this, &ChartFermenter::tooltip); 230 pwr_cool->attachAxis(axisYR);
231 if (use_heater)
232 pwr_heat->attachAxis(axisYR);
233 }
234
235 if (use_air)
236 connect(pv_air, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
237 if (use_beer)
238 connect(pv_beer, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
239 if (use_chiller)
240 connect(pv_chiller, &QLineSeries::hovered, this, &ChartFermenter::tooltip);
131 241
132 chartView = new QChartView(chart); 242 chartView = new QChartView(chart);
133 chartView->setRenderHint(QPainter::Antialiasing); 243 chartView->setRenderHint(QPainter::Antialiasing);
134 dialog->setLayout(new QHBoxLayout); 244 dialog->setLayout(new QHBoxLayout);
135 dialog->layout()->addWidget(chartView); 245 dialog->layout()->addWidget(chartView);
147 ChartFermenter::~ChartFermenter() {} 257 ChartFermenter::~ChartFermenter() {}
148 258
149 259
150 void ChartFermenter::savePNG() 260 void ChartFermenter::savePNG()
151 { 261 {
152 QString path = QFileDialog::getSaveFileName(this, tr("Save Image"), QDir::homePath() + "/fermenter.png", tr("Image (*.png)")); 262 QSettings settings(QSettings::IniFormat, QSettings::UserScope, "mbse", "bmsapp");
263 QString dirName;
264
265 /*
266 * First check if the directory stored in the settings file exists.
267 * It might be on a removable media that was last used ...
268 * If so, fallback to the user's home directory.
269 */
270 dirName = settings.value("paths/download").toString();
271 if (! QDir(dirName).exists()) {
272 dirName = QDir::homePath();
273 }
274
275 QString path = QFileDialog::getSaveFileName(this, tr("Save Image"), dirName + "/fermenter.png", tr("Image (*.png)"));
153 if (path.isEmpty()) { 276 if (path.isEmpty()) {
154 QMessageBox::warning(this, tr("Save File"), tr("No image file selected.")); 277 QMessageBox::warning(this, tr("Save File"), tr("No image file selected."));
155 return; 278 return;
156 } 279 }
280
281 /*
282 * Update to current selected path
283 */
284 settings.setValue("paths/download", QFileInfo(path).absolutePath());
157 285
158 QImage img((chartView->size()), QImage::Format_ARGB32); 286 QImage img((chartView->size()), QImage::Format_ARGB32);
159 QPainter painter; 287 QPainter painter;
160 painter.begin(&img); 288 painter.begin(&img);
161 chartView->render(&painter); 289 chartView->render(&painter);

mercurial