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