From 32b94d954fd9856e4e290d490ccf98479a0264a9 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Tue, 22 Dec 2009 13:46:03 +0000 Subject: [PATCH] add bring to front/send to back to PfPvPlot Another rightclick menu for intervals, adding a bring to front and send to back option but only when viewing the pfPvPlot, additionally the algorithm in PfPv plot for determining which interval a point is used for has been adjusted to fully populate every interval curve where appropriate (and incorrect comments and redundant code have been removed). IntervalItems now have a display sequence number so when you have overlapping intervals you can bring to front and send to back on the PfPv plot. The display sequence could be used on other plots if/when they distinguish between intervals. Previously, the coloring of intervals on PfPvPlot was determined solely by the order they were defined which could be quite confusing. --- src/AllPlotWindow.cpp | 3 +- src/BestIntervalDialog.cpp | 6 ++-- src/IntervalItem.cpp | 2 +- src/IntervalItem.h | 4 ++- src/MainWindow.cpp | 61 ++++++++++++++++++++++++++++++++++-- src/MainWindow.h | 2 ++ src/PfPvPlot.cpp | 63 +++++++++++++++++++------------------- src/PfPvPlot.h | 1 - src/PfPvWindow.cpp | 1 + 9 files changed, 101 insertions(+), 42 deletions(-) diff --git a/src/AllPlotWindow.cpp b/src/AllPlotWindow.cpp index d30a95cb9..bdf8e3eb6 100644 --- a/src/AllPlotWindow.cpp +++ b/src/AllPlotWindow.cpp @@ -405,7 +405,8 @@ AllPlotWindow::setEndSelection(double xValue, bool newInterval, QString name) // add average power to the end of the selection name name += QString("(%1 watts)").arg(round((wattsTotal && arrayLength) ? wattsTotal/arrayLength : 0)); - QTreeWidgetItem *last = new IntervalItem(ride->ride(), name, duration1, duration2, distance1, distance2); + QTreeWidgetItem *last = new IntervalItem(ride->ride(), name, duration1, duration2, distance1, distance2, + allIntervals->childCount()+1); allIntervals->addChild(last); // now update the RideFileIntervals and all the plots etc diff --git a/src/BestIntervalDialog.cpp b/src/BestIntervalDialog.cpp index dbedf415d..02ad889f5 100644 --- a/src/BestIntervalDialog.cpp +++ b/src/BestIntervalDialog.cpp @@ -283,13 +283,13 @@ BestIntervalDialog::addClicked() QString name = resultsTable->item(i,2)->text(); const RideFile *ride = mainWindow->currentRide(); + QTreeWidgetItem *allIntervals = mainWindow->mutableIntervalItems(); QTreeWidgetItem *last = new IntervalItem(ride, name, start, stop, ride->timeToDistance(start), - ride->timeToDistance(stop)); - + ride->timeToDistance(stop), + allIntervals->childCount()+1); // add - QTreeWidgetItem *allIntervals = mainWindow->mutableIntervalItems(); allIntervals->addChild(last); } } diff --git a/src/IntervalItem.cpp b/src/IntervalItem.cpp index f8421bd1e..127061fc2 100644 --- a/src/IntervalItem.cpp +++ b/src/IntervalItem.cpp @@ -19,7 +19,7 @@ #include "IntervalItem.h" #include "RideFile.h" -IntervalItem::IntervalItem(const RideFile *ride, QString name, double start, double stop, double startKM, double stopKM) : ride(ride), start(start), stop(stop), startKM(startKM), stopKM(stopKM) +IntervalItem::IntervalItem(const RideFile *ride, QString name, double start, double stop, double startKM, double stopKM, int displaySequence) : ride(ride), start(start), stop(stop), startKM(startKM), stopKM(stopKM), displaySequence(displaySequence) { setText(0, name); } diff --git a/src/IntervalItem.h b/src/IntervalItem.h index 3f53661b1..25073e6c3 100644 --- a/src/IntervalItem.h +++ b/src/IntervalItem.h @@ -29,8 +29,10 @@ class IntervalItem : public QTreeWidgetItem const RideFile *ride; double start, stop; // by Time double startKM, stopKM; // by Distance + int displaySequence; - IntervalItem(const RideFile *, QString, double, double, double, double); + IntervalItem(const RideFile *, QString, double, double, double, double, int); + void setDisplaySequence(int seq) { displaySequence = seq; } }; #endif // _GC_IntervalItem_h diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 3406d9b6a..a26aac395 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -695,7 +695,10 @@ MainWindow::addIntervalForPowerPeaksForSecs(RideFile *ride, int windowSizeSecs, double watts = j.value(); QTreeWidgetItem *peak = new IntervalItem(ride, name+tr(" (%1 watts)").arg((int) round(watts)), - secs, secs+windowSizeSecs, ride->timeToDistance(secs), ride->timeToDistance(secs+windowSizeSecs)); + secs, secs+windowSizeSecs, + ride->timeToDistance(secs), + ride->timeToDistance(secs+windowSizeSecs), + allIntervals->childCount()+1); allIntervals->addChild(peak); } } @@ -766,7 +769,8 @@ MainWindow::rideTreeWidgetSelectionChanged() intervals.at(i).start, intervals.at(i).stop, selected->timeToDistance(intervals.at(i).start), - selected->timeToDistance(intervals.at(i).stop)); + selected->timeToDistance(intervals.at(i).stop), + allIntervals->childCount()+1); allIntervals->addChild(add); } } @@ -834,14 +838,22 @@ MainWindow::showContextMenuPopup(const QPoint &pos) QAction *actRenameInt = new QAction(tr("Rename interval"), intervalWidget); QAction *actDeleteInt = new QAction(tr("Delete interval"), intervalWidget); QAction *actZoomInt = new QAction(tr("Zoom to interval"), intervalWidget); + QAction *actFrontInt = new QAction(tr("Bring to Front"), intervalWidget); + QAction *actBackInt = new QAction(tr("Send to back"), intervalWidget); connect(actRenameInt, SIGNAL(triggered(void)), this, SLOT(renameInterval(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))); if (tabWidget->currentIndex() == 1) // on ride plot menu.addAction(actZoomInt); menu.addAction(actRenameInt); menu.addAction(actDeleteInt); + if (tabWidget->currentIndex() == 4 && activeInterval->isSelected()) { // on PfPv plot + menu.addAction(actFrontInt); + menu.addAction(actBackInt); + } menu.exec(intervalWidget->mapToGlobal( pos )); } } @@ -867,7 +879,17 @@ MainWindow::updateRideFileIntervals() } void -MainWindow::deleteInterval() { +MainWindow::deleteInterval() +{ + // renumber remaining + int oindex = activeInterval->displaySequence; + for (int i=0; ichildCount(); i++) { + IntervalItem *it = (IntervalItem *)allIntervals->child(i); + int ds = it->displaySequence; + if (ds > oindex) it->setDisplaySequence(ds-1); + } + + // now delete! int index = allIntervals->indexOfChild(activeInterval); delete allIntervals->takeChild(index); updateRideFileIntervals(); // will emit intervalChanged() signal @@ -892,6 +914,39 @@ MainWindow::zoomInterval() { allPlotWindow->zoomInterval(activeInterval); } +void +MainWindow::frontInterval() +{ + int oindex = activeInterval->displaySequence; + for (int i=0; ichildCount(); i++) { + IntervalItem *it = (IntervalItem *)allIntervals->child(i); + int ds = it->displaySequence; + if (ds > oindex) + it->setDisplaySequence(ds-1); + } + activeInterval->setDisplaySequence(allIntervals->childCount()); + + // signal! + intervalsChanged(); +} + +void +MainWindow::backInterval() +{ + int oindex = activeInterval->displaySequence; + for (int i=0; ichildCount(); i++) { + IntervalItem *it = (IntervalItem *)allIntervals->child(i); + int ds = it->displaySequence; + if (ds < oindex) + it->setDisplaySequence(ds+1); + } + activeInterval->setDisplaySequence(1); + + // signal! + intervalsChanged(); + +} + void MainWindow::intervalTreeWidgetSelectionChanged() { diff --git a/src/MainWindow.h b/src/MainWindow.h index 606a63231..12ae5fc49 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -126,6 +126,8 @@ class MainWindow : public QMainWindow void deleteInterval(); void renameInterval(); void zoomInterval(); + void frontInterval(); + void backInterval(); void intervalEdited(QTreeWidgetItem *, int); protected: diff --git a/src/PfPvPlot.cpp b/src/PfPvPlot.cpp index b2ed59e3a..04954a849 100644 --- a/src/PfPvPlot.cpp +++ b/src/PfPvPlot.cpp @@ -412,14 +412,8 @@ PfPvPlot::showIntervals(RideItem *_rideItem) RideFile *ride = rideItem->ride(); if (ride) { - // due to the discrete power and cadence values returned by the - // power meter, there will very likely be many duplicate values. - // Rather than pass them all to the curve, use a set to strip - // out duplicates. - std::set > dataSet; - std::set > dataSetSelected; - int num_intervals=intervalCount(); + if (mergeIntervals()) num_intervals = 1; QVector > > dataSetInterval(num_intervals); @@ -432,9 +426,17 @@ PfPvPlot::showIntervals(RideItem *_rideItem) double aepf = (p1->watts * 60.0) / (p1->cad * cl_ * 2.0 * PI); double cpv = (p1->cad * cl_ * 2.0 * PI) / 60.0; - int selection = isSelected(p1); - if (selection > -1) { - dataSetInterval[selection].insert(std::make_pair(aepf, cpv)); + for (int high=-1, t=0; tallIntervalItems()->childCount(); t++) { + IntervalItem *current = dynamic_cast(mainWindow->allIntervalItems()->child(t)); + if ((current != NULL) && current->isSelected()) { + ++high; + if (p1->secs>=current->start && p1->secs<=current->stop) { + if (mergeIntervals()) + dataSetInterval[0].insert(std::make_pair(aepf, cpv)); + else + dataSetInterval[high].insert(std::make_pair(aepf, cpv)); + } + } } tot_cad += p1->cad; tot_cad_points++; @@ -476,7 +478,25 @@ PfPvPlot::showIntervals(RideItem *_rideItem) } } - for (int z = 0; z < num_intervals; z ++) { + // honor display sequencing + QMap intervalOrder; + int count=0; + + if (mergeIntervals()) intervalOrder.insert(1,0); + else { + for (int i=0; iallIntervalItems()->childCount(); i++) { + IntervalItem *current = dynamic_cast(mainWindow->allIntervalItems()->child(i)); + if (current != NULL && current->isSelected() == true) { + intervalOrder.insert(current->displaySequence, count++); + } + } + } + + QMapIterator order(intervalOrder); + while (order.hasNext()) { + order.next(); + int z = order.value(); + QwtPlotCurve *curve; curve = new QwtPlotCurve(); @@ -599,24 +619,3 @@ PfPvPlot::setMergeIntervals(bool value) merge_intervals = value; showIntervals(rideItem); } - -int -PfPvPlot::isSelected(const RideFilePoint *p) { - int highlighted=-1; // Return -1 for point not in interval - if (mainWindow->allIntervalItems() != NULL) { - for (int i=0; iallIntervalItems()->childCount(); i++) { - IntervalItem *current = dynamic_cast(mainWindow->allIntervalItems()->child(i)); - if (current != NULL) { - if (current->isSelected()) { - ++highlighted; - if (p->secs>=current->start && p->secs<=current->stop) { - if (mergeIntervals()) - return 0; - return highlighted; - } - } - } - } - } - return -1; -} diff --git a/src/PfPvPlot.h b/src/PfPvPlot.h index 4aaf56370..0a85976d4 100644 --- a/src/PfPvPlot.h +++ b/src/PfPvPlot.h @@ -78,7 +78,6 @@ signals: QwtPlotMarker *mY; static QwtArray contour_xvalues; // values used in CP and contour plots: djconnel - int isSelected(const RideFilePoint *p); int cp_; int cad_; diff --git a/src/PfPvWindow.cpp b/src/PfPvWindow.cpp index 2d887db12..be369f14c 100644 --- a/src/PfPvWindow.cpp +++ b/src/PfPvWindow.cpp @@ -75,6 +75,7 @@ PfPvWindow::PfPvWindow(MainWindow *mainWindow) : this, SLOT(setMergeIntervalsPfPvFromCheckBox())); connect(mainWindow, SIGNAL(rideSelected()), this, SLOT(rideSelected())); connect(mainWindow, SIGNAL(intervalSelected()), this, SLOT(intervalSelected())); + connect(mainWindow, SIGNAL(intervalsChanged()), this, SLOT(intervalSelected())); connect(mainWindow, SIGNAL(zonesChanged()), this, SLOT(zonesChanged())); }