diff --git a/qxt/src/qxtstringspinbox.cpp b/qxt/src/qxtstringspinbox.cpp new file mode 100755 index 000000000..f24b340a1 --- /dev/null +++ b/qxt/src/qxtstringspinbox.cpp @@ -0,0 +1,159 @@ +#include "qxtstringspinbox.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + + +class QxtStringSpinBoxPrivate : public QxtPrivate +{ +public: + QXT_DECLARE_PUBLIC(QxtStringSpinBox) + int startsWith(const QString& start, QString& string) const; + QStringList strings; +}; + +int QxtStringSpinBoxPrivate::startsWith(const QString& start, QString& string) const +{ + const int size = strings.size(); + for (int i = 0; i < size; ++i) + { + if (strings.at(i).startsWith(start, Qt::CaseInsensitive)) + { + // found + string = strings.at(i); + return i; + } + } + // not found + return -1; +} + +/*! + \class QxtStringSpinBox + \inmodule QxtWidgets + \brief The QxtStringSpinBox widget is a spin box with string items. + + QxtStringSpinBox is spin box that takes strings. QxtStringSpinBox allows + the user to choose a value by clicking the up and down buttons or by + pressing Up or Down on the keyboard to increase or decrease the value + currently displayed. The user can also type the value in manually. + + \image qxtstringspinbox.png "QxtStringSpinBox in Cleanlooks style." + */ + +/*! + Constructs a new QxtStringSpinBox with \a pParent. + */ +QxtStringSpinBox::QxtStringSpinBox(QWidget* pParent) : QSpinBox(pParent) +{ + setRange(0, 0); +} + +/*! + Destructs the spin box. + */ +QxtStringSpinBox::~QxtStringSpinBox() +{} + +/*! + \property QxtStringSpinBox::strings + \brief the string items of the spin box. + */ +const QStringList& QxtStringSpinBox::strings() const +{ + return qxt_d().strings; +} + +void QxtStringSpinBox::setStrings(const QStringList& strings) +{ + qxt_d().strings = strings; + setRange(0, strings.size() - 1); + if (!strings.isEmpty()) + setValue(0); +} + +/*! + \reimp + */ +void QxtStringSpinBox::fixup(QString& input) const +{ + // just attempt to change the input string to be valid according to the string list + // no need to result in a valid string, callers of this function are responsible to + // re-test the validity afterwards + + // try finding a string from the list which starts with input + input = input.simplified(); + if (!input.isEmpty()) + { + qxt_d().startsWith(input, input); + } +} + +/*! + \reimp + */ +QValidator::State QxtStringSpinBox::validate(QString& input, int& pos) const +{ + // Invalid: input is invalid according to the string list + // Intermediate: it is likely that a little more editing will make the input acceptable + // (e.g. the user types "A" and stringlist contains "ABC") + // Acceptable: the input is valid. + Q_UNUSED(pos); + QString temp; + QValidator::State state = QValidator::Invalid; + if (qxt_d().strings.contains(input)) + { + // exact match + state = QValidator::Acceptable; + } + else if (input.isEmpty() || qxt_d().startsWith(input, temp) != -1) + { + // still empty or some string in the list starts with input + state = QValidator::Intermediate; + } + // else invalid + return state; +} + +/*! + \reimp + */ +QString QxtStringSpinBox::textFromValue(int value) const +{ + Q_ASSERT(qxt_d().strings.isEmpty() || (value >= 0 && value < qxt_d().strings.size())); + return qxt_d().strings.isEmpty() ? QLatin1String("") : qxt_d().strings.at(value); +} + +/*! + \reimp + */ +int QxtStringSpinBox::valueFromText(const QString& text) const +{ + return qxt_d().strings.indexOf(text); +} diff --git a/qxt/src/qxtstringspinbox.h b/qxt/src/qxtstringspinbox.h new file mode 100755 index 000000000..4e93c293f --- /dev/null +++ b/qxt/src/qxtstringspinbox.h @@ -0,0 +1,60 @@ +#ifndef QXTSTRINGSPINBOX_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTSTRINGSPINBOX_H + +#include +#include "qxtglobal.h" + +class QxtStringSpinBoxPrivate; + +class QXT_GUI_EXPORT QxtStringSpinBox : public QSpinBox +{ + Q_OBJECT + QXT_DECLARE_PRIVATE(QxtStringSpinBox) + Q_PROPERTY(QStringList strings READ strings WRITE setStrings) + +public: + explicit QxtStringSpinBox(QWidget* pParent = 0); + virtual ~QxtStringSpinBox(); + + const QStringList& strings() const; + void setStrings(const QStringList& strings); + + virtual void fixup(QString& input) const; + virtual QValidator::State validate(QString& input, int& pos) const; + +protected: + virtual QString textFromValue(int value) const; + virtual int valueFromText(const QString& text) const; +}; + +#endif // QXTSTRINGSPINBOX_H diff --git a/src/ScatterWindow.cpp b/src/ScatterWindow.cpp index 787ac7952..c7d9dbd27 100644 --- a/src/ScatterWindow.cpp +++ b/src/ScatterWindow.cpp @@ -45,19 +45,85 @@ ScatterWindow::addStandardChannels(QComboBox *box) //box->addItem(tr("Longitude"), MODEL_LONG); //XXX weird values make the plot ugly } +void +ScatterWindow::addrStandardChannels(QxtStringSpinBox *box) +{ + QStringList list; + list.append(tr("Power")); + list.append(tr("Cadence")); + list.append(tr("Heartrate")); + list.append(tr("Speed")); + list.append(tr("Altitude")); + list.append(tr("Torque")); + list.append(tr("AEPF")); + list.append(tr("CPV")); + list.append(tr("Time")); + list.append(tr("Distance")); + box->setStrings(list); +} + ScatterWindow::ScatterWindow(MainWindow *parent, const QDir &home) : GcWindow(parent), home(home), main(parent), ride(NULL), current(NULL) { setInstanceName("2D Window"); + // Main layout + QGridLayout *mainLayout = new QGridLayout(this); + mainLayout->setContentsMargins(2,2,2,2); + + // + // reveal controls widget + // + + // reveal widget + revealControls = new QWidget(this); + revealControls->setFixedHeight(50); + revealControls->setStyleSheet("background-color: rgba(100%, 100%, 100%, 80%)"); + revealControls->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + + // reveal controls + QLabel *rxLabel = new QLabel(tr("X-Axis:"), this); + rxSelector = new QxtStringSpinBox(revealControls); + addrStandardChannels(rxSelector); + + QLabel *ryLabel = new QLabel(tr("Y-Axis:"), this); + rySelector = new QxtStringSpinBox(revealControls); + addrStandardChannels(rySelector); + + rIgnore = new QCheckBox(tr("Ignore Zero")); + rIgnore->setChecked(true); + rFrameInterval = new QCheckBox(tr("Frame intervals")); + rFrameInterval->setChecked(true); + + // layout reveal controls + QHBoxLayout *r = new QHBoxLayout; + r->setContentsMargins(0,0,0,0); + r->addStretch(); + r->addWidget(rxLabel); + r->addWidget(rxSelector); + r->addWidget(ryLabel); + r->addWidget(rySelector); + r->addSpacing(5); + r->addWidget(rIgnore); + r->addWidget(rFrameInterval); + r->addStretch(); + revealControls->setLayout(r); + + // hide them initially + revealControls->hide(); + QWidget *c = new QWidget; QFormLayout *cl = new QFormLayout(c); setControls(c); // the plot widget scatterPlot= new ScatterPlot(main); - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(scatterPlot); + QVBoxLayout *vlayout = new QVBoxLayout; + vlayout->addWidget(scatterPlot); + + mainLayout->addLayout(vlayout,0,0); + mainLayout->addWidget(revealControls,0,0, Qt::AlignTop); + revealControls->raise(); setLayout(mainLayout); // labels @@ -65,12 +131,14 @@ ScatterWindow::ScatterWindow(MainWindow *parent, const QDir &home) : xSelector = new QComboBox; addStandardChannels(xSelector); xSelector->setCurrentIndex(0); // power + rxSelector->setValue(0); cl->addRow(xLabel, xSelector); yLabel = new QLabel(tr("Y-Axis:"), this); ySelector = new QComboBox; addStandardChannels(ySelector); ySelector->setCurrentIndex(2); // heartrate + rySelector->setValue(2); cl->addRow(yLabel, ySelector); timeLabel = new QLabel(tr("00:00:00"), this); @@ -104,11 +172,16 @@ ScatterWindow::ScatterWindow(MainWindow *parent, const QDir &home) : connect(main, SIGNAL(intervalsChanged()), this, SLOT(intervalSelected())); connect(xSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(setData())); connect(ySelector, SIGNAL(currentIndexChanged(int)), this, SLOT(setData())); + connect(rxSelector, SIGNAL(valueChanged(int)), this, SLOT(rxSelectorChanged(int))); + connect(rySelector, SIGNAL(valueChanged(int)), this, SLOT(rySelectorChanged(int))); connect(timeSlider, SIGNAL(valueChanged(int)), this, SLOT(setTime(int))); connect(grid, SIGNAL(stateChanged(int)), this, SLOT(setGrid())); //connect(legend, SIGNAL(stateChanged(int)), this, SLOT(setLegend())); connect(frame, SIGNAL(stateChanged(int)), this, SLOT(setFrame())); connect(ignore, SIGNAL(stateChanged(int)), this, SLOT(setIgnore())); + connect(rFrameInterval, SIGNAL(stateChanged(int)), this, SLOT(setrFrame())); + connect(rIgnore, SIGNAL(stateChanged(int)), this, SLOT(setrIgnore())); + } void @@ -143,6 +216,15 @@ void ScatterWindow::setFrame() { settings.frame = frame->isChecked(); + rFrameInterval->setChecked(frame->isChecked()); + setData(); +} + +void +ScatterWindow::setrFrame() +{ + settings.frame = rFrameInterval->isChecked(); + frame->setChecked(rFrameInterval->isChecked()); setData(); } @@ -150,6 +232,15 @@ void ScatterWindow::setIgnore() { settings.ignore = ignore->isChecked(); + rIgnore->setChecked(ignore->isChecked()); + setData(); +} + +void +ScatterWindow::setrIgnore() +{ + settings.ignore = rIgnore->isChecked(); + ignore->setChecked(rIgnore->isChecked()); setData(); } @@ -172,6 +263,20 @@ ScatterWindow::setTime(int value) scatterPlot->showTime(&settings, value, 30); } +void +ScatterWindow::rxSelectorChanged(int value) +{ + xSelector->setCurrentIndex(value); + setData(); +} + +void +ScatterWindow::rySelectorChanged(int value) +{ + ySelector->setCurrentIndex(value); + setData(); +} + void ScatterWindow::setData() { diff --git a/src/ScatterWindow.h b/src/ScatterWindow.h index 954fe7807..ac9d20539 100644 --- a/src/ScatterWindow.h +++ b/src/ScatterWindow.h @@ -22,8 +22,10 @@ #include #include +#include "qxtstringspinbox.h" #include "MainWindow.h" + class ScatterPlot; // we don't include the header because it uses namespaces class ScatterDataColor; @@ -58,11 +60,16 @@ class ScatterWindow : public GcWindow ScatterWindow(MainWindow *, const QDir &); + // reveal + bool hasReveal() { return true; } + void reveal() { revealControls->show(); } + void unreveal() { revealControls->hide(); } + // set/get properties int xseries() const { return xSelector->currentIndex(); } - void setXSeries(int x) { xSelector->setCurrentIndex(x); } + void setXSeries(int x) { xSelector->setCurrentIndex(x); rxSelector->setValue(x); } int yseries() const { return ySelector->currentIndex(); } - void setYSeries(int x) { ySelector->setCurrentIndex(x); } + void setYSeries(int x) { ySelector->setCurrentIndex(x); rySelector->setValue(x); } bool isGrid() const { return grid->isChecked(); } void set_Grid(bool x) { grid->setChecked(x); } bool isIgnore() const { return ignore->isChecked(); } @@ -77,10 +84,15 @@ class ScatterWindow : public GcWindow void intervalSelected(); void setData(); + void rxSelectorChanged(int); + void rySelectorChanged(int); + // these set the plot when the properties change void setGrid(); void setFrame(); void setIgnore(); + void setrFrame(); + void setrIgnore(); void setTime(int); protected: @@ -116,8 +128,17 @@ class ScatterWindow : public GcWindow RideItem *current; private: + // reveal controls + QWidget *revealControls; + QxtStringSpinBox *rxSelector, + *rySelector; + QCheckBox *rFrameInterval, + *rIgnore; void addStandardChannels(QComboBox *); + void addrStandardChannels(QxtStringSpinBox *box); + + bool _lockReveal; }; #endif // _GC_ScatterWindow_h diff --git a/src/src.pro b/src/src.pro index 5d7f8e107..717d728a8 100644 --- a/src/src.pro +++ b/src/src.pro @@ -215,6 +215,7 @@ SOURCES += ../qxt/src/qxtspanslider.cpp \ ../qxt/src/qxtscheduleviewheadermodel_p.cpp \ ../qxt/src/qxtscheduleitemdelegate.cpp \ ../qxt/src/qxtstyleoptionscheduleviewitem.cpp \ + ../qxt/src/qxtstringspinbox.cpp \ isEmpty( QTSOAP_INSTALL ) { include( ../qtsolutions/soap/qtsoap.pri ) @@ -232,7 +233,8 @@ HEADERS += ../qxt/src/qxtspanslider.h \ ../qxt/src/qxtscheduleheaderwidget.h \ ../qxt/src/qxtscheduleviewheadermodel_p.h \ ../qxt/src/qxtscheduleitemdelegate.h \ - ../qxt/src/qxtstyleoptionscheduleviewitem.h + ../qxt/src/qxtstyleoptionscheduleviewitem.h \ + ../qxt/src/qxtstringspinbox.h \ HEADERS += \ AboutDialog.h \