1 /**
2  * \file GuiHSpace.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Spitzmüller
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10 
11 #include <config.h>
12 
13 #include "GuiHSpace.h"
14 
15 #include "LengthCombo.h"
16 #include "qt_helpers.h"
17 #include "Validator.h"
18 
19 #include "Spacing.h"
20 
21 #include "insets/InsetSpace.h"
22 
23 #include "mathed/InsetMathSpace.h"
24 
25 #include "support/gettext.h"
26 #include "support/lstrings.h"
27 
28 #include <QCheckBox>
29 #include <QLineEdit>
30 #include <QPushButton>
31 #include <QValidator>
32 
33 using namespace std;
34 
35 namespace lyx {
36 namespace frontend {
37 
GuiHSpace(bool math_mode,QWidget * parent)38 GuiHSpace::GuiHSpace(bool math_mode, QWidget * parent)
39 	: InsetParamsWidget(parent), math_mode_(math_mode)
40 {
41 	setupUi(this);
42 
43 	spacingCO->clear();
44 	if (math_mode_) {
45 		spacingCO->addItem(qt_("Interword Space"), "normal");
46 		spacingCO->addItem(qt_("Thin Space"), "thinspace");
47 		spacingCO->addItem(qt_("Medium Space"), "medspace");
48 		spacingCO->addItem(qt_("Thick Space"), "thickspace");
49 		spacingCO->addItem(qt_("Negative Thin Space"), "negthinspace");
50 		spacingCO->addItem(qt_("Negative Medium Space"), "negmedspace");
51 		spacingCO->addItem(qt_("Negative Thick Space"), "negthickspace");
52 		spacingCO->addItem(qt_("Half Quad (0.5 em)"), "halfquad");
53 		spacingCO->addItem(qt_("Quad (1 em)"), "quad");
54 		spacingCO->addItem(qt_("Double Quad (2 em)"), "qquad");
55 		spacingCO->addItem(qt_("Horizontal Fill"), "hfill");
56 		spacingCO->addItem(qt_("Custom"), "custom");
57 	} else {
58 		spacingCO->addItem(qt_("Interword Space"), "normal");
59 		spacingCO->addItem(qt_("Thin Space"), "thinspace");
60 		spacingCO->addItem(qt_("Negative Thin Space"), "negthinspace");
61 		spacingCO->addItem(qt_("Negative Medium Space"), "negmedspace");
62 		spacingCO->addItem(qt_("Negative Thick Space"), "negthickspace");
63 		spacingCO->addItem(qt_("Half Quad (0.5 em)"), "halfquad");
64 		spacingCO->addItem(qt_("Quad (1 em)"), "quad");
65 		spacingCO->addItem(qt_("Double Quad (2 em)"), "qquad");
66 		spacingCO->addItem(qt_("Horizontal Fill"), "hfill");
67 		spacingCO->addItem(qt_("Custom"), "custom");
68 		spacingCO->addItem(qt_("Visible Space"), "visible");
69 	}
70 
71 	connect(spacingCO, SIGNAL(highlighted(QString)),
72 		this, SLOT(changedSlot()));
73 	connect(valueLE, SIGNAL(textChanged(QString)),
74 		this, SLOT(changedSlot()));
75 	connect(spacingCO, SIGNAL(activated(int)),
76 		this, SLOT(changedSlot()));
77 	connect(keepCB, SIGNAL(clicked()),
78 		this, SLOT(changedSlot()));
79 	connect(unitCO, SIGNAL(selectionChanged(lyx::Length::UNIT)),
80 		this, SLOT(changedSlot()));
81 	connect(fillPatternCO, SIGNAL(activated(int)),
82 		this, SLOT(changedSlot()));
83 
84 	// Set up a signed (glue) length validator
85 	LengthValidator * v = new LengthValidator(valueLE);
86 	if (math_mode_)
87 		v->setBottom(Length());
88 	else
89 		v->setBottom(GlueLength());
90 	valueLE->setValidator(v);
91 
92 	// initialize the length validator
93 	addCheckedWidget(valueLE, valueL);
94 	enableWidgets();
95 }
96 
97 
changedSlot()98 void GuiHSpace::changedSlot()
99 {
100 	enableWidgets();
101 	changed();
102 }
103 
104 
enableWidgets() const105 void GuiHSpace::enableWidgets() const
106 {
107 	QString const selection = spacingCO->itemData(spacingCO->currentIndex()).toString();
108 	bool const custom = selection == "custom";
109 	valueLE->setEnabled(custom);
110 	if (custom)
111 		valueLE->setFocus();
112 	valueL->setEnabled(custom);
113 	unitCO->setEnabled(custom);
114 	fillPatternCO->setEnabled(!math_mode_ && selection == "hfill");
115 	fillPatternL->setEnabled(!math_mode_ && selection == "hfill");
116 	bool const no_pattern = fillPatternCO->currentIndex() == 0 || math_mode_;
117 	bool const enable_keep =
118 		selection == "normal" || selection == "halfquad"
119 		|| (selection == "hfill" && no_pattern) || custom;
120 	keepCB->setEnabled(enable_keep);
121 	keepL->setEnabled(enable_keep);
122 }
123 
124 
paramsToDialog(Inset const * inset)125 void GuiHSpace::paramsToDialog(Inset const * inset)
126 {
127 	InsetSpaceParams const params = math_mode_
128 		? static_cast<InsetMathSpace const *>(inset)->params()
129 		: static_cast<InsetSpace const *>(inset)->params();
130 
131 	QString item;
132 	int pattern = 0;
133 	bool protect = false;
134 	switch (params.kind) {
135 		case InsetSpaceParams::NORMAL:
136 			item = "normal";
137 			break;
138 		case InsetSpaceParams::PROTECTED:
139 			item = "normal";
140 			protect = true;
141 			break;
142 		case InsetSpaceParams::VISIBLE:
143 			item = "visible";
144 			protect = true;
145 			break;
146 		case InsetSpaceParams::THIN:
147 			item = "thinspace";
148 			break;
149 		case InsetSpaceParams::MEDIUM:
150 			item = "medspace";
151 			break;
152 		case InsetSpaceParams::THICK:
153 			item = "thickspace";
154 			break;
155 		case InsetSpaceParams::NEGTHIN:
156 			item = "negthinspace";
157 			break;
158 		case InsetSpaceParams::NEGMEDIUM:
159 			item = "negmedspace";
160 			break;
161 		case InsetSpaceParams::NEGTHICK:
162 			item = "negthickspace";
163 			break;
164 		case InsetSpaceParams::ENSKIP:
165 			item = "halfquad";
166 			break;
167 		case InsetSpaceParams::ENSPACE:
168 			item = "halfquad";
169 			protect = true;
170 			break;
171 		case InsetSpaceParams::QUAD:
172 			item = "quad";
173 			break;
174 		case InsetSpaceParams::QQUAD:
175 			item = "qquad";
176 			break;
177 		case InsetSpaceParams::HFILL:
178 			item = "hfill";
179 			break;
180 		case InsetSpaceParams::HFILL_PROTECTED:
181 			item = "hfill";
182 			protect = true;
183 			break;
184 		case InsetSpaceParams::DOTFILL:
185 			item = "hfill";
186 			pattern = 1;
187 			break;
188 		case InsetSpaceParams::HRULEFILL:
189 			item = "hfill";
190 			pattern = 2;
191 			break;
192 		case InsetSpaceParams::LEFTARROWFILL:
193 			item = "hfill";
194 			pattern = 3;
195 			break;
196 		case InsetSpaceParams::RIGHTARROWFILL:
197 			item = "hfill";
198 			pattern = 4;
199 			break;
200 		case InsetSpaceParams::UPBRACEFILL:
201 			item = "hfill";
202 			pattern = 5;
203 			break;
204 		case InsetSpaceParams::DOWNBRACEFILL:
205 			item = "hfill";
206 			pattern = 6;
207 			break;
208 		case InsetSpaceParams::CUSTOM:
209 			item = "custom";
210 			break;
211 		case InsetSpaceParams::CUSTOM_PROTECTED:
212 			item = "custom";
213 			protect = true;
214 			break;
215 	}
216 	spacingCO->setCurrentIndex(spacingCO->findData(item));
217 	fillPatternCO->setCurrentIndex(pattern);
218 	keepCB->setChecked(protect);
219 	if (item == "halfquad") {
220 		keepCB->setToolTip(qt_("Insert the spacing even after a line break.\n"
221 				       "Note that a protected Half Quad will be turned into\n"
222 				       "a vertical space if used at the beginning of a paragraph!"));
223 	} else {
224 		keepCB->setToolTip(qt_("Insert the spacing even after a line break"));
225 	}
226 	Length::UNIT const default_unit = Length::defaultUnit();
227 	if (item == "custom") {
228 		string length = params.length.asString();
229 		lengthToWidgets(valueLE, unitCO, length, default_unit);
230 	} else
231 		lengthToWidgets(valueLE, unitCO, "", default_unit);
232 
233 	enableWidgets();
234 }
235 
236 
dialogToParams() const237 docstring GuiHSpace::dialogToParams() const
238 {
239 	InsetSpaceParams params = math_mode_ ?
240 		InsetSpaceParams(true) : InsetSpaceParams(false);
241 
242 	QString const item =
243 		spacingCO->itemData(spacingCO->currentIndex()).toString();
244 
245 	if (item == "normal")
246 		params.kind = keepCB->isChecked() ?
247 			InsetSpaceParams::PROTECTED : InsetSpaceParams::NORMAL;
248 	else if (item == "thinspace")
249 		params.kind = InsetSpaceParams::THIN;
250 	else if (item == "medspace")
251 		params.kind = InsetSpaceParams::MEDIUM;
252 	else if (item == "thickspace")
253 		params.kind = InsetSpaceParams::THICK;
254 	else if (item == "negthinspace")
255 		params.kind = InsetSpaceParams::NEGTHIN;
256 	else if (item == "negmedspace")
257 		params.kind = InsetSpaceParams::NEGMEDIUM;
258 	else if (item == "negthickspace")
259 		params.kind = InsetSpaceParams::NEGTHICK;
260 	else if (item == "halfquad")
261 		params.kind = keepCB->isChecked() ?
262 			InsetSpaceParams::ENSPACE : InsetSpaceParams::ENSKIP;
263 	else if (item == "quad")
264 			params.kind = InsetSpaceParams::QUAD;
265 	else if (item == "qquad")
266 			params.kind = InsetSpaceParams::QQUAD;
267 	else if (item == "hfill") {
268 		switch (fillPatternCO->currentIndex()) {
269 		case 1:
270 			params.kind = InsetSpaceParams::DOTFILL;
271 			break;
272 		case 2:
273 			params.kind = InsetSpaceParams::HRULEFILL;
274 			break;
275 		case 3:
276 			params.kind = InsetSpaceParams::LEFTARROWFILL;
277 			break;
278 		case 4:
279 			params.kind = InsetSpaceParams::RIGHTARROWFILL;
280 			break;
281 		case 5:
282 			params.kind = InsetSpaceParams::UPBRACEFILL;
283 			break;
284 		case 6:
285 			params.kind = InsetSpaceParams::DOWNBRACEFILL;
286 			break;
287 		default:
288 			if (keepCB->isChecked())
289 				params.kind = InsetSpaceParams::HFILL_PROTECTED;
290 			else
291 				params.kind = InsetSpaceParams::HFILL;
292 			break;
293 		}
294 	} else if (item == "custom") {
295 			params.kind = keepCB->isChecked() ?
296 				InsetSpaceParams::CUSTOM_PROTECTED : InsetSpaceParams::CUSTOM;
297 			params.length = GlueLength(widgetsToLength(valueLE, unitCO));
298 	} else if (item == "visible")
299 		params.kind = InsetSpaceParams::VISIBLE;
300 
301 	return from_ascii(InsetSpace::params2string(params));
302 }
303 
304 
checkWidgets(bool readonly) const305 bool GuiHSpace::checkWidgets(bool readonly) const
306 {
307 	valueLE->setReadOnly(readonly);
308 
309 	if (readonly) {
310 		spacingCO->setEnabled(false);
311 		unitCO->setEnabled(false);
312 		fillPatternCO->setEnabled(false);
313 		keepCB->setEnabled(false);
314 		valueLE->setEnabled(false);
315 	} else
316 		enableWidgets();
317 
318 	if (!InsetParamsWidget::checkWidgets())
319 		return false;
320 	return spacingCO->itemData(spacingCO->currentIndex()).toString() != "custom"
321 		|| !valueLE->text().isEmpty();
322 }
323 
324 } // namespace frontend
325 } // namespace lyx
326 
327 
328 #include "moc_GuiHSpace.cpp"
329