From: Jens Steinhauser Date: Sat, 29 Aug 2015 14:40:13 +0000 (+0200) Subject: Add a spin box widget for timestamp values X-Git-Tag: pulseview-0.3.0~123 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=806d3e1eb3d60e93ff95d23e79588a0486730967;p=pulseview.git Add a spin box widget for timestamp values --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 326499f1..bde27c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,7 @@ set(pulseview_SOURCES pv/widgets/popup.cpp pv/widgets/popuptoolbutton.cpp pv/widgets/sweeptimingwidget.cpp + pv/widgets/timestampspinbox.cpp pv/widgets/wellarray.cpp ) @@ -277,6 +278,7 @@ set(pulseview_HEADERS pv/widgets/popup.hpp pv/widgets/popuptoolbutton.hpp pv/widgets/sweeptimingwidget.hpp + pv/widgets/timestampspinbox.hpp pv/widgets/wellarray.hpp ) diff --git a/pv/util.hpp b/pv/util.hpp index b1e45dfb..e9689ec0 100644 --- a/pv/util.hpp +++ b/pv/util.hpp @@ -25,6 +25,7 @@ #include +#include #include namespace pv { @@ -83,4 +84,6 @@ QString format_second(const Timestamp& second); } // namespace util } // namespace pv +Q_DECLARE_METATYPE(pv::util::Timestamp) + #endif // PULSEVIEW_UTIL_HPP diff --git a/pv/view/timemarker.cpp b/pv/view/timemarker.cpp index f1424627..8c136a18 100644 --- a/pv/view/timemarker.cpp +++ b/pv/view/timemarker.cpp @@ -25,6 +25,7 @@ #include "timemarker.hpp" #include "view.hpp" +#include "pv/widgets/timestampspinbox.hpp" #include #include @@ -63,7 +64,7 @@ void TimeMarker::set_time(const pv::util::Timestamp& time) if (value_widget_) { updating_value_widget_ = true; - value_widget_->setValue(time.convert_to()); + value_widget_->setValue(time); updating_value_widget_ = false; } @@ -173,22 +174,18 @@ pv::widgets::Popup* TimeMarker::create_popup(QWidget *parent) QFormLayout *const form = new QFormLayout(popup); popup->setLayout(form); - value_widget_ = new QDoubleSpinBox(parent); - value_widget_->setDecimals(9); - value_widget_->setSuffix("s"); - value_widget_->setSingleStep(1e-6); - value_widget_->setRange(-1.0e9, 1.0e9); - value_widget_->setValue(time_.convert_to()); + value_widget_ = new pv::widgets::TimestampSpinBox(parent); + value_widget_->setValue(time_); - connect(value_widget_, SIGNAL(valueChanged(double)), - this, SLOT(on_value_changed(double))); + connect(value_widget_, SIGNAL(valueChanged(const pv::util::Timestamp&)), + this, SLOT(on_value_changed(const pv::util::Timestamp&))); form->addRow(tr("Time"), value_widget_); return popup; } -void TimeMarker::on_value_changed(double value) +void TimeMarker::on_value_changed(const pv::util::Timestamp& value) { if (!updating_value_widget_) set_time(value); diff --git a/pv/view/timemarker.hpp b/pv/view/timemarker.hpp index 10e3331c..371b6e4a 100644 --- a/pv/view/timemarker.hpp +++ b/pv/view/timemarker.hpp @@ -33,6 +33,10 @@ class QPainter; class QRect; namespace pv { +namespace widgets { + class TimestampSpinBox; +} + namespace view { class View; @@ -109,7 +113,7 @@ public: virtual pv::widgets::Popup* create_popup(QWidget *parent); private Q_SLOTS: - void on_value_changed(double value); + void on_value_changed(const pv::util::Timestamp& value); protected: const QColor &colour_; @@ -119,7 +123,7 @@ protected: QSizeF text_size_; QWidgetAction *value_action_; - QDoubleSpinBox *value_widget_; + pv::widgets::TimestampSpinBox *value_widget_; bool updating_value_widget_; }; diff --git a/pv/widgets/timestampspinbox.cpp b/pv/widgets/timestampspinbox.cpp new file mode 100644 index 00000000..703da6ea --- /dev/null +++ b/pv/widgets/timestampspinbox.cpp @@ -0,0 +1,122 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Jens Steinhauser + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "timestampspinbox.hpp" + +#include +#include + +namespace pv { +namespace widgets { + +TimestampSpinBox::TimestampSpinBox(QWidget* parent) + : QAbstractSpinBox(parent) + , precision_(9) + , stepsize_("1e-6") +{ + connect(this, SIGNAL(editingFinished()), this, SLOT(on_editingFinished())); + + updateEdit(); +} + +void TimestampSpinBox::stepBy(int steps) +{ + setValue(value_ + steps * stepsize_); +} + +QAbstractSpinBox::StepEnabled TimestampSpinBox::stepEnabled() const +{ + return QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; +} + +unsigned TimestampSpinBox::precision() const +{ + return precision_; +} + +void TimestampSpinBox::setPrecision(unsigned precision) +{ + precision_ = precision; + updateEdit(); +} + +const pv::util::Timestamp& TimestampSpinBox::singleStep() const +{ + return stepsize_; +} + +void TimestampSpinBox::setSingleStep(const pv::util::Timestamp& step) +{ + stepsize_ = step; +} + +const pv::util::Timestamp& TimestampSpinBox::value() const +{ + return value_; +} + +QSize TimestampSpinBox::minimumSizeHint() const +{ + const QFontMetrics fm(fontMetrics()); + const int l = round(value_).str().size() + precision_ + 10; + const int w = fm.width(QString(l, '0')); + const int h = lineEdit()->minimumSizeHint().height(); + return QSize(w, h); +} + +void TimestampSpinBox::setValue(const pv::util::Timestamp& val) +{ + if (val == value_) + return; + + value_ = val; + updateEdit(); + Q_EMIT valueChanged(value_); +} + +void TimestampSpinBox::on_editingFinished() +{ + if (!lineEdit()->isModified()) + return; + lineEdit()->setModified(false); + + QRegExp re(R"(\s*([-+]?)\s*([0-9]+\.?[0-9]*).*)"); + + if (re.exactMatch(text())) { + QStringList captures = re.capturedTexts(); + captures.removeFirst(); // remove entire match + QString str = captures.join(""); + setValue(pv::util::Timestamp(str.toStdString())); + } + else { + // replace the malformed entered string with the old value + updateEdit(); + } +} + +void TimestampSpinBox::updateEdit() +{ + QString newtext = pv::util::format_si_value( + value_, "s", 8, precision_); + lineEdit()->setText(newtext); +} + +} // widgets +} // pv diff --git a/pv/widgets/timestampspinbox.hpp b/pv/widgets/timestampspinbox.hpp new file mode 100644 index 00000000..bac7cac1 --- /dev/null +++ b/pv/widgets/timestampspinbox.hpp @@ -0,0 +1,93 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2015 Jens Steinhauser + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PULSEVIEW_PV_WIDGETS_TIMESTAMPSPINBOX_HPP +#define PULSEVIEW_PV_WIDGETS_TIMESTAMPSPINBOX_HPP + +#include "pv/util.hpp" + +#include + +namespace pv { +namespace widgets { + +class TimestampSpinBox : public QAbstractSpinBox +{ + Q_OBJECT + + Q_PROPERTY(unsigned precision + READ precision + WRITE setPrecision) + + // Needed because of some strange behaviour of the Qt4 MOC that would add + // a reference to a 'staticMetaObject' member of 'pv::util' (the namespace) + // if pv::util::Timestamp is used directly in the Q_PROPERTY macros below. + // Didn't happen with the Qt5 MOC in this case, however others have had + // similar problems with Qt5: https://bugreports.qt.io/browse/QTBUG-37519 + typedef pv::util::Timestamp Timestamp; + + Q_PROPERTY(Timestamp singleStep + READ singleStep + WRITE setSingleStep) + + Q_PROPERTY(Timestamp value + READ value + WRITE setValue + NOTIFY valueChanged + USER true) + +public: + TimestampSpinBox(QWidget* parent = nullptr); + + void stepBy(int steps) override; + + StepEnabled stepEnabled() const override; + + unsigned precision() const; + void setPrecision(unsigned precision); + + const pv::util::Timestamp& singleStep() const; + void setSingleStep(const pv::util::Timestamp& step); + + const pv::util::Timestamp& value() const; + + QSize minimumSizeHint() const override; + +public Q_SLOTS: + void setValue(const pv::util::Timestamp& val); + +Q_SIGNALS: + void valueChanged(const pv::util::Timestamp&); + +private Q_SLOTS: + void on_editingFinished(); + +private: + unsigned precision_; + pv::util::Timestamp stepsize_; + pv::util::Timestamp value_; + + void updateEdit(); +}; + +} // widgets +} // pv + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e41d39a..f2262b4a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -69,6 +69,7 @@ set(pulseview_TEST_SOURCES ${PROJECT_SOURCE_DIR}/pv/widgets/popup.cpp ${PROJECT_SOURCE_DIR}/pv/widgets/popuptoolbutton.cpp ${PROJECT_SOURCE_DIR}/pv/widgets/sweeptimingwidget.cpp + ${PROJECT_SOURCE_DIR}/pv/widgets/timestampspinbox.cpp ${PROJECT_SOURCE_DIR}/pv/widgets/wellarray.cpp data/analogsegment.cpp data/logicsegment.cpp @@ -111,6 +112,7 @@ set(pulseview_TEST_HEADERS ${PROJECT_SOURCE_DIR}/pv/widgets/popup.hpp ${PROJECT_SOURCE_DIR}/pv/widgets/popuptoolbutton.hpp ${PROJECT_SOURCE_DIR}/pv/widgets/sweeptimingwidget.hpp + ${PROJECT_SOURCE_DIR}/pv/widgets/timestampspinbox.hpp ${PROJECT_SOURCE_DIR}/pv/widgets/wellarray.hpp )