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