/*************************************************************************** * Copyright (c) 2006 Werner Mayer * * * * 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 * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "customwidgets.h" using namespace Gui; UrlLabel::UrlLabel ( QWidget * parent, Qt::WindowFlags f ) : QLabel("TextLabel", parent, f) { _url = "http://localhost"; setToolTip(this->_url); } UrlLabel::~UrlLabel() { } void UrlLabel::enterEvent ( QEvent * ) { setCursor(Qt::PointingHandCursor); } void UrlLabel::leaveEvent ( QEvent * ) { setCursor(Qt::ArrowCursor); } 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->setMargin( 0 ); layout->setSpacing( 6 ); lineEdit = new QLineEdit( this ); layout->addWidget( lineEdit ); connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SIGNAL(fileNameChanged(const QString &))); button = new QPushButton( "...", this ); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) button->setFixedWidth(2 * button->fontMetrics().horizontalAdvance(" ... ")); #else button->setFixedWidth(2*button->fontMetrics().width( " ... " )); #endif layout->addWidget( button ); connect(button, SIGNAL(clicked()), this, SLOT(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 ); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) int w1 = 2 * button->fontMetrics().horizontalAdvance(txt); int w2 = 2 * button->fontMetrics().horizontalAdvance(" ... "); #else int w1 = 2 * button->fontMetrics().width(txt); int w2 = 2*button->fontMetrics().width(" ... "); #endif 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) { setText(tr("none")); } void AccelLineEdit::keyPressEvent ( QKeyEvent * e) { QString txt; setText(tr("none")); int key = e->key(); Qt::KeyboardModifiers state = e->modifiers(); if ( key == Qt::Key_Control ) return; else if ( key == Qt::Key_Shift ) return; else if ( key == Qt::Key_Alt ) return; else if ( state == Qt::NoModifier && key == Qt::Key_Backspace ) return; // clears the edit field switch( state ) { case Qt::ControlModifier: { QKeySequence keyseq(Qt::CTRL+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::AltModifier: { QKeySequence keyseq(Qt::ALT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::ShiftModifier: { QKeySequence keyseq(Qt::SHIFT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::ControlModifier+Qt::AltModifier: { QKeySequence keyseq(Qt::CTRL+Qt::ALT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::ControlModifier+Qt::ShiftModifier: { QKeySequence keyseq(Qt::CTRL+Qt::SHIFT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::ShiftModifier+Qt::AltModifier: { QKeySequence keyseq(Qt::SHIFT+Qt::ALT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; case Qt::ControlModifier+Qt::AltModifier+Qt::ShiftModifier: { QKeySequence keyseq(Qt::CTRL+Qt::ALT+Qt::SHIFT+key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; default: { QKeySequence keyseq(key); txt += keyseq.toString(QKeySequence::NativeText); setText(txt); } break; } } // ------------------------------------------------------------------------------ ActionSelector::ActionSelector(QWidget* parent) : QWidget(parent) { addButton = new QPushButton(this); addButton->setMinimumSize(QSize(30, 30)); QIcon icon; icon.addFile(QString::fromUtf8(":/icons/button_right.xpm"), 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.xpm"), 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.xpm"), 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.xpm"), 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(INT_MAX), Minimum(-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; } // -------------------------------------------------------------------- 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(format.option); Lc.setNumberOptions(static_cast(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(format.option); Lc.setNumberOptions(static_cast(opt)); } QString Ln = Lc.toString(value, format.toFormat(), format.precision); return QString::fromUtf8("%1 %2").arg(Ln, unit.getString()); } } namespace Gui { class QuantitySpinBoxPrivate { public: QuantitySpinBoxPrivate() : validInput(true), pendingEmit(false), unitValue(0), maximum(INT_MAX), minimum(-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= 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; }; } QuantitySpinBox::QuantitySpinBox(QWidget *parent) : QAbstractSpinBox(parent), d_ptr(new QuantitySpinBoxPrivate()) { d_ptr->locale = locale(); this->setContextMenuPolicy(Qt::DefaultContextMenu); QObject::connect(lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(userInput(QString))); QObject::connect(this, SIGNAL(editingFinished()), this, SLOT(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 { return QAbstractSpinBox::sizeHint(); } QSize QuantitySpinBox::minimumSizeHint() const { return QAbstractSpinBox::minimumSizeHint(); } 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); } bool QuantitySpinBox::event(QEvent * event) { // issue #0004059: Tooltips for Gui::QuantitySpinBox not showing // Here we must not try to show the tooltip of the icon label // because it would override a custom tooltip set to this widget. // // We could also check if the text of this tooltip is empty but // it will fail in cases where the widget is embedded into the // property editor and the corresponding item has set a tooltip. // Instead of showing the item's tooltip it will again show the // tooltip of the icon label. #if 0 if (event->type() == QEvent::ToolTip) { if (isBound() && getExpression() && lineEdit()->isReadOnly()) { QHelpEvent * helpEvent = static_cast(event); QToolTip::showText( helpEvent->globalPos(), Base::Tools::fromStdString(getExpression()->toString()), this); event->accept(); return true; } } #endif return QAbstractSpinBox::event(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 str = lineEdit()->text(); unsigned int i = 0; QChar d = locale().decimalPoint(); QChar g = locale().groupSeparator(); QChar n = locale().negativeSign(); for (QString::iterator it = str.begin(); it != str.end(); ++it) { if (it->isDigit()) i++; else if (*it == d) i++; else if (*it == g) i++; else if (*it == n) i++; else // any non-number character break; } lineEdit()->setSelection(0, i); } 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, SIGNAL (currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT (onSelectionChanged(QListWidgetItem *, QListWidgetItem *)) ); } CommandIconView::~CommandIconView () { } void CommandIconView::startDrag ( Qt::DropActions /*supportedActions*/ ) { QList items = selectedItems(); QByteArray itemData; QDataStream dataStream(&itemData, QIODevice::WriteOnly); QPixmap pixmap; dataStream << items.count(); for (QList::ConstIterator it = items.begin(); it != items.end(); ++it) { if (it == items.begin()) pixmap = ((*it)->data(Qt::UserRole)).value(); 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 = UINT_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) { } uint mapToUInt( int v ) const { uint ui; if ( v == INT_MIN ) { ui = 0; } else if ( v == INT_MAX ) { ui = UINT_MAX; } else if ( v < 0 ) { v -= INT_MIN; ui = (uint)v; } else { ui = (uint)v; ui -= INT_MIN; } return ui; } int mapToInt( uint v ) const { int in; if ( v == UINT_MAX ) { in = INT_MAX; } else if ( v == 0 ) { in = INT_MIN; } else if ( v > INT_MAX ) { v += INT_MIN; in = (int)v; } else { in = v; in += INT_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, SIGNAL(valueChanged(int)), this, SLOT(valueChange(int))); 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) { valueChanged(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), _drawFrame(true) { _col = palette().color(QPalette::Active,QPalette::Midlight); connect( this, SIGNAL( clicked() ), SLOT( 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::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.init(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; }