// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * 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 * * * ***************************************************************************/ #ifndef GUI_CUSTOMWIDGETS_H #define GUI_CUSTOMWIDGETS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Base { class Exception { }; class Unit { public: Unit(); Unit(const QString&); bool isEmpty() const; bool operator==(const Unit&); bool operator!=(const Unit&); const QString& getString() const; private: QString unit; }; struct QuantityFormat { enum NumberOption { None = 0x00, OmitGroupSeparator = 0x01, RejectGroupSeparator = 0x02 }; enum NumberFormat { Default = 0, Fixed = 1, Scientific = 2 }; using NumberOptions = int; NumberOptions option; NumberFormat format; int precision; int denominator; // Default denominator of minimum fractional inch. Only used in certain // schemas. static int defaultDenominator; // i.e 8 for 1/8" static inline int getDefaultDenominator() { return defaultDenominator; } static inline void setDefaultDenominator(int denom) { defaultDenominator = denom; } inline int getDenominator() const { return denominator; } inline void setDenominator(int denom) { denominator = denom; } QuantityFormat(); inline char toFormat() const { switch (format) { case Fixed: return 'f'; case Scientific: return 'e'; default: return 'g'; } } static inline NumberFormat toFormat(char c, bool* ok = 0) { if (ok) { *ok = true; } switch (c) { case 'f': return Fixed; case 'e': return Scientific; case 'g': return Default; default: if (ok) { *ok = false; } return Default; } } }; class Quantity { public: Quantity(void); explicit Quantity(double Value, const Unit& unit = Unit()); static Quantity parse(const QString&); void setValue(double); double getValue() const; void setUnit(const Unit&); Unit getUnit() const; const QuantityFormat& getFormat() const { return format; } void setFormat(const QuantityFormat& f) { format = f; } QString getUserString() const; QString getUserString(double& factor, QString& unitString) const; private: double value; Unit unit; QuantityFormat format; }; } // namespace Base Q_DECLARE_METATYPE(Base::Quantity) namespace Gui { class UrlLabel: public QLabel { Q_OBJECT Q_PROPERTY(QString url READ url WRITE setUrl) public: UrlLabel(QWidget* parent = 0, Qt::WindowFlags f = Qt::WindowFlags()); virtual ~UrlLabel(); QString url() const; public Q_SLOTS: void setUrl(const QString& u); protected: void mouseReleaseEvent(QMouseEvent*); private: QString _url; }; class LocationWidget: public QWidget { Q_OBJECT public: LocationWidget(QWidget* parent = 0); virtual ~LocationWidget(); QSize sizeHint() const; public Q_SLOTS: private: void changeEvent(QEvent*); void retranslateUi(); private: QGridLayout* box; QLabel* xLabel; QLabel* yLabel; QLabel* zLabel; QLabel* dLabel; QDoubleSpinBox* xValue; QDoubleSpinBox* yValue; QDoubleSpinBox* zValue; QComboBox* dValue; }; /** * There is a bug in QtDesigner of Qt version 4.0, 4.1 and 4.2. If a class declaration * is inside a namespace and it uses the Q_ENUM macro then QtDesigner doesn't handle * the enum(s) correctly in its property editor. This bug is fixed since Qt 4.3.0. */ class FileChooser: public QWidget { Q_OBJECT public: enum Mode { File, Directory }; private: Q_ENUM(Mode) Q_PROPERTY(Mode mode READ mode WRITE setMode) Q_PROPERTY(QString fileName READ fileName WRITE setFileName) Q_PROPERTY(QString filter READ filter WRITE setFilter) Q_PROPERTY(QString buttonText READ buttonText WRITE setButtonText) public: FileChooser(QWidget* parent = 0); virtual ~FileChooser(); QString filter() const; QString fileName() const; Mode mode() const; QString buttonText() const; public Q_SLOTS: void setFileName(const QString& fn); void setMode(FileChooser::Mode m); void setFilter(const QString&); void setButtonText(const QString&); Q_SIGNALS: void fileNameChanged(const QString&); void fileNameSelected(const QString&); private Q_SLOTS: void chooseFile(); private: QLineEdit* lineEdit; QPushButton* button; Mode md; QString _filter; }; // ------------------------------------------------------------------------------ class PrefFileChooser: public FileChooser { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefFileChooser(QWidget* parent = 0); virtual ~PrefFileChooser(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class AccelLineEdit: public QLineEdit { Q_OBJECT public: AccelLineEdit(QWidget* parent = 0); bool isNone() const; protected: void keyPressEvent(QKeyEvent* e); private: int keyPressedCount; }; // ------------------------------------------------------------------------------ class ActionSelector: public QWidget { Q_OBJECT public: ActionSelector(QWidget* parent = 0); ~ActionSelector(); private: QGridLayout* gridLayout; QVBoxLayout* vboxLayout; QVBoxLayout* vboxLayout1; QPushButton* addButton; QPushButton* removeButton; QPushButton* upButton; QPushButton* downButton; QLabel* labelAvailable; QLabel* labelSelected; QTreeWidget* availableWidget; QTreeWidget* selectedWidget; QSpacerItem* spacerItem; QSpacerItem* spacerItem1; }; // ------------------------------------------------------------------------------ class InputField: public QLineEdit { Q_OBJECT Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep) Q_PROPERTY(double maximum READ maximum WRITE setMaximum) Q_PROPERTY(double minimum READ minimum WRITE setMinimum) Q_PROPERTY(int historySize READ historySize WRITE setHistorySize) Q_PROPERTY(QString unit READ getUnitText WRITE setUnitText) Q_PROPERTY(double quantity READ getQuantity WRITE setValue) public: InputField(QWidget* parent = 0); virtual ~InputField(); void setValue(double); double getQuantity(void) const; double singleStep(void) const; void setSingleStep(double); double maximum(void) const; void setMaximum(double); double minimum(void) const; void setMinimum(double); int historySize(void) const; void setHistorySize(int); void setUnitText(QString); QString getUnitText(void); QByteArray paramGrpPath() const; void setParamGrpPath(const QByteArray& name); Q_SIGNALS: void valueChanged(const Base::Quantity&); void valueChanged(double); void parseError(const QString& errorText); private: QByteArray m_sPrefGrp; QString UnitStr; double Value; double Maximum; double Minimum; double StepSize; int HistorySize; }; // ------------------------------------------------------------------------------ class ExpressionLineEdit: public QLineEdit { Q_OBJECT public: ExpressionLineEdit(QWidget* parent = nullptr); public Q_SLOTS: void slotTextChanged(const QString& text); void slotCompleteText(const QString& completionPrefix, bool isActivated); void slotCompleteTextHighlighted(const QString& completionPrefix); void slotCompleteTextSelected(const QString& completionPrefix); void setExactMatch(bool enabled = true); protected: void keyPressEvent(QKeyEvent* event) override; void contextMenuEvent(QContextMenuEvent* event) override; Q_SIGNALS: void textChanged2(QString text, int pos); private: QCompleter* completer; bool exactMatch; }; // ------------------------------------------------------------------------------ class QuantitySpinBoxPrivate; class QuantitySpinBox: public QAbstractSpinBox { Q_OBJECT Q_PROPERTY(QString unit READ unitText WRITE setUnitText) Q_PROPERTY(double minimum READ minimum WRITE setMinimum) Q_PROPERTY(double maximum READ maximum WRITE setMaximum) Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep) Q_PROPERTY(double rawValue READ rawValue WRITE setValue NOTIFY valueChanged DESIGNABLE false) Q_PROPERTY(double value READ rawValue WRITE setValue NOTIFY valueChanged USER true) // Q_PROPERTY(Base::Quantity value READ value WRITE setValue NOTIFY valueChanged USER true) public: explicit QuantitySpinBox(QWidget* parent = 0); virtual ~QuantitySpinBox(); /// Get the current quantity Base::Quantity value() const; /// Get the current quantity without unit double rawValue() const; /// Gives the current state of the user input, gives true if it is a valid input with correct /// quantity or returns false if the input is a unparsable string or has a wrong unit. bool hasValidInput() const; /** Sets the Unit this widget is working with. * After setting the Unit the widget will only accept * user input with this unit type. Or if the user input * a value without unit, this one will be added to the resulting * Quantity. */ Base::Unit unit() const; void setUnit(const Base::Unit& unit); /// Set the unit property void setUnitText(const QString&); /// Get the unit property QString unitText(void); /// Get the value of the singleStep property double singleStep() const; /// Set the value of the singleStep property void setSingleStep(double val); /// Gets the value of the minimum property double minimum() const; /// Sets the value of the minimum property void setMinimum(double min); /// Gets the value of the maximum property double maximum() const; /// Sets the value of the maximum property void setMaximum(double max); /// Gets the number of decimals int decimals() const; /// Sets the number of decimals void setDecimals(int v); /// Clears the schemaand again use the system-wide schema. void clearSchema(); /// Set the number portion selected void selectNumber(); void setRange(double min, double max); Base::Quantity valueFromText(const QString& text) const; QString textFromValue(const Base::Quantity& val) const; virtual void stepBy(int steps); virtual void clear(); virtual QValidator::State validate(QString& input, int& pos) const; virtual void fixup(QString& str) const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: /// Sets the field with a quantity void setValue(const Base::Quantity& val); /// Set a numerical value which gets converted to a quantity with the currently set unit type void setValue(double); protected Q_SLOTS: void userInput(const QString& text); void handlePendingEmit(); protected: virtual StepEnabled stepEnabled() const; virtual void showEvent(QShowEvent* event); virtual void hideEvent(QHideEvent* event); virtual void closeEvent(QCloseEvent* event); virtual void focusInEvent(QFocusEvent* event); virtual void focusOutEvent(QFocusEvent* event); virtual void keyPressEvent(QKeyEvent* event); virtual void resizeEvent(QResizeEvent* event); private: void updateText(const Base::Quantity&); void updateFromCache(bool); QString getUserString(const Base::Quantity& val, double& factor, QString& unitString) const; QString getUserString(const Base::Quantity& val) const; Q_SIGNALS: /** Gets emitted if the user has entered a VALID input * Valid means the user inputted string obeys all restrictions * like: minimum, maximum and/or the right Unit (if specified). */ void valueChanged(const Base::Quantity&); /** Gets emitted if the user has entered a VALID input * Valid means the user inputted string obeys all restrictions * like: minimum, maximum and/or the right Unit (if specified). */ void valueChanged(double); /** * The new value is passed in \a text with unit. */ void textChanged(const QString&); /** Gets emitted if formula dialog is about to be opened (true) * or finished (false). */ void showFormulaDialog(bool); private: QScopedPointer d_ptr; Q_DISABLE_COPY(QuantitySpinBox) Q_DECLARE_PRIVATE(QuantitySpinBox) }; // ------------------------------------------------------------------------------ class PrefUnitSpinBox: public QuantitySpinBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefUnitSpinBox(QWidget* parent = 0); virtual ~PrefUnitSpinBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefQuantitySpinBox: public QuantitySpinBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefQuantitySpinBox(QWidget* parent = 0); virtual ~PrefQuantitySpinBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class CommandIconView: public QListWidget { Q_OBJECT public: CommandIconView(QWidget* parent = 0); virtual ~CommandIconView(); protected: void startDrag(Qt::DropActions supportedActions); protected Q_SLOTS: void onSelectionChanged(QListWidgetItem* item, QListWidgetItem*); Q_SIGNALS: void emitSelectionChanged(const QString&); }; // ------------------------------------------------------------- class UIntSpinBoxPrivate; class UIntSpinBox: public QSpinBox { Q_OBJECT Q_OVERRIDE(uint maximum READ maximum WRITE setMaximum) Q_OVERRIDE(uint minimum READ minimum WRITE setMinimum) Q_OVERRIDE(uint value READ value WRITE setValue) public: UIntSpinBox(QWidget* parent); virtual ~UIntSpinBox(); void setRange(uint minVal, uint maxVal); uint value() const; virtual QValidator::State validate(QString& input, int& pos) const; uint minimum() const; void setMinimum(uint value); uint maximum() const; void setMaximum(uint value); Q_SIGNALS: void unsignedChanged(uint value); public Q_SLOTS: void setValue(uint value); private Q_SLOTS: void valueChange(int value); protected: virtual QString textFromValue(int v) const; virtual int valueFromText(const QString& text) const; private: void updateValidator(); UIntSpinBoxPrivate* d; }; // ------------------------------------------------------------------------------ class IntSpinBox: public QSpinBox { Q_OBJECT public: IntSpinBox(QWidget* parent = 0); virtual ~IntSpinBox(); }; // ------------------------------------------------------------------------------ class DoubleSpinBox: public QDoubleSpinBox { Q_OBJECT public: DoubleSpinBox(QWidget* parent = 0); virtual ~DoubleSpinBox(); }; // ------------------------------------------------------------- class PrefSpinBox: public QSpinBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefSpinBox(QWidget* parent = 0); virtual ~PrefSpinBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class ColorButton: public QPushButton { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor) Q_PROPERTY(bool allowChangeColor READ allowChangeColor WRITE setAllowChangeColor) Q_PROPERTY(bool drawFrame READ drawFrame WRITE setDrawFrame) Q_PROPERTY(bool allowTransparency READ allowTransparency WRITE setAllowTransparency) public: ColorButton(QWidget* parent = 0); ~ColorButton(); void setColor(const QColor&); QColor color() const; void setAllowChangeColor(bool); bool allowChangeColor() const; void setAllowTransparency(bool); bool allowTransparency() const; void setDrawFrame(bool); bool drawFrame() const; public Q_SLOTS: virtual void onChooseColor(); Q_SIGNALS: void changed(); protected: void paintEvent(QPaintEvent*); private: QColor _col; bool _allowChange; bool _allowTransparency; bool _drawFrame; }; // ------------------------------------------------------------------------------ class PrefColorButton: public ColorButton { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefColorButton(QWidget* parent = 0); virtual ~PrefColorButton(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefDoubleSpinBox: public QDoubleSpinBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefDoubleSpinBox(QWidget* parent = 0); virtual ~PrefDoubleSpinBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefLineEdit: public QLineEdit { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefLineEdit(QWidget* parent = 0); virtual ~PrefLineEdit(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefComboBox: public QComboBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefComboBox(QWidget* parent = 0); virtual ~PrefComboBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefCheckBox: public QCheckBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefCheckBox(QWidget* parent = 0); virtual ~PrefCheckBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefRadioButton: public QRadioButton { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefRadioButton(QWidget* parent = 0); virtual ~PrefRadioButton(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefSlider: public QSlider { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefSlider(QWidget* parent = 0); virtual ~PrefSlider(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; // ------------------------------------------------------------------------------ class PrefFontBox: public QFontComboBox { Q_OBJECT Q_PROPERTY(QByteArray prefEntry READ entryName WRITE setEntryName) Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath) public: PrefFontBox(QWidget* parent = 0); virtual ~PrefFontBox(); QByteArray entryName() const; QByteArray paramGrpPath() const; void setEntryName(const QByteArray& name); void setParamGrpPath(const QByteArray& name); private: QByteArray m_sPrefName; QByteArray m_sPrefGrp; }; } // namespace Gui #endif // GUI_CUSTOMWIDGETS_H