1 /*
2  * Strawberry Music Player
3  * This file was part of Clementine.
4  * Copyright 2010, David Sansome <me@davidsansome.com>
5  * Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
6  *
7  * Strawberry is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * Strawberry is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Strawberry.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef LINEEDIT_H
23 #define LINEEDIT_H
24 
25 #include "config.h"
26 
27 #include <QtGlobal>
28 #include <QObject>
29 #include <QWidget>
30 #include <QString>
31 #include <QLineEdit>
32 #include <QPlainTextEdit>
33 #include <QSpinBox>
34 #include <QCheckBox>
35 
36 class QToolButton;
37 class QPaintDevice;
38 class QPaintEvent;
39 class QResizeEvent;
40 
41 class LineEditInterface {
42 
43  public:
44   explicit LineEditInterface(QWidget *widget) : widget_(widget) {}
45 
46   QWidget *widget() const { return widget_; }
47 
48   virtual ~LineEditInterface() {}
49 
50   virtual void set_enabled(const bool enabled) = 0;
51   virtual void set_focus() = 0;
52 
53   virtual void clear() = 0;
54   virtual QVariant value() const = 0;
55   virtual void set_value(const QVariant &value) = 0;
56 
57   virtual QString hint() const = 0;
58   virtual void set_hint(const QString &hint) = 0;
59   virtual void clear_hint() = 0;
60 
61   virtual void set_partially() {}
62 
63  protected:
64   QWidget *widget_;
65 
66  private:
67   Q_DISABLE_COPY(LineEditInterface)
68 };
69 
70 class ExtendedEditor : public LineEditInterface {
71 
72  public:
73   explicit ExtendedEditor(QWidget *widget, int extra_right_padding = 0, bool draw_hint = true);
74   ~ExtendedEditor() override {}
75 
76   virtual bool is_empty() const { return value().toString().isEmpty(); }
77 
78   QString hint() const override { return hint_; }
79   void set_hint(const QString &hint) override;
80   void clear_hint() override { set_hint(QString()); }
81 
82   bool has_clear_button() const { return has_clear_button_; }
83   void set_clear_button(const bool visible);
84 
85   bool has_reset_button() const;
86   void set_reset_button(const bool visible);
87 
88   qreal font_point_size() const { return font_point_size_; }
89   void set_font_point_size(const qreal size) { font_point_size_ = size; }
90 
91  protected:
92   void Paint(QPaintDevice *device);
93   void Resize();
94 
95  private:
96   void UpdateButtonGeometry();
97 
98  protected:
99   QString hint_;
100 
101   bool has_clear_button_;
102   QToolButton *clear_button_;
103   QToolButton *reset_button_;
104 
105   int extra_right_padding_;
106   bool draw_hint_;
107   qreal font_point_size_;
108   bool is_rtl_;
109 };
110 
111 class LineEdit : public QLineEdit, public ExtendedEditor {
112   Q_OBJECT
113 
114   Q_PROPERTY(QString hint READ hint WRITE set_hint)
115   Q_PROPERTY(qreal font_point_size READ font_point_size WRITE set_font_point_size)
116   Q_PROPERTY(bool has_clear_button READ has_clear_button WRITE set_clear_button)
117   Q_PROPERTY(bool has_reset_button READ has_reset_button WRITE set_reset_button)
118 
119  public:
120   explicit LineEdit(QWidget *parent = nullptr);
121 
122   // ExtendedEditor
123   void set_enabled(bool enabled) override { QLineEdit::setEnabled(enabled); }
124 
125   QVariant value() const override { return QLineEdit::text(); }
126   void set_value(const QVariant &value) override { QLineEdit::setText(value.toString()); }
127 
128  public slots:
129   void set_focus() override { QLineEdit::setFocus(); }
130   void clear() override { QLineEdit::clear(); }
131 
132  protected:
133   void paintEvent(QPaintEvent*) override;
134   void resizeEvent(QResizeEvent*) override;
135 
136  private:
137   bool is_rtl() const { return is_rtl_; }
138   void set_rtl(bool rtl) { is_rtl_ = rtl; }
139 
140  private slots:
141   void text_changed(const QString &text);
142 
143  signals:
144   void Reset();
145 };
146 
147 class TextEdit : public QPlainTextEdit, public ExtendedEditor {
148   Q_OBJECT
149   Q_PROPERTY(QString hint READ hint WRITE set_hint)
150   Q_PROPERTY(bool has_clear_button READ has_clear_button WRITE set_clear_button)
151   Q_PROPERTY(bool has_reset_button READ has_reset_button WRITE set_reset_button)
152 
153  public:
154   explicit TextEdit(QWidget *parent = nullptr);
155 
156   // ExtendedEditor
157   void set_enabled(bool enabled) override { QPlainTextEdit::setEnabled(enabled); }
158 
159   QVariant value() const override { return QPlainTextEdit::toPlainText(); }
160   void set_value(const QVariant &value) override { QPlainTextEdit::setPlainText(value.toString()); }
161 
162  public slots:
163   void set_focus() override { QPlainTextEdit::setFocus(); }
164   void clear() override { QPlainTextEdit::clear(); }
165 
166  protected:
167   void paintEvent(QPaintEvent*) override;
168   void resizeEvent(QResizeEvent*) override;
169 
170  signals:
171   void Reset();
172 };
173 
174 class SpinBox : public QSpinBox, public ExtendedEditor {
175   Q_OBJECT
176   Q_PROPERTY(QString hint READ hint WRITE set_hint)
177   Q_PROPERTY(bool has_clear_button READ has_clear_button WRITE set_clear_button)
178   Q_PROPERTY(bool has_reset_button READ has_reset_button WRITE set_reset_button)
179 
180  public:
181   explicit SpinBox(QWidget *parent = nullptr);
182 
183   // QSpinBox
184   QString textFromValue(int val) const override;
185 
186   // ExtendedEditor
187   void set_enabled(bool enabled) override { QSpinBox::setEnabled(enabled); }
188 
189   QVariant value() const override { return QSpinBox::value(); }
190   void set_value(const QVariant &value) override { QSpinBox::setValue(value.toInt()); }
191   bool is_empty() const override { return text().isEmpty() || text() == "0"; }
192 
193  public slots:
194   void set_focus() override { QSpinBox::setFocus(); }
195   void clear() override { QSpinBox::clear(); }
196 
197  protected:
198   void paintEvent(QPaintEvent*) override;
199   void resizeEvent(QResizeEvent*) override;
200 
201  signals:
202   void Reset();
203 };
204 
205 class CheckBox : public QCheckBox, public ExtendedEditor {
206   Q_OBJECT
207   Q_PROPERTY(QString hint READ hint WRITE set_hint)
208   Q_PROPERTY(bool has_clear_button READ has_clear_button WRITE set_clear_button)
209   Q_PROPERTY(bool has_reset_button READ has_reset_button WRITE set_reset_button)
210 
211  public:
212   explicit CheckBox(QWidget *parent = nullptr);
213 
214   // ExtendedEditor
215   void set_enabled(bool enabled) override { QCheckBox::setEnabled(enabled); }
216 
217   bool is_empty() const override { return text().isEmpty() || text() == "0"; }
218   QVariant value() const override { return QCheckBox::isChecked(); }
219   void set_value(const QVariant &value) override { QCheckBox::setCheckState(value.toBool() ? Qt::Checked : Qt::Unchecked); }
220   void set_partially() override { QCheckBox::setCheckState(Qt::PartiallyChecked); }
221 
222  public slots:
223   void set_focus() override { QCheckBox::setFocus(); }
224   void clear() override { QCheckBox::setChecked(false); }
225 
226  protected:
227   void paintEvent(QPaintEvent*) override;
228   void resizeEvent(QResizeEvent*) override;
229 
230  signals:
231   void Reset();
232 };
233 
234 #endif  // LINEEDIT_H
235