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