]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/FloatPlacement.cpp
Add Float tag to determine allowed positioning options (#7752)
[lyx.git] / src / frontends / qt4 / 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  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "FloatPlacement.h"
15 #include "qt_helpers.h"
16
17 #include "Buffer.h"
18 #include "BufferParams.h"
19 #include "FloatList.h"
20 #include "TextClass.h"
21
22 #include "insets/InsetFloat.h"
23 #include "support/lstrings.h"
24
25 #include <map>
26
27 using namespace std;
28 using namespace lyx::support;
29
30
31 namespace lyx {
32
33 namespace frontend {
34
35 FloatPlacement::FloatPlacement(bool show_options, QWidget * parent)
36         : InsetParamsWidget(parent), float_list_(0)
37 {
38         setupUi(this);
39
40         connect(floatTypeCO, SIGNAL(activated(int)), this, SLOT(changedSlot()));
41         connect(topCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
42         connect(bottomCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
43         connect(pageCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
44         connect(herepossiblyCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
45         connect(heredefinitelyCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
46         connect(ignoreCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
47         connect(spanCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
48         connect(sidewaysCB, SIGNAL(clicked()), this, SLOT(changedSlot()));
49
50         floatTypeTitle->setVisible(show_options);
51         floatTypeCO->setVisible(show_options);
52         spanCB->setVisible(show_options);
53         sidewaysCB->setVisible(show_options);
54 }
55
56
57 docstring FloatPlacement::dialogToParams() const
58 {
59         InsetFloatParams params;
60         params.type = fromqstr(floatTypeCO->itemData(floatTypeCO->currentIndex()).toString());
61         params.placement = get(params.wide, params.sideways);
62         return from_ascii(InsetFloat::params2string(params));
63 }
64
65
66 void FloatPlacement::useWide()
67 {
68         spanCB->show();
69 }
70
71
72 void FloatPlacement::useSideways()
73 {
74         sidewaysCB->show();
75 }
76
77
78 bool FloatPlacement::possiblePlacement(char const & p) const
79 {
80         return !spanCB->isVisible() || contains(allowed_placement_, p);
81 }
82
83
84 void FloatPlacement::set(string const & placement)
85 {
86         bool def_placement = false;
87         bool top = false;
88         bool bottom = false;
89         bool page = false;
90         bool here = false;
91         bool force = false;
92         bool here_definitely = false;
93
94         if (placement.empty()) {
95                 def_placement = true;
96         } else if (contains(placement, 'H') && possiblePlacement('H')) {
97                 here_definitely = true;
98         } else {
99                 if (contains(placement, '!') && possiblePlacement('!')) {
100                         force = true;
101                 }
102                 if (contains(placement, 't') && possiblePlacement('t')) {
103                         top = true;
104                 }
105                 if (contains(placement, 'b') && possiblePlacement('b')) {
106                         bottom = true;
107                 }
108                 if (contains(placement, 'p') && possiblePlacement('p')) {
109                         page = true;
110                 }
111                 if (contains(placement, 'h') && possiblePlacement('h')) {
112                         here = true;
113                 }
114         }
115
116         defaultsCB->setChecked(def_placement);
117         topCB->setChecked(top);
118         bottomCB->setChecked(bottom);
119         pageCB->setChecked(page);
120         herepossiblyCB->setChecked(here);
121         ignoreCB->setChecked(force);
122         heredefinitelyCB->setChecked(here_definitely);
123         checkAllowed();
124 }
125
126
127 void FloatPlacement::initFloatTypeCO(FloatList const & floats)
128 {
129         if (float_list_ == &floats)
130                 return;
131
132         float_list_ = &floats;
133         floatTypeCO->clear();
134         FloatList::const_iterator it = floats.begin();
135         FloatList::const_iterator const end = floats.end();
136         for (; it != end; ++it) {
137                 floatTypeCO->addItem(qt_(it->second.name()),
138                                      toqstr(it->second.floattype()));
139         }
140 }
141
142
143 void FloatPlacement::paramsToDialog(Inset const * inset)
144 {
145         InsetFloat const * fl = static_cast<InsetFloat const *>(inset);
146         InsetFloatParams const & params = fl->params();
147
148         BufferParams const & bp = fl->buffer().params();
149         initFloatTypeCO(bp.documentClass().floats());
150
151         int const item = floatTypeCO->findData(toqstr(params.type));
152         floatTypeCO->setCurrentIndex(item);
153
154         allowed_placement_ =
155                 bp.documentClass().floats().allowedPlacement(params.type);
156
157         set(params.placement);
158
159         standardfloat_ = (params.type == "figure"
160                 || params.type == "table");
161
162         if (params.wide) {
163                 herepossiblyCB->setChecked(false);
164                 heredefinitelyCB->setChecked(false);
165                 bottomCB->setChecked(false);
166         }
167
168         spanCB->setChecked(params.wide);
169         sidewaysCB->setChecked(params.sideways);
170         // the package rotfloat only has *-versions for figure and table
171         spanCB->setEnabled(!params.sideways || standardfloat_);
172         checkAllowed();
173 }
174
175
176 string const FloatPlacement::get(bool & wide, bool & sideways) const
177 {
178         wide = spanCB->isChecked();
179         sideways = sidewaysCB->isChecked();
180
181         return get();
182 }
183
184
185 string const FloatPlacement::get() const
186 {
187         string placement;
188
189         if (defaultsCB->isChecked())
190                 return placement;
191
192         if (heredefinitelyCB->isChecked()) {
193                 placement += 'H';
194         } else {
195                 if (ignoreCB->isChecked()) {
196                         placement += '!';
197                 }
198                 if (topCB->isChecked()) {
199                         placement += 't';
200                 }
201                 if (bottomCB->isChecked()) {
202                         placement += 'b';
203                 }
204                 if (pageCB->isChecked()) {
205                         placement += 'p';
206                 }
207                 if (herepossiblyCB->isChecked()) {
208                         placement += 'h';
209                 }
210         }
211         return placement;
212 }
213
214
215 void FloatPlacement::on_defaultsCB_stateChanged(int state)
216 {
217         checkAllowed();
218         if (state == Qt::Checked)
219                 return;
220         if (topCB->isChecked() || bottomCB->isChecked()
221            || pageCB->isChecked() || herepossiblyCB->isChecked()
222            || heredefinitelyCB->isChecked() || ignoreCB->isChecked())
223                 changed();
224 }
225
226
227 void FloatPlacement::changedSlot()
228 {
229         checkAllowed();
230         changed();
231 }
232
233
234 void FloatPlacement::checkAllowed() const
235 {
236         bool const defaults = defaultsCB->isChecked();
237         bool const ignore = topCB->isChecked() || bottomCB->isChecked()
238                       || pageCB->isChecked() || herepossiblyCB->isChecked();
239         bool const heredefinitely = heredefinitelyCB->isChecked();
240
241         // float or document dialog?
242         if (spanCB->isVisible()) {
243                 bool const span = spanCB->isChecked();
244                 bool const sideways = sidewaysCB->isChecked();
245                 defaultsCB->setEnabled(!sideways);
246                 topCB->setEnabled(!sideways && !defaults && !heredefinitely
247                                   && contains(allowed_placement_, 't'));
248                 bottomCB->setEnabled(!sideways && !defaults && !span && !heredefinitely
249                                      && contains(allowed_placement_, 'b'));
250                 pageCB->setEnabled(!sideways && !defaults && !heredefinitely
251                                    && contains(allowed_placement_, 'p'));
252                 herepossiblyCB->setEnabled(!sideways && !defaults && !span && !heredefinitely
253                                            && contains(allowed_placement_, 'h'));
254                 heredefinitelyCB->setEnabled(!sideways && !defaults && !span
255                                              && contains(allowed_placement_, 'H'));
256                 ignoreCB->setEnabled(!sideways && !defaults && ignore && !heredefinitely
257                                      && contains(allowed_placement_, '!'));
258                 spanCB->setEnabled(!sideways || standardfloat_);
259         } else {
260                 topCB->setEnabled(!defaults && !heredefinitely);
261                 bottomCB->setEnabled(!defaults && !heredefinitely);
262                 pageCB->setEnabled(!defaults && !heredefinitely);
263                 herepossiblyCB->setEnabled(!defaults && !heredefinitely);
264                 heredefinitelyCB->setEnabled(!defaults);
265                 ignoreCB->setEnabled(!defaults && ignore && !heredefinitely);
266         }
267 }
268
269
270 bool FloatPlacement::checkWidgets(bool readonly) const
271 {
272         if (readonly) {
273                 floatTypeCO->setEnabled(false);
274                 defaultsCB->setEnabled(false);
275                 options->setEnabled(false);
276                 spanCB->setEnabled(false);
277                 sidewaysCB->setEnabled(false);
278         } else
279                 checkAllowed();
280
281         return InsetParamsWidget::checkWidgets();
282 }
283
284 } // namespace frontend
285 } // namespace lyx
286
287 #include "moc_FloatPlacement.cpp"