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