File indexing completed on 2024-06-02 05:19:16
0001 /* 0002 * spinbox.h - spin box with shift-click step value and read-only option 0003 * Program: kalarm 0004 * SPDX-FileCopyrightText: 2002-2023 David Jarvie <djarvie@kde.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #pragma once 0010 0011 #include <QSpinBox> 0012 class QEvent; 0013 class QStyle; 0014 class QStyleOptionSpinBox; 0015 0016 0017 /** 0018 * @short Spin box with accelerated shift or control key stepping, and read-only option. 0019 * 0020 * The SpinBox class provides a QSpinBox with accelerated stepping using the shift or 0021 * control key. 0022 * 0023 * A separate step increment may optionally be specified for use when the shift or 0024 * control key is held down. Typically this would be larger than the normal step. Then, 0025 * when the user clicks the spin buttons, he/she can increment or decrement the value 0026 * faster by holding the shift key down. 0027 * 0028 * The widget may be set as read-only. This has the same effect as disabling it, except 0029 * that its appearance is unchanged. 0030 * 0031 * @author David Jarvie <djarvie@kde.org> 0032 */ 0033 class SpinBox : public QSpinBox 0034 { 0035 Q_OBJECT 0036 public: 0037 /** Constructor. 0038 * @param parent The parent object of this widget. 0039 */ 0040 explicit SpinBox(QWidget* parent = nullptr); 0041 0042 /** Constructor. 0043 * @param minValue The minimum value which the spin box can have. 0044 * @param maxValue The maximum value which the spin box can have. 0045 * @param parent The parent object of this widget. 0046 */ 0047 SpinBox(int minValue, int maxValue, QWidget* parent = nullptr); 0048 0049 ~SpinBox() override; 0050 0051 /** Returns true if the widget is read only. */ 0052 bool isReadOnly() const { return mReadOnly; } 0053 0054 /** Sets whether the spin box can be changed by the user. 0055 * @param readOnly True to set the widget read-only, false to set it read-write. 0056 */ 0057 virtual void setReadOnly(bool readOnly); 0058 0059 /** Returns whether the spin box value text is selected when its value is stepped. */ 0060 bool selectOnStep() const { return mSelectOnStep; } 0061 0062 /** Sets whether the spin box value text should be selected when its value is stepped. */ 0063 void setSelectOnStep(bool sel) { mSelectOnStep = sel; } 0064 0065 /** Adds a value to the current value of the spin box. */ 0066 void addValue(int change) { addValue(change, false); } 0067 0068 /** Returns the minimum value of the spin box. */ 0069 int minimum() const { return mMinValue; } 0070 0071 /** Returns the maximum value of the spin box. */ 0072 int maximum() const { return mMaxValue; } 0073 0074 /** Sets the minimum value of the spin box. */ 0075 void setMinimum(int val); 0076 0077 /** Sets the maximum value of the spin box. */ 0078 void setMaximum(int val); 0079 0080 /** Sets the minimum and maximum values of the spin box. */ 0081 void setRange(int minValue, int maxValue) { setMinimum(minValue); setMaximum(maxValue); } 0082 0083 /** Returns the specified value clamped to the range of the spin box. */ 0084 int bound(int val) const; 0085 0086 /** Called whenever the user triggers a step, to adjust the value of 0087 * the spin box by the unshifted increment. 0088 */ 0089 void stepBy(int steps) override; 0090 0091 /** Returns the unshifted step increment, i.e. the amount by which the spin box value 0092 * changes when a spin button is clicked without the shift or control key being pressed. 0093 */ 0094 int singleStep() const { return mLineStep; } 0095 0096 /** Sets the unshifted step increment, i.e. the amount by which the spin box value 0097 * changes when a spin button is clicked without the shift or control key being pressed. 0098 */ 0099 void setSingleStep(int step); 0100 0101 /** Returns the shifted step increment, i.e. the amount by which the spin box value 0102 * changes when a spin button is clicked while the shift key is pressed. 0103 */ 0104 int singleShiftStep() const { return mLineShiftStep; } 0105 0106 /** Sets the shifted step increment, i.e. the amount by which the spin box value 0107 * changes when a spin button is clicked while the shift key is pressed. 0108 */ 0109 void setSingleShiftStep(int step); 0110 0111 /** Returns the control step increment, i.e. the amount by which the spin box value 0112 * changes when a spin button is clicked while the control key is pressed. 0113 * @return control key step increment, or 0 if none has been set. 0114 */ 0115 int singleControlStep() const { return mLineControlStep; } 0116 0117 /** Returns whether control steps should always set the value to a multiple of 0118 * the control step increment. 0119 */ 0120 bool modControlStep() const { return mModControlStep; } 0121 0122 /** Sets the control step increment, i.e. the amount by which the spin box value 0123 * changes when a spin button is clicked while the control key is pressed. 0124 * By default, Qt uses the single step increment multiplied by 10. 0125 * @param step Increment when control key is pressed, or 0 to use default Qt 0126 * handling which multiplies the default step by 10. 0127 * @param mod Control steps should always set value to multiple of @p step. 0128 */ 0129 void setSingleControlStep(int step, bool mod = true); 0130 0131 /** Returns the rectangle containing the up arrow. */ 0132 QRect upRect() const; 0133 0134 /** Returns the rectangle containing the down arrow. */ 0135 QRect downRect() const; 0136 0137 /** Returns the rectangle containing the up and down arrows. */ 0138 QRect upDownRect() const; 0139 0140 /** Sets whether the edit field is displayed. */ 0141 void setUpDownOnly(bool only) { mUpDownOnly = only; } 0142 0143 /** Initialise a QStyleOptionSpinBox with this instance's details. */ 0144 void initStyleOption(QStyleOptionSpinBox*) const override; 0145 0146 Q_SIGNALS: 0147 /** Signal emitted when the spin box's value is stepped (by the shifted or unshifted increment). 0148 * @param step The requested step in the spin box's value. Note that the actual change in value 0149 * may have been less than this. 0150 * @param modified Qt has automatically modified the step due to the control key. 0151 */ 0152 void stepped(int step, bool control); 0153 0154 protected: 0155 /** Returns the initial adjustment to the value for a shift step up or down. 0156 * The default is to step up or down to the nearest multiple of the shift 0157 * increment, so the adjustment returned is for stepping up the decrement 0158 * required to round down to a multiple of the shift increment <= current value, 0159 * or for stepping down the increment required to round up to a multiple of the 0160 * shift increment >= current value. 0161 * This method's caller then adjusts the resultant value if necessary to cater 0162 * for the widget's minimum/maximum value, and wrapping. 0163 * This should really be a static method, but it needs to be virtual... 0164 */ 0165 virtual int shiftStepAdjustment(int oldValue, int shiftStep); 0166 0167 /** Receives events destined for the spin widget or for the edit field. */ 0168 bool eventFilter(QObject*, QEvent*) override; 0169 0170 void paintEvent(QPaintEvent*) override; 0171 void focusOutEvent(QFocusEvent*) override; 0172 void mousePressEvent(QMouseEvent*) override; 0173 void mouseDoubleClickEvent(QMouseEvent*) override; 0174 void mouseReleaseEvent(QMouseEvent*) override; 0175 void mouseMoveEvent(QMouseEvent*) override; 0176 void keyPressEvent(QKeyEvent*) override; 0177 void keyReleaseEvent(QKeyEvent*) override; 0178 void wheelEvent(QWheelEvent*) override; 0179 0180 private Q_SLOTS: 0181 void textEdited(); 0182 void valueChange(); 0183 private: 0184 enum class Modifier { None, Shift, Control }; 0185 0186 void init(); 0187 void addValue(int change, bool current); 0188 int whichButton(const QPoint&); 0189 bool setShiftStepping(Modifier, int currentButton); 0190 bool clickEvent(QMouseEvent*); 0191 bool keyEvent(QKeyEvent*); 0192 static Modifier getModifier(Qt::KeyboardModifiers); 0193 0194 enum { NO_BUTTON, UP, DOWN }; 0195 0196 int mMinValue; 0197 int mMaxValue; 0198 int mLineStep; // step when spin arrows are pressed 0199 int mLineShiftStep; // step when spin arrows are pressed with shift key 0200 int mLineControlStep {0}; // step when spin arrows are pressed with control key 0201 int mCurrentButton {NO_BUTTON}; // current spin widget button 0202 Modifier mMouseKey {Modifier::None}; // which modifier key applies while left button is being held down 0203 QStyle* mControlStyle {nullptr}; // style to prevent Qt multiplying control step by 10 0204 bool mShiftMinBound {false}; // true if a temporary minimum bound has been set during shift stepping 0205 bool mShiftMaxBound {false}; // true if a temporary maximum bound has been set during shift stepping 0206 bool mSelectOnStep {true}; // select the editor text whenever spin buttons are clicked (default) 0207 bool mModControlStep {true}; // control steps set value to multiple of step 0208 bool mUpDownOnly {false}; // true if edit field isn't displayed 0209 bool mReadOnly {false}; // value cannot be changed 0210 bool mSuppressSignals {false}; 0211 bool mEdited {false}; // text field has been edited 0212 }; 0213 0214 // vim: et sw=4: