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