From 94dfd109c5513e2a50408aab04fe10ad97900793 Mon Sep 17 00:00:00 2001 From: David Graeff Date: Sun, 17 Dec 2017 04:34:00 +0100 Subject: [PATCH] Move widget files into subfolder --- openhantek/src/colorbox.cpp | 69 --------------------------------------------------------------------- openhantek/src/colorbox.h | 54 ------------------------------------------------------ openhantek/src/levelslider.cpp | 628 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- openhantek/src/levelslider.h | 115 ------------------------------------------------------------------------------------------------------------------- openhantek/src/sispinbox.cpp | 198 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ openhantek/src/sispinbox.h | 74 -------------------------------------------------------------------------- openhantek/src/widgets/colorbox.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ openhantek/src/widgets/colorbox.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ openhantek/src/widgets/levelslider.cpp | 628 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ openhantek/src/widgets/levelslider.h | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ openhantek/src/widgets/sispinbox.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ openhantek/src/widgets/sispinbox.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 1138 insertions(+), 1138 deletions(-) delete mode 100644 openhantek/src/colorbox.cpp delete mode 100644 openhantek/src/colorbox.h delete mode 100644 openhantek/src/levelslider.cpp delete mode 100644 openhantek/src/levelslider.h delete mode 100644 openhantek/src/sispinbox.cpp delete mode 100644 openhantek/src/sispinbox.h create mode 100644 openhantek/src/widgets/colorbox.cpp create mode 100644 openhantek/src/widgets/colorbox.h create mode 100644 openhantek/src/widgets/levelslider.cpp create mode 100644 openhantek/src/widgets/levelslider.h create mode 100644 openhantek/src/widgets/sispinbox.cpp create mode 100644 openhantek/src/widgets/sispinbox.h diff --git a/openhantek/src/colorbox.cpp b/openhantek/src/colorbox.cpp deleted file mode 100644 index 9027acc..0000000 --- a/openhantek/src/colorbox.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -// colorbox.cpp -// -// Copyright (C) 2010 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include - -#include "colorbox.h" - -//////////////////////////////////////////////////////////////////////////////// -// class ColorBox -/// \brief Initializes the widget. -/// \param color Initial color value. -/// \param parent The parent widget. -ColorBox::ColorBox(QColor color, QWidget *parent) : QPushButton(parent) { - this->setColor(color); - - connect(this, SIGNAL(clicked()), this, SLOT(waitForColor())); -} - -/// \brief Cleans up the widget. -ColorBox::~ColorBox() {} - -/// \brief Get the current color. -/// \return The current color as QColor. -const QColor ColorBox::getColor() { return this->color; } - -/// \brief Sets the color. -/// \param color The new color. -void ColorBox::setColor(QColor color) { - this->color = color; - this->setText( - QString("#%1").arg((unsigned int)this->color.rgba(), 8, 16, QChar('0'))); - this->setPalette(QPalette(this->color)); - - emit colorChanged(this->color); -} - -/// \brief Wait for the color dialog and apply chosen color. -void ColorBox::waitForColor() { - this->setFocus(); - this->setDown(true); - - QColor color = QColorDialog::getColor(this->color, this, 0, - QColorDialog::ShowAlphaChannel); - - if (color.isValid()) - this->setColor(color); -} diff --git a/openhantek/src/colorbox.h b/openhantek/src/colorbox.h deleted file mode 100644 index 9b84c87..0000000 --- a/openhantek/src/colorbox.h +++ /dev/null @@ -1,54 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -/// \file colorbox.h -/// \brief Declares the ColorBox class. -// -// Copyright (C) 2010 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef COLORBOX_H -#define COLORBOX_H - -#include -#include - -//////////////////////////////////////////////////////////////////////////////// -/// \class ColorBox colorbox.h -/// \brief A widget for the selection of a color. -class ColorBox : public QPushButton { - Q_OBJECT - -public: - ColorBox(QColor color, QWidget *parent = 0); - ~ColorBox(); - - const QColor getColor(); - -public slots: - void setColor(QColor color); - void waitForColor(); - -private: - QColor color; - -signals: - void colorChanged(QColor color); ///< The color has been changed -}; - -#endif diff --git a/openhantek/src/levelslider.cpp b/openhantek/src/levelslider.cpp deleted file mode 100644 index 664abea..0000000 --- a/openhantek/src/levelslider.cpp +++ /dev/null @@ -1,628 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -// levelslider.cpp -// -// Copyright (C) 2010 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#include - -#include -#include -#include - -#include "levelslider.h" - -//////////////////////////////////////////////////////////////////////////////// -// class LevelSlider -/// \brief Initializes the slider container. -/// \param direction The side on which the sliders are shown. -/// \param parent The parent widget. -LevelSlider::LevelSlider(Qt::ArrowType direction, QWidget *parent) - : QWidget(parent) { - QFont font = this->font(); - font.setPointSize(font.pointSize() * 0.8); - this->setFont(font); - - this->pressedSlider = -1; - this->sliderWidth = 8; - - this->setDirection(direction); -} - -/// \brief Cleans up the widget. -LevelSlider::~LevelSlider() {} - -/// \brief Return the margin before the slider. -/// \return The margin the Slider has at the top/left. -int LevelSlider::preMargin() const { return this->_preMargin; } - -/// \brief Return the margin after the slider. -/// \return The margin the Slider has at the bottom/right. -int LevelSlider::postMargin() const { return this->_postMargin; } - -/// \brief Add a new slider to the slider container. -/// \param index The index where the slider should be inserted, 0 to append. -/// \return The index of the slider, -1 on error. -int LevelSlider::addSlider(int index) { return this->addSlider(0, index); } - -/// \brief Add a new slider to the slider container. -/// \param text The text that will be shown next to the slider. -/// \param index The index where the slider should be inserted, 0 to append. -/// \return The index of the slider, -1 on error. -int LevelSlider::addSlider(QString text, int index) { - if (index < -1) - return -1; - - LevelSliderParameters *parameters = new LevelSliderParameters; - parameters->color = Qt::white; - parameters->minimum = 0x00; - parameters->maximum = 0xff; - parameters->value = 0x00; - parameters->visible = false; - - if (index == -1) { - this->slider.append(parameters); - index = this->slider.count() - 1; - } else - this->slider.insert(index, parameters); - - this->setText(index, text); - - return index; -} - -/// \brief Remove a slider from the slider container. -/// \param index The index of the slider that should be removed. -/// \return The index of the removed slider, -1 on error. -int LevelSlider::removeSlider(int index) { - if (index < -1) - return -1; - - if (index == -1) { - this->slider.removeLast(); - index = this->slider.count(); - } else { - this->slider.removeAt(index); - } - - this->calculateWidth(); - - return index; -} - -/// \brief Size hint for the widget. -/// \return The recommended size for the widget. -QSize LevelSlider::sizeHint() const { - if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) - return QSize(this->sliderWidth, 16); - else - return QSize(16, this->sliderWidth); -} - -/// \brief Return the color of a slider. -/// \param index The index of the slider whose color should be returned. -/// \return The current color of the slider. -const QColor LevelSlider::color(int index) const { - if (index < 0 || index >= this->slider.count()) - return Qt::black; - - return this->slider[index]->color; -} - -/// \brief Set the color of the slider. -/// \param index The index of the slider whose color should be set. -/// \param color The new color for the slider. -/// \return The index of the slider, -1 on error. -int LevelSlider::setColor(int index, QColor color) { - if (index < 0 || index >= this->slider.count()) - return -1; - - this->slider[index]->color = color; - this->repaint(); - - return index; -} - -/// \brief Return the text shown beside a slider. -/// \param index The index of the slider whose text should be returned. -/// \return The current text of the slider. -const QString LevelSlider::text(int index) const { - if (index < 0 || index >= this->slider.count()) - return QString(); - - return this->slider[index]->text; -} - -/// \brief Set the text for a slider. -/// \param index The index of the slider whose text should be set. -/// \param text The text shown next to the slider. -/// \return The index of the slider, -1 on error. -int LevelSlider::setText(int index, QString text) { - if (index < 0 || index >= this->slider.count()) - return -1; - - this->slider[index]->text = text; - this->calculateWidth(); - - return index; -} - -/// \brief Return the visibility of a slider. -/// \param index The index of the slider whose visibility should be returned. -/// \return true if the slider is visible, false if it's hidden. -bool LevelSlider::visible(int index) const { - if (index < 0 || index >= this->slider.count()) - return false; - - return this->slider[index]->visible; -} - -/// \brief Set the visibility of a slider. -/// \param index The index of the slider whose visibility should be set. -/// \param visible true to show the slider, false to hide it. -/// \return The index of the slider, -1 on error. -int LevelSlider::setVisible(int index, bool visible) { - if (index < 0 || index >= this->slider.count()) - return -1; - - this->slider[index]->visible = visible; - this->repaint(); - - return index; -} - -/// \brief Return the minimal value of the sliders. -/// \return The value a slider has at the bottommost/leftmost position. -double LevelSlider::minimum(int index) const { - if (index < 0 || index >= this->slider.count()) - return -1; - - return this->slider[index]->minimum; -} - -/// \brief Return the maximal value of the sliders. -/// \return The value a slider has at the topmost/rightmost position. -double LevelSlider::maximum(int index) const { - if (index < 0 || index >= this->slider.count()) - return -1; - - return this->slider[index]->maximum; -} - -/// \brief Set the maximal value of the sliders. -/// \param index The index of the slider whose limits should be set. -/// \param minimum The value a slider has at the bottommost/leftmost position. -/// \param maximum The value a slider has at the topmost/rightmost position. -/// \return -1 on error, fixValue result on success. -int LevelSlider::setLimits(int index, double minimum, double maximum) { - if (index < 0 || index >= this->slider.count()) - return -1; - - this->slider[index]->minimum = minimum; - this->slider[index]->maximum = maximum; - int result = this->fixValue(index); - - this->calculateRect(index); - this->repaint(); - - return result; -} - -/// \brief Return the step width of the sliders. -/// \param index The index of the slider whose step width should be returned. -/// \return The distance between the selectable slider positions. -double LevelSlider::step(int index) const { - if (index < 0 || index >= this->slider.count()) - return -1; - - return this->slider[index]->step; -} - -/// \brief Set the step width of the sliders. -/// \param index The index of the slider whose step width should be set. -/// \param step The distance between the selectable slider positions. -/// \return The new step width. -double LevelSlider::setStep(int index, double step) { - if (index < 0 || index >= this->slider.count()) - return -1; - - if (step > 0) - this->slider[index]->step = step; - - return this->slider[index]->step; -} - -/// \brief Return the current position of a slider. -/// \param index The index of the slider whose value should be returned. -/// \return The value of the slider. -double LevelSlider::value(int index) const { - if (index < 0 || index >= this->slider.count()) - return -1; - - return this->slider[index]->value; -} - -/// \brief Set the current position of a slider. -/// \param index The index of the slider whose value should be set. -/// \param value The new value of the slider. -/// \return The new value of the slider. -double LevelSlider::setValue(int index, double value) { - if (index < 0 || index >= this->slider.count()) - return -1; - - // Apply new value - this->slider[index]->value = value; - this->fixValue(index); - - this->calculateRect(index); - this->repaint(); - - if (this->pressedSlider < 0) - emit valueChanged(index, value); - - return this->slider[index]->value; -} - -/// \brief Return the direction of the sliders. -/// \return The side on which the sliders are shown. -Qt::ArrowType LevelSlider::direction() const { return this->_direction; } - -/// \brief Set the direction of the sliders. -/// \param direction The side on which the sliders are shown. -/// \return The index of the direction, -1 on error. -int LevelSlider::setDirection(Qt::ArrowType direction) { - if (direction < Qt::UpArrow || direction > Qt::RightArrow) - return -1; - - this->_direction = direction; - - if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { - this->_preMargin = this->fontMetrics().lineSpacing(); - this->_postMargin = 3; - } else { - this->_preMargin = this->fontMetrics().averageCharWidth() * 3; - this->_postMargin = 3; - } - - return this->_direction; -} - -/// \brief Move the slider if it's pressed. -/// \param event The mouse event that should be handled. -void LevelSlider::mouseMoveEvent(QMouseEvent *event) { - if (this->pressedSlider < 0) { - event->ignore(); - return; - } - - // Get new value - double value; - if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) - value = this->slider[pressedSlider]->maximum - - (this->slider[pressedSlider]->maximum - - this->slider[pressedSlider]->minimum) * - ((double)event->y() - this->_preMargin + 0.5) / - (this->height() - this->_preMargin - this->_postMargin - 1); - else - value = this->slider[pressedSlider]->minimum + - (this->slider[pressedSlider]->maximum - - this->slider[pressedSlider]->minimum) * - ((double)event->x() - this->_preMargin + 0.5) / - (this->width() - this->_preMargin - this->_postMargin - 1); - - // Move the slider - if (event->modifiers() & Qt::AltModifier) - // Alt allows every position - this->setValue(this->pressedSlider, value); - else - // Set to nearest possible position - this->setValue(this->pressedSlider, - floor(value / this->slider[pressedSlider]->step + 0.5) * - this->slider[pressedSlider]->step); - - event->accept(); -} - -/// \brief Prepare slider for movement if the left mouse button is pressed. -/// \param event The mouse event that should be handled. -void LevelSlider::mousePressEvent(QMouseEvent *event) { - if (!(event->button() & Qt::LeftButton)) { - event->ignore(); - return; - } - - this->pressedSlider = -1; - for (int sliderId = 0; sliderId < this->slider.count(); ++sliderId) { - if (this->slider[sliderId]->visible && - this->slider[sliderId]->rect.contains(event->pos())) { - this->pressedSlider = sliderId; - break; - } - } - - // Accept event if a slider was pressed - event->setAccepted(this->pressedSlider >= 0); -} - -/// \brief Movement is done if the left mouse button is released. -/// \param event The mouse event that should be handled. -void LevelSlider::mouseReleaseEvent(QMouseEvent *event) { - if (!(event->button() & Qt::LeftButton) || this->pressedSlider == -1) { - event->ignore(); - return; - } - - emit valueChanged(this->pressedSlider, - this->slider[this->pressedSlider]->value); - this->pressedSlider = -1; - - event->accept(); -} - -/// \brief Paint the widget. -/// \param event The paint event that should be handled. -void LevelSlider::paintEvent(QPaintEvent *event) { - QPainter painter(this); - - Qt::Alignment alignment; - switch (this->_direction) { - case Qt::LeftArrow: - alignment = Qt::AlignLeft | Qt::AlignBottom; - break; - case Qt::UpArrow: - alignment = Qt::AlignTop | Qt::AlignHCenter; - break; - case Qt::DownArrow: - alignment = Qt::AlignBottom | Qt::AlignHCenter; - break; - default: - alignment = Qt::AlignRight | Qt::AlignBottom; - } - - QList::iterator slider = this->slider.end(); - while (slider != this->slider.begin()) { - --slider; - - if (!(*slider)->visible) - continue; - - painter.setPen((*slider)->color); - - if ((*slider)->text.isEmpty()) { - int needlePoints[6]; - - switch (this->_direction) { - case Qt::LeftArrow: - needlePoints[0] = (*slider)->rect.left() + 4; - needlePoints[1] = (*slider)->rect.top(); - needlePoints[2] = (*slider)->rect.left() + 1; - needlePoints[3] = (*slider)->rect.top() + 3; - needlePoints[4] = (*slider)->rect.left() + 4; - needlePoints[5] = (*slider)->rect.top() + 6; - break; - case Qt::UpArrow: - needlePoints[0] = (*slider)->rect.left(); - needlePoints[1] = (*slider)->rect.top() + 4; - needlePoints[2] = (*slider)->rect.left() + 3; - needlePoints[3] = (*slider)->rect.top() + 1; - needlePoints[4] = (*slider)->rect.left() + 6; - needlePoints[5] = (*slider)->rect.top() + 4; - break; - case Qt::DownArrow: - needlePoints[0] = (*slider)->rect.left(); - needlePoints[1] = (*slider)->rect.top() + this->sliderWidth - 5; - needlePoints[2] = (*slider)->rect.left() + 3; - needlePoints[3] = (*slider)->rect.top() + this->sliderWidth - 2; - needlePoints[4] = (*slider)->rect.left() + 6; - needlePoints[5] = (*slider)->rect.top() + this->sliderWidth - 5; - break; - default: - needlePoints[0] = (*slider)->rect.left() + this->sliderWidth - 5; - needlePoints[1] = (*slider)->rect.top(); - needlePoints[2] = (*slider)->rect.left() + this->sliderWidth - 2; - needlePoints[3] = (*slider)->rect.top() + 3; - needlePoints[4] = (*slider)->rect.left() + this->sliderWidth - 5; - needlePoints[5] = (*slider)->rect.top() + 6; - } - - painter.setBrush(QBrush((*slider)->color, Qt::SolidPattern)); - painter.drawPolygon(QPolygon(3, needlePoints)); - painter.setBrush(Qt::NoBrush); - } else { - // Get rect for text and draw needle - QRect textRect = (*slider)->rect; - if (this->_direction == Qt::UpArrow || - this->_direction == Qt::DownArrow) { - textRect.setRight(textRect.right() - 1); - if (this->_direction == Qt::UpArrow) { - textRect.setTop(textRect.top() + 1); - painter.drawLine((*slider)->rect.right(), 0, (*slider)->rect.right(), - 7); - } else { - textRect.setBottom(textRect.bottom() - 1); - painter.drawLine((*slider)->rect.right(), this->sliderWidth - 8, - (*slider)->rect.right(), this->sliderWidth - 1); - } - } else { - textRect.setBottom(textRect.bottom() - 1); - if (this->_direction == Qt::LeftArrow) { - textRect.setLeft(textRect.left() + 1); - painter.drawLine(0, (*slider)->rect.bottom(), 7, - (*slider)->rect.bottom()); - } else { - textRect.setRight(textRect.right() - 1); - painter.drawLine(this->sliderWidth - 8, (*slider)->rect.bottom(), - this->sliderWidth - 1, (*slider)->rect.bottom()); - } - } - // Draw text - painter.drawText(textRect, alignment, (*slider)->text); - } - } - - event->accept(); -} - -/// \brief Resize the widget and adapt the slider positions. -/// \param event The resize event that should be handled. -void LevelSlider::resizeEvent(QResizeEvent *event) { - Q_UNUSED(event); - - for (int sliderId = 0; sliderId < this->slider.count(); ++sliderId) - this->calculateRect(sliderId); - - this->repaint(); -} - -/// \brief Calculate the drawing area for the slider for it's current value. -/// \param sliderId The id of the slider whose rect should be calculated. -/// \return The calculated rect. -QRect LevelSlider::calculateRect(int sliderId) { - // Is it a vertical slider? - if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { - // Is it a triangular needle? - if (this->slider[sliderId]->text.isEmpty()) { - this->slider[sliderId]->rect = - QRect(0, // Start at the left side - // The needle should be center-aligned, 0.5 pixel offset for - // exact pixelization - (long)((double)(this->height() - this->_preMargin - - this->_postMargin - 1) * - (this->slider[sliderId]->maximum - - this->slider[sliderId]->value) / - (this->slider[sliderId]->maximum - - this->slider[sliderId]->minimum) + - 0.5f) + - this->_preMargin - 3, - this->sliderWidth, // Fill the whole width - 7 // The needle is 7 px wide - ); - } - // Or a thin needle with text? - else { - this->slider[sliderId]->rect = - QRect(0, // Start at the left side - // The needle is at the bottom, the text above it, 0.5 pixel - // offset for exact pixelization - (long)((double)(this->height() - this->_preMargin - - this->_postMargin - 1) * - (this->slider[sliderId]->maximum - - this->slider[sliderId]->value) / - (this->slider[sliderId]->maximum - - this->slider[sliderId]->minimum) + - 0.5f), - this->sliderWidth, // Fill the whole width - this->preMargin() + 1 // Use the full margin - ); - } - } - // Or a horizontal slider? - else { - // Is it a triangular needle? - if (this->slider[sliderId]->text.isEmpty()) { - this->slider[sliderId]->rect = QRect( - // The needle should be center-aligned, 0.5 pixel offset for exact - // pixelization - (long)((double)(this->width() - this->_preMargin - this->_postMargin - - 1) * - (this->slider[sliderId]->value - - this->slider[sliderId]->minimum) / - (this->slider[sliderId]->maximum - - this->slider[sliderId]->minimum) + - 0.5f) + - this->_preMargin - 3, - 0, // Start at the top - 7, // The needle is 7 px wide - this->sliderWidth // Fill the whole height - ); - } - // Or a thin needle with text? - else { - int sliderLength = - this->fontMetrics().size(0, this->slider[sliderId]->text).width() + 2; - this->slider[sliderId]->rect = QRect( - // The needle is at the right side, the text before it, 0.5 pixel - // offset for exact pixelization - (long)((double)(this->width() - this->_preMargin - this->_postMargin - - 1) * - (this->slider[sliderId]->value - - this->slider[sliderId]->minimum) / - (this->slider[sliderId]->maximum - - this->slider[sliderId]->minimum) + - 0.5f) + - this->_preMargin - sliderLength + 1, - 0, // Start at the top - sliderLength, // The width depends on the text - this->sliderWidth // Fill the whole height - ); - } - } - - return this->slider[sliderId]->rect; -} - -/// \brief Search for the widest slider element. -/// \return The calculated width of the slider. -int LevelSlider::calculateWidth() { - // At least 8 px for the needles - this->sliderWidth = 8; - - // Is it a vertical slider? - if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { - for (QList::iterator slider = this->slider.begin(); - slider != this->slider.end(); ++slider) { - int sliderWidth = this->fontMetrics().size(0, (*slider)->text).width(); - if (sliderWidth > this->sliderWidth) - this->sliderWidth = sliderWidth; - } - } - // Or a horizontal slider? - else { - for (QList::iterator slider = this->slider.begin(); - slider != this->slider.end(); ++slider) { - int sliderWidth = this->fontMetrics().size(0, (*slider)->text).height(); - if (sliderWidth > this->sliderWidth) - this->sliderWidth = sliderWidth; - } - } - - return this->sliderWidth; -} - -/// \brief Fix the value if it's outside the limits. -/// \param index The index of the slider who should be fixed. -/// \return 0 when ok, -1 on error, 1 when increased and 2 when decreased. -int LevelSlider::fixValue(int index) { - if (index < 0 || index >= this->slider.count()) - return -1; - - double lowest = - qMin(this->slider[index]->minimum, this->slider[index]->maximum); - double highest = - qMax(this->slider[index]->minimum, this->slider[index]->maximum); - if (this->slider[index]->value < lowest) { - this->slider[index]->value = lowest; - return 1; - } else if (this->slider[index]->value > highest) { - this->slider[index]->value = highest; - return 2; - } - return 0; -} diff --git a/openhantek/src/levelslider.h b/openhantek/src/levelslider.h deleted file mode 100644 index cc0dd0d..0000000 --- a/openhantek/src/levelslider.h +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -/// \file levelslider.h -/// \brief Declares the LevelSlider class. -// -// Copyright (C) 2010 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef LEVELSLIDER_H -#define LEVELSLIDER_H - -#include - -class QColor; - -//////////////////////////////////////////////////////////////////////////////// -/// \struct LevelSliderParameters levelslider.h -/// \brief Contains the color, text and value of one slider. -struct LevelSliderParameters { - QColor color; ///< The color of the slider and font - QString text; ///< The text beside the slider, a empty string disables text - bool visible; ///< Visibility of the slider - - double minimum; ///< Minimum (left/top) value for the slider - double maximum; ///< Maximum (right/bottom) value for the slider - double step; ///< The distance between selectable slider positions - double value; ///< The current value of the slider - - // Needed for moving and drawing - QRect rect; ///< The area where the slider is drawn -}; - -//////////////////////////////////////////////////////////////////////////////// -/// \class LevelSlider levelslider.h -/// \brief Slider widget for multiple level sliders. -/// These are used for the trigger levels, offsets and so on. -class LevelSlider : public QWidget { - Q_OBJECT - -public: - LevelSlider(Qt::ArrowType direction = Qt::RightArrow, QWidget *parent = 0); - ~LevelSlider(); - - QSize sizeHint() const; - - int preMargin() const; - int postMargin() const; - - int addSlider(int index = -1); - int addSlider(QString text, int index = -1); - int removeSlider(int index = -1); - - // Parameters for a specific slider - const QColor color(int index) const; - int setColor(int index, QColor color); - const QString text(int index) const; - int setText(int index, QString text); - bool visible(int index) const; - int setVisible(int index, bool visible); - - double minimum(int index) const; - double maximum(int index) const; - int setLimits(int index, double minimum, double maximum); - double step(int index) const; - double setStep(int index, double step); - double value(int index) const; - double setValue(int index, double value); - - // Parameters for all sliders - Qt::ArrowType direction() const; - int setDirection(Qt::ArrowType direction); - -protected: - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *event); - - QRect calculateRect(int sliderId); - int calculateWidth(); - int fixValue(int index); - - QList slider; ///< The parameters for each slider - int pressedSlider; ///< The currently pressed (moved) slider - int sliderWidth; ///< The slider width (dimension orthogonal to the sliding - ///direction) - - Qt::ArrowType _direction; ///< The direction the sliders point to - int _preMargin; ///< The margin before the minimum slider position - int _postMargin; ///< The margin after the maximum slider position - -signals: - void valueChanged(int index, - double value); ///< The value of a slider has changed -}; - -#endif diff --git a/openhantek/src/sispinbox.cpp b/openhantek/src/sispinbox.cpp deleted file mode 100644 index 0e486ed..0000000 --- a/openhantek/src/sispinbox.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -// sispinbox.cpp -// -// Copyright (C) 2012 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#include -#include - -#include "sispinbox.h" - -#include "utils/printutils.h" - -//////////////////////////////////////////////////////////////////////////////// -// class OpenHantekMainWindow -/// \brief Initializes the SiSpinBox internals. -/// \param parent The parent widget. -SiSpinBox::SiSpinBox(QWidget *parent) : QDoubleSpinBox(parent) { this->init(); } - -/// \brief Initializes the SiSpinBox, allowing the user to choose the unit. -/// \param unit The unit shown for the value in the spin box. -/// \param parent The parent widget. -SiSpinBox::SiSpinBox(Unit unit, QWidget *parent) - : QDoubleSpinBox(parent) { - this->init(); - - this->setUnit(unit); -} - -/// \brief Cleans up the main window. -SiSpinBox::~SiSpinBox() {} - -/// \brief Validates the text after user input. -/// \param input The content of the text box. -/// \param pos The position of the cursor in the text box. -/// \return Validity of the current text. -QValidator::State SiSpinBox::validate(QString &input, int &pos) const { - Q_UNUSED(pos); - - bool ok; - double value = stringToValue(input, this->unit, &ok); - - if (!ok) - return QValidator::Invalid; - - if (input == this->textFromValue(value)) - return QValidator::Acceptable; - return QValidator::Intermediate; -} - -/// \brief Parse value from input text. -/// \param text The content of the text box. -/// \return Value in base unit. -double SiSpinBox::valueFromText(const QString &text) const { - return stringToValue(text, this->unit); -} - -/// \brief Get string representation of value. -/// \param val Value in base unit. -/// \return String representation containing value and (prefix+)unit. -QString SiSpinBox::textFromValue(double val) const { - return valueToString(val, this->unit, -1) + this->unitPostfix; -} - -/// \brief Fixes the text after the user finished changing it. -/// \param input The content of the text box. -void SiSpinBox::fixup(QString &input) const { - bool ok; - double value = stringToValue(input, this->unit, &ok); - - if (!ok) - value = this->value(); - - input = this->textFromValue(value); -} - -/// \brief Increase/decrease the values in fixed steps. -/// \param steps The number of steps, positive means increase. -void SiSpinBox::stepBy(int steps) { - double stepsSpan = this->steps.last() / this->steps.first(); - int stepsCount = this->steps.size() - 1; - double value = 0; - - // Skip if we are already at a limit or if steps is null - if (steps == 0 || (steps < 0 && this->value() <= this->minimum()) || - (steps > 0 && this->value() >= this->maximum())) { - return; - } - - if (!this->steppedTo) { // No step done directly before this one, so we need - // to check where we are - // Get how often the steps have to be fully ran through - int stepsFully = (this->mode == 0) - ? (int)floor(log(this->value() / this->steps.first()) / - log(stepsSpan)) - : 0; - // And now the remaining multiple - double stepMultiple = (this->mode == 0) - ? this->value() / pow(stepsSpan, stepsFully) - : this->value() / this->minimum(); - // Now get the neighbours of the current value from our steps list - int remainingSteps = 0; - for (; remainingSteps <= stepsCount; ++remainingSteps) { - if (this->steps[remainingSteps] > stepMultiple) - break; - } - if (remainingSteps > - 0) // Shouldn't happen, but double may have rounding errors - --remainingSteps; - this->stepId = stepsFully * stepsCount + remainingSteps; - // We need to do one step less down if we are inbetween two of them since - // our step is lower than the value - if (steps < 0 && this->steps[remainingSteps] < stepMultiple) - ++this->stepId; - } - - int subStep = steps / abs(steps); - for (int i = 0; i != steps; i += subStep) { - this->stepId += subStep; - if (!this->mode) { - int stepsId = this->stepId % stepsCount; - if (stepsId < 0) - stepsId += stepsCount; - value = pow(stepsSpan, floor((double)this->stepId / stepsCount)) * - this->steps[stepsId]; - } else { - value = this->minimum() * this->steps[stepId]; - } - if (value <= this->minimum() || value >= this->maximum()) - break; - } - this->setValue(value); - value = this->value(); - this->steppedTo = true; -} - -/// \brief Set the unit for this spin box. -/// \param unit The unit shown for the value in the spin box. -/// \return true on success, false on invalid unit. -bool SiSpinBox::setUnit(Unit unit) { - if ((unsigned int)unit >= UNIT_COUNT) - return false; - - this->unit = unit; - return true; -} - -/// \brief Set the unit postfix for this spin box. -/// \param postfix the string shown after the unit in the spin box. -void SiSpinBox::setUnitPostfix(const QString &postfix) { - this->unitPostfix = postfix; -} - -/// \brief Set the steps the spin box will take. -/// \param steps The steps, will be extended with the ratio from the start after -/// the last element. -void SiSpinBox::setSteps(const QList &steps) { this->steps = steps; } - -/// \brief Set the mode. -/// \param mode The mode, the value 0 will have fixed interval, otherwise the -/// value will have interval within steps itself. -void SiSpinBox::setMode(const int mode) { this->mode = mode; } - -/// \brief Generic initializations. -void SiSpinBox::init() { - this->setMinimum(1e-12); - this->setMaximum(1e12); - this->setValue(1.0); - this->setDecimals(DBL_MAX_10_EXP + DBL_DIG); // Disable automatic rounding - this->unit = unit; - this->steps << 1.0 << 2.0 << 5.0 << 10.0; - - this->steppedTo = false; - this->stepId = 0; - this->mode = 0; - - connect(this, SIGNAL(valueChanged(double)), this, SLOT(resetSteppedTo())); -} - -/// \brief Resets the ::steppedTo flag after the value has been changed. -void SiSpinBox::resetSteppedTo() { this->steppedTo = false; } diff --git a/openhantek/src/sispinbox.h b/openhantek/src/sispinbox.h deleted file mode 100644 index d6a8ecc..0000000 --- a/openhantek/src/sispinbox.h +++ /dev/null @@ -1,74 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// -// OpenHantek -/// \file sispinbox.h -/// \brief Declares the SiSpinBox class. -// -// Copyright (C) 2010, 2011 Oliver Haag -// oliver.haag@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 3 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, see . -// -//////////////////////////////////////////////////////////////////////////////// - -#ifndef SISPINBOX_H -#define SISPINBOX_H - -#include -#include - -#include "utils/printutils.h" - -//////////////////////////////////////////////////////////////////////////////// -/// \class SiSpinBox sispinbox.h -/// \brief A spin box with SI prefix support. -/// This spin box supports the SI prefixes (k/M/G/T) after its value and allows -/// floating point values. The step size is increasing in an exponential way, to -/// keep the percentual difference between the steps at equal levels. -class SiSpinBox : public QDoubleSpinBox { - Q_OBJECT - -public: - explicit SiSpinBox(QWidget *parent = 0); - SiSpinBox(Unit unit, QWidget *parent = 0); - ~SiSpinBox(); - - QValidator::State validate(QString &input, int &pos) const; - double valueFromText(const QString &text) const; - QString textFromValue(double val) const; - void fixup(QString &input) const; - void stepBy(int steps); - bool setUnit(Unit unit); - void setUnitPostfix(const QString &postfix); - void setSteps(const QList &steps); - void setMode(const int mode); - -private: - void init(); - - Unit unit; ///< The SI unit used for this spin box - QString unitPostfix; ///< Shown after the unit - QList steps; ///< The steps, begins from start after last element - int mode; ///< The mode, fixed or constant - - bool steppedTo; ///< true, if the current value was reached using stepBy - int stepId; ///< The index of the last step reached using stepBy - -signals: - -private slots: - void resetSteppedTo(); -}; - -#endif diff --git a/openhantek/src/widgets/colorbox.cpp b/openhantek/src/widgets/colorbox.cpp new file mode 100644 index 0000000..9027acc --- /dev/null +++ b/openhantek/src/widgets/colorbox.cpp @@ -0,0 +1,69 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +// colorbox.cpp +// +// Copyright (C) 2010 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "colorbox.h" + +//////////////////////////////////////////////////////////////////////////////// +// class ColorBox +/// \brief Initializes the widget. +/// \param color Initial color value. +/// \param parent The parent widget. +ColorBox::ColorBox(QColor color, QWidget *parent) : QPushButton(parent) { + this->setColor(color); + + connect(this, SIGNAL(clicked()), this, SLOT(waitForColor())); +} + +/// \brief Cleans up the widget. +ColorBox::~ColorBox() {} + +/// \brief Get the current color. +/// \return The current color as QColor. +const QColor ColorBox::getColor() { return this->color; } + +/// \brief Sets the color. +/// \param color The new color. +void ColorBox::setColor(QColor color) { + this->color = color; + this->setText( + QString("#%1").arg((unsigned int)this->color.rgba(), 8, 16, QChar('0'))); + this->setPalette(QPalette(this->color)); + + emit colorChanged(this->color); +} + +/// \brief Wait for the color dialog and apply chosen color. +void ColorBox::waitForColor() { + this->setFocus(); + this->setDown(true); + + QColor color = QColorDialog::getColor(this->color, this, 0, + QColorDialog::ShowAlphaChannel); + + if (color.isValid()) + this->setColor(color); +} diff --git a/openhantek/src/widgets/colorbox.h b/openhantek/src/widgets/colorbox.h new file mode 100644 index 0000000..9b84c87 --- /dev/null +++ b/openhantek/src/widgets/colorbox.h @@ -0,0 +1,54 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +/// \file colorbox.h +/// \brief Declares the ColorBox class. +// +// Copyright (C) 2010 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef COLORBOX_H +#define COLORBOX_H + +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +/// \class ColorBox colorbox.h +/// \brief A widget for the selection of a color. +class ColorBox : public QPushButton { + Q_OBJECT + +public: + ColorBox(QColor color, QWidget *parent = 0); + ~ColorBox(); + + const QColor getColor(); + +public slots: + void setColor(QColor color); + void waitForColor(); + +private: + QColor color; + +signals: + void colorChanged(QColor color); ///< The color has been changed +}; + +#endif diff --git a/openhantek/src/widgets/levelslider.cpp b/openhantek/src/widgets/levelslider.cpp new file mode 100644 index 0000000..664abea --- /dev/null +++ b/openhantek/src/widgets/levelslider.cpp @@ -0,0 +1,628 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +// levelslider.cpp +// +// Copyright (C) 2010 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#include + +#include +#include +#include + +#include "levelslider.h" + +//////////////////////////////////////////////////////////////////////////////// +// class LevelSlider +/// \brief Initializes the slider container. +/// \param direction The side on which the sliders are shown. +/// \param parent The parent widget. +LevelSlider::LevelSlider(Qt::ArrowType direction, QWidget *parent) + : QWidget(parent) { + QFont font = this->font(); + font.setPointSize(font.pointSize() * 0.8); + this->setFont(font); + + this->pressedSlider = -1; + this->sliderWidth = 8; + + this->setDirection(direction); +} + +/// \brief Cleans up the widget. +LevelSlider::~LevelSlider() {} + +/// \brief Return the margin before the slider. +/// \return The margin the Slider has at the top/left. +int LevelSlider::preMargin() const { return this->_preMargin; } + +/// \brief Return the margin after the slider. +/// \return The margin the Slider has at the bottom/right. +int LevelSlider::postMargin() const { return this->_postMargin; } + +/// \brief Add a new slider to the slider container. +/// \param index The index where the slider should be inserted, 0 to append. +/// \return The index of the slider, -1 on error. +int LevelSlider::addSlider(int index) { return this->addSlider(0, index); } + +/// \brief Add a new slider to the slider container. +/// \param text The text that will be shown next to the slider. +/// \param index The index where the slider should be inserted, 0 to append. +/// \return The index of the slider, -1 on error. +int LevelSlider::addSlider(QString text, int index) { + if (index < -1) + return -1; + + LevelSliderParameters *parameters = new LevelSliderParameters; + parameters->color = Qt::white; + parameters->minimum = 0x00; + parameters->maximum = 0xff; + parameters->value = 0x00; + parameters->visible = false; + + if (index == -1) { + this->slider.append(parameters); + index = this->slider.count() - 1; + } else + this->slider.insert(index, parameters); + + this->setText(index, text); + + return index; +} + +/// \brief Remove a slider from the slider container. +/// \param index The index of the slider that should be removed. +/// \return The index of the removed slider, -1 on error. +int LevelSlider::removeSlider(int index) { + if (index < -1) + return -1; + + if (index == -1) { + this->slider.removeLast(); + index = this->slider.count(); + } else { + this->slider.removeAt(index); + } + + this->calculateWidth(); + + return index; +} + +/// \brief Size hint for the widget. +/// \return The recommended size for the widget. +QSize LevelSlider::sizeHint() const { + if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) + return QSize(this->sliderWidth, 16); + else + return QSize(16, this->sliderWidth); +} + +/// \brief Return the color of a slider. +/// \param index The index of the slider whose color should be returned. +/// \return The current color of the slider. +const QColor LevelSlider::color(int index) const { + if (index < 0 || index >= this->slider.count()) + return Qt::black; + + return this->slider[index]->color; +} + +/// \brief Set the color of the slider. +/// \param index The index of the slider whose color should be set. +/// \param color The new color for the slider. +/// \return The index of the slider, -1 on error. +int LevelSlider::setColor(int index, QColor color) { + if (index < 0 || index >= this->slider.count()) + return -1; + + this->slider[index]->color = color; + this->repaint(); + + return index; +} + +/// \brief Return the text shown beside a slider. +/// \param index The index of the slider whose text should be returned. +/// \return The current text of the slider. +const QString LevelSlider::text(int index) const { + if (index < 0 || index >= this->slider.count()) + return QString(); + + return this->slider[index]->text; +} + +/// \brief Set the text for a slider. +/// \param index The index of the slider whose text should be set. +/// \param text The text shown next to the slider. +/// \return The index of the slider, -1 on error. +int LevelSlider::setText(int index, QString text) { + if (index < 0 || index >= this->slider.count()) + return -1; + + this->slider[index]->text = text; + this->calculateWidth(); + + return index; +} + +/// \brief Return the visibility of a slider. +/// \param index The index of the slider whose visibility should be returned. +/// \return true if the slider is visible, false if it's hidden. +bool LevelSlider::visible(int index) const { + if (index < 0 || index >= this->slider.count()) + return false; + + return this->slider[index]->visible; +} + +/// \brief Set the visibility of a slider. +/// \param index The index of the slider whose visibility should be set. +/// \param visible true to show the slider, false to hide it. +/// \return The index of the slider, -1 on error. +int LevelSlider::setVisible(int index, bool visible) { + if (index < 0 || index >= this->slider.count()) + return -1; + + this->slider[index]->visible = visible; + this->repaint(); + + return index; +} + +/// \brief Return the minimal value of the sliders. +/// \return The value a slider has at the bottommost/leftmost position. +double LevelSlider::minimum(int index) const { + if (index < 0 || index >= this->slider.count()) + return -1; + + return this->slider[index]->minimum; +} + +/// \brief Return the maximal value of the sliders. +/// \return The value a slider has at the topmost/rightmost position. +double LevelSlider::maximum(int index) const { + if (index < 0 || index >= this->slider.count()) + return -1; + + return this->slider[index]->maximum; +} + +/// \brief Set the maximal value of the sliders. +/// \param index The index of the slider whose limits should be set. +/// \param minimum The value a slider has at the bottommost/leftmost position. +/// \param maximum The value a slider has at the topmost/rightmost position. +/// \return -1 on error, fixValue result on success. +int LevelSlider::setLimits(int index, double minimum, double maximum) { + if (index < 0 || index >= this->slider.count()) + return -1; + + this->slider[index]->minimum = minimum; + this->slider[index]->maximum = maximum; + int result = this->fixValue(index); + + this->calculateRect(index); + this->repaint(); + + return result; +} + +/// \brief Return the step width of the sliders. +/// \param index The index of the slider whose step width should be returned. +/// \return The distance between the selectable slider positions. +double LevelSlider::step(int index) const { + if (index < 0 || index >= this->slider.count()) + return -1; + + return this->slider[index]->step; +} + +/// \brief Set the step width of the sliders. +/// \param index The index of the slider whose step width should be set. +/// \param step The distance between the selectable slider positions. +/// \return The new step width. +double LevelSlider::setStep(int index, double step) { + if (index < 0 || index >= this->slider.count()) + return -1; + + if (step > 0) + this->slider[index]->step = step; + + return this->slider[index]->step; +} + +/// \brief Return the current position of a slider. +/// \param index The index of the slider whose value should be returned. +/// \return The value of the slider. +double LevelSlider::value(int index) const { + if (index < 0 || index >= this->slider.count()) + return -1; + + return this->slider[index]->value; +} + +/// \brief Set the current position of a slider. +/// \param index The index of the slider whose value should be set. +/// \param value The new value of the slider. +/// \return The new value of the slider. +double LevelSlider::setValue(int index, double value) { + if (index < 0 || index >= this->slider.count()) + return -1; + + // Apply new value + this->slider[index]->value = value; + this->fixValue(index); + + this->calculateRect(index); + this->repaint(); + + if (this->pressedSlider < 0) + emit valueChanged(index, value); + + return this->slider[index]->value; +} + +/// \brief Return the direction of the sliders. +/// \return The side on which the sliders are shown. +Qt::ArrowType LevelSlider::direction() const { return this->_direction; } + +/// \brief Set the direction of the sliders. +/// \param direction The side on which the sliders are shown. +/// \return The index of the direction, -1 on error. +int LevelSlider::setDirection(Qt::ArrowType direction) { + if (direction < Qt::UpArrow || direction > Qt::RightArrow) + return -1; + + this->_direction = direction; + + if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { + this->_preMargin = this->fontMetrics().lineSpacing(); + this->_postMargin = 3; + } else { + this->_preMargin = this->fontMetrics().averageCharWidth() * 3; + this->_postMargin = 3; + } + + return this->_direction; +} + +/// \brief Move the slider if it's pressed. +/// \param event The mouse event that should be handled. +void LevelSlider::mouseMoveEvent(QMouseEvent *event) { + if (this->pressedSlider < 0) { + event->ignore(); + return; + } + + // Get new value + double value; + if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) + value = this->slider[pressedSlider]->maximum - + (this->slider[pressedSlider]->maximum - + this->slider[pressedSlider]->minimum) * + ((double)event->y() - this->_preMargin + 0.5) / + (this->height() - this->_preMargin - this->_postMargin - 1); + else + value = this->slider[pressedSlider]->minimum + + (this->slider[pressedSlider]->maximum - + this->slider[pressedSlider]->minimum) * + ((double)event->x() - this->_preMargin + 0.5) / + (this->width() - this->_preMargin - this->_postMargin - 1); + + // Move the slider + if (event->modifiers() & Qt::AltModifier) + // Alt allows every position + this->setValue(this->pressedSlider, value); + else + // Set to nearest possible position + this->setValue(this->pressedSlider, + floor(value / this->slider[pressedSlider]->step + 0.5) * + this->slider[pressedSlider]->step); + + event->accept(); +} + +/// \brief Prepare slider for movement if the left mouse button is pressed. +/// \param event The mouse event that should be handled. +void LevelSlider::mousePressEvent(QMouseEvent *event) { + if (!(event->button() & Qt::LeftButton)) { + event->ignore(); + return; + } + + this->pressedSlider = -1; + for (int sliderId = 0; sliderId < this->slider.count(); ++sliderId) { + if (this->slider[sliderId]->visible && + this->slider[sliderId]->rect.contains(event->pos())) { + this->pressedSlider = sliderId; + break; + } + } + + // Accept event if a slider was pressed + event->setAccepted(this->pressedSlider >= 0); +} + +/// \brief Movement is done if the left mouse button is released. +/// \param event The mouse event that should be handled. +void LevelSlider::mouseReleaseEvent(QMouseEvent *event) { + if (!(event->button() & Qt::LeftButton) || this->pressedSlider == -1) { + event->ignore(); + return; + } + + emit valueChanged(this->pressedSlider, + this->slider[this->pressedSlider]->value); + this->pressedSlider = -1; + + event->accept(); +} + +/// \brief Paint the widget. +/// \param event The paint event that should be handled. +void LevelSlider::paintEvent(QPaintEvent *event) { + QPainter painter(this); + + Qt::Alignment alignment; + switch (this->_direction) { + case Qt::LeftArrow: + alignment = Qt::AlignLeft | Qt::AlignBottom; + break; + case Qt::UpArrow: + alignment = Qt::AlignTop | Qt::AlignHCenter; + break; + case Qt::DownArrow: + alignment = Qt::AlignBottom | Qt::AlignHCenter; + break; + default: + alignment = Qt::AlignRight | Qt::AlignBottom; + } + + QList::iterator slider = this->slider.end(); + while (slider != this->slider.begin()) { + --slider; + + if (!(*slider)->visible) + continue; + + painter.setPen((*slider)->color); + + if ((*slider)->text.isEmpty()) { + int needlePoints[6]; + + switch (this->_direction) { + case Qt::LeftArrow: + needlePoints[0] = (*slider)->rect.left() + 4; + needlePoints[1] = (*slider)->rect.top(); + needlePoints[2] = (*slider)->rect.left() + 1; + needlePoints[3] = (*slider)->rect.top() + 3; + needlePoints[4] = (*slider)->rect.left() + 4; + needlePoints[5] = (*slider)->rect.top() + 6; + break; + case Qt::UpArrow: + needlePoints[0] = (*slider)->rect.left(); + needlePoints[1] = (*slider)->rect.top() + 4; + needlePoints[2] = (*slider)->rect.left() + 3; + needlePoints[3] = (*slider)->rect.top() + 1; + needlePoints[4] = (*slider)->rect.left() + 6; + needlePoints[5] = (*slider)->rect.top() + 4; + break; + case Qt::DownArrow: + needlePoints[0] = (*slider)->rect.left(); + needlePoints[1] = (*slider)->rect.top() + this->sliderWidth - 5; + needlePoints[2] = (*slider)->rect.left() + 3; + needlePoints[3] = (*slider)->rect.top() + this->sliderWidth - 2; + needlePoints[4] = (*slider)->rect.left() + 6; + needlePoints[5] = (*slider)->rect.top() + this->sliderWidth - 5; + break; + default: + needlePoints[0] = (*slider)->rect.left() + this->sliderWidth - 5; + needlePoints[1] = (*slider)->rect.top(); + needlePoints[2] = (*slider)->rect.left() + this->sliderWidth - 2; + needlePoints[3] = (*slider)->rect.top() + 3; + needlePoints[4] = (*slider)->rect.left() + this->sliderWidth - 5; + needlePoints[5] = (*slider)->rect.top() + 6; + } + + painter.setBrush(QBrush((*slider)->color, Qt::SolidPattern)); + painter.drawPolygon(QPolygon(3, needlePoints)); + painter.setBrush(Qt::NoBrush); + } else { + // Get rect for text and draw needle + QRect textRect = (*slider)->rect; + if (this->_direction == Qt::UpArrow || + this->_direction == Qt::DownArrow) { + textRect.setRight(textRect.right() - 1); + if (this->_direction == Qt::UpArrow) { + textRect.setTop(textRect.top() + 1); + painter.drawLine((*slider)->rect.right(), 0, (*slider)->rect.right(), + 7); + } else { + textRect.setBottom(textRect.bottom() - 1); + painter.drawLine((*slider)->rect.right(), this->sliderWidth - 8, + (*slider)->rect.right(), this->sliderWidth - 1); + } + } else { + textRect.setBottom(textRect.bottom() - 1); + if (this->_direction == Qt::LeftArrow) { + textRect.setLeft(textRect.left() + 1); + painter.drawLine(0, (*slider)->rect.bottom(), 7, + (*slider)->rect.bottom()); + } else { + textRect.setRight(textRect.right() - 1); + painter.drawLine(this->sliderWidth - 8, (*slider)->rect.bottom(), + this->sliderWidth - 1, (*slider)->rect.bottom()); + } + } + // Draw text + painter.drawText(textRect, alignment, (*slider)->text); + } + } + + event->accept(); +} + +/// \brief Resize the widget and adapt the slider positions. +/// \param event The resize event that should be handled. +void LevelSlider::resizeEvent(QResizeEvent *event) { + Q_UNUSED(event); + + for (int sliderId = 0; sliderId < this->slider.count(); ++sliderId) + this->calculateRect(sliderId); + + this->repaint(); +} + +/// \brief Calculate the drawing area for the slider for it's current value. +/// \param sliderId The id of the slider whose rect should be calculated. +/// \return The calculated rect. +QRect LevelSlider::calculateRect(int sliderId) { + // Is it a vertical slider? + if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { + // Is it a triangular needle? + if (this->slider[sliderId]->text.isEmpty()) { + this->slider[sliderId]->rect = + QRect(0, // Start at the left side + // The needle should be center-aligned, 0.5 pixel offset for + // exact pixelization + (long)((double)(this->height() - this->_preMargin - + this->_postMargin - 1) * + (this->slider[sliderId]->maximum - + this->slider[sliderId]->value) / + (this->slider[sliderId]->maximum - + this->slider[sliderId]->minimum) + + 0.5f) + + this->_preMargin - 3, + this->sliderWidth, // Fill the whole width + 7 // The needle is 7 px wide + ); + } + // Or a thin needle with text? + else { + this->slider[sliderId]->rect = + QRect(0, // Start at the left side + // The needle is at the bottom, the text above it, 0.5 pixel + // offset for exact pixelization + (long)((double)(this->height() - this->_preMargin - + this->_postMargin - 1) * + (this->slider[sliderId]->maximum - + this->slider[sliderId]->value) / + (this->slider[sliderId]->maximum - + this->slider[sliderId]->minimum) + + 0.5f), + this->sliderWidth, // Fill the whole width + this->preMargin() + 1 // Use the full margin + ); + } + } + // Or a horizontal slider? + else { + // Is it a triangular needle? + if (this->slider[sliderId]->text.isEmpty()) { + this->slider[sliderId]->rect = QRect( + // The needle should be center-aligned, 0.5 pixel offset for exact + // pixelization + (long)((double)(this->width() - this->_preMargin - this->_postMargin - + 1) * + (this->slider[sliderId]->value - + this->slider[sliderId]->minimum) / + (this->slider[sliderId]->maximum - + this->slider[sliderId]->minimum) + + 0.5f) + + this->_preMargin - 3, + 0, // Start at the top + 7, // The needle is 7 px wide + this->sliderWidth // Fill the whole height + ); + } + // Or a thin needle with text? + else { + int sliderLength = + this->fontMetrics().size(0, this->slider[sliderId]->text).width() + 2; + this->slider[sliderId]->rect = QRect( + // The needle is at the right side, the text before it, 0.5 pixel + // offset for exact pixelization + (long)((double)(this->width() - this->_preMargin - this->_postMargin - + 1) * + (this->slider[sliderId]->value - + this->slider[sliderId]->minimum) / + (this->slider[sliderId]->maximum - + this->slider[sliderId]->minimum) + + 0.5f) + + this->_preMargin - sliderLength + 1, + 0, // Start at the top + sliderLength, // The width depends on the text + this->sliderWidth // Fill the whole height + ); + } + } + + return this->slider[sliderId]->rect; +} + +/// \brief Search for the widest slider element. +/// \return The calculated width of the slider. +int LevelSlider::calculateWidth() { + // At least 8 px for the needles + this->sliderWidth = 8; + + // Is it a vertical slider? + if (this->_direction == Qt::RightArrow || this->_direction == Qt::LeftArrow) { + for (QList::iterator slider = this->slider.begin(); + slider != this->slider.end(); ++slider) { + int sliderWidth = this->fontMetrics().size(0, (*slider)->text).width(); + if (sliderWidth > this->sliderWidth) + this->sliderWidth = sliderWidth; + } + } + // Or a horizontal slider? + else { + for (QList::iterator slider = this->slider.begin(); + slider != this->slider.end(); ++slider) { + int sliderWidth = this->fontMetrics().size(0, (*slider)->text).height(); + if (sliderWidth > this->sliderWidth) + this->sliderWidth = sliderWidth; + } + } + + return this->sliderWidth; +} + +/// \brief Fix the value if it's outside the limits. +/// \param index The index of the slider who should be fixed. +/// \return 0 when ok, -1 on error, 1 when increased and 2 when decreased. +int LevelSlider::fixValue(int index) { + if (index < 0 || index >= this->slider.count()) + return -1; + + double lowest = + qMin(this->slider[index]->minimum, this->slider[index]->maximum); + double highest = + qMax(this->slider[index]->minimum, this->slider[index]->maximum); + if (this->slider[index]->value < lowest) { + this->slider[index]->value = lowest; + return 1; + } else if (this->slider[index]->value > highest) { + this->slider[index]->value = highest; + return 2; + } + return 0; +} diff --git a/openhantek/src/widgets/levelslider.h b/openhantek/src/widgets/levelslider.h new file mode 100644 index 0000000..cc0dd0d --- /dev/null +++ b/openhantek/src/widgets/levelslider.h @@ -0,0 +1,115 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +/// \file levelslider.h +/// \brief Declares the LevelSlider class. +// +// Copyright (C) 2010 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LEVELSLIDER_H +#define LEVELSLIDER_H + +#include + +class QColor; + +//////////////////////////////////////////////////////////////////////////////// +/// \struct LevelSliderParameters levelslider.h +/// \brief Contains the color, text and value of one slider. +struct LevelSliderParameters { + QColor color; ///< The color of the slider and font + QString text; ///< The text beside the slider, a empty string disables text + bool visible; ///< Visibility of the slider + + double minimum; ///< Minimum (left/top) value for the slider + double maximum; ///< Maximum (right/bottom) value for the slider + double step; ///< The distance between selectable slider positions + double value; ///< The current value of the slider + + // Needed for moving and drawing + QRect rect; ///< The area where the slider is drawn +}; + +//////////////////////////////////////////////////////////////////////////////// +/// \class LevelSlider levelslider.h +/// \brief Slider widget for multiple level sliders. +/// These are used for the trigger levels, offsets and so on. +class LevelSlider : public QWidget { + Q_OBJECT + +public: + LevelSlider(Qt::ArrowType direction = Qt::RightArrow, QWidget *parent = 0); + ~LevelSlider(); + + QSize sizeHint() const; + + int preMargin() const; + int postMargin() const; + + int addSlider(int index = -1); + int addSlider(QString text, int index = -1); + int removeSlider(int index = -1); + + // Parameters for a specific slider + const QColor color(int index) const; + int setColor(int index, QColor color); + const QString text(int index) const; + int setText(int index, QString text); + bool visible(int index) const; + int setVisible(int index, bool visible); + + double minimum(int index) const; + double maximum(int index) const; + int setLimits(int index, double minimum, double maximum); + double step(int index) const; + double setStep(int index, double step); + double value(int index) const; + double setValue(int index, double value); + + // Parameters for all sliders + Qt::ArrowType direction() const; + int setDirection(Qt::ArrowType direction); + +protected: + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + + QRect calculateRect(int sliderId); + int calculateWidth(); + int fixValue(int index); + + QList slider; ///< The parameters for each slider + int pressedSlider; ///< The currently pressed (moved) slider + int sliderWidth; ///< The slider width (dimension orthogonal to the sliding + ///direction) + + Qt::ArrowType _direction; ///< The direction the sliders point to + int _preMargin; ///< The margin before the minimum slider position + int _postMargin; ///< The margin after the maximum slider position + +signals: + void valueChanged(int index, + double value); ///< The value of a slider has changed +}; + +#endif diff --git a/openhantek/src/widgets/sispinbox.cpp b/openhantek/src/widgets/sispinbox.cpp new file mode 100644 index 0000000..0e486ed --- /dev/null +++ b/openhantek/src/widgets/sispinbox.cpp @@ -0,0 +1,198 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +// sispinbox.cpp +// +// Copyright (C) 2012 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "sispinbox.h" + +#include "utils/printutils.h" + +//////////////////////////////////////////////////////////////////////////////// +// class OpenHantekMainWindow +/// \brief Initializes the SiSpinBox internals. +/// \param parent The parent widget. +SiSpinBox::SiSpinBox(QWidget *parent) : QDoubleSpinBox(parent) { this->init(); } + +/// \brief Initializes the SiSpinBox, allowing the user to choose the unit. +/// \param unit The unit shown for the value in the spin box. +/// \param parent The parent widget. +SiSpinBox::SiSpinBox(Unit unit, QWidget *parent) + : QDoubleSpinBox(parent) { + this->init(); + + this->setUnit(unit); +} + +/// \brief Cleans up the main window. +SiSpinBox::~SiSpinBox() {} + +/// \brief Validates the text after user input. +/// \param input The content of the text box. +/// \param pos The position of the cursor in the text box. +/// \return Validity of the current text. +QValidator::State SiSpinBox::validate(QString &input, int &pos) const { + Q_UNUSED(pos); + + bool ok; + double value = stringToValue(input, this->unit, &ok); + + if (!ok) + return QValidator::Invalid; + + if (input == this->textFromValue(value)) + return QValidator::Acceptable; + return QValidator::Intermediate; +} + +/// \brief Parse value from input text. +/// \param text The content of the text box. +/// \return Value in base unit. +double SiSpinBox::valueFromText(const QString &text) const { + return stringToValue(text, this->unit); +} + +/// \brief Get string representation of value. +/// \param val Value in base unit. +/// \return String representation containing value and (prefix+)unit. +QString SiSpinBox::textFromValue(double val) const { + return valueToString(val, this->unit, -1) + this->unitPostfix; +} + +/// \brief Fixes the text after the user finished changing it. +/// \param input The content of the text box. +void SiSpinBox::fixup(QString &input) const { + bool ok; + double value = stringToValue(input, this->unit, &ok); + + if (!ok) + value = this->value(); + + input = this->textFromValue(value); +} + +/// \brief Increase/decrease the values in fixed steps. +/// \param steps The number of steps, positive means increase. +void SiSpinBox::stepBy(int steps) { + double stepsSpan = this->steps.last() / this->steps.first(); + int stepsCount = this->steps.size() - 1; + double value = 0; + + // Skip if we are already at a limit or if steps is null + if (steps == 0 || (steps < 0 && this->value() <= this->minimum()) || + (steps > 0 && this->value() >= this->maximum())) { + return; + } + + if (!this->steppedTo) { // No step done directly before this one, so we need + // to check where we are + // Get how often the steps have to be fully ran through + int stepsFully = (this->mode == 0) + ? (int)floor(log(this->value() / this->steps.first()) / + log(stepsSpan)) + : 0; + // And now the remaining multiple + double stepMultiple = (this->mode == 0) + ? this->value() / pow(stepsSpan, stepsFully) + : this->value() / this->minimum(); + // Now get the neighbours of the current value from our steps list + int remainingSteps = 0; + for (; remainingSteps <= stepsCount; ++remainingSteps) { + if (this->steps[remainingSteps] > stepMultiple) + break; + } + if (remainingSteps > + 0) // Shouldn't happen, but double may have rounding errors + --remainingSteps; + this->stepId = stepsFully * stepsCount + remainingSteps; + // We need to do one step less down if we are inbetween two of them since + // our step is lower than the value + if (steps < 0 && this->steps[remainingSteps] < stepMultiple) + ++this->stepId; + } + + int subStep = steps / abs(steps); + for (int i = 0; i != steps; i += subStep) { + this->stepId += subStep; + if (!this->mode) { + int stepsId = this->stepId % stepsCount; + if (stepsId < 0) + stepsId += stepsCount; + value = pow(stepsSpan, floor((double)this->stepId / stepsCount)) * + this->steps[stepsId]; + } else { + value = this->minimum() * this->steps[stepId]; + } + if (value <= this->minimum() || value >= this->maximum()) + break; + } + this->setValue(value); + value = this->value(); + this->steppedTo = true; +} + +/// \brief Set the unit for this spin box. +/// \param unit The unit shown for the value in the spin box. +/// \return true on success, false on invalid unit. +bool SiSpinBox::setUnit(Unit unit) { + if ((unsigned int)unit >= UNIT_COUNT) + return false; + + this->unit = unit; + return true; +} + +/// \brief Set the unit postfix for this spin box. +/// \param postfix the string shown after the unit in the spin box. +void SiSpinBox::setUnitPostfix(const QString &postfix) { + this->unitPostfix = postfix; +} + +/// \brief Set the steps the spin box will take. +/// \param steps The steps, will be extended with the ratio from the start after +/// the last element. +void SiSpinBox::setSteps(const QList &steps) { this->steps = steps; } + +/// \brief Set the mode. +/// \param mode The mode, the value 0 will have fixed interval, otherwise the +/// value will have interval within steps itself. +void SiSpinBox::setMode(const int mode) { this->mode = mode; } + +/// \brief Generic initializations. +void SiSpinBox::init() { + this->setMinimum(1e-12); + this->setMaximum(1e12); + this->setValue(1.0); + this->setDecimals(DBL_MAX_10_EXP + DBL_DIG); // Disable automatic rounding + this->unit = unit; + this->steps << 1.0 << 2.0 << 5.0 << 10.0; + + this->steppedTo = false; + this->stepId = 0; + this->mode = 0; + + connect(this, SIGNAL(valueChanged(double)), this, SLOT(resetSteppedTo())); +} + +/// \brief Resets the ::steppedTo flag after the value has been changed. +void SiSpinBox::resetSteppedTo() { this->steppedTo = false; } diff --git a/openhantek/src/widgets/sispinbox.h b/openhantek/src/widgets/sispinbox.h new file mode 100644 index 0000000..d6a8ecc --- /dev/null +++ b/openhantek/src/widgets/sispinbox.h @@ -0,0 +1,74 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// OpenHantek +/// \file sispinbox.h +/// \brief Declares the SiSpinBox class. +// +// Copyright (C) 2010, 2011 Oliver Haag +// oliver.haag@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 3 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, see . +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef SISPINBOX_H +#define SISPINBOX_H + +#include +#include + +#include "utils/printutils.h" + +//////////////////////////////////////////////////////////////////////////////// +/// \class SiSpinBox sispinbox.h +/// \brief A spin box with SI prefix support. +/// This spin box supports the SI prefixes (k/M/G/T) after its value and allows +/// floating point values. The step size is increasing in an exponential way, to +/// keep the percentual difference between the steps at equal levels. +class SiSpinBox : public QDoubleSpinBox { + Q_OBJECT + +public: + explicit SiSpinBox(QWidget *parent = 0); + SiSpinBox(Unit unit, QWidget *parent = 0); + ~SiSpinBox(); + + QValidator::State validate(QString &input, int &pos) const; + double valueFromText(const QString &text) const; + QString textFromValue(double val) const; + void fixup(QString &input) const; + void stepBy(int steps); + bool setUnit(Unit unit); + void setUnitPostfix(const QString &postfix); + void setSteps(const QList &steps); + void setMode(const int mode); + +private: + void init(); + + Unit unit; ///< The SI unit used for this spin box + QString unitPostfix; ///< Shown after the unit + QList steps; ///< The steps, begins from start after last element + int mode; ///< The mode, fixed or constant + + bool steppedTo; ///< true, if the current value was reached using stepBy + int stepId; ///< The index of the last step reached using stepBy + +signals: + +private slots: + void resetSteppedTo(); +}; + +#endif -- libgit2 0.21.4