/* * Copyright (c) 2010 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 "LTMTool.h" #include "MainWindow.h" #include "Settings.h" #include "Units.h" #include #include #include // seasons support #include "Season.h" #include "SeasonParser.h" #include #include LTMTool::LTMTool(MainWindow *parent, const QDir &home) : QWidget(parent), home(home), main(parent) { // get application settings boost::shared_ptr appsettings = GetApplicationSettings(); useMetricUnits = appsettings->value(GC_UNIT).toString() == "Metric"; QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0,0,0,0); dateRangeTree = new QTreeWidget; dateRangeTree->setColumnCount(1); dateRangeTree->setSelectionMode(QAbstractItemView::SingleSelection); dateRangeTree->header()->hide(); dateRangeTree->setAlternatingRowColors (true); dateRangeTree->setIndentation(5); allDateRanges = new QTreeWidgetItem(dateRangeTree, ROOT_TYPE); allDateRanges->setText(0, tr("Date Range")); readSeasons(); dateRangeTree->expandItem(allDateRanges); dateRangeTree->setContextMenuPolicy(Qt::CustomContextMenu); metricTree = new QTreeWidget; metricTree->setColumnCount(1); metricTree->setSelectionMode(QAbstractItemView::ExtendedSelection); metricTree->header()->hide(); metricTree->setAlternatingRowColors (true); metricTree->setIndentation(5); allMetrics = new QTreeWidgetItem(metricTree, ROOT_TYPE); allMetrics->setText(0, tr("Metric")); metricTree->setContextMenuPolicy(Qt::CustomContextMenu); // initialise the metrics catalogue and user selector const RideMetricFactory &factory = RideMetricFactory::instance(); for (int i = 0; i < factory.metricCount(); ++i) { // metrics catalogue and settings MetricDetail adds; QColor cHSV; adds.symbol = factory.metricName(i); adds.metric = factory.rideMetric(factory.metricName(i)); qsrand(QTime::currentTime().msec()); cHSV.setHsv((i%6)*(255/(factory.metricCount()/5)), 255, 255); adds.penColor = cHSV.convertTo(QColor::Rgb); adds.curveStyle = curveStyle(factory.metricType(i)); adds.symbolStyle = symbolStyle(factory.metricType(i)); adds.smooth = false; adds.trend = false; adds.topN = 5; // show top 5 by default always QTextEdit processHTML(adds.metric->name()); // process html encoding of(TM) adds.name = processHTML.toPlainText(); // set default for the user overiddable fields adds.uname = adds.name; adds.uunits = adds.metric->units(useMetricUnits); // default units to metric name if it is blank if (adds.uunits == "") adds.uunits = adds.name; metrics.append(adds); } // // Add PM metrics, which are calculated over the metric dataset // // SKIBA LTS MetricDetail skibaLTS; skibaLTS.type = METRIC_PM; skibaLTS.symbol = "skiba_lts"; skibaLTS.metric = NULL; // not a factory metric skibaLTS.penColor = QColor(Qt::blue); skibaLTS.curveStyle = QwtPlotCurve::Lines; skibaLTS.symbolStyle = QwtSymbol::NoSymbol; skibaLTS.smooth = false; skibaLTS.trend = false; skibaLTS.topN = 5; skibaLTS.uname = skibaLTS.name = "Skiba Long Term Stress"; skibaLTS.uunits = "Stress"; metrics.append(skibaLTS); MetricDetail skibaSTS; skibaSTS.type = METRIC_PM; skibaSTS.symbol = "skiba_sts"; skibaSTS.metric = NULL; // not a factory metric skibaSTS.penColor = QColor(Qt::magenta); skibaSTS.curveStyle = QwtPlotCurve::Lines; skibaSTS.symbolStyle = QwtSymbol::NoSymbol; skibaSTS.smooth = false; skibaSTS.trend = false; skibaSTS.topN = 5; skibaSTS.uname = skibaSTS.name = "Skiba Short Term Stress"; skibaSTS.uunits = "Stress"; metrics.append(skibaSTS); MetricDetail skibaSB; skibaSB.type = METRIC_PM; skibaSB.symbol = "skiba_sb"; skibaSB.metric = NULL; // not a factory metric skibaSB.penColor = QColor(Qt::yellow); skibaSB.curveStyle = QwtPlotCurve::Steps; skibaSB.symbolStyle = QwtSymbol::NoSymbol; skibaSB.smooth = false; skibaSB.trend = false; skibaSB.topN = 1; skibaSB.uname = skibaSB.name = "Skiba Stress Balance"; skibaSB.uunits = "Stress Balance"; metrics.append(skibaSB); MetricDetail skibaSTR; skibaSTR.type = METRIC_PM; skibaSTR.symbol = "skiba_sr"; skibaSTR.metric = NULL; // not a factory metric skibaSTR.penColor = QColor(Qt::darkGreen); skibaSTR.curveStyle = QwtPlotCurve::Steps; skibaSTR.symbolStyle = QwtSymbol::NoSymbol; skibaSTR.smooth = false; skibaSTR.trend = false; skibaSTR.topN = 1; skibaSTR.uname = skibaSTR.name = "Skiba STS Ramp"; skibaSTR.uunits = "Ramp"; metrics.append(skibaSTR); MetricDetail skibaLTR; skibaLTR.type = METRIC_PM; skibaLTR.symbol = "skiba_lr"; skibaLTR.metric = NULL; // not a factory metric skibaLTR.penColor = QColor(Qt::darkBlue); skibaLTR.curveStyle = QwtPlotCurve::Steps; skibaLTR.symbolStyle = QwtSymbol::NoSymbol; skibaLTR.smooth = false; skibaLTR.trend = false; skibaLTR.topN = 1; skibaLTR.uname = skibaLTR.name = "Skiba LTS Ramp"; skibaLTR.uunits = "Ramp"; metrics.append(skibaLTR); // DANIELS LTS MetricDetail danielsLTS; danielsLTS.type = METRIC_PM; danielsLTS.symbol = "daniels_lts"; danielsLTS.metric = NULL; // not a factory metric danielsLTS.penColor = QColor(Qt::blue); danielsLTS.curveStyle = QwtPlotCurve::Lines; danielsLTS.symbolStyle = QwtSymbol::NoSymbol; danielsLTS.smooth = false; danielsLTS.trend = false; danielsLTS.topN = 5; danielsLTS.uname = danielsLTS.name = "Daniels Long Term Stress"; danielsLTS.uunits = "Stress"; metrics.append(danielsLTS); MetricDetail danielsSTS; danielsSTS.type = METRIC_PM; danielsSTS.symbol = "daniels_sts"; danielsSTS.metric = NULL; // not a factory metric danielsSTS.penColor = QColor(Qt::magenta); danielsSTS.curveStyle = QwtPlotCurve::Lines; danielsSTS.symbolStyle = QwtSymbol::NoSymbol; danielsSTS.smooth = false; danielsSTS.trend = false; danielsSTS.topN = 5; danielsSTS.uname = danielsSTS.name = "Daniels Short Term Stress"; danielsSTS.uunits = "Stress"; metrics.append(danielsSTS); MetricDetail danielsSB; danielsSB.type = METRIC_PM; danielsSB.symbol = "daniels_sb"; danielsSB.metric = NULL; // not a factory metric danielsSB.penColor = QColor(Qt::yellow); danielsSB.curveStyle = QwtPlotCurve::Steps; danielsSB.symbolStyle = QwtSymbol::NoSymbol; danielsSB.smooth = false; danielsSB.trend = false; danielsSB.topN = 1; danielsSB.uname = danielsSB.name = "Daniels Stress Balance"; danielsSB.uunits = "Stress Balance"; metrics.append(danielsSB); MetricDetail danielsSTR; danielsSTR.type = METRIC_PM; danielsSTR.symbol = "daniels_sr"; danielsSTR.metric = NULL; // not a factory metric danielsSTR.penColor = QColor(Qt::darkGreen); danielsSTR.curveStyle = QwtPlotCurve::Steps; danielsSTR.symbolStyle = QwtSymbol::NoSymbol; danielsSTR.smooth = false; danielsSTR.trend = false; danielsSTR.topN = 1; danielsSTR.uname = danielsSTR.name = "Daniels STS Ramp"; danielsSTR.uunits = "Ramp"; metrics.append(danielsSTR); MetricDetail danielsLTR; danielsLTR.type = METRIC_PM; danielsLTR.symbol = "daniels_lr"; danielsLTR.metric = NULL; // not a factory metric danielsLTR.penColor = QColor(Qt::darkBlue); danielsLTR.curveStyle = QwtPlotCurve::Steps; danielsLTR.symbolStyle = QwtSymbol::NoSymbol; danielsLTR.smooth = false; danielsLTR.trend = false; danielsLTR.topN = 1; danielsLTR.uname = danielsLTR.name = "Daniels LTS Ramp"; danielsLTR.uunits = "Ramp"; metrics.append(danielsLTR); // sort the list qSort(metrics); foreach(MetricDetail metric, metrics) { QTreeWidgetItem *add; add = new QTreeWidgetItem(allMetrics, METRIC_TYPE); add->setText(0, metric.name); } metricTree->expandItem(allMetrics); configChanged(); // will reset the metric tree ltmSplitter = new QSplitter; ltmSplitter->setContentsMargins(0,0,0,0); ltmSplitter->setOrientation(Qt::Vertical); mainLayout->addWidget(ltmSplitter); ltmSplitter->addWidget(dateRangeTree); ltmSplitter->setCollapsible(0, true); ltmSplitter->addWidget(metricTree); ltmSplitter->setCollapsible(1, true); connect(dateRangeTree,SIGNAL(itemSelectionChanged()), this, SLOT(dateRangeTreeWidgetSelectionChanged())); connect(metricTree,SIGNAL(itemSelectionChanged()), this, SLOT(metricTreeWidgetSelectionChanged())); connect(main, SIGNAL(configChanged()), this, SLOT(configChanged())); connect(dateRangeTree,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(dateRangePopup(const QPoint &))); connect(metricTree,SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(metricTreePopup(const QPoint &))); connect(dateRangeTree,SIGNAL(itemChanged(QTreeWidgetItem *,int)), this, SLOT(dateRangeChanged(QTreeWidgetItem*, int))); } void LTMTool::selectDateRange(int index) { allDateRanges->child(index)->setSelected(true); } QwtPlotCurve::CurveStyle LTMTool::curveStyle(RideMetric::MetricType type) { switch (type) { case RideMetric::Average : return QwtPlotCurve::Lines; case RideMetric::Total : return QwtPlotCurve::Steps; case RideMetric::Peak : return QwtPlotCurve::Lines; default : return QwtPlotCurve::Lines; } } QwtSymbol::Style LTMTool::symbolStyle(RideMetric::MetricType type) { switch (type) { case RideMetric::Average : return QwtSymbol::Ellipse; case RideMetric::Total : return QwtSymbol::Ellipse; case RideMetric::Peak : return QwtSymbol::Rect; default : return QwtSymbol::XCross; } } void LTMTool::configChanged() { } /*---------------------------------------------------------------------- * Selections Made *----------------------------------------------------------------------*/ void LTMTool::dateRangeTreeWidgetSelectionChanged() { if (dateRangeTree->selectedItems().isEmpty()) dateRange = NULL; else { QTreeWidgetItem *which = dateRangeTree->selectedItems().first(); if (which != allDateRanges) { dateRange = &seasons.at(allDateRanges->indexOfChild(which)); } else { dateRange = NULL; } } dateRangeSelected(dateRange); } void LTMTool::metricTreeWidgetSelectionChanged() { metricSelected(); } /*---------------------------------------------------------------------- * Date ranges from Seasons.xml *--------------------------------------------------------------------*/ void LTMTool::readSeasons() { QFile seasonFile(home.absolutePath() + "/seasons.xml"); QXmlInputSource source( &seasonFile ); QXmlSimpleReader xmlReader; SeasonParser( handler ); xmlReader.setContentHandler(&handler); xmlReader.setErrorHandler(&handler); xmlReader.parse( source ); seasons = handler.getSeasons(); int i; for (i=0; i setText(0, season.getName()); } Season season; QDate today = QDate::currentDate(); QDate eom = QDate::QDate(today.year(), today.month(), today.daysInMonth()); // add Default Date Ranges season.setName(tr("All Dates")); season.setType(Season::temporary); season.setStart(QDate::currentDate().addYears(-50)); season.setEnd(QDate::currentDate().addYears(50)); seasons.append(season); season.setName(tr("This Year")); season.setType(Season::temporary); season.setStart(QDate::QDate(today.year(), 1,1)); season.setEnd(QDate::QDate(today.year(), 12, 31)); seasons.append(season); season.setName(tr("This Month")); season.setType(Season::temporary); season.setStart(QDate::QDate(today.year(), today.month(),1)); season.setEnd(eom); seasons.append(season); season.setName(tr("This Week")); season.setType(Season::temporary); // from Mon-Sun QDate wstart = QDate::currentDate(); wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek()); QDate wend = wstart.addDays(6); // first day + 6 more season.setStart(wstart); season.setEnd(wend); seasons.append(season); season.setName(tr("Last 7 days")); season.setType(Season::temporary); season.setStart(today.addDays(-6)); // today plus previous 6 season.setEnd(today); seasons.append(season); season.setName(tr("Last 14 days")); season.setType(Season::temporary); season.setStart(today.addDays(-13)); season.setEnd(today); seasons.append(season); season.setName(tr("Last 28 days")); season.setType(Season::temporary); season.setStart(today.addDays(-27)); season.setEnd(today); seasons.append(season); season.setName(tr("Last 3 months")); season.setType(Season::temporary); season.setEnd(today); season.setStart(today.addMonths(-3)); seasons.append(season); season.setName(tr("Last 6 months")); season.setType(Season::temporary); season.setEnd(today); season.setStart(today.addMonths(-6)); seasons.append(season); season.setName(tr("Last 12 months")); season.setType(Season::temporary); season.setEnd(today); season.setStart(today.addMonths(-12)); seasons.append(season); for (;i setText(0, season.getName()); } dateRangeTree->expandItem(allDateRanges); } QString LTMTool::metricName(QTreeWidgetItem *item) { int idx = allMetrics->indexOfChild(item); if (idx >= 0) return metrics[idx].name; else return tr("Unknown Metric"); } QString LTMTool::metricSymbol(QTreeWidgetItem *item) { int idx = allMetrics->indexOfChild(item); if (idx >= 0) return metrics[idx].symbol; else return tr("Unknown Metric"); } MetricDetail LTMTool::metricDetails(QTreeWidgetItem *item) { MetricDetail empty; int idx = allMetrics->indexOfChild(item); if (idx >= 0) return metrics[idx]; else return empty; } int LTMTool::newSeason(QString name, QDate start, QDate end, int type) { Season add; add.setName(name); add.setStart(start); add.setEnd(end); add.setType(type); seasons.insert(0, add); // save changes away writeSeasons(); QTreeWidgetItem *item = new QTreeWidgetItem(USER_DATE); item->setText(0, add.getName()); allDateRanges->insertChild(0, item); return 0; // always add at the top } void LTMTool::updateSeason(int index, QString name, QDate start, QDate end, int type) { seasons[index].setName(name); seasons[index].setStart(start); seasons[index].setEnd(end); seasons[index].setType(type); allDateRanges->child(index)->setText(0, name); // save changes away writeSeasons(); } void LTMTool::dateRangePopup(QPoint pos) { QTreeWidgetItem *item = dateRangeTree->itemAt(pos); if (item != NULL && item->type() != ROOT_TYPE && item->type() != SYS_DATE) { // save context activeDateRange = item; // create context menu QMenu menu(dateRangeTree); QAction *rename = new QAction(tr("Rename range"), dateRangeTree); QAction *edit = new QAction(tr("Edit details"), dateRangeTree); QAction *del = new QAction(tr("Delete range"), dateRangeTree); menu.addAction(rename); menu.addAction(edit); menu.addAction(del); // connect menu to functions connect(rename, SIGNAL(triggered(void)), this, SLOT(renameRange(void))); connect(edit, SIGNAL(triggered(void)), this, SLOT(editRange(void))); connect(del, SIGNAL(triggered(void)), this, SLOT(deleteRange(void))); // execute the menu menu.exec(dateRangeTree->mapToGlobal(pos)); } } void LTMTool::renameRange() { // go edit the name activeDateRange->setFlags(activeDateRange->flags() | Qt::ItemIsEditable); dateRangeTree->editItem(activeDateRange, 0); } void LTMTool::dateRangeChanged(QTreeWidgetItem*item, int) { if (item != activeDateRange) return; int index = allDateRanges->indexOfChild(item); seasons[index].setName(item->text(0)); // save changes away writeSeasons(); // signal date selected changed dateRangeSelected(&seasons[index]); } void LTMTool::editRange() { // throw up modal dialog box to edit all the season // fields. int index = allDateRanges->indexOfChild(activeDateRange); EditSeasonDialog dialog(main, &seasons[index]); if (dialog.exec()) { // update name activeDateRange->setText(0, seasons[index].getName()); // save changes away writeSeasons(); // signal its changed! dateRangeSelected(&seasons[index]); } } void LTMTool::deleteRange() { // now delete! int index = allDateRanges->indexOfChild(activeDateRange); delete allDateRanges->takeChild(index); seasons.removeAt(index); // now update season.xml writeSeasons(); } void LTMTool::writeSeasons() { // update seasons.xml QString file = QString(home.absolutePath() + "/seasons.xml"); SeasonParser::serialize(file, seasons); } void LTMTool::metricTreePopup(QPoint pos) { QTreeWidgetItem *item = metricTree->itemAt(pos); if (item != NULL && item->type() != ROOT_TYPE) { // save context activeMetric = item; // create context menu QMenu menu(metricTree); QAction *color = new QAction(tr("Pick Color"), metricTree); QAction *edit = new QAction(tr("Settings"), metricTree); menu.addAction(color); menu.addAction(edit); // connect menu to functions connect(color, SIGNAL(triggered(void)), this, SLOT(colorPicker(void))); connect(edit, SIGNAL(triggered(void)), this, SLOT(editMetric(void))); // execute the menu menu.exec(metricTree->mapToGlobal(pos)); } } void LTMTool::editMetric() { int index = allMetrics->indexOfChild(activeMetric); EditMetricDetailDialog dialog(main, &metrics[index]); if (dialog.exec()) { // notify of change metricSelected(); } } void LTMTool::colorPicker() { int index = allMetrics->indexOfChild(activeMetric); QColorDialog picker(main); picker.setCurrentColor(metrics[index].penColor); QColor color = picker.getColor(); // if we got a good color use it and notify others if (color.isValid()) { metrics[index].penColor = color; metricSelected(); } } void LTMTool::applySettings(LTMSettings *settings) { disconnect(metricTree,SIGNAL(itemSelectionChanged()), this, SLOT(metricTreeWidgetSelectionChanged())); metricTree->clearSelection(); // de-select everything foreach (MetricDetail metricDetail, settings->metrics) { // get index for the symbol for (int i=0; iconversion() != 1.0 && metrics[i].uunits.contains(saved->units(!useMetricUnits))) metrics[i].uunits.replace(saved->units(!useMetricUnits), saved->units(useMetricUnits)); // select it on the tool allMetrics->child(i)->setSelected(true); break; } } } connect(metricTree,SIGNAL(itemSelectionChanged()), this, SLOT(metricTreeWidgetSelectionChanged())); metricTreeWidgetSelectionChanged(); } /*---------------------------------------------------------------------- * EDIT METRIC DETAIL DIALOG *--------------------------------------------------------------------*/ EditMetricDetailDialog::EditMetricDetailDialog(MainWindow *mainWindow, MetricDetail *metricDetail) : QDialog(mainWindow, Qt::Dialog), mainWindow(mainWindow), metricDetail(metricDetail) { setWindowTitle(tr("Settings")); QVBoxLayout *mainLayout = new QVBoxLayout(this); // Metric Name mainLayout->addSpacing(5); QLabel *metricName = new QLabel(metricDetail->name, this); metricName->setAlignment(Qt::AlignHCenter); QFont def; def.setBold(true); metricName->setFont(def); mainLayout->addWidget(metricName); mainLayout->addSpacing(5); // Grid QGridLayout *grid = new QGridLayout; QLabel *name = new QLabel("Name"); QLabel *units = new QLabel("Axis Label / Units"); userName = new QLineEdit(this); userName->setText(metricDetail->uname); userUnits = new QLineEdit(this); userUnits->setText(metricDetail->uunits); QLabel *style = new QLabel("Curve"); curveStyle = new QComboBox(this); curveStyle->addItem("Bar", QwtPlotCurve::Steps); curveStyle->addItem("Line", QwtPlotCurve::Lines); curveStyle->addItem("Sticks", QwtPlotCurve::Sticks); curveStyle->addItem("Dots", QwtPlotCurve::Dots); curveStyle->setCurrentIndex(curveStyle->findData(metricDetail->curveStyle)); QLabel *symbol = new QLabel("Symbol"); curveSymbol = new QComboBox(this); curveSymbol->addItem("None", QwtSymbol::NoSymbol); curveSymbol->addItem("Circle", QwtSymbol::Ellipse); curveSymbol->addItem("Square", QwtSymbol::Rect); curveSymbol->addItem("Diamond", QwtSymbol::Diamond); curveSymbol->addItem("Triangle", QwtSymbol::Triangle); curveSymbol->addItem("Cross", QwtSymbol::XCross); curveSymbol->addItem("Hexagon", QwtSymbol::Hexagon); curveSymbol->addItem("Star", QwtSymbol::Star1); curveSymbol->setCurrentIndex(curveSymbol->findData(metricDetail->symbolStyle)); QLabel *color = new QLabel("Color"); curveColor = new QPushButton(this); // color background... penColor = metricDetail->penColor; setButtonIcon(penColor); QLabel *topN = new QLabel("Highlight Best"); showBest = new QDoubleSpinBox(this); showBest->setDecimals(0); showBest->setMinimum(0); showBest->setMaximum(999); showBest->setSingleStep(1.0); showBest->setValue(metricDetail->topN); QLabel *baseline = new QLabel("Baseline"); baseLine = new QDoubleSpinBox(this); baseLine->setDecimals(0); baseLine->setMinimum(-999999); baseLine->setMaximum(999999); baseLine->setSingleStep(1.0); baseLine->setValue(metricDetail->baseline); curveSmooth = new QCheckBox("Smooth Curve", this); curveSmooth->setChecked(metricDetail->smooth); curveTrend = new QCheckBox("Trend Line", this); curveTrend->setChecked(metricDetail->trend); // add to grid grid->addWidget(name, 0,0); grid->addWidget(userName, 0,1); grid->addWidget(units, 1,0); grid->addWidget(userUnits, 1,1); grid->addWidget(style, 2,0); grid->addWidget(curveStyle, 2,1); grid->addWidget(symbol, 3,0); grid->addWidget(curveSymbol, 3,1); grid->addWidget(color, 4,0); grid->addWidget(curveColor, 4,1); grid->addWidget(topN, 5,0); grid->addWidget(showBest, 5,1); grid->addWidget(baseline, 6, 0); grid->addWidget(baseLine, 6,1); grid->addWidget(curveSmooth, 7,1); grid->addWidget(curveTrend, 8,1); mainLayout->addLayout(grid); mainLayout->addStretch(); // Buttons QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); applyButton = new QPushButton(tr("&OK"), this); cancelButton = new QPushButton(tr("&Cancel"), this); buttonLayout->addWidget(cancelButton); buttonLayout->addWidget(applyButton); mainLayout->addLayout(buttonLayout); // connect up slots connect(applyButton, SIGNAL(clicked()), this, SLOT(applyClicked())); connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked())); connect(curveColor, SIGNAL(clicked()), this, SLOT(colorClicked())); } // uh. i hate enums when you need to modify from ints // this is fugly and prone to error. Tied directly to the // combo box above. all better solutions gratefully received // but wanna get this code running for now static QwtPlotCurve::CurveStyle styleMap[] = { QwtPlotCurve::Steps, QwtPlotCurve::Lines, QwtPlotCurve::Sticks, QwtPlotCurve::Dots }; static QwtSymbol::Style symbolMap[] = { QwtSymbol::NoSymbol, QwtSymbol::Ellipse, QwtSymbol::Rect, QwtSymbol::Diamond, QwtSymbol::Triangle, QwtSymbol::XCross, QwtSymbol::Hexagon, QwtSymbol::Star1 }; void EditMetricDetailDialog::applyClicked() { // get the values back metricDetail->smooth = curveSmooth->isChecked(); metricDetail->trend = curveTrend->isChecked(); metricDetail->topN = showBest->value(); metricDetail->baseline = baseLine->value(); metricDetail->curveStyle = styleMap[curveStyle->currentIndex()]; metricDetail->symbolStyle = symbolMap[curveSymbol->currentIndex()]; metricDetail->penColor = penColor; metricDetail->uname = userName->text(); metricDetail->uunits = userUnits->text(); accept(); } void EditMetricDetailDialog::cancelClicked() { reject(); } void EditMetricDetailDialog::colorClicked() { QColorDialog picker(mainWindow); picker.setCurrentColor(penColor); QColor color = picker.getColor(); if (color.isValid()) { setButtonIcon(penColor=color); } } void EditMetricDetailDialog::setButtonIcon(QColor color) { // create an icon QPixmap pix(24, 24); QPainter painter(&pix); if (color.isValid()) { painter.setPen(Qt::gray); painter.setBrush(QBrush(color)); painter.drawRect(0, 0, 24, 24); } QIcon icon; icon.addPixmap(pix); curveColor->setIcon(icon); curveColor->setContentsMargins(2,2,2,2); curveColor->setFixedWidth(34); }