Introduce Toolbox to GUI

The left side of MainWindow is now a toolbox which contains
Ride Analysis and Racing and Training options. The Right side
tabs have been reorganised and associated with the toolbox.

To support the population of the Racing and Training left tool
the config dialog has been updated to enable the user to configure
the location of their workouts.

In addition, the config dialog now calls upon MainWindow to issue
a configUpdate() signal to notify widgets when config has been
updated. This is a refactoring of the existing mechanism that
only called realtimeWindow->updateConfig, now any widget can
connect to the MainWindow signal and re-read its config appropriately.
Currently, the TrainTool and RealtimeWindow widgets have been coded to
use this.
This commit is contained in:
Mark Liversedge
2009-12-20 22:56:22 +00:00
committed by Sean Rhea
parent e5affbbc64
commit e93970ed4d
13 changed files with 439 additions and 92 deletions

View File

@@ -153,6 +153,7 @@ void ConfigDialog::save_Clicked()
settings->setValue(GC_CRANKLENGTH, configPage->crankLengthCombo->currentText());
settings->setValue(GC_BIKESCOREDAYS, configPage->BSdaysEdit->text());
settings->setValue(GC_BIKESCOREMODE, configPage->bsModeCombo->currentText());
settings->setValue(GC_WORKOUTDIR, configPage->workoutDirectory->text());
settings->setValue(GC_INITIAL_STS, cyclistPage->perfManStart->text());
settings->setValue(GC_INITIAL_LTS, cyclistPage->perfManStart->text());
settings->setValue(GC_STS_DAYS, cyclistPage->perfManSTSavg->text());
@@ -196,9 +197,9 @@ void ConfigDialog::save_Clicked()
DeviceConfigurations all;
all.writeConfig(devicePage->deviceListModel->Configuration);
// update widgets to let them know config has changed
// only realtime sorted thus far;
mainWindow->realtimeWindow->configUpdate();
// Tell MainWindow we changed config, so it can emit the signal
// configChanged() to all its children
mainWindow->notifyConfigChanged();
}
void ConfigDialog::moveCalendarToCurrentRange() {

View File

@@ -57,6 +57,8 @@
#include "MetricAggregator.h"
#include "SplitRideDialog.h"
#include "PerformanceManagerWindow.h"
#include "TrainTabs.h"
#include "TrainTool.h"
#ifndef GC_VERSION
#define GC_VERSION "(developer build)"
@@ -127,6 +129,7 @@ MainWindow::MainWindow(const QDir &home) :
setCentralWidget(splitter);
splitter->setContentsMargins(10, 20, 10, 10); // attempting to follow some UI guides
// Analysis toolbox contents
calendar = new RideCalendar;
calendar->setFirstDayOfWeek(Qt::Monday);
calendar->setHome(home);
@@ -179,7 +182,16 @@ MainWindow::MainWindow(const QDir &home) :
leftLayout->setCollapsible(0, true);
leftLayout->addWidget(intervalsplitter);
leftLayout->setCollapsible(1, false);
splitter->addWidget(leftLayout);
// Train toolbox contents
TrainTool *trainTool = new TrainTool(this, home);
// Setup Toolbox
leftToolBox = new QToolBox;
leftToolBox->addItem(leftLayout, tr("Ride Analysis"));
leftToolBox->addItem(trainTool, tr("Racing and Training"));
splitter->addWidget(leftToolBox);
splitter->setCollapsible(0, true);
QVariant calendarSizes = settings->value(GC_SETTINGS_CALENDAR_SIZES);
if (calendarSizes != QVariant()) {
@@ -200,8 +212,17 @@ MainWindow::MainWindow(const QDir &home) :
}
tabWidget = new QTabWidget;
trainTabs = new TrainTabs(this, trainTool, home);
tabWidget->setUsesScrollButtons(true);
rightSide = new QStackedWidget;
rightSide->addWidget(tabWidget);
rightSide->addWidget(trainTabs);
// Start with Analysis by default
rightSide->setCurrentIndex(0);
leftToolBox->setCurrentIndex(0);
rideSummaryWindow = new RideSummaryWindow(this);
QLabel *notesLabel = new QLabel(tr("Notes:"));
notesLabel->setMaximumHeight(30);
@@ -232,7 +253,7 @@ MainWindow::MainWindow(const QDir &home) :
/////////////////////////// Ride Plot Tab ///////////////////////////
allPlotWindow = new AllPlotWindow(this);
tabWidget->addTab(allPlotWindow, tr("Ride Plot"));
splitter->addWidget(tabWidget);
splitter->addWidget(rightSide);
splitter->setCollapsible(1, true);
QVariant splitterSizes = settings->value(GC_SETTINGS_SPLITTER_SIZES);
@@ -271,11 +292,6 @@ MainWindow::MainWindow(const QDir &home) :
performanceManagerWindow = new PerformanceManagerWindow(this);
tabWidget->addTab(performanceManagerWindow, tr("Performance Manager"));
//////////////////////// Realtime ////////////////////////
realtimeWindow = new RealtimeWindow(this, home);
tabWidget->addTab(realtimeWindow, tr("Realtime"));
////////////////////////////// Signals //////////////////////////////
connect(calendar, SIGNAL(clicked(const QDate &)),
@@ -296,7 +312,8 @@ MainWindow::MainWindow(const QDir &home) :
this, SLOT(intervalTreeWidgetSelectionChanged()));
connect(intervalWidget,SIGNAL(itemChanged(QTreeWidgetItem *,int)),
this, SLOT(intervalEdited(QTreeWidgetItem*, int)));
connect(leftToolBox, SIGNAL(currentChanged(int)),
this, SLOT(toolboxChanged(int)));
/////////////////////////////// Menus ///////////////////////////////
@@ -364,6 +381,12 @@ MainWindow::MainWindow(const QDir &home) :
setAttribute(Qt::WA_DeleteOnClose);
}
void
MainWindow::toolboxChanged(int index)
{
rightSide->setCurrentIndex(index); // right stack has one page per toolbox
}
void
MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
@@ -1155,3 +1178,9 @@ void MainWindow::dateChanged(const QDate &date)
}
}
// notify children that config has changed
void
MainWindow::notifyConfigChanged()
{
configChanged();
}

View File

@@ -42,6 +42,8 @@ class Zones;
class RideCalendar;
class PerformanceManagerWindow;
class RideSummaryWindow;
class TrainTabs;
class TrainTool;
class MainWindow : public QMainWindow
{
@@ -60,14 +62,16 @@ class MainWindow : public QMainWindow
QDir home;
void setCriticalPower(int cp);
RealtimeWindow *realtimeWindow; // public so config dialog can notify it of changes config
const Zones *zones() const { return zones_; }
void updateRideFileIntervals();
void saveSilent(RideItem *);
bool saveRideSingleDialog(RideItem *);
RideItem *rideItem() const { return ride; }
void notifyConfigChanged(); // used by ConfigDialog to notify MainWindow
// when config has changed - and to get a
// signal emitted to notify its children
protected:
Zones *zones_;
@@ -84,11 +88,13 @@ class MainWindow : public QMainWindow
void intervalSelected();
void intervalsChanged();
void zonesChanged();
void configChanged();
private slots:
void rideTreeWidgetSelectionChanged();
void intervalTreeWidgetSelectionChanged();
void leftLayoutMoved();
void toolboxChanged(int);
void splitterMoved();
void newCyclist();
void openCyclist();
@@ -130,6 +136,10 @@ class MainWindow : public QMainWindow
boost::shared_ptr<QSettings> settings;
IntervalItem *activeInterval; // currently active for context menu popup
QToolBox *leftToolBox;
QStackedWidget *rightSide;
// Analysis
RideCalendar *calendar;
QSplitter *splitter;
QTreeWidget *treeWidget;
@@ -148,6 +158,10 @@ class MainWindow : public QMainWindow
QVBoxLayout *notesLayout;
QSplitter *summarySplitter;
// Train
TrainTool *trainTool;
TrainTabs *trainTabs;
QwtPlotCurve *weeklyBSCurve;
QwtPlotCurve *weeklyRICurve;
PerformanceManagerWindow *performanceManagerWindow;

View File

@@ -136,7 +136,18 @@ ConfigurationPage::ConfigurationPage()
bsModeLayout->addWidget(BSModeLabel);
bsModeLayout->addWidget(bsModeCombo);
// Workout Library
QVariant workoutDir = settings->value(GC_WORKOUTDIR);
workoutLabel = new QLabel(tr("Workout Library"));
workoutDirectory = new QLineEdit;
workoutDirectory->setText(workoutDir.toString());
workoutBrowseButton = new QPushButton(tr("Browse"));
workoutLayout = new QHBoxLayout;
workoutLayout->addWidget(workoutLabel);
workoutLayout->addWidget(workoutBrowseButton);
workoutLayout->addWidget(workoutDirectory);
connect(workoutBrowseButton, SIGNAL(clicked()),
this, SLOT(browseWorkoutDir()));
configLayout = new QVBoxLayout;
@@ -146,6 +157,7 @@ ConfigurationPage::ConfigurationPage()
configLayout->addLayout(crankLengthLayout);
configLayout->addLayout(bsDaysLayout);
configLayout->addLayout(bsModeLayout);
configLayout->addLayout(workoutLayout);
configLayout->addLayout(warningLayout);
configGroup->setLayout(configLayout);
@@ -289,6 +301,14 @@ CyclistPage::CyclistPage(const Zones *_zones):
setLayout(mainLayout);
}
void
ConfigurationPage::browseWorkoutDir()
{
QString dir = QFileDialog::getExistingDirectory(this, tr("Select Workout Library"),
"", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
workoutDirectory->setText(dir);
}
QString CyclistPage::getText()
{
return txtThreshold->text();

View File

@@ -36,16 +36,22 @@ class ConfigurationPage : public QWidget
QCheckBox *allRidesAscending;
QLineEdit *BSdaysEdit;
QComboBox *bsModeCombo;
QLineEdit *workoutDirectory;
QPushButton *workoutBrowseButton;
public slots:
void browseWorkoutDir();
private:
QGroupBox *configGroup;
QLabel *langLabel;
QLabel *unitLabel;
QLabel *warningLabel;
QLabel *workoutLabel;
QHBoxLayout *langLayout;
QHBoxLayout *unitLayout;
QHBoxLayout *warningLayout;
QHBoxLayout *workoutLayout;
QVBoxLayout *configLayout;
QVBoxLayout *mainLayout;
QGridLayout *bsDaysLayout;

View File

@@ -29,6 +29,8 @@
#include "SimpleNetworkController.h"
#include "ErgFile.h"
#include "TrainTool.h"
void
RealtimeWindow::configUpdate()
{
@@ -78,11 +80,13 @@ RealtimeWindow::configUpdate()
}
}
RealtimeWindow::RealtimeWindow(MainWindow *parent, const QDir &home) : QWidget(parent)
RealtimeWindow::RealtimeWindow(MainWindow *parent, TrainTool *trainTool, const QDir &home) : QWidget(parent)
{
// set home
this->home = home;
this->trainTool = trainTool;
main = parent;
deviceController = NULL;
streamController = NULL;
ergFile = NULL;
@@ -103,11 +107,6 @@ RealtimeWindow::RealtimeWindow(MainWindow *parent, const QDir &home) : QWidget(
deviceSelector = new QComboBox(this);
streamSelector = new QComboBox(this);
workoutSelector = new QComboBox(this);
workoutSelector->addItem(tr("Manual Mode"), 0);
workoutSelector->addItem(tr("Workout Mode"), 1);
workoutSelector->addItem(tr("Slope Mode"), 2);
// get configured devices
DeviceConfigurations all;
@@ -152,15 +151,16 @@ RealtimeWindow::RealtimeWindow(MainWindow *parent, const QDir &home) : QWidget(
streamSelector->hide();
option_layout->addSpacing(10);
option_layout->addWidget(workoutSelector);
controls_layout->addItem(option_layout);
controls_layout->addItem(button_layout);
// handle config changes
connect(main, SIGNAL(configChanged()), this, SLOT(configUpdate()));
connect(deviceSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectDevice(int)));
connect(recordSelector, SIGNAL(clicked()), this, SLOT(SelectRecord()));
connect(streamSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectStream(int)));
connect(workoutSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(SelectWorkout(int)));
connect(trainTool, SIGNAL(workoutSelected()), this, SLOT(SelectWorkout()));
if (Devices.count() > 0) {
connect(startButton, SIGNAL(clicked()), this, SLOT(Start()));
@@ -299,7 +299,6 @@ RealtimeWindow::RealtimeWindow(MainWindow *parent, const QDir &home) : QWidget(
displayWorkoutDistance = displayDistance = displayPower = displayHeartRate =
displaySpeed = displayCadence = displayGradient = displayLoad = 0;
avgPower= avgHeartRate= avgSpeed= avgCadence= avgLoad= 0;
main = parent;
connect(gui_timer, SIGNAL(timeout()), this, SLOT(guiUpdate()));
connect(disk_timer, SIGNAL(timeout()), this, SLOT(diskUpdate()));
@@ -372,7 +371,6 @@ void RealtimeWindow::Start() // when start button is pressed
recordSelector->setEnabled(false);
streamSelector->setEnabled(false);
deviceSelector->setEnabled(false);
workoutSelector->setEnabled(false);
if (status & RT_WORKOUT) {
load_timer->start(LOADRATE); // start recording
@@ -479,7 +477,6 @@ void RealtimeWindow::Stop() // when stop button is pressed
recordSelector->setEnabled(true);
streamSelector->setEnabled(true);
deviceSelector->setEnabled(true);
workoutSelector->setEnabled(true);
// reset counters etc
pwrcount = 0;
@@ -715,83 +712,72 @@ void RealtimeWindow::diskUpdate()
//----------------------------------------------------------------------
void
RealtimeWindow::SelectWorkout(int index)
RealtimeWindow::SelectWorkout()
{
int mode;
// wip away the current selected workout
if (ergFile) {
delete ergFile;
ergFile = NULL;
}
if (index == 1) {
status |= RT_WORKOUT;
// which one is selected?
if (trainTool->currentWorkout() == NULL || trainTool->currentWorkout()->type() != WORKOUT_TYPE) return;
// choose a file and then parse it!
QString filename = QFileDialog::getOpenFileName(this,
tr("Open Workout File"), home.dirName(), tr("Workout Files (*.erg *.mrc *.crs)"));
if (!filename.isEmpty()) {
// Get users CP for relative watts calculations
QDate today = QDate::currentDate();
double Cp=285; // default to 285 if zones are not set
int range = main->zones()->whichRange(today);
if (range != -1) Cp = main->zones()->getCP(range);
ergFile = new ErgFile(filename, mode, Cp);
if (ergFile->isValid()) {
// success! we have a load file
// setup the course profile in the
// display!
ergPlot->setData(ergFile);
ergPlot->setVisible(true);
ergPlot->replot();
// set the device to the right mode
if (mode == ERG) {
status |= RT_MODE_ERGO;
status &= ~RT_MODE_SPIN;
if (deviceController != NULL) deviceController->setMode(RT_MODE_ERGO);
// set the labels on the gui
loadLabel->setText("Load WATTS");
avgloadLabel->setText("Avg Load WATTS");
} else { // SLOPE MODE
status |= RT_MODE_SPIN;
status &= ~RT_MODE_ERGO;
if (deviceController != NULL) deviceController->setMode(RT_MODE_SPIN);
// set the labels on the gui
loadLabel->setText("Gradient PERCENT");
avgloadLabel->setText("Avg Gradient PERCENT");
}
return;
}
}
// oops didn't parse or no file selected
workoutSelector->setCurrentIndex(0); // will drop back here and delet/unset!
} else if (index == 2) {
// spinscan mode
// is it the auto mode?
int index = trainTool->workoutItems()->indexOfChild((QTreeWidgetItem *)trainTool->currentWorkout());
if (index == 0) {
// ergo mode
mode = ERG;
status &= ~RT_WORKOUT;
ergPlot->setVisible(false);
} else if (index == 1) {
// slope mode
mode = CRS;
status &= ~RT_WORKOUT;
ergPlot->setVisible(false);
status |= RT_MODE_SPIN;
status &= ~RT_MODE_ERGO;
status &= ~RT_WORKOUT; // temp
if (deviceController != NULL) deviceController->setMode(RT_MODE_SPIN);
loadLabel->setText("Gradient PERCENT");
avgloadLabel->setText("Avg Gradient PERCENT");
} else {
// workout mode
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
QVariant workoutDir = settings->value(GC_WORKOUTDIR);
QString fileName = workoutDir.toString() + "/" + trainTool->currentWorkout()->text(0); // filename
// Get users CP for relative watts calculations
QDate today = QDate::currentDate();
double Cp=285; // default to 285 if zones are not set
int range = main->zones()->whichRange(today);
if (range != -1) Cp = main->zones()->getCP(range);
ergFile = new ErgFile(fileName, mode, Cp);
if (ergFile->isValid()) {
status |= RT_WORKOUT;
// success! we have a load file
// setup the course profile in the
// display!
ergPlot->setData(ergFile);
ergPlot->setVisible(true);
ergPlot->replot();
}
}
// set the device to the right mode
if (mode == ERG) {
status |= RT_MODE_ERGO;
status &= ~RT_MODE_SPIN;
if (deviceController != NULL) deviceController->setMode(RT_MODE_ERGO);
// set the labels on the gui
loadLabel->setText("Load WATTS");
avgloadLabel->setText("Avg Load WATTS");
if (deviceController != NULL) deviceController->setMode(RT_MODE_ERGO);
ergPlot->setVisible(false);
status &= ~RT_WORKOUT;
} else { // SLOPE MODE
status |= RT_MODE_SPIN;
status &= ~RT_MODE_ERGO;
if (deviceController != NULL) deviceController->setMode(RT_MODE_SPIN);
// set the labels on the gui
loadLabel->setText("Gradient PERCENT");
avgloadLabel->setText("Avg Gradient PERCENT");
}
}

View File

@@ -55,14 +55,13 @@ class RealtimeWindow : public QWidget
RealtimeController *deviceController; // read from
RealtimeController *streamController; // send out to
RealtimeWindow(MainWindow *, const QDir &);
RealtimeWindow(MainWindow *, TrainTool *, const QDir &);
void updateData(RealtimeData &); // to update telemetry by push devices
void newLap(); // start new Lap!
void nextDisplayMode(); // show next display mode
void setDeviceController(); // based upon selected device
void setStreamController(); // based upon selected device
void configUpdate(); // called when config changes
public slots:
@@ -79,7 +78,7 @@ class RealtimeWindow : public QWidget
void SelectDevice(int); // when combobox chooses device
void SelectRecord(); // when checkbox chooses record mode
void SelectStream(int); // when remote server to stream to is selected
void SelectWorkout(int); // to select a Workout to use
void SelectWorkout(); // to select a Workout to use
// Timed actions
void guiUpdate(); // refreshes the telemetry
@@ -87,6 +86,9 @@ class RealtimeWindow : public QWidget
void streamUpdate(); // writes to remote Peer
void loadUpdate(); // sets Load on CT like devices
// Handle config updates
void configUpdate(); // called when config changes
// When no config has been setup
void warnnoConfig();
@@ -96,6 +98,7 @@ class RealtimeWindow : public QWidget
// passed from MainWindow
QDir home;
MainWindow *main;
TrainTool *trainTool;
QList<DeviceConfiguration> Devices;
bool useMetricUnits;
@@ -152,8 +155,7 @@ class RealtimeWindow : public QWidget
QVBoxLayout *controls_layout;
QCheckBox *recordSelector;
QComboBox *deviceSelector,
*streamSelector,
*workoutSelector;
*streamSelector;
QPushButton *startButton,
*pauseButton,
*stopButton;

View File

@@ -49,6 +49,7 @@
#define GC_SB_ACRONYM "SB"
#define GC_WARNCONVERT "warnconvert"
#define GC_WARNEXIT "warnexit"
#define GC_WORKOUTDIR "workoutDir"
// device Configurations NAME/SPEC/TYPE/DEFI/DEFR all get a number appended
// to them to specify which configured device i.e. devices1 ... devicesn where

27
src/TrainTabs.cpp Normal file
View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2009 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 "TrainTabs.h"
#include "RealtimeWindow.h"
TrainTabs::TrainTabs(MainWindow *parent, TrainTool *trainTool, const QDir &home) :
trainTool(trainTool), home(home), main(parent)
{
realtimeWindow = new RealtimeWindow(parent, trainTool, home); // public so config dialog can notify it of changes config
addTab(realtimeWindow, tr("Turbo Training"));
};

43
src/TrainTabs.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2000 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_TrainTabs_h
#define _GC_TrainTabs_h 1
#include <QDir>
#include <QtGui>
#include "MainWindow.h"
#include "TrainTool.h"
#include "RealtimeWindow.h"
class TrainTabs : public QTabWidget
{
Q_OBJECT
public:
TrainTabs(MainWindow *parent, TrainTool *trainTool, const QDir &home);
private:
RealtimeWindow *realtimeWindow; // public so config dialog can notify it of changes config
TrainTool *trainTool;
const QDir home;
const MainWindow *main;
};
#endif // _GC_TrainTabs_h

145
src/TrainTool.cpp Normal file
View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2009 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 "TrainTool.h"
#include "MainWindow.h"
#include "Settings.h"
#include "Units.h"
#include "DeviceTypes.h"
#include "DeviceConfiguration.h"
#include <assert.h>
#include <QApplication>
#include <QtGui>
#include <QRegExp>
TrainTool::TrainTool(MainWindow *parent, const QDir &home) : QWidget(parent), home(home), main(parent)
{
QVBoxLayout *mainLayout = new QVBoxLayout(this);
//XXX Commented out for this release
//serverTree = new QTreeWidget;
//serverTree->setColumnCount(1);
//serverTree->setSelectionMode(QAbstractItemView::SingleSelection);
//serverTree->header()->hide();
//serverTree->setAlternatingRowColors (true);
//serverTree->setIndentation(5);
//allServers = new QTreeWidgetItem(serverTree, ROOT_TYPE);
//allServers->setText(0, tr("Race Servers"));
//serverTree->expandItem(allServers);
//DeviceConfigurations all;
//QList<DeviceConfiguration> Devices;
//Devices = all.getList();
//for (int i=0; i<Devices.count(); i++) {
// if (Devices.at(i).type == DEV_GSERVER) {
// QTreeWidgetItem *server = new QTreeWidgetItem(allServers, SERVER_TYPE);
// server->setText(0, Devices.at(i).name);
// }
//}
//connect(serverTree,SIGNAL(itemSelectionChanged()),
// this, SLOT(serverTreeWidgetSelectionChanged()));
workoutTree = new QTreeWidget;
workoutTree->setColumnCount(1);
workoutTree->setSelectionMode(QAbstractItemView::SingleSelection);
workoutTree->header()->hide();
workoutTree->setAlternatingRowColors (true);
workoutTree->setIndentation(5);
allWorkouts = new QTreeWidgetItem(workoutTree, ROOT_TYPE);
allWorkouts->setText(0, tr("Workout Library"));
workoutTree->expandItem(allWorkouts);
configChanged(); // will reset the workout tree
//trainSplitter = new QSplitter;
//trainSplitter->setOrientation(Qt::Vertical);
//trainSplitter->addWidget(serverTree);
//trainSplitter->setCollapsible(0, true);
//trainSplitter->addWidget(workoutTree);
//trainSplitter->setCollapsible(0, true);
//mainLayout->addWidget(trainSplitter);
mainLayout->addWidget(workoutTree); // XXX replace above line for this release
connect(workoutTree,SIGNAL(itemSelectionChanged()),
this, SLOT(workoutTreeWidgetSelectionChanged()));
connect(main, SIGNAL(configChanged()),
this, SLOT(configChanged()));
}
void
TrainTool::configChanged()
{
// zap whats there
QList<QTreeWidgetItem *> workouts = allWorkouts->takeChildren();
for (int i=0; i<workouts.count(); i++) delete workouts.at(i);
// standard workouts - ergo and slope
QTreeWidgetItem *ergomode = new QTreeWidgetItem(allWorkouts, WORKOUT_TYPE);
ergomode->setText(0, tr("Manual Ergo Mode"));
QTreeWidgetItem *slopemode = new QTreeWidgetItem(allWorkouts, WORKOUT_TYPE);
slopemode->setText(0, tr("Manual Slope Mode"));
// add all the workouts in the library
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
QVariant workoutDir = settings->value(GC_WORKOUTDIR);
QStringListIterator w(listWorkoutFiles(workoutDir.toString()));
while (w.hasNext()) {
QString name = w.next();
QTreeWidgetItem *work = new QTreeWidgetItem(allWorkouts, WORKOUT_TYPE);
work->setText(0, name);
}
}
/*----------------------------------------------------------------------
* Race Server or Workout Selected
*----------------------------------------------------------------------*/
//void
//TrainTool::serverTreeWidgetSelectionChanged()
//{
// serverSelected();
//}
void
TrainTool::workoutTreeWidgetSelectionChanged()
{
assert(workoutTree->selectedItems().size() <= 1);
if (workoutTree->selectedItems().isEmpty())
workout = NULL;
else {
QTreeWidgetItem *which = workoutTree->selectedItems().first();
if (which->type() != WORKOUT_TYPE)
workout = NULL;
else
workout = which;
}
workoutSelected();
}
QStringList
TrainTool::listWorkoutFiles(const QDir &dir) const
{
QStringList filters;
filters << "*.erg";
filters << "*.mrc";
filters << "*.crs";
return dir.entryList(filters, QDir::Files, QDir::Name);
}

69
src/TrainTool.h Normal file
View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2009 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_TrainTool_h
#define _GC_TrainTool_h 1
#include "MainWindow.h"
#include <QDir>
#include <QtGui>
#define ROOT_TYPE 1
#define SERVER_TYPE 2
#define WORKOUT_TYPE 3
class TrainTool : public QWidget
{
Q_OBJECT
public:
TrainTool(MainWindow *parent, const QDir &home);
QStringList listWorkoutFiles(const QDir &) const;
const QTreeWidgetItem *currentWorkout() { return workout; }
const QTreeWidgetItem *workoutItems() { return allWorkouts; }
//const QTreeWidgetItem *currentServer() { return server; }
//const QTreeWidgetItem *serverItems() { return allServers; }
signals:
//void serverSelected();
void workoutSelected();
private slots:
//void serverTreeWidgetSelectionChanged();
void workoutTreeWidgetSelectionChanged();
void configChanged();
private:
const QDir home;
MainWindow *main;
QTreeWidget *workoutTree;
QTabWidget *trainTabs;
QTreeWidgetItem *allWorkouts;
QTreeWidgetItem *workout;
//QSplitter *trainSplitter; // XXX commented out for this release
//QTreeWidget *serverTree; // XXX commented out for this release
//QTreeWidgetItem *allServers; // XXX commented out for this release
//QTreeWidgetItem *server; // XXX commented out for this release
};
#endif // _GC_TrainTool_h

View File

@@ -111,6 +111,8 @@ HEADERS += \
TcxRideFile.h \
TimeUtils.h \
ToolsDialog.h \
TrainTabs.h \
TrainTool.h \
Units.h \
WeeklySummaryWindow.h \
WkoRideFile.h \
@@ -187,6 +189,8 @@ SOURCES += \
TcxRideFile.cpp \
TimeUtils.cpp \
ToolsDialog.cpp \
TrainTabs.cpp \
TrainTool.cpp \
WeeklySummaryWindow.cpp \
WkoRideFile.cpp \
Zones.cpp \