1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 
8 
9 #include "propertiespalette_text.h"
10 
11 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
12 #define _USE_MATH_DEFINES
13 #endif
14 #include <cmath>
15 #include <QSignalBlocker>
16 
17 #include "appmodes.h"
18 #include "colorcombo.h"
19 #include "colorlistbox.h"
20 #include "commonstrings.h"
21 #include "fontcombo.h"
22 #include "iconmanager.h"
23 #include "localemgr.h"
24 #include "pageitem.h"
25 #include "pageitem_table.h"
26 #include "pageitem_textframe.h"
27 #include "propertiespalette_utils.h"
28 #include "propertywidget_advanced.h"
29 #include "propertywidget_distance.h"
30 #include "propertywidget_flop.h"
31 #include "propertywidget_fontfeatures.h"
32 #include "propertywidget_hyphenation.h"
33 #include "propertywidget_optmargins.h"
34 #include "propertywidget_orphans.h"
35 #include "propertywidget_pareffect.h"
36 #include "propertywidget_pathtext.h"
37 #include "propertywidget_textcolor.h"
38 #include "scfonts.h"
39 #include "scraction.h"
40 #include "scribusapp.h"
41 #include "scribuscore.h"
42 #include "selection.h"
43 #include "stylecombos.h"
44 #include "styleselect.h"
45 #include "tabmanager.h"
46 #include "undomanager.h"
47 #include "units.h"
48 #include "util.h"
49 #include "util_math.h"
50 #include "langmgr.h"
51 
52 //using namespace std;
53 
PropertiesPalette_Text(QWidget * parent)54 PropertiesPalette_Text::PropertiesPalette_Text( QWidget* parent) : QWidget(parent)
55 {
56 	setupUi(this);
57 
58 	fontSize->setPrefix( "" );
59 
60 	iconSetChange();
61 
62 	colorWidgets = new PropertyWidget_TextColor(textTree);
63 	colorWidgetsItem = textTree->addItem( colorWidgets, tr("Color && Effects") );
64 
65 	flopBox = new PropertyWidget_Flop(textTree);
66 	flopItem = textTree->addItem( flopBox, tr("First Line Offset"));
67 
68 	orphanBox = new PropertyWidget_Orphans(textTree);
69 	orphanItem = textTree->addItem(orphanBox, tr("Orphans and Widows"));
70 
71 	parEffectWidgets = new PropertyWidget_ParEffect(textTree);
72 	parEffectItem = textTree->addItem(parEffectWidgets, tr("Paragraph Effects"));
73 
74 	distanceWidgets = new PropertyWidget_Distance(textTree);
75 	distanceItem = textTree->addItem(distanceWidgets, tr("Columns && Text Distances"));
76 
77 	//<< Optical Margins
78 	optMargins = new PropertyWidget_OptMargins(textTree);
79 	optMarginsItem = textTree->addItem(optMargins, tr("Optical Margins"));
80 	//>> Optical Margins
81 
82 	hyphenationWidget = new PropertyWidget_Hyphenation(textTree);
83 	hyphenationWidgetItem = textTree->addItem(hyphenationWidget, tr("Hyphenation"));
84 
85 	//<<Advanced Settings
86 	advancedWidgets = new PropertyWidget_Advanced(textTree);
87 	advancedWidgetsItem = textTree->addItem(advancedWidgets, tr("Advanced Settings"));
88 
89 	//>>Advanced Settings
90 	fontfeaturesWidget = new PropertyWidget_FontFeatures(textTree);
91 	fontfeaturesWidgetItem = textTree->addItem(fontfeaturesWidget, tr("Font Features"));
92 
93 	pathTextWidgets = new PropertyWidget_PathText(textTree);
94 	pathTextItem = textTree->addItem(pathTextWidgets, tr("Path Text Properties"));
95 
96 	languageChange();
97 
98 	connect(lineSpacing   , SIGNAL(valueChanged(double)), this, SLOT(handleLineSpacing()));
99 	connect(fonts         , SIGNAL(fontSelected(QString)), this, SLOT(handleTextFont(QString)));
100 	connect(fontSize      , SIGNAL(valueChanged(double)), this, SLOT(handleFontSize()));
101 	connect(textAlignment , SIGNAL(State(int))   , this, SLOT(handleAlignment(int)));
102 	connect(textDirection , SIGNAL(State(int))   , this, SLOT(handleDirection(int)));
103 	connect(charStyleClear, SIGNAL(clicked()), this, SLOT(doClearCStyle()));
104 	connect(paraStyleClear, SIGNAL(clicked()), this, SLOT(doClearPStyle()));
105 
106 	connect(flopBox->flopGroup, SIGNAL(buttonClicked( int )), this, SLOT(handleFirstLinePolicy(int)));
107 
108 	connect(lineSpacingModeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(handleLineSpacingMode(int)));
109 	connect(langCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeLang(int)));
110 
111 	connect(fontfeaturesWidget, SIGNAL(needsRelayout()), this, SLOT(updateTreeLayout()));
112 	connect(parEffectWidgets,   SIGNAL(needsRelayout()), this, SLOT(updateTreeLayout()));
113 
114 	connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
115 	connect(ScQApp, SIGNAL(localeChanged()), this, SLOT(localeChange()));
116 
117 	setEnabled(false);
118 }
119 
setMainWindow(ScribusMainWindow * mw)120 void PropertiesPalette_Text::setMainWindow(ScribusMainWindow* mw)
121 {
122 	m_ScMW = mw;
123 
124 	advancedWidgets->setMainWindow(mw);
125 	fontfeaturesWidget->setMainWindow(mw);
126 	colorWidgets->setMainWindow(mw);
127 	distanceWidgets->setMainWindow(mw);
128 	hyphenationWidget->setMainWindow(mw);
129 	parEffectWidgets->setMainWindow(mw);
130 	optMargins->setMainWindow(mw);
131 	pathTextWidgets->setMainWindow(mw);
132 
133 	connect(m_ScMW, SIGNAL(UpdateRequest(int))     , this  , SLOT(handleUpdateRequest(int)));
134 
135 	connect(paraStyleCombo, SIGNAL(newStyle(const QString&)), m_ScMW, SLOT(setNewParStyle(const QString&)), Qt::UniqueConnection);
136 	connect(charStyleCombo, SIGNAL(newStyle(const QString&)), m_ScMW, SLOT(setNewCharStyle(const QString&)), Qt::UniqueConnection);
137 }
138 
setDoc(ScribusDoc * d)139 void PropertiesPalette_Text::setDoc(ScribusDoc *d)
140 {
141 	if((d == (ScribusDoc*) m_doc) || (m_ScMW && m_ScMW->scriptIsRunning()))
142 		return;
143 
144 	if (m_doc)
145 	{
146 		disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
147 		disconnect(m_doc             , SIGNAL(docChanged())      , this, SLOT(handleSelectionChanged()));
148 	}
149 
150 	m_doc  = d;
151 	m_item = nullptr;
152 
153 	m_unitRatio = m_doc->unitRatio();
154 	m_unitIndex = m_doc->unitIndex();
155 
156 	m_haveDoc  = true;
157 	m_haveItem = false;
158 
159 	fontSize->setValues(0.5, 2048, 2, 1);
160 	lineSpacing->setValues(1, 2048, 2, 1);
161 
162 	advancedWidgets->setDoc(m_doc);
163 	fontfeaturesWidget->setDoc(m_doc);
164 	colorWidgets->setDoc(m_doc);
165 	distanceWidgets->setDoc(m_doc);
166 	parEffectWidgets->setDoc(m_doc);
167 	flopBox->setDoc(m_doc);
168 	hyphenationWidget->setDoc(m_doc);
169 	optMargins->setDoc(m_doc);
170 	orphanBox->setDoc(m_doc);
171 	pathTextWidgets->setDoc(m_doc);
172 
173 	fonts->rebuildList(m_doc);
174 	paraStyleCombo->setDoc(m_doc);
175 	charStyleCombo->setDoc(m_doc);
176 
177 	connect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
178 	connect(m_doc             , SIGNAL(docChanged())      , this, SLOT(handleSelectionChanged()));
179 }
180 
unsetDoc()181 void PropertiesPalette_Text::unsetDoc()
182 {
183 	if (m_doc)
184 	{
185 		disconnect(m_doc->m_Selection, SIGNAL(selectionChanged()), this, SLOT(handleSelectionChanged()));
186 		disconnect(m_doc             , SIGNAL(docChanged())      , this, SLOT(handleSelectionChanged()));
187 	}
188 
189 	m_haveDoc  = false;
190 	m_haveItem = false;
191 	m_doc      = nullptr;
192 	m_item     = nullptr;
193 
194 	paraStyleCombo->setDoc(nullptr);
195 	charStyleCombo->setDoc(nullptr);
196 
197 	advancedWidgets->setDoc(nullptr);
198 	fontfeaturesWidget->setDoc(nullptr);
199 	colorWidgets->setDoc(nullptr);
200 	distanceWidgets->setDoc(nullptr);
201 	flopBox->setDoc(nullptr);
202 	hyphenationWidget->setDoc(nullptr);
203 	optMargins->setDoc(nullptr);
204 	orphanBox->setDoc(nullptr);
205 	parEffectWidgets->setDoc(nullptr);
206 	pathTextWidgets->setDoc(nullptr);
207 
208 	m_haveItem = false;
209 
210 	setEnabled(false);
211 }
212 
unsetItem()213 void PropertiesPalette_Text::unsetItem()
214 {
215 	m_haveItem = false;
216 	m_item     = nullptr;
217 	colorWidgets->setCurrentItem(m_item);
218 	handleSelectionChanged();
219 }
220 
currentItemFromSelection()221 PageItem* PropertiesPalette_Text::currentItemFromSelection()
222 {
223 	PageItem *currentItem = nullptr;
224 
225 	if (m_doc)
226 	{
227 		if (m_doc->m_Selection->count() > 1)
228 			currentItem = m_doc->m_Selection->itemAt(0);
229 		else if (m_doc->m_Selection->count() == 1)
230 			currentItem = m_doc->m_Selection->itemAt(0);
231 		if (currentItem  && currentItem->isTable() && m_doc->appMode == modeEditTable)
232 			currentItem = currentItem->asTable()->activeCell().textFrame();
233 	}
234 
235 	return currentItem;
236 }
237 
handleSelectionChanged()238 void PropertiesPalette_Text::handleSelectionChanged()
239 {
240 	if (!m_haveDoc || !m_ScMW || m_ScMW->scriptIsRunning())
241 		return;
242 
243 	PageItem* currItem = currentItemFromSelection();
244 	if (m_doc->m_Selection->count() > 1)
245 	{
246 		setEnabled(false);
247 		flopBox->flopRealHeight->setChecked(true);
248 	}
249 	else
250 	{
251 		int itemType = currItem ? (int) currItem->itemType() : -1;
252 		m_haveItem = (itemType != -1);
253 
254 		switch (itemType)
255 		{
256 		case -1:
257 			m_haveItem = false;
258 			m_item = nullptr;
259 			setEnabled(false);
260 			break;
261 		case PageItem::TextFrame:
262 		case PageItem::PathText:
263 			setEnabled(true);
264 			break;
265 		case PageItem::Table:
266 			setEnabled(m_doc->appMode == modeEditTable);
267 			break;
268 		default:
269 			setEnabled(false);
270 			break;
271 		}
272 	}
273 	if (currItem)
274 	{
275 		setCurrentItem(currItem);
276 	}
277 	updateGeometry();
278 	//repaint();
279 }
280 
handleUpdateRequest(int updateFlags)281 void PropertiesPalette_Text::handleUpdateRequest(int updateFlags)
282 {
283 	// ColorWidget will handle its update itself
284 	/*if (updateFlags & reqColorsUpdate)
285 		updateColorList();*/
286 	if (updateFlags & reqCharStylesUpdate)
287 	{
288 		charStyleCombo->updateStyleList();
289 		parEffectWidgets->updateCharStyles();
290 	}
291 	if (updateFlags & reqParaStylesUpdate)
292 		paraStyleCombo->updateStyleList();
293 	if (updateFlags & reqDefFontListUpdate)
294 		fonts->rebuildList(nullptr);
295 	if (updateFlags & reqDocFontListUpdate)
296 		fonts->rebuildList(m_haveDoc ? m_doc : nullptr);
297 	if (updateFlags & reqStyleComboDocUpdate)
298 	{
299 		paraStyleCombo->setDoc(m_haveDoc ? m_doc : nullptr);
300 		charStyleCombo->setDoc(m_haveDoc ? m_doc : nullptr);
301 		parEffectWidgets->setDoc(m_haveDoc ? m_doc : nullptr);
302 	}
303 }
304 
setCurrentItem(PageItem * item)305 void PropertiesPalette_Text::setCurrentItem(PageItem *item)
306 {
307 	if (!m_ScMW || m_ScMW->scriptIsRunning())
308 		return;
309 	//CB We shouldn't really need to process this if our item is the same one
310 	//maybe we do if the item has been changed by scripter.. but that should probably
311 	//set some status if so.
312 	//FIXME: This won't work until when a canvas deselect happens, m_item must be nullptr.
313 	//if (m_item == i)
314 	//	return;
315 
316 	if (!m_doc)
317 		setDoc(item->doc());
318 
319 	m_haveItem = false;
320 	m_item = item;
321 
322 	showFirstLinePolicy(m_item->firstLineOffset());
323 
324 	if ((m_item->isGroup()) && (!m_item->isSingleSel))
325 	{
326 		setEnabled(false);
327 	}
328 
329 	m_haveItem = true;
330 
331 	if (!sender())
332 	{
333 		colorWidgets->handleSelectionChanged();
334 		distanceWidgets->handleSelectionChanged();
335 		parEffectWidgets->handleSelectionChanged();
336 	}
337 
338 	if (m_item->isTextFrame() || m_item->isPathText() || m_item->isTable())
339 	{
340 		ParagraphStyle parStyle =  m_item->itemText.defaultStyle();
341 		if (m_doc->appMode == modeEdit || m_doc->appMode == modeEditTable)
342 			m_item->currentTextProps(parStyle);
343 		updateStyle(parStyle);
344 	}
345 	if (m_item->isOSGFrame())
346 	{
347 		setEnabled(false);
348 	}
349 	if (m_item->asSymbol())
350 	{
351 		setEnabled(false);
352 	}
353 }
354 
iconSetChange()355 void PropertiesPalette_Text::iconSetChange()
356 {
357 	IconManager& iconManager = IconManager::instance();
358 
359 	fontSizeLabel->setPixmap(iconManager.loadPixmap("zeichen.png"));
360 	lineSpacingLabel->setPixmap(iconManager.loadPixmap("linespacing2.png"));
361 	textAlignmentLabel->setPixmap(iconManager.loadPixmap("22/text-align.png"));
362 	langLabel->setPixmap(iconManager.loadPixmap("22/language.png"));
363 	paraStyleLabel->setPixmap(iconManager.loadPixmap("22/paragraph-style.png"));
364 	charStyleLabel->setPixmap(iconManager.loadPixmap("22/character-style.png"));
365 
366 	paraStyleClear->setIcon(iconManager.loadPixmap("16/edit-clear.png"));
367 	charStyleClear->setIcon(iconManager.loadPixmap("16/edit-clear.png"));
368 }
369 
unitChange()370 void PropertiesPalette_Text::unitChange()
371 {
372 	if (!m_haveDoc)
373 		return;
374 	bool tmp = m_haveItem;
375 	m_haveItem = false;
376 
377 	advancedWidgets->unitChange();
378 	fontfeaturesWidget->unitChange();
379 	colorWidgets->unitChange();
380 	distanceWidgets->unitChange();
381 	flopBox->unitChange();
382 	optMargins->unitChange();
383 	pathTextWidgets->unitChange();
384 	parEffectWidgets->unitChange();
385 
386 	m_haveItem = tmp;
387 }
388 
localeChange()389 void PropertiesPalette_Text::localeChange()
390 {
391 	const QLocale& l(LocaleManager::instance().userPreferredLocale());
392 	fontSize->setLocale(l);
393 	lineSpacing->setLocale(l);
394 	advancedWidgets->localeChange();
395 	colorWidgets->localeChange();
396 	distanceWidgets->localeChange();
397 	parEffectWidgets->localeChange();
398 	pathTextWidgets->localeChange();
399 }
400 
handleLineSpacingMode(int id)401 void PropertiesPalette_Text::handleLineSpacingMode(int id)
402 {
403 	if (!m_haveDoc || !m_haveItem)
404 		return;
405 	Selection tempSelection(this, false);
406 	tempSelection.addItem(m_item, true);
407 	m_doc->itemSelection_SetLineSpacingMode(id, &tempSelection);
408 //	updateStyle(((m_doc->appMode == modeEdit) || (m_doc->appMode == modeEditTable)) ? m_item->currentStyle() : m_item->itemText.defaultStyle());
409 	m_doc->regionsChanged()->update(QRect());
410 }
411 
changeLang(int id)412 void PropertiesPalette_Text::changeLang(int id)
413 {
414 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
415 		return;
416 	QStringList languageList;
417 	LanguageManager::instance()->fillInstalledStringList(&languageList);
418 	QString abrv = LanguageManager::instance()->getAbbrevFromLang(languageList.value(id),false);
419 	Selection tempSelection(this, false);
420 	tempSelection.addItem(m_item, true);
421 	m_doc->itemSelection_SetLanguage(abrv, &tempSelection);
422 }
423 
showLineSpacing(double r)424 void PropertiesPalette_Text::showLineSpacing(double r)
425 {
426 	if (!m_ScMW || m_ScMW->scriptIsRunning())
427 		return;
428 	bool inEditMode = (m_doc->appMode == modeEdit || m_doc->appMode == modeEditTable);
429 	bool tmp = m_haveItem;
430 	m_haveItem = false;
431 	lineSpacing->showValue(r);
432 	const ParagraphStyle& curStyle(m_haveItem && inEditMode ? m_item->currentStyle() : m_item->itemText.defaultStyle());
433 	if (tmp)
434 	{
435 		setupLineSpacingSpinbox(curStyle.lineSpacingMode(), r);
436 		lineSpacingModeCombo->setCurrentIndex(curStyle.lineSpacingMode());
437 	}
438 	m_haveItem = tmp;
439 }
440 
showFontFace(const QString & newFont)441 void PropertiesPalette_Text::showFontFace(const QString& newFont)
442 {
443 	if (!m_ScMW || m_ScMW->scriptIsRunning())
444 		return;
445 	bool tmp = m_haveItem;
446 	m_haveItem = false;
447 	if (m_item != nullptr)
448 		fonts->rebuildList(m_doc, m_item->isAnnotation());
449 	fonts->setCurrentFont(newFont);
450 	m_haveItem = tmp;
451 }
452 
showFontSize(double s)453 void PropertiesPalette_Text::showFontSize(double s)
454 {
455 	if (!m_ScMW || m_ScMW->scriptIsRunning())
456 		return;
457 	fontSize->showValue(s / 10.0);
458 }
459 
showLanguage(const QString & w)460 void PropertiesPalette_Text::showLanguage(const QString& w)
461 {
462 	if (!m_ScMW || m_ScMW->scriptIsRunning())
463 		return;
464 	QStringList lang;
465 	LanguageManager::instance()->fillInstalledStringList(&lang);
466 	QString langName = LanguageManager::instance()->getLangFromAbbrev(w, true);
467 
468 	bool sigBlocked  = langCombo->blockSignals(true);
469 	langCombo->setCurrentIndex(lang.indexOf(langName));
470 	langCombo->blockSignals(sigBlocked);
471 }
472 
showFirstLinePolicy(FirstLineOffsetPolicy f)473 void PropertiesPalette_Text::showFirstLinePolicy( FirstLineOffsetPolicy f )
474 {
475 	if(f == FLOPFontAscent)
476 		flopBox->flopFontAscent->setChecked(true);
477 	else if(f == FLOPLineSpacing)
478 		flopBox->flopLineSpacing->setChecked(true);
479 	else if (f == FLOPRealGlyphHeight)
480 		flopBox->flopRealHeight->setChecked(true); //It’s historical behaviour.
481 	else // if (f == FLOPBaseline)
482 		flopBox->flopBaselineGrid->setChecked(true);
483 }
484 
setupLineSpacingSpinbox(int mode,double value)485 void PropertiesPalette_Text::setupLineSpacingSpinbox(int mode, double value)
486 {
487 	bool blocked = lineSpacing->blockSignals(true);
488 	if (mode > 0)
489 	{
490 		if (mode == 1)
491 			lineSpacing->setSpecialValueText( tr( "Auto" ) );
492 		if (mode == 2)
493 			lineSpacing->setSpecialValueText( tr( "Baseline" ) );
494 		lineSpacing->setMinimum(0);
495 		lineSpacing->setValue(0);
496 		lineSpacing->setEnabled(false);
497 	}
498 	else
499 	{
500 		lineSpacing->setSpecialValueText("");
501 		lineSpacing->setMinimum(1);
502 		lineSpacing->setValue(value);
503 		lineSpacing->setEnabled(true);
504 	}
505 	lineSpacing->blockSignals(blocked);
506 }
507 
updateCharStyle(const CharStyle & charStyle)508 void PropertiesPalette_Text::updateCharStyle(const CharStyle& charStyle)
509 {
510 	if (!m_ScMW || m_ScMW->scriptIsRunning())
511 		return;
512 
513 	advancedWidgets->updateCharStyle(charStyle);
514 	fontfeaturesWidget->updateCharStyle(charStyle);
515 	colorWidgets->updateCharStyle(charStyle);
516 	hyphenationWidget->updateCharStyle(charStyle);
517 
518 	showFontFace(charStyle.font().scName());
519 	showFontSize(charStyle.fontSize());
520 	showLanguage(charStyle.language());
521 }
522 
updateStyle(const ParagraphStyle & newCurrent)523 void PropertiesPalette_Text::updateStyle(const ParagraphStyle& newCurrent)
524 {
525 	if (!m_ScMW || m_ScMW->scriptIsRunning())
526 		return;
527 
528 	const CharStyle& charStyle = newCurrent.charStyle();
529 
530 	advancedWidgets->updateStyle(newCurrent);
531 	fontfeaturesWidget->updateStyle(newCurrent);
532 	colorWidgets->updateStyle(newCurrent);
533 	optMargins->updateStyle(newCurrent);
534 	orphanBox->updateStyle (newCurrent);
535 	parEffectWidgets->updateStyle(newCurrent);
536 	hyphenationWidget->updateStyle(newCurrent);
537 
538 	showFontFace(charStyle.font().scName());
539 	showFontSize(charStyle.fontSize());
540 	showLanguage(charStyle.language());
541 
542 	if (m_item)
543 	{
544 		QString defaultParStyle = m_item->itemText.defaultStyle().parent();
545 		if (defaultParStyle.isEmpty())
546 			defaultParStyle = CommonStrings::DefaultParagraphStyle;
547 		paraStyleCombo->setDefaultStyle(defaultParStyle);
548 	}
549 	showParStyle(newCurrent.parent());
550 
551 	if (m_item)
552 	{
553 		QString defaultCharStyle;
554 		if (!newCurrent.parent().isEmpty())
555 		{
556 			const ParagraphStyle& paraStyle = m_doc->paragraphStyles().get(newCurrent.parent());
557 			defaultCharStyle = paraStyle.charStyle().parent();
558 			if (defaultCharStyle.isEmpty())
559 				defaultCharStyle = CommonStrings::DefaultCharacterStyle;
560 		}
561 		if (defaultCharStyle.isEmpty())
562 			defaultCharStyle = m_item->itemText.defaultStyle().charStyle().parent();
563 		if (defaultCharStyle.isEmpty())
564 			defaultCharStyle = CommonStrings::DefaultCharacterStyle;
565 		charStyleCombo->setDefaultStyle(defaultCharStyle);
566 	}
567 	showCharStyle(charStyle.parent());
568 
569 	bool tmp = m_haveItem;
570 	m_haveItem = false;
571 
572 	setupLineSpacingSpinbox(newCurrent.lineSpacingMode(), newCurrent.lineSpacing());
573 	lineSpacingModeCombo->setCurrentIndex(newCurrent.lineSpacingMode());
574 	textAlignment->setStyle(newCurrent.alignment(), newCurrent.direction());
575 	textDirection->setStyle(newCurrent.direction());
576 
577 	m_haveItem = tmp;
578 }
579 
updateCharStyles()580 void PropertiesPalette_Text::updateCharStyles()
581 {
582 	charStyleCombo->updateStyleList();
583 	parEffectWidgets->updateCharStyles();
584 }
585 
updateParagraphStyles()586 void PropertiesPalette_Text::updateParagraphStyles()
587 {
588 	paraStyleCombo->updateStyleList();
589 	charStyleCombo->updateStyleList();
590 	parEffectWidgets->updateCharStyles();
591 }
592 
updateTextStyles()593 void PropertiesPalette_Text::updateTextStyles()
594 {
595 	paraStyleCombo->updateStyleList();
596 	charStyleCombo->updateStyleList();
597 }
598 
updateTreeLayout()599 void PropertiesPalette_Text::updateTreeLayout()
600 {
601 	textTree->doItemsLayout();
602 }
603 
showAlignment(int e)604 void PropertiesPalette_Text::showAlignment(int e)
605 {
606 	if (!m_ScMW || m_ScMW->scriptIsRunning())
607 		return;
608 	bool tmp = m_haveItem;
609 	m_haveItem = false;
610 	textAlignment->setEnabled(true);
611 	textAlignment->setStyle(e, textDirection->getStyle());
612 	m_haveItem = tmp;
613 }
614 
showDirection(int e)615 void PropertiesPalette_Text::showDirection(int e)
616 {
617 	if (!m_ScMW || m_ScMW->scriptIsRunning())
618 		return;
619 	bool tmp = m_haveItem;
620 	m_haveItem = false;
621 	textDirection->setEnabled(true);
622 	textDirection->setStyle(e);
623 	m_haveItem = tmp;
624 }
625 
showCharStyle(const QString & name)626 void PropertiesPalette_Text::showCharStyle(const QString& name)
627 {
628 	if (!m_ScMW || m_ScMW->scriptIsRunning())
629 		return;
630 	bool blocked = charStyleCombo->blockSignals(true);
631 	charStyleCombo->setStyle(name);
632 	charStyleCombo->blockSignals(blocked);
633 }
634 
showParStyle(const QString & name)635 void PropertiesPalette_Text::showParStyle(const QString& name)
636 {
637 	if (!m_ScMW || m_ScMW->scriptIsRunning())
638 		return;
639 	bool blocked = paraStyleCombo->blockSignals(true);
640 	paraStyleCombo->setStyle(name);
641 	paraStyleCombo->blockSignals(blocked);
642 }
643 
handleLineSpacing()644 void PropertiesPalette_Text::handleLineSpacing()
645 {
646 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
647 		return;
648 	Selection tempSelection(this, false);
649 	tempSelection.addItem(m_item, true);
650 	m_doc->itemSelection_SetLineSpacing(lineSpacing->value(), &tempSelection);
651 }
652 
handleFontSize()653 void PropertiesPalette_Text::handleFontSize()
654 {
655 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
656 		return;
657 	Selection tempSelection(this, false);
658 	tempSelection.addItem(m_item, true);
659 	m_doc->itemSelection_SetFontSize(qRound(fontSize->value()*10.0), &tempSelection);
660 }
661 
handleAlignment(int a)662 void PropertiesPalette_Text::handleAlignment(int a)
663 {
664 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
665 		return;
666 	Selection tempSelection(this, false);
667 	tempSelection.addItem(m_item, true);
668 	m_doc->itemSelection_SetAlignment(a, &tempSelection);
669 	if (m_item->isPathText())
670 		pathTextWidgets->handleSelectionChanged();
671 }
672 
handleDirection(int d)673 void PropertiesPalette_Text::handleDirection(int d)
674 {
675 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
676 		return;
677 	Selection tempSelection(this, false);
678 	tempSelection.addItem(m_item, true);
679 	m_doc->itemSelection_SetDirection(d, &tempSelection);
680 	// If current text alignment is left or right, change it to match direction
681 	if (d == ParagraphStyle::RTL && textAlignment->selectedId() == ParagraphStyle::LeftAligned)
682 	{
683 		m_doc->itemSelection_SetAlignment(ParagraphStyle::RightAligned, &tempSelection);
684 		textAlignment->setTypeStyle(ParagraphStyle::RightAligned);
685 	}
686 	else if (d == ParagraphStyle::LTR && textAlignment->selectedId() == ParagraphStyle::RightAligned)
687 	{
688 		m_doc->itemSelection_SetAlignment(ParagraphStyle::LeftAligned, &tempSelection);
689 		textAlignment->setTypeStyle(ParagraphStyle::LeftAligned);
690 	}
691 }
692 
handleTextFont(const QString & font)693 void PropertiesPalette_Text::handleTextFont(const QString& font)
694 {
695 	if (!m_haveDoc || !m_haveItem || !m_ScMW || m_ScMW->scriptIsRunning())
696 		return;
697 	Selection tempSelection(this, false);
698 	tempSelection.addItem(m_item, true);
699 	m_doc->itemSelection_SetFont(font, &tempSelection);
700 }
701 
doClearCStyle()702 void PropertiesPalette_Text::doClearCStyle()
703 {
704 	if (!m_ScMW || m_ScMW->scriptIsRunning() || !m_haveDoc || !m_haveItem)
705 		return;
706 	Selection tempSelection(this, false);
707 	tempSelection.addItem(m_item, true);
708 	m_doc->itemSelection_EraseCharStyle(&tempSelection);
709 }
710 
711 
doClearPStyle()712 void PropertiesPalette_Text::doClearPStyle()
713 {
714 	if (!m_ScMW || m_ScMW->scriptIsRunning() || !m_haveDoc || !m_haveItem)
715 		return;
716 
717 	UndoTransaction activeTransaction;
718 	if (UndoManager::undoEnabled())
719 		activeTransaction = UndoManager::instance()->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::RemoveTextStyle, tr( "remove direct paragraph formatting" ), Um::IFont);
720 
721 	Selection tempSelection(this, false);
722 	tempSelection.addItem(m_item, true);
723 	m_doc->itemSelection_ClearBulNumStrings(&tempSelection);
724 	m_doc->itemSelection_EraseParagraphStyle(&tempSelection);
725 	CharStyle emptyCStyle;
726 	m_doc->itemSelection_SetCharStyle(emptyCStyle, &tempSelection);
727 
728 	if (activeTransaction)
729 		activeTransaction.commit();
730 }
731 
updateColorList()732 void PropertiesPalette_Text::updateColorList()
733 {
734 	if (!m_haveDoc || !m_ScMW || m_ScMW->scriptIsRunning())
735 		return;
736 
737 	colorWidgets->updateColorList();
738 }
739 
changeEvent(QEvent * e)740 void PropertiesPalette_Text::changeEvent(QEvent *e)
741 {
742 	if (e->type() == QEvent::LanguageChange)
743 	{
744 		languageChange();
745 		return;
746 	}
747 	QWidget::changeEvent(e);
748 }
749 
languageChange()750 void PropertiesPalette_Text::languageChange()
751 {
752 	retranslateUi(this);
753 
754 	textTree->setItemText(colorWidgetsItem, tr("Color && Effects"));
755 	textTree->setItemText(flopItem, tr("First Line Offset"));
756 	textTree->setItemText(hyphenationWidgetItem, tr("Hyphenation"));
757 	textTree->setItemText(orphanItem, tr("Orphans and Widows"));
758 	textTree->setItemText(parEffectItem, tr("Paragraph Effects"));
759 	textTree->setItemText(distanceItem, tr("Columns && Text Distances"));
760 	textTree->setItemText(optMarginsItem, tr("Optical Margins"));
761 	textTree->setItemText(advancedWidgetsItem, tr("Advanced Settings"));
762 	textTree->setItemText(fontfeaturesWidgetItem, tr("Font Features"));
763 	textTree->setItemText(pathTextItem, tr("Path Text Properties"));
764 
765 	QSignalBlocker lineSpacingModeBlocker(lineSpacingModeCombo);
766 	int oldLineSpacingMode = lineSpacingModeCombo->currentIndex();
767 	lineSpacingModeCombo->clear();
768 	lineSpacingModeCombo->addItem( tr("Fixed Linespacing"));
769 	lineSpacingModeCombo->addItem( tr("Automatic Linespacing"));
770 	lineSpacingModeCombo->addItem( tr("Align to Baseline Grid"));
771 	lineSpacingModeCombo->setCurrentIndex(oldLineSpacingMode);
772 
773 	QSignalBlocker langComboBlocker(langCombo);
774 	QStringList languageList;
775 	LanguageManager::instance()->fillInstalledStringList(&languageList);
776 	int oldLang = langCombo->currentIndex();
777 	langCombo->clear();
778 	langCombo->addItems(languageList);
779 	langCombo->setCurrentIndex(oldLang);
780 
781 	colorWidgets->languageChange();
782 	flopBox->languageChange();
783 	orphanBox->languageChange();
784 	distanceWidgets->languageChange();
785 	optMargins->languageChange();
786 	advancedWidgets->languageChange();
787 	pathTextWidgets->languageChange();
788 	fontfeaturesWidget->languageChange();
789 	hyphenationWidget->languageChange();
790 
791 	textAlignment->languageChange();
792 	textDirection->languageChange();
793 }
794 
handleFirstLinePolicy(int radioFlop)795 void PropertiesPalette_Text::handleFirstLinePolicy(int radioFlop)
796 {
797 	if (!m_ScMW || m_ScMW->scriptIsRunning() || !m_haveDoc || !m_haveItem)
798 		return;
799 	if( radioFlop == PropertyWidget_Flop::RealHeightID)
800 		m_item->setFirstLineOffset(FLOPRealGlyphHeight);
801 	else if( radioFlop == PropertyWidget_Flop::FontAscentID)
802 		m_item->setFirstLineOffset(FLOPFontAscent);
803 	else if( radioFlop == PropertyWidget_Flop::LineSpacingID)
804 		m_item->setFirstLineOffset(FLOPLineSpacing);
805 	else if( radioFlop == PropertyWidget_Flop::BaselineGridID)
806 		m_item->setFirstLineOffset(FLOPBaselineGrid);
807 	m_item->update();
808 	if (m_doc->appMode == modeEditTable)
809 		m_item->parentTable()->update();
810 	else
811 		m_item->update();
812 	m_doc->regionsChanged()->update(QRect());
813 }
814