]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiBox.cpp
GuiBox.cpp: fix update of height checkbox
[lyx.git] / src / frontends / qt4 / GuiBox.cpp
1 /**
2  * \file GuiBox.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna (Minipage stuff)
7  * \author Martin Vermeer
8  * \author Jürgen Spitzmüller
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiBox.h"
16
17 #include "LengthCombo.h"
18 #include "qt_helpers.h"
19 #include "lengthcommon.h"
20 #include "LyXRC.h" // to set the default length values
21 #include "Validator.h"
22
23 #include "insets/InsetBox.h"
24
25 #include "support/lstrings.h"
26
27 #include <QPushButton>
28 #include <QLineEdit>
29 #include <QCloseEvent>
30
31
32 using std::string;
33
34 namespace lyx {
35 namespace frontend {
36
37 GuiBoxDialog::GuiBoxDialog(LyXView & lv)
38         : GuiDialog(lv, "box")
39 {
40         setupUi(this);
41         setViewTitle(_("Box Settings"));
42         setController(new ControlBox(*this));
43
44         // fill the box type choice
45         box_gui_tokens(ids_, gui_names_);
46         for (unsigned int i = 0; i < gui_names_.size(); ++i)
47                 typeCO->addItem(toqstr(gui_names_[i]));
48
49         // add the special units to the height choice
50         // width needs different handling
51         box_gui_tokens_special_length(ids_spec_, gui_names_spec_);
52         for (unsigned int i = 1; i < gui_names_spec_.size(); ++i)
53                 heightUnitsLC->addItem(toqstr(gui_names_spec_[i]));
54
55         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
56         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
57         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
58         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
59
60         connect(widthED, SIGNAL(textChanged(const QString &)),
61                 this, SLOT(change_adaptor()));
62         connect(widthUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
63                 this, SLOT(change_adaptor()));
64         connect(valignCO, SIGNAL(highlighted(const QString &)),
65                 this, SLOT(change_adaptor()));
66         connect(heightCB, SIGNAL(stateChanged(int)),
67                 this, SLOT(change_adaptor()));
68         connect(heightED, SIGNAL(textChanged(const QString &)),
69                 this, SLOT(change_adaptor()));
70         connect(heightUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT) ),
71                 this, SLOT(change_adaptor()));
72         connect(restorePB, SIGNAL(clicked()), this, SLOT(restoreClicked()));
73         connect(typeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
74         connect(typeCO, SIGNAL(activated(int)), this, SLOT(typeChanged(int)));
75         connect(halignCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
76         connect(ialignCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
77         connect(innerBoxCO, SIGNAL(activated(const QString&)),
78                 this, SLOT(innerBoxChanged(const QString &)));
79         connect(innerBoxCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
80
81         heightED->setValidator(unsignedLengthValidator(heightED));
82         widthED->setValidator(unsignedLengthValidator(widthED));
83
84         bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
85
86         bc().addReadOnly(typeCO);
87         bc().addReadOnly(innerBoxCO);
88         bc().addReadOnly(valignCO);
89         bc().addReadOnly(ialignCO);
90         bc().addReadOnly(halignCO);
91         bc().addReadOnly(widthED);
92         bc().addReadOnly(widthUnitsLC);
93         bc().addReadOnly(heightCB);
94         bc().addReadOnly(heightED);
95         bc().addReadOnly(heightUnitsLC);
96
97         bc().setRestore(restorePB);
98         bc().setOK(okPB);
99         bc().setApply(applyPB);
100         bc().setCancel(closePB);
101
102         // initialize the length validator
103         bc().addCheckedLineEdit(widthED, widthLA);
104         bc().addCheckedLineEdit(heightED, heightCB);
105 }
106
107
108 ControlBox & GuiBoxDialog::controller()
109 {
110         return static_cast<ControlBox &>(GuiDialog::controller());
111 }
112
113
114 void GuiBoxDialog::closeEvent(QCloseEvent * e)
115 {
116         slotClose();
117         e->accept();
118 }
119
120
121 void GuiBoxDialog::change_adaptor()
122 {
123         changed();
124 }
125
126
127 void GuiBoxDialog::innerBoxChanged(const QString & str)
128 {
129         bool const ibox = (str != qt_("None"));
130         valignCO->setEnabled(ibox);
131         ialignCO->setEnabled(ibox);
132         halignCO->setEnabled(!ibox);
133         heightCB->setEnabled(ibox);
134         if (heightCB->checkState() == Qt::Checked && ibox) {
135                 heightED->setEnabled(true);
136                 heightUnitsLC->setEnabled(true);
137         }
138         setSpecial(ibox);
139 }
140
141
142 void GuiBoxDialog::typeChanged(int index)
143 {
144         bool const frameless = (index == 0);
145         if (frameless) {
146                 valignCO->setEnabled(true);
147                 ialignCO->setEnabled(true);
148                 halignCO->setEnabled(false);
149                 heightCB->setEnabled(true);
150                 heightED->setEnabled(true);
151                 heightUnitsLC->setEnabled(true);
152                 setSpecial(true);
153         }
154         int itype = innerBoxCO->currentIndex();
155         setInnerType(frameless, itype);
156 }
157
158
159 void GuiBoxDialog::restoreClicked()
160 {
161         setInnerType(true, 2);
162         widthED->setText("100");
163         widthUnitsLC->setCurrentItem(Length::PCW);
164         heightCB->setCheckState(Qt::Checked);
165         heightED->setText("1");
166         for (int j = 0; j < heightUnitsLC->count(); j++) {
167                 if (heightUnitsLC->itemText(j) == qt_("Total Height"))
168                         heightUnitsLC->setCurrentItem(j);
169         }
170 }
171
172
173 void GuiBoxDialog::updateContents()
174 {
175         string type(controller().params().type);
176         for (unsigned int i = 0; i < gui_names_.size(); ++i) {
177                 if (type == ids_[i])
178                         typeCO->setCurrentIndex(i);
179         }
180
181         // default: minipage
182         unsigned int inner_type = 2;
183         if (!controller().params().inner_box)
184                 // none
185                 inner_type = 0;
186         if (controller().params().use_parbox)
187                 // parbox
188                 inner_type = 1;
189         bool frameless = (controller().params().type == "Frameless");
190         setInnerType(frameless, inner_type);
191
192         char c = controller().params().pos;
193         valignCO->setCurrentIndex(string("tcb").find(c, 0));
194         c = controller().params().inner_pos;
195         ialignCO->setCurrentIndex(string("tcbs").find(c, 0));
196         c = controller().params().hor_pos;
197         halignCO->setCurrentIndex(string("lcrs").find(c, 0));
198
199         bool ibox = controller().params().inner_box;
200         valignCO->setEnabled(ibox);
201         ialignCO->setEnabled(ibox);
202         halignCO->setEnabled(!ibox);
203         setSpecial(ibox);
204
205         Length::UNIT default_unit =
206                 (lyxrc.default_papersize > 3) ? Length::CM : Length::IN;
207
208         lengthToWidgets(widthED, widthUnitsLC,
209                 (controller().params().width).asString(), default_unit);
210
211         string const special = controller().params().special;
212         if (!special.empty() && special != "none") {
213                 QString spc;
214                 for (unsigned int i = 0; i < gui_names_spec_.size(); i++) {
215                         if (special == ids_spec_[i])
216                                 spc = toqstr(gui_names_spec_[i].c_str());
217                 }
218                 for (int j = 0; j < widthUnitsLC->count(); j++) {
219                         if (widthUnitsLC->itemText(j) == spc)
220                                 widthUnitsLC->setCurrentIndex(j);
221                 }
222         }
223
224         lengthToWidgets(heightED, heightUnitsLC,
225                 (controller().params().height).asString(), default_unit);
226         
227         string const height_special = controller().params().height_special;
228         if (!height_special.empty() && height_special != "none") {
229                 QString hspc;
230                 for (unsigned int i = 0; i < gui_names_spec_.size(); i++) {
231                         if (height_special == ids_spec_[i]) {
232                                 hspc = toqstr(gui_names_spec_[i].c_str());
233                         }
234                 }
235                 for (int j = 0; j < heightUnitsLC->count(); j++) {
236                         if (heightUnitsLC->itemText(j) == hspc) {
237                                 heightUnitsLC->setCurrentIndex(j);
238                         }
239                 }
240         }
241         // set no optional height when the value is the default "1\height"
242         // (special units like \height are handled as "in",
243         if (height_special == "totalheight" &&  
244                 controller().params().height == Length("1in"))
245                 heightCB->setCheckState(Qt::Unchecked);
246         else
247                 heightCB->setCheckState(Qt::Checked);
248
249         heightCB->setEnabled(ibox);
250 }
251
252
253 void GuiBoxDialog::applyView()
254 {
255         controller().params().type =
256                 ids_[typeCO->currentIndex()];
257
258         controller().params().inner_box =
259                 innerBoxCO->currentText() != qt_("None");
260         controller().params().use_parbox =
261                 innerBoxCO->currentText() ==  qt_("Parbox");
262
263         controller().params().pos =
264                 "tcb"[valignCO->currentIndex()];
265         controller().params().inner_pos =
266                 "tcbs"[ialignCO->currentIndex()];
267         controller().params().hor_pos =
268                 "lcrs"[halignCO->currentIndex()];
269
270         int i = 0;
271         bool spec = false;
272         QString special = widthUnitsLC->currentText();
273         QString value = widthED->text();
274         if (special == qt_("Height")) {
275                 i = 1;
276                 spec = true;
277         } else if (special == qt_("Depth")) {
278                 i = 2;
279                 spec = true;
280         } else if (special == qt_("Total Height")) {
281                 i = 3;
282                 spec = true;
283         } else if (special == qt_("Width")) {
284                 i = 4;
285                 spec = true;
286         }
287         // the user might insert a non-special value in the line edit
288         if (isValidLength(fromqstr(value))) {
289                 i = 0;
290                 spec = false;
291         }
292         controller().params().special = ids_spec_[i];
293
294         string width;
295         if (spec) {
296                 width = fromqstr(value);
297                 // beware: bogosity! the unit is simply ignored in this case
298                 width += "in";
299         } else
300                 width = widgetsToLength(widthED, widthUnitsLC);
301
302         controller().params().width = Length(width);
303
304         i = 0;
305         spec = false;
306         special = heightUnitsLC->currentText();
307         value = heightED->text();
308         if (special == qt_("Height")) {
309                 i = 1;
310                 spec = true;
311         } else if (special == qt_("Depth")) {
312                 i = 2;
313                 spec = true;
314         } else if (special == qt_("Total Height")) {
315                 i = 3;
316                 spec = true;
317         } else if (special == qt_("Width")) {
318                 i = 4;
319                 spec = true;
320         }
321         // the user might insert a non-special value in the line edit
322         if (isValidLength(fromqstr(value))) {
323                 i = 0;
324                 spec = false;
325         }
326         controller().params().height_special = ids_spec_[i];
327
328         string height;
329         if (spec  && !isValidLength(fromqstr(heightED->text()))) {
330                 height = fromqstr(value);
331                 // beware: bogosity! the unit is simply ignored in this case
332                 height += "in";
333         } else
334                 height = widgetsToLength(heightED, heightUnitsLC);
335
336         // the height parameter is omitted in InsetBox.cpp when the value
337         // is "1in" and "Total Height" is used as unit.
338         // 1in + "Total Height" means "1\height" which is the LaTeX default when
339         // no height is given
340         if (heightCB->checkState() == Qt::Checked)
341                 controller().params().height = Length(height);
342         else {
343                 controller().params().height = Length("1in");
344                 controller().params().height_special = ids_spec_[3];
345         }
346 }
347
348
349 void GuiBoxDialog::setSpecial(bool ibox)
350 {
351         box_gui_tokens_special_length(ids_spec_, gui_names_spec_);
352         // check if the widget contains the special units
353         int count = widthUnitsLC->count();
354         bool has_special = false;
355         for (int i = 0; i < count; i++)
356                 if (widthUnitsLC->itemText(i).contains(qt_("Total Height")) > 0)
357                         has_special = true;
358         // insert 'em if needed...
359         if (!ibox && !has_special) {
360                 for (unsigned int i = 1; i < gui_names_spec_.size(); i++)
361                         widthUnitsLC->addItem(toqstr(gui_names_spec_[i]));
362         // ... or remove 'em if needed
363         } else if (ibox && has_special) {
364                 widthUnitsLC->clear();
365                 for (int i = 0; i < num_units; i++)
366                         widthUnitsLC->addItem(qt_(unit_name_gui[i]));
367         }
368 }
369
370
371 void GuiBoxDialog::setInnerType(bool frameless, int i)
372 {
373         // with "frameless" boxes, inner box is mandatory (i.e. is the actual box)
374         // we have to remove "none" then and adjust the combo
375         if (frameless) {
376                 innerBoxCO->clear();
377                 innerBoxCO->addItem(qt_("Parbox"));
378                 innerBoxCO->addItem(qt_("Minipage"));
379                 if (i != 0)
380                         innerBoxCO->setCurrentIndex(i - 1);
381                 else
382                         innerBoxCO->setCurrentIndex(i);
383         } else {
384                 if (innerBoxCO->count() == 2)
385                         ++i;
386                 innerBoxCO->clear();
387                 innerBoxCO->addItem(qt_("None"));
388                 innerBoxCO->addItem(qt_("Parbox"));
389                 innerBoxCO->addItem(qt_("Minipage"));
390                 innerBoxCO->setCurrentIndex(i);
391         }
392 }
393
394 } // namespace frontend
395 } // namespace lyx
396
397
398 #include "GuiBox_moc.cpp"