]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiBox.cpp
header cleanup
[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 "FuncRequest.h"
18 #include "support/gettext.h"
19
20 #include "LengthCombo.h"
21 #include "Length.h"
22 #include "qt_helpers.h"
23 #include "LyXRC.h" // to set the default length values
24 #include "Validator.h"
25
26 #include "insets/InsetBox.h"
27
28 #include "support/lstrings.h"
29
30 #include <QPushButton>
31 #include <QLineEdit>
32
33 using namespace std;
34
35 namespace lyx {
36 namespace frontend {
37
38
39 void box_gui_tokens(vector<string> & ids, vector<docstring> & gui_names)
40 {
41         char const * const ids_[] = {
42                 "Frameless", "Boxed", "ovalbox",
43                 "Ovalbox", "Shadowbox", "Shaded", "Doublebox"};
44         size_t const ids_size = sizeof(ids_) / sizeof(char *);
45         ids = vector<string>(ids_, ids_ + ids_size);
46         gui_names.clear();
47         gui_names.push_back(_("No frame"));
48         gui_names.push_back(_("Simple rectangular frame"));
49         gui_names.push_back(_("Oval frame, thin"));
50         gui_names.push_back(_("Oval frame, thick"));
51         gui_names.push_back(_("Drop shadow"));
52         gui_names.push_back(_("Shaded background"));
53         gui_names.push_back(_("Double rectangular frame"));
54 }
55
56
57 void box_gui_tokens_special_length(vector<string> & ids,
58         vector<docstring> & gui_names)
59 {
60         char const * const ids_[] = {
61                 "none", "height", "depth",
62                 "totalheight", "width"};
63         size_t const ids_size = sizeof(ids_) / sizeof(char *);
64         ids = vector<string>(ids_, ids_ + ids_size);
65         gui_names.clear();
66         gui_names.push_back(_("None"));
67         gui_names.push_back(_("Height"));
68         gui_names.push_back(_("Depth"));
69         gui_names.push_back(_("Total Height"));
70         gui_names.push_back(_("Width"));
71 }
72
73
74 GuiBox::GuiBox(GuiView & lv)
75         : GuiDialog(lv, "box", qt_("Box Settings")), params_("")
76 {
77         setupUi(this);
78
79         // fill the box type choice
80         box_gui_tokens(ids_, gui_names_);
81         for (unsigned int i = 0; i < gui_names_.size(); ++i)
82                 typeCO->addItem(toqstr(gui_names_[i]));
83
84         // add the special units to the height choice
85         // width needs different handling
86         box_gui_tokens_special_length(ids_spec_, gui_names_spec_);
87         for (unsigned int i = 1; i < gui_names_spec_.size(); ++i)
88                 heightUnitsLC->addItem(toqstr(gui_names_spec_[i]));
89
90         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
91         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
92         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
93         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
94
95         connect(widthED, SIGNAL(textChanged(QString)),
96                 this, SLOT(change_adaptor()));
97         connect(widthUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
98                 this, SLOT(change_adaptor()));
99         connect(valignCO, SIGNAL(highlighted(QString)),
100                 this, SLOT(change_adaptor()));
101         connect(heightCB, SIGNAL(stateChanged(int)),
102                 this, SLOT(change_adaptor()));
103         connect(heightED, SIGNAL(textChanged(const QString &)),
104                 this, SLOT(change_adaptor()));
105         connect(heightUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT) ),
106                 this, SLOT(change_adaptor()));
107         connect(restorePB, SIGNAL(clicked()), this, SLOT(restoreClicked()));
108         connect(typeCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
109         connect(typeCO, SIGNAL(activated(int)), this, SLOT(typeChanged(int)));
110         connect(halignCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
111         connect(ialignCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
112         connect(innerBoxCO, SIGNAL(activated(const QString&)),
113                 this, SLOT(innerBoxChanged(const QString &)));
114         connect(innerBoxCO, SIGNAL(activated(int)), this, SLOT(change_adaptor()));
115         connect(pagebreakCB, SIGNAL(stateChanged(int)),
116                 this, SLOT(pagebreakClicked()));
117
118         heightED->setValidator(unsignedLengthValidator(heightED));
119         widthED->setValidator(unsignedLengthValidator(widthED));
120
121         bc().setPolicy(ButtonPolicy::OkApplyCancelReadOnlyPolicy);
122
123         bc().addReadOnly(typeCO);
124         bc().addReadOnly(innerBoxCO);
125         bc().addReadOnly(valignCO);
126         bc().addReadOnly(ialignCO);
127         bc().addReadOnly(halignCO);
128         bc().addReadOnly(widthED);
129         bc().addReadOnly(widthUnitsLC);
130         bc().addReadOnly(heightCB);
131         bc().addReadOnly(heightED);
132         bc().addReadOnly(heightUnitsLC);
133         bc().addReadOnly(pagebreakCB);
134
135         bc().setRestore(restorePB);
136         bc().setOK(okPB);
137         bc().setApply(applyPB);
138         bc().setCancel(closePB);
139
140         // initialize the length validator
141         bc().addCheckedLineEdit(widthED, widthLA);
142         bc().addCheckedLineEdit(heightED, heightCB);
143 }
144
145
146 void GuiBox::change_adaptor()
147 {
148         changed();
149 }
150
151
152 void GuiBox::innerBoxChanged(const QString & str)
153 {
154         bool const ibox = (str != qt_("None"));
155         valignCO->setEnabled(ibox);
156         ialignCO->setEnabled(ibox);
157         halignCO->setEnabled(!ibox);
158         heightCB->setEnabled(ibox);
159         if (heightCB->checkState() == Qt::Checked && ibox) {
160                 heightED->setEnabled(true);
161                 heightUnitsLC->setEnabled(true);
162         }
163         setSpecial(ibox);
164 }
165
166
167 void GuiBox::typeChanged(int index)
168 {
169         bool const frameless = (index == 0);
170         if (frameless) {
171                 valignCO->setEnabled(true);
172                 ialignCO->setEnabled(true);
173                 halignCO->setEnabled(false);
174                 heightCB->setEnabled(true);
175                 heightED->setEnabled(true);
176                 heightUnitsLC->setEnabled(true);
177                 setSpecial(true);
178         }
179         if (index != 1)
180                 pagebreakCB->setChecked(false);
181         pagebreakCB->setEnabled(index == 1);
182         int itype = innerBoxCO->currentIndex();
183         setInnerType(frameless, itype);
184 }
185
186
187 void GuiBox::restoreClicked()
188 {
189         setInnerType(true, 2);
190         widthED->setText("100");
191         widthUnitsLC->setCurrentItem(Length::PCW);
192         heightCB->setCheckState(Qt::Checked);
193         heightED->setText("1");
194         for (int j = 0; j < heightUnitsLC->count(); j++) {
195                 if (heightUnitsLC->itemText(j) == qt_("Total Height"))
196                         heightUnitsLC->setCurrentItem(j);
197         }
198 }
199
200
201 void GuiBox::pagebreakClicked()
202 {
203         bool pbreak = (pagebreakCB->checkState() == Qt::Checked);
204         innerBoxCO->setEnabled(!pbreak);
205         if (pbreak) {
206                 valignCO->setEnabled(false);
207                 ialignCO->setEnabled(false);
208                 halignCO->setEnabled(false);
209                 heightCB->setEnabled(false);
210                 heightED->setEnabled(false);
211                 heightUnitsLC->setEnabled(false);
212                 setSpecial(false);
213         } else
214                 typeChanged(typeCO->currentIndex());
215         change_adaptor();
216 }
217
218 void GuiBox::updateContents()
219 {
220         string type = params_.type;
221         if (type == "Framed") {
222                 pagebreakCB->setChecked(true);
223                 type = "Boxed";
224         } else
225                 pagebreakCB->setChecked(false);
226
227         pagebreakCB->setEnabled(type == "Boxed");
228
229         for (unsigned int i = 0; i < gui_names_.size(); ++i) {
230                 if (type == ids_[i])
231                         typeCO->setCurrentIndex(i);
232         }
233
234         // default: minipage
235         unsigned int inner_type = 2;
236         if (!params_.inner_box)
237                 // none
238                 inner_type = 0;
239         if (params_.use_parbox)
240                 // parbox
241                 inner_type = 1;
242         bool frameless = (params_.type == "Frameless");
243         setInnerType(frameless, inner_type);
244
245         char c = params_.pos;
246         valignCO->setCurrentIndex(string("tcb").find(c, 0));
247         c = params_.inner_pos;
248         ialignCO->setCurrentIndex(string("tcbs").find(c, 0));
249         c = params_.hor_pos;
250         halignCO->setCurrentIndex(string("lcrs").find(c, 0));
251
252         bool ibox = params_.inner_box;
253         valignCO->setEnabled(ibox);
254         ialignCO->setEnabled(ibox);
255         halignCO->setEnabled(!ibox);
256         setSpecial(ibox);
257
258         Length::UNIT default_unit =
259                 (lyxrc.default_papersize > 3) ? Length::CM : Length::IN;
260
261         lengthToWidgets(widthED, widthUnitsLC,
262                 (params_.width).asString(), default_unit);
263
264         string const special = params_.special;
265         if (!special.empty() && special != "none") {
266                 QString spc;
267                 for (unsigned int i = 0; i < gui_names_spec_.size(); i++) {
268                         if (special == ids_spec_[i])
269                                 spc = toqstr(gui_names_spec_[i].c_str());
270                 }
271                 for (int j = 0; j < widthUnitsLC->count(); j++) {
272                         if (widthUnitsLC->itemText(j) == spc)
273                                 widthUnitsLC->setCurrentIndex(j);
274                 }
275         }
276
277         lengthToWidgets(heightED, heightUnitsLC,
278                 (params_.height).asString(), default_unit);
279         
280         string const height_special = params_.height_special;
281         if (!height_special.empty() && height_special != "none") {
282                 QString hspc;
283                 for (unsigned int i = 0; i != gui_names_spec_.size(); i++) {
284                         if (height_special == ids_spec_[i])
285                                 hspc = toqstr(gui_names_spec_[i].c_str());
286                 }
287                 for (int j = 0; j != heightUnitsLC->count(); j++) {
288                         if (heightUnitsLC->itemText(j) == hspc)
289                                 heightUnitsLC->setCurrentIndex(j);
290                 }
291         }
292         // set no optional height when the value is the default "1\height"
293         // (special units like \height are handled as "in",
294         if (height_special == "totalheight" &&  
295                 params_.height == Length("1in"))
296                 heightCB->setCheckState(Qt::Unchecked);
297         else
298                 heightCB->setCheckState(Qt::Checked);
299
300         heightCB->setEnabled(ibox);
301 }
302
303
304 void GuiBox::applyView()
305 {
306         bool pagebreak = pagebreakCB->isChecked();
307         if (pagebreak)
308                 params_.type = "Framed";
309         else
310                 params_.type = ids_[typeCO->currentIndex()];
311
312         params_.inner_box = (!pagebreak && innerBoxCO->currentText() != qt_("None"));
313         params_.use_parbox = (!pagebreak && innerBoxCO->currentText() == qt_("Parbox"));
314
315         params_.pos = "tcb"[valignCO->currentIndex()];
316         params_.inner_pos = "tcbs"[ialignCO->currentIndex()];
317         params_.hor_pos = "lcrs"[halignCO->currentIndex()];
318
319         int i = 0;
320         bool spec = false;
321         QString special = widthUnitsLC->currentText();
322         QString value = widthED->text();
323         if (special == qt_("Height")) {
324                 i = 1;
325                 spec = true;
326         } else if (special == qt_("Depth")) {
327                 i = 2;
328                 spec = true;
329         } else if (special == qt_("Total Height")) {
330                 i = 3;
331                 spec = true;
332         } else if (special == qt_("Width")) {
333                 i = 4;
334                 spec = true;
335         }
336         // the user might insert a non-special value in the line edit
337         if (isValidLength(fromqstr(value))) {
338                 i = 0;
339                 spec = false;
340         }
341         params_.special = ids_spec_[i];
342
343         string width;
344         if (spec) {
345                 width = fromqstr(value);
346                 // beware: bogosity! the unit is simply ignored in this case
347                 width += "in";
348         } else {
349                 width = widgetsToLength(widthED, widthUnitsLC);
350         }
351
352         params_.width = Length(width);
353
354         i = 0;
355         spec = false;
356         special = heightUnitsLC->currentText();
357         value = heightED->text();
358         if (special == qt_("Height")) {
359                 i = 1;
360                 spec = true;
361         } else if (special == qt_("Depth")) {
362                 i = 2;
363                 spec = true;
364         } else if (special == qt_("Total Height")) {
365                 i = 3;
366                 spec = true;
367         } else if (special == qt_("Width")) {
368                 i = 4;
369                 spec = true;
370         }
371         // the user might insert a non-special value in the line edit
372         if (isValidLength(fromqstr(value))) {
373                 i = 0;
374                 spec = false;
375         }
376         params_.height_special = ids_spec_[i];
377
378         string height;
379         if (spec  && !isValidLength(fromqstr(heightED->text()))) {
380                 height = fromqstr(value);
381                 // beware: bogosity! the unit is simply ignored in this case
382                 height += "in";
383         } else
384                 height = widgetsToLength(heightED, heightUnitsLC);
385
386         // the height parameter is omitted in InsetBox.cpp when the value
387         // is "1in" and "Total Height" is used as unit.
388         // 1in + "Total Height" means "1\height" which is the LaTeX default when
389         // no height is given
390         if (heightCB->checkState() == Qt::Checked)
391                 params_.height = Length(height);
392         else {
393                 params_.height = Length("1in");
394                 params_.height_special = ids_spec_[3];
395         }
396 }
397
398
399 void GuiBox::setSpecial(bool ibox)
400 {
401         box_gui_tokens_special_length(ids_spec_, gui_names_spec_);
402         // check if the widget contains the special units
403         int count = widthUnitsLC->count();
404         bool has_special = false;
405         for (int i = 0; i < count; i++)
406                 if (widthUnitsLC->itemText(i).contains(qt_("Total Height")) > 0)
407                         has_special = true;
408         // insert 'em if needed...
409         if (!ibox && !has_special) {
410                 for (unsigned int i = 1; i < gui_names_spec_.size(); i++)
411                         widthUnitsLC->addItem(toqstr(gui_names_spec_[i]));
412         // ... or remove 'em if needed
413         } else if (ibox && has_special) {
414                 widthUnitsLC->clear();
415                 for (int i = 0; i < num_units; i++)
416                         widthUnitsLC->addItem(qt_(unit_name_gui[i]));
417         }
418 }
419
420
421 void GuiBox::setInnerType(bool frameless, int i)
422 {
423         // with "frameless" boxes, inner box is mandatory (i.e. is the actual box)
424         // we have to remove "none" then and adjust the combo
425         if (frameless) {
426                 innerBoxCO->clear();
427                 innerBoxCO->addItem(qt_("Parbox"));
428                 innerBoxCO->addItem(qt_("Minipage"));
429                 if (i != 0)
430                         innerBoxCO->setCurrentIndex(i - 1);
431                 else
432                         innerBoxCO->setCurrentIndex(i);
433         } else {
434                 if (innerBoxCO->count() == 2)
435                         ++i;
436                 innerBoxCO->clear();
437                 innerBoxCO->addItem(qt_("None"));
438                 innerBoxCO->addItem(qt_("Parbox"));
439                 innerBoxCO->addItem(qt_("Minipage"));
440                 innerBoxCO->setCurrentIndex(i);
441         }
442 }
443
444 bool GuiBox::initialiseParams(string const & data)
445 {
446         InsetBoxMailer::string2params(data, params_);
447         return true;
448
449 }
450
451
452 void GuiBox::clearParams()
453 {
454         params_ = InsetBoxParams("");
455 }
456
457
458 void GuiBox::dispatchParams()
459 {
460         dispatch(FuncRequest(getLfun(), InsetBoxMailer::params2string(params_)));
461 }
462
463
464 Dialog * createGuiBox(GuiView & lv) { return new GuiBox(lv); }
465
466
467 } // namespace frontend
468 } // namespace lyx
469
470
471 #include "GuiBox_moc.cpp"