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