]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QTabular.C
rename LFUN enum values according to their command (as used in th minibuffer/bind...
[lyx.git] / src / frontends / qt4 / QTabular.C
1 /**
2  * \file QTabular.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Jürgen Spitzmüller
8  * \author Herbert Voß
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "checkedwidgets.h"
16 #include "QTabular.h"
17 #include "QTabularDialog.h"
18 #include "Qt2BC.h"
19
20 #include "lengthcombo.h"
21 #include "qt_helpers.h"
22
23 #include "controllers/ButtonController.h"
24 #include "controllers/ControlTabular.h"
25
26 #include "support/convert.h"
27
28 #include <qcheckbox.h>
29 #include <qlineedit.h>
30 #include <qpushbutton.h>
31 #include "qsetborder.h"
32
33 using std::string;
34
35 namespace lyx {
36 namespace frontend {
37
38 typedef QController<ControlTabular, QView<QTabularDialog> > base_class;
39
40 QTabular::QTabular(Dialog & parent)
41         : base_class(parent, _("Table Settings"))
42 {
43 }
44
45
46 void QTabular::build_dialog()
47 {
48         dialog_.reset(new QTabularDialog(this));
49
50         bcview().setCancel(dialog_->closePB);
51
52         bcview().addReadOnly(dialog_->multicolumnCB);
53         bcview().addReadOnly(dialog_->rotateCellCB);
54         bcview().addReadOnly(dialog_->rotateTabularCB);
55         bcview().addReadOnly(dialog_->specialAlignmentED);
56         bcview().addReadOnly(dialog_->widthED);
57         bcview().addReadOnly(dialog_->widthUnit);
58         bcview().addReadOnly(dialog_->hAlignCB);
59         bcview().addReadOnly(dialog_->vAlignCB);
60         bcview().addReadOnly(dialog_->borderSetPB);
61         bcview().addReadOnly(dialog_->borderUnsetPB);
62         bcview().addReadOnly(dialog_->borders);
63         bcview().addReadOnly(dialog_->longTabularCB);
64         bcview().addReadOnly(dialog_->headerStatusCB);
65         bcview().addReadOnly(dialog_->headerBorderAboveCB);
66         bcview().addReadOnly(dialog_->headerBorderBelowCB);
67         bcview().addReadOnly(dialog_->firstheaderStatusCB);
68         bcview().addReadOnly(dialog_->firstheaderBorderAboveCB);
69         bcview().addReadOnly(dialog_->firstheaderBorderBelowCB);
70         bcview().addReadOnly(dialog_->firstheaderNoContentsCB);
71         bcview().addReadOnly(dialog_->footerStatusCB);
72         bcview().addReadOnly(dialog_->footerBorderAboveCB);
73         bcview().addReadOnly(dialog_->footerBorderBelowCB);
74         bcview().addReadOnly(dialog_->lastfooterStatusCB);
75         bcview().addReadOnly(dialog_->lastfooterBorderAboveCB);
76         bcview().addReadOnly(dialog_->lastfooterBorderBelowCB);
77         bcview().addReadOnly(dialog_->lastfooterNoContentsCB);
78         bcview().addReadOnly(dialog_->newpageCB);
79
80         // initialize the length validator
81         addCheckedLineEdit(bcview(), dialog_->widthED,
82                 dialog_->fixedWidthColLA);
83 }
84
85
86 bool QTabular::isValid()
87 {
88         return true;
89 }
90
91
92 void QTabular::update_borders()
93 {
94         LyXTabular const & tabular = controller().tabular();
95         LyXTabular::idx_type const cell = controller().getActiveCell();
96         bool const isMulticolumnCell = tabular.isMultiColumn(cell);
97
98         if (!isMulticolumnCell) {
99                 dialog_->borders->setLeftEnabled(true);
100                 dialog_->borders->setRightEnabled(true);
101                 dialog_->borders->setTop(tabular.topLine(cell, true));
102                 dialog_->borders->setBottom(tabular.bottomLine(cell, true));
103                 dialog_->borders->setLeft(tabular.leftLine(cell, true));
104                 dialog_->borders->setRight(tabular.rightLine(cell, true));
105                 // repaint the setborder widget
106                 dialog_->borders->update();
107                 return;
108         }
109
110         dialog_->borders->setTop(tabular.topLine(cell));
111         dialog_->borders->setBottom(tabular.bottomLine(cell));
112         // pay attention to left/right lines: they are only allowed
113         // to set if we are in first/last cell of row or if the left/right
114         // cell is also a multicolumn.
115         if (tabular.isFirstCellInRow(cell) || tabular.isMultiColumn(cell - 1)) {
116                 dialog_->borders->setLeftEnabled(true);
117                 dialog_->borders->setLeft(tabular.leftLine(cell));
118         } else {
119                 dialog_->borders->setLeft(false);
120                 dialog_->borders->setLeftEnabled(false);
121         }
122         if (tabular.isLastCellInRow(cell) || tabular.isMultiColumn(cell + 1)) {
123                 dialog_->borders->setRightEnabled(true);
124                 dialog_->borders->setRight(tabular.rightLine(cell));
125         } else {
126                 dialog_->borders->setRight(false);
127                 dialog_->borders->setRightEnabled(false);
128         }
129         // repaint the setborder widget
130         dialog_->borders->update();
131 }
132
133
134 void QTabular::update_contents()
135 {
136         LyXTabular const & tabular(controller().tabular());
137         LyXTabular::idx_type const cell = controller().getActiveCell();
138
139         LyXTabular::row_type const row(tabular.row_of_cell(cell));
140         LyXTabular::col_type const col(tabular.column_of_cell(cell));
141
142         dialog_->tabularRowED->setText(toqstr(convert<string>(row + 1)));
143         dialog_->tabularColumnED->setText(toqstr(convert<string>(col + 1)));
144
145         bool const multicol(tabular.isMultiColumn(cell));
146
147         dialog_->multicolumnCB->setChecked(multicol);
148
149         dialog_->rotateCellCB->setChecked(tabular.getRotateCell(cell));
150         dialog_->rotateTabularCB->setChecked(tabular.getRotateTabular());
151
152         dialog_->longTabularCB->setChecked(tabular.isLongTabular());
153
154         update_borders();
155
156         LyXLength pwidth;
157         string special;
158
159         if (multicol) {
160                 special = tabular.getAlignSpecial(cell, LyXTabular::SET_SPECIAL_MULTI);
161                 pwidth = tabular.getMColumnPWidth(cell);
162         } else {
163                 special = tabular.getAlignSpecial(cell, LyXTabular::SET_SPECIAL_COLUMN);
164                 pwidth = tabular.getColumnPWidth(cell);
165         }
166
167         dialog_->specialAlignmentED->setText(toqstr(special));
168
169         bool const isReadonly = bc().bp().isReadOnly();
170         dialog_->specialAlignmentED->setEnabled(!isReadonly);
171
172         LyXLength::UNIT default_unit = controller().useMetricUnits() ? LyXLength::CM : LyXLength::IN;
173
174         string colwidth;
175         if (!pwidth.zero())
176                 colwidth = pwidth.asString();
177         lengthToWidgets(dialog_->widthED, dialog_->widthUnit,
178                 colwidth, default_unit);
179
180         dialog_->widthED->setEnabled(!isReadonly);
181         dialog_->widthUnit->setEnabled(!isReadonly);
182
183         dialog_->hAlignCB->clear();
184         dialog_->hAlignCB->insertItem(qt_("Left"));
185         dialog_->hAlignCB->insertItem(qt_("Center"));
186         dialog_->hAlignCB->insertItem(qt_("Right"));
187         if (!multicol && !pwidth.zero())
188                 dialog_->hAlignCB->insertItem(qt_("Block"));
189
190         int align = 0;
191         switch (tabular.getAlignment(cell)) {
192         case LYX_ALIGN_LEFT:
193                 align = 0;
194                 break;
195         case LYX_ALIGN_CENTER:
196                 align = 1;
197                 break;
198         case LYX_ALIGN_RIGHT:
199                 align = 2;
200                 break;
201         case LYX_ALIGN_BLOCK:
202         {
203                 if (!multicol && !pwidth.zero())
204                         align = 3;
205                 break;
206         }
207         default:
208                 align = 0;
209                 break;
210         }
211         dialog_->hAlignCB->setCurrentItem(align);
212
213         int valign = 0;
214         switch (tabular.getVAlignment(cell)) {
215         case LyXTabular::LYX_VALIGN_TOP:
216                 valign = 0;
217                 break;
218         case LyXTabular::LYX_VALIGN_MIDDLE:
219                 valign = 1;
220                 break;
221         case LyXTabular::LYX_VALIGN_BOTTOM:
222                 valign = 2;
223                 break;
224         default:
225                 valign = 1;
226                 break;
227         }
228         if (pwidth.zero())
229                 valign = 1;
230         dialog_->vAlignCB->setCurrentItem(valign);
231
232         dialog_->hAlignCB->setEnabled(true);
233         dialog_->vAlignCB->setEnabled(!pwidth.zero());
234
235         if (!tabular.isLongTabular()) {
236                 dialog_->headerStatusCB->setChecked(false);
237                 dialog_->headerBorderAboveCB->setChecked(false);
238                 dialog_->headerBorderBelowCB->setChecked(false);
239                 dialog_->firstheaderStatusCB->setChecked(false);
240                 dialog_->firstheaderBorderAboveCB->setChecked(false);
241                 dialog_->firstheaderBorderBelowCB->setChecked(false);
242                 dialog_->firstheaderNoContentsCB->setChecked(false);
243                 dialog_->footerStatusCB->setChecked(false);
244                 dialog_->footerBorderAboveCB->setChecked(false);
245                 dialog_->footerBorderBelowCB->setChecked(false);
246                 dialog_->lastfooterStatusCB->setChecked(false);
247                 dialog_->lastfooterBorderAboveCB->setChecked(false);
248                 dialog_->lastfooterBorderBelowCB->setChecked(false);
249                 dialog_->lastfooterNoContentsCB->setChecked(false);
250                 dialog_->newpageCB->setChecked(false);
251                 dialog_->newpageCB->setEnabled(false);
252                 return;
253         }
254
255         LyXTabular::ltType ltt;
256         bool use_empty;
257         bool row_set = tabular.getRowOfLTHead(row, ltt);
258         dialog_->headerStatusCB->setChecked(row_set);
259         if (ltt.set) {
260                 dialog_->headerBorderAboveCB->setChecked(ltt.topDL);
261                 dialog_->headerBorderBelowCB->setChecked(ltt.bottomDL);
262                 use_empty = true;
263         } else {
264                 dialog_->headerBorderAboveCB->setChecked(false);
265                 dialog_->headerBorderBelowCB->setChecked(false);
266                 dialog_->headerBorderAboveCB->setEnabled(false);
267                 dialog_->headerBorderBelowCB->setEnabled(false);
268                 dialog_->firstheaderNoContentsCB->setChecked(false);
269                 dialog_->firstheaderNoContentsCB->setEnabled(false);
270                 use_empty = false;
271         }
272
273         row_set = tabular.getRowOfLTFirstHead(row, ltt);
274         dialog_->firstheaderStatusCB->setChecked(row_set);
275         if (ltt.set && (!ltt.empty || !use_empty)) {
276                 dialog_->firstheaderBorderAboveCB->setChecked(ltt.topDL);
277                 dialog_->firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
278         } else {
279                 dialog_->firstheaderBorderAboveCB->setEnabled(false);
280                 dialog_->firstheaderBorderBelowCB->setEnabled(false);
281                 dialog_->firstheaderBorderAboveCB->setChecked(false);
282                 dialog_->firstheaderBorderBelowCB->setChecked(false);
283                 if (use_empty) {
284                         dialog_->firstheaderNoContentsCB->setChecked(ltt.empty);
285                         if (ltt.empty)
286                                 dialog_->firstheaderStatusCB->setEnabled(false);
287                 }
288         }
289
290         row_set = tabular.getRowOfLTFoot(row, ltt);
291         dialog_->footerStatusCB->setChecked(row_set);
292         if (ltt.set) {
293                 dialog_->footerBorderAboveCB->setChecked(ltt.topDL);
294                 dialog_->footerBorderBelowCB->setChecked(ltt.bottomDL);
295                 use_empty = true;
296         } else {
297                 dialog_->footerBorderAboveCB->setChecked(false);
298                 dialog_->footerBorderBelowCB->setChecked(false);
299                 dialog_->footerBorderAboveCB->setEnabled(false);
300                 dialog_->footerBorderBelowCB->setEnabled(false);
301                 dialog_->lastfooterNoContentsCB->setChecked(false);
302                 dialog_->lastfooterNoContentsCB->setEnabled(false);
303                 use_empty = false;
304         }
305
306         row_set = tabular.getRowOfLTLastFoot(row, ltt);
307                 dialog_->lastfooterStatusCB->setChecked(row_set);
308         if (ltt.set && (!ltt.empty || !use_empty)) {
309                 dialog_->lastfooterBorderAboveCB->setChecked(ltt.topDL);
310                 dialog_->lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
311         } else {
312                 dialog_->lastfooterBorderAboveCB->setEnabled(false);
313                 dialog_->lastfooterBorderBelowCB->setEnabled(false);
314                 dialog_->lastfooterBorderAboveCB->setChecked(false);
315                 dialog_->lastfooterBorderBelowCB->setChecked(false);
316                 if (use_empty) {
317                         dialog_->lastfooterNoContentsCB->setChecked(ltt.empty);
318                         if (ltt.empty)
319                                 dialog_->lastfooterStatusCB->setEnabled(false);
320                 }
321         }
322         dialog_->newpageCB->setChecked(tabular.getLTNewPage(row));
323 }
324
325
326 void QTabular::closeGUI()
327 {
328         // ugly hack to auto-apply the stuff that hasn't been
329         // yet. don't let this continue to exist ...
330
331         // Subtle here, we must /not/ apply any changes and
332         // then refer to tabular, as it will have been freed
333         // since the changes update the actual controller().tabular()
334         LyXTabular const & tabular(controller().tabular());
335
336         // apply the fixed width values
337         LyXTabular::idx_type const cell = controller().getActiveCell();
338         bool const multicol = tabular.isMultiColumn(cell);
339         string width = widgetsToLength(dialog_->widthED, dialog_->widthUnit);
340         string width2;
341
342         LyXLength llen = tabular.getColumnPWidth(cell);
343         LyXLength llenMulti = tabular.getMColumnPWidth(cell);
344
345         if (multicol && !llenMulti.zero())
346                         width2 = llenMulti.asString();
347         else if (!multicol && !llen.zero())
348                         width2 = llen.asString();
349
350         // apply the special alignment
351         string const sa1 = fromqstr(dialog_->specialAlignmentED->text());
352         string sa2;
353
354         if (multicol)
355                 sa2 = tabular.getAlignSpecial(cell, LyXTabular::SET_SPECIAL_MULTI);
356         else
357                 sa2 = tabular.getAlignSpecial(cell, LyXTabular::SET_SPECIAL_COLUMN);
358
359         if (sa1 != sa2) {
360                 if (multicol)
361                         controller().set(LyXTabular::SET_SPECIAL_MULTI, sa1);
362                 else
363                         controller().set(LyXTabular::SET_SPECIAL_COLUMN, sa1);
364         }
365
366         if (width != width2) {
367                 if (multicol)
368                         controller().set(LyXTabular::SET_MPWIDTH, width);
369                 else
370                         controller().set(LyXTabular::SET_PWIDTH, width);
371         }
372 }
373
374 } // namespace frontend
375 } // namespace lyx