mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 16:39:57 +00:00
602 lines
23 KiB
C++
602 lines
23 KiB
C++
/*
|
|
* Copyright (c) 2012 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 "AnalysisSidebar.h"
|
|
#include "MainWindow.h"
|
|
#include "Context.h"
|
|
#include "Athlete.h"
|
|
#include "Settings.h"
|
|
#include "Units.h"
|
|
#include <QtGui>
|
|
|
|
// metadata support
|
|
#include "RideMetadata.h"
|
|
#include "SpecialFields.h"
|
|
|
|
// working with intervals
|
|
#include "IntervalItem.h"
|
|
#include "AddIntervalDialog.h"
|
|
#include "BestIntervalDialog.h"
|
|
|
|
AnalysisSidebar::AnalysisSidebar(Context *context) : QWidget(context->mainWindow), context(context)
|
|
{
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
mainLayout->setContentsMargins(0,0,0,0);
|
|
mainLayout->setSpacing(0);
|
|
setContentsMargins(0,0,0,0);
|
|
|
|
splitter = new GcSplitter(Qt::Vertical);
|
|
mainLayout->addWidget(splitter);
|
|
|
|
// calendar
|
|
calendarWidget = new GcMultiCalendar(context);
|
|
calendarItem = new GcSplitterItem(tr("Calendar"), iconFromPNG(":images/sidebar/calendar.png"), this);
|
|
calendarItem->addWidget(calendarWidget);
|
|
|
|
// Activity History
|
|
rideNavigator = new RideNavigator(context, true);
|
|
rideNavigator->setProperty("nomenu", true);
|
|
groupByMapper = NULL;
|
|
|
|
// retrieve settings (properties are saved when we close the window)
|
|
if (appsettings->cvalue(context->athlete->cyclist, GC_NAVHEADINGS, "").toString() != "") {
|
|
rideNavigator->setSortByIndex(appsettings->cvalue(context->athlete->cyclist, GC_SORTBY).toInt());
|
|
rideNavigator->setSortByOrder(appsettings->cvalue(context->athlete->cyclist, GC_SORTBYORDER).toInt());
|
|
rideNavigator->setGroupBy(appsettings->cvalue(context->athlete->cyclist, GC_NAVGROUPBY).toInt());
|
|
rideNavigator->setColumns(appsettings->cvalue(context->athlete->cyclist, GC_NAVHEADINGS).toString());
|
|
rideNavigator->setWidths(appsettings->cvalue(context->athlete->cyclist, GC_NAVHEADINGWIDTHS).toString());
|
|
}
|
|
|
|
QWidget *activityHistory = new QWidget(this);
|
|
activityHistory->setContentsMargins(0,0,0,0);
|
|
#ifndef Q_OS_MAC // not on mac thanks
|
|
activityHistory->setStyleSheet("padding: 0px; border: 0px; margin: 0px;");
|
|
#endif
|
|
QVBoxLayout *activityLayout = new QVBoxLayout(activityHistory);
|
|
activityLayout->setSpacing(0);
|
|
activityLayout->setContentsMargins(0,0,0,0);
|
|
activityLayout->addWidget(rideNavigator);
|
|
|
|
activityItem = new GcSplitterItem(tr("Activities"), iconFromPNG(":images/sidebar/folder.png"), this);
|
|
QAction *activityAction = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
|
|
activityItem->addAction(activityAction);
|
|
connect(activityAction, SIGNAL(triggered(void)), this, SLOT(analysisPopup()));
|
|
activityItem->addWidget(activityHistory);
|
|
|
|
// INTERVALS
|
|
intervalSummaryWindow = new IntervalSummaryWindow(context);
|
|
|
|
intervalSplitter = new QSplitter(this);
|
|
intervalSplitter->setHandleWidth(1);
|
|
intervalSplitter->setOrientation(Qt::Vertical);
|
|
intervalSplitter->addWidget(context->athlete->intervalWidget);
|
|
activeInterval = NULL;
|
|
intervalSplitter->addWidget(intervalSummaryWindow);
|
|
intervalSplitter->setFrameStyle(QFrame::NoFrame);
|
|
intervalSplitter->setCollapsible(0, false);
|
|
intervalSplitter->setCollapsible(1, false);
|
|
|
|
intervalItem = new GcSplitterItem(tr("Intervals"), iconFromPNG(":images/mac/stop.png"), this);
|
|
QAction *moreIntervalAct = new QAction(iconFromPNG(":images/sidebar/extra.png"), tr("Menu"), this);
|
|
intervalItem->addAction(moreIntervalAct);
|
|
connect(moreIntervalAct, SIGNAL(triggered(void)), this, SLOT(intervalPopup()));
|
|
intervalItem->addWidget(intervalSplitter);
|
|
|
|
splitter->addWidget(calendarItem);
|
|
splitter->addWidget(activityItem);
|
|
splitter->addWidget(intervalItem);
|
|
|
|
splitter->prepare(context->athlete->cyclist, "analysis");
|
|
|
|
// GC signal
|
|
connect(context, SIGNAL(configChanged()), this, SLOT(configChanged()));
|
|
|
|
// right click menus...
|
|
connect(rideNavigator,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showActivityMenu(const QPoint &)));
|
|
connect(context->athlete->intervalWidget,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showIntervalMenu(const QPoint &)));
|
|
|
|
connect (context, SIGNAL(filterChanged()), this, SLOT(filterChanged()));
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::setRide(RideItem*ride)
|
|
{
|
|
calendarWidget->setRide(ride);
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::close()
|
|
{
|
|
appsettings->setCValue(context->athlete->cyclist, GC_SORTBY, rideNavigator->sortByIndex());
|
|
appsettings->setCValue(context->athlete->cyclist, GC_SORTBYORDER, rideNavigator->sortByOrder());
|
|
appsettings->setCValue(context->athlete->cyclist, GC_NAVGROUPBY, rideNavigator->groupBy());
|
|
appsettings->setCValue(context->athlete->cyclist, GC_NAVHEADINGS, rideNavigator->columns());
|
|
appsettings->setCValue(context->athlete->cyclist, GC_NAVHEADINGWIDTHS, rideNavigator->widths());
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::configChanged()
|
|
{
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::filterChanged()
|
|
{
|
|
if (context->isfiltered) setFilter(context->filters);
|
|
else clearFilter();
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::setFilter(QStringList filter)
|
|
{
|
|
rideNavigator->searchStrings(filter);
|
|
calendarWidget->setFilter(filter);
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::clearFilter()
|
|
{
|
|
rideNavigator->clearSearch();
|
|
calendarWidget->clearFilter();
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Sidebar Menus
|
|
**********************************************************************/
|
|
void
|
|
AnalysisSidebar::analysisPopup()
|
|
{
|
|
// set the point for the menu and call below
|
|
showActivityMenu(this->mapToGlobal(QPoint(activityItem->pos().x()+activityItem->width()-20, activityItem->pos().y())));
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::showActivityMenu(const QPoint &pos)
|
|
{
|
|
if (context->athlete->treeWidget->selectedItems().size() == 0) return; //none selected!
|
|
|
|
RideItem *rideItem = (RideItem *)context->athlete->treeWidget->selectedItems().first();
|
|
if (rideItem != NULL && rideItem->text(0) != tr("All Activities")) {
|
|
QMenu menu(context->athlete->treeWidget);
|
|
|
|
|
|
QAction *actSaveRide = new QAction(tr("Save Changes"), context->athlete->treeWidget);
|
|
connect(actSaveRide, SIGNAL(triggered(void)), context->mainWindow, SLOT(saveRide()));
|
|
|
|
QAction *revertRide = new QAction(tr("Revert to Saved version"), context->athlete->treeWidget);
|
|
connect(revertRide, SIGNAL(triggered(void)), context->mainWindow, SLOT(revertRide()));
|
|
|
|
QAction *actDeleteRide = new QAction(tr("Delete Activity"), context->athlete->treeWidget);
|
|
connect(actDeleteRide, SIGNAL(triggered(void)), context->mainWindow, SLOT(deleteRide()));
|
|
|
|
QAction *actSplitRide = new QAction(tr("Split Activity"), context->athlete->treeWidget);
|
|
connect(actSplitRide, SIGNAL(triggered(void)), context->mainWindow, SLOT(splitRide()));
|
|
|
|
if (rideItem->isDirty() == true) {
|
|
menu.addAction(actSaveRide);
|
|
menu.addAction(revertRide);
|
|
}
|
|
|
|
menu.addAction(actDeleteRide);
|
|
menu.addAction(actSplitRide);
|
|
#ifdef GC_HAVE_ICAL
|
|
QAction *actUploadCalendar = new QAction(tr("Upload Activity to Calendar"), context->athlete->treeWidget);
|
|
connect(actUploadCalendar, SIGNAL(triggered(void)), context->mainWindow, SLOT(uploadCalendar()));
|
|
menu.addAction(actUploadCalendar);
|
|
#endif
|
|
menu.addSeparator();
|
|
|
|
// ride navigator stuff
|
|
QAction *colChooser = new QAction(tr("Show Column Chooser"), context->athlete->treeWidget);
|
|
connect(colChooser, SIGNAL(triggered(void)), rideNavigator, SLOT(showColumnChooser()));
|
|
menu.addAction(colChooser);
|
|
|
|
if (rideNavigator->groupBy() >= 0) {
|
|
|
|
// already grouped lets ungroup
|
|
QAction *nogroups = new QAction(tr("Do Not Show In Groups"), context->athlete->treeWidget);
|
|
connect(nogroups, SIGNAL(triggered(void)), rideNavigator, SLOT(noGroups()));
|
|
menu.addAction(nogroups);
|
|
|
|
} else {
|
|
|
|
QMenu *groupByMenu = new QMenu(tr("Group By"), context->athlete->treeWidget);
|
|
groupByMenu->setEnabled(true);
|
|
menu.addMenu(groupByMenu);
|
|
|
|
// add menu options for each column
|
|
if (groupByMapper) delete groupByMapper;
|
|
groupByMapper = new QSignalMapper(this);
|
|
connect(groupByMapper, SIGNAL(mapped(const QString &)), rideNavigator, SLOT(setGroupByColumnName(QString)));
|
|
|
|
foreach(QString heading, rideNavigator->columnNames()) {
|
|
if (heading == "*") continue; // special hidden column
|
|
|
|
QAction *groupByAct = new QAction(heading, context->athlete->treeWidget);
|
|
connect(groupByAct, SIGNAL(triggered()), groupByMapper, SLOT(map()));
|
|
groupByMenu->addAction(groupByAct);
|
|
|
|
// map action to column heading
|
|
groupByMapper->setMapping(groupByAct, heading);
|
|
}
|
|
}
|
|
// expand / collapse
|
|
QAction *expandAll = new QAction(tr("Expand All"), context->athlete->treeWidget);
|
|
connect(expandAll, SIGNAL(triggered(void)), rideNavigator->tableView, SLOT(expandAll()));
|
|
menu.addAction(expandAll);
|
|
|
|
// expand / collapse
|
|
QAction *collapseAll = new QAction(tr("Collapse All"), context->athlete->treeWidget);
|
|
connect(collapseAll, SIGNAL(triggered(void)), rideNavigator->tableView, SLOT(collapseAll()));
|
|
menu.addAction(collapseAll);
|
|
menu.exec(pos);
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::intervalPopup()
|
|
{
|
|
// always show the 'find best' 'find peaks' options
|
|
QMenu menu(intervalItem);
|
|
|
|
RideItem *rideItem = (RideItem *)context->athlete->treeWidget->selectedItems().first();
|
|
|
|
if (rideItem != NULL && rideItem->ride() && rideItem->ride()->dataPoints().count()) {
|
|
QAction *actFindPeak = new QAction(tr("Find Peak Intervals"), intervalItem);
|
|
QAction *actFindBest = new QAction(tr("Find Best Intervals"), intervalItem);
|
|
connect(actFindPeak, SIGNAL(triggered(void)), this, SLOT(findPowerPeaks(void)));
|
|
connect(actFindBest, SIGNAL(triggered(void)), this, SLOT(addIntervals(void)));
|
|
menu.addAction(actFindPeak);
|
|
menu.addAction(actFindBest);
|
|
|
|
// sort but only if 2 or more intervals
|
|
if (context->athlete->allIntervals->childCount() > 1) {
|
|
QAction *actSort = new QAction(tr("Sort Intervals"), intervalItem);
|
|
connect(actSort, SIGNAL(triggered(void)), this, SLOT(sortIntervals(void)));
|
|
menu.addAction(actSort);
|
|
}
|
|
|
|
if (context->athlete->intervalWidget->selectedItems().count()) menu.addSeparator();
|
|
}
|
|
|
|
|
|
if (context->athlete->intervalWidget->selectedItems().count() == 1) {
|
|
|
|
// we can zoom, rename etc if only 1 interval is selected
|
|
QAction *actZoomInt = new QAction(tr("Zoom to interval"), context->athlete->intervalWidget);
|
|
QAction *actEditInt = new QAction(tr("Edit interval"), context->athlete->intervalWidget);
|
|
QAction *actDeleteInt = new QAction(tr("Delete interval"), context->athlete->intervalWidget);
|
|
|
|
connect(actZoomInt, SIGNAL(triggered(void)), this, SLOT(zoomIntervalSelected(void)));
|
|
connect(actEditInt, SIGNAL(triggered(void)), this, SLOT(editIntervalSelected(void)));
|
|
connect(actDeleteInt, SIGNAL(triggered(void)), this, SLOT(deleteIntervalSelected(void)));
|
|
|
|
menu.addAction(actZoomInt);
|
|
menu.addAction(actEditInt);
|
|
menu.addAction(actDeleteInt);
|
|
}
|
|
|
|
if (context->athlete->intervalWidget->selectedItems().count() > 1) {
|
|
QAction *actRenameInt = new QAction(tr("Rename selected intervals"), context->athlete->intervalWidget);
|
|
connect(actRenameInt, SIGNAL(triggered(void)), this, SLOT(renameIntervalsSelected(void)));
|
|
QAction *actDeleteInt = new QAction(tr("Delete selected intervals"), context->athlete->intervalWidget);
|
|
connect(actDeleteInt, SIGNAL(triggered(void)), this, SLOT(deleteIntervalSelected(void)));
|
|
|
|
menu.addAction(actRenameInt);
|
|
menu.addAction(actDeleteInt);
|
|
}
|
|
|
|
menu.exec(mapToGlobal((QPoint(intervalItem->pos().x()+intervalItem->width()-20, intervalItem->pos().y()))));
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::showIntervalMenu(const QPoint &pos)
|
|
{
|
|
QTreeWidgetItem *trItem = context->athlete->intervalWidget->itemAt(pos);
|
|
if (trItem != NULL && trItem->text(0) != tr("Intervals")) {
|
|
|
|
activeInterval = (IntervalItem *)trItem;
|
|
QMenu menu(context->athlete->intervalWidget);
|
|
|
|
QAction *actEditInt = new QAction(tr("Edit interval"), context->athlete->intervalWidget);
|
|
QAction *actDeleteInt = new QAction(tr("Delete interval"), context->athlete->intervalWidget);
|
|
QAction *actZoomInt = new QAction(tr("Zoom to interval"), context->athlete->intervalWidget);
|
|
QAction *actFrontInt = new QAction(tr("Bring to Front"), context->athlete->intervalWidget);
|
|
QAction *actBackInt = new QAction(tr("Send to back"), context->athlete->intervalWidget);
|
|
connect(actEditInt, SIGNAL(triggered(void)), this, SLOT(editInterval(void)));
|
|
connect(actDeleteInt, SIGNAL(triggered(void)), this, SLOT(deleteInterval(void)));
|
|
connect(actZoomInt, SIGNAL(triggered(void)), this, SLOT(zoomInterval(void)));
|
|
connect(actFrontInt, SIGNAL(triggered(void)), this, SLOT(frontInterval(void)));
|
|
connect(actBackInt, SIGNAL(triggered(void)), this, SLOT(backInterval(void)));
|
|
|
|
menu.addAction(actZoomInt);
|
|
menu.addAction(actEditInt);
|
|
menu.addAction(actDeleteInt);
|
|
menu.exec(context->athlete->intervalWidget->mapToGlobal(pos));
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------
|
|
* Intervals
|
|
*--------------------------------------------------------------------*/
|
|
|
|
void
|
|
AnalysisSidebar::addIntervals()
|
|
{
|
|
if (context->ride && context->ride->ride() && context->ride->ride()->dataPoints().count()) {
|
|
|
|
AddIntervalDialog *p = new AddIntervalDialog(context);
|
|
p->setWindowModality(Qt::ApplicationModal); // don't allow select other ride or it all goes wrong!
|
|
p->exec();
|
|
|
|
} else {
|
|
|
|
if (!context->ride || !context->ride->ride())
|
|
QMessageBox::critical(this, tr("Find Best Intervals"), tr("No activity selected"));
|
|
else
|
|
QMessageBox::critical(this, tr("Find Best Intervals"), tr("Current activity contains no data"));
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::addIntervalForPowerPeaksForSecs(RideFile *ride, int windowSizeSecs, QString name)
|
|
{
|
|
QList<BestIntervalDialog::BestInterval> results;
|
|
BestIntervalDialog::findBests(ride, windowSizeSecs, 1, results);
|
|
if (results.isEmpty()) return;
|
|
const BestIntervalDialog::BestInterval &i = results.first();
|
|
QTreeWidgetItem *peak =
|
|
new IntervalItem(ride, name+tr(" (%1 watts)").arg((int) round(i.avg)),
|
|
i.start, i.stop,
|
|
ride->timeToDistance(i.start),
|
|
ride->timeToDistance(i.stop),
|
|
context->athlete->allIntervals->childCount()+1);
|
|
peak->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
|
context->athlete->allIntervals->addChild(peak);
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::findPowerPeaks()
|
|
{
|
|
|
|
if (!context->ride) return;
|
|
|
|
QTreeWidgetItem *which = context->athlete->treeWidget->selectedItems().first();
|
|
if (which->type() != RIDE_TYPE) {
|
|
return;
|
|
}
|
|
|
|
if (context->ride && context->ride->ride() && context->ride->ride()->dataPoints().count()) {
|
|
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 5, "Peak 5s");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 10, "Peak 10s");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 20, "Peak 20s");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 30, "Peak 30s");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 60, "Peak 1min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 120, "Peak 2min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 300, "Peak 5min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 600, "Peak 10min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 1200, "Peak 20min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 1800, "Peak 30min");
|
|
addIntervalForPowerPeaksForSecs(context->ride->ride(), 3600, "Peak 60min");
|
|
|
|
// now update the RideFileIntervals
|
|
context->athlete->updateRideFileIntervals();
|
|
|
|
} else {
|
|
if (!context->ride || !context->ride->ride())
|
|
QMessageBox::critical(this, tr("Find Power Peaks"), tr("No activity selected"));
|
|
else
|
|
QMessageBox::critical(this, tr("Find Power Peaks"), tr("Current activity contains no data"));
|
|
}
|
|
}
|
|
|
|
|
|
bool
|
|
lessItem(const IntervalItem *s1, const IntervalItem *s2) {
|
|
return s1->start < s2->start;
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::sortIntervals()
|
|
{
|
|
// sort them chronologically
|
|
QList<IntervalItem*> intervals;
|
|
|
|
// set string to first interval selected
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();i++)
|
|
intervals.append((IntervalItem*)(context->athlete->allIntervals->child(i)));
|
|
|
|
// now sort them into start time order
|
|
qStableSort(intervals.begin(), intervals.end(), lessItem);
|
|
|
|
// empty context->athlete->allIntervals
|
|
context->athlete->allIntervals->takeChildren();
|
|
|
|
// and put em back in chronological sequence
|
|
foreach(IntervalItem* item, intervals) {
|
|
context->athlete->allIntervals->addChild(item);
|
|
}
|
|
|
|
// now update the ridefile
|
|
context->athlete->updateRideFileIntervals(); // will emit intervalChanged() signal
|
|
}
|
|
|
|
// rename multiple intervals
|
|
void
|
|
AnalysisSidebar::renameIntervalsSelected()
|
|
{
|
|
QString string;
|
|
|
|
// set string to first interval selected
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();i++) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected()) {
|
|
string = context->athlete->allIntervals->child(i)->text(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// type in a name and we will renumber all the intervals
|
|
// in the same fashion -- esp if the last characters are
|
|
RenameIntervalDialog dialog(string, this);
|
|
dialog.setFixedWidth(320);
|
|
|
|
if (dialog.exec()) {
|
|
|
|
int number = 1;
|
|
|
|
// does it end in a number?
|
|
// if so we use that to renumber from
|
|
QRegExp ends("^(.*[^0-9])([0-9]+)$");
|
|
if (ends.exactMatch(string)) {
|
|
|
|
string = ends.cap(1);
|
|
number = ends.cap(2).toInt();
|
|
|
|
} else if (!string.endsWith(" ")) string += " ";
|
|
|
|
// now go and renumber from 'number' with prefix 'string'
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();i++) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected())
|
|
context->athlete->allIntervals->child(i)->setText(0, QString("%1%2").arg(string).arg(number++));
|
|
}
|
|
|
|
context->athlete->updateRideFileIntervals(); // will emit intervalChanged() signal
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::deleteIntervalSelected()
|
|
{
|
|
// delete the intervals that are selected (from the menu)
|
|
// the normal delete intervals does that already
|
|
deleteInterval();
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::deleteInterval()
|
|
{
|
|
// now delete highlighted!
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected()) delete context->athlete->allIntervals->takeChild(i);
|
|
else i++;
|
|
}
|
|
|
|
context->athlete->updateRideFileIntervals(); // will emit intervalChanged() signal
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::renameIntervalSelected()
|
|
{
|
|
// go edit the name
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected()) {
|
|
context->athlete->allIntervals->child(i)->setFlags(context->athlete->allIntervals->child(i)->flags() | Qt::ItemIsEditable);
|
|
context->athlete->intervalWidget->editItem(context->athlete->allIntervals->child(i), 0);
|
|
break;
|
|
} else i++;
|
|
}
|
|
context->athlete->updateRideFileIntervals(); // will emit intervalChanged() signal
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::renameInterval() {
|
|
// go edit the name
|
|
activeInterval->setFlags(activeInterval->flags() | Qt::ItemIsEditable);
|
|
context->athlete->intervalWidget->editItem(activeInterval, 0);
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::editIntervalSelected()
|
|
{
|
|
// go edit the interval
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected()) {
|
|
activeInterval = (IntervalItem*)context->athlete->allIntervals->child(i);
|
|
editInterval();
|
|
break;
|
|
} else i++;
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::editInterval()
|
|
{
|
|
IntervalItem temp = *activeInterval;
|
|
EditIntervalDialog dialog(this, temp);
|
|
|
|
if (dialog.exec()) {
|
|
*activeInterval = temp;
|
|
context->athlete->updateRideFileIntervals(); // will emit intervalChanged() signal
|
|
context->athlete->intervalWidget->update();
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::zoomIntervalSelected()
|
|
{
|
|
// zoom the one interval that is selected via popup menu
|
|
for (int i=0; i<context->athlete->allIntervals->childCount();) {
|
|
if (context->athlete->allIntervals->child(i)->isSelected()) {
|
|
context->notifyIntervalZoom((IntervalItem*)(context->athlete->allIntervals->child(i)));
|
|
break;
|
|
} else i++;
|
|
}
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::zoomInterval() {
|
|
// zoom into this interval on allPlot
|
|
context->notifyIntervalZoom(activeInterval);
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::frontInterval()
|
|
{
|
|
int oindex = activeInterval->displaySequence;
|
|
for (int i=0; i<context->athlete->allIntervals->childCount(); i++) {
|
|
IntervalItem *it = (IntervalItem *)context->athlete->allIntervals->child(i);
|
|
int ds = it->displaySequence;
|
|
if (ds > oindex)
|
|
it->setDisplaySequence(ds-1);
|
|
}
|
|
activeInterval->setDisplaySequence(context->athlete->allIntervals->childCount());
|
|
|
|
// signal!
|
|
context->notifyIntervalsChanged();
|
|
}
|
|
|
|
void
|
|
AnalysisSidebar::backInterval()
|
|
{
|
|
int oindex = activeInterval->displaySequence;
|
|
for (int i=0; i<context->athlete->allIntervals->childCount(); i++) {
|
|
IntervalItem *it = (IntervalItem *)context->athlete->allIntervals->child(i);
|
|
int ds = it->displaySequence;
|
|
if (ds < oindex)
|
|
it->setDisplaySequence(ds+1);
|
|
}
|
|
activeInterval->setDisplaySequence(1);
|
|
|
|
// signal!
|
|
context->notifyIntervalsChanged();
|
|
|
|
}
|
|
|
|
|