]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiParagraph.cpp
abb11fd1a07f32d0822373417faa25f7fe4b8ad8
[lyx.git] / src / frontends / qt4 / GuiParagraph.cpp
1 /**
2  * \file GuiParagraph.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 Richard Heck
8  * \author Abdelrazak Younes
9  * \author Angus Leeming
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiParagraph.h"
17
18 #include "Buffer.h"
19 #include "BufferParams.h"
20 #include "BufferView.h"
21 #include "Cursor.h"
22 #include "FuncRequest.h"
23 #include "GuiView.h"
24 #include "Lexer.h"
25 #include "Paragraph.h"
26 #include "ParagraphParameters.h"
27 #include "qt_helpers.h"
28 #include "Spacing.h"
29
30 #include "support/debug.h"
31 #include "support/gettext.h"
32
33 #include <QCheckBox>
34 #include <QLineEdit>
35 #include <QPushButton>
36
37 #include <sstream>
38
39 using namespace std;
40
41 namespace lyx {
42 namespace frontend {
43
44 GuiParagraph::GuiParagraph(GuiView & lv)
45         : DialogView(lv, "paragraph", qt_("Paragraph Settings"))
46 {
47         setupUi(this);
48
49         connect(alignDefaultRB, SIGNAL(clicked()), this, SLOT(changed()));
50         connect(alignJustRB, SIGNAL(clicked()), this, SLOT(changed()));
51         connect(alignLeftRB, SIGNAL(clicked()), this, SLOT(changed()));
52         connect(alignRightRB, SIGNAL(clicked()), this, SLOT(changed()));
53         connect(alignCenterRB, SIGNAL(clicked()), this, SLOT(changed()));
54         connect(linespacing, SIGNAL(activated(int)), this, SLOT(changed()));
55         connect(linespacingValue, SIGNAL(textChanged(QString)),
56                 this, SLOT(changed()));
57         connect(indentCB, SIGNAL(clicked()), this, SLOT(changed()));
58         connect(labelWidth, SIGNAL(textChanged(QString)),
59                 this, SLOT(changed()));
60
61 #ifdef Q_WS_MACX
62         // On Mac it's common to have tool windows which are always in the
63         // foreground and are hidden when the main window is not focused.
64         setWindowFlags(Qt::Tool);
65         synchronizedViewCB->setChecked(true);
66 #else
67         synchronizedViewCB->setChecked(false);
68 #endif
69
70         on_synchronizedViewCB_toggled();
71         linespacingValue->setValidator(new QDoubleValidator(linespacingValue));
72
73         labelWidth->setWhatsThis( qt_(
74                 "As described in the User Guide, the width of"
75                 " this text determines the width of the label part"
76                 " of each item in environments like List and"
77                 " Description.\n"
78                 "\n"
79                 " Normally, you won't need to set this,"
80                 " since the largest label width of all the"
81                 " items is used."
82         ));
83
84         radioMap[LYX_ALIGN_LAYOUT] = alignDefaultRB;
85         radioMap[LYX_ALIGN_BLOCK]  = alignJustRB;
86         radioMap[LYX_ALIGN_LEFT]   = alignLeftRB;
87         radioMap[LYX_ALIGN_RIGHT]  = alignRightRB;
88         radioMap[LYX_ALIGN_CENTER] = alignCenterRB;
89
90         labelMap[LYX_ALIGN_BLOCK]  = _("Justified");
91         labelMap[LYX_ALIGN_LEFT]   = _("Left");
92         labelMap[LYX_ALIGN_RIGHT]  = _("Right");
93         labelMap[LYX_ALIGN_CENTER] = _("Center");
94
95         const_cast<QString &>(alignDefaultLabel) = alignDefaultRB->text();
96 }
97
98
99 void GuiParagraph::on_linespacing_activated(int index)
100 {
101         linespacingValue->setEnabled(index == 4);
102 }
103
104
105 void GuiParagraph::checkAlignmentRadioButtons()
106 {
107         RadioMap::iterator it = radioMap.begin();
108         for (; it != radioMap.end(); ++it) {
109                 LyXAlignment const align = it->first;
110                 it->second->setEnabled(align & alignPossible());
111         }
112         if (haveMultiParSelection())
113                 alignDefaultRB->setText(alignDefaultLabel);
114         else
115                 alignDefaultRB->setText(alignDefaultLabel + " ("
116                         + toqstr(labelMap[alignDefault()]) + ")");
117 }
118
119
120 void GuiParagraph::alignmentToRadioButtons(LyXAlignment align)
121 {
122         RadioMap::const_iterator it = radioMap.begin();
123         for (;it != radioMap.end(); ++it) {
124                 it->second->blockSignals(true);
125                 it->second->setChecked(align == it->first);
126                 it->second->blockSignals(false);
127         }
128 }
129
130
131 LyXAlignment GuiParagraph::getAlignmentFromDialog()
132 {
133         LyXAlignment alignment = LYX_ALIGN_NONE;
134         RadioMap::const_iterator it = radioMap.begin();
135         for (; it != radioMap.end(); ++it) {
136                 if (it->second->isChecked()) {
137                         alignment = it->first;
138                         break;
139                 }
140         }
141         return alignment;
142 }
143
144
145 void GuiParagraph::on_synchronizedViewCB_toggled()
146 {
147         bool in_sync = synchronizedViewCB->isChecked();
148         restorePB->setEnabled(!in_sync);
149         applyPB->setEnabled(!in_sync);
150 }
151
152
153 void GuiParagraph::changed()
154 {
155         if (synchronizedViewCB->isChecked())
156                 on_applyPB_clicked();
157 }
158
159
160 void GuiParagraph::on_applyPB_clicked()
161 {
162         ParagraphParameters & pp = params();
163
164         pp.align(getAlignmentFromDialog());
165
166         // get spacing
167         Spacing::Space ls = Spacing::Default;
168         string other;
169         switch (linespacing->currentIndex()) {
170         case 0:
171                 ls = Spacing::Default;
172                 break;
173         case 1:
174                 ls = Spacing::Single;
175                 break;
176         case 2:
177                 ls = Spacing::Onehalf;
178                 break;
179         case 3:
180                 ls = Spacing::Double;
181                 break;
182         case 4:
183                 ls = Spacing::Other;
184                 other = fromqstr(linespacingValue->text());
185                 break;
186         }
187
188         Spacing const spacing(ls, other);
189         pp.spacing(spacing);
190
191         // label width
192         pp.labelWidthString(qstring_to_ucs4(labelWidth->text()));
193         // indendation
194         pp.noindent(!indentCB->isChecked());
195
196         dispatchParams();
197 }
198
199
200 void GuiParagraph::on_restorePB_clicked()
201 {
202         updateView();
203 }
204
205
206 void GuiParagraph::updateView()
207 {
208         on_synchronizedViewCB_toggled();
209
210         ParagraphParameters const & pp = params();
211
212         // label width
213         docstring const & labelwidth = pp.labelWidthString();
214         // FIXME We should not compare translated strings
215         if (labelwidth != _("Senseless with this layout!")) {
216                 labelwidthGB->setEnabled(true);
217                 labelWidth->setText(toqstr(labelwidth));
218         } else {
219                 labelwidthGB->setEnabled(false);
220                 labelWidth->setText("");
221         }
222
223         // alignment
224         checkAlignmentRadioButtons();
225         alignmentToRadioButtons(pp.align());
226
227         //indentation
228         bool const canindent = canIndent();
229         indentCB->setEnabled(canindent);
230         indentCB->setChecked(canindent && !pp.noindent());
231
232         // linespacing
233         int ls;
234         Spacing const & space = pp.spacing();
235         switch (space.getSpace()) {
236         case Spacing::Single:
237                 ls = 1;
238                 break;
239         case Spacing::Onehalf:
240                 ls = 2;
241                 break;
242         case Spacing::Double:
243                 ls = 3;
244                 break;
245         case Spacing::Other:
246                 ls = 4;
247                 break;
248         default:
249                 ls = 0;
250                 break;
251         }
252         linespacing->setCurrentIndex(ls);
253         if (space.getSpace() == Spacing::Other) {
254                 linespacingValue->setText(toqstr(space.getValueAsString()));
255                 linespacingValue->setEnabled(true);
256         } else {
257                 linespacingValue->setText(QString());
258                 linespacingValue->setEnabled(false);
259         }
260 }
261
262
263 void GuiParagraph::enableView(bool enable)
264 {
265         indentCB->setEnabled(enable);
266         linespacing->setEnabled(enable);
267         labelWidth->setEnabled(enable);
268         synchronizedViewCB->setEnabled(enable);
269         applyPB->setEnabled(enable);
270         restorePB->setEnabled(enable);
271         if (!enable)
272                 synchronizedViewCB->setChecked(true);
273         RadioMap::const_iterator it = radioMap.begin();
274         for (; it != radioMap.end(); ++it)
275                 it->second->setEnabled(enable);
276 }
277
278
279 ParagraphParameters & GuiParagraph::params()
280 {
281         if (haveMultiParSelection()) {
282                 multiparsel_ = ParagraphParameters();
283                 // FIXME: It would be nice to initialise the parameters that
284                 // are common to all paragraphs.
285                 return multiparsel_;
286         }
287
288         return bufferview()->cursor().innerParagraph().params();
289 }
290
291
292 ParagraphParameters const & GuiParagraph::params() const
293 {
294         return bufferview()->cursor().innerParagraph().params();
295 }
296
297
298 void GuiParagraph::dispatchParams()
299 {
300         if (haveMultiParSelection()) {
301                 ostringstream data;
302                 multiparsel_.write(data);
303                 FuncRequest const fr(getLfun(), data.str());
304                 dispatch(fr);
305                 return;
306         }
307
308         bufferview()->updateMetrics();
309         bufferview()->buffer().changed();
310 }
311
312
313 bool GuiParagraph::haveMultiParSelection()
314 {
315         Cursor cur = bufferview()->cursor();
316         return cur.selection() && cur.selBegin().pit() != cur.selEnd().pit();
317 }
318
319         
320 bool GuiParagraph::canIndent() const
321 {
322         return buffer().params().paragraph_separation ==
323                 BufferParams::PARSEP_INDENT;
324 }
325
326
327 LyXAlignment GuiParagraph::alignPossible() const
328 {
329         return bufferview()->cursor().innerParagraph().layout()->alignpossible;
330 }
331
332
333 LyXAlignment GuiParagraph::alignDefault() const
334 {
335         return bufferview()->cursor().innerParagraph().layout()->align;
336 }
337
338
339 Dialog * createGuiParagraph(GuiView & lv)
340 {
341         return new GuiParagraph(lv);
342 }
343
344
345 } // namespace frontend
346 } // namespace lyx
347
348 #include "GuiParagraph_moc.cpp"