mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 00:28:42 +00:00
Make Analysis view configurable
You can now configure the Analysis view to drag and drop charts on the page and lay them out etc. A default setup displays basic data such as ride summary, histograms and ride plot. MainWindow still needs a bit of a tidy-up as the basic code has been edited and re-edited by a cast of thousands and its a bit of a mess as a result.
This commit is contained in:
@@ -357,7 +357,8 @@ AllPlotWindow::AllPlotWindow(MainWindow *mainWindow) :
|
||||
void
|
||||
AllPlotWindow::configChanged()
|
||||
{
|
||||
fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL));
|
||||
//We now use the window background color
|
||||
//fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL));
|
||||
|
||||
// we're going to replot, but only if we're active
|
||||
// and all the other guff
|
||||
@@ -414,7 +415,8 @@ AllPlotWindow::redrawFullPlot()
|
||||
|
||||
// hide the usual plot decorations etc
|
||||
fullPlot->showPower(1);
|
||||
fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL));
|
||||
//We now use the window background color
|
||||
//fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL));
|
||||
fullPlot->setCanvasLineWidth(0);
|
||||
fullPlot->grid->enableY(false);
|
||||
fullPlot->enableAxis(QwtPlot::yLeft, false);
|
||||
|
||||
@@ -462,6 +462,12 @@ HomeWindow::removeChart(int num)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::showEvent(QShowEvent *)
|
||||
{
|
||||
resizeEvent(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
HomeWindow::resizeEvent(QResizeEvent * /* e */)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ class HomeWindow : public GcWindow
|
||||
virtual void dragEnterEvent(QDragEnterEvent *);
|
||||
virtual void dropEvent(QDropEvent *);
|
||||
void resizeEvent(QResizeEvent *);
|
||||
void showEvent(QShowEvent *);
|
||||
bool eventFilter(QObject *object, QEvent *e);
|
||||
|
||||
// My widget signals and events
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
class QwtPlotPanner;
|
||||
class QwtPlotPicker;
|
||||
class QwtPlotZoomer;
|
||||
|
||||
#include <qwt_plot_picker.h>
|
||||
#include <qwt_text_engine.h>
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ MainWindow::parseRideFileName(const QString &name, QString *notesFileName, QDate
|
||||
|
||||
MainWindow::MainWindow(const QDir &home) :
|
||||
home(home), session(0), isclean(false),
|
||||
zones_(new Zones), hrzones_(new HrZones), calendar(NULL),
|
||||
zones_(new Zones), hrzones_(new HrZones),
|
||||
ride(NULL)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
@@ -273,12 +273,6 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
calendarDownload = new CalendarDownload(this);
|
||||
|
||||
|
||||
// Analysis toolbox contents
|
||||
calendar = new RideCalendar(this);
|
||||
calendar->setHome(home);
|
||||
calendar->setFixedHeight(250);
|
||||
calendar->hide();
|
||||
|
||||
chartTool = new GcWindowTool(this);
|
||||
|
||||
treeWidget = new QTreeWidget;
|
||||
@@ -334,18 +328,12 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
last = new RideItem(RIDE_TYPE, home.path(),
|
||||
name, dt, zones(), hrZones(), notesFileName, this);
|
||||
allRides->addChild(last);
|
||||
calendar->update();
|
||||
}
|
||||
}
|
||||
|
||||
splitter = new QSplitter;
|
||||
splitter->setContentsMargins(0, 0, 0, 0); // attempting to follow some UI guides
|
||||
|
||||
tabWidget = new QTabWidget;
|
||||
tabWidget->setUsesScrollButtons(true);
|
||||
tabWidget->setTabPosition(QTabWidget::North);
|
||||
tabWidget->setContentsMargins(0,0,0,0);
|
||||
|
||||
// setup the stacks for all the view controls
|
||||
// a stacked widget for each toolbar option
|
||||
masterControls = new QStackedWidget(this);
|
||||
@@ -388,9 +376,14 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
trainWindow = new HomeWindow(this, "train", "Training");
|
||||
trainControls->addWidget(new TrainTool(this, this->home));
|
||||
|
||||
// analysis
|
||||
analWindow = new HomeWindow(this, "analysis", "Analysis");
|
||||
analysisControls->addWidget(analWindow->controls());
|
||||
|
||||
// ToolBox has one thing at the mo... will change soon
|
||||
toolBox = new QToolBox(this);
|
||||
toolBox->setStyleSheet(" QToolBox::tab:selected { font: bold; }");
|
||||
toolBox->setFixedWidth(300);
|
||||
|
||||
//toolBox->addItem(calendar, "Calendar"); //XXX some folks will complain, I HATE IT with a PASSION!
|
||||
#ifdef Q_OS_MAC // on a mac the controls go into a dock drawer widget
|
||||
@@ -417,11 +410,6 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
splitter->setSizes(sizes);
|
||||
}
|
||||
|
||||
/////////////////////////// Summary /////////////////////////
|
||||
|
||||
summaryWindow = new SummaryWindow(this);
|
||||
tabs.append(TabInfo(summaryWindow, tr("Summary")));
|
||||
|
||||
/////////////////////////// Diary ///////////////////////////
|
||||
#ifdef GC_HAVE_ICAL
|
||||
diaryWindow = new DiaryWindow(this);
|
||||
@@ -429,89 +417,12 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
diaryControls->addWidget(diaryWindow->controls());
|
||||
#endif
|
||||
|
||||
/////////////////////////// Ride Plot Tab ///////////////////////////
|
||||
allPlotWindow = new AllPlotWindow(this);
|
||||
tabs.append(TabInfo(allPlotWindow, tr("Ride Plot")));
|
||||
|
||||
////////////////////// Critical Power Plot Tab //////////////////////
|
||||
|
||||
criticalPowerWindow = new CriticalPowerWindow(home, this);
|
||||
tabs.append(TabInfo(criticalPowerWindow, tr("Critical Durations")));
|
||||
|
||||
//////////////////////// Power Histogram Tab ////////////////////////
|
||||
|
||||
histogramWindow = new HistogramWindow(this);
|
||||
tabs.append(TabInfo(histogramWindow, tr("Histograms")));
|
||||
|
||||
//////////////////////// Pedal Force/zones_Velocity Plot ////////////////////////
|
||||
|
||||
pfPvWindow = new PfPvWindow(this);
|
||||
tabs.append(TabInfo(pfPvWindow, tr("PF/PV")));
|
||||
|
||||
//////////////////////// HrPw Plot ////////////////////////
|
||||
|
||||
hrPwWindow = new HrPwWindow(this);
|
||||
tabs.append(TabInfo(hrPwWindow, tr("HrPw")));
|
||||
|
||||
//////////////////////// Scatter Plot ////////////////////////
|
||||
|
||||
scatterWindow = new ScatterWindow(this, home);
|
||||
tabs.append(TabInfo(scatterWindow, tr("2D")));
|
||||
|
||||
//////////////////////// 3d Model Window ////////////////////////////
|
||||
|
||||
#ifdef GC_HAVE_QWTPLOT3D
|
||||
modelWindow = new ModelWindow(this, home);
|
||||
tabs.append(TabInfo(modelWindow, tr("3D")));
|
||||
#endif
|
||||
|
||||
//////////////////////// Weekly Summary ////////////////////////
|
||||
|
||||
// add daily distance / duration graph:
|
||||
weeklySummaryWindow = new WeeklySummaryWindow(useMetricUnits, this);
|
||||
tabs.append(TabInfo(weeklySummaryWindow, tr("Weekly Summary")));
|
||||
|
||||
//////////////////////// LTM ////////////////////////
|
||||
|
||||
// long term metrics window
|
||||
ltmWindow = new LTMWindow(this, useMetricUnits, home);
|
||||
ltmWindow->setChart(0); // XXX mimic old style, before properties managed by layout manager
|
||||
ltmWindow->setDateRange("All Dates"); // XXX this is going soon anyway
|
||||
tabs.append(TabInfo(ltmWindow, tr("Metrics")));
|
||||
|
||||
//////////////////////// Treemap ////////////////////////
|
||||
|
||||
// treemap window
|
||||
treemapWindow = new TreeMapWindow(this, useMetricUnits, home);
|
||||
tabs.append(TabInfo(treemapWindow, tr("Treemap")));
|
||||
|
||||
//////////////////////// Performance Manager ////////////////////////
|
||||
|
||||
performanceManagerWindow = new PerformanceManagerWindow(this);
|
||||
tabs.append(TabInfo(performanceManagerWindow, tr("PM")));
|
||||
|
||||
|
||||
///////////////////////////// Aerolab //////////////////////////////////
|
||||
|
||||
aerolabWindow = new AerolabWindow(this);
|
||||
tabs.append(TabInfo(aerolabWindow, tr("Aerolab")));
|
||||
|
||||
///////////////////////////// GoogleMaps //////////////////////////////////
|
||||
|
||||
googleMap = new GoogleMapControl(this);
|
||||
tabs.append(TabInfo(googleMap, tr("Map")));
|
||||
|
||||
///////////////////////////// Editor //////////////////////////////////
|
||||
|
||||
rideEdit = new RideEditor(this);
|
||||
tabs.append(TabInfo(rideEdit, tr("Editor")));
|
||||
|
||||
/////////////////////////// Views //////////////////////////////////////
|
||||
|
||||
// Setup the two views
|
||||
views = new QStackedWidget(this);
|
||||
views->setFrameStyle(QFrame::Plain | QFrame::NoFrame);
|
||||
views->addWidget(tabWidget); // Analysis stuff
|
||||
views->addWidget(analWindow); // Analysis stuff
|
||||
views->addWidget(trainWindow); // Train Stuff
|
||||
#ifdef GC_HAVE_ICAL
|
||||
views->addWidget(diaryWindow);
|
||||
@@ -526,10 +437,10 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
// on a mac it has only one widget since the
|
||||
// toolBox is in a drawer, on other platforms
|
||||
// it has the views and the toolBox
|
||||
splitter->addWidget(views);
|
||||
#ifndef Q_OS_MAC
|
||||
splitter->addWidget(toolBox);
|
||||
#endif
|
||||
splitter->addWidget(views);
|
||||
setCentralWidget(splitter);
|
||||
|
||||
/////////////////////////////// Menus ///////////////////////////////
|
||||
@@ -644,6 +555,7 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
@@ -677,6 +589,7 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
viewMenu->addAction(tab.action);
|
||||
}
|
||||
tabViewTriggered(true);
|
||||
#endif
|
||||
|
||||
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
|
||||
helpMenu->addAction(tr("&About GoldenCheetah"), this, SLOT(aboutDialog()));
|
||||
@@ -697,16 +610,10 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
setUnifiedTitleAndToolBarOnMac(true);
|
||||
|
||||
// now we're up and runnning lets connect the signals
|
||||
connect(calendar, SIGNAL(clicked(const QDate &)),
|
||||
this, SLOT(dateChanged(const QDate &)));
|
||||
connect(treeWidget,SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
this, SLOT(showTreeContextMenuPopup(const QPoint &)));
|
||||
connect(treeWidget, SIGNAL(itemSelectionChanged()),
|
||||
this, SLOT(rideTreeWidgetSelectionChanged()));
|
||||
connect(splitter, SIGNAL(splitterMoved(int,int)),
|
||||
this, SLOT(splitterMoved()));
|
||||
connect(tabWidget, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(tabChanged(int)));
|
||||
connect(intervalWidget,SIGNAL(customContextMenuRequested(const QPoint &)),
|
||||
this, SLOT(showContextMenuPopup(const QPoint &)));
|
||||
connect(intervalWidget,SIGNAL(itemSelectionChanged()),
|
||||
@@ -716,6 +623,9 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
|
||||
// Kick off
|
||||
rideTreeWidgetSelectionChanged();
|
||||
|
||||
// default to analysis
|
||||
analWindow->selected();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -724,35 +634,6 @@ MainWindow::showDock()
|
||||
dock->toggleViewAction()->activate(QAction::Trigger);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::tabViewTriggered(bool)
|
||||
{
|
||||
#ifndef Q_OS_MAC
|
||||
// lets show/hide
|
||||
if (sideView->isChecked()) toolBox->show();
|
||||
else toolBox->hide();
|
||||
#endif
|
||||
|
||||
disconnect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
|
||||
QWidget *currentWidget = tabWidget->currentWidget();
|
||||
int currentIndex = tabWidget->currentIndex();
|
||||
tabWidget->clear();
|
||||
QStringList tabsToHide;
|
||||
foreach (const TabInfo &tab, tabs) {
|
||||
if (!tab.action || tab.action->isChecked())
|
||||
tabWidget->addTab(tab.contents, tab.name);
|
||||
else
|
||||
tabsToHide << tab.name;
|
||||
}
|
||||
if (tabWidget->indexOf(currentWidget) >= 0)
|
||||
tabWidget->setCurrentWidget(currentWidget);
|
||||
else if (currentIndex < tabWidget->count())
|
||||
tabWidget->setCurrentIndex(currentIndex);
|
||||
tabChanged(tabWidget->currentIndex());
|
||||
connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
|
||||
appsettings->setValue(GC_TABS_TO_HIDE, tabsToHide.join(","));
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
@@ -780,7 +661,7 @@ MainWindow::dropEvent(QDropEvent *event)
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::addRide(QString name, bool bSelect /*=true*/)
|
||||
MainWindow::addRide(QString name, bool /* bSelect =true*/)
|
||||
{
|
||||
QString notesFileName;
|
||||
QDateTime dt;
|
||||
@@ -814,13 +695,6 @@ MainWindow::addRide(QString name, bool bSelect /*=true*/)
|
||||
}
|
||||
rideAdded(last); // here so emitted BEFORE rideSelected is emitted!
|
||||
allRides->insertChild(index, last);
|
||||
calendar->update();
|
||||
criticalPowerWindow->newRideAdded();
|
||||
if (bSelect)
|
||||
{
|
||||
tabWidget->setCurrentWidget(summaryWindow);
|
||||
treeWidget->setCurrentItem(last);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -886,7 +760,6 @@ MainWindow::removeCurrentRide()
|
||||
|
||||
treeWidget->setCurrentItem(itemToSelect);
|
||||
rideTreeWidgetSelectionChanged();
|
||||
calendar->update();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1190,21 +1063,15 @@ MainWindow::rideTreeWidgetSelectionChanged()
|
||||
// update the ride property on all widgets
|
||||
// to let them know they need to replot new
|
||||
// selected ride
|
||||
foreach (TabInfo tab, tabs) {
|
||||
tab.contents->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
}
|
||||
_rideMetadata->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
|
||||
analWindow->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
homeWindow->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
#ifdef GC_HAVE_ICAL
|
||||
diaryWindow->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
#endif
|
||||
trainWindow->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
|
||||
if (!ride)
|
||||
return;
|
||||
|
||||
calendar->setSelectedDate(ride->dateTime.date());
|
||||
if (!ride) return;
|
||||
|
||||
// refresh interval list for bottom left
|
||||
// first lets wipe away the existing intervals
|
||||
@@ -1230,25 +1097,8 @@ MainWindow::rideTreeWidgetSelectionChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// turn off tabs that don't make sense for manual file entry
|
||||
int histIndex = tabWidget->indexOf(histogramWindow);
|
||||
int pfpvIndex = tabWidget->indexOf(pfPvWindow);
|
||||
int plotIndex = tabWidget->indexOf(allPlotWindow);
|
||||
int modelIndex = tabWidget->indexOf(modelWindow);
|
||||
int mapIndex = tabWidget->indexOf(googleMap);
|
||||
int editorIndex = tabWidget->indexOf(rideEdit);
|
||||
|
||||
bool enabled = (ride->ride() && ride->ride()->deviceType() != QString("Manual CSV") &&
|
||||
!ride->ride()->dataPoints().isEmpty());
|
||||
|
||||
if (histIndex >= 0) tabWidget->setTabEnabled(histIndex, enabled);
|
||||
if (pfpvIndex >= 0) tabWidget->setTabEnabled(pfpvIndex, enabled);
|
||||
if (plotIndex >= 0) tabWidget->setTabEnabled(plotIndex, enabled);
|
||||
if (modelIndex >= 0) tabWidget->setTabEnabled(modelIndex, enabled);
|
||||
if (mapIndex >= 0) tabWidget->setTabEnabled(mapIndex, enabled);
|
||||
if (editorIndex >= 0) tabWidget->setTabEnabled(editorIndex, enabled);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::showTreeContextMenuPopup(const QPoint &pos)
|
||||
{
|
||||
@@ -1315,15 +1165,19 @@ MainWindow::showContextMenuPopup(const QPoint &pos)
|
||||
connect(actFrontInt, SIGNAL(triggered(void)), this, SLOT(frontInterval(void)));
|
||||
connect(actBackInt, SIGNAL(triggered(void)), this, SLOT(backInterval(void)));
|
||||
|
||||
#if 0
|
||||
if (tabWidget->currentWidget() == allPlotWindow)
|
||||
menu.addAction(actZoomInt);
|
||||
#endif
|
||||
menu.addAction(actRenameInt);
|
||||
menu.addAction(actDeleteInt);
|
||||
#if 0
|
||||
if ((tabWidget->currentWidget() == pfPvWindow || tabWidget->currentWidget() == scatterWindow)
|
||||
&& activeInterval->isSelected()) {
|
||||
menu.addAction(actFrontInt);
|
||||
menu.addAction(actBackInt);
|
||||
}
|
||||
#endif
|
||||
menu.exec(intervalWidget->mapToGlobal( pos ));
|
||||
}
|
||||
}
|
||||
@@ -1381,7 +1235,7 @@ MainWindow::intervalEdited(QTreeWidgetItem *, int) {
|
||||
void
|
||||
MainWindow::zoomInterval() {
|
||||
// zoom into this interval on allPlot
|
||||
allPlotWindow->zoomInterval(activeInterval);
|
||||
//allPlotWindow->zoomInterval(activeInterval);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1495,6 +1349,7 @@ MainWindow::closeEvent(QCloseEvent* event)
|
||||
else {
|
||||
|
||||
// save the state of all the pages
|
||||
analWindow->saveState();
|
||||
homeWindow->saveState();
|
||||
trainWindow->saveState();
|
||||
|
||||
@@ -1503,23 +1358,6 @@ MainWindow::closeEvent(QCloseEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::leftLayoutMoved()
|
||||
{
|
||||
appsettings->setValue(GC_SETTINGS_CALENDAR_SIZES, leftLayout->saveState());
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::splitterMoved()
|
||||
{
|
||||
appsettings->setValue(GC_SETTINGS_SPLITTER_SIZES, splitter->saveState());
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::summarySplitterMoved()
|
||||
{
|
||||
appsettings->setValue(GC_SETTINGS_SUMMARYSPLITTER_SIZES, metaSplitter->saveState());
|
||||
}
|
||||
// set the rider value of CP to the value derived from the CP model extraction
|
||||
void
|
||||
MainWindow::setCriticalPower(int cp)
|
||||
@@ -1557,25 +1395,6 @@ MainWindow::setCriticalPower(int cp)
|
||||
zonesChanged();
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::tabChanged(int id)
|
||||
{
|
||||
// id is the tab number and not the offset
|
||||
// into the full list, so lets find the tab
|
||||
// we just changed to and set the controls
|
||||
// to the one selected
|
||||
if (ride == NULL) return;
|
||||
|
||||
GcWindow *selected = static_cast<GcWindow*>(tabWidget->widget(id));
|
||||
for(int i=0; i< tabs.count(); i++) {
|
||||
if (tabs[i].contents == selected) {
|
||||
analysisControls->setCurrentIndex(i);
|
||||
tabs[i].contents->setProperty("ride", QVariant::fromValue<RideItem*>(dynamic_cast<RideItem*>(ride)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::aboutDialog()
|
||||
{
|
||||
@@ -1747,8 +1566,6 @@ MainWindow::notifyConfigChanged()
|
||||
void
|
||||
MainWindow::notifyRideSelected()
|
||||
{
|
||||
//rideSelected();
|
||||
if (calendar) calendar->configUpdate(); //XXX << nasty hack fix to refresh calendar when ride start changes
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1862,6 +1679,7 @@ MainWindow::selectAnalysis()
|
||||
{
|
||||
masterControls->setCurrentIndex(0);
|
||||
views->setCurrentIndex(0);
|
||||
analWindow->selected(); // tell it!
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
218
src/MainWindow.h
218
src/MainWindow.h
@@ -32,77 +32,99 @@
|
||||
#include "SpecialFields.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class AerolabWindow;
|
||||
class GoogleMapControl;
|
||||
class AllPlotWindow;
|
||||
class CriticalPowerWindow;
|
||||
class HistogramWindow;
|
||||
class PfPvWindow;
|
||||
class HrPwWindow;
|
||||
class QwtPlotPanner;
|
||||
class QwtPlotPicker;
|
||||
class QwtPlotZoomer;
|
||||
class LTMWindow;
|
||||
class MetricAggregator;
|
||||
class ModelWindow;
|
||||
class ScatterWindow;
|
||||
class RealtimeWindow;
|
||||
class RideFile;
|
||||
class RideMetadata;
|
||||
class WeeklySummaryWindow;
|
||||
class Zones;
|
||||
class HrZones;
|
||||
class RideCalendar;
|
||||
class PerformanceManagerWindow;
|
||||
class SummaryWindow;
|
||||
class ViewSelection;
|
||||
class TrainWindow;
|
||||
class RideEditor;
|
||||
class RideNavigator;
|
||||
class RideFile;
|
||||
class ErgFile;
|
||||
class RideMetadata;
|
||||
class WithingsDownload;
|
||||
class CalendarDownload;
|
||||
class DiaryWindow;
|
||||
class TreeMapWindow;
|
||||
class GcWindowTool;
|
||||
class HomeWindow;
|
||||
class ICalendar;
|
||||
class CalDAV;
|
||||
class HomeWindow;
|
||||
class GcWindowTool;
|
||||
class Seasons;
|
||||
class IntervalSummaryWindow;
|
||||
class ErgFile;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
MainWindow(const QDir &home);
|
||||
void addRide(QString name, bool bSelect=true);
|
||||
void removeCurrentRide();
|
||||
const RideFile *currentRide();
|
||||
const RideItem *currentRideItem() { return ride; }
|
||||
const QTreeWidgetItem *allRideItems() { return allRides; }
|
||||
const QTreeWidgetItem *allIntervalItems() { return allIntervals; }
|
||||
QTreeWidget *intervalTreeWidget() { return intervalWidget; }
|
||||
QTreeWidget *rideTreeWidget() { return treeWidget; }
|
||||
QTreeWidgetItem *mutableIntervalItems() { return allIntervals; }
|
||||
void getBSFactors(double &timeBS, double &distanceBS,
|
||||
double &timeDP, double &distanceDP);
|
||||
QDir home;
|
||||
void setCriticalPower(int cp);
|
||||
|
||||
MainWindow(const QDir &home);
|
||||
|
||||
// *********************************************
|
||||
// ATHLETE INFO
|
||||
// *********************************************
|
||||
|
||||
// general data
|
||||
QString cyclist; // the cyclist name
|
||||
bool useMetricUnits; // metric/imperial prefs
|
||||
QDir home;
|
||||
const Zones *zones() const { return zones_; }
|
||||
const HrZones *hrZones() const { return hrzones_; }
|
||||
void setCriticalPower(int cp);
|
||||
QSqlDatabase db;
|
||||
MetricAggregator *metricDB;
|
||||
Seasons *seasons;
|
||||
|
||||
void updateRideFileIntervals();
|
||||
// athlete's ride library
|
||||
void addRide(QString name, bool bSelect=true);
|
||||
void removeCurrentRide();
|
||||
void getBSFactors(double &timeBS, double &distanceBS,
|
||||
double &timeDP, double &distanceDP);
|
||||
|
||||
// athlete's calendar
|
||||
CalendarDownload *calendarDownload;
|
||||
#ifdef GC_HAVE_ICAL
|
||||
ICalendar *rideCalendar;
|
||||
CalDAV *davCalendar;
|
||||
#endif
|
||||
|
||||
// *********************************************
|
||||
// ATHLETE RIDE LIBRARY
|
||||
// *********************************************
|
||||
|
||||
// save a ride to disk
|
||||
void saveSilent(RideItem *);
|
||||
bool saveRideSingleDialog(RideItem *);
|
||||
|
||||
// currently selected ride item, files, metadata
|
||||
void selectRideFile(QString);
|
||||
QTreeWidget *rideTreeWidget() { return treeWidget; }
|
||||
const QTreeWidgetItem *allRideItems() { return allRides; }
|
||||
RideItem *rideItem() const { return ride; }
|
||||
const RideFile *currentRide();
|
||||
const RideItem *currentRideItem() { return ride; }
|
||||
void updateRideFileIntervals();
|
||||
RideMetadata *rideMetadata() { return _rideMetadata; }
|
||||
|
||||
// let the other widgets know when ride status changes
|
||||
// ride intervals
|
||||
const QTreeWidgetItem *allIntervalItems() { return allIntervals; }
|
||||
QTreeWidget *intervalTreeWidget() { return intervalWidget; }
|
||||
QTreeWidgetItem *mutableIntervalItems() { return allIntervals; }
|
||||
|
||||
// *********************************************
|
||||
// MAINWINDOW STATE DATA
|
||||
// *********************************************
|
||||
|
||||
// state data
|
||||
SpecialFields specialFields;
|
||||
int session;
|
||||
bool isclean;
|
||||
|
||||
|
||||
// *********************************************
|
||||
// APPLICATION EVENTS
|
||||
// *********************************************
|
||||
|
||||
// MainWindow signals are used to notify
|
||||
// widgets of important events, these methods
|
||||
// can be called to raise signals
|
||||
void notifyConfigChanged(); // used by ConfigDialog to notify MainWindow
|
||||
// when config has changed - and to get a
|
||||
// signal emitted to notify its children
|
||||
@@ -110,30 +132,13 @@ class MainWindow : public QMainWindow
|
||||
// rideItem date/time changes
|
||||
void notifyRideClean() { rideClean(); }
|
||||
void notifyRideDirty() { rideDirty(); }
|
||||
void selectView(int);
|
||||
void selectRideFile(QString);
|
||||
|
||||
// realtime signals
|
||||
void notifyTelemetryUpdate(RealtimeData rtData) { telemetryUpdate(rtData); }
|
||||
void notifyErgFileSelected(ErgFile *x) { ergFileSelected(x); }
|
||||
void notifySetNow(long now) { setNow(now); }
|
||||
|
||||
// db connections to cyclistdir/metricDB - one per active MainWindow
|
||||
QSqlDatabase db;
|
||||
MetricAggregator *metricDB;
|
||||
SpecialFields specialFields;
|
||||
Seasons *seasons;
|
||||
|
||||
int session;
|
||||
bool isclean;
|
||||
QString cyclist; // the cyclist name
|
||||
bool useMetricUnits; // whether metric units are used (or imperial)
|
||||
|
||||
CalendarDownload *calendarDownload;
|
||||
#ifdef GC_HAVE_ICAL
|
||||
ICalendar *rideCalendar;
|
||||
CalDAV *davCalendar;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -148,7 +153,6 @@ class MainWindow : public QMainWindow
|
||||
|
||||
signals:
|
||||
|
||||
//void rideSelected();
|
||||
void intervalSelected();
|
||||
void intervalsChanged();
|
||||
void zonesChanged();
|
||||
@@ -163,12 +167,8 @@ class MainWindow : public QMainWindow
|
||||
void setNow(long);
|
||||
|
||||
private slots:
|
||||
void tabViewTriggered(bool);
|
||||
void rideTreeWidgetSelectionChanged();
|
||||
void intervalTreeWidgetSelectionChanged();
|
||||
void leftLayoutMoved();
|
||||
void splitterMoved();
|
||||
void summarySplitterMoved();
|
||||
void newCyclist();
|
||||
void openCyclist();
|
||||
void downloadRide();
|
||||
@@ -195,7 +195,6 @@ class MainWindow : public QMainWindow
|
||||
void findPowerPeaks();
|
||||
void splitRide();
|
||||
void deleteRide();
|
||||
void tabChanged(int index);
|
||||
void aboutDialog();
|
||||
void saveRide(); // save current ride menu item
|
||||
void revertRide();
|
||||
@@ -203,9 +202,9 @@ class MainWindow : public QMainWindow
|
||||
void showOptions();
|
||||
void showTools();
|
||||
void showWorkoutWizard();
|
||||
void importRideToDB();
|
||||
void importRideToDB();
|
||||
void scanForMissing();
|
||||
void dateChanged(const QDate &);
|
||||
void dateChanged(const QDate &);
|
||||
void showTreeContextMenuPopup(const QPoint &);
|
||||
void showContextMenuPopup(const QPoint &);
|
||||
void deleteInterval();
|
||||
@@ -243,21 +242,13 @@ class MainWindow : public QMainWindow
|
||||
static QString notesFileName(QString rideFileName);
|
||||
|
||||
private:
|
||||
RideItem *ride; // the currently selected ride
|
||||
|
||||
QToolBox *toolBox;
|
||||
QToolBar *toolbar;
|
||||
QDockWidget *dock;
|
||||
QDockWidget *dock;
|
||||
QAction *homeAct, *diaryAct, *analysisAct, *measuresAct, *trainAct, *athleteAct, *helpAct, *configAct;
|
||||
|
||||
bool parseRideFileName(const QString &name, QString *notesFileName, QDateTime *dt);
|
||||
struct TabInfo {
|
||||
GcWindow *contents;
|
||||
QString name;
|
||||
QAction *action;
|
||||
TabInfo(GcWindow *contents, QString name) :
|
||||
contents(contents), name(name), action(NULL) {}
|
||||
};
|
||||
QList<TabInfo> tabs;
|
||||
|
||||
boost::shared_ptr<QSettings> settings;
|
||||
IntervalItem *activeInterval; // currently active for context menu popup
|
||||
RideItem *activeRide; // currently active for context menu popup
|
||||
@@ -274,57 +265,32 @@ class MainWindow : public QMainWindow
|
||||
QAction *sideView;
|
||||
QAction *toolView;
|
||||
|
||||
// Analysis
|
||||
RideCalendar *calendar;
|
||||
// Top-level views
|
||||
HomeWindow *homeWindow;
|
||||
DiaryWindow *diaryWindow;
|
||||
HomeWindow *trainWindow;
|
||||
HomeWindow *analWindow;
|
||||
|
||||
// sidebar
|
||||
QTreeWidgetItem *allRides;
|
||||
QTreeWidgetItem *allIntervals;
|
||||
IntervalSummaryWindow *intervalSummaryWindow;
|
||||
QSplitter *leftLayout;
|
||||
RideMetadata *_rideMetadata;
|
||||
GcWindowTool *chartTool;
|
||||
|
||||
QSplitter *summarySplitter;
|
||||
QSplitter *splitter;
|
||||
QSplitter *metaSplitter;
|
||||
QTreeWidget *treeWidget;
|
||||
QSplitter *intervalSplitter;
|
||||
QTreeWidget *intervalWidget;
|
||||
IntervalSummaryWindow *intervalSummaryWindow;
|
||||
QTabWidget *tabWidget;
|
||||
SummaryWindow *summaryWindow;
|
||||
DiaryWindow *diaryWindow;
|
||||
HomeWindow *homeWindow;
|
||||
HomeWindow *trainWindow;
|
||||
AllPlotWindow *allPlotWindow;
|
||||
HistogramWindow *histogramWindow;
|
||||
WeeklySummaryWindow *weeklySummaryWindow;
|
||||
LTMWindow *ltmWindow;
|
||||
CriticalPowerWindow *criticalPowerWindow;
|
||||
ModelWindow *modelWindow;
|
||||
ScatterWindow *scatterWindow;
|
||||
AerolabWindow *aerolabWindow;
|
||||
GoogleMapControl *googleMap;
|
||||
TreeMapWindow *treemapWindow;
|
||||
RideEditor *rideEdit;
|
||||
RideNavigator *rideNavigator;
|
||||
QTreeWidgetItem *allRides;
|
||||
QTreeWidgetItem *allIntervals;
|
||||
QSplitter *leftLayout;
|
||||
RideMetadata *_rideMetadata;
|
||||
QSplitter *summarySplitter;
|
||||
|
||||
//QwtPlotCurve *weeklyBSCurve;
|
||||
//QwtPlotCurve *weeklyRICurve;
|
||||
PerformanceManagerWindow *performanceManagerWindow;
|
||||
|
||||
|
||||
// pedal force/pedal velocity scatter plot widgets
|
||||
PfPvWindow *pfPvWindow;
|
||||
|
||||
HrPwWindow *hrPwWindow;
|
||||
|
||||
RideItem *ride; // the currently selected ride
|
||||
|
||||
|
||||
QuarqdClient *client;
|
||||
|
||||
QSignalMapper *toolMapper;
|
||||
WithingsDownload *withingsDownload;
|
||||
|
||||
GcWindowTool *chartTool;
|
||||
|
||||
// Miscellany
|
||||
QuarqdClient *client;
|
||||
QSignalMapper *toolMapper;
|
||||
WithingsDownload *withingsDownload;
|
||||
bool parseRideFileName(const QString &name, QString *notesFileName, QDateTime *dt);
|
||||
};
|
||||
|
||||
#endif // _GC_MainWindow_h
|
||||
|
||||
@@ -37,6 +37,7 @@ class MainWindow;
|
||||
class RideItem;
|
||||
class RideFilePoint;
|
||||
class RideFileCache;
|
||||
class HistogramWindow;
|
||||
class PowerHistBackground;
|
||||
class PowerHistZoneLabel;
|
||||
class HrHistBackground;
|
||||
|
||||
@@ -146,7 +146,6 @@ class TrainTool : public QWidget
|
||||
|
||||
const QDir home;
|
||||
MainWindow *main;
|
||||
ViewSelection *viewSelection;
|
||||
|
||||
QTreeWidget *workoutTree;
|
||||
QTreeWidget *deviceTree;
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
class TreeMapWindow;
|
||||
|
||||
// for sorting
|
||||
class TreeMap;
|
||||
bool TreeMapLessThan(const TreeMap *, const TreeMap *);
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <qwt_plot_picker.h>
|
||||
#include <qwt_text_engine.h>
|
||||
|
||||
class TreeMapPlot;
|
||||
|
||||
class TreeMapWindow : public GcWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<file>xml/metadata.xml</file>
|
||||
<file>xml/measures.xml</file>
|
||||
<file>xml/train-layout.xml</file>
|
||||
<file>xml/analysis-layout.xml</file>
|
||||
<file>html/ltm-summary.html</file>
|
||||
<file>images/toolbar/close-icon.png</file>
|
||||
<file>images/toolbar/save.png</file>
|
||||
|
||||
99
src/xml/analysis-layout.xml
Normal file
99
src/xml/analysis-layout.xml
Normal file
@@ -0,0 +1,99 @@
|
||||
<layout name="analysis">
|
||||
<chart id="14" name="Ride Summary Window" title="Summary" >
|
||||
<property name="instanceName" type="QString" value="Ride Summary Window" />
|
||||
<property name="title" type="QString" value="Summary" />
|
||||
<property name="widthFactor" type="double" value="1.7042" />
|
||||
<property name="heightFactor" type="double" value="1.65821" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
</chart>
|
||||
<chart id="5" name="Google Map" title="Map" >
|
||||
<property name="instanceName" type="QString" value="Google Map" />
|
||||
<property name="title" type="QString" value="Map" />
|
||||
<property name="widthFactor" type="double" value="2.45521" />
|
||||
<property name="heightFactor" type="double" value="1.66194" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
</chart>
|
||||
<chart id="6" name="Histogram Window" title="Power Distribution" >
|
||||
<property name="instanceName" type="QString" value="Histogram Window" />
|
||||
<property name="title" type="QString" value="Power Distribution" />
|
||||
<property name="widthFactor" type="double" value="4" />
|
||||
<property name="heightFactor" type="double" value="2.51311" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
<property name="series" type="int" value="0" />
|
||||
<property name="percent" type="int" value="0" />
|
||||
<property name="bin" type="double" value="4" />
|
||||
<property name="logY" type="bool" value="0" />
|
||||
<property name="zeroes" type="bool" value="0" />
|
||||
<property name="shade" type="bool" value="0" />
|
||||
<property name="zoned" type="bool" value="0" />
|
||||
<property name="scope" type="bool" value="0" />
|
||||
</chart>
|
||||
<chart id="6" name="Histogram Window" title="Cadence Distribution" >
|
||||
<property name="instanceName" type="QString" value="Histogram Window" />
|
||||
<property name="title" type="QString" value="Cadence Distribution" />
|
||||
<property name="widthFactor" type="double" value="4" />
|
||||
<property name="heightFactor" type="double" value="2.51349" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
<property name="series" type="int" value="3" />
|
||||
<property name="percent" type="int" value="0" />
|
||||
<property name="bin" type="double" value="1" />
|
||||
<property name="logY" type="bool" value="0" />
|
||||
<property name="zeroes" type="bool" value="0" />
|
||||
<property name="shade" type="bool" value="0" />
|
||||
<property name="zoned" type="bool" value="0" />
|
||||
<property name="scope" type="bool" value="0" />
|
||||
</chart>
|
||||
<chart id="6" name="Histogram Window" title="Heartrate Distribution" >
|
||||
<property name="instanceName" type="QString" value="Histogram Window" />
|
||||
<property name="title" type="QString" value="Heartrate Distribution" />
|
||||
<property name="widthFactor" type="double" value="4" />
|
||||
<property name="heightFactor" type="double" value="2.51349" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
<property name="series" type="int" value="1" />
|
||||
<property name="percent" type="int" value="0" />
|
||||
<property name="bin" type="double" value="1" />
|
||||
<property name="logY" type="bool" value="0" />
|
||||
<property name="zeroes" type="bool" value="0" />
|
||||
<property name="shade" type="bool" value="0" />
|
||||
<property name="zoned" type="bool" value="0" />
|
||||
<property name="scope" type="bool" value="0" />
|
||||
</chart>
|
||||
<chart id="6" name="Histogram Window" title="Speed Distribution" >
|
||||
<property name="instanceName" type="QString" value="Histogram Window" />
|
||||
<property name="title" type="QString" value="Speed Distribution" />
|
||||
<property name="widthFactor" type="double" value="4" />
|
||||
<property name="heightFactor" type="double" value="2.51349" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
<property name="series" type="int" value="2" />
|
||||
<property name="percent" type="int" value="0" />
|
||||
<property name="bin" type="double" value="20" />
|
||||
<property name="logY" type="bool" value="0" />
|
||||
<property name="zeroes" type="bool" value="0" />
|
||||
<property name="shade" type="bool" value="0" />
|
||||
<property name="zoned" type="bool" value="0" />
|
||||
<property name="scope" type="bool" value="0" />
|
||||
</chart>
|
||||
<chart id="23" name="Metadata Window" title="Information" >
|
||||
<property name="instanceName" type="QString" value="Metadata Window" />
|
||||
<property name="title" type="QString" value="Information" />
|
||||
<property name="widthFactor" type="double" value="1.00103" />
|
||||
<property name="heightFactor" type="double" value="2.16898" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
</chart>
|
||||
<chart id="2" name="Ride Plot Window" title="Ride Plot" >
|
||||
<property name="instanceName" type="QString" value="Ride Plot Window" />
|
||||
<property name="title" type="QString" value="Ride Plot" />
|
||||
<property name="widthFactor" type="double" value="1" />
|
||||
<property name="heightFactor" type="double" value="1" />
|
||||
<property name="resizable" type="bool" value="1" />
|
||||
<property name="stacked" type="bool" value="0" />
|
||||
<property name="showGrid" type="int" value="2" />
|
||||
<property name="showHr" type="int" value="2" />
|
||||
<property name="showSpeed" type="int" value="2" />
|
||||
<property name="showCad" type="int" value="2" />
|
||||
<property name="showAlt" type="int" value="2" />
|
||||
<property name="showPower" type="int" value="1" />
|
||||
<property name="byDistance" type="int" value="0" />
|
||||
<property name="smoothing" type="int" value="1" />
|
||||
</chart>
|
||||
</layout>
|
||||
Reference in New Issue
Block a user