Add XDATA to Ride Editor Part 1 of 2

.. add XDataDialog and tabs to the ride editor, so you can
   add and remove xdata and the individual data series.

.. next commit will add editing of the xdata values.
This commit is contained in:
Mark Liversedge
2016-07-04 16:33:37 +01:00
parent dfff9e2ba6
commit aaec9ce43c
9 changed files with 803 additions and 8 deletions

View File

@@ -27,6 +27,7 @@
#include "TabView.h"
#include "HelpWhatsThis.h"
#include "HrZones.h"
#include "XDataDialog.h"
#include <QtGui>
#include <QString>
@@ -122,6 +123,17 @@ RideEditor::RideEditor(Context *context) : GcChartWindow(context), data(NULL), r
connect(checkAct, SIGNAL(triggered()), this, SLOT(anomalies()));
toolbar->addAction(checkAct);
QIcon xdataIcon(":images/toolbar/properties.png");
xdataAct = new QAction(xdataIcon, tr("XData"), this);
connect(xdataAct, SIGNAL(triggered()), this, SLOT(xdata()));
toolbar->addAction(xdataAct);
// add a tabbar, with no tabs, hide it and only show
// if there are more than one tabs (i.e. we have XDATA)
tabbar = new EditorTabBar(this);
tabbar->setCurrentIndex(0);
tabbar->hide();
// empty model
model = new RideFileTableModel(NULL);
@@ -151,6 +163,7 @@ RideEditor::RideEditor(Context *context) : GcChartWindow(context), data(NULL), r
//mainLayout->addWidget(title);
mainLayout->addWidget(toolbar);
mainLayout->addWidget(table);
mainLayout->addWidget(tabbar);
// trap GC signals
connect(context, SIGNAL(intervalSelected()), this, SLOT(intervalSelected()));
@@ -166,6 +179,10 @@ RideEditor::RideEditor(Context *context) : GcChartWindow(context), data(NULL), r
anomalyTool = new AnomalyDialog(this);
anomalyTool->hide();
// xdatatool
xdataTool = new XDataDialog(this);
xdataTool->hide();
// allow us to jump to an anomaly
connect(anomalyTool->anomalyList, SIGNAL(itemSelectionChanged()), this, SLOT(anomalySelected()));
@@ -186,6 +203,13 @@ RideEditor::configChanged(qint32)
palette.setColor(QPalette::Text, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
palette.setColor(QPalette::Normal, QPalette::Window, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
setPalette(palette);
tabbar->setPalette(palette);
QColor faded = GCColor::invertColor(GColor(CPLOTBACKGROUND));
tabbar->setStyleSheet(QString("QTabBar::tab { background-color: %1; border: 2px %1; color: rgba(%3,%4,%5,25%) }"
"QTabBar::tab:selected { background-color: %1; color: %2; border: 2px %1 }")
.arg(GColor(CPLOTBACKGROUND).name())
.arg(GCColor::invertColor(GColor(CPLOTBACKGROUND)).name())
.arg(faded.red()).arg(faded.green()).arg(faded.blue()));
table->setPalette(palette);
table->setStyleSheet(QString("QTableView QTableCornerButton::section { background-color: %1; color: %2; border: %1 }")
.arg(GColor(CPLOTBACKGROUND).name())
@@ -360,6 +384,7 @@ RideEditor::hideEvent(QHideEvent *)
{
findTool->hide();
anomalyTool->hide();
xdataTool->hide();
}
void
@@ -379,6 +404,16 @@ RideEditor::anomalies()
}
void
RideEditor::xdata()
{
// work with xdata series (add / remove)
if (ride && ride->ride()) {
// show the xdata dialog
xdataTool->show();
}
}
void
AnomalyDialog::check()
{
@@ -1277,6 +1312,7 @@ RideEditor::rideSelected()
{
findTool->hide(); // hide the dialog!
anomalyTool->hide();
xdataTool->hide();
RideItem *current = myRideItem;
if (!current || !current->ride() || !current->ride()->dataPoints().count()) {
@@ -1300,6 +1336,9 @@ RideEditor::rideSelected()
}
model->setRide(ride->ride());
// Set for XDATA
setTabBar();
// reset the save icon on the toolbar
if (ride->isDirty()) saveAct->setEnabled(true);
else saveAct->setEnabled(false);
@@ -1326,6 +1365,32 @@ RideEditor::rideSelected()
// update finder pane to show available channels
findTool->rideSelected();
// xdata
xdataTool->setRideItem(ride);
}
void
RideEditor::setTabBar()
{
while(tabbar->count()) tabbar->removeTab(0);
tabbar->hide();
tabbar->addTab(tr("STANDARD"));
if (ride->ride()->xdata().count()) {
// we need xdata editing too
QMapIterator<QString, XDataSeries *>it(ride->ride()->xdata());
it.toFront();
while(it.hasNext()) {
it.next();
QString name = it.key();
tabbar->addTab(name);
}
tabbar->show();
} else {
tabbar->hide();
}
tabbar->setCurrentIndex(0);
}
void
@@ -1385,6 +1450,9 @@ RideEditor::endCommand(bool undo, RideCommand *cmd)
if (ride->ride()->command->undoCount() == 0) undoAct->setEnabled(false);
else undoAct->setEnabled(true);
// react to xdata changes
setTabBar();
// update the selection model when a command has been executed
switch (cmd->type) {
@@ -1536,6 +1604,7 @@ RideEditor::endCommand(bool undo, RideCommand *cmd)
// check for anomalies
if (!inLUW) {
anomalyTool->check();
xdataTool->setRideItem(ride);// rebuild tables
// let everyone know we changed some data
ride->notifyRideDataChanged();
@@ -2629,3 +2698,10 @@ AnomalyDialog::reject()
{
hide();
}
QSize EditorTabBar::tabSizeHint(int index) const
{
QSize def = QTabBar::tabSizeHint(index);
def.setWidth(20); // totally ignored, I hate QT sometimes
return def;
}

View File

@@ -29,6 +29,8 @@
#include <QtGui>
#include <QGroupBox>
#include <QCheckBox>
#include <QSize>
#include <QTabBar>
#include <QTableView>
#include <QTableWidget>
#include <QHeaderView>
@@ -42,7 +44,9 @@ class CellDelegate;
class RideModel;
class FindDialog;
class AnomalyDialog;
class XDataDialog;
class PasteSpecialDialog;
class EditorTabBar;
class RideEditor : public GcChartWindow
{
@@ -89,6 +93,7 @@ class RideEditor : public GcChartWindow
void redo();
void find();
void anomalies();
void xdata();
// anomaly list
void anomalySelected();
@@ -120,6 +125,7 @@ class RideEditor : public GcChartWindow
// GC signals
void configChanged(qint32);
void rideSelected();
void setTabBar();
void intervalSelected();
void rideDirty();
void rideClean();
@@ -135,6 +141,7 @@ class RideEditor : public GcChartWindow
QStringList copyHeadings;
FindDialog *findTool;
AnomalyDialog *anomalyTool;
XDataDialog *xdataTool;
private:
Context *context;
@@ -145,9 +152,11 @@ class RideEditor : public GcChartWindow
QList<QString> whatColumns();
QSignalMapper *colMapper;
EditorTabBar *tabbar;
QToolBar *toolbar;
QAction *saveAct, *undoAct, *redoAct,
*searchAct, *checkAct;
*searchAct, *checkAct, *xdataAct;
// state data
struct { int row, column; } currentCell;
@@ -328,4 +337,14 @@ class PasteSpecialDialog : public QDialog
QPushButton *okButton, *cancelButton;
};
class EditorTabBar : public QTabBar
{
public:
EditorTabBar(QWidget *p) : QTabBar(p) {}
protected:
virtual QSize tabSizeHint(int index) const;
};
#endif // _GC_RideEditor_h

View File

@@ -661,12 +661,12 @@ JsonFileReader::writeRideFile(Context *, const RideFile *ride, QFile &file) cons
//
// XDATA
//
if (ride->xdata().count()) {
if (const_cast<RideFile*>(ride)->xdata().count()) {
// output the xdata series
out << ",\n\t\t\"XDATA\":[\n";
bool first = true;
QMapIterator<QString,XDataSeries*> xdata(ride->xdata());
QMapIterator<QString,XDataSeries*> xdata(const_cast<RideFile*>(ride)->xdata());
xdata.toFront();
while(xdata.hasNext()) {
@@ -731,6 +731,8 @@ JsonFileReader::writeRideFile(Context *, const RideFile *ride, QFile &file) cons
}
out << "\n\t\t\t]\n";
} else {
out << "\n";
}
out << "\t\t}";

View File

@@ -328,9 +328,9 @@ class RideFile : public QObject // QObject to emit signals
WPrime *wprimeData(); // return wprime, init/refresh if needed
// XDATA
XDataSeries *xdata(QString name);
XDataSeries *xdata(QString name) { return xdata_.value(name, NULL); }
void addXData(QString name, XDataSeries *series);
const QMap<QString,XDataSeries*> &xdata() const { return xdata_; }
QMap<QString,XDataSeries*> &xdata() { return xdata_; }
// METRIC OVERRIDES
QMap<QString,QMap<QString,QString> > metricOverrides;
@@ -541,10 +541,19 @@ public:
class XDataSeries {
public:
XDataSeries() {}
XDataSeries(XDataSeries &other) {
name = other.name;
valuename = other.valuename;
valuetype = other.valuetype;
datapoints = other.datapoints;
}
~XDataSeries() { foreach(XDataPoint *p, datapoints) delete p; }
QString name;
QStringList valuename;
QList<RideFile::SeriesType> valuetype;
QVector<XDataPoint*> datapoints;
};

View File

@@ -102,6 +102,35 @@ RideFileCommand::changeLog()
}
return log;
}
void
RideFileCommand::removeXData(QString name)
{
RemoveXDataCommand *cmd = new RemoveXDataCommand(ride, name);
doCommand(cmd);
}
void
RideFileCommand::addXData(XDataSeries *series)
{
AddXDataCommand *cmd = new AddXDataCommand(ride, series);
doCommand(cmd);
}
void
RideFileCommand::addXDataSeries(QString xdata, QString name)
{
AddXDataSeriesCommand *cmd = new AddXDataSeriesCommand(ride, xdata, name);
doCommand(cmd);
}
void
RideFileCommand::removeXDataSeries(QString xdata, QString name)
{
RemoveXDataSeriesCommand *cmd = new RemoveXDataSeriesCommand(ride, xdata, name);
doCommand(cmd);
}
//----------------------------------------------------------------------
// Manage the Command Stack
//----------------------------------------------------------------------
@@ -407,3 +436,142 @@ SetDataPresentCommand::undoCommand()
ride->setDataPresent(series, oldvalue);
return true;
}
RemoveXDataCommand::RemoveXDataCommand(RideFile *ride, QString name) : RideCommand(ride), name(name) {
type = RideCommand::removeXData;
description = tr("Remove XData");
}
bool
RemoveXDataCommand::doCommand()
{
series = ride->xdata(name);
ride->xdata().remove(name);
return true;
}
bool
RemoveXDataCommand::undoCommand()
{
ride->xdata().insert(name, series);
return true;
}
AddXDataCommand::AddXDataCommand(RideFile *ride, XDataSeries *series) : RideCommand(ride), series(series) {
type = RideCommand::addXData;
description = tr("Add XData");
}
bool
AddXDataCommand::doCommand()
{
ride->xdata().insert(series->name, series);
return true;
}
bool
AddXDataCommand::undoCommand()
{
ride->xdata().remove(series->name);
return true;
}
RemoveXDataSeriesCommand::RemoveXDataSeriesCommand(RideFile *ride, QString xdata, QString name) : RideCommand(ride), xdata(xdata), name(name) {
type = RideCommand::RemoveXDataSeries;
description = tr("Remove XData Series");
}
bool
RemoveXDataSeriesCommand::doCommand()
{
index = -1;
// whats the index?
XDataSeries *series = ride->xdata(xdata);
if (series == NULL) return false;
index = series->valuename.indexOf(name);
if (index == -1) return false;
// snaffle away the data and clear
values.resize(series->datapoints.count());
for(int i=0; i<series->datapoints.count(); i++) {
values[i] = series->datapoints[i]->number[index];
series->datapoints[i]->number[index] = 0;
// shift the values down
for(int j=index+1; j<8; j++) {
series->datapoints[i]->number[j-1] =
series->datapoints[i]->number[j];
}
}
// remove the name
series->valuename.removeAt(index);
return true;
}
bool
RemoveXDataSeriesCommand::undoCommand()
{
if (index == -1 || name == "") return false;
// add the series back
XDataSeries *series = ride->xdata(xdata);
if (series == NULL) return false;
series->valuename.insert(index, name);
// put data back
for(int i=0; i<series->datapoints.count(); i++) {
// shift the values right
for(int j=index; j<7; j++) {
series->datapoints[i]->number[j+1] =
series->datapoints[i]->number[j];
}
series->datapoints[i]->number[index] = values[i];
}
return true;
}
AddXDataSeriesCommand::AddXDataSeriesCommand(RideFile *ride, QString xdata, QString name) : RideCommand(ride), xdata(xdata), name(name) {
type = RideCommand::AddXDataSeries;
description = tr("Add XData Series");
}
bool
AddXDataSeriesCommand::doCommand()
{
// whats the index?
XDataSeries *series = ride->xdata(xdata);
if (series == NULL) return false;
series->valuename.append(name);
int index = series->valuename.indexOf(name);
if (index == -1) return false;
// Clear the value
for(int i=0; i<series->datapoints.count(); i++) {
series->datapoints[i]->number[index] = 0;
}
return true;
}
bool
AddXDataSeriesCommand::undoCommand()
{
// add the series back
XDataSeries *series = ride->xdata(xdata);
if (series == NULL) return false;
int index = series->valuename.count()-1;
if (index == -1) return false;
series->valuename.removeAt(index);
return true;
}

View File

@@ -55,6 +55,12 @@ class RideFileCommand : public QObject
void appendPoints(QVector <struct RideFilePoint> newRows);
void setDataPresent(RideFile::SeriesType, bool);
// working with xdata
void removeXData(QString name);
void addXData(XDataSeries *series);
void removeXDataSeries(QString xdata, QString name);
void addXDataSeries(QString xdata, QString name);
// execute atomic actions
void doCommand(RideCommand*, bool noexec=false);
void undoCommand();
@@ -94,7 +100,8 @@ class RideCommand
{
public:
// supported command types
enum commandtype { NoOp, LUW, SetPointValue, DeletePoint, DeletePoints, InsertPoint, AppendPoints, SetDataPresent };
enum commandtype { NoOp, LUW, SetPointValue, DeletePoint, DeletePoints, InsertPoint, AppendPoints, SetDataPresent,
removeXData, addXData, RemoveXDataSeries, AddXDataSeries };
typedef enum commandtype CommandType;
@@ -127,6 +134,61 @@ class LUWCommand : public RideCommand
RideFileCommand *commander;
};
class RemoveXDataCommand : public RideCommand
{
Q_DECLARE_TR_FUNCTIONS(RemoveXDataCommand)
public:
RemoveXDataCommand(RideFile *ride, QString name);
bool doCommand();
bool undoCommand();
// state
QString name;
XDataSeries *series;
};
class AddXDataCommand : public RideCommand
{
Q_DECLARE_TR_FUNCTIONS(addXDataCommand)
public:
AddXDataCommand(RideFile *ride, XDataSeries *series);
bool doCommand();
bool undoCommand();
// state
XDataSeries *series;
};
class RemoveXDataSeriesCommand : public RideCommand
{
Q_DECLARE_TR_FUNCTIONS(RemoveXDataSeriesCommand)
public:
RemoveXDataSeriesCommand(RideFile *ride, QString xdata, QString name);
bool doCommand();
bool undoCommand();
// state
QString xdata, name;
int index;
QVector<double> values;
};
class AddXDataSeriesCommand : public RideCommand
{
Q_DECLARE_TR_FUNCTIONS(AddXDataSeriesCommand)
public:
AddXDataSeriesCommand(RideFile *ride, QString xdata, QString name);
bool doCommand();
bool undoCommand();
// state
QString xdata, name;
};
class SetPointValueCommand : public RideCommand
{
Q_DECLARE_TR_FUNCTIONS(SetPointValueCommand)

354
src/FileIO/XDataDialog.cpp Normal file
View File

@@ -0,0 +1,354 @@
/*
* Copyright (c) 2016 Mark Liversedge <liversedge@gmail.com>
*
* This program 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 2 of the License, or (at your option)
* any later version.
*
* This program 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, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "XDataDialog.h"
#include "RideItem.h"
#include "RideFile.h"
#include "RideFileCommand.h"
#include <QFormLayout>
#include <QLabel>
#include <QMessageBox>
///
/// XDataDialog
///
XDataDialog::XDataDialog(QWidget *parent) : QDialog(parent), item(NULL)
{
setWindowTitle("XData");
//setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::Tool);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// create all the widgets
QLabel *xlabel = new QLabel(tr("xData"));
xdataTable = new QTableWidget(this);
#ifdef Q_OS_MAX
xdataTable->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
xdataTable->setColumnCount(1);
xdataTable->horizontalHeader()->setStretchLastSection(true);
xdataTable->horizontalHeader()->hide();
xdataTable->setSortingEnabled(false);
xdataTable->verticalHeader()->hide();
xdataTable->setShowGrid(false);
xdataTable->setSelectionMode(QAbstractItemView::SingleSelection);
xdataTable->setSelectionBehavior(QAbstractItemView::SelectRows);
QLabel *xslabel = new QLabel(tr("Data Series"));
xdataSeriesTable = new QTableWidget(this);
#ifdef Q_OS_MAX
xdataSeriesTable->setAttribute(Qt::WA_MacShowFocusRect, 0);
#endif
xdataSeriesTable->setColumnCount(1);
xdataSeriesTable->horizontalHeader()->setStretchLastSection(true);
xdataSeriesTable->horizontalHeader()->hide();
xdataSeriesTable->setSortingEnabled(false);
xdataSeriesTable->verticalHeader()->hide();
xdataSeriesTable->setShowGrid(false);
xdataSeriesTable->setSelectionMode(QAbstractItemView::SingleSelection);
xdataSeriesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
addXData = new QPushButton("+", this);
removeXData = new QPushButton("-", this);
addXDataSeries = new QPushButton("+", this);
removeXDataSeries = new QPushButton("-", this);
#ifdef Q_OS_MAC
addXData->setText(tr("Add"));
removeXData->setText(tr("Delete"));
addXDataSeries->setText(tr("Add"));
removeXDataSeries->setText(tr("Delete"));
#else
addXData->setFixedSize(20,20);
addXDataSeries->setFixedSize(20,20);
removeXData->setFixedSize(20,20);
removeXDataSeries->setFixedSize(20,20);
#endif
// lay it out
mainLayout->addWidget(xlabel);
mainLayout->addWidget(xdataTable);
QHBoxLayout *xb = new QHBoxLayout();
xb->addStretch();
xb->addWidget(addXData);
xb->addWidget(removeXData);
mainLayout->addLayout(xb);
mainLayout->addWidget(xslabel);
mainLayout->addWidget(xdataSeriesTable);
QHBoxLayout *xs = new QHBoxLayout();
xs->addStretch();
xs->addWidget(addXDataSeries);
xs->addWidget(removeXDataSeries);
mainLayout->addLayout(xs);
connect(xdataTable, SIGNAL(currentItemChanged(QTableWidgetItem*,QTableWidgetItem*)), this, SLOT(xdataSelected()));
connect(removeXData, SIGNAL(clicked(bool)), this, SLOT(removeXDataClicked()));
connect(addXData, SIGNAL(clicked(bool)), this, SLOT(addXDataClicked()));
connect(removeXDataSeries, SIGNAL(clicked(bool)), this, SLOT(removeXDataSeriesClicked()));
connect(addXDataSeries, SIGNAL(clicked(bool)), this, SLOT(addXDataSeriesClicked()));
}
void XDataDialog::close()
{
}
void XDataDialog::setRideItem(RideItem *item)
{
this->item = item;
xdataTable->clear();
xdataSeriesTable->clear();
// add a row for each xdata
if (item && item->ride() && item->ride()->xdata().count()) {
QMapIterator<QString,XDataSeries *> it(item->ride()->xdata());
it.toFront();
int n=0;
xdataTable->setRowCount(item->ride()->xdata().count());
while(it.hasNext()) {
it.next();
QString name = it.key();
QTableWidgetItem *add = new QTableWidgetItem();
add->setFlags(add->flags() & (~Qt::ItemIsEditable));
add->setText(name);
xdataTable->setItem(n++, 0, add);
}
if (xdataTable->currentRow()==0) {
xdataSelected();
} else {
xdataTable->selectRow(0);
}
}
}
void XDataDialog::xdataSelected()
{
// update xdata series table to reflect the selection
xdataSeriesTable->clear();
// lets find the one we have selected...
int n=0, index=xdataTable->currentIndex().row();
const XDataSeries *series = NULL;
QMapIterator<QString,XDataSeries *> it(item->ride()->xdata());
it.toFront();
xdataTable->setRowCount(item->ride()->xdata().count());
while(it.hasNext()) {
it.next();
series= it.value();
if (n++==index) break;
}
// lets populate
if (series) {
n=0;
xdataSeriesTable->setRowCount(series->valuename.count());
foreach(QString name, series->valuename) {
// add a row for each name
QTableWidgetItem *add = new QTableWidgetItem();
add->setFlags(add->flags() & (~Qt::ItemIsEditable));
add->setText(name);
xdataSeriesTable->setItem(n++, 0, add);
}
if (n) xdataSeriesTable->selectRow(0);
}
}
void
XDataDialog::removeXDataClicked()
{
// pressed minus on an xdata so do via ridefilecommand
if (item && item->ride() && xdataTable->currentIndex().row() >=0 && xdataTable->currentIndex().row() < xdataTable->rowCount()) {
// lets zap it via the ride file command
item->ride()->command->removeXData(xdataTable->item(xdataTable->currentIndex().row(),0)->text());
}
}
void
XDataDialog::removeXDataSeriesClicked()
{
QString xdata;
if (item && item->ride() && xdataTable->currentIndex().row() >=0 && xdataTable->currentIndex().row() < xdataTable->rowCount()) {
// lets zap it via the ride file command
xdata = xdataTable->item(xdataTable->currentIndex().row(),0)->text();
}
// pressed minus on an xdata so do via ridefilecommand
if (item && item->ride() && xdataSeriesTable->currentIndex().row() >=0 && xdataSeriesTable->currentIndex().row() < xdataSeriesTable->rowCount()) {
// lets zap it via the ride file command
item->ride()->command->removeXDataSeries(xdata, xdataSeriesTable->item(xdataSeriesTable->currentIndex().row(),0)->text());
}
}
void
XDataDialog::addXDataClicked()
{
XDataSeries add;
XDataSettingsDialog *dialog = new XDataSettingsDialog(this, add);
int ret = dialog->exec();
if (ret==QDialog::Accepted) {
item->ride()->command->addXData(new XDataSeries(add));
}
}
void
XDataDialog::addXDataSeriesClicked()
{
// lets find the one we have selected...
int index=xdataTable->currentIndex().row();
if (index <0) return;
QString xdata = xdataTable->item(index,0)->text();
const XDataSeries *series = item->ride()->xdata(xdata);
if (series == NULL) return;
QString name;
XDataSeriesSettingsDialog *dialog = new XDataSeriesSettingsDialog(this, name);
int ret = dialog->exec();
if (ret == QDialog::Accepted) {
item->ride()->command->addXDataSeries(xdata, name);
}
}
///
/// XDataSettingsDialog
///
XDataSettingsDialog::XDataSettingsDialog(QWidget *parent, XDataSeries &series) : QDialog(parent), series(series)
{
setWindowTitle("XData Settings");
setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::Tool);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
QFormLayout *form = new QFormLayout();
mainLayout->addLayout(form);
QLabel *xdataLabel = new QLabel(tr("xData"), this);
xdataName = new QLineEdit(this);
form->addRow(xdataLabel, xdataName);
form->addRow(new QLabel("",this), new QLabel("", this));
form->addRow(new QLabel(tr("Data Series"),this));
for (int i=0; i<8; i++) {
xdataSeriesName[i] = new QLineEdit(this);
form->addRow(new QLabel(QString(tr("Series %1")).arg(i+1)), xdataSeriesName[i]);
}
form->addRow(new QLabel("",this), new QLabel("", this));
mainLayout->addStretch();
cancelButton = new QPushButton(tr("Cancel"), this);
okButton = new QPushButton(tr("OK"), this);
QHBoxLayout *buttons = new QHBoxLayout();
buttons->addStretch();
buttons->addWidget(cancelButton);
buttons->addWidget(okButton);
mainLayout->addLayout(buttons);
connect(okButton, SIGNAL(clicked(bool)), this, SLOT(okClicked()));
connect(cancelButton, SIGNAL(clicked(bool)), this, SLOT(reject()));
}
void XDataSettingsDialog::okClicked()
{
// lets just check we have something etc
if (xdataName->text() == "") {
QMessageBox::warning(0, tr("Error"), tr("XData name is blank"));
return;
} else {
series.name = xdataName->text();
}
series.valuename.clear();
for(int i=0; i<8; i++) {
if (xdataSeriesName[i]->text() != "")
series.valuename << xdataSeriesName[i]->text();
}
if (series.valuename.count() >0) accept();
else {
QMessageBox::warning(0, tr("Error"), tr("Must have at least one data series."));
return;
}
}
///
/// XDataSeriesSettingsDialog
///
XDataSeriesSettingsDialog::XDataSeriesSettingsDialog(QWidget *parent, QString &name) : QDialog(parent), name(name)
{
setWindowTitle("XData Series Name");
setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::Tool);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
QFormLayout *form = new QFormLayout();
mainLayout->addLayout(form);
QLabel *nameLabel = new QLabel(tr("Name"), this);
nameEdit = new QLineEdit(this);
nameEdit->setText(name);
form->addRow(nameLabel, nameEdit);
form->addRow(new QLabel("",this), new QLabel("", this));
mainLayout->addStretch();
cancelButton = new QPushButton(tr("Cancel"), this);
okButton = new QPushButton(tr("OK"), this);
QHBoxLayout *buttons = new QHBoxLayout();
buttons->addStretch();
buttons->addWidget(cancelButton);
buttons->addWidget(okButton);
mainLayout->addLayout(buttons);
connect(okButton, SIGNAL(clicked(bool)), this, SLOT(okClicked()));
connect(cancelButton, SIGNAL(clicked(bool)), this, SLOT(reject()));
}
void XDataSeriesSettingsDialog::okClicked()
{
// lets just check we have something etc
if (nameEdit->text() == "") {
QMessageBox::warning(0, tr("Error"), tr("Name is blank"));
return;
} else {
name = nameEdit->text();
}
accept();
}

104
src/FileIO/XDataDialog.h Normal file
View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2016 Mark Liversedge <liversedge@gmail.com>
*
* This program 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 2 of the License, or (at your option)
* any later version.
*
* This program 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, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _GC_XDataDialog_h
#define _GC_XDataDialog_h 1
#include "GoldenCheetah.h"
#include "RideFile.h"
#include <QtGui>
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QTableWidget>
#include <QHeaderView>
class Context;
class RideFile;
class XDataDialog : public QDialog
{
Q_OBJECT
G_OBJECT
public:
XDataDialog(QWidget *parent);
void setRideItem(RideItem *item);
private slots:
void xdataSelected();
void close();
void removeXDataClicked();
void addXDataClicked();
void removeXDataSeriesClicked();
void addXDataSeriesClicked();
private:
RideItem *item;
QTableWidget *xdataTable;
QTableWidget *xdataSeriesTable;
QPushButton *addXData, *removeXData;
QPushButton *addXDataSeries, *removeXDataSeries;
QPushButton *closeButton;
};
class XDataSettingsDialog : public QDialog
{
Q_OBJECT
public:
XDataSettingsDialog(QWidget *parent, XDataSeries &series);
private slots:
void okClicked();
private:
XDataSeries &series;
QLineEdit *xdataName;
QLineEdit *xdataSeriesName[8];
QPushButton *cancelButton, *okButton;
};
class XDataSeriesSettingsDialog : public QDialog
{
Q_OBJECT
public:
XDataSeriesSettingsDialog(QWidget *parent, QString &name);
private slots:
void okClicked();
private:
QString &name;
QLineEdit *nameEdit;
QPushButton *cancelButton, *okButton;
};
#endif // _GC_XDataDialog_h

View File

@@ -652,7 +652,7 @@ HEADERS += FileIO/AthleteBackup.h FileIO/Bin2RideFile.h FileIO/BinRideFile.h Fi
FileIO/RideFileCommand.h FileIO/RideFile.h FileIO/RideFileTableModel.h FileIO/Serial.h \
FileIO/SlfParser.h FileIO/SlfRideFile.h FileIO/SmfParser.h FileIO/SmfRideFile.h FileIO/SmlParser.h FileIO/SmlRideFile.h \
FileIO/SrdRideFile.h FileIO/SrmRideFile.h FileIO/SyncRideFile.h FileIO/TcxParser.h \
FileIO/TcxRideFile.h FileIO/TxtRideFile.h FileIO/WkoRideFile.h
FileIO/TcxRideFile.h FileIO/TxtRideFile.h FileIO/WkoRideFile.h FileIO/XDataDialog.h
# GUI components
HEADERS += Gui/AboutDialog.h Gui/AddIntervalDialog.h Gui/AnalysisSidebar.h Gui/ChooseCyclistDialog.h Gui/ColorButton.h \
@@ -733,7 +733,8 @@ SOURCES += FileIO/AthleteBackup.cpp FileIO/Bin2RideFile.cpp FileIO/BinRideFile.c
FileIO/RideFileCache.cpp FileIO/RideFileCommand.cpp FileIO/RideFile.cpp FileIO/RideFileTableModel.cpp \
FileIO/Serial.cpp FileIO/SlfParser.cpp FileIO/SlfRideFile.cpp FileIO/SmfParser.cpp FileIO/SmfRideFile.cpp FileIO/SmlParser.cpp \
FileIO/SmlRideFile.cpp FileIO/SrdRideFile.cpp FileIO/SrmRideFile.cpp FileIO/SyncRideFile.cpp \
FileIO/TacxCafRideFile.cpp FileIO/TcxParser.cpp FileIO/TcxRideFile.cpp FileIO/TxtRideFile.cpp FileIO/WkoRideFile.cpp
FileIO/TacxCafRideFile.cpp FileIO/TcxParser.cpp FileIO/TcxRideFile.cpp FileIO/TxtRideFile.cpp FileIO/WkoRideFile.cpp \
FileIO/XDataDialog.cpp
## GUI Elements and Dialogs
SOURCES += Gui/AboutDialog.cpp Gui/AddIntervalDialog.cpp Gui/AnalysisSidebar.cpp Gui/ChooseCyclistDialog.cpp Gui/ColorButton.cpp \