]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/ButtonController.cpp
Fix readability
[lyx.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 #include "GuiApplication.h"
15 #include "PanelStack.h"
16
17 #include "qt_helpers.h"
18
19 #include "support/debug.h"
20
21 #include <QCheckBox>
22 #include <QPushButton>
23 #include <QLineEdit>
24 #include <QLabel>
25 #include <QList>
26 #include <QTabWidget>
27 #include <QValidator>
28
29
30 namespace lyx {
31 namespace frontend {
32
33 /////////////////////////////////////////////////////////////////////////
34 //
35 // CheckedLineEdit
36 //
37 /////////////////////////////////////////////////////////////////////////
38
39 class CheckedLineEdit
40 {
41 public:
42         CheckedLineEdit(QLineEdit * input, QWidget * label = nullptr,
43                         int tabindex = -1, QString const panel = QString());
44         /// check the widget and do visual marking
45         bool check() const;
46         /// reset all visual markings for tabs or panel sections
47         void setSectionsValid() const;
48
49 private:
50         // non-owned
51         QLineEdit * input_;
52         QWidget * target_;
53         int tab_index_;
54         QString panel_name_;
55 };
56
57
58 CheckedLineEdit::CheckedLineEdit(QLineEdit * input, QWidget * label,
59                                  int tabindex, QString const panel)
60         : input_(input), target_(label), tab_index_(tabindex), panel_name_(panel)
61 {}
62
63
64 bool CheckedLineEdit::check() const
65 {
66         if (!input_->isEnabled()) {
67                 // we do not check diabled widgets
68                 if (target_)
69                         setValid(target_, true);
70                 return true;
71         }
72
73         QValidator const * validator = input_->validator();
74         if (!validator)
75                 return true;
76
77         QString t = input_->text();
78         int p = 0;
79         bool const valid = validator->validate(t, p) == QValidator::Acceptable;
80
81         // Visual feedback.
82         setValid(input_, valid);
83         if (target_) {
84                 if (!valid && !panel_name_.isEmpty() && qobject_cast<PanelStack*>(target_) != nullptr) {
85                         qobject_cast<PanelStack*>(target_)->markPanelValid(panel_name_, false);
86                         // this is a panel, so stop here.
87                         return valid;
88                 }
89                 setValid(target_, valid);
90                 if (!valid && tab_index_ >= 0 && qobject_cast<QTabWidget*>(target_) != nullptr) {
91                         QIcon warn(guiApp ? guiApp->getScaledPixmap("images/", "emblem-shellescape")
92                                           : getPixmap("images/", "emblem-shellescape", "svgz,png"));
93                         QTabBar * tb = qobject_cast<QTabWidget*>(target_)->tabBar();
94                         tb->setTabIcon(tab_index_, warn);
95                         tb->setTabToolTip(tab_index_, qt_("This tab contains invalid input. Please fix!"));
96                 }
97         }
98
99         return valid;
100 }
101
102
103 void CheckedLineEdit::setSectionsValid() const
104 {
105         if (target_ && tab_index_ >= 0 && qobject_cast<QTabWidget*>(target_) != nullptr) {
106                 QTabBar * tb = qobject_cast<QTabWidget*>(target_)->tabBar();
107                 tb->setTabIcon(tab_index_, QIcon());
108                 tb->setTabToolTip(tab_index_, QString());
109         }
110         else if (!panel_name_.isEmpty() && qobject_cast<PanelStack*>(target_) != nullptr)
111                 qobject_cast<PanelStack*>(target_)->markPanelValid(panel_name_, true);
112 }
113
114
115 /////////////////////////////////////////////////////////////////////////
116 //
117 // ButtonController::Private
118 //
119 /////////////////////////////////////////////////////////////////////////
120
121 class ButtonController::Private
122 {
123 public:
124         typedef QList<CheckedLineEdit> CheckedWidgetList;
125
126         Private() {}
127
128         /// \return true if all CheckedWidgets are in a valid state.
129         bool checkWidgets() const
130         {
131                 bool valid = true;
132                 for (const CheckedLineEdit & w : checked_widgets_) {
133                         w.setSectionsValid();
134                 }
135                 for (const CheckedLineEdit & w : checked_widgets_)
136                         valid &= w.check();
137                 return valid;
138         }
139
140 public:
141         CheckedWidgetList checked_widgets_;
142
143         QPushButton * okay_ = nullptr;
144         QPushButton * apply_ = nullptr;
145         QPushButton * cancel_ = nullptr;
146         QPushButton * restore_ = nullptr;
147         QCheckBox * auto_apply_ = nullptr;
148         QPushButton * default_ = nullptr;
149
150         typedef QList<QWidget *> Widgets;
151         Widgets read_only_;
152
153         ButtonPolicy policy_ {ButtonPolicy::IgnorantPolicy};
154 };
155
156
157 /////////////////////////////////////////////////////////////////////////
158 //
159 // ButtonController
160 //
161 /////////////////////////////////////////////////////////////////////////
162
163 ButtonController::ButtonController()
164         : d(new Private)
165 {}
166
167
168 ButtonController::~ButtonController()
169 {
170         delete d;
171 }
172
173
174 void ButtonController::setPolicy(ButtonPolicy::Policy policy)
175 {
176         d->policy_.setPolicy(policy);
177 }
178
179
180 void ButtonController::ok()
181 {
182         input(ButtonPolicy::SMI_OKAY);
183 }
184
185
186 void ButtonController::input(ButtonPolicy::SMInput in)
187 {
188         if (ButtonPolicy::SMI_NOOP == in)
189                 return;
190         d->policy_.input(in);
191         refresh();
192 }
193
194
195 void ButtonController::apply()
196 {
197         input(ButtonPolicy::SMI_APPLY);
198 }
199
200
201 void ButtonController::autoApply()
202 {
203         input(ButtonPolicy::SMI_AUTOAPPLY);
204 }
205
206
207 void ButtonController::cancel()
208 {
209         input(ButtonPolicy::SMI_CANCEL);
210 }
211
212
213 void ButtonController::restore()
214 {
215         input(ButtonPolicy::SMI_RESTORE);
216 }
217
218
219 void ButtonController::hide()
220 {
221         input(ButtonPolicy::SMI_HIDE);
222 }
223
224
225 void ButtonController::setValid(bool v)
226 {
227         input(v ? ButtonPolicy::SMI_VALID : ButtonPolicy::SMI_INVALID);
228 }
229
230
231 bool ButtonController::setReadOnly(bool ro)
232 {
233         LYXERR(Debug::GUI, "Setting controller ro: " << ro);
234
235         d->policy_.input(ro ?
236                 ButtonPolicy::SMI_READ_ONLY : ButtonPolicy::SMI_READ_WRITE);
237
238         refresh();
239         return ro;
240 }
241
242
243 void ButtonController::refresh() const
244 {
245         LYXERR(Debug::GUI, "Calling BC refresh()");
246
247         bool const all_valid = d->checkWidgets();
248
249         if (d->okay_) {
250                 bool const enabled =
251                         all_valid && policy().buttonStatus(ButtonPolicy::OKAY);
252                 d->okay_->setEnabled(enabled);
253         }
254         if (d->apply_) {
255                 bool const enabled =
256                         all_valid && policy().buttonStatus(ButtonPolicy::APPLY);
257                 d->apply_->setEnabled(enabled);
258         }
259         if (d->restore_) {
260                 bool const enabled =
261                         all_valid && policy().buttonStatus(ButtonPolicy::RESTORE);
262                 d->restore_->setEnabled(enabled);
263         }
264         if (d->cancel_) {
265                 bool const enabled = policy().buttonStatus(ButtonPolicy::CANCEL);
266                 if (enabled)
267                         d->cancel_->setText(qt_("Cancel"));
268                 else
269                         d->cancel_->setText(qt_("Close"));
270         }
271         if (d->auto_apply_) {
272                 bool const enabled = policy().buttonStatus(ButtonPolicy::AUTOAPPLY);
273                 d->auto_apply_->setEnabled(enabled);
274         }
275         if (d->default_)
276                 // Somewhere in the chain this can lose default status (#11417)
277                 d->default_->setDefault(true);
278 }
279
280
281 void ButtonController::addCheckedLineEdit(QLineEdit * input, QWidget * target, int tabindex)
282 {
283         d->checked_widgets_.append(CheckedLineEdit(input, target, tabindex));
284 }
285
286
287 void ButtonController::addCheckedLineEditPanel(QLineEdit * input, QWidget * target, QString const panel)
288 {
289         d->checked_widgets_.append(CheckedLineEdit(input, target, -1, panel));
290 }
291
292
293 void ButtonController::setOK(QPushButton * obj, bool const default_button)
294 {
295         d->okay_ = obj;
296         if (default_button)
297                 d->default_ = obj;
298 }
299
300
301 void ButtonController::setApply(QPushButton * obj, bool const default_button)
302 {
303         d->apply_ = obj;
304         if (default_button)
305                 d->default_ = obj;
306 }
307
308
309 void ButtonController::setAutoApply(QCheckBox * obj)
310 {
311         d->auto_apply_ = obj;
312 }
313
314
315 void ButtonController::setCancel(QPushButton * obj, bool const default_button)
316 {
317         d->cancel_ = obj;
318         if (default_button)
319                 d->default_ = obj;
320 }
321
322
323 void ButtonController::setRestore(QPushButton * obj, bool const default_button)
324 {
325         d->restore_ = obj;
326         if (default_button)
327                 d->default_ = obj;
328 }
329
330
331 void ButtonController::addReadOnly(QWidget * obj)
332 {
333         d->read_only_.push_back(obj);
334 }
335
336 ButtonPolicy const & ButtonController::policy() const
337 {
338         return d->policy_;
339 }
340
341
342 ButtonPolicy & ButtonController::policy()
343 {
344         return d->policy_;
345 }
346
347 } // namespace frontend
348 } // namespace lyx