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