virtual void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &, const QRect &rect) const { RideItem *rideItem = parent->rideItem; if (! rideItem) return; const Zones *zones = rideItem->zones; int zone_range = rideItem->zoneRange(); if (parent->shadeZones() && (zone_range >= 0)) { QList <int> zone_lows = zones->getZoneLows(zone_range); int num_zones = zone_lows.size(); if (num_zones > 0) { for (int z = 0; z < num_zones; z ++) { QRect r = rect; QColor shading_color = zoneColor(z, num_zones); shading_color.setHsv( shading_color.hue(), shading_color.saturation() / 4, shading_color.value() ); r.setLeft(xMap.transform(zone_lows[z])); if (z + 1 < num_zones) r.setRight(xMap.transform(zone_lows[z + 1])); if (r.right() >= r.left()) painter->fillRect(r, shading_color); } } } }
void AllPlotWindow::redrawAllPlot() { if (!showStack->isChecked() && current) { RideItem *ride = current; int startidx, stopidx; if (fullPlot->bydist == true) { startidx =ride->ride()->distanceIndex((double)spanSlider->lowerValue()/(double)1000); stopidx = ride->ride()->distanceIndex((double)spanSlider->upperValue()/(double)1000); } else { startidx = ride->ride()->timeIndex(spanSlider->lowerValue()); stopidx = ride->ride()->timeIndex(spanSlider->upperValue()); } // need more than 1 sample to plot if (stopidx - startidx > 1) { allPlot->setDataFromPlot(fullPlot, startidx, stopidx); allZoomer->setZoomBase(); //allPlot->setTitle(""); allPlot->replot(); } } }
void PfPvWindow::rideSelected() { // we need to refresh for compare mode if (isCompare()) { if (isVisible() && compareStale) compareChanged(); return; } if (!amVisible()) { compareStale = true; return; } RideItem *ride = myRideItem; if (!ride || !ride->ride() || !ride->ride()->isDataPresent(RideFile::watts) || !ride->ride()->isDataPresent(RideFile::cad)) { setIsBlank(true); current = NULL; return; } else { setIsBlank(false); } if (!stale && ride == current) return; pfPvPlot->setData(ride); current = ride; stale = false; // update the QLabel widget with the CP value set in PfPvPlot::setData() qaCPValue->setText(QString("%1").arg(pfPvPlot->getCP())); }
void IntervalSummaryWindow::intervalHover(IntervalItem* x) { // if we're not visible don't bother if (!isVisible()) return; // we already have summaries! if (x && x->rideItem()->intervalsSelected().count()) return; // its to clear, but if the current ride has selected intervals then we will ignore it RideItem *rideItem = const_cast<RideItem*>(context->currentRideItem()); if (!x && rideItem && rideItem->intervalsSelected().count()) return; QString html = GCColor::css(); html += "<body>"; if (x == NULL) { html += "<i>" + tr("select an interval for summary info") + "</i>"; } else { html += summary(x); } html += "</body>"; setHtml(html); return; }
void AllPlotWindow::redrawFullPlot() { // always peformed sincethe data is used // by both the stack plots and the allplot RideItem *ride = current; // null rides are possible on new cyclist if (!ride) return; // hide the usual plot decorations etc fullPlot->setShowPower(1); //We now use the window background color //fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL)); fullPlot->setCanvasLineWidth(0); fullPlot->grid->enableY(false); fullPlot->enableAxis(QwtPlot::yLeft, false); fullPlot->enableAxis(QwtPlot::yLeft2, false); fullPlot->enableAxis(QwtPlot::yRight, false); fullPlot->enableAxis(QwtPlot::yRight2, false); fullPlot->enableAxis(QwtPlot::xBottom, false); //fullPlot->legend()->clear(); //fullPlot->setTitle(""); if (fullPlot->bydist) fullPlot->setAxisScale(QwtPlot::xBottom, ride->ride()->dataPoints().first()->km * (fullPlot->useMetricUnits ? 1 : MILES_PER_KM), ride->ride()->dataPoints().last()->km * (fullPlot->useMetricUnits ? 1 : MILES_PER_KM)); else fullPlot->setAxisScale(QwtPlot::xBottom, ride->ride()->dataPoints().first()->secs/60, ride->ride()->dataPoints().last()->secs/60); fullPlot->replot(); }
void IntervalSummaryWindow::intervalSelected() { // if no ride available don't bother - just reset for color changes RideItem *rideItem = const_cast<RideItem*>(context->currentRideItem()); if (context->athlete->intervalTreeWidget()->selectedItems().count() == 0 || rideItem == NULL || rideItem->ride() == NULL) { // no ride just update the colors QString html = GCColor::css(); html += "<body></body>"; setHtml(html); return; } QString html = GCColor::css(); html += "<body>"; if (context->athlete->allIntervalItems() != NULL) { for (int i=0; i<context->athlete->allIntervalItems()->childCount(); i++) { IntervalItem *current = dynamic_cast<IntervalItem*>(context->athlete->allIntervalItems()->child(i)); if (current != NULL) { if (current->isSelected()) { calcInterval(current, html); } } } } if (html == GCColor::css()+"<body>") { html += "<i>" + tr("select an interval for summary info") + "</i>"; } html += "</body>"; setHtml(html); return; }
PfPvPlotZoneLabel(PfPvPlot *_parent, int _zone_number) { parent = _parent; zone_number = _zone_number; RideItem *rideItem = parent->rideItem; const Zones *zones = rideItem->zones; int zone_range = rideItem->zoneRange(); setZ(1.0 + zone_number / 100.0); // create new zone labels if we're shading if (zone_range >= 0) { // retrieve zone setup QList <int> zone_lows = zones->getZoneLows(zone_range); QList <QString> zone_names = zones->getZoneNames(zone_range); int num_zones = zone_lows.size(); assert(zone_names.size() == num_zones); if (zone_number < num_zones) { watts = ((zone_number + 1 < num_zones) ? 0.5 * (zone_lows[zone_number] + zone_lows[zone_number + 1]) : ( (zone_number > 0) ? (1.5 * zone_lows[zone_number] - 0.5 * zone_lows[zone_number - 1]) : 2.0 * zone_lows[zone_number])); text = QwtText(zone_names[zone_number]); text.setFont(QFont("Helvetica",24, QFont::Bold)); QColor text_color = zoneColor(zone_number, num_zones); text_color.setAlpha(64); text.setColor(text_color); } } }
void IntervalSummaryWindow::intervalSelected() { // if no ride available don't bother - just reset for color changes RideItem *rideItem = const_cast<RideItem*>(context->currentRideItem()); if (rideItem->intervalsSelected().count() == 0 || rideItem == NULL || rideItem->ride() == NULL) { // no ride just update the colors QString html = GCColor::css(); html += "<body></body>"; setHtml(html); return; } // summary is html QString html = GCColor::css(); html += "<body>"; // summarise all the intervals selected - this is painful! //if (rideItem->intervalsSelected().count()>1) summarise(rideItem->intervalsSelected(), html); // summary for each of the currently selected intervals foreach(IntervalItem *interval, rideItem->intervalsSelected()) html += summary(interval); if (html == GCColor::css()+"<body>") html += "<i>" + tr("select an interval for summary info") + "</i>"; html += "</body>"; setHtml(html); return; }
PfPvPlotZoneLabel(PfPvPlot *_parent, int _zone_number) { parent = _parent; RideItem *rideItem = parent->rideItem; zone_number = _zone_number; // get zone data from ride or athlete ... const Zones *zones; int zone_range = -1; if (parent->context->isCompareIntervals) { zones = parent->context->athlete->zones(); if (!zones) return; // use first compare interval date if (parent->context->compareIntervals.count()) zone_range = zones->whichRange(parent->context->compareIntervals[0].data->startTime().date()); // still not set if (zone_range == -1) zone_range = zones->whichRange(QDate::currentDate()); } else if (rideItem) { zones = rideItem->zones; zone_range = rideItem->zoneRange(); } else { return; // nulls } setZ(1.0 + zone_number / 100.0); // create new zone labels if we're shading if (zone_range >= 0) { // retrieve zone setup QList <int> zone_lows = zones->getZoneLows(zone_range); QList <QString> zone_names = zones->getZoneNames(zone_range); int num_zones = zone_lows.size(); if(zone_names.size() != num_zones) return; if (zone_number < num_zones) { watts = ((zone_number + 1 < num_zones) ? 0.5 * (zone_lows[zone_number] + zone_lows[zone_number + 1]) : ( (zone_number > 0) ? (1.5 * zone_lows[zone_number] - 0.5 * zone_lows[zone_number - 1]) : 2.0 * zone_lows[zone_number])); text = QwtText(zone_names[zone_number]); text.setFont(QFont("Helvetica",24, QFont::Bold)); QColor text_color = zoneColor(zone_number, num_zones); text_color.setAlpha(64); text.setColor(text_color); } } }
void RideWindow::rideSelected() { // skip display if data drawn or invalid if (myRideItem == NULL || !amVisible()) return; RideItem * r = myRideItem; if (ride == r || !r || !r->ride()) return; else ride = r; loadRide(); }
void HrPwWindow::rideSelected() { if (!amVisible()) return; RideItem *ride = myRideItem; if (!ride || !ride->ride()) return; setData(ride); }
void HrPwWindow::rideSelected() { if (!amVisible()) return; RideItem *ride = myRideItem; if (!ride || !ride->ride() || !ride->ride()->isDataPresent(RideFile::watts) || !ride->ride()->isDataPresent(RideFile::hr)) setIsBlank(true); else { setIsBlank(false); setData(ride); } }
void AllPlotWindow::rideSelected() { RideItem *ride = mainWindow->rideItem(); // ignore if not active if (mainWindow->activeTab() != this) { stale = true; return; } // ignore if null, or manual / empty if (!ride || !ride->ride() || !ride->ride()->dataPoints().count()) return; // we already plotted it! if (ride == current && stale == false) return; // ok, its now the current ride current = ride; // clear any previous selections clearSelection(); // setup the control widgets, dependant on // data present in this ride, needs to happen // before we set the plots below... setAllPlotWidgets(ride); // setup the charts to reflect current ride selection fullPlot->setDataFromRide(ride); allPlot->setDataFromPlot(fullPlot, ride->ride()->timeIndex(spanSlider->lowerValue()), ride->ride()->timeIndex(spanSlider->upperValue())); // redraw all the plots, they will check // to see if they are currently visible // and only redraw if neccessary redrawFullPlot(); redrawAllPlot(); setupStackPlots(); stale = false; }
void AllPlotWindow::rideSelected() { RideItem *ride = myRideItem; if (ride == NULL) current = NULL; // ignore if not active if (!amVisible()) { stale = true; return; } // ignore if null, or manual / empty if (!ride || !ride->ride() || !ride->ride()->dataPoints().count()) { current = NULL; return; } // we already plotted it! if (ride == current && stale == false) return; // ok, its now the current ride current = ride; // clear any previous selections clearSelection(); // setup the control widgets, dependant on // data present in this ride, needs to happen // before we set the plots below... setAllPlotWidgets(ride); // setup the charts to reflect current ride selection fullPlot->setDataFromRide(ride); // Fixup supplied by Josef Gebel int startidx, stopidx; if ( fullPlot->bydist == true ) { startidx = ride->ride()->distanceIndex( ( double ) spanSlider->lowerValue() / 1000.0 ); stopidx = ride->ride()->distanceIndex( ( double ) spanSlider->upperValue() / 1000.0 ); } else { startidx = ride->ride()->timeIndex( spanSlider->lowerValue() ); stopidx = ride->ride()->timeIndex( spanSlider->upperValue() ); } allPlot->setDataFromPlot( fullPlot, startidx, stopidx ); // redraw all the plots, they will check // to see if they are currently visible // and only redraw if neccessary redrawFullPlot(); redrawAllPlot(); setupStackPlots(); stale = false; }
void Athlete::updateRideFileIntervals() { // iterate over context->athlete->allIntervals as they are now defined // and update the RideFile->intervals RideItem *which = (RideItem *)treeWidget->selectedItems().first(); RideFile *current = which->ride(); current->clearIntervals(); for (int i=0; i < allIntervals->childCount(); i++) { // add the intervals as updated IntervalItem *it = (IntervalItem *)allIntervals->child(i); current->addInterval(it->start, it->stop, it->text(0)); } // emit signal for interval data changed context->notifyIntervalsChanged(); // set dirty which->setDirty(true); }
void AllPlotWindow::configChanged() { fullPlot->setCanvasBackground(GColor(CPLOTTHUMBNAIL)); // we're going to replot, but only if we're active // and all the other guff RideItem *ride = mainWindow->rideItem(); if (mainWindow->activeTab() != this) { stale = true; return; } // ignore if null, or manual / empty if (!ride || !ride->ride() || !ride->ride()->dataPoints().count()) return; // ok replot with the new config! redrawFullPlot(); redrawAllPlot(); redrawStackPlot(); }
void IntervalSidebar::showRouteMenu(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 Rides")) { QMenu menu(context->athlete->treeWidget); // ride navigator stuff QAction *colChooser = new QAction(tr("Show Column Chooser"), context->athlete->treeWidget); connect(colChooser, SIGNAL(triggered(void)), routeNavigator, SLOT(showColumnChooser())); menu.addAction(colChooser); /*if (routeNavigator->groupBy() >= 0) { // already grouped lets ungroup QAction *nogroups = new QAction(tr("Do Not Show In Groups"), context->athlete->treeWidget); connect(nogroups, SIGNAL(triggered(void)), routeNavigator, SLOT(noGroups())); menu.addAction(nogroups); } else { QMenu *groupByMenu = new QMenu(tr("Group"), context->athlete->treeWidget); groupByMenu->setEnabled(true); menu.addMenu(groupByMenu); connect(groupByMenu, SIGNAL(triggered()), routeNavigator, SLOT(setGroupByColumnName())); }*/ // expand / collapse QAction *expandAll = new QAction(tr("Expand All"), context->athlete->treeWidget); connect(expandAll, SIGNAL(triggered(void)), routeNavigator->tableView, SLOT(expandAll())); menu.addAction(expandAll); // expand / collapse QAction *collapseAll = new QAction(tr("Collapse All"), context->athlete->treeWidget); connect(collapseAll, SIGNAL(triggered(void)), routeNavigator->tableView, SLOT(collapseAll())); menu.addAction(collapseAll); menu.exec(pos); }
//---------------------------------------------------------------------- // Check if data needs saving on exit and prompt user for action //---------------------------------------------------------------------- bool MainWindow::saveRideExitDialog() { QList<RideItem*> dirtyList; // have we been told to not warn on exit? if (warnExit() == false) return true; // just close regardless! for (int i=0; i<allRides->childCount(); i++) { RideItem *curr = (RideItem *)allRides->child(i); if (curr->isDirty() == true) dirtyList.append(curr); } // we have some files to save... if (dirtyList.count() > 0) { SaveOnExitDialogWidget dialog(this, dirtyList); int result = dialog.exec(); if (result == QDialog::Rejected) return false; // cancel that closeEvent! } // You can exit and close now return true; }