]> git.lyx.org Git - features.git/blob - src/frontends/qt/ButtonController.cpp
d2910c88c1d1c9ae21afe15cc2d00692fa9e1940
[features.git] / src / frontends / qt / ButtonController.cpp
1 /**
2  * \file ButtonController.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Allan Rae
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "ButtonController.h"
14
15 #include "qt_helpers.h"
16
17 #include "support/debug.h"
18
19 #include <QCheckBox>
20 #include <QPushButton>
21 #include <QLineEdit>
22 #include <QLabel>
23 #include <QList>
24 #include <QValidator>
25
26
27 namespace lyx {
28 namespace frontend {
29
30 static void setWidgetEnabled(QWidget * obj, bool enabled)
31 {
32         if (QLineEdit * le = qobject_cast<QLineEdit*>(obj))
33                 le->setReadOnly(!enabled);
34         else
35                 obj->setEnabled(enabled);
36
37         obj->setFocusPolicy(enabled ? Qt::StrongFocus : Qt::NoFocus);
38 }
39
40
41 /////////////////////////////////////////////////////////////////////////
42 //
43 // CheckedLineEdit
44 //
45 /////////////////////////////////////////////////////////////////////////
46
47 class CheckedLineEdit
48 {
49 public:
50         CheckedLineEdit(QLineEdit * input, QWidget * label = nullptr);
51         bool check() const;
52
53 private:
54         // non-owned
55         QLineEdit * input_;
56         QWidget * label_;
57 };
58
59
60 CheckedLineEdit::CheckedLineEdit(QLineEdit * input, QWidget * label)
61         : input_(input), label_(label)
62 {}
63
64
65 bool CheckedLineEdit::check() const
66 {
67         QValidator const * validator = input_->validator();
68         if (!validator)
69                 return true;
70
71         QString t = input_->text();
72         int p = 0;
73         bool const valid = validator->validate(t, p) == QValidator::Acceptable;
74
75         // Visual feedback.
76         setValid(input_, valid);
77         if (label_)
78                 setValid(label_, valid);
79
80         return valid;
81 }
82
83
84 /////////////////////////////////////////////////////////////////////////
85 //
86 // ButtonController::Private
87 //
88 /////////////////////////////////////////////////////////////////////////
89
90 class ButtonController::Private
91 {
92 public:
93         typedef QList<CheckedLineEdit> CheckedWidgetList;
94
95         Private()
96                 : okay_(nullptr), apply_(nullptr), cancel_(nullptr),
97                         restore_(nullptr), auto_apply_(nullptr), default_(nullptr),
98                         policy_(ButtonPolicy::IgnorantPolicy)
99         {}
100
101         /// \return true if all CheckedWidgets are in a valid state.
102         bool checkWidgets() const
103         {
104                 bool valid = true;
105                 for (const CheckedLineEdit & w : checked_widgets_)
106                         valid &= w.check();
107                 return valid;
108         }
109
110 public:
111         CheckedWidgetList checked_widgets_;
112
113         QPushButton * okay_;
114         QPushButton * apply_;
115         QPushButton * cancel_;
116         QPushButton * restore_;
117         QCheckBox * auto_apply_;
118         QPushButton * default_;
119
120         typedef QList<QWidget *> Widgets;
121         Widgets read_only_;
122
123         ButtonPolicy policy_;
124 };
125
126
127 /////////////////////////////////////////////////////////////////////////
128 //
129 // ButtonController
130 //
131 /////////////////////////////////////////////////////////////////////////
132
133 ButtonController::ButtonController()
134         : d(new Private)
135 {}
136
137
138 ButtonController::~ButtonController()
139 {
140         delete d;
141 }
142
143
144 void ButtonController::setPolicy(ButtonPolicy::Policy policy)
145 {
146         d->policy_.setPolicy(policy);
147 }
148
149
150 void ButtonController::ok()
151 {
152         input(ButtonPolicy::SMI_OKAY);
153 }
154
155
156 void ButtonController::input(ButtonPolicy::SMInput in)
157 {
158         if (ButtonPolicy::SMI_NOOP == in)
159                 return;
160         d->policy_.input(in);
161         refresh();
162 }
163
164
165 void ButtonController::apply()
166 {
167         input(ButtonPolicy::SMI_APPLY);
168 }
169
170
171 void ButtonController::autoApply()
172 {
173         input(ButtonPolicy::SMI_AUTOAPPLY);
174 }
175
176
177 void ButtonController::cancel()
178 {
179         input(ButtonPolicy::SMI_CANCEL);
180 }
181
182
183 void ButtonController::restore()
184 {
185         input(ButtonPolicy::SMI_RESTORE);
186 }
187
188
189 void ButtonController::hide()
190 {
191         input(ButtonPolicy::SMI_HIDE);
192 }
193
194
195 void ButtonController::setValid(bool v)
196 {
197         input(v ? ButtonPolicy::SMI_VALID : ButtonPolicy::SMI_INVALID);
198 }
199
200
201 bool ButtonController::setReadOnly(bool ro)
202 {
203         LYXERR(Debug::GUI, "Setting controller ro: " << ro);
204
205         d->policy_.input(ro ?
206                 ButtonPolicy::SMI_READ_ONLY : ButtonPolicy::SMI_READ_WRITE);
207         // refreshReadOnly(); This will enable all widgets in dialogs, no matter if
208         //                    they allowed to be enabled, so when you plan to
209         //                    reenable this call, read this before:
210         // http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg128222.html
211         refresh();
212         return ro;
213 }
214
215
216 void ButtonController::refresh() const
217 {
218         LYXERR(Debug::GUI, "Calling BC refresh()");
219
220         bool const all_valid = d->checkWidgets();
221
222         if (d->okay_) {
223                 bool const enabled =
224                         all_valid && policy().buttonStatus(ButtonPolicy::OKAY);
225                 d->okay_->setEnabled(enabled);
226         }
227         if (d->apply_) {
228                 bool const enabled =
229                         all_valid && policy().buttonStatus(ButtonPolicy::APPLY);
230                 d->apply_->setEnabled(enabled);
231         }
232         if (d->restore_) {
233                 bool const enabled =
234                         all_valid && policy().buttonStatus(ButtonPolicy::RESTORE);
235                 d->restore_->setEnabled(enabled);
236         }
237         if (d->cancel_) {
238                 bool const enabled = policy().buttonStatus(ButtonPolicy::CANCEL);
239                 if (enabled)
240                         d->cancel_->setText(qt_("Cancel"));
241                 else
242                         d->cancel_->setText(qt_("Close"));
243         }
244         if (d->auto_apply_) {
245                 bool const enabled = policy().buttonStatus(ButtonPolicy::AUTOAPPLY);
246                 d->auto_apply_->setEnabled(enabled);
247         }
248         if (d->default_)
249                 // Somewhere in the chain this can lose default status (#11417)
250                 d->default_->setDefault(true);
251 }
252
253
254 void ButtonController::refreshReadOnly() const
255 {
256         if (d->read_only_.empty())
257                 return;
258         bool const enable = !policy().isReadOnly();
259         for(QWidget * w : d->read_only_)
260                 setWidgetEnabled(w, enable);
261 }
262
263
264 void ButtonController::addCheckedLineEdit(QLineEdit * input, QWidget * label)
265 {
266         d->checked_widgets_.append(CheckedLineEdit(input, label));
267 }
268
269
270 void ButtonController::setOK(QPushButton * obj, bool const default_button)
271 {
272         d->okay_ = obj;
273         if (default_button)
274                 d->default_ = obj;
275 }
276
277
278 void ButtonController::setApply(QPushButton * obj, bool const default_button)
279 {
280         d->apply_ = obj;
281         if (default_button)
282                 d->default_ = obj;
283 }
284
285
286 void ButtonController::setAutoApply(QCheckBox * obj)
287 {
288         d->auto_apply_ = obj;
289 }
290
291
292 void ButtonController::setCancel(QPushButton * obj, bool const default_button)
293 {
294         d->cancel_ = obj;
295         if (default_button)
296                 d->default_ = obj;
297 }
298
299
300 void ButtonController::setRestore(QPushButton * obj, bool const default_button)
301 {
302         d->restore_ = obj;
303         if (default_button)
304                 d->default_ = obj;
305 }
306
307
308 void ButtonController::addReadOnly(QWidget * obj)
309 {
310         d->read_only_.push_back(obj);
311 }
312
313 ButtonPolicy const & ButtonController::policy() const
314 {
315         return d->policy_;
316 }
317
318
319 ButtonPolicy & ButtonController::policy()
320 {
321         return d->policy_;
322 }
323
324 } // namespace frontend
325 } // namespace lyx