Download src/Tools/plugins/widget/customwidgets.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 52.7 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Tools/plugins/widget/customwidgets.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Tools/plugins/widget/customwidgets.cpp
-
curl -L -o customwidgets.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Tools/plugins/widget/customwidgets.cpp
52.7 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2006 Werner Mayer <werner.wm.mayer@gmx.de> * | |
| * * | |
| * This file is part of the FreeCAD CAx development system. * | |
| * * | |
| * This library is free software; you can redistribute it and/or * | |
| * modify it under the terms of the GNU Library General Public * | |
| * License as published by the Free Software Foundation; either * | |
| * version 2 of the License, or (at your option) any later version. * | |
| * * | |
| * This library 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 Library General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Library General Public * | |
| * License along with this library; see the file COPYING.LIB. If not, * | |
| * write to the Free Software Foundation, Inc., 59 Temple Place, * | |
| * Suite 330, Boston, MA 02111-1307, USA * | |
| * * | |
| ***************************************************************************/ | |
| using namespace Gui; | |
| UrlLabel::UrlLabel(QWidget* parent, Qt::WindowFlags f) | |
| : QLabel("TextLabel", parent, f) | |
| { | |
| _url = "http://localhost"; | |
| setToolTip(this->_url); | |
| setCursor(Qt::PointingHandCursor); | |
| } | |
| UrlLabel::~UrlLabel() | |
| {} | |
| void UrlLabel::mouseReleaseEvent(QMouseEvent*) | |
| { | |
| QMessageBox::information(this, "Browser", QString("This starts your browser with url %1").arg(_url)); | |
| } | |
| QString UrlLabel::url() const | |
| { | |
| return this->_url; | |
| } | |
| void UrlLabel::setUrl(const QString& u) | |
| { | |
| this->_url = u; | |
| setToolTip(this->_url); | |
| } | |
| LocationWidget::LocationWidget(QWidget* parent) | |
| : QWidget(parent) | |
| { | |
| box = new QGridLayout(); | |
| xValue = new QDoubleSpinBox(this); | |
| xValue->setMinimum(-2.14748e+09); | |
| xValue->setMaximum(2.14748e+09); | |
| xLabel = new QLabel(this); | |
| box->addWidget(xLabel, 0, 0, 1, 1); | |
| box->addWidget(xValue, 0, 1, 1, 1); | |
| yValue = new QDoubleSpinBox(this); | |
| yValue->setMinimum(-2.14748e+09); | |
| yValue->setMaximum(2.14748e+09); | |
| yLabel = new QLabel(this); | |
| box->addWidget(yLabel, 1, 0, 1, 1); | |
| box->addWidget(yValue, 1, 1, 1, 1); | |
| zValue = new QDoubleSpinBox(this); | |
| zValue->setMinimum(-2.14748e+09); | |
| zValue->setMaximum(2.14748e+09); | |
| zLabel = new QLabel(this); | |
| box->addWidget(zLabel, 2, 0, 1, 1); | |
| box->addWidget(zValue, 2, 1, 1, 1); | |
| dLabel = new QLabel(this); | |
| dValue = new QComboBox(this); | |
| dValue->setCurrentIndex(-1); | |
| box->addWidget(dLabel, 3, 0, 1, 1); | |
| box->addWidget(dValue, 3, 1, 1, 1); | |
| QGridLayout* gridLayout = new QGridLayout(this); | |
| gridLayout->addLayout(box, 0, 0, 1, 2); | |
| retranslateUi(); | |
| } | |
| LocationWidget::~LocationWidget() | |
| {} | |
| QSize LocationWidget::sizeHint() const | |
| { | |
| return QSize(150, 100); | |
| } | |
| void LocationWidget::changeEvent(QEvent* e) | |
| { | |
| if (e->type() == QEvent::LanguageChange) { | |
| this->retranslateUi(); | |
| } | |
| QWidget::changeEvent(e); | |
| } | |
| void LocationWidget::retranslateUi() | |
| { | |
| xLabel->setText(QApplication::translate("Gui::LocationWidget", "X:")); | |
| yLabel->setText(QApplication::translate("Gui::LocationWidget", "Y:")); | |
| zLabel->setText(QApplication::translate("Gui::LocationWidget", "Z:")); | |
| dLabel->setText(QApplication::translate("Gui::LocationWidget", "Direction:")); | |
| } | |
| FileChooser::FileChooser(QWidget* parent) | |
| : QWidget(parent) | |
| , md(File) | |
| , _filter(QString()) | |
| { | |
| QHBoxLayout* layout = new QHBoxLayout(this); | |
| layout->setContentsMargins(0, 0, 0, 0); | |
| layout->setSpacing(6); | |
| lineEdit = new QLineEdit(this); | |
| layout->addWidget(lineEdit); | |
| connect(lineEdit, &QLineEdit::textChanged, this, &FileChooser::fileNameChanged); | |
| button = new QPushButton("...", this); | |
| button->setFixedWidth(2 * button->fontMetrics().horizontalAdvance(" ... ")); | |
| layout->addWidget(button); | |
| connect(button, &QPushButton::clicked, this, &FileChooser::chooseFile); | |
| setFocusProxy(lineEdit); | |
| } | |
| FileChooser::~FileChooser() | |
| {} | |
| QString FileChooser::fileName() const | |
| { | |
| return lineEdit->text(); | |
| } | |
| void FileChooser::setFileName(const QString& fn) | |
| { | |
| lineEdit->setText(fn); | |
| } | |
| void FileChooser::chooseFile() | |
| { | |
| QFileDialog::Options dlgOpt = QFileDialog::DontUseNativeDialog; | |
| QString fn; | |
| if (mode() == File) { | |
| fn = QFileDialog::getOpenFileName(this, tr("Select a file"), lineEdit->text(), _filter, 0, dlgOpt); | |
| } | |
| else { | |
| QFileDialog::Options option = QFileDialog::ShowDirsOnly | dlgOpt; | |
| fn = QFileDialog::getExistingDirectory(this, tr("Select a directory"), lineEdit->text(), option); | |
| } | |
| if (!fn.isEmpty()) { | |
| lineEdit->setText(fn); | |
| Q_EMIT fileNameSelected(fn); | |
| } | |
| } | |
| FileChooser::Mode FileChooser::mode() const | |
| { | |
| return md; | |
| } | |
| void FileChooser::setMode(Mode m) | |
| { | |
| md = m; | |
| } | |
| QString FileChooser::filter() const | |
| { | |
| return _filter; | |
| } | |
| void FileChooser::setFilter(const QString& filter) | |
| { | |
| _filter = filter; | |
| } | |
| void FileChooser::setButtonText(const QString& txt) | |
| { | |
| button->setText(txt); | |
| int w1 = 2 * button->fontMetrics().horizontalAdvance(txt); | |
| int w2 = 2 * button->fontMetrics().horizontalAdvance(" ... "); | |
| button->setFixedWidth((w1 > w2 ? w1 : w2)); | |
| } | |
| QString FileChooser::buttonText() const | |
| { | |
| return button->text(); | |
| } | |
| // ------------------------------------------------------------------------------ | |
| PrefFileChooser::PrefFileChooser(QWidget* parent) | |
| : FileChooser(parent) | |
| {} | |
| PrefFileChooser::~PrefFileChooser() | |
| {} | |
| QByteArray PrefFileChooser::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefFileChooser::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefFileChooser::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefFileChooser::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| AccelLineEdit::AccelLineEdit(QWidget* parent) | |
| : QLineEdit(parent) | |
| { | |
| setPlaceholderText(tr("Press a keyboard shortcut")); | |
| setClearButtonEnabled(true); | |
| keyPressedCount = 0; | |
| } | |
| bool AccelLineEdit::isNone() const | |
| { | |
| return text().isEmpty(); | |
| } | |
| void AccelLineEdit::keyPressEvent(QKeyEvent* e) | |
| { | |
| if (isReadOnly()) { | |
| QLineEdit::keyPressEvent(e); | |
| return; | |
| } | |
| QString txtLine = text(); | |
| int key = e->key(); | |
| Qt::KeyboardModifiers state = e->modifiers(); | |
| // Backspace clears the shortcut if text is present, else sets Backspace as shortcut. | |
| // If a modifier is pressed without any other key, return. | |
| // AltGr is not a modifier but doesn't have a QString representation. | |
| switch (key) { | |
| case Qt::Key_Backspace: | |
| case Qt::Key_Delete: | |
| if (state == Qt::NoModifier) { | |
| keyPressedCount = 0; | |
| if (isNone()) { | |
| QKeySequence ks(key); | |
| setText(ks.toString(QKeySequence::NativeText)); | |
| } | |
| else { | |
| clear(); | |
| } | |
| } | |
| case Qt::Key_Control: | |
| case Qt::Key_Shift: | |
| case Qt::Key_Alt: | |
| case Qt::Key_Meta: | |
| case Qt::Key_AltGr: | |
| return; | |
| default: | |
| break; | |
| } | |
| if (txtLine.isEmpty()) { | |
| // Text maybe cleared by QLineEdit's built in clear button | |
| keyPressedCount = 0; | |
| } | |
| else { | |
| // 4 keys are allowed for QShortcut | |
| switch (keyPressedCount) { | |
| case 4: | |
| keyPressedCount = 0; | |
| txtLine.clear(); | |
| break; | |
| case 0: | |
| txtLine.clear(); | |
| break; | |
| default: | |
| txtLine += QString::fromLatin1(","); | |
| break; | |
| } | |
| } | |
| // Handles modifiers applying a mask. | |
| if ((state & Qt::ControlModifier) == Qt::ControlModifier) { | |
| QKeySequence ks(Qt::CTRL); | |
| txtLine += ks.toString(QKeySequence::NativeText); | |
| } | |
| if ((state & Qt::AltModifier) == Qt::AltModifier) { | |
| QKeySequence ks(Qt::ALT); | |
| txtLine += ks.toString(QKeySequence::NativeText); | |
| } | |
| if ((state & Qt::ShiftModifier) == Qt::ShiftModifier) { | |
| QKeySequence ks(Qt::SHIFT); | |
| txtLine += ks.toString(QKeySequence::NativeText); | |
| } | |
| if ((state & Qt::MetaModifier) == Qt::MetaModifier) { | |
| QKeySequence ks(Qt::META); | |
| txtLine += ks.toString(QKeySequence::NativeText); | |
| } | |
| // Handles normal keys | |
| QKeySequence ks(key); | |
| txtLine += ks.toString(QKeySequence::NativeText); | |
| setText(txtLine); | |
| keyPressedCount++; | |
| } | |
| // ------------------------------------------------------------------------------ | |
| ActionSelector::ActionSelector(QWidget* parent) | |
| : QWidget(parent) | |
| { | |
| addButton = new QPushButton(this); | |
| addButton->setMinimumSize(QSize(30, 30)); | |
| QIcon icon; | |
| icon.addFile(QString::fromUtf8(":/icons/button_right.svg"), QSize(), QIcon::Normal, QIcon::Off); | |
| addButton->setIcon(icon); | |
| gridLayout = new QGridLayout(this); | |
| gridLayout->addWidget(addButton, 1, 1, 1, 1); | |
| spacerItem = new QSpacerItem(33, 57, QSizePolicy::Minimum, QSizePolicy::Expanding); | |
| gridLayout->addItem(spacerItem, 5, 1, 1, 1); | |
| spacerItem1 = new QSpacerItem(33, 58, QSizePolicy::Minimum, QSizePolicy::Expanding); | |
| gridLayout->addItem(spacerItem1, 0, 1, 1, 1); | |
| removeButton = new QPushButton(this); | |
| removeButton->setMinimumSize(QSize(30, 30)); | |
| QIcon icon1; | |
| icon1.addFile(QString::fromUtf8(":/icons/button_left.svg"), QSize(), QIcon::Normal, QIcon::Off); | |
| removeButton->setIcon(icon1); | |
| removeButton->setAutoDefault(true); | |
| removeButton->setDefault(false); | |
| gridLayout->addWidget(removeButton, 2, 1, 1, 1); | |
| upButton = new QPushButton(this); | |
| upButton->setMinimumSize(QSize(30, 30)); | |
| QIcon icon3; | |
| icon3.addFile(QString::fromUtf8(":/icons/button_up.svg"), QSize(), QIcon::Normal, QIcon::Off); | |
| upButton->setIcon(icon3); | |
| gridLayout->addWidget(upButton, 3, 1, 1, 1); | |
| downButton = new QPushButton(this); | |
| downButton->setMinimumSize(QSize(30, 30)); | |
| QIcon icon2; | |
| icon2.addFile(QString::fromUtf8(":/icons/button_down.svg"), QSize(), QIcon::Normal, QIcon::Off); | |
| downButton->setIcon(icon2); | |
| downButton->setAutoDefault(true); | |
| gridLayout->addWidget(downButton, 4, 1, 1, 1); | |
| vboxLayout = new QVBoxLayout(); | |
| vboxLayout->setContentsMargins(0, 0, 0, 0); | |
| labelAvailable = new QLabel(this); | |
| vboxLayout->addWidget(labelAvailable); | |
| availableWidget = new QTreeWidget(this); | |
| availableWidget->setRootIsDecorated(false); | |
| availableWidget->setHeaderLabels(QStringList() << QString()); | |
| availableWidget->header()->hide(); | |
| vboxLayout->addWidget(availableWidget); | |
| gridLayout->addLayout(vboxLayout, 0, 0, 6, 1); | |
| vboxLayout1 = new QVBoxLayout(); | |
| vboxLayout1->setContentsMargins(0, 0, 0, 0); | |
| labelSelected = new QLabel(this); | |
| vboxLayout1->addWidget(labelSelected); | |
| selectedWidget = new QTreeWidget(this); | |
| selectedWidget->setRootIsDecorated(false); | |
| selectedWidget->setHeaderLabels(QStringList() << QString()); | |
| selectedWidget->header()->hide(); | |
| vboxLayout1->addWidget(selectedWidget); | |
| gridLayout->addLayout(vboxLayout1, 0, 2, 6, 1); | |
| addButton->setText(QString()); | |
| removeButton->setText(QString()); | |
| upButton->setText(QString()); | |
| downButton->setText(QString()); | |
| labelAvailable->setText(QApplication::translate("Gui::ActionSelector", "Available:")); | |
| labelSelected->setText(QApplication::translate("Gui::ActionSelector", "Selected:")); | |
| addButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Add")); | |
| removeButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Remove")); | |
| upButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move up")); | |
| downButton->setToolTip(QApplication::translate("Gui::ActionSelector", "Move down")); | |
| } | |
| ActionSelector::~ActionSelector() | |
| {} | |
| // -------------------------------------------------------------------- | |
| InputField::InputField(QWidget* parent) | |
| : QLineEdit(parent) | |
| , Value(0) | |
| , Maximum(std::numeric_limits<int>::max()) | |
| , Minimum(-std::numeric_limits<int>::max()) | |
| , StepSize(1.0) | |
| , HistorySize(5) | |
| {} | |
| InputField::~InputField() | |
| {} | |
| /** Sets the preference path to \a path. */ | |
| void InputField::setParamGrpPath(const QByteArray& path) | |
| { | |
| m_sPrefGrp = path; | |
| } | |
| /** Returns the widget's preferences path. */ | |
| QByteArray InputField::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| /// sets the field with a quantity | |
| void InputField::setValue(double quant) | |
| { | |
| Value = quant; | |
| setText(QString("%1 %2").arg(Value).arg(UnitStr)); | |
| } | |
| /// sets the field with a quantity | |
| double InputField::getQuantity() const | |
| { | |
| return Value; | |
| } | |
| /// get the value of the singleStep property | |
| double InputField::singleStep(void) const | |
| { | |
| return StepSize; | |
| } | |
| /// set the value of the singleStep property | |
| void InputField::setSingleStep(double s) | |
| { | |
| StepSize = s; | |
| } | |
| /// get the value of the maximum property | |
| double InputField::maximum(void) const | |
| { | |
| return Maximum; | |
| } | |
| /// set the value of the maximum property | |
| void InputField::setMaximum(double m) | |
| { | |
| Maximum = m; | |
| } | |
| /// get the value of the minimum property | |
| double InputField::minimum(void) const | |
| { | |
| return Minimum; | |
| } | |
| /// set the value of the minimum property | |
| void InputField::setMinimum(double m) | |
| { | |
| Minimum = m; | |
| } | |
| void InputField::setUnitText(QString str) | |
| { | |
| UnitStr = str; | |
| setText(QString("%1 %2").arg(Value).arg(UnitStr)); | |
| } | |
| QString InputField::getUnitText(void) | |
| { | |
| return UnitStr; | |
| } | |
| // get the value of the minimum property | |
| int InputField::historySize(void) const | |
| { | |
| return HistorySize; | |
| } | |
| // set the value of the minimum property | |
| void InputField::setHistorySize(int i) | |
| { | |
| HistorySize = i; | |
| } | |
| // -------------------------------------------------------------------- | |
| ExpressionLineEdit::ExpressionLineEdit(QWidget* parent) | |
| : QLineEdit(parent) | |
| , exactMatch {false} | |
| { | |
| completer = new QCompleter(this); | |
| connect(this, &QLineEdit::textEdited, this, &ExpressionLineEdit::slotTextChanged); | |
| } | |
| void ExpressionLineEdit::setExactMatch(bool enabled) | |
| { | |
| exactMatch = enabled; | |
| if (completer) { | |
| completer->setFilterMode(exactMatch ? Qt::MatchStartsWith : Qt::MatchContains); | |
| } | |
| } | |
| void ExpressionLineEdit::slotTextChanged(const QString& text) | |
| { | |
| Q_EMIT textChanged2(text, cursorPosition()); | |
| } | |
| void ExpressionLineEdit::slotCompleteText(const QString& completionPrefix, bool isActivated) | |
| { | |
| Q_UNUSED(completionPrefix) | |
| Q_UNUSED(isActivated) | |
| } | |
| void ExpressionLineEdit::slotCompleteTextHighlighted(const QString& completionPrefix) | |
| { | |
| slotCompleteText(completionPrefix, false); | |
| } | |
| void ExpressionLineEdit::slotCompleteTextSelected(const QString& completionPrefix) | |
| { | |
| slotCompleteText(completionPrefix, true); | |
| } | |
| void ExpressionLineEdit::keyPressEvent(QKeyEvent* e) | |
| { | |
| QLineEdit::keyPressEvent(e); | |
| } | |
| void ExpressionLineEdit::contextMenuEvent(QContextMenuEvent* event) | |
| { | |
| QMenu* menu = createStandardContextMenu(); | |
| if (completer) { | |
| menu->addSeparator(); | |
| QAction* match = menu->addAction(tr("Exact match")); | |
| match->setCheckable(true); | |
| match->setChecked(completer->filterMode() == Qt::MatchStartsWith); | |
| QObject::connect(match, &QAction::toggled, this, &Gui::ExpressionLineEdit::setExactMatch); | |
| } | |
| menu->setAttribute(Qt::WA_DeleteOnClose); | |
| menu->popup(event->globalPos()); | |
| } | |
| // -------------------------------------------------------------------- | |
| namespace Base | |
| { | |
| Unit::Unit() | |
| {} | |
| Unit::Unit(const QString& u) | |
| : unit(u) | |
| {} | |
| bool Unit::isEmpty() const | |
| { | |
| return unit.isEmpty(); | |
| } | |
| bool Unit::operator==(const Unit& that) | |
| { | |
| return this->unit == that.unit; | |
| } | |
| bool Unit::operator!=(const Unit& that) | |
| { | |
| return this->unit != that.unit; | |
| } | |
| const QString& Unit::getString() const | |
| { | |
| return unit; | |
| } | |
| int QuantityFormat::defaultDenominator = 8; // for 1/8" | |
| QuantityFormat::QuantityFormat() | |
| : option(OmitGroupSeparator | RejectGroupSeparator) | |
| , format(Fixed) | |
| , precision(4) | |
| , denominator(defaultDenominator) | |
| {} | |
| Quantity::Quantity() | |
| : value(0) | |
| , unit() | |
| {} | |
| Quantity::Quantity(double v, const Unit& u) | |
| : value(v) | |
| , unit(u) | |
| {} | |
| Quantity Quantity::parse(const QString& str) | |
| { | |
| bool ok; | |
| QString txt = str; | |
| QString unit; | |
| while (!txt.isEmpty() && txt[txt.length() - 1].isLetter()) { | |
| unit.prepend(txt[txt.length() - 1]); | |
| txt.chop(1); | |
| } | |
| double v = QLocale::system().toDouble(txt, &ok); | |
| // if (!ok && !txt.isEmpty()) | |
| // throw Base::Exception(); | |
| return Quantity(v, Unit(unit)); | |
| } | |
| void Quantity::setValue(double v) | |
| { | |
| value = v; | |
| } | |
| double Quantity::getValue() const | |
| { | |
| return value; | |
| } | |
| void Quantity::setUnit(const Unit& u) | |
| { | |
| unit = u; | |
| } | |
| Unit Quantity::getUnit() const | |
| { | |
| return unit; | |
| } | |
| QString Quantity::getUserString() const | |
| { | |
| QLocale Lc; | |
| const QuantityFormat& format = getFormat(); | |
| if (format.option != QuantityFormat::None) { | |
| uint opt = static_cast<uint>(format.option); | |
| Lc.setNumberOptions(static_cast<QLocale::NumberOptions>(opt)); | |
| } | |
| QString Ln = Lc.toString(value, format.toFormat(), format.precision); | |
| return QString::fromUtf8("%1 %2").arg(Ln, unit.getString()); | |
| } | |
| QString Quantity::getUserString(double& factor, QString& unitString) const | |
| { | |
| factor = 1; | |
| unitString = unit.getString(); | |
| QLocale Lc; | |
| const QuantityFormat& format = getFormat(); | |
| if (format.option != QuantityFormat::None) { | |
| uint opt = static_cast<uint>(format.option); | |
| Lc.setNumberOptions(static_cast<QLocale::NumberOptions>(opt)); | |
| } | |
| QString Ln = Lc.toString(value, format.toFormat(), format.precision); | |
| return QString::fromUtf8("%1 %2").arg(Ln, unit.getString()); | |
| } | |
| } // namespace Base | |
| namespace Gui | |
| { | |
| class QuantitySpinBoxPrivate | |
| { | |
| public: | |
| QuantitySpinBoxPrivate() | |
| : validInput(true) | |
| , pendingEmit(false) | |
| , unitValue(0) | |
| , maximum(std::numeric_limits<int>::max()) | |
| , minimum(-std::numeric_limits<int>::max()) | |
| , singleStep(1.0) | |
| {} | |
| ~QuantitySpinBoxPrivate() | |
| {} | |
| QString stripped(const QString& t, int* pos) const | |
| { | |
| QString text = t; | |
| const int s = text.size(); | |
| text = text.trimmed(); | |
| if (pos) { | |
| (*pos) -= (s - text.size()); | |
| } | |
| return text; | |
| } | |
| bool validate(QString& input, Base::Quantity& result) const | |
| { | |
| bool success = false; | |
| QString tmp = input; | |
| int pos = 0; | |
| QValidator::State state; | |
| Base::Quantity res = validateAndInterpret(tmp, pos, state); | |
| res.setFormat(quantity.getFormat()); | |
| if (state == QValidator::Acceptable) { | |
| success = true; | |
| result = res; | |
| input = tmp; | |
| } | |
| else if (state == QValidator::Intermediate) { | |
| tmp = tmp.trimmed(); | |
| tmp += QLatin1Char(' '); | |
| tmp += unitStr; | |
| Base::Quantity res2 = validateAndInterpret(tmp, pos, state); | |
| res2.setFormat(quantity.getFormat()); | |
| if (state == QValidator::Acceptable) { | |
| success = true; | |
| result = res2; | |
| input = tmp; | |
| } | |
| } | |
| return success; | |
| } | |
| Base::Quantity validateAndInterpret(QString& input, int& pos, QValidator::State& state) const | |
| { | |
| Base::Quantity res; | |
| const double max = this->maximum; | |
| const double min = this->minimum; | |
| QString copy = input; | |
| int len = copy.size(); | |
| const bool plus = max >= 0; | |
| const bool minus = min <= 0; | |
| switch (len) { | |
| case 0: | |
| state = max != min ? QValidator::Intermediate : QValidator::Invalid; | |
| goto end; | |
| case 1: | |
| if (copy.at(0) == locale.decimalPoint()) { | |
| state = QValidator::Intermediate; | |
| copy.prepend(QLatin1Char('0')); | |
| pos++; | |
| len++; | |
| goto end; | |
| } | |
| else if (copy.at(0) == QLatin1Char('+')) { | |
| // the quantity parser doesn't allow numbers of the form '+1.0' | |
| state = QValidator::Invalid; | |
| goto end; | |
| } | |
| else if (copy.at(0) == QLatin1Char('-')) { | |
| if (minus) { | |
| state = QValidator::Intermediate; | |
| } | |
| else { | |
| state = QValidator::Invalid; | |
| } | |
| goto end; | |
| } | |
| break; | |
| case 2: | |
| if (copy.at(1) == locale.decimalPoint() && (plus && copy.at(0) == QLatin1Char('+'))) { | |
| state = QValidator::Intermediate; | |
| goto end; | |
| } | |
| if (copy.at(1) == locale.decimalPoint() && (minus && copy.at(0) == QLatin1Char('-'))) { | |
| state = QValidator::Intermediate; | |
| copy.insert(1, QLatin1Char('0')); | |
| pos++; | |
| len++; | |
| goto end; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| { | |
| if (copy.at(0) == locale.groupSeparator()) { | |
| state = QValidator::Invalid; | |
| goto end; | |
| } | |
| else if (len > 1) { | |
| bool decOccurred = false; | |
| for (int i = 0; i < copy.size(); i++) { | |
| if (copy.at(i) == locale.decimalPoint()) { | |
| // Disallow multiple decimal points within the same numeric substring | |
| if (decOccurred) { | |
| state = QValidator::Invalid; | |
| goto end; | |
| } | |
| decOccurred = true; | |
| } | |
| // Reset decOcurred if non-numeric character found | |
| else if (!(copy.at(i) == locale.groupSeparator() || copy.at(i).isDigit())) { | |
| decOccurred = false; | |
| } | |
| } | |
| } | |
| bool ok = false; | |
| double value = min; | |
| QChar plus = QLatin1Char('+'), minus = QLatin1Char('-'); | |
| if (locale.negativeSign() != minus) { | |
| copy.replace(locale.negativeSign(), minus); | |
| } | |
| if (locale.positiveSign() != plus) { | |
| copy.replace(locale.positiveSign(), plus); | |
| } | |
| try { | |
| QString copy2 = copy; | |
| copy2.remove(locale.groupSeparator()); | |
| res = Base::Quantity::parse(copy2); | |
| value = res.getValue(); | |
| ok = true; | |
| } | |
| catch (Base::Exception&) { | |
| } | |
| if (!ok) { | |
| // input may not be finished | |
| state = QValidator::Intermediate; | |
| } | |
| else if (value >= min && value <= max) { | |
| if (copy.endsWith(locale.decimalPoint())) { | |
| // input shouldn't end with a decimal point | |
| state = QValidator::Intermediate; | |
| } | |
| else if (res.getUnit().isEmpty() && !this->unit.isEmpty()) { | |
| // if not dimensionless the input should have a dimension | |
| state = QValidator::Intermediate; | |
| } | |
| else if (res.getUnit() != this->unit) { | |
| state = QValidator::Invalid; | |
| } | |
| else { | |
| state = QValidator::Acceptable; | |
| } | |
| } | |
| else if (max == min) { // when max and min is the same the only non-Invalid input is | |
| // max (or min) | |
| state = QValidator::Invalid; | |
| } | |
| else { | |
| if ((value >= 0 && value > max) || (value < 0 && value < min)) { | |
| state = QValidator::Invalid; | |
| } | |
| else { | |
| state = QValidator::Intermediate; | |
| } | |
| } | |
| } | |
| end: | |
| if (state != QValidator::Acceptable) { | |
| res.setValue(max > 0 ? min : max); | |
| } | |
| input = copy; | |
| return res; | |
| } | |
| QLocale locale; | |
| bool validInput; | |
| bool pendingEmit; | |
| QString validStr; | |
| Base::Quantity quantity; | |
| Base::Quantity cached; | |
| Base::Unit unit; | |
| double unitValue; | |
| QString unitStr; | |
| double maximum; | |
| double minimum; | |
| double singleStep; | |
| }; | |
| } // namespace Gui | |
| QuantitySpinBox::QuantitySpinBox(QWidget* parent) | |
| : QAbstractSpinBox(parent) | |
| , d_ptr(new QuantitySpinBoxPrivate()) | |
| { | |
| d_ptr->locale = locale(); | |
| this->setContextMenuPolicy(Qt::DefaultContextMenu); | |
| connect(lineEdit(), &QLineEdit::textChanged, this, &QuantitySpinBox::userInput); | |
| connect(this, &QuantitySpinBox::editingFinished, this, &QuantitySpinBox::handlePendingEmit); | |
| } | |
| QuantitySpinBox::~QuantitySpinBox() | |
| {} | |
| void QuantitySpinBox::resizeEvent(QResizeEvent* event) | |
| { | |
| QAbstractSpinBox::resizeEvent(event); | |
| } | |
| void Gui::QuantitySpinBox::keyPressEvent(QKeyEvent* event) | |
| { | |
| QAbstractSpinBox::keyPressEvent(event); | |
| } | |
| void QuantitySpinBox::updateText(const Base::Quantity& quant) | |
| { | |
| Q_D(QuantitySpinBox); | |
| double dFactor; | |
| QString txt = getUserString(quant, dFactor, d->unitStr); | |
| d->unitValue = quant.getValue() / dFactor; | |
| lineEdit()->setText(txt); | |
| handlePendingEmit(); | |
| } | |
| Base::Quantity QuantitySpinBox::value() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->quantity; | |
| } | |
| double QuantitySpinBox::rawValue() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->quantity.getValue(); | |
| } | |
| void QuantitySpinBox::setValue(const Base::Quantity& value) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->quantity = value; | |
| // check limits | |
| if (d->quantity.getValue() > d->maximum) { | |
| d->quantity.setValue(d->maximum); | |
| } | |
| if (d->quantity.getValue() < d->minimum) { | |
| d->quantity.setValue(d->minimum); | |
| } | |
| d->unit = value.getUnit(); | |
| updateText(value); | |
| } | |
| void QuantitySpinBox::setValue(double value) | |
| { | |
| Q_D(QuantitySpinBox); | |
| setValue(Base::Quantity(value, d->unit)); | |
| } | |
| bool QuantitySpinBox::hasValidInput() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->validInput; | |
| } | |
| // Gets called after call of 'validateAndInterpret' | |
| void QuantitySpinBox::userInput(const QString& text) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->pendingEmit = true; | |
| QString tmp = text; | |
| Base::Quantity res; | |
| if (d->validate(tmp, res)) { | |
| d->validStr = tmp; | |
| d->validInput = true; | |
| } | |
| else { | |
| d->validInput = false; | |
| return; | |
| } | |
| if (keyboardTracking()) { | |
| d->cached = res; | |
| handlePendingEmit(); | |
| } | |
| else { | |
| d->cached = res; | |
| } | |
| } | |
| void QuantitySpinBox::handlePendingEmit() | |
| { | |
| updateFromCache(true); | |
| } | |
| void QuantitySpinBox::updateFromCache(bool notify) | |
| { | |
| Q_D(QuantitySpinBox); | |
| if (d->pendingEmit) { | |
| double factor; | |
| const Base::Quantity& res = d->cached; | |
| QString text = getUserString(res, factor, d->unitStr); | |
| d->unitValue = res.getValue() / factor; | |
| d->quantity = res; | |
| // signaling | |
| if (notify) { | |
| d->pendingEmit = false; | |
| valueChanged(res); | |
| valueChanged(res.getValue()); | |
| textChanged(text); | |
| } | |
| } | |
| } | |
| Base::Unit QuantitySpinBox::unit() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->unit; | |
| } | |
| void QuantitySpinBox::setUnit(const Base::Unit& unit) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->unit = unit; | |
| d->quantity.setUnit(unit); | |
| updateText(d->quantity); | |
| } | |
| void QuantitySpinBox::setUnitText(const QString& str) | |
| { | |
| try { | |
| Base::Quantity quant = Base::Quantity::parse(str); | |
| setUnit(quant.getUnit()); | |
| } | |
| catch (const Base::Exception&) { | |
| } | |
| } | |
| QString QuantitySpinBox::unitText(void) | |
| { | |
| Q_D(QuantitySpinBox); | |
| return d->unitStr; | |
| } | |
| double QuantitySpinBox::singleStep() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->singleStep; | |
| } | |
| void QuantitySpinBox::setSingleStep(double value) | |
| { | |
| Q_D(QuantitySpinBox); | |
| if (value >= 0) { | |
| d->singleStep = value; | |
| } | |
| } | |
| double QuantitySpinBox::minimum() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->minimum; | |
| } | |
| void QuantitySpinBox::setMinimum(double minimum) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->minimum = minimum; | |
| } | |
| double QuantitySpinBox::maximum() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->maximum; | |
| } | |
| void QuantitySpinBox::setMaximum(double maximum) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->maximum = maximum; | |
| } | |
| void QuantitySpinBox::setRange(double minimum, double maximum) | |
| { | |
| Q_D(QuantitySpinBox); | |
| d->minimum = minimum; | |
| d->maximum = maximum; | |
| } | |
| int QuantitySpinBox::decimals() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| return d->quantity.getFormat().precision; | |
| } | |
| void QuantitySpinBox::setDecimals(int v) | |
| { | |
| Q_D(QuantitySpinBox); | |
| Base::QuantityFormat f = d->quantity.getFormat(); | |
| f.precision = v; | |
| d->quantity.setFormat(f); | |
| updateText(d->quantity); | |
| } | |
| void QuantitySpinBox::clearSchema() | |
| { | |
| Q_D(QuantitySpinBox); | |
| updateText(d->quantity); | |
| } | |
| QString QuantitySpinBox::getUserString(const Base::Quantity& val, double& factor, QString& unitString) const | |
| { | |
| return val.getUserString(factor, unitString); | |
| } | |
| QString QuantitySpinBox::getUserString(const Base::Quantity& val) const | |
| { | |
| return val.getUserString(); | |
| } | |
| QAbstractSpinBox::StepEnabled QuantitySpinBox::stepEnabled() const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| if (isReadOnly() /* || !d->validInput*/) { | |
| return StepNone; | |
| } | |
| if (wrapping()) { | |
| return StepEnabled(StepUpEnabled | StepDownEnabled); | |
| } | |
| StepEnabled ret = StepNone; | |
| if (d->quantity.getValue() < d->maximum) { | |
| ret |= StepUpEnabled; | |
| } | |
| if (d->quantity.getValue() > d->minimum) { | |
| ret |= StepDownEnabled; | |
| } | |
| return ret; | |
| } | |
| void QuantitySpinBox::stepBy(int steps) | |
| { | |
| Q_D(QuantitySpinBox); | |
| updateFromCache(false); | |
| double step = d->singleStep * steps; | |
| double val = d->unitValue + step; | |
| if (val > d->maximum) { | |
| val = d->maximum; | |
| } | |
| else if (val < d->minimum) { | |
| val = d->minimum; | |
| } | |
| lineEdit()->setText(QString::fromUtf8("%L1 %2").arg(val).arg(d->unitStr)); | |
| updateFromCache(true); | |
| update(); | |
| selectNumber(); | |
| } | |
| QSize QuantitySpinBox::sizeHint() const | |
| { | |
| ensurePolished(); | |
| const QFontMetrics fm(fontMetrics()); | |
| int frameWidth = lineEdit()->style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth); | |
| int iconHeight = fm.height() - frameWidth; | |
| int h = lineEdit()->sizeHint().height(); | |
| int w = 0; | |
| QString s = QLatin1String("000000000000000000"); | |
| QString fixedContent = QLatin1String(" "); | |
| s += fixedContent; | |
| w = fm.horizontalAdvance(s); | |
| w += 2; // cursor blinking space | |
| w += iconHeight; | |
| QStyleOptionSpinBox opt; | |
| initStyleOption(&opt); | |
| QSize hint(w, h); | |
| QSize size = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this); | |
| return size; | |
| } | |
| QSize QuantitySpinBox::minimumSizeHint() const | |
| { | |
| ensurePolished(); | |
| const QFontMetrics fm(fontMetrics()); | |
| int frameWidth = lineEdit()->style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth); | |
| int iconHeight = fm.height() - frameWidth; | |
| int h = lineEdit()->minimumSizeHint().height(); | |
| int w = 0; | |
| QString s = QLatin1String("000000000000000000"); | |
| QString fixedContent = QLatin1String(" "); | |
| s += fixedContent; | |
| w = fm.horizontalAdvance(s); | |
| w += 2; // cursor blinking space | |
| w += iconHeight; | |
| QStyleOptionSpinBox opt; | |
| initStyleOption(&opt); | |
| QSize hint(w, h); | |
| QSize size = style()->sizeFromContents(QStyle::CT_SpinBox, &opt, hint, this); | |
| return size; | |
| } | |
| void QuantitySpinBox::showEvent(QShowEvent* event) | |
| { | |
| Q_D(QuantitySpinBox); | |
| QAbstractSpinBox::showEvent(event); | |
| bool selected = lineEdit()->hasSelectedText(); | |
| updateText(d->quantity); | |
| if (selected) { | |
| selectNumber(); | |
| } | |
| } | |
| void QuantitySpinBox::hideEvent(QHideEvent* event) | |
| { | |
| handlePendingEmit(); | |
| QAbstractSpinBox::hideEvent(event); | |
| } | |
| void QuantitySpinBox::closeEvent(QCloseEvent* event) | |
| { | |
| handlePendingEmit(); | |
| QAbstractSpinBox::closeEvent(event); | |
| } | |
| void QuantitySpinBox::focusInEvent(QFocusEvent* event) | |
| { | |
| bool hasSel = lineEdit()->hasSelectedText(); | |
| QAbstractSpinBox::focusInEvent(event); | |
| if (event->reason() == Qt::TabFocusReason || event->reason() == Qt::BacktabFocusReason | |
| || event->reason() == Qt::ShortcutFocusReason) { | |
| if (!hasSel) { | |
| selectNumber(); | |
| } | |
| } | |
| } | |
| void QuantitySpinBox::focusOutEvent(QFocusEvent* event) | |
| { | |
| Q_D(QuantitySpinBox); | |
| int pos = 0; | |
| QString text = lineEdit()->text(); | |
| QValidator::State state; | |
| d->validateAndInterpret(text, pos, state); | |
| if (state != QValidator::Acceptable) { | |
| lineEdit()->setText(d->validStr); | |
| } | |
| handlePendingEmit(); | |
| QToolTip::hideText(); | |
| QAbstractSpinBox::focusOutEvent(event); | |
| } | |
| void QuantitySpinBox::clear() | |
| { | |
| QAbstractSpinBox::clear(); | |
| } | |
| void QuantitySpinBox::selectNumber() | |
| { | |
| QString expr = QString::fromLatin1("^([%1%2]?[0-9\\%3]*)\\%4?([0-9]+(%5[%1%2]?[0-9]+)?)") | |
| .arg(locale().negativeSign()) | |
| .arg(locale().positiveSign()) | |
| .arg(locale().groupSeparator()) | |
| .arg(locale().decimalPoint()) | |
| .arg(locale().exponential()); | |
| auto rmatch = QRegularExpression(expr).match(lineEdit()->text()); | |
| if (rmatch.hasMatch()) { | |
| lineEdit()->setSelection(0, rmatch.capturedLength()); | |
| } | |
| } | |
| QString QuantitySpinBox::textFromValue(const Base::Quantity& value) const | |
| { | |
| double factor; | |
| QString unitStr; | |
| QString str = getUserString(value, factor, unitStr); | |
| if (qAbs(value.getValue()) >= 1000.0) { | |
| str.remove(locale().groupSeparator()); | |
| } | |
| return str; | |
| } | |
| Base::Quantity QuantitySpinBox::valueFromText(const QString& text) const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| QString copy = text; | |
| int pos = lineEdit()->cursorPosition(); | |
| QValidator::State state = QValidator::Acceptable; | |
| Base::Quantity quant = d->validateAndInterpret(copy, pos, state); | |
| if (state != QValidator::Acceptable) { | |
| fixup(copy); | |
| quant = d->validateAndInterpret(copy, pos, state); | |
| } | |
| return quant; | |
| } | |
| QValidator::State QuantitySpinBox::validate(QString& text, int& pos) const | |
| { | |
| Q_D(const QuantitySpinBox); | |
| QValidator::State state; | |
| d->validateAndInterpret(text, pos, state); | |
| return state; | |
| } | |
| void QuantitySpinBox::fixup(QString& input) const | |
| { | |
| input.remove(locale().groupSeparator()); | |
| } | |
| // ------------------------------------------------------------------------------ | |
| PrefUnitSpinBox::PrefUnitSpinBox(QWidget* parent) | |
| : QuantitySpinBox(parent) | |
| {} | |
| PrefUnitSpinBox::~PrefUnitSpinBox() | |
| {} | |
| QByteArray PrefUnitSpinBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefUnitSpinBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefUnitSpinBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefUnitSpinBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefQuantitySpinBox::PrefQuantitySpinBox(QWidget* parent) | |
| : QuantitySpinBox(parent) | |
| {} | |
| PrefQuantitySpinBox::~PrefQuantitySpinBox() | |
| {} | |
| QByteArray PrefQuantitySpinBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefQuantitySpinBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefQuantitySpinBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefQuantitySpinBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| CommandIconView::CommandIconView(QWidget* parent) | |
| : QListWidget(parent) | |
| { | |
| connect(this, &QListWidget::currentItemChanged, this, &CommandIconView::onSelectionChanged); | |
| } | |
| CommandIconView::~CommandIconView() | |
| {} | |
| void CommandIconView::startDrag(Qt::DropActions /*supportedActions*/) | |
| { | |
| QList<QListWidgetItem*> items = selectedItems(); | |
| QByteArray itemData; | |
| QDataStream dataStream(&itemData, QIODevice::WriteOnly); | |
| QPixmap pixmap; | |
| dataStream << items.count(); | |
| for (QList<QListWidgetItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) { | |
| if (it == items.begin()) { | |
| pixmap = ((*it)->data(Qt::UserRole)).value<QPixmap>(); | |
| } | |
| dataStream << (*it)->text(); | |
| } | |
| QMimeData* mimeData = new QMimeData; | |
| mimeData->setData("text/x-action-items", itemData); | |
| QDrag* drag = new QDrag(this); | |
| drag->setMimeData(mimeData); | |
| drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); | |
| drag->setPixmap(pixmap); | |
| drag->exec(Qt::MoveAction); | |
| } | |
| void CommandIconView::onSelectionChanged(QListWidgetItem* item, QListWidgetItem*) | |
| { | |
| if (item) { | |
| emitSelectionChanged(item->toolTip()); | |
| } | |
| } | |
| // ------------------------------------------------------------------------------ | |
| namespace Gui | |
| { | |
| class UnsignedValidator: public QValidator | |
| { | |
| public: | |
| UnsignedValidator(QObject* parent); | |
| UnsignedValidator(uint minimum, uint maximum, QObject* parent); | |
| ~UnsignedValidator(); | |
| QValidator::State validate(QString&, int&) const; | |
| void setBottom(uint); | |
| void setTop(uint); | |
| virtual void setRange(uint bottom, uint top); | |
| uint bottom() const | |
| { | |
| return b; | |
| } | |
| uint top() const | |
| { | |
| return t; | |
| } | |
| private: | |
| uint b, t; | |
| }; | |
| UnsignedValidator::UnsignedValidator(QObject* parent) | |
| : QValidator(parent) | |
| { | |
| b = 0; | |
| t = std::numeric_limits<unsigned>::max(); | |
| } | |
| UnsignedValidator::UnsignedValidator(uint minimum, uint maximum, QObject* parent) | |
| : QValidator(parent) | |
| { | |
| b = minimum; | |
| t = maximum; | |
| } | |
| UnsignedValidator::~UnsignedValidator() | |
| {} | |
| QValidator::State UnsignedValidator::validate(QString& input, int&) const | |
| { | |
| QString stripped; // = input.stripWhiteSpace(); | |
| if (stripped.isEmpty()) { | |
| return Intermediate; | |
| } | |
| bool ok; | |
| uint entered = input.toUInt(&ok); | |
| if (!ok) { | |
| return Invalid; | |
| } | |
| else if (entered < b) { | |
| return Intermediate; | |
| } | |
| else if (entered > t) { | |
| return Invalid; | |
| } | |
| // else if ( entered < b || entered > t ) | |
| // return Invalid; | |
| else { | |
| return Acceptable; | |
| } | |
| } | |
| void UnsignedValidator::setRange(uint minimum, uint maximum) | |
| { | |
| b = minimum; | |
| t = maximum; | |
| } | |
| void UnsignedValidator::setBottom(uint bottom) | |
| { | |
| setRange(bottom, top()); | |
| } | |
| void UnsignedValidator::setTop(uint top) | |
| { | |
| setRange(bottom(), top); | |
| } | |
| class UIntSpinBoxPrivate | |
| { | |
| public: | |
| UnsignedValidator* mValidator; | |
| UIntSpinBoxPrivate() | |
| : mValidator(0) | |
| {} | |
| unsigned mapToUInt(int v) const | |
| { | |
| using int_limits = std::numeric_limits<int>; | |
| using uint_limits = std::numeric_limits<unsigned>; | |
| unsigned ui; | |
| if (v == int_limits::min()) { | |
| ui = 0; | |
| } | |
| else if (v == int_limits::max()) { | |
| ui = uint_limits::max(); | |
| } | |
| else if (v < 0) { | |
| v -= int_limits::min(); | |
| ui = static_cast<unsigned>(v); | |
| } | |
| else { | |
| ui = static_cast<unsigned>(v); | |
| ui -= int_limits::min(); | |
| } | |
| return ui; | |
| } | |
| int mapToInt(unsigned v) const | |
| { | |
| using int_limits = std::numeric_limits<int>; | |
| using uint_limits = std::numeric_limits<unsigned>; | |
| int in; | |
| if (v == uint_limits::max()) { | |
| in = int_limits::max(); | |
| } | |
| else if (v == 0) { | |
| in = int_limits::min(); | |
| } | |
| else if (v > int_limits::max()) { | |
| v += int_limits::min(); | |
| in = static_cast<int>(v); | |
| } | |
| else { | |
| in = v; | |
| in += int_limits::min(); | |
| } | |
| return in; | |
| } | |
| }; | |
| } // namespace Gui | |
| // ------------------------------------------------------------- | |
| UIntSpinBox::UIntSpinBox(QWidget* parent) | |
| : QSpinBox(parent) | |
| { | |
| d = new UIntSpinBoxPrivate; | |
| d->mValidator = new UnsignedValidator(this->minimum(), this->maximum(), this); | |
| connect(this, qOverload<int>(&QSpinBox::valueChanged), this, &UIntSpinBox::valueChange); | |
| setRange(0, 99); | |
| setValue(0); | |
| updateValidator(); | |
| } | |
| UIntSpinBox::~UIntSpinBox() | |
| { | |
| delete d->mValidator; | |
| delete d; | |
| d = 0; | |
| } | |
| void UIntSpinBox::setRange(uint minVal, uint maxVal) | |
| { | |
| int iminVal = d->mapToInt(minVal); | |
| int imaxVal = d->mapToInt(maxVal); | |
| QSpinBox::setRange(iminVal, imaxVal); | |
| updateValidator(); | |
| } | |
| QValidator::State UIntSpinBox::validate(QString& input, int& pos) const | |
| { | |
| return d->mValidator->validate(input, pos); | |
| } | |
| uint UIntSpinBox::value() const | |
| { | |
| return d->mapToUInt(QSpinBox::value()); | |
| } | |
| void UIntSpinBox::setValue(uint value) | |
| { | |
| QSpinBox::setValue(d->mapToInt(value)); | |
| } | |
| void UIntSpinBox::valueChange(int value) | |
| { | |
| unsignedChanged(d->mapToUInt(value)); | |
| } | |
| uint UIntSpinBox::minimum() const | |
| { | |
| return d->mapToUInt(QSpinBox::minimum()); | |
| } | |
| void UIntSpinBox::setMinimum(uint minVal) | |
| { | |
| uint maxVal = maximum(); | |
| if (maxVal < minVal) { | |
| maxVal = minVal; | |
| } | |
| setRange(minVal, maxVal); | |
| } | |
| uint UIntSpinBox::maximum() const | |
| { | |
| return d->mapToUInt(QSpinBox::maximum()); | |
| } | |
| void UIntSpinBox::setMaximum(uint maxVal) | |
| { | |
| uint minVal = minimum(); | |
| if (minVal > maxVal) { | |
| minVal = maxVal; | |
| } | |
| setRange(minVal, maxVal); | |
| } | |
| QString UIntSpinBox::textFromValue(int v) const | |
| { | |
| uint val = d->mapToUInt(v); | |
| QString s; | |
| s.setNum(val); | |
| return s; | |
| } | |
| int UIntSpinBox::valueFromText(const QString& text) const | |
| { | |
| bool ok; | |
| QString s = text; | |
| uint newVal = s.toUInt(&ok); | |
| if (!ok && !(prefix().isEmpty() && suffix().isEmpty())) { | |
| s = cleanText(); | |
| newVal = s.toUInt(&ok); | |
| } | |
| return d->mapToInt(newVal); | |
| } | |
| void UIntSpinBox::updateValidator() | |
| { | |
| d->mValidator->setRange(this->minimum(), this->maximum()); | |
| } | |
| // -------------------------------------------------------------------- | |
| IntSpinBox::IntSpinBox(QWidget* parent) | |
| : QSpinBox(parent) | |
| {} | |
| IntSpinBox::~IntSpinBox() | |
| {} | |
| // -------------------------------------------------------------------- | |
| PrefSpinBox::PrefSpinBox(QWidget* parent) | |
| : QSpinBox(parent) | |
| {} | |
| PrefSpinBox::~PrefSpinBox() | |
| {} | |
| QByteArray PrefSpinBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefSpinBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefSpinBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefSpinBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| DoubleSpinBox::DoubleSpinBox(QWidget* parent) | |
| : QDoubleSpinBox(parent) | |
| {} | |
| DoubleSpinBox::~DoubleSpinBox() | |
| {} | |
| // -------------------------------------------------------------------- | |
| PrefDoubleSpinBox::PrefDoubleSpinBox(QWidget* parent) | |
| : QDoubleSpinBox(parent) | |
| {} | |
| PrefDoubleSpinBox::~PrefDoubleSpinBox() | |
| {} | |
| QByteArray PrefDoubleSpinBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefDoubleSpinBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefDoubleSpinBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefDoubleSpinBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // ------------------------------------------------------------- | |
| ColorButton::ColorButton(QWidget* parent) | |
| : QPushButton(parent) | |
| , _allowChange(true) | |
| , _allowTransparency(false) | |
| , _drawFrame(true) | |
| { | |
| _col = palette().color(QPalette::Active, QPalette::Midlight); | |
| connect(this, &ColorButton::clicked, this, &ColorButton::onChooseColor); | |
| } | |
| ColorButton::~ColorButton() | |
| {} | |
| void ColorButton::setColor(const QColor& c) | |
| { | |
| _col = c; | |
| update(); | |
| } | |
| QColor ColorButton::color() const | |
| { | |
| return _col; | |
| } | |
| void ColorButton::setAllowChangeColor(bool ok) | |
| { | |
| _allowChange = ok; | |
| } | |
| bool ColorButton::allowChangeColor() const | |
| { | |
| return _allowChange; | |
| } | |
| void ColorButton::setAllowTransparency(bool ok) | |
| { | |
| _allowTransparency = ok; | |
| } | |
| bool ColorButton::allowTransparency() const | |
| { | |
| return _allowTransparency; | |
| } | |
| void ColorButton::setDrawFrame(bool ok) | |
| { | |
| _drawFrame = ok; | |
| } | |
| bool ColorButton::drawFrame() const | |
| { | |
| return _drawFrame; | |
| } | |
| void ColorButton::paintEvent(QPaintEvent* e) | |
| { | |
| // first paint the complete button | |
| QPushButton::paintEvent(e); | |
| // repaint the rectangle area | |
| QPalette::ColorGroup group = isEnabled() ? hasFocus() ? QPalette::Active : QPalette::Inactive | |
| : QPalette::Disabled; | |
| QColor pen = palette().color(group, QPalette::ButtonText); | |
| { | |
| QPainter paint(this); | |
| paint.setPen(pen); | |
| if (_drawFrame) { | |
| paint.setBrush(QBrush(_col)); | |
| paint.drawRect(5, 5, width() - 10, height() - 10); | |
| } | |
| else { | |
| paint.fillRect(5, 5, width() - 10, height() - 10, QBrush(_col)); | |
| } | |
| } | |
| // overpaint the rectangle to paint icon and text | |
| QStyleOptionButton opt; | |
| opt.initFrom(this); | |
| opt.text = text(); | |
| opt.icon = icon(); | |
| opt.iconSize = iconSize(); | |
| QStylePainter p(this); | |
| p.drawControl(QStyle::CE_PushButtonLabel, opt); | |
| } | |
| void ColorButton::onChooseColor() | |
| { | |
| if (!_allowChange) { | |
| return; | |
| } | |
| QColor c = QColorDialog::getColor(_col, this); | |
| if (c.isValid()) { | |
| setColor(c); | |
| Q_EMIT changed(); | |
| } | |
| } | |
| // ------------------------------------------------------------------------------ | |
| PrefColorButton::PrefColorButton(QWidget* parent) | |
| : ColorButton(parent) | |
| {} | |
| PrefColorButton::~PrefColorButton() | |
| {} | |
| QByteArray PrefColorButton::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefColorButton::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefColorButton::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefColorButton::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefLineEdit::PrefLineEdit(QWidget* parent) | |
| : QLineEdit(parent) | |
| {} | |
| PrefLineEdit::~PrefLineEdit() | |
| {} | |
| QByteArray PrefLineEdit::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefLineEdit::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefLineEdit::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefLineEdit::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefComboBox::PrefComboBox(QWidget* parent) | |
| : QComboBox(parent) | |
| { | |
| setEditable(false); | |
| } | |
| PrefComboBox::~PrefComboBox() | |
| {} | |
| QByteArray PrefComboBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefComboBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefComboBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefComboBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefCheckBox::PrefCheckBox(QWidget* parent) | |
| : QCheckBox(parent) | |
| { | |
| setText("CheckBox"); | |
| } | |
| PrefCheckBox::~PrefCheckBox() | |
| {} | |
| QByteArray PrefCheckBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefCheckBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefCheckBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefCheckBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefRadioButton::PrefRadioButton(QWidget* parent) | |
| : QRadioButton(parent) | |
| { | |
| setText("RadioButton"); | |
| } | |
| PrefRadioButton::~PrefRadioButton() | |
| {} | |
| QByteArray PrefRadioButton::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefRadioButton::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefRadioButton::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefRadioButton::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefSlider::PrefSlider(QWidget* parent) | |
| : QSlider(parent) | |
| {} | |
| PrefSlider::~PrefSlider() | |
| {} | |
| QByteArray PrefSlider::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefSlider::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefSlider::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefSlider::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |
| // -------------------------------------------------------------------- | |
| PrefFontBox::PrefFontBox(QWidget* parent) | |
| : QFontComboBox(parent) | |
| {} | |
| PrefFontBox::~PrefFontBox() | |
| {} | |
| QByteArray PrefFontBox::entryName() const | |
| { | |
| return m_sPrefName; | |
| } | |
| QByteArray PrefFontBox::paramGrpPath() const | |
| { | |
| return m_sPrefGrp; | |
| } | |
| void PrefFontBox::setEntryName(const QByteArray& name) | |
| { | |
| m_sPrefName = name; | |
| } | |
| void PrefFontBox::setParamGrpPath(const QByteArray& name) | |
| { | |
| m_sPrefGrp = name; | |
| } | |