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