mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}";
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
354
src/FileIO/XDataDialog.cpp
Normal 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
104
src/FileIO/XDataDialog.h
Normal 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
|
||||
@@ -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 \
|
||||
|
||||
Reference in New Issue
Block a user