]> git.lyx.org Git - lyx.git/blob - src/frontends/qt/FloatPlacement.cpp
Move Fullscreen preferences from Editing>Control section into Look & Feel>User Interf...
[lyx.git] / src / frontends / qt / FloatPlacement.cpp
1 /**
2  * \file FloatPlacement.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Edwin Leuven
7  * \author John Levon
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 "FloatPlacement.h"
16 #include "qt_helpers.h"
17
18 #include "Buffer.h"
19 #include "BufferParams.h"
20 #include "FloatList.h"
21 #include "TextClass.h"
22
23 #include "insets/InsetFloat.h"
24 #include "support/lstrings.h"
25
26 #include <map>
27
28 using namespace std;
29 using namespace lyx::support;
30
31
32 namespace lyx {
33
34 namespace frontend {
35
36 FloatPlacement::FloatPlacement(bool show_options, QWidget * parent)
37         : InsetParamsWidget(parent), standardfloat_(true),
38           allows_wide_(true), allows_sideways_(true), float_list_(nullptr)
39 {
40         setupUi(this);
41
42         connect(floatTypeCO, SIGNAL(activated(int)), this, SLOT(changedSlot()));
43         connect(placementCO, SIGNAL(activated(int)), this, SLOT(changedSlot()));
44         connect(topCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
45         connect(bottomCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
46         connect(pageCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
47         connect(herepossiblyCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
48         connect(heredefinitelyCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
49         connect(ignoreCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
50         connect(spanCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
51         connect(sidewaysCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
52         connect(alignClassDefaultRB, SIGNAL(clicked()), this, SLOT(changedSlot()));
53         connect(alignDocDefaultRB, SIGNAL(clicked()), this, SLOT(changedSlot()));
54         connect(alignLeftRB, SIGNAL(clicked()), this, SLOT(changedSlot()));
55         connect(alignCenterRB, SIGNAL(clicked()), this, SLOT(changedSlot()));
56         connect(alignRightRB, SIGNAL(clicked()), this, SLOT(changedSlot()));
57
58         floatTypeTitle->setVisible(show_options);
59         floatTypeCO->setVisible(show_options);
60         alignDocDefaultRB->setVisible(show_options);
61         spanCB->setVisible(show_options);
62         sidewaysCB->setVisible(show_options);
63         optionsGB->setVisible(show_options);
64         initFloatPlacementCO(show_options);
65 }
66
67
68 docstring FloatPlacement::dialogToParams() const
69 {
70         InsetFloatParams params;
71         params.type = fromqstr(floatTypeCO->itemData(floatTypeCO->currentIndex()).toString());
72         params.wide = spanCB->isChecked();
73         params.sideways = sidewaysCB->isChecked();
74         params.alignment = getAlignment();
75         params.placement = getPlacement();
76         return from_ascii(InsetFloat::params2string(params));
77 }
78
79
80 void FloatPlacement::useWide()
81 {
82         spanCB->show();
83 }
84
85
86 void FloatPlacement::useSideways()
87 {
88         sidewaysCB->show();
89 }
90
91
92 bool FloatPlacement::possiblePlacement(char p) const
93 {
94         return !spanCB->isVisible() || contains(allowed_placement_, p);
95 }
96
97
98 void FloatPlacement::setPlacement(string const & placement)
99 {
100         bool def_placement = false;
101         bool doc_placement = false;
102         bool top = false;
103         bool bottom = false;
104         bool page = false;
105         bool here = false;
106         bool force = false;
107         bool here_definitely = false;
108
109         if (placement.empty() || placement == "class")
110                 def_placement = true;
111         else if (placement == "document")
112                 doc_placement = true;
113         else if (contains(placement, 'H') && possiblePlacement('H')) {
114                 here_definitely = true;
115         } else {
116                 if (contains(placement, '!') && possiblePlacement('!')) {
117                         force = true;
118                 }
119                 if (contains(placement, 't') && possiblePlacement('t')) {
120                         top = true;
121                 }
122                 if (contains(placement, 'b') && possiblePlacement('b')) {
123                         bottom = true;
124                 }
125                 if (contains(placement, 'p') && possiblePlacement('p')) {
126                         page = true;
127                 }
128                 if (contains(placement, 'h') && possiblePlacement('h')) {
129                         here = true;
130                 }
131         }
132
133         if (def_placement)
134                 placementCO->setCurrentIndex(placementCO->findData(toqstr("class")));
135         else if (doc_placement)
136                 placementCO->setCurrentIndex(placementCO->findData(toqstr("document")));
137         else
138                 placementCO->setCurrentIndex(placementCO->findData(toqstr("custom")));
139         topCB->setChecked(top);
140         bottomCB->setChecked(bottom);
141         pageCB->setChecked(page);
142         herepossiblyCB->setChecked(here);
143         ignoreCB->setChecked(force);
144         heredefinitelyCB->setChecked(here_definitely);
145         checkAllowed();
146 }
147
148
149 void FloatPlacement::setAlignment(string const & alignment)
150 {
151         if (alignment == "document")
152                 alignDocDefaultRB->setChecked(true);
153         else if (alignment == "left")
154                 alignLeftRB->setChecked(true);
155         else if (alignment == "center")
156                 alignCenterRB->setChecked(true);
157         else if (alignment == "right")
158                 alignRightRB->setChecked(true);
159         else
160                 alignClassDefaultRB->setChecked(true);
161 }
162
163
164 void FloatPlacement::initFloatTypeCO(FloatList const & floats)
165 {
166         if (float_list_ == &floats)
167                 return;
168
169         float_list_ = &floats;
170         floatTypeCO->clear();
171         FloatList::const_iterator it = floats.begin();
172         FloatList::const_iterator const end = floats.end();
173         for (; it != end; ++it) {
174                 floatTypeCO->addItem(qt_(it->second.name()),
175                                      toqstr(it->second.floattype()));
176         }
177 }
178
179
180 void FloatPlacement::initFloatPlacementCO(bool const local)
181 {
182         placementCO->addItem(qt_("Class Default"), "class");
183         if (local)
184                 placementCO->addItem(qt_("Document Default"), "document");
185         placementCO->addItem(qt_("Custom"), "custom");
186 }
187
188
189 void FloatPlacement::paramsToDialog(Inset const * inset)
190 {
191         InsetFloat const * fl = static_cast<InsetFloat const *>(inset);
192         InsetFloatParams const & params = fl->params();
193
194         BufferParams const & bp = fl->buffer().params();
195         FloatList const & floats = bp.documentClass().floats();
196         initFloatTypeCO(floats);
197
198         int const item = floatTypeCO->findData(toqstr(params.type));
199         floatTypeCO->setCurrentIndex(item);
200
201         allowed_placement_ = floats.allowedPlacement(params.type);
202         allows_sideways_ = floats.allowsSideways(params.type);
203         allows_wide_ = floats.allowsWide(params.type);
204
205         setPlacement(params.placement);
206         setAlignment(params.alignment);
207
208         standardfloat_ = (params.type == "figure"
209                 || params.type == "table");
210
211         if (params.wide) {
212                 herepossiblyCB->setChecked(false);
213                 heredefinitelyCB->setChecked(false);
214                 bottomCB->setChecked(false);
215         }
216
217         spanCB->setChecked(params.wide && allows_wide_);
218         sidewaysCB->setChecked(params.sideways && allows_sideways_);
219
220         checkAllowed();
221 }
222
223
224 string const FloatPlacement::getPlacement() const
225 {
226         string placement;
227
228         QString const data =
229                 placementCO->itemData(placementCO->currentIndex()).toString();
230         if (data == "class")
231                 return "class";
232         if (data == "document")
233                 return "document";
234
235         if (heredefinitelyCB->isChecked()) {
236                 placement += 'H';
237         } else {
238                 if (ignoreCB->isChecked()) {
239                         placement += '!';
240                 }
241                 if (topCB->isChecked()) {
242                         placement += 't';
243                 }
244                 if (bottomCB->isChecked()) {
245                         placement += 'b';
246                 }
247                 if (pageCB->isChecked()) {
248                         placement += 'p';
249                 }
250                 if (herepossiblyCB->isChecked()) {
251                         placement += 'h';
252                 }
253         }
254         return placement;
255 }
256
257
258 string const FloatPlacement::getAlignment() const
259 {
260         if (alignDocDefaultRB->isChecked())
261                 return "document";
262         if (alignLeftRB->isChecked())
263                 return "left";
264         if (alignCenterRB->isChecked())
265                 return "center";
266         if (alignRightRB->isChecked())
267                 return "right";
268         return "class";
269 }
270
271
272 void FloatPlacement::on_placementCO_currentIndexChanged(int index)
273 {
274         checkAllowed();
275         if (placementCO->itemText(index) != "custom")
276                 return;
277         if (topCB->isChecked() || bottomCB->isChecked()
278            || pageCB->isChecked() || herepossiblyCB->isChecked()
279            || heredefinitelyCB->isChecked() || ignoreCB->isChecked())
280                 changed();
281 }
282
283
284 void FloatPlacement::changedSlot()
285 {
286         checkAllowed();
287         changed();
288 }
289
290
291 void FloatPlacement::checkAllowed() const
292 {
293         bool const defaults =
294                 placementCO->itemData(placementCO->currentIndex()).toString() != "custom";
295         bool const ignore = topCB->isChecked() || bottomCB->isChecked()
296                       || pageCB->isChecked() || herepossiblyCB->isChecked();
297         bool const heredefinitely = heredefinitelyCB->isChecked();
298
299         // float or document dialog?
300         if (spanCB->isVisible()) {
301                 bool const span = spanCB->isChecked();
302                 bool const sideways = sidewaysCB->isChecked();
303                 topCB->setEnabled(!sideways && !defaults && !heredefinitely
304                                   && contains(allowed_placement_, 't'));
305                 bottomCB->setEnabled(!sideways && !defaults && !span && !heredefinitely
306                                      && contains(allowed_placement_, 'b'));
307                 pageCB->setEnabled(!sideways && !defaults && !heredefinitely
308                                    && contains(allowed_placement_, 'p'));
309                 if (!pageCB->isChecked())
310                         pageCB->setChecked(sideways && contains(allowed_placement_, 'p'));
311                 herepossiblyCB->setEnabled(!defaults && !span && !heredefinitely
312                                            && contains(allowed_placement_, 'h'));
313                 heredefinitelyCB->setEnabled(!defaults && !span
314                                              && contains(allowed_placement_, 'H'));
315                 ignoreCB->setEnabled(!defaults && ignore && !heredefinitely
316                                      && contains(allowed_placement_, '!'));
317                 // handle special case with sideways
318                 if ((!herepossiblyCB->isChecked() && sideways) || (span && sideways))
319                         ignoreCB->setEnabled(false);
320                 // when disabled the options must be unchecked to avoid strange LaTeX export
321                 // don't do it for pageCB because this case is handled with sideways
322                 if (ignoreCB->isChecked() && !ignoreCB->isEnabled())
323                         ignoreCB->setChecked(false);
324                 if (herepossiblyCB->isChecked() && !herepossiblyCB->isEnabled())
325                         herepossiblyCB->setChecked(false);
326                 if (topCB->isChecked() && !topCB->isEnabled())
327                         topCB->setChecked(false);
328                 if (bottomCB->isChecked() && !bottomCB->isEnabled())
329                         bottomCB->setChecked(false);
330                 spanCB->setEnabled(allows_wide_ && (!sideways || standardfloat_));
331                 sidewaysCB->setEnabled(allows_sideways_);
332                 placementCO->setEnabled(!(sideways && span));
333         } else {
334                 topCB->setEnabled(!defaults && !heredefinitely);
335                 bottomCB->setEnabled(!defaults && !heredefinitely);
336                 pageCB->setEnabled(!defaults && !heredefinitely);
337                 herepossiblyCB->setEnabled(!defaults && !heredefinitely);
338                 heredefinitelyCB->setEnabled(!defaults);
339                 ignoreCB->setEnabled(!defaults && ignore && !heredefinitely);
340         }
341 }
342
343
344 bool FloatPlacement::checkWidgets(bool readonly) const
345 {
346         if (readonly) {
347                 floatTypeCO->setEnabled(false);
348                 placementCO->setEnabled(false);
349                 aligmentGB->setEnabled(false);
350                 spanCB->setEnabled(false);
351                 sidewaysCB->setEnabled(false);
352         } else
353                 checkAllowed();
354
355         return InsetParamsWidget::checkWidgets();
356 }
357
358 } // namespace frontend
359 } // namespace lyx
360
361 #include "moc_FloatPlacement.cpp"