Merge pull request #2191 from opentx/griebd/log_viewer_on_next_1863

log viewer #1863 for next
This commit is contained in:
Damjan Adamic
2015-04-12 09:22:47 +02:00
13 changed files with 325 additions and 273 deletions
+273 -248
View File
@@ -1,7 +1,6 @@
#include "logsdialog.h"
#include "appdata.h"
#include "ui_logsdialog.h"
#include "qcustomplot.h"
#include "helpers.h"
#if defined WIN32 || !defined __GNUC__
#include <windows.h>
@@ -14,25 +13,43 @@ logsDialog::logsDialog(QWidget *parent) :
ui(new Ui::logsDialog)
{
csvlog.clear();
srand(QDateTime::currentDateTime().toTime_t());
ui->setupUi(this);
this->setWindowIcon(CompanionIcon("logs.png"));
palette.clear();
plotLock=false;
for (int i=0; i< 60; i++)
palette << QColor(rand()%245+10, rand()%245+10, rand()%245+10);
colors.append(Qt::green);
colors.append(Qt::red);
colors.append(Qt::yellow);
colors.append(Qt::magenta);
colors.append(Qt::cyan);
colors.append(Qt::darkBlue);
colors.append(Qt::darkGreen);
colors.append(Qt::darkRed);
colors.append(Qt::darkYellow);
colors.append(Qt::darkMagenta);
colors.append(Qt::darkCyan);
colors.append(Qt::blue);
pen.setWidthF(1.5);
ui->customPlot->setInteractions(QCustomPlot::iRangeDrag | QCustomPlot::iRangeZoom | QCustomPlot::iSelectAxes |
QCustomPlot::iSelectLegend | QCustomPlot::iSelectPlottables | QCustomPlot::iSelectTitle | QCustomPlot::iSelectItems);
ui->customPlot->setRangeDrag(Qt::Horizontal|Qt::Vertical);
ui->customPlot->setRangeZoom(Qt::Horizontal|Qt::Vertical);
ui->customPlot->yAxis->setRange(-1100, 1100);
ui->customPlot->setupFullAxesBox();
ui->customPlot->setTitle(tr("Telemetry logs"));
ui->customPlot->xAxis->setLabel(tr("Time"));
ui->customPlot->xAxis->setLabel(tr("Time (hh:mm:ss)"));
ui->customPlot->xAxis->setTickLabelType(QCPAxis::ltDateTime);
ui->customPlot->xAxis->setDateTimeFormat("hh:mm:ss");
QDateTime now = QDateTime::currentDateTime();
ui->customPlot->xAxis->setRange(now.addSecs(-60*60*2).toTime_t(),
now.toTime_t());
ui->customPlot->legend->setVisible(true);
ui->customPlot->yAxis->setTickLabels(false);
ui->customPlot->yAxis->setAutoTickCount(10);
ui->customPlot->xAxis2->setTicks(false);
ui->customPlot->yAxis2->setTicks(false);
ui->customPlot->setRangeZoomFactor(2, 2);
QFont legendFont = font();
@@ -44,23 +61,22 @@ logsDialog::logsDialog(QWidget *parent) :
QString Path=g.gePath();
if (Path.isEmpty() || !QFile(Path).exists()) {
ui->mapsButton->hide();
}
}
// connect slot that ties some axis selections together (especially opposite axes):
connect(ui->customPlot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
// connect slots that takes care that when an axis is selected, only that direction can be dragged and zoomed:
connect(ui->customPlot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePress()));
connect(ui->customPlot, SIGNAL(mouseWheel(QWheelEvent*)), this, SLOT(mouseWheel()));
// make bottom and left axes transfer their ranges to top and right axes:
connect(ui->customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->customPlot->yAxis2, SLOT(setRange(QCPRange)));
// make left axes transfer its ranges to right axes:
connect(ui->customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(setRangeyAxis2(QCPRange)));
// connect some interaction slots:
connect(ui->customPlot, SIGNAL(titleDoubleClick(QMouseEvent*)), this, SLOT(titleDoubleClick()));
connect(ui->customPlot, SIGNAL(axisDoubleClick(QCPAxis*,QCPAxis::SelectablePart,QMouseEvent*)), this, SLOT(axisLabelDoubleClick(QCPAxis*,QCPAxis::SelectablePart)));
connect(ui->customPlot, SIGNAL(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*,QMouseEvent*)), this, SLOT(legendDoubleClick(QCPLegend*,QCPAbstractLegendItem*)));
connect(ui->customPlot, SIGNAL(plottableDoubleClick(QCPAbstractPlottable *, QMouseEvent *)), this, SLOT(plottableItemDoubleClick(QCPAbstractPlottable *, QMouseEvent *)));
// connect(ui->customPlot, SIGNAL(plottableDoubleClick(QCPAbstractPlottable *, QMouseEvent *)), this, SLOT(plottableItemDoubleClick(QCPAbstractPlottable *, QMouseEvent *)));
connect(ui->FieldsTW, SIGNAL(itemSelectionChanged()), this, SLOT(plotLogs()));
connect(ui->logTable, SIGNAL(itemSelectionChanged()), this, SLOT(plotLogs()));
connect(ui->Reset_PB, SIGNAL(clicked()), this, SLOT(plotLogs()));
@@ -71,24 +87,12 @@ logsDialog::~logsDialog()
delete ui;
}
double logsDialog::GetScale(QString channel) {
QString Analog="Rud,Ele,Thr,Ail,P1,P2,P3";
QString Switches="THR,RUD,ELE,ID0,ID1,ID2,AIL,GEA,TRN";
if (Analog.contains(channel)) {
return 1.0;
}
if (Switches.contains(channel)) {
return 0.001;
}
return -1;
}
void logsDialog::titleDoubleClick()
{
// Set the plot title by double clicking on it
bool ok;
QString newTitle = QInputDialog::getText(this, "QCustomPlot example", "New plot title:", QLineEdit::Normal, ui->customPlot->title(), &ok);
QString newTitle = QInputDialog::getText(this, "Plot Title Change", "New plot title:", QLineEdit::Normal, ui->customPlot->title(), &ok);
if (ok)
{
ui->customPlot->setTitle(newTitle);
@@ -99,11 +103,11 @@ void logsDialog::titleDoubleClick()
void logsDialog::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart part)
{
// Set an axis label by double clicking on it
if (part == QCPAxis::spAxisLabel) // only react when the actual axis label is clicked, not tick label or axis backbone
{
bool ok;
QString newLabel = QInputDialog::getText(this, "QCustomPlot example", "New axis label:", QLineEdit::Normal, axis->label(), &ok);
QString newLabel = QInputDialog::getText(this, "Axis Label Change", "New axis label:", QLineEdit::Normal, axis->label(), &ok);
if (ok)
{
axis->setLabel(newLabel);
@@ -115,13 +119,11 @@ void logsDialog::axisLabelDoubleClick(QCPAxis *axis, QCPAxis::SelectablePart par
void logsDialog::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *item)
{
// Rename a graph by double clicking on its legend item
Q_UNUSED(legend)
if (item) // only react if item was clicked (user could have clicked on border padding of legend where there is no item, then item is 0)
{
QCPPlottableLegendItem *plItem = qobject_cast<QCPPlottableLegendItem*>(item);
bool ok;
QString newName = QInputDialog::getText(this, "QCustomPlot example", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok);
QString newName = QInputDialog::getText(this, "Graph Name Change", "New graph name:", QLineEdit::Normal, plItem->plottable()->name(), &ok);
if (ok)
{
plItem->plottable()->setName(newName);
@@ -129,10 +131,11 @@ void logsDialog::legendDoubleClick(QCPLegend *legend, QCPAbstractLegendItem *ite
}
}
}
void logsDialog::plottableItemDoubleClick(QCPAbstractPlottable * plottable, QMouseEvent * event)
{
// void logsDialog::plottableItemDoubleClick(QCPAbstractPlottable * plottable, QMouseEvent * event)
// {
// qDebug() << plottable->
}
// }
void logsDialog::selectionChanged()
{
@@ -140,31 +143,33 @@ void logsDialog::selectionChanged()
normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
and the axis base line together. However, the axis label shall be selectable individually.
The selection state of the left and right axes shall be synchronized as well as the state of the
bottom and top axes.
Further, we want to synchronize the selection of the graphs with the selection state of the respective
legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
or on its legend item.
*/
if (plotLock)
return;
// make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
if (ui->customPlot->xAxis->selected().testFlag(QCPAxis::spAxis) || ui->customPlot->xAxis->selected().testFlag(QCPAxis::spTickLabels) ||
ui->customPlot->xAxis2->selected().testFlag(QCPAxis::spAxis) || ui->customPlot->xAxis2->selected().testFlag(QCPAxis::spTickLabels))
if (plotLock) return;
// handle bottom axis and tick labels as one selectable object:
if (ui->customPlot->xAxis->selected().testFlag(QCPAxis::spAxis) || ui->customPlot->xAxis->selected().testFlag(QCPAxis::spTickLabels))
{
ui->customPlot->xAxis2->setSelected(QCPAxis::spAxis|QCPAxis::spTickLabels);
ui->customPlot->xAxis->setSelected(QCPAxis::spAxis|QCPAxis::spTickLabels);
}
// make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
// make left and right axes be selected synchronously,
// and handle axis and tick labels as one selectable object:
if (ui->customPlot->yAxis->selected().testFlag(QCPAxis::spAxis) || ui->customPlot->yAxis->selected().testFlag(QCPAxis::spTickLabels) ||
ui->customPlot->yAxis2->selected().testFlag(QCPAxis::spAxis) || ui->customPlot->yAxis2->selected().testFlag(QCPAxis::spTickLabels))
{
ui->customPlot->yAxis2->setSelected(QCPAxis::spAxis|QCPAxis::spTickLabels);
ui->customPlot->yAxis->setSelected(QCPAxis::spAxis|QCPAxis::spTickLabels);
if (hasyAxis2) {
ui->customPlot->yAxis2->setSelected(QCPAxis::spAxis|QCPAxis::spTickLabels);
}
}
// synchronize selection of graphs with selection of corresponding legend items:
for (int i=0; i<ui->customPlot->graphCount(); ++i)
{
@@ -178,7 +183,8 @@ void logsDialog::selectionChanged()
}
}
void logsDialog::on_mapsButton_clicked() {
void logsDialog::on_mapsButton_clicked()
{
int n = csvlog.count(); // number of points in graph
if (n==0) return;
int latcol=0, longcol=0, altcol=0, speedcol=0;
@@ -186,13 +192,13 @@ void logsDialog::on_mapsButton_clicked() {
bool rangeSelected=false;
ui->FieldsTW->setDisabled(true);
ui->logTable->setDisabled(true);
QString gePath=g.gePath();
if (gePath.isEmpty() || !QFile(gePath).exists()) {
ui->FieldsTW->setDisabled(false);
ui->logTable->setDisabled(false);
return;
}
}
QSet<int> nondataCols;
for (int i=1; i<csvlog.at(0).count(); i++) {
//Long,Lat,Course,GPS Speed,GPS Alt
@@ -225,7 +231,7 @@ void logsDialog::on_mapsButton_clicked() {
if (itemSelected==0) {
itemSelected=n-1;
}
QString geIconFilename = generateProcessUniqueTempFileName("track0.png");
if (QFile::exists(geIconFilename)) {
QFile::remove(geIconFilename);
@@ -247,7 +253,7 @@ void logsDialog::on_mapsButton_clicked() {
return;
}
QString latitude,longitude;
double flatitude, flongitude,temp;
double flatitude, flongitude,temp;
QTextStream outputStream(&geFile);
outputStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n";
outputStream << "\t<Document>\n\t\t<name>" << logFilename << "</name>\n";
@@ -269,7 +275,7 @@ void logsDialog::on_mapsButton_clicked() {
}
}
outputStream << "\t\t</Schema>\n";
QString planeName;
if (logFilename.indexOf("-")>0) {
planeName=logFilename.left(logFilename.indexOf("-"));
@@ -286,7 +292,7 @@ void logsDialog::on_mapsButton_clicked() {
outputStream << "\t\t\t\t\t<when>"<< tstamp <<"</when>\n";
}
}
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
latitude=csvlog.at(i).at(latcol).trimmed();
@@ -348,7 +354,7 @@ void logsDialog::mousePress()
{
// if an axis is selected, only allow the direction of that axis to be dragged
// if no axis is selected, both directions may be dragged
if (ui->customPlot->xAxis->selected().testFlag(QCPAxis::spAxis))
ui->customPlot->setRangeDrag(ui->customPlot->xAxis->orientation());
else if (ui->customPlot->yAxis->selected().testFlag(QCPAxis::spAxis))
@@ -370,173 +376,8 @@ void logsDialog::mouseWheel()
}
if (orientation) {
ui->customPlot->setRangeZoom((Qt::Orientation)orientation);
}
}
void logsDialog::plotValue(int index, int plot, int numplots)
{
if (plotLock)
return;
int n = csvlog.count(); // number of points in graph
bool rangeSelected=false;
uint minx;
uint maxx;
uint itemSelected=0;
uint itemCount=0;
double miny=9999;
double maxy=-9999;
minx=-1;
maxx=0;
double tmpval,yscale;
for (int i=1; i<n; i++) {
if (ui->logTable->item(i-1,1)->isSelected()) {
rangeSelected=true;
itemSelected++;
}
}
if (itemSelected==0) {
itemSelected=n-1;
}
QVector<double> x(itemSelected), y(itemSelected);
if (numplots<3) {
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
double tmp;
QString tstamp=csvlog.at(i).at(0)+QString(" ")+csvlog.at(i).at(1);
if (csvlog.at(i).at(1).contains(".")) {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss.zzz").toTime_t();
tmp+=csvlog.at(i).at(1).mid(csvlog.at(i).at(1).indexOf(".")).toDouble();
} else {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss").toTime_t();
}
if (minx>tmp) {
minx=tmp;
}
if (maxx<tmp) {
maxx=tmp;
}
tmpval = csvlog.at(i).at(index).toDouble();
if (tmpval>maxy) {
maxy=tmpval;
}
if (tmpval<miny) {
miny=tmpval;
}
}
}
yscale=1;
} else {
yscale=GetScale(csvlog.at(0).at(index));
for (int i=1; i<n; i++)
{
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
double tmp;
QString tstamp=csvlog.at(i).at(0)+QString(" ")+csvlog.at(i).at(1);
if (csvlog.at(i).at(1).contains(".")) {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss.zzz").toTime_t();
tmp+=csvlog.at(i).at(1).mid(csvlog.at(i).at(1).indexOf(".")).toDouble();
} else {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss").toTime_t();
}
if (minx>tmp) {
minx=tmp;
}
if (maxx<tmp) {
maxx=tmp;
}
if (yscale<0) {
tmpval = csvlog.at(i).at(index).toDouble();
if (tmpval>maxy) {
maxy=tmpval;
}
if (tmpval<miny) {
miny=tmpval;
}
}
}
}
if (yscale<0) {
if (miny<0) {
miny=-miny;
}
if (maxy<0) {
maxy=-maxy;
}
if (miny>maxy) {
yscale=miny/1000.0;
} else {
yscale=maxy/1000.0;
}
if (yscale==0) {
yscale=1;
}
}
}
for (int i=1; i<n; i++) {
if ((ui->logTable->item(i-1,1)->isSelected() &&rangeSelected) || !rangeSelected) {
double tmp;
QString tstamp=csvlog.at(i).at(0)+QString(" ")+csvlog.at(i).at(1);
if (csvlog.at(i).at(1).contains(".")) {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss.zzz").toTime_t();
tmp+=csvlog.at(i).at(1).mid(csvlog.at(i).at(1).indexOf(".")).toDouble();
} else {
tmp=QDateTime::fromString(tstamp, "yyyy-MM-dd HH:mm:ss").toTime_t();
}
x[itemCount] = tmp-minx;
y[itemCount] = csvlog.at(i).at(index).toDouble()/yscale;
itemCount++;
}
}
QPen graphPen;
QColor color=palette.at(index % 60);
graphPen.setColor(color);
graphPen.setWidthF(1.5);
if (numplots<3) {
if (plot==1) {
ui->customPlot->xAxis->setRange(0, maxx-minx);
ui->customPlot->yAxis->setRange(miny,maxy);
ui->customPlot->yAxis->setLabelColor(color);
ui->customPlot->yAxis->setLabel(csvlog.at(0).at(index));
ui->customPlot->yAxis->setTickLabels(true);
ui->customPlot->yAxis->setVisible(true);
ui->customPlot->yAxis2->setVisible(false);
ui->customPlot->addGraph(ui->customPlot->xAxis, ui->customPlot->yAxis);
ui->customPlot->graph(0)->setName(csvlog.at(0).at(index));
ui->customPlot->graph(0)->setData(x, y);
ui->customPlot->graph(0)->setLineStyle(QCPGraph::lsLine);
ui->customPlot->graph(0)->setScatterStyle(QCP::ssNone);
//ui->customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(rand()%5+1));
ui->customPlot->graph(0)->setPen(graphPen);
}
else {
ui->customPlot->xAxis2->setRange(0, maxx-minx);
ui->customPlot->yAxis2->setTickLabels(true);
ui->customPlot->yAxis2->setRange(miny,maxy);
ui->customPlot->yAxis2->setVisible(true);
ui->customPlot->yAxis2->setLabelColor(color);
ui->customPlot->yAxis2->setLabel(csvlog.at(0).at(index));
ui->customPlot->addGraph(ui->customPlot->xAxis2, ui->customPlot->yAxis2);
ui->customPlot->graph(1)->setName(csvlog.at(0).at(index));
ui->customPlot->graph(1)->setData(x, y);
ui->customPlot->graph(1)->setLineStyle(QCPGraph::lsLine);
ui->customPlot->graph(1)->setScatterStyle(QCP::ssNone);
//ui->customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(rand()%5+1));
ui->customPlot->graph(1)->setPen(graphPen);
}
}
else {
ui->customPlot->yAxis->setTickLabels(false);
ui->customPlot->yAxis2->setTickLabels(false);
ui->customPlot->yAxis->setRange(-1100, 1100);
ui->customPlot->yAxis->setVisible(false);
ui->customPlot->yAxis2->setVisible(false);
ui->customPlot->addGraph();
ui->customPlot->graph()->setName(csvlog.at(0).at(index));
ui->customPlot->graph()->setData(x, y);
ui->customPlot->graph()->setLineStyle(QCPGraph::lsLine);
ui->customPlot->graph()->setScatterStyle(QCP::ssNone);
//ui->customPlot->graph()->setLineStyle((QCPGraph::LineStyle)(rand()%5+1));
ui->customPlot->graph()->setPen(graphPen);
ui->customPlot->setRangeZoom(Qt::Horizontal|Qt::Vertical);
}
}
@@ -552,6 +393,9 @@ void logsDialog::removeSelectedGraph()
void logsDialog::removeAllGraphs()
{
ui->customPlot->clearGraphs();
ui->customPlot->legend->setVisible(false);
ui->customPlot->yAxis2->setVisible(false);
ui->customPlot->yAxis->setTickLabels(false);
ui->customPlot->replot();
}
@@ -602,7 +446,7 @@ void logsDialog::on_fileOpen_BT_clicked()
}
ui->logTable->setItem(i-1,j,item );
}
}
}
ui->logTable->resizeColumnsToContents();
ui->logTable->resizeRowsToContents();
// Hack - add some pixel of space to columns as Qt resize them too small
@@ -614,7 +458,7 @@ void logsDialog::on_fileOpen_BT_clicked()
}
}
bool logsDialog::cvsFileParse()
bool logsDialog::cvsFileParse()
{
QFile file(ui->FileName_LE->text());
int errors=0;
@@ -676,7 +520,7 @@ bool logsDialog::cvsFileParse()
}
logFilename=QFileInfo(file.fileName()).baseName();
}
file.close();
if (errors>1) {
QMessageBox::warning(this, "Companion", tr("The selected logfile contains %1 invalid lines out of %2 total lines").arg(errors).arg(lines));
@@ -687,8 +531,8 @@ bool logsDialog::cvsFileParse()
csvlog.clear();
return false;
}
int lastvalue=0;
int tmp;
double lastvalue=0;
double tmp;
ui->sessions_CB->addItem("---");
for (int i=1; i<n; i++) {
QString tstamp=csvlog.at(i).at(0)+QString(" ")+csvlog.at(i).at(1);
@@ -715,19 +559,19 @@ void logsDialog::on_sessions_CB_currentIndexChanged(int index)
if (plotLock)
return;
plotLock=true;
int start=0;
int stop=-1;
double start=0;
double stop=-1;
if (index!=0) {
start=ui->sessions_CB->itemData(index,Qt::UserRole).toInt();
start=ui->sessions_CB->itemData(index,Qt::UserRole).toDouble();
if (index<(ui->sessions_CB->count()-1)) {
stop=ui->sessions_CB->itemData(index+1,Qt::UserRole).toInt();
stop=ui->sessions_CB->itemData(index+1,Qt::UserRole).toDouble();
}
}
// if (ui->logTable->item(i-1,1)->isSelected()) {
ui->logTable->clearSelection();
if (start>0) {
int n=csvlog.count();
int tmp;
double tmp;
ui->logTable->setSelectionBehavior(QAbstractItemView::SelectRows);
for (int i=1; i<n; i++) {
QString tstamp=csvlog.at(i).at(0)+QString(" ")+csvlog.at(i).at(1);
@@ -750,7 +594,7 @@ void logsDialog::on_sessions_CB_currentIndexChanged(int index)
ui->logTable->selectionModel()->select(ui->logTable->model()->index(i-1,0), QItemSelectionModel::Select|QItemSelectionModel::Rows);
}
}
}
}
}
plotLock=false;
plotLogs();
@@ -758,24 +602,205 @@ void logsDialog::on_sessions_CB_currentIndexChanged(int index)
void logsDialog::plotLogs()
{
if (plotLock)
if (plotLock) return;
if (!ui->FieldsTW->selectedItems().length()) {
removeAllGraphs();
return;
int n = csvlog.at(0).count(); // number of points in graph
}
plotsCollection plots;
QList<QTableWidgetSelectionRange> selections = ui->logTable->selectedRanges();
int rowCount = selections.length();
bool hasLogSelection;
QVarLengthArray<int> selectedRows;
if (rowCount) {
hasLogSelection = true;
foreach (QTableWidgetSelectionRange range, selections) {
for (int i = range.topRow(); i <= range.bottomRow(); i++) {
selectedRows.append(i);
}
}
} else {
hasLogSelection = false;
rowCount = ui->logTable->rowCount();
}
plots.min_x = QDateTime::currentDateTime().toTime_t();
plots.max_x = 0;
foreach (QTableWidgetItem *plot, ui->FieldsTW->selectedItems()) {
coords plotCoords;
int plotColumn = plot->row() + 2; // Date and Time first
plotCoords.min_y = 999999;
plotCoords.max_y = -999999;
plotCoords.secondRange = false;
plotCoords.name = plot->text();
for (int row = 0; row < rowCount; row++) {
QTableWidgetItem *logValue;
if (hasLogSelection) {
logValue = ui->logTable->item(selectedRows.at(row), plotColumn);
} else {
logValue = ui->logTable->item(row, plotColumn);
}
double y;
double time;
QString time_str;
y = logValue->text().toDouble();
plotCoords.y.push_back(y);
if (plotCoords.min_y > y) {
plotCoords.min_y = y;
} else if (plotCoords.max_y < y) {
plotCoords.max_y = y;
}
time_str = ui->logTable->item(row, 0)->text() + QString(" ")
+ ui->logTable->item(row, 1)->text();
if (time_str.contains('.')) {
time = QDateTime::fromString(time_str, "yyyy-MM-dd HH:mm:ss.zzz")
.toTime_t();
time += time_str.mid(time_str.indexOf('.')).toDouble();
} else {
time = QDateTime::fromString(time_str, "yyyy-MM-dd HH:mm:ss")
.toTime_t();
}
plotCoords.x.push_back(time);
if (plots.min_x > time) {
plots.min_x = time;
} else if (plots.max_x < time) {
plots.max_x = time;
}
}
plots.coords.append(plotCoords);
}
plots.rangeOneMin = plots.coords.at(0).min_y;
plots.rangeOneMax = plots.coords.at(0).max_y;
plots.twoRanges = false;
plots.tooManyRanges = false;
for (int i = 1; i < plots.coords.size(); i++) {
if (plots.tooManyRanges) {
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
}
continue;
}
double actualRange = plots.rangeOneMax - plots.rangeOneMin;
double thisRange = plots.coords.at(i).max_y - plots.coords.at(i).min_y;
if (thisRange > actualRange * 1.3 || thisRange * 1.3 < actualRange ||
plots.coords.at(i).min_y > plots.rangeOneMax ||
plots.coords.at(i).max_y < plots.rangeOneMin) {
plots.coords[i].secondRange = true;
if (plots.twoRanges) {
actualRange = plots.rangeTwoMax - plots.rangeTwoMin;
if (thisRange > actualRange * 1.3 || thisRange * 1.3 < actualRange ||
plots.coords.at(i).min_y > plots.rangeTwoMax ||
plots.coords.at(i).max_y < plots.rangeTwoMin) {
plots.tooManyRanges = true;
plots.twoRanges = false;
if (plots.rangeTwoMin < plots.rangeOneMin) {
plots.rangeOneMin = plots.rangeTwoMin;
}
if (plots.rangeTwoMax > plots.rangeOneMax) {
plots.rangeOneMax = plots.rangeTwoMax;
}
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
}
} else {
if (plots.coords.at(i).min_y < plots.rangeTwoMin) {
plots.rangeTwoMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeTwoMax) {
plots.rangeTwoMax = plots.coords.at(i).max_y;
}
}
} else {
plots.twoRanges = true;
plots.rangeTwoMax = plots.coords.at(i).max_y;
plots.rangeTwoMin = plots.coords.at(i).min_y;
}
} else {
if (plots.coords.at(i).min_y < plots.rangeOneMin) {
plots.rangeOneMin = plots.coords.at(i).min_y;
}
if (plots.coords.at(i).max_y > plots.rangeOneMax) {
plots.rangeOneMax = plots.coords.at(i).max_y;
}
}
}
if (plots.twoRanges) {
rangeRatio = (plots.rangeTwoMax - plots.rangeTwoMin) /
(plots.rangeOneMax - plots.rangeOneMin);
rangeyAxisMin = plots.rangeOneMin;
rangeyAxisMax = plots.rangeOneMax;
rangeyAxis2Min = plots.rangeTwoMin;
rangeyAxis2Max = plots.rangeTwoMax;
hasyAxis2 = true;
} else {
hasyAxis2 = false;
}
removeAllGraphs();
int numplots=0;
int plots=0;
for (int i=0; i<n-2; i++) {
if (ui->FieldsTW->item(0,i)->isSelected()) {
numplots++;
}
ui->customPlot->xAxis->setRange(plots.min_x, plots.max_x);
ui->customPlot->yAxis->setRange(plots.rangeOneMin, plots.rangeOneMax);
ui->customPlot->yAxis->setTickLabels(true);
if (plots.twoRanges) {
ui->customPlot->yAxis2->setRange(plots.rangeTwoMin, plots.rangeTwoMax);
ui->customPlot->yAxis2->setVisible(true);
}
for (int i=0; i<n-2; i++) {
if (ui->FieldsTW->item(0,i)->isSelected()) {
plots++;
plotValue(i+2,plots, numplots);
for (int i = 0; i < plots.coords.size(); i++) {
if (plots.coords.at(i).secondRange && plots.twoRanges) {
ui->customPlot->addGraph(ui->customPlot->xAxis, ui->customPlot->yAxis2);
} else {
ui->customPlot->addGraph();
}
ui->customPlot->graph(i)->setData(plots.coords.at(i).x,
plots.coords.at(i).y);
pen.setColor(colors.at(i % colors.size()));
ui->customPlot->graph(i)->setPen(pen);
ui->customPlot->graph(i)->setName(plots.coords.at(i).name);
}
ui->customPlot->legend->setVisible((numplots>2));
ui->customPlot->replot();
ui->customPlot->legend->setVisible(true);
ui->customPlot->replot();
}
void logsDialog::setRangeyAxis2(QCPRange range)
{
if (hasyAxis2) {
double lowerChange = (range.lower - rangeyAxisMin) * rangeRatio;
double upperChange = (range.upper - rangeyAxisMax) * rangeRatio;
rangeyAxisMin = range.lower;
rangeyAxisMax = range.upper;
rangeyAxis2Min += lowerChange;
rangeyAxis2Max += upperChange;
ui->customPlot->yAxis2->setRange(rangeyAxis2Min, rangeyAxis2Max);
}
}
+35 -8
View File
@@ -5,6 +5,26 @@
#include <QtGui>
#include "qcustomplot.h"
struct coords {
QVector<double> x, y;
double min_y;
double max_y;
bool secondRange;
QString name;
};
struct plotsCollection {
QVarLengthArray<struct coords> coords;
double min_x;
double max_x;
bool twoRanges;
bool tooManyRanges;
double rangeOneMin;
double rangeOneMax;
double rangeTwoMin;
double rangeTwoMax;
};
namespace Ui {
class logsDialog;
}
@@ -12,12 +32,11 @@ namespace Ui {
class logsDialog : public QDialog
{
Q_OBJECT
public:
explicit logsDialog(QWidget *parent = 0);
~logsDialog();
private slots:
void titleDoubleClick();
void axisLabelDoubleClick(QCPAxis* axis, QCPAxis::SelectablePart part);
@@ -29,21 +48,29 @@ private slots:
void removeAllGraphs();
void moveLegend();
void plotLogs();
void plotValue(int index, int plot, int numplots);
void plottableItemDoubleClick(QCPAbstractPlottable * plottable, QMouseEvent * event);
// void plottableItemDoubleClick(QCPAbstractPlottable * plottable, QMouseEvent * event);
// void graphClicked(QCPAbstractPlottable *plottable);
void on_fileOpen_BT_clicked();
void on_sessions_CB_currentIndexChanged(int index);
void on_mapsButton_clicked();
void setRangeyAxis2(QCPRange range);
private:
QList<QStringList> csvlog;
Ui::logsDialog *ui;
bool cvsFileParse();
double GetScale(QString channel);
QList<QColor> palette;
bool plotLock;
QString logFilename;
QVarLengthArray<Qt::GlobalColor> colors;
QPen pen;
bool hasyAxis2;
double rangeRatio;
double rangeyAxisMin;
double rangeyAxisMax;
double rangeyAxis2Min;
double rangeyAxis2Max;
};
#endif // LOGSDIALOG_H
+1 -1
View File
@@ -11191,7 +11191,7 @@ Tlačítkem Zrušit přerušíte kalibraci</translation>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Čas</translation>
</message>
<message>
+4 -4
View File
@@ -1926,7 +1926,7 @@ If blank then the input is considered to be &quot;ON&quot; all the time.</source
<message>
<source>Set language of voice.
May be different from firmware language</source>
<translation type="obsolete">Sprachdatei einstellen
<translation type="obsolete">Sprachdatei einstellen
kann auch von der Firmwaresprache abweichen</translation>
</message>
<message>
@@ -3304,7 +3304,7 @@ Werte liegen zwischen 5-10V</translation>
This function cannot be disabled by the radio.
Are you sure ?</source>
<translation>Wenn Sie den FAI-Mode aktiveren gibt es kein Vario, keine Ansagen und Telemetrieanzeigen mehr
Diese Funktionen können dann am Sedner nicht wieder freigeschaltet werden!
Diese Funktionen können dann am Sedner nicht wieder freigeschaltet werden!
Sind Sie sicher, dass sie das so wollen?</translation>
</message>
<message>
@@ -8601,7 +8601,7 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
</source>
<translation>Vollgas hinten?
Wenn das angewählt wird, dann ist Leerlauf vorne. Auch die Gas-Leerlauftrimmung und die Gasstellungs-Warung wird
Wenn das angewählt wird, dann ist Leerlauf vorne. Auch die Gas-Leerlauftrimmung und die Gasstellungs-Warung wird
umgedreht und ist dann vorne
</translation>
</message>
@@ -11971,7 +11971,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Zeit</translation>
</message>
<message>
+1 -1
View File
@@ -13030,7 +13030,7 @@ Paina &quot;peruuta&quot; niin joystickin kalibrointi perutetaan</translation>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Aika</translation>
</message>
<message>
+2 -2
View File
@@ -4426,7 +4426,7 @@ Voulez-vous la télécharger maintenant ?</translation>
<source>The file %1
has not been recognized as a valid Models and Settings file
Write anyway ?</source>
<translation>Le fichier %1
<translation>Le fichier %1
n&apos;a pas été reconnu comme un fichier de réglages et modèles valide.
Ecrire quand même?</translation>
</message>
@@ -10711,7 +10711,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Heure</translation>
</message>
<message>
+1 -1
View File
@@ -10239,7 +10239,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation type="unfinished"></translation>
</message>
<message>
+1 -1
View File
@@ -11451,7 +11451,7 @@ Premere annulla per cancellare l&apos;operazione</translation>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Tempo</translation>
</message>
<message>
+1 -1
View File
@@ -10232,7 +10232,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation type="unfinished"></translation>
</message>
<message>
+2 -2
View File
@@ -6904,7 +6904,7 @@ Pozostałe
Kajakarstwo
Łucznictwo
MTB
Pięciobój nowoczesny
Podnoszenie ciężarów
@@ -11971,7 +11971,7 @@ Anuluj w celu przerwania kalibracji joysticka</translation>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Czas</translation>
</message>
<message>
+1 -1
View File
@@ -10478,7 +10478,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation type="unfinished"></translation>
</message>
<message>
+1 -1
View File
@@ -10414,7 +10414,7 @@ Press cancel to abort joystick calibration</source>
</message>
<message>
<location filename="../logsdialog.cpp" line="31"/>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation type="unfinished"></translation>
</message>
<message>
+2 -2
View File
@@ -2744,7 +2744,7 @@ Mode 4:
</message>
<message>
<source>Play Delay (switch mid position)</source>
<translation>Talfördröjning för
<translation>Talfördröjning för
brytare</translation>
</message>
<message>
@@ -8895,7 +8895,7 @@ Tryck på Avbryt för att avburyta kalibreringen</translation>
<translation>Telemetriloggar</translation>
</message>
<message>
<source>Time</source>
<source>Time (hh:mm:ss)</source>
<translation>Tid</translation>
</message>
<message>