/* * Copyright (c) 2009 Sean C. Rhea (srhea@srhea.net) * * 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 "MainWindow.h" #include "AllPlotWindow.h" #include "AllPlot.h" #include "MainWindow.h" #include "RideFile.h" #include "RideItem.h" #include "IntervalItem.h" #include "TimeUtils.h" #include "Settings.h" #include "Units.h" // for MILES_PER_KM #include #include #include #include #include AllPlotWindow::AllPlotWindow(MainWindow *mainWindow) : QWidget(mainWindow), mainWindow(mainWindow) { QVBoxLayout *vlayout = new QVBoxLayout; QHBoxLayout *showLayout = new QHBoxLayout; QLabel *showLabel = new QLabel(tr("Show:"), this); showLayout->addWidget(showLabel); showStack = new QCheckBox(tr("Stacked view"), this); showStack->setCheckState(Qt::Unchecked); showLayout->addWidget(showStack); stackWidth = 15; QCheckBox *showGrid = new QCheckBox(tr("Grid"), this); showGrid->setCheckState(Qt::Checked); showLayout->addWidget(showGrid); showHr = new QCheckBox(tr("Heart Rate"), this); showHr->setCheckState(Qt::Checked); showLayout->addWidget(showHr); showSpeed = new QCheckBox(tr("Speed"), this); showSpeed->setCheckState(Qt::Checked); showLayout->addWidget(showSpeed); showCad = new QCheckBox(tr("Cadence"), this); showCad->setCheckState(Qt::Checked); showLayout->addWidget(showCad); showAlt = new QCheckBox(tr("Altitude"), this); showAlt->setCheckState(Qt::Checked); showLayout->addWidget(showAlt); showPower = new QComboBox(); showPower->addItem(tr("Power + shade")); showPower->addItem(tr("Power - shade")); showPower->addItem(tr("No Power")); showLayout->addWidget(showPower); QHBoxLayout *smoothLayout = new QHBoxLayout; QComboBox *comboDistance = new QComboBox(); comboDistance->addItem(tr("X Axis Shows Time")); comboDistance->addItem(tr("X Axis Shows Distance")); smoothLayout->addWidget(comboDistance); QLabel *smoothLabel = new QLabel(tr("Smoothing (secs)"), this); smoothLineEdit = new QLineEdit(this); smoothLineEdit->setFixedWidth(40); smoothLayout->addWidget(smoothLabel); smoothLayout->addWidget(smoothLineEdit); smoothSlider = new QSlider(Qt::Horizontal); smoothSlider->setTickPosition(QSlider::TicksBelow); smoothSlider->setTickInterval(10); smoothSlider->setMinimum(2); smoothSlider->setMaximum(600); smoothLineEdit->setValidator(new QIntValidator(smoothSlider->minimum(), smoothSlider->maximum(), smoothLineEdit)); smoothLayout->addWidget(smoothSlider); allPlot = new AllPlot(this, mainWindow); smoothSlider->setValue(allPlot->smoothing()); smoothLineEdit->setText(QString("%1").arg(allPlot->smoothing())); allZoomer = new QwtPlotZoomer(allPlot->canvas()); allZoomer->setRubberBand(QwtPicker::RectRubberBand); allZoomer->setRubberBandPen(QColor(Qt::black)); allZoomer->setSelectionFlags(QwtPicker::DragSelection | QwtPicker::CornerToCorner); allZoomer->setTrackerMode(QwtPicker::AlwaysOff); allZoomer->setEnabled(true); // TODO: Hack for OS X one-button mouse // allZoomer->initMousePattern(1); // RightButton: zoom out by 1 // Ctrl+RightButton: zoom out to full size allZoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); allZoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); allPanner = new QwtPlotPanner(allPlot->canvas()); allPanner->setMouseButton(Qt::MidButton); // TODO: zoomer doesn't interact well with automatic axis resizing // Interval selection allPicker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::RectSelection | QwtPicker::CornerToCorner|QwtPicker::DragSelection, QwtPicker::VLineRubberBand, QwtPicker::ActiveOnly, allPlot->canvas()); allPicker->setRubberBandPen(QColor(Qt::blue)); allPicker->setRubberBand(QwtPicker::CrossRubberBand); allPicker->setTrackerPen(QColor(Qt::blue)); // now select rectangles allPicker->setSelectionFlags(QwtPicker::PointSelection | QwtPicker::RectSelection | QwtPicker::DragSelection); allPicker->setRubberBand(QwtPicker::VLineRubberBand); allPicker->setMousePattern(QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier); connect(allPicker, SIGNAL(moved(const QPoint &)), SLOT(plotPickerMoved(const QPoint &))); connect(allPicker, SIGNAL(appended(const QPoint &)), SLOT(plotPickerSelected(const QPoint &))); QwtPlotMarker* allMarker1 = new QwtPlotMarker(); allMarker1->setLineStyle(QwtPlotMarker::VLine); allMarker1->attach(allPlot); allMarker1->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); allPlot->allMarker1=allMarker1; QwtPlotMarker* allMarker2 = new QwtPlotMarker(); allMarker2->setLineStyle(QwtPlotMarker::VLine); allMarker2->attach(allPlot); allMarker2->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); allPlot->allMarker2=allMarker2; QwtPlotMarker* allMarker3 = new QwtPlotMarker(); allMarker3->setLineStyle(QwtPlotMarker::VLine); allMarker3->attach(allPlot); allPlot->allMarker3=allMarker3; stackFrame = new QScrollArea(); stackFrame->hide(); vlayout->addWidget(allPlot); vlayout->addWidget(stackFrame); vlayout->addLayout(showLayout); vlayout->addLayout(smoothLayout); setLayout(vlayout); connect(showPower, SIGNAL(currentIndexChanged(int)), this, SLOT(setShowPower(int))); connect(showHr, SIGNAL(stateChanged(int)), this, SLOT(setShowHr(int))); connect(showSpeed, SIGNAL(stateChanged(int)), this, SLOT(setShowSpeed(int))); connect(showCad, SIGNAL(stateChanged(int)), this, SLOT(setShowCad(int))); connect(showAlt, SIGNAL(stateChanged(int)), this, SLOT(setShowAlt(int))); connect(showGrid, SIGNAL(stateChanged(int)), this, SLOT(setShowGrid(int))); connect(showStack, SIGNAL(stateChanged(int)), this, SLOT(setShowStack(int))); connect(comboDistance, SIGNAL(currentIndexChanged(int)), this, SLOT(setByDistance(int))); connect(smoothSlider, SIGNAL(valueChanged(int)), this, SLOT(setSmoothingFromSlider())); connect(smoothLineEdit, SIGNAL(editingFinished()), this, SLOT(setSmoothingFromLineEdit())); connect(mainWindow, SIGNAL(rideSelected()), this, SLOT(rideSelected())); connect(mainWindow, SIGNAL(zonesChanged()), this, SLOT(zonesChanged())); connect(mainWindow, SIGNAL(intervalsChanged()), this, SLOT(intervalsChanged())); connect(mainWindow, SIGNAL(intervalSelected()), this, SLOT(intervalSelected())); } void AllPlotWindow::rideSelected() { RideItem *ride = mainWindow->rideItem(); if (!ride) return; clearSelection(); // clear any ride interval selection data setAllPlotWidgets(ride); allPlot->setDataI(ride); allZoomer->setZoomBase(); // update stacked view if that is set int showit = showStack->isChecked(); setShowStack(0); // zap whats there setShowStack(showit); } void AllPlotWindow::zonesChanged() { allPlot->refreshZoneLabels(); allPlot->replot(); } void AllPlotWindow::intervalsChanged() { allPlot->refreshIntervalMarkers(); allPlot->replot(); foreach (AllPlot *plot, allPlots) { plot->refreshIntervalMarkers(); plot->replot(); } } void AllPlotWindow::intervalSelected() { hideSelection(); } void AllPlotWindow::setSmoothingFromSlider() { if (allPlot->smoothing() != smoothSlider->value()) { setSmoothing(smoothSlider->value()); smoothLineEdit->setText(QString("%1").arg(allPlot->smoothing())); } } void AllPlotWindow::setSmoothingFromLineEdit() { int value = smoothLineEdit->text().toInt(); if (value != allPlot->smoothing()) { setSmoothing(value); smoothSlider->setValue(value); } } void AllPlotWindow::setAllPlotWidgets(RideItem *ride) { if (ride->ride() && ride->ride()->deviceType() != QString("Manual CSV")) { const RideFileDataPresent *dataPresent = ride->ride()->areDataPresent(); showPower->setEnabled(dataPresent->watts); showHr->setEnabled(dataPresent->hr); showSpeed->setEnabled(dataPresent->kph); showCad->setEnabled(dataPresent->cad); showAlt->setEnabled(dataPresent->alt); } else { showPower->setEnabled(false); showHr->setEnabled(false); showSpeed->setEnabled(false); showCad->setEnabled(false); showAlt->setEnabled(false); } } void AllPlotWindow::zoomInterval(IntervalItem *which) { QwtDoubleRect rect; if (!allPlot->byDistance()) { rect.setLeft(which->start/60); rect.setRight(which->stop/60); } else { rect.setLeft(which->startKM); rect.setRight(which->stopKM); } rect.setTop(allPlot->wattsCurve->maxYValue()*1.1); rect.setBottom(0); allZoomer->zoom(rect); } void AllPlotWindow::plotPickerSelected(const QPoint &pos) { QwtPlotPicker* pick = qobject_cast(sender()); AllPlot* plot = qobject_cast(pick->plot()); // set start of selection in xunits (minutes assumed for now) setStartSelection(plot, pos.x()); } void AllPlotWindow::plotPickerMoved(const QPoint &pos) { QString name = QString("Selection #%1 ").arg(selection); QwtPlotPicker* pick = qobject_cast(sender()); AllPlot* plot = qobject_cast(pick->plot()); if (allPlots.length()>0) { int posX = pos.x(); int posY = plot->y()+pos.y()+50; foreach (AllPlot *_plot, allPlots) { _plot->allMarker1->setValue(plot->allMarker1->value()); if (_plot->y()<=plot->y() && posY<_plot->y()){ if (_plot->transform(QwtPlot::xBottom, _plot->allMarker2->xValue())>0){ setEndSelection(_plot, 0, false, name); _plot->allMarker2->setLabel(QString("")); } } else if (_plot->y()>=plot->y() && posY>_plot->y()+_plot->height()){ if (_plot->transform(QwtPlot::xBottom, _plot->allMarker2->xValue())width()){ setEndSelection(_plot, plot->width(), false, name); } } else if (posY>_plot->y() && posY<_plot->y()+_plot->height()){ if (pos.x()<6) posX = 6; else if (!_plot->byDistance() && pos.x()>_plot->transform(QwtPlot::xBottom, _plot->timeArray[_plot->timeArray.size()-1])) posX = _plot->transform(QwtPlot::xBottom, _plot->timeArray[_plot->timeArray.size()-1]); else if (plot->byDistance() && pos.x()>_plot->transform(QwtPlot::xBottom, _plot->distanceArray[_plot->distanceArray.size()-1])) posX = _plot->transform(QwtPlot::xBottom, _plot->distanceArray[_plot->distanceArray.size()-1]); setEndSelection(_plot, posX, true, name); if (plot->y()<_plot->y()) { plot->allMarker1->setLabel(_plot->allMarker1->label()); plot->allMarker2->setLabel(_plot->allMarker2->label()); } } else {//if (_plot->y()height() || _plot->y()y()+3*plot->height()) //hide plot for 3 next plots _plot->allMarker1->hide(); _plot->allMarker2->hide(); _plot->allMarker3->hide(); } } } else // set end of selection in xunits (minutes assumed for now) setEndSelection(plot, pos.x(), true, name); } void AllPlotWindow::setStartSelection(AllPlot* plot, int xPosition) { double xValue = plot->invTransform(QwtPlot::xBottom, xPosition); QwtPlotMarker* allMarker1 = plot->allMarker1; selection++; if (!allMarker1->isVisible() || allMarker1->xValue() != xValue) { hideSelection(); allMarker1->setValue(xValue, plot->byDistance() ? 0 : 100); allMarker1->show(); } } void AllPlotWindow::setEndSelection(AllPlot* plot, int xPosition, bool newInterval, QString name) { double xValue = plot->invTransform(QwtPlot::xBottom, xPosition); QwtPlotMarker* allMarker1 = plot->allMarker1; QwtPlotMarker* allMarker2 = plot->allMarker2; QwtPlotMarker* allMarker3 = plot->allMarker3; bool useMetricUnits = plot->useMetricUnits; if (!allMarker2->isVisible() || allMarker2->xValue() != xValue) { allMarker2->setValue(xValue, plot->byDistance() ? 0 : 100); allMarker2->show(); double x1, x2; // time or distance depending upon mode selected // swap to low-high if neccessary if (allMarker1->xValue()>allMarker2->xValue()){ x2 = allMarker1->xValue(); x1 = allMarker2->xValue(); } else { x1 = allMarker1->xValue(); x2 = allMarker2->xValue(); } double lwidth=plot->transform(QwtPlot::xBottom, x2)-plot->transform(QwtPlot::xBottom, x1); allMarker3->setValue((x2-x1)/2+x1, 100); QColor marker_color = QColor(Qt::blue); marker_color.setAlpha(64); allMarker3->setLinePen(QPen(QBrush(marker_color), lwidth, Qt::SolidLine)) ; //allMarker3->setZ(-1000.0); allMarker3->show(); RideFile tmpRide = RideFile(); QTreeWidgetItem *which = mainWindow->rideItem(); RideItem *ride = (RideItem*)which; double distance1 = -1; double distance2 = -1; double duration1 = -1; double duration2 = -1; double secsMoving = 0; double wattsTotal = 0; double bpmTotal = 0; int arrayLength = 0; // if we are in distance mode then x1 and x2 are distances // we need to make sure they are in KM for the rest of this // code. if (plot->byDistance() && useMetricUnits == false) { x1 *= KM_PER_MILE; x2 *= KM_PER_MILE; } foreach (const RideFilePoint *point, ride->ride()->dataPoints()) { if ((plot->byDistance()==true && point->km>=x1 && point->kmbyDistance()==false && point->secs/60>=x1 && point->secs/60km; distance2 = point->km; if (duration1 == -1) duration1 = point->secs; duration2 = point->secs; if (point->kph > 0.0) secsMoving += ride->ride()->recIntSecs(); wattsTotal += point->watts; bpmTotal += point->hr; ++arrayLength; } } QString s("\n%1%2 %3 %4\n%5%6 %7%8 %9%10"); s = s.arg(useMetricUnits ? distance2-distance1 : (distance2-distance1)*MILES_PER_KM, 0, 'f', 1); s = s.arg((useMetricUnits? "km":"m")); s = s.arg(time_to_string(duration2-duration1)); if (duration2-duration1-secsMoving>1) s = s.arg("("+time_to_string(secsMoving)+")"); else s = s.arg(""); s = s.arg((useMetricUnits ? 1 : MILES_PER_KM) * (distance2-distance1)/secsMoving*3600, 0, 'f', 1); s = s.arg((useMetricUnits? "km/h":"m/h")); if (wattsTotal>0) { s = s.arg(wattsTotal/arrayLength, 0, 'f', 1); s = s.arg("W"); } else{ s = s.arg(""); s = s.arg(""); } if (bpmTotal>0) { s = s.arg(bpmTotal/arrayLength, 0, 'f', 0); s = s.arg("bpm"); } else { s = s.arg(""); s = s.arg(""); } if (allMarker1->xValue()xValue()) { allMarker1->setLabel(s); allMarker2->setLabel(QString("")); } else { allMarker2->setLabel(s); allMarker1->setLabel(QString("")); } if (newInterval) { QTreeWidgetItem *allIntervals = mainWindow->mutableIntervalItems(); int count = allIntervals->childCount(); // are we adjusting an existing interval? - if so delete it and readd it if (count > 0) { IntervalItem *bottom = (IntervalItem *) allIntervals->child(count-1); if (bottom->text(0).startsWith(name)) delete allIntervals->takeChild(count-1); } // 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, allIntervals->childCount()+1); allIntervals->addChild(last); // now update the RideFileIntervals and all the plots etc mainWindow->updateRideFileIntervals(); } } } void AllPlotWindow::clearSelection() { selection = 0; hideSelection(); } void AllPlotWindow::hideSelection() { allPlot->allMarker1->setVisible(false); allPlot->allMarker2->setVisible(false); allPlot->allMarker3->setVisible(false); allPlot->replot(); foreach (AllPlot *plot, allPlots) { plot->allMarker1->setVisible(false); plot->allMarker2->setVisible(false); plot->allMarker3->setVisible(false); plot->replot(); } } void AllPlotWindow::setShowPower(int value) { allPlot->showPower(value); if (allPlots.count()>0) resetStackedDatas(); } void AllPlotWindow::setShowHr(int value) { allPlot->showHr(value); foreach (AllPlot *plot, allPlots) plot->showHr(value); } void AllPlotWindow::setShowSpeed(int value) { allPlot->showSpeed(value); foreach (AllPlot *plot, allPlots) plot->showSpeed(value); } void AllPlotWindow::setShowCad(int value) { allPlot->showCad(value); foreach (AllPlot *plot, allPlots) plot->showCad(value); } void AllPlotWindow::setShowAlt(int value) { allPlot->showAlt(value); foreach (AllPlot *plot, allPlots) plot->showAlt(value); } void AllPlotWindow::setShowGrid(int value) { allPlot->showGrid(value); foreach (AllPlot *plot, allPlots) plot->showGrid(value); } void AllPlotWindow::setByDistance(int value) { allPlot->setByDistance(value); if (allPlots.count()>0) { setShowStack(false); setShowStack(true); } } void AllPlotWindow::setSmoothing(int value) { allPlot->setSmoothing(value); if (allPlots.count()>0) resetStackedDatas(); } void AllPlotWindow::resetStackedDatas() { int _stackWidth = stackWidth; if (allPlot->byDistance()) _stackWidth = stackWidth/3; for(int i = 0 ; i < allPlots.count() ; i++) { AllPlot *plot = allPlots[i]; int startIndex, stopIndex; if (plot->byDistance()) { startIndex = allPlot->rideItem->ride()->distanceIndex((allPlot->useMetricUnits ? 1 : KM_PER_MILE) * _stackWidth*i); stopIndex = allPlot->rideItem->ride()->distanceIndex((allPlot->useMetricUnits ? 1 : KM_PER_MILE) * _stackWidth*(i+1)); } else { startIndex = allPlot->rideItem->ride()->timeIndex(60*_stackWidth*i); stopIndex = allPlot->rideItem->ride()->timeIndex(60*_stackWidth*(i+1)); } // Update AllPlot for stacked view plot->setDataP(allPlot, startIndex, stopIndex); } } void AllPlotWindow::setShowStack(int value) { if (value) { int _stackWidth = stackWidth; if (allPlot->byDistance()) _stackWidth = stackWidth/3; allPlot->hide(); QVBoxLayout *vLayout = new QVBoxLayout(); RideItem* rideItem = allPlot->rideItem; double duration = rideItem->ride()->dataPoints().last()->secs; double distance = (allPlot->useMetricUnits ? 1 : MILES_PER_KM) * rideItem->ride()->dataPoints().last()->km; int nbplot; if (allPlot->byDistance()) nbplot = (int)floor(distance/_stackWidth)+1; else nbplot = (int)floor(duration/_stackWidth/60)+1; for(int i = 0 ; i < nbplot ; i++) { AllPlot *_allPlot = new AllPlot(this, mainWindow); allPlots.append(_allPlot); addPickers(_allPlot); int startIndex, stopIndex; if (allPlot->byDistance()) { startIndex = allPlot->rideItem->ride()->distanceIndex((allPlot->useMetricUnits ? 1 : KM_PER_MILE) * _stackWidth*i); stopIndex = allPlot->rideItem->ride()->distanceIndex((allPlot->useMetricUnits ? 1 : KM_PER_MILE) * _stackWidth*(i+1)); } else { startIndex = allPlot->rideItem->ride()->timeIndex(60*_stackWidth*i); stopIndex = allPlot->rideItem->ride()->timeIndex(60*_stackWidth*(i+1)); } vLayout->addWidget(_allPlot); // Update AllPlot for stacked view _allPlot->setDataP(allPlot, startIndex, stopIndex); _allPlot->setAxisScale(QwtPlot::xBottom, _stackWidth*i, _stackWidth*(i+1), 1); if (i==0){ // First plot view title and legend _allPlot->setTitle(allPlot->title()); _allPlot->plotLayout()->setLegendPosition(QwtPlot::TopLegend); _allPlot->setFixedHeight(200); } else { _allPlot->setTitle(""); _allPlot->insertLegend(NULL); _allPlot->setFixedHeight(150); } // No x axis titles _allPlot->setAxisTitle(QwtPlot::xBottom,NULL); // Smaller y axis Titles QFont axisFont = QFont("Helvetica",10, QFont::Normal); QwtText text = _allPlot->axisTitle(QwtPlot::yLeft); text.setFont(axisFont); _allPlot->setAxisTitle(QwtPlot::yLeft,text); text = _allPlot->axisTitle(QwtPlot::yLeft2); text.setFont(axisFont); _allPlot->setAxisTitle(QwtPlot::yLeft2,text); text = _allPlot->axisTitle(QwtPlot::yRight); text.setFont(axisFont); _allPlot->setAxisTitle(QwtPlot::yRight,text); text = _allPlot->axisTitle(QwtPlot::yRight2); text.setFont(axisFont); _allPlot->setAxisTitle(QwtPlot::yRight2,text); } QWidget *stack = new QWidget(); stack->setLayout(vLayout); stackFrame->setWidgetResizable(true); stackFrame->setWidget(stack); stackFrame->show(); } else { stackFrame->hide(); allPlot->show(); if (allPlots.count()>1) { foreach (AllPlot *plot, allPlots) { //layout()->removeWidget(plot); delete plot; allPlots.removeOne(plot); } } } } void AllPlotWindow::addPickers(AllPlot *_allPlot) { QwtPlotMarker* allMarker1 = new QwtPlotMarker(); allMarker1->setLineStyle(QwtPlotMarker::VLine); allMarker1->attach(_allPlot); allMarker1->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); _allPlot->allMarker1 = allMarker1; QwtPlotMarker* allMarker2 = new QwtPlotMarker(); allMarker2->setLineStyle(QwtPlotMarker::VLine); allMarker2->attach(_allPlot); allMarker2->setLabelAlignment(Qt::AlignTop|Qt::AlignRight); _allPlot->allMarker2 = allMarker2; QwtPlotMarker* allMarker3 = new QwtPlotMarker(); allMarker3->setLineStyle(QwtPlotMarker::VLine); allMarker3->attach(_allPlot); _allPlot->allMarker3 = allMarker3; // Interval selection 2 QwtPlotPicker* allPicker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft, QwtPicker::RectSelection | QwtPicker::CornerToCorner|QwtPicker::DragSelection, QwtPicker::NoRubberBand, QwtPicker::ActiveOnly, _allPlot->canvas()); allPickers.append(allPicker); allPicker->setRubberBandPen(QColor(Qt::blue)); allPicker->setRubberBand(QwtPicker::NoRubberBand); allPicker->setTrackerPen(QColor(Qt::blue)); // now select rectangles allPicker->setSelectionFlags(QwtPicker::PointSelection | QwtPicker::RectSelection | QwtPicker::DragSelection); allPicker->setMousePattern(QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ShiftModifier); //void appended(const QwtPlotPicker* pick, const QwtDoublePoint &pos); connect(allPicker, SIGNAL(appended(const QPoint &)), SLOT(plotPickerSelected(const QPoint &))); connect(allPicker, SIGNAL(moved(const QPoint &)), SLOT(plotPickerMoved(const QPoint &))); }