diff --git a/ground/gcs/src/plugins/pfdqml/fonts/PTS75F.ttf b/ground/gcs/src/libs/utils/fonts/PTS75F.ttf similarity index 100% rename from ground/gcs/src/plugins/pfdqml/fonts/PTS75F.ttf rename to ground/gcs/src/libs/utils/fonts/PTS75F.ttf diff --git a/ground/gcs/src/plugins/pfdqml/fonts/Paratype PT Sans Free Font License.txt b/ground/gcs/src/libs/utils/fonts/Paratype PT Sans Free Font License.txt similarity index 100% rename from ground/gcs/src/plugins/pfdqml/fonts/Paratype PT Sans Free Font License.txt rename to ground/gcs/src/libs/utils/fonts/Paratype PT Sans Free Font License.txt diff --git a/ground/gcs/src/libs/utils/textbubbleslider.cpp b/ground/gcs/src/libs/utils/textbubbleslider.cpp new file mode 100644 index 000000000..b3ee79bad --- /dev/null +++ b/ground/gcs/src/libs/utils/textbubbleslider.cpp @@ -0,0 +1,199 @@ +/** + ****************************************************************************** + * + * @file textbubbleslider.h + * @author Tau Labs, http://taulabs.org Copyright (C) 2013. + * @brief Creates a slider with a text bubble showing the slider value + * @see The GNU Public License (GPL) Version 3 + * @defgroup + * @{ + * + *****************************************************************************/ +/* + * 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "textbubbleslider.h" + +/** + * @brief TextBubbleSlider::TextBubbleSlider Constructs a regular text-bubble slider + * @param parent + */ +TextBubbleSlider::TextBubbleSlider(QWidget *parent) : + QSlider(parent) +{ + QFontDatabase::addApplicationFont(":/utils/fonts/PTS75F.ttf"); + + construct(); +} + +/** + * @brief TextBubbleSlider::TextBubbleSlider Constructs a text-bubble slider that copys + * all relevant data from the previous slider + * @param copySlider + * @param parent + */ +TextBubbleSlider::TextBubbleSlider(QSlider *copySlider, QWidget *parent) : + QSlider(parent) +{ + construct(); + + // Copy settings + setSizePolicy(copySlider->sizePolicy()); + setMinimumSize(copySlider->minimumSize()); + setMaximumSize(copySlider->maximumSize()); + setFocusPolicy(copySlider->focusPolicy()); + setOrientation(copySlider->orientation()); + setMaximum(copySlider->maximum()); + setMinimum(copySlider->minimum()); + setToolTip(copySlider->toolTip()); +} + + +/** + * @brief TextBubbleSlider::construct This function needs to be called from all constructors. It + * provides a single point where settings can be changed. + */ +void TextBubbleSlider::construct() +{ + font = QFont("PT Sans", 13, QFont::Bold); + slideHandleMargin = 2; // This is a dubious way to set the margin. In reality, it should be read from the style sheet. +} + +TextBubbleSlider::~TextBubbleSlider() +{} + + +/** + * @brief numIntegerDigits Counts the number of digits in an integer + * @param number Input integer + * @return Number of digits in input integer + */ +unsigned int numIntegerDigits(int number) +{ + unsigned int digits = 0; + + // If there is a negative sign, be sure to include it in digit count + if (number < 0) { + digits = 1; + } + + while (number) { + number /= 10; + digits++; + } + + return digits; +} + + +/** + * @brief TextBubbleSlider::setMaxPixelWidth Sets maximum pixel width for slider handle + */ +void TextBubbleSlider::setMaxPixelWidth() +{ + // Calculate maximum number of digits possible in string + int maxNumDigits = numIntegerDigits(maximum()) > numIntegerDigits(minimum()) ? numIntegerDigits(maximum()) : numIntegerDigits(minimum()); + + // Generate string with maximum pixel width. Suppose that "0" is + // the widest number in pixels. + QString maximumWidthString; + + for (int i = 0; i < maxNumDigits; i++) { + maximumWidthString.append("0"); + } + + // Calculate maximum possible pixel width for string. + QFontMetrics fontMetrics(font); + maximumFontWidth = fontMetrics.width(QString("%1").arg(maximumWidthString)); + maximumFontHeight = fontMetrics.height(); + + // Override stylesheet slider handle width + slideHandleWidth = maximumFontWidth + 6; + setStyleSheet(QString("QSlider::handle:horizontal { width: %1px; margin: -5px 0;}").arg(slideHandleWidth)); +} + + +/** + * @brief TextBubbleSlider::setMinimum Reimplements setMinimum. Ensures that the slider + * handle is the correct size for the text field. + * @param max maximum + */ +void TextBubbleSlider::setMinimum(int max) +{ + // Pass value on to QSlider + QSlider::setMinimum(max); + + // Reset handler size + setMaxPixelWidth(); +} + + +/** + * @brief TextBubbleSlider::setMaximum Reimplements setMaximum. Ensures that the slider + * handle is the correct size for the text field. + * @param max maximum + */ +void TextBubbleSlider::setMaximum(int max) +{ + // Pass value on to QSlider + QSlider::setMaximum(max); + + // Reset handler size + setMaxPixelWidth(); +} + + +/** + * @brief TextBubbleSlider::paintEvent Reimplements QSlider::paintEvent. + * @param bob + */ +void TextBubbleSlider::paintEvent(QPaintEvent *paintEvent) +{ + // Pass paint event on to QSlider + QSlider::paintEvent(paintEvent); + + /* Add numbers on top of handler */ + + // Calculate pixel position for text. + int sliderWidth = width(); + int sliderHeight = height(); + double valuePos; + + if (!invertedAppearance()) { + valuePos = (slideHandleWidth - maximumFontWidth) / 2 + slideHandleMargin + // First part centers text in handle... + (value() - minimum()) / (double)(maximum() - minimum()) * (sliderWidth - (slideHandleWidth + slideHandleMargin) - 1); // ... and second part moves text with handle + } else { + valuePos = (slideHandleWidth - maximumFontWidth) / 2 + slideHandleMargin + // First part centers text in handle... + (maximum() - value()) / (double)(maximum() - minimum()) * (sliderWidth - (slideHandleWidth + slideHandleMargin) - 1); // ... and second part moves text with handle + } + + // Create painter and set font + QPainter painter(this); + painter.setFont(font); + painter.setPen(QPen(QColor(80, 80, 80))); + + // Draw neutral value text. Vertically center it in the handle + QString neutralStringWidth = QString("%1").arg(value()); + QFontMetrics fontMetrics(font); + int textWidth = fontMetrics.width(neutralStringWidth); + painter.drawText(QRectF(valuePos + maximumFontWidth - textWidth, ceil((sliderHeight - maximumFontHeight) / 2.0), textWidth, maximumFontHeight), + neutralStringWidth); +} diff --git a/ground/gcs/src/libs/utils/textbubbleslider.h b/ground/gcs/src/libs/utils/textbubbleslider.h new file mode 100644 index 000000000..9438b87a7 --- /dev/null +++ b/ground/gcs/src/libs/utils/textbubbleslider.h @@ -0,0 +1,59 @@ +/** + ****************************************************************************** + * + * @file textbubbleslider.h + * @author Tau Labs, http://taulabs.org Copyright (C) 2013. + * @brief Creates a slider with a text bubble showing the slider value + * @see The GNU Public License (GPL) Version 3 + * @defgroup + * @{ + * + *****************************************************************************/ +/* + * 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, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TEXTBUBBLESLIDER_H +#define TEXTBUBBLESLIDER_H + +#include +#include + +class TextBubbleSlider : public QSlider { + Q_OBJECT + +public: + explicit TextBubbleSlider(QWidget *parent = 0); + explicit TextBubbleSlider(QSlider *, QWidget *parent = 0); + void construct(); + ~TextBubbleSlider(); + + void setMinimum(int); + void setMaximum(int); + +protected: + void paintEvent(QPaintEvent *event); + +private: + void setMaxPixelWidth(); + + QFont font; + int maximumFontWidth; + int maximumFontHeight; + int slideHandleWidth; + int slideHandleMargin; +}; + +#endif // TEXTBUBBLESLIDER_H diff --git a/ground/gcs/src/libs/utils/utils.pro b/ground/gcs/src/libs/utils/utils.pro index 17ca57c65..e14cfcd5e 100644 --- a/ground/gcs/src/libs/utils/utils.pro +++ b/ground/gcs/src/libs/utils/utils.pro @@ -57,7 +57,8 @@ SOURCES += \ hostosinfo.cpp \ logfile.cpp \ crc.cpp \ - mustache.cpp + mustache.cpp \ + textbubbleslider.cpp SOURCES += xmlconfig.cpp @@ -120,7 +121,8 @@ HEADERS += \ hostosinfo.h \ logfile.h \ crc.h \ - mustache.h + mustache.h \ + textbubbleslider.h HEADERS += xmlconfig.h diff --git a/ground/gcs/src/libs/utils/utils.qrc b/ground/gcs/src/libs/utils/utils.qrc index ef180b21f..ee388cc66 100644 --- a/ground/gcs/src/libs/utils/utils.qrc +++ b/ground/gcs/src/libs/utils/utils.qrc @@ -1,5 +1,6 @@ images/removesubmitfield.png + fonts/PTS75F.ttf diff --git a/ground/gcs/src/plugins/config/configinputwidget.cpp b/ground/gcs/src/plugins/config/configinputwidget.cpp index 0d2d6fb85..7bbe10bf8 100644 --- a/ground/gcs/src/plugins/config/configinputwidget.cpp +++ b/ground/gcs/src/plugins/config/configinputwidget.cpp @@ -1730,12 +1730,15 @@ void ConfigInputWidget::updatePositionSlider() if (sp->objectName() == "channelNeutral") { if (count == 4) { sp->setStyleSheet( - "QSlider::groove:horizontal {border: 2px solid rgb(196, 196, 196); height: 12px; border-radius: 4px; " + "QSlider::groove:horizontal {border: 2px solid rgb(196, 196, 196); margin: 0px 23px 0px 23px; height: 12px; border-radius: 5px; " "border-image:url(:/configgadget/images/flightmode_bg" + fmNumber + ".png); }" "QSlider::add-page:horizontal { background: none; border: none; }" "QSlider::sub-page:horizontal { background: none; border: none; }" - "QSlider::handle:horizontal { background: rgba(196, 196, 196, 255); width: 10px; height: 28px; " - "margin: -3px -2px; border-radius: 3px; border: 1px solid #777; }"); + "QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, " + "stop: 0 rgba(196, 196, 196, 180), stop: 0.45 rgba(196, 196, 196, 180), " + "stop: 0.46 rgba(255,0,0,100), stop: 0.54 rgba(255,0,0,100), " + "stop: 0.55 rgba(196, 196, 196, 180), stop: 1 rgba(196, 196, 196, 180)); " + "width: 46px; height: 28px; margin: -6px -23px -6px -23px; border-radius: 5px; border: 1px solid #777; }"); count++; } else { count++; diff --git a/ground/gcs/src/plugins/config/inputchannelform.cpp b/ground/gcs/src/plugins/config/inputchannelform.cpp index 962bb7006..165241842 100644 --- a/ground/gcs/src/plugins/config/inputchannelform.cpp +++ b/ground/gcs/src/plugins/config/inputchannelform.cpp @@ -12,7 +12,6 @@ InputChannelForm::InputChannelForm(const int index, QWidget *parent) : connect(ui->channelMin, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); connect(ui->channelMax, SIGNAL(valueChanged(int)), this, SLOT(minMaxUpdated())); connect(ui->neutralValue, SIGNAL(valueChanged(int)), this, SLOT(neutralUpdated())); - connect(ui->channelNeutral, SIGNAL(valueChanged(int)), this, SLOT(updateTooltip())); connect(ui->channelGroup, SIGNAL(currentIndexChanged(int)), this, SLOT(groupUpdated())); connect(ui->channelRev, SIGNAL(toggled(bool)), this, SLOT(reversedUpdated())); @@ -58,13 +57,6 @@ void InputChannelForm::minMaxUpdated() updateNeutralMark(); } -void InputChannelForm::updateTooltip() -{ - int currentValue = ui->channelNeutral->value(); - - ui->channelNeutral->setToolTip(QString::number(currentValue)); -} - void InputChannelForm::neutralUpdated() { int neutralValue = ui->neutralValue->value(); @@ -98,13 +90,17 @@ void InputChannelForm::updateNeutralMark() float neutralPosition = offset / range; ui->channelNeutral->setStyleSheet( - "QSlider::groove:horizontal { border: 1px solid rgb(196, 196, 196); height: 6px; border-radius: 2px; " + "QSlider::groove:horizontal { border: 1px solid rgb(196, 196, 196); margin: 0px 23px 0px 23px; height: 6px; border-radius: 2px; " "background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:" + QString::number(neutralPosition - 0.01) + " transparent, stop:" + QString::number(neutralPosition) + " red, stop:" + QString::number(neutralPosition + 0.01) + " transparent); }" - "QSlider::add-page:horizontal { background: rgba(255,255,255,180); border: 1px solid #777; margin: 0px 0px 0px 2px; border-radius: 4px; }" - "QSlider::sub-page:horizontal { background: rgba(78,147,246,180); border: 1px solid #777; margin: 0px 2px 0px 0px; border-radius: 4px; }" - "QSlider::handle:horizontal { background: rgba(196,196,196,180); width: 18px; height: 28px; margin: -2px 0px; border-radius: 3px; " - "border: 1px solid #777; }" + "QSlider::add-page:horizontal { background: rgba(255,255,255,120); border: 1px solid #777; margin: 0px 23px 0px 2px; border-radius: 4px; }" + "QSlider::sub-page:horizontal { background: rgba(78,147,246,120); border: 1px solid #777; margin: 0px 2px 0px 23px; border-radius: 4px; }" + + "QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, " + "stop: 0 rgba(196, 196, 196, 180), stop: 0.45 rgba(196, 196, 196, 180), " + "stop: 0.46 rgba(255,0,0,100), stop: 0.54 rgba(255,0,0,100), " + "stop: 0.55 rgba(196, 196, 196, 180), stop: 1 rgba(196, 196, 196, 180)); " + "width: 46px; height: 28px; margin: -6px -23px -6px -23px; border-radius: 6px; border: 1px solid #777; }" ); } diff --git a/ground/gcs/src/plugins/config/inputchannelform.h b/ground/gcs/src/plugins/config/inputchannelform.h index 7763e0d4b..7c4464d8c 100644 --- a/ground/gcs/src/plugins/config/inputchannelform.h +++ b/ground/gcs/src/plugins/config/inputchannelform.h @@ -24,7 +24,6 @@ public: private slots: void updateNeutralMark(); - void updateTooltip(); void minMaxUpdated(); void neutralUpdated(); void reversedUpdated(); diff --git a/ground/gcs/src/plugins/config/inputchannelform.ui b/ground/gcs/src/plugins/config/inputchannelform.ui index 156d653ac..bc097770b 100644 --- a/ground/gcs/src/plugins/config/inputchannelform.ui +++ b/ground/gcs/src/plugins/config/inputchannelform.ui @@ -6,8 +6,8 @@ 0 0 - 923 - 57 + 993 + 100 @@ -141,7 +141,7 @@ margin:1px; - 110 + 120 0 @@ -169,7 +169,7 @@ margin:1px; - 100 + 80 0 @@ -737,7 +737,7 @@ margin:1px; - + 0 @@ -746,13 +746,16 @@ margin:1px; - 50 + 200 0 Qt::StrongFocus + + Channel input value (µs) + @@ -841,6 +844,20 @@ margin:1px; + + + TextBubbleSlider + QSlider +
utils/textbubbleslider.h
+
+
+ + channelGroup + channelNumber + channelMin + channelNeutral + channelMax + diff --git a/ground/gcs/src/plugins/pfdqml/PfdResources.qrc b/ground/gcs/src/plugins/pfdqml/PfdResources.qrc deleted file mode 100644 index 5c802bcc5..000000000 --- a/ground/gcs/src/plugins/pfdqml/PfdResources.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - fonts/PTS75F.ttf - - diff --git a/ground/gcs/src/plugins/pfdqml/pfdqml.pro b/ground/gcs/src/plugins/pfdqml/pfdqml.pro index e9e63e1a0..9af8bdb21 100644 --- a/ground/gcs/src/plugins/pfdqml/pfdqml.pro +++ b/ground/gcs/src/plugins/pfdqml/pfdqml.pro @@ -39,7 +39,3 @@ contains(DEFINES,USE_OSG) { OTHER_FILES += PfdQml.pluginspec FORMS += pfdqmlgadgetoptionspage.ui - -RESOURCES += \ - PfdResources.qrc - diff --git a/ground/gcs/src/share/pfd/default/Pfd.qml b/ground/gcs/src/share/pfd/default/Pfd.qml index 2b9aacb76..6eed0626d 100644 --- a/ground/gcs/src/share/pfd/default/Pfd.qml +++ b/ground/gcs/src/share/pfd/default/Pfd.qml @@ -26,7 +26,7 @@ Rectangle { FontLoader { id: pt_bold - source: "qrc:/pfdqml/fonts/PTS75F.ttf" + source: "qrc:/utils/fonts/PTS75F.ttf" } width: Math.floor((parent.paintedHeight * 1.32) - (parent.paintedHeight * 0.013))