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                           scribusdoc.cpp  -  description
9                              -------------------
10     begin                : Fre Apr  6 21:47:55 CEST 2001
11     copyright            : (C) 2001 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13  ***************************************************************************/
14 
15 /***************************************************************************
16  *                                                                         *
17  *   This program is free software; you can redistribute it and/or modify  *
18  *   it under the terms of the GNU General Public License as published by  *
19  *   the Free Software Foundation; either version 2 of the License, or     *
20  *   (at your option) any later version.                                   *
21  *                                                                         *
22  ***************************************************************************/
23 
24 #include <cstdlib>
25 #include <memory>
26 #include <utility>
27 #include <sstream>
28 
29 #include <QByteArray>
30 #include <QDebug>
31 #include <QDialog>
32 #include <QEventLoop>
33 #include <QFile>
34 #include <QList>
35 #include <QMessageBox>
36 #include <QPainter>
37 #include <QPixmap>
38 #include <QPointer>
39 #include <QProgressBar>
40 #include <QRandomGenerator>
41 #include <QRegExp>
42 #include <QtAlgorithms>
43 #include <QTime>
44 #include <QTransform>
45 //#include <qtconcurrentmap.h>
46 
47 #include "actionmanager.h"
48 #include "text/boxes.h"
49 #include "canvas.h"
50 #include "colorblind.h"
51 #include "colormgmt/sccolormgmtenginefactory.h"
52 #include "commonstrings.h"
53 #include "desaxe/digester.h"
54 #include "fileloader.h"
55 #include "filewatcher.h"
56 #include "fpoint.h"
57 #include "hyphenator.h"
58 #include "langmgr.h"
59 #include "notesstyles.h"
60 #include "numeration.h"
61 #include "pageitem.h"
62 #include "pageitemiterator.h"
63 #include "pageitem_imageframe.h"
64 #include "pageitem_latexframe.h"
65 #include "pageitem_line.h"
66 #include "pageitem_noteframe.h"
67 #include "pageitem_pathtext.h"
68 #include "pageitem_polygon.h"
69 #include "pageitem_polyline.h"
70 #include "pageitem_table.h"
71 #include "pageitem_textframe.h"
72 #ifdef HAVE_OSG
73 	#include "pageitem_osgframe.h"
74 #endif
75 #include "pageitem_arc.h"
76 #include "pageitem_group.h"
77 #include "pageitem_regularpolygon.h"
78 #include "pageitem_spiral.h"
79 #include "pageitem_symbol.h"
80 #include "pagesize.h"
81 #include "pagestructs.h"
82 #include "pdfwriter.h"
83 #include "prefsfile.h"
84 #include "prefsmanager.h"
85 #include "resourcecollection.h"
86 #include "scclocale.h"
87 #include "sccolorengine.h"
88 #include "sclimits.h"
89 #include "scpage.h"
90 #include "scpainter.h"
91 #include "scraction.h"
92 #include "scribusXml.h"
93 #include "scribuscore.h"
94 #include "scribusdoc.h"
95 #include "scribusview.h"
96 #include "scribuswin.h"
97 #include "selection.h"
98 #include "serializer.h"
99 #include "tableborder.h"
100 #include "text/textlayoutpainter.h"
101 #include "text/textshaper.h"
102 #include "ui/guidemanager.h"
103 #include "ui/hruler.h"
104 #include "ui/inserttablecolumnsdialog.h"
105 #include "ui/inserttablerowsdialog.h"
106 #include "ui/layers.h"
107 #include "ui/mark2item.h"
108 #include "ui/mark2mark.h"
109 #include "ui/markanchor.h"
110 #include "ui/markinsert.h"
111 #include "ui/marksmanager.h"
112 #include "ui/markvariabletext.h"
113 #include "ui/notesstyleseditor.h"
114 #include "ui/outlinepalette.h"
115 #include "ui/pagepalette.h"
116 #include "ui/storyeditor.h"
117 #include "ui/tablecolumnwidthsdialog.h"
118 #include "ui/tablerowheightsdialog.h"
119 #include "undomanager.h"
120 #include "units.h"
121 #include "util.h"
122 #include "util_math.h"
123 #include "util_printer.h"
124 
125 
126 // static const bool FRAMESELECTION_EDITS_DEFAULTSTYLE = false;
127 
128 
129 
130 /**
131  This class forwards change events for pages and pageitems to
132  the region occupied by this page or pageitem.
133  */
134 class DocUpdater : public Observer<ScPage*>, public Observer<PageItem*>
135 {
136 	ScribusDoc* doc;
137 	int  m_updateEnabled;
138 	bool m_docChangeNeeded;
139 public:
DocUpdater(ScribusDoc * d)140 	DocUpdater(ScribusDoc* d) : doc(d), m_updateEnabled(0), m_docChangeNeeded(false) {}
141 
inUpdateSession() const142 	bool inUpdateSession() const
143 	{
144 		return m_updateEnabled > 0;
145 	}
146 
beginUpdate()147 	void beginUpdate()
148 	{
149 		if (m_updateEnabled == 0)
150 			m_docChangeNeeded = false;
151 		++m_updateEnabled;
152 	}
153 
endUpdate()154 	void endUpdate()
155 	{
156 		--m_updateEnabled;
157 		if (m_updateEnabled <= 0)
158 		{
159 			if (m_docChangeNeeded)
160 			{
161 				doc->changed();
162 				m_docChangeNeeded = false;
163 			}
164 		}
165 	}
166 
changed(ScPage * pg,bool)167 	void changed(ScPage* pg, bool /*doLayout*/) override
168 	{
169 		QRectF pagebox(pg->xOffset(), pg->yOffset(), pg->width(), pg->height());
170 		doc->invalidateRegion(pagebox);
171 		doc->regionsChanged()->update(pagebox);
172 		if (m_updateEnabled <= 0)
173 		{
174 			doc->changed();
175 			return;
176 		}
177 		m_docChangeNeeded = true;
178 	}
179 
changed(PageItem * it,bool doLayout)180 	void changed(PageItem* it, bool doLayout) override
181 	{
182 		it->invalidateLayout();
183 		if (doLayout)
184 			it->layout();
185 		double x, y, w, h;
186 		QTransform t = it->getTransform();
187 		w = it->visualWidth();
188 		h = it->visualHeight();
189 		x = -it->visualLineWidth() / 2.0;
190 		y = -it->visualLineWidth() / 2.0;
191 		QRectF upRect = t.mapRect(QRectF(x, y, w, h));
192 		doc->regionsChanged()->update(upRect);
193 		if (m_updateEnabled <= 0)
194 		{
195 			doc->changed();
196 			return;
197 		}
198 		m_docChangeNeeded = true;
199 	}
200 
setDocChangeNeeded(bool changeNeeded=true)201 	void setDocChangeNeeded(bool changeNeeded = true)
202 	{
203 		m_docChangeNeeded = changeNeeded;
204 	}
205 };
206 
207 
208 
209 
ScribusDoc()210 ScribusDoc::ScribusDoc() : UndoObject( tr("Document")), Observable<ScribusDoc>(nullptr),
211 	m_appPrefsData(PrefsManager::instance().appPrefs),
212 	m_docPrefsData(PrefsManager::instance().appPrefs),
213 	m_undoManager(UndoManager::instance()),
214 	m_automaticTextFrames(false),
215 	m_guardedObject(this),
216 	m_documentFileName( tr("Document") + "-"),
217 	minCanvasCoordinate(FPoint(0, 0)),
218 	m_Selection(new Selection(this, true)),
219 	PageSp(1), PageSpa(0),
220 	FirstPnum(1),
221 	PageColors(this, true),
222 	AllFonts(&m_appPrefsData.fontPrefs.AvailFonts),
223 	colorEngine(ScCore->defaultEngine),
224 	autoSaveTimer(new QTimer(this)),
225 	m_itemCreationTransaction(nullptr),
226 	m_alignTransaction(nullptr)
227 {
228 	m_docUnitRatio = unitGetRatioFromIndex(m_docPrefsData.docSetupPrefs.docUnitIndex);
229 	m_docPrefsData.docSetupPrefs.pageHeight = 0;
230 	m_docPrefsData.docSetupPrefs.pageWidth = 0;
231 	m_docPrefsData.docSetupPrefs.pagePositioning = 0;
232 	maxCanvasCoordinate = FPoint(m_docPrefsData.displayPrefs.scratch.left() + m_docPrefsData.displayPrefs.scratch.right(), m_docPrefsData.displayPrefs.scratch.top() + m_docPrefsData.displayPrefs.scratch.bottom());
233 	init();
234 	//create default numeration
235 	auto* numS = new NumStruct;
236 	numS->m_name = "default";
237 	Numeration newNum;
238 	newNum.suffix = ".";
239 	numS->m_nums.insert(0, newNum);
240 	numS->m_counters.insert(0, 0);
241 	numS->m_lastlevel = -1;
242 	numerations.insert("default", numS);
243 }
244 
245 
ScribusDoc(const QString & docName,int unitindex,const PageSize & pagesize,const MarginStruct & margins,const DocPagesSetup & pagesSetup)246 ScribusDoc::ScribusDoc(const QString& docName, int unitindex, const PageSize& pagesize, const MarginStruct& margins, const DocPagesSetup& pagesSetup) : UndoObject( tr("Document")),
247 	m_appPrefsData(PrefsManager::instance().appPrefs),
248 	m_docPrefsData(PrefsManager::instance().appPrefs),
249 	m_undoManager(UndoManager::instance()),
250 	m_docUnitRatio(unitGetRatioFromIndex(m_appPrefsData.docSetupPrefs.docUnitIndex)),
251 	m_automaticTextFrames(pagesSetup.autoTextFrames),
252 	m_guardedObject(this),
253 	m_documentFileName(docName),
254 	minCanvasCoordinate(FPoint(0, 0)),
255 	m_Selection(new Selection(this, true)),
256 	PageSp(pagesSetup.columnCount), PageSpa(pagesSetup.columnDistance),
257 	FirstPnum(pagesSetup.firstPageNumber),
258 	PageColors(this, true),
259 	AllFonts(&m_appPrefsData.fontPrefs.AvailFonts),
260 	colorEngine(ScCore->defaultEngine),
261 	autoSaveTimer(new QTimer(this)),
262 	m_itemCreationTransaction(nullptr),
263 	m_alignTransaction(nullptr)
264 {
265 	m_docPrefsData.docSetupPrefs.docUnitIndex = unitindex;
266 	m_docPrefsData.docSetupPrefs.pageHeight = pagesize.height();
267 	m_docPrefsData.docSetupPrefs.pageWidth = pagesize.width();
268 	m_docPrefsData.docSetupPrefs.pageSize = pagesize.name();
269 	m_docPrefsData.docSetupPrefs.margins = margins;
270 	maxCanvasCoordinate = FPoint(m_docPrefsData.displayPrefs.scratch.left() + m_docPrefsData.displayPrefs.scratch.right(), m_docPrefsData.displayPrefs.scratch.top() + m_docPrefsData.displayPrefs.scratch.bottom());
271 	setPageSetFirstPage(pagesSetup.pageArrangement, pagesSetup.firstPageLocation);
272 	init();
273 	m_docPrefsData.docSetupPrefs.pageOrientation = pagesSetup.orientation;
274 	m_docPrefsData.docSetupPrefs.pagePositioning = pagesSetup.pageArrangement;
275 }
276 
277 
init()278 void ScribusDoc::init()
279 {
280 	Q_CHECK_PTR(m_Selection);
281 	Q_CHECK_PTR(autoSaveTimer);
282 
283 	m_docPrefsData.colorPrefs.DCMSset.CMSinUse = false;
284 
285 	colorEngine = ScCore->defaultEngine;
286 	SetDefaultCMSParams();
287 
288 	// init update change management
289 	setUpdateManager(&m_updateManager);
290 	m_itemsChanged.setUpdateManager(&m_updateManager);
291 	m_pagesChanged.setUpdateManager(&m_updateManager);
292 	m_regionsChanged.setUpdateManager(&m_updateManager);
293 	nodeEdit.setUpdateManager(&m_updateManager);
294 
295 	// setup update() event chains
296 	m_docUpdater = new DocUpdater(this);
297 	m_itemsChanged.connectObserver(m_docUpdater);
298 	m_pagesChanged.connectObserver(m_docUpdater);
299 
300 	PrefsManager& prefsManager = PrefsManager::instance();
301 	m_docPrefsData.colorPrefs.DCMSset = prefsManager.appPrefs.colorPrefs.DCMSset;
302 
303 	Print_Options.firstUse = true;
304 	PrinterUtil::getDefaultPrintOptions(Print_Options, m_docPrefsData.docSetupPrefs.bleeds);
305 	Print_Options.bleeds = m_docPrefsData.docSetupPrefs.bleeds;
306 	Print_Options.useDocBleeds = true;
307 
308 	m_docPrefsData.pdfPrefs.firstUse = true;
309 	m_docPrefsData.pdfPrefs.Version = m_appPrefsData.pdfPrefs.Version;
310 	m_docPrefsData.pdfPrefs.SolidProf = m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile;
311 	m_docPrefsData.pdfPrefs.ImageProf = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
312 	m_docPrefsData.pdfPrefs.PrintProf = m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile;
313 	m_docPrefsData.pdfPrefs.Intent  = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
314 	m_docPrefsData.pdfPrefs.Intent2 = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
315 	m_docPrefsData.pdfPrefs.useDocBleeds = true;
316 	m_docPrefsData.pdfPrefs.bleeds = m_docPrefsData.docSetupPrefs.bleeds;
317 
318 	AddFont(m_appPrefsData.itemToolPrefs.textFont);//, prefsData.AvailFonts[prefsData.itemToolPrefs.textFont]->Font);
319 	//FIXME: aren't we doing this now anyway with prefs struct copy?
320 	m_docPrefsData.itemToolPrefs.textFont = m_appPrefsData.itemToolPrefs.textFont;
321 	m_docPrefsData.itemToolPrefs.textSize = m_appPrefsData.itemToolPrefs.textSize;
322 	m_docPrefsData.itemToolPrefs.textTabFillChar = m_appPrefsData.itemToolPrefs.textTabFillChar;
323 	m_docPrefsData.opToolPrefs.dispX = m_appPrefsData.opToolPrefs.dispX;
324 	m_docPrefsData.opToolPrefs.dispY = m_appPrefsData.opToolPrefs.dispY;
325 	m_docPrefsData.opToolPrefs.constrain = m_appPrefsData.opToolPrefs.constrain;
326 
327 	PageColors.ensureDefaultColors();
328 	if (m_appPrefsData.itemToolPrefs.shapeLineColor != CommonStrings::None)
329 		PageColors.insert(m_appPrefsData.itemToolPrefs.shapeLineColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.shapeLineColor]);
330 	m_docPrefsData.itemToolPrefs.shapeLineColor = m_appPrefsData.itemToolPrefs.shapeLineColor;
331 	if (m_appPrefsData.itemToolPrefs.lineColor != CommonStrings::None)
332 		PageColors.insert(m_appPrefsData.itemToolPrefs.lineColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.lineColor]);
333 	m_docPrefsData.itemToolPrefs.lineColor = m_appPrefsData.itemToolPrefs.lineColor;
334 	if (m_appPrefsData.itemToolPrefs.textColor != CommonStrings::None)
335 		PageColors.insert(m_appPrefsData.itemToolPrefs.textColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.textColor]);
336 	m_docPrefsData.itemToolPrefs.textColor = m_appPrefsData.itemToolPrefs.textColor;
337 	if (m_appPrefsData.itemToolPrefs.textStrokeColor != CommonStrings::None)
338 		PageColors.insert(m_appPrefsData.itemToolPrefs.textStrokeColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.textStrokeColor]);
339 	m_docPrefsData.itemToolPrefs.textStrokeColor = m_appPrefsData.itemToolPrefs.textStrokeColor;
340 	if (m_appPrefsData.itemToolPrefs.shapeFillColor != CommonStrings::None)
341 		PageColors.insert(m_appPrefsData.itemToolPrefs.shapeFillColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.shapeFillColor]);
342 	m_docPrefsData.itemToolPrefs.shapeFillColor = m_appPrefsData.itemToolPrefs.shapeFillColor;
343 	if (m_appPrefsData.itemToolPrefs.imageFillColor != CommonStrings::None)
344 		PageColors.insert(m_appPrefsData.itemToolPrefs.imageFillColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.imageFillColor]);
345 	m_docPrefsData.itemToolPrefs.imageFillColor = m_appPrefsData.itemToolPrefs.imageFillColor;
346 	if (m_appPrefsData.itemToolPrefs.imageStrokeColor != CommonStrings::None)
347 		PageColors.insert(m_appPrefsData.itemToolPrefs.imageStrokeColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.imageStrokeColor]);
348 	m_docPrefsData.itemToolPrefs.imageStrokeColor = m_appPrefsData.itemToolPrefs.imageStrokeColor;
349 	if (m_appPrefsData.itemToolPrefs.textFillColor != CommonStrings::None)
350 		PageColors.insert(m_appPrefsData.itemToolPrefs.textFillColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.textFillColor]);
351 	m_docPrefsData.itemToolPrefs.textFillColor = m_appPrefsData.itemToolPrefs.textFillColor;
352 	if (m_appPrefsData.itemToolPrefs.textLineColor != CommonStrings::None)
353 		PageColors.insert(m_appPrefsData.itemToolPrefs.textLineColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.textLineColor]);
354 	if (m_appPrefsData.itemToolPrefs.calligraphicPenFillColor != CommonStrings::None)
355 		PageColors.insert(m_appPrefsData.itemToolPrefs.calligraphicPenFillColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.calligraphicPenFillColor]);
356 	if (m_appPrefsData.itemToolPrefs.calligraphicPenLineColor != CommonStrings::None)
357 		PageColors.insert(m_appPrefsData.itemToolPrefs.calligraphicPenLineColor, m_appPrefsData.colorPrefs.DColors[m_appPrefsData.itemToolPrefs.calligraphicPenLineColor]);
358 
359 	ParagraphStyle pstyle;
360 	pstyle.setDefaultStyle(true);
361 	pstyle.setName(CommonStrings::DefaultParagraphStyle);
362 	pstyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
363 	pstyle.setLineSpacing(15);
364 	pstyle.setAlignment(ParagraphStyle::LeftAligned);
365 	pstyle.setDirection(ParagraphStyle::LTR);
366 	pstyle.setLeftMargin(0);
367 	pstyle.setFirstIndent(0);
368 	pstyle.setRightMargin(0);
369 	pstyle.setGapBefore(0);
370 	pstyle.setGapAfter(0);
371 	pstyle.setHasDropCap(false);
372 	pstyle.setHasBullet(false);
373 	pstyle.setHasNum(false);
374 	pstyle.setHyphenConsecutiveLines(2);
375 	pstyle.setDropCapLines(2);
376 	pstyle.setParEffectOffset(0);
377 	pstyle.setBackgroundColor(CommonStrings::None);
378 	pstyle.setBackgroundShade(100);
379 	pstyle.charStyle().setParent("");
380 
381 	CharStyle cstyle;
382 	cstyle.setDefaultStyle(true);
383 	cstyle.setName(CommonStrings::DefaultCharacterStyle);
384 	cstyle.setFont(m_appPrefsData.fontPrefs.AvailFonts[m_docPrefsData.itemToolPrefs.textFont]);
385 	cstyle.setFontSize(m_docPrefsData.itemToolPrefs.textSize);
386 	cstyle.setFontFeatures("");
387 	cstyle.setFeatures(QStringList(CharStyle::INHERIT));
388 	cstyle.setHyphenWordMin(3);
389 	cstyle.setFillColor(m_docPrefsData.itemToolPrefs.textColor);
390 	cstyle.setFillShade(m_docPrefsData.itemToolPrefs.textShade);
391 	cstyle.setStrokeColor(m_docPrefsData.itemToolPrefs.textStrokeColor);
392 	cstyle.setStrokeShade(m_docPrefsData.itemToolPrefs.textStrokeShade);
393 	cstyle.setBackColor(CommonStrings::None);
394 	cstyle.setBackShade(100);
395 	cstyle.setBaselineOffset(0);
396 	cstyle.setShadowXOffset(50);
397 	cstyle.setShadowYOffset(-50);
398 	cstyle.setOutlineWidth(10);
399 	cstyle.setUnderlineOffset(m_docPrefsData.typoPrefs.valueUnderlinePos);
400 	cstyle.setUnderlineWidth(m_docPrefsData.typoPrefs.valueUnderlineWidth);
401 	cstyle.setStrikethruOffset(m_docPrefsData.typoPrefs.valueStrikeThruPos);
402 	cstyle.setStrikethruWidth(m_docPrefsData.typoPrefs.valueStrikeThruPos);
403 	cstyle.setScaleH(1000);
404 	cstyle.setScaleV(1000);
405 	cstyle.setTracking(0);
406 	cstyle.setLanguage(PrefsManager::instance().appPrefs.docSetupPrefs.language);
407 
408 	m_docParagraphStyles.create(pstyle);
409 	m_docParagraphStyles.makeDefault( &(m_docParagraphStyles[0]) );
410 
411 	m_docCharStyles.create(cstyle);
412 	m_docCharStyles.makeDefault( &(m_docCharStyles[0]) );
413 
414 	m_docParagraphStyles[0].breakImplicitCharStyleInheritance();
415 	m_docParagraphStyles[0].charStyle().setContext( & m_docCharStyles );
416 //	docParagraphStyles[0].charStyle().setName( "cdocdefault" ); // DON'T TRANSLATE
417 
418 	currentStyle = pstyle;
419 
420 	// Create default table style.
421 	// TODO: We should have preferences for the default values.
422 	TableStyle defaultTableStyle;
423 	defaultTableStyle.setDefaultStyle(true);
424 	defaultTableStyle.setName(CommonStrings::DefaultTableStyle);
425 	defaultTableStyle.setFillColor(CommonStrings::None);
426 	defaultTableStyle.setFillShade(100);
427 	defaultTableStyle.setLeftBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
428 	defaultTableStyle.setRightBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
429 	defaultTableStyle.setTopBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
430 	defaultTableStyle.setBottomBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
431 	m_docTableStyles.create(defaultTableStyle);
432 	m_docTableStyles.makeDefault(&(m_docTableStyles[0]));
433 
434 	// Create default table cell style.
435 	// TODO: We should have preferences for the default values.
436 	CellStyle defaultCellStyle;
437 	defaultCellStyle.setDefaultStyle(true);
438 	defaultCellStyle.setName(CommonStrings::DefaultCellStyle);
439 	defaultCellStyle.setFillColor(CommonStrings::None);
440 	defaultCellStyle.setFillShade(100);
441 	defaultCellStyle.setLeftBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
442 	defaultCellStyle.setRightBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
443 	defaultCellStyle.setTopBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
444 	defaultCellStyle.setBottomBorder(TableBorder(1.0, Qt::SolidLine, "Black", 100));
445 	defaultCellStyle.setLeftPadding(1.0);
446 	defaultCellStyle.setRightPadding(1.0);
447 	defaultCellStyle.setTopPadding(1.0);
448 	defaultCellStyle.setBottomPadding(1.0);
449 	m_docCellStyles.create(defaultCellStyle);
450 	m_docCellStyles.makeDefault(&(m_docCellStyles[0]));
451 
452 	Layers.addLayer( tr("Background") );
453 	// FIXME: Check PDF version input
454 	//TODO: Check if this is needed now we ue appPrefsData --> docPrefsData
455 	docPatterns.clear();
456 	docGradients.clear();
457 
458 	if (autoSave() && ScCore->usingGUI())
459 		autoSaveTimer->start(autoSaveTime());
460 	//Do this after all the collections have been created and cleared!
461 	m_masterPageMode = true; // quick hack to force the change of pointers in setMasterPageMode();
462 	setMasterPageMode(false);
463 	addSymbols();
464 	//for loading old documents where default notes style is not saved
465 	if (m_docNotesStylesList.isEmpty())
466 		m_docNotesStylesList.append(new NotesStyle());
467 }
468 
469 
~ScribusDoc()470 ScribusDoc::~ScribusDoc()
471 {
472 	m_guardedObject.nullify();
473 	CloseCMSProfiles();
474 	ScCore->fileWatcher->stop();
475 	ScCore->fileWatcher->removeFile(m_documentFileName);
476 	QList<PageItem*> allItems;
477 	for (int i = 0; i < DocItems.count(); ++i)
478 	{
479 		PageItem *currItem = DocItems.at(i);
480 		if (currItem->isGroup())
481 			allItems = currItem->getAllChildren();
482 		else
483 			allItems.append(currItem);
484 		for (int j = 0; j < allItems.count(); j++)
485 		{
486 			currItem = allItems.at(j);
487 			if (currItem->imageIsAvailable)
488 				ScCore->fileWatcher->removeFile(currItem->Pfile);
489 			if ((currItem->isImageFrame()) && (!currItem->Pfile.isEmpty()))
490 			{
491 				QFileInfo fi(currItem->Pfile);
492 				ScCore->fileWatcher->removeDir(fi.absolutePath());
493 			}
494 		}
495 		allItems.clear();
496 	}
497 	for (int i = 0; i < MasterItems.count(); ++i)
498 	{
499 		PageItem *currItem = MasterItems.at(i);
500 		if (currItem->isGroup())
501 			allItems = currItem->getAllChildren();
502 		else
503 			allItems.append(currItem);
504 		for (int j = 0; j < allItems.count(); j++)
505 		{
506 			currItem = allItems.at(j);
507 			if (currItem->imageIsAvailable)
508 				ScCore->fileWatcher->removeFile(currItem->Pfile);
509 			if ((currItem->isImageFrame()) && (!currItem->Pfile.isEmpty()))
510 			{
511 				QFileInfo fi(currItem->Pfile);
512 				ScCore->fileWatcher->removeDir(fi.absolutePath());
513 			}
514 		}
515 		allItems.clear();
516 	}
517 	for (auto itf = FrameItems.begin(); itf != FrameItems.end(); ++itf)
518 	{
519 		PageItem *currItem = itf.value();
520 		if (currItem->isGroup())
521 			allItems = currItem->getAllChildren();
522 		else
523 			allItems.append(currItem);
524 		for (int ii = 0; ii < allItems.count(); ii++)
525 		{
526 			currItem = allItems.at(ii);
527 			if (currItem->imageIsAvailable)
528 				ScCore->fileWatcher->removeFile(currItem->Pfile);
529 			if ((currItem->isImageFrame()) && (!currItem->Pfile.isEmpty()))
530 			{
531 				QFileInfo fi(currItem->Pfile);
532 				ScCore->fileWatcher->removeDir(fi.absolutePath());
533 			}
534 		}
535 		allItems.clear();
536 	}
537 	auto patternEnd = docPatterns.end();
538 	for (auto it = docPatterns.begin(); it != patternEnd; ++it)
539 	{
540 		ScPattern& pa = it.value();
541 		for (int j = 0; j < pa.items.count(); j++)
542 		{
543 			PageItem *currItem = pa.items.at(j);
544 			if (currItem->isGroup())
545 				allItems = currItem->getAllChildren();
546 			else
547 				allItems.append(currItem);
548 			for (int k = 0; k < allItems.count(); k++)
549 			{
550 				currItem = allItems.at(k);
551 				if (currItem->itemType() == PageItem::ImageFrame)
552 				{
553 					if ((currItem->imageIsAvailable) && (!currItem->Pfile.isEmpty()))
554 					{
555 						ScCore->fileWatcher->removeFile(currItem->Pfile);
556 						QFileInfo fi(currItem->Pfile);
557 						ScCore->fileWatcher->removeDir(fi.absolutePath());
558 					}
559 				}
560 			}
561 			allItems.clear();
562 		}
563 		while (!pa.items.isEmpty())
564 		{
565 			delete pa.items.takeFirst();
566 		}
567 	}
568 	//deleting resources alocated for marks and notes
569 	while (! m_docNotesList.isEmpty())
570 		delete m_docNotesList.takeFirst();
571 	while (!m_docMarksList.isEmpty())
572 		delete m_docMarksList.takeFirst();
573 	while (! m_docNotesStylesList.isEmpty())
574 		delete m_docNotesStylesList.takeFirst();
575 	docPatterns.clear();
576 	docGradients.clear();
577 
578 	for (NumStruct* ns : numerations.values())
579 		delete ns;
580 	numerations.clear();
581 
582 	while (!DocItems.isEmpty())
583 		delete DocItems.takeFirst();
584 
585 	QList<PageItem*> tmList = FrameItems.values();
586 	while (!tmList.isEmpty())
587 		delete tmList.takeFirst();
588 	FrameItems.clear();
589 
590 	while (!MasterPages.isEmpty())
591 		delete MasterPages.takeFirst();
592 
593 	while (!DocPages.isEmpty())
594 		delete DocPages.takeFirst();
595 
596 	while (!MasterItems.isEmpty())
597 		delete MasterItems.takeFirst();
598 
599 	for (auto it3 = UsedFonts.begin(); it3 != UsedFonts.end(); ++it3)
600 	{
601 		if (!(*AllFonts)[it3.key()].localForDocument().isEmpty())
602 			(*AllFonts).removeFont(it3.key());
603 		else
604 			(*AllFonts)[it3.key()].decreaseUsage();
605 	}
606 	delete docHyphenator;
607 	delete m_serializer;
608 	delete m_tserializer;
609 	delete m_docUpdater;
610 	if (!m_docPrefsData.docSetupPrefs.AutoSaveKeep)
611 	{
612 		if (autoSaveFiles.count() != 0)
613 		{
614 			for (int i = 0; i < autoSaveFiles.count(); i++)
615 			{
616 				QFile f(autoSaveFiles[i]);
617 				f.remove();
618 			}
619 			autoSaveFiles.clear();
620 		}
621 	}
622 	ScCore->fileWatcher->start();
623 }
624 
inAnEditMode() const625 bool ScribusDoc::inAnEditMode() const
626 {
627 	return appMode == modeDrawBezierLine ||
628 			appMode == modeEdit ||
629 			appMode == modeEditArc ||
630 			appMode == modeEditClip ||
631 			appMode == modeEditGradientVectors ||
632 			appMode == modeEditMeshGradient ||
633 			appMode == modeEditMeshPatch ||
634 			appMode == modeEditPolygon ||
635 			appMode == modeEditSpiral ||
636 			appMode == modeEditTable ||
637 			appMode == modeEditWeldPoint;
638 }
639 
inASpecialEditMode() const640 bool ScribusDoc::inASpecialEditMode() const
641 { // #12897, modes that use setSpecialEditMode() function in appmodehelper.cpp
642 	return appMode == modeDrawBezierLine ||
643 			appMode == modeEditArc ||
644 			appMode == modeEditGradientVectors ||
645 			appMode == modeEditMeshGradient ||
646 			appMode == modeEditMeshPatch ||
647 			appMode == modeEditPolygon ||
648 			appMode == modeEditSpiral ||
649 			appMode == modeEditWeldPoint;
650 }
651 
getAllItems(QList<PageItem * > & items)652 QList<PageItem*> ScribusDoc::getAllItems(QList<PageItem*> &items)
653 {
654 	QList<PageItem*> ret;
655 	for (int em = 0; em < items.count(); ++em)
656 	{
657 		PageItem* embedded = items.at(em);
658 		ret.append(embedded);
659 		if (embedded->isGroup())
660 			ret += embedded->getAllChildren();
661 	}
662 	return ret;
663 }
664 
parentGroup(PageItem * item,QList<PageItem * > * list)665 QList<PageItem*> *ScribusDoc::parentGroup(PageItem* item, QList<PageItem*> *list)
666 {
667 	QList<PageItem*> *retList = nullptr;
668 	if (list->contains(item))
669 		retList = list;
670 	else
671 	{
672 		for (int i = 0; i < list->count(); ++i)
673 		{
674 			PageItem* embedded = list->at(i);
675 			if (embedded->isGroup())
676 			{
677 				retList = parentGroup(item, &embedded->asGroupFrame()->groupItemList);
678 				if (retList != nullptr)
679 					break;
680 			}
681 		}
682 	}
683 	return retList;
684 }
685 
setup(int unitIndex,int fp,int firstLeft,int orientation,int firstPageNumber,const QString & defaultPageSize,const QString & documentName)686 void ScribusDoc::setup(int unitIndex, int fp, int firstLeft, int orientation, int firstPageNumber, const QString& defaultPageSize, const QString& documentName)
687 {
688 	m_docPrefsData.docSetupPrefs.docUnitIndex=unitIndex;
689 	setPageSetFirstPage(fp, firstLeft);
690 	m_docPrefsData.docSetupPrefs.pageOrientation = orientation;
691 	m_docPrefsData.docSetupPrefs.pageSize = defaultPageSize;
692 	FirstPnum = firstPageNumber;
693 	m_docPrefsData.docSetupPrefs.pagePositioning = fp;
694 	setDocumentFileName(documentName);
695 	HasCMS = false;
696 	if (!pdfOptions().UseLPI)
697 	{
698 		pdfOptions().LPISettings.clear();
699 		struct LPIData lpo;
700 		lpo.Frequency = 133;
701 		lpo.SpotFunc = 3;
702 		lpo.Angle = 105;
703 		pdfOptions().LPISettings.insert("Cyan", lpo);
704 		lpo.Angle = 75;
705 		pdfOptions().LPISettings.insert("Magenta", lpo);
706 		lpo.Angle = 90;
707 		pdfOptions().LPISettings.insert("Yellow", lpo);
708 		lpo.Angle = 45;
709 		pdfOptions().LPISettings.insert("Black", lpo);
710 		m_ActiveLayer = 0;
711 	}
712 
713 	appMode = modeNormal;
714 	PrefsManager& prefsManager=PrefsManager::instance();
715 
716 	m_docPrefsData.colorPrefs.DCMSset = prefsManager.appPrefs.colorPrefs.DCMSset;
717 	m_docPrefsData.pdfPrefs.SolidProf = m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile;
718 	m_docPrefsData.pdfPrefs.ImageProf = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
719 	m_docPrefsData.pdfPrefs.PrintProf = m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile;
720 	m_docPrefsData.pdfPrefs.Intent  = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
721 	m_docPrefsData.pdfPrefs.Intent2 = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
722 	BlackPoint   = m_docPrefsData.colorPrefs.DCMSset.BlackPoint;
723 	SoftProofing = m_docPrefsData.colorPrefs.DCMSset.SoftProofOn;
724 	Gamut        = m_docPrefsData.colorPrefs.DCMSset.GamutCheck;
725 	IntentColors = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
726 	IntentImages = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
727 	if (ScCore->haveCMS() && m_docPrefsData.colorPrefs.DCMSset.CMSinUse)
728 	{
729 		if (OpenCMSProfiles(ScCore->InputProfiles, ScCore->InputProfilesCMYK, ScCore->MonitorProfiles, ScCore->PrinterProfiles))
730 		{
731 			HasCMS = true;
732 			pdfOptions().SComp = m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2;
733 		}
734 		else
735 		{
736 			SetDefaultCMSParams();
737 			HasCMS = false;
738 		}
739 	}
740 }
741 
742 
setGUI(bool hasgui,ScribusMainWindow * mw,ScribusView * view)743 void ScribusDoc::setGUI(bool hasgui, ScribusMainWindow* mw, ScribusView* view)
744 {
745 	m_hasGUI = hasgui;
746 	m_ScMW = mw;
747 	//FIXME: stop using m_View
748 	m_View = view;
749 }
750 
createHyphenator()751 void ScribusDoc::createHyphenator()
752 {
753 	if (m_hasGUI)
754 	{
755 		if (docHyphenator)
756 			return;
757 		docHyphenator = new Hyphenator(m_ScMW, this);
758 		Q_CHECK_PTR(docHyphenator);
759 	}
760 	else
761 		docHyphenator = nullptr;
762 }
763 
764 
setLoading(bool docLoading)765 void ScribusDoc::setLoading(bool docLoading)
766 {
767 	m_loading = docLoading;
768 }
769 
770 
isLoading() const771 bool ScribusDoc::isLoading() const
772 {
773 	return m_loading;
774 }
775 
776 
777 //AV: eeks. That should not be used
view() const778 ScribusView* ScribusDoc::view() const
779 {
780 	return m_View;
781 }
782 
783 
guardedPtr() const784 const ScGuardedPtr<ScribusDoc>& ScribusDoc::guardedPtr() const
785 {
786 	return m_guardedObject;
787 }
788 
789 
CloseCMSProfiles()790 void ScribusDoc::CloseCMSProfiles()
791 {
792 	HasCMS = false;
793 	SetDefaultCMSParams();
794 }
795 
SetDefaultCMSParams()796 void ScribusDoc::SetDefaultCMSParams()
797 {
798 	BlackPoint     = true;
799 	SoftProofing   = false;
800 	Gamut          = false;
801 	IntentColors   = Intent_Relative_Colorimetric;
802 	IntentImages   = Intent_Relative_Colorimetric;
803 	DocInputRGBProf       = ScCore->defaultRGBProfile;
804 	DocInputCMYKProf      = ScCore->defaultCMYKProfile;
805 	DocInputImageRGBProf  = ScCore->defaultRGBProfile;
806 	DocInputImageCMYKProf = ScCore->defaultCMYKProfile;
807 	DocDisplayProf        = ScCore->defaultRGBProfile;
808 	DocPrinterProf        = ScCore->defaultCMYKProfile;
809 	stdTransRGBMon        = ScCore->defaultRGBToScreenSolidTrans;
810 	stdTransCMYKMon       = ScCore->defaultCMYKToRGBTrans;
811 	stdTransRGB           = ScCore->defaultCMYKToRGBTrans;
812 	stdTransCMYK          = ScCore->defaultRGBToCMYKTrans;
813 	stdProof              = ScCore->defaultRGBToScreenSolidTrans;
814 	stdProofGC            = ScCore->defaultRGBToScreenSolidTrans;
815 	stdProofCMYK          = ScCore->defaultCMYKToRGBTrans;
816 	stdProofCMYKGC        = ScCore->defaultCMYKToRGBTrans;
817 	stdTransImg           = ScCore->defaultRGBToScreenImageTrans;
818 	stdProofImg           = ScCore->defaultRGBToScreenImageTrans;
819 	stdProofImgCMYK       = ScCore->defaultCMYKToScreenImageTrans;
820 	stdLabToRGBTrans      = ScCore->defaultLabToRGBTrans;
821 	stdLabToCMYKTrans     = ScCore->defaultLabToCMYKTrans;
822 	stdLabToScreenTrans   = ScCore->defaultLabToScreenTrans;
823 	stdProofLab           = ScCore->defaultLabToRGBTrans;
824 	stdProofLabGC         = ScCore->defaultLabToRGBTrans;
825 }
826 
OpenCMSProfiles(ProfilesL InPo,ProfilesL InPoCMYK,ProfilesL,ProfilesL PrPo)827 bool ScribusDoc::OpenCMSProfiles(ProfilesL InPo, ProfilesL InPoCMYK, ProfilesL  /*MoPo*/, ProfilesL PrPo)
828 {
829 	HasCMS = false;
830 	ScColorProfile inputProf;
831 
832 	colorEngine = colorMgmtEngineFactory.createDefaultEngine();
833 	ScColorMgmtStrategy colorStrategy;
834 	colorStrategy.setUseBlackPointCompensation(m_docPrefsData.colorPrefs.DCMSset.BlackPoint);
835 	colorStrategy.setUseBlackPreservation(false);
836 	colorEngine.setStrategy(colorStrategy);
837 
838 	DocDisplayProf   = ScCore->monitorProfile;
839 	DocInputRGBProf  = colorEngine.openProfileFromFile( InPo[m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile] );
840 	DocInputCMYKProf = colorEngine.openProfileFromFile( InPoCMYK[m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorCMYKProfile] );
841 	DocPrinterProf   = colorEngine.openProfileFromFile( PrPo[m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile] );
842 	DocInputImageRGBProf  = colorEngine.openProfileFromFile( InPo[m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile] );
843 	DocInputImageCMYKProf = colorEngine.openProfileFromFile( InPoCMYK[m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile] );
844 	if ((!DocDisplayProf) || (!DocInputRGBProf) || (!DocInputCMYKProf) || (!DocPrinterProf) || (!DocInputImageCMYKProf) || (!DocInputImageRGBProf))
845 	{
846 		m_docPrefsData.colorPrefs.DCMSset.CMSinUse = false;
847 		return false;
848 	}
849 
850 	int dcmsFlags   = 0;
851 	int dcmsFlagsGC = 0;
852 	if (m_docPrefsData.colorPrefs.DCMSset.GamutCheck)
853 		dcmsFlagsGC |= Ctf_GamutCheck;
854 	if (m_docPrefsData.colorPrefs.DCMSset.BlackPoint)
855 	{
856 		dcmsFlags   |= Ctf_BlackPointCompensation;
857 		dcmsFlagsGC |= Ctf_BlackPointCompensation;
858 	}
859 	stdTransRGBMon  = colorEngine.createTransform(DocInputRGBProf, Format_RGB_16,
860 										DocDisplayProf, Format_RGB_16,
861 										IntentColors, dcmsFlags);
862 	stdTransCMYKMon = colorEngine.createTransform(DocInputCMYKProf, Format_CMYK_16,
863 										DocDisplayProf, Format_RGB_16,
864 										IntentColors, dcmsFlags);
865 	// TODO : check input profiles used for images
866 	stdProofImg = colorEngine.createProofingTransform(DocInputImageRGBProf, Format_BGRA_8,
867 	                  DocDisplayProf, Format_BGRA_8, DocPrinterProf,
868 	                  IntentImages, Intent_Relative_Colorimetric, dcmsFlagsGC);
869 	stdProofImgCMYK = colorEngine.createProofingTransform(DocInputImageCMYKProf, Format_CMYK_8,
870 	                  DocDisplayProf, Format_BGRA_8, DocPrinterProf,
871 	                  IntentImages, Intent_Relative_Colorimetric, dcmsFlagsGC);
872 	stdTransImg = colorEngine.createTransform(DocInputRGBProf, Format_BGRA_8,
873 	                  DocDisplayProf, Format_BGRA_8,
874 					  IntentImages, dcmsFlags);
875 	stdTransRGB = colorEngine.createTransform(DocInputCMYKProf, Format_CMYK_16,
876 					  DocInputRGBProf, Format_RGB_16,
877 					  IntentColors, dcmsFlags);
878 	stdTransCMYK = colorEngine.createTransform(DocInputRGBProf, Format_RGB_16,
879 					  DocInputCMYKProf, Format_CMYK_16,
880 					  IntentColors, dcmsFlags);
881 
882 	ScColorProfile inputProfRGB;
883 	ScColorProfile inputProfCMYK;
884 	if (DocPrinterProf.colorSpace() == ColorSpace_Cmyk)
885 	{
886 		inputProf = (m_docPrefsData.colorPrefs.DCMSset.SoftProofOn && m_docPrefsData.colorPrefs.DCMSset.SoftProofFullOn) ? DocInputCMYKProf : DocPrinterProf;
887 		inputProfRGB  = DocInputRGBProf;
888 		inputProfCMYK = inputProf;
889 	}
890 	else
891 	{
892 		inputProf = (m_docPrefsData.colorPrefs.DCMSset.SoftProofOn && m_docPrefsData.colorPrefs.DCMSset.SoftProofFullOn) ? DocInputRGBProf : DocPrinterProf;
893 		inputProfRGB  = inputProf;
894 		inputProfCMYK = DocInputCMYKProf;
895 	}
896 	stdProof = colorEngine.createProofingTransform(inputProfRGB, Format_RGB_16,
897 						DocDisplayProf, Format_RGB_16,
898 						DocPrinterProf,
899 						IntentColors,
900 						Intent_Relative_Colorimetric, dcmsFlags);
901 	stdProofGC = colorEngine.createProofingTransform(inputProfRGB, Format_RGB_16,
902 						DocDisplayProf, Format_RGB_16,
903 						DocPrinterProf, IntentColors,
904 						Intent_Relative_Colorimetric, dcmsFlags| Ctf_GamutCheck);
905 	stdProofCMYK = colorEngine.createProofingTransform(inputProfCMYK, Format_CMYK_16,
906 						DocDisplayProf, Format_RGB_16,
907 						DocPrinterProf, IntentColors,
908 						Intent_Relative_Colorimetric, dcmsFlags);
909 	stdProofCMYKGC = colorEngine.createProofingTransform(inputProfCMYK, Format_CMYK_16,
910 						DocDisplayProf, Format_RGB_16,
911 						DocPrinterProf,
912 						IntentColors,
913 						Intent_Relative_Colorimetric, dcmsFlags | Ctf_GamutCheck);
914 	stdProofLab = colorEngine.createProofingTransform(ScCore->defaultLabProfile, Format_Lab_Dbl,
915 						DocDisplayProf, Format_RGB_16,
916 						DocPrinterProf,
917 						IntentColors,
918 						Intent_Relative_Colorimetric, dcmsFlags);
919 	stdProofLabGC = colorEngine.createProofingTransform(ScCore->defaultLabProfile, Format_Lab_Dbl,
920 						DocDisplayProf, Format_RGB_16,
921 						DocPrinterProf, IntentColors,
922 						Intent_Relative_Colorimetric, dcmsFlags| Ctf_GamutCheck);
923 
924 	if (DocInputRGBProf.colorSpace() == ColorSpace_Rgb)
925 			m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2 = 3;
926 	if (DocInputRGBProf.colorSpace() == ColorSpace_Cmyk)
927 			m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2 = 4;
928 	if (DocInputRGBProf.colorSpace() == ColorSpace_Cmy)
929 			m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2 = 3;
930 
931 	stdLabToRGBTrans  = colorEngine.createTransform(ScCore->defaultLabProfile, Format_Lab_Dbl, DocInputRGBProf, Format_RGB_16, Intent_Absolute_Colorimetric, dcmsFlags);
932 	stdLabToCMYKTrans = colorEngine.createTransform(ScCore->defaultLabProfile, Format_Lab_Dbl, DocInputCMYKProf, Format_CMYK_16, Intent_Absolute_Colorimetric, dcmsFlags);
933 	stdLabToScreenTrans = colorEngine.createTransform(ScCore->defaultLabProfile, Format_Lab_Dbl, DocDisplayProf, Format_RGB_16, Intent_Absolute_Colorimetric, dcmsFlags);
934 
935 	bool success = (stdTransRGBMon   && stdTransCMYKMon   && stdProofImg    && stdProofImgCMYK &&
936 					stdTransImg      && stdTransRGB       && stdTransCMYK   && stdProof        &&
937 					stdProofGC       && stdProofCMYK      && stdProofCMYKGC &&
938 					stdLabToRGBTrans && stdLabToCMYKTrans && stdLabToScreenTrans && stdProofLab && stdProofLabGC);
939 	if (!success)
940 	{
941 		CloseCMSProfiles();
942 		m_docPrefsData.colorPrefs.DCMSset.CMSinUse = false;
943 		QString message = tr("An error occurred while opening ICC profiles, color management is not enabled." );
944 		ScMessageBox::warning(m_ScMW, CommonStrings::trWarning, message);
945 	}
946 	return true;
947 }
948 
949 
enableCMS(bool enable)950 void ScribusDoc::enableCMS(bool enable)
951 {
952 	m_ScMW->setStatusBarInfoText( tr("Adjusting Colors"));
953 	m_ScMW->mainWindowProgressBar->reset();
954 	int progressBarCount = PageColors.count() + MasterItems.count() + DocItems.count() + FrameItems.count();
955 	m_ScMW->mainWindowProgressBar->setMaximum(progressBarCount);
956 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
957 	bool oldCM = m_docPrefsData.colorPrefs.DCMSset.CMSinUse;
958 	bool newCM = enable;
959 	CloseCMSProfiles();
960 	m_docPrefsData.colorPrefs.DCMSset.CMSinUse = newCM;
961 	HasCMS       = m_docPrefsData.colorPrefs.DCMSset.CMSinUse;
962 	BlackPoint   = m_docPrefsData.colorPrefs.DCMSset.BlackPoint;
963 	SoftProofing = m_docPrefsData.colorPrefs.DCMSset.SoftProofOn;
964 	Gamut        = m_docPrefsData.colorPrefs.DCMSset.GamutCheck;
965 	IntentColors = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
966 	IntentImages = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
967 	if (!m_docPrefsData.colorPrefs.DCMSset.CMSinUse)
968 	{
969 		HasCMS = false;
970 		if (oldCM)
971 		{
972 			m_ScMW->recalcColors();
973 			RecalcPictures(&ScCore->InputProfiles, &ScCore->InputProfilesCMYK, m_ScMW->mainWindowProgressBar);
974 		}
975 	}
976 	else if (OpenCMSProfiles(ScCore->InputProfiles, ScCore->InputProfilesCMYK, ScCore->MonitorProfiles, ScCore->PrinterProfiles) )
977 	{
978 		HasCMS = true;
979 		m_docPrefsData.pdfPrefs.SComp = m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2;
980 		m_docPrefsData.pdfPrefs.SolidProf = m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile;
981 		m_docPrefsData.pdfPrefs.ImageProf = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
982 		m_docPrefsData.pdfPrefs.PrintProf = m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile;
983 		m_docPrefsData.pdfPrefs.Intent  = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
984 		m_docPrefsData.pdfPrefs.Intent2 = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
985 		m_ScMW->recalcColors();
986 		RecalcPictures(&ScCore->InputProfiles, &ScCore->InputProfilesCMYK, m_ScMW->mainWindowProgressBar);
987 	}
988 	else
989 	{
990 		SetDefaultCMSParams();
991 		HasCMS = false;
992 	}
993 	m_ScMW->mainWindowProgressBar->setValue(progressBarCount);
994 	qApp->restoreOverrideCursor();
995 	m_ScMW->setStatusBarInfoText("");
996 	m_ScMW->mainWindowProgressBar->reset();
997 }
998 
999 
getNamedResources(ResourceCollection & lists) const1000 void ScribusDoc::getNamedResources(ResourceCollection& lists) const
1001 {
1002 	lists.availableFonts = AllFonts;
1003 	lists.availableColors = const_cast<ColorList*>(& PageColors);
1004 
1005 	const QList<PageItem*> * itemlist = & MasterItems;
1006 	while (itemlist != nullptr)
1007 	{
1008 		for (int i=0; i < itemlist->count(); ++i)
1009 		{
1010 			const PageItem * currItem = const_cast<QList<PageItem*>*>(itemlist)->at(i);
1011 			if (currItem)
1012 				currItem->getNamedResources(lists);
1013 		}
1014 		if (itemlist == &MasterItems)
1015 			itemlist = &DocItems;
1016 		else
1017 			itemlist = nullptr;
1018 	}
1019 	for (QHash<int, PageItem*>::const_iterator itf = FrameItems.begin(); itf != FrameItems.end(); ++itf)
1020 	{
1021 		PageItem *currItem = itf.value();
1022 		if (currItem)
1023 			currItem->getNamedResources(lists);
1024 	}
1025 	for (int i = 0; i < m_docParagraphStyles.count(); ++i)
1026 		m_docParagraphStyles[i].getNamedResources(lists);
1027 	for (int i = 0; i < m_docCharStyles.count(); ++i)
1028 		m_docCharStyles[i].getNamedResources(lists);
1029 	for (int i = 0; i < m_docTableStyles.count(); ++i)
1030 		m_docTableStyles[i].getNamedResources(lists);
1031 	for (int i = 0; i < m_docCellStyles.count(); ++i)
1032 		m_docCellStyles[i].getNamedResources(lists);
1033 
1034 	QHash<QString,ScPattern>::ConstIterator it;
1035 	for (it = docPatterns.begin(); it != docPatterns.end(); ++it)
1036 	{
1037 		ScPattern pa = *it;
1038 		for (int o = 0; o < pa.items.count(); o++)
1039 		{
1040 			pa.items.at(o)->getNamedResources(lists);
1041 		}
1042 	}
1043 	QHash<QString,VGradient>::ConstIterator itg;
1044 	for (itg = docGradients.begin(); itg != docGradients.end(); ++itg)
1045 	{
1046 		QList<VColorStop*> cstops = itg.value().colorStops();
1047 		for (int cst = 0; cst < itg.value().stops(); ++cst)
1048 		{
1049 			lists.collectColor(cstops.at(cst)->name);
1050 		}
1051 	}
1052 }
1053 
styleExists(const QString & styleName) const1054 bool ScribusDoc::styleExists(const QString& styleName) const
1055 {
1056 	return m_docParagraphStyles.contains(styleName);
1057 }
1058 
charStyleExists(const QString & styleName) const1059 bool ScribusDoc::charStyleExists(const QString& styleName) const
1060 {
1061 	return m_docCharStyles.contains(styleName);
1062 }
1063 
getSortedStyleList()1064 QList<int> ScribusDoc::getSortedStyleList()
1065 {
1066 	QList<int> retList;
1067 	for (int i = 0; i < m_docParagraphStyles.count(); ++i)
1068 	{
1069 		if (m_docParagraphStyles[i].parent().isEmpty())
1070 		{
1071 			if (!retList.contains(i))
1072 				retList.append(i);
1073 			continue;
1074 		}
1075 
1076 		QList<int> retList2;
1077 		QString name = m_docParagraphStyles[i].name();
1078 		QString par  = m_docParagraphStyles[i].parent();
1079 		retList2.prepend(i);
1080 		while ((!par.isEmpty()) && (par != name))
1081 		{
1082 			int pp = m_docParagraphStyles.find(par);
1083 			if ((pp >= 0) && (!retList2.contains(pp)))
1084 				retList2.prepend(pp);
1085 			par = (pp >= 0) ? m_docParagraphStyles[pp].parent() : QString();
1086 		}
1087 		for (int r = 0; r < retList2.count(); ++r)
1088 		{
1089 			if (!retList.contains(retList2[r]))
1090 				retList.append(retList2[r]);
1091 		}
1092 	}
1093 	return retList;
1094 }
1095 
getSortedCharStyleList()1096 QList<int> ScribusDoc::getSortedCharStyleList()
1097 {
1098 	QList<int> retList;
1099 	for (int i = 0; i < m_docCharStyles.count(); ++i)
1100 	{
1101 		if (m_docCharStyles[i].parent().isEmpty())
1102 		{
1103 			if (!retList.contains(i))
1104 				retList.append(i);
1105 			continue;
1106 		}
1107 
1108 		QList<int> retList2;
1109 		QString name = m_docCharStyles[i].name();
1110 		QString par  = m_docCharStyles[i].parent();
1111 		retList2.prepend(i);
1112 		while ((!par.isEmpty()) && (par != name))
1113 		{
1114 			int pp = m_docCharStyles.find(par);
1115 			if ((pp >= 0) && (!retList2.contains(pp)))
1116 				retList2.prepend(pp);
1117 			par = (pp >= 0) ? m_docCharStyles[pp].parent() : QString();
1118 		}
1119 		for (int r = 0; r < retList2.count(); ++r)
1120 		{
1121 			if (!retList.contains(retList2[r]))
1122 				retList.append(retList2[r]);
1123 		}
1124 	}
1125 	return retList;
1126 }
1127 
getSortedTableStyleList()1128 QList<int> ScribusDoc::getSortedTableStyleList()
1129 {
1130 	QList<int> retList;
1131 	for (int i = 0; i < m_docTableStyles.count(); ++i)
1132 	{
1133 		if (m_docTableStyles[i].parent().isEmpty())
1134 		{
1135 			if (!retList.contains(i))
1136 				retList.append(i);
1137 			continue;
1138 		}
1139 
1140 		QList<int> retList2;
1141 		QString name = m_docTableStyles[i].name();
1142 		QString par  = m_docTableStyles[i].parent();
1143 		retList2.prepend(i);
1144 		while ((!par.isEmpty()) && (par != name))
1145 		{
1146 			int pp = m_docTableStyles.find(par);
1147 			if ((pp >= 0) && (!retList2.contains(pp)))
1148 				retList2.prepend(pp);
1149 			par = (pp >= 0) ? m_docTableStyles[pp].parent() : QString();
1150 		}
1151 		for (int r = 0; r < retList2.count(); ++r)
1152 		{
1153 			if (!retList.contains(retList2[r]))
1154 				retList.append(retList2[r]);
1155 		}
1156 	}
1157 	return retList;
1158 }
1159 
getSortedCellStyleList()1160 QList<int> ScribusDoc::getSortedCellStyleList()
1161 {
1162 	QList<int> retList;
1163 	for (int i = 0; i < m_docCellStyles.count(); ++i)
1164 	{
1165 		if (m_docCellStyles[i].parent().isEmpty())
1166 		{
1167 			if (!retList.contains(i))
1168 				retList.append(i);
1169 			continue;
1170 		}
1171 
1172 		QList<int> retList2;
1173 		QString name = m_docCellStyles[i].name();
1174 		QString par  = m_docCellStyles[i].parent();
1175 		retList2.prepend(i);
1176 		while ((!par.isEmpty()) && (par != name))
1177 		{
1178 			int pp = m_docCellStyles.find(par);
1179 			if ((pp >= 0) && (!retList2.contains(pp)))
1180 				retList2.prepend(pp);
1181 			par = (pp >= 0) ? m_docCellStyles[pp].parent() : QString();
1182 		}
1183 		for (int r = 0; r < retList2.count(); ++r)
1184 		{
1185 			if (!retList.contains(retList2[r]))
1186 				retList.append(retList2[r]);
1187 		}
1188 	}
1189 	return retList;
1190 }
1191 
replaceStyles(const QMap<QString,QString> & newNameForOld)1192 void ScribusDoc::replaceStyles(const QMap<QString,QString>& newNameForOld)
1193 {
1194 	ResourceCollection newNames;
1195 	newNames.mapStyles(newNameForOld);
1196 	replaceNamedResources(newNames);
1197 }
1198 
replaceNamedResources(ResourceCollection & newNames)1199 void ScribusDoc::replaceNamedResources(ResourceCollection& newNames)
1200 {
1201 	// replace names in items
1202 	QList<PageItem*> * itemlist = & MasterItems;
1203 	while (itemlist != nullptr)
1204 	{
1205 		for (int i=0; i < itemlist->count(); ++i)
1206 		{
1207 			PageItem * currItem = itemlist->at(i);
1208 			if (currItem)
1209 				currItem->replaceNamedResources(newNames);
1210 		}
1211 		if (itemlist == &MasterItems)
1212 			itemlist = &DocItems;
1213 		else
1214 			itemlist = nullptr;
1215 	}
1216 	for (NotesStyle* nStyle : qAsConst(m_docNotesStylesList))
1217 	{ //update styles names in notes styles
1218 		if (nStyle == nullptr)
1219 			continue;
1220 		if (newNames.styles().contains(nStyle->notesParStyle()))
1221 			nStyle->setNotesParStyle(newNames.styles().value(nStyle->notesParStyle()));
1222 		if (newNames.charStyles().contains(nStyle->marksChStyle()))
1223 			nStyle->setMarksCharStyle(newNames.charStyles().value(nStyle->marksChStyle()));
1224 	}
1225 	for (auto itf = FrameItems.begin(); itf != FrameItems.end(); ++itf)
1226 	{
1227 		PageItem *currItem = itf.value();
1228 		if (currItem)
1229 			currItem->replaceNamedResources(newNames);
1230 	}
1231 	// replace names in styles...
1232 	for (int i=m_docParagraphStyles.count()-1; i >= 0; --i)
1233 	{
1234 		if (newNames.styles().contains(m_docParagraphStyles[i].name()))
1235 			m_docParagraphStyles.remove(i);
1236 		else
1237 			m_docParagraphStyles[i].replaceNamedResources(newNames);
1238 	}
1239 	for (int i=m_docCharStyles.count()-1; i >= 0; --i)
1240 	{
1241 		if (newNames.charStyles().contains(m_docCharStyles[i].name()))
1242 			m_docCharStyles.remove(i);
1243 		else
1244 			m_docCharStyles[i].replaceNamedResources(newNames);
1245 	}
1246 	for (int i = m_docTableStyles.count() - 1; i >= 0; --i)
1247 	{
1248 		if (newNames.tableStyles().contains(m_docTableStyles[i].name()))
1249 			m_docTableStyles.remove(i);
1250 		else
1251 			m_docTableStyles[i].replaceNamedResources(newNames);
1252 	}
1253 	for (int i = m_docCellStyles.count() - 1; i >= 0; --i)
1254 	{
1255 		if (newNames.cellStyles().contains(m_docCellStyles[i].name()))
1256 			m_docCellStyles.remove(i);
1257 		else
1258 			m_docCellStyles[i].replaceNamedResources(newNames);
1259 	}
1260 
1261 	QHash<QString,ScPattern>::Iterator it = docPatterns.begin();
1262 	while (it != docPatterns.end())
1263 	{
1264 		if (newNames.patterns().contains(it.key()))
1265 		{
1266 			it = docPatterns.erase(it);
1267 			continue;
1268 		}
1269 
1270 		ScPattern pa = *it;
1271 		for (int o = 0; o < pa.items.count(); o++)
1272 		{
1273 			pa.items.at(o)->replaceNamedResources(newNames);
1274 		}
1275 		++it;
1276 	}
1277 
1278 	QHash<QString,VGradient>::Iterator itg = docGradients.begin();
1279 	while (itg != docGradients.end())
1280 	{
1281 		if (newNames.gradients().contains(itg.key()))
1282 		{
1283 			itg = docGradients.erase(itg);
1284 			continue;
1285 		}
1286 
1287 		QMap<QString,QString>::ConstIterator itc;
1288 		QList<VColorStop*> cstops = itg.value().colorStops();
1289 		for (int cst = 0; cst < itg.value().stops(); ++cst)
1290 		{
1291 			itc = newNames.colors().find(cstops.at(cst)->name);
1292 			if (itc != newNames.colors().end())
1293 			{
1294 				if (*itc != CommonStrings::None)
1295 					cstops.at(cst)->name = *itc;
1296 			}
1297 		}
1298 		++itg;
1299 	}
1300 
1301 	if (newNames.colors().count() > 0 || newNames.fonts().count() > 0)
1302 	{
1303 		m_docCharStyles.invalidate();
1304 		m_docParagraphStyles.invalidate();
1305 		m_docTableStyles.invalidate();
1306 		m_docCellStyles.invalidate();
1307 	}
1308 	else
1309 	{
1310 		if (newNames.charStyles().count() > 0)
1311 			m_docCharStyles.invalidate();
1312 		if (newNames.styles().count() > 0)
1313 			m_docParagraphStyles.invalidate();
1314 		if (newNames.tableStyles().count() > 0)
1315 			m_docTableStyles.invalidate();
1316 		if (newNames.cellStyles().count() > 0)
1317 			m_docCellStyles.invalidate();
1318 	}
1319 	if (!isLoading() && !(newNames.colors().isEmpty() && newNames.fonts().isEmpty() && newNames.patterns().isEmpty()
1320 			&& newNames.styles().isEmpty() && newNames.charStyles().isEmpty() && newNames.lineStyles().isEmpty()
1321 			&& newNames.tableStyles().isEmpty() && newNames.cellStyles().isEmpty()))
1322 		changed();
1323 }
1324 
1325 
replaceCharStyles(const QMap<QString,QString> & newNameForOld)1326 void ScribusDoc::replaceCharStyles(const QMap<QString,QString>& newNameForOld)
1327 {
1328 	ResourceCollection newNames;
1329 	newNames.mapCharStyles(newNameForOld);
1330 	replaceNamedResources(newNames);
1331 }
1332 
replaceTableStyles(const QMap<QString,QString> & newNameForOld)1333 void ScribusDoc::replaceTableStyles(const QMap<QString, QString>& newNameForOld)
1334 {
1335 	ResourceCollection newNames;
1336 	newNames.mapTableStyles(newNameForOld);
1337 	replaceNamedResources(newNames);
1338 }
1339 
replaceCellStyles(const QMap<QString,QString> & newNameForOld)1340 void ScribusDoc::replaceCellStyles(const QMap<QString, QString>& newNameForOld)
1341 {
1342 	ResourceCollection newNames;
1343 	newNames.mapCellStyles(newNameForOld);
1344 	replaceNamedResources(newNames);
1345 }
1346 
redefineStyles(const StyleSet<ParagraphStyle> & newStyles,bool removeUnused)1347 void ScribusDoc::redefineStyles(const StyleSet<ParagraphStyle>& newStyles, bool removeUnused)
1348 {
1349 	m_docParagraphStyles.redefine(newStyles, false);
1350 	if (removeUnused)
1351 	{
1352 		QMap<QString, QString> deletion;
1353 		QString deflt("");
1354 		for (int i=0; i < m_docParagraphStyles.count(); ++i)
1355 		{
1356 			const QString& nam(m_docParagraphStyles[i].name());
1357 			if (newStyles.find(nam) < 0)
1358 				deletion[nam] = deflt;
1359 		}
1360 		if (deletion.count() > 0)
1361 			replaceStyles(deletion);
1362 	}
1363 	// repair charstyle context:
1364 	for (int i=0; i < m_docParagraphStyles.count(); ++i)
1365 	{
1366 		ParagraphStyle& sty(m_docParagraphStyles[i]);
1367 		if (m_docParagraphStyles.isDefault(sty))
1368 		{
1369 			sty.breakImplicitCharStyleInheritance(true);
1370 			sty.charStyle().setContext( & m_docCharStyles );
1371 		}
1372 		else {
1373 			sty.breakImplicitCharStyleInheritance(false);
1374 		}
1375 	}
1376 	m_docParagraphStyles.invalidate();
1377 	if (!isLoading())
1378 	{
1379 		flag_Renumber = true;
1380 		flag_NumUpdateRequest = true;
1381 	}
1382 }
1383 
redefineCharStyles(const StyleSet<CharStyle> & newStyles,bool removeUnused)1384 void ScribusDoc::redefineCharStyles(const StyleSet<CharStyle>& newStyles, bool removeUnused)
1385 {
1386 	m_docCharStyles.redefine(newStyles, false);
1387 	if (removeUnused)
1388 	{
1389 		QMap<QString, QString> deletion;
1390 		QString deflt("");
1391 		for (int i=0; i < m_docCharStyles.count(); ++i)
1392 		{
1393 			const QString& nam(m_docCharStyles[i].name());
1394 			if (newStyles.find(nam) < 0)
1395 			{
1396 				deletion[nam] = deflt;
1397 			}
1398 		}
1399 		if (deletion.count() > 0)
1400 			replaceCharStyles(deletion);
1401 	}
1402 	m_docCharStyles.invalidate();
1403 }
1404 
redefineTableStyles(const StyleSet<TableStyle> & newStyles,bool removeUnused)1405 void ScribusDoc::redefineTableStyles(const StyleSet<TableStyle>& newStyles, bool removeUnused)
1406 {
1407 	m_docTableStyles.redefine(newStyles, false);
1408 	if (removeUnused)
1409 	{
1410 		QMap<QString, QString> deletion;
1411 		QString deflt("");
1412 		for (int i = 0; i < m_docTableStyles.count(); ++i)
1413 		{
1414 			const QString& nam(m_docTableStyles[i].name());
1415 			if (newStyles.find(nam) < 0)
1416 			{
1417 				deletion[nam] = deflt;
1418 			}
1419 		}
1420 		if (deletion.count() > 0)
1421 			replaceTableStyles(deletion);
1422 	}
1423 	m_docTableStyles.invalidate();
1424 }
1425 
redefineCellStyles(const StyleSet<CellStyle> & newStyles,bool removeUnused)1426 void ScribusDoc::redefineCellStyles(const StyleSet<CellStyle>& newStyles, bool removeUnused)
1427 {
1428 	m_docCellStyles.redefine(newStyles, false);
1429 	if (removeUnused)
1430 	{
1431 		QMap<QString, QString> deletion;
1432 		QString deflt("");
1433 		for (int i = 0; i < m_docCellStyles.count(); ++i)
1434 		{
1435 			const QString& nam(m_docCellStyles[i].name());
1436 			if (newStyles.find(nam) < 0)
1437 			{
1438 				deletion[nam] = deflt;
1439 			}
1440 		}
1441 		if (deletion.count() > 0)
1442 			replaceCellStyles(deletion);
1443 	}
1444 	m_docCellStyles.invalidate();
1445 }
1446 
1447 /*
1448  * Split out from loadStyles in editFormats.cpp so it's callable from anywhere,
1449  * including plugins.
1450  * - 2004-09-14 Craig Ringer
1451  */
1452 // don't like this here. could as well be a static method for reading this stuff into temp., then always use redefineXY() - av
loadStylesFromFile(const QString & fileName)1453 void ScribusDoc::loadStylesFromFile(const QString& fileName)
1454 {
1455 	StyleSet<ParagraphStyle> *wrkStyles     = &m_docParagraphStyles;
1456 	StyleSet<CharStyle> *wrkCharStyles      = &m_docCharStyles;
1457 	QHash<QString, multiLine> *wrkLineStyles = &docLineStyles;
1458 
1459 	int oldStyles = wrkStyles->count();
1460 	int oldCharStyles = wrkCharStyles->count();
1461 	int oldLineStyles = wrkLineStyles->count();
1462 
1463 	if (!fileName.isEmpty())
1464 	{
1465 		FileLoader fl(fileName);
1466 		if (fl.testFile() == -1)
1467 		//TODO put in nice user warning
1468 			return;
1469 
1470 		if (!fl.readStyles(this, *wrkStyles))
1471 		{
1472 			//TODO put in nice user warning
1473 		}
1474 
1475 		if (!fl.readCharStyles(this, *wrkCharStyles))
1476 		{
1477 			//TODO put in nice user warning
1478 		}
1479 
1480 		if (!fl.readLineStyles(wrkLineStyles))
1481 		{
1482 			//TODO put in nice user warning
1483 		}
1484 
1485 		if ( !isLoading() && ((wrkStyles->count() > oldStyles)
1486 				    || (wrkCharStyles->count() > oldCharStyles)
1487 				    || (wrkLineStyles->count() > oldLineStyles) ) )
1488 			changed();
1489 	}
1490 }
1491 
loadStylesFromFile(const QString & fileName,StyleSet<ParagraphStyle> * tempStyles,StyleSet<CharStyle> * tempCharStyles,QHash<QString,multiLine> * tempLineStyles)1492 void ScribusDoc::loadStylesFromFile(const QString& fileName, StyleSet<ParagraphStyle> *tempStyles,
1493                                                       StyleSet<CharStyle> *tempCharStyles,
1494 													  QHash<QString, multiLine> *tempLineStyles)
1495 {
1496 	StyleSet<ParagraphStyle> *wrkStyles     = tempStyles;
1497 	StyleSet<CharStyle> *wrkCharStyles      = tempCharStyles;
1498 	QHash<QString, multiLine> *wrkLineStyles = tempLineStyles;
1499 
1500 	if (!fileName.isEmpty())
1501 	{
1502 		FileLoader fl(fileName);
1503 		if (fl.testFile() == -1)
1504 		//TODO put in nice user warning
1505 			return;
1506 
1507 		if (!fl.readStyles(this, *wrkStyles))
1508 		{
1509 			//TODO put in nice user warning
1510 		}
1511 
1512 		if (!fl.readCharStyles(this, *wrkCharStyles))
1513 		{
1514 			//TODO put in nice user warning
1515 		}
1516 
1517 		if (!fl.readLineStyles(wrkLineStyles))
1518 		{
1519 			//TODO put in nice user warning
1520 		}
1521 
1522 		// Which are the default styles
1523 		// Sadly StyleSet is not updated at import
1524 		// and it might break something to do so.
1525 		// We need to loop then - pm
1526 
1527 		QFileInfo fi(fileName);
1528 		QString importPrefix(tr("Imported ","Prefix of imported default style"));
1529 		QString importSuffix(" (" +  fi.baseName() + ")");
1530 
1531 		for (int j(0) ; j < wrkStyles->count() ; ++j)
1532 		{
1533 			if ((*wrkStyles)[j].isDefaultStyle())
1534 			{
1535 				ParagraphStyle& parDefault((*wrkStyles)[j]);
1536 				parDefault.setDefaultStyle(false);
1537 				QMap<QString, QString> namesMap;
1538 				namesMap[parDefault.name()] = importPrefix + parDefault.name() + importSuffix;
1539 				for (int i(0) ; i < wrkStyles->count() ; ++i)
1540 				{
1541 					if ((*wrkStyles)[i] != parDefault)
1542 						namesMap[(*wrkStyles)[i].name()] = (*wrkStyles)[i].name();
1543 				}
1544 				wrkStyles->rename(namesMap);
1545 			}
1546 		}
1547 		for (int j(0) ; j < wrkCharStyles->count() ; ++j)
1548 		{
1549 			if ((*wrkCharStyles)[j].isDefaultStyle())
1550 			{
1551 				CharStyle& charDefault((*wrkCharStyles)[j]);
1552 				charDefault.setDefaultStyle(false);
1553 				QMap<QString, QString> namesMap;
1554 				namesMap[charDefault.name()] = importPrefix + charDefault.name() + importSuffix;
1555 				for (int i(0) ; i < wrkCharStyles->count() ; ++i)
1556 				{
1557 					if ((*wrkCharStyles)[i] != charDefault)
1558 						namesMap[(*wrkCharStyles)[i].name()] = (*wrkCharStyles)[i].name();
1559 				}
1560 				wrkCharStyles->rename(namesMap);
1561 			}
1562 		}
1563 	}
1564 }
1565 
1566 
lockGuides(bool isLocked)1567 void ScribusDoc::lockGuides(bool isLocked)
1568 {
1569 	if (GuideLock == isLocked)
1570 		return;
1571 	GuideLock = isLocked;
1572 	if (UndoManager::undoEnabled())
1573 	{
1574 		QString name;
1575 		if (isLocked)
1576 			name = Um::LockGuides;
1577 		else
1578 			name = Um::UnlockGuides;
1579 		SimpleState *ss = new SimpleState(name, "", Um::ILockGuides);
1580 		ss->set("GUIDE_LOCK", isLocked);
1581 		m_undoManager->action(this, ss);
1582 	}
1583 }
1584 
undoRedoBegin()1585 void ScribusDoc::undoRedoBegin()
1586 {
1587 	m_docUpdater->beginUpdate();
1588 	m_Selection->delaySignalsOn();
1589 	++m_undoRedoOngoing;
1590 }
1591 
undoRedoDone()1592 void ScribusDoc::undoRedoDone()
1593 {
1594 	--m_undoRedoOngoing;
1595 	m_Selection->delaySignalsOff();
1596 	m_docUpdater->endUpdate();
1597 }
1598 
restore(UndoState * state,bool isUndo)1599 void ScribusDoc::restore(UndoState* state, bool isUndo)
1600 {
1601 	SimpleState *ss = dynamic_cast<SimpleState*>(state);
1602 	if (!ss)
1603 		return;
1604 
1605 	bool layersUndo = false;
1606 	if (ss->contains("GROUP"))
1607 		restoreGrouping(ss, isUndo);
1608 	else if (ss->contains("UNGROUP"))
1609 		restoreGrouping(ss, !isUndo);
1610 	else if (ss->contains("GUIDE_LOCK"))
1611 		restoreGuideLock(ss, isUndo);
1612 	else if (ss->contains("UP_LAYER"))
1613 	{
1614 		if (isUndo)
1615 			lowerLayer(ss->getInt("ACTIVE"));
1616 		else
1617 			raiseLayer(ss->getInt("ACTIVE"));
1618 		layersUndo = true;
1619 	}
1620 	else if (ss->contains("DOWN_LAYER"))
1621 	{
1622 		if (isUndo)
1623 			raiseLayer(ss->getInt("ACTIVE"));
1624 		else
1625 			lowerLayer(ss->getInt("ACTIVE"));
1626 		layersUndo = true;
1627 	}
1628 	else if (ss->contains("PRINT_LAYER"))
1629 	{
1630 		bool print = ss->getBool("PRINT");
1631 		setLayerPrintable(ss->getInt("ACTIVE"), isUndo ? !print : print);
1632 		layersUndo = true;
1633 	}
1634 	else if (ss->contains("LAYER_FLOW"))
1635 	{
1636 		bool flow = ss->getBool("FLOW");
1637 		setLayerFlow(ss->getInt("ACTIVE"), isUndo ? !flow : flow);
1638 		layersUndo = true;
1639 	}
1640 	else if (ss->contains("LAYER_LOCK"))
1641 	{
1642 		bool lock = ss->getBool("LOCK");
1643 		setLayerLocked(ss->getInt("ACTIVE"), isUndo ? !lock : lock);
1644 		layersUndo = true;
1645 	}
1646 	else if (ss->contains("LAYER_TRANSPARENCY"))
1647 	{
1648 		double old_trans = ss->getDouble("OLD_TRANS");
1649 		double new_trans = ss->getDouble("NEW_TRANS");
1650 		setLayerTransparency(ss->getInt("ACTIVE"), isUndo ? old_trans : new_trans);
1651 		layersUndo = true;
1652 	}
1653 	else if (ss->contains("LAYER_BLENDMODE"))
1654 	{
1655 		int old_blend = ss->getInt("OLD_BLENDMODE");
1656 		int new_blend = ss->getInt("NEW_BLENDMODE");
1657 		setLayerBlendMode(ss->getInt("ACTIVE"), isUndo ? old_blend : new_blend);
1658 		layersUndo = true;
1659 	}
1660 	else if (ss->contains("ADD_LAYER"))
1661 	{
1662 		if (isUndo)
1663 			deleteLayer(ss->getInt("LAYER_NR"), false);
1664 		else
1665 		{
1666 			int layerID = addLayer(ss->get("NAME"), false);
1667 			int newLayerID = ss->getInt("LAYER_NR");
1668 			bool renumberedOk=renumberLayer(layerID, newLayerID);
1669 			Q_ASSERT(renumberedOk);
1670 		}
1671 		layersUndo = true;
1672 	}
1673 	else if (ss->contains("REMOVE_LAYER"))
1674 	{
1675 		if (isUndo)
1676 		{
1677 			int layerID = addLayer(ss->get("NAME"), false);
1678 			int newLayerID = ss->getInt("LAYER_NR");
1679 			bool renumberedOk=renumberLayer(layerID, newLayerID);
1680 			Q_ASSERT(renumberedOk);
1681 			layerID = newLayerID;
1682 			//Layer is at the top now, lower it until it reaches the old level
1683 			int level = ss->getInt("LEVEL");
1684 			while (layerLevelFromID(layerID)!=level)
1685 				lowerLayer(layerID);
1686 		}
1687 		else
1688 			deleteLayer(ss->getInt("LAYER_NR"), ss->getBool("DELETE"));
1689 		layersUndo = true;
1690 	}
1691 	else if (ss->contains("CHANGE_NAME"))
1692 	{
1693 		QString name = ss->get("OLD_NAME");
1694 		if (!isUndo)
1695 			name = ss->get("NEW_NAME");
1696 		changeLayerName(ss->getInt("ACTIVE"), name);
1697 		layersUndo = true;
1698 	}
1699 	else if (ss->contains("MASTERPAGE_ADD"))
1700 		restoreAddMasterPage(ss, isUndo);
1701 	else if (ss->contains("MASTERPAGE_RENAME"))
1702 		restoreMasterPageRenaming(ss, isUndo);
1703 	else if (ss->contains("OLD_MASTERPAGE"))
1704 		restoreMasterPageApplying(ss, isUndo);
1705 	else if (ss->contains("PAGE_COPY"))
1706 		restoreCopyPage(ss, isUndo);
1707 	else if (ss->contains("PAGE_MOVE"))
1708 		restoreMovePage(ss, isUndo);
1709 	else if (ss->contains("PAGE_SWAP"))
1710 		restoreSwapPage(ss, isUndo);
1711 	else if (ss->contains("LEVEL_DOWN"))
1712 		restoreLevelDown(ss,isUndo);
1713 	else if (ss->contains("LEVEL_UP"))
1714 		restoreLevelDown(ss,!isUndo);
1715 	else if (ss->contains("LEVEL_BOTTOM"))
1716 		restoreLevelBottom(ss,isUndo);
1717 	else if (ss->contains("LEVEL_TOP"))
1718 		restoreLevelBottom(ss,!isUndo);
1719 	else if (ss->contains("PAGE_CHANGEPROPS"))
1720 		restoreChangePageProperties(ss,isUndo);
1721 	else if (ss->contains("DELETE_FRAMETEXT"))
1722 	{
1723 		PageItem * nF = getItemFromName(ss->get("noteframeName"));
1724 		Q_ASSERT(nF != nullptr);
1725 		nF->asNoteFrame()->restoreDeleteNoteText(ss, isUndo);
1726 	}
1727 	else if (ss->contains("DELETE_FRAMEPARA"))
1728 	{
1729 		PageItem * nF = getItemFromName(ss->get("noteframeName"));
1730 		Q_ASSERT(nF != nullptr);
1731 		nF->asNoteFrame()->restoreDeleteNoteParagraph(ss, isUndo);
1732 	}
1733 	else if (ss->contains("INSERT_FRAMETEXT"))
1734 	{
1735 		PageItem * nF = getItemFromName(ss->get("noteframeName"));
1736 		Q_ASSERT(nF != nullptr);
1737 		nF->asNoteFrame()->restoreInsertNoteText(ss,isUndo);
1738 	}
1739 	else if (ss->contains("INSERT_FRAMEPARA"))
1740 	{
1741 		PageItem * nF = getItemFromName(ss->get("noteframeName"));
1742 		Q_ASSERT(nF != nullptr);
1743 		nF->asNoteFrame()->restoreInsertNoteParagraph(ss,isUndo);
1744 	}
1745 	else if (ss->contains("NSTYLE"))
1746 		restoreNoteStyle(ss, isUndo);
1747 	else if (ss->contains("DELETE_NOTE"))
1748 		restoreDeleteNote(state, isUndo);
1749 	else if (ss->contains("MARK"))
1750 		restoreMarks(state, isUndo);
1751 
1752 	if (layersUndo)
1753 	{
1754 		if (ScCore->usingGUI())
1755 		{
1756 			if (ss->contains("ACTIVE"))
1757 				scMW()->layerPalette->setActiveLayer(layerLevelFromID(ss->getInt("ACTIVE")),0);
1758 			m_ScMW->changeLayer(ss->getInt("ACTIVE"));
1759 			m_ScMW->layerPalette->rebuildList();
1760 			if (m_ScMW->outlinePalette->isVisible())
1761 				m_ScMW->outlinePalette->BuildTree();
1762 		}
1763 	}
1764 }
1765 
restoreLevelDown(SimpleState * ss,bool isUndo)1766 void ScribusDoc::restoreLevelDown(SimpleState* ss, bool isUndo)
1767 {
1768 	ScItemState<QList<QPointer<PageItem> > > *is = dynamic_cast<ScItemState<QList<QPointer<PageItem> > > *>(ss);
1769 	if (!is)
1770 		return;
1771 	QList<QPointer<PageItem> > listItem = is->getItem();
1772 	m_Selection->clear();
1773 	for (int i = 0; i<listItem.size();i++)
1774 		m_Selection->addItem(listItem.at(i));
1775 	if (isUndo)
1776 		itemSelection_RaiseItem();
1777 	else
1778 		itemSelection_LowerItem();
1779 }
1780 
restoreLevelBottom(SimpleState * ss,bool isUndo)1781 void ScribusDoc::restoreLevelBottom(SimpleState* ss, bool isUndo)
1782 {
1783 	ScItemState<QList<QPointer<PageItem> > > *is = dynamic_cast<ScItemState<QList<QPointer<PageItem> > > *>(ss);
1784 	if (!is)
1785 		return;
1786 	QList<QPointer<PageItem> > listItem = is->getItem();
1787 	m_Selection->clear();
1788 	for (int i = 0; i<listItem.size();i++)
1789 		m_Selection->addItem(listItem.at(i));
1790 	if (isUndo)
1791 		bringItemSelectionToFront();
1792 	else
1793 		sendItemSelectionToBack();
1794 }
1795 
restoreGuideLock(SimpleState * ss,bool isUndo)1796 void ScribusDoc::restoreGuideLock(SimpleState* ss, bool isUndo)
1797 {
1798 	if (isUndo)
1799 		GuideLock = !ss->getBool("GUIDE_LOCK");
1800 	else
1801 		GuideLock = ss->getBool("GUIDE_LOCK");
1802 }
1803 
restoreAddMasterPage(SimpleState * ss,bool isUndo)1804 void ScribusDoc::restoreAddMasterPage(SimpleState* ss, bool isUndo)
1805 {
1806 	QString pageName = ss->get("MASTERPAGE_NAME");
1807 	int pageNr = ss->getInt("MASTERPAGE_NBR");
1808 
1809 	bool oldMPMode  = masterPageMode();
1810 	ScPage* oldPage = currentPage();
1811 
1812 	setMasterPageMode(true);
1813 	if (isUndo)
1814 	{
1815 		DummyUndoObject *duo = new DummyUndoObject();
1816 		uint did = static_cast<uint>(duo->getUId());
1817 		m_undoManager->replaceObject(Pages->at(MasterNames[pageName])->getUId(), duo);
1818 		ss->set("DUMMY_ID", did);
1819 
1820 		scMW()->deletePage2(MasterNames[pageName]);
1821 		rebuildMasterNames();
1822 	}
1823 	else
1824 	{
1825 		ScPage* Mpage = addMasterPage(pageNr, pageName);
1826 		setCurrentPage(Mpage);
1827 		UndoObject *tmp = m_undoManager->replaceObject(
1828 					ss->getUInt("DUMMY_ID"), Pages->at(MasterNames[pageName]));
1829 		delete tmp;
1830 	}
1831 	setMasterPageMode(oldMPMode);
1832 	if (!oldMPMode)
1833 		setCurrentPage(oldPage);
1834 	scMW()->pagePalette->updateMasterPageList();
1835 	m_View->reformPages();
1836 }
1837 
restoreChangePageProperties(SimpleState * state,bool isUndo)1838 void ScribusDoc::restoreChangePageProperties(SimpleState* state, bool isUndo)
1839 {
1840 	bool oldMPMode  = masterPageMode();
1841 	ScPage* oldPage = currentPage();
1842 
1843 	setMasterPageMode(state->getBool("MASTER_PAGE_MODE"));
1844 	setCurrentPage(Pages->at(state->getInt("PAGE_NUM")));
1845 	if (isUndo)
1846 	{
1847 //		qDebug()<<"undo setting orientation to"<<state->getInt("OLD_PAGE_ORIENTATION");
1848 		changePageProperties(state->getDouble("OLD_PAGE_INITIALTOP"), state->getDouble("OLD_PAGE_INITIALBOTTOM"),
1849 				state->getDouble("OLD_PAGE_INITIALLEFT"), state->getDouble("OLD_PAGE_INITIALRIGHT"),
1850 				state->getDouble("OLD_PAGE_INITIALHEIGHT"), state->getDouble("OLD_PAGE_INITIALWIDTH"),
1851 				state->getDouble("OLD_PAGE_HEIGHT"), state->getDouble("OLD_PAGE_WIDTH"), state->getInt("OLD_PAGE_ORIENTATION"),
1852 				state->get("OLD_PAGE_SIZE"), state->getInt("OLD_PAGE_MARGINPRESET"), state->getBool("OLD_PAGE_MOVEOBJECTS"), state->getInt("PAGE_NUM"), state->getInt("OLD_PAGE_TYPE"));
1853 	}
1854 	else
1855 	{
1856 //		qDebug()<<"redo setting orientation to"<<state->getInt("NEW_PAGE_ORIENTATION");
1857 		changePageProperties(state->getDouble("NEW_PAGE_INITIALTOP"), state->getDouble("NEW_PAGE_INITIALBOTTOM"),
1858 				state->getDouble("NEW_PAGE_INITIALLEFT"), state->getDouble("NEW_PAGE_INITIALRIGHT"),
1859 				state->getDouble("NEW_PAGE_INITIALHEIGHT"), state->getDouble("NEW_PAGE_INITIALWIDTH"),
1860 				state->getDouble("NEW_PAGE_HEIGHT"), state->getDouble("NEW_PAGE_WIDTH"), state->getInt("NEW_PAGE_ORIENTATION"),
1861 				state->get("NEW_PAGE_SIZE"), state->getInt("NEW_PAGE_MARGINPRESET"), state->getBool("OLD_PAGE_MOVEOBJECTS"), state->getInt("PAGE_NUM"), state->getInt("NEW_PAGE_TYPE"));
1862 	}
1863 	setMasterPageMode(oldMPMode);
1864 	setCurrentPage(oldPage);
1865 }
1866 
restoreGrouping(SimpleState * ss,bool isUndo)1867 void ScribusDoc::restoreGrouping(SimpleState* ss, bool isUndo)
1868 {
1869 	ScItemState<QList<QPointer<PageItem> > >* is = dynamic_cast<ScItemState<QList<QPointer<PageItem> > >*>(ss);
1870 	if (!is)
1871 		qFatal("ScribusDoc::restoreGrouping: dynamic cast failed");
1872 
1873 	QList<QPointer<PageItem> > select = is->getItem();
1874 	m_Selection->delaySignalsOn();
1875 	for (int i = 0; i < select.count(); ++i)
1876 		m_Selection->removeItem(select.at(i));
1877 	Selection tempSelect(this, false);
1878 	double x, y, w, h;
1879 	if (isUndo)
1880 	{
1881 		tempSelect.addItem(select.first()->Parent);
1882 		tempSelect.getGroupRect(&x, &y, &w, &h);
1883 		itemSelection_UnGroupObjects(&tempSelect);
1884 	}
1885 	else
1886 	{
1887 		for (int i = 0; i < select.size() - 1; ++i)
1888 			tempSelect.addItem(select.at(i));
1889 		tempSelect.getGroupRect(&x, &y, &w, &h);
1890 		PageItem_Group* oldGroupItem = select.last()->asGroupFrame();
1891 		PageItem* newGroupItem = itemSelection_GroupObjects(false, false, &tempSelect, oldGroupItem);
1892 		select.removeLast();
1893 		select.append(newGroupItem);
1894 		is->setItem(select);
1895 	}
1896 	QRectF rect(x, y , w, h);
1897 	regionsChanged()->update(rect.adjusted(-10, -10, 20, 20));
1898 	m_Selection->delaySignalsOff();
1899 }
1900 
restoreMarks(UndoState * state,bool isUndo)1901 void ScribusDoc::restoreMarks(UndoState* state, bool isUndo)
1902 {
1903 	ScItemsState *is = dynamic_cast<ScItemsState*>(state);
1904 	if (!is)
1905 		return;
1906 
1907 	Mark* mrk = getMark(is->get("label"), (MarkType) is->getInt("type"));
1908 	if (mrk == nullptr && is->contains("labelOLD"))
1909 		mrk = getMark(is->get("labelOLD"), (MarkType) is->getInt("type"));
1910 	int pos = is->getInt("at");
1911 
1912 	bool isAutoNoteFrame = false;
1913 	PageItem* currItem = nullptr;
1914 	if (is->contains("noteframeName"))
1915 	{
1916 		currItem = getItemFromName(is->get("noteframeName"));
1917 		if (currItem != nullptr)
1918 			isAutoNoteFrame = currItem->asNoteFrame()->isAutoFrame();
1919 	}
1920 	else
1921 		currItem = (PageItem*) is->getItem("inItem");
1922 
1923 	QString markAction = is->get("MARK");
1924 	if (isUndo)
1925 	{
1926 		if (markAction == "new")
1927 		{
1928 			Q_ASSERT(mrk != nullptr);
1929 			if (mrk->isNoteType())
1930 			{
1931 				TextNote* note = mrk->getNotePtr();
1932 				NotesStyle* nStyle = note->notesStyle();
1933 				if (note->isEndNote())
1934 					flag_updateEndNotes = true;
1935 				deleteNote(note);
1936 				updateNotesNums(nStyle);
1937 			}
1938 			else
1939 				eraseMark(mrk, true, currItem, true);
1940 		}
1941 		else if (markAction == "replace")
1942 		{
1943 			Q_ASSERT(pos >= 0);
1944 			Q_ASSERT(currItem != nullptr);
1945 			Q_ASSERT(mrk != nullptr);
1946 			Mark* mrk = getMark(is->get("label"), (MarkType) is->getInt("type"));
1947 			currItem->itemText.replaceMark(pos, mrk);
1948 			if (is->contains("strtxtOLD"))
1949 			{
1950 				mrk->setString(is->get("strtxtOLD"));
1951 				invalidateVariableTextFrames(mrk, false);
1952 			}
1953 			if (is->contains("labelOLD"))
1954 				mrk->label = is->get("labelOLD");
1955 		}
1956 		else if (markAction == "edit")
1957 		{
1958 			Q_ASSERT(mrk != nullptr);
1959 			if (is->contains("labelOLD"))
1960 				mrk->label = is->get("labelOLD");
1961 			if (is->contains("strtxtOLD"))
1962 			{
1963 				mrk->setString(is->get("strtxtOLD"));
1964 				invalidateVariableTextFrames(mrk, false);
1965 			}
1966 			if (is->contains("dNameOLD"))
1967 				mrk->setMark(is->get("dNameOLD"), (MarkType) is->getInt("dTypeOLD"));
1968 			if (is->getItem("itemPtrOLD") != nullptr)
1969 				mrk->setItemPtr((PageItem*) is->getItem("itemPtrOLD"));
1970 		}
1971 		else if (markAction == "insert_existing")
1972 		{
1973 			Q_ASSERT(pos >= 0);
1974 			Q_ASSERT(currItem != nullptr);
1975 			Q_ASSERT(mrk != nullptr);
1976 			currItem->itemText.removeChars(pos, 1);
1977 			if (is->contains("strOLD"))
1978 			{
1979 				mrk->setString(is->get("strOLD"));
1980 				invalidateVariableTextFrames(mrk, false);
1981 			}
1982 			if (is->contains("labelOLD"))
1983 				mrk->label = is->get("labelOLD");
1984 		}
1985 		else if (markAction == "delete")
1986 		{
1987 			mrk = newMark();
1988 			mrk->label = is->get("label");
1989 			mrk->setType((MarkType) is->getInt("type"));
1990 			Q_ASSERT(pos >= 0);
1991 			Q_ASSERT(currItem != nullptr);
1992 			currItem->itemText.insertMark(mrk, pos);
1993 			if (is->contains("strtxt"))
1994 			{
1995 				mrk->setString(is->get("strtxt"));
1996 				invalidateVariableTextFrames(mrk, false);
1997 			}
1998 			if (is->contains("dName"))
1999 				mrk->setMark(is->get("dName"), (MarkType) is->getInt("dType"));
2000 			if (is->getItem("itemPtr") != nullptr)
2001 				mrk->setItemPtr((PageItem*) is->getItem("itemPtr"));
2002 		}
2003 		else if (markAction == "eraseFromText") ////for non-unique marks
2004 		{
2005 			Q_ASSERT(pos >= 0);
2006 			Q_ASSERT(mrk != nullptr);
2007 			Q_ASSERT(currItem != nullptr);
2008 			currItem->itemText.insertMark(mrk, pos);
2009 			if (is->contains("strNew"))
2010 			{
2011 				mrk->setString(is->get("strNEW"));
2012 				invalidateVariableTextFrames(mrk, false);
2013 			}
2014 		}
2015 		else if (markAction == "delNonUnique")
2016 		{
2017 			//used if deleting non-unique marks by MarksManager
2018 			mrk = newMark();
2019 			mrk->label = is->get("label");
2020 			mrk->setType((MarkType) is->getInt("type"));
2021 			mrk->setString(is->get("strtxt"));
2022 			for (int i=0; i < is->insertItemPos.count(); ++i)
2023 			{
2024 				PageItem* item = (PageItem*) is->insertItemPos[i].first;
2025 				item->itemText.insertMark(mrk, is->insertItemPos[i].second);
2026 				item->invalid = true;
2027 			}
2028 		}
2029 		else
2030 		{
2031 			Q_ASSERT(false);
2032 			qDebug() << "MARK undo - unhandled " << is->get("MARK");
2033 		}
2034 	}
2035 	else  //REDO
2036 	{
2037 		if (markAction == "new")
2038 		{
2039 			if (currItem == nullptr)
2040 			{
2041 				qDebug() << "Wrong inItem in undo step for mark";
2042 				return;
2043 			}
2044 			mrk = newMark();
2045 			mrk->label = is->get("label");
2046 			mrk->setType((MarkType) is->getInt("type"));
2047 			Q_ASSERT(currItem != nullptr);
2048 			Q_ASSERT(pos >= 0);
2049 			currItem->itemText.insertMark(mrk, pos);
2050 			if (is->contains("strtxt"))
2051 				mrk->setString(is->get("strtxt"));
2052 			if (is->contains("dName"))
2053 				mrk->setMark(is->get("dName"), (MarkType) is->getInt("dType"));
2054 			if (is->getItem("itemPtr") != nullptr)
2055 				mrk->setItemPtr((PageItem*) is->getItem("itemPtr"));
2056 			if (mrk->isType(MARKNoteMasterType))
2057 			{
2058 				NotesStyle* nStyle = getNotesStyle(is->get("nStyle"));
2059 				TextNote* note = newNote(nStyle);
2060 				mrk->setNotePtr(note);
2061 				note->setMasterMark(mrk);
2062 				if (nStyle->isEndNotes())
2063 					flag_updateEndNotes = true;
2064 				updateNotesNums(nStyle);
2065 			}
2066 		}
2067 		else if (markAction == "replace")
2068 		{
2069 			Q_ASSERT(currItem != nullptr);
2070 			Q_ASSERT(pos >= 0);
2071 			currItem->itemText.replaceMark(pos, getMark(is->get("label"), (MarkType) is->getInt("type")));
2072 			if (is->contains("strtxtNEW"))
2073 			{
2074 				mrk->setString(is->get("strtxtNEW"));
2075 				invalidateVariableTextFrames(mrk, false);
2076 			}
2077 			if (is->contains("labelNEW"))
2078 				mrk->label = is->get("labelNEW");
2079 		}
2080 		else if (markAction == "edit")
2081 		{
2082 			if (is->contains("labelNEW"))
2083 				mrk->label = is->get("labelNEW");
2084 			if (is->contains("strtxtNEW"))
2085 			{
2086 				mrk->setString(is->get("strtxtNEW"));
2087 				invalidateVariableTextFrames(mrk, false);
2088 			}
2089 			if (is->contains("dNameNEW"))
2090 				mrk->setMark(is->get("dNameNEW"), (MarkType) is->getInt("dTypeNEW"));
2091 			if (is->getItem("itemPtrNEW") != nullptr)
2092 				mrk->setItemPtr((PageItem*) is->getItem("itemPtrNEW"));
2093 		}
2094 		else if (markAction == "insert_existing")
2095 		{
2096 			Q_ASSERT(currItem != nullptr);
2097 			Q_ASSERT(pos >= 0);
2098 			currItem->itemText.insertMark(mrk, pos);
2099 			if (is->contains("strNew"))
2100 			{
2101 				mrk->setString(is->get("strNEW"));
2102 				invalidateVariableTextFrames(mrk, false);
2103 			}
2104 			if (is->contains("labelNEW"))
2105 				mrk->label = is->get("labelNEW");
2106 		}
2107 		else if (markAction == "eraseFromText") //for non-unique marks
2108 		{
2109 			Q_ASSERT(currItem != nullptr);
2110 			Q_ASSERT(pos >= 0);
2111 			currItem->itemText.removeChars(pos, 1);
2112 		}
2113 		else if (markAction == "delete")
2114 		{
2115 			if (!mrk->isUnique())
2116 			{
2117 				Q_ASSERT(currItem != nullptr);
2118 				Q_ASSERT(pos >= 0);
2119 				currItem->itemText.removeChars(pos, 1);
2120 			}
2121 			else
2122 			{
2123 				if (mrk->isType(MARKNoteMasterType))
2124 				{
2125 					TextNote* note = mrk->getNotePtr();
2126 					NotesStyle* nStyle = note->notesStyle();
2127 					if (note->isEndNote())
2128 						flag_updateEndNotes = true;
2129 					deleteNote(note);
2130 					updateNotesNums(nStyle);
2131 				}
2132 				else
2133 					eraseMark(mrk, true);
2134 			}
2135 		}
2136 		else if (markAction == "delNonUnique")
2137 		{
2138 			//used if deleting non-unique marks by MarksManager
2139 			eraseMark(mrk, true, nullptr, true);
2140 		}
2141 		else
2142 		{
2143 			qDebug() << "MARK redo - unhandled " << is->get("MARK");
2144 		}
2145 	}
2146 
2147 	scMW()->emitUpdateRequest(reqMarksUpdate);
2148 	if (currItem != nullptr && !isAutoNoteFrame)
2149 	{
2150 		currItem->invalidateLayout();
2151 		currItem->updateLayout();
2152 	}
2153 }
2154 
restoreNoteStyle(SimpleState * ss,bool isUndo)2155 void ScribusDoc::restoreNoteStyle(SimpleState* ss, bool isUndo)
2156 {
2157 	NotesStyle* noteStyle = nullptr;
2158 	if ((ss->get("NSTYLE") == "new" && isUndo) || (ss->get("NSTYLE") == "delete" && !isUndo))
2159 		deleteNotesStyle(ss->get("name"));
2160 	else if ((ss->get("NSTYLE") == "new" && !isUndo) || (ss->get("NSTYLE") == "delete" && isUndo))
2161 	{
2162 		noteStyle = new NotesStyle();
2163 		noteStyle->setName(ss->get("name"));
2164 		noteStyle->setStart(ss->getInt("start"));
2165 		noteStyle->setEndNotes(ss->getBool("endNotes"));
2166 		noteStyle->setType((NumFormat) ss->getInt("numFormat"));
2167 		noteStyle->setRange((NumerationRange) ss->getInt("range"));
2168 		noteStyle->setPrefix(ss->get("prefix"));
2169 		noteStyle->setSuffix(ss->get("suffix"));
2170 		noteStyle->setAutoNotesHeight(ss->getBool("autoH"));
2171 		noteStyle->setAutoNotesWidth(ss->getBool("autoW"));
2172 		noteStyle->setAutoWeldNotesFrames(ss->getBool("autoWeld"));
2173 		noteStyle->setAutoRemoveEmptyNotesFrames(ss->getBool("autoRemove"));
2174 		noteStyle->setSuperscriptInMaster(ss->getBool("superMaster"));
2175 		noteStyle->setSuperscriptInNote(ss->getBool("superNote"));
2176 		noteStyle->setMarksCharStyle(ss->get("marksChStyle"));
2177 		noteStyle->setNotesParStyle(ss->get("notesParStyle"));
2178 		m_docNotesStylesList.append(noteStyle);
2179 		scMW()->emitUpdateRequest(reqMarksUpdate);
2180 	}
2181 	else if (ss->get("NSTYLE") == "edit")
2182 	{
2183 		if (isUndo)
2184 			noteStyle = getNotesStyle(ss->get("NEWname"));
2185 		else
2186 			noteStyle = getNotesStyle(ss->get("name"));
2187 		Q_ASSERT(noteStyle != nullptr);
2188 		//check if Notes Style change form footnotes to endnotes or range of numeration was changed
2189 		//if use delete all notes frames with current style
2190 		bool delNF = false;
2191 		if (ss->getBool("NEWendNotes") != ss->getBool("endNotes")
2192 			|| ((isUndo && (ss->getBool("endNotes") && (NumerationRange) ss->getInt("range") != (NumerationRange) ss->getInt("NEWrange")))
2193 			|| (!isUndo && (ss->getBool("NEWendNotes") && ((NumerationRange) ss->getInt("NEWrange") != (NumerationRange) ss->getInt("range"))))))
2194 				delNF = true;
2195 		if (delNF)
2196 		{
2197 			auto noteFrameList = listNotesFrames(noteStyle);
2198 			for (PageItem_NoteFrame* noteFrame : qAsConst(noteFrameList))
2199 				delNoteFrame(noteFrame, false);
2200 			flag_updateEndNotes = noteStyle->isEndNotes();
2201 		}
2202 		if (isUndo)
2203 		{
2204 			noteStyle->setName(ss->get("name"));
2205 			noteStyle->setStart(ss->getInt("start"));
2206 			noteStyle->setRange((NumerationRange) ss->getInt("range"));
2207 			noteStyle->setEndNotes(ss->getBool("endNotes"));
2208 			noteStyle->setType((NumFormat) ss->getInt("numFormat"));
2209 			noteStyle->setPrefix(ss->get("prefix"));
2210 			noteStyle->setSuffix(ss->get("suffix"));
2211 			noteStyle->setAutoNotesHeight(ss->getBool("autoH"));
2212 			noteStyle->setAutoNotesWidth(ss->getBool("autoW"));
2213 			noteStyle->setAutoWeldNotesFrames(ss->getBool("autoWeld"));
2214 			noteStyle->setAutoRemoveEmptyNotesFrames(ss->getBool("autoRemove"));
2215 			noteStyle->setSuperscriptInMaster(ss->getBool("superMaster"));
2216 			noteStyle->setSuperscriptInNote(ss->getBool("superNote"));
2217 			noteStyle->setMarksCharStyle(ss->get("marksChStyle"));
2218 			noteStyle->setNotesParStyle(ss->get("notesParStyle"));
2219 		}
2220 		else
2221 		{
2222 			noteStyle->setName(ss->get("NEWname"));
2223 			noteStyle->setStart(ss->getInt("NEWstart"));
2224 			noteStyle->setRange((NumerationRange) ss->getInt("NEWrange"));
2225 			noteStyle->setEndNotes(ss->getBool("NEWendNotes"));
2226 			noteStyle->setType((NumFormat) ss->getInt("NEWnumFormat"));
2227 			noteStyle->setPrefix(ss->get("NEWprefix"));
2228 			noteStyle->setSuffix(ss->get("NEWsuffix"));
2229 			noteStyle->setAutoNotesHeight(ss->getBool("NEWautoH"));
2230 			noteStyle->setAutoNotesWidth(ss->getBool("NEWautoW"));
2231 			noteStyle->setAutoWeldNotesFrames(ss->getBool("NEWautoWeld"));
2232 			noteStyle->setAutoRemoveEmptyNotesFrames(ss->getBool("NEWautoRemove"));
2233 			noteStyle->setSuperscriptInMaster(ss->getBool("NEWsuperMaster"));
2234 			noteStyle->setSuperscriptInNote(ss->getBool("NEWsuperNote"));
2235 			noteStyle->setMarksCharStyle(ss->get("NEWmarksChStyle"));
2236 			noteStyle->setNotesParStyle(ss->get("NEWnotesParStyle"));
2237 		}
2238 		setNotesChanged(true);
2239 		if ((ss->get("marksChStyle") != ss->get("NEWmarksChStyle"))
2240 			|| (ss->getBool("superMaster") != ss->getBool("NEWsuperMaster")))
2241 			invalidateMasterFrames(noteStyle);
2242 		updateNotesNums(noteStyle);
2243 		updateNotesFramesSettings(noteStyle);
2244 		if (flag_updateEndNotes)
2245 			updateEndnotesFrames(noteStyle, true);
2246 		updateNotesFramesStyles(noteStyle);
2247 		if (notesChanged())
2248 		{
2249 			flag_updateMarksLabels = true;
2250 			changed();
2251 			regionsChanged()->update(QRectF());
2252 		}
2253 	}
2254 	if (noteStyle != nullptr)
2255 		scMW()->nsEditor->setNotesStyle(noteStyle);
2256 	else
2257 		scMW()->nsEditor->updateNSList();
2258 }
2259 
restoreDeleteNote(UndoState * state,bool isUndo)2260 void ScribusDoc::restoreDeleteNote(UndoState* state, bool isUndo)
2261 {
2262 	ScItemsState *is = dynamic_cast<ScItemsState*>(state);
2263 	if (!is)
2264 		return;
2265 
2266 	NotesStyle* nStyle = getNotesStyle(is->get("nStyle"));
2267 	PageItem* master = nullptr;
2268 	if (is->contains("noteframeName"))
2269 		master = getItemFromName(is->get("noteframeName"));
2270 	else
2271 		master = (PageItem*) is->getItem("inItem");
2272 
2273 	if (isUndo)
2274 	{
2275 		TextNote* note = newNote(nStyle);
2276 		Mark* mrk = newMark();
2277 		mrk->setType(MARKNoteMasterType);
2278 		mrk->setNotePtr(note);
2279 		note->setMasterMark(mrk);
2280 		note->setSaxedText(is->get("noteTXT"));
2281 		master->itemText.insertMark(mrk, is->getInt("at"));
2282 		master->invalid = true;
2283 		if (!nStyle->isAutoRemoveEmptyNotesFrames())
2284 		{
2285 			PageItem_NoteFrame* nF = (PageItem_NoteFrame*) is->getItem("noteframe");
2286 			Q_ASSERT(nF != nullptr);
2287 			master->asTextFrame()->setNoteFrame(nF);
2288 		}
2289 		setNotesChanged(true);
2290 		if (note->isEndNote())
2291 			flag_updateEndNotes = true;
2292 	}
2293 	else
2294 	{
2295 		TextNote* note = master->itemText.mark(is->getInt("at"))->getNotePtr();
2296 		if (note->isEndNote())
2297 			flag_updateEndNotes = true;
2298 		deleteNote(note);
2299 	}
2300 	master->invalidateLayout();
2301 	master->updateLayout();
2302 }
2303 
setModified(bool isModified)2304 void ScribusDoc::setModified(bool isModified)
2305 {
2306 	if (m_modified != isModified)
2307 	{
2308 		m_modified = isModified;
2309 		update();
2310 	}
2311 }
2312 
isModified() const2313 bool ScribusDoc::isModified() const
2314 {
2315 	return m_modified;
2316 }
2317 
isUndoRedoOngoing() const2318 bool ScribusDoc::isUndoRedoOngoing() const
2319 {
2320 	return (m_undoRedoOngoing != 0);
2321 }
2322 
2323 /** sets page properties */
setPage(double w,double h,double t,double l,double r,double b,double sp,double ab,bool atf,int fp)2324 void ScribusDoc::setPage(double w, double h, double t, double l, double r, double b, double sp, double ab, bool atf, int fp)
2325 {
2326 	m_docPrefsData.docSetupPrefs.pageWidth = w;
2327 	m_docPrefsData.docSetupPrefs.pageHeight = h;
2328 	m_docPrefsData.docSetupPrefs.margins.set(t, l, b ,r);
2329 	PageSp = sp;
2330 	PageSpa = ab;
2331 	m_docPrefsData.docSetupPrefs.pagePositioning = fp;
2332 	m_automaticTextFrames = atf;
2333 }
2334 
2335 
2336 
AddFont(const QString & name,int fsize)2337 bool ScribusDoc::AddFont(const QString& name, int fsize)
2338 {
2339 	if (UsedFonts.contains(name))
2340 		return true;
2341 
2342 	if (! AllFonts->contains(name) || name == "" )
2343 		return false;
2344 
2345 	UsedFonts[name] = fsize;
2346 	(*AllFonts)[name].increaseUsage();
2347 
2348 	return true;
2349 }
2350 
2351 
getItemAttributeNames()2352 QStringList ScribusDoc::getItemAttributeNames()
2353 {
2354 	QStringList nameList;
2355 
2356 	for (ObjAttrVector::Iterator it = itemAttributes().begin(); it!= itemAttributes().end(); ++it)
2357 		nameList.append((*it).name);
2358 	return nameList;
2359 }
2360 
2361 
addSymbols()2362 void ScribusDoc::addSymbols()
2363 {
2364 	symReturn.resize(0);
2365 	symReturn.addQuadPoint(1.98438, 9.14062, 1.98438, 9.14062, 1.98438, 4.03125, 1.98438, 4.03125);
2366 	symReturn.addQuadPoint(1.98438, 4.03125, 1.98438, 4.03125, 0.546875, 3.45312, 1.09375, 4);
2367 	symReturn.addQuadPoint(0.546875, 3.45312, 0.546875, 3.45312, 0, 2.0625, 0, 2.92188);
2368 	symReturn.addQuadPoint(0, 2.0625, 0, 2.0625, 0.65625, 0.5, 0, 1.04688);
2369 	symReturn.addQuadPoint(0.65625, 0.5, 0.65625, 0.5, 2.3125, 0, 1.28125, 0);
2370 	symReturn.addQuadPoint(2.3125, 0, 2.3125, 0, 5.40625, 0, 5.40625, 0);
2371 	symReturn.addQuadPoint(5.40625, 0, 5.40625, 0, 5.40625, 0.84375, 5.40625, 0.84375);
2372 	symReturn.addQuadPoint(5.40625, 0.84375, 5.40625, 0.84375, 4.70312, 0.84375, 4.70312, 0.84375);
2373 	symReturn.addQuadPoint(4.70312, 0.84375, 4.70312, 0.84375, 4.70312, 9.14062, 4.70312, 9.14062);
2374 	symReturn.addQuadPoint(4.70312, 9.14062, 4.70312, 9.14062, 3.875, 9.14062, 3.875, 9.14062);
2375 	symReturn.addQuadPoint(3.875, 9.14062, 3.875, 9.14062, 3.875, 0.84375, 3.875, 0.84375);
2376 	symReturn.addQuadPoint(3.875, 0.84375, 3.875, 0.84375, 2.78125, 0.84375, 2.78125, 0.84375);
2377 	symReturn.addQuadPoint(2.78125, 0.84375, 2.78125, 0.84375, 2.78125, 9.14062, 2.78125, 9.14062);
2378 	symReturn.addQuadPoint(2.78125, 9.14062, 2.78125, 9.14062, 1.98438, 9.14062, 1.98438, 9.14062);
2379 	symNewLine.resize(0);
2380 	symNewLine.addQuadPoint(6.51562, 2.625, 6.51562, 2.625, 0.90625, 2.64062, 0.90625, 2.64062);
2381 	symNewLine.addQuadPoint(0.90625, 2.64062, 0.90625, 2.64062, 1.4375, 1.92188, 1.26562, 2.1875);
2382 	symNewLine.addQuadPoint(1.4375, 1.92188, 1.4375, 1.92188, 1.76562, 1.14062, 1.75, 1.42188);
2383 	symNewLine.addQuadPoint(1.76562, 1.14062, 1.76562, 1.14062, 1.60938, 1.03125, 1.60938, 1.03125);
2384 	symNewLine.addQuadPoint(1.60938, 1.03125, 1.60938, 1.03125, 0.90625, 1.92188, 0.90625, 1.92188);
2385 	symNewLine.addQuadPoint(0.90625, 1.92188, 0.90625, 1.92188, 0, 2.90625, 0.578125, 2.23438);
2386 	symNewLine.addQuadPoint(0, 2.90625, 0, 2.90625, 0.75, 3.875, 0.75, 3.875);
2387 	symNewLine.addQuadPoint(0.75, 3.875, 0.75, 3.875, 1.57812, 4.78125, 1.1875, 4.40625);
2388 	symNewLine.addQuadPoint(1.57812, 4.78125, 1.57812, 4.78125, 1.65625, 4.79688, 1.65625, 4.79688);
2389 	symNewLine.addQuadPoint(1.65625, 4.79688, 1.65625, 4.79688, 1.76562, 4.65625, 1.76562, 4.65625);
2390 	symNewLine.addQuadPoint(1.76562, 4.65625, 1.76562, 4.65625, 0.90625, 3.17188, 1.73438, 4.34375);
2391 	symNewLine.addQuadPoint(0.90625, 3.17188, 0.90625, 3.17188, 0.96875, 3.125, 0.96875, 3.125);
2392 	symNewLine.addQuadPoint(0.96875, 3.125, 0.96875, 3.125, 6.75, 3.125, 6.75, 3.125);
2393 	symNewLine.addQuadPoint(6.75, 3.125, 6.75, 3.125, 6.51562, 2.625, 6.51562, 2.625);
2394 	symNewLine.addQuadPoint(6.51562, 2.625, 6.51562, 2.625, 6.51562, 2.625, 6.51562, 2.625);
2395 	symNewLine.setMarker();
2396 	symNewLine.addQuadPoint(6.875, 0, 6.875, 0, 6.51562, 0, 6.51562, 0);
2397 	symNewLine.addQuadPoint(6.51562, 0, 6.51562, 0, 6.51562, 2.84375, 6.51562, 2.84375);
2398 	symNewLine.addQuadPoint(6.51562, 2.84375, 6.51562, 2.84375, 6.75, 3.125, 6.51562, 3.125);
2399 	symNewLine.addQuadPoint(6.75, 3.125, 6.75, 3.125, 6.85938, 3.0625, 6.85938, 3.0625);
2400 	symNewLine.addQuadPoint(6.85938, 3.0625, 6.85938, 3.0625, 6.875, 0, 6.875, 0);
2401 	symTab.resize(0);
2402 	symTab.addQuadPoint(4.82812, 3.96875, 4.82812, 3.96875, 4.5625, 3.73438, 4.5625, 3.96875);
2403 	symTab.addQuadPoint(4.5625, 3.73438, 4.5625, 3.73438, 5.07812, 3.10938, 4.5625, 3.57812);
2404 	symTab.addQuadPoint(5.07812, 3.10938, 5.07812, 3.10938, 0, 3.10938, 0, 3.10938);
2405 	symTab.addQuadPoint(0, 3.10938, 0, 3.10938, 0, 2.625, 0, 2.625);
2406 	symTab.addQuadPoint(0, 2.625, 0, 2.625, 5.53125, 2.625, 5.53125, 2.625);
2407 	symTab.addQuadPoint(5.53125, 2.625, 5.53125, 2.625, 6.3125, 1.8125, 6.3125, 1.8125);
2408 	symTab.addQuadPoint(6.3125, 1.8125, 6.3125, 1.8125, 5.64062, 1.29688, 5.64062, 1.29688);
2409 	symTab.addQuadPoint(5.64062, 1.29688, 5.64062, 1.29688, 0, 1.29688, 0, 1.29688);
2410 	symTab.addQuadPoint(0, 1.29688, 0, 1.29688, 0, 0.8125, 0, 0.8125);
2411 	symTab.addQuadPoint(0, 0.8125, 0, 0.8125, 5.01562, 0.8125, 5.01562, 0.8125);
2412 	symTab.addQuadPoint(5.01562, 0.8125, 5.01562, 0.8125, 4.45312, 0.265625, 4.45312, 0.453125);
2413 	symTab.addQuadPoint(4.45312, 0.265625, 4.45312, 0.265625, 4.6875, 0, 4.45312, 0);
2414 	symTab.addQuadPoint(4.6875, 0, 4.6875, 0, 5.90625, 0.828125, 4.875, 0);
2415 	symTab.addQuadPoint(5.90625, 0.828125, 5.90625, 0.828125, 6.9375, 1.79688, 6.9375, 1.64062);
2416 	symTab.addQuadPoint(6.9375, 1.79688, 6.9375, 1.79688, 5.95312, 2.96875, 6.9375, 1.95312);
2417 	symTab.addQuadPoint(5.95312, 2.96875, 5.95312, 2.96875, 4.82812, 3.96875, 4.98438, 3.96875);
2418 	symNonBreak.resize(0);
2419 	symNonBreak.addQuadPoint(1.32812, 2.59375, 1.32812, 2.59375, 0.390625, 2.21875, 0.796875, 2.59375);
2420 	symNonBreak.addQuadPoint(0.390625, 2.21875, 0.390625, 2.21875, 0, 1.3125, 0, 1.84375);
2421 	symNonBreak.addQuadPoint(0, 1.3125, 0, 1.3125, 0.390625, 0.390625, 0, 0.765625);
2422 	symNonBreak.addQuadPoint(0.390625, 0.390625, 0.390625, 0.390625, 1.32812, 0, 0.796875, 0);
2423 	symNonBreak.addQuadPoint(1.32812, 0, 1.32812, 0, 2.23438, 0.390625, 1.85938, 0);
2424 	symNonBreak.addQuadPoint(2.23438, 0.390625, 2.23438, 0.390625, 2.60938, 1.29688, 2.60938, 0.765625);
2425 	symNonBreak.addQuadPoint(2.60938, 1.29688, 2.60938, 1.29688, 2.23438, 2.21875, 2.60938, 1.84375);
2426 	symNonBreak.addQuadPoint(2.23438, 2.21875, 2.23438, 2.21875, 1.32812, 2.59375, 1.875, 2.59375);
2427 	symNewCol.resize(0);
2428 	symNewCol.addQuadPoint(1.73438, 0, 1.73438, 0, 2.67188, 0.109375, 2.03125, 0);
2429 	symNewCol.addQuadPoint(2.67188, 0.109375, 2.67188, 0.109375, 3.59375, 0.203125, 3.26562, 0.21875);
2430 	symNewCol.addQuadPoint(3.59375, 0.203125, 3.59375, 0.203125, 3.79688, 0.1875, 3.64062, 0.203125);
2431 	symNewCol.addQuadPoint(3.79688, 0.1875, 3.79688, 0.1875, 4, 0.171875, 3.92188, 0.171875);
2432 	symNewCol.addQuadPoint(4, 0.171875, 4, 0.171875, 4.20312, 0.1875, 4.20312, 0.1875);
2433 	symNewCol.addQuadPoint(4.20312, 0.1875, 4.20312, 0.1875, 4.3125, 1.39062, 4.20312, 0.5625);
2434 	symNewCol.addQuadPoint(4.3125, 1.39062, 4.3125, 1.39062, 4.42188, 2.64062, 4.42188, 2.21875);
2435 	symNewCol.addQuadPoint(4.42188, 2.64062, 4.42188, 2.64062, 4.28125, 2.73438, 4.28125, 2.73438);
2436 	symNewCol.addQuadPoint(4.28125, 2.73438, 4.28125, 2.73438, 3.75, 1.03125, 4.01562, 2.64062);
2437 	symNewCol.addQuadPoint(3.75, 1.03125, 3.75, 1.03125, 3.67188, 1.03125, 3.67188, 1.03125);
2438 	symNewCol.addQuadPoint(3.67188, 1.03125, 3.67188, 1.03125, 0.28125, 6.20312, 0.28125, 6.20312);
2439 	symNewCol.addQuadPoint(0.28125, 6.20312, 0.28125, 6.20312, 0, 5.95312, 0.03125, 6.17188);
2440 	symNewCol.addQuadPoint(0, 5.95312, 0, 5.95312, 3.35938, 0.71875, 3.35938, 0.71875);
2441 	symNewCol.addQuadPoint(3.35938, 0.71875, 3.35938, 0.71875, 3.375, 0.640625, 3.375, 0.640625);
2442 	symNewCol.addQuadPoint(3.375, 0.640625, 3.375, 0.640625, 2.4375, 0.484375, 2.79688, 0.5625);
2443 	symNewCol.addQuadPoint(2.4375, 0.484375, 2.4375, 0.484375, 1.67188, 0.140625, 1.71875, 0.328125);
2444 	symNewCol.addQuadPoint(1.67188, 0.140625, 1.67188, 0.140625, 1.73438, 0, 1.73438, 0);
2445 	symNewFrame.resize(0);
2446 	symNewFrame.addQuadPoint(1.75, 6.20312, 1.75, 6.20312, 2.67188, 6.09375, 2.0625, 6.20312);
2447 	symNewFrame.addQuadPoint(2.67188, 6.09375, 2.67188, 6.09375, 3.60938, 5.98438, 3.28125, 5.98438);
2448 	symNewFrame.addQuadPoint(3.60938, 5.98438, 3.60938, 5.98438, 3.84375, 6.01562, 3.6875, 5.98438);
2449 	symNewFrame.addQuadPoint(3.84375, 6.01562, 3.84375, 6.01562, 4.07812, 6.03125, 4, 6.03125);
2450 	symNewFrame.addQuadPoint(4.07812, 6.03125, 4.07812, 6.03125, 4.20312, 6.01562, 4.20312, 6.01562);
2451 	symNewFrame.addQuadPoint(4.20312, 6.01562, 4.20312, 6.01562, 4.32812, 4.79688, 4.21875, 5.625);
2452 	symNewFrame.addQuadPoint( 4.32812, 4.79688, 4.32812, 4.79688, 4.42188, 3.5625, 4.42188, 3.98438);
2453 	symNewFrame.addQuadPoint(4.42188, 3.5625, 4.42188, 3.5625, 4.29688, 3.45312, 4.29688, 3.45312);
2454 	symNewFrame.addQuadPoint(4.29688, 3.45312, 4.29688, 3.45312, 3.75, 5.17188, 4.03125, 3.54688);
2455 	symNewFrame.addQuadPoint(3.75, 5.17188, 3.75, 5.17188, 3.67188, 5.17188, 3.67188, 5.17188);
2456 	symNewFrame.addQuadPoint(3.67188, 5.17188, 3.67188, 5.17188, 0.28125, 0, 0.28125, 0);
2457 	symNewFrame.addQuadPoint(0.28125, 0, 0.28125, 0, 0, 0.25, 0.03125, 0.015625);
2458 	symNewFrame.addQuadPoint(0, 0.25, 0, 0.25, 3.375, 5.46875, 3.375, 5.46875);
2459 	symNewFrame.addQuadPoint(3.375, 5.46875, 3.375, 5.46875, 3.39062, 5.54688, 3.39062, 5.54688);
2460 	symNewFrame.addQuadPoint(3.39062, 5.54688, 3.39062, 5.54688, 2.4375, 5.70312, 2.8125, 5.625);
2461 	symNewFrame.addQuadPoint(2.4375, 5.70312, 2.4375, 5.70312, 1.67188, 6.0625, 1.71875, 5.875);
2462 	symNewFrame.addQuadPoint(1.67188, 6.0625, 1.67188, 6.0625, 1.75, 6.20312, 1.75, 6.20312);
2463 }
2464 
2465 
addPage(int pageNumber,const QString & masterPageName,bool addAutoFrame)2466 ScPage* ScribusDoc::addPage(int pageNumber, const QString& masterPageName, bool addAutoFrame)
2467 {
2468 	assert(masterPageMode() == false);
2469 	ScPage* addedPage = new ScPage(m_docPrefsData.displayPrefs.scratch.left(), DocPages.count()*(m_docPrefsData.docSetupPrefs.pageHeight+m_docPrefsData.displayPrefs.scratch.bottom()+m_docPrefsData.displayPrefs.scratch.top())+m_docPrefsData.displayPrefs.scratch.top(), m_docPrefsData.docSetupPrefs.pageWidth, m_docPrefsData.docSetupPrefs.pageHeight);
2470 	assert(addedPage != nullptr);
2471 	addedPage->setDocument(this);
2472 	addedPage->Margins.setTop(m_docPrefsData.docSetupPrefs.margins.top());
2473 	addedPage->Margins.setBottom(m_docPrefsData.docSetupPrefs.margins.bottom());
2474 	addedPage->initialMargins = m_docPrefsData.docSetupPrefs.margins;
2475 	addedPage->setPageNr(pageNumber);
2476 	addedPage->setSize(m_docPrefsData.docSetupPrefs.pageSize);
2477 	addedPage->setOrientation(m_docPrefsData.docSetupPrefs.pageOrientation);
2478 	addedPage->marginPreset = m_docPrefsData.docSetupPrefs.marginPreset;
2479 	DocPages.insert(pageNumber, addedPage);
2480 	assert(DocPages.at(pageNumber) != nullptr);
2481 	setCurrentPage(addedPage);
2482 	if (!masterPageName.isEmpty())
2483 		applyMasterPage(masterPageName, pageNumber);
2484 	setLocationBasedPageLRMargins(pageNumber);
2485 	if (addAutoFrame && m_automaticTextFrames)
2486 		addAutomaticTextFrame(pageNumber);
2487 	return addedPage;
2488 }
2489 
2490 
addMasterPage(int pageNumber,const QString & pageName)2491 ScPage* ScribusDoc::addMasterPage(int pageNumber, const QString& pageName)
2492 {
2493 	ScPage* addedPage = new ScPage(m_docPrefsData.displayPrefs.scratch.left(), m_docPrefsData.displayPrefs.scratch.top(), m_docPrefsData.docSetupPrefs.pageWidth, m_docPrefsData.docSetupPrefs.pageHeight);
2494 	assert(addedPage != nullptr);
2495 	addedPage->setDocument(this);
2496 	addedPage->Margins = m_docPrefsData.docSetupPrefs.margins;
2497 	addedPage->initialMargins = m_docPrefsData.docSetupPrefs.margins;
2498 	addedPage->setSize(m_docPrefsData.docSetupPrefs.pageSize);
2499 	addedPage->setOrientation(m_docPrefsData.docSetupPrefs.pageOrientation);
2500 	addedPage->marginPreset = m_docPrefsData.docSetupPrefs.marginPreset;
2501 	addedPage->clearMasterPageName();
2502 	int pgN = pageNumber;
2503 	if (pageNumber > MasterPages.count())
2504 		pgN = MasterPages.count();
2505 	addedPage->setPageName(pageName);
2506 	addedPage->setPageNr(pgN);
2507 	MasterNames.insert(pageName, pgN);
2508 	MasterPages.insert(pgN, addedPage);
2509 	assert(MasterPages.at(pgN) != nullptr);
2510 	if (!isLoading())
2511 		changed();
2512 	if (UndoManager::undoEnabled())
2513 	{
2514 		SimpleState *ss = new SimpleState(Um::NewMasterPage, "", Um::IDocument);
2515 		ss->set("MASTERPAGE_ADD");
2516 		ss->set("MASTERPAGE_NAME", pageName);
2517 		ss->set("MASTERPAGE_NBR", pgN);
2518 		m_undoManager->action(this, ss);
2519 	}
2520 	return addedPage;
2521 }
2522 
2523 
renameMasterPage(const QString & oldPageName,const QString & newPageName)2524 bool ScribusDoc::renameMasterPage(const QString& oldPageName, const QString& newPageName)
2525 {
2526 	Q_ASSERT(oldPageName!=CommonStrings::masterPageNormal && oldPageName!=CommonStrings::trMasterPageNormal);
2527 	if (!MasterNames.contains(oldPageName) || MasterNames.contains(newPageName))
2528 		return false;
2529 
2530 	//Rename our master page lists
2531 	int number = MasterNames[oldPageName];
2532 	MasterNames.insert(newPageName, number);
2533 	MasterNames.remove(oldPageName);
2534 	Q_ASSERT(MasterPages.at(number)->pageName() == oldPageName);
2535 	MasterPages.at(number)->setPageName(newPageName);
2536 	//Update any pages that were linking to our old name
2537 	ScPage* docPage=nullptr;
2538 	for (int i=0; i < DocPages.count(); ++i )
2539 	{
2540 		docPage=DocPages[i];
2541 		if (docPage->masterPageName() == oldPageName)
2542 			docPage->setMasterPageName(newPageName);
2543 	}
2544 	//Update any items that were linking to our old name
2545 	int masterItemsCount=MasterItems.count();
2546 	for (int i = 0; i < masterItemsCount; ++i)
2547 	{
2548 		if (MasterItems.at(i)->OnMasterPage == oldPageName)
2549 			MasterItems.at(i)->setMasterPageName(newPageName);
2550 	}
2551 	changed();
2552 	if (UndoManager::undoEnabled())
2553 	{
2554 		SimpleState *ss = new SimpleState(Um::RenameMasterPage, "", Um::IDocument);
2555 		ss->set("MASTERPAGE_RENAME");
2556 		ss->set("OLD_MASTERPAGE", oldPageName);
2557 		ss->set("NEW_MASTERPAGE", newPageName);
2558 		m_undoManager->action(this, ss);
2559 	}
2560 	return true;
2561 }
2562 
2563 
deleteMasterPage(int pageNumber)2564 void ScribusDoc::deleteMasterPage(int pageNumber)
2565 {
2566 	assert(masterPageMode());
2567 	assert( Pages->count() > 1 && Pages->count() > pageNumber );
2568 	setCurrentPage(Pages->at(0));
2569 	ScPage* page = Pages->takeAt(pageNumber);
2570 	delete page;
2571 	// #10658 : renumber masterpages and masterpage objects
2572 	// in order to avoid crash after masterpage deletion
2573 	for (int i = 0; i < MasterPages.count(); ++i)
2574 		MasterPages.at(i)->setPageNr(i);
2575 	for (int i = 0; i < MasterItems.count(); ++i)
2576 	{
2577 		if (MasterItems.at(i)->OwnPage > pageNumber)
2578 			MasterItems.at(i)->OwnPage--;
2579 	}
2580 	changed();
2581 }
2582 
2583 
rebuildMasterNames()2584 void ScribusDoc::rebuildMasterNames()
2585 {
2586 	MasterNames.clear();
2587 	for (int i = 0; i < MasterPages.count(); ++i)
2588 		MasterNames[MasterPages.at(i)->pageName()] = i;
2589 }
2590 
2591 
replaceMasterPage(const QString & oldMasterPage)2592 void ScribusDoc::replaceMasterPage(const QString& oldMasterPage)
2593 {
2594 	uint pageIndex = 0;
2595 	QMap<QString,int>::Iterator it = MasterNames.begin();
2596 	QListIterator<ScPage *> dpIt(DocPages);
2597 	ScPage* docPage=nullptr;
2598 	while (dpIt.hasNext())
2599 	{
2600 		docPage = dpIt.next();
2601 		if (docPage->masterPageName() == oldMasterPage)
2602 		{
2603 			PageLocation pageLoc = locationOfPage(pageIndex);
2604 			if (pageLoc == LeftPage)
2605 			{
2606 				if (MasterNames.contains(CommonStrings::trMasterPageNormalLeft))
2607 					docPage->setMasterPageName(CommonStrings::trMasterPageNormalLeft);
2608 				else if (MasterNames.contains(CommonStrings::trMasterPageNormal))
2609 					docPage->setMasterPageNameNormal();
2610 				else
2611 					docPage->setMasterPageName(it.key());
2612 			}
2613 			else if (pageLoc == RightPage)
2614 			{
2615 				if (MasterNames.contains(CommonStrings::trMasterPageNormalRight))
2616 					docPage->setMasterPageName(CommonStrings::trMasterPageNormalRight);
2617 				else if (MasterNames.contains(CommonStrings::trMasterPageNormal))
2618 					docPage->setMasterPageNameNormal();
2619 				else
2620 					docPage->setMasterPageName(it.key());
2621 			}
2622 			else
2623 			{
2624 				if (MasterNames.contains(CommonStrings::trMasterPageNormalMiddle))
2625 					docPage->setMasterPageName(CommonStrings::trMasterPageNormalMiddle);
2626 				else if (MasterNames.contains(CommonStrings::trMasterPageNormal))
2627 					docPage->setMasterPageNameNormal();
2628 				else
2629 					docPage->setMasterPageName(it.key());
2630 			}
2631 		}
2632 		pageIndex++;
2633 	}
2634 }
2635 
2636 
deletePage(int pageNumber)2637 void ScribusDoc::deletePage(int pageNumber)
2638 {
2639 	assert( Pages->count() > 1 && Pages->count() > pageNumber );
2640 	//#5561: If we are going to delete the first page, do not set the current page to it
2641 	setCurrentPage(Pages->at(pageNumber!=0?0:1));
2642 	ScPage* page = Pages->takeAt(pageNumber);
2643 	delete page;
2644 	reformPages();
2645 	changed();
2646 }
2647 
swapPage(int a,int b)2648 void ScribusDoc::swapPage(int a, int b)
2649 {
2650 	if (UndoManager::undoEnabled())
2651 	{
2652 		SimpleState *ss = new SimpleState(Um::SwapPage, "", Um::IDocument);
2653 		ss->set("PAGE_SWAP");
2654 		ss->set("PAGE_SWAP_FROM", a);
2655 		ss->set("PAGE_SWAP_TO", b);
2656 		m_undoManager->action(this, ss);
2657 	}
2658 	Pages->swapItemsAt(a, b);
2659 	reformPages();
2660 	changed();
2661 }
2662 
restoreSwapPage(SimpleState * ss,bool isUndo)2663 void ScribusDoc::restoreSwapPage(SimpleState* ss, bool isUndo)
2664 {
2665 	int a = ss->getInt("PAGE_SWAP_FROM");
2666 	int b = ss->getInt("PAGE_SWAP_TO");
2667 
2668 	if (isUndo)
2669 		swapPage(b, a);
2670 	else
2671 		swapPage(a, b);
2672 }
2673 
movePage(int fromPage,int toPage,int dest,int position)2674 void ScribusDoc::movePage(int fromPage, int toPage, int dest, int position)
2675 {
2676 	QList<ScPage*> pageList;
2677 	int numPages = dest;
2678 	pageList.clear();
2679 	for (int i = fromPage; i < toPage; ++i)
2680 	{
2681 		pageList.append(Pages->takeAt(fromPage));
2682 		if (i <= numPages)
2683 			--numPages;
2684 	}
2685 	int pageListCount=pageList.count();
2686 	switch (position)
2687 	{
2688 		case 0: //Before Page
2689 			for (int j = 0; j < pageListCount; ++j)
2690 				Pages->insert(numPages++, pageList.at(j));
2691 			break;
2692 		case 1: //After Page
2693 			for (int j = 0; j < pageListCount; ++j)
2694 				Pages->insert(++numPages, pageList.at(j));
2695 			break;
2696 		case 2: //To End
2697 			for (int j = 0; j < pageListCount; ++j)
2698 				Pages->append(pageList.at(j));
2699 			break;
2700 	}
2701 
2702 	if (UndoManager::undoEnabled())
2703 	{
2704 		SimpleState *ss = new SimpleState(Um::MovePage, "", Um::IDocument);
2705 		ss->set("PAGE_MOVE");
2706 		ss->set("PAGE_MOVE_FROM", fromPage);
2707 		ss->set("PAGE_MOVE_TO", toPage);
2708 		ss->set("PAGE_MOVE_DEST", dest);
2709 		ss->set("PAGE_MOVE_NEWPOS", position);
2710 		m_undoManager->action(this, ss);
2711 	}
2712 	reformPages();
2713 	if (m_View && m_ScMW)
2714 	{
2715 		m_View->reformPagesView();
2716 		m_ScMW->updateGUIAfterPagesChanged();
2717 	}
2718 	updateEndnotesFrames();
2719 	changed();
2720 }
2721 
restoreMovePage(SimpleState * ss,bool isUndo)2722 void ScribusDoc::restoreMovePage(SimpleState* ss, bool isUndo)
2723 {
2724 	int fromPage = ss->getInt("PAGE_MOVE_FROM");
2725 	int toPage = ss->getInt("PAGE_MOVE_TO");
2726 	int position = ss->getInt("PAGE_MOVE_NEWPOS");
2727 	int dest = ss->getInt("PAGE_MOVE_DEST");
2728 
2729 	if (isUndo)
2730 	{
2731 		int newPageDest = fromPage;
2732 		int newPageFrom = 0;
2733 		int newPageTo   = 0;
2734 		int newPosition = 0;
2735 		int pagesMoved  = toPage - fromPage;
2736 		switch (position)
2737 		{
2738 			case 0: //Before Page
2739 				newPageDest = (toPage <= dest) ? fromPage : toPage;
2740 				newPageFrom = (toPage <= dest) ? (dest - pagesMoved) : dest;
2741 				break;
2742 			case 1: //After Page
2743 				newPageDest = (toPage <= dest) ? fromPage : toPage;
2744 				newPageFrom = (toPage <= dest) ? (dest-pagesMoved + 1) : (dest + 1);
2745 				break;
2746 			case 2: //To End
2747 				newPageFrom = Pages->count() - pagesMoved;
2748 				break;
2749 		}
2750 		newPageTo = newPageFrom + pagesMoved;
2751 		movePage(newPageFrom, newPageTo, newPageDest, newPosition);
2752 	}
2753 	else
2754 		movePage(fromPage, toPage, dest, position);
2755 }
2756 
2757 
addAutomaticTextFrame(int pageNumber)2758 int ScribusDoc::addAutomaticTextFrame(int pageNumber)
2759 {
2760 	if (!m_automaticTextFrames)
2761 		return -1;
2762 	ScPage *addToPage=DocPages.at(pageNumber);
2763 	if ((!masterPageMode()) && (usesAutomaticTextFrames()))// && (!isLoading()))
2764 	{
2765 		int z = itemAdd(PageItem::TextFrame, PageItem::Unspecified,
2766 						addToPage->Margins.left()+addToPage->xOffset(),
2767 						addToPage->Margins.top()+addToPage->yOffset(), m_docPrefsData.docSetupPrefs.pageWidth-addToPage->Margins.right()-addToPage->Margins.left(),
2768 						m_docPrefsData.docSetupPrefs.pageHeight-addToPage->Margins.bottom()-addToPage->Margins.top(),
2769 						1, CommonStrings::None, m_docPrefsData.itemToolPrefs.shapeLineColor);
2770 		Items->at(z)->isAutoText = true;
2771 		Items->at(z)->m_columns = qRound(PageSp);
2772 		Items->at(z)->m_columnGap = PageSpa;
2773 		if (LastAuto != nullptr)
2774 			LastAuto->link(Items->at(z));
2775 		else
2776 			FirstAuto = Items->at(z);
2777 		LastAuto = Items->at(z);
2778 		Items->at(z)->setRedrawBounding();
2779 		updateEndnotesFrames();
2780 		return z;
2781 	}
2782 	return -1;
2783 }
2784 
2785 
addLayer(const QString & layerName,bool activate)2786 int ScribusDoc::addLayer(const QString& layerName, bool activate)
2787 {
2788 	int lId = Layers.addLayer(layerName);
2789 	if (lId==-1)
2790 		return -1;
2791 	if (activate)
2792 		setActiveLayer(lId);
2793 	const ScLayer* ll = Layers.layerByID(lId);
2794 	if (!ll)
2795 		qWarning() << "Layer added without undo, could not get layer back for undo action creation";
2796 	else
2797 		if (UndoManager::undoEnabled())
2798 		{
2799 			SimpleState *ss = new SimpleState(Um::AddLayer, "", Um::ICreate);
2800 			ss->set("ADD_LAYER");
2801 			ss->set("ACTIVE", m_ActiveLayer);
2802 			ss->set("NAME", ll->Name);
2803 			ss->set("LAYER_NR", ll->ID);
2804 			m_undoManager->action(this, ss, m_documentFileName, Um::ILayer);
2805 		}
2806 
2807 	changed();
2808 	return lId;
2809 }
2810 
2811 
copyLayer(int layerIDToCopy,int whereToInsert)2812 void ScribusDoc::copyLayer(int layerIDToCopy, int whereToInsert)
2813 {
2814 	if (!setActiveLayer(whereToInsert))
2815 		return;
2816 	Selection sourceSelection(this);
2817 	for (int ite = 0; ite < Items->count(); ++ite)
2818 	{
2819 		PageItem *itemToCopy = Items->at(ite);
2820 		if (itemToCopy->m_layerID == layerIDToCopy)
2821 		{
2822 			sourceSelection.addItem(itemToCopy);
2823 		}
2824 	}
2825 	if (sourceSelection.count() != 0)
2826 	{
2827 		ScriXmlDoc ss;
2828 		QString dataS = ss.writeElem(this, &sourceSelection);
2829 		ss.readElemToLayer(dataS, this, Pages->at(0)->xOffset(), Pages->at(0)->yOffset(), false, true, whereToInsert);
2830 	}
2831 	sourceSelection.clear();
2832 	changed();
2833 }
2834 
2835 
deleteLayer(int layerID,bool deleteItems)2836 bool ScribusDoc::deleteLayer(int layerID, bool deleteItems)
2837 {
2838 	if (Layers.count() < 2)
2839 		return false;
2840 	const ScLayer* lToRemove = Layers.layerByID(layerID);
2841 	if (!lToRemove)
2842 		return false;
2843 	int layerLevel = lToRemove->Level;
2844 	QString name   = lToRemove->Name;
2845 	UndoTransaction activeTransaction;
2846 	if (UndoManager::undoEnabled())
2847 		activeTransaction = m_undoManager->beginTransaction(Um::Layer, Um::IDocument, Um::DeleteLayer, "", Um::IDelete);
2848 
2849 	rebuildItemLists();
2850 	if (ScCore->usingGUI())
2851 		removeLayer(layerID, deleteItems);
2852 
2853 	//Now delete the layer
2854 	Layers.removeLayerByID(layerID);
2855 
2856 	if (activeTransaction)
2857 	{
2858 		SimpleState *ss = new SimpleState(Um::DeleteLayer, "", Um::IDelete);
2859 		ss->set("REMOVE_LAYER");
2860 		ss->set("ACTIVE", layerID);
2861 		ss->set("LEVEL", layerLevel);
2862 		ss->set("NAME", name);
2863 		ss->set("LAYER_NR", layerID);
2864 		ss->set("DELETE", deleteItems);
2865 		m_undoManager->action(this, ss, m_documentFileName, Um::ILayer);
2866 		activeTransaction.commit();
2867 	}
2868 
2869 	changed();
2870 	return true;
2871 }
2872 
2873 
activeLayer()2874 int ScribusDoc::activeLayer()
2875 {
2876 	return m_ActiveLayer;
2877 }
2878 
2879 
activeLayerName()2880 const QString& ScribusDoc::activeLayerName()
2881 {
2882 	const ScLayer* ll = Layers.layerByID(m_ActiveLayer);
2883 	Q_ASSERT(ll);
2884 	return ll->Name;
2885 }
2886 
2887 
setActiveLayer(int layerToActivate)2888 bool ScribusDoc::setActiveLayer(int layerToActivate)
2889 {
2890 	const ScLayer* ll = Layers.layerByID(layerToActivate);
2891 	Q_ASSERT(ll);
2892 	if (ll)
2893 		m_ActiveLayer = layerToActivate;
2894 	return (ll != nullptr);
2895 }
2896 
2897 
setActiveLayer(const QString & layerNameToActivate)2898 bool ScribusDoc::setActiveLayer(const QString& layerNameToActivate)
2899 {
2900 	const ScLayer* ll = Layers.layerByName(layerNameToActivate);
2901 	Q_ASSERT(ll);
2902 	if (ll)
2903 		m_ActiveLayer=ll->ID;
2904 	return (ll != nullptr);
2905 }
2906 
2907 
setLayerPrintable(int layerID,bool isPrintable)2908 bool ScribusDoc::setLayerPrintable(int layerID, bool isPrintable)
2909 {
2910 	bool found = false;
2911 	auto itend = Layers.end();
2912 	for (auto it = Layers.begin(); it != itend; ++it)
2913 	{
2914 		if (it->ID == layerID)
2915 		{
2916 			if (it->isPrintable!=isPrintable && UndoManager::undoEnabled())
2917 			{
2918 				SimpleState *ss = new SimpleState(isPrintable ? Um::PrintLayer : Um::DoNotPrintLayer, "", Um::IPrint);
2919 				ss->set("PRINT_LAYER");
2920 				ss->set("ACTIVE", it->ID);
2921 				ss->set("PRINT", isPrintable);
2922 				m_undoManager->action(this, ss, it->Name, Um::ILayer);
2923 			}
2924 			it->isPrintable = isPrintable;
2925 			found=true;
2926 			break;
2927 		}
2928 	}
2929 	if (found)
2930 		changed();
2931 	return found;
2932 }
2933 
2934 
layerPrintable(int layerID) const2935 bool ScribusDoc::layerPrintable(int layerID) const
2936 {
2937 	auto itend = Layers.cend();
2938 	for (auto it = Layers.cbegin(); it != itend; ++it)
2939 	{
2940 		if (it->ID == layerID)
2941 			return it->isPrintable;
2942 	}
2943 	return false;
2944 }
2945 
2946 
setLayerVisible(int layerID,bool isViewable)2947 bool ScribusDoc::setLayerVisible(int layerID, bool isViewable)
2948 {
2949 	bool found = false;
2950 	auto itend = Layers.end();
2951 	for (auto it = Layers.begin(); it != itend; ++it)
2952 	{
2953 		if (it->ID == layerID)
2954 		{
2955 			it->isViewable = isViewable;
2956 			found=true;
2957 			break;
2958 		}
2959 	}
2960 	if (found)
2961 		changed();
2962 	return found;
2963 }
2964 
2965 
layerVisible(int layerID) const2966 bool ScribusDoc::layerVisible(int layerID) const
2967 {
2968 	auto itend = Layers.cend();
2969 	for (auto it = Layers.cbegin(); it != itend; ++it)
2970 	{
2971 		if (it->ID == layerID)
2972 			return it->isViewable;
2973 	}
2974 	return false;
2975 }
2976 
setLayerSelectable(int layerID,bool isSelectable)2977 bool ScribusDoc::setLayerSelectable(int layerID, bool isSelectable)
2978 {
2979 	bool found = false;
2980 	auto itend = Layers.end();
2981 	for (auto it = Layers.begin(); it != itend; ++it)
2982 	{
2983 		if (it->ID == layerID)
2984 		{
2985 			it->isSelectable = isSelectable;
2986 			found=true;
2987 			break;
2988 		}
2989 	}
2990 	if (found)
2991 		changed();
2992 	return found;
2993 }
2994 
2995 
layerSelectable(int layerID) const2996 bool ScribusDoc::layerSelectable(int layerID) const
2997 {
2998 	auto itend = Layers.cend();
2999 	for (auto it = Layers.cbegin(); it != itend; ++it)
3000 	{
3001 		if (it->ID == layerID)
3002 			return it->isSelectable;
3003 	}
3004 	return false;
3005 }
3006 
3007 
setLayerLocked(int layerID,bool isLocked)3008 bool ScribusDoc::setLayerLocked(int layerID, bool isLocked)
3009 {
3010 	bool found = false;
3011 	auto itend = Layers.end();
3012 	for (auto it = Layers.begin(); it != itend; ++it)
3013 	{
3014 		if (it->ID == layerID)
3015 		{
3016 			// == because isEditable vs isLocked...
3017 			if (it->isEditable==isLocked && UndoManager::undoEnabled())
3018 			{
3019 				SimpleState *ss = new SimpleState(isLocked ? Um::SetLayerLocked : Um::SetLayerUnlocked, "", Um::ILayer);
3020 				ss->set("LAYER_LOCK");
3021 				ss->set("ACTIVE", it->ID);
3022 				ss->set("LOCK", isLocked);
3023 				m_undoManager->action(this, ss, it->Name, Um::ILayer);
3024 			}
3025 			it->isEditable = !isLocked;
3026 			found=true;
3027 			break;
3028 		}
3029 	}
3030 	if (found)
3031 		changed();
3032 	return found;
3033 }
3034 
3035 
layerLocked(int layerID) const3036 bool ScribusDoc::layerLocked(int layerID) const
3037 {
3038 	auto itend = Layers.cend();
3039 	for (auto it = Layers.cbegin(); it != itend; ++it)
3040 	{
3041 		if (it->ID == layerID)
3042 			return !it->isEditable;
3043 	}
3044 	return false;
3045 }
3046 
3047 
setLayerFlow(int layerID,bool flow)3048 bool ScribusDoc::setLayerFlow(int layerID, bool flow)
3049 {
3050 	bool found = false;
3051 	auto itend = Layers.end();
3052 	for (auto it = Layers.begin(); it != itend; ++it)
3053 	{
3054 		if (it->ID == layerID)
3055 		{
3056 			if (it->flowControl!=flow && UndoManager::undoEnabled())
3057 			{
3058 				SimpleState *ss = new SimpleState(flow ? Um::FlowLayer : Um::DisableFlowLayer, "", Um::ITextFrame);
3059 				ss->set("LAYER_FLOW");
3060 				ss->set("ACTIVE", it->ID);
3061 				ss->set("FLOW", flow);
3062 				m_undoManager->action(this, ss, it->Name, Um::ILayer);
3063 			}
3064 			it->flowControl = flow;
3065 			found=true;
3066 			break;
3067 		}
3068 	}
3069 	if (found)
3070 	{
3071 		// #9188 : invalidate layout of items below layer
3072 		for (auto it = Layers.begin(); it != itend; ++it)
3073 		{
3074 			if (it->ID == layerID)
3075 				break;
3076 			invalidateLayer(it->ID);
3077 		}
3078 		changed();
3079 	}
3080 	return found;
3081 }
3082 
3083 
layerFlow(int layerID) const3084 bool ScribusDoc::layerFlow(int layerID) const
3085 {
3086 	auto itend = Layers.cend();
3087 	for (auto it = Layers.cbegin(); it != itend; ++it)
3088 	{
3089 		if (it->ID == layerID)
3090 			return it->flowControl;
3091 	}
3092 	return false;
3093 }
3094 
3095 
setLayerTransparency(int layerID,double trans)3096 bool ScribusDoc::setLayerTransparency(int layerID, double trans)
3097 {
3098 	bool found = false;
3099 	auto itend = Layers.end();
3100 	for (auto it = Layers.begin(); it != itend; ++it)
3101 	{
3102 		if (it->ID == layerID)
3103 		{
3104 			if (it->transparency!=trans && UndoManager::undoEnabled())
3105 			{
3106 				SimpleState *ss = new SimpleState(Um::SetLayerTransparency, "", Um::ILayer);
3107 				ss->set("LAYER_TRANSPARENCY");
3108 				ss->set("ACTIVE", it->ID);
3109 				ss->set("OLD_TRANS", it->transparency);
3110 				ss->set("NEW_TRANS", trans);
3111 				m_undoManager->action(this, ss, it->Name, Um::ILayer);
3112 			}
3113 			it->transparency = trans;
3114 			found=true;
3115 			break;
3116 		}
3117 	}
3118 	if (found)
3119 		changed();
3120 	return found;
3121 }
3122 
3123 
layerTransparency(int layerID) const3124 double ScribusDoc::layerTransparency(int layerID) const
3125 {
3126 	auto itend = Layers.cend();
3127 	for (auto it = Layers.cbegin(); it != itend; ++it)
3128 	{
3129 		if (it->ID == layerID)
3130 			return it->transparency;
3131 	}
3132 	return 1.0;
3133 }
3134 
3135 
setLayerBlendMode(int layerID,int blend)3136 bool ScribusDoc::setLayerBlendMode(int layerID, int blend)
3137 {
3138 	bool found = false;
3139 	auto itend = Layers.end();
3140 	for (auto it = Layers.begin(); it != itend; ++it)
3141 	{
3142 		if (it->ID == layerID)
3143 		{
3144 			if (it->blendMode!=blend && UndoManager::undoEnabled())
3145 			{
3146 				SimpleState *ss = new SimpleState(Um::SetLayerBlendMode, "", Um::ILayer);
3147 				ss->set("LAYER_BLENDMODE");
3148 				ss->set("ACTIVE", it->ID);
3149 				ss->set("OLD_BLENDMODE", it->blendMode);
3150 				ss->set("NEW_BLENDMODE", blend);
3151 				m_undoManager->action(this, ss, it->Name, Um::ILayer);
3152 			}
3153 			it->blendMode = blend;
3154 			found=true;
3155 			break;
3156 		}
3157 	}
3158 	if (found)
3159 		changed();
3160 	return found;
3161 }
3162 
3163 
layerBlendMode(int layerID) const3164 int ScribusDoc::layerBlendMode(int layerID) const
3165 {
3166 	auto itend = Layers.cend();
3167 	for (auto it = Layers.cbegin(); it != itend; ++it)
3168 	{
3169 		if (it->ID == layerID)
3170 			return it->blendMode;
3171 	}
3172 	return 0;
3173 }
3174 
3175 
setLayerOutline(int layerID,bool outline)3176 bool ScribusDoc::setLayerOutline(int layerID, bool outline)
3177 {
3178 	bool found = false;
3179 	auto itend = Layers.end();
3180 	for (auto it = Layers.begin(); it != itend; ++it)
3181 	{
3182 		if (it->ID == layerID)
3183 		{
3184 			it->outlineMode = outline;
3185 			found=true;
3186 			break;
3187 		}
3188 	}
3189 	if (found)
3190 		changed();
3191 	return found;
3192 }
3193 
3194 
layerOutline(int layerID) const3195 bool ScribusDoc::layerOutline(int layerID) const
3196 {
3197 	auto  itend = Layers.cend();
3198 	for (auto it = Layers.cbegin(); it != itend; ++it)
3199 	{
3200 		if (it->ID == layerID)
3201 			return it->outlineMode;
3202 	}
3203 	return false;
3204 }
3205 
3206 
setLayerMarker(int layerID,const QColor & color)3207 bool ScribusDoc::setLayerMarker(int layerID, const QColor& color)
3208 {
3209 	bool found = false;
3210 	auto itend = Layers.end();
3211 	for (auto it = Layers.begin(); it != itend; ++it)
3212 	{
3213 		if (it->ID == layerID)
3214 		{
3215 			it->markerColor = color;
3216 			found=true;
3217 			break;
3218 		}
3219 	}
3220 	if (found)
3221 		changed();
3222 	return found;
3223 }
3224 
3225 
layerMarker(int layerID) const3226 QColor ScribusDoc::layerMarker(int layerID) const
3227 {
3228 	auto itend = Layers.cend();
3229 	for (auto it = Layers.cbegin(); it != itend; ++it)
3230 	{
3231 		if (it->ID == layerID)
3232 			return it->markerColor;
3233 	}
3234 	return QColor(0, 0, 0);
3235 }
3236 
3237 
layerLevelFromID(int layerID) const3238 int ScribusDoc::layerLevelFromID(int layerID) const
3239 {
3240 	int layerCount = Layers.count();
3241 	for (int i=0; i < layerCount; ++i)
3242 	{
3243 		const ScLayer& layer = Layers.at(i);
3244 		if (layer.ID == layerID)
3245 			return layer.Level;
3246 	}
3247 	return -1;
3248 }
3249 
3250 
layerCount() const3251 int ScribusDoc::layerCount() const
3252 {
3253 	return Layers.count();
3254 }
3255 
3256 
layerIDFromLevel(int layerLevel) const3257 int ScribusDoc::layerIDFromLevel(int layerLevel) const
3258 {
3259 	int layerCount = Layers.count();
3260 	for (int i = 0; i < layerCount; ++i)
3261 	{
3262 		const ScLayer& layer = Layers.at(i);
3263 		if (layer.Level == layerLevel)
3264 			return layer.ID;
3265 	}
3266 	return -1;
3267 }
3268 
layerIDFromName(const QString & name) const3269 int ScribusDoc::layerIDFromName(const QString& name) const
3270 {
3271 	auto itend = Layers.cend();
3272 	for (auto it = Layers.cbegin(); it != itend; ++it)
3273 	{
3274 		if (it->Name == name)
3275 			return it->ID;
3276 	}
3277 	return -1;
3278 }
3279 
lowerLayer(int layerID)3280 bool ScribusDoc::lowerLayer(int layerID)
3281 {
3282 	return lowerLayerByLevel(layerLevelFromID(layerID));
3283 }
3284 
3285 
lowerLayerByLevel(int layerLevel)3286 bool ScribusDoc::lowerLayerByLevel(int layerLevel)
3287 {
3288 	if (layerLevel <= 0)
3289 		return false;
3290 	if (Layers.count() < 2)
3291 		return false;
3292 	if (UndoManager::undoEnabled())
3293 	{
3294 		SimpleState *ss = new SimpleState(Um::LowerLayer, "", Um::IDown);
3295 		ss->set("DOWN_LAYER");
3296 		ss->set("ACTIVE", layerIDFromLevel(layerLevel));
3297 		m_undoManager->action(this, ss, m_documentFileName, Um::ILayer);
3298 	}
3299 
3300 	ScLayers::iterator it;
3301 	ScLayers::iterator itend=Layers.end();
3302 	for (it = Layers.begin(); it != itend; ++it)
3303 	{
3304 		if (it->Level == layerLevel-1)
3305 			break;
3306 	}
3307 	ScLayers::iterator it2;
3308 	ScLayers::iterator it2end=Layers.end();
3309 	for (it2 = Layers.begin(); it2 != it2end; ++it2)
3310 	{
3311 		if (it2->Level == layerLevel)
3312 			break;
3313 	}
3314 	it2->Level -= 1;
3315 	it->Level  += 1;
3316 	// #9188 : invalidate layout of items in below layers
3317 	int maxLevel = qMax(it->Level, it2->Level);
3318 	for (it = Layers.begin(); it != itend; ++it)
3319 	{
3320 		if (it->flowControl)
3321 			invalidateLayer(it->ID);
3322 		if (it->Level == maxLevel)
3323 			break;
3324 	}
3325 	return true;
3326 }
3327 
3328 
raiseLayer(int layerID)3329 bool ScribusDoc::raiseLayer(int layerID)
3330 {
3331 	return raiseLayerByLevel(layerLevelFromID(layerID));
3332 }
3333 
3334 
raiseLayerByLevel(int layerLevel)3335 bool ScribusDoc::raiseLayerByLevel(int layerLevel)
3336 {
3337 	if (layerLevel >= Layers.count() - 1)
3338 		return false;
3339 	if (Layers.count() < 2)
3340 		return false;
3341 	if (UndoManager::undoEnabled())
3342 	{
3343 		SimpleState *ss = new SimpleState(Um::RaiseLayer, "", Um::IUp);
3344 		ss->set("UP_LAYER");
3345 		ss->set("ACTIVE", layerIDFromLevel(layerLevel));
3346 		m_undoManager->action(this, ss, m_documentFileName, Um::ILayer);
3347 	}
3348 
3349 	ScLayers::iterator it;
3350 	ScLayers::iterator itend=Layers.end();
3351 	for (it = Layers.begin(); it != itend; ++it)
3352 	{
3353 		if (it->Level == layerLevel+1)
3354 			break;
3355 	}
3356 	ScLayers::iterator it2;
3357 	ScLayers::iterator it2end=Layers.end();
3358 	for (it2 = Layers.begin(); it2 != it2end; ++it2)
3359 	{
3360 		if (it2->Level == layerLevel)
3361 			break;
3362 	}
3363 	it2->Level += 1;
3364 	it->Level  -= 1;
3365 	// #9188 : invalidate layout of items in below layers
3366 	int maxLevel = qMax(it->Level, it2->Level);
3367 	for (it = Layers.begin(); it != itend; ++it)
3368 	{
3369 		if (it->flowControl)
3370 			invalidateLayer(it->ID);
3371 		if (it->Level == maxLevel)
3372 			break;
3373 	}
3374 	return true;
3375 }
3376 
3377 
layerName(int layerID) const3378 QString ScribusDoc::layerName(int layerID) const
3379 {
3380 	int layerCount = Layers.count();
3381 	for (int i=0; i < layerCount; ++i)
3382 	{
3383 		const ScLayer& layer = Layers[i];
3384 		if (layer.ID == layerID)
3385 			return layer.Name;
3386 	}
3387 	return QString();
3388 }
3389 
3390 
changeLayerName(int layerID,const QString & newName)3391 bool ScribusDoc::changeLayerName(int layerID, const QString& newName)
3392 {
3393 	int layerCount=Layers.count();
3394 	bool found=false;
3395 	for (int i=0; i < layerCount; ++i)
3396 	{
3397 		if (Layers[i].ID == layerID)
3398 		{
3399 			if (Layers[i].Name != newName)
3400 			{
3401 				if (UndoManager::undoEnabled())
3402 				{
3403 					SimpleState *ss = new SimpleState(Um::SetLayerName, QString(Um::FromTo).arg(Layers[i].Name, newName), Um::IDown);
3404 					ss->set("CHANGE_NAME");
3405 					ss->set("ACTIVE", m_ActiveLayer);
3406 					ss->set("NEW_NAME", newName);
3407 					ss->set("OLD_NAME", Layers[i].Name);
3408 					m_undoManager->action(this, ss, m_documentFileName, Um::ILayer);
3409 				}
3410 				Layers[i].Name = newName;
3411 				found=true;
3412 			}
3413 			break;
3414 		}
3415 	}
3416 	if (found)
3417 		changed();
3418 	return found;
3419 }
3420 
canSelectItemOnLayer(int layerID) const3421 bool ScribusDoc::canSelectItemOnLayer(int layerID) const
3422 {
3423 	if ((m_ActiveLayer != layerID) && !layerSelectable(layerID))
3424 		return false;
3425 
3426 	bool canSelect = layerVisible(layerID);
3427 	if (!canSelect)
3428 		return false;
3429 	canSelect = !layerLocked(layerID);
3430 	return canSelect;
3431 }
3432 
layerContainsItems(int layerID) const3433 bool ScribusDoc::layerContainsItems(int layerID) const
3434 {
3435 	QList<PageItem*> allItems;
3436 	int masterItemsCount = MasterItems.count();
3437 	for (int i = 0; i < masterItemsCount; ++i)
3438 	{
3439 		PageItem* currItem = MasterItems.at(i);
3440 		if (currItem->isGroup())
3441 			allItems = currItem->getAllChildren();
3442 		else
3443 			allItems.append(currItem);
3444 		for (int ii = 0; ii < allItems.count(); ii++)
3445 		{
3446 			currItem = allItems.at(ii);
3447 			if (currItem->m_layerID == layerID)
3448 				return true;
3449 		}
3450 		allItems.clear();
3451 	}
3452 
3453 	int docItemsCount = DocItems.count();
3454 	for (int i = 0; i < docItemsCount; ++i)
3455 	{
3456 		PageItem* currItem = DocItems.at(i);
3457 		if (currItem->isGroup())
3458 			allItems = currItem->getAllChildren();
3459 		else
3460 			allItems.append(currItem);
3461 		for (int ii = 0; ii < allItems.count(); ii++)
3462 		{
3463 			currItem = allItems.at(ii);
3464 			if (currItem->m_layerID == layerID)
3465 				return true;
3466 		}
3467 		allItems.clear();
3468 	}
3469 	return false;
3470 }
3471 
3472 
orderedLayerList(QStringList * list) const3473 void ScribusDoc::orderedLayerList(QStringList* list) const
3474 {
3475 	Q_ASSERT(list != nullptr);
3476 
3477 	int layerCount = Layers.count();
3478 	if (layerCount == 0)
3479 		return;
3480 
3481 	for (int i=0; i < layerCount; ++i)
3482 	{
3483 		auto itend = Layers.cend();
3484 		for (auto it = Layers.cbegin(); it != itend; ++it)
3485 		{
3486 			if (layerCount - it->Level - 1 == i)
3487 				list->append(it->Name);
3488 		}
3489  	}
3490 }
3491 
firstLayerID() const3492 int ScribusDoc::firstLayerID() const
3493 {
3494 	QStringList newNames;
3495 	orderedLayerList(&newNames);
3496 	return layerIDFromName(newNames.first());
3497 }
3498 
renumberLayer(int layerID,int newLayerID)3499 bool ScribusDoc::renumberLayer(int layerID, int newLayerID)
3500 {
3501 	int layerCount=Layers.count();
3502 	int foundIndex = 0;
3503 	bool found=false;
3504 	//Find layer to renumber, if found the new number, return as it exists already.
3505 	for (int i=0; i < layerCount; ++i)
3506 	{
3507 		if (Layers[i].ID == layerID)
3508 		{
3509 			foundIndex=i;
3510 			found=true;
3511 		}
3512 		else
3513 		if (Layers[i].ID == newLayerID)
3514 			return false;
3515 	}
3516 	if (!found)
3517 		return false;
3518 	Layers[foundIndex].ID=newLayerID;
3519 	return true;
3520 }
3521 
replaceLineStyleColors(const QMap<QString,QString> & colorMap)3522 void ScribusDoc::replaceLineStyleColors(const QMap<QString, QString>& colorMap)
3523 {
3524 	multiLine::iterator its;
3525 	QMap<QString, QString>::const_iterator it;
3526 	for (auto itl = docLineStyles.begin(); itl != docLineStyles.end(); ++itl)
3527 	{
3528 		multiLine& mline = itl.value();
3529 		for (its = mline.begin(); its != mline.end(); ++its)
3530 		{
3531 			struct SingleLine& sline = *its;
3532 			it = colorMap.find(sline.Color);
3533 			if (it != colorMap.end())
3534 				sline.Color = it.value();
3535 		}
3536 	}
3537 }
3538 
getUsedColors(ColorList & colorsToUse,bool spot) const3539 void ScribusDoc::getUsedColors(ColorList &colorsToUse, bool spot) const
3540 {
3541 	bool found;
3542 	colorsToUse.clear();
3543 	colorsToUse.setDocument(const_cast<ScribusDoc*>(this));
3544 
3545 	ResourceCollection resources;
3546 	this->getNamedResources(resources);
3547 	const QMap<QString, QString>& resColors = resources.colors();
3548 
3549 	for (auto it = PageColors.cbegin(); it != PageColors.cend(); ++it)
3550 	{
3551 		found = false;
3552 		// Tool preferences colors
3553 		if ((it.key() == m_docPrefsData.itemToolPrefs.shapeFillColor) || (it.key() == m_docPrefsData.itemToolPrefs.shapeLineColor) || (it.key() == m_docPrefsData.itemToolPrefs.imageFillColor)
3554 				 || (it.key() == m_docPrefsData.itemToolPrefs.imageStrokeColor) || (it.key() == m_docPrefsData.itemToolPrefs.lineColor) || (it.key() == m_docPrefsData.itemToolPrefs.textColor))
3555 		{
3556 			if (spot)
3557 			{
3558 				if (it.value().isSpotColor())
3559 					colorsToUse.insert(it.key(), it.value());
3560 			}
3561 			else
3562 				colorsToUse.insert(it.key(), it.value());
3563 			continue;
3564 		}
3565 		// Current paragraph style colors
3566 		if ((it.key() == currentStyle.charStyle().fillColor()) || (it.key() == currentStyle.charStyle().strokeColor()) || (it.key() == currentStyle.charStyle().backColor()))
3567 			found = true;
3568 		// Resources colors
3569 		if (!found)
3570 			found = resColors.contains(it.key());
3571 		// Line styles colors
3572 		if (!found)
3573 			found = lineStylesUseColor(it.key());
3574 		if (found)
3575 		{
3576 			if (spot)
3577 			{
3578 				if (it.value().isSpotColor())
3579 					colorsToUse.insert(it.key(), it.value());
3580 			}
3581 			else
3582 				colorsToUse.insert(it.key(), it.value());
3583 			continue;
3584 		}
3585 	}
3586 }
3587 
arrowStyle(const QString & name)3588 ArrowDesc* ScribusDoc::arrowStyle(const QString& name)
3589 {
3590 	for (ArrowDesc& arrowDesc : m_docPrefsData.arrowStyles)
3591 	{
3592 		if (arrowDesc.name == name)
3593 			return &arrowDesc;
3594 	}
3595 	return nullptr;
3596 }
3597 
hasArrowStyle(const QString & name) const3598 bool ScribusDoc::hasArrowStyle(const QString& name) const
3599 {
3600 	for (const ArrowDesc& arrowDesc : m_docPrefsData.arrowStyles)
3601 	{
3602 		if (arrowDesc.name == name)
3603 			return true;
3604 	}
3605 	return false;
3606 }
3607 
lineStylesUseColor(const QString & colorName) const3608 bool ScribusDoc::lineStylesUseColor(const QString& colorName) const
3609 {
3610 	bool found = false;
3611 	multiLine::const_iterator its, itsend;
3612 	auto itmend = docLineStyles.constEnd();
3613 	for (auto itm = docLineStyles.constBegin(); itm != itmend && !found; ++itm)
3614 	{
3615 		const multiLine& ml = itm.value();
3616 		itsend = ml.constEnd();
3617 		for (its = ml.constBegin(); its != itsend; ++its)
3618 		{
3619 			if (its->Color == colorName)
3620 			{
3621 				found = true;
3622 				break;
3623 			}
3624 		}
3625 	}
3626 	return found;
3627 }
3628 
getUsedGradients(QHash<QString,VGradient> & gradients) const3629 void ScribusDoc::getUsedGradients(QHash<QString, VGradient> &gradients) const
3630 {
3631 	ResourceCollection resources;
3632 	this->getNamedResources(resources);
3633 	const QMap<QString, QString>& resGradients = resources.gradients();
3634 	for (auto it = docGradients.cbegin(); it != docGradients.cend(); ++it)
3635 	{
3636 		if (resGradients.contains(it.key()))
3637 			gradients.insert(it.key(), it.value());
3638 	}
3639 }
3640 
addGradient(QString & name,const VGradient & gradient)3641 bool ScribusDoc::addGradient(QString &name, const VGradient &gradient)
3642 {
3643 	for (auto it = docGradients.cbegin(); it != docGradients.cend(); ++it)
3644  	{
3645 		if (it.value() == gradient)
3646 		{
3647 			name = it.key();
3648 			return false;
3649 		}
3650  	}
3651 	QString tmp;
3652 	if (docGradients.contains(name))
3653 		name += "("+tmp.setNum(docGradients.count())+")";
3654 	docGradients.insert(name, gradient);
3655 	return true;
3656 }
3657 
setGradients(const QHash<QString,VGradient> & gradients)3658 void ScribusDoc::setGradients(const QHash<QString, VGradient> &gradients)
3659 {
3660 	docGradients.clear();
3661 	docGradients = gradients;
3662 }
3663 
addPattern(QString & name,ScPattern & pattern)3664 bool ScribusDoc::addPattern(QString &name, ScPattern& pattern)
3665 {
3666 	QString tmp;
3667 	if (docPatterns.contains(name))
3668 		name += "("+tmp.setNum(docPatterns.count())+")";
3669 //		name = tr("Copy_of_")+name;
3670 	docPatterns.insert(name, pattern);
3671 	QList<PageItem*> allItems = getAllItems(pattern.items);
3672 	for (int i = 0; i < allItems.count(); i++)
3673 	{
3674 		PageItem* currItem = allItems.at(i);
3675 		currItem->setLayer(0);
3676 	}
3677 	return true;
3678 }
3679 
removePattern(const QString & name)3680 void ScribusDoc::removePattern(const QString& name)
3681 {
3682 	docPatterns.remove(name);
3683 
3684 	for (PageItemIterator it(this, PageItemIterator::IterateInDocDefaults); *it; ++it)
3685 	{
3686 		PageItem *currItem = *it;
3687 		if (currItem->pattern() == name)
3688 			currItem->setPattern(QString());
3689 		if (currItem->strokePattern() == name)
3690 			currItem->setStrokePattern(QString());
3691 	}
3692 }
3693 
checkedPattern(const QString & name)3694 ScPattern* ScribusDoc::checkedPattern(const QString &name)
3695 {
3696 	if (name.isEmpty() || !docPatterns.contains(name))
3697 		return nullptr;
3698 	ScPattern* pattern = &docPatterns[name];
3699 	if (pattern->width <= 0 || pattern->height <= 0)
3700 		return nullptr;
3701 	if (pattern->getPattern()->isNull())
3702 		return nullptr;
3703 	return pattern;
3704 }
3705 
setPatterns(const QHash<QString,ScPattern> & patterns)3706 void ScribusDoc::setPatterns(const QHash<QString, ScPattern> &patterns)
3707 {
3708 	docPatterns.clear();
3709 	docPatterns = patterns;
3710 }
3711 
getUniquePatternName(const QString & originalName) const3712 QString ScribusDoc::getUniquePatternName(const QString& originalName) const
3713 {
3714 	if (!docPatterns.contains(originalName))
3715 		return originalName;
3716 
3717 	QString newName(originalName);
3718 
3719 	// Search the string for (number) at the end and capture
3720 	// both the number and the text leading up to it sans brackets.
3721 	//     Copy of fred (5)
3722 	//     ^^^^^^^^^^^^  ^   (where ^ means captured)
3723 	QRegExp rx("^(.*)\\s+\\((\\d+)\\)$");
3724 	int numMatches = rx.lastIndexIn(originalName);
3725 	// Add a (number) suffix to the end of the name. We start at the
3726 	// old suffix's value if there was one, or at 2 if there was not.
3727 	int suffixNum = 1;
3728 	QString prefix(newName);
3729 	if (numMatches != -1)
3730 	{
3731 		// Already had a suffix; use the name w/o suffix for prefix and
3732 		// grab the old suffix value as a starting point.
3733 		QStringList matches = rx.capturedTexts();
3734 		prefix = matches[1];
3735 		suffixNum = matches[2].toInt();
3736 	}
3737 	// Keep on incrementing the suffix 'till we find a free name
3738 	do
3739 	{
3740 		suffixNum ++;
3741 		newName = prefix + " (" + QString::number(suffixNum) + ")";
3742 	}
3743 	while (docPatterns.contains(newName));
3744 
3745 	return newName;
3746 }
3747 
getUsedPatterns() const3748 QStringList ScribusDoc::getUsedPatterns() const
3749 {
3750 	QList<PageItem*> allItems;
3751 	QStringList results;
3752 
3753 	for (PageItemIterator it(this, PageItemIterator::IterateInDocNoPatterns); *it; ++it)
3754 	{
3755 		PageItem* currItem = *it;
3756 		if ((!results.contains(currItem->pattern())) && ((currItem->GrType == Gradient_Pattern) || (currItem->itemType() == PageItem::Symbol)))
3757 			results.append(currItem->pattern());
3758 		if (!currItem->strokePattern().isEmpty())
3759 		{
3760 			if (!results.contains(currItem->strokePattern()))
3761 				results.append(currItem->strokePattern());
3762 		}
3763 		if (!currItem->patternMask().isEmpty())
3764 		{
3765 			if (!results.contains(currItem->patternMask()))
3766 				results.append(currItem->patternMask());
3767 		}
3768 	}
3769 
3770 	for (auto it = docPatterns.constBegin(); it != docPatterns.constEnd(); ++it)
3771 	{
3772 		const ScPattern& pattern = it.value();
3773 		for (int i = 0; i < pattern.items.count(); ++i)
3774 		{
3775 			PageItem* currItem = pattern.items.at(i);
3776 			if (currItem->isGroup())
3777 				allItems = currItem->getAllChildren();
3778 			else
3779 				allItems.append(currItem);
3780 			for (int j = 0; j < allItems.count(); j++)
3781 			{
3782 				currItem = allItems.at(j);
3783 				if ((currItem->GrType == Gradient_Pattern) || (currItem->itemType() == PageItem::Symbol))
3784 				{
3785 					const QString& patName = currItem->pattern();
3786 					if (!patName.isEmpty() && !results.contains(patName))
3787 						results.append(patName);
3788 				}
3789 				const QString& pat2 = currItem->strokePattern();
3790 				if (!pat2.isEmpty() && !results.contains(pat2))
3791 					results.append(pat2);
3792 				const QString& pat3 = currItem->patternMask();
3793 				if (!pat3.isEmpty() && !results.contains(pat3))
3794 					results.append(pat3);
3795 			}
3796 			allItems.clear();
3797 		}
3798 	}
3799 	return results;
3800 }
3801 
3802 
getUsedPatternsSelection(Selection * customSelection) const3803 QStringList ScribusDoc::getUsedPatternsSelection(Selection* customSelection) const
3804 {
3805 	QStringList results;
3806 	int selectedItemCount = customSelection->count();
3807 	if (selectedItemCount == 0)
3808 		return QStringList();
3809 
3810 	for (int i = 0; i < selectedItemCount; ++i)
3811 	{
3812 		PageItem *currItem = customSelection->itemAt(i);
3813 		QList<PageItem*> allItems;
3814 		if (currItem->isGroup())
3815 			allItems = currItem->getAllChildren();
3816 		else
3817 			allItems.append(currItem);
3818 		for (int j = 0; j < allItems.count(); j++)
3819 		{
3820 			currItem = allItems.at(j);
3821 			if ((currItem->GrType == Gradient_Pattern) || (currItem->itemType() == PageItem::Symbol))
3822 			{
3823 				const QString& pat = currItem->pattern();
3824 				if (!pat.isEmpty() && !results.contains(pat))
3825 					results.append(currItem->pattern());
3826 			}
3827 			const QString& pat2 = currItem->strokePattern();
3828 			if (!pat2.isEmpty() && !results.contains(pat2))
3829 				results.append(currItem->strokePattern());
3830 			const QString& pat3 = currItem->patternMask();
3831 			if (!pat3.isEmpty() && !results.contains(pat3))
3832 				results.append(currItem->patternMask());
3833 		}
3834 		allItems.clear();
3835 	}
3836 	QStringList results2 = results;
3837 	for (int i = 0; i < results.count(); ++i)
3838 	{
3839 		QStringList pats = getUsedPatternsHelper(results[i], results2);
3840 		if (pats.isEmpty())
3841 			continue;
3842 		for (int j = 0; j < pats.count(); j++)
3843 		{
3844 			if (!results2.contains(pats[j]))
3845 				results2.append(pats[j]);
3846 		}
3847 	}
3848 	return results2;
3849 }
3850 
getUsedPatternsHelper(const QString & pattern,QStringList & results) const3851 QStringList ScribusDoc::getUsedPatternsHelper(const QString& pattern, QStringList &results) const
3852 {
3853 	auto patIter = docPatterns.constFind(pattern);
3854 	if (patIter == docPatterns.end())
3855 		return QStringList();
3856 	const ScPattern &pat = patIter.value();
3857 
3858 	QStringList pats;
3859 	for (int i = 0; i < pat.items.count(); ++i)
3860 	{
3861 		QList<PageItem*> allItems;
3862 		if (pat.items.at(i)->isGroup())
3863 			allItems = pat.items.at(i)->getAllChildren();
3864 		else
3865 			allItems.append(pat.items.at(i));
3866 		for (int j = 0; j < allItems.count(); j++)
3867 		{
3868 			PageItem *currItem = allItems.at(j);
3869 			if ((currItem->GrType == Gradient_Pattern) || (currItem->itemType() == PageItem::Symbol))
3870 			{
3871 				const QString& patName = currItem->pattern();
3872 				if (!patName.isEmpty() && !results.contains(patName))
3873 					pats.append(patName);
3874 			}
3875 			const QString& pat2 = currItem->strokePattern();
3876 			if (!pat2.isEmpty() && !results.contains(pat2))
3877 				pats.append(currItem->strokePattern());
3878 			const QString& pat3 = currItem->patternMask();
3879 			if (!pat3.isEmpty() && !results.contains(pat3))
3880 				pats.append(currItem->patternMask());
3881 		}
3882 		allItems.clear();
3883 	}
3884 	if (!pats.isEmpty())
3885 	{
3886 		results += pats;
3887 		for (int i = 0; i < pats.count(); ++i)
3888 		{
3889 			QStringList pp = getUsedPatternsHelper(pats[i], results);
3890 			if (pp.isEmpty())
3891 				continue;
3892 			for (int cc = 0; cc < pp.count(); cc++)
3893 			{
3894 				if (!results.contains(pp[cc]))
3895 					results.append(pp[cc]);
3896 			}
3897 		}
3898 	}
3899 	return results;
3900 }
3901 
getPatternDependencyList(const QStringList & used) const3902 QStringList ScribusDoc::getPatternDependencyList(const QStringList& used) const
3903 {
3904 	QStringList results;
3905 	QStringList pp;
3906 	QStringList pats = used;
3907 	QStack<QStringList> patternStack;
3908 	patternStack.push(pats);
3909 	while (!pats.isEmpty())
3910 	{
3911 		for (int i = 0; i < pats.count(); ++i)
3912 		{
3913 			pp = getUsedPatternsHelper(pats[i], results);
3914 		}
3915 		pats = results;
3916 		results.clear();
3917 		if (!pats.isEmpty())
3918 			patternStack.push(pats);
3919 	}
3920 	results.clear();
3921 	while (patternStack.count() != 0)
3922 	{
3923 		pp = patternStack.pop();
3924 		for (int i = 0; i < pp.count(); i++)
3925 		{
3926 			if (!results.contains(pp[i]))
3927 				results.append(pp[i]);
3928 		}
3929 		if (patternStack.count() == 0)
3930 			break;
3931 	}
3932 	return results;
3933 }
3934 
getUsedSymbols() const3935 QStringList ScribusDoc::getUsedSymbols() const
3936 {
3937 	QStringList results;
3938 
3939 	for (PageItemIterator it(this, PageItemIterator::IterateInDocDefaults); *it; ++it)
3940 	{
3941 		PageItem* currItem = *it;
3942 		if (currItem->isGroup())
3943 			continue;
3944 		if ((!results.contains(currItem->pattern())) && (currItem->itemType() == PageItem::Symbol) && (!currItem->pattern().isEmpty()))
3945 			results.append(currItem->pattern());
3946 		if ((!currItem->strokePattern().isEmpty()) && (currItem->patternStrokePath))
3947 		{
3948 			if (!results.contains(currItem->strokePattern()))
3949 				results.append(currItem->strokePattern());
3950 		}
3951 		if ((!results.contains(currItem->strokePattern())) && ((!currItem->strokePattern().isEmpty()) && (currItem->patternStrokePath)))
3952 			results.append(currItem->pattern());
3953 	}
3954 	return results;
3955 }
3956 
getUsedSymbolsHelper(const QString & pattern,QStringList & results) const3957 QStringList ScribusDoc::getUsedSymbolsHelper(const QString& pattern, QStringList &results) const
3958 {
3959 	auto patIter = docPatterns.constFind(pattern);
3960 	if (patIter == docPatterns.end())
3961 		return QStringList();
3962 	const ScPattern &pat = patIter.value();
3963 
3964 	QStringList pats;
3965 	for (int i = 0; i < pat.items.count(); ++i)
3966 	{
3967 		if (pat.items.at(i)->itemType() == PageItem::Symbol)
3968 		{
3969 			const QString& patName = pat.items.at(i)->pattern();
3970 			if (!patName.isEmpty() && !results.contains(patName))
3971 				pats.append(patName);
3972 		}
3973 	}
3974 	if (!pats.isEmpty())
3975 	{
3976 		for (int i = 0; i < pats.count(); ++i)
3977 			getUsedSymbolsHelper(pats[i], results);
3978 	}
3979 	return pats;
3980 }
3981 
reorganiseFonts()3982 QMap<QString,int> ScribusDoc::reorganiseFonts()
3983 {
3984 	QMap<QString,int> Really;
3985 	QList<PageItem*> allItems;
3986 
3987 	bool wasMasterPageMode = m_masterPageMode;
3988 
3989 	for (int i = 0; i < 2; ++i)
3990 	{
3991 		switch (i)
3992 		{
3993 			case 0:
3994 				setMasterPageMode(true); // Necessary to avoid crash if some relayouting is necessary
3995 				allItems = MasterItems;
3996 				break;
3997 			case 1:
3998 				setMasterPageMode(false);
3999 				allItems = DocItems;
4000 				break;
4001 		}
4002 		PageItem* it = nullptr;
4003 		while (allItems.count() > 0)
4004 		{
4005 			it = allItems.takeFirst();
4006 			if (it->isGroup() || it->isTable())
4007 			{
4008 				allItems = it->getChildren() + allItems;
4009 				continue;
4010 			}
4011 			if ((it->itemType() == PageItem::TextFrame) || (it->itemType() == PageItem::PathText))
4012 			{
4013 				if (it->invalid)
4014 					it->layout();
4015 				QString fontName(it->itemText.defaultStyle().charStyle().font().replacementName());
4016 				Really.insert(fontName, UsedFonts[fontName]);
4017 				int start = it->firstInFrame();
4018 				int stop = it->lastInFrame();
4019 				for (int e = start; e <= stop; ++e)
4020 				{
4021 					QString rep = it->itemText.charStyle(e).font().replacementName();
4022 					if (Really.contains(rep))
4023 						continue;
4024 					Really.insert(rep, UsedFonts[rep]);
4025 				}
4026 			}
4027 		}
4028 	}
4029 
4030 	setMasterPageMode(wasMasterPageMode);
4031 
4032 	allItems = FrameItems.values();
4033 	while (allItems.count() > 0)
4034 	{
4035 		PageItem *it = allItems.takeFirst();
4036 		if (it->isGroup() || it->isTable())
4037 		{
4038 			allItems = it->getChildren() + allItems;
4039 			continue;
4040 		}
4041 		if ((it->itemType() == PageItem::TextFrame) || (it->itemType() == PageItem::PathText))
4042 		{
4043 			if (it->invalid)
4044 				it->layout();
4045 			QString fontName(it->itemText.defaultStyle().charStyle().font().replacementName());
4046 			Really.insert(fontName, UsedFonts[fontName]);
4047 			int start = it->firstInFrame();
4048 			int stop = it->lastInFrame();
4049 			for (int e = start; e <= stop; ++e)
4050 			{
4051 				QString rep = it->itemText.charStyle(e).font().replacementName();
4052 				if (Really.contains(rep))
4053 					continue;
4054 				Really.insert(rep, UsedFonts[rep]);
4055 			}
4056 		}
4057 	}
4058 
4059 	auto patternEnd = docPatterns.cend();
4060 	for (auto patIter = docPatterns.cbegin(); patIter != patternEnd; ++patIter)
4061 	{
4062 		const ScPattern& pat = patIter.value();
4063 		allItems = pat.items;
4064 		while (allItems.count() > 0)
4065 		{
4066 			PageItem *it = allItems.takeFirst();
4067 			if (it->isGroup() || it->isTable())
4068 			{
4069 				allItems = it->getChildren() + allItems;
4070 				continue;
4071 			}
4072 			if ((it->itemType() == PageItem::TextFrame) || (it->itemType() == PageItem::PathText))
4073 			{
4074 				if (it->invalid)
4075 					it->layout();
4076 				QString fontName(it->itemText.defaultStyle().charStyle().font().replacementName());
4077 				Really.insert(fontName, UsedFonts[fontName]);
4078 				int start = it->firstInFrame();
4079 				int stop = it->lastInFrame();
4080 				for (int e = start; e <= stop; ++e)
4081 				{
4082 					QString rep = it->itemText.charStyle(e).font().replacementName();
4083 					if (Really.contains(rep))
4084 						continue;
4085 					Really.insert(rep, UsedFonts[rep]);
4086 				}
4087 			}
4088 		}
4089 	}
4090 
4091 	QMap<QString,int>::Iterator itfo, itnext;
4092 	for (itfo = UsedFonts.begin(); itfo != UsedFonts.end(); itfo = itnext)
4093 	{
4094 		itnext = itfo;
4095 		++itnext;
4096 		if (!Really.contains(itfo.key()))
4097 		{
4098 			(*AllFonts)[itfo.key()].decreaseUsage();
4099 			UsedFonts.erase(itfo);
4100 		}
4101 	}
4102 	PrefsManager& prefsManager=PrefsManager::instance();
4103 	AddFont(prefsManager.appPrefs.itemToolPrefs.textFont);//, prefsManager.appPrefs.AvailFonts[prefsManager.appPrefs.itemToolPrefs.textFont]->Font);
4104 	AddFont(m_docPrefsData.itemToolPrefs.textFont);//, prefsManager.appPrefs.AvailFonts[itemToolPrefs.textFont]->Font);
4105 	return Really;
4106 }
4107 
getUsedFonts(QMap<QString,QMap<uint,QString>> & Really)4108 void ScribusDoc::getUsedFonts(QMap<QString, QMap<uint, QString> > & Really)
4109 {
4110 	QList<PageItem*>  allItems;
4111 	QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems };
4112 	PageItem* it = nullptr;
4113 
4114 	for (int i = 0; i < 2; ++i)
4115 	{
4116 		allItems = *(itemLists[i]);
4117 		while (allItems.count() > 0)
4118 		{
4119 			it = allItems.takeFirst();
4120 			if (it->isGroup() || it->isTable())
4121 			{
4122 				allItems = it->getChildren() + allItems;
4123 				continue;
4124 			}
4125 			checkItemForFonts(it, Really, i);
4126 		}
4127 	}
4128 
4129 	allItems = FrameItems.values();
4130 	while (allItems.count() > 0)
4131 	{
4132 		PageItem *ite = allItems.takeFirst();
4133 		if (it->isGroup() || it->isTable())
4134 		{
4135 			allItems = it->getChildren() + allItems;
4136 			continue;
4137 		}
4138 		checkItemForFonts(ite, Really, 3);
4139 	}
4140 
4141 	QStringList patterns = getUsedPatterns();
4142 	for (int c = 0; c < patterns.count(); ++c)
4143 	{
4144 		ScPattern pa = docPatterns[patterns[c]];
4145 		allItems = pa.items;
4146 		while (allItems.count() > 0)
4147 		{
4148 			it = allItems.takeFirst();
4149 			if (it->isGroup() || it->isTable())
4150 			{
4151 				allItems = it->getChildren() + allItems;
4152 				continue;
4153 			}
4154 			checkItemForFonts(it, Really, 3);
4155 		}
4156 	}
4157 }
4158 
4159 // a special painter that does not actually paint anything,
4160 // but collects the glyphs used in the frame.
4161 class UsedGlyphsPainter: public TextLayoutPainter
4162 {
4163 public:
UsedGlyphsPainter(QMap<QString,QMap<uint,QString>> & usedFonts)4164 	UsedGlyphsPainter(QMap<QString, QMap<uint, QString> > & usedFonts)
4165 		: m_fonts(usedFonts)
4166 	{}
4167 
drawGlyph(const GlyphCluster & gc)4168 	void drawGlyph(const GlyphCluster& gc) override
4169 	{
4170 		if (gc.isControlGlyphs())
4171 			return;
4172 
4173 		const QList<GlyphLayout>& glyphs = gc.glyphs();
4174 		int glyphCount = glyphs.count();
4175 
4176 		for (const GlyphLayout& gl : gc.glyphs())
4177 		{
4178 			uint gid = gl.glyph;
4179 			if (gid >= ScFace::CONTROL_GLYPHS)
4180 				continue;
4181 
4182 			QString replacementName = font().replacementName();
4183 			if (!replacementName.isEmpty())
4184 			{
4185 				QString unicode;
4186 				if (glyphCount == 1)
4187 					unicode = gc.getText();
4188 				m_fonts[replacementName].insert(gid, unicode);
4189 			}
4190 		}
4191 	}
4192 
drawGlyphOutline(const GlyphCluster & gc,bool)4193 	void drawGlyphOutline(const GlyphCluster& gc, bool) override
4194 	{
4195 		drawGlyph(gc);
4196 	}
4197 
4198 	// we don't need this one
drawLine(QPointF,QPointF)4199 	void drawLine(QPointF, QPointF) override {}
drawRect(QRectF)4200 	void drawRect(QRectF) override {}
drawObject(PageItem *)4201 	void drawObject(PageItem*) override {}
4202 
4203 private:
4204 	QMap<QString, QMap<uint, QString> > & m_fonts;
4205 };
4206 
checkItemForFonts(PageItem * it,QMap<QString,QMap<uint,QString>> & usedFonts,uint lc)4207 void ScribusDoc::checkItemForFonts(PageItem *it, QMap<QString, QMap<uint, QString> > & usedFonts, uint lc)
4208 {
4209 	if (!it->isTextFrame() && !it->isPathText())
4210 		return;
4211 
4212 	if (it->invalid)
4213 	{
4214 		bool wasMasterPageMode = m_masterPageMode;
4215 		setMasterPageMode(it->OnMasterPage.length() > 0);
4216 		it->layout();
4217 		setMasterPageMode(wasMasterPageMode);
4218 	}
4219 
4220 	// This works pretty well except for the case of page numbers and al. placed on masterpages
4221 	// where layout may depend on the page where the masterpage item is placed
4222 	UsedGlyphsPainter p(usedFonts);
4223 	it->textLayout.render(&p);
4224 
4225 	// Process page numbers and page count special characters on master pages
4226 	if (!it->OnMasterPage.isEmpty())
4227 	{
4228 		bool hasPageNumbers = false;
4229 
4230 		int start = it->isTextFrame() ? it->firstInFrame() : 0;
4231 		int stop = it->isTextFrame() ? it->lastInFrame() + 1 : it->itemText.length();
4232 		for (int e = start; e < stop; ++e)
4233 		{
4234 			uint chr = it->itemText.text(e).unicode();
4235 			if ((chr == SpecialChars::PAGENUMBER) || (chr == SpecialChars::PAGECOUNT))
4236 			{
4237 				hasPageNumbers = true;
4238 				break;
4239 			}
4240 		}
4241 
4242 		if (hasPageNumbers)
4243 		{
4244 			it->savedOwnPage = it->OwnPage;
4245 			int docPageCount = DocPages.count();
4246 			for (int i = 0; i < docPageCount; ++i)
4247 			{
4248 				it->OwnPage = i;
4249 				it->invalid = true;
4250 				it->layout();
4251 				it->textLayout.render(&p);
4252 			}
4253 			it->OwnPage = it->savedOwnPage;
4254 			it->invalid = true;
4255 		}
4256 	}
4257 
4258 	// Process annotation fonts
4259 	if (it->isAnnotation() && (it->isTextFrame() || it->isPathText()))
4260 	{
4261 		int annotType  = it->annotation().Type();
4262 		bool requiredFont = ((annotType >= Annotation::Button) && (annotType <= Annotation::Listbox) && (annotType != Annotation::Checkbox));
4263 		if (it->itemText.length() > 0 || requiredFont)
4264 		{
4265 			const ScFace& font = it->itemText.defaultStyle().charStyle().font();
4266 			QString fontName = font.replacementName();
4267 
4268 			if (!usedFonts.contains(fontName) && !fontName.isEmpty())
4269 				usedFonts.insert(fontName, QMap<uint, QString>());
4270 
4271 			for (uint ww = 32; ww < 256; ++ww)
4272 			{
4273 				int unicode = Pdf::fromPDFDocEncoding(ww);
4274 				uint glyph  = font.char2CMap(unicode);
4275 				if (glyph > 0)
4276 				{
4277 					QString uniStr = QChar(unicode);
4278 					if (!fontName.isEmpty())
4279 						usedFonts[fontName].insert(glyph, uniStr);
4280 				}
4281 			}
4282 		}
4283 	}
4284 }
4285 
4286 
getUsedProfiles(ProfilesL & usedProfiles) const4287 void ScribusDoc::getUsedProfiles(ProfilesL& usedProfiles) const
4288 {
4289 	PageItem* it = nullptr;
4290 	QStringList profileNames;
4291 	QList<PageItem*> allItems;
4292 	int counter = 0;
4293 
4294 	usedProfiles.clear();
4295 
4296 	profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile);
4297 	profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorCMYKProfile);
4298 	if (profileNames.indexOf(m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile) < 0)
4299 		profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile);
4300 	if (profileNames.indexOf(m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile) < 0)
4301 		profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile);
4302 	if (profileNames.indexOf(m_docPrefsData.colorPrefs.DCMSset.DefaultMonitorProfile) < 0)
4303 		profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultMonitorProfile);
4304 	if (profileNames.indexOf(m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile) < 0)
4305 		profileNames.append(m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile);
4306 
4307 	if (profileNames.indexOf(m_docPrefsData.pdfPrefs.SolidProf) < 0)
4308 		profileNames.append(m_docPrefsData.pdfPrefs.SolidProf);
4309 	if (profileNames.indexOf(m_docPrefsData.pdfPrefs.ImageProf) < 0)
4310 		profileNames.append(m_docPrefsData.pdfPrefs.ImageProf);
4311 	if (profileNames.indexOf(m_docPrefsData.pdfPrefs.PrintProf) < 0)
4312 		profileNames.append(m_docPrefsData.pdfPrefs.PrintProf);
4313 
4314 	const QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems };
4315 	for (int lc = 0; lc < 2; ++lc)
4316 	{
4317 		const auto* pItemList = itemLists[lc];
4318 		counter = pItemList->count();
4319 		for (int d = 0; d < counter; ++d)
4320 		{
4321 			it = pItemList->at(d);
4322 			if (it->isGroup())
4323 				allItems = it->getAllChildren();
4324 			else
4325 				allItems.append(it);
4326 			for (int ii = 0; ii < allItems.count(); ii++)
4327 			{
4328 				it = allItems.at(ii);
4329 				if (it->ImageProfile.isEmpty() || profileNames.contains(it->ImageProfile))
4330 					continue;
4331 				profileNames.append(it->ImageProfile);
4332 			}
4333 			allItems.clear();
4334 		}
4335 	}
4336 
4337 	for (auto itf = FrameItems.cbegin(); itf != FrameItems.cend(); ++itf)
4338 	{
4339 		PageItem *it = itf.value();
4340 		if (it->isGroup())
4341 			allItems = it->getAllChildren();
4342 		else
4343 			allItems.append(it);
4344 		for (int ii = 0; ii < allItems.count(); ii++)
4345 		{
4346 			it = allItems.at(ii);
4347 			if (it->ImageProfile.isEmpty() || profileNames.contains(it->ImageProfile))
4348 				continue;
4349 			profileNames.append(it->ImageProfile);
4350 		}
4351 		allItems.clear();
4352 	}
4353 
4354 	for (auto pIter = profileNames.cbegin(); pIter != profileNames.cend(); pIter++)
4355 	{
4356 		if (ScCore->InputProfiles.contains(*pIter))
4357 			usedProfiles[*pIter] = ScCore->InputProfiles[*pIter];
4358 		else if (ScCore->InputProfilesCMYK.contains(*pIter))
4359 			usedProfiles[*pIter] = ScCore->InputProfilesCMYK[*pIter];
4360 		else if (ScCore->PrinterProfiles.contains(*pIter))
4361 			usedProfiles[*pIter] = ScCore->PrinterProfiles[*pIter];
4362 	}
4363 }
4364 
useAcroFormFields() const4365 bool ScribusDoc::useAcroFormFields() const
4366 {
4367 	QList<PageItem*>  allItems;
4368 	const QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems };
4369 	const PageItem* it = nullptr;
4370 
4371 	for (int i = 0; i < 2; ++i)
4372 	{
4373 		allItems = *(itemLists[i]);
4374 		while (allItems.count() > 0)
4375 		{
4376 			it = allItems.takeFirst();
4377 			if (it->isGroup() || it->isTable())
4378 			{
4379 				allItems += it->getChildren();
4380 				continue;
4381 			}
4382 			if ((it->itemType() != PageItem::TextFrame) || !it->isAnnotation())
4383 				continue;
4384 			if (it->annotation().isAcroFormField())
4385 				return true;
4386 		}
4387 	}
4388 
4389 	allItems = FrameItems.values();
4390 	while (allItems.count() > 0)
4391 	{
4392 		it = allItems.takeFirst();
4393 		if (it->isGroup() || it->isTable())
4394 		{
4395 			allItems += it->getChildren();
4396 			continue;
4397 		}
4398 		if ((it->itemType() != PageItem::TextFrame) || !it->isAnnotation())
4399 			continue;
4400 		if (it->annotation().isAcroFormField())
4401 			return true;
4402 	}
4403 
4404 	QStringList patterns = getUsedPatterns();
4405 	for (int c = 0; c < patterns.count(); ++c)
4406 	{
4407 		ScPattern pa = docPatterns[patterns[c]];
4408 		allItems = pa.items;
4409 		while (allItems.count() > 0)
4410 		{
4411 			it = allItems.takeFirst();
4412 			if (it->isGroup() || it->isTable())
4413 			{
4414 				allItems += it->getChildren();
4415 				continue;
4416 			}
4417 			if ((it->itemType() != PageItem::TextFrame) || !it->isAnnotation())
4418 				continue;
4419 			if (it->annotation().isAcroFormField())
4420 				return true;
4421 		}
4422 	}
4423 
4424 	return false;
4425 }
4426 
useAnnotations() const4427 bool ScribusDoc::useAnnotations() const
4428 {
4429 	QList<PageItem*>  allItems;
4430 	const QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems };
4431 	const PageItem* it = nullptr;
4432 
4433 	for (int i = 0; i < 2; ++i)
4434 	{
4435 		allItems = *(itemLists[i]);
4436 		while (allItems.count() > 0)
4437 		{
4438 			it = allItems.takeFirst();
4439 			if (it->isGroup() || it->isTable())
4440 			{
4441 				allItems += it->getChildren();
4442 				continue;
4443 			}
4444 			if (it->itemType() != PageItem::TextFrame)
4445 				continue;
4446 			if (it->isAnnotation())
4447 				return true;
4448 		}
4449 	}
4450 
4451 	allItems = FrameItems.values();
4452 	while (allItems.count() > 0)
4453 	{
4454 		it = allItems.takeFirst();
4455 		if (it->isGroup() || it->isTable())
4456 		{
4457 			allItems += it->getChildren();
4458 			continue;
4459 		}
4460 		if (it->itemType() != PageItem::TextFrame)
4461 			continue;
4462 		if (it->isAnnotation())
4463 			return true;
4464 	}
4465 
4466 	QStringList patterns = getUsedPatterns();
4467 	for (int c = 0; c < patterns.count(); ++c)
4468 	{
4469 		ScPattern pa = docPatterns[patterns[c]];
4470 		allItems = pa.items;
4471 		while (allItems.count() > 0)
4472 		{
4473 			it = allItems.takeFirst();
4474 			if (it->isGroup() || it->isTable())
4475 			{
4476 				allItems += it->getChildren();
4477 				continue;
4478 			}
4479 			if (it->itemType() != PageItem::TextFrame)
4480 				continue;
4481 			if (it->isAnnotation())
4482 				return true;
4483 		}
4484 	}
4485 
4486 	return false;
4487 }
4488 
useImageEffects() const4489 bool ScribusDoc::useImageEffects() const
4490 {
4491 	QList<PageItem*> frameItemList = FrameItems.values();
4492 	const QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems, &frameItemList };
4493 	PageItemIterator it;
4494 
4495 	for (int i = 0; i < 3; ++i)
4496 	{
4497 		const auto& itemList = *(itemLists[i]);
4498 		for (it.begin(itemList); *it; ++it)
4499 		{
4500 			PageItem *currItem = *it;
4501 			if (!currItem->isImageFrame() || !currItem->imageIsAvailable)
4502 				continue;
4503 			if (currItem->effectsInUse.count() > 0)
4504 				return true;
4505 		}
4506 	}
4507 
4508 	auto patternEnd = docPatterns.constEnd();
4509 	for (auto patIter = docPatterns.constBegin(); patIter != patternEnd; ++patIter)
4510 	{
4511 		const ScPattern& pa = patIter.value();
4512 		for (it.begin(pa.items); *it; ++it)
4513 		{
4514 			PageItem *currItem = *it;
4515 			if (!currItem->isImageFrame() || !currItem->imageIsAvailable)
4516 				continue;
4517 			if (currItem->effectsInUse.count() > 0)
4518 				return true;
4519 		}
4520 	}
4521 
4522 	return false;
4523 }
4524 
useImageColorEffects() const4525 bool ScribusDoc::useImageColorEffects() const
4526 {
4527 	QList<PageItem*> frameItemList = FrameItems.values();
4528 	const QList<PageItem*>* itemLists[] = { &MasterItems, &DocItems, &frameItemList };
4529 	PageItemIterator it;
4530 
4531 	for (int i = 0; i < 3; ++i)
4532 	{
4533 		const auto& itemList = *(itemLists[i]);
4534 		for (it.begin(itemList); *it; ++it)
4535 		{
4536 			PageItem *currItem = *it;
4537 			if (!currItem->isImageFrame() || !currItem->imageIsAvailable)
4538 				continue;
4539 			if (currItem->effectsInUse.useColorEffect())
4540 				return true;
4541 		}
4542 	}
4543 
4544 	auto patternEnd = docPatterns.constEnd();
4545 	for (auto patIter = docPatterns.constBegin(); patIter != patternEnd; ++patIter)
4546 	{
4547 		const ScPattern& pa = patIter.value();
4548 		for (it.begin(pa.items); *it; ++it)
4549 		{
4550 			PageItem *currItem = *it;
4551 			if (!currItem->isImageFrame() || !currItem->imageIsAvailable)
4552 				continue;
4553 			if (currItem->effectsInUse.useColorEffect())
4554 				return true;
4555 		}
4556 	}
4557 
4558 	return false;
4559 }
4560 
setUnitIndex(int newIndex)4561 void ScribusDoc::setUnitIndex(int newIndex)
4562 {
4563 	m_docPrefsData.docSetupPrefs.docUnitIndex=newIndex;
4564 	m_docUnitRatio = unitGetRatioFromIndex( newIndex );
4565 }
4566 
4567 
unitIndex() const4568 int ScribusDoc::unitIndex() const
4569 {
4570 	return m_docPrefsData.docSetupPrefs.docUnitIndex;
4571 }
4572 
unitRatio() const4573 double ScribusDoc::unitRatio() const
4574 {
4575 	return m_docUnitRatio;
4576 }
4577 
applyMasterPage(const QString & pageName,int pageNumber)4578 bool ScribusDoc::applyMasterPage(const QString& pageName, int pageNumber)
4579 {
4580 	if (!MasterNames.contains(pageName))
4581 		return false;
4582 
4583 	if (UndoManager::undoEnabled())
4584 	{
4585 		if (DocPages.at(pageNumber)->masterPageName() != pageName)
4586 		{
4587 			SimpleState *ss = new SimpleState(Um::ApplyMasterPage, QString(Um::FromTo).arg(DocPages.at(pageNumber)->masterPageName(), pageName));
4588 			ss->set("PAGE_NUMBER", pageNumber);
4589 			ss->set("OLD_MASTERPAGE", DocPages.at(pageNumber)->masterPageName());
4590 			ss->set("NEW_MASTERPAGE", pageName);
4591 			m_undoManager->action(this, ss);
4592 		}
4593 	}
4594 	ScPage* Ap = DocPages.at(pageNumber);
4595 	Ap->setMasterPageName(pageName);
4596 	const int MpNr = MasterNames[pageName];
4597 	ScPage* Mp = MasterPages.at(MpNr);
4598 	PageItem *currItem;
4599 	Ap->FromMaster.clear();
4600 	for (int itn = 0; itn < MasterItems.count(); ++itn)
4601 	{
4602 		currItem = MasterItems.at(itn);
4603 		if (currItem->OwnPage == MpNr)
4604 			Ap->FromMaster.append(currItem);
4605 	}
4606 	if (!isLoading())
4607 	{
4608 		// PV - apply auto guides from MP only if there are no auto guides
4609 		// on original page
4610 		if (Ap->guides.horizontalAutoCount() != 0 || Ap->guides.verticalAutoCount() != 0)
4611 			Mp->guides.copy(&Ap->guides, GuideManagerCore::Standard);
4612 		else
4613 			Mp->guides.copy(&Ap->guides);
4614 
4615 		Ap->initialMargins.setTop(Mp->Margins.top());
4616 		Ap->initialMargins.setBottom(Mp->Margins.bottom());
4617 		if (pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns == 1)
4618 		{
4619 			Ap->initialMargins.setLeft(Mp->Margins.left());
4620 			Ap->initialMargins.setRight(Mp->Margins.right());
4621 		}
4622 		else
4623 		{
4624 			PageLocation pageLoc=locationOfPage(pageNumber);
4625 			if (pageLoc==LeftPage) //Left hand page
4626 			{
4627 				if (Mp->LeftPg != 0)
4628 				{
4629 					Ap->initialMargins.setRight(Mp->initialMargins.right());
4630 					Ap->initialMargins.setLeft(Mp->initialMargins.left());
4631 				}
4632 				else
4633 				{
4634 					Ap->initialMargins.setLeft(Mp->initialMargins.right());
4635 					Ap->initialMargins.setRight(Mp->initialMargins.left());
4636 				}
4637 			}
4638 			else if (pageLoc==RightPage) // Right hand page
4639 			{
4640 				if (Mp->LeftPg != 0)
4641 				{
4642 					Ap->initialMargins.setLeft(Mp->initialMargins.right());
4643 					Ap->initialMargins.setRight(Mp->initialMargins.left());
4644 				}
4645 				else
4646 				{
4647 					Ap->initialMargins.setRight(Mp->initialMargins.right());
4648 					Ap->initialMargins.setLeft(Mp->initialMargins.left());
4649 				}
4650 			}
4651 			else //Middle pages
4652 			{
4653 				Ap->initialMargins.setLeft(Mp->initialMargins.left());
4654 				Ap->initialMargins.setRight(Mp->initialMargins.right());
4655 			}
4656 		}
4657 
4658 		//#8212: Apply page settings
4659 		Ap->setInitialHeight(Mp->initialHeight());
4660 		Ap->setInitialWidth(Mp->initialWidth());
4661 		Ap->setHeight(Mp->height());
4662 		Ap->setWidth(Mp->width());
4663 		Ap->setOrientation(Mp->orientation());
4664 		Ap->setSize(Mp->size());
4665 	}
4666 	//TODO make a return false if not possible to apply the master page
4667 	if (!isLoading())
4668 		changed();
4669 	return true;
4670 }
4671 
4672 
restoreMasterPageApplying(SimpleState * ss,bool isUndo)4673 void ScribusDoc::restoreMasterPageApplying(SimpleState* ss, bool isUndo)
4674 {
4675 	int pageNumber = ss->getInt("PAGE_NUMBER");
4676 	QString oldName = ss->get("OLD_MASTERPAGE");
4677 	QString newName = ss->get("NEW_MASTERPAGE");
4678 	if (isUndo)
4679 		applyMasterPage(oldName, pageNumber);
4680 	else
4681 		applyMasterPage(newName, pageNumber);
4682 	scMW()->pagePalette->rebuildPages();
4683 }
4684 
restoreMasterPageRenaming(SimpleState * ss,bool isUndo)4685 void ScribusDoc::restoreMasterPageRenaming(SimpleState* ss, bool isUndo)
4686 {
4687 	QString oldName = ss->get("OLD_MASTERPAGE");
4688 	QString newName = ss->get("NEW_MASTERPAGE");
4689 	if (isUndo)
4690 		renameMasterPage(newName, oldName);
4691 	else
4692 		renameMasterPage(oldName, newName);
4693 	scMW()->pagePalette->updateMasterPageList();
4694 }
4695 
restoreCopyPage(SimpleState * ss,bool isUndo)4696 void ScribusDoc::restoreCopyPage(SimpleState* ss, bool isUndo)
4697 {
4698 	int pnum = ss->getInt("PAGE_NUM");
4699 	int extPage = ss->getInt("EXISTING_PAGE");
4700 	int whereTo = ss->getInt("WHERE_TO");
4701 	int copyCount = ss->getInt("COPY_COUNT");
4702 
4703 	if (isUndo)
4704 	{
4705 		int destLocation=extPage + 1;
4706 		if (whereTo==0)
4707 			--destLocation;
4708 		else if (whereTo==2)
4709 			destLocation=DocPages.count();
4710 		for (int i = 0; i < copyCount; ++i)
4711 		{
4712 			m_ScMW->deletePage(destLocation, destLocation);
4713 			if (whereTo == 2)
4714 				--destLocation;
4715 		}
4716 	}
4717 	else
4718 	{
4719 		copyPage(pnum, extPage, whereTo, copyCount);
4720 		if (m_ScMW->outlinePalette->isVisible())
4721 			m_ScMW->outlinePalette->BuildTree();
4722 	}
4723 
4724 }
4725 
4726 
4727 //TODO: Handle saving to versions of SLA, and other formats
save(const QString & fileName,QString * savedFile)4728 bool ScribusDoc::save(const QString& fileName, QString* savedFile)
4729 {
4730 	QProgressBar* mainWindowProgressBar=nullptr;
4731 	if (ScCore->usingGUI())
4732 	{
4733 		mainWindowProgressBar=m_ScMW->mainWindowProgressBar;
4734 		mainWindowProgressBar->reset();
4735 	}
4736 	FileLoader fl(fileName);
4737 	bool ret = fl.saveFile(fileName, this, savedFile);
4738 	if (ret)
4739 	{
4740 		setDocumentFileName(fileName);
4741 		setModified(false);
4742 		hasName = true;
4743 		isConverted = false;
4744 	}
4745 	return ret;
4746 }
4747 
4748 
changePageProperties(double initialTop,double initialBottom,double initialLeft,double initialRight,double initialHeight,double initialWidth,double height,double width,int orientation,const QString & pageSize,int marginPreset,bool moveObjects,int pageNumber,int pageType)4749 bool ScribusDoc::changePageProperties(double initialTop, double initialBottom, double initialLeft, double initialRight, double initialHeight, double initialWidth, double height, double width, int orientation, const QString& pageSize, int marginPreset, bool moveObjects, int pageNumber, int pageType)
4750 {
4751 	if (pageNumber == -1 || m_currentPage == nullptr)
4752 		return false;
4753 
4754 	QRectF pagebox(m_currentPage->xOffset(), m_currentPage->yOffset(), qMax( m_currentPage->width(), width), qMax(m_currentPage->height(), height));
4755 	if (UndoManager::undoEnabled())
4756 	{
4757 		SimpleState *ss = new SimpleState(Um::ChangePageProps);//, QString("%1").arg(pageNumber), Um::IPage);
4758 		ss->set("PAGE_CHANGEPROPS");
4759 		ss->set("PAGE_NUM", pageNumber);
4760 		ss->set("OLD_PAGE_INITIALTOP", m_currentPage->initialMargins.top());
4761 		ss->set("OLD_PAGE_INITIALBOTTOM", m_currentPage->initialMargins.bottom());
4762 		ss->set("OLD_PAGE_INITIALLEFT", m_currentPage->initialMargins.left());
4763 		ss->set("OLD_PAGE_INITIALRIGHT", m_currentPage->initialMargins.right());
4764 		ss->set("OLD_PAGE_INITIALHEIGHT", m_currentPage->initialHeight());
4765 		ss->set("OLD_PAGE_INITIALWIDTH", m_currentPage->initialWidth());
4766 		ss->set("OLD_PAGE_HEIGHT", m_currentPage->height());
4767 		ss->set("OLD_PAGE_WIDTH", m_currentPage->width());
4768 		ss->set("OLD_PAGE_ORIENTATION", m_currentPage->orientation());
4769 		ss->set("OLD_PAGE_SIZE", m_currentPage->size());
4770 		ss->set("OLD_PAGE_TYPE", m_currentPage->LeftPg);
4771 		ss->set("OLD_PAGE_MARGINPRESET", m_currentPage->marginPreset);
4772 		ss->set("OLD_PAGE_MOVEOBJECTS", moveObjects);
4773 		ss->set("NEW_PAGE_INITIALTOP", initialTop);
4774 		ss->set("NEW_PAGE_INITIALBOTTOM", initialBottom);
4775 		ss->set("NEW_PAGE_INITIALLEFT", initialLeft);
4776 		ss->set("NEW_PAGE_INITIALRIGHT", initialRight);
4777 		ss->set("NEW_PAGE_INITIALHEIGHT", initialHeight);
4778 		ss->set("NEW_PAGE_INITIALWIDTH", initialWidth);
4779 		ss->set("NEW_PAGE_HEIGHT", height);
4780 		ss->set("NEW_PAGE_WIDTH", width);
4781 		ss->set("NEW_PAGE_ORIENTATION", orientation);
4782 		ss->set("NEW_PAGE_SIZE", pageSize);
4783 		ss->set("NEW_PAGE_TYPE", pageType);
4784 		ss->set("NEW_PAGE_MARGINPRESET", marginPreset);
4785 		ss->set("MASTER_PAGE_MODE", masterPageMode());
4786 		m_undoManager->action(this, ss);
4787 	}
4788 	//set the current page's values
4789 	m_currentPage->initialMargins.setTop(initialTop);
4790 	m_currentPage->initialMargins.setBottom(initialBottom);
4791 	m_currentPage->initialMargins.setLeft(initialLeft);
4792 	m_currentPage->initialMargins.setRight(initialRight);
4793 	m_currentPage->setInitialHeight(initialHeight);
4794 	m_currentPage->setInitialWidth(initialWidth);
4795 	m_currentPage->setHeight(height);
4796 	m_currentPage->setWidth(width);
4797 	m_currentPage->setOrientation(orientation);
4798 	m_currentPage->setSize(pageSize);
4799 	m_currentPage->LeftPg = pageType;
4800 	m_currentPage->marginPreset = marginPreset;
4801 	reformPages(moveObjects);
4802 	invalidateRegion(pagebox);
4803 	regionsChanged()->update(pagebox);
4804 	changed();
4805 
4806 	return true;
4807 }
4808 
recalculateColorsList(QList<PageItem * > * itemList)4809 void ScribusDoc::recalculateColorsList(QList<PageItem*> *itemList)
4810 {
4811 	QList<PageItem*> allItems;
4812 	for (int c = 0; c < itemList->count(); ++c)
4813 	{
4814 		PageItem *ite = itemList->at(c);
4815 		if (ite->isGroup())
4816 			allItems = ite->getAllChildren();
4817 		else
4818 			allItems.append(ite);
4819 		for (int ii = 0; ii < allItems.count(); ii++)
4820 		{
4821 			ite = allItems.at(ii);
4822 			ite->setLineQColor();
4823 			ite->setFillQColor();
4824 			ite->set4ColorColors(ite->GrColorP1, ite->GrColorP2, ite->GrColorP3, ite->GrColorP4);
4825 			for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
4826 			{
4827 				for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
4828 				{
4829 					MeshPoint mp = ite->meshGradientArray[grow][gcol];
4830 					ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
4831 				}
4832 			}
4833 			for (int grow = 0; grow < ite->meshGradientPatches.count(); grow++)
4834 			{
4835 				meshGradientPatch patch = ite->meshGradientPatches[grow];
4836 				ite->setMeshPointColor(grow, 1, patch.TL.colorName, patch.TL.shade, patch.TL.transparency, true);
4837 				ite->setMeshPointColor(grow, 2, patch.TR.colorName, patch.TR.shade, patch.TR.transparency, true);
4838 				ite->setMeshPointColor(grow, 3, patch.BR.colorName, patch.BR.shade, patch.BR.transparency, true);
4839 				ite->setMeshPointColor(grow, 4, patch.BL.colorName, patch.BL.shade, patch.BL.transparency, true);
4840 			}
4841 			QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
4842 			for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
4843 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4844 			cstops = ite->stroke_gradient.colorStops();
4845 			for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
4846 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4847 			cstops = ite->mask_gradient.colorStops();
4848 			for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
4849 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4850 			if (ite->GrType == Gradient_Conical)
4851 				ite->createConicalMesh();
4852 		}
4853 		allItems.clear();
4854 	}
4855 }
4856 
recalculateColorItem(PageItem * item)4857 void ScribusDoc::recalculateColorItem(PageItem *item)
4858 {
4859 	QList<PageItem*> allItems;
4860 	if (item->isGroup())
4861 		allItems = item->getAllChildren();
4862 	else
4863 		allItems.append(item);
4864 	for (int ii = 0; ii < allItems.count(); ii++)
4865 	{
4866 		PageItem *ite = allItems.at(ii);
4867 		ite->setLineQColor();
4868 		ite->setFillQColor();
4869 		ite->set4ColorColors(ite->GrColorP1, ite->GrColorP2, ite->GrColorP3, ite->GrColorP4);
4870 		for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
4871 		{
4872 			for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
4873 			{
4874 				MeshPoint mp = ite->meshGradientArray[grow][gcol];
4875 				ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
4876 			}
4877 		}
4878 		for (int grow = 0; grow < ite->meshGradientPatches.count(); grow++)
4879 		{
4880 			meshGradientPatch patch = ite->meshGradientPatches[grow];
4881 			ite->setMeshPointColor(grow, 1, patch.TL.colorName, patch.TL.shade, patch.TL.transparency, true);
4882 			ite->setMeshPointColor(grow, 2, patch.TR.colorName, patch.TR.shade, patch.TR.transparency, true);
4883 			ite->setMeshPointColor(grow, 3, patch.BR.colorName, patch.BR.shade, patch.BR.transparency, true);
4884 			ite->setMeshPointColor(grow, 4, patch.BL.colorName, patch.BL.shade, patch.BL.transparency, true);
4885 		}
4886 		QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
4887 		for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
4888 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4889 		cstops = ite->stroke_gradient.colorStops();
4890 		for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
4891 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4892 		cstops = ite->mask_gradient.colorStops();
4893 		for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
4894 			ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4895 		if (ite->GrType == Gradient_Conical)
4896 			ite->createConicalMesh();
4897 	}
4898 	allItems.clear();
4899 }
4900 
recalculateColors()4901 void ScribusDoc::recalculateColors()
4902 {
4903 	// #12658, #13889 : disable undo temporarily, there is nothing to cancel here
4904 	m_undoManager->setUndoEnabled(false);
4905 
4906 	//Adjust Items of the 3 types to the colors
4907 	QHash<QString, VGradient>::Iterator itGrad;
4908 	for (itGrad = docGradients.begin(); itGrad != docGradients.end(); ++itGrad)
4909 	{
4910 		QList<VColorStop*> cstops = itGrad.value().colorStops();
4911 		for (int cst = 0; cst < itGrad.value().stops(); ++cst)
4912 		{
4913 			if (cstops.at(cst)->name != CommonStrings::None)
4914 			{
4915 				const ScColor& col = PageColors[cstops.at(cst)->name];
4916 				QColor tmp = ScColorEngine::getShadeColorProof(col, this, cstops.at(cst)->shade);
4917 				if (viewAsPreview)
4918 				{
4919 					VisionDefectColor defect;
4920 					tmp = defect.convertDefect(tmp, previewVisual);
4921 				}
4922 				cstops.at(cst)->color = tmp;
4923 			}
4924 		}
4925 	}
4926 
4927 	recalculateColorsList(&DocItems);
4928 	recalculateColorsList(&MasterItems);
4929 	QList<PageItem*> itemList = FrameItems.values();
4930 	recalculateColorsList(&itemList);
4931 	QList<PageItem*> allItems;
4932 	for (auto it = FrameItems.begin(); it != FrameItems.end(); ++it)
4933 	{
4934 		PageItem *ite = it.value();
4935 		if (ite->isGroup())
4936 			allItems = ite->getAllChildren();
4937 		else
4938 			allItems.append(ite);
4939 		for (int ii = 0; ii < allItems.count(); ii++)
4940 		{
4941 			ite = allItems.at(ii);
4942 			ite->setLineQColor();
4943 			ite->setFillQColor();
4944 			ite->set4ColorColors(ite->GrColorP1, ite->GrColorP2, ite->GrColorP3, ite->GrColorP4);
4945 			for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
4946 			{
4947 				for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
4948 				{
4949 					MeshPoint mp = ite->meshGradientArray[grow][gcol];
4950 					ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
4951 				}
4952 			}
4953 			for (int grow = 0; grow < ite->meshGradientPatches.count(); grow++)
4954 			{
4955 				meshGradientPatch patch = ite->meshGradientPatches[grow];
4956 				ite->setMeshPointColor(grow, 1, patch.TL.colorName, patch.TL.shade, patch.TL.transparency, true);
4957 				ite->setMeshPointColor(grow, 2, patch.TR.colorName, patch.TR.shade, patch.TR.transparency, true);
4958 				ite->setMeshPointColor(grow, 3, patch.BR.colorName, patch.BR.shade, patch.BR.transparency, true);
4959 				ite->setMeshPointColor(grow, 4, patch.BL.colorName, patch.BL.shade, patch.BL.transparency, true);
4960 			}
4961 			QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
4962 			for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
4963 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4964 			cstops = ite->stroke_gradient.colorStops();
4965 			for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
4966 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4967 			cstops = ite->mask_gradient.colorStops();
4968 			for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
4969 				ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
4970 			if (ite->GrType == Gradient_Conical)
4971 				ite->createConicalMesh();
4972 		}
4973 		allItems.clear();
4974 	}
4975 	auto patternEnd = docPatterns.end();
4976 	for (auto patIter = docPatterns.begin(); patIter != patternEnd; ++patIter)
4977 	{
4978 		ScPattern& pa = patIter.value();
4979 		if (pa.items.count() <= 0)
4980 			continue;
4981 		for (int o = 0; o < pa.items.count(); o++)
4982 		{
4983 			QList<PageItem*> allItems;
4984 			PageItem *ite = pa.items.at(o);
4985 			if (ite->isGroup())
4986 				allItems = ite->getAllChildren();
4987 			else
4988 				allItems.append(ite);
4989 			for (int ii = 0; ii < allItems.count(); ii++)
4990 			{
4991 				ite = allItems.at(ii);
4992 				ite->setLineQColor();
4993 				ite->setFillQColor();
4994 				ite->set4ColorColors(ite->GrColorP1, ite->GrColorP2, ite->GrColorP3, ite->GrColorP4);
4995 				for (int grow = 0; grow < ite->meshGradientArray.count(); grow++)
4996 				{
4997 					for (int gcol = 0; gcol < ite->meshGradientArray[grow].count(); gcol++)
4998 					{
4999 						MeshPoint mp = ite->meshGradientArray[grow][gcol];
5000 						ite->setMeshPointColor(grow, gcol, mp.colorName, mp.shade, mp.transparency);
5001 					}
5002 				}
5003 				for (int grow = 0; grow < ite->meshGradientPatches.count(); grow++)
5004 				{
5005 					meshGradientPatch patch = ite->meshGradientPatches[grow];
5006 					ite->setMeshPointColor(grow, 1, patch.TL.colorName, patch.TL.shade, patch.TL.transparency, true);
5007 					ite->setMeshPointColor(grow, 2, patch.TR.colorName, patch.TR.shade, patch.TR.transparency, true);
5008 					ite->setMeshPointColor(grow, 3, patch.BR.colorName, patch.BR.shade, patch.BR.transparency, true);
5009 					ite->setMeshPointColor(grow, 4, patch.BL.colorName, patch.BL.shade, patch.BL.transparency, true);
5010 				}
5011 				QList<VColorStop*> cstops = ite->fill_gradient.colorStops();
5012 				for (int cst = 0; cst < ite->fill_gradient.stops(); ++cst)
5013 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
5014 				cstops = ite->stroke_gradient.colorStops();
5015 				for (int cst = 0; cst < ite->stroke_gradient.stops(); ++cst)
5016 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
5017 				cstops = ite->mask_gradient.colorStops();
5018 				for (int cst = 0; cst < ite->mask_gradient.stops(); ++cst)
5019 					ite->SetQColor(&cstops.at(cst)->color, cstops.at(cst)->name, cstops.at(cst)->shade);
5020 				if (ite->isImageFrame())
5021 					loadPict(ite->Pfile, ite, true, false);
5022 				if (ite->GrType == Gradient_Conical)
5023 					ite->createConicalMesh();
5024 			}
5025 			allItems.clear();
5026 		}
5027 		PageItem *ite = pa.items.at(0);
5028 		double minx =  std::numeric_limits<double>::max();
5029 		double miny =  std::numeric_limits<double>::max();
5030 		double maxx = -std::numeric_limits<double>::max();
5031 		double maxy = -std::numeric_limits<double>::max();
5032 		double x1, x2, y1, y2;
5033 		ite->getVisualBoundingRect(&x1, &y1, &x2, &y2);
5034 		minx = qMin(minx, x1);
5035 		miny = qMin(miny, y1);
5036 		maxx = qMax(maxx, x2);
5037 		maxy = qMax(maxy, y2);
5038 		pa.pattern = ite->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
5039 	}
5040 
5041 	m_undoManager->setUndoEnabled(true);
5042 }
5043 
copyPageToMasterPage(int pageNumber,int leftPage,int maxLeftPage,const QString & masterPageName,bool copyFromAppliedMaster)5044 bool ScribusDoc::copyPageToMasterPage(int pageNumber, int leftPage, int maxLeftPage,  const QString& masterPageName, bool copyFromAppliedMaster)
5045 {
5046 	assert(!masterPageMode());
5047 	if (masterPageMode())
5048 		return false;
5049 	int GrMax = GroupCounter;
5050 	ScPage* sourcePage = Pages->at(pageNumber);
5051 	int nr = MasterPages.count();
5052 	ScPage* targetPage = addMasterPage(nr, masterPageName);
5053 	assert(targetPage != nullptr);
5054 	//Backup currentpage, and don't use sourcepage here as we might convert a non current page
5055 	ScPage* oldCurrentPage = currentPage();
5056 	//Must set current page for pasteitem to work properly
5057 	setLoading(true);
5058 	targetPage->copySizingProperties(sourcePage, sourcePage->Margins);
5059 	//Grab the left page setting for the current document layout from the dialog, and increment, singlePage==1 remember.
5060 	if (m_docPrefsData.docSetupPrefs.pagePositioning != singlePage)
5061 	{
5062 		int lp = leftPage;
5063 		if (lp == 0)
5064 			lp = 1;
5065 		else if (lp == maxLeftPage-1)
5066 			lp = 0;
5067 		else
5068 			++lp;
5069 		targetPage->LeftPg = lp;
5070 	}
5071 	sourcePage->guides.copy(&targetPage->guides);
5072 	int docItemsOldCount = DocItems.count();
5073 	int masterItemsOldCount = MasterItems.count();
5074 	Selection tempSelection(this, false);
5075 	m_Selection->clear();
5076 	//Copy the items from our current document page's applied *master* page
5077 	if (copyFromAppliedMaster)
5078 	{
5079 		if (!sourcePage->masterPageNameEmpty() && MasterNames.contains(sourcePage->masterPageName()))
5080 		{
5081 			ScPage* pageMaster = nullptr;
5082 			for (int i = 0; i < MasterPages.count(); ++i )
5083 			{
5084 				pageMaster = MasterPages[i];
5085 				if (pageMaster->pageName() == sourcePage->masterPageName())
5086 					break;
5087 			}
5088 			if (Layers.count() != 0 && pageMaster != nullptr)
5089 			{
5090 				int currActiveLayer = activeLayer();
5091 				for (ScLayers::iterator it = Layers.begin(); it != Layers.end(); ++it)
5092 				{
5093 					setActiveLayer(it->ID);
5094 					for (int ite = 0; ite < masterItemsOldCount; ++ite)
5095 					{
5096 						PageItem *itemToCopy = MasterItems.at(ite);
5097 						if ((itemToCopy->OnMasterPage == pageMaster->pageName()) && (it->ID == itemToCopy->m_layerID))
5098 							tempSelection.addItem(itemToCopy, true);
5099 					}
5100 					if (tempSelection.count() != 0)
5101 					{
5102 						ScriXmlDoc ss;
5103 						setMasterPageMode(true);
5104 						setCurrentPage(pageMaster); // Needed for writeElem to write proper page relative coordinates
5105 						QString dataS = ss.writeElem(this, &tempSelection);
5106 						setCurrentPage(targetPage);
5107 						ss.readElemToLayer(dataS, this, targetPage->xOffset(), targetPage->yOffset(), false, true, it->ID);
5108 						setMasterPageMode(false);
5109 						setCurrentPage(oldCurrentPage);
5110 					}
5111 					tempSelection.clear();
5112 				}
5113 				setActiveLayer(currActiveLayer);
5114 			}
5115 		}
5116 	}
5117 	//Copy the items from our current *document* page
5118 	if (Layers.count() != 0)
5119 	{
5120 		int currActiveLayer = activeLayer();
5121 		for (ScLayers::iterator it = Layers.begin(); it != Layers.end(); ++it)
5122 		{
5123 			setActiveLayer(it->ID);
5124 			for (int ite = 0; ite < docItemsOldCount; ++ite)
5125 			{
5126 				PageItem *itemToCopy = DocItems.at(ite);
5127 				if ((itemToCopy->OwnPage == sourcePage->pageNr()) && (it->ID == itemToCopy->m_layerID))
5128 					tempSelection.addItem(itemToCopy, true);
5129 			}
5130 			if (tempSelection.count() != 0)
5131 			{
5132 				ScriXmlDoc ss;
5133 				setCurrentPage(sourcePage); // Needed for writeElem to write proper page relative coordinates
5134 				QString dataS = ss.writeElem(this, &tempSelection);
5135 				setMasterPageMode(true);
5136 				setCurrentPage(targetPage);
5137 				ss.readElemToLayer(dataS, this, targetPage->xOffset(), targetPage->yOffset(), false, true, it->ID);
5138 				setMasterPageMode(false);
5139 				setCurrentPage(oldCurrentPage);
5140 			}
5141 			tempSelection.clear();
5142 		}
5143 		setActiveLayer(currActiveLayer);
5144 	}
5145 	//Make sure our copied items have the master page name and own page set.
5146 	int masterItemsNewCount = MasterItems.count();
5147 	for (int i = masterItemsOldCount; i < masterItemsNewCount; ++i)
5148 	{
5149 		PageItem *newItem = MasterItems.at(i);
5150 		newItem->setMasterPage(MasterNames[masterPageName], masterPageName);
5151 	}
5152 	targetPage->clearMasterPageName();
5153 	setLoading(false);
5154 	GroupCounter = GrMax + 1;
5155 	//Reset the current page..
5156 	setMasterPageMode(false);
5157 	setCurrentPage(oldCurrentPage);
5158 	changed();
5159 	return true;
5160 }
5161 
createPageItem(const PageItem::ItemType itemType,const PageItem::ItemFrameType frameType,double x,double y,double b,double h,double w,const QString & fill,const QString & outline)5162 PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline)
5163 {
5164 	PageItem* newItem=nullptr;
5165 	switch (itemType)
5166 	{
5167 		//Q_ASSERTs here will warn on creation issues when a coder specifies the frameType incorrectly
5168 		//for items that do not have/need a frameType for creation.
5169 		case PageItem::ImageFrame:
5170 			newItem = new PageItem_ImageFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
5171 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5172 			break;
5173 		case PageItem::TextFrame:
5174 			newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline);
5175 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5176 			break;
5177 		case PageItem::Line:
5178 			{
5179 				//CB 5521 Remove false minimum line width
5180 				double lineWidth = w; // == 0.0 ? 1.0 : w;
5181 				newItem = new PageItem_Line(this, x, y, b, h, lineWidth, CommonStrings::None, outline);
5182 //				Q_ASSERT(frameType==PageItem::Unspecified);
5183 			}
5184 			break;
5185 		case PageItem::Table:
5186 			newItem = new PageItem_Table(this, x, y, b, h, w, fill, outline);
5187 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5188 			break;
5189 		case PageItem::Polygon:
5190 			newItem = new PageItem_Polygon(this, x, y, b, h, w, fill, outline);
5191 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
5192 			break;
5193 		case PageItem::PolyLine:
5194 			newItem = new PageItem_PolyLine(this, x, y, b, h, w, fill, outline);
5195 //			Q_ASSERT(frameType==PageItem::Unspecified);
5196 			break;
5197 		case PageItem::PathText:
5198 			//Currently used only in fileloader
5199 			newItem = new PageItem_PathText(this, x, y, b, h, w, fill, outline);
5200 //			Q_ASSERT(frameType==PageItem::Unspecified);
5201 			break;
5202 		case PageItem::LatexFrame:
5203 			newItem = new PageItem_LatexFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
5204 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5205 			break;
5206 #ifdef HAVE_OSG
5207 		case PageItem::OSGFrame:
5208 			newItem = new PageItem_OSGFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
5209 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5210 			break;
5211 #endif
5212 		case PageItem::Symbol:
5213 			newItem = new PageItem_Symbol(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
5214 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5215 			break;
5216 		case PageItem::Group:
5217 			newItem = new PageItem_Group(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
5218 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
5219 			break;
5220 		case PageItem::RegularPolygon:
5221 			newItem = new PageItem_RegularPolygon(this, x, y, b, h, w, fill, outline);
5222 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
5223 			break;
5224 		case PageItem::Arc:
5225 			newItem = new PageItem_Arc(this, x, y, b, h, w, fill, outline);
5226 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
5227 			break;
5228 		case PageItem::Spiral:
5229 			newItem = new PageItem_Spiral(this, x, y, b, h, w, fill, outline);
5230 //			Q_ASSERT(frameType==PageItem::Unspecified);
5231 			break;
5232 		default:
5233 //			qDebug() << "unknown item type";
5234 			assert (false);
5235 	}
5236 	if (newItem != nullptr)
5237 	{
5238 		//Add in item default values based on itemType and frameType
5239 		itemAddDetails(itemType, frameType, newItem);
5240 	}
5241 	return newItem;
5242 }
5243 
itemAdd(const PageItem::ItemType itemType,const PageItem::ItemFrameType frameType,double x,double y,double b,double h,double w,const QString & fill,const QString & outline,PageItem::ItemKind itemKind)5244 int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
5245 {
5246 	UndoTransaction activeTransaction;
5247 	if (UndoManager::undoEnabled()) // && !m_itemCreationTransaction)
5248 	{
5249 		activeTransaction = m_undoManager->beginTransaction();
5250 	}
5251 
5252 	PageItem* newItem;
5253 	if (itemType == PageItem::NoteFrame)
5254 	{
5255 		newItem = new PageItem_NoteFrame(this, x, y, b, h, w, CommonStrings::None, outline);
5256 		itemAddDetails(PageItem::TextFrame, frameType, newItem);
5257 	}
5258 	else
5259 		newItem = createPageItem(itemType, frameType, x, y, b, h, w, fill, outline);
5260 
5261 	Q_CHECK_PTR(newItem);
5262 	if (newItem == nullptr)
5263 		return -1;
5264 
5265 	if (itemKind == PageItem::InlineItem || itemKind == PageItem::PatternItem)
5266 	{
5267 		newItem->OnMasterPage.clear();
5268 		newItem->OwnPage = -1;
5269 	}
5270 
5271 	Items->append(newItem);
5272 
5273 	if (UndoManager::undoEnabled())
5274 	{
5275 		ScItemState<PageItem*> *is = new ScItemState<PageItem*>("Create PageItem");
5276 		is->set("CREATE_ITEM");
5277 		is->setItem(newItem);
5278 		//Undo target rests with the Page for object specific undo
5279 		UndoObject *target = Pages->at(0);
5280 		if (newItem->OwnPage > -1)
5281 			target = Pages->at(newItem->OwnPage);
5282 		m_undoManager->action(target, is);
5283 		//If the item is created "complete" (ie, not being created by drag/resize, commit to undomanager)
5284 		if (activeTransaction)
5285 		{
5286 			//don't think we need this now ... newItem->checkChanges(true);
5287 			activeTransaction.commit(target->getUName(), newItem->getUPixmap(), Um::Create + " " + newItem->getUName(),  "", Um::ICreate);
5288 		}
5289 	}
5290 	return Items->count()-1;
5291 }
5292 
5293 
itemAddArea(const PageItem::ItemType itemType,const PageItem::ItemFrameType frameType,double x,double y,double w,const QString & fill,const QString & outline,PageItem::ItemKind itemKind)5294 int ScribusDoc::itemAddArea(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
5295 {
5296 	double xo = m_currentPage->xOffset();
5297 	double yo = m_currentPage->yOffset();
5298 	QPair<double, double> tl = m_currentPage->guides.topLeft(x - xo, y - yo);
5299 	QPair<double, double> tr = m_currentPage->guides.topRight(x - xo, y - yo);
5300 	QPair<double, double> bl = m_currentPage->guides.bottomLeft(x - xo, y - yo);
5301 	return itemAdd(itemType, frameType, tl.first + xo, tl.second + yo, tr.first - tl.first, bl.second - tl.second, w, fill, outline, itemKind);
5302 }
5303 
5304 
itemAddUserFrame(InsertAFrameData & iafData)5305 int ScribusDoc::itemAddUserFrame(InsertAFrameData &iafData)
5306 {
5307 	double x1 = 0.0,y1 = 0.0, w1 = iafData.width, h1 = iafData.height;
5308 	std::vector<int> pageNs;
5309 
5310 	if (iafData.locationType == 0) // On the current page or on a range of pages
5311 		pageNs.push_back(m_currentPage->pageNr() + 1);
5312 	else if (iafData.locationType == 1) // On all pages
5313 		parsePagesString(QString("1-%1").arg(Pages->count()), &pageNs, Pages->count());
5314 	else
5315 		parsePagesString(iafData.pageList, &pageNs, Pages->count());
5316 
5317 	ScPage* oldCurrentPage = currentPage();
5318 	int z=-2;
5319 	PageItem *prevItem=nullptr; //Previous item for text frame linking
5320 	if (iafData.linkToExistingFrame && iafData.linkToExistingFramePtr != nullptr &&
5321 			iafData.linkToExistingFramePtr->itemType() == PageItem::TextFrame &&
5322 			DocItems.contains(iafData.linkToExistingFramePtr))
5323 		prevItem=iafData.linkToExistingFramePtr;
5324 	UndoTransaction transaction;
5325 	if (UndoManager::undoEnabled())
5326 		transaction = m_undoManager->beginTransaction(iafData.frameType==PageItem::TextFrame ? Um::TextFrame : Um::ImageFrame,
5327 													iafData.frameType==PageItem::TextFrame ? Um::ITextFrame : Um::IImageFrame,
5328 													Um::InsertFrame, "", Um::ICreate);
5329 	for (uint i=0;i<pageNs.size();++i)
5330 	{
5331 		ScPage* targetPage = Pages->at(pageNs[i]-1);
5332 		//We need this for the itemAdd, FIXME later
5333 		setCurrentPage(targetPage);
5334 
5335 		if (iafData.positionType==0) // Frame starts at top left of page margins
5336 		{
5337 			x1 = targetPage->xOffset() + targetPage->Margins.left();
5338 			y1 = targetPage->yOffset() + targetPage->Margins.top();
5339 		}
5340 		else if (iafData.positionType==1) // Frame starts at top left of page
5341 		{
5342 			x1 = targetPage->xOffset();
5343 			y1 = targetPage->yOffset();
5344 		}
5345 		else if (iafData.positionType==2) // Frame starts at top left of page - bleeds
5346 		{
5347 			MarginStruct values;
5348 			getBleeds(targetPage, m_docPrefsData.docSetupPrefs.bleeds, values);
5349 			x1 = targetPage->xOffset() - values.left();
5350 			y1 = targetPage->yOffset() - values.top();
5351 		}
5352 		else if (iafData.positionType==3) // Frame starts at custom position
5353 		{
5354 			x1 = targetPage->xOffset() + iafData.x;
5355 			y1 = targetPage->yOffset() + iafData.y;
5356 		}
5357 
5358 		if (iafData.sizeType==0) // Frame is size of page margins
5359 		{
5360 			w1 = targetPage->width() - targetPage->Margins.right()- targetPage->Margins.left();
5361 			h1 = targetPage->height() - targetPage->Margins.bottom()- targetPage->Margins.top();
5362 		}
5363 		else if (iafData.sizeType==1) // Frame is size of page
5364 		{
5365 			w1 = targetPage->width();
5366 			h1 = targetPage->height();
5367 		}
5368 		else if (iafData.sizeType==2) // Frame is size of page + bleed
5369 		{
5370 			w1 = targetPage->width() + m_docPrefsData.docSetupPrefs.bleeds.right() + m_docPrefsData.docSetupPrefs.bleeds.left();
5371 			h1 = targetPage->height() + m_docPrefsData.docSetupPrefs.bleeds.bottom() + m_docPrefsData.docSetupPrefs.bleeds.top();
5372 		}
5373 		else if (iafData.sizeType==3) //Frame is size of imported image, we resize below when we load it
5374 		{
5375 			w1 = h1 =1;
5376 		}
5377 		else if (iafData.sizeType==4) // Frame is custom size
5378 		{
5379 			w1 = iafData.width;
5380 			h1 = iafData.height;
5381 		}
5382 		z=itemAdd(iafData.frameType, PageItem::Unspecified, x1, y1, w1, h1, m_docPrefsData.itemToolPrefs.shapeLineWidth, CommonStrings::None, m_docPrefsData.itemToolPrefs.textColor);
5383 		if (z!=-1)
5384 		{
5385 			PageItem* currItem=Items->at(z);
5386 			setRedrawBounding(currItem);
5387 			if (iafData.frameType==PageItem::ImageFrame && !iafData.source.isEmpty())
5388 			{
5389 				if (QFile::exists(iafData.source))
5390 				{
5391 					PrefsManager::instance().prefsFile->getContext("dirs")->set("images", iafData.source.left(iafData.source.lastIndexOf("/")));
5392 					currItem->pixm.imgInfo.isRequest = false;
5393 					currItem->UseEmbedded = true;
5394 					currItem->EmbeddedProfile.clear();
5395 					currItem->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
5396 					currItem->ImageIntent = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
5397 					qApp->setOverrideCursor( QCursor(Qt::WaitCursor) );
5398 					qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
5399 					loadPict(iafData.source, currItem, false, true);
5400 					if (iafData.sizeType==3) //Frame is size of imported image
5401 					{
5402 						currItem->setWidth(static_cast<double>(currItem->OrigW * 72.0 / currItem->pixm.imgInfo.xres));
5403 						currItem->setHeight(static_cast<double>(currItem->OrigH * 72.0 / currItem->pixm.imgInfo.yres));
5404 						currItem->OldB2 = currItem->width();
5405 						currItem->OldH2 = currItem->height();
5406 						currItem->updateClip();
5407 					}
5408 					qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
5409 					qApp->restoreOverrideCursor();
5410 				}
5411 			}
5412 			if (iafData.frameType==PageItem::TextFrame)
5413 			{
5414 				currItem->setColumns(iafData.columnCount);
5415 				currItem->setColumnGap(iafData.columnGap/m_docUnitRatio);
5416 				if (i==0 && iafData.linkToExistingFrame && prevItem != nullptr)
5417 				{
5418 					prevItem->link(currItem);
5419 				}
5420 				if (i!=0 && iafData.linkTextFrames && prevItem != nullptr)
5421 				{
5422 					prevItem->link(currItem);
5423 				}
5424 				if (!iafData.source.isEmpty() && prevItem == nullptr && QFile::exists(iafData.source))
5425 				{
5426 					gtGetText* gt = new gtGetText(this);
5427 					if (iafData.impsetup.runDialog)
5428 						gt->launchImporter(iafData.impsetup.importer, iafData.impsetup.filename, iafData.impsetup.textOnly, iafData.impsetup.encoding, true, iafData.impsetup.prefixNames, currItem);
5429 					delete gt;
5430 				}
5431 				prevItem=currItem;
5432 			}
5433 		}
5434 	}
5435 
5436 	if (transaction)
5437 		transaction.commit();
5438 	setCurrentPage(oldCurrentPage);
5439 	changed();
5440 	regionsChanged()->update(QRectF());
5441 	return z;
5442 }
5443 
5444 
itemAddDetails(const PageItem::ItemType itemType,const PageItem::ItemFrameType frameType,PageItem * newItem)5445 void ScribusDoc::itemAddDetails(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, PageItem* newItem)
5446 {
5447 	ParagraphStyle defaultParagraphStyle;
5448 	Q_ASSERT(newItem->realItemType() == itemType);
5449 	switch (itemType)
5450 	{
5451 		case PageItem::ImageFrame:
5452 			newItem->setImageXYScale(m_docPrefsData.itemToolPrefs.imageScaleX, m_docPrefsData.itemToolPrefs.imageScaleY);
5453 			newItem->ScaleType = m_docPrefsData.itemToolPrefs.imageScaleType;
5454 			newItem->AspectRatio = m_docPrefsData.itemToolPrefs.imageAspectRatio;
5455 			newItem->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
5456 			newItem->ImageIntent = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
5457 			newItem->setFillShade(m_docPrefsData.itemToolPrefs.imageFillColorShade);
5458 			newItem->setLineShade(m_docPrefsData.itemToolPrefs.imageStrokeColorShade);
5459 			break;
5460 		case PageItem::LatexFrame:
5461 		case PageItem::OSGFrame:
5462 			newItem->setFillShade(m_docPrefsData.itemToolPrefs.imageFillColorShade);
5463 			newItem->setLineShade(m_docPrefsData.itemToolPrefs.imageStrokeColorShade);
5464 			break;
5465 		case PageItem::NoteFrame:
5466 		case PageItem::TextFrame:
5467 			newItem->setFillColor(m_docPrefsData.itemToolPrefs.textFillColor);
5468 			newItem->setFillShade(m_docPrefsData.itemToolPrefs.textFillColorShade);
5469 			newItem->setLineColor(m_docPrefsData.itemToolPrefs.textLineColor);
5470 			newItem->setLineShade(m_docPrefsData.itemToolPrefs.textLineColorShade);
5471 			// 13792 : Commented out because this trigger the first line of a text frame having
5472 			// default character style explictly assigned, which we don't want
5473 			/*defaultParagraphStyle.setParent(CommonStrings::DefaultParagraphStyle);
5474 			defaultParagraphStyle.charStyle().setParent(CommonStrings::DefaultCharacterStyle);
5475 			newItem->itemText.setDefaultStyle(defaultParagraphStyle);*/
5476 			break;
5477 		case PageItem::Line:
5478 			newItem->PLineArt = Qt::PenStyle(m_docPrefsData.itemToolPrefs.lineStyle);
5479 			newItem->setLineShade(m_docPrefsData.itemToolPrefs.lineColorShade);
5480 			break;
5481 		case PageItem::Polygon:
5482 			if (frameType!=PageItem::Rectangle && frameType!=PageItem::Ellipse)
5483 			{
5484 				newItem->ClipEdited = true;
5485 				newItem->FrameType = 3;
5486 			}
5487 			break;
5488 		case PageItem::PolyLine:
5489 			newItem->ClipEdited = true;
5490 			break;
5491 		case PageItem::PathText:
5492 			break;
5493 		case PageItem::Symbol:
5494 		case PageItem::Group:
5495 		case PageItem::RegularPolygon:
5496 		case PageItem::Arc:
5497 		case PageItem::Spiral:
5498 			newItem->ClipEdited = true;
5499 			newItem->FrameType = 3;
5500 		//At this point, we cannot create a PathText item like this, only by conversion, do nothing
5501 			break;
5502 		default:
5503 			break;
5504 	}
5505 
5506 	if (frameType == PageItem::Rectangle || itemType == PageItem::TextFrame || itemType == PageItem::ImageFrame || itemType == PageItem::LatexFrame || itemType == PageItem::OSGFrame || itemType == PageItem::Symbol || itemType == PageItem::Group || itemType == PageItem::Table || itemType == PageItem::NoteFrame)
5507 	{
5508 		newItem->SetRectFrame();
5509 		//TODO one day hopefully, if (ScCore->usingGUI())
5510 		newItem->setRedrawBounding();
5511 		newItem->ContourLine = newItem->PoLine.copy();
5512 	}
5513 
5514 	if (frameType==PageItem::Ellipse)
5515 	{
5516 		newItem->SetOvalFrame();
5517 		//TODO one day hopefully, if (ScCore->usingGUI())
5518 		newItem->setRedrawBounding();
5519 		newItem->ContourLine = newItem->PoLine.copy();
5520 	}
5521 
5522 	//ItemType Polygon
5523 	if (itemType == PageItem::Polygon || itemType == PageItem::PolyLine || itemType == PageItem::Spiral || itemType == PageItem::RegularPolygon || itemType == PageItem::Arc)
5524 	{
5525 		newItem->PLineArt = Qt::PenStyle(m_docPrefsData.itemToolPrefs.shapeLineStyle);
5526 		newItem->setFillShade(m_docPrefsData.itemToolPrefs.shapeFillColorShade);
5527 		newItem->setLineShade(m_docPrefsData.itemToolPrefs.shapeLineColorShade);
5528 		if ((itemType == PageItem::Polygon) || (itemType == PageItem::RegularPolygon) || (itemType == PageItem::Arc))
5529 			newItem->ContourLine = newItem->PoLine.copy();
5530 	}
5531 }
5532 
5533 
itemAddCommit(PageItem * item)5534 bool ScribusDoc::itemAddCommit(PageItem* item)
5535 {
5536 	//TODO use the parameter
5537 	if (m_itemCreationTransaction.isStarted() && appMode !=  modeDrawBezierLine)
5538 	{
5539 		if (item != nullptr)
5540 		{
5541 			item->checkChanges(true);
5542 			QString targetName = Um::ScratchSpace;
5543 			if (item->OwnPage > -1)
5544 				targetName = Pages->at(item->OwnPage)->getUName();
5545 			m_itemCreationTransaction.commit(targetName, item->getUPixmap(), Um::Create + " " + item->getUName(),  "", Um::ICreate);
5546 			m_itemCreationTransaction.reset();
5547 			if (!isLoading())
5548 				return true;
5549 		}
5550 	}
5551 	return false;
5552 }
5553 
5554 
getItemNrFromUniqueID(uint unique)5555 int ScribusDoc::getItemNrFromUniqueID(uint unique)
5556 {
5557 	// FIXME : don't work for items inside groups
5558 	// Needs to fix group/ungroup undo first
5559 	int ret = 0;
5560 	for (int i = 0; i < Items->count(); ++i)
5561 	{
5562 		if (Items->at(i)->uniqueNr == unique)
5563 		{
5564 			ret = Items->indexOf(Items->at(i));
5565 			break;
5566 		}
5567 	}
5568 	return ret;
5569 }
5570 
getItemFromName(const QString & name) const5571 PageItem* ScribusDoc::getItemFromName(const QString& name) const
5572 {
5573 	PageItemIterator it(*Items, PageItemIterator::IterateInGroups);
5574 	for (PageItem* currItem = *it; currItem != nullptr; currItem = it.next())
5575 	{
5576 		if (currItem->itemName() == name)
5577 			return currItem;
5578 	}
5579 	return nullptr;
5580 }
5581 
rebuildItemLists()5582 void ScribusDoc::rebuildItemLists()
5583 {
5584 	// #5826 Rebuild items list in case layer order as been changed
5585 	QList<PageItem*> newDocItems, newMasterItems;
5586 	Layers.sort();
5587 	int layerCount = this->layerCount();
5588 	for (int la = 0; la < layerCount; ++la)
5589 	{
5590 		PageItem* currItem;
5591 		int layerID = Layers.at(la).ID;
5592 		for (int it = 0; it < DocItems.count(); ++it)
5593 		{
5594 			currItem = DocItems.at(it);
5595 			if (currItem->m_layerID != layerID)
5596 				continue;
5597 			newDocItems.append(currItem);
5598 		}
5599 		for (int it = 0; it < MasterItems.count(); ++it)
5600 		{
5601 			currItem = MasterItems.at(it);
5602 			if (currItem->m_layerID != layerID)
5603 				continue;
5604 			newMasterItems.append(currItem);
5605 		}
5606 	}
5607 	DocItems    = newDocItems;
5608 	MasterItems = newMasterItems;
5609 }
5610 
5611 
usesAutomaticTextFrames() const5612 bool ScribusDoc::usesAutomaticTextFrames() const
5613 {
5614 	return m_automaticTextFrames;
5615 }
5616 
setUsesAutomaticTextFrames(bool atf)5617 void ScribusDoc::setUsesAutomaticTextFrames(bool atf)
5618 {
5619 	m_automaticTextFrames = atf;
5620 }
5621 
loadPict(const QString & fn,PageItem * pageItem,bool reload,bool showMsg)5622 bool ScribusDoc::loadPict(const QString& fn, PageItem *pageItem, bool reload, bool showMsg)
5623 {
5624 	if (!reload)
5625 	{
5626 		if (pageItem->imageIsAvailable)
5627 		{
5628 			if (ScCore->fileWatcher->isWatching(pageItem->Pfile))
5629 				ScCore->fileWatcher->removeFile(pageItem->Pfile);
5630 			if (pageItem->isTempFile)
5631 			{
5632 				QFile::remove(pageItem->Pfile);
5633 				pageItem->Pfile.clear();
5634 			}
5635 			pageItem->isInlineImage = false;
5636 			pageItem->isTempFile = false;
5637 		}
5638 	}
5639 	if (!pageItem->loadImage(fn, reload, -1, showMsg))
5640 	{
5641 		if (!reload)
5642 		{
5643 			if (m_hasGUI)
5644 			{
5645 				QFileInfo fi(pageItem->Pfile);
5646 				ScCore->fileWatcher->addDir(fi.absolutePath());
5647 			}
5648 		}
5649 		return false;
5650 	}
5651 	if (!reload)
5652 	{
5653 		if (m_hasGUI)
5654 		{
5655 			ScCore->fileWatcher->addFile(pageItem->Pfile);
5656 		}
5657 	}
5658 	if (!isLoading())
5659 	{
5660 		pageItem->update();
5661 		changed();
5662 	}
5663 	return true;
5664 }
5665 
5666 
canvasMinMax(FPoint & minPoint,FPoint & maxPoint)5667 void ScribusDoc::canvasMinMax(FPoint& minPoint, FPoint& maxPoint)
5668 {
5669 	PageItem *currItem;
5670 	double minx =  std::numeric_limits<double>::max();
5671 	double miny =  std::numeric_limits<double>::max();
5672 	double maxx = -std::numeric_limits<double>::max();
5673 	double maxy = -std::numeric_limits<double>::max();
5674 	int docItemsCount=Items->count();
5675 	if (docItemsCount != 0)
5676 	{
5677 		for (int i = 0; i < docItemsCount; ++i)
5678 		{
5679 			currItem = Items->at(i);
5680 			if (currItem->rotation() != 0.0)
5681 			{
5682 				FPointArray pb;
5683 				pb.resize(0);
5684 				pb.addPoint(FPoint(currItem->xPos(), currItem->yPos()));
5685 				FPoint p1(currItem->width(), 0.0, currItem->xPos(), currItem->yPos(), currItem->rotation(), 1.0, 1.0);
5686 				pb.addPoint(p1);
5687 				FPoint p2(currItem->width(), currItem->height(), currItem->xPos(), currItem->yPos(), currItem->rotation(), 1.0, 1.0);
5688 				pb.addPoint(p2);
5689 				FPoint p3(0.0, currItem->height(), currItem->xPos(), currItem->yPos(), currItem->rotation(), 1.0, 1.0);
5690 				pb.addPoint(p3);
5691 				for (uint pc = 0; pc < 4; ++pc)
5692 				{
5693 					minx = qMin(minx, pb.point(pc).x());
5694 					miny = qMin(miny, pb.point(pc).y());
5695 					maxx = qMax(maxx, pb.point(pc).x());
5696 					maxy = qMax(maxy, pb.point(pc).y());
5697 				}
5698 			}
5699 			else
5700 			{
5701 				minx = qMin(minx, currItem->xPos());
5702 				miny = qMin(miny, currItem->yPos());
5703 				maxx = qMax(maxx, currItem->xPos() + currItem->width());
5704 				maxy = qMax(maxy, currItem->yPos() + currItem->height());
5705 			}
5706 		}
5707 	}
5708 	else
5709 	{
5710 		ScPage* page;
5711 		MarginStruct pageBleeds;
5712 		int docPageCount = Pages->count();
5713 		for (int i = 0; i < docPageCount; ++i)
5714 		{
5715 			page = Pages->at(i);
5716 			getBleeds(page, pageBleeds);
5717 			minx = qMin(minx, page->xOffset() - pageBleeds.left());
5718 			miny = qMin(miny, page->yOffset() - pageBleeds.top());
5719 			maxx = qMax(maxx, page->xOffset() + page->width() + pageBleeds.left() + pageBleeds.right());
5720 			maxy = qMax(maxy, page->yOffset() + page->height() + pageBleeds.top() + pageBleeds.bottom());
5721 		}
5722 	}
5723 	minPoint.setX(minx);
5724 	minPoint.setY(miny);
5725 	maxPoint.setX(maxx);
5726 	maxPoint.setY(maxy);
5727 }
5728 
canvasOptimalRect()5729 QRectF ScribusDoc::canvasOptimalRect()
5730 {
5731 	double x, y, width, height;
5732 	QRectF canvasRect;
5733 	MarginStruct pageBleeds;
5734 	PageItem *currItem;
5735 	ScPage* page;
5736 
5737 	int pageCount = Pages->count();
5738 	for (int i = 0; i < pageCount; ++i)
5739 	{
5740 		page = Pages->at(i);
5741 		getBleeds(page, pageBleeds);
5742 		x = page->xOffset() - pageBleeds.left();
5743 		y = page->yOffset() - pageBleeds.top();
5744 		width  = page->width() + pageBleeds.left() + pageBleeds.right();
5745 		height = page->height() + pageBleeds.top() + pageBleeds.bottom();
5746 		canvasRect = canvasRect.united(QRectF(x, y, width, height));
5747 	}
5748 
5749 	int itemsCount = Items->count();
5750 	for (int i = 0; i < itemsCount; ++i)
5751 	{
5752 		currItem = Items->at(i);
5753 		QRectF itemRect = currItem->getBoundingRect();
5754 		canvasRect = canvasRect.united(itemRect);
5755 	}
5756 
5757 	const MarginStruct& scratch = m_docPrefsData.displayPrefs.scratch;
5758 	canvasRect.adjust(-scratch.left(), -scratch.top(), scratch.right(), scratch.bottom());
5759 
5760 	return canvasRect;
5761 }
5762 
5763 
OnPage(double x2,double y2)5764 int ScribusDoc::OnPage(double x2, double  y2)
5765 {
5766 	int retw = -1;
5767 	if (masterPageMode())
5768 	{
5769 		int x = static_cast<int>(m_currentPage->xOffset() - m_docPrefsData.docSetupPrefs.bleeds.left());
5770 		int y = static_cast<int>(m_currentPage->yOffset() - m_docPrefsData.docSetupPrefs.bleeds.top());
5771 		int w = static_cast<int>(m_currentPage->width() + m_docPrefsData.docSetupPrefs.bleeds.left() + m_docPrefsData.docSetupPrefs.bleeds.right());
5772 		int h = static_cast<int>(m_currentPage->height() + m_docPrefsData.docSetupPrefs.bleeds.bottom() + m_docPrefsData.docSetupPrefs.bleeds.top());
5773 		if (QRect(x, y, w, h).contains(qRound(x2), qRound(y2)))
5774 			retw = m_currentPage->pageNr();
5775 	}
5776 	else
5777 	{
5778 		int docPageCount = Pages->count();
5779 		MarginStruct pageBleeds;
5780 		for (int a = 0; a < docPageCount; ++a)
5781 		{
5782 			getBleeds(a, pageBleeds);
5783 			int x = static_cast<int>(Pages->at(a)->xOffset() - pageBleeds.left());
5784 			int y = static_cast<int>(Pages->at(a)->yOffset() - pageBleeds.top());
5785 			int w = static_cast<int>(Pages->at(a)->width() + pageBleeds.left() + pageBleeds.right());
5786 			int h = static_cast<int>(Pages->at(a)->height() + pageBleeds.bottom() + pageBleeds.top());
5787 			if (QRect(x, y, w, h).contains(qRound(x2), qRound(y2)))
5788 			{
5789 				retw = static_cast<int>(a);
5790 				break;
5791 			}
5792 		}
5793 	}
5794 	return retw;
5795 }
5796 
5797 
OnPage(PageItem * currItem)5798 int ScribusDoc::OnPage(PageItem *currItem)
5799 {
5800 	int retw = -1;
5801 
5802 	double w2 = currItem->visualWidth();
5803 	double h2 = currItem->visualHeight();
5804 	double x2 = -currItem->visualLineWidth() / 2.0;
5805 	double y2 = -currItem->visualLineWidth() / 2.0;
5806 	QTransform t = currItem->getTransform();
5807 	QRectF itemRect = t.mapRect(QRectF(x2, y2, w2, h2));
5808 
5809 	if (masterPageMode())
5810 	{
5811 		ScPage* currPage = m_currentPage;
5812 		double x1 = currPage->xOffset() - m_docPrefsData.docSetupPrefs.bleeds.left();
5813 		double y1 = currPage->yOffset() - m_docPrefsData.docSetupPrefs.bleeds.top();
5814 		double w1 = currPage->width() + m_docPrefsData.docSetupPrefs.bleeds.left() + m_docPrefsData.docSetupPrefs.bleeds.right();
5815 		double h1 = currPage->height() + m_docPrefsData.docSetupPrefs.bleeds.bottom() + m_docPrefsData.docSetupPrefs.bleeds.top();
5816 		QRectF pageRect(x1, y1, w1, h1);
5817 		if (itemRect.intersects(pageRect))
5818 			retw = currPage->pageNr();
5819 	}
5820 	else
5821 	{
5822 		MarginStruct pageBleeds;
5823 		int docPageCount = Pages->count();
5824 		for (int a = 0; a < docPageCount; ++a)
5825 		{
5826 			getBleeds(a, pageBleeds);
5827 			double x1 = Pages->at(a)->xOffset() - pageBleeds.left();
5828 			double y1 = Pages->at(a)->yOffset() - pageBleeds.top();
5829 			double w1 = Pages->at(a)->width() + pageBleeds.left() + pageBleeds.right();
5830 			double h1 = Pages->at(a)->height() + pageBleeds.bottom() + pageBleeds.top();
5831 			QRectF pageRect(x1, y1, w1, h1);
5832 			if (itemRect.intersects(pageRect))
5833 			{
5834 				retw = static_cast<int>(a);
5835 				break;
5836 			}
5837 		}
5838 	}
5839 	if ((retw == -1) && (currItem->isBookmark))
5840 	{
5841 		//FIXME emit DelBM(currItem);
5842 		currItem->isBookmark = false;
5843 	}
5844 	return retw;
5845 }
5846 
5847 
GroupOnPage(PageItem * currItem)5848 void ScribusDoc::GroupOnPage(PageItem* currItem)
5849 {
5850 	if (!currItem->isGroup())
5851 		return;
5852 	QList<PageItem*> Objects = currItem->getAllChildren();
5853 	int Off_Page = -1;
5854 	int On_Page = 999999;
5855 	uint objectCount = Objects.count();
5856 	for (uint a = 0; a < objectCount; ++a)
5857 	{
5858 		int res = OnPage(Objects.at(a));
5859 		Off_Page = qMax(Off_Page, res);
5860 		if (res != -1)
5861 			On_Page = qMin(On_Page, res);
5862 	}
5863 	int final = -1;
5864 	if (Off_Page != -1)
5865 		final = On_Page;
5866 	for (uint a = 0; a < objectCount; ++a)
5867 	{
5868 		Objects.at(a)->OwnPage = final;
5869 	}
5870 	currItem->OwnPage = OnPage(currItem);
5871 }
5872 
fixItemPageOwner()5873 void  ScribusDoc::fixItemPageOwner()
5874 {
5875 	int pageNr;
5876 	ScPage* page;
5877 	PageItem* currItem;
5878 	MarginStruct pageBleeds;
5879 
5880 	for (int i = 0; i < Items->count(); ++i)
5881 	{
5882 		currItem = Items->at(i);
5883 		pageNr = currItem->OwnPage;
5884 
5885 		// TODO check group owner
5886 		if (currItem->getAllChildren().count() > 0)
5887 			continue;
5888 
5889 		// If item has a valid page, check that
5890 		// specified page effectively contain the item
5891 		if (pageNr >= 0 && pageNr < Pages->count())
5892 		{
5893 			page = Pages->at(pageNr);
5894 			getBleeds(page, pageBleeds);
5895 			double x1 = page->xOffset() - pageBleeds.left();
5896 			double y1 = page->yOffset() - pageBleeds.top();
5897 			double w1 = page->width()   + pageBleeds.left() + pageBleeds.right();
5898 			double h1 = page->height()  + pageBleeds.bottom() + pageBleeds.top();
5899 			QTransform t = currItem->getTransform();
5900 			double w2 = currItem->visualWidth();
5901 			double h2 = currItem->visualHeight();
5902 			double x2 = -currItem->visualLineWidth() / 2.0;
5903 			double y2 = -currItem->visualLineWidth() / 2.0;
5904 
5905 			QRectF pageRect(x1, y1, w1, h1);
5906 			QRectF itemRect = t.mapRect(QRectF(x2, y2, w2, h2));
5907 			if (itemRect.intersects(pageRect))
5908 				continue;
5909 		}
5910 
5911 		// If no or page owner is incorrect, recompute page owner
5912 		currItem->setOwnerPage(OnPage(currItem));
5913  	}
5914 
5915 	// #10379: Scribus crash when opening .sla document
5916 	// OwnPage is not meaningful for inline frame
5917 	for (auto it = FrameItems.begin(); it != FrameItems.end(); ++it)
5918 	{
5919 		currItem = it.value();
5920 		currItem->OwnPage = -1;
5921  	}
5922 
5923 	// #11274: Scribus crash when opening .sla document
5924 	// OwnPage is not meaningful for pattern items
5925 	for (auto patternIt = docPatterns.begin(); patternIt != docPatterns.end(); ++patternIt)
5926 	{
5927 		QList<PageItem*> patternItems = patternIt->items;
5928 		while (patternItems.count() > 0)
5929 		{
5930 			PageItem* patItem = patternItems.takeAt(0);
5931 			if (patItem->isGroup())
5932 				patternItems += patItem->groupItemList;
5933 			patItem->OwnPage = -1;
5934 		}
5935 	}
5936 }
5937 
fixCharacterStyles()5938 void ScribusDoc::fixCharacterStyles()
5939 {
5940 	for (int i = 0; i < m_docCharStyles.count(); ++i)
5941 	{
5942 		CharStyle& charStyle = m_docCharStyles[i];
5943 		QString parentName = charStyle.parent();
5944 		if (parentName.isEmpty())
5945 			continue;
5946 		if (!m_docCharStyles.contains(parentName))
5947 			charStyle.setParent(QString());
5948 	}
5949 }
5950 
fixParagraphStyles()5951 void ScribusDoc::fixParagraphStyles()
5952 {
5953 	for (int i = 0; i < m_docParagraphStyles.count(); ++i)
5954 	{
5955 		ParagraphStyle& parStyle = m_docParagraphStyles[i];
5956 		QString parentName = parStyle.parent();
5957 		if (!parentName.isEmpty())
5958 		{
5959 			if (!m_docParagraphStyles.contains(parentName))
5960 				parStyle.setParent(QString());
5961 		}
5962 		QString charStyleName = parStyle.charStyle().parent();
5963 		if (!charStyleName.isEmpty())
5964 		{
5965 			if (!m_docCharStyles.contains(charStyleName))
5966 				parStyle.charStyle().setParent(QString());
5967 		}
5968 		QString peStyleName = parStyle.peCharStyleName();
5969 		if (peStyleName.isEmpty())
5970 			continue;
5971 		if (!m_docCharStyles.contains(peStyleName))
5972 			parStyle.resetPeCharStyleName();
5973 	}
5974 }
5975 
fixNotesStyles()5976 void ScribusDoc::fixNotesStyles()
5977 {
5978 	for (int i = 0; i < m_docNotesStylesList.count(); ++i)
5979 	{
5980 		NotesStyle* noteStyle = m_docNotesStylesList[i];
5981 		QString markChStyle = noteStyle->marksChStyle();
5982 		if (!markChStyle.isEmpty() && !m_docCharStyles.contains(markChStyle))
5983 			noteStyle->setMarksCharStyle(QString());
5984 		QString noteParStyle = noteStyle->notesParStyle();
5985 		if (!noteParStyle.isEmpty() && !m_docParagraphStyles.contains(noteParStyle))
5986 			noteStyle->setNotesParStyle(QString());
5987 	}
5988 }
5989 
5990 struct oldPageVar
5991 {
5992 	uint newPg;
5993 	double oldXO;
5994 	double oldYO;
5995 };
5996 
5997 
5998 //CB TODO make a function to determine the place of the page.. ie, so we know the left and right margins
5999 // without running this monster
reformPages(bool moveObjects)6000 void ScribusDoc::reformPages(bool moveObjects)
6001 {
6002 	QMap<uint, oldPageVar> pageTable;
6003 	struct oldPageVar oldPg;
6004 	int counter = pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].FirstPage;
6005 	int rowcounter = 0;
6006 	double maxYPos=0.0, maxXPos=0.0;
6007 	double currentXPos=m_docPrefsData.displayPrefs.scratch.left(), currentYPos=m_docPrefsData.displayPrefs.scratch.top(), lastYPos=Pages->at(0)->initialHeight();
6008 //	currentXPos += (pageWidth+pageSets[currentPageLayout].GapHorizontal) * counter;
6009 	currentXPos += (m_docPrefsData.docSetupPrefs.pageWidth+m_docPrefsData.displayPrefs.pageGapHorizontal) * counter;
6010 
6011 	lastYPos = Pages->at(0)->initialHeight();
6012 	ScPage* page;
6013 	int docPageCount=Pages->count();
6014 	for (int i = 0; i < docPageCount; ++i)
6015 	{
6016 		page = Pages->at(i);
6017 		oldPg.oldXO = page->xOffset();
6018 		oldPg.oldYO = page->yOffset();
6019 		oldPg.newPg = i;
6020 		pageTable.insert(page->pageNr(), oldPg);
6021 		page->setPageNr(i);
6022 		if (masterPageMode())
6023 		{
6024 			page->setXOffset(m_docPrefsData.displayPrefs.scratch.left());
6025 			page->setYOffset(m_docPrefsData.displayPrefs.scratch.top());
6026 			if (page->LeftPg == 0)
6027 			{
6028 				page->Margins.setRight(page->initialMargins.right());
6029 				page->Margins.setLeft(page->initialMargins.left());
6030 			}
6031 			else if ((page->LeftPg > 1) && (page->LeftPg < pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns))
6032 			{
6033 				page->Margins.setLeft(page->initialMargins.left());
6034 				page->Margins.setRight(page->initialMargins.left());
6035 			}
6036 			else
6037 			{
6038 				page->Margins.setLeft(page->initialMargins.right());
6039 				page->Margins.setRight(page->initialMargins.left());
6040 			}
6041 		}
6042 		else
6043 		{
6044 			page->setWidth(page->initialWidth());
6045 			page->setHeight(page->initialHeight());
6046 			page->setXOffset(currentXPos);
6047 			page->setYOffset(currentYPos);
6048 			if (counter < pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns-1)
6049 			{
6050 				currentXPos += page->width() + m_docPrefsData.displayPrefs.pageGapHorizontal;
6051 				lastYPos = qMax(lastYPos, page->height());
6052 				if (counter == 0)
6053 				{
6054 					page->Margins.setLeft(page->initialMargins.right());
6055 					page->Margins.setRight(page->initialMargins.left());
6056 				}
6057 				else
6058 				{
6059 					page->Margins.setLeft(page->initialMargins.left());
6060 					page->Margins.setRight(page->initialMargins.left());
6061 				}
6062 			}
6063 			else
6064 			{
6065 				currentXPos = m_docPrefsData.displayPrefs.scratch.left();
6066 				if (pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns > 1)
6067 					currentYPos += qMax(lastYPos, page->height())+m_docPrefsData.displayPrefs.pageGapVertical;
6068 				else
6069 					currentYPos += page->height()+m_docPrefsData.displayPrefs.pageGapVertical;
6070 				lastYPos = 0;
6071 				page->Margins.setRight(page->initialMargins.right());
6072 				page->Margins.setLeft(page->initialMargins.left());
6073 			}
6074 			counter++;
6075 			if (counter > pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns-1)
6076 			{
6077 				counter = 0;
6078 				rowcounter++;
6079 				if (rowcounter > pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Rows-1)
6080 					rowcounter = 0;
6081 			}
6082 		}
6083 		page->Margins.setTop(page->initialMargins.top());
6084 		page->Margins.setBottom(page->initialMargins.bottom());
6085 		maxXPos = qMax(maxXPos, page->xOffset()+page->width()+m_docPrefsData.displayPrefs.scratch.right());
6086 		maxYPos = qMax(maxYPos, page->yOffset()+page->height()+m_docPrefsData.displayPrefs.scratch.bottom());
6087 	}
6088 	if (!isLoading())
6089 	{
6090 		QList<PageItem*> weldedItems;
6091 		m_undoManager->setUndoEnabled(false);
6092 		this->beginUpdate();
6093 		int docItemsCount = Items->count();
6094 		for (int ite = 0; ite < docItemsCount; ++ite)
6095 		{
6096 			PageItem *item = Items->at(ite);
6097 			if (item->OwnPage < 0)
6098 			{
6099 				if (item->isGroup())
6100 					GroupOnPage(item);
6101 				else
6102 					item->OwnPage = OnPage(item);
6103 			}
6104 			else if (moveObjects)
6105 			{
6106 				oldPg = pageTable[item->OwnPage];
6107 				if (item->isWelded())
6108 					weldedItems.append(item->itemsWeldedTo());
6109 				if (!weldedItems.contains(item))
6110 				{
6111 					const ScPage* oldPage = Pages->at(oldPg.newPg);
6112 					item->moveBy(-oldPg.oldXO + oldPage->xOffset(), -oldPg.oldYO + oldPage->yOffset());
6113 				}
6114 				item->OwnPage = static_cast<int>(oldPg.newPg);
6115 				if (item->isGroup())
6116 				{
6117 					QList<PageItem*> groupItems = item->groupItemList;
6118 					while (groupItems.count() > 0)
6119 					{
6120 						PageItem* groupItem = groupItems.takeAt(0);
6121 						if (groupItem->isGroup())
6122 							groupItems += groupItem->groupItemList;
6123 						if (groupItem->OwnPage < 0)
6124 							continue;
6125 						oldPg = pageTable[groupItem->OwnPage];
6126 						groupItem->OwnPage = static_cast<int>(oldPg.newPg);
6127 					}
6128 				}
6129 			}
6130 			else
6131 			{
6132 				if (item->isGroup())
6133 					GroupOnPage(item);
6134 				else
6135 					item->OwnPage = OnPage(item);
6136 			}
6137 			item->setRedrawBounding();
6138 		}
6139 		this->endUpdate();
6140 		m_undoManager->setUndoEnabled(true);
6141 	}
6142 
6143 	if (isLoading() && is12doc)
6144 		return;
6145 	if (!isLoading())
6146 	{
6147 		FPoint minPoint, maxPoint;
6148 		const MarginStruct& scratch = m_docPrefsData.displayPrefs.scratch;
6149 		updateMarks(true);
6150 		canvasMinMax(minPoint, maxPoint);
6151 		FPoint maxSize(qMax(maxXPos, maxPoint.x() + scratch.right()), qMax(maxYPos, maxPoint.y() + scratch.bottom()));
6152 		adjustCanvas(FPoint(qMin(0.0, minPoint.x() - scratch.left()), qMin(0.0, minPoint.y() - scratch.top())), maxSize, true);
6153 		changed();
6154 	}
6155 	else
6156 	{
6157 		FPoint maxSize(maxXPos, maxYPos);
6158 		adjustCanvas(FPoint(0, 0), maxSize);
6159 	}
6160 }
6161 
refreshGuides()6162 void ScribusDoc::refreshGuides()
6163 {
6164 	for (int i = 0; i < Pages->count(); ++i)
6165 	{
6166 		ScPage* page = Pages->at(i);
6167 		page->guides.addHorizontals(page->guides.getAutoHorizontals(page), GuideManagerCore::Auto);
6168 		page->guides.addVerticals(page->guides.getAutoVerticals(page), GuideManagerCore::Auto);
6169 	}
6170 }
6171 
getXOffsetForPage(int pageNumber)6172 double ScribusDoc::getXOffsetForPage(int pageNumber)
6173 {
6174 	if (Pages->at(pageNumber) != nullptr)
6175 		return Pages->at(pageNumber)->xOffset();
6176 	return -1.0;
6177 }
6178 
getYOffsetForPage(int pageNumber)6179 double ScribusDoc::getYOffsetForPage(int pageNumber)
6180 {
6181 	if (Pages->at(pageNumber) != nullptr)
6182 		return Pages->at(pageNumber)->yOffset();
6183 	return -1.0;
6184 }
6185 
getBleeds(int pageNumber,MarginStruct & bleedData)6186 void ScribusDoc::getBleeds(int pageNumber, MarginStruct &bleedData)
6187 {
6188 	if (pageNumber >= 0 && pageNumber < Pages->size())
6189 		getBleeds(Pages->at(pageNumber), bleedData);
6190 	else
6191 		qCritical() << "Attempting to get bleeds for non-existant page";
6192 }
6193 
getBleeds(const ScPage * page,MarginStruct & bleedData)6194 void ScribusDoc::getBleeds(const ScPage* page, MarginStruct& bleedData)
6195 {
6196 	getBleeds(page, m_docPrefsData.docSetupPrefs.bleeds, bleedData);
6197 }
6198 
getBleeds(const ScPage * page,const MarginStruct & baseValues,MarginStruct & bleedData)6199 void ScribusDoc::getBleeds(const ScPage* page, const MarginStruct& baseValues, MarginStruct& bleedData)
6200 {
6201 	bleedData.setBottom(baseValues.bottom());
6202 	bleedData.setTop(baseValues.top());
6203 	if (pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns == 1)
6204 	{
6205 		bleedData.setRight(baseValues.right());
6206 		bleedData.setLeft(baseValues.left());
6207 	}
6208 	else
6209 	{
6210 		PageLocation pageLocation = MiddlePage;
6211 		if (page->pageNameEmpty()) // Standard page
6212 			pageLocation = locationOfPage(page->pageNr());
6213 		else if (page->LeftPg == 1) // Left Master page
6214 			pageLocation = LeftPage;
6215 		else if (page->LeftPg == 0) // Right Master page
6216 			pageLocation = RightPage;
6217 		else // Middle Master page
6218 			pageLocation = MiddlePage;
6219 
6220 		if (pageLocation == LeftPage)
6221 		{
6222 			bleedData.setRight(baseValues.left());
6223 			bleedData.setLeft(baseValues.right());
6224 		}
6225 		else if (pageLocation == RightPage)
6226 		{
6227 			bleedData.setRight(baseValues.right());
6228 			bleedData.setLeft(baseValues.left());
6229 		}
6230 		else
6231 		{
6232 			bleedData.setRight(baseValues.left());
6233 			bleedData.setLeft(baseValues.left());
6234 		}
6235 	}
6236 }
6237 
6238 
convertItemTo(PageItem * currItem,PageItem::ItemType newType,PageItem * secondaryItem)6239 PageItem* ScribusDoc::convertItemTo(PageItem *currItem, PageItem::ItemType newType, PageItem* secondaryItem)
6240 {
6241 	//Item to convert is nullptr, return
6242 	Q_ASSERT(currItem != nullptr);
6243 	if (currItem == nullptr)
6244 		return nullptr;
6245 	//Don't attempt a Line conversion
6246 	if (newType==PageItem::Line)
6247 		return nullptr;
6248 	PageItem *oldItem = currItem;
6249 	uint oldItemNr;
6250 	if (currItem->isGroupChild())
6251 		oldItemNr = currItem->Parent->asGroupFrame()->groupItemList.indexOf(currItem);
6252 	else
6253 		oldItemNr = Items->indexOf(currItem);
6254 	//Remove old item from the doc's selection if it was in it
6255 	bool removedFromSelection=m_Selection->removeItem(oldItem);
6256 	//Create a new item from the old one
6257 	UndoTransaction transactionConversion;
6258 	PageItem *newItem;
6259 	switch (newType)
6260 	{
6261 		case PageItem::ImageFrame:
6262 			newItem = new PageItem_ImageFrame(*oldItem);
6263 			break;
6264 		case PageItem::TextFrame:
6265 			newItem = new PageItem_TextFrame(*oldItem);
6266 			if (UndoManager::undoEnabled() && oldItem->itemType() == PageItem::PathText)
6267 				transactionConversion = m_undoManager->beginTransaction(m_currentPage->getUName(), nullptr, Um::TextFrame, "", Um::ITextFrame);
6268 			break;
6269 		//We don't allow this
6270 /*		case PageItem::Line:
6271 			newItem = new PageItem_PolyLine(*oldItem);
6272 			break; */
6273 		case PageItem::Polygon:
6274 			newItem = new PageItem_Polygon(*oldItem);
6275 			break;
6276 		case PageItem::PolyLine:
6277 			newItem = new PageItem_PolyLine(*oldItem);
6278 			break;
6279 		case PageItem::PathText:
6280 			if (secondaryItem == nullptr)
6281 				return nullptr;
6282 			if (UndoManager::undoEnabled())
6283 				transactionConversion = m_undoManager->beginTransaction(m_currentPage->getUName(), nullptr, Um::PathText, "", Um::ITextFrame);
6284 			newItem = new PageItem_PathText(*oldItem);
6285 			break;
6286 		default:
6287 			newItem = nullptr;
6288 			break;
6289 	}
6290 	Q_ASSERT(newItem != nullptr);
6291 	//If the new item is null, return. If converting Text to Path, start a transaction
6292 	//as the old bezier will be deleted
6293 	if (newItem == nullptr)
6294 	{
6295 		if (transactionConversion)
6296 		{
6297 			transactionConversion.cancel();
6298 			transactionConversion.reset();
6299 		}
6300 		return nullptr;
6301 	}
6302 	//Do new item type specific adjustments to the new item. Some of this may move when new
6303 	//constructors are built into the item classes
6304 	switch (newType)
6305 	{
6306 		case PageItem::ImageFrame:
6307 			newItem->convertTo(PageItem::ImageFrame);
6308 			break;
6309 		case PageItem::TextFrame:
6310 			newItem->convertTo(PageItem::TextFrame);
6311 			if (oldItem->itemType() == PageItem::PathText)
6312 			{
6313 				uint newPolyItemNo = itemAdd(PageItem::PolyLine, PageItem::Unspecified, currItem->xPos(), currItem->yPos(), currItem->width(), currItem->height(), currItem->lineWidth(), CommonStrings::None, currItem->lineColor());
6314 				PageItem *polyLineItem = Items->at(newPolyItemNo);
6315 				polyLineItem->PoLine = currItem->PoLine.copy();
6316 				polyLineItem->ClipEdited = true;
6317 				polyLineItem->FrameType = 3;
6318 				polyLineItem->setRotation(currItem->rotation());
6319 				adjustItemSize(polyLineItem);
6320 
6321 				newItem->setLineColor(CommonStrings::None);
6322 				newItem->SetRectFrame();
6323 				newItem->setRedrawBounding();
6324 				newItem->setTextToFrameDistLeft(0);
6325 			}
6326 			break;
6327 		//We don't allow this right now
6328 	/*	case PageItem::Line:
6329 			break; */
6330 		case PageItem::Polygon:
6331 			newItem->convertTo(PageItem::Polygon);
6332 			newItem->ClipEdited = true;
6333 			newItem->FrameType = 3;
6334 			if (oldItem->itemType() == PageItem::PolyLine)
6335 			{
6336 				newItem->PoLine.addPoint(newItem->PoLine.point(newItem->PoLine.size()-2));
6337 				newItem->PoLine.addPoint(newItem->PoLine.point(newItem->PoLine.size()-3));
6338 				newItem->PoLine.addPoint(newItem->PoLine.point(0));
6339 				newItem->PoLine.addPoint(newItem->PoLine.point(0));
6340 			}
6341 			newItem->Clip = flattenPath(newItem->PoLine, newItem->Segments);
6342 			newItem->ContourLine = newItem->PoLine.copy();
6343 			break;
6344 		case PageItem::PolyLine:
6345 			newItem->convertTo(PageItem::PolyLine);
6346 			newItem->ClipEdited = true;
6347 			newItem->FrameType = 3;
6348 			if (oldItem->itemType() == PageItem::Line)
6349 			{
6350 				QTransform ma;
6351 				newItem->FrameType = 3;
6352 				ma.rotate(newItem->rotation());
6353 				newItem->PoLine.resize(0);
6354 				newItem->PoLine.addPoint(0.0, 0.0);
6355 				newItem->PoLine.addPoint(0.0, 0.0);
6356 				newItem->PoLine.addPoint(newItem->width(), 0.0);
6357 				newItem->PoLine.addPoint(newItem->width(), 0.0);
6358 				newItem->PoLine.map(ma);
6359 				newItem->setRotation(0.0);
6360 			}
6361 			adjustItemSize(newItem);
6362 			break;
6363 		case PageItem::PathText:
6364 			{
6365 				newItem->convertTo(PageItem::PathText);
6366 				newItem->ClipEdited = true;
6367 				newItem->PoLine = secondaryItem->PoLine.copy();
6368 				newItem->setLineWidth(secondaryItem->lineWidth());
6369 				newItem->setLineColor(secondaryItem->lineColor());
6370 				newItem->PLineArt = secondaryItem->PLineArt;
6371 				newItem->PLineEnd = secondaryItem->PLineEnd;
6372 				newItem->PLineJoin = secondaryItem->PLineJoin;
6373 				//FIXME: Stop using the view here
6374 				adjustItemSize(newItem);
6375 				double dx = secondaryItem->xPos() - newItem->xPos();
6376 				double dy = secondaryItem->yPos() - newItem->yPos();
6377 				moveItem(dx, dy, newItem);
6378 				newItem->setRotation(secondaryItem->rotation());
6379 				newItem->FrameType = 3;
6380 			}
6381 			break;
6382 		default:
6383 			newItem = nullptr;
6384 			break;
6385 	}
6386 	newItem->uniqueNr = oldItem->uniqueNr;
6387 	if (oldItem->isGroupChild())
6388 	{
6389 		oldItem->Parent->asGroupFrame()->groupItemList.replace(oldItemNr, newItem);
6390 		newItem->Parent = oldItem->Parent;
6391 	}
6392 	else
6393 		Items->replace(oldItemNr, newItem);
6394 	//FIXME: shouldn't we delete the oldItem ???
6395 	//Add new item back to selection if old item was in selection
6396 	if (removedFromSelection)
6397 		m_Selection->addItem(newItem);
6398 	// If converting a text frame to another object, drop links
6399 	if (oldItem->isTextFrame() && (newType != PageItem::TextFrame))
6400 		oldItem->dropLinks();
6401 	// If converting text to path, delete the bezier
6402 	if (newType == PageItem::PathText)
6403 	{
6404 		//FIXME: Stop using the view here
6405 		m_View->selectItem(secondaryItem);
6406 		itemSelection_DeleteItem();
6407 		regionsChanged()->update(QRectF());
6408 		m_View->deselectItems(true);
6409 	}
6410 	//Create the undo action for the new item
6411 	if (UndoManager::undoEnabled())
6412 	{
6413 		ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >("Convert Item");
6414 		is->set("CONVERT_ITEM");
6415 		is->setItem(qMakePair(oldItem, newItem));
6416 		//Undo target rests with the Page for object specific undo
6417 		UndoObject *target = Pages->at(0);
6418 		if (newItem->OwnPage > -1)
6419 			target = Pages->at(newItem->OwnPage);
6420 		m_undoManager->action(target, is);
6421 	}
6422 	//Close any undo transaction
6423 	if (transactionConversion)
6424 		transactionConversion.commit();
6425 	return newItem;
6426 }
6427 
currentPageNumber()6428 int ScribusDoc::currentPageNumber()
6429 {
6430 	return m_currentPage->pageNr();
6431 }
6432 
6433 
itemNameExists(const QString & checkItemName)6434 bool ScribusDoc::itemNameExists(const QString& checkItemName)
6435 {
6436 	bool found = false;
6437 	QList<PageItem*> allItems;
6438 	int docItemCount = Items->count();
6439 	for (int i = 0; i < docItemCount; ++i)
6440 	{
6441 		PageItem *currItem = Items->at(i);
6442 		if (checkItemName == currItem->itemName())
6443 			return true;
6444 		if (currItem->isGroup())
6445 		{
6446 			allItems = currItem->getAllChildren();
6447 			for (int ii = 0; ii < allItems.count(); ii++)
6448 			{
6449 				if (checkItemName == allItems.at(ii)->itemName())
6450 					return true;
6451 			}
6452 		}
6453 		allItems.clear();
6454 	}
6455 	return found;
6456 }
6457 
6458 
setMasterPageMode(bool changeToMasterPageMode)6459 void ScribusDoc::setMasterPageMode(bool changeToMasterPageMode)
6460 {
6461 	if (changeToMasterPageMode == m_masterPageMode)
6462 		return;
6463 	m_masterPageMode = changeToMasterPageMode;
6464 	assignPageModeLists();
6465 }
6466 
assignPageModeLists()6467 void ScribusDoc::assignPageModeLists()
6468 {
6469 	if (m_masterPageMode)
6470 	{
6471 		Pages = &MasterPages;
6472 		Items = &MasterItems;
6473 	}
6474 	else
6475 	{
6476 		Pages = &DocPages;
6477 		Items = &DocItems;
6478 	}
6479 }
6480 
setSymbolEditMode(bool mode,const QString & symbolName)6481 void ScribusDoc::setSymbolEditMode(bool mode, const QString& symbolName)
6482 {
6483 	if (mode == m_symbolEditMode)
6484 		return;
6485 	m_symbolEditMode = mode;
6486 	if (mode)
6487 	{
6488 		m_storedLayerID = activeLayer();
6489 		int layerID = firstLayerID();
6490 		m_storedLayerLock = layerLocked(layerID);
6491 		m_storedLayerVis = layerVisible(layerID);
6492 		setActiveLayer(layerID);
6493 		setLayerVisible(layerID, true);
6494 		setLayerLocked(layerID, false);
6495 		ScPattern pa = docPatterns[symbolName];
6496 		m_currentEditedSymbol = symbolName;
6497 		ScPage* addedPage = new ScPage(m_docPrefsData.displayPrefs.scratch.left(), m_docPrefsData.displayPrefs.scratch.top(), pa.width, pa.height);
6498 		addedPage->setDocument(this);
6499 		addedPage->Margins.set(0, 0, 0, 0);
6500 		addedPage->initialMargins.set(0, 0, 0, 0);
6501 		addedPage->setPageNr(0);
6502 		addedPage->clearMasterPageName();
6503 		addedPage->setPageName(QString());
6504 		TempPages.clear();
6505 		TempPages.append(addedPage);
6506 		Pages = &TempPages;
6507 		Items = &docPatterns[symbolName].items;
6508 		m_Selection->delaySignalsOn();
6509 		for (int as = 0; as < Items->count(); ++as)
6510 		{
6511 			m_Selection->addItem(Items->at(as));
6512 			Items->at(as)->setLayer(layerID);
6513 		}
6514 		QRectF selRect = m_Selection->getVisualGroupRect();
6515 		moveGroup(addedPage->xOffset() - selRect.x(), addedPage->yOffset() - selRect.y());
6516 		if (Items->at(0)->isGroup())
6517 			Items->at(0)->asGroupFrame()->adjustXYPosition();
6518 		m_Selection->clear();
6519 		m_Selection->delaySignalsOff();
6520 		m_ScMW->changeLayer(layerID);
6521 		changed();
6522 	}
6523 	else
6524 	{
6525 		ScPage* addedPage = TempPages.at(0);
6526 		if (Items->isEmpty())
6527 		{
6528 			removePattern(m_currentEditedSymbol);
6529 		}
6530 		else
6531 		{
6532 			PageItem* currItem = Items->at(0);
6533 			if (Items->count() > 1)
6534 			{
6535 				if ((!currItem->isGroup()) && (Items->count() > 1))
6536 				{
6537 					itemAdd(PageItem::Group, PageItem::Rectangle, addedPage->xOffset(), addedPage->yOffset(), 10, 10, 0, CommonStrings::None, CommonStrings::None);
6538 					PageItem *groupItem = Items->takeLast();
6539 					groupItem->setLayer(firstLayerID());
6540 					Items->insert(0, groupItem);
6541 					double minx =  std::numeric_limits<double>::max();
6542 					double miny =  std::numeric_limits<double>::max();
6543 					double maxx = -std::numeric_limits<double>::max();
6544 					double maxy = -std::numeric_limits<double>::max();
6545 					for (int as = 1; as < Items->count(); ++as)
6546 					{
6547 						PageItem* currItem = Items->at(as);
6548 						groupItem->groupItemList.append(currItem);
6549 						double x1, x2, y1, y2;
6550 						currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
6551 						minx = qMin(minx, x1);
6552 						miny = qMin(miny, y1);
6553 						maxx = qMax(maxx, x2);
6554 						maxy = qMax(maxy, y2);
6555 					}
6556 					Items->clear();
6557 					Items->append(groupItem);
6558 					for (int em = 0; em < groupItem->groupItemList.count(); ++em)
6559 					{
6560 						PageItem* currItem = groupItem->groupItemList.at(em);
6561 						currItem->gXpos = currItem->xPos() - minx;
6562 						currItem->gYpos = currItem->yPos() - miny;
6563 						currItem->gWidth = maxx - minx;
6564 						currItem->gHeight = maxy - miny;
6565 					}
6566 					groupItem->setXYPos(minx, miny, true);
6567 					groupItem->setWidthHeight(maxx - minx, maxy - miny, true);
6568 					groupItem->groupWidth = maxx - minx;
6569 					groupItem->groupHeight = maxy - miny;
6570 					groupItem->gWidth = maxx - minx;
6571 					groupItem->gHeight = maxy - miny;
6572 					groupItem->SetRectFrame();
6573 					groupItem->ClipEdited = true;
6574 					groupItem->FrameType = 3;
6575 					groupItem->setTextFlowMode(PageItem::TextFlowDisabled);
6576 					groupItem->AutoName = false;
6577 					groupItem->setFillTransparency(0);
6578 					groupItem->setLineTransparency(0);
6579 					groupItem->asGroupFrame()->adjustXYPosition();
6580 					GroupCounter++;
6581 				}
6582 			}
6583 			currItem = Items->at(0);
6584 			double minx =  std::numeric_limits<double>::max();
6585 			double miny =  std::numeric_limits<double>::max();
6586 			double maxx = -std::numeric_limits<double>::max();
6587 			double maxy = -std::numeric_limits<double>::max();
6588 			double x1, x2, y1, y2;
6589 			currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
6590 			minx = qMin(minx, x1);
6591 			miny = qMin(miny, y1);
6592 			maxx = qMax(maxx, x2);
6593 			maxy = qMax(maxy, y2);
6594 			currItem->gXpos = currItem->xPos() - minx;
6595 			currItem->gYpos = currItem->yPos() - miny;
6596 			currItem->setXYPos(currItem->gXpos, currItem->gYpos, true);
6597 			ScPattern& currentEditedSymbol = docPatterns[m_currentEditedSymbol];
6598 			currentEditedSymbol.pattern = currItem->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
6599 			currentEditedSymbol.width  = maxx - minx;
6600 			currentEditedSymbol.height = maxy - miny;
6601 		}
6602 		if (m_ScMW->patternsDependingOnThis.count() > 1)
6603 		{
6604 			for (int a = 1; a < m_ScMW->patternsDependingOnThis.count(); a++)
6605 			{
6606 				Items = &docPatterns[m_ScMW->patternsDependingOnThis[a]].items;
6607 				PageItem *currItem = Items->at(0);
6608 				double x1, x2, y1, y2;
6609 				currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
6610 				docPatterns[m_ScMW->patternsDependingOnThis[a]].pattern = currItem->DrawObj_toImage(qMin(qMax(x2 - x1, y2 - y1), 500.0));
6611 			}
6612 		}
6613 		assignPageModeLists();
6614 		delete addedPage;
6615 		setActiveLayer(m_storedLayerID);
6616 		setLayerVisible(m_storedLayerID, m_storedLayerVis);
6617 		setLayerLocked(m_storedLayerID, m_storedLayerLock);
6618 		m_ScMW->changeLayer(m_storedLayerID);
6619 	}
6620 }
6621 
setInlineEditMode(bool mode,int id)6622 void ScribusDoc::setInlineEditMode(bool mode, int id)
6623 {
6624 	if (mode == m_inlineEditMode)
6625 		return;
6626 	m_inlineEditMode = mode;
6627 	if (mode)
6628 	{
6629 		m_storedLayerID = activeLayer();
6630 		int layerID = firstLayerID();
6631 		m_storedLayerLock = layerLocked(layerID);
6632 		m_storedLayerVis = layerVisible(layerID);
6633 		setActiveLayer(layerID);
6634 		setLayerVisible(layerID, true);
6635 		setLayerLocked(layerID, false);
6636 		PageItem *pa = FrameItems[id];
6637 		pa->isEmbedded = false;
6638 		m_currentEditedIFrame = id;
6639 		QRectF bBox = pa->getVisualBoundingRect();
6640 		ScPage* addedPage = new ScPage(m_docPrefsData.displayPrefs.scratch.left(), m_docPrefsData.displayPrefs.scratch.top(), bBox.width(), bBox.height());
6641 		addedPage->setDocument(this);
6642 		addedPage->Margins.set(0, 0, 0, 0);
6643 		addedPage->initialMargins.set(0, 0, 0, 0);
6644 		addedPage->setPageNr(0);
6645 		addedPage->clearMasterPageName();
6646 		addedPage->resetPageName();
6647 		TempPages.clear();
6648 		TempPages.append(addedPage);
6649 		Pages = &TempPages;
6650 		EditFrameItems.clear();
6651 		EditFrameItems.append(pa);
6652 		Items = &EditFrameItems;
6653 		m_Selection->delaySignalsOn();
6654 		for (int as = 0; as < Items->count(); ++as)
6655 		{
6656 			m_Selection->addItem(Items->at(as));
6657 			Items->at(as)->setLayer(layerID);
6658 		}
6659 		moveGroup(addedPage->xOffset(), addedPage->yOffset());
6660 		if (Items->at(0)->isGroup())
6661 			Items->at(0)->asGroupFrame()->adjustXYPosition();
6662 		m_Selection->clear();
6663 		m_Selection->delaySignalsOff();
6664 		m_ScMW->changeLayer(layerID);
6665 		changed();
6666 	}
6667 	else
6668 	{
6669 		ScPage* addedPage = TempPages.at(0);
6670 		if (Items->isEmpty())
6671 		{
6672 			removeInlineFrame(m_currentEditedIFrame);
6673 		}
6674 		else
6675 		{
6676 			PageItem* currItem = Items->at(0);
6677 			if (Items->count() > 1)
6678 			{
6679 				if ((!currItem->isGroup()) && (Items->count() > 1))
6680 				{
6681 					itemAdd(PageItem::Group, PageItem::Rectangle, addedPage->xOffset(), addedPage->yOffset(), 10, 10, 0, CommonStrings::None, CommonStrings::None);
6682 					PageItem *groupItem = Items->takeLast();
6683 					groupItem->setLayer(firstLayerID());
6684 					Items->insert(0, groupItem);
6685 					double minx =  std::numeric_limits<double>::max();
6686 					double miny =  std::numeric_limits<double>::max();
6687 					double maxx = -std::numeric_limits<double>::max();
6688 					double maxy = -std::numeric_limits<double>::max();
6689 					for (int as = 1; as < Items->count(); ++as)
6690 					{
6691 						PageItem* currItem = Items->at(as);
6692 						groupItem->groupItemList.append(currItem);
6693 						double x1, x2, y1, y2;
6694 						currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
6695 						minx = qMin(minx, x1);
6696 						miny = qMin(miny, y1);
6697 						maxx = qMax(maxx, x2);
6698 						maxy = qMax(maxy, y2);
6699 					}
6700 					Items->clear();
6701 					Items->append(groupItem);
6702 					for (int em = 0; em < groupItem->groupItemList.count(); ++em)
6703 					{
6704 						PageItem* currItem = groupItem->groupItemList.at(em);
6705 						currItem->gXpos = currItem->xPos() - minx;
6706 						currItem->gYpos = currItem->yPos() - miny;
6707 						currItem->gWidth = maxx - minx;
6708 						currItem->gHeight = maxy - miny;
6709 					}
6710 					groupItem->setXYPos(minx, miny, true);
6711 					groupItem->setWidthHeight(maxx - minx, maxy - miny, true);
6712 					groupItem->groupWidth = maxx - minx;
6713 					groupItem->groupHeight = maxy - miny;
6714 					groupItem->gWidth = maxx - minx;
6715 					groupItem->gHeight = maxy - miny;
6716 					groupItem->SetRectFrame();
6717 					groupItem->ClipEdited = true;
6718 					groupItem->FrameType = 3;
6719 					groupItem->setTextFlowMode(PageItem::TextFlowDisabled);
6720 					groupItem->AutoName = false;
6721 					groupItem->setFillTransparency(0);
6722 					groupItem->setLineTransparency(0);
6723 					groupItem->asGroupFrame()->adjustXYPosition();
6724 					GroupCounter++;
6725 				}
6726 			}
6727 			currItem = Items->at(0);
6728 			double minx =  std::numeric_limits<double>::max();
6729 			double miny =  std::numeric_limits<double>::max();
6730 			double maxx = -std::numeric_limits<double>::max();
6731 			double maxy = -std::numeric_limits<double>::max();
6732 			double x1, x2, y1, y2;
6733 			currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
6734 			minx = qMin(minx, x1);
6735 			miny = qMin(miny, y1);
6736 			maxx = qMax(maxx, x2);
6737 			maxy = qMax(maxy, y2);
6738 			currItem->gXpos = currItem->xPos() - minx;
6739 			currItem->gYpos = currItem->yPos() - miny;
6740 			currItem->gWidth = maxx - minx;
6741 			currItem->gHeight = maxy - miny;
6742 			currItem->setXYPos(currItem->gXpos, currItem->gYpos, true);
6743 			currItem->isEmbedded = true;
6744 			currItem->inlineCharID = m_currentEditedIFrame;
6745 			FrameItems[m_currentEditedIFrame] = currItem;
6746 		}
6747 		assignPageModeLists();
6748 		delete addedPage;
6749 		EditFrameItems.clear();
6750 		setActiveLayer(m_storedLayerID);
6751 		setLayerVisible(m_storedLayerID, m_storedLayerVis);
6752 		setLayerLocked(m_storedLayerID, m_storedLayerLock);
6753 		m_ScMW->changeLayer(m_storedLayerID);
6754 	}
6755 }
6756 
addSection(int number,const QString & name,const uint fromindex,const uint toindex,const NumFormat type,const uint sectionstartindex,bool reversed,bool active,const QChar fillChar,int fieldWidth)6757 void ScribusDoc::addSection(int number, const QString& name, const uint fromindex, const uint toindex, const NumFormat type, const uint sectionstartindex, bool reversed, bool active, const QChar fillChar, int fieldWidth)
6758 {
6759 	struct DocumentSection newSection;
6760 	int docPageCount=DocPages.count();
6761 	bool empty=m_docPrefsData.docSectionMap.isEmpty();
6762 	if (empty)
6763 	{
6764 		newSection.number = 0;
6765 		newSection.name = "0";
6766 		newSection.fromindex = 0;
6767 		newSection.toindex = docPageCount-1;
6768 		newSection.type = Type_1_2_3;
6769 		newSection.sectionstartindex = 1;
6770 		newSection.reversed = false;
6771 		newSection.active = true;
6772 		newSection.pageNumberFillChar = QChar();
6773 		newSection.pageNumberWidth = 0;
6774 		m_docPrefsData.docSectionMap.insert(newSection.number, newSection);
6775 	}
6776 	else if (number!=-1)
6777 	{
6778 		newSection.number = number;
6779 		newSection.name = name;
6780 		newSection.fromindex = fromindex;
6781 		newSection.toindex = toindex;
6782 		if (newSection.toindex > (uint) docPageCount - 1)
6783 			newSection.toindex = docPageCount - 1;
6784 		newSection.type = type;
6785 		newSection.sectionstartindex = sectionstartindex;
6786 		newSection.reversed = reversed;
6787 		newSection.active = active;
6788 		newSection.pageNumberFillChar = fillChar;
6789 		newSection.pageNumberWidth = fieldWidth;
6790 		m_docPrefsData.docSectionMap.insert(newSection.number, newSection);
6791 	}
6792 }
6793 
6794 
deleteSection(const uint number)6795 bool ScribusDoc::deleteSection(const uint number)
6796 {
6797 	if (!m_docPrefsData.docSectionMap.contains(number))
6798 		return false;
6799 	if (m_docPrefsData.docSectionMap.count() <= 1)
6800 		return false;
6801 	QMap<uint, DocumentSection>::Iterator itprev = m_docPrefsData.docSectionMap.begin();
6802 	QMap<uint, DocumentSection>::Iterator it = itprev;
6803 	uint currMaxIndex = itprev.value().toindex;
6804 	for ( ; it != m_docPrefsData.docSectionMap.end(); ++it)
6805 	{
6806 		currMaxIndex=it.value().toindex;
6807 
6808 		if (it.key() != number)
6809 			itprev = it;
6810 		else
6811 			break;
6812 	}
6813 	if (it != itprev)
6814 		itprev.value().toindex = currMaxIndex;
6815 	else {
6816 		// special case: delete first section
6817 		QMap<uint, DocumentSection>::Iterator itnext = it;
6818 		++itnext;
6819 		itnext.value().fromindex = it.value().fromindex;
6820 	}
6821 	m_docPrefsData.docSectionMap.erase(it);
6822 	return true;
6823 }
6824 
6825 
getSectionKeyForPageIndex(uint pageIndex) const6826 int ScribusDoc::getSectionKeyForPageIndex(uint pageIndex) const
6827 {
6828 	int retVal = -1;
6829 	DocumentSectionMap::ConstIterator it = m_docPrefsData.docSectionMap.begin();
6830 	for (; it != m_docPrefsData.docSectionMap.end(); ++it)
6831 	{
6832 		if (pageIndex >= it.value().fromindex && pageIndex <= it.value().toindex)
6833 		{
6834 			retVal = it.key();
6835 			break;
6836 		}
6837 	}
6838 	return retVal;
6839 }
6840 
getSectionNameForPageIndex(uint pageIndex) const6841 QString ScribusDoc::getSectionNameForPageIndex(uint pageIndex) const
6842 {
6843 	DocumentSectionMap::ConstIterator it = m_docPrefsData.docSectionMap.begin();
6844 	for (; it != m_docPrefsData.docSectionMap.end(); ++it)
6845 	{
6846 		if (pageIndex >= it.value().fromindex && pageIndex <= it.value().toindex)
6847 			return it.value().name;
6848 	}
6849 	return QString();
6850 }
6851 
6852 
getSectionPageNumberForPageIndex(uint pageIndex) const6853 const QString ScribusDoc::getSectionPageNumberForPageIndex(uint pageIndex) const
6854 {
6855 	QString retVal;
6856 	int key=getSectionKeyForPageIndex(pageIndex);
6857 	if (key==-1)
6858 		return retVal;
6859 	//If a section is inactive, theres no page numbers printed
6860 	if (!m_docPrefsData.docSectionMap[key].active)
6861 		return "";
6862 	uint sectionIndexOffset;
6863 	if (!m_docPrefsData.docSectionMap[key].reversed)
6864 		sectionIndexOffset = pageIndex - m_docPrefsData.docSectionMap[key].fromindex + m_docPrefsData.docSectionMap[key].sectionstartindex;
6865 	else
6866 		sectionIndexOffset = - static_cast<int>(pageIndex) + m_docPrefsData.docSectionMap[key].toindex  + m_docPrefsData.docSectionMap[key].sectionstartindex;
6867 	retVal = getStringFromSequence(m_docPrefsData.docSectionMap[key].type, sectionIndexOffset);
6868 	return retVal;
6869 }
6870 
getSectionPageNumberFillCharForPageIndex(uint pageIndex) const6871 const QChar ScribusDoc::getSectionPageNumberFillCharForPageIndex(uint pageIndex) const
6872 {
6873 	QChar retVal;
6874 	int key = getSectionKeyForPageIndex(pageIndex);
6875 	if (key == -1)
6876 		return retVal;
6877 
6878 	//If a section is inactive, theres no page numbers printed
6879 	if (!m_docPrefsData.docSectionMap[key].active)
6880 		return retVal;
6881 	retVal = m_docPrefsData.docSectionMap[key].pageNumberFillChar;
6882 	if (retVal == QChar(0))
6883 		retVal = QChar(32);
6884 	return retVal;
6885 }
6886 
getSectionPageNumberWidthForPageIndex(uint pageIndex) const6887 int ScribusDoc::getSectionPageNumberWidthForPageIndex(uint pageIndex) const
6888 {
6889 	int retVal = 0;
6890 	int key = getSectionKeyForPageIndex(pageIndex);
6891 	if (key == -1)
6892 		return retVal;
6893 
6894 	//If a section is inactive, theres no page numbers printed
6895 	if (!m_docPrefsData.docSectionMap[key].active)
6896 		return retVal;
6897 	retVal = qMin(m_docPrefsData.docSectionMap[key].pageNumberWidth, 20);			// added the qmin as a sanity check -> fixes bug #9721
6898 	return retVal;
6899 }
6900 
updateSectionPageNumbersToPages()6901 void ScribusDoc::updateSectionPageNumbersToPages()
6902 {
6903 	int docPageCount = DocPages.count();
6904 	for (int i = 0; i < docPageCount; ++i)
6905 		DocPages.at(i)->setPageSectionNumber(getSectionPageNumberForPageIndex(i));
6906 }
6907 
6908 
addPageToSection(uint otherPageIndex,uint location,uint count)6909 void ScribusDoc::addPageToSection(uint otherPageIndex, uint location, uint count)
6910 {
6911 	uint fromIndex, toIndex;
6912 	uint searchedIndex = (otherPageIndex > 0) ? (otherPageIndex - 1) : 0;
6913 	if ((location == 0) && (searchedIndex > 0))
6914 		--searchedIndex;
6915 	DocumentSectionMap::Iterator it = m_docPrefsData.docSectionMap.begin();
6916 	for (; it!= m_docPrefsData.docSectionMap.end(); ++it)
6917 	{
6918 		fromIndex = it.value().fromindex;
6919 		toIndex   = it.value().toindex;
6920 		if  (fromIndex > searchedIndex)
6921 			it.value().fromindex += count;
6922 		if  (toIndex >= searchedIndex)
6923 			it.value().toindex += count;
6924 	}
6925 	//Now update the Pages' internal storage of their page number
6926 	updateSectionPageNumbersToPages();
6927 }
6928 
6929 
removePageFromSection(uint pageIndex)6930 void ScribusDoc::removePageFromSection(uint pageIndex)
6931 {
6932 	//Get the section of the new page index.
6933 	uint fromIndex, toIndex;
6934 	DocumentSectionMap::Iterator it = m_docPrefsData.docSectionMap.begin();
6935 	for (; it!= m_docPrefsData.docSectionMap.end(); ++it)
6936 	{
6937 		if (pageIndex>=it.value().fromindex && pageIndex<=it.value().toindex)
6938 		{
6939 			fromIndex = it.value().fromindex;
6940 			toIndex   = it.value().toindex - 1;
6941 			if (fromIndex > toIndex) // Remove section in that case
6942 				m_docPrefsData.docSectionMap.remove(it.key());
6943 			break;
6944 		}
6945 	}
6946 	for (it = m_docPrefsData.docSectionMap.begin(); it != m_docPrefsData.docSectionMap.end(); ++it)
6947 	{
6948 		fromIndex = it.value().fromindex;
6949 		toIndex   = it.value().toindex;
6950 		if  (fromIndex > pageIndex)
6951 			--it.value().fromindex;
6952 		if  (toIndex >= pageIndex)
6953 			--it.value().toindex;
6954 	}
6955 	//Now update the Pages' internal storage of their page number
6956 	updateSectionPageNumbersToPages();
6957 }
6958 
6959 
setFirstSectionFromFirstPageNumber()6960 void ScribusDoc::setFirstSectionFromFirstPageNumber()
6961 {
6962 	DocumentSectionMap::Iterator it = m_docPrefsData.docSectionMap.begin();
6963 	it.value().sectionstartindex=FirstPnum;
6964 	updateSectionPageNumbersToPages();
6965 }
6966 
addPageToAnnotLinks(int otherPageIndex,int location,int count)6967 void ScribusDoc::addPageToAnnotLinks(int otherPageIndex, int location, int count)
6968 {
6969 	int searchedIndex = (otherPageIndex > 0) ? (otherPageIndex - 1) : 0;
6970 	if ((location == 0) && (searchedIndex > 0))
6971 		--searchedIndex;
6972 
6973 	QList<PageItem*> itemList = DocItems;
6974 	while (itemList.count() > 0)
6975 	{
6976 		PageItem *currItem = itemList.takeLast();
6977 		if (currItem->isGroup())
6978 		{
6979 			itemList += currItem->groupItemList;
6980 			continue;
6981 		}
6982 		if (!currItem->isAnnotation())
6983 			continue;
6984 
6985 		Annotation& annotation = currItem->annotation();
6986 		if (annotation.ActionType() != Annotation::Action_GoTo)
6987 			continue;
6988 
6989 		int targetPage = annotation.Ziel();
6990 		if (targetPage >= searchedIndex)
6991 		{
6992 			targetPage += count;
6993 			annotation.setZiel(targetPage);
6994 		}
6995 	}
6996 }
6997 
removePageFromAnnotLinks(int pageIndex)6998 void ScribusDoc::removePageFromAnnotLinks(int pageIndex)
6999 {
7000 	QList<PageItem*> itemList = DocItems;
7001 	while (itemList.count() > 0)
7002 	{
7003 		PageItem *currItem = itemList.takeLast();
7004 		if (currItem->isGroup())
7005 		{
7006 			itemList += currItem->groupItemList;
7007 			continue;
7008 		}
7009 		if (!currItem->isAnnotation())
7010 			continue;
7011 
7012 		Annotation& annotation = currItem->annotation();
7013 		if (annotation.ActionType() != Annotation::Action_GoTo)
7014 			continue;
7015 
7016 		int targetPage = annotation.Ziel();
7017 		if (targetPage >= pageIndex)
7018 		{
7019 			--targetPage;
7020 			annotation.setZiel(targetPage);
7021 		}
7022 	}
7023 }
7024 
copyPage(int pageNumberToCopy,int existingPage,int whereToInsert,int copyCount)7025 void ScribusDoc::copyPage(int pageNumberToCopy, int existingPage, int whereToInsert, int copyCount)
7026 {
7027 	UndoTransaction copyTransaction;
7028 	if (UndoManager::undoEnabled())
7029 	{
7030 		copyTransaction = m_undoManager->beginTransaction(getUName(), Um::IDocument, Um::CopyPage, "", Um::ICreate);
7031 		SimpleState *ss = new SimpleState(Um::Copy, "", Um::ICreate);
7032 		ss->set("PAGE_COPY");
7033 		ss->set("PAGE_NUM", pageNumberToCopy);
7034 		ss->set("EXISTING_PAGE", existingPage);
7035 		ss->set("WHERE_TO", whereToInsert);
7036 		ss->set("COPY_COUNT", copyCount);
7037 		m_undoManager->action(this, ss);
7038 	}
7039 
7040 	m_undoManager->setUndoEnabled(false);
7041 	//CB Should we really be disabling auto text frames here?
7042 	bool autoText = usesAutomaticTextFrames();
7043 	setUsesAutomaticTextFrames(false);
7044 	ScPage* from = DocPages.at(pageNumberToCopy);
7045 	ScPage* lastDest = nullptr;
7046 	setCurrentPage(from);
7047 
7048 	int oldItems = Items->count();
7049 	QList<QString> itemBuffer;
7050 	Selection tempSelection(this, false);
7051 	m_Selection->clear();
7052 	tempSelection.delaySignalsOn();
7053 	if (oldItems > 0)
7054 	{
7055 		if (Layers.count()!= 0)
7056 		{
7057 			int currActiveLayer = activeLayer();
7058 			for (ScLayers::iterator it = Layers.begin(); it != Layers.end(); ++it)
7059 			{
7060 				setActiveLayer(it->ID);
7061 				for (int ite = 0; ite < oldItems; ++ite)
7062 				{
7063 					PageItem *itemToCopy = Items->at(ite);
7064 					if ((itemToCopy->OwnPage == from->pageNr()) && (it->ID == itemToCopy->m_layerID))
7065 						tempSelection.addItem(itemToCopy, true);
7066 				}
7067 				if (tempSelection.count() != 0)
7068 				{
7069 					ScriXmlDoc ss;
7070 					QString dataS = ss.writeElem(this, &tempSelection);
7071 					itemBuffer.append(dataS);
7072 				}
7073 				else
7074 					itemBuffer.append(QString());
7075 				tempSelection.clear();
7076 			}
7077 			setActiveLayer(currActiveLayer);
7078 		}
7079 	}
7080 	tempSelection.delaySignalsOff();
7081 
7082 
7083 	for (int copyNumber=1; copyNumber<=copyCount; ++copyNumber)
7084 	{
7085 		//For multiple insertions we can insert in the same place
7086 		int destLocation=existingPage;
7087 		if (whereToInsert==0)
7088 			--destLocation;
7089 		else if (whereToInsert==2)
7090 			destLocation=DocPages.count();
7091 		ScPage* destination = new ScPage(m_docPrefsData.displayPrefs.scratch.left(), DocPages.count()*(m_docPrefsData.docSetupPrefs.pageHeight+m_docPrefsData.displayPrefs.scratch.bottom()+m_docPrefsData.displayPrefs.scratch.top())+m_docPrefsData.displayPrefs.scratch.top(), m_docPrefsData.docSetupPrefs.pageWidth, m_docPrefsData.docSetupPrefs.pageHeight);
7092 		destination->setDocument(this);
7093 		destination->setPageNr(destLocation);
7094 		lastDest = destination;
7095 		DocPages.insert(destLocation, destination);
7096 		setLocationBasedPageLRMargins(destLocation);
7097 		applyMasterPage(from->masterPageName(), destLocation);
7098 		destination->setInitialHeight(from->height());
7099 		destination->setInitialWidth(from->width());
7100 		destination->setOrientation(from->orientation());
7101 		destination->setSize(from->size());
7102 		//CB: Can possibly partially use the code from applyMasterPage here instead of runnin all of this again..
7103 		//TODO make a function to do this margin stuff and use elsewhere too
7104 		destination->initialMargins.setTop(from->initialMargins.top());
7105 		destination->initialMargins.setBottom(from->initialMargins.bottom());
7106 		if (pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns == 1)
7107 		{
7108 			destination->initialMargins.setLeft(from->initialMargins.left());
7109 			destination->initialMargins.setRight(from->initialMargins.right());
7110 		}
7111 		else
7112 		{
7113 			if (locationOfPage(destination->pageNr()) != locationOfPage(from->pageNr()))
7114 			{
7115 				if (locationOfPage(destination->pageNr()) == MiddlePage)
7116 				{
7117 					destination->initialMargins.setRight(from->initialMargins.left());
7118 					destination->initialMargins.setLeft(from->initialMargins.left());
7119 				}
7120 				else
7121 				{
7122 					destination->initialMargins.setRight(from->initialMargins.left());
7123 					destination->initialMargins.setLeft(from->initialMargins.right());
7124 				}
7125 			}
7126 			else
7127 			{
7128 				destination->initialMargins.setLeft(from->initialMargins.left());
7129 				destination->initialMargins.setRight(from->initialMargins.right());
7130 			}
7131 		}
7132 		reformPages();
7133 		// FIXME: stop using m_View
7134 		if (m_View)
7135 			m_View->reformPagesView();
7136 		if (itemBuffer.count() > 0)
7137 		{
7138 			int lcount = 0;
7139 			ScLayers::iterator it;
7140 			if (Layers.count()!= 0)
7141 			{
7142 				int currActiveLayer = activeLayer();
7143 				bool savedAlignGrid   = this->SnapGrid;
7144 				bool savedAlignGuides = this->SnapGuides;
7145 				bool savedAlignElement = this->SnapElement;
7146 				this->SnapGrid   = false;
7147 				this->SnapGuides = false;
7148 				this->SnapElement = false;
7149 				for (it = Layers.begin(); it != Layers.end(); ++it)
7150 				{
7151 					if ((lcount < itemBuffer.count()) && !itemBuffer[lcount].isEmpty())
7152 					{
7153 						ScriXmlDoc ss;
7154 						QString fragment = itemBuffer[lcount];
7155 						ss.readElemToLayer(fragment, this, destination->xOffset(), destination->yOffset(), false, true, it->ID);
7156 					}
7157 					lcount++;
7158 				}
7159 				this->SnapGrid   = savedAlignGrid;
7160 				this->SnapGuides = savedAlignGuides;
7161 				this->SnapElement = savedAlignElement;
7162 				setActiveLayer(currActiveLayer);
7163 			}
7164 		}
7165 		from->guides.copy(&destination->guides);
7166 	}
7167 	setUsesAutomaticTextFrames(autoText);
7168 	addPageToSection(existingPage, whereToInsert, copyCount);
7169 	if (lastDest != nullptr)
7170 		setCurrentPage(lastDest);
7171 	else
7172 		setCurrentPage(from);
7173 	changed();
7174 	m_undoManager->setUndoEnabled(true);
7175 	if (copyTransaction)
7176 		copyTransaction.commit();
7177 }
7178 
7179 
setLocationBasedPageLRMargins(uint pageIndex)7180 void ScribusDoc::setLocationBasedPageLRMargins(uint pageIndex)
7181 {
7182 	int setcol=pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns;
7183 	if (setcol==1)
7184 	{
7185 		ScPage* pageToAdjust=DocPages.at(pageIndex);
7186 		pageToAdjust->Margins.setLeft(pageToAdjust->initialMargins.left());
7187 		pageToAdjust->Margins.setRight(pageToAdjust->initialMargins.right());
7188 		return;
7189 	}
7190 
7191 	ScPage* pageToAdjust=DocPages.at(pageIndex);
7192 	PageLocation pageLoc=locationOfPage(pageIndex);
7193 	if (pageLoc==LeftPage) //Left hand page
7194 	{
7195 		pageToAdjust->Margins.setLeft(pageToAdjust->initialMargins.right());
7196 		pageToAdjust->Margins.setRight(pageToAdjust->initialMargins.left());
7197 	}
7198 	else if (pageLoc==RightPage) // Right hand page
7199 	{
7200 		pageToAdjust->Margins.setRight(pageToAdjust->initialMargins.right());
7201 		pageToAdjust->Margins.setLeft(pageToAdjust->initialMargins.left());
7202 	}
7203 	else //Middle pages
7204 	{
7205 		pageToAdjust->Margins.setLeft(pageToAdjust->initialMargins.left());
7206 		pageToAdjust->Margins.setRight(pageToAdjust->initialMargins.left());
7207 	}
7208 }
7209 
7210 
locationOfPage(int pageIndex) const7211 PageLocation ScribusDoc::locationOfPage(int pageIndex) const
7212 {
7213 	int myCol=columnOfPage(pageIndex);
7214 	if (myCol==0) //Left hand page
7215 		return LeftPage;
7216 	if (myCol>= pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns-1) // Right hand page
7217 		return RightPage;
7218 	//Middle pages
7219 	return MiddlePage;
7220 }
7221 
columnOfPage(int pageIndex) const7222 int ScribusDoc::columnOfPage(int pageIndex) const
7223 {
7224 	int setcol=pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns;
7225 	return ((pageIndex % setcol) + pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].FirstPage) % setcol;
7226 }
7227 
RecalcPictures(ProfilesL * Pr,ProfilesL * PrCMYK,QProgressBar * dia)7228 void ScribusDoc::RecalcPictures(ProfilesL *Pr, ProfilesL *PrCMYK, QProgressBar *dia)
7229 {
7230 	RecalcPictures(&MasterItems, Pr, PrCMYK, dia);
7231 	RecalcPictures(&DocItems, Pr, PrCMYK, dia);
7232 	QList<PageItem*> itemList = FrameItems.values();
7233 	RecalcPictures(&itemList, Pr, PrCMYK, dia);
7234 	QList<PageItem*> allItems;
7235 	if (FrameItems.isEmpty())
7236 		return;
7237 	bool usingGUI=ScCore->usingGUI();
7238 	int counter = 0;
7239 	if (usingGUI && dia != nullptr)
7240 		counter = dia->value();
7241 	for (auto itf = FrameItems.begin(); itf != FrameItems.end(); ++itf)
7242 	{
7243 		PageItem *it = itf.value();
7244 		if (it->isGroup())
7245 			allItems = it->getAllChildren();
7246 		else
7247 			allItems.append(it);
7248 		for (int i = 0; i < allItems.count(); i++)
7249 		{
7250 			it = allItems.at(i);
7251 			if ((it->itemType() == PageItem::ImageFrame) && (it->imageIsAvailable))
7252 			{
7253 				if (it->pixm.imgInfo.colorspace == ColorSpaceCMYK)
7254 				{
7255 					if (!PrCMYK->contains(it->ImageProfile))
7256 						it->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile;
7257 				}
7258 				else
7259 				{
7260 					if (!Pr->contains(it->ImageProfile))
7261 						it->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
7262 				}
7263 				loadPict(it->Pfile, it, true);
7264 			}
7265 		}
7266 		allItems.clear();
7267 		if (usingGUI)
7268 		{
7269 			++counter;
7270 			if (dia != nullptr)
7271 				dia->setValue(counter);
7272 		}
7273 	}
7274 }
7275 
RecalcPictures(QList<PageItem * > * items,ProfilesL * Pr,ProfilesL * PrCMYK,QProgressBar * dia)7276 void ScribusDoc::RecalcPictures(QList<PageItem*>* items, ProfilesL *Pr, ProfilesL *PrCMYK, QProgressBar *dia)
7277 {
7278 	if (items->isEmpty())
7279 		return;
7280 	QList<PageItem*> allItems;
7281 	bool usingGUI=ScCore->usingGUI();
7282 	int counter = 0;
7283 	if (usingGUI && dia != nullptr)
7284 		counter = dia->value();
7285 	PageItem* it;
7286 	int docItemCount = items->count();
7287 	for (int i=0; i < docItemCount; ++i)
7288 	{
7289 		it = items->at(i);
7290 		if (it->isGroup())
7291 			allItems = it->getAllChildren();
7292 		else
7293 			allItems.append(it);
7294 		for (int j = 0; j < allItems.count(); j++)
7295 		{
7296 			it = allItems.at(j);
7297 			if ((it->itemType() == PageItem::ImageFrame) && (it->imageIsAvailable))
7298 			{
7299 				if (it->pixm.imgInfo.colorspace == ColorSpaceCMYK)
7300 				{
7301 					if (!PrCMYK->contains(it->ImageProfile))
7302 						it->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile;
7303 				}
7304 				else
7305 				{
7306 					if (!Pr->contains(it->ImageProfile))
7307 						it->ImageProfile = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
7308 				}
7309 				loadPict(it->Pfile, it, true);
7310 			}
7311 		}
7312 		allItems.clear();
7313 		if (usingGUI)
7314 		{
7315 			++counter;
7316 			if (dia != nullptr)
7317 				dia->setValue(counter);
7318 		}
7319 	}
7320 }
7321 
7322 
7323 
insertColor(const QString & name,double c,double m,double y,double k)7324 void ScribusDoc::insertColor(const QString& name, double c, double m, double y, double k)
7325 {
7326 	if (PageColors.contains(name))
7327 		return;
7328 	ScColor tmp = ScColor(static_cast<int>(255 * c), static_cast<int>(255 * m), static_cast<int>(255 * y), static_cast<int>(255 * k));
7329 	PageColors.insert(name, tmp);
7330 }
7331 
7332 struct objOrdHelper
7333 {
7334 	int objNrSel;
7335 	PageItem* parent;
7336 };
7337 
sendItemSelectionToBack()7338 void ScribusDoc::sendItemSelectionToBack()
7339 {
7340 	int docSelectionCount = m_Selection->count();
7341 	if (docSelectionCount == 0)
7342 		return;
7343 	QRectF selRect = m_Selection->getGroupRect();
7344 	if (UndoManager::undoEnabled())
7345 	{
7346 		ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(Um::LevelBottom);
7347 		is->set("LEVEL_BOTTOM");
7348 		is->setItem(m_Selection->selectionList());
7349 		m_undoManager->action(this, is);
7350 	}
7351 	if (docSelectionCount > 1)
7352 	{
7353 		PageItem *firstItem = m_Selection->itemAt(0);
7354 		for (int a = 1; a < docSelectionCount; ++a)
7355 		{
7356 			if (m_Selection->itemAt(a)->Parent != firstItem->Parent)
7357 				return;
7358 		}
7359 	}
7360 	PageItem *currItem;
7361 	QMap<int, objOrdHelper> objOrder;
7362 	int d;
7363 	for (int c = 0; c < docSelectionCount; ++c)
7364 	{
7365 		objOrdHelper oHlp;
7366 		currItem = m_Selection->itemAt(c);
7367 		oHlp.objNrSel = c;
7368 		if (currItem->isGroupChild())
7369 		{
7370 			if (currItem->Parent->asGroupFrame()->groupItemList.count() > 1)
7371 			{
7372 				d = currItem->Parent->asGroupFrame()->groupItemList.indexOf(currItem);
7373 				oHlp.parent = currItem->Parent;
7374 				objOrder.insert(d, oHlp);
7375 			}
7376 		}
7377 		else if (Items->count() > 1)
7378 		{
7379 			d = Items->indexOf(currItem);
7380 			oHlp.parent = nullptr;
7381 			objOrder.insert(d, oHlp);
7382 		}
7383 	}
7384 	QList<objOrdHelper> objIndex = objOrder.values();
7385 	for (int c = objIndex.count() - 1; c > -1; c--)
7386 	{
7387 		objOrdHelper oHlp = objIndex[c];
7388 		PageItem* objItem = m_Selection->itemAt(oHlp.objNrSel);
7389 		if (oHlp.parent == nullptr)
7390 		{
7391 			Items->removeOne(objItem);
7392 			Items->prepend(objItem);
7393 		}
7394 		else
7395 		{
7396 			oHlp.parent->asGroupFrame()->groupItemList.removeOne(objItem);
7397 			oHlp.parent->asGroupFrame()->groupItemList.prepend(objItem);
7398 		}
7399 	}
7400 	changed();
7401 	invalidateRegion(selRect);
7402 	regionsChanged()->update(QRectF());
7403 }
7404 
bringItemSelectionToFront()7405 void ScribusDoc::bringItemSelectionToFront()
7406 {
7407 	int docSelectionCount = m_Selection->count();
7408 	if (docSelectionCount == 0)
7409 		return;
7410 	QRectF selRect = m_Selection->getGroupRect();
7411 	if (UndoManager::undoEnabled())
7412 	{
7413 		ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(Um::LevelTop);
7414 		is->set("LEVEL_TOP");
7415 		is->setItem(m_Selection->selectionList());
7416 		m_undoManager->action(this, is);
7417 	}
7418 	if (docSelectionCount > 1)
7419 	{
7420 		PageItem *firstItem = m_Selection->itemAt(0);
7421 		for (int a = 1; a < docSelectionCount; ++a)
7422 		{
7423 			if (m_Selection->itemAt(a)->Parent != firstItem->Parent)
7424 				return;
7425 		}
7426 	}
7427 	PageItem *currItem;
7428 	QMap<int, objOrdHelper> objOrder;
7429 	int d;
7430 	for (int c = 0; c < docSelectionCount; ++c)
7431 	{
7432 		objOrdHelper oHlp;
7433 		currItem = m_Selection->itemAt(c);
7434 		oHlp.objNrSel = c;
7435 		if (currItem->isGroupChild())
7436 		{
7437 			if (currItem->Parent->asGroupFrame()->groupItemList.count() > 1)
7438 			{
7439 				d = currItem->Parent->asGroupFrame()->groupItemList.indexOf(currItem);
7440 				oHlp.parent = currItem->Parent;
7441 				objOrder.insert(d, oHlp);
7442 			}
7443 		}
7444 		else if (Items->count() > 1)
7445 		{
7446 			d = Items->indexOf(currItem);
7447 			oHlp.parent = nullptr;
7448 			objOrder.insert(d, oHlp);
7449 		}
7450 	}
7451 	QList<objOrdHelper> objIndex = objOrder.values();
7452 	for (int c = 0; c < objIndex.count(); ++c)
7453 	{
7454 		objOrdHelper oHlp = objIndex[c];
7455 		PageItem* objItem = m_Selection->itemAt(oHlp.objNrSel);
7456 		if (oHlp.parent == nullptr)
7457 		{
7458 			Items->removeOne(objItem);
7459 			Items->append(objItem);
7460 		}
7461 		else
7462 		{
7463 			oHlp.parent->asGroupFrame()->groupItemList.removeOne(objItem);
7464 			oHlp.parent->asGroupFrame()->groupItemList.append(m_Selection->itemAt(oHlp.objNrSel));
7465 		}
7466 	}
7467 	changed();
7468 	invalidateRegion(selRect);
7469 	regionsChanged()->update(QRectF());
7470 }
7471 
itemSelection_LowerItem()7472 void ScribusDoc::itemSelection_LowerItem()
7473 {
7474 	int docSelectionCount = m_Selection->count();
7475 	if (docSelectionCount == 0)
7476 		return;
7477 	QRectF selRect = m_Selection->getGroupRect();
7478 	if (UndoManager::undoEnabled())
7479 	{
7480 		ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(Um::LevelDown);
7481 		is->set("LEVEL_DOWN");
7482 		is->setItem(m_Selection->selectionList());
7483 		m_undoManager->action(this, is);
7484 	}
7485 	if (docSelectionCount > 1)
7486 	{
7487 		PageItem *firstItem = m_Selection->itemAt(0);
7488 		for (int a = 1; a < docSelectionCount; ++a)
7489 		{
7490 			if (m_Selection->itemAt(a)->Parent != firstItem->Parent)
7491 				return;
7492 		}
7493 	}
7494 	QList<PageItem*> *itemList;
7495 	if (m_Selection->itemAt(0)->isGroupChild())
7496 		itemList = &(m_Selection->itemAt(0)->parentGroup()->groupItemList);
7497 	else
7498 		itemList = Items;
7499 	if (itemList->count() <= 1)
7500 		return;
7501 	int low = itemList->count();
7502 	int high = 0;
7503 	int d;
7504 	QMap<int, int> ObjOrder;
7505 	PageItem *currItem=nullptr;
7506 	for (int c = 0; c < docSelectionCount; ++c)
7507 	{
7508 		currItem = m_Selection->itemAt(c);
7509 		int id = itemList->indexOf(currItem);
7510 		low = qMin(id, low);
7511 		high = qMax(id, high);
7512 	}
7513 	if (low == 0)
7514 		return;
7515 	PageItem *b2 = itemList->at(high);
7516 	bool wasSignalDelayed = !m_Selection->signalsDelayed();
7517 	m_Selection->delaySignalsOn();
7518 	if (!wasSignalDelayed)
7519 		m_Selection->disconnectAllItemsFromGUI();
7520 	Selection tempSelection(*m_Selection);
7521 	m_Selection->clear();
7522 	m_Selection->addItem(itemList->at(low - 1));
7523 	for (int c = 0; c < m_Selection->count(); ++c)
7524 	{
7525 		currItem = m_Selection->itemAt(c);
7526 		d = itemList->indexOf(currItem);
7527 		ObjOrder.insert(d, c);
7528 		itemList->takeAt(d);
7529 	}
7530 	d = itemList->indexOf(b2);
7531 	QList<int> Oindex = ObjOrder.values();
7532 	for (int c = static_cast<int>(Oindex.count()-1); c > -1; c--)
7533 	{
7534 		itemList->insert(d+1, m_Selection->itemAt(Oindex[c]));
7535 	}
7536 	m_Selection->clear();
7537 	*m_Selection = tempSelection;
7538 	m_Selection->delaySignalsOff();
7539 	changed();
7540 	invalidateRegion(selRect);
7541 	regionsChanged()->update(QRectF());
7542 }
7543 
itemSelection_RaiseItem()7544 void ScribusDoc::itemSelection_RaiseItem()
7545 {
7546 	int docSelectionCount = m_Selection->count();
7547 	if (docSelectionCount == 0)
7548 		return;
7549 	QRectF selRect = m_Selection->getGroupRect();
7550 	if (UndoManager::undoEnabled())
7551 	{
7552 		ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(Um::LevelUp);
7553 		is->set("LEVEL_UP");
7554 		is->setItem(m_Selection->selectionList());
7555 		m_undoManager->action(this, is);
7556 	}
7557 	if (docSelectionCount > 1)
7558 	{
7559 		PageItem *firstItem = m_Selection->itemAt(0);
7560 		for (int a = 1; a < docSelectionCount; ++a)
7561 		{
7562 			if (m_Selection->itemAt(a)->Parent != firstItem->Parent)
7563 				return;
7564 		}
7565 	}
7566 	QList<PageItem*> *itemList;
7567 	if (m_Selection->itemAt(0)->isGroupChild())
7568 		itemList = &(m_Selection->itemAt(0)->parentGroup()->groupItemList);
7569 	else
7570 		itemList = Items;
7571 
7572 	if (itemList->count() <= 1)
7573 		return;
7574 	int low = itemList->count();
7575 	int high = 0;
7576 	QMap<int, int> ObjOrder;
7577 	PageItem *currItem=nullptr;
7578 	for (int i = 0; i < docSelectionCount; ++i)
7579 	{
7580 		currItem = m_Selection->itemAt(i);
7581 		int id = itemList->indexOf(currItem);
7582 		low = qMin(id, low);
7583 		high = qMax(id, high);
7584 	}
7585 	if (high == itemList->count()-1)
7586 		return;
7587 	PageItem *b2 = itemList->at(low);
7588 	bool wasSignalDelayed = !m_Selection->signalsDelayed();
7589 	m_Selection->delaySignalsOn();
7590 	if (!wasSignalDelayed)
7591 		m_Selection->disconnectAllItemsFromGUI();
7592 	Selection tempSelection(*m_Selection);
7593 	m_Selection->clear();
7594 	m_Selection->addItem(itemList->at(high + 1));
7595 	for (int i = 0; i < m_Selection->count(); ++i)
7596 	{
7597 		currItem = m_Selection->itemAt(i);
7598 		int d = itemList->indexOf(currItem);
7599 		ObjOrder.insert(d, i);
7600 		itemList->takeAt(d);
7601 	}
7602 	QList<int> Oindex = ObjOrder.values();
7603 	for (int i = 0; i <static_cast<int>(Oindex.count()); ++i)
7604 	{
7605 		int d = itemList->indexOf(b2);
7606 		if (d == -1)
7607 			d = 0;
7608 		itemList->insert(d, m_Selection->itemAt(Oindex[i]));
7609 	}
7610 	m_Selection->clear();
7611 	*m_Selection = tempSelection;
7612 	m_Selection->delaySignalsOff();
7613 	changed();
7614 	invalidateRegion(selRect);
7615 	regionsChanged()->update(QRectF());
7616 }
7617 
itemSelection_SetSoftShadow(bool has,QString color,double dx,double dy,double radius,int shade,double opac,int blend,bool erase,bool objopa)7618 void ScribusDoc::itemSelection_SetSoftShadow(bool has, QString color, double dx, double dy, double radius, int shade, double opac, int blend, bool erase, bool objopa)
7619 {
7620 	if (color == CommonStrings::tr_NoneColor)
7621 		color = CommonStrings::None;
7622 	int selectedItemCount = m_Selection->count();
7623 	if (selectedItemCount == 0)
7624 		return;
7625 	UndoTransaction activeTransaction;
7626 	m_updateManager.setUpdatesDisabled();
7627 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
7628 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::LineWidth, "", Um::ILineStyle);
7629 
7630 	for (int i = 0; i < selectedItemCount; ++i)
7631 	{
7632 		PageItem *currItem = m_Selection->itemAt(i);
7633 		currItem->setHasSoftShadow(has);
7634 		currItem->setSoftShadowColor(color);
7635 		currItem->setSoftShadowXOffset(dx);
7636 		currItem->setSoftShadowYOffset(dy);
7637 		currItem->setSoftShadowBlurRadius(radius);
7638 		currItem->setSoftShadowShade(shade);
7639 		currItem->setSoftShadowOpacity(opac);
7640 		currItem->setSoftShadowBlendMode(blend);
7641 		currItem->setSoftShadowErasedByObject(erase);
7642 		currItem->setSoftShadowHasObjectTransparency(objopa);
7643 		QRectF newRect = currItem->getVisualBoundingRect().adjusted(-dx, -dy, dx, dy);
7644 		currItem->invalidateLayout();
7645 		regionsChanged()->update(newRect);
7646 	}
7647 	if (activeTransaction)
7648 		activeTransaction.commit();
7649 	m_updateManager.setUpdatesEnabled();
7650 	changed();
7651 
7652 }
7653 
itemSelection_SetLineWidth(double w,Selection * customSelection)7654 void ScribusDoc::itemSelection_SetLineWidth(double w, Selection* customSelection)
7655 {
7656 	Selection *itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7657 	int selectedItemCount = itemSelection->count();
7658 	if (selectedItemCount == 0)
7659 		return;
7660 
7661 	UndoTransaction activeTransaction;
7662 	m_updateManager.setUpdatesDisabled();
7663 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
7664 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
7665 														  Um::IGroup, Um::LineWidth, "", Um::ILineStyle);
7666 	for (int i = 0; i < selectedItemCount; ++i)
7667 	{
7668 		PageItem *currItem = itemSelection->itemAt(i);
7669 		QRectF oldRect = currItem->getVisualBoundingRect();
7670 		//cb moved to setlinewidth
7671 		//currItem->m_oldLineWidth = currItem->lineWidth();
7672 		currItem->setLineWidth(w);
7673 		if (currItem->isPolyLine() || currItem->isSpiral())
7674 			currItem->setPolyClip(qRound(qMax(currItem->lineWidth() / 2, 1.0)));
7675 		if (currItem->isLine())
7676 			currItem->asLine()->setLineClip();
7677 		QRectF newRect = currItem->getVisualBoundingRect();
7678 		//currItem->update();
7679 		currItem->invalidateLayout();
7680 		regionsChanged()->update(newRect.united(oldRect));
7681 	}
7682 	if (activeTransaction)
7683 		activeTransaction.commit();
7684 	m_updateManager.setUpdatesEnabled();
7685 	changed();
7686 }
7687 
7688 
7689 
itemSelection_SetLineArt(Qt::PenStyle w,Selection * customSelection)7690 void ScribusDoc::itemSelection_SetLineArt(Qt::PenStyle w, Selection* customSelection)
7691 {
7692 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7693 	int selectedItemCount = itemSelection->count();
7694 	if (selectedItemCount == 0)
7695 		return;
7696 	UndoTransaction activeTransaction;
7697 	m_updateManager.setUpdatesDisabled();
7698 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
7699 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::LineStyle, "", Um::ILineStyle);
7700 	for (int i = 0; i < selectedItemCount; ++i)
7701 	{
7702 		PageItem* item = itemSelection->itemAt(i);
7703 		item->setLineStyle(w);
7704 		item->update();
7705 	}
7706 	if (activeTransaction)
7707 		activeTransaction.commit();
7708 	m_updateManager.setUpdatesEnabled();
7709 	changed();
7710 }
7711 
7712 
7713 
itemSelection_SetLineJoin(Qt::PenJoinStyle w,Selection * customSelection)7714 void ScribusDoc::itemSelection_SetLineJoin(Qt::PenJoinStyle w, Selection* customSelection)
7715 {
7716 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7717 	int selectedItemCount = itemSelection->count();
7718 	if (selectedItemCount == 0)
7719 		return;
7720 
7721 	UndoTransaction activeTransaction;
7722 	m_updateManager.setUpdatesDisabled();
7723 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
7724 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::LineJoin, "", Um::ILineStyle);
7725 	for (int i = 0; i < selectedItemCount; ++i)
7726 	{
7727 		PageItem* item = itemSelection->itemAt(i);
7728 		item->setLineJoin(w);
7729 		item->update();
7730 	}
7731 	if (activeTransaction)
7732 		activeTransaction.commit();
7733 	m_updateManager.setUpdatesEnabled();
7734 	changed();
7735 }
7736 
7737 
7738 
itemSelection_SetLineEnd(Qt::PenCapStyle w,Selection * customSelection)7739 void ScribusDoc::itemSelection_SetLineEnd(Qt::PenCapStyle w, Selection* customSelection)
7740 {
7741 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7742 	int selectedItemCount = itemSelection->count();
7743 	if (selectedItemCount == 0)
7744 		return;
7745 
7746 	UndoTransaction activeTransaction;
7747 	m_updateManager.setUpdatesDisabled();
7748 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
7749 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::LineEnd, "", Um::ILineStyle);
7750 	for (int i = 0; i < selectedItemCount; ++i)
7751 	{
7752 		PageItem* item = itemSelection->itemAt(i);
7753 		item->setLineEnd(w);
7754 		item->update();
7755 	}
7756 	if (activeTransaction)
7757 		activeTransaction.commit();
7758 	m_updateManager.setUpdatesEnabled();
7759 	changed();
7760 }
7761 
itemSelection_SetLineSpacing(double w,Selection * customSelection)7762 void ScribusDoc::itemSelection_SetLineSpacing(double w, Selection* customSelection)
7763 {
7764 	ParagraphStyle newStyle;
7765 	newStyle.setLineSpacing(w);
7766 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
7767 }
7768 
itemSelection_SetFont(const QString & font,Selection * customSelection)7769 void ScribusDoc::itemSelection_SetFont(const QString& font, Selection* customSelection)
7770 {
7771 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7772 	assert(itemSelection != nullptr);
7773 
7774 	uint selectedItemCount = itemSelection->count();
7775 	if (selectedItemCount == 0)
7776 		return;
7777 
7778 	QString newFont(font);
7779 	if (!UsedFonts.contains(newFont))
7780 	{
7781 		if (!AddFont(font))
7782 		{
7783 			PageItem *currItem = itemSelection->itemAt(0);
7784 			newFont = currItem->currentCharStyle().font().scName();
7785 		}
7786 	}
7787 
7788 	CharStyle newStyle;
7789 	newStyle.setFont((*AllFonts)[newFont]);
7790 	itemSelection_ApplyCharStyle(newStyle, customSelection, "FONT");
7791 }
7792 
itemSelection_SetFontSize(int size,Selection * customSelection)7793 void ScribusDoc::itemSelection_SetFontSize(int size, Selection* customSelection)
7794 {
7795 	CharStyle newStyle;
7796 	newStyle.setFontSize(size);
7797 	itemSelection_ApplyCharStyle(newStyle, customSelection, "FONT_SIZE");
7798 }
7799 
itemSelection_SetFontFeatures(const QString & fontfeature,Selection * customSelection)7800 void ScribusDoc::itemSelection_SetFontFeatures(const QString& fontfeature, Selection* customSelection)
7801 {
7802 	CharStyle newStyle;
7803 	newStyle.setFontFeatures(fontfeature);
7804 	itemSelection_ApplyCharStyle(newStyle, customSelection, "FONTFEATURES");
7805 }
7806 
itemSelection_SetHyphenWordMin(int wordMin,Selection * customSelection)7807 void ScribusDoc::itemSelection_SetHyphenWordMin(int wordMin, Selection* customSelection)
7808 {
7809 	CharStyle newStyle;
7810 	newStyle.setHyphenWordMin(wordMin);
7811 	itemSelection_ApplyCharStyle(newStyle, customSelection, "HYPHEN_WORDMIN");
7812 }
7813 
itemSelection_SetHyphenConsecutiveLines(int consecutiveLines,Selection * customSelection)7814 void ScribusDoc::itemSelection_SetHyphenConsecutiveLines(int consecutiveLines, Selection* customSelection)
7815 {
7816 	ParagraphStyle newStyle;
7817 	newStyle.setHyphenConsecutiveLines(consecutiveLines);
7818 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
7819 }
7820 
itemSelection_SetHyphenChar(uint hyphenChar,Selection * customSelection)7821 void ScribusDoc::itemSelection_SetHyphenChar(uint hyphenChar, Selection *customSelection)
7822 {
7823 	CharStyle newStyle;
7824 	newStyle.setHyphenChar(hyphenChar);
7825 	itemSelection_ApplyCharStyle(newStyle, customSelection, "HYPHEN_CHAR");
7826 }
7827 
itemSelection_SetNamedCharStyle(const QString & name,Selection * customSelection)7828 void ScribusDoc::itemSelection_SetNamedCharStyle(const QString& name, Selection* customSelection)
7829 {
7830 	CharStyle newStyle;
7831 	newStyle.setParent(name.isEmpty()? BaseStyle::INHERIT_PARENT : name);
7832 	itemSelection_ApplyCharStyle(newStyle, customSelection, "NAMED_STYLE");
7833 }
7834 
7835 
7836 
itemSelection_SetNamedParagraphStyle(const QString & name,Selection * customSelection)7837 void ScribusDoc::itemSelection_SetNamedParagraphStyle(const QString& name, Selection* customSelection)
7838 {
7839 	ParagraphStyle newStyle;
7840 	newStyle.setParent(name.isEmpty()? BaseStyle::INHERIT_PARENT : name);
7841 	itemSelection_ApplyParagraphStyle(newStyle, customSelection, false);
7842 }
7843 
7844 
itemSelection_SetNamedLineStyle(const QString & name,Selection * customSelection)7845 void ScribusDoc::itemSelection_SetNamedLineStyle(const QString &name, Selection* customSelection)
7846 {
7847 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7848 	uint docSelectionCount   = itemSelection->count();
7849 	if (docSelectionCount <= 0)
7850 		return;
7851 
7852 	UndoTransaction activeTransaction;
7853 	m_updateManager.setUpdatesDisabled();
7854 	if (UndoManager::undoEnabled() && docSelectionCount > 1)
7855 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::LineStyle, name, Um::ILineStyle);
7856 	for (uint aa = 0; aa < docSelectionCount; ++aa)
7857 	{
7858 		PageItem *currItem = itemSelection->itemAt(aa);
7859 		currItem->setCustomLineStyle(name);
7860 		currItem->update();
7861 	}
7862 	if (activeTransaction)
7863 		activeTransaction.commit();
7864 	m_updateManager.setUpdatesEnabled();
7865 	changed();
7866 }
7867 
7868 
itemSelection_SetItemPen(QString color,Selection * customSelection)7869 void ScribusDoc::itemSelection_SetItemPen(QString color, Selection* customSelection)
7870 {
7871 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
7872 	int selectedItemCount = itemSelection->count();
7873 	if (selectedItemCount <= 0)
7874 		return;
7875 
7876 	UndoTransaction activeTransaction;
7877 	m_updateManager.setUpdatesDisabled();
7878 	if (color == CommonStrings::tr_NoneColor)
7879 		color = CommonStrings::None;
7880 	if (selectedItemCount > 1 && UndoManager::undoEnabled())
7881 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
7882 															Um::IGroup, Um::SetLineColor, color, Um::IFill);
7883 	PageItem *currItem;
7884 	for (int i = 0; i < selectedItemCount; ++i)
7885 	{
7886 		currItem = itemSelection->itemAt(i);
7887 		if ((currItem->isLine()) && (color == CommonStrings::None))
7888 			continue;
7889 
7890 		currItem->setLineColor(color);
7891 		currItem->update();
7892 	}
7893 	if (activeTransaction)
7894 		activeTransaction.commit();
7895 	m_updateManager.setUpdatesEnabled();
7896 	changed();
7897 }
7898 
itemSelection_SetParBackgroundColor(QString farbe,Selection * customSelection)7899 void ScribusDoc::itemSelection_SetParBackgroundColor(QString farbe, Selection* customSelection)
7900 {
7901 	if (farbe == CommonStrings::tr_NoneColor)
7902 		farbe = CommonStrings::None;
7903 	ParagraphStyle newStyle;
7904 	newStyle.setBackgroundColor(farbe);
7905 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
7906 }
7907 
itemSelection_SetParBackgroundShade(int sha,Selection * customSelection)7908 void ScribusDoc::itemSelection_SetParBackgroundShade(int sha, Selection* customSelection)
7909 {
7910 	ParagraphStyle newStyle;
7911 	newStyle.setBackgroundShade(sha);
7912 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
7913 }
7914 
itemSelection_SetBackgroundColor(QString farbe,Selection * customSelection)7915 void ScribusDoc::itemSelection_SetBackgroundColor(QString farbe, Selection* customSelection)
7916 {
7917 	if (farbe == CommonStrings::tr_NoneColor)
7918 		farbe = CommonStrings::None;
7919 	CharStyle newStyle;
7920 	newStyle.setBackColor(farbe);
7921 	itemSelection_ApplyCharStyle(newStyle, customSelection, "BACK_COLOR");
7922 }
7923 
itemSelection_SetBackgroundShade(int sha,Selection * customSelection)7924 void ScribusDoc::itemSelection_SetBackgroundShade(int sha, Selection* customSelection)
7925 {
7926 	CharStyle newStyle;
7927 	newStyle.setBackShade(sha);
7928 	itemSelection_ApplyCharStyle(newStyle, customSelection, "BACK_SHADE");
7929 }
7930 
itemSelection_SetFillColor(QString farbe,Selection * customSelection)7931 void ScribusDoc::itemSelection_SetFillColor(QString farbe, Selection* customSelection)
7932 {
7933 	if (farbe == CommonStrings::tr_NoneColor)
7934 		farbe = CommonStrings::None;
7935 	CharStyle newStyle;
7936 	newStyle.setFillColor(farbe);
7937 	itemSelection_ApplyCharStyle(newStyle, customSelection, "FILL_COLOR");
7938 }
7939 
itemSelection_SetFillShade(int sha,Selection * customSelection)7940 void ScribusDoc::itemSelection_SetFillShade(int sha, Selection* customSelection)
7941 {
7942 	CharStyle newStyle;
7943 	newStyle.setFillShade(sha);
7944 	itemSelection_ApplyCharStyle(newStyle, customSelection, "FILL_SHADE");
7945 }
7946 
itemSelection_SetStrokeColor(QString farbe,Selection * customSelection)7947 void ScribusDoc::itemSelection_SetStrokeColor(QString farbe, Selection* customSelection)
7948 {
7949 	if (farbe == CommonStrings::tr_NoneColor)
7950 		farbe = CommonStrings::None;
7951 	CharStyle newStyle;
7952 	newStyle.setStrokeColor(farbe);
7953 	itemSelection_ApplyCharStyle(newStyle, customSelection, "STROKE_COLOR");
7954 }
7955 
itemSelection_SetStrokeShade(int sha,Selection * customSelection)7956 void ScribusDoc::itemSelection_SetStrokeShade(int sha, Selection* customSelection)
7957 {
7958 	CharStyle newStyle;
7959 	newStyle.setStrokeShade(sha);
7960 	itemSelection_ApplyCharStyle(newStyle, customSelection, "STROKE_SHADE");
7961 }
7962 
itemSelection_SetScaleV(int scale,Selection * customSelection)7963 void ScribusDoc::itemSelection_SetScaleV(int scale, Selection* customSelection)
7964 {
7965 	CharStyle newStyle;
7966 	newStyle.setScaleV(scale);
7967 	itemSelection_ApplyCharStyle(newStyle, customSelection, "SCALE_V");
7968 }
7969 
itemSelection_SetScaleH(int scale,Selection * customSelection)7970 void ScribusDoc::itemSelection_SetScaleH(int scale, Selection* customSelection)
7971 {
7972 	CharStyle newStyle;
7973 	newStyle.setScaleH(scale);
7974 	itemSelection_ApplyCharStyle(newStyle, customSelection, "SCALE_H");
7975 }
7976 
itemSelection_SetShadowOffsets(int shx,int shy,Selection * customSelection)7977 void ScribusDoc::itemSelection_SetShadowOffsets(int shx, int shy, Selection* customSelection)
7978 {
7979 	CharStyle newStyle;
7980 	newStyle.setShadowXOffset(shx);
7981 	newStyle.setShadowYOffset(shy);
7982 	itemSelection_ApplyCharStyle(newStyle, customSelection, "SHADOW_OFFSET");
7983 }
7984 
itemSelection_SetUnderline(int pos,int wid,Selection * customSelection)7985 void ScribusDoc::itemSelection_SetUnderline(int pos, int wid, Selection* customSelection)
7986 {
7987 	CharStyle newStyle;
7988 	newStyle.setUnderlineOffset(pos);
7989 	newStyle.setUnderlineWidth(wid);
7990 	itemSelection_ApplyCharStyle(newStyle, customSelection, "UNDERLINE");
7991 }
7992 
itemSelection_SetStrikethru(int pos,int wid,Selection * customSelection)7993 void ScribusDoc::itemSelection_SetStrikethru(int pos, int wid, Selection* customSelection)
7994 {
7995 	CharStyle newStyle;
7996 	newStyle.setStrikethruOffset(pos);
7997 	newStyle.setStrikethruWidth(wid);
7998 	itemSelection_ApplyCharStyle(newStyle, customSelection, "STRIKE_THRU");
7999 }
8000 
itemSelection_SetBaselineOffset(int sha,Selection * customSelection)8001 void ScribusDoc::itemSelection_SetBaselineOffset(int sha, Selection* customSelection)
8002 {
8003 	CharStyle newStyle;
8004 	newStyle.setBaselineOffset(sha);
8005 	itemSelection_ApplyCharStyle(newStyle, customSelection, "BASELINE_OFFSET");
8006 }
8007 
itemSelection_SetOutlineWidth(int wid,Selection * customSelection)8008 void ScribusDoc::itemSelection_SetOutlineWidth(int wid, Selection* customSelection)
8009 {
8010 	CharStyle newStyle;
8011 	newStyle.setOutlineWidth(wid);
8012 	itemSelection_ApplyCharStyle(newStyle, customSelection, "OUTLINE_WIDTH");
8013 }
8014 
itemSelection_SetItemBrush(QString colorName,Selection * customSelection)8015 void ScribusDoc::itemSelection_SetItemBrush(QString colorName, Selection* customSelection)
8016 {
8017 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8018 	int selectedItemCount = itemSelection->count();
8019 	if (selectedItemCount == 0)
8020 		return;
8021 
8022 	if (colorName == CommonStrings::tr_NoneColor)
8023 		colorName = CommonStrings::None;
8024 
8025 	UndoTransaction activeTransaction;
8026 	m_updateManager.setUpdatesDisabled();
8027 	if (selectedItemCount > 1 && UndoManager::undoEnabled())
8028 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
8029 															Um::IGroup, Um::SetFill, colorName, Um::IFill);
8030 	PageItem *currItem;
8031 	for (int i = 0; i < selectedItemCount; ++i)
8032 	{
8033 		currItem = itemSelection->itemAt(i);
8034 		currItem->setFillColor(colorName);
8035 		currItem->update();
8036 	}
8037 	if (activeTransaction)
8038 		activeTransaction.commit();
8039 	m_updateManager.setUpdatesEnabled();
8040 	changed();
8041 }
8042 
itemSelection_SetItemBrushShade(int sha,Selection * customSelection)8043 void ScribusDoc::itemSelection_SetItemBrushShade(int sha, Selection* customSelection)
8044 {
8045 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8046 	int selectedItemCount = itemSelection->count();
8047 	if (selectedItemCount == 0)
8048 		return;
8049 
8050 	UndoTransaction activeTransaction;
8051 	m_updateManager.setUpdatesDisabled();
8052 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
8053 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
8054 														  Um::IGroup, Um::SetShade, QString("%1").arg(sha),
8055 														  Um::IShade);
8056 	PageItem *currItem;
8057 	for (int i = 0; i < selectedItemCount; ++i)
8058 	{
8059 		currItem = itemSelection->itemAt(i);
8060 		currItem->setFillShade(sha);
8061 		currItem->update();
8062 	}
8063 	if (activeTransaction)
8064 		activeTransaction.commit();
8065 	m_updateManager.setUpdatesEnabled();
8066 	changed();
8067 }
8068 
itemSelection_SetItemPenShade(int sha,Selection * customSelection)8069 void ScribusDoc::itemSelection_SetItemPenShade(int sha, Selection* customSelection)
8070 {
8071 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8072 	int selectedItemCount = itemSelection->count();
8073 	if (selectedItemCount == 0)
8074 		return;
8075 
8076 	UndoTransaction activeTransaction;
8077 	m_updateManager.setUpdatesDisabled();
8078 	if (selectedItemCount > 1 && UndoManager::undoEnabled())
8079 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
8080 														  Um::IGroup, Um::SetLineShade, QString("%1").arg(sha), Um::IShade);
8081 	PageItem *currItem;
8082 	for (int i = 0; i < selectedItemCount; ++i)
8083 	{
8084 		currItem = itemSelection->itemAt(i);
8085 		currItem->setLineShade(sha);
8086 		currItem->update();
8087 	}
8088 	if (activeTransaction)
8089 		activeTransaction.commit();
8090 	m_updateManager.setUpdatesEnabled();
8091 	changed();
8092 }
8093 
itemSelection_SetItemGradMask(int typ,Selection * customSelection)8094 void ScribusDoc::itemSelection_SetItemGradMask(int typ, Selection* customSelection)
8095 {
8096 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8097 	int selectedItemCount = itemSelection->count();
8098 	if (selectedItemCount == 0)
8099 		return;
8100 
8101 	UndoTransaction activeTransaction;
8102 	m_updateManager.setUpdatesDisabled();
8103 	PageItem *currItem;
8104 	if (selectedItemCount > 1 && UndoManager::undoEnabled())
8105 		activeTransaction = m_undoManager->beginTransaction(Um::Selection,Um::IFill,Um::GradTypeMask,"",Um::IFill);
8106 	for (int i = 0; i < selectedItemCount; ++i)
8107 	{
8108 		currItem = itemSelection->itemAt(i);
8109 		currItem->setMaskType(typ);
8110 		if ((typ > 0) && (typ < 9))
8111 			currItem->updateGradientVectors();
8112 		currItem->update();
8113 	}
8114 	if (activeTransaction)
8115 		activeTransaction.commit();
8116 	m_updateManager.setUpdatesEnabled();
8117 	changed();
8118 }
8119 
itemSelection_SetItemGradStroke(int typ,Selection * customSelection)8120 void ScribusDoc::itemSelection_SetItemGradStroke(int typ, Selection* customSelection)
8121 {
8122 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8123 	int selectedItemCount = itemSelection->count();
8124 	if (selectedItemCount == 0)
8125 		return;
8126 
8127 	UndoTransaction activeTransaction;
8128 	m_updateManager.setUpdatesDisabled();
8129 	PageItem *currItem;
8130 	if (UndoManager::undoEnabled())
8131 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IFill, Um::GradTypeMask, "", Um::IFill);
8132 	for (int i = 0; i < selectedItemCount; ++i)
8133 	{
8134 		currItem = itemSelection->itemAt(i);
8135 		currItem->setStrokeGradientType(typ);
8136 		if (currItem->strokeGradientType() == 0)
8137 		{
8138 			if (currItem->lineColor() != CommonStrings::None)
8139 			{
8140 				if (!PageColors.contains(currItem->lineColor()))
8141 				{
8142 					switch (currItem->itemType())
8143 					{
8144 						case PageItem::TextFrame:
8145 						case PageItem::PathText:
8146 							currItem->setLineColor(m_docPrefsData.itemToolPrefs.textLineColor);
8147 							break;
8148 						case PageItem::Line:
8149 						case PageItem::PolyLine:
8150 						case PageItem::Polygon:
8151 						case PageItem::ImageFrame:
8152 						case PageItem::LatexFrame:
8153 						case PageItem::Spiral:
8154 							currItem->setLineColor(m_docPrefsData.itemToolPrefs.shapeLineColor);
8155 							break;
8156 						default:
8157 							break;
8158 					}
8159 				}
8160 			}
8161 		}
8162 		if ((typ > 0) && (typ < 8))
8163 			currItem->updateGradientVectors();
8164 		currItem->update();
8165 	}
8166 	if (activeTransaction)
8167 		activeTransaction.commit();
8168 	m_updateManager.setUpdatesEnabled();
8169 	changed();
8170 }
8171 
itemSelection_SetItemGradFill(int typ,Selection * customSelection)8172 void ScribusDoc::itemSelection_SetItemGradFill(int typ, Selection* customSelection)
8173 {
8174 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8175 	int selectedItemCount = itemSelection->count();
8176 	if (selectedItemCount == 0)
8177 		return;
8178 
8179 	UndoTransaction trans;
8180 	m_updateManager.setUpdatesDisabled();
8181 	PageItem *currItem;
8182 	if (UndoManager::undoEnabled())
8183 		trans = m_undoManager->beginTransaction(Um::Selection,Um::IPolygon,Um::SetFill,"",Um::IFill);
8184 	for (int i = 0; i < selectedItemCount; ++i)
8185 	{
8186 		currItem = itemSelection->itemAt(i);
8187 		currItem->setGradientType(typ);
8188 		switch (currItem->gradientType())
8189 		{
8190 			case Gradient_None:
8191 				if (currItem->fillColor() != CommonStrings::None)
8192 				{
8193 					if (!PageColors.contains(currItem->fillColor()))
8194 					{
8195 						switch (currItem->itemType())
8196 						{
8197 							case PageItem::ImageFrame:
8198 							case PageItem::LatexFrame:
8199 								currItem->setFillColor(m_docPrefsData.itemToolPrefs.imageFillColor);
8200 								break;
8201 							case PageItem::TextFrame:
8202 							case PageItem::PathText:
8203 								currItem->setFillColor(m_docPrefsData.itemToolPrefs.textFillColor);
8204 								break;
8205 							case PageItem::Line:
8206 							case PageItem::PolyLine:
8207 							case PageItem::Polygon:
8208 							case PageItem::Spiral:
8209 								currItem->setFillColor(m_docPrefsData.itemToolPrefs.shapeFillColor);
8210 								break;
8211 							default:
8212 								break;
8213 						}
8214 					}
8215 				}
8216 				break;
8217 			case Gradient_LinearLegacy1:
8218 				currItem->setGradientStart(0.0, currItem->height() / 2.0);
8219 				currItem->setGradientEnd(currItem->width(), currItem->height() / 2.0);
8220 				break;
8221 			case Gradient_LinearLegacy2:
8222 				currItem->setGradientStart(currItem->width() / 2.0, 0.0);
8223 				currItem->setGradientEnd(currItem->width() / 2.0, currItem->height());
8224 				break;
8225 			case Gradient_LinearLegacy3:
8226 				currItem->setGradientStart(0.0, 0.0);
8227 				currItem->setGradientEnd(currItem->width(), currItem->height());
8228 				break;
8229 			case Gradient_LinearLegacy4:
8230 				currItem->setGradientStart(0.0, currItem->height());
8231 				currItem->setGradientEnd(currItem->width(), 0.0);
8232 				break;
8233 			case Gradient_RadialLegacy5:
8234 				currItem->setGradientStart(currItem->width() / 2.0, currItem->height() / 2.0);
8235 				if (currItem->width() >= currItem->height())
8236 					currItem->setGradientEnd(currItem->width(), currItem->height() / 2.0);
8237 				else
8238 					currItem->setGradientEnd(currItem->width() / 2.0, currItem->height());
8239 				break;
8240 			default:
8241 				currItem->selectedMeshPointX = -1;
8242 				currItem->selectedMeshPointY = 0;
8243 				break;
8244 		}
8245 		if ((typ > 0) && (typ < 8))
8246 			currItem->updateGradientVectors();
8247 		if (currItem->gradientType() == Gradient_Conical)
8248 			currItem->createConicalMesh();
8249 		currItem->update();
8250 	}
8251 	if (trans)
8252 		trans.commit();
8253 	m_updateManager.setUpdatesEnabled();
8254 	changed();
8255 }
8256 
itemSelection_SetItemPatternFill(const QString & pattern,Selection * customSelection)8257 void ScribusDoc::itemSelection_SetItemPatternFill(const QString& pattern, Selection* customSelection)
8258 {
8259 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8260 	int selectedItemCount = itemSelection->count();
8261 	if (selectedItemCount == 0)
8262 		return;
8263 
8264 	m_updateManager.setUpdatesDisabled();
8265 	PageItem *currItem;
8266 	for (int i = 0; i < selectedItemCount; ++i)
8267 	{
8268 		currItem = itemSelection->itemAt(i);
8269 		currItem->setPattern(pattern);
8270 		currItem->update();
8271 	}
8272 	m_updateManager.setUpdatesEnabled();
8273 	changed();
8274 }
8275 
itemSelection_SetItemPatternProps(double imageScaleX,double imageScaleY,double offsetX,double offsetY,double rotation,double skewX,double skewY,bool mirrorX,bool mirrorY)8276 void ScribusDoc::itemSelection_SetItemPatternProps(double imageScaleX, double imageScaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY)
8277 {
8278 	int selectedItemCount = m_Selection->count();
8279 	if (selectedItemCount == 0)
8280 		return;
8281 	m_updateManager.setUpdatesDisabled();
8282 	PageItem *currItem;
8283 	for (int i = 0; i < selectedItemCount; ++i)
8284 	{
8285 		currItem = m_Selection->itemAt(i);
8286 		currItem->setPatternTransform(imageScaleX, imageScaleY, offsetX, offsetY, rotation, skewX, skewY);
8287 		currItem->setPatternFlip(mirrorX, mirrorY);
8288 		currItem->update();
8289 	}
8290 	m_updateManager.setUpdatesEnabled();
8291 	changed();
8292 }
8293 
itemSelection_SetItemStrokePattern(const QString & pattern,Selection * customSelection)8294 void ScribusDoc::itemSelection_SetItemStrokePattern(const QString& pattern, Selection* customSelection)
8295 {
8296 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8297 	int selectedItemCount = itemSelection->count();
8298 	if (selectedItemCount == 0)
8299 		return;
8300 
8301 	m_updateManager.setUpdatesDisabled();
8302 	PageItem *currItem;
8303 	for (int i = 0; i < selectedItemCount; ++i)
8304 	{
8305 		currItem = itemSelection->itemAt(i);
8306 		currItem->setStrokePattern(pattern);
8307 		currItem->update();
8308 	}
8309 	m_updateManager.setUpdatesEnabled();
8310 	changed();
8311 }
8312 
itemSelection_SetItemStrokePatternProps(double imageScaleX,double imageScaleY,double offsetX,double offsetY,double rotation,double skewX,double skewY,double space,bool mirrorX,bool mirrorY,Selection * customSelection)8313 void ScribusDoc::itemSelection_SetItemStrokePatternProps(double imageScaleX, double imageScaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, double space, bool mirrorX, bool mirrorY, Selection* customSelection)
8314 {
8315 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8316 	int selectedItemCount = itemSelection->count();
8317 	if (selectedItemCount == 0)
8318 		return;
8319 
8320 	m_updateManager.setUpdatesDisabled();
8321 	PageItem *currItem;
8322 	for (int i = 0; i < selectedItemCount; ++i)
8323 	{
8324 		currItem = itemSelection->itemAt(i);
8325 		currItem->setStrokePatternTransform(imageScaleX, imageScaleY, offsetX, offsetY, rotation, skewX, skewY, space);
8326 		currItem->setStrokePatternFlip(mirrorX, mirrorY);
8327 		currItem->update();
8328 	}
8329 	m_updateManager.setUpdatesEnabled();
8330 	changed();
8331 }
8332 
itemSelection_SetItemStrokePatternType(bool type,Selection * customSelection)8333 void ScribusDoc::itemSelection_SetItemStrokePatternType(bool type, Selection* customSelection)
8334 {
8335 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8336 	int selectedItemCount = itemSelection->count();
8337 	if (selectedItemCount == 0)
8338 		return;
8339 
8340 	m_updateManager.setUpdatesDisabled();
8341 	PageItem *currItem;
8342 	for (int i = 0; i < selectedItemCount; ++i)
8343 	{
8344 		currItem = itemSelection->itemAt(i);
8345 		currItem->setStrokePatternToPath(type);
8346 		currItem->update();
8347 	}
8348 	m_updateManager.setUpdatesEnabled();
8349 	changed();
8350 }
8351 
itemSelection_SetItemPatternMask(const QString & pattern,Selection * customSelection)8352 void ScribusDoc::itemSelection_SetItemPatternMask(const QString& pattern, Selection* customSelection)
8353 {
8354 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8355 	int selectedItemCount = itemSelection->count();
8356 	if (selectedItemCount == 0)
8357 		return;
8358 
8359 	m_updateManager.setUpdatesDisabled();
8360 	PageItem *currItem;
8361 	for (int i = 0; i < selectedItemCount; ++i)
8362 	{
8363 		currItem = itemSelection->itemAt(i);
8364 		currItem->setPatternMask(pattern);
8365 		currItem->update();
8366 	}
8367 	m_updateManager.setUpdatesEnabled();
8368 	changed();
8369 }
8370 
itemSelection_SetItemPatternMaskProps(double imageScaleX,double imageScaleY,double offsetX,double offsetY,double rotation,double skewX,double skewY,bool mirrorX,bool mirrorY,Selection * customSelection)8371 void ScribusDoc::itemSelection_SetItemPatternMaskProps(double imageScaleX, double imageScaleY, double offsetX, double offsetY, double rotation, double skewX, double skewY, bool mirrorX, bool mirrorY, Selection* customSelection)
8372 {
8373 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8374 	int selectedItemCount = itemSelection->count();
8375 	if (selectedItemCount == 0)
8376 		return;
8377 
8378 	m_updateManager.setUpdatesDisabled();
8379 	PageItem *currItem;
8380 	for (int i = 0; i < selectedItemCount; ++i)
8381 	{
8382 		currItem = itemSelection->itemAt(i);
8383 		currItem->setMaskTransform(imageScaleX, imageScaleY, offsetX, offsetY, rotation, skewX, skewY);
8384 		currItem->setMaskFlip(mirrorX, mirrorY);
8385 		currItem->update();
8386 	}
8387 	m_updateManager.setUpdatesEnabled();
8388 	changed();
8389 }
8390 
itemSelection_InsertTableRows()8391 void ScribusDoc::itemSelection_InsertTableRows()
8392 {
8393 	PageItem* item = m_Selection->itemAt(0);
8394 	if (!item || !item->isTable())
8395 		return;
8396 
8397 	PageItem_Table* table = item->asTable();
8398 	if (!table)
8399 		return;
8400 
8401 	QScopedPointer<InsertTableRowsDialog> dialog(new InsertTableRowsDialog(appMode, m_ScMW));
8402 	if (dialog->exec() == QDialog::Accepted)
8403 	{
8404 		dontResize = true;
8405 		/*
8406 		 * In table edit mode we insert either before or after the active
8407 		 * cell, otherwise we insert at beginning or end of table.
8408 		 */
8409 		int index = 0;
8410 		const TableCell cell = table->activeCell();
8411 		if (dialog->position() == InsertTableRowsDialog::Before)
8412 			index = appMode == modeEditTable ? cell.row() : 0;
8413 		else
8414 			index = appMode == modeEditTable ? cell.row() + cell.rowSpan() : table->rows();
8415 
8416 		// Insert the rows.
8417 		table->insertRows(index, dialog->numberOfRows());
8418 		table->clearSelection();
8419 		table->adjustTable();
8420 		table->update();
8421 
8422 		m_ScMW->updateTableMenuActions();
8423 		changed();
8424 	}
8425 }
8426 
itemSelection_InsertTableColumns()8427 void ScribusDoc::itemSelection_InsertTableColumns()
8428 {
8429 	PageItem* item = m_Selection->itemAt(0);
8430 	if (!item || !item->isTable())
8431 		return;
8432 
8433 	PageItem_Table* table = item->asTable();
8434 	if (!table)
8435 		return;
8436 
8437 	QPointer<InsertTableColumnsDialog> dialog = new InsertTableColumnsDialog(appMode, m_ScMW);
8438 	if (dialog->exec() == QDialog::Accepted)
8439 	{
8440 		dontResize = true;
8441 		/*
8442 		 * In table edit mode we insert either before or after the active
8443 		 * cell, otherwise we insert at beginning or end of table.
8444 		 */
8445 		int index = 0;
8446 		const TableCell cell = table->activeCell();
8447 		if (dialog->position() == InsertTableColumnsDialog::Before)
8448 			index = appMode == modeEditTable ? cell.column() : 0;
8449 		else
8450 			index = appMode == modeEditTable ? cell.column() + cell.columnSpan() : table->columns();
8451 
8452 		// Insert the columns.
8453 		table->insertColumns(index, dialog->numberOfColumns());
8454 		table->clearSelection();
8455 		table->adjustTable();
8456 		table->update();
8457 
8458 		m_ScMW->updateTableMenuActions();
8459 		changed();
8460 	}
8461 
8462 	delete dialog;
8463 }
8464 
itemSelection_DeleteTableRows()8465 void ScribusDoc::itemSelection_DeleteTableRows()
8466 {
8467 	PageItem* item = m_Selection->itemAt(0);
8468 	if (!item || !item->isTable())
8469 		return;
8470 
8471 	PageItem_Table* table = item->asTable();
8472 	if (!table)
8473 		return;
8474 
8475 	if (appMode != modeEditTable)
8476 		return;
8477 
8478 	if (table->selectedRows().size() >= table->rows())
8479 		return;
8480 
8481 	dontResize = true;
8482 	if (table->selectedRows().isEmpty())
8483 	{
8484 		// Remove rows spanned by active cell.
8485 		TableCell activeCell = table->activeCell();
8486 		table->removeRows(activeCell.row(), activeCell.rowSpan());
8487 	}
8488 	else
8489 	{
8490 		// Remove selected row(s).
8491 		QList<int> selectedRows = table->selectedRows().values();
8492 		std::sort(selectedRows.begin(), selectedRows.end(), std::greater<int>());
8493 
8494 		int index = 0;
8495 		int numRows = 1;
8496 		for (int i = 0; i < selectedRows.size() - 1; ++i)
8497 		{
8498 			index = selectedRows[i];
8499 			if (selectedRows[i] - 1 == selectedRows[i + 1])
8500 			{
8501 				index = selectedRows[i + 1];
8502 				numRows++;
8503 			}
8504 			else
8505 			{
8506 				table->removeRows(index, numRows);
8507 				numRows = 1;
8508 			}
8509 		}
8510 		table->removeRows(index, numRows);
8511 	}
8512 
8513 	m_View->stopGesture(); // FIXME: Don't use m_View.
8514 	table->adjustTable();
8515 	table->update();
8516 
8517 	m_ScMW->updateTableMenuActions();
8518 	changed();
8519 }
8520 
itemSelection_DeleteTableColumns()8521 void ScribusDoc::itemSelection_DeleteTableColumns()
8522 {
8523 	PageItem* item = m_Selection->itemAt(0);
8524 	if (!item || !item->isTable())
8525 		return;
8526 
8527 	PageItem_Table* table = item->asTable();
8528 	if (!table)
8529 		return;
8530 
8531 	if (appMode != modeEditTable)
8532 		return;
8533 
8534 	if (table->selectedColumns().size() >= table->columns())
8535 		return;
8536 
8537 	dontResize = true;
8538 	if (table->selectedColumns().isEmpty())
8539 	{
8540 		// Remove columns spanned by active cell.
8541 		TableCell activeCell = table->activeCell();
8542 		table->removeColumns(activeCell.column(), activeCell.columnSpan());
8543 	}
8544 	else
8545 	{
8546 		// Remove selected column(s).
8547 		QList<int> selectedColumns = table->selectedColumns().values();
8548 		std::sort(selectedColumns.begin(), selectedColumns.end(), std::greater<int>());
8549 
8550 		int index = 0;
8551 		int numColumns = 1;
8552 		for (int i = 0; i < selectedColumns.size() - 1; ++i)
8553 		{
8554 			index = selectedColumns[i];
8555 			if (selectedColumns[i] - 1 == selectedColumns[i + 1])
8556 			{
8557 				index = selectedColumns[i + 1];
8558 				numColumns++;
8559 			}
8560 			else
8561 			{
8562 				table->removeColumns(index, numColumns);
8563 				numColumns = 1;
8564 			}
8565 		}
8566 		table->removeColumns(index, numColumns);
8567 	}
8568 
8569 	m_View->stopGesture(); // FIXME: Don't use m_View.
8570 	table->adjustTable();
8571 	table->update();
8572 
8573 	m_ScMW->updateTableMenuActions();
8574 	changed();
8575 }
8576 
itemSelection_MergeTableCells()8577 void ScribusDoc::itemSelection_MergeTableCells()
8578 {
8579 	PageItem* item = m_Selection->itemAt(0);
8580 	if (!item || !item->isTable())
8581 		return;
8582 
8583 	PageItem_Table* table = item->asTable();
8584 	if (!table)
8585 		return;
8586 
8587 	if (appMode != modeEditTable)
8588 		return;
8589 
8590 	if (table->selectedCells().size() < 2)
8591 		return;
8592 
8593 	QList<int> selectedRows = table->selectedRows().values();
8594 	QList<int> selectedColumns = table->selectedColumns().values();
8595 	std::sort(selectedRows.begin(), selectedRows.end());
8596 	std::sort(selectedColumns.begin(), selectedColumns.end());
8597 
8598 	const int row = selectedRows.first();
8599 	const int column = selectedColumns.first();
8600 	const int numRows = selectedRows.last() - row + 1;
8601 	const int numColumns = selectedColumns.last() - column + 1;
8602 
8603 	dontResize = true;
8604 	table->mergeCells(row, column, numRows, numColumns);
8605 
8606 	m_View->stopGesture(); // FIXME: Don't use m_View.
8607 	table->adjustTable();
8608 	table->update();
8609 
8610 	m_ScMW->updateTableMenuActions();
8611 	changed();
8612 }
8613 
itemSelection_SetTableRowHeights()8614 void ScribusDoc::itemSelection_SetTableRowHeights()
8615 {
8616 	PageItem* item = m_Selection->itemAt(0);
8617 	if (!item || !item->isTable())
8618 		return;
8619 
8620 	PageItem_Table* table = item->asTable();
8621 	if (!table)
8622 		return;
8623 
8624 	QPointer<TableRowHeightsDialog> dialog = new TableRowHeightsDialog(this, m_ScMW);
8625 	if (dialog->exec() == QDialog::Rejected)
8626 		return;
8627 
8628 	const qreal rowHeight = dialog->rowHeight();
8629 	dontResize = true;
8630 	if (appMode == modeEditTable)
8631 	{
8632 		if (table->selectedCells().isEmpty())
8633 		{
8634 			// Set height of rows spanned by active cell.
8635 			TableCell activeCell = table->activeCell();
8636 			int startRow = activeCell.row();
8637 			int endRow = startRow + activeCell.rowSpan() - 1;
8638 			for (int row = startRow; row <= endRow; ++row)
8639 				table->resizeRow(row, rowHeight / unitRatio());
8640 		}
8641 		else
8642 		{
8643 			// Set height of selected rows.
8644 			for (const int row : table->selectedRows())
8645 				table->resizeRow(row, rowHeight / unitRatio());
8646 		}
8647 	}
8648 	else
8649 	{
8650 		// Set height of all rows in table.
8651 		for (int row = 0; row < table->rows(); ++row)
8652 			table->resizeRow(row, rowHeight / unitRatio());
8653 	}
8654 
8655 	delete dialog;
8656 
8657 	table->adjustTable();
8658 	table->update();
8659 	changed();
8660 }
8661 
itemSelection_SetTableColumnWidths()8662 void ScribusDoc::itemSelection_SetTableColumnWidths()
8663 {
8664 	PageItem* item = m_Selection->itemAt(0);
8665 	if (!item || !item->isTable())
8666 		return;
8667 
8668 	PageItem_Table* table = item->asTable();
8669 	if (!table)
8670 		return;
8671 
8672 	QPointer<TableColumnWidthsDialog> dialog = new TableColumnWidthsDialog(this, m_ScMW);
8673 	if (dialog->exec() == QDialog::Rejected)
8674 		return;
8675 
8676 	const qreal columnWidth = dialog->columnWidth();
8677 	dontResize = true;
8678 	if (appMode == modeEditTable)
8679 	{
8680 		if (table->selectedCells().isEmpty())
8681 		{
8682 			// Set width of columns spanned by active cell.
8683 			TableCell activeCell = table->activeCell();
8684 			int startColumn = activeCell.column();
8685 			int endColumn = startColumn + activeCell.columnSpan() - 1;
8686 			for (int column = startColumn; column <= endColumn; ++column)
8687 				table->resizeColumn(column, columnWidth / unitRatio());
8688 		}
8689 		else
8690 		{
8691 			// Set width of selected columns.
8692 			for (int column : table->selectedColumns())
8693 				table->resizeColumn(column, columnWidth / unitRatio());
8694 		}
8695 	}
8696 	else
8697 	{
8698 		// Set width of all columns in table.
8699 		for (int column = 0; column < table->columns(); ++column)
8700 			table->resizeColumn(column, columnWidth / unitRatio());
8701 	}
8702 
8703 	delete dialog;
8704 
8705 	table->adjustTable();
8706 	table->update();
8707 	changed();
8708 }
8709 
itemSelection_DistributeTableRowsEvenly()8710 void ScribusDoc::itemSelection_DistributeTableRowsEvenly()
8711 {
8712 	PageItem* item = m_Selection->itemAt(0);
8713 	if (!item || !item->isTable())
8714 		return;
8715 
8716 	PageItem_Table* table = item->asTable();
8717 	if (!table)
8718 		return;
8719 
8720 	dontResize = true;
8721 	if (appMode == modeEditTable && !table->selectedRows().isEmpty())
8722 	{
8723 		// Distribute each contigous range of selected rows.
8724 		QList<int> selectedRows = table->selectedRows().values();
8725 		std::sort(selectedRows.begin(), selectedRows.end());
8726 		int startRow = selectedRows.first();
8727 		int endRow = startRow;
8728 		for (int i = 0; i < selectedRows.size() - 1; ++i)
8729 		{
8730 			if (selectedRows[i + 1] == endRow + 1)
8731 				endRow++; // Extend range.
8732 			else
8733 			{
8734 				table->distributeRows(startRow, endRow);
8735 				// Move range.
8736 				startRow = selectedRows[i + 1];
8737 				endRow = startRow;
8738 			}
8739 		}
8740 		table->distributeRows(startRow, endRow);
8741 	}
8742 	else
8743 	{
8744 		// Distribute all rows in the table.
8745 		table->distributeRows(0, table->rows() - 1);
8746 	}
8747 
8748 	table->adjustTable();
8749 	table->update();
8750 	changed();
8751 }
8752 
itemSelection_DistributeTableColumnsEvenly()8753 void ScribusDoc::itemSelection_DistributeTableColumnsEvenly()
8754 {
8755 	PageItem* item = m_Selection->itemAt(0);
8756 	if (!item || !item->isTable())
8757 		return;
8758 
8759 	PageItem_Table* table = item->asTable();
8760 	if (!table)
8761 		return;
8762 
8763 	dontResize = true;
8764 	if (appMode == modeEditTable && !table->selectedColumns().isEmpty())
8765 	{
8766 		// Distribute each contigous range of selected columns.
8767 		QList<int> selectedColumns = table->selectedColumns().values();
8768 		std::sort(selectedColumns.begin(), selectedColumns.end());
8769 		int startColumn = selectedColumns.first();
8770 		int endColumn = startColumn;
8771 		for (int i = 0; i < selectedColumns.size() - 1; ++i)
8772 		{
8773 			if (selectedColumns[i + 1] == endColumn + 1)
8774 				endColumn++; // Extend range.
8775 			else
8776 			{
8777 				table->distributeColumns(startColumn, endColumn);
8778 				// Move range.
8779 				startColumn = selectedColumns[i + 1];
8780 				endColumn = startColumn;
8781 			}
8782 		}
8783 		table->distributeColumns(startColumn, endColumn);
8784 	}
8785 	else
8786 	{
8787 		// Distribute all columns in the table.
8788 		table->distributeColumns(0, table->columns() - 1);
8789 	}
8790 
8791 	table->adjustTable();
8792 	table->update();
8793 	changed();
8794 }
8795 
itemSelection_SetEffects(int s,Selection * customSelection)8796 void ScribusDoc::itemSelection_SetEffects(int s, Selection* customSelection)
8797 {
8798 	CharStyle newStyle;
8799 	newStyle.setFeatures(static_cast<StyleFlag>(s).featureList());
8800 	itemSelection_ApplyCharStyle(newStyle, customSelection, "EFFECTS");
8801 }
8802 
itemSelection_SetOpticalMargins(int i,Selection * customSelection)8803 void ScribusDoc::itemSelection_SetOpticalMargins(int i, Selection* customSelection)
8804 {
8805 	ParagraphStyle newStyle;
8806 	newStyle.setOpticalMargins(i);
8807 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
8808 }
8809 
8810 
itemSelection_resetOpticalMargins(Selection * customSelection)8811 void ScribusDoc::itemSelection_resetOpticalMargins(Selection* customSelection)
8812 {
8813 	//TODO
8814 //	ParagraphStyle newStyle;
8815 //	newStyle.setOpticalMargins(i);
8816 //	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
8817 }
8818 
itemSelection_SetTracking(int kern,Selection * customSelection)8819 void ScribusDoc::itemSelection_SetTracking(int kern, Selection* customSelection)
8820 {
8821 	CharStyle newStyle;
8822 	newStyle.setTracking(kern);
8823 	itemSelection_ApplyCharStyle(newStyle, customSelection, "TRACKING");
8824 }
8825 
itemSelection_SetLineSpacingMode(int m,Selection * customSelection)8826 void ScribusDoc::itemSelection_SetLineSpacingMode(int m, Selection* customSelection)
8827 {
8828 	ParagraphStyle newStyle;
8829 	newStyle.setLineSpacingMode(static_cast<ParagraphStyle::LineSpacingMode>(m));
8830 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
8831 }
8832 
itemSelection_SetLanguage(const QString & m,Selection * customSelection)8833 void ScribusDoc::itemSelection_SetLanguage(const QString & m, Selection* customSelection)
8834 {
8835 	CharStyle newStyle;
8836 	newStyle.setLanguage(m);
8837 	itemSelection_ApplyCharStyle(newStyle, customSelection, "LANGUAGE");
8838 }
8839 
itemSelection_ToggleBookMark(Selection * customSelection)8840 void ScribusDoc::itemSelection_ToggleBookMark(Selection *customSelection)
8841 {
8842 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8843 	assert(itemSelection != nullptr);
8844 	int selectedItemCount = itemSelection->count();
8845 	if (selectedItemCount == 0)
8846 		return;
8847 
8848 	for (int i = 0; i < selectedItemCount; ++i)
8849 	{
8850 		UndoTransaction activeTransaction;
8851 		if (UndoManager::undoEnabled())
8852 			activeTransaction = m_undoManager->beginTransaction();
8853 		PageItem* currItem = itemSelection->itemAt(i);
8854 		if (currItem->isTextFrame())
8855 		{
8856 			if (currItem->OwnPage != -1)
8857 			{
8858 				bool old = currItem->isBookmark;
8859 				currItem->setIsBookMark(!currItem->isBookmark);
8860 				if (currItem->isBookmark)
8861 				{
8862 					currItem->setIsAnnotation(false);
8863 					emit addBookmark(currItem);
8864 				}
8865 				else
8866 				{
8867 					if (old)
8868 						emit deleteBookmark(currItem);
8869 				}
8870 			}
8871 		}
8872 		if (activeTransaction) {
8873 			activeTransaction.commit(Um::Selection,
8874 									 Um::IGroup,
8875 									 Um::ActionPDF,
8876 									 "",
8877 									 Um::IGroup);
8878 		}
8879 	}
8880 	m_ScMW->actionManager->setPDFActions(m_View);
8881 	changed();
8882 }
8883 
itemSelection_ToggleAnnotation(Selection * customSelection)8884 void ScribusDoc::itemSelection_ToggleAnnotation(Selection *customSelection)
8885 {
8886 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8887 	assert(itemSelection != nullptr);
8888 	int selectedItemCount = itemSelection->count();
8889 	if (selectedItemCount == 0)
8890 		return;
8891 
8892 	for (int i = 0; i < selectedItemCount; ++i)
8893 	{
8894 		UndoTransaction activeTransaction;
8895 		if (UndoManager::undoEnabled())
8896 			activeTransaction = m_undoManager->beginTransaction();
8897 		PageItem* currItem = itemSelection->itemAt(i);
8898 		if (currItem->isTextFrame())
8899 		{
8900 			bool old = currItem->isBookmark;
8901 			currItem->setIsAnnotation(!currItem->isAnnotation());
8902 			if (currItem->isAnnotation())
8903 			{
8904 				currItem->AutoName = false;
8905 				if (m_masterPageMode)
8906 				{
8907 					currItem->annotation().setType(Annotation::Link);
8908 					currItem->annotation().setZiel(0);
8909 					currItem->annotation().setAction("0 0");
8910 				}
8911 				if (old)
8912 					emit deleteBookmark(currItem);
8913 				currItem->isBookmark = false;
8914 			}
8915 		}
8916 		if (activeTransaction) {
8917 			activeTransaction.commit(Um::Selection,
8918 									  Um::IGroup,
8919 									  Um::ActionPDF,
8920 									  "",
8921 									  Um::IGroup);
8922 		}
8923 	}
8924 	m_ScMW->actionManager->setPDFActions(m_View);
8925 	changed();
8926 }
8927 
itemSelection_SetParagraphStyle(const ParagraphStyle & newStyle,Selection * customSelection)8928 void ScribusDoc::itemSelection_SetParagraphStyle(const ParagraphStyle & newStyle, Selection* customSelection)
8929 {
8930 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8931 	assert(itemSelection != nullptr);
8932 	int selectedItemCount = itemSelection->count();
8933 	if (selectedItemCount == 0)
8934 		return;
8935 	UndoTransaction activeTransaction;
8936 	if (UndoManager::undoEnabled())
8937 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::SetStyle, newStyle.displayName(), Um::IFont);
8938 	for (int i = 0; i < selectedItemCount; ++i)
8939 	{
8940 		PageItem *currItem = itemSelection->itemAt(i);
8941 		int currItemTextCount = currItem->itemText.length();
8942 		if ((currItemTextCount > 0) && ((appMode == modeEdit) || (appMode == modeEditTable)))
8943 		{
8944 			int start = currItem->firstInFrame();
8945 			int stop = currItem->lastInFrame() + 1;
8946 			if ((appMode == modeEdit) || (appMode == modeEditTable))
8947 			{
8948 				start = currItem->itemText.startOfSelection();
8949 				stop = currItem->itemText.endOfSelection();
8950 				if (start >= stop)
8951 					start = stop = currItem->itemText.normalizedCursorPosition();
8952 			}
8953 			for (int pos = start; pos < stop; ++pos)
8954 			{
8955 				if (currItem->itemText.text(pos) == SpecialChars::PARSEP)
8956 				{
8957 					currItem->itemText.setStyle(pos, newStyle);
8958 				}
8959 			}
8960 			currItem->itemText.setStyle(stop, newStyle);
8961 			currItem->invalid = true;
8962 		}
8963 		else
8964 		{
8965 			if (currItem->isNoteFrame())
8966 				setNotesChanged(true);
8967 			else if (currItem->isTextFrame())
8968 				updateItemNotesFramesStyles(currItem, newStyle);
8969 			else
8970 				currItem->itemText.setDefaultStyle(newStyle);
8971 		}
8972 		if (currItem->isPathText())
8973 			currItem->updatePolyClip();
8974 	}
8975 	if (activeTransaction)
8976 		activeTransaction.commit();
8977 	changed();
8978 	regionsChanged()->update(QRectF());
8979 }
8980 
itemSelection_EraseParagraphStyle(Selection * customSelection)8981 void ScribusDoc::itemSelection_EraseParagraphStyle(Selection* customSelection)
8982 {
8983 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
8984 	assert(itemSelection != nullptr);
8985 	int selectedItemCount = itemSelection->count();
8986 	if (selectedItemCount == 0)
8987 		return;
8988 	UndoTransaction activeTransaction;
8989 	if (UndoManager::undoEnabled())
8990 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::RemoveTextStyle, tr( "remove direct paragraph formatting" ), Um::IFont);
8991 	for (int i = 0; i < selectedItemCount; ++i)
8992 	{
8993 		PageItem *currItem = itemSelection->itemAt(i);
8994 		int currItemTextCount = currItem->itemText.length();
8995 		if ((currItemTextCount > 0) && ((appMode == modeEdit) || (appMode == modeEditTable)))
8996 		{
8997 			int start = currItem->firstInFrame();
8998 			int stop = currItem->lastInFrame()+1;
8999 			if ((appMode == modeEdit) || (appMode == modeEditTable))
9000 			{
9001 				start = currItem->itemText.startOfSelection();
9002 				stop = currItem->itemText.endOfSelection();
9003 				if (start >= stop)
9004 					start = stop = currItem->itemText.normalizedCursorPosition();
9005 			}
9006 			for (int pos = start; pos < stop; ++pos)
9007 			{
9008 				if (currItem->itemText.text(pos) == SpecialChars::PARSEP)
9009 				{
9010 					ParagraphStyle newStyle;
9011 					newStyle.setParent(currItem->itemText.paragraphStyle(pos).parent());
9012 					if (UndoManager::undoEnabled())
9013 					{
9014 						ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9015 						is->set("SET_PARASTYLE");
9016 						is->set("POS", pos);
9017 						is->setItem(qMakePair(newStyle, currItem->itemText.paragraphStyle(pos)));
9018 						m_undoManager->action(currItem, is);
9019 					}
9020 					currItem->itemText.setStyle(pos, newStyle);
9021 				}
9022 			}
9023 			ParagraphStyle newStyle2;
9024 			newStyle2.setParent(currItem->itemText.paragraphStyle(stop).parent());
9025 			if (UndoManager::undoEnabled())
9026 			{
9027 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9028 				is->set("SET_PARASTYLE");
9029 				is->set("POS", stop);
9030 				is->setItem(qMakePair(newStyle2, currItem->itemText.paragraphStyle(stop)));
9031 				m_undoManager->action(currItem, is);
9032 			}
9033 			currItem->itemText.setStyle(stop, newStyle2);
9034 		}
9035 		else
9036 		{
9037 			ParagraphStyle newStyle;
9038 			//for notes frames apply style from master frame
9039 			if (currItem->isNoteFrame() && (currItem->asNoteFrame()->masterFrame() != nullptr))
9040 			{
9041 				newStyle.setParent(currItem->asNoteFrame()->masterFrame()->itemText.defaultStyle().parent());
9042 				newStyle.applyStyle(currItem->asNoteFrame()->masterFrame()->currentStyle());
9043 			}
9044 			else
9045 				newStyle.setParent(currItem->itemText.defaultStyle().parent());
9046 			if (UndoManager::undoEnabled())
9047 			{
9048 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9049 				is->set("APPLY_DEFAULTPARASTYLE");
9050 				is->setItem(qMakePair(newStyle, currItem->itemText.defaultStyle()));
9051 				m_undoManager->action(currItem, is);
9052 			}
9053 			currItem->itemText.setDefaultStyle(newStyle);
9054 			if (currItem->isTextFrame() && !currItem->isNoteFrame())
9055 				updateItemNotesFramesStyles(currItem, newStyle);
9056 			else if (currItem->isNoteFrame())
9057 				setNotesChanged(true);
9058 		}
9059 		currItem->invalid = true;
9060 		if (currItem->isPathText())
9061 			currItem->updatePolyClip();
9062 		if (currItem->isNoteFrame())
9063 			currItem->asNoteFrame()->updateNotesText();
9064 		else if (currItem->isTextFrame() && currItem->asTextFrame()->hasNoteFrame(nullptr, true))
9065 			setNotesChanged(true);
9066 	}
9067 	if (activeTransaction)
9068 		activeTransaction.commit();
9069 	changed();
9070 	regionsChanged()->update(QRectF());
9071 }
9072 
itemSelection_ClearBulNumStrings(Selection * customSelection)9073 void ScribusDoc::itemSelection_ClearBulNumStrings(Selection* customSelection)
9074 {
9075 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
9076 	assert(itemSelection != nullptr);
9077 	int selectedItemCount = itemSelection->count();
9078 	if (selectedItemCount == 0)
9079 		return;
9080 	for (int i = 0; i < selectedItemCount; ++i)
9081 	{
9082 		PageItem *currItem = itemSelection->itemAt(i);
9083 		if (currItem->itemText.length() == 0)
9084 			continue;
9085 		int currItemTextCount = currItem->itemText.length();
9086 		if ((appMode != modeEdit) && (appMode != modeEditTable))
9087 		{
9088 			for (int pos = 0; pos < currItemTextCount; ++pos)
9089 			{
9090 				if (currItem->itemText.hasMark(pos))
9091 				{
9092 					Mark* mark = currItem->itemText.mark(pos);
9093 					if (mark->isType(MARKBullNumType))
9094 					{
9095 						if (UndoManager::undoEnabled())
9096 						{
9097 							ScItemState<QPair<int,QString> > *is = new ScItemState<QPair <int,QString> >(Um::SetStyle);
9098 							is->set("CLEARMARK");
9099 							is->setItem(qMakePair(pos, mark->getString()));
9100 							m_undoManager->action(currItem, is);
9101 						}
9102 						mark->setString(QString());
9103 					}
9104 				}
9105 			}
9106 		}
9107 		else
9108 		{
9109 			int start;
9110 			int stop;
9111 			start = stop = currItem->itemText.normalizedCursorPosition();
9112 			if (currItem->HasSel)
9113 			{
9114 				start = currItem->itemText.startOfSelection();
9115 				stop = currItem->itemText.endOfSelection();
9116 			}
9117 			start = currItem->itemText.startOfParagraph(currItem->itemText.nrOfParagraph(start));
9118 			stop = currItem->itemText.endOfParagraph(currItem->itemText.nrOfParagraph(stop));
9119 			for (int pos=start; pos < stop; ++pos)
9120 			{
9121 				if (currItem->itemText.hasMark(pos))
9122 				{
9123 					Mark* mark = currItem->itemText.mark(pos);
9124 					if (mark->isType(MARKBullNumType))
9125 					{
9126 						if (UndoManager::undoEnabled())
9127 						{
9128 							ScItemState<QPair<int,QString> > *is = new ScItemState<QPair <int,QString> >(Um::SetStyle);
9129 							is->set("CLEARMARKSTRING");
9130 							is->setItem(qMakePair(pos, mark->getString()));
9131 							m_undoManager->action(currItem, is);
9132 						}
9133 						mark->setString(QString());
9134 					}
9135 				}
9136 			}
9137 		}
9138 	}
9139 	flag_Renumber = true;
9140 }
9141 
itemSelection_ApplyParagraphStyle(const ParagraphStyle & newStyle,Selection * customSelection,bool rmDirectFormatting)9142 void ScribusDoc::itemSelection_ApplyParagraphStyle(const ParagraphStyle & newStyle, Selection* customSelection, bool rmDirectFormatting)
9143 {
9144 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
9145 	assert(itemSelection != nullptr);
9146 	int selectedItemCount = itemSelection->count();
9147 	if (selectedItemCount == 0)
9148 		return;
9149 	UndoTransaction activeTransaction;
9150 	if (UndoManager::undoEnabled())
9151 	{
9152 		PageItem* currItem = itemSelection->itemAt(0);
9153 		QString  targetName = (selectedItemCount > 1) ? Um::SelectionGroup : currItem->getUName();
9154 		QPixmap* targetPixmap = (selectedItemCount > 1) ? Um::IGroup : currItem->getUPixmap();
9155 		activeTransaction = m_undoManager->beginTransaction(targetName, targetPixmap, Um::ApplyTextStyle, newStyle.displayName(), Um::IFont);
9156 	}
9157 	itemSelection_ClearBulNumStrings(itemSelection);
9158 	for (int i = 0; i < selectedItemCount; ++i)
9159 	{
9160 		PageItem *currItem = itemSelection->itemAt(i);
9161 		if (currItem->isTable() && appMode == modeEditTable)
9162 			currItem = currItem->asTable()->activeCell().textFrame();
9163 		int currItemTextCount = currItem->itemText.length();
9164 		if ((currItemTextCount == 0) || ((appMode != modeEdit) && (appMode != modeEditTable)))
9165 		{
9166 			ParagraphStyle dstyle(currItem->itemText.defaultStyle());
9167 			dstyle.applyStyle(newStyle);
9168 			if (UndoManager::undoEnabled())
9169 			{
9170 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9171 				is->set("APPLY_DEFAULTPARASTYLE");
9172 				is->setItem(qMakePair(dstyle, currItem->itemText.defaultStyle()));
9173 				m_undoManager->action(currItem, is);
9174 			}
9175 			currItem->itemText.setDefaultStyle(dstyle);
9176 			if (currItem->isNoteFrame())
9177 				setNotesChanged(true);
9178 			else if (currItem->isTextFrame())
9179 				updateItemNotesFramesStyles(currItem, dstyle);
9180 		}
9181 		if (currItemTextCount > 0)
9182 		{
9183 			int start = currItem->asPathText() ? currItem->firstInFrame() : 0;
9184 			int stop  = currItem->asPathText() ? currItem->lastInFrame() + 1 :  currItemTextCount;
9185 			if ((appMode == modeEdit) || (appMode == modeEditTable))
9186 			{
9187 				start = currItem->itemText.startOfSelection();
9188 				stop = currItem->itemText.endOfSelection();
9189 				if (start >= stop)
9190 					start = stop = currItem->itemText.normalizedCursorPosition();
9191 			}
9192 			for (int pos = start; pos < stop; ++pos)
9193 			{
9194 				if (currItem->itemText.text(pos) == SpecialChars::PARSEP)
9195 				{
9196 					if (UndoManager::undoEnabled())
9197 					{
9198 						ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9199 						is->set("APPLY_PARASTYLE");
9200 						is->set("POS",pos);
9201 						is->setItem(qMakePair(newStyle, currItem->itemText.paragraphStyle(pos)));
9202 						m_undoManager->action(currItem, is);
9203 					}
9204 					currItem->itemText.applyStyle(pos, newStyle, rmDirectFormatting);
9205 				}
9206 			}
9207 			if (UndoManager::undoEnabled())
9208 			{
9209 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9210 				is->set("APPLY_PARASTYLE");
9211 				is->set("POS",stop);
9212 				is->setItem(qMakePair(newStyle, currItem->itemText.paragraphStyle(stop)));
9213 				m_undoManager->action(currItem, is);
9214 			}
9215 			currItem->itemText.applyStyle(stop, newStyle, rmDirectFormatting);
9216 			currItem->invalid = true;
9217 		}
9218 		if (currItem->isPathText())
9219 			currItem->updatePolyClip();
9220 		if (currItem->isNoteFrame())
9221 			currItem->asNoteFrame()->updateNotesText();
9222 		else if (currItem->isTextFrame() && currItem->asTextFrame()->hasNoteFrame(nullptr, true))
9223 			setNotesChanged(true);
9224 		currItem->invalidateLayout();
9225 	}
9226 	if (activeTransaction)
9227 		activeTransaction.commit();
9228 	changed();
9229 	regionsChanged()->update(QRectF());
9230 }
9231 
itemSelection_ApplyCharStyle(const CharStyle & newStyle,Selection * customSelection,const QString & ETEA)9232 void ScribusDoc::itemSelection_ApplyCharStyle(const CharStyle & newStyle, Selection* customSelection, const QString& ETEA)
9233 {
9234 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
9235 	assert(itemSelection != nullptr);
9236 	uint selectedItemCount = itemSelection->count();
9237 	if (selectedItemCount == 0)
9238 		return;
9239 	UndoTransaction activeTransaction;
9240 	if (UndoManager::undoEnabled())
9241 	{
9242 		PageItem* currItem = itemSelection->itemAt(0);
9243 		QString  targetName = (selectedItemCount > 1) ? Um::SelectionGroup : currItem->getUName();
9244 		QPixmap* targetPixmap = (selectedItemCount > 1) ? Um::IGroup : currItem->getUPixmap();
9245 		activeTransaction = m_undoManager->beginTransaction(targetName, targetPixmap, Um::ApplyTextStyle, newStyle.asString(), Um::IFont);
9246 	}
9247 	for (uint aa = 0; aa < selectedItemCount; ++aa)
9248 	{
9249 		PageItem *currItem = itemSelection->itemAt(aa);
9250 		if (currItem->isTable() && appMode == modeEditTable)
9251 			currItem = currItem->asTable()->activeCell().textFrame();
9252 		int currItemTextCount = currItem->itemText.length();
9253 		if ((currItemTextCount > 0) && ((appMode == modeEdit) || (appMode == modeEditTable)))
9254 		{
9255 			int start = currItem->firstInFrame();
9256 			int length = currItem->lastInFrame() - start + 1;
9257 			if ((appMode == modeEdit) || (appMode == modeEditTable))
9258 			{
9259 				if (currItem->itemText.hasSelection())
9260 				{
9261 					start = currItem->itemText.startOfSelection();
9262 					length = currItem->itemText.endOfSelection() - start;
9263 				}
9264 				else
9265 				{
9266 					start = qMax(currItem->firstInFrame(), currItem->itemText.cursorPosition());
9267 					length = start < currItem->itemText.length() ? 1 : 0;
9268 				}
9269 			}
9270 			CharStyle lastParent = currItem->itemText.charStyle(start);
9271 			int stop = start + qMax(0,length);
9272 			int lastPos = start;
9273 			for (int i = start; i <= stop; ++i)
9274 			{
9275 				const CharStyle& curParent(currItem->itemText.charStyle(i));
9276 				if (!curParent.equiv(lastParent) || i==stop)
9277 				{
9278 					if (UndoManager::undoEnabled())
9279 					{
9280 						UndoState* state = m_undoManager->getLastUndo();
9281 						ScItemState<QPair<CharStyle,CharStyle> > *is = nullptr;
9282 						SimpleState *ss = nullptr;
9283 						TransactionState *ts = nullptr;
9284 						while (state && state->isTransaction())
9285 						{
9286 							ts = dynamic_cast<TransactionState*>(state);
9287 							ss = dynamic_cast<SimpleState*>(ts->last());
9288 							state = ts->last();
9289 						}
9290 						if (ts && ss && ss->get("ETEA") == ETEA)
9291 						{
9292 							for (int i = ts->sizet() - 1; i >= 0; --i)
9293 							{
9294 								is = dynamic_cast<ScItemState<QPair<CharStyle, CharStyle> > *>(ts->at(i));
9295 								if (!is || (is->get("ETEA") != ETEA))
9296 									break;
9297 								is->setItem(qMakePair(newStyle, is->getItem().second));
9298 							}
9299 						}
9300 						else
9301 						{
9302 							is = new ScItemState<QPair <CharStyle,CharStyle> >(Um::ApplyTextStyle);
9303 							is->set("APPLY_CHARSTYLE");
9304 							is->set("START", lastPos);
9305 							is->set("LENGTH", i - lastPos);
9306 							is->set("ETEA", ETEA);
9307 							is->setItem(qMakePair(newStyle, currItem->itemText.charStyle(lastPos)));
9308 							m_undoManager->action(currItem, is);
9309 						}
9310 					}
9311 					lastPos = i;
9312 					lastParent = curParent;
9313 				}
9314 			}
9315 			currItem->itemText.applyCharStyle(start, qMax(0, length), newStyle);
9316 			currItem->invalid = true;
9317 		}
9318 		else
9319 		{
9320 			ParagraphStyle dstyle(currItem->itemText.defaultStyle());
9321 			dstyle.charStyle().applyCharStyle(newStyle);
9322 			if (UndoManager::undoEnabled())
9323 			{
9324 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9325 				is->set("APPLY_DEFAULTPARASTYLE");
9326 				is->setItem(qMakePair(dstyle, currItem->itemText.defaultStyle()));
9327 				m_undoManager->action(currItem, is);
9328 			}
9329 			CharStyle lastParent = currItem->itemText.charStyle(0);
9330 			int stop = currItem->itemText.length();
9331 			int lastPos = 0;
9332 			for (int i = 0; i <= stop; ++i)
9333 			{
9334 				const CharStyle& curParent(currItem->itemText.charStyle(i));
9335 				if (!curParent.equiv(lastParent) || i==stop)
9336 				{
9337 					if (UndoManager::undoEnabled())
9338 					{
9339 						ScItemState<QPair<CharStyle,CharStyle> > *ist = new ScItemState<QPair <CharStyle,CharStyle> >(Um::ApplyTextStyle);
9340 						ist->set("APPLY_CHARSTYLE");
9341 						ist->set("START", lastPos);
9342 						ist->set("LENGTH", i - lastPos);
9343 						ist->setItem(qMakePair(newStyle, currItem->itemText.charStyle(lastPos)));
9344 						m_undoManager->action(currItem, ist);
9345 					}
9346 					lastPos = i;
9347 					lastParent = curParent;
9348 				}
9349 			}
9350 			currItem->itemText.setDefaultStyle(dstyle);
9351 			currItem->itemText.applyCharStyle(0, currItem->itemText.length(), newStyle);
9352 			currItem->invalid = true;
9353 			if (currItem->isNoteFrame())
9354 				setNotesChanged(true);
9355 			else if (currItem->isTextFrame())
9356 				updateItemNotesFramesStyles(currItem, dstyle);
9357 		}
9358 		if (currItem->isPathText())
9359 			currItem->updatePolyClip();
9360 		if (currItem->isNoteFrame())
9361 			currItem->asNoteFrame()->updateNotesText();
9362 		currItem->invalidateLayout();
9363 	}
9364 	if (activeTransaction)
9365 		activeTransaction.commit();
9366 	changed();
9367 	regionsChanged()->update(QRectF());
9368 }
9369 
itemSelection_SetCharStyle(const CharStyle & newStyle,Selection * customSelection)9370 void ScribusDoc::itemSelection_SetCharStyle(const CharStyle & newStyle, Selection* customSelection)
9371 {
9372 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
9373 	assert(itemSelection != nullptr);
9374 	int selectedItemCount = itemSelection->count();
9375 	if (selectedItemCount == 0)
9376 		return;
9377 	UndoTransaction activeTransaction;
9378 	if (UndoManager::undoEnabled())
9379 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::ApplyTextStyle, newStyle.asString(), Um::IFont);
9380 	for (int i = 0; i < selectedItemCount; ++i)
9381 	{
9382 		PageItem *currItem = itemSelection->itemAt(i);
9383 		int currItemTextCount = currItem->itemText.length();
9384 		if ((currItemTextCount > 0) && ((appMode == modeEdit) || (appMode == modeEditTable)))
9385 		{
9386 			int start = currItem->firstInFrame();
9387 			int length = currItem->lastInFrame() - start + 1;
9388 			if ((appMode == modeEdit) || (appMode == modeEditTable))
9389 			{
9390 				if (currItem->itemText.hasSelection())
9391 				{
9392 					start = currItem->itemText.startOfSelection();
9393 					length = currItem->itemText.endOfSelection() - start;
9394 				}
9395 				else
9396 				{
9397 					start = qMax(currItem->firstInFrame(), currItem->itemText.cursorPosition());
9398 					length = start < currItem->itemText.length() ? 1 : 0;
9399 				}
9400 			}
9401 			if (UndoManager::undoEnabled())
9402 			{
9403 				ScItemState<QPair<CharStyle,CharStyle> > *is = new ScItemState<QPair <CharStyle,CharStyle> >(Um::ApplyTextStyle);
9404 				is->set("SET_CHARSTYLE");
9405 				is->set("START",start);
9406 				is->set("LENGTH",length);
9407 				is->setItem(qMakePair(newStyle, currItem->itemText.charStyle(start)));
9408 				m_undoManager->action(currItem, is);
9409 			}
9410 			currItem->itemText.setCharStyle(start, length, newStyle);
9411 			currItem->invalid = true;
9412 		}
9413 		else
9414 		{
9415 			ParagraphStyle dstyle(currItem->itemText.defaultStyle());
9416 			dstyle.charStyle().setStyle(newStyle);
9417 			if (UndoManager::undoEnabled())
9418 			{
9419 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9420 				is->set("APPLY_DEFAULTPARASTYLE");
9421 				is->setItem(qMakePair(dstyle, currItem->itemText.defaultStyle()));
9422 				m_undoManager->action(currItem, is);
9423 
9424 				ScItemState<QPair<CharStyle,CharStyle> > *ist = new ScItemState<QPair <CharStyle,CharStyle> >(Um::ApplyTextStyle);
9425 				ist->set("SET_CHARSTYLE");
9426 				ist->set("START",0);
9427 				ist->set("LENGTH",currItem->itemText.length());
9428 				ist->setItem(qMakePair(newStyle, currItem->itemText.charStyle(0)));
9429 				m_undoManager->action(currItem, ist);
9430 			}
9431 			currItem->itemText.setDefaultStyle(dstyle);
9432 			currItem->itemText.setCharStyle(0, currItem->itemText.length(), newStyle);
9433 			if (currItem->isNoteFrame())
9434 				setNotesChanged(true);
9435 			else if (currItem->isTextFrame())
9436 				updateItemNotesFramesStyles(currItem, dstyle);
9437 		}
9438 		if (currItem->isPathText())
9439 			currItem->updatePolyClip();
9440 		if (currItem->isNoteFrame())
9441 			currItem->asNoteFrame()->updateNotesText();
9442 		currItem->invalidateLayout();
9443 	}
9444 	if (activeTransaction)
9445 		activeTransaction.commit();
9446 	changed();
9447 	regionsChanged()->update(QRectF());
9448 }
9449 
itemSelection_EraseCharStyle(Selection * customSelection)9450 void ScribusDoc::itemSelection_EraseCharStyle(Selection* customSelection)
9451 {
9452 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
9453 	assert(itemSelection != nullptr);
9454 	int selectedItemCount = itemSelection->count();
9455 	if (selectedItemCount == 0)
9456 		return;
9457 	UndoTransaction activeTransaction;
9458 	if (UndoManager::undoEnabled())
9459 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::RemoveTextStyle, tr( "remove direct char formatting" ), Um::IFont);
9460 	for (int i = 0; i < selectedItemCount; ++i)
9461 	{
9462 		PageItem *currItem = itemSelection->itemAt(i);
9463 		int currItemTextCount = currItem->itemText.length();
9464 		if ((currItemTextCount > 0) && ((appMode == modeEdit) || (appMode == modeEditTable)))
9465 		{
9466 			int start = currItem->firstInFrame();
9467 			int length = currItem->lastInFrame() - start + 1;
9468 			if ((appMode == modeEdit) || (appMode == modeEditTable))
9469 			{
9470 				if (currItem->itemText.hasSelection())
9471 				{
9472 					start = currItem->itemText.startOfSelection();
9473 					length = currItem->itemText.endOfSelection() - start;
9474 				}
9475 				else
9476 				{
9477 					start = qMax(currItem->firstInFrame(), currItem->itemText.cursorPosition());
9478 					length = start < currItem->itemText.length() ? 1 : 0;
9479 				}
9480 			}
9481 			QString lastParent;
9482 			int stop = start + length;
9483 			int lastPos = start;
9484 			for (int i = start; i < stop; ++i)
9485 			{
9486 				const QString& curParent(currItem->itemText.charStyle(i).parent());
9487 				if (curParent != lastParent)
9488 				{
9489 					if (i - lastPos > 0)
9490 					{
9491 						CharStyle newStyle;
9492 						newStyle.setParent(lastParent);
9493 						if (UndoManager::undoEnabled())
9494 						{
9495 							ScItemState<QPair<CharStyle,CharStyle> > *is = new ScItemState<QPair <CharStyle, CharStyle> >(Um::ApplyTextStyle);
9496 							is->set("SET_CHARSTYLE");
9497 							is->set("START", lastPos);
9498 							is->set("LENGTH", i - lastPos);
9499 							is->setItem(qMakePair(newStyle, currItem->itemText.charStyle(lastPos)));
9500 							m_undoManager->action(currItem, is);
9501 						}
9502 						currItem->itemText.setCharStyle(lastPos, i - lastPos, newStyle);
9503 						lastPos = i;
9504 					}
9505 					lastParent = curParent;
9506 				}
9507 			}
9508 			if (lastPos < stop)
9509 			{
9510 				CharStyle newStyle2;
9511 				newStyle2.setParent(lastParent);
9512 				if (UndoManager::undoEnabled())
9513 				{
9514 					ScItemState<QPair<CharStyle,CharStyle> > *is = new ScItemState<QPair <CharStyle,CharStyle> >(Um::ApplyTextStyle);
9515 					is->set("SET_CHARSTYLE");
9516 					is->set("START", lastPos);
9517 					is->set("LENGTH", stop - lastPos);
9518 					is->setItem(qMakePair(newStyle2, currItem->itemText.charStyle(lastPos)));
9519 					m_undoManager->action(currItem, is);
9520 				}
9521 				currItem->itemText.setCharStyle(lastPos, stop - lastPos, newStyle2);
9522 			}
9523 		}
9524 		else
9525 		{
9526 			ParagraphStyle defStyle = currItem->itemText.defaultStyle();
9527 			CharStyle newStyle;
9528 			newStyle.setParent(defStyle.charStyle().parent());
9529 			defStyle.charStyle() = newStyle;
9530 			if (UndoManager::undoEnabled())
9531 			{
9532 				ScItemState<QPair<ParagraphStyle, ParagraphStyle> > *is = new ScItemState<QPair <ParagraphStyle, ParagraphStyle> >(Um::SetStyle);
9533 				is->set("APPLY_DEFAULTPARASTYLE");
9534 				is->setItem(qMakePair(defStyle, currItem->itemText.defaultStyle()));
9535 				m_undoManager->action(currItem, is);
9536 			}
9537 			currItem->itemText.setDefaultStyle(defStyle);
9538 			if (currItem->isNoteFrame())
9539 				setNotesChanged(true);
9540 			else if (currItem->isTextFrame())
9541 				updateItemNotesFramesStyles(currItem, defStyle);
9542 		}
9543 		if (currItem->isPathText())
9544 			currItem->updatePolyClip();
9545 		if (currItem->isNoteFrame())
9546 			currItem->asNoteFrame()->updateNotesText();
9547 		currItem->invalidateLayout();
9548 	}
9549 	if (activeTransaction)
9550 		activeTransaction.commit();
9551 	changed();
9552 	regionsChanged()->update(QRectF());
9553 }
9554 
9555 //AV -> NodeEditContext
9556 //CB removed looping, called by itemSelection_FlipH
MirrorPolyH(PageItem * currItem)9557 void ScribusDoc::MirrorPolyH(PageItem* currItem)
9558 {
9559 	currItem->ClipEdited = true;
9560 	QTransform ma;
9561 	if (nodeEdit.isContourLine())
9562 	{
9563 		if (UndoManager::undoEnabled())
9564 		{
9565 			SimpleState *ss = new SimpleState(Um::FlipH, "", Um::IFlipH);
9566 			ss->set("MIRROR_PATH_H");
9567 			ss->set("IS_CONTOUR", true);
9568 			m_undoManager->action(currItem, ss, Um::IBorder);
9569 		}
9570 		//FPoint tp2(getMinClipF(&currItem->ContourLine));
9571 		FPoint tp(getMaxClipF(&currItem->ContourLine));
9572 		ma.translate(qRound(tp.x()), 0);
9573 		ma.scale(-1, 1);
9574 		currItem->ContourLine.map(ma);
9575 		regionsChanged()->update(QRectF());
9576 		changed();
9577 		return;
9578 	}
9579 	ma.scale(-1, 1);
9580 	currItem->PoLine.map(ma);
9581 	currItem->PoLine.translate(currItem->width(), 0);
9582 	if (currItem->isPathText())
9583 		currItem->updatePolyClip();
9584 	else
9585 		currItem->Clip = flattenPath(currItem->PoLine, currItem->Segments);
9586 	setRedrawBounding(currItem);
9587 	currItem->update();
9588 	if (UndoManager::undoEnabled())
9589 	{
9590 		SimpleState *ss = new SimpleState(Um::FlipH, "", Um::IFlipH);
9591 		ss->set("MIRROR_PATH_H");
9592 		ss->set("IS_CONTOUR", false);
9593 		m_undoManager->action(currItem, ss, Um::IBorder);
9594 	}
9595 	changed();
9596 }
9597 
9598 
9599 //AV -> NodeEditContext
9600 //CB removed looping, called by itemSelection_FlipV
MirrorPolyV(PageItem * currItem)9601 void ScribusDoc::MirrorPolyV(PageItem* currItem)
9602 {
9603 	currItem->ClipEdited = true;
9604 	QTransform ma;
9605 	if (nodeEdit.isContourLine())
9606 	{
9607 		if (UndoManager::undoEnabled())
9608 		{
9609 			SimpleState *ss = new SimpleState(Um::FlipV, "", Um::IFlipV);
9610 			ss->set("MIRROR_PATH_V");
9611 			ss->set("IS_CONTOUR", true);
9612 			m_undoManager->action(currItem, ss, Um::IBorder);
9613 		}
9614 		FPoint tp(getMaxClipF(&currItem->ContourLine));
9615 		ma.translate(0, qRound(tp.y()));
9616 		ma.scale(1, -1);
9617 		currItem->ContourLine.map(ma);
9618 		regionsChanged()->update(QRectF());
9619 		changed();
9620 		return;
9621 	}
9622 	ma.scale(1, -1);
9623 	currItem->PoLine.map(ma);
9624 	currItem->PoLine.translate(0, currItem->height());
9625 	if (currItem->isPathText())
9626 		currItem->updatePolyClip();
9627 	else
9628 		currItem->Clip = flattenPath(currItem->PoLine, currItem->Segments);
9629 	setRedrawBounding(currItem);
9630 	currItem->update();
9631 	if (UndoManager::undoEnabled())
9632 	{
9633 		SimpleState *ss = new SimpleState(Um::FlipV, "", Um::IFlipV);
9634 		ss->set("MIRROR_PATH_V");
9635 		ss->set("IS_CONTOUR", false);
9636 		m_undoManager->action(currItem, ss, Um::IBorder);
9637 	}
9638 	changed();
9639 }
9640 
getItem(PageItem ** currItem,int nr)9641 bool ScribusDoc::getItem(PageItem **currItem, int nr)
9642 {
9643 	int n=nr;
9644 	if (n == -1)
9645 		n=0;
9646 	*(currItem) = m_Selection->itemAt(n);
9647 	return (*(currItem) != nullptr);
9648 }
9649 
setFrameRect()9650 void ScribusDoc::setFrameRect()
9651 {
9652 	nodeEdit.deselect();
9653 	PageItem *currItem;
9654 	if (getItem(&currItem))
9655 	{
9656 		currItem->SetRectFrame();
9657 		setRedrawBounding(currItem);
9658 		regionsChanged()->update(currItem->getRedrawBounding(1.0));
9659 	}
9660 }
9661 
setFrameRounded()9662 void ScribusDoc::setFrameRounded()
9663 {
9664 	nodeEdit.deselect();
9665 	PageItem *currItem;
9666 	if (getItem(&currItem))
9667 	{
9668 		if (currItem->cornerRadius() == 0)
9669 		{
9670 			setFrameRect();
9671 			return;
9672 		}
9673 		currItem->SetFrameRound();
9674 		setRedrawBounding(currItem);
9675 		regionsChanged()->update(currItem->getRedrawBounding(1.0));
9676 	}
9677 }
9678 
setFrameOval()9679 void ScribusDoc::setFrameOval()
9680 {
9681 	nodeEdit.deselect();
9682 	PageItem *currItem;
9683 	if (getItem(&currItem))
9684 	{
9685 		currItem->SetOvalFrame();
9686 		setRedrawBounding(currItem);
9687 		regionsChanged()->update(currItem->getRedrawBounding(1.0));
9688 	}
9689 }
9690 
9691 
setRedrawBounding(PageItem * currItem)9692 void ScribusDoc::setRedrawBounding(PageItem *currItem)
9693 {
9694 	currItem->setRedrawBounding();
9695 	FPoint maxSize(currItem->BoundingX+currItem->BoundingW+m_docPrefsData.displayPrefs.scratch.right(), currItem->BoundingY+currItem->BoundingH+m_docPrefsData.displayPrefs.scratch.bottom());
9696 	FPoint minSize(currItem->BoundingX-m_docPrefsData.displayPrefs.scratch.left(), currItem->BoundingY-m_docPrefsData.displayPrefs.scratch.top());
9697 	adjustCanvas(minSize, maxSize);
9698 }
9699 
9700 
adjustCanvas(const FPoint & minPos,const FPoint & maxPos,bool absolute)9701 void ScribusDoc::adjustCanvas(const FPoint& minPos, const FPoint& maxPos, bool absolute)
9702 {
9703 	if (dontResize)
9704 		return;
9705 	double newMaxX, newMaxY, newMinX, newMinY;
9706 	if (absolute)
9707 	{
9708 		newMaxX = maxPos.x();
9709 		newMaxY = maxPos.y();
9710 		newMinX = minPos.x();
9711 		newMinY = minPos.y();
9712 	}
9713 	else
9714 	{
9715 		newMaxX = qMax(maxCanvasCoordinate.x(), maxPos.x());
9716 		newMaxY = qMax(maxCanvasCoordinate.y(), maxPos.y());
9717 		newMinX = qMin(minCanvasCoordinate.x(), minPos.x());
9718 		newMinY = qMin(minCanvasCoordinate.y(), minPos.y());
9719 	}
9720 	if ((newMaxX != maxCanvasCoordinate.x()) || (newMaxY != maxCanvasCoordinate.y())
9721 	|| (newMinX != minCanvasCoordinate.x()) || (newMinY != minCanvasCoordinate.y()))
9722 	{
9723 		maxCanvasCoordinate = FPoint(newMaxX, newMaxY);
9724 		minCanvasCoordinate = FPoint(newMinX, newMinY);
9725 		regionsChanged()->update(QRectF());
9726 	}
9727 }
9728 
9729 
connectDocSignals()9730 void ScribusDoc::connectDocSignals()
9731 {
9732 	if (ScCore->usingGUI())
9733 	{
9734 		if (m_hasGUI)
9735 		{
9736 			connect(this, SIGNAL(docChanged()), m_ScMW, SLOT(slotDocCh()));
9737 			connect(this, SIGNAL(firstSelectedItemType(int)), m_ScMW, SLOT(HaveNewSel()));
9738 			connect(this->m_Selection, SIGNAL(selectionChanged()), m_ScMW, SLOT(HaveNewSel()));
9739 			connect(autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
9740 		}
9741 	}
9742 }
9743 
disconnectDocSignals()9744 void ScribusDoc::disconnectDocSignals()
9745 {
9746 	if (ScCore->usingGUI())
9747 	{
9748 		if (m_hasGUI)
9749 		{
9750 			disconnect(this, SIGNAL(docChanged()), m_ScMW, SLOT(slotDocCh()));
9751 			disconnect(this, SIGNAL(firstSelectedItemType(int)), m_ScMW, SLOT(HaveNewSel()));
9752 			disconnect(this->m_Selection, SIGNAL(selectionChanged()), m_ScMW, SLOT(HaveNewSel()));
9753 			disconnect(autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
9754 		}
9755 	}
9756 }
9757 
9758 //CB Same as RecalcPicturesRes apart from the name checking, which should be able to be removed
updatePict(const QString & name)9759 void ScribusDoc::updatePict(const QString& name)
9760 {
9761 	bool updated = false;
9762 	QList<PageItem*> allItems;
9763 
9764 	for (PageItemIterator it(this, PageItemIterator::IterateInDocNoPatterns); *it; ++it)
9765 	{
9766 		PageItem *currItem = *it;
9767 		if ((!currItem->imageIsAvailable) || (currItem->Pfile != name))
9768 			continue;
9769 		bool fho = currItem->imageFlippedH();
9770 		bool fvo = currItem->imageFlippedV();
9771 		double imgX = currItem->imageXOffset();
9772 		double imgY = currItem->imageYOffset();
9773 		loadPict(currItem->Pfile, currItem, true);
9774 		currItem->setImageFlippedH(fho);
9775 		currItem->setImageFlippedV(fvo);
9776 		currItem->setImageXOffset(imgX);
9777 		currItem->setImageYOffset(imgY);
9778 		updated = true;
9779 	}
9780 
9781 	auto patternEnd = docPatterns.end();
9782 	for (auto it = docPatterns.begin(); it != patternEnd; ++it)
9783 	{
9784 		ScPattern& pa = it.value();
9785 		if (pa.items.count() <= 0)
9786 			continue;
9787 		for (int j = 0; j < pa.items.count(); j++)
9788 		{
9789 			PageItem *currItem = pa.items.at(j);
9790 			if (currItem->isGroup())
9791 				allItems = currItem->getAllChildren();
9792 			else
9793 				allItems.append(currItem);
9794 			for (int k = 0; k < allItems.count(); k++)
9795 			{
9796 				currItem = allItems.at(k);
9797 				if ((!currItem->imageIsAvailable) || (currItem->Pfile != name))
9798 					continue;
9799 				bool fho = currItem->imageFlippedH();
9800 				bool fvo = currItem->imageFlippedV();
9801 				double imgX = currItem->imageXOffset();
9802 				double imgY = currItem->imageYOffset();
9803 				loadPict(currItem->Pfile, currItem, true);
9804 				currItem->setImageFlippedH(fho);
9805 				currItem->setImageFlippedV(fvo);
9806 				currItem->setImageXOffset(imgX);
9807 				currItem->setImageYOffset(imgY);
9808 				updated = true;
9809 			}
9810 			allItems.clear();
9811 		}
9812 		PageItem *ite = pa.items.at(0);
9813 		double minx =  std::numeric_limits<double>::max();
9814 		double miny =  std::numeric_limits<double>::max();
9815 		double maxx = -std::numeric_limits<double>::max();
9816 		double maxy = -std::numeric_limits<double>::max();
9817 		double x1, x2, y1, y2;
9818 		ite->getVisualBoundingRect(&x1, &y1, &x2, &y2);
9819 		minx = qMin(minx, x1);
9820 		miny = qMin(miny, y1);
9821 		maxx = qMax(maxx, x2);
9822 		maxy = qMax(maxy, y2);
9823 		pa.pattern = ite->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
9824 	}
9825 	if (updated)
9826 	{
9827 		regionsChanged()->update(QRectF());
9828 		changed();
9829 	}
9830 }
9831 
updatePictDir(const QString & name)9832 void ScribusDoc::updatePictDir(const QString& name)
9833 {
9834 	bool updated = false;
9835 	QList<PageItem*> allItems;
9836 
9837 	for (PageItemIterator it(this, PageItemIterator::IterateInDocNoPatterns); *it; ++it)
9838 	{
9839 		PageItem *currItem = *it;
9840 		if (!currItem->isImageFrame() || currItem->imageIsAvailable || currItem->Pfile.isEmpty())
9841 			continue;
9842 		QFileInfo fi(currItem->Pfile);
9843 		if ((fi.absolutePath() != name) || !fi.exists())
9844 			continue;
9845 		bool fho = currItem->imageFlippedH();
9846 		bool fvo = currItem->imageFlippedV();
9847 		double imgX = currItem->imageXOffset();
9848 		double imgY = currItem->imageYOffset();
9849 		loadPict(currItem->Pfile, currItem, true);
9850 		currItem->setImageFlippedH(fho);
9851 		currItem->setImageFlippedV(fvo);
9852 		currItem->setImageXOffset(imgX);
9853 		currItem->setImageYOffset(imgY);
9854 		ScCore->fileWatcher->addFile(currItem->Pfile);
9855 		updated = true;
9856 	}
9857 
9858 	auto patternEnd = docPatterns.end();
9859 	for (auto it = docPatterns.begin(); it != patternEnd; ++it)
9860 	{
9861 		ScPattern& pa = it.value();
9862 		if (pa.items.count() <= 0)
9863 			continue;
9864 		for (int o = 0; o < pa.items.count(); o++)
9865 		{
9866 			PageItem *currItem = pa.items.at(o);
9867 			if (currItem->isGroup())
9868 				allItems = currItem->getAllChildren();
9869 			else
9870 				allItems.append(currItem);
9871 			for (int ii = 0; ii < allItems.count(); ii++)
9872 			{
9873 				currItem = allItems.at(ii);
9874 				if (!currItem->isImageFrame() || currItem->imageIsAvailable || currItem->Pfile.isEmpty())
9875 					continue;
9876 				QFileInfo fi(currItem->Pfile);
9877 				if ((fi.absolutePath() != name) || !fi.exists())
9878 					continue;
9879 				bool fho = currItem->imageFlippedH();
9880 				bool fvo = currItem->imageFlippedV();
9881 				double imgX = currItem->imageXOffset();
9882 				double imgY = currItem->imageYOffset();
9883 				loadPict(currItem->Pfile, currItem, true);
9884 				currItem->setImageFlippedH(fho);
9885 				currItem->setImageFlippedV(fvo);
9886 				currItem->setImageXOffset(imgX);
9887 				currItem->setImageYOffset(imgY);
9888 				ScCore->fileWatcher->addFile(currItem->Pfile);
9889 				updated = true;
9890 			}
9891 			allItems.clear();
9892 		}
9893 		PageItem *ite = pa.items.at(0);
9894 		double minx =  std::numeric_limits<double>::max();
9895 		double miny =  std::numeric_limits<double>::max();
9896 		double maxx = -std::numeric_limits<double>::max();
9897 		double maxy = -std::numeric_limits<double>::max();
9898 		double x1, x2, y1, y2;
9899 		ite->getVisualBoundingRect(&x1, &y1, &x2, &y2);
9900 		minx = qMin(minx, x1);
9901 		miny = qMin(miny, y1);
9902 		maxx = qMax(maxx, x2);
9903 		maxy = qMax(maxy, y2);
9904 		pa.pattern = ite->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
9905 	}
9906 	if (updated)
9907 	{
9908 		regionsChanged()->update(QRectF());
9909 		changed();
9910 	}
9911 }
9912 
9913 //CB Same as updatePict apart from the name checking, this should be able to be removed
recalcPicturesRes(int recalcFlags)9914 void ScribusDoc::recalcPicturesRes(int recalcFlags)
9915 {
9916 	int imageCount = 0;
9917 	int progress = 0;
9918 	PageItemIterator itemIt;
9919 	ScGuardedPtr<ScribusDoc> docPtr = guardedPtr();
9920 	QList<PageItem*> frameItemList = FrameItems.values();
9921 
9922 	for (itemIt.begin(DocItems); *itemIt; ++itemIt)
9923 	{
9924 		PageItem *currItem = *itemIt;
9925 		if (currItem->imageIsAvailable)
9926 			imageCount++;
9927 	}
9928 	for (itemIt.begin(MasterItems); *itemIt; ++itemIt)
9929 	{
9930 		PageItem *currItem = *itemIt;
9931 		if (currItem->imageIsAvailable)
9932 			imageCount++;
9933 	}
9934 	for (itemIt.begin(frameItemList); *itemIt; ++itemIt)
9935 	{
9936 		PageItem *currItem = *itemIt;
9937 		if (currItem->imageIsAvailable)
9938 			imageCount++;
9939 	}
9940 	auto patternConstEnd = docPatterns.constEnd();
9941 	for (auto patIt = docPatterns.constBegin(); patIt != patternConstEnd; ++patIt)
9942 	{
9943 		const ScPattern& pa = patIt.value();
9944 		for (itemIt.begin(pa.items); *itemIt; ++itemIt)
9945 		{
9946 			PageItem *currItem = *itemIt;
9947 			if (currItem->imageIsAvailable)
9948 				imageCount++;
9949 		}
9950 	}
9951 
9952 	if (imageCount <= 0)
9953 		return;
9954 
9955 	m_ScMW->mainWindowProgressBar->reset();
9956 	m_ScMW->mainWindowProgressBar->setMaximum((imageCount > 0) ? imageCount : 1);
9957 
9958 	for (itemIt.begin(DocItems); *itemIt; ++itemIt)
9959 	{
9960 		PageItem *currItem = *itemIt;
9961 		if (!currItem->imageIsAvailable)
9962 			continue;
9963 		if (recalcFlags & (RecalcPicRes_ImageWithEffectsOnly | RecalcPicRes_ImageWithColorEffectsOnly))
9964 		{
9965 			if (currItem->effectsInUse.count() <= 0)
9966 				continue;
9967 		}
9968 		if (recalcFlags & RecalcPicRes_ImageWithColorEffectsOnly)
9969 		{
9970 			if (!currItem->effectsInUse.useColorEffect())
9971 				continue;
9972 		}
9973 		bool fho = currItem->imageFlippedH();
9974 		bool fvo = currItem->imageFlippedV();
9975 		double imgX = currItem->imageXOffset();
9976 		double imgY = currItem->imageYOffset();
9977 		if (recalcFlags & RecalcPicRes_ApplyNewRes)
9978 			currItem->pixm.imgInfo.lowResType = m_docPrefsData.itemToolPrefs.imageLowResType;
9979 		if (currItem->isLatexFrame())
9980 			currItem->asLatexFrame()->rerunApplication(false);
9981 		else
9982 			loadPict(currItem->Pfile, currItem, true);
9983 		currItem->setImageFlippedH(fho);
9984 		currItem->setImageFlippedV(fvo);
9985 		currItem->setImageXOffset(imgX);
9986 		currItem->setImageYOffset(imgY);
9987 		currItem->adjustPictScale();
9988 		progress++;
9989 		m_ScMW->mainWindowProgressBar->setValue(progress);
9990 		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
9991 		if (!docPtr) return;
9992 	}
9993 
9994 	for (itemIt.begin(MasterItems); *itemIt; ++itemIt)
9995 	{
9996 		PageItem *currItem = *itemIt;
9997 		if (!currItem->imageIsAvailable)
9998 			continue;
9999 		if (recalcFlags & (RecalcPicRes_ImageWithEffectsOnly | RecalcPicRes_ImageWithColorEffectsOnly))
10000 		{
10001 			if (currItem->effectsInUse.count() <= 0)
10002 				continue;
10003 		}
10004 		if (recalcFlags & RecalcPicRes_ImageWithColorEffectsOnly)
10005 		{
10006 			if (!currItem->effectsInUse.useColorEffect())
10007 				continue;
10008 		}
10009 		bool fho = currItem->imageFlippedH();
10010 		bool fvo = currItem->imageFlippedV();
10011 		double imgX = currItem->imageXOffset();
10012 		double imgY = currItem->imageYOffset();
10013 		if (recalcFlags & RecalcPicRes_ApplyNewRes)
10014 			currItem->pixm.imgInfo.lowResType = m_docPrefsData.itemToolPrefs.imageLowResType;
10015 		if (currItem->isLatexFrame())
10016 			currItem->asLatexFrame()->rerunApplication(false);
10017 		else
10018 			loadPict(currItem->Pfile, currItem, true);
10019 		currItem->setImageFlippedH(fho);
10020 		currItem->setImageFlippedV(fvo);
10021 		currItem->setImageXOffset(imgX);
10022 		currItem->setImageYOffset(imgY);
10023 		currItem->adjustPictScale();
10024 		progress++;
10025 		m_ScMW->mainWindowProgressBar->setValue(progress);
10026 		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
10027 		if (!docPtr) return;
10028 	}
10029 
10030 	for (itemIt.begin(frameItemList); *itemIt; ++itemIt)
10031 	{
10032 		PageItem *currItem = *itemIt;
10033 		if (!currItem->imageIsAvailable)
10034 			continue;
10035 		if (recalcFlags & (RecalcPicRes_ImageWithEffectsOnly | RecalcPicRes_ImageWithColorEffectsOnly))
10036 		{
10037 			if (currItem->effectsInUse.count() <= 0)
10038 				continue;
10039 		}
10040 		if (recalcFlags & RecalcPicRes_ImageWithColorEffectsOnly)
10041 		{
10042 			if (!currItem->effectsInUse.useColorEffect())
10043 				continue;
10044 		}
10045 		bool fho = currItem->imageFlippedH();
10046 		bool fvo = currItem->imageFlippedV();
10047 		double imgX = currItem->imageXOffset();
10048 		double imgY = currItem->imageYOffset();
10049 		if (recalcFlags & RecalcPicRes_ApplyNewRes)
10050 			currItem->pixm.imgInfo.lowResType = m_docPrefsData.itemToolPrefs.imageLowResType;
10051 		if (currItem->isLatexFrame())
10052 			currItem->asLatexFrame()->rerunApplication(false);
10053 		else
10054 			loadPict(currItem->Pfile, currItem, true);
10055 		currItem->setImageFlippedH(fho);
10056 		currItem->setImageFlippedV(fvo);
10057 		currItem->setImageXOffset(imgX);
10058 		currItem->setImageYOffset(imgY);
10059 		currItem->adjustPictScale();
10060 		progress++;
10061 		m_ScMW->mainWindowProgressBar->setValue(progress);
10062 		qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
10063 		if (!docPtr) return;
10064 	}
10065 
10066 	auto patternEnd = docPatterns.end();
10067 	for (auto patIt = docPatterns.begin(); patIt != patternEnd; ++patIt)
10068 	{
10069 		ScPattern& pa = patIt.value();
10070 		if (pa.items.count() <= 0)
10071 			continue;
10072 		for (itemIt.begin(pa.items); *itemIt; ++itemIt)
10073 		{
10074 			PageItem *currItem = *itemIt;
10075 			if (!currItem->imageIsAvailable)
10076 				continue;
10077 			if (recalcFlags & (RecalcPicRes_ImageWithEffectsOnly | RecalcPicRes_ImageWithColorEffectsOnly))
10078 			{
10079 				if (currItem->effectsInUse.count() <= 0)
10080 					continue;
10081 			}
10082 			if (recalcFlags & RecalcPicRes_ImageWithColorEffectsOnly)
10083 			{
10084 				if (!currItem->effectsInUse.useColorEffect())
10085 					continue;
10086 			}
10087 			bool fho = currItem->imageFlippedH();
10088 			bool fvo = currItem->imageFlippedV();
10089 			double imgX = currItem->imageXOffset();
10090 			double imgY = currItem->imageYOffset();
10091 			if (recalcFlags & RecalcPicRes_ApplyNewRes)
10092 				currItem->pixm.imgInfo.lowResType = m_docPrefsData.itemToolPrefs.imageLowResType;
10093 			if (currItem->isLatexFrame())
10094 				currItem->asLatexFrame()->rerunApplication(false);
10095 			else
10096 				loadPict(currItem->Pfile, currItem, true);
10097 			currItem->setImageFlippedH(fho);
10098 			currItem->setImageFlippedV(fvo);
10099 			currItem->setImageXOffset(imgX);
10100 			currItem->setImageYOffset(imgY);
10101 			currItem->adjustPictScale();
10102 			progress++;
10103 			m_ScMW->mainWindowProgressBar->setValue(progress);
10104 			qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
10105 			if (!docPtr) return;
10106 		}
10107 		PageItem *ite = pa.items.at(0);
10108 		double minx =  std::numeric_limits<double>::max();
10109 		double miny =  std::numeric_limits<double>::max();
10110 		double maxx = -std::numeric_limits<double>::max();
10111 		double maxy = -std::numeric_limits<double>::max();
10112 		double x1, x2, y1, y2;
10113 		ite->getVisualBoundingRect(&x1, &y1, &x2, &y2);
10114 		minx = qMin(minx, x1);
10115 		miny = qMin(miny, y1);
10116 		maxx = qMax(maxx, x2);
10117 		maxy = qMax(maxy, y2);
10118 		pa.pattern = ite->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
10119 	}
10120 	regionsChanged()->update(QRectF());
10121 	changed();
10122 	m_ScMW->mainWindowProgressBar->reset();
10123 }
10124 
previewQuality()10125 int ScribusDoc::previewQuality()
10126 {
10127 	return itemToolPrefs().imageLowResType;
10128 }
10129 
10130 
removePict(const QString & name)10131 void ScribusDoc::removePict(const QString& name)
10132 {
10133 	bool updated = false;
10134 	QList<PageItem*> allItems;
10135 
10136 	for (PageItemIterator it(this, PageItemIterator::IterateInDocNoPatterns); *it; ++it)
10137 	{
10138 		PageItem *currItem =*it;
10139 		if ((currItem->imageIsAvailable) && (currItem->Pfile == name))
10140 		{
10141 			currItem->imageIsAvailable = false;
10142 			currItem->pixm = ScImage();
10143 			updated = true;
10144 		}
10145 	}
10146 
10147 	auto patternEnd = docPatterns.end();
10148 	for (auto it = docPatterns.begin(); it != patternEnd; ++it)
10149 	{
10150 		ScPattern& pa = it.value();
10151 		if (pa.items.count() <= 0)
10152 			continue;
10153 		for (int o = 0; o < pa.items.count(); o++)
10154 		{
10155 			PageItem *currItem = pa.items.at(o);
10156 			if (currItem->isGroup())
10157 				allItems = currItem->getAllChildren();
10158 			else
10159 				allItems.append(currItem);
10160 			for (int ii = 0; ii < allItems.count(); ii++)
10161 			{
10162 				currItem = allItems.at(ii);
10163 				if ((currItem->imageIsAvailable) && (currItem->Pfile == name))
10164 				{
10165 					currItem->imageIsAvailable = false;
10166 					currItem->pixm = ScImage();
10167 					updated = true;
10168 				}
10169 			}
10170 			allItems.clear();
10171 		}
10172 		PageItem *ite = pa.items.at(0);
10173 		double minx =  std::numeric_limits<double>::max();
10174 		double miny =  std::numeric_limits<double>::max();
10175 		double maxx = -std::numeric_limits<double>::max();
10176 		double maxy = -std::numeric_limits<double>::max();
10177 		double x1, x2, y1, y2;
10178 		ite->getVisualBoundingRect(&x1, &y1, &x2, &y2);
10179 		minx = qMin(minx, x1);
10180 		miny = qMin(miny, y1);
10181 		maxx = qMax(maxx, x2);
10182 		maxy = qMax(maxy, y2);
10183 		pa.pattern = ite->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
10184 	}
10185 	if (updated)
10186 	{
10187 		regionsChanged()->update(QRectF());
10188 		changed();
10189 	}
10190 }
10191 
10192 
updatePic()10193 void ScribusDoc::updatePic()
10194 {
10195 	//TODO? Getting the pointer with m_Selection->itemAt(i) over and over again in the loop
10196 	// seems to be a waste of resources
10197 	uint docSelectionCount = m_Selection->count();
10198 	if (docSelectionCount <= 0)
10199 		return;
10200 
10201 	bool toUpdate = false;
10202 	for (uint i = 0; i < docSelectionCount; ++i)
10203 	{
10204 		PageItem* currItem = m_Selection->itemAt(i);
10205 		if (!currItem)
10206 			continue;
10207 		m_updateManager.setUpdatesDisabled();
10208 		if (currItem->isLatexFrame())
10209 		{
10210 			PageItem_LatexFrame *latexframe = currItem->asLatexFrame();
10211 			latexframe->rerunApplication();
10212 			toUpdate = true;
10213 		}
10214 		else if ((currItem->isImageFrame()) || (currItem->isOSGFrame()))
10215 		{
10216 			if (currItem->imageIsAvailable)
10217 			{
10218 				int fho = currItem->imageFlippedH();
10219 				int fvo = currItem->imageFlippedV();
10220 				double imgX = currItem->imageXOffset();
10221 				double imgY = currItem->imageYOffset();
10222 				loadPict(currItem->Pfile, currItem, true);
10223 				currItem->setImageFlippedH(fho);
10224 				currItem->setImageFlippedV(fvo);
10225 				currItem->setImageXOffset(imgX);
10226 				currItem->setImageYOffset(imgY);
10227 				toUpdate = true;
10228 			}
10229 		}
10230 		m_updateManager.setUpdatesEnabled();
10231 	}
10232 	if (toUpdate)
10233 		regionsChanged()->update(QRectF());
10234 }
10235 
removeLayer(int l,bool dl)10236 void ScribusDoc::removeLayer(int l, bool dl)
10237 {
10238 	//FIXME: stop using m_View
10239 	m_View->deselectItems();
10240 	Selection tmpSelection(this, false);
10241 	int newLayerID = 0;
10242 	// Find the new layer identifier
10243 	const ScLayer* lcurr = Layers.layerByID(l);
10244 	if (lcurr)
10245 	{
10246 		const ScLayer* lbelow = Layers.layerBelow(lcurr->Level);
10247 		if (lcurr == lbelow)
10248 		{
10249 			const ScLayer* labove = Layers.layerAbove(lcurr->Level);
10250 			if (labove)
10251 				newLayerID = labove->ID;
10252 		}
10253 		else if (lbelow)
10254 			newLayerID = lbelow->ID;
10255 	}
10256 	for (int b = 0; b < MasterItems.count(); ++b)
10257 	{
10258 		if (MasterItems.at(b)->m_layerID == l)
10259 		{
10260 			if (dl)
10261 			{
10262 				tmpSelection.addItem(MasterItems.at(b));
10263 				MasterItems.at(b)->setLocked(false);
10264 			}
10265 			else
10266 				MasterItems.at(b)->setLayer(newLayerID);
10267 		}
10268 	}
10269 	if (tmpSelection.count() != 0)
10270 		itemSelection_DeleteItem(&tmpSelection);
10271 	tmpSelection.clear();
10272 	for (int b = 0; b < DocItems.count(); ++b)
10273 	{
10274 		PageItem* currItem = DocItems.at(b);
10275 		if (currItem->m_layerID == l)
10276 		{
10277 			if (dl)
10278 			{
10279 				tmpSelection.addItem(currItem);
10280 				currItem->setLocked(false);
10281 			}
10282 			else
10283 				currItem->setLayer(newLayerID);
10284 		}
10285 	}
10286 	if (tmpSelection.count() != 0)
10287 		itemSelection_DeleteItem(&tmpSelection);
10288 	tmpSelection.clear();
10289 	//FIXME signal these
10290 	m_ScMW->rebuildLayersList();
10291 	m_ScMW->updateLayerMenu();
10292 	setActiveLayer(newLayerID);
10293 }
10294 
selectionChanged()10295 void ScribusDoc::selectionChanged()
10296 {
10297 	if (m_ScMW->isObjectSpecificUndo())
10298 	{
10299 		uint docSelectionCount = m_Selection->count();
10300 		if (docSelectionCount == 1)
10301 			m_undoManager->showObject(m_Selection->itemAt(0)->getUId());
10302 		else if (docSelectionCount == 0)
10303 			m_undoManager->showObject(m_currentPage->getUId());
10304 		else
10305 			m_undoManager->showObject(Um::NO_UNDO_STACK);
10306 	}
10307 }
10308 
10309 
itemSelection_ToggleLock()10310 void ScribusDoc::itemSelection_ToggleLock( )
10311 {
10312 	uint docSelectionCount=m_Selection->count();
10313 	if (docSelectionCount != 0)
10314 	{
10315 		UndoTransaction activeTransaction;
10316 		m_updateManager.setUpdatesDisabled();
10317 		if (UndoManager::undoEnabled() && docSelectionCount > 1)
10318 		{
10319 			if (m_Selection->itemAt(0)->locked())
10320 				activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::UnLock, nullptr, Um::IUnLock);
10321 			else
10322 				activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::Lock, nullptr, Um::ILock);
10323 		}
10324 		for (uint a = 0; a < docSelectionCount; ++a)
10325 		{
10326 			m_Selection->itemAt(a)->toggleLock();
10327 			m_Selection->itemAt(a)->update();
10328 		}
10329 		if (activeTransaction)
10330 			activeTransaction.commit();
10331 		m_updateManager.setUpdatesEnabled();
10332 		changed();
10333  		emit firstSelectedItemType(m_Selection->itemAt(0)->itemType());
10334 	}
10335 }
10336 
10337 
itemSelection_ToggleSizeLock()10338 void ScribusDoc::itemSelection_ToggleSizeLock( )
10339 {
10340 	int selectedItemCount = m_Selection->count();
10341 	if (selectedItemCount != 0)
10342 	{
10343 		UndoTransaction activeTransaction;
10344 		m_updateManager.setUpdatesDisabled();
10345 		if (UndoManager::undoEnabled() && selectedItemCount > 1)
10346 		{
10347 			if (m_Selection->itemAt(0)->sizeLocked())
10348 				activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::SizeUnLock, nullptr, Um::IUnLock);
10349 			else
10350 				activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::SizeLock, nullptr, Um::ILock);
10351 		}
10352 		for (int i = 0; i < selectedItemCount; ++i)
10353 		{
10354 			m_Selection->itemAt(i)->toggleSizeLock();
10355 			m_Selection->itemAt(i)->update();
10356 		}
10357 		if (activeTransaction)
10358 			activeTransaction.commit();
10359 		m_updateManager.setUpdatesEnabled();
10360 		changed();
10361  		emit firstSelectedItemType(m_Selection->itemAt(0)->itemType());
10362 	}
10363 }
10364 
10365 
itemSelection_ToggleImageShown()10366 void ScribusDoc::itemSelection_ToggleImageShown()
10367 {
10368 	if (m_Selection->count() != 0)
10369 	{
10370 		m_updateManager.setUpdatesDisabled();
10371 		for (int a = 0; a < m_Selection->count(); ++a)
10372 		{
10373 			PageItem_ImageFrame* imageItem = m_Selection->itemAt(a)->asImageFrame();
10374 			if (imageItem == nullptr)
10375 				continue;
10376 			imageItem->setImageVisible(!imageItem->imageVisible());
10377 			imageItem->update();
10378 		}
10379 		m_updateManager.setUpdatesEnabled();
10380 		changed();
10381 		//Return to normal mode if in edit mode. We should not allow dragging of
10382 		//an image in a frame if its not shown.
10383 		if (appMode == modeEdit)
10384 			m_ScMW->view->requestMode(modeNormal);
10385 	}
10386 }
10387 
10388 
itemSelection_TogglePrintEnabled()10389 void ScribusDoc::itemSelection_TogglePrintEnabled( )
10390 {
10391 	int docSelectionCount=m_Selection->count();
10392 	if (docSelectionCount == 0)
10393 		return;
10394 	UndoTransaction activeTransaction;
10395 	m_updateManager.setUpdatesDisabled();
10396 	if (docSelectionCount > 1 && UndoManager::undoEnabled())
10397 	{
10398 		if (m_Selection->itemAt(0)->printEnabled())
10399 			activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::DisablePrint, nullptr, Um::IDisablePrint);
10400 		else
10401 			activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::EnablePrint, nullptr, Um::IEnablePrint);
10402 	}
10403 	for (int i = 0; i < docSelectionCount; ++i)
10404 	{
10405 		m_Selection->itemAt(i)->togglePrintEnabled();
10406 		m_Selection->itemAt(i)->update();
10407 	}
10408 	if (activeTransaction)
10409 		activeTransaction.commit();
10410 	m_updateManager.setUpdatesEnabled();
10411 	changed();
10412 	emit firstSelectedItemType(m_Selection->itemAt(0)->itemType());
10413 }
10414 
itemSelection_Transform(int nrOfCopies,const QTransform & matrix,int basepoint)10415 void ScribusDoc::itemSelection_Transform(int nrOfCopies, const QTransform& matrix, int basepoint)
10416 {
10417 	int docSelectionCount=m_Selection->count();
10418 	if (docSelectionCount == 0)
10419 		return;
10420 	m_updateManager.setUpdatesDisabled();
10421 	if (nrOfCopies == 0)
10422 	{
10423 		double gx, gy, gh, gw;
10424 		PageItem *currItem = m_Selection->itemAt(0);
10425 		if (m_Selection->count() == 1)
10426 		{
10427 			gx = currItem->xPos();
10428 			gy = currItem->yPos();
10429 			gw = currItem->width();
10430 			gh = currItem->height();
10431 		}
10432 		else
10433 			m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
10434 		for (int a = 0; a < m_Selection->count(); ++a)
10435 		{
10436 			PageItem *currItem = m_Selection->itemAt(a);
10437 			double deltaX = currItem->xPos() - gx;
10438 			double deltaY = currItem->yPos() - gy;
10439 			QTransform matrixPre = QTransform();
10440 			QTransform matrixAft = QTransform();
10441 			switch (basepoint)
10442 			{
10443 			case 2:
10444 				matrixPre.translate(-gw/2.0, -gh/2.0);
10445 				matrixAft.translate(gw/2.0, gh/2.0);
10446 				break;
10447 			case 4:
10448 				matrixPre.translate(-gw, -gh);
10449 				matrixAft.translate(gw, gh);
10450 				break;
10451 			case 3:
10452 				matrixPre.translate(0, -gh);
10453 				matrixAft.translate(0, gh);
10454 				break;
10455 			case 1:
10456 				matrixPre.translate(-gw, 0);
10457 				matrixAft.translate(gw, 0);
10458 				break;
10459 			}
10460 			if (UndoManager::undoEnabled())
10461 			{
10462 				ScItemState<QList<QTransform> > *state = new ScItemState<QList<QTransform> >(Um::Transform);
10463 				state->set("TRANSFORM");
10464 				state->set("DX",deltaX);
10465 				state->set("DY",deltaY);
10466 				state->set("POSX",currItem->xPos());
10467 				state->set("POSY",currItem->yPos());
10468 				QList<QTransform> l;
10469 				l.append(matrixPre);
10470 				l.append(matrix);
10471 				l.append(matrixAft);
10472 				state->setItem(l);
10473 				m_undoManager->action(currItem, state);
10474 			}
10475 
10476 			currItem->PoLine.translate(deltaX, deltaY);
10477 			currItem->PoLine.map(matrixPre);
10478 			currItem->PoLine.map(matrix);
10479 			currItem->PoLine.map(matrixAft);
10480 			currItem->PoLine.translate(-deltaX, -deltaY);
10481 			currItem->ContourLine.translate(deltaX, deltaY);
10482 			currItem->ContourLine.map(matrixPre);
10483 			currItem->ContourLine.map(matrix);
10484 			currItem->ContourLine.map(matrixAft);
10485 			currItem->ContourLine.translate(-deltaX, -deltaY);
10486 //			currItem->Frame = false;
10487 			currItem->ClipEdited = true;
10488 //			currItem->FrameType = 3;
10489 			m_undoManager->setUndoEnabled(false);
10490 			adjustItemSize(currItem);
10491 			m_undoManager->setUndoEnabled(true);
10492 		}
10493 	}
10494 	else
10495 	{
10496 		QList<PageItem*> Elements;
10497 		bool savedAlignGrid = SnapGrid;
10498 		bool savedAlignGuides = SnapGuides;
10499 		bool savedAlignElement = SnapElement;
10500 		SnapGrid  = false;
10501 		SnapGuides = false;
10502 		SnapElement = false;
10503 		DoDrawing = false;
10504 		view()->updatesOn(false);
10505 		m_Selection->delaySignalsOn();
10506 		QTransform comulatedMatrix = matrix;
10507 		PageItem *currItem = m_Selection->itemAt(0);
10508 		Elements.append(currItem);
10509 		int rotBack = rotationMode();
10510 		setRotationMode ( 0 );
10511 		ScriXmlDoc xmlDoc;
10512 		QString copyBuffer = xmlDoc.writeElem(this, m_Selection);
10513 		view()->deselectItems(true);
10514 		for (int b = 0; b < nrOfCopies; b++)
10515 		{
10516 			uint ac = Items->count();
10517 			xmlDoc.readElem(copyBuffer, this, m_currentPage->xOffset(), m_currentPage->yOffset(), false, true);
10518 			for (int as = ac; as < Items->count(); ++as)
10519 			{
10520 				PageItem* bItem = Items->at(as);
10521 				m_Selection->addItem(bItem);
10522 			}
10523 			double gx, gy, gh, gw;
10524 			currItem = m_Selection->itemAt(0);
10525 			if (m_Selection->count() == 1)
10526 			{
10527 				gx = currItem->xPos();
10528 				gy = currItem->yPos();
10529 				gw = currItem->width();
10530 				gh = currItem->height();
10531 			}
10532 			else
10533 				m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
10534 			for (int a = 0; a < m_Selection->count(); ++a)
10535 			{
10536 				currItem = m_Selection->itemAt(a);
10537 				double deltaX = currItem->xPos() - gx;
10538 				double deltaY = currItem->yPos() - gy;
10539 				QTransform matrixPre = QTransform();
10540 				QTransform matrixAft = QTransform();
10541 				switch (basepoint)
10542 				{
10543 				case 2:
10544 					matrixPre.translate(-gw/2.0, -gh/2.0);
10545 					matrixAft.translate(gw/2.0, gh/2.0);
10546 					break;
10547 				case 4:
10548 					matrixPre.translate(-gw, -gh);
10549 					matrixAft.translate(gw, gh);
10550 					break;
10551 				case 3:
10552 					matrixPre.translate(0, -gh);
10553 					matrixAft.translate(0, gh);
10554 					break;
10555 				case 1:
10556 					matrixPre.translate(-gw, 0);
10557 					matrixAft.translate(gw, 0);
10558 					break;
10559 				}
10560 
10561 				if (UndoManager::undoEnabled())
10562 				{
10563 					ScItemState<QList<QTransform> > *state = new ScItemState<QList<QTransform> >(Um::Transform);
10564 					state->set("TRANSFORM");
10565 					state->set("DX",deltaX);
10566 					state->set("DY",deltaY);
10567 					state->set("POSX",currItem->xPos());
10568 					state->set("POSY",currItem->yPos());
10569 					QList<QTransform> l;
10570 					l.append(matrixPre);
10571 					l.append(matrix);
10572 					l.append(matrixAft);
10573 					state->setItem(l);
10574 					m_undoManager->action(currItem, state);
10575 				}
10576 				currItem->PoLine.translate(deltaX, deltaY);
10577 				currItem->PoLine.map(matrixPre);
10578 				currItem->PoLine.map(comulatedMatrix);
10579 				currItem->PoLine.map(matrixAft);
10580 				currItem->PoLine.translate(-deltaX, -deltaY);
10581 				currItem->ContourLine.translate(deltaX, deltaY);
10582 				currItem->ContourLine.map(matrixPre);
10583 				currItem->ContourLine.map(comulatedMatrix);
10584 				currItem->ContourLine.map(matrixAft);
10585 				currItem->ContourLine.translate(-deltaX, -deltaY);
10586 				currItem->ClipEdited = true;
10587 				m_undoManager->setUndoEnabled(false);
10588 				adjustItemSize(currItem);
10589 				m_undoManager->setUndoEnabled(true);
10590 				Elements.append(currItem);
10591 			}
10592 			comulatedMatrix *= matrix;
10593 			m_Selection->clear();
10594 		}
10595 		for (int c = 0; c < Elements.count(); ++c)
10596 		{
10597 			m_Selection->addItem(Elements.at(c), true);
10598 		}
10599 		m_Selection->setGroupRect();
10600 		setRotationMode (rotBack);
10601 		SnapGrid  = savedAlignGrid;
10602 		SnapGuides = savedAlignGuides;
10603 		SnapElement = savedAlignElement;
10604 		DoDrawing = true;
10605 		m_Selection->delaySignalsOff();
10606 		view()->updatesOn(true);
10607 		m_Selection->connectItemToGUI();
10608 	}
10609 	m_updateManager.setUpdatesEnabled();
10610 	regionsChanged()->update(QRectF());
10611 	changed();
10612 }
10613 
10614 
itemSelection_FlipH(Selection * customSelection)10615 void ScribusDoc::itemSelection_FlipH(Selection* customSelection)
10616 {
10617 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
10618 	if (itemSelection->isEmpty())
10619 		return;
10620 	int docSelectionCount = itemSelection->count();
10621 
10622 	UndoTransaction trans;
10623 	if (UndoManager::undoEnabled())
10624 		trans = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::FlipH, nullptr, Um::IFlipH);
10625 	if (docSelectionCount > 1)
10626 	{
10627 		double gx, gy, gh, gw, ix, iy, iw, ih;
10628 		itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
10629 		for (int i = 0; i < docSelectionCount; ++i)
10630 		{
10631 			PageItem* currItem = itemSelection->itemAt(i);
10632 			currItem->getBoundingRect(&ix, &iy, &iw, &ih);
10633 			double dx =  ((gw / 2.0) -  ((ix - gx) + (iw - ix) / 2.0)) * 2.0;
10634 			if (currItem->rotation() != 0.0)
10635 			{
10636 				double ix2, iy2, iw2, ih2;
10637 				double newRotation = -currItem->rotation();
10638 				if (currItem->itemType() == PageItem::Line)
10639 					newRotation = 180 - currItem->rotation();
10640 				while (newRotation < 0)
10641 					newRotation += 360.0;
10642 				while (newRotation >= 360.0)
10643 					newRotation -= 360.0;
10644 				currItem->setRotation(newRotation);
10645 				currItem->setRedrawBounding();
10646 				currItem->getBoundingRect(&ix2, &iy2, &iw2, &ih2);
10647 				currItem->moveBy(ix - ix2, iy - iy2, false);
10648 				currItem->setRedrawBounding();
10649 			}
10650 			if (currItem->isImageFrame() || currItem->isTextFrame() || currItem->isLatexFrame() || currItem->isOSGFrame() || currItem->isSymbol() || currItem->isGroup() || currItem->isSpiral())
10651 				currItem->flipImageH();
10652 			if (currItem->itemType() != PageItem::Line)
10653 				MirrorPolyH(currItem);
10654 			currItem->moveBy(dx, 0, false);
10655 			currItem->GrStartX = currItem->width() - currItem->GrStartX;
10656 			currItem->GrEndX = currItem->width() - currItem->GrEndX;
10657 			if (currItem->isArc())
10658 			{
10659 				PageItem_Arc *ar = currItem->asArc();
10660 				ar->arcStartAngle = (180 - ar->arcStartAngle) - ar->arcSweepAngle;
10661 				if (ar->arcStartAngle < 0)
10662 					ar->arcStartAngle += 360;
10663 				else if (ar->arcStartAngle > 360)
10664 					ar->arcStartAngle -= 360;
10665 				ar->recalcPath();
10666 				adjustItemSize(currItem);
10667 				emit updateEditItem();
10668 			}
10669 			else if (currItem->isRegularPolygon())
10670 			{
10671 				PageItem_RegularPolygon *ar = currItem->asRegularPolygon();
10672 				ar->polyRotation *= -1;
10673 				ar->polyInnerRot *= -1;
10674 				ar->recalcPath();
10675 				emit updateEditItem();
10676 			}
10677 			else if (currItem->isSpiral())
10678 				emit updateEditItem();
10679 			currItem->setRedrawBounding();
10680 		}
10681 	}
10682 	else
10683 	{
10684 		PageItem* currItem = itemSelection->itemAt(0);
10685 		if (currItem->isImageFrame() || currItem->isTextFrame() || currItem->isLatexFrame() || currItem->isOSGFrame() || currItem->isSymbol() || currItem->isGroup() || currItem->isSpiral())
10686 			currItem->flipImageH();
10687 		if (currItem->itemType() != PageItem::Line)
10688 			MirrorPolyH(currItem);
10689 		else
10690 		{
10691 			double ix2, iy2, iw2, ih2, ix, iy, iw, ih;
10692 			currItem->getBoundingRect(&ix, &iy, &iw, &ih);
10693 			double newRotation = 180 - currItem->rotation();
10694 			while (newRotation < 0)
10695 				newRotation += 360.0;
10696 			while (newRotation >= 360.0)
10697 				newRotation -= 360.0;
10698 			currItem->setRotation(newRotation);
10699 			currItem->setRedrawBounding();
10700 			currItem->getBoundingRect(&ix2, &iy2, &iw2, &ih2);
10701 			currItem->moveBy(ix - ix2, iy - iy2, false);
10702 			currItem->setRedrawBounding();
10703 		}
10704 		currItem->GrStartX = currItem->width() - currItem->GrStartX;
10705 		currItem->GrEndX = currItem->width() - currItem->GrEndX;
10706 		if (currItem->isArc())
10707 		{
10708 			PageItem_Arc *ar = currItem->asArc();
10709 			ar->arcStartAngle = (180 - ar->arcStartAngle) - ar->arcSweepAngle;
10710 			if (ar->arcStartAngle < 0)
10711 				ar->arcStartAngle += 360;
10712 			else if (ar->arcStartAngle > 360)
10713 				ar->arcStartAngle -= 360;
10714 			ar->recalcPath();
10715 			adjustItemSize(currItem);
10716 			emit updateEditItem();
10717 		}
10718 		else if (currItem->isRegularPolygon())
10719 		{
10720 			PageItem_RegularPolygon *ar = currItem->asRegularPolygon();
10721 			ar->polyRotation *= -1;
10722 			ar->polyInnerRot *= -1;
10723 			ar->recalcPath();
10724 			emit updateEditItem();
10725 		}
10726 		else if (currItem->isSpiral())
10727 			emit updateEditItem();
10728 	}
10729 	if (trans)
10730 		trans.commit();
10731 	regionsChanged()->update(QRectF());
10732 	changed();
10733 	emit firstSelectedItemType(itemSelection->itemAt(0)->itemType());
10734 }
10735 
10736 
itemSelection_FlipV(Selection * customSelection)10737 void ScribusDoc::itemSelection_FlipV(Selection* customSelection)
10738 {
10739 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
10740 	if (itemSelection->isEmpty())
10741 		return;
10742 	int docSelectionCount = itemSelection->count();
10743 
10744 	UndoTransaction trans;
10745 	if (UndoManager::undoEnabled())
10746 		trans = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::FlipV, nullptr, Um::IFlipV);
10747 	if (docSelectionCount > 1)
10748 	{
10749 		double gx, gy, gh, gw, ix, iy, iw, ih;
10750 		itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
10751 		for (int i = 0; i < docSelectionCount; ++i)
10752 		{
10753 			PageItem* currItem = itemSelection->itemAt(i);
10754 			currItem->getBoundingRect(&ix, &iy, &iw, &ih);
10755 			double dx =  ((gh / 2.0) -  ((iy - gy) + (ih - iy) / 2.0)) * 2.0;
10756 			if (currItem->rotation() != 0.0)
10757 			{
10758 				double ix2, iy2, iw2, ih2;
10759 				currItem->rotateBy(currItem->rotation() * -2.0);
10760 				currItem->setRedrawBounding();
10761 				currItem->getBoundingRect(&ix2, &iy2, &iw2, &ih2);
10762 				currItem->moveBy(ix-ix2, iy-iy2, false);
10763 				currItem->setRedrawBounding();
10764 			}
10765 			if (currItem->isImageFrame() || currItem->isTextFrame() || currItem->isLatexFrame() || currItem->isOSGFrame() || currItem->isSymbol() || currItem->isGroup() || currItem->isSpiral())
10766 				currItem->flipImageV();
10767 			if (currItem->itemType() != PageItem::Line)
10768 				MirrorPolyV(currItem);
10769 			currItem->moveBy(0, dx, false);
10770 			currItem->GrStartY = currItem->height() - currItem->GrStartY;
10771 			currItem->GrEndY = currItem->height() - currItem->GrEndY;
10772 			if (currItem->isArc())
10773 			{
10774 				PageItem_Arc *ar = currItem->asArc();
10775 				ar->arcStartAngle *= -1;
10776 				ar->arcStartAngle -= ar->arcSweepAngle;
10777 				if (ar->arcStartAngle < 0)
10778 					ar->arcStartAngle += 360;
10779 				else if (ar->arcStartAngle > 360)
10780 					ar->arcStartAngle -= 360;
10781 				ar->recalcPath();
10782 				adjustItemSize(currItem);
10783 				emit updateEditItem();
10784 			}
10785 			else if (currItem->isRegularPolygon())
10786 			{
10787 				PageItem_RegularPolygon *ar = currItem->asRegularPolygon();
10788 				ar->polyRotation = 180.0 - ar->polyRotation;
10789 				ar->polyRotation *= -1;
10790 				ar->polyInnerRot *= -1;
10791 				ar->recalcPath();
10792 				emit updateEditItem();
10793 			}
10794 			else if (currItem->isSpiral())
10795 				emit updateEditItem();
10796 			currItem->setRedrawBounding();
10797 		}
10798 		regionsChanged()->update(QRectF());
10799 	}
10800 	else
10801 	{
10802 		PageItem* currItem = itemSelection->itemAt(0);
10803 		if (currItem->isImageFrame() || currItem->isTextFrame() || currItem->isLatexFrame() || currItem->isOSGFrame() || currItem->isSymbol() || currItem->isGroup() || currItem->isSpiral())
10804 			currItem->flipImageV();
10805 		if (currItem->itemType() != PageItem::Line)
10806 			MirrorPolyV(currItem);
10807 		else
10808 		{
10809 			double ix2, iy2, iw2, ih2, ix, iy, iw, ih;
10810 			currItem->getBoundingRect(&ix, &iy, &iw, &ih);
10811 			currItem->rotateBy(currItem->rotation() * -2.0);
10812 			currItem->setRedrawBounding();
10813 			currItem->getBoundingRect(&ix2, &iy2, &iw2, &ih2);
10814 			currItem->moveBy(ix-ix2, iy-iy2, false);
10815 			currItem->setRedrawBounding();
10816 		}
10817 		currItem->GrStartY = currItem->height() - currItem->GrStartY;
10818 		currItem->GrEndY = currItem->height() - currItem->GrEndY;
10819 		if (currItem->isArc())
10820 		{
10821 			PageItem_Arc *ar = currItem->asArc();
10822 			ar->arcStartAngle *= -1;
10823 			ar->arcStartAngle -= ar->arcSweepAngle;
10824 			if (ar->arcStartAngle < 0)
10825 				ar->arcStartAngle += 360;
10826 			else if (ar->arcStartAngle > 360)
10827 				ar->arcStartAngle -= 360;
10828 			ar->recalcPath();
10829 			adjustItemSize(currItem);
10830 			emit updateEditItem();
10831 		}
10832 		else if (currItem->isRegularPolygon())
10833 		{
10834 			PageItem_RegularPolygon *ar = currItem->asRegularPolygon();
10835 			ar->polyRotation = 180.0 - ar->polyRotation;
10836 			ar->polyRotation *= -1;
10837 			ar->polyInnerRot *= -1;
10838 			ar->recalcPath();
10839 			emit updateEditItem();
10840 		}
10841 		else if (currItem->isSpiral())
10842 			emit updateEditItem();
10843 		regionsChanged()->update(QRectF());
10844 	}
10845 	if (trans)
10846 		trans.commit();
10847 	changed();
10848 	emit firstSelectedItemType(m_Selection->itemAt(0)->itemType());
10849 }
10850 
itemSelection_Rotate(double angle,Selection * customSelection)10851 void ScribusDoc::itemSelection_Rotate(double angle, Selection* customSelection)
10852 {
10853 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
10854 	assert(itemSelection != nullptr);
10855 
10856 	if (itemSelection->isEmpty())
10857 		return;
10858 
10859 	if (itemSelection->count() > 1)
10860 		rotateGroup(angle, itemSelection);
10861 	else if (itemSelection->count() == 1)
10862 		rotateItem(angle, itemSelection->itemAt(0));
10863 	changed();
10864 }
10865 
itemSelection_ChangePreviewResolution(int id)10866 void ScribusDoc::itemSelection_ChangePreviewResolution(int id)
10867 {
10868 	int selectedItemCount = m_Selection->count();
10869 	if (selectedItemCount == 0)
10870 		return;
10871 	UndoTransaction activeTransaction;
10872 	if (UndoManager::undoEnabled())
10873 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IGroup,Um::ResTyp, "", Um::IImageFrame);
10874 	PageItem *currItem;
10875 	bool found=false;
10876 	for (int i = 0; i < selectedItemCount; ++i)
10877 	{
10878 		currItem = m_Selection->itemAt(i);
10879 		if (!currItem || !currItem->isImageFrame())
10880 			continue;
10881 		currItem->setResolution(id);
10882 		found = true;
10883 	}
10884 	if (activeTransaction)
10885 		activeTransaction.commit();
10886 	if (!found) //No image frames in the current selection!
10887 		return;
10888 	updatePic();
10889 }
10890 
allItems_ChangePreviewResolution(int id)10891 void ScribusDoc::allItems_ChangePreviewResolution(int id)
10892 {
10893 	bool found=false;
10894 	QList<PageItem*> allItems;
10895 	for (int c=0; c<DocItems.count(); ++c)
10896 	{
10897 		PageItem *currItem = DocItems.at(c);
10898 		if (currItem->isGroup())
10899 			allItems = currItem->getAllChildren();
10900 		else
10901 			allItems.append(currItem);
10902 		for (int ii = 0; ii < allItems.count(); ii++)
10903 		{
10904 			currItem = allItems.at(ii);
10905 			if (currItem != nullptr)
10906 			{
10907 				if (currItem->isImageFrame())
10908 				{
10909 					currItem->pixm.imgInfo.lowResType = id;
10910 					if (!found)
10911 						found=true;
10912 				}
10913 			}
10914 		}
10915 		allItems.clear();
10916 	}
10917 	for (int c=0; c<MasterItems.count(); ++c)
10918 	{
10919 		PageItem *currItem = MasterItems.at(c);
10920 		if (currItem->isGroup())
10921 			allItems = currItem->getAllChildren();
10922 		else
10923 			allItems.append(currItem);
10924 		for (int ii = 0; ii < allItems.count(); ii++)
10925 		{
10926 			currItem = allItems.at(ii);
10927 			if (currItem != nullptr)
10928 			{
10929 				if (currItem->isImageFrame())
10930 				{
10931 					currItem->pixm.imgInfo.lowResType = id;
10932 					if (!found)
10933 						found=true;
10934 				}
10935 			}
10936 		}
10937 		allItems.clear();
10938 	}
10939 	for (auto it = FrameItems.begin(); it != FrameItems.end(); ++it)
10940 	{
10941 		PageItem *currItem = it.value();
10942 		if (currItem->isGroup())
10943 			allItems = currItem->getAllChildren();
10944 		else
10945 			allItems.append(currItem);
10946 		for (int ii = 0; ii < allItems.count(); ii++)
10947 		{
10948 			currItem = allItems.at(ii);
10949 			if (currItem != nullptr)
10950 			{
10951 				if (currItem->isImageFrame())
10952 				{
10953 					currItem->pixm.imgInfo.lowResType = id;
10954 					if (!found)
10955 						found=true;
10956 				}
10957 			}
10958 		}
10959 		allItems.clear();
10960 	}
10961 
10962 	if (!found) //No image frames in the current selection!
10963 		return;
10964 	recalcPicturesRes();
10965 	changed();
10966 }
10967 
item_setFrameShape(PageItem * item,int frameType,int count,double * points)10968 void ScribusDoc::item_setFrameShape(PageItem* item, int frameType, int count, double* points)
10969 {
10970 	if ((item->itemType() == PageItem::PolyLine) || (item->itemType() == PageItem::PathText))
10971 			return;
10972 	UndoTransaction activeTransaction;
10973 	if (UndoManager::undoEnabled())
10974 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IImageFrame, Um::ChangeShapeType, QString(), Um::IBorder);
10975 
10976 	if (frameType != 0)
10977 		item->setCornerRadius(0);
10978 	if (UndoManager::undoEnabled())
10979 	{
10980 		// Store shape info in this form:
10981 		// CHANGE_SHAPE_TYPE - ID of the undo operation
10982 		// OLD_FRAME_TYPE - original frame type
10983 		// NEW_FRAME_TYPE - change of frame type
10984 		// binary QPair<FPointArray, FPointArray> - .first original shape, .second new shape
10985 		ScItemState<QPair<FPointArray, FPointArray> >* is = new ScItemState<QPair<FPointArray,FPointArray> >(Um::ChangeShapeType, "", Um::IBorder);
10986 		is->set("CHANGE_SHAPE_TYPE");
10987 		is->set("OLD_FRAME_TYPE", item->FrameType);
10988 		is->set("NEW_FRAME_TYPE", frameType);
10989 		// HACK: this is propably Evil Code (TM). I have to find better way...
10990 		FPointArray newShape;
10991 		int ix = 0;
10992 		for (int i = 0; i < count/2; ++i)
10993 		{
10994 			double x = item->width()  * points[ix] / 100.0;
10995 			double y = item->height() * points[ix+1] / 100.0;
10996 			newShape.addPoint(x, y);
10997 			ix += 2;
10998 		}
10999 		// HACK: end of hack
11000 		is->setItem(qMakePair(item->shape(), newShape));
11001 		UndoManager::instance()->action(item, is);
11002 	}
11003 
11004 	switch (frameType)
11005 	{
11006 		case 0:
11007 			item->SetRectFrame();
11008 			this->setRedrawBounding(item);
11009 			break;
11010 		case 1:
11011 			item->SetOvalFrame();
11012 			this->setRedrawBounding(item);
11013 			break;
11014 		default:
11015 			item->SetFrameShape(count, points);
11016 			if (item->isSymbol() || item->isGroup())
11017 			{
11018 				if (item->imageFlippedH())
11019 				{
11020 					QTransform ma;
11021 					ma.scale(-1, 1);
11022 					item->PoLine.map(ma);
11023 					item->PoLine.translate(item->width(), 0);
11024 				}
11025 				if (item->imageFlippedV())
11026 				{
11027 					QTransform ma;
11028 					ma.scale(1, -1);
11029 					item->PoLine.map(ma);
11030 					item->PoLine.translate(0, item->height());
11031 				}
11032 			}
11033 			this->setRedrawBounding(item);
11034 			item->FrameType = frameType + 2;
11035 			break;
11036 	}
11037 	item->update();
11038 	changed();
11039 	if (activeTransaction)
11040 		activeTransaction.commit();
11041 }
11042 
itemSelection_ClearItem(Selection * customSelection,bool useWarning)11043 void ScribusDoc::itemSelection_ClearItem(Selection* customSelection, bool useWarning)
11044 {
11045 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11046 	assert(itemSelection != nullptr);
11047 
11048 	int selectedItemCount = itemSelection->count();
11049 	if (selectedItemCount <= 0)
11050 		return;
11051 	if (ScCore->usingGUI() && useWarning)
11052 	{
11053 		int t = ScMessageBox::warning(m_ScMW, CommonStrings::trWarning, tr("Do you really want to clear the content of all selected frames?"),
11054 							QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
11055 							QMessageBox::No,	// GUI default
11056 							QMessageBox::Yes);	// batch default
11057 		if (t == QMessageBox::No)
11058 			return;
11059 	}
11060 	for (int i = 0; i < selectedItemCount; ++i)
11061 	{
11062 		PageItem *currItem = itemSelection->itemAt(i);
11063 		if (currItem->isImageFrame())
11064 		{
11065 			if (ScCore->fileWatcher->isWatching(currItem->Pfile) && currItem->imageIsAvailable)
11066 				ScCore->fileWatcher->removeFile(currItem->Pfile);
11067 		}
11068 		currItem->clearContents();
11069 	}
11070 	regionsChanged()->update(QRectF());
11071 	changed();
11072 }
11073 
itemSelection_TruncateItem(Selection * customSelection)11074 void ScribusDoc::itemSelection_TruncateItem(Selection* customSelection)
11075 {
11076 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11077 	assert(itemSelection != nullptr);
11078 
11079 	int selectedItemCount = itemSelection->count();
11080 	if (selectedItemCount <= 0)
11081 		return;
11082 
11083 	UndoTransaction undoTransaction;
11084 	if (UndoManager::undoEnabled() && (selectedItemCount > 1))
11085 		undoTransaction = UndoManager::instance()->beginTransaction(Um::Selection, Um::IGroup, Um::TruncateText);
11086 
11087 	for (int i = 0; i < selectedItemCount; ++i)
11088 	{
11089 		PageItem *currItem = itemSelection->itemAt(i);
11090 		currItem->truncateContents();
11091 	}
11092 
11093 	if (undoTransaction)
11094 		undoTransaction.commit();
11095 
11096 	regionsChanged()->update(QRectF());
11097 	changed();
11098 }
11099 
groupOfItem(QList<PageItem * > * itemList,PageItem * item)11100 QList<PageItem*>* ScribusDoc::groupOfItem(QList<PageItem*>* itemList, PageItem* item)
11101 {
11102 	if (itemList->contains(item))
11103 		return itemList;
11104 	for (int i = 0; i < itemList->count(); i++)
11105 	{
11106 		if (itemList->at(i)->isGroup())
11107 		{
11108 			QList<PageItem*>* ite = groupOfItem(&itemList->at(i)->groupItemList, item);
11109 			if (ite != nullptr)
11110 				return ite;
11111 		}
11112 	}
11113 	return nullptr;
11114 }
11115 
itemSelection_DeleteItem(Selection * customSelection,bool forceDeletion)11116 void ScribusDoc::itemSelection_DeleteItem(Selection* customSelection, bool forceDeletion)
11117 {
11118 	if (appMode == modeEditClip)
11119 		return;
11120 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11121 	assert(itemSelection != nullptr);
11122 	int selectedItemCount = itemSelection->count();
11123 	if (selectedItemCount == 0)
11124 		return;
11125 	QList<PageItem*> delItems;
11126 	QList<PageItem*> textInteractionItems;// text frames possibly interested in removal of selected items
11127 	PageItem *currItem;
11128 	QList<PageItem*>* itemList = Items;
11129 	uint offs = 0;
11130 	QString tooltip = Um::ItemsInvolved + "\n";
11131 	if (selectedItemCount > Um::ItemsInvolvedLimit)
11132 		tooltip = Um::ItemsInvolved2 + "\n";
11133 	itemSelection->delaySignalsOn();
11134 	for (int de = 0; de < selectedItemCount; ++de)
11135 	{
11136 		currItem = itemSelection->itemAt(offs);
11137 		if (((currItem->isSingleSel) && (!Items->contains(currItem))) || (currItem->locked()))
11138 		{
11139 			if (currItem->locked())
11140 			{
11141 				offs++;
11142 				continue;
11143 			}
11144 		}
11145 		//#12371 don't delete group items
11146 		if(currItem->isGroupChild())
11147 			continue;
11148 		//CB FIXME remove this and include of storyeditor.h too
11149 		if ((currItem->isTextFrame() || currItem->isPathText()) && currItem==m_ScMW->storyEditor->currentItem() && this==m_ScMW->storyEditor->currentDocument())
11150 		{
11151 			if (forceDeletion)
11152 				m_ScMW->storyEditor->setCurrentDocumentAndItem(this, nullptr);
11153 			else
11154 			{
11155 				ScMessageBox::critical(m_ScMW, tr("Cannot Delete In-Use Item"), tr("The item %1 is currently being edited by Story Editor. The delete operation will be cancelled").arg(currItem->itemName()));
11156 				itemSelection->delaySignalsOff();
11157 				return;
11158 			}
11159 		}
11160 		if (currItem->textFlowMode() != PageItem::TextFlowDisabled)
11161 		{
11162 			int id = Items->indexOf(currItem) - 1;
11163 			for (int tIdx = id; tIdx >= 0; --tIdx)
11164 			{
11165 				if ( (Items->at(tIdx)->isTextFrame())
11166 					&& (!itemSelection->containsItem(Items->at(tIdx)))
11167 					&& (currItem->getBoundingRect().intersects(Items->at(tIdx)->getBoundingRect()))
11168 					&& (!textInteractionItems.contains(Items->at(tIdx))) )
11169 				{
11170 					textInteractionItems.append( Items->at(tIdx) );
11171 				}
11172 			}
11173 		}
11174 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
11175 			tooltip += "\t" + currItem->getUName() + "\n";
11176 		delItems.append(itemSelection->takeItem(offs));
11177 	}
11178 	if (delItems.count() == 0)
11179 	{
11180 		itemSelection->delaySignalsOff();
11181 		return;
11182 	}
11183 
11184 	UndoTransaction activeTransaction;
11185 	if (UndoManager::undoEnabled()) //always create transaction or check if item is reference for any mark or contains any mark or is welded etc
11186 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup,
11187 														  Um::Delete, tooltip, Um::IDelete);
11188 
11189 	selectedItemCount = delItems.count();
11190 	for (int de = 0; de < selectedItemCount; ++de)
11191 	{
11192 		currItem = delItems.at(selectedItemCount - (de + 1));
11193 		itemList = groupOfItem(Items, currItem);
11194 		if (itemList == nullptr)
11195 			continue;
11196 		if (currItem->isImageFrame() && ScCore->fileWatcher->isWatching(currItem->Pfile) && currItem->imageIsAvailable)
11197 			ScCore->fileWatcher->removeFile(currItem->Pfile);
11198 		//delete marks pointed to that item
11199 		for (int a=0; a < m_docMarksList.count(); a++)
11200 		{
11201 			Mark* m = m_docMarksList.at(a);
11202 			Q_ASSERT(m != nullptr);
11203 			if (m->isType(MARK2ItemType) && (m->getItemPtr() == currItem))
11204 			{
11205 				setUndoDelMark(m);
11206 				eraseMark(m, true, nullptr, true);
11207 			}
11208 		}
11209 		if (currItem->isNoteFrame())
11210 		{
11211 			if (currItem->itemText.length() >0)
11212 			{
11213 				currItem->itemText.selectAll();
11214 				currItem->asTextFrame()->deleteSelectedTextFromFrame();
11215 				if (currItem->asNoteFrame()->masterFrame())
11216 					currItem->asNoteFrame()->masterFrame()->invalid = true;
11217 			}
11218 			if (!UndoManager::undoEnabled() || forceDeletion || currItem->isAutoNoteFrame())
11219 			{
11220 				itemList->removeAll(currItem);
11221 				delNoteFrame(currItem->asNoteFrame(), false, false);
11222 				continue;
11223 			}
11224 		}
11225 		else
11226 		{
11227 			if (currItem->isTextFrame() && !currItem->isInChain())
11228 			{
11229 				currItem->itemText.selectAll();
11230 				currItem->asTextFrame()->removeMarksFromText(true);
11231 				currItem->asTextFrame()->delAllNoteFrames(false);
11232 				currItem->itemText.deselectAll();
11233 			}
11234 			if (currItem->isTextFrame())
11235 				currItem->dropLinks();
11236 		}
11237 		if (currItem->isWelded())
11238 			currItem->unWeld();
11239 		if (currItem->isBookmark)
11240 			//CB From view   emit DelBM(currItem);
11241 			m_ScMW->DelBookMark(currItem);
11242 		if (UndoManager::undoEnabled() && (selectedItemCount > 0) && !forceDeletion)
11243 		{
11244 			ScItemState< QList<PageItem*> > *is = new ScItemState< QList<PageItem*> >(Um::Delete + " " + currItem->getUName(), "", Um::IDelete);
11245 			is->setItem(delItems);
11246 			is->set("DELETE_ITEM");
11247 			is->set("ITEMID", itemList->indexOf(currItem));
11248 			is->set("ID", selectedItemCount - (de + 1));
11249 			m_undoManager->action(Pages->at(0), is, currItem->getUPixmap());
11250 		}
11251 		itemList->removeAll(currItem);
11252 //		undoManager->action(Pages->at(0), is, currItem->getUPixmap());
11253 		if (forceDeletion)
11254 			delete currItem;
11255 	}
11256 	itemSelection->delaySignalsOff();
11257 	if (activeTransaction)
11258 		activeTransaction.commit();
11259 	// JG resetting ElemToLink fixes #5629
11260 	ElemToLink = nullptr;
11261 
11262 	for (PageItem* tii : textInteractionItems)
11263 		tii->update();
11264 
11265 	regionsChanged()->update(QRectF());
11266 	if (m_View)
11267 		m_View->setCursor(QCursor(Qt::ArrowCursor));
11268 
11269 	if (itemSelection->isGUISelection() && !itemSelection->signalsDelayed())
11270 	{
11271 		if (itemSelection->isEmpty())
11272 			emit firstSelectedItemType(-1);
11273 		else
11274 			itemSelection->itemAt(0)->emitAllToGUI();
11275 	}
11276 	changed();
11277 }
11278 
11279 
itemSelection_SetItemFillTransparency(double t,Selection * customSelection)11280 void ScribusDoc::itemSelection_SetItemFillTransparency(double t, Selection* customSelection)
11281 {
11282 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11283 	int selectedItemCount = itemSelection->count();
11284 	if (selectedItemCount == 0)
11285 		return;
11286 
11287 	for (int i = 0; i < selectedItemCount; ++i)
11288 	{
11289 		PageItem *currItem = itemSelection->itemAt(i);
11290 		currItem->setFillTransparency(t);
11291 		if (currItem->isGroup())
11292 			currItem->update(); // FIXME: not sure this is needed
11293 	}
11294 	regionsChanged()->update(QRectF());
11295 	changed();
11296 }
11297 
11298 
itemSelection_SetItemLineTransparency(double t,Selection * customSelection)11299 void ScribusDoc::itemSelection_SetItemLineTransparency(double t, Selection* customSelection)
11300 {
11301 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11302 	int selectedItemCount = itemSelection->count();
11303 	if (selectedItemCount == 0)
11304 		return;
11305 
11306 	for (int i = 0; i < selectedItemCount; ++i)
11307 	{
11308 		PageItem *currItem = itemSelection->itemAt(i);
11309 		currItem->setLineTransparency(t);
11310 	}
11311 	regionsChanged()->update(QRectF());
11312 	changed();
11313 }
11314 
11315 
itemSelection_SetItemFillBlend(int t)11316 void ScribusDoc::itemSelection_SetItemFillBlend(int t)
11317 {
11318 	int selectedItemCount = m_Selection->count();
11319 	if (selectedItemCount == 0)
11320 		return;
11321 	UndoTransaction activeTransaction;
11322 	if (UndoManager::undoEnabled())
11323 		activeTransaction = m_undoManager->beginTransaction();
11324 	for (int i = 0; i < selectedItemCount; ++i)
11325 	{
11326 		PageItem *currItem = m_Selection->itemAt(i);
11327 		if (currItem->isGroup())
11328 			continue;
11329 		currItem->setFillBlendmode(t);
11330 	}
11331 	regionsChanged()->update(QRectF());
11332 	changed();
11333 	if (activeTransaction)
11334 	{
11335 		activeTransaction.commit(Um::Selection,
11336 								 Um::IGroup,
11337 								 Um::BlendMode,
11338 								 "",
11339 								 Um::IGroup);
11340 	}
11341 }
11342 
11343 
itemSelection_SetItemLineBlend(int t)11344 void ScribusDoc::itemSelection_SetItemLineBlend(int t)
11345 {
11346 	int selectedItemCount = m_Selection->count();
11347 	if (selectedItemCount == 0)
11348 		return;
11349 	UndoTransaction activeTransaction;
11350 	if (UndoManager::undoEnabled())
11351 		activeTransaction = m_undoManager->beginTransaction();
11352 	for (int i = 0; i < selectedItemCount; ++i)
11353 	{
11354 		PageItem *currItem = m_Selection->itemAt(i);
11355 		currItem->setLineBlendmode(t);
11356 	}
11357 	regionsChanged()->update(QRectF());
11358 	changed();
11359 	if (activeTransaction)
11360 	{
11361 		activeTransaction.commit(Um::Selection,
11362 								 Um::IGroup,
11363 								 Um::BlendMode,
11364 								 "",
11365 								 Um::IGroup);
11366 	}
11367 }
11368 
11369 
itemSelection_SetLineGradient(VGradient & newGradient,Selection * customSelection)11370 void ScribusDoc::itemSelection_SetLineGradient(VGradient& newGradient, Selection* customSelection)
11371 {
11372 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11373 	assert(itemSelection != nullptr);
11374 	int selectedItemCount = itemSelection->count();
11375 	if (selectedItemCount == 0)
11376 		return;
11377 	m_updateManager.setUpdatesDisabled();
11378 	for (int i = 0; i < selectedItemCount; ++i)
11379 	{
11380 		PageItem *currItem;
11381 		currItem = itemSelection->itemAt(i);
11382 		currItem->setStrokeGradient(newGradient);
11383 		currItem->update();
11384 	}
11385 	m_updateManager.setUpdatesEnabled();
11386 	changed();
11387 }
11388 
itemSelection_SetFillGradient(VGradient & newGradient,Selection * customSelection)11389 void ScribusDoc::itemSelection_SetFillGradient(VGradient& newGradient, Selection* customSelection)
11390 {
11391 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11392 	assert(itemSelection != nullptr);
11393 	int selectedItemCount = itemSelection->count();
11394 	if (selectedItemCount == 0)
11395 		return;
11396 	m_updateManager.setUpdatesDisabled();
11397 	for (int i = 0; i < selectedItemCount; ++i)
11398 	{
11399 		PageItem *currItem;
11400 		currItem = itemSelection->itemAt(i);
11401 		currItem->setFillGradient(newGradient);
11402 		if (currItem->gradientType() == Gradient_Conical)
11403 			currItem->createConicalMesh();
11404 		currItem->update();
11405 	}
11406 	m_updateManager.setUpdatesEnabled();
11407 	changed();
11408 }
11409 
itemSelection_SetMaskGradient(VGradient & newGradient,Selection * customSelection)11410 void ScribusDoc::itemSelection_SetMaskGradient(VGradient& newGradient, Selection* customSelection)
11411 {
11412 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11413 	assert(itemSelection != nullptr);
11414 	int selectedItemCount = itemSelection->count();
11415 	if (selectedItemCount == 0)
11416 		return;
11417 	m_updateManager.setUpdatesDisabled();
11418 	for (int i = 0; i < selectedItemCount; ++i)
11419 	{
11420 		PageItem *currItem;
11421 		currItem = itemSelection->itemAt(i);
11422 		currItem->setMaskGradient(newGradient);
11423 		currItem->update();
11424 	}
11425 	m_updateManager.setUpdatesEnabled();
11426 	changed();
11427 }
11428 
11429 
itemSelection_SetOverprint(bool overprint,Selection * customSelection)11430 void ScribusDoc::itemSelection_SetOverprint(bool overprint, Selection* customSelection)
11431 {
11432 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11433 	assert(itemSelection != nullptr);
11434 	int selectedItemCount = itemSelection->count();
11435 	if (selectedItemCount == 0)
11436 		return;
11437 	m_updateManager.setUpdatesDisabled();
11438 	UndoTransaction activeTransaction;
11439 	if (UndoManager::undoEnabled())
11440 		activeTransaction = m_undoManager->beginTransaction();
11441 	for (int i = 0; i < selectedItemCount; ++i)
11442 	{
11443 		PageItem* currItem = itemSelection->itemAt(i);
11444 		currItem->setOverprint(overprint);
11445 		currItem->update();
11446 	}
11447 	if (activeTransaction)
11448 	{
11449 		activeTransaction.commit(Um::Selection,
11450 								 Um::IGroup,
11451 							     Um::Overprint,
11452 								 "",
11453 								 Um::IGroup);
11454 	}
11455 	m_updateManager.setUpdatesEnabled();
11456 	changed();
11457 }
11458 
itemSelection_DoHyphenate()11459 void ScribusDoc::itemSelection_DoHyphenate()
11460 {
11461 	int selectedItemCount = m_Selection->count();
11462 	if (selectedItemCount == 0)
11463 		return;
11464 	for (int i = 0; i < selectedItemCount; ++i)
11465 	{
11466 		PageItem *currItem = m_Selection->itemAt(i);
11467 		docHyphenator->slotHyphenate(currItem);
11468 	}
11469 	//FIXME: stop using m_View
11470 	m_View->DrawNew(); //CB draw new until NLS for redraw through text chains
11471 	changed();
11472 }
11473 
itemSelection_DoDeHyphenate()11474 void ScribusDoc::itemSelection_DoDeHyphenate()
11475 {
11476 	int selectedItemCount = m_Selection->count();
11477 	if (selectedItemCount == 0)
11478 		return;
11479 	for (int i = 0; i < selectedItemCount; ++i)
11480 	{
11481 		PageItem *currItem = m_Selection->itemAt(i);
11482 		docHyphenator->slotDeHyphenate(currItem);
11483 	}
11484 	//FIXME: stop using m_View
11485 	m_View->DrawNew(); //CB draw new until NLS for redraw through text chains
11486 	changed();
11487 }
11488 
itemSelection_SendToLayer(int layerID)11489 void ScribusDoc::itemSelection_SendToLayer(int layerID)
11490 {
11491 	int selectedItemCount = m_Selection->count();
11492 	if (selectedItemCount != 0)
11493 	{
11494 		UndoTransaction activeTransaction;
11495 		if (UndoManager::undoEnabled() && selectedItemCount > 1)
11496 			activeTransaction = m_undoManager->beginTransaction();
11497 		QString tooltip = Um::ItemsInvolved + "\n";
11498 		if (selectedItemCount > Um::ItemsInvolvedLimit)
11499 			tooltip = Um::ItemsInvolved2 + "\n";
11500 		for (int i = 0; i < selectedItemCount; ++i)
11501 		{
11502 			PageItem *currItem = m_Selection->itemAt(i);
11503 			currItem->setLayer(layerID);
11504 			if (selectedItemCount <= Um::ItemsInvolvedLimit)
11505 				tooltip += "\t" + currItem->getUName() + "\n";
11506 		}
11507 		if (activeTransaction)
11508 		{
11509 			activeTransaction.commit(Um::Selection,
11510 									 Um::IGroup,
11511 									 Um::SendToLayer,
11512 									 tooltip,
11513 									 Um::ILayerAction);
11514 		}
11515 	}
11516 	m_View->deselectItems(true);
11517 	regionsChanged()->update(QRectF());
11518 	changed();
11519 }
11520 
itemSelection_SetAlignment(int s,Selection * customSelection)11521 void ScribusDoc::itemSelection_SetAlignment(int s, Selection* customSelection)
11522 {
11523 	ParagraphStyle newStyle;
11524 	newStyle.setAlignment(static_cast<ParagraphStyle::AlignmentType>(s));
11525 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
11526 }
11527 
itemSelection_SetDirection(int s,Selection * customSelection)11528 void ScribusDoc::itemSelection_SetDirection(int s, Selection* customSelection)
11529 {
11530 	ParagraphStyle newStyle;
11531 	newStyle.setDirection(static_cast<ParagraphStyle::DirectionType>(s));
11532 	itemSelection_ApplyParagraphStyle(newStyle, customSelection);
11533 }
11534 
itemSelection_SetImageOffset(double x,double y,Selection * customSelection)11535 void ScribusDoc::itemSelection_SetImageOffset(double x, double y, Selection* customSelection)
11536 {
11537 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11538 	assert(itemSelection != nullptr);
11539 	int selectedItemCount = itemSelection->count();
11540 	if (selectedItemCount <= 0)
11541 		return;
11542 
11543 	UndoTransaction activeTransaction;
11544 	m_updateManager.setUpdatesDisabled();
11545 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
11546 		activeTransaction = m_undoManager->beginTransaction();
11547 	QString tooltip = Um::ItemsInvolved + "\n";
11548 	if (selectedItemCount > Um::ItemsInvolvedLimit)
11549 		tooltip = Um::ItemsInvolved2 + "\n";
11550 	for (int i = 0; i < selectedItemCount; ++i)
11551 	{
11552 		PageItem *currItem = itemSelection->itemAt(i);
11553 		currItem->setImageXYOffset(x, y);
11554 		if (!currItem->imageClip.empty())
11555 		{
11556 			currItem->imageClip = currItem->pixm.imgInfo.PDSpathData[currItem->pixm.imgInfo.usedPath].copy();
11557 			QTransform cl;
11558 			cl.translate(currItem->imageXOffset()*currItem->imageXScale(), currItem->imageYOffset()*currItem->imageYScale());
11559 			cl.rotate(currItem->imageRotation());
11560 			cl.scale(currItem->imageXScale(), currItem->imageYScale());
11561 			currItem->imageClip.map(cl);
11562 		}
11563 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
11564 			tooltip += "\t" + currItem->getUName() + "\n";
11565 		currItem->update();
11566 	}
11567 	if (activeTransaction)
11568 	{
11569 		activeTransaction.commit(Um::Selection,
11570 									Um::IGroup,
11571 									Um::ImageOffset,
11572 									tooltip,
11573 									Um::IImageScaling);
11574 	}
11575 	m_updateManager.setUpdatesEnabled();
11576 	changed();
11577 }
11578 
itemSelection_SetImageScale(double x,double y,Selection * customSelection)11579 void ScribusDoc::itemSelection_SetImageScale(double x, double y, Selection* customSelection)
11580 {
11581 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11582 	assert(itemSelection != nullptr);
11583 	int selectedItemCount = itemSelection->count();
11584 	if (selectedItemCount <= 0)
11585 		return;
11586 
11587 	UndoTransaction activeTransaction;
11588 	m_updateManager.setUpdatesDisabled();
11589 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
11590 		activeTransaction = m_undoManager->beginTransaction();
11591 	QString tooltip = Um::ItemsInvolved + "\n";
11592 	if (selectedItemCount > Um::ItemsInvolvedLimit)
11593 		tooltip = Um::ItemsInvolved2 + "\n";
11594 	for (int i = 0; i < selectedItemCount; ++i)
11595 	{
11596 		PageItem *currItem = itemSelection->itemAt(i);
11597 		currItem->setImageXYScale(x, y);
11598 		if (!currItem->imageClip.empty())
11599 		{
11600 			currItem->imageClip = currItem->pixm.imgInfo.PDSpathData[currItem->pixm.imgInfo.usedPath].copy();
11601 			QTransform cl;
11602 			cl.translate(currItem->imageXOffset()*currItem->imageXScale(), currItem->imageYOffset()*currItem->imageYScale());
11603 			cl.rotate(currItem->imageRotation());
11604 			cl.scale(currItem->imageXScale(), currItem->imageYScale());
11605 			currItem->imageClip.map(cl);
11606 		}
11607 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
11608 			tooltip += "\t" + currItem->getUName() + "\n";
11609 		currItem->update();
11610 	}
11611 	if (activeTransaction)
11612 	{
11613 		activeTransaction.commit(Um::Selection,
11614 							Um::IGroup,
11615 							Um::ImageScale,
11616 							tooltip,
11617 							Um::IImageScaling);
11618 	}
11619 	m_updateManager.setUpdatesEnabled();
11620 	changed();
11621 }
11622 
itemSelection_SetImageScaleAndOffset(double sx,double sy,double ox,double oy,Selection * customSelection)11623 void ScribusDoc::itemSelection_SetImageScaleAndOffset(double sx, double sy, double ox, double oy, Selection* customSelection)
11624 {
11625 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11626 	assert(itemSelection != nullptr );
11627 	int selectedItemCount = itemSelection->count();
11628 	if (selectedItemCount == 0)
11629 		return;
11630 
11631 	m_updateManager.setUpdatesDisabled();
11632 	UndoTransaction outerTransaction;
11633 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
11634 		outerTransaction = m_undoManager->beginTransaction();
11635 	QString tooltip = Um::ItemsInvolved + "\n";
11636 	if (selectedItemCount > Um::ItemsInvolvedLimit)
11637 		tooltip = Um::ItemsInvolved2 + "\n";
11638 	for (int i = 0; i < selectedItemCount; ++i)
11639 	{
11640 		UndoTransaction activeTransaction;
11641 		PageItem *currItem = itemSelection->itemAt(i);
11642 		if (UndoManager::undoEnabled())
11643 			activeTransaction = m_undoManager->beginTransaction();
11644 		currItem->setImageXYScale(sx, sy);
11645 		currItem->setImageXYOffset(ox/sx, oy/sy);
11646 		if (!currItem->imageClip.empty())
11647 		{
11648 			currItem->imageClip = currItem->pixm.imgInfo.PDSpathData[currItem->pixm.imgInfo.usedPath].copy();
11649 			QTransform cl;
11650 			cl.translate(currItem->imageXOffset()*currItem->imageXScale(), currItem->imageYOffset()*currItem->imageYScale());
11651 			cl.rotate(currItem->imageRotation());
11652 			cl.scale(currItem->imageXScale(), currItem->imageYScale());
11653 			currItem->imageClip.map(cl);
11654 		}
11655 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
11656 			tooltip += "\t" + currItem->getUName() + "\n";
11657 		if (activeTransaction)
11658 		{
11659 			activeTransaction.commit(Um::Selection,
11660 									 Um::IImageFrame,
11661 									 Um::ImageScale,
11662 									 tooltip,
11663 									 Um::IImageScaling);
11664 		}
11665 		currItem->update();
11666 	}
11667 	if (outerTransaction)
11668 	{
11669 		outerTransaction.commit(Um::Selection,
11670 								Um::IGroup,
11671 								Um::ImageScale,
11672 								tooltip,
11673 								Um::IImageScaling);
11674 	}
11675 	m_updateManager.setUpdatesEnabled();
11676 	changed();
11677 }
11678 
itemSelection_SetImageRotation(double rot,Selection * customSelection)11679 void ScribusDoc::itemSelection_SetImageRotation(double rot, Selection* customSelection)
11680 {
11681 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11682 	assert(itemSelection != nullptr);
11683 	int selectedItemCount = itemSelection->count();
11684 	if (selectedItemCount == 0)
11685 		return;
11686 
11687 	UndoTransaction trans;
11688 	if (UndoManager::undoEnabled())
11689 		trans = m_undoManager->beginTransaction(Um::Selection,Um::IImageFrame,Um::Rotate,"",Um::IRotate);
11690 	for (int i = 0; i < selectedItemCount; ++i)
11691 	{
11692 		PageItem *currItem = itemSelection->itemAt(i);
11693 		currItem->setImageRotation(rot);
11694 		if (!currItem->imageClip.empty())
11695 		{
11696 			currItem->imageClip = currItem->pixm.imgInfo.PDSpathData[currItem->pixm.imgInfo.usedPath].copy();
11697 			QTransform cl;
11698 			cl.translate(currItem->imageXOffset()*currItem->imageXScale(), currItem->imageYOffset()*currItem->imageYScale());
11699 			cl.rotate(currItem->imageRotation());
11700 			cl.scale(currItem->imageXScale(), currItem->imageYScale());
11701 			currItem->imageClip.map(cl);
11702 		}
11703 		currItem->update();
11704 	}
11705 	if (trans)
11706 		trans.commit();
11707 	changed();
11708 }
11709 
buildAlignItemList(Selection * customSelection)11710 void ScribusDoc::buildAlignItemList(Selection* customSelection)
11711 {
11712 	Q_UNUSED(customSelection);
11713 	//CB TODO Handling custom selections
11714 	//Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
11715 	Selection* itemSelection = m_Selection;
11716 	assert(itemSelection != nullptr);
11717 	int selectedItemCount = itemSelection->count();
11718 	PageItem *currItem;
11719 	struct AlignObjs Object;
11720 	AObjects.clear();
11721 	for (int i = 0; i < selectedItemCount; ++i)
11722 	{
11723 		currItem = itemSelection->itemAt(i);
11724 		currItem->getBoundingRect(&Object.x1, &Object.y1, &Object.x2, &Object.y2);
11725 		Object.Group = 0;
11726 		Object.ObjNr = Items->indexOf(currItem);
11727 		Object.Object = currItem;
11728 		AObjects.append(Object);
11729 	}
11730 	for (int i = 0; i < AObjects.count(); ++i)
11731 	{
11732 		AObjects[i].width = AObjects[i].x2 - AObjects[i].x1;
11733 		AObjects[i].height = AObjects[i].y2 - AObjects[i].y1;
11734 	}
11735 }
11736 
11737 
startAlign(uint minObjects)11738 bool ScribusDoc::startAlign(uint minObjects)
11739 {
11740 	buildAlignItemList();
11741 	int alignObjectsCount = AObjects.count();
11742 	if (alignObjectsCount < static_cast<int>(minObjects))
11743 		return false;
11744 
11745 	bool oneLocked = false;
11746 	for (int i = 0; i < alignObjectsCount && !oneLocked; ++i)
11747 	{
11748 		if (AObjects[i].Object->locked())
11749 			oneLocked = true;
11750 	}
11751 	int t = 2;
11752 	if (oneLocked)
11753 	{
11754 		ScMessageBox msgBox;
11755 		QPushButton *abortButton = msgBox.addButton(QMessageBox::Cancel);
11756 		QPushButton *lockButton = msgBox.addButton(tr("&Unlock All"), QMessageBox::AcceptRole);
11757 		QPushButton *unlockButton = msgBox.addButton(tr("&Skip locked objects"), QMessageBox::AcceptRole);
11758 		msgBox.setIcon(QMessageBox::Warning);
11759 		msgBox.setWindowTitle(CommonStrings::trWarning);
11760 		msgBox.setText( tr("Some objects are locked."));
11761 		msgBox.setDefaultBatchButton(lockButton);
11762 		msgBox.exec();
11763 		if (msgBox.clickedButton() == abortButton)
11764 			return false;
11765 		if (msgBox.clickedButton() == lockButton)
11766 			t = 0;
11767 		else if (msgBox.clickedButton() == unlockButton)
11768 			t = 1;
11769 	}
11770 
11771 	QString targetTooltip;
11772 	if (m_Selection->count() <= (int) Um::ItemsInvolvedLimit)
11773 	{
11774 		targetTooltip = Um::ItemsInvolved + "\n";
11775 		for (int i = 0; i < m_Selection->count(); ++i)
11776 			targetTooltip += "\t" + m_Selection->itemAt(i)->getUName() + "\n";
11777 	}
11778 	else
11779 		targetTooltip = Um::ItemsInvolved2 + "\n";
11780 	// Make the align action a single action in Action History
11781 	m_alignTransaction = m_undoManager->beginTransaction(Um::Selection, nullptr, Um::AlignDistribute, targetTooltip, Um::IAlignDistribute);
11782 	if (oneLocked && (t == 0))
11783 	{
11784 		for (int i = 0; i < alignObjectsCount; ++i)
11785 		{
11786 			if (AObjects[i].Object->locked())
11787 				AObjects[i].Object->setLocked(false);
11788 		}
11789 	}
11790 	return true;
11791 }
11792 
endAlign()11793 void ScribusDoc::endAlign()
11794 {
11795 	changed();
11796 	m_ScMW->HaveNewSel();
11797 	for (int i = 0; i < m_Selection->count(); ++i)
11798 	{
11799 		setRedrawBounding(m_Selection->itemAt(i));
11800 		m_Selection->itemAt(i)->invalidateLayout();
11801 	}
11802 	m_alignTransaction.commit(); // commit and send the action to the UndoManager
11803 	m_alignTransaction.reset();
11804 	regionsChanged()->update(QRectF());
11805 }
11806 
itemSelection_AlignItemRight(int i,double newX,AlignMethod how)11807 void ScribusDoc::itemSelection_AlignItemRight(int i, double newX, AlignMethod how)
11808 {
11809 	double diff=newX-AObjects[i].x2;
11810 	double width=AObjects[i].x2-AObjects[i].x1;
11811 	bool resize = (how == alignByResizing && diff > -width);
11812 	if (!AObjects[i].Object->locked())
11813 	{
11814 		if (resize)
11815 		{
11816 			AObjects[i].Object->resizeBy(diff, 0.0);
11817 			AObjects[i].Object->updateClip();
11818 		}
11819 		else
11820 			AObjects[i].Object->moveBy(diff, 0.0);
11821 	}
11822 }
11823 
itemSelection_AlignItemLeft(int i,double newX,AlignMethod how)11824 void ScribusDoc::itemSelection_AlignItemLeft(int i, double newX, AlignMethod how)
11825 {
11826 	double diff=newX-AObjects[i].x1;
11827 	double width=AObjects[i].x2-AObjects[i].x1;
11828 	bool resize = (how == alignByResizing && -diff > -width);
11829 	if (!AObjects[i].Object->locked())
11830 	{
11831 		AObjects[i].Object->moveBy(diff, 0.0);
11832 		if (resize)
11833 		{
11834 			AObjects[i].Object->resizeBy(-diff, 0.0);
11835 			AObjects[i].Object->updateClip();
11836 		}
11837 	}
11838 }
11839 
itemSelection_AlignItemBottom(int i,double newY,AlignMethod how)11840 void ScribusDoc::itemSelection_AlignItemBottom(int i, double newY, AlignMethod how)
11841 {
11842 	double diff=newY-AObjects[i].y2;
11843 	double height=AObjects[i].y2-AObjects[i].y1;
11844 	bool resize = (how == alignByResizing && diff > -height);
11845 	if (!AObjects[i].Object->locked())
11846 	{
11847 		if (resize)
11848 		{
11849 			AObjects[i].Object->resizeBy(0.0, diff);
11850 			AObjects[i].Object->updateClip();
11851 		}
11852 		else AObjects[i].Object->moveBy(0.0, diff);
11853 	}
11854 }
11855 
itemSelection_AlignItemTop(int i,double newY,AlignMethod how)11856 void ScribusDoc::itemSelection_AlignItemTop(int i, double newY, AlignMethod how)
11857 {
11858 	double diff=newY-AObjects[i].y1;
11859 	double height=AObjects[i].y2-AObjects[i].y1;
11860 	bool resize = (how == alignByResizing && -diff > -height);
11861 	if (!AObjects[i].Object->locked())
11862 	{
11863 		AObjects[i].Object->moveBy(0.0, diff);
11864 		if (resize)
11865 		{
11866 			AObjects[i].Object->resizeBy(0.0, -diff);
11867 			AObjects[i].Object->updateClip();
11868 		}
11869 	}
11870 }
11871 
itemSelection_AlignLeftOut(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)11872 void ScribusDoc::itemSelection_AlignLeftOut(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
11873 {
11874 	if (!startAlign())
11875 		return;
11876 	int alignObjectsCount = AObjects.count();
11877 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
11878 	double newX = std::numeric_limits<double>::max();
11879 	switch (currAlignTo)
11880 	{
11881 		case alignFirst:
11882 			newX = AObjects[0].x1;
11883 			loopStart = 1;
11884 			break;
11885 		case alignLast:
11886 			newX = AObjects[alignObjectsCount-1].x1;
11887 			loopEnd = alignObjectsCount-2;
11888 			break;
11889 		case alignPage:
11890 			newX = m_currentPage->xOffset();
11891 			break;
11892 		case alignMargins:
11893 			newX = m_currentPage->xOffset();
11894 			newX += m_currentPage->Margins.left();
11895 			break;
11896 		case alignGuide:
11897 			newX = m_currentPage->xOffset() + guidePosition;
11898 			break;
11899 		case alignSelection:
11900 			for (int i = 0; i < alignObjectsCount; ++i)
11901 				newX = qMin(AObjects[i].x1, newX);
11902 			break;
11903 	}
11904 	for (int i = loopStart; i <= loopEnd; ++i)
11905 		itemSelection_AlignItemRight(i, newX, currAlignMethod);
11906 	endAlign();
11907 }
11908 
11909 
itemSelection_AlignLeftIn(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)11910 void ScribusDoc::itemSelection_AlignLeftIn(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
11911 {
11912 	if (!startAlign())
11913 		return;
11914 	int alignObjectsCount = AObjects.count();
11915 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
11916 	double newX = std::numeric_limits<double>::max();
11917 	switch ( currAlignTo )
11918 	{
11919 		case alignFirst:
11920 			newX = AObjects[0].x1;
11921 			loopStart = 1;
11922 			break;
11923 		case alignLast:
11924 			newX = AObjects[alignObjectsCount-1].x1;
11925 			loopEnd = alignObjectsCount-2;
11926 			break;
11927 		case alignPage:
11928 			newX = m_currentPage->xOffset();
11929 			break;
11930 		case alignMargins:
11931 			newX = m_currentPage->xOffset();
11932 			newX += m_currentPage->Margins.left();
11933 			break;
11934 		case alignGuide:
11935 			newX = m_currentPage->xOffset() + guidePosition;
11936 			break;
11937 		case alignSelection:
11938 			for (int i = 0; i < alignObjectsCount; ++i)
11939 				newX = qMin(AObjects[i].x1, newX);
11940 			break;
11941 	}
11942 	for (int i = loopStart; i <= loopEnd; ++i)
11943 		itemSelection_AlignItemLeft(i, newX, currAlignMethod);
11944 	endAlign();
11945 }
11946 
11947 
itemSelection_AlignCenterHor(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)11948 void ScribusDoc::itemSelection_AlignCenterHor(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
11949 {
11950 	if (!startAlign())
11951 		return;
11952 	int alignObjectsCount = AObjects.count();
11953 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
11954 	double newX = 0.0;
11955 	switch (currAlignTo)
11956 	{
11957 		case alignFirst:
11958 			newX = AObjects[0].x1 + (AObjects[0].width)/2;
11959 			loopStart=1;
11960 			break;
11961 		case alignLast:
11962 			{
11963 				int objindex=alignObjectsCount-1;
11964 				newX = AObjects[objindex].x1 + (AObjects[objindex].width)/2;
11965 				loopEnd=alignObjectsCount-2;
11966 			}
11967 			break;
11968 		case alignPage:
11969 			newX = m_currentPage->xOffset();
11970 			newX += m_currentPage->width()/2;
11971 			break;
11972 		case alignMargins:
11973 			newX = m_currentPage->xOffset();
11974 			newX += m_currentPage->Margins.left();
11975 			newX += (m_currentPage->width() - m_currentPage->Margins.right() - m_currentPage->Margins.left())/2;
11976 			break;
11977 		case alignGuide:
11978 			newX = m_currentPage->xOffset() + guidePosition;
11979 			break;
11980 		case alignSelection:
11981 			double minX =  std::numeric_limits<double>::max();
11982 			double maxX = -std::numeric_limits<double>::max();
11983 			for (int i = 0; i < alignObjectsCount; ++i)
11984 			{
11985 				minX = qMin(AObjects[i].x1, minX);
11986 				maxX = qMax(AObjects[i].x2, maxX);
11987 			}
11988 			newX = minX + (maxX-minX) / 2;
11989 			break;
11990 	}
11991 	for (int i = loopStart; i <= loopEnd; ++i)
11992 	{
11993 		double diff=newX-AObjects[i].x1-(AObjects[i].width)/2;
11994 		if (!AObjects[i].Object->locked())
11995 			AObjects[i].Object->moveBy(diff, 0.0);
11996 	}
11997 	endAlign();
11998 }
11999 
12000 
itemSelection_AlignRightIn(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12001 void ScribusDoc::itemSelection_AlignRightIn(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12002 {
12003 	if (!startAlign())
12004 		return;
12005 	int alignObjectsCount = AObjects.count();
12006 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12007 	double newX = -std::numeric_limits<double>::max();
12008 	switch ( currAlignTo )
12009 	{
12010 		case alignFirst:
12011 			newX = AObjects[0].x2;
12012 			loopStart=1;
12013 			break;
12014 		case alignLast:
12015 			newX = AObjects[alignObjectsCount-1].x2;
12016 			loopEnd=alignObjectsCount-2;
12017 			break;
12018 		case alignPage:
12019 			newX = m_currentPage->xOffset();
12020 			newX += m_currentPage->width();
12021 			break;
12022 		case alignMargins:
12023 			newX = m_currentPage->xOffset();
12024 			newX += m_currentPage->width();
12025 			newX -= m_currentPage->Margins.right();
12026 			break;
12027 		case alignGuide:
12028 			newX = m_currentPage->xOffset() + guidePosition;
12029 			break;
12030 		case alignSelection:
12031 			for (int i = 0; i < alignObjectsCount; ++i)
12032 				newX = qMax(AObjects[i].x2, newX);
12033 			break;
12034 	}
12035 	for (int i = loopStart; i <= loopEnd; ++i)
12036 		itemSelection_AlignItemRight(i, newX, currAlignMethod);
12037 	endAlign();
12038 }
12039 
12040 
itemSelection_AlignRightOut(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12041 void ScribusDoc::itemSelection_AlignRightOut(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12042 {
12043 	if (!startAlign())
12044 		return;
12045 	int alignObjectsCount = AObjects.count();
12046 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12047 	double newX = -std::numeric_limits<double>::max();
12048 	switch ( currAlignTo )
12049 	{
12050 		case alignFirst:
12051 			newX = AObjects[0].x2;
12052 			loopStart=1;
12053 			break;
12054 		case alignLast:
12055 			newX = AObjects[alignObjectsCount-1].x2;
12056 			loopEnd=alignObjectsCount-2;
12057 			break;
12058 		case alignPage:
12059 			newX = m_currentPage->xOffset();
12060 			newX += m_currentPage->width();
12061 			break;
12062 		case alignMargins:
12063 			newX = m_currentPage->xOffset();
12064 			newX += m_currentPage->width();
12065 			newX -= m_currentPage->Margins.right();
12066 			break;
12067 		case alignGuide:
12068 			newX = m_currentPage->xOffset() + guidePosition;
12069 			break;
12070 		case alignSelection:
12071 			for (int i = 0; i < alignObjectsCount; ++i)
12072 				newX = qMax(AObjects[i].x2, newX);
12073 			break;
12074 	}
12075 	for (int i = loopStart; i <= loopEnd; ++i)
12076 		itemSelection_AlignItemLeft(i, newX, currAlignMethod);
12077 	endAlign();
12078 }
12079 
12080 
itemSelection_AlignTopOut(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12081 void ScribusDoc::itemSelection_AlignTopOut(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12082 {
12083 	if (!startAlign())
12084 		return;
12085 	int alignObjectsCount = AObjects.count();
12086 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12087 	double newY = std::numeric_limits<double>::max();
12088 	switch ( currAlignTo )
12089 	{
12090 		case alignFirst:
12091 			newY = AObjects[0].y1;
12092 			loopStart=1;
12093 			break;
12094 		case alignLast:
12095 			newY = AObjects[alignObjectsCount-1].y1;
12096 			loopEnd=alignObjectsCount-2;
12097 			break;
12098 		case alignPage:
12099 			newY = m_currentPage->yOffset();
12100 			break;
12101 		case alignMargins:
12102 			newY = m_currentPage->yOffset();
12103 			newY += m_currentPage->Margins.top();
12104 			break;
12105 		case alignGuide:
12106 			newY = m_currentPage->yOffset() + guidePosition;
12107 			break;
12108 		case alignSelection:
12109 			for (int i = 0; i < alignObjectsCount; ++i)
12110 				newY = qMin(AObjects[i].y1, newY);
12111 			break;
12112 	}
12113 	for (int i = loopStart; i <= loopEnd; ++i)
12114 		itemSelection_AlignItemBottom(i, newY, currAlignMethod);
12115 	endAlign();
12116 }
12117 
12118 
itemSelection_AlignTopIn(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12119 void ScribusDoc::itemSelection_AlignTopIn(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12120 {
12121 	if (!startAlign())
12122 		return;
12123 	int alignObjectsCount = AObjects.count();
12124 	int loopStart = 0;
12125 	int loopEnd = alignObjectsCount - 1;
12126 	double newY = std::numeric_limits<double>::max();
12127 	switch ( currAlignTo )
12128 	{
12129 		case alignFirst:
12130 			newY = AObjects[0].y1;
12131 			loopStart = 1;
12132 			break;
12133 		case alignLast:
12134 			newY = AObjects[alignObjectsCount - 1].y1;
12135 			loopEnd = alignObjectsCount - 2;
12136 			break;
12137 		case alignPage:
12138 			newY = m_currentPage->yOffset();
12139 			break;
12140 		case alignMargins:
12141 			newY = m_currentPage->yOffset();
12142 			newY += m_currentPage->Margins.top();
12143 			break;
12144 		case alignGuide:
12145 			newY = m_currentPage->yOffset() + guidePosition;
12146 			break;
12147 		case alignSelection:
12148 			for (int i = 0; i < alignObjectsCount; ++i)
12149 				newY = qMin(AObjects[i].y1, newY);
12150 			break;
12151 	}
12152 	for (int i = loopStart; i <= loopEnd; ++i)
12153 		itemSelection_AlignItemTop(i, newY, currAlignMethod);
12154 	endAlign();
12155 }
12156 
12157 
itemSelection_AlignCenterVer(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12158 void ScribusDoc::itemSelection_AlignCenterVer(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12159 {
12160 	if (!startAlign())
12161 		return;
12162 	int alignObjectsCount = AObjects.count();
12163 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12164 	double newY = 0.0;
12165 	switch ( currAlignTo )
12166 	{
12167 		case alignFirst:
12168 			newY = AObjects[0].y1 + (AObjects[0].height)/2;
12169 			loopStart=1;
12170 			break;
12171 		case alignLast:
12172 			{
12173 				int objindex=alignObjectsCount-1;
12174 				newY = AObjects[objindex].y1 + (AObjects[objindex].height)/2;
12175 				loopEnd=alignObjectsCount-2;
12176 			}
12177 			break;
12178 		case alignPage:
12179 			newY = m_currentPage->yOffset();
12180 			newY += m_currentPage->height()/2;
12181 			break;
12182 		case alignMargins:
12183 			newY = m_currentPage->yOffset();
12184 			newY += m_currentPage->Margins.top();
12185 			newY += (m_currentPage->height() - m_currentPage->Margins.bottom() - m_currentPage->Margins.top())/2;
12186 			break;
12187 		case alignGuide:
12188 			newY = m_currentPage->yOffset() + guidePosition;
12189 			break;
12190 		case alignSelection:
12191 			double minY =  std::numeric_limits<double>::max();
12192 			double maxY = -std::numeric_limits<double>::max();
12193 			for (int i = 0; i < alignObjectsCount; ++i)
12194 			{
12195 				minY = qMin(AObjects[i].y1, minY);
12196 				maxY = qMax(AObjects[i].y2, maxY);
12197 			}
12198 			newY = minY + (maxY-minY)/2;
12199 			break;
12200 	}
12201 	for (int i = loopStart; i <= loopEnd; ++i)
12202 	{
12203 		double diff=newY-AObjects[i].y1-(AObjects[i].height)/2;
12204 		if (!AObjects[i].Object->locked())
12205 			AObjects[i].Object->moveBy(0.0, diff);
12206 	}
12207 	endAlign();
12208 }
12209 
12210 
itemSelection_AlignBottomIn(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12211 void ScribusDoc::itemSelection_AlignBottomIn(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12212 {
12213 	if (!startAlign())
12214 		return;
12215 	int alignObjectsCount = AObjects.count();
12216 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12217 	double newY = -std::numeric_limits<double>::max();
12218 	switch ( currAlignTo )
12219 	{
12220 		case alignFirst:
12221 			newY = AObjects[0].y2;
12222 			loopStart=1;
12223 			break;
12224 		case alignLast:
12225 			newY = AObjects[alignObjectsCount-1].y2;
12226 			loopEnd=alignObjectsCount-2;
12227 			break;
12228 		case alignPage:
12229 			newY = m_currentPage->yOffset();
12230 			newY += m_currentPage->height();
12231 			break;
12232 		case alignMargins:
12233 			newY = m_currentPage->yOffset();
12234 			newY += m_currentPage->height();
12235 			newY -= m_currentPage->Margins.bottom();
12236 			break;
12237 		case alignGuide:
12238 			newY = m_currentPage->yOffset() + guidePosition;
12239 			break;
12240 		case alignSelection:
12241 			for (int i = 0; i < alignObjectsCount; ++i)
12242 				newY = qMax(AObjects[i].y2, newY);
12243 			break;
12244 	}
12245 	for (int i = loopStart; i <= loopEnd; ++i)
12246 		itemSelection_AlignItemBottom(i, newY, currAlignMethod);
12247 	endAlign();
12248 }
12249 
12250 
itemSelection_AlignBottomOut(ScribusDoc::AlignTo currAlignTo,ScribusDoc::AlignMethod currAlignMethod,double guidePosition)12251 void ScribusDoc::itemSelection_AlignBottomOut(ScribusDoc::AlignTo currAlignTo, ScribusDoc::AlignMethod currAlignMethod, double guidePosition)
12252 {
12253 	if (!startAlign())
12254 		return;
12255 	int alignObjectsCount = AObjects.count();
12256 	int loopStart = 0, loopEnd = alignObjectsCount - 1;
12257 	double newY = -std::numeric_limits<double>::max();
12258 	switch ( currAlignTo )
12259 	{
12260 		case alignFirst:
12261 			newY = AObjects[0].y2;
12262 			loopStart=1;
12263 			break;
12264 		case alignLast:
12265 			newY = AObjects[alignObjectsCount - 1].y2;
12266 			loopEnd = alignObjectsCount - 2;
12267 			break;
12268 		case alignPage:
12269 			newY = m_currentPage->yOffset();
12270 			newY += m_currentPage->height();
12271 			break;
12272 		case alignMargins:
12273 			newY = m_currentPage->yOffset();
12274 			newY += m_currentPage->height();
12275 			newY -= m_currentPage->Margins.bottom();
12276 			break;
12277 		case alignGuide:
12278 			newY = m_currentPage->yOffset() + guidePosition;
12279 			break;
12280 		case alignSelection:
12281 			for (int i = 0; i < alignObjectsCount; ++i)
12282 				newY = qMax(AObjects[i].y2, newY);
12283 			break;
12284 	}
12285 	for (int i = loopStart; i <= loopEnd; ++i)
12286 		itemSelection_AlignItemTop(i, newY, currAlignMethod);
12287 	endAlign();
12288 }
12289 
12290 
itemSelection_DistributeLeft()12291 void ScribusDoc::itemSelection_DistributeLeft()
12292 {
12293 	if (!startAlign(2))
12294 		return;
12295 	int alignObjectsCount = AObjects.count();
12296 	QMap<double,uint> Xsorted;
12297 	for (int i = 0; i < alignObjectsCount; ++i)
12298 	{
12299 		if (!Xsorted.contains(AObjects[i].x1))
12300 			Xsorted.insert(AObjects[i].x1, i);
12301 	}
12302 	QMap<double,uint>::Iterator it = Xsorted.begin();
12303 	QMap<double,uint>::Iterator itend = Xsorted.end();
12304 	double minX=it.key();
12305 	double maxX=it.key();
12306 	while ( it != itend)
12307 	{
12308 		if (minX>it.key())
12309 			minX=it.key();
12310 		if (maxX<it.key())
12311 			maxX=it.key();
12312 		++it;
12313 	}
12314 
12315 	double separation=(maxX-minX)/static_cast<double>(alignObjectsCount-1);
12316 	int i=0;
12317 	for (QMap<double,uint>::Iterator it = Xsorted.begin(); it != Xsorted.end(); ++it)
12318 	{
12319 		double diff=minX + i*separation-AObjects[it.value()].x1;
12320 		if (!AObjects[it.value()].Object->locked())
12321 			AObjects[it.value()].Object->moveBy(diff, 0.0);
12322 		i++;
12323 	}
12324 	endAlign();
12325 }
12326 
12327 
itemSelection_DistributeCenterH()12328 void ScribusDoc::itemSelection_DistributeCenterH()
12329 {
12330 	if (!startAlign(2))
12331 		return;
12332 	int alignObjectsCount = AObjects.count();
12333 	QMap<double,uint> Xsorted;
12334 	for (int i = 0; i < alignObjectsCount; ++i)
12335 	{
12336 		if (!Xsorted.contains(AObjects[i].x1+(AObjects[i].width)/2))
12337 			Xsorted.insert(AObjects[i].x1+(AObjects[i].width)/2, i);
12338 	}
12339 	QMap<double,uint>::Iterator it = Xsorted.begin();
12340 	QMap<double,uint>::Iterator itend = Xsorted.end();
12341 	double minX=it.key();
12342 	double maxX=it.key();
12343 	while ( it != itend)
12344 	{
12345 		if (minX>it.key())
12346 			minX=it.key();
12347 		if (maxX<it.key())
12348 			maxX=it.key();
12349 		++it;
12350 	}
12351 
12352 	double separation=(maxX-minX)/static_cast<double>(alignObjectsCount-1);
12353 	int i=0;
12354 	for (QMap<double,uint>::Iterator it = Xsorted.begin(); it != Xsorted.end(); ++it)
12355 	{
12356 		double diff=minX + i*separation-AObjects[it.value()].x1-(AObjects[it.value()].width)/2;
12357 		if (!AObjects[it.value()].Object->locked())
12358 			AObjects[it.value()].Object->moveBy(diff, 0.0);
12359 		i++;
12360 	}
12361 	endAlign();
12362 }
12363 
12364 
itemSelection_DistributeRight()12365 void ScribusDoc::itemSelection_DistributeRight()
12366 {
12367 	if (!startAlign(2))
12368 		return;
12369 	int alignObjectsCount = AObjects.count();
12370 	QMap<double,uint> Xsorted;
12371 	for (int i = 0; i < alignObjectsCount; ++i)
12372 	{
12373 		if (!Xsorted.contains(AObjects[i].x2))
12374 			Xsorted.insert(AObjects[i].x2, i);
12375 	}
12376 	QMap<double,uint>::Iterator it = Xsorted.begin();
12377 	QMap<double,uint>::Iterator itend = Xsorted.end();
12378 	double minX=it.key();
12379 	double maxX=it.key();
12380 	while ( it != itend)
12381 	{
12382 		if (minX>it.key())
12383 			minX=it.key();
12384 		if (maxX<it.key())
12385 			maxX=it.key();
12386 		++it;
12387 	}
12388 
12389 	double separation=(maxX-minX)/static_cast<double>(alignObjectsCount-1);
12390 	int i=0;
12391 	for (QMap<double,uint>::Iterator it = Xsorted.begin(); it != Xsorted.end(); ++it)
12392 	{
12393 		double diff=minX + i*separation-AObjects[it.value()].x2;
12394 		if (!AObjects[it.value()].Object->locked())
12395 			AObjects[it.value()].Object->moveBy(diff, 0.0);
12396 		i++;
12397 	}
12398 	endAlign();
12399 }
12400 
12401 
itemSelection_DistributeDistH(bool usingDistance,double distance,bool reverseDistribute)12402 void ScribusDoc::itemSelection_DistributeDistH(bool usingDistance, double distance, bool reverseDistribute)
12403 {
12404 	if (!startAlign(2))
12405 		return;
12406 	int alignObjectsCount = AObjects.count();
12407 	QMap<double, int> x1Sorted, x2Sorted;
12408 	for (int i = 0; i < alignObjectsCount; ++i)
12409 	{
12410 		if (!x1Sorted.contains(AObjects[i].x1))
12411 			x1Sorted.insert(AObjects[i].x1, i);
12412 		if (!x2Sorted.contains(AObjects[i].x2))
12413 			x2Sorted.insert(AObjects[i].x2, i);
12414 	}
12415 	int left = x1Sorted.begin().value();
12416 	int right = x2Sorted[x2Sorted.keys().back()];
12417 	double minX = AObjects[left].x2;
12418 	double maxX = AObjects[right].x2;
12419 	double separation=0.0;
12420 	if (!usingDistance)
12421 	{
12422 		double maxX = AObjects[right].x1;
12423 		double totalSpace = maxX - minX;
12424 		double totalWidth = 0;
12425 		uint insideObjectCount = 0;
12426 		for (int i = 0; i < alignObjectsCount; ++i)
12427 		{
12428 			if (i == left)
12429 				continue;
12430 			if (i == right)
12431 				continue;
12432 			totalWidth += AObjects[i].width;
12433 			++insideObjectCount;
12434 		}
12435 		separation = (totalSpace - totalWidth) / (insideObjectCount + 1);
12436 	}
12437 	else
12438 		separation = value2pts(distance, unitIndex());
12439 	if (!reverseDistribute)
12440 	{
12441 		double currX = minX;
12442 		for (auto it = x1Sorted.constBegin(); it != x1Sorted.constEnd(); ++it)
12443 		{
12444 			if (it.value() == left)
12445 				continue;
12446 			if (it.value() == right && !usingDistance)
12447 				continue;
12448 			currX+=separation;
12449 
12450 			double diff = currX - AObjects[it.value()].x1;
12451 			if (!AObjects[it.value()].Object->locked())
12452 				AObjects[it.value()].Object->moveBy(diff, 0.0);
12453 			currX += AObjects[it.value()].width;
12454 		}
12455 	}
12456 	else
12457 	{
12458 		QMapIterator<double, int> it(x1Sorted);
12459 		it.toBack();
12460 		double currX = maxX;
12461 		while (it.hasPrevious())
12462 		{
12463 			it.previous();
12464 			if (it.value() == right)
12465 			{
12466 				currX -= AObjects[it.value()].width;
12467 				continue;
12468 			}
12469 			if (it.value() == left && !usingDistance)
12470 				continue;
12471 			currX -= separation;
12472 
12473 			double diff = currX-AObjects[it.value()].x2;
12474 			if (!AObjects[it.value()].Object->locked())
12475 				AObjects[it.value()].Object->moveBy(diff, 0.0);
12476 			currX -= AObjects[it.value()].width;
12477 		}
12478 	}
12479 	endAlign();
12480 }
12481 
12482 
itemSelection_DistributeBottom()12483 void ScribusDoc::itemSelection_DistributeBottom()
12484 {
12485 	if (!startAlign(2))
12486 		return;
12487 	int alignObjectsCount = AObjects.count();
12488 	QMap<double,uint> Ysorted;
12489 	for (int i = 0; i < alignObjectsCount; ++i)
12490 	{
12491 		if (!Ysorted.contains(AObjects[i].y2))
12492 			Ysorted.insert(AObjects[i].y2, i);
12493 	}
12494 	QMap<double,uint>::Iterator it = Ysorted.begin();
12495 	QMap<double,uint>::Iterator itend = Ysorted.end();
12496 	double minY=it.key();
12497 	double maxY=it.key();
12498 	while ( it != itend)
12499 	{
12500 		if (minY>it.key())
12501 			minY=it.key();
12502 		if (maxY<it.key())
12503 			maxY=it.key();
12504 		++it;
12505 	}
12506 
12507 	double separation=(maxY-minY)/static_cast<double>(alignObjectsCount-1);
12508 	int i=0;
12509 	for (QMap<double,uint>::Iterator it = Ysorted.begin(); it != Ysorted.end(); ++it)
12510 	{
12511 		double diff=minY + i*separation-AObjects[it.value()].y2;
12512 		if (!AObjects[it.value()].Object->locked())
12513 			AObjects[it.value()].Object->moveBy(0.0, diff);
12514 		i++;
12515 	}
12516 	endAlign();
12517 }
12518 
12519 
itemSelection_DistributeCenterV()12520 void ScribusDoc::itemSelection_DistributeCenterV()
12521 {
12522 	if (!startAlign(2))
12523 		return;
12524 	int alignObjectsCount = AObjects.count();
12525 	QMap<double,uint> Ysorted;
12526 	for (int i = 0; i < alignObjectsCount; ++i)
12527 	{
12528 		if (!Ysorted.contains(AObjects[i].y1+(AObjects[i].height)/2))
12529 			Ysorted.insert(AObjects[i].y1+(AObjects[i].height)/2, i);
12530 	}
12531 	QMap<double,uint>::Iterator it = Ysorted.begin();
12532 	QMap<double,uint>::Iterator itend = Ysorted.end();
12533 	double minY=it.key();
12534 	double maxY=it.key();
12535 	while ( it != itend)
12536 	{
12537 		if (minY>it.key())
12538 			minY=it.key();
12539 		if (maxY<it.key())
12540 			maxY=it.key();
12541 		++it;
12542 	}
12543 
12544 	double separation=(maxY-minY)/static_cast<double>(alignObjectsCount-1);
12545 	int i=0;
12546 	for (QMap<double,uint>::Iterator it = Ysorted.begin(); it != Ysorted.end(); ++it)
12547 	{
12548 		double diff=minY + i*separation-AObjects[it.value()].y1-(AObjects[it.value()].height)/2;
12549 		if (!AObjects[it.value()].Object->locked())
12550 			AObjects[it.value()].Object->moveBy(0.0, diff);
12551 		i++;
12552 	}
12553 	endAlign();
12554 }
12555 
12556 
itemSelection_DistributeTop()12557 void ScribusDoc::itemSelection_DistributeTop()
12558 {
12559 	if (!startAlign(2))
12560 		return;
12561 	int alignObjectsCount = AObjects.count();
12562 	QMap<double,uint> Ysorted;
12563 	for (int i = 0; i < alignObjectsCount; ++i)
12564 	{
12565 		if (!Ysorted.contains(AObjects[i].y1))
12566 			Ysorted.insert(AObjects[i].y1, i);
12567 	}
12568 	QMap<double,uint>::Iterator it = Ysorted.begin();
12569 	QMap<double,uint>::Iterator itend = Ysorted.end();
12570 	double minY=it.key();
12571 	double maxY=it.key();
12572 	while ( it != itend)
12573 	{
12574 		if (minY>it.key())
12575 			minY=it.key();
12576 		if (maxY<it.key())
12577 			maxY=it.key();
12578 		++it;
12579 	}
12580 
12581 	double separation=(maxY-minY)/static_cast<double>(alignObjectsCount-1);
12582 	int i=0;
12583 	for (QMap<double,uint>::Iterator it = Ysorted.begin(); it != Ysorted.end(); ++it)
12584 	{
12585 		double diff=minY + i*separation-AObjects[it.value()].y1;
12586 		if (!AObjects[it.value()].Object->locked())
12587 			AObjects[it.value()].Object->moveBy(0.0,diff);
12588 		i++;
12589 	}
12590 	endAlign();
12591 }
12592 
12593 
itemSelection_DistributeDistV(bool usingDistance,double distance,bool reverseDistribute)12594 void ScribusDoc::itemSelection_DistributeDistV(bool usingDistance, double distance, bool reverseDistribute)
12595 {
12596 	if (!startAlign(2))
12597 		return;
12598 	int alignObjectsCount = AObjects.count();
12599 	QMap<double, int> y1sorted, y2sorted;
12600 	for (int i = 0; i < alignObjectsCount; ++i)
12601 	{
12602 		if (!y1sorted.contains(AObjects[i].y1))
12603 			y1sorted.insert(AObjects[i].y1, i);
12604 		if (!y2sorted.contains(AObjects[i].y2))
12605 			y2sorted.insert(AObjects[i].y2, i);
12606 	}
12607 	int top = y1sorted.begin().value();
12608 	int bottom = y2sorted[y2sorted.keys().back()];
12609 	double minY = AObjects[top].y2;
12610 	double maxY = AObjects[bottom].y2;
12611 	double separation=0.0;
12612 	if (!usingDistance)
12613 	{
12614 		double maxY = AObjects[bottom].y1;
12615 		double totalSpace = maxY - minY;
12616 		double totalHeight = 0;
12617 		uint insideObjectCount = 0;
12618 		for (int i = 0; i < alignObjectsCount; ++i)
12619 		{
12620 			if (i == top)
12621 				continue;
12622 			if (i == bottom)
12623 				continue;
12624 			totalHeight += AObjects[i].height;
12625 			++insideObjectCount;
12626 		}
12627 		separation = (totalSpace - totalHeight) / (insideObjectCount + 1);
12628 	}
12629 	else
12630 		separation=value2pts(distance, unitIndex());
12631 	if (!reverseDistribute)
12632 	{
12633 		double currY = minY;
12634 		for (auto it = y1sorted.constBegin(); it != y1sorted.constEnd(); ++it)
12635 		{
12636 			if (it.value() == top)
12637 				continue;
12638 			if (it.value() == bottom && !usingDistance)
12639 				continue;
12640 			currY += separation;
12641 
12642 			double diff = currY-AObjects[it.value()].y1;
12643 			if (!AObjects[it.value()].Object->locked())
12644 				AObjects[it.value()].Object->moveBy(0.0, diff);
12645 			currY+=AObjects[it.value()].height;
12646 		}
12647 	}
12648 	else
12649 	{
12650 		QMapIterator<double, int> it(y1sorted);
12651 		it.toBack();
12652 		double currY = maxY;
12653 		while (it.hasPrevious())
12654 		{
12655 			it.previous();
12656 			if (it.value() == bottom)
12657 			{
12658 				currY -= AObjects[it.value()].height;
12659 				continue;
12660 			}
12661 			if (it.value() == top && !usingDistance)
12662 				continue;
12663 			currY -= separation;
12664 
12665 			double diff = currY - AObjects[it.value()].y2;
12666 			if (!AObjects[it.value()].Object->locked())
12667 				AObjects[it.value()].Object->moveBy(0.0, diff);
12668 			currY -= AObjects[it.value()].height;
12669 		}
12670 	}
12671 	endAlign();
12672 }
12673 
12674 
itemSelection_DistributeAcrossPage(bool useMargins)12675 void ScribusDoc::itemSelection_DistributeAcrossPage(bool useMargins)
12676 {
12677 	if (!startAlign(2))
12678 		return;
12679 
12680 	QMap<double, int> x1Sorted;
12681 	int alignObjectsCount = AObjects.count();
12682 	for (int i = 0; i < alignObjectsCount; ++i)
12683 	{
12684 		if (!x1Sorted.contains(AObjects[i].x1))
12685 			x1Sorted.insert(AObjects[i].x1, i);
12686 	}
12687 
12688 	double totalSpace = 0.0;
12689 	if (useMargins)
12690 		totalSpace = m_currentPage->width() - m_currentPage->Margins.left() - m_currentPage->Margins.right();
12691 	else
12692 		totalSpace = m_currentPage->width();
12693 	double totalWidth = 0.0;
12694 	uint insideObjectCount = 0;
12695 	for (int i = 0; i < alignObjectsCount; ++i)
12696 	{
12697 		totalWidth += AObjects[i].width;
12698 		++insideObjectCount;
12699 	}
12700 	double separation = (totalSpace - totalWidth) / (insideObjectCount + 1);
12701 	double currX = m_currentPage->xOffset();
12702 	if (useMargins)
12703 		currX += m_currentPage->Margins.left();
12704 	//Handle when our items are too wide for the page.
12705 	if (separation < 0.0)
12706 	{
12707 		separation = (totalSpace - totalWidth) / (insideObjectCount - 1);
12708 		currX -= separation;
12709 	}
12710 
12711 	for (auto it = x1Sorted.constBegin(); it != x1Sorted.constEnd(); ++it)
12712 	{
12713 		currX += separation;
12714 		double diff = currX - AObjects[it.value()].x1;
12715 		if (!AObjects[it.value()].Object->locked())
12716 			AObjects[it.value()].Object->moveBy(diff, 0.0);
12717 		currX += AObjects[it.value()].width;
12718 	}
12719 	endAlign();
12720 }
12721 
12722 
itemSelection_DistributeDownPage(bool useMargins)12723 void ScribusDoc::itemSelection_DistributeDownPage(bool useMargins)
12724 {
12725 	if (!startAlign(2))
12726 		return;
12727 
12728 	QMap<double, int> y1sorted;
12729 	int alignObjectsCount = AObjects.count();
12730 	for (int i = 0; i < alignObjectsCount; ++i)
12731 	{
12732 		if (!y1sorted.contains(AObjects[i].y1))
12733 			y1sorted.insert(AObjects[i].y1, i);
12734 	}
12735 
12736 	double totalSpace = 0.0;
12737 	if (useMargins)
12738 		totalSpace = m_currentPage->height() - m_currentPage->Margins.top() - m_currentPage->Margins.bottom();
12739 	else
12740 		totalSpace = m_currentPage->height();
12741 	double totalHeight = 0.0;
12742 	uint insideObjectCount = 0;
12743 	for (int i = 0; i < alignObjectsCount; ++i)
12744 	{
12745 		totalHeight += AObjects[i].height;
12746 		++insideObjectCount;
12747 	}
12748 	double separation = (totalSpace - totalHeight) / (insideObjectCount + 1);
12749 	double currY = m_currentPage->yOffset();
12750 	if (useMargins)
12751 		currY += m_currentPage->Margins.top();
12752 	//Handle when our items are too high for the page.
12753 	if (separation < 0.0)
12754 	{
12755 		separation = (totalSpace - totalHeight) / (insideObjectCount - 1);
12756 		currY -= separation;
12757 	}
12758 
12759 	for (auto it = y1sorted.constBegin(); it != y1sorted.constEnd(); ++it)
12760 	{
12761 		currY += separation;
12762 		double diff = currY-AObjects[it.value()].y1;
12763 		if (!AObjects[it.value()].Object->locked())
12764 			AObjects[it.value()].Object->moveBy(0.0, diff);
12765 		currY += AObjects[it.value()].height;
12766 	}
12767 	endAlign();
12768 }
12769 
beginUpdate()12770 void ScribusDoc::beginUpdate()
12771 {
12772 	m_docUpdater->beginUpdate();
12773 	m_updateManager.setUpdatesEnabled(false);
12774 }
12775 
endUpdate()12776 void ScribusDoc::endUpdate()
12777 {
12778 	m_updateManager.setUpdatesEnabled(true);
12779 	m_docUpdater->endUpdate();
12780 }
12781 
itemSelection_SwapLeft()12782 void ScribusDoc::itemSelection_SwapLeft()
12783 {
12784 	if (!startAlign(2))
12785 		return;
12786 	int alignObjectsCount = AObjects.count();
12787 	QList<int> circleList;
12788 	int circleListCounter = 0;
12789 	//X
12790 	QMap<double,uint> Xsorted;
12791 	for (int i = 0; i < alignObjectsCount; ++i)
12792 	{
12793 		if (!Xsorted.contains(AObjects[i].x1))
12794 			Xsorted.insert(AObjects[i].x1, i);
12795 	}
12796 	QMap<double,uint>::Iterator itX = Xsorted.begin();
12797 	QMap<double,uint>::Iterator itXend = Xsorted.end();
12798 	double minX = itX.key();
12799 	double maxX = itX.key();
12800 	while (itX != itXend)
12801 	{
12802 		if (minX > itX.key())
12803 			minX = itX.key();
12804 		if (maxX < itX.key())
12805 			maxX = itX.key();
12806 		++itX;
12807 	}
12808 	//Y
12809 	QMap<double,uint> Ysorted;
12810 	for (int i = 0; i < alignObjectsCount; ++i)
12811 	{
12812 		if (!Ysorted.contains(AObjects[i].y1))
12813 			Ysorted.insert(AObjects[i].y1, i);
12814 	}
12815 	QMap<double,uint>::Iterator itY = Ysorted.begin();
12816 	QMap<double,uint>::Iterator itYend = Ysorted.end();
12817 	double minY = itY.key();
12818 	double maxY = itY.key();
12819 	while (itY != itYend)
12820 	{
12821 		if (minY > itY.key())
12822 			minY = itY.key();
12823 		if (maxY < itY.key())
12824 			maxY = itY.key();
12825 		++itY;
12826 	}
12827 
12828 	itX = Xsorted.begin(); //first item is left most
12829 	int itemIndex = itX.value(); //get our first item's index in the AObjects array
12830 //	bool found=false;
12831 //	double itXX=itX.key();
12832 	minY =  std::numeric_limits<double>::max();
12833 	maxY = -std::numeric_limits<double>::max();
12834 	int nextItemIndex = itemIndex;
12835 	circleList.append(nextItemIndex);
12836 	++circleListCounter;
12837 	// find the next X item with the minimum Y
12838 
12839 	QMap<double,uint>::Iterator itX2_1 = Xsorted.begin();
12840 	QMap<double,uint>::Iterator itLast = Xsorted.begin();
12841 	double xBeginYValue = AObjects[itX2_1.value()].y1;
12842 	while (itX2_1 != Xsorted.end())
12843 	{
12844 		if (AObjects[itX2_1.value()].y1 < xBeginYValue)
12845 		{
12846 			circleList.append(itX2_1.value());
12847 			++circleListCounter;
12848 		}
12849 		itLast = itX2_1;
12850 		itX2_1++;
12851 	}
12852 
12853 
12854 	if (circleListCounter != static_cast<int>(alignObjectsCount)) //need to reverse back now
12855 	{
12856 		QMap<double,uint>::Iterator itX2_2 = itLast;
12857 		while (itX2_2 != Xsorted.begin())
12858 		{
12859 			if (AObjects[itX2_2.value()].y1 >= xBeginYValue)
12860 			{
12861 				circleList.append(itX2_2.value());
12862 				++circleListCounter;
12863 			}
12864 			itX2_2--;
12865 		}
12866 	}
12867 
12868 	int i=0;
12869 	double swapX = AObjects[i].x1;
12870 	double swapY = AObjects[i].y1;
12871 	if (!AObjects[i].Object->locked())
12872 		AObjects[i].Object->moveBy(AObjects[circleListCounter-1].x1 - AObjects[i].x1, AObjects[circleListCounter-1].y1 - AObjects[i].y1);
12873 	++i;
12874 	while (i < circleListCounter-1)
12875 	{
12876 		double diffX = swapX-AObjects[i].x1;
12877 		double diffY = swapY-AObjects[i].y1;
12878 		swapX = AObjects[i].x1;
12879 		swapY = AObjects[i].y1;
12880 		if (!AObjects[i].Object->locked())
12881 			AObjects[i].Object->moveBy(diffX, diffY);
12882 		++i;
12883 	}
12884 	double diffX3 = swapX-AObjects[circleListCounter-1].x1;
12885 	double diffY3 = swapY-AObjects[circleListCounter-1].y1;
12886 	if (!AObjects[circleListCounter-1].Object->locked())
12887 		AObjects[circleListCounter-1].Object->moveBy(diffX3, diffY3);
12888 	endAlign();
12889 }
12890 
itemSelection_SwapRight()12891 void ScribusDoc::itemSelection_SwapRight()
12892 {
12893 	if (!startAlign(2))
12894 		return;
12895 	int alignObjectsCount = AObjects.count();
12896 	QList<int> circleList;
12897 	int circleListCounter = 0;
12898 	//X
12899 	QMap<double,uint> Xsorted;
12900 	for (int i = 0; i < alignObjectsCount; ++i)
12901 	{
12902 		if (!Xsorted.contains(AObjects[i].x1))
12903 			Xsorted.insert(AObjects[i].x1, i);
12904 	}
12905 	QMap<double,uint>::Iterator itX = Xsorted.begin();
12906 	QMap<double,uint>::Iterator itXend = Xsorted.end();
12907 	double minX = itX.key();
12908 	double maxX = itX.key();
12909 	while (itX != itXend)
12910 	{
12911 		if (minX > itX.key())
12912 			minX = itX.key();
12913 		if (maxX < itX.key())
12914 			maxX = itX.key();
12915 		++itX;
12916 	}
12917 	//Y
12918 	QMap<double,uint> Ysorted;
12919 	for (int i = 0; i < alignObjectsCount; ++i)
12920 	{
12921 		if (!Ysorted.contains(AObjects[i].y1))
12922 			Ysorted.insert(AObjects[i].y1, i);
12923 	}
12924 	QMap<double,uint>::Iterator itY = Ysorted.begin();
12925 	QMap<double,uint>::Iterator itYend = Ysorted.end();
12926 	double minY = itY.key();
12927 	double maxY = itY.key();
12928 	while (itY != itYend)
12929 	{
12930 		if (minY > itY.key())
12931 			minY = itY.key();
12932 		if (maxY < itY.key())
12933 			maxY = itY.key();
12934 		++itY;
12935 	}
12936 
12937 	itX = Xsorted.begin(); //first item is left most
12938 	int itemIndex = itX.value(); //get our first item's index in the AObjects array
12939 //	bool found=false;
12940 //	double itXX=itX.key();
12941 	minY =  std::numeric_limits<double>::max();
12942 	maxY = -std::numeric_limits<double>::max();
12943 	int nextItemIndex=itemIndex;
12944 	circleList.append(nextItemIndex);
12945 	++circleListCounter;
12946 	// find the next X item with the minimum Y
12947 
12948 	QMap<double,uint>::Iterator itX2_1 = Xsorted.begin();
12949 	QMap<double,uint>::Iterator itLast = Xsorted.begin();
12950 	double xBeginYValue = AObjects[itX2_1.value()].y1;
12951 	while (itX2_1!=Xsorted.end())
12952 	{
12953 		if (AObjects[itX2_1.value()].y1 < xBeginYValue)
12954 		{
12955 			circleList.append(itX2_1.value());
12956 			++circleListCounter;
12957 		}
12958 		itLast = itX2_1;
12959 		itX2_1++;
12960 	}
12961 
12962 
12963 	if (circleListCounter!=static_cast<int>(alignObjectsCount)) //need to reverse back now
12964 	{
12965 		QMap<double,uint>::Iterator itX2_2 = itLast;
12966 		while (itX2_2 != Xsorted.begin())
12967 		{
12968 			if (AObjects[itX2_2.value()].y1 >= xBeginYValue)
12969 			{
12970 				circleList.append(itX2_2.value());
12971 				++circleListCounter;
12972 			}
12973 			itX2_2--;
12974 		}
12975 	}
12976 
12977 	int i = circleListCounter - 1;
12978 	double swapX = AObjects[i].x1;
12979 	double swapY = AObjects[i].y1;
12980 	if (!AObjects[i].Object->locked())
12981 		AObjects[i].Object->moveBy(AObjects[0].x1-AObjects[i].x1, AObjects[0].y1-AObjects[i].y1);
12982 	--i;
12983 	while (i > 0)
12984 	{
12985 		double diffX = swapX - AObjects[i].x1;
12986 		double diffY = swapY - AObjects[i].y1;
12987 		swapX = AObjects[i].x1;
12988 		swapY = AObjects[i].y1;
12989 		if (!AObjects[i].Object->locked())
12990 			AObjects[i].Object->moveBy(diffX, diffY);
12991 		--i;
12992 	}
12993 	double diffX3 = swapX - AObjects[0].x1;
12994 	double diffY3 = swapY - AObjects[0].y1;
12995 	if (!AObjects[0].Object->locked())
12996 		AObjects[0].Object->moveBy(diffX3, diffY3);
12997 	endAlign();
12998 }
12999 
changed()13000 void ScribusDoc::changed()
13001 {
13002 	setModified(true);
13003 	// Do not emit docChanged signal() unnecessarily
13004 	// Processing of that signal is slowwwwwww and
13005 	// DocUpdater will trigger it when necessary
13006 	if (m_docUpdater->inUpdateSession())
13007 	{
13008 		m_docUpdater->setDocChangeNeeded();
13009 		return;
13010 	}
13011 	emit docChanged();
13012 }
13013 
invalidateAll()13014 void ScribusDoc::invalidateAll()
13015 {
13016 	QList<PageItem*> allItems;
13017 	for (int c = 0; c < DocItems.count(); ++c)
13018 	{
13019 		PageItem *ite = DocItems.at(c);
13020 		if (ite->isGroup())
13021 			allItems = ite->getAllChildren();
13022 		else
13023 			allItems.append(ite);
13024 		for (int ii = 0; ii < allItems.count(); ii++)
13025 		{
13026 			ite = allItems.at(ii);
13027 			ite->invalidateLayout();
13028 		}
13029 		allItems.clear();
13030 	}
13031 	for (int c=0; c < MasterItems.count(); ++c)
13032 	{
13033 		PageItem *ite = MasterItems.at(c);
13034 		if (ite->isGroup())
13035 			allItems = ite->getAllChildren();
13036 		else
13037 			allItems.append(ite);
13038 		for (int ii = 0; ii < allItems.count(); ii++)
13039 		{
13040 			ite = allItems.at(ii);
13041 			ite->invalidateLayout();
13042 		}
13043 		allItems.clear();
13044 	}
13045 	// for now hope that frameitems get invalidated by their parents layout() method.
13046 }
13047 
invalidateLayer(int layerID)13048 void ScribusDoc::invalidateLayer(int layerID)
13049 {
13050 	QList<PageItem*> allItems;
13051 	for (int i = 0; i < DocItems.count(); ++i)
13052 	{
13053 		PageItem *ite = DocItems.at(i);
13054 		if (ite->isGroup())
13055 			allItems = ite->getAllChildren();
13056 		else
13057 			allItems.append(ite);
13058 		for (int ii = 0; ii < allItems.count(); ii++)
13059 		{
13060 			ite = allItems.at(ii);
13061 			if (ite->m_layerID == layerID)
13062 					ite->invalidateLayout();
13063 		}
13064 		allItems.clear();
13065 	}
13066 	if (this->masterPageMode())
13067 	{
13068 		for (int i = 0; i < MasterItems.count(); ++i)
13069 		{
13070 			PageItem *ite = MasterItems.at(i);
13071 			if (ite->isGroup())
13072 				allItems = ite->getAllChildren();
13073 			else
13074 				allItems.append(ite);
13075 			for (int ii = 0; ii < allItems.count(); ii++)
13076 			{
13077 				ite = allItems.at(ii);
13078 				if (ite->m_layerID == layerID)
13079 					ite->invalidateLayout();
13080 			}
13081 			allItems.clear();
13082 		}
13083 	}
13084 	// for now hope that frameitems get invalidated by their parents layout() method.
13085 }
13086 
invalidateRegion(QRectF region)13087 void ScribusDoc::invalidateRegion(QRectF region)
13088 {
13089 	QList<PageItem*> allItems;
13090 	for (int i = 0; i < DocItems.count(); ++i)
13091 	{
13092 		PageItem *ite = DocItems.at(i);
13093 		if (ite->isGroup())
13094 			allItems = ite->getAllChildren();
13095 		else
13096 			allItems.append(ite);
13097 		for (int ii = 0; ii < allItems.count(); ii++)
13098 		{
13099 			ite = allItems.at(ii);
13100 			if (ite->getBoundingRect().intersects(region))
13101 				ite->invalidateLayout();
13102 		}
13103 		allItems.clear();
13104 	}
13105 	for (int i = 0; i < MasterItems.count(); ++i)
13106 	{
13107 		PageItem *ite = MasterItems.at(i);
13108 		if (ite->isGroup())
13109 			allItems = ite->getAllChildren();
13110 		else
13111 			allItems.append(ite);
13112 		for (int ii = 0; ii < allItems.count(); ii++)
13113 		{
13114 			ite = allItems.at(ii);
13115 		// for now invalidate all masteritems, should be only necessary in masterpagemode
13116 			ite->invalidateLayout();
13117 		}
13118 		allItems.clear();
13119 	}
13120 	// for now hope that frameitems get invalidated by their parents layout() method.
13121 }
13122 
13123 
currentPage()13124 ScPage* ScribusDoc::currentPage()
13125 {
13126 	return m_currentPage;
13127 }
13128 
13129 
setCurrentPage(ScPage * newPage)13130 void ScribusDoc::setCurrentPage(ScPage *newPage)
13131 {
13132 	if (newPage == nullptr)
13133 		return;
13134 	m_currentPage = newPage;
13135 	if (m_ScMW)
13136 	{
13137 		m_ScMW->guidePalette->setDoc(this);
13138 		if (!isLoading())
13139 		{
13140 			// #9476 : call setupPage with false arg to setup only guidePalette GUI
13141 			// Otherwise expect problems when applying masterpages with guides
13142 			m_ScMW->guidePalette->setupPage(false);
13143 			m_ScMW->pagePalette->markPage(newPage->pageNr());
13144 		}
13145 	}
13146 	m_constants.insert("pagewidth", newPage->width());
13147 	m_constants.insert("pageheight", newPage->height());
13148 	m_constants.insert("marginleft", newPage->Margins.left());
13149 	m_constants.insert("marginright", newPage->width() - newPage->Margins.right());
13150 	m_constants.insert("margintop", newPage->Margins.top());
13151 	m_constants.insert("marginbottom", newPage->height() - newPage->Margins.bottom());
13152 }
13153 
13154 
ApplyGrid(const QPoint & in)13155 QPoint ScribusDoc::ApplyGrid(const QPoint& in)
13156 {
13157 	int onp = OnPage(in.x(), in.y());
13158 	if (!SnapGrid || (onp == -1))
13159 		return in;
13160 
13161 	QPoint np;
13162 	const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13163 	double pageX = Pages->at(onp)->xOffset();
13164 	double pageY = Pages->at(onp)->yOffset();
13165 	np.setX(static_cast<int>(qRound((in.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX));
13166 	np.setY(static_cast<int>(qRound((in.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY));
13167 	return np;
13168 }
13169 
13170 
ApplyGridF(const FPoint & in)13171 FPoint ScribusDoc::ApplyGridF(const FPoint& in)
13172 {
13173 	int onp = OnPage(in.x(), in.y());
13174 	if (!SnapGrid || (onp == -1))
13175 		return in;
13176 
13177 	FPoint np;
13178 	const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13179 	double pageX = Pages->at(onp)->xOffset();
13180 	double pageY = Pages->at(onp)->yOffset();
13181 	np.setX(qRound((in.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX);
13182 	np.setY(qRound((in.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY);
13183 	return np;
13184 }
13185 
ApplyGridF(const QRectF & in)13186 QRectF ScribusDoc::ApplyGridF(const QRectF& in)
13187 {
13188 	QRectF nr(in);
13189 	if (!SnapGrid)
13190 		return nr;
13191 
13192 	bool   onPage = false;
13193 	double dX = m_docPrefsData.guidesPrefs.minorGridSpacing;
13194 	double dY = m_docPrefsData.guidesPrefs.minorGridSpacing;
13195 	double newX = in.x(), newY = in.y();
13196 	double pageX, pageY;
13197 
13198 	FPoint fp1(in.x(), in.y());
13199 	FPoint fp2(in.x(), in.y() + in.height());
13200 	FPoint fp3(in.x() + in.width(), in.y());
13201 	FPoint fp4(in.x() + in.width(), in.y() + in.height());
13202 
13203 	int onp = OnPage(fp1.x(), fp1.y());
13204 	if (onp >= 0)
13205 	{
13206 		const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13207 		pageX = Pages->at(onp)->xOffset();
13208 		pageY = Pages->at(onp)->yOffset();
13209 		newX  = qRound((fp1.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX;
13210 		newY  = qRound((fp1.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY;
13211 		if (fabs(newX - fp1.x()) < fabs(dX))
13212 			dX = newX - fp1.x();
13213 		if (fabs(newY - fp1.y()) < fabs(dY))
13214 			dY = newY - fp1.y();
13215 		onPage = true;
13216 	}
13217 
13218 	onp = OnPage(fp2.x(), fp2.y());
13219 	if (onp >= 0)
13220 	{
13221 		const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13222 		pageX = Pages->at(onp)->xOffset();
13223 		pageY = Pages->at(onp)->yOffset();
13224 		newX  = qRound((fp2.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX;
13225 		newY  = qRound((fp2.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY;
13226 		if (fabs(newX - fp2.x()) < fabs(dX))
13227 			dX = newX - fp2.x();
13228 		if (fabs(newY - fp2.y()) < fabs(dY))
13229 			dY = newY - fp2.y();
13230 		onPage = true;
13231 	}
13232 
13233 	onp = OnPage(fp3.x(), fp3.y());
13234 	if (onp >= 0)
13235 	{
13236 		const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13237 		pageX = Pages->at(onp)->xOffset();
13238 		pageY = Pages->at(onp)->yOffset();
13239 		newX  = qRound((fp3.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX;
13240 		newY  = qRound((fp3.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY;
13241 		if (fabs(newX - fp3.x()) < fabs(dX))
13242 			dX = newX - fp3.x();
13243 		if (fabs(newY - fp3.y()) < fabs(dY))
13244 			dY = newY - fp3.y();
13245 		onPage = true;
13246 	}
13247 
13248 	onp = OnPage(fp4.x(), fp4.y());
13249 	if (onp >= 0)
13250 	{
13251 		const GuidesPrefs& guidesPrefs = m_docPrefsData.guidesPrefs;
13252 		pageX = Pages->at(onp)->xOffset();
13253 		pageY = Pages->at(onp)->yOffset();
13254 		newX  = qRound((fp4.x() - pageX) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageX;
13255 		newY  = qRound((fp4.y() - pageY) / guidesPrefs.minorGridSpacing) * guidesPrefs.minorGridSpacing + pageY;
13256 		if (fabs(newX - fp4.x()) < fabs(dX))
13257 			dX = newX - fp4.x();
13258 		if (fabs(newY - fp4.y()) < fabs(dY))
13259 			dY = newY - fp4.y();
13260 		onPage = true;
13261 	}
13262 
13263 	if (onPage)
13264 		nr.translate(dX, dY);
13265 	return nr;
13266 }
13267 
itemSelection_Duplicate(double shiftX,double shiftY,Selection * customSelection)13268 void ScribusDoc::itemSelection_Duplicate(double shiftX, double shiftY, Selection* customSelection)
13269 {
13270 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
13271 	assert(itemSelection != nullptr);
13272 
13273 	bool savedAlignGrid = this->SnapGrid;
13274 	bool savedAlignGuides = this->SnapGuides;
13275 	bool savedAlignElement = this->SnapElement;
13276 	this->SnapGrid  = false;
13277 	this->SnapGuides = false;
13278 	this->SnapElement = false;
13279 
13280 	UndoTransaction trans;
13281 	if (UndoManager::undoEnabled())
13282 		trans = m_undoManager->beginTransaction(Um::Selection, Um::IPolygon, Um::Duplicate, QString(), Um::IMultipleDuplicate);
13283 
13284 	ItemMultipleDuplicateData mdData;
13285 	mdData.type = 0;
13286 	mdData.copyCount = 1;
13287 	mdData.copyShiftOrGap = 0;
13288 	mdData.copyShiftGapH = shiftX;
13289 	mdData.copyShiftGapV = shiftY;
13290 
13291 	int oldItemCount = Items->count();
13292 	m_Selection->delaySignalsOn();
13293 	itemSelection_MultipleDuplicate(mdData, itemSelection);
13294 	m_Selection->clear();
13295 	for (int i = oldItemCount; i < Items->count(); ++i)
13296 	{
13297 		PageItem* item = Items->at(i);
13298 		m_Selection->addItem(item);
13299 	}
13300 	m_Selection->delaySignalsOff();
13301 
13302 	if (trans)
13303 		trans.commit();
13304 
13305 	this->SnapGrid  = savedAlignGrid;
13306 	this->SnapGuides = savedAlignGuides;
13307 	this->SnapElement = savedAlignElement;
13308 
13309 	regionsChanged()->update(QRectF());
13310 }
13311 
itemSelection_MultipleDuplicate(const ItemMultipleDuplicateData & mdData,Selection * customSelection)13312 void ScribusDoc::itemSelection_MultipleDuplicate(const ItemMultipleDuplicateData& mdData, Selection* customSelection)
13313 {
13314 	if ((mdData.type == 0 && mdData.copyCount < 1) || (mdData.type == 1 && (mdData.gridRows == 1 && mdData.gridCols == 1)))
13315 		return;
13316 	if ((mdData.type == 2) && (Pages->count() == 1))
13317 		return;
13318 
13319 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
13320 	assert(itemSelection != nullptr);
13321 
13322 	QString tooltip;
13323 	UndoTransaction activeTransaction;
13324 
13325 	if (UndoManager::undoEnabled())
13326 	{ // Make multiple duplicate a single action in the action history
13327 		if (itemSelection->count() > 1)
13328 			activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::MultipleDuplicate, "", Um::IMultipleDuplicate);
13329 		else
13330 		{
13331 			PageItem* item = itemSelection->itemAt(0);
13332 			activeTransaction = m_undoManager->beginTransaction(item->getUName(), item->getUPixmap(), Um::MultipleDuplicate, "", Um::IMultipleDuplicate);
13333 		}
13334 	}
13335 	DoDrawing = false;
13336 	view()->updatesOn(false);
13337 
13338 	QList<PageItem*> selectedItems = itemSelection->items();
13339 	std::stable_sort(selectedItems.begin(), selectedItems.end(), compareItemLevel);
13340 
13341 	Selection selection(this, false);
13342 	for (int i = 0; i < selectedItems.count(); ++i)
13343 		selection.addItem(selectedItems.at(i));
13344 
13345 	if (mdData.type == 0) // Copy and offset or set a gap
13346 	{
13347 		double dH = mdData.copyShiftGapH / m_docUnitRatio;
13348 		double dV = mdData.copyShiftGapV / m_docUnitRatio;
13349 		double dH2 = dH;
13350 		double dV2 = dV;
13351 		double dR = mdData.copyRotation;
13352 		double dR2 = dR;
13353 		if (mdData.copyShiftOrGap == 1)
13354 		{
13355 			if (dH != 0.0)
13356 				dH2 += selection.width();
13357 			if (dV != 0.0)
13358 				dV2 += selection.height();
13359 		}
13360 		ScriXmlDoc ss;
13361 		QString BufferS = ss.writeElem(this, &selection);
13362 		//FIXME: stop using m_View
13363 		Selection tempSelection(nullptr, false);
13364 		m_View->deselectItems(true);
13365 		for (int i = 0; i < mdData.copyCount; ++i)
13366 		{
13367 			int oldItemCount = Items->count();
13368 			ss.readElem(BufferS, this, m_currentPage->xOffset(), m_currentPage->yOffset(), false, true);
13369 			tempSelection.delaySignalsOn();
13370 			for (int j = oldItemCount; j < Items->count(); ++j)
13371 			{
13372 				PageItem* bItem = Items->at(j);
13373 				bItem->setLocked(false);
13374 				bItem->moveBy(dH2, dV2, true);
13375 				if (bItem->isGroup())
13376 					GroupOnPage(bItem);
13377 				else
13378 					bItem->OwnPage = OnPage(bItem);
13379 				tempSelection.addItem(bItem);
13380 			}
13381 			tempSelection.delaySignalsOff();
13382 			tempSelection.setGroupRect();
13383 			if (dR != 0.0)
13384 			{
13385 				if (tempSelection.count() > 1)
13386 					rotateGroup(dR2, &tempSelection); //FIXME:av
13387 				else
13388 					rotateItem(dR2, tempSelection.itemAt(0));
13389 			}
13390 			dH2 += dH;
13391 			dV2 += dV;
13392 			if (mdData.copyShiftOrGap == 1)
13393 			{
13394 				if (dH != 0.0)
13395 					dH2 += tempSelection.width();
13396 				if (dV != 0.0)
13397 					dV2 += tempSelection.height();
13398 			}
13399 			dR2 += dR;
13400 			tempSelection.clear();
13401 		}
13402 		QString unitSuffix = unitGetStrFromIndex(this->unitIndex());
13403 		int unitPrecision = unitGetPrecisionFromIndex(this->unitIndex());
13404 		QString hString = QString::number(dH * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
13405 		QString vString = QString::number(dV * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
13406 		QString dString = QString::number(dR) + " " + unitGetStrFromIndex(SC_DEGREES);
13407 		tooltip = tr("Number of copies: %1\nHorizontal shift: %2\nVertical shift: %3\nRotation: %4").arg(mdData.copyCount).arg(hString, vString, dString);
13408 	}
13409 	else if (mdData.type == 1) // Create a grid of duplicated items
13410 	{
13411 		double dX = mdData.gridGapH / m_docUnitRatio + selection.width();
13412 		double dY = mdData.gridGapV / m_docUnitRatio + selection.height();
13413 		ScriXmlDoc ss;
13414 		QString BufferS = ss.writeElem(this, &selection);
13415 		for (int i = 0; i < mdData.gridRows; ++i) //skip 0, the item is the one we are copying
13416 		{
13417 			for (int j = 0; j < mdData.gridCols; ++j) //skip 0, the item is the one we are copying
13418 			{
13419 				// We can comment out this conditional jump if we use slotEditCut(), would not be cool? ;-)
13420 				if (i == 0 && j == 0)
13421 					continue;
13422 				uint ac = Items->count();
13423 				ss.readElem(BufferS, this, m_currentPage->xOffset(), m_currentPage->yOffset(), false, true);
13424 				for (int as = ac; as < Items->count(); ++as)
13425 				{
13426 					PageItem* bItem = Items->at(as);
13427 					bItem->setLocked(false);
13428 					bItem->moveBy(j * dX, i * dY, true);
13429 					if (bItem->isGroup())
13430 						GroupOnPage(bItem);
13431 					else
13432 						bItem->OwnPage = OnPage(bItem);
13433 				}
13434 			}
13435 		}
13436 		QString unitSuffix = unitGetStrFromIndex(this->unitIndex());
13437 		int unitPrecision = unitGetPrecisionFromIndex(this->unitIndex());
13438 		QString hString = QString::number(mdData.gridGapH, 'f', unitPrecision) + " " + unitSuffix;
13439 		QString vString = QString::number(mdData.gridGapV, 'f', unitPrecision) + " " + unitSuffix;
13440 		tooltip = tr("Number of rows: %1\nNumber of columns: %2\nHorizontal gap: %3\nVertical gap: %4").arg(mdData.gridRows).arg(mdData.gridCols).arg(hString, vString, unitSuffix);
13441 	}
13442 	else if (mdData.type == 2)
13443 	{
13444 		multipleDuplicateByPage(mdData, selection, tooltip);
13445 	}
13446 	if (activeTransaction)
13447 	{
13448 		activeTransaction.commit("", nullptr, "", tooltip, nullptr);
13449 	}
13450 	DoDrawing = true;
13451 	view()->updatesOn(true);
13452 	//FIXME: stop using m_View
13453 	m_View->deselectItems(true);
13454 
13455 	regionsChanged()->update(QRectF());
13456 	changed();
13457 }
13458 
multipleDuplicateByPage(const ItemMultipleDuplicateData & dialogData,Selection & selection,QString & tooltip)13459 void ScribusDoc::multipleDuplicateByPage(const ItemMultipleDuplicateData& dialogData, Selection& selection, QString& tooltip)
13460 {
13461 	int currPageNumber = currentPageNumber();
13462 	std::vector<int> pages;
13463 	QString pageRange;
13464 
13465 	if (!m_Selection->itemsAreOnSamePage())
13466 	{
13467 		int firstPage = Pages->count(), lastPage = 0;
13468 		for (auto item: selection.items())
13469 		{
13470 			if ((item->OwnPage >= 0) && (item->OwnPage < firstPage))
13471 				firstPage = item->OwnPage;
13472 			if ((item->OwnPage) >= 0 && (item->OwnPage > lastPage))
13473 				lastPage = item->OwnPage;
13474 		}
13475 		setCurrentPage(Pages->at(firstPage));
13476 		int pageSpread = lastPage - firstPage + 1;
13477 		QStringList pageList;
13478 		if (dialogData.pageSelection == 1)
13479 			for (int i = lastPage + 2; i < Pages->count(); i += pageSpread)
13480 				pageList << QString::number(i);
13481 		else if (dialogData.pageSelection == 4)
13482 		{
13483 			// TODO: what to do with manual selections?
13484 			pageRange = dialogData.pageRange;
13485 		}
13486 		pageRange = pageList.join(',');
13487 	}
13488 	else if (dialogData.pageSelection == 1)
13489 		pageRange = QString("%1-%2").arg(currPageNumber + 2).arg(Pages->count());
13490 	else if ((dialogData.pageSelection == 2) || dialogData.pageSelection == 3)
13491 	{
13492 		int start = currPageNumber + 2;
13493 		// round to the next odd / even number
13494 		if (dialogData.pageSelection == 2)
13495 			start += start % 2;
13496 		else
13497 			start += 1 - (start % 2);
13498 
13499 		QStringList pageList;
13500 		for (int i = start; i <= Pages->count(); i += 2)
13501 			pageList << QString::number(i);
13502 		pageRange = pageList.join(',');
13503 	}
13504 	else if (dialogData.pageSelection == 4)
13505 	{
13506 		pageRange = dialogData.pageRange;
13507 	}
13508 	parsePagesString(pageRange, &pages, Pages->count());
13509 
13510 	PageItem* lastInChain = nullptr;
13511 	if (dialogData.pageLinkText)
13512 	{
13513 		for (auto item: selection.items())
13514 		{
13515 			// get the first text frame in the selection, the first frame in the chain
13516 			if (item->itemType() != PageItem::TextFrame)
13517 				continue;
13518 			if (item->isInChain())
13519 				lastInChain = item->lastInChain();
13520 			else
13521 				lastInChain = item;
13522 			break;
13523 		}
13524 	}
13525 
13526 	ScPage* oldCurrentPage = currentPage();
13527 	ScriXmlDoc xmlStream;
13528 	QString buffer = xmlStream.writeElem(this, &selection);
13529 	for (const auto page: pages)
13530 	{
13531 		if (currPageNumber == page - 1)
13532 			continue;
13533 		ScPage* targetPage = Pages->at(page - 1);
13534 		setCurrentPage(targetPage);
13535 		int countBeforeInsert = Items->count();
13536 		xmlStream.readElem(buffer, this, currentPage()->xOffset(), currentPage()->yOffset(), false, true);
13537 		if (!lastInChain)
13538 			continue;
13539 		for (int i = countBeforeInsert; i < Items->count(); ++i)
13540 		{
13541 			PageItem* item = Items->at(i);
13542 			if (item->itemType() != PageItem::TextFrame)
13543 				continue;
13544 			item->clearContents();
13545 			if (item->isInChain())
13546 			{
13547 				lastInChain->link(item->firstInChain());
13548 				lastInChain = item->lastInChain();
13549 			}
13550 			else
13551 			{
13552 				lastInChain->link(item);
13553 				lastInChain = item;
13554 			}
13555 			break;
13556 		}
13557 	}
13558 
13559 	setCurrentPage(oldCurrentPage);
13560 
13561 	tooltip = tr("Copied %1 items on %2 pages").arg(selection.count()).arg(pages.size());
13562 }
13563 
13564 
itemSelection_ApplyImageEffects(ScImageEffectList & newEffectList,Selection * customSelection)13565 void ScribusDoc::itemSelection_ApplyImageEffects(ScImageEffectList& newEffectList, Selection* customSelection)
13566 {
13567 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
13568 	assert(itemSelection != nullptr);
13569 	int selectedItemCount = itemSelection->count();
13570 	if (selectedItemCount == 0)
13571 		return;
13572 	PageItem *currItem = itemSelection->itemAt(0);
13573 	ScImageEffectList oldEffects(currItem->effectsInUse);
13574 	currItem->effectsInUse = newEffectList;
13575 	updatePic();
13576 
13577 	if (UndoManager::undoEnabled())
13578 	{
13579 		ScItemState<QPair<ScImageEffectList, ScImageEffectList> > *state =
13580 				new ScItemState<QPair<ScImageEffectList, ScImageEffectList> >(
13581 					Um::ImageEffects, "", currItem->getUPixmap());
13582 		state->set("APPLY_IMAGE_EFFECTS");
13583 		state->setItem(qMakePair(oldEffects, currItem->effectsInUse));
13584 		m_undoManager->action(currItem, state);
13585 	}
13586 	changed();
13587 }
13588 
13589 
itemSelection_ApplyArrowHead(int startArrowID,int endArrowID,Selection * customSelection)13590 void ScribusDoc::itemSelection_ApplyArrowHead(int startArrowID, int endArrowID, Selection* customSelection)
13591 {
13592 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
13593 	assert(itemSelection != nullptr);
13594 	int selectedItemCount = itemSelection->count();
13595 	if (selectedItemCount == 0)
13596 		return;
13597 
13598 	if ((startArrowID < 0) && (endArrowID < 0))
13599 		return;
13600 
13601 	UndoTransaction activeTransaction;
13602 	m_updateManager.setUpdatesDisabled();
13603 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
13604 		activeTransaction = m_undoManager->beginTransaction();
13605 	QString tooltip = Um::ItemsInvolved + "\n";
13606 	if (selectedItemCount > Um::ItemsInvolvedLimit)
13607 		tooltip = Um::ItemsInvolved2 + "\n";
13608 
13609 	QRectF updateRect;
13610 	for (int i = 0; i < selectedItemCount; ++i)
13611 	{
13612 		PageItem *currItem = itemSelection->itemAt(i);
13613 		if (!(currItem->isLine() || currItem->asPolyLine() || currItem->asSpiral()))
13614 			continue;
13615 		updateRect = updateRect.united(currItem->getBoundingRect());
13616 		if (startArrowID != -1)
13617 			currItem->setStartArrowIndex(startArrowID);
13618 		if (endArrowID != -1)
13619 			currItem->setEndArrowIndex(endArrowID);
13620 		updateRect = updateRect.united(currItem->getBoundingRect());
13621 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
13622 			tooltip += "\t" + currItem->getUName() + "\n";
13623 		//currItem->update();
13624 	}
13625 
13626 	if (!updateRect.isEmpty())
13627 		regionsChanged()->update(updateRect);
13628 
13629 	QString undoText;
13630 	if (startArrowID!=-1 && endArrowID!=-1)
13631 		undoText = Um::StartAndEndArrow;
13632 	else
13633 		undoText = (startArrowID != -1) ? Um::StartArrow : Um::EndArrow;
13634 	if (activeTransaction)
13635 	{
13636 		activeTransaction.commit(Um::Selection,
13637 								 Um::IGroup,
13638 								 undoText,
13639 								 tooltip,
13640 								 Um::IArrow);
13641 	}
13642 	m_updateManager.setUpdatesEnabled();
13643 	changed();
13644 }
13645 
itemSelection_ApplyArrowScale(int startArrowSc,int endArrowSc,Selection * customSelection)13646 void ScribusDoc::itemSelection_ApplyArrowScale(int startArrowSc, int endArrowSc, Selection* customSelection)
13647 {
13648 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
13649 	assert(itemSelection != nullptr);
13650 	int selectedItemCount = itemSelection->count();
13651 	if (selectedItemCount == 0)
13652 		return;
13653 
13654 	UndoTransaction activeTransaction;
13655 	m_updateManager.setUpdatesDisabled();
13656 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
13657 		activeTransaction = m_undoManager->beginTransaction();
13658 	QString tooltip = Um::ItemsInvolved + "\n";
13659 	if (selectedItemCount > Um::ItemsInvolvedLimit)
13660 		tooltip = Um::ItemsInvolved2 + "\n";
13661 	for (int i = 0; i < selectedItemCount; ++i)
13662 	{
13663 		PageItem *currItem = itemSelection->itemAt(i);
13664 		if (!(currItem->isLine() || currItem->isPolyLine() || currItem->isSpiral()))
13665 			continue;
13666 		if (startArrowSc !=  -1)
13667 			currItem->setStartArrowScale(startArrowSc);
13668 		if (endArrowSc != -1)
13669 			currItem->setEndArrowScale(endArrowSc);
13670 		if (selectedItemCount <= Um::ItemsInvolvedLimit)
13671 			tooltip += "\t" + currItem->getUName() + "\n";
13672 		currItem->update();
13673 	}
13674 	QString undoText;
13675 	if (startArrowSc!=-1 && endArrowSc!=-1)
13676 		undoText=Um::StartAndEndArrow;
13677 	else
13678 		undoText=(startArrowSc!=-1) ? Um::StartArrow : Um::EndArrow;
13679 	if (activeTransaction)
13680 	{
13681 		activeTransaction.commit(Um::Selection,
13682 								 Um::IGroup,
13683 								 undoText,
13684 								 tooltip,
13685 								 Um::IArrow);
13686 	}
13687 	m_updateManager.setUpdatesEnabled();
13688 	changed();
13689 }
13690 
13691 
createDefaultMasterPages()13692 void ScribusDoc::createDefaultMasterPages()
13693 {
13694 	int setcol = pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns;
13695 	if (setcol == 1)
13696 	{
13697 		addMasterPage(0, CommonStrings::trMasterPageNormal);
13698 	}
13699 	else if (setcol == 2)
13700 	{
13701 		ScPage *lp = addMasterPage(0, CommonStrings::trMasterPageNormalLeft);
13702 		lp->LeftPg = 1;
13703 		lp->Margins.setLeft(lp->initialMargins.right());
13704 		lp->Margins.setRight(lp->initialMargins.left());
13705 		lp = addMasterPage(1, CommonStrings::trMasterPageNormalRight);
13706 		lp->LeftPg = 0;
13707 		lp->Margins.setRight(lp->initialMargins.right());
13708 		lp->Margins.setLeft(lp->initialMargins.left());
13709 	}
13710 	else if ((setcol == 3) || (setcol == 4))
13711 	{
13712 		ScPage *lp = addMasterPage(0, CommonStrings::trMasterPageNormalLeft);
13713 		lp->LeftPg = 1;
13714 		lp->Margins.setLeft(lp->initialMargins.right());
13715 		lp->Margins.setRight(lp->initialMargins.left());
13716 		lp = addMasterPage(1, CommonStrings::trMasterPageNormalRight);
13717 		lp->LeftPg = 0;
13718 		lp->Margins.setRight(lp->initialMargins.right());
13719 		lp->Margins.setLeft(lp->initialMargins.left());
13720 		lp = addMasterPage(2, CommonStrings::trMasterPageNormalMiddle);
13721 		lp->LeftPg = 2;
13722 		lp->Margins.setLeft(lp->initialMargins.left());
13723 		lp->Margins.setRight(lp->initialMargins.left());
13724 	}
13725 }
13726 
13727 
createNewDocPages(int pageCount)13728 void ScribusDoc::createNewDocPages(int pageCount)
13729 {
13730 	int setcol = pageSets()[m_docPrefsData.docSetupPrefs.pagePositioning].Columns;
13731 	int createCount=qMax(pageCount, 1);
13732 	if (setcol == 1)
13733 	{
13734 		for (int i = 0; i < createCount; ++i)
13735 			addPage(i, CommonStrings::trMasterPageNormal, true);
13736 	}
13737 	else if (setcol == 2)
13738 	{
13739 		for (int i = 0; i < createCount; ++i)
13740 		{
13741 			PageLocation pageLoc = locationOfPage(i);
13742 			if (pageLoc == LeftPage)
13743 				addPage(i, CommonStrings::trMasterPageNormalLeft, true);
13744 			else
13745 				addPage(i, CommonStrings::trMasterPageNormalRight, true);
13746 		}
13747 	}
13748 	else if ((setcol == 3) || (setcol == 4))
13749 	{
13750 		for (int i = 0; i < createCount; ++i)
13751 		{
13752 			PageLocation pageLoc = locationOfPage(i);
13753 			if (pageLoc == LeftPage)
13754 				addPage(i, CommonStrings::trMasterPageNormalLeft, true);
13755 			else if (pageLoc == RightPage)
13756 				addPage(i, CommonStrings::trMasterPageNormalRight, true);
13757 			else
13758 				addPage(i, CommonStrings::trMasterPageNormalMiddle, true);
13759 		}
13760 	}
13761 }
13762 
13763 
getClosestGuides(double xin,double yin,double * xout,double * yout,ScPage * refPage)13764 void ScribusDoc::getClosestGuides(double xin, double yin, double *xout, double *yout, ScPage* refPage)
13765 {
13766 	int gxM = -1;
13767 	int gyM = -1;
13768 	ScPage* page = (refPage == nullptr) ? currentPage() : refPage;
13769 	QMap<double, uint> tmpGuidesSel;
13770 	Guides tmpGuides = page->guides.horizontals(GuideManagerCore::Standard);
13771 	Guides::iterator it;
13772 	double viewScale = m_View->scale();
13773 	const double snappingDistance = prefsData().guidesPrefs.guideRad / viewScale;
13774 
13775 	*xout = xin;
13776 	*yout = yin;
13777 
13778 	uint xg = 0;
13779 	uint yg = 0;
13780 	for (it = tmpGuides.begin(); it != tmpGuides.end(); ++it, ++yg)
13781 	{
13782 		if (fabs((*it) + page->yOffset() - yin) < snappingDistance)
13783 			tmpGuidesSel.insert(fabs((*it) + page->yOffset() - yin), yg);
13784 	}
13785 	if (tmpGuidesSel.count() != 0)
13786 	{
13787 		gyM = tmpGuidesSel.begin().value();
13788 		*yout = tmpGuides[gyM] + page->yOffset();
13789 	}
13790 	tmpGuidesSel.clear();
13791 	tmpGuides = page->guides.verticals(GuideManagerCore::Standard);
13792 	for (it = tmpGuides.begin(); it != tmpGuides.end(); ++it, ++xg)
13793 	{
13794 		if (fabs((*it) + page->xOffset() - xin) < snappingDistance)
13795 			tmpGuidesSel.insert(fabs((*it) + page->xOffset() - xin), xg);
13796 	}
13797 	if (tmpGuidesSel.count() != 0)
13798 	{
13799 		gxM = tmpGuidesSel.begin().value();
13800 		*xout = tmpGuides[gxM] + page->xOffset();
13801 	}
13802 	yg = 0;
13803 	xg = 0;
13804 	tmpGuidesSel.clear();
13805 	tmpGuides = page->guides.horizontals(GuideManagerCore::Auto);
13806 	for (it = tmpGuides.begin(); it != tmpGuides.end(); ++it, ++yg)
13807 	{
13808 		if (fabs((*it) + page->yOffset() - yin) < snappingDistance)
13809 			tmpGuidesSel.insert(fabs((*it) + page->yOffset() - yin), yg);
13810 	}
13811 	if (tmpGuidesSel.count() != 0)
13812 	{
13813 		gyM = tmpGuidesSel.begin().value();
13814 		*yout = tmpGuides[gyM] + page->yOffset();
13815 	}
13816 	tmpGuidesSel.clear();
13817 	tmpGuides = page->guides.verticals(GuideManagerCore::Auto);
13818 	for (it = tmpGuides.begin(); it != tmpGuides.end(); ++it, ++xg)
13819 	{
13820 		if (fabs((*it) + page->xOffset() - xin) < snappingDistance)
13821 			tmpGuidesSel.insert(fabs((*it) + page->xOffset() - xin), xg);
13822 	}
13823 	if (tmpGuidesSel.count() != 0)
13824 	{
13825 		gxM = tmpGuidesSel.begin().value();
13826 		*xout = tmpGuides[gxM] + page->xOffset();
13827 	}
13828 }
13829 
getClosestElementBorder(double xin,double yin,double * xout,double * yout,SelectionSkipBehavior behavior)13830 void ScribusDoc::getClosestElementBorder(double xin, double yin, double *xout, double *yout, SelectionSkipBehavior behavior)
13831 {
13832 	int gxM = -1;
13833 	int gyM = -1;
13834 	QMap<double, uint> tmpGuidesSel;
13835 	double viewScale = m_View->scale();
13836 	const double snappingDistance = prefsData().guidesPrefs.guideRad / viewScale;
13837 
13838 	*xout = xin;
13839 	*yout = yin;
13840 
13841 	QList<PageItem*> items = getAllItems(*Items);
13842 	PageItem *parentI = nullptr;
13843 	if (m_Selection->count() > 0)
13844 		parentI = m_Selection->itemAt(0)->Parent;
13845 
13846 	for (int i = 0; i < items.size(); ++i)
13847 	{
13848 		if ((behavior == ExcludeSelection) && m_Selection->containsItem(items.at(i)))
13849 			continue;
13850 		if (items.at(i)->OwnPage != OnPage(xin, yin))
13851 			continue;
13852 		if (items.at(i)->Parent != parentI)
13853 			continue;
13854 		double visualYPos = items.at(i)->visualYPos();
13855 		double visualHeight = items.at(i)->visualHeight();
13856 		if (fabs(visualYPos - yin) < snappingDistance)
13857 			tmpGuidesSel.insert(fabs(visualYPos - yin), i * 3);
13858 		else if (fabs(visualYPos + visualHeight - yin) < snappingDistance)
13859 			tmpGuidesSel.insert(fabs(visualYPos + visualHeight - yin), i * 3 + 1);
13860 		else if (fabs(visualYPos + visualHeight / 2 - yin) < snappingDistance)
13861 			tmpGuidesSel.insert(fabs(visualYPos + visualHeight / 2 - yin), i * 3 + 2);
13862 	}
13863 	if (tmpGuidesSel.count() != 0)
13864 	{
13865 		gyM = tmpGuidesSel.begin().value();
13866 		if (gyM % 3 == 0)
13867 			*yout = items.at(gyM / 3)->visualYPos();
13868 		else if (gyM %3 == 1)
13869 			*yout = items.at(gyM / 3)->visualYPos() + items.at(gyM / 3)->visualHeight();
13870 		else if (gyM %3 == 2)
13871 			*yout = items.at(gyM / 3)->visualYPos() + items.at(gyM / 3)->visualHeight() / 2;
13872 	}
13873 	tmpGuidesSel.clear();
13874 
13875 	for (int i = 0; i < items.size(); ++i)
13876 	{
13877 		if ((behavior == ExcludeSelection) && m_Selection->containsItem(items.at(i)))
13878 			continue;
13879 		if (items.at(i)->OwnPage != OnPage(xin, yin))
13880 			continue;
13881 		if (items.at(i)->Parent != parentI)
13882 			continue;
13883 		double visualXPos = items.at(i)->visualXPos();
13884 		double visualWidth = items.at(i)->visualWidth();
13885 		if (fabs(visualXPos - xin) < snappingDistance)
13886 			tmpGuidesSel.insert(fabs(visualXPos - xin), i * 3);
13887 		else if (fabs(visualXPos + visualWidth - xin) < snappingDistance)
13888 			tmpGuidesSel.insert(fabs(visualXPos + visualWidth - xin), i * 3 + 1);
13889 		else if (fabs(visualXPos + visualWidth / 2 - xin) < snappingDistance)
13890 			tmpGuidesSel.insert(fabs(visualXPos + visualWidth / 2 - xin), i * 3 + 2);
13891 	}
13892 	if (tmpGuidesSel.count() != 0)
13893 	{
13894 		gxM = tmpGuidesSel.begin().value();
13895 		if (gxM % 3 == 0)
13896 			*xout = items.at(gxM / 3)->visualXPos();
13897 		else if (gxM %3 == 1)
13898 			*xout = items.at(gxM / 3)->visualXPos() + items.at(gxM / 3)->visualWidth();
13899 		else if (gxM %3 == 2)
13900 			*xout = items.at(gxM / 3)->visualXPos() + items.at(gxM / 3)->visualWidth() / 2;
13901 	}
13902 }
13903 
getClosestPageBoundaries(double xin,double yin,double & xout,double & yout,ScPage * refPage)13904 void ScribusDoc::getClosestPageBoundaries(double xin, double yin, double &xout, double &yout, ScPage* refPage)
13905 {
13906 	ScPage* page = (refPage == nullptr) ? currentPage() : refPage;
13907 
13908 	MarginStruct bleedValues;
13909 	getBleeds(page, m_docPrefsData.docSetupPrefs.bleeds, bleedValues);
13910 
13911 	const double snapDistance = m_docPrefsData.guidesPrefs.guideRad / m_View->scale();
13912 
13913 	xout = xin;
13914 	yout = yin;
13915 
13916 	// Left
13917 	if (fabs(page->xOffset() - bleedValues.left() - xin) < snapDistance)
13918 		xout = page->xOffset() - bleedValues.left();
13919 
13920 	if (fabs(page->Margins.left() + page->xOffset() - xin) < snapDistance)
13921 		xout = page->xOffset() + page->Margins.left();
13922 
13923 	if (fabs(page->xOffset() - xin) < snapDistance)
13924 		xout = page->xOffset();
13925 
13926 	// Right
13927 	if (fabs(page->width() + bleedValues.right() + page->xOffset() - xin) < snapDistance)
13928 		xout = page->xOffset() + page->width() + bleedValues.right();
13929 
13930 	if (fabs((page->width() - page->Margins.right()) + page->xOffset() - xin) < snapDistance)
13931 		xout = page->xOffset() + page->width() - page->Margins.right();
13932 
13933 	if (fabs((page->width() + page->xOffset()) - xin) < snapDistance)
13934 		xout = page->xOffset() + page->width();
13935 
13936 	// Top side
13937 	if (fabs(page->height() + bleedValues.bottom() + page->yOffset() - yin) < snapDistance)
13938 		yout = page->yOffset() + page->height() + bleedValues.bottom();
13939 
13940 	if (fabs(page->Margins.top() + page->yOffset() - yin) < snapDistance)
13941 		yout = page->yOffset() + page->Margins.top();
13942 
13943 	if (fabs(page->yOffset() - yin) < snapDistance)
13944 		yout = page->yOffset();
13945 
13946 	// Bottom
13947 	if (fabs(page->yOffset() - bleedValues.top() - yin) < snapDistance)
13948 		yout = page->yOffset() - bleeds()->top();
13949 
13950 	if (fabs((page->height() - page->Margins.bottom()) + page->yOffset() - yin) < snapDistance)
13951 		yout = page->yOffset() + page->height() - page->Margins.bottom();
13952 
13953 	if (fabs((page->height() + page->yOffset()) - yin) < snapDistance)
13954 		yout =  page->yOffset() + page->height();
13955 }
13956 
SnapToGuides(PageItem * currItem)13957 void ScribusDoc::SnapToGuides(PageItem *currItem)
13958 {
13959 	int pg = OnPage(currItem);
13960 	if (pg == -1)
13961 		return;
13962 
13963 	double xout, yout;
13964 
13965 	getClosestGuides(0, currItem->yPos(), &xout, &yout);
13966 	if (currItem->yPos() != yout)
13967 		currItem->setYPos(yout);
13968 	if (currItem->isLine())
13969 	{
13970 		QTransform ma;
13971 		ma.translate(currItem->xPos(), currItem->yPos());
13972 		ma.rotate(currItem->rotation());
13973 		double my = ma.m12() * currItem->width() + ma.dy();
13974 		getClosestGuides(0, my, &xout, &yout);
13975 		if (my != yout)
13976 			currItem->moveBy(0.0, yout - my);
13977 	}
13978 	else
13979 	{
13980 		getClosestGuides(0, currItem->yPos() + currItem->height(), &xout, &yout);
13981 		if (currItem->yPos() + currItem->height() != yout)
13982 			currItem->setYPos(yout - currItem->height());
13983 	}
13984 	getClosestGuides(currItem->xPos(), 0, &xout, &yout);
13985 	if (currItem->xPos() != xout)
13986 		currItem->setXPos(xout);
13987 	if (currItem->isLine())
13988 	{
13989 		QTransform ma;
13990 		ma.translate(currItem->xPos(), currItem->yPos());
13991 		ma.rotate(currItem->rotation());
13992 		double mx = ma.m11() * currItem->width() + ma.dx();
13993 		getClosestGuides(mx,  0, &xout, &yout);
13994 		if (mx != xout)
13995 			currItem->moveBy(xout - mx, 0.0);
13996 	}
13997 	else
13998 	{
13999 		getClosestGuides(currItem->xPos() + currItem->width(), 0, &xout, &yout);
14000 		if (currItem->xPos() + currItem->width() != xout)
14001 			currItem->setXPos(xout - currItem->width());
14002 	}
14003 }
14004 
14005 
ApplyGuides(double * x,double * y,bool elementSnap)14006 bool ScribusDoc::ApplyGuides(double *x, double *y, bool elementSnap)
14007 {
14008 	bool ret = false;
14009 	double xout = *x, yout = *y;
14010 	int pg = OnPage(*x, *y);
14011 	if (pg == -1)
14012 		return ret;
14013 	ScPage* page = Pages->at(pg);
14014 
14015 	//	if ((SnapGuides) && (m_SnapCounter > 1))
14016 	if ((SnapGuides && !elementSnap) || (SnapElement && elementSnap))
14017 	{
14018 		if (!elementSnap)
14019 			getClosestGuides(*x, *y, &xout, &yout, page);
14020 		else
14021 			getClosestElementBorder(*x, *y, &xout, &yout, ExcludeSelection);
14022 
14023 		if ((*x != xout) || (*y != yout))
14024 			ret = true;
14025 		*x = xout;
14026 		*y = yout;
14027 
14028 		getClosestPageBoundaries(*x, *y, xout, yout, page);
14029 		if ((*x != xout) || (*y != yout))
14030 			ret = true;
14031 		*x = xout;
14032 		*y = yout;
14033 	}
14034 	return ret;
14035 }
14036 
ApplyGuides(FPoint * point,bool elementSnap)14037 bool ScribusDoc::ApplyGuides(FPoint* point, bool elementSnap)
14038 {
14039 	double newX = point->x();
14040 	double newY = point->y();
14041 	bool ret = ApplyGuides(&newX, &newY, elementSnap);
14042 	point->setX(newX);
14043 	point->setY(newY);
14044 
14045 	return ret;
14046 }
14047 
moveItem(double newX,double newY,PageItem * currItem)14048 bool ScribusDoc::moveItem(double newX, double newY, PageItem* currItem)
14049 {
14050 	if (currItem->locked())
14051 		return false;
14052 	bool retw = false;
14053 	double oldx = currItem->xPos();
14054 	double oldy = currItem->yPos();
14055 	currItem->moveBy(newX, newY);
14056 	if ((currItem->xPos() != oldx) || (currItem->yPos() != oldy))
14057 		retw = true;
14058 	// In the future, it may be good to adjust embedded group items position here
14059 	/*if (currItem->isGroup() || currItem->isSymbol())
14060 	{
14061 		for (int em = 0; em < currItem->groupItemList.count(); ++em)
14062 		{
14063 			PageItem* embedded = currItem->groupItemList.at(em);
14064 			embedded->setXYPos(currItem->xPos() + embedded->gXpos, currItem->yPos() + embedded->gYpos, true);
14065 		}
14066 	}*/
14067 	setRedrawBounding(currItem);
14068 	if (currItem->isGroup())
14069 		GroupOnPage(currItem);
14070 	else
14071 		currItem->OwnPage = OnPage(currItem);
14072 	return retw;
14073 }
14074 
rotateItem(double angle,PageItem * currItem)14075 void ScribusDoc::rotateItem(double angle, PageItem *currItem)
14076 {
14077 	if (currItem->locked())
14078 		return;
14079 	QRectF oldR = currItem->getBoundingRect();
14080 //	if ((Doc->RotMode != 0) && (m_MouseButtonPressed))
14081 	if (m_rotMode != 0)
14082 	{
14083 		QTransform ma;
14084 		ma.translate(currItem->xPos(), currItem->yPos());
14085 		ma.scale(1, 1);
14086 		ma.rotate(currItem->rotation());
14087 		double ro = angle - currItem->rotation();
14088 		currItem->setRotation(angle);
14089 		FPoint n(0,0);
14090 		switch (m_rotMode)
14091 		{
14092 		case 2:
14093 			ma.translate(currItem->width() / 2.0, currItem->height() / 2.0);
14094 			n = FPoint(-currItem->width() / 2.0, -currItem->height() / 2.0);
14095 			break;
14096 		case 4:
14097 			ma.translate(currItem->width(), currItem->height());
14098 			n = FPoint(-currItem->width(), -currItem->height());
14099 			break;
14100 		case 3:
14101 			ma.translate(0, currItem->height());
14102 			n = FPoint(0, -currItem->height());
14103 			break;
14104 		case 1:
14105 			ma.translate(currItem->width(), 0);
14106 			n = FPoint(-currItem->width(), 0);
14107 			break;
14108 		}
14109 		ma.rotate(ro);
14110 		double x = ma.m11() * n.x() + ma.m21() * n.y() + ma.dx();
14111 		double y = ma.m22() * n.y() + ma.m12() * n.x() + ma.dy();
14112 		bool oldS = currItem->Sizing;
14113 		currItem->Sizing = true;
14114 		currItem->moveBy(x - currItem->xPos(), y - currItem->yPos(), true);
14115 		setRedrawBounding(currItem);
14116 		currItem->OwnPage = OnPage(currItem);
14117 		currItem->Sizing = oldS;
14118 		currItem->checkChanges();
14119 	}
14120 	else
14121 	{
14122 		currItem->setRotation(angle);
14123 		setRedrawBounding(currItem);
14124 	}
14125 	if (!m_loading)
14126 	{
14127 		QRectF newR(currItem->getBoundingRect());
14128 		regionsChanged()->update(newR.united(oldR));
14129 	}
14130 	//emit SetAngle(currItem->rotation());
14131 }
14132 
14133 
14134 
moveRotated(PageItem * currItem,const FPoint & npv)14135 void ScribusDoc::moveRotated(PageItem *currItem, const FPoint& npv)
14136 {
14137 	QTransform ma;
14138 	ma.translate(currItem->xPos(), currItem->yPos());
14139 	ma.rotate(currItem->rotation());
14140 	double mxc = currItem->xPos() - (ma.m11() * npv.x() + ma.m21() * npv.y() + ma.dx());
14141 	double myc = currItem->yPos() - (ma.m22() * npv.y() + ma.m12() * npv.x() + ma.dy());
14142 	moveItem(-mxc, -myc, currItem);
14143 }
14144 
sizeItem(double newW,double newH,PageItem * pi,bool fromMP,bool DoUpdateClip,bool redraw)14145 bool ScribusDoc::sizeItem(double newW, double newH, PageItem *pi, bool fromMP, bool DoUpdateClip, bool redraw)
14146 {
14147 	PageItem *currItem = pi;
14148 	if (currItem->locked())
14149 		return false;
14150 	QRectF oldR(currItem->getBoundingRect());
14151 	//Uncomment for stopping resize in any direction
14152 	//and remove the height/width <0 tests in item sizing switch
14153 	/*
14154 	if (!currItem->asLine())
14155 	{
14156 		newW = qMax(newW, 1);
14157 		newH = qMax(newH, 1);
14158 	}
14159 	*/
14160 	UndoTransaction activeTransaction;
14161 	if (UndoManager::undoEnabled())
14162 	{
14163 		QString unitSuffix = unitGetStrFromIndex(this->unitIndex());
14164 		int unitPrecision  = unitGetPrecisionFromIndex(this->unitIndex());
14165 		QString owString  = QString::number(currItem->oldWidth * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
14166 		QString ohString  = QString::number(currItem->oldHeight * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
14167 		QString nwString  = QString::number(newW * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
14168 		QString nhString  = QString::number(newH * m_docUnitRatio, 'f', unitPrecision) + " " + unitSuffix;
14169 		QString transacDesc = QString(Um::ResizeFromTo).arg(owString, ohString, nwString, nhString);
14170 		activeTransaction = m_undoManager->beginTransaction(currItem->getUName(), currItem->getUPixmap(), Um::Resize, transacDesc, Um::IResize);
14171 	}
14172 	if ((m_rotMode != 0) && (fromMP) && (!isLoading()) && (appMode == modeNormal))
14173 	{
14174 		QTransform ma;
14175 		ma.rotate(currItem->rotation());
14176 		double moveX = ma.m11() * (currItem->width() - newW) + ma.m21() * (currItem->height() - newH) + ma.dx();
14177 		double moveY = ma.m22() * (currItem->height() - newH) + ma.m12() * (currItem->width() - newW) + ma.dy();
14178 		if (m_rotMode == 2)
14179 		{
14180 			moveX /= 2.0;
14181 			moveY /= 2.0;
14182 		}
14183 		else if (m_rotMode == 1)
14184 		{
14185 			moveX = ma.m11() * (currItem->width() - newW);
14186 			moveY = ma.m12() * (currItem->width() - newW);
14187 		}
14188 		else if (m_rotMode == 3)
14189 		{
14190 			moveX = ma.m21() * (currItem->height() - newH);
14191 			moveY = ma.m22() * (currItem->height() - newH);
14192 		}
14193 		moveItem(moveX, moveY, currItem);
14194 	}
14195 	//	#8541, #8761: "when resizing with ALT-arrow, the size values in the PP aren't updated"
14196 //	currItem->setWidthHeight(newW, newH, true);
14197 	currItem->setWidthHeight(newW, newH);
14198 
14199 	if ((currItem->isImageFrame()) && (!currItem->Sizing) && (appMode != modeEditClip))
14200 	{
14201 		currItem->adjustPictScale();
14202 	}
14203 	if (currItem->isLine())
14204 	{
14205 		//int ph = static_cast<int>(qMax(1.0, currItem->lineWidth() / 2.0));
14206 		if (!fromMP)
14207 		{
14208 			FPoint g(currItem->xPos(), currItem->yPos());
14209 			FPoint t(currItem->width(), 0, currItem->xPos(), currItem->yPos(), currItem->rotation(), 1, 1);
14210 			t -= g;
14211 			currItem->setRotation( atan2(t.y(), t.x()) * (180.0 / M_PI));
14212 			currItem->setWidthHeight( sqrt(pow(t.x(), 2) + pow(t.y(), 2)), 1.0);
14213 			//currItem->setXYPos(currItem->xPos(), currItem->yPos());
14214 		}
14215 		currItem->asLine()->setLineClip();
14216 	}
14217 	// In the future, it may be good to adjust embedded group items position here
14218 	/*if (currItem->isGroup() || currItem->isSymbol())
14219 	{
14220 		for (int em = 0; em < currItem->groupItemList.count(); ++em)
14221 		{
14222 			PageItem* embedded = currItem->groupItemList.at(em);
14223 			embedded->setXYPos(currItem->xPos() + embedded->gXpos, currItem->yPos() + embedded->gYpos, true);
14224 		}
14225 	}*/
14226 	setRedrawBounding(currItem);
14227 	currItem->OwnPage = OnPage(currItem);
14228 	if (currItem->Sizing)
14229 	{
14230 		currItem->FrameOnly = true;
14231 
14232 		if (currItem->FrameType != 0 && !currItem->asLine())
14233 		{
14234 			currItem->updateClip();
14235 //			currItem->updateGradientVectors();
14236 		}
14237 
14238 		if (activeTransaction)
14239 		{
14240 			currItem->checkChanges();
14241 			activeTransaction.commit();
14242 		}
14243 		return true;
14244 	}
14245 	if (DoUpdateClip)
14246 	{
14247 		// (JG) #5988 : break image position when resizing frame especially on undo
14248 		/*double nX=0.0, nY=0.0;
14249 		if (fromMP)
14250 		{
14251 			if (currItem->imageFlippedH())
14252 				nX = -(currItem->width() - currItem->OldB2) / currItem->imageXScale();
14253 			if (currItem->imageFlippedV())
14254 				nY = -(currItem->height() - currItem->OldH2) / currItem->imageYScale();
14255 		}
14256 		else
14257 		{
14258 			if (!currItem->imageFlippedH())
14259 				nX = (currItem->width() - currItem->OldB2) / currItem->imageXScale();
14260 			if (!currItem->imageFlippedV())
14261 				nY = (currItem->height() - currItem->OldH2) / currItem->imageYScale();
14262 		}
14263 		if (nX!=0.0 || nY!=0.0)
14264 			currItem->moveImageInFrame(dX,dY);*/
14265 		currItem->updateClip();
14266 	}
14267 //	currItem->updateGradientVectors();
14268 	if (!m_loading)
14269 	{
14270 		QRectF newR(currItem->getBoundingRect());
14271 		invalidateRegion(newR.united(oldR));
14272 	}
14273 	if ((redraw) && (!m_loading))
14274 	{
14275 		QRectF newR(currItem->getBoundingRect());
14276 		QRectF updateRect = newR.united(oldR);
14277 		if (currItem->isTextFrame() && currItem->nextInChain())
14278 		{
14279 			// If current frame is a text frame, force update of linked frames currently displayed on screen
14280 			if (currItem->itemText.length() > 0)
14281 				updateRect = QRectF();
14282 		}
14283 		regionsChanged()->update(updateRect);
14284 	}
14285 	if (!fromMP)
14286 	{
14287 		if (m_Selection->isMultipleSelection())
14288 		{
14289 			double gx, gy, gh, gw;
14290 			m_Selection->setGroupRect();
14291 			m_Selection->getGroupRect(&gx, &gy, &gw, &gh);
14292 		}
14293 	}
14294 	currItem->setCornerRadius(qMin(currItem->cornerRadius(), qMin(currItem->width(), currItem->height()) / 2));
14295 	if (activeTransaction)
14296 	{
14297 		currItem->checkChanges();
14298 		activeTransaction.commit();
14299 	}
14300 	return true;
14301 }
14302 
moveSizeItem(const FPoint & newX,const FPoint & newY,PageItem * currItem,bool fromMP,bool constrainRotation)14303 bool ScribusDoc::moveSizeItem(const FPoint& newX, const FPoint& newY, PageItem* currItem, bool fromMP, bool constrainRotation)
14304 {
14305 	QRectF oldR(currItem->getBoundingRect());
14306 	if (currItem->isLine())
14307 	{
14308 		QTransform ma;
14309 		ma.translate(currItem->xPos(), currItem->yPos());
14310 		ma.rotate(currItem->rotation());
14311 		double mx = ma.m11() * currItem->width() + ma.dx();
14312 		double my = ma.m12() * currItem->width() + ma.dy();
14313 		moveItem(newX.x(), newX.y(), currItem);
14314 		double newRot=xy2Deg(mx - currItem->xPos(), my - currItem->yPos());
14315 		currItem->setRotation(newRot);
14316 		currItem->setWidthHeight(sqrt(pow(mx - currItem->xPos(),2)+pow(my - currItem->yPos(),2)), 1.0);
14317 		currItem->updateClip();
14318 		setRedrawBounding(currItem);
14319 		QRectF newR(currItem->getBoundingRect());
14320 		if (!m_loading)
14321 		{
14322 			regionsChanged()->update(oldR);
14323 			regionsChanged()->update(newR);
14324 		}
14325 	}
14326 	else
14327 	{
14328 		currItem->OldB2 = currItem->width();
14329 		currItem->OldH2 = currItem->height();
14330 		if (currItem->rotation() != 0)
14331 		{
14332 			FPoint npv(newX.x(), newX.y());
14333 			QTransform ma3;
14334 			ma3.translate(currItem->xPos(), currItem->yPos());
14335 			ma3.rotate(currItem->rotation());
14336 			double mxc3 = currItem->xPos() - (ma3.m11() * npv.x() + ma3.m21() * npv.y() + ma3.dx());
14337 			double myc3 = currItem->yPos() - (ma3.m22() * npv.y() + ma3.m12() * npv.x() + ma3.dy());
14338 			sizeItem(currItem->width() - newY.x(), currItem->height() - newY.y(), currItem, fromMP, true, false);
14339 			moveItem(-mxc3, -myc3, currItem);
14340 		}
14341 		else
14342 		{
14343 			sizeItem(currItem->width() - newY.x(), currItem->height() - newY.y(), currItem, fromMP, true, false);
14344 			moveItem(newX.x(), newX.y(), currItem);
14345 		}
14346 	}
14347 	return true;
14348 }
14349 
14350 
adjustItemSize(PageItem * currItem,bool includeGroup)14351 void ScribusDoc::adjustItemSize(PageItem *currItem, bool includeGroup)
14352 {
14353 	if (currItem->isArc())
14354 		return;
14355 	// Added by r17735: why? this break resizing of multiple item selections
14356 	//m_undoManager->setUndoEnabled(false);
14357 	bool siz = currItem->Sizing;
14358 	currItem->Sizing = false;
14359 	if ((!(currItem->isGroup() || currItem->isSymbol())) || includeGroup)
14360 	{
14361 //		double oldX = currItem->xPos();
14362 //		double oldY = currItem->yPos();
14363 //		double oldW = currItem->width();
14364 //		double oldH = currItem->height();
14365 //		double oldgW = currItem->groupWidth;
14366 //		double oldgH = currItem->groupHeight;
14367 		FPointArray clip = currItem->PoLine;
14368 		QRectF clipRect = clip.toQPainterPath(false).boundingRect();
14369 		FPoint tp2(clipRect.left(), clipRect.top());
14370 		//sizeItem(currItem->width() - tp2.x(), currItem->height() - tp2.y(), currItem, true, false, false);
14371 		clip.translate(-tp2.x(), -tp2.y());
14372 		if (currItem->rotation() != 0)
14373 		{
14374 			FPoint npv(tp2.x(), tp2.y());
14375 			moveRotated(currItem, npv);
14376 		}
14377 		else
14378 			moveItem(tp2.x(), tp2.y(), currItem);
14379 		if (!currItem->imageFlippedH())
14380 			currItem->moveImageInFrame(-tp2.x() / currItem->imageXScale(), 0);
14381 		if (!currItem->imageFlippedV())
14382 			currItem->moveImageInFrame(0, -tp2.y() / currItem->imageYScale());
14383 		FPoint tp(clipRect.right(), clipRect.bottom());
14384 		if (currItem->imageFlippedH())
14385 			currItem->moveImageInFrame((currItem->width() - tp.x()) / currItem->imageXScale(), 0);
14386 		if (currItem->imageFlippedV())
14387 			currItem->moveImageInFrame(0, (currItem->height() - tp.y()) / currItem->imageYScale());
14388 		sizeItem(clipRect.width(), clipRect.height(), currItem, true, false, false);
14389 		currItem->PoLine = clip.copy();
14390 		if ((currItem->isGroup() || currItem->isSymbol()) && includeGroup)
14391 		{
14392 			//currItem->groupWidth = oldgW * (currItem->width() / oldW);
14393 			//currItem->groupHeight = oldgH * (currItem->height() / oldH);
14394 			// #15759: the division by item dimension looks incorrect
14395 			//double dx = (currItem->xPos() - oldX) / (currItem->width() / currItem->groupWidth);
14396 			//double dy = (currItem->yPos() - oldY) / (currItem->height() / currItem->groupHeight);
14397 			for (int em = 0; em < currItem->groupItemList.count(); ++em)
14398 			{
14399 				PageItem* embedded = currItem->groupItemList.at(em);
14400 				//moveItem(-dx, -dy, embedded);
14401 				embedded->setXYPos(currItem->xPos() + embedded->gXpos, currItem->yPos() + embedded->gYpos, true);
14402 				embedded->gWidth = currItem->groupWidth;
14403 				embedded->gHeight = currItem->groupHeight;
14404 				if (embedded->isGroup())
14405 					embedded->asGroupFrame()->adjustXYPosition();
14406 			}
14407 			// JG : Break flipped group positionning when resizing on canvas
14408 			/*if (currItem->imageFlippedH())
14409 			{
14410 				if (oldX - currItem->xPos() == 0)
14411 					moveItem(oldW - currItem->width(), 0, currItem);
14412 				else
14413 					moveItem((oldX - currItem->xPos()), 0, currItem);
14414 			}
14415 			if (currItem->imageFlippedV())
14416 			{
14417 				if (oldY- currItem->yPos() == 0)
14418 					moveItem(0, oldH - currItem->height(), currItem);
14419 				else
14420 					moveItem(0, oldY - currItem->yPos(), currItem);
14421 			}*/
14422 		}
14423 	}
14424 	currItem->ClipEdited = true;
14425 	currItem->OldB2 = currItem->width();
14426 	currItem->OldH2 = currItem->height();
14427 	if (currItem->isPolyLine() || currItem->asSpiral())
14428 		currItem->setPolyClip(qRound(qMax(currItem->lineWidth() / 2, 1.0)));
14429 	else if (currItem->isPathText())
14430 		currItem->updatePolyClip();
14431 	else
14432 		currItem->Clip = flattenPath(currItem->PoLine, currItem->Segments);
14433 	currItem->updateGradientVectors();
14434 	currItem->Sizing = siz;
14435 	// Added by r17735: why? this break resizing of multiple item selections
14436 	//m_undoManager->setUndoEnabled(true);
14437 }
14438 
moveGroup(double x,double y,Selection * customSelection)14439 void ScribusDoc::moveGroup(double x, double y, Selection* customSelection)
14440 {
14441 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14442 	Q_ASSERT(itemSelection != nullptr);
14443 	int selectedItemCount = itemSelection->count();
14444 	if (selectedItemCount == 0)
14445 		return;
14446 	if (x == 0.0 && y == 0.0)
14447 		return;
14448 
14449 	PageItem* currItem;
14450 	double gx, gy, gw, gh;
14451 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14452 	QRectF oldRect = QRectF(gx, gy, gw, gh);
14453 	QList<PageItem*> weldL;
14454 	for (int i = 0; i < selectedItemCount; ++i)
14455 	{
14456 		currItem = itemSelection->itemAt(i);
14457 		if (!weldL.contains(currItem))
14458 		{
14459 			if (currItem->isWelded())
14460 				weldL.append(currItem->itemsWeldedTo());
14461 			moveItem(x, y, currItem);
14462 		}
14463 	}
14464 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14465 	if (itemSelection->isMultipleSelection())
14466 	{
14467 		// FIXME:av emit ItemPos(gx, gy);
14468 		currItem = itemSelection->itemAt(0);
14469 		GroupOnPage(currItem);
14470 	}
14471 	oldRect = oldRect.united(QRectF(gx, gy, gw, gh));
14472 	regionsChanged()->update(oldRect.adjusted(-10, -10, 20, 20));
14473 }
14474 
rotateGroup(double angle,Selection * customSelection)14475 void ScribusDoc::rotateGroup(double angle, Selection* customSelection)
14476 {
14477 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14478 	Q_ASSERT(itemSelection != nullptr);
14479 	if (itemSelection->count() == 0)
14480 		return;
14481 	double gx, gy, gh, gw;
14482 	FPoint rotationPoint(0, 0);
14483 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14484 	if (this->m_rotMode == 0)
14485 		rotationPoint = FPoint(gx, gy);
14486 	if (this->m_rotMode == 1)
14487 		rotationPoint = FPoint(gx, gy);
14488 	if (this->m_rotMode == 2)
14489 		rotationPoint = FPoint(gx + gw / 2.0, gy + gh / 2.0);
14490 	if (this->m_rotMode == 3)
14491 		rotationPoint = FPoint(gx, gy + gh);
14492 	if (this->m_rotMode == 4)
14493 		rotationPoint = FPoint(gx + gw, gy + gh);
14494 	rotateGroup(angle, rotationPoint, itemSelection);
14495 }
14496 
rotateGroup(double angle,const FPoint & RCenter,Selection * customSelection)14497 void ScribusDoc::rotateGroup(double angle, const FPoint& RCenter, Selection* customSelection)
14498 {
14499 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14500 	Q_ASSERT(itemSelection != nullptr);
14501 	if (itemSelection->count() == 0)
14502 		return;
14503 	double gxS, gyS, ghS, gwS;
14504 	double sc = 1; // FIXME:av Scale;
14505 	PageItem* currItem;
14506 	itemSelection->getGroupRect(&gxS, &gyS, &gwS, &ghS);
14507 	QTransform ma;
14508 	ma.translate(RCenter.x(), RCenter.y());
14509 	ma.scale(1, 1);
14510 	ma.rotate(angle);
14511 	QRect oldR = QRect(static_cast<int>(gxS*sc-5), static_cast<int>(gyS*sc-5), static_cast<int>(gwS*sc+10), static_cast<int>(ghS*sc+10));
14512 	FPoint n;
14513 	for (int a = 0; a < itemSelection->count(); ++a)
14514 	{
14515 		currItem = itemSelection->itemAt(a);
14516 		n = FPoint(currItem->xPos() - RCenter.x(), currItem->yPos() - RCenter.y());
14517 		currItem->setXYPos(ma.m11() * n.x() + ma.m21() * n.y() + ma.dx(), ma.m22() * n.y() + ma.m12() * n.x() + ma.dy());
14518 		currItem->rotateBy(angle);
14519 		setRedrawBounding(currItem);
14520 	}
14521 	currItem = itemSelection->itemAt(0);
14522 	GroupOnPage(currItem);
14523 	itemSelection->getGroupRect(&gxS, &gyS, &gwS, &ghS);
14524 	regionsChanged()->update(QRectF(gxS - 5, gyS - 5, gwS + 10, ghS + 10).united(oldR));
14525 }
14526 
scaleGroup(double scx,double scy,bool scaleText,Selection * customSelection,bool scaleLine)14527 void ScribusDoc::scaleGroup(double scx, double scy, bool scaleText, Selection* customSelection, bool scaleLine)
14528 {
14529 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14530 	Q_ASSERT(itemSelection != nullptr);
14531 	int selectedItemCount = itemSelection->count();
14532 	if (selectedItemCount == 0)
14533 		return;
14534 
14535 	PageItem *item;
14536 	double gx, gy, gh, gw; //, x, y;
14537 	double sc = 1; //FIXME:av Scale;
14538 	int drm = m_rotMode;
14539 	m_rotMode = 0;
14540 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14541 	QRect oldR(static_cast<int>(gx*sc-5), static_cast<int>(gy*sc-5), static_cast<int>(gw*sc+10), static_cast<int>(gh*sc+10));
14542 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14543 	double origGW = gw;
14544 	double origGH = gh;
14545 	updateManager()->setUpdatesDisabled();
14546 
14547 	UndoTransaction activeTransaction;
14548 	if (UndoManager::undoEnabled())
14549 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IResize, Um::Resize, "", Um::IResize);
14550 
14551 	for (int i = 0; i < selectedItemCount; ++i)
14552 	{
14553 		item = itemSelection->itemAt(i);
14554 		if ((item->locked()) || (item->sizeLocked()))
14555 			continue;
14556 		item->OldB = item->width();
14557 		item->OldH = item->height();
14558 		item->OldB2 = item->width();
14559 		item->OldH2 = item->height();
14560 		double dw = (item->width() * scx) - item->width();
14561 		double dh = (item->height() * scy) - item->height();
14562 		double dsch = 1.0;
14563 		double dscw = 1.0;
14564 		if (item->isArc())
14565 		{
14566 			PageItem_Arc* arcItem = item->asArc();
14567 			if (arcItem->height() != 0.0)
14568 				dsch = arcItem->arcHeight / arcItem->height();
14569 			if (arcItem->width() != 0.0)
14570 				dscw = arcItem->arcWidth / arcItem->width();
14571 		}
14572 		item->Sizing = false;
14573 		double oldRot, oldLocalX, oldLocalY;
14574 		oldRot = item->rotation();
14575 		oldLocalX = item->imageXOffset();
14576 		oldLocalY = item->imageYOffset();
14577 		FPointArray gr;
14578 		gr.addPoint(item->GrStartX, item->GrStartY);
14579 		gr.addPoint(item->GrEndX, item->GrEndY);
14580 		gr.addPoint(item->GrFocalX, item->GrFocalY);
14581 		gr.addPoint(item->GrControl1);
14582 		gr.addPoint(item->GrControl2);
14583 		gr.addPoint(item->GrControl3);
14584 		gr.addPoint(item->GrControl4);
14585 		gr.addPoint(item->GrControl5);
14586 		FPoint g(gx, gy);
14587 		FPoint b(0, 0, item->xPos(), item->yPos(), item->rotation(), 1, 1);
14588 		b -= g;
14589 		FPoint b1(b.x(), b.y(), 0, 0, 0, scx, scy);
14590 		FPoint t(item->width(), 0, item->xPos(), item->yPos(), item->rotation(), 1, 1);
14591 		t -= g;
14592 		FPoint t1(t.x(), t.y(), 0, 0, 0, scx, scy);
14593 		FPoint h(0, item->height(), item->xPos(), item->yPos(), item->rotation(), 1, 1);
14594 		h -= g;
14595 		FPoint h1(h.x(), h.y(), 0, 0, 0, scx, scy);
14596 		if (item->isGroup() || scaleLine)				// change the LineWidth only when the item is within a real Group
14597 		{
14598 			if (item->lineWidth() != 0)				// don't try to scale hairlines
14599 				item->setLineWidth(qMax(item->lineWidth() * ((scx + scy) / 2), 0.01));
14600 		}
14601 		if (item->itemType() == PageItem::Line)
14602 		{
14603 			item->setRotation(atan2(t1.y() - b1.y(), t1.x() - b1.x()) * (180.0 / M_PI));
14604 			item->setWidth(sqrt(pow(t1.x() - b1.x(), 2) + pow(t1.y() - b1.y(), 2)));
14605 			item->setXYPos(b1.x() + gx, b1.y() + gy);
14606 		}
14607 		else
14608 		{
14609 			FPoint oldPos(item->xPos(), item->yPos());
14610 			QTransform ma;
14611 			ma.rotate(item->rotation());
14612 			item->PoLine.map(ma);
14613 			QTransform ma2;
14614 			ma2.translate(gx - item->xPos(), gy - item->yPos());
14615 			ma2.scale(scx, scy);
14616 			item->PoLine.map(ma2);
14617 			item->setRotation(0.0);
14618 			item->ClipEdited = true;
14619 			if (item->isArc())
14620 			{
14621 				PageItem_Arc* arc = item->asArc();
14622 				arc->arcWidth += dw * dscw;
14623 				arc->arcHeight += dh * dsch;
14624 				arc->recalcPath();
14625 			}
14626 			if (item->isSpiral())
14627 			{
14628 				PageItem_Spiral* spiral = item->asSpiral();
14629 				spiral->setWidthHeight(spiral->width() * scx, spiral->height() * scy, true);
14630 				spiral->recalcPath();
14631 			}
14632 			else if (item->isRegularPolygon())
14633 			{
14634 				PageItem_RegularPolygon* poly = item->asRegularPolygon();
14635 				poly->setWidthHeight(poly->width() * scx, poly->height() * scy, true);
14636 				poly->recalcPath();
14637 			}
14638 			else if (item->isGroup() || item->isSymbol())
14639 			{
14640 				//double oldGW = item->groupWidth;
14641 				//double oldGH = item->groupHeight;
14642 				adjustItemSize(item, true);
14643 				//item->groupWidth = oldGW;
14644 				//item->groupHeight = oldGH;
14645 			}
14646 			else
14647 				adjustItemSize(item, true);
14648 			if (item->isArc() || item->isSpiral() || item->isRegularPolygon())
14649 				item->setXYPos(b1.x() + gx, b1.y() + gy);
14650 			else
14651 			{
14652 				QTransform ma3;
14653 				ma3.translate(gx, gy);
14654 				ma3.scale(scx, scy);
14655 				FPoint n(oldPos.x() - gx, oldPos.y() - gy);
14656 				double x = ma3.m11() * n.x() + ma3.m21() * n.y() + ma3.dx();
14657 				double y = ma3.m22() * n.y() + ma3.m12() * n.x() + ma3.dy();
14658 				item->moveBy(x - gx, y - gy);
14659 			}
14660 			if (oldRot != 0)
14661 			{
14662 				item->setRotation(atan2(t1.y() - b1.y(), t1.x() - b1.x()) * (180.0 / M_PI));
14663 				if (!item->isArc() && !item->isSpiral() && !item->isRegularPolygon())
14664 				{
14665 					QTransform ma;
14666 					ma.rotate(-item->rotation());
14667 					item->PoLine.map(ma);
14668 				}
14669 				if (item->isGroup() || item->isSymbol())
14670 				{
14671 					// #15759: save/restoring group dimensions looks unnecessary
14672 					// after fixing adjustItemSize() for groups
14673 					//double oldGW = item->groupWidth;
14674 					//double oldGH = item->groupHeight;
14675 					adjustItemSize(item, true);
14676 					//item->groupWidth = oldGW;
14677 					//item->groupHeight = oldGH;
14678 				}
14679 				else
14680 					adjustItemSize(item, true);
14681 			}
14682 		}
14683 		if (scaleText)
14684 		{
14685 			if (item->itemText.length() != 0)
14686 			{
14687 				for (int j = 0; j < item->itemText.length(); ++j)
14688 				{
14689 					CharStyle fsStyle;
14690 					fsStyle.setFontSize(qMax(qRound(item->itemText.charStyle(j).fontSize() * ((scx + scy) / 2)), 1));
14691 					item->itemText.applyCharStyle(j, 1, fsStyle);
14692 				}
14693 				if (item->asPathText())
14694 					item->updatePolyClip();
14695 			}
14696 		}
14697 
14698 		item->checkChanges();
14699 
14700 		item->setImageXYOffset(oldLocalX, oldLocalY);
14701 		item->OldB2 = item->width();
14702 		item->OldH2 = item->height();
14703 		QTransform ma4;
14704 		ma4.rotate(oldRot);
14705 		ma4.scale(scx, scy);
14706 		gr.map(ma4);
14707 		for (int grow = 0; grow < item->meshGradientArray.count(); grow++)
14708 		{
14709 			for (int gcol = 0; gcol < item->meshGradientArray[grow].count(); gcol++)
14710 			{
14711 				item->meshGradientArray[grow][gcol].transform(ma4);
14712 			}
14713 		}
14714 		item->ContourLine.map(ma4);
14715 		item->setGradientStart(gr.point(0).x(), gr.point(0).y());
14716 		item->setGradientEnd(gr.point(1).x(), gr.point(1).y());
14717 		item->setGradientFocal(gr.point(2).x(), gr.point(2).y());
14718 		item->setGradientControl1(gr.point(3));
14719 		item->setGradientControl2(gr.point(4));
14720 		item->setGradientControl3(gr.point(5));
14721 		item->setGradientControl4(gr.point(6));
14722 		item->setGradientControl5(gr.point(7));
14723 		item->updateGradientVectors();
14724 	}
14725 	item = itemSelection->itemAt(0);
14726 	GroupOnPage(item);
14727 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14728 	m_rotMode = drm;
14729 	if ((m_rotMode != 0) && (!isLoading()))
14730 	{
14731 		switch (m_rotMode)
14732 		{
14733 		case 2:
14734 			moveGroup((origGW - gw) / 2.0, (origGH - gh) / 2.0);
14735 			break;
14736 		case 4:
14737 			moveGroup(origGW - gw, origGH - gh);
14738 			break;
14739 		case 3:
14740 			moveGroup(0.0, origGH - gh);
14741 			break;
14742 		case 1:
14743 			moveGroup(origGW - gw, 0.0);
14744 			break;
14745 		}
14746 	}
14747 	updateManager()->setUpdatesEnabled();
14748 	regionsChanged()->update(QRectF(gx - 5, gy - 5, gw + 10, gh + 10).united(oldR));
14749 	itemSelection->getGroupRect(&gx, &gy, &gw, &gh);
14750 	for (int i = 0; i < selectedItemCount; ++i)
14751 	{
14752 		PageItem *currItem = itemSelection->itemAt(i);
14753 		currItem->gXpos = currItem->xPos() - ((currItem->Parent) ? currItem->Parent->xPos() : 0.0);
14754 		currItem->gYpos = currItem->yPos() - ((currItem->Parent) ? currItem->Parent->yPos() : 0.0);
14755 		currItem->gWidth = (currItem->Parent) ? currItem->Parent->width() : currItem->width();
14756 		currItem->gHeight = (currItem->Parent) ? currItem->Parent->height() : currItem->height();
14757 	}
14758 
14759 	if (activeTransaction)
14760 		activeTransaction.commit();
14761 	// FIXME:av emit DocChanged();
14762 }
14763 
groupObjectsSelection(Selection * customSelection)14764 PageItem* ScribusDoc::groupObjectsSelection(Selection* customSelection)
14765 {
14766 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14767 	if (itemSelection->count() < 1)
14768 		return nullptr;
14769 	int objectsLayer = itemSelection->objectsLayer();
14770 	if (objectsLayer == -1)
14771 		return nullptr;
14772 	PageItem *currItem;
14773 	double x, y, w, h;
14774 	int selectedItemCount = itemSelection->count();
14775 	itemSelection->getVisualGroupRect(&x, &y, &w, &h);
14776 	int lowestItem = 999999;
14777 	for (int i = 0; i < selectedItemCount; ++i)
14778 	{
14779 		currItem = itemSelection->itemAt(i);
14780 		currItem->gXpos = currItem->xPos() - x;
14781 		currItem->gYpos = currItem->yPos() - y;
14782 		currItem->gWidth = w;
14783 		currItem->gHeight = h;
14784 		lowestItem = qMin(lowestItem, Items->indexOf(currItem));
14785 	}
14786 	double minx =  std::numeric_limits<double>::max();
14787 	double miny =  std::numeric_limits<double>::max();
14788 	double maxx = -std::numeric_limits<double>::max();
14789 	double maxy = -std::numeric_limits<double>::max();
14790 	for (int i = 0; i < selectedItemCount; ++i)
14791 	{
14792 		PageItem* currItem = itemSelection->itemAt(i);
14793 		double x1, x2, y1, y2;
14794 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
14795 		minx = qMin(minx, x1);
14796 		miny = qMin(miny, y1);
14797 		maxx = qMax(maxx, x2);
14798 		maxy = qMax(maxy, y2);
14799 	}
14800 	double gx = minx;
14801 	double gy = miny;
14802 	double gw = maxx - minx;
14803 	double gh = maxy - miny;
14804 	int z = itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
14805 	PageItem *groupItem = Items->takeAt(z);
14806 	Items->insert(lowestItem, groupItem);
14807 	groupItem->setItemName( tr("Group%1").arg(GroupCounter));
14808 	groupItem->AutoName = false;
14809 	groupItem->groupWidth = gw;
14810 	groupItem->groupHeight = gh;
14811 	groupItem->m_layerID = objectsLayer;
14812 	for (int i = 0; i < selectedItemCount; ++i)
14813 	{
14814 		currItem = itemSelection->itemAt(i);
14815 		int d = Items->indexOf(currItem);
14816 		if (d >= 0)
14817 			groupItem->groupItemList.append(Items->takeAt(d));
14818 		else
14819 			groupItem->groupItemList.append(currItem);
14820 		currItem->Parent = groupItem;
14821 	}
14822 	groupItem->asGroupFrame()->adjustXYPosition();
14823 	itemSelection->clear();
14824 	itemSelection->addItem(groupItem);
14825 	GroupCounter++;
14826 	return groupItem;
14827 }
14828 
groupObjectsList(QList<PageItem * > & itemList)14829 PageItem* ScribusDoc::groupObjectsList(QList<PageItem*> &itemList)
14830 {
14831 	if (itemList.count() < 1)
14832 		return nullptr;
14833 	PageItem *currItem;
14834 	int selectedItemCount = itemList.count();
14835 	int lowestItem = 999999;
14836 	for (int i = 0; i < selectedItemCount; ++i)
14837 	{
14838 		currItem = itemList.at(i);
14839 		lowestItem = qMin(lowestItem, Items->indexOf(currItem));
14840 	}
14841 	double minx =  std::numeric_limits<double>::max();
14842 	double miny =  std::numeric_limits<double>::max();
14843 	double maxx = -std::numeric_limits<double>::max();
14844 	double maxy = -std::numeric_limits<double>::max();
14845 	for (int i = 0; i < selectedItemCount; ++i)
14846 	{
14847 		currItem = itemList.at(i);
14848 		double x1, x2, y1, y2;
14849 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
14850 		minx = qMin(minx, x1);
14851 		miny = qMin(miny, y1);
14852 		maxx = qMax(maxx, x2);
14853 		maxy = qMax(maxy, y2);
14854 	}
14855 	double gx = minx;
14856 	double gy = miny;
14857 	double gw = maxx - minx;
14858 	double gh = maxy - miny;
14859 	int z = itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
14860 	PageItem *groupItem = Items->takeAt(z);
14861 	Items->insert(lowestItem, groupItem);
14862 	groupItem->setItemName( tr("Group%1").arg(GroupCounter));
14863 	groupItem->AutoName = false;
14864 	groupItem->groupWidth = gw;
14865 	groupItem->groupHeight = gh;
14866 	for (int i = 0; i < selectedItemCount; ++i)
14867 	{
14868 		currItem = itemList.at(i);
14869 		int d = Items->indexOf(currItem);
14870 		if (d >= 0)
14871 			groupItem->groupItemList.append(Items->takeAt(d));
14872 		else
14873 			groupItem->groupItemList.append(currItem);
14874 		currItem->gXpos = currItem->xPos() - minx;
14875 		currItem->gYpos = currItem->yPos() - miny;
14876 		currItem->gWidth = maxx - minx;
14877 		currItem->gHeight = maxy - miny;
14878 		currItem->Parent = groupItem;
14879 	}
14880 	groupItem->asGroupFrame()->adjustXYPosition();
14881 	GroupCounter++;
14882 	itemList.clear();
14883 	itemList.append(groupItem);
14884 	return groupItem;
14885 }
14886 
groupObjectsToItem(PageItem * groupItem,QList<PageItem * > & itemList)14887 void ScribusDoc::groupObjectsToItem(PageItem* groupItem, QList<PageItem*> &itemList)
14888 {
14889 	if (itemList.count() < 1)
14890 		return;
14891 	PageItem *currItem;
14892 	uint selectedItemCount = itemList.count();
14893 	double minx =  std::numeric_limits<double>::max();
14894 	double miny =  std::numeric_limits<double>::max();
14895 	double maxx = -std::numeric_limits<double>::max();
14896 	double maxy = -std::numeric_limits<double>::max();
14897 	for (uint ep = 0; ep < selectedItemCount; ++ep)
14898 	{
14899 		currItem = itemList.at(ep);
14900 		double x1, x2, y1, y2;
14901 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
14902 		minx = qMin(minx, x1);
14903 		miny = qMin(miny, y1);
14904 		maxx = qMax(maxx, x2);
14905 		maxy = qMax(maxy, y2);
14906 	}
14907 	if (groupItem->width() == 0)
14908 		groupItem->setWidth(maxx - minx);
14909 	if (groupItem->height() == 0)
14910 		groupItem->setHeight(maxy - miny);
14911 	groupItem->groupWidth = groupItem->width();
14912 	groupItem->groupHeight = groupItem->height();
14913 	for (uint c = 0; c < selectedItemCount; ++c)
14914 	{
14915 		currItem = itemList.at(c);
14916 		int d = Items->indexOf(currItem);
14917 		if (d >= 0)
14918 			groupItem->groupItemList.append(Items->takeAt(d));
14919 		else
14920 			groupItem->groupItemList.append(currItem);
14921 		currItem->gXpos = currItem->xPos() - groupItem->xPos();
14922 		currItem->gYpos = currItem->yPos() - groupItem->yPos();
14923 		currItem->gWidth = maxx - minx;
14924 		currItem->gHeight = maxy - miny;
14925 		currItem->Parent = groupItem;
14926 	}
14927 	GroupCounter++;
14928 	groupItem->asGroupFrame()->adjustXYPosition();
14929 	itemList.clear();
14930 	itemList.append(groupItem);
14931 }
14932 
itemSelection_GroupObjects(bool changeLock,bool lock,Selection * customSelection,PageItem_Group * groupItem)14933 PageItem * ScribusDoc::itemSelection_GroupObjects(bool changeLock, bool lock, Selection* customSelection, PageItem_Group* groupItem)
14934 {
14935 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
14936 	if (itemSelection->count() < 1)
14937 		return nullptr;
14938 	int objectsLayer = itemSelection->objectsLayer();
14939 	if (objectsLayer == -1)
14940 		return nullptr;
14941 	PageItem *currItem;
14942 
14943 	// Remove from selection any item which may already be grouped
14944 	QList<PageItem*> selectedItems = itemSelection->items();
14945 	for (int i = 0; i < selectedItems.count(); ++i)
14946 	{
14947 		currItem = selectedItems.at(i);
14948 		if (currItem->Parent)
14949 		{
14950 			selectedItems.removeAt(i);
14951 			--i;
14952 		}
14953 	}
14954 
14955 	int selectedItemCount = selectedItems.count();
14956 	if (selectedItemCount <= 1)
14957 		return nullptr;
14958 
14959 	// Sort selection so as to preserve item levels
14960 	std::stable_sort(selectedItems.begin(), selectedItems.end(), compareItemLevel);
14961 
14962 	UndoTransaction activeTransaction;
14963 	if (UndoManager::undoEnabled())
14964 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IGroup, Um::Group, "", Um::IGroup);
14965 	QString tooltip = Um::ItemsInvolved + "\n";
14966 	if (selectedItemCount > Um::ItemsInvolvedLimit)
14967 		tooltip = Um::ItemsInvolved2 + "\n";
14968 	if (changeLock)
14969 	{
14970 		for (int i = 0; i < selectedItemCount; ++i)
14971 		{
14972 			currItem = selectedItems.at(i);
14973 			currItem->setLocked(lock);
14974 			if (selectedItemCount <= Um::ItemsInvolvedLimit)
14975 				tooltip += "\t" + currItem->getUName() + "\n";
14976 		}
14977 	}
14978 
14979 	double x, y, w, h;
14980 	Selection tempSelection(this, false);
14981 	tempSelection.addItems(selectedItems);
14982 	tempSelection.getVisualGroupRect(&x, &y, &w, &h);
14983 
14984 	int lowestItem = std::numeric_limits<int>::max();
14985 	for (int i = 0; i < selectedItemCount; ++i)
14986 	{
14987 		currItem = selectedItems.at(i);
14988 		currItem->gXpos = currItem->xPos() - x;
14989 		currItem->gYpos = currItem->yPos() - y;
14990 		currItem->gWidth = w;
14991 		currItem->gHeight = h;
14992 		lowestItem = qMin(lowestItem, Items->indexOf(currItem));
14993 	}
14994 
14995 	bool needTextInteractionCheck = false;
14996 	double minx =  std::numeric_limits<double>::max();
14997 	double miny =  std::numeric_limits<double>::max();
14998 	double maxx = -std::numeric_limits<double>::max();
14999 	double maxy = -std::numeric_limits<double>::max();
15000 	for (int i = 0; i < selectedItemCount; ++i)
15001 	{
15002 		PageItem* currItem = selectedItems.at(i);
15003 		double x1, x2, y1, y2;
15004 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
15005 		minx = qMin(minx, x1);
15006 		miny = qMin(miny, y1);
15007 		maxx = qMax(maxx, x2);
15008 		maxy = qMax(maxy, y2);
15009 		needTextInteractionCheck |= currItem->textFlowAroundObject();
15010 	}
15011 
15012 	double gx = minx;
15013 	double gy = miny;
15014 	double gw = maxx - minx;
15015 	double gh = maxy - miny;
15016 
15017 	m_undoManager->setUndoEnabled(false);
15018 	if (!groupItem)
15019 	{
15020 		int z = itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
15021 		groupItem = Items->takeAt(z)->asGroupFrame();
15022 	}
15023 	Items->insert(lowestItem, groupItem);
15024 	groupItem->setItemName( tr("Group%1").arg(GroupCounter));
15025 	groupItem->AutoName = false;
15026 	groupItem->groupWidth = gw;
15027 	groupItem->groupHeight = gh;
15028 	groupItem->m_layerID = objectsLayer;
15029 	m_undoManager->setUndoEnabled(true);
15030 	for (int i = 0; i < selectedItemCount; ++i)
15031 	{
15032 		currItem = selectedItems.at(i);
15033 		int d = Items->indexOf(currItem);
15034 		groupItem->groupItemList.append(Items->takeAt(d));
15035 		currItem->Parent = groupItem;
15036 	}
15037 	groupItem->asGroupFrame()->adjustXYPosition();
15038 
15039 	if (UndoManager::undoEnabled())
15040 	{
15041 		ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(UndoManager::Group);
15042 		is->set("GROUP");
15043 		tempSelection.addItem(groupItem, true);
15044 		is->setItem(tempSelection.selectionList());
15045 		m_undoManager->action(this, is);
15046 	}
15047 	if (activeTransaction)
15048 		activeTransaction.commit();
15049 	itemSelection->clear();
15050 	itemSelection->addItem(groupItem);
15051 
15052 	GroupCounter++;
15053 	QRectF regionToUpdate = QRectF(gx - 5, gy - 5, gw + 10, gh + 10);
15054 	if (needTextInteractionCheck)
15055 		invalidateRegion(regionToUpdate);
15056 	regionsChanged()->update(needTextInteractionCheck ? QRectF() : regionToUpdate);
15057 	emit docChanged();
15058 
15059 	if (m_ScMW && ScCore->usingGUI())
15060 	{
15061 		m_ScMW->scrActions["itemAttachTextToPath"]->setEnabled(false);
15062 		m_ScMW->scrActions["itemGroup"]->setEnabled(false);
15063 		m_ScMW->scrActions["itemUngroup"]->setEnabled(true);
15064 	}
15065 	return groupItem;
15066 }
15067 
itemSelection_UnGroupObjects(Selection * customSelection)15068 void ScribusDoc::itemSelection_UnGroupObjects(Selection* customSelection)
15069 {
15070 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15071 	if (itemSelection->isEmpty())
15072 		return;
15073 
15074 	bool wasLoad = isLoading();
15075 	bool needTextInteractionCheck = false;
15076 	int docSelectionCount = itemSelection->count();
15077 	PageItem *currItem;
15078 
15079 	UndoTransaction activeTransaction;
15080 	if (UndoManager::undoEnabled())
15081 		activeTransaction = m_undoManager->beginTransaction(Um::Selection, Um::IGroup, Um::Ungroup, "", Um::IGroup);
15082 
15083 	QList<PageItem*> toDelete;
15084 	QRectF textInteractionRect;
15085 	for (int i = 0; i < docSelectionCount; ++i)
15086 	{
15087 		currItem = itemSelection->itemAt(i);
15088 		if (!currItem->isGroup())
15089 			continue;
15090 		needTextInteractionCheck |= currItem->textFlowAroundObject();
15091 		toDelete.append(currItem);
15092 	}
15093 
15094 	// Remove group control objects
15095 	setLoading(true);
15096 	itemSelection->delaySignalsOn();
15097 	dontResize = true;
15098 	for (int i = 0; i < toDelete.count(); i++)
15099 	{
15100 		currItem = toDelete.at(i);
15101 		QList<PageItem*> *list = Items;
15102 		list = parentGroup(currItem, Items);
15103 		int d = list->indexOf(currItem);
15104 		if (d >= 0)
15105 			list->removeAt(d);
15106 		itemSelection->removeItem(currItem);
15107 		QList<PageItem*> oldGroupItems = currItem->groupItemList;
15108 		int gcount = currItem->groupItemList.count();
15109 		for (int j = 0; j < gcount; j++)
15110 		{
15111 			PageItem* gItem = currItem->groupItemList.last();
15112 			needTextInteractionCheck |= gItem->textFlowAroundObject();
15113 			removeFromGroup(gItem);
15114 			if (currItem->isGroupChild())
15115 			{
15116 				addToGroup(currItem->Parent, gItem);
15117 				list->insert(d, gItem);
15118 			}
15119 			else
15120 			{
15121 				Items->insert(d, gItem);
15122 				gItem->OwnPage = OnPage(gItem);
15123 			}
15124 			itemSelection->addItem(gItem);
15125 		}
15126 		if (UndoManager::undoEnabled())
15127 		{
15128 			ScItemState<QList<QPointer<PageItem> > > *is = new ScItemState<QList<QPointer<PageItem> > >(UndoManager::Ungroup);
15129 			is->set("UNGROUP");
15130 			Selection tempSelection(this, false);
15131 			tempSelection.addItems(oldGroupItems);
15132 			tempSelection.addItem(currItem, true);
15133 			is->setItem(tempSelection.selectionList());
15134 			m_undoManager->action(this, is);
15135 		}
15136 	}
15137 	dontResize = false;
15138 	setLoading(wasLoad);
15139 	itemSelection->delaySignalsOff();
15140 
15141 	// Delete items after delaySignalsOff() call so that palette are updated before item deletion
15142 	for (int i = 0; i < toDelete.count(); i++)
15143 	{
15144 		currItem = toDelete.at(i);
15145 		if (currItem->isWelded())
15146 			currItem->unWeld();
15147 		if (!UndoManager::undoEnabled() && !isUndoRedoOngoing())
15148 			delete currItem;
15149 	}
15150 
15151 	if (activeTransaction)
15152 		activeTransaction.commit();
15153 
15154 	double x, y, w, h;
15155 	itemSelection->connectItemToGUI();
15156 	itemSelection->getGroupRect(&x, &y, &w, &h);
15157 	emit docChanged();
15158 	if (itemSelection->count() > 0)
15159 		m_ScMW->HaveNewSel();
15160 
15161 	QRectF regionToUpdate = QRectF(x - 5, y - 5, w + 10, h + 10);
15162 	if (needTextInteractionCheck)
15163 		invalidateRegion(regionToUpdate);
15164 	regionsChanged()->update(needTextInteractionCheck ? QRectF() : regionToUpdate);
15165 }
15166 
addToGroup(PageItem * group,PageItem * item)15167 void ScribusDoc::addToGroup(PageItem* group, PageItem* item)
15168 {
15169 	QTransform groupTrans = group->getTransform();
15170 	QTransform itemTrans = item->getTransform();
15171 	QPointF grPos = groupTrans.map(QPointF(0, 0));
15172 	QPointF itPos = itemTrans.map(QPointF(0, 0));
15173 	double gRot = getRotationDFromMatrix(groupTrans);
15174 	groupTrans.scale(group->width() / group->groupWidth, group->height() / group->groupHeight);
15175 	double grScXi = 1.0;
15176 	double grScYi = 1.0;
15177 	getScaleFromMatrix(groupTrans, grScXi, grScYi);
15178 	QTransform mm;
15179 	mm.rotate(gRot);
15180 	mm.scale(1.0 / grScXi, 1.0 / grScYi);
15181 	QLineF d = QLineF(0.0, 0.0, itPos.x() - grPos.x(), itPos.y() - grPos.y());
15182 	d = mm.map(d);
15183 	item->gXpos = d.p2().x();
15184 	item->gYpos = d.p2().y();
15185 	sizeItem(item->width() * (1.0 / grScXi), item->height() * (1.0 / grScYi), item, false, true, false);
15186 	if (item->isGroupChild())
15187 		item->Parent->groupItemList.removeAll(item);
15188 	else
15189 		Items->removeAll(item);
15190 	item->Parent = group;
15191 	item->rotateBy(gRot);
15192 	item->setLineWidth(item->lineWidth() / qMax(grScXi, grScYi));
15193 	item->setImageXScale(item->imageXScale() / grScXi);
15194 	item->setImageYScale(item->imageYScale() / grScYi);
15195 
15196 	itemTrans = item->getTransform();
15197 	if (itemTrans.m11() < 0)
15198 	{
15199 		item->gXpos -= item->width();
15200 		if (item->isImageFrame() || item->isTextFrame() || item->isLatexFrame() || item->isOSGFrame() || item->isSymbol() || item->isGroup() || item->isSpiral())
15201 			item->flipImageH();
15202 		if (item->itemType() != PageItem::Line)
15203 		{
15204 			QTransform ma;
15205 			ma.scale(-1, 1);
15206 			item->PoLine.map(ma);
15207 			item->PoLine.translate(item->width(), 0);
15208 		}
15209 	}
15210 	if (itemTrans.m22() < 0)
15211 	{
15212 		item->gYpos -= item->height();
15213 		if (item->isImageFrame() || item->isTextFrame() || item->isLatexFrame() || item->isOSGFrame() || item->isSymbol() || item->isGroup() || item->isSpiral())
15214 			item->flipImageV();
15215 		if (item->itemType() != PageItem::Line)
15216 		{
15217 			QTransform ma;
15218 			ma.scale(1, -1);
15219 			item->PoLine.map(ma);
15220 			item->PoLine.translate(0, item->height());
15221 		}
15222 	}
15223 }
15224 
removeFromGroup(PageItem * item)15225 void ScribusDoc::removeFromGroup(PageItem* item)
15226 {
15227 	if (!item->isGroupChild())
15228 		return;
15229 	PageItem* group = item->Parent;
15230 	QTransform itemTrans = item->getTransform();
15231 	QTransform groupTrans = group->getTransform();
15232 	group->groupItemList.removeAll(item);
15233 	item->Parent = nullptr;
15234 	double grScXi = 1.0;
15235 	double grScYi = 1.0;
15236 	getScaleFromMatrix(itemTrans, grScXi, grScYi);
15237 	double gRot = getRotationDFromMatrix(groupTrans);
15238 	sizeItem(item->width() * grScXi, item->height() * grScYi, item, false, true, false);
15239 	if (group->imageFlippedH())
15240 	{
15241 		groupTrans.translate(group->width(), 0);
15242 		groupTrans.translate(-item->width(), 0);
15243 		groupTrans.scale(-1, 1);
15244 		if (item->isImageFrame() || item->isTextFrame() || item->isLatexFrame() || item->isOSGFrame() || item->isSymbol() || item->isGroup() || item->isSpiral())
15245 			item->flipImageH();
15246 		if (item->itemType() != PageItem::Line)
15247 		{
15248 			QTransform ma;
15249 			ma.scale(-1, 1);
15250 			item->PoLine.map(ma);
15251 			item->PoLine.translate(item->width(), 0);
15252 		}
15253 	}
15254 	if (group->imageFlippedV())
15255 	{
15256 		groupTrans.translate(0, group->height());
15257 		groupTrans.translate(0, -item->height());
15258 		groupTrans.scale(1, -1);
15259 		if (item->isImageFrame() || item->isTextFrame() || item->isLatexFrame() || item->isOSGFrame() || item->isSymbol() || item->isGroup() || item->isSpiral())
15260 			item->flipImageV();
15261 		if (item->itemType() != PageItem::Line)
15262 		{
15263 			QTransform ma;
15264 			ma.scale(1, -1);
15265 			item->PoLine.map(ma);
15266 			item->PoLine.translate(0, item->height());
15267 		}
15268 	}
15269 	QPointF itPos = groupTrans.map(QPointF(item->gXpos * grScXi, item->gYpos * grScYi));
15270 	double nX = itPos.x();
15271 	double nY = itPos.y();
15272 	if (item->isTextFrame() || item->isPathText())
15273 	{
15274 		if (item->itemText.length() != 0)
15275 		{
15276 			for (int aa = 0; aa < item->itemText.length(); ++aa)
15277 			{
15278 				CharStyle fsStyle;
15279 				fsStyle.setFontSize(qMax(qRound(item->itemText.charStyle(aa).fontSize()*((grScXi+grScYi)/2)), 1));
15280 				item->itemText.applyCharStyle(aa, 1, fsStyle);
15281 			}
15282 			if (item->asPathText())
15283 				item->updatePolyClip();
15284 		}
15285 	}
15286 	item->setXYPos(nX, nY, true);
15287 	item->rotateBy(-gRot);
15288 	item->setLineWidth(item->lineWidth() * qMax(grScXi, grScYi));
15289 	if (!item->ScaleType)
15290 		item->adjustPictScale();
15291 	else
15292 	{
15293 		item->setImageXScale(item->imageXScale() * grScXi);
15294 		item->setImageYScale(item->imageYScale() * grScYi);
15295 	}
15296 	if (item->GrType == Gradient_Pattern)
15297 	{
15298 		double psx, psy, pox, poy, prot, pskx, psky;
15299 		item->patternTransform(psx, psy, pox, poy, prot, pskx, psky);
15300 		item->setPatternTransform(psx * grScXi, psy * grScYi, pox, poy, prot, pskx, psky);
15301 	}
15302 	if ((item->GrMask == GradMask_Pattern) || (item->GrMask == GradMask_PatternLumAlpha) || (item->GrMask == GradMask_PatternLumAlphaInverted) || (item->GrMask == GradMask_PatternInverted))
15303 	{
15304 		double psx, psy, pox, poy, prot, pskx, psky;
15305 		item->maskTransform(psx, psy, pox, poy, prot, pskx, psky);
15306 		item->setMaskTransform(psx * grScXi, psy * grScYi, pox, poy, prot, pskx, psky);
15307 	}
15308 	if (item->isArc())
15309 	{
15310 		PageItem_Arc* ite = item->asArc();
15311 		ite->arcWidth = ite->arcWidth * grScXi;
15312 		ite->arcHeight = ite->arcHeight * grScYi;
15313 		ite->recalcPath();
15314 	}
15315 	if (item->isSpiral())
15316 	{
15317 		PageItem_Spiral* ite = item->asSpiral();
15318 		ite->recalcPath();
15319 	}
15320 	if (item->asPathText())
15321 		item->updatePolyClip();
15322 	else
15323 		item->Clip = flattenPath(item->PoLine, item->Segments);
15324 	setRedrawBounding(item);
15325 }
15326 
rescaleGroup(PageItem * group,double scale)15327 void ScribusDoc::rescaleGroup(PageItem* group, double scale)
15328 {
15329 	group->PoLine.scale(scale, scale);
15330 	group->setWidthHeight(group->width() * scale, group->height() * scale);
15331 	group->ClipEdited = true;
15332 	group->FrameType = 3;
15333 	adjustItemSize(group, true);
15334 	group->OldB2 = group->width();
15335 	group->OldH2 = group->height();
15336 	if (group->isGroup())
15337 		group->asGroupFrame()->adjustXYPosition();
15338 	group->updateClip();
15339 	setRedrawBounding(group);
15340 }
15341 
resizeGroupToContents(PageItem * group)15342 void ScribusDoc::resizeGroupToContents(PageItem* group)
15343 {
15344 	PageItem_Group* currItem = group->asGroupFrame();
15345 	if (currItem == nullptr)
15346 		return;
15347 	QTransform groupTrans = group->getTransform();
15348 	QPainterPath input1 = currItem->PoLine.toQPainterPath(true);
15349 	if (currItem->fillEvenOdd())
15350 		input1.setFillRule(Qt::OddEvenFill);
15351 	else
15352 		input1.setFillRule(Qt::WindingFill);
15353 	input1 = groupTrans.map(input1);
15354 	double minx =  std::numeric_limits<double>::max();
15355 	double miny =  std::numeric_limits<double>::max();
15356 	double maxx = -std::numeric_limits<double>::max();
15357 	double maxy = -std::numeric_limits<double>::max();
15358 	double oldX = currItem->xPos();
15359 	double oldY = currItem->yPos();
15360 	double oldW = currItem->width();
15361 	double oldH = currItem->height();
15362 	int gcount = currItem->groupItemList.count();
15363 	double scw = currItem->width() / currItem->groupWidth;
15364 	double sch = currItem->height() / currItem->groupHeight;
15365 	for (int c = 0; c < gcount; c++)
15366 	{
15367 		PageItem* gItem = currItem->groupItemList.at(c);
15368 		gItem->setXYPos(oldX + gItem->gXpos, oldY + gItem->gYpos, true);
15369 		double x1, x2, y1, y2;
15370 		gItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
15371 		minx = qMin(minx, x1);
15372 		miny = qMin(miny, y1);
15373 		maxx = qMax(maxx, x2);
15374 		maxy = qMax(maxy, y2);
15375 	}
15376 	groupTrans.scale(scw, sch);
15377 	QPointF newXY = groupTrans.map(QPointF(minx - oldX, miny - oldY));
15378 	currItem->setXYPos(minx, miny, true);
15379 	currItem->setWidthHeight((maxx - minx) * scw, (maxy - miny) * sch, true);
15380 	currItem->groupWidth = maxx - minx;
15381 	currItem->groupHeight = maxy - miny;
15382 	for (int c = 0; c < gcount; c++)
15383 	{
15384 		PageItem* gItem = currItem->groupItemList.at(c);
15385 		gItem->gXpos = (gItem->xPos() - currItem->xPos());
15386 		gItem->gYpos = (gItem->yPos() - currItem->yPos());
15387 		gItem->gWidth = maxx - minx;
15388 		gItem->gHeight = maxy - miny;
15389 	}
15390 	currItem->setXYPos(newXY.x(), newXY.y(), true);
15391 	currItem->SetRectFrame();
15392 	currItem->ClipEdited = true;
15393 	currItem->FrameType = 3;
15394 	currItem->adjustXYPosition();
15395 	if ((currItem->width() != oldW) || (currItem->height() != oldH))
15396 	{
15397 		QTransform groupTrans2 = group->getTransform();
15398 		QPainterPath input2 = currItem->PoLine.toQPainterPath(true);
15399 		if (currItem->fillEvenOdd())
15400 			input2.setFillRule(Qt::OddEvenFill);
15401 		else
15402 			input2.setFillRule(Qt::WindingFill);
15403 		input2 = groupTrans2.map(input2);
15404 		QPainterPath result = input1.intersected(input2);
15405 		result = groupTrans2.inverted().map(result);
15406 		currItem->PoLine.fromQPainterPath(result, true);
15407 	}
15408 }
15409 
itemSelection_resizeGroupToContents(Selection * customSelection)15410 void ScribusDoc::itemSelection_resizeGroupToContents(Selection* customSelection)
15411 {
15412 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15413 	if (itemSelection->isEmpty())
15414 		return;
15415 	int docSelectionCount = itemSelection->count();
15416 	for (int a = 0; a < docSelectionCount; ++a)
15417 	{
15418 		PageItem *group = itemSelection->itemAt(a);
15419 		if (group->isGroup())
15420 			resizeGroupToContents(group);
15421 	}
15422 	regionsChanged()->update(QRectF());
15423 }
15424 
itemSelection_UniteItems(Selection *)15425 void ScribusDoc::itemSelection_UniteItems(Selection* /*customSelection*/)
15426 {
15427 	int docSelectionCount = m_Selection->count();
15428 	if (docSelectionCount <= 1)
15429 		return;
15430 	PageItem *currItem;
15431 	PageItem *bb;
15432 	QList<QTransform> transform;
15433 	QList<PageItem *> toDel;
15434 	toDel.clear();
15435 	UndoTransaction transaction;
15436 	if (UndoManager::undoEnabled())
15437 	{
15438 		transaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::UniteItem, "", Um::IGroup);
15439 		transform.clear();
15440 	}
15441 	m_undoManager->setUndoEnabled(false);
15442 	currItem = m_Selection->itemAt(0);
15443 	if (currItem->isGroup())
15444 		return;
15445 	m_Selection->delaySignalsOn();
15446 	bool currClipEdited = currItem->ClipEdited;
15447 	int currFrameType = currItem->FrameType;
15448 	currItem->ClipEdited = true;
15449 	currItem->FrameType = 3;
15450 	for (int i = 1; i < docSelectionCount; ++i)
15451 	{
15452 		bb = m_Selection->itemAt(i);
15453 		toDel.append(bb);
15454 		QTransform ma;
15455 		ma.translate(bb->xPos(), bb->yPos());
15456 		ma.rotate(bb->rotation());
15457 		QTransform ma2;
15458 		ma2.translate(currItem->xPos(), currItem->yPos());
15459 		ma2.rotate(currItem->rotation());
15460 		ma2 = ma2.inverted();
15461 		ma = ma * ma2;
15462 		bb->PoLine.map(ma);
15463 		m_undoManager->setUndoEnabled(true);
15464 		if (UndoManager::undoEnabled())
15465 			transform.append(ma);
15466 		m_undoManager->setUndoEnabled(false);
15467 		currItem->PoLine.setMarker();
15468 		currItem->PoLine.putPoints(currItem->PoLine.size(), bb->PoLine.size(), bb->PoLine);
15469 	}
15470 	int oldRotMode = m_rotMode;
15471 	m_rotMode = 0;
15472 	adjustItemSize(currItem);
15473 	m_rotMode = oldRotMode;
15474 	currItem->ContourLine = currItem->PoLine.copy();
15475 	m_undoManager->setUndoEnabled(true);
15476 	//FIXME: stop using m_View
15477 	if (UndoManager::undoEnabled())
15478 	{
15479 		ScItemState< QPair<QList<PageItem*> , QList<QTransform> > > *is = new ScItemState< QPair<QList<PageItem*> , QList<QTransform> > >(Um::UniteItem, "", Um::IGroup);
15480 		is->setItem(qMakePair(toDel,transform));
15481 		is->set("UNITEITEM");
15482 		is->set("FRAMETYPE",currFrameType);
15483 		is->set("CLIPEDITED",currClipEdited);
15484 		m_undoManager->action(currItem, is);
15485 	}
15486 	m_View->deselectItems(true);
15487 	for (int c = 0; c < toDel.count(); ++c)
15488 		m_View->selectItem(toDel.at(c));
15489 	m_Selection->delaySignalsOff();
15490 	itemSelection_DeleteItem();
15491 	regionsChanged()->update(QRectF());
15492 	if (transaction)
15493 		transaction.commit();
15494 	m_Selection->addItem(currItem);
15495 }
15496 
itemSelection_SplitItems(Selection *)15497 void ScribusDoc::itemSelection_SplitItems(Selection* /*customSelection*/)
15498 {
15499 	PageItem *bb;
15500 	m_Selection->delaySignalsOn();
15501 	UndoTransaction transaction;
15502 	if (UndoManager::undoEnabled())
15503 		transaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::SplitItem, "", Um::IGroup);
15504 	m_undoManager->setUndoEnabled(false);
15505 	int oldRotMode = m_rotMode;
15506 	m_rotMode = 0;
15507 	for (int i = 0; i < m_Selection->count(); ++i)
15508 	{
15509 		QList< int> itemsList;
15510 		itemsList.clear();
15511 		PageItem *currItem = m_Selection->itemAt(i);
15512 		if (!currItem->isPolygon() || currItem->Segments.count() <= 0)
15513 			continue;
15514 		uint StartInd = 0;
15515 		int currItemNr = Items->indexOf(currItem);
15516 		uint EndInd = currItem->PoLine.size();
15517 		m_Selection->clear();
15518 		m_Selection->addItem(currItem);
15519 		for (uint a = EndInd-1; a > 0; --a)
15520 		{
15521 			if (currItem->PoLine.isMarker(a))
15522 			{
15523 				StartInd = a + 1;
15524 				bb = new PageItem_Polygon(*currItem);
15525 				currItemNr++;
15526 				itemsList.append(currItemNr);
15527 				Items->insert(currItemNr, bb);
15528 				bb->convertTo(PageItem::Polygon);
15529 				bb->FrameType = 3;
15530 				bb->PoLine.resize(0);
15531 				bb->PoLine.putPoints(0, EndInd - StartInd, currItem->PoLine, StartInd);
15532 				bb->setRotation(currItem->rotation());
15533 				adjustItemSize(bb);
15534 				bb->ContourLine = bb->PoLine.copy();
15535 				bb->ClipEdited = true;
15536 				m_Selection->addItem(bb, false);
15537 				a -= 3;
15538 				EndInd = StartInd - 4;
15539 			}
15540 		}
15541 		currItem->PoLine.resize(StartInd-4);
15542 		adjustItemSize(currItem);
15543 		currItem->ContourLine = currItem->PoLine.copy();
15544 		currItem->ClipEdited = true;
15545 		m_undoManager->setUndoEnabled(true);
15546 		if (UndoManager::undoEnabled())
15547 		{
15548 			ScItemState< QList<int> > *is = new ScItemState< QList<int> >(Um::SplitItem, "", Um::IGroup);
15549 			is->setItem(QList<int>(itemsList));
15550 			is->set("SPLITITEM");
15551 			m_undoManager->action(currItem, is);
15552 		}
15553 		m_undoManager->setUndoEnabled(false);
15554 	}
15555 	m_rotMode = oldRotMode;
15556 	m_undoManager->setUndoEnabled(true);
15557 	m_Selection->delaySignalsOff();
15558 	view()->deselectItems(true);
15559 	regionsChanged()->update(QRectF());
15560 	if (transaction)
15561 		transaction.commit();
15562 }
15563 
itemSelection_convertItemsTo(const PageItem::ItemType newType,Selection * restoredSelection,Selection * customSelection)15564 void ScribusDoc::itemSelection_convertItemsTo(const PageItem::ItemType newType, Selection* restoredSelection, Selection* customSelection)
15565 {
15566 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15567 	assert(itemSelection != nullptr);
15568 	int selectedItemCount = itemSelection->count();
15569 	if (selectedItemCount == 0)
15570 		return;
15571 	//Create our copy selection as our item *s will be invalidated as we go through the loop and the selection index won't work
15572 	//convertItemTo does this
15573 	Selection tmpSel(*itemSelection);
15574 	tmpSel.disconnectAllItemsFromGUI();
15575 	tmpSel.delaySignalsOn();
15576 	m_updateManager.setUpdatesDisabled();
15577 	UndoTransaction convertTransaction;
15578 	if (UndoManager::undoEnabled() && selectedItemCount > 1)
15579 		convertTransaction = m_undoManager->beginTransaction(Um::SelectionGroup, Um::IGroup, Um::ConvertTo, "", Um::IGroup);
15580 
15581 	for (int i = 0; i < selectedItemCount; ++i)
15582 	{
15583 		PageItem *currItem = itemSelection->itemAt(i);
15584 		if (currItem)
15585 		{
15586 			if (currItem->isGroup())  // don't convert group control items.
15587 				restoredSelection->addItem(currItem);
15588 			else
15589 			{
15590 				PageItem* newItem=convertItemTo(currItem, newType);
15591 				if (newItem)
15592 				{
15593 					newItem->update();
15594 					if (restoredSelection)
15595 						restoredSelection->addItem(newItem);
15596 				}
15597 			}
15598 		}
15599 	}
15600 	if (convertTransaction)
15601 		convertTransaction.commit();
15602 	tmpSel.delaySignalsOff();
15603 	m_updateManager.setUpdatesEnabled();
15604 	changed();
15605 }
15606 
itemSelection_convertItemsToSymbol(QString & patternName)15607 void ScribusDoc::itemSelection_convertItemsToSymbol(QString& patternName)
15608 {
15609 	int docSelectionCount = m_Selection->count();
15610 	/* #11365 will be fixed once undo here is fixed
15611 	UndoTransaction activeTransaction;
15612 	if (UndoManager::undoEnabled()) // && !m_itemCreationTransaction)
15613 		activeTransaction = undoManager->beginTransaction();
15614 	*/
15615 	PageItem* currItem;
15616 	Selection itemSelection(this, false);
15617 	itemSelection.copy(*m_Selection, false);
15618 	m_View->deselectItems(true);
15619 	if (docSelectionCount > 1)
15620 		currItem = groupObjectsSelection(&itemSelection);
15621 	else
15622 		currItem = itemSelection.itemAt(0);
15623 	QList<PageItem*> allItems;
15624 	if (currItem->isGroup())
15625 		allItems = currItem->getAllChildren();
15626 	else
15627 		allItems.append(currItem);
15628 	QStringList results;
15629 	for (int i = 0; i < allItems.count(); i++)
15630 	{
15631 		PageItem *item = allItems.at(i);
15632 		if ((!results.contains(item->pattern())) && ((item->GrType == Gradient_Pattern) || (item->itemType() == PageItem::Symbol)))
15633 			results.append(item->pattern());
15634 		if (!item->strokePattern().isEmpty())
15635 		{
15636 			if (!results.contains(item->strokePattern()))
15637 				results.append(item->strokePattern());
15638 		}
15639 		if (!item->patternMask().isEmpty())
15640 		{
15641 			if (!results.contains(item->patternMask()))
15642 				results.append(item->patternMask());
15643 		}
15644 	}
15645 	m_ScMW->patternsDependingOnThis.clear();
15646 	QStringList mainPatterns = docPatterns.keys();
15647 	for (int i = 0; i < results.count(); i++)
15648 	{
15649 		QString temp = results[i];
15650 		for (int j = 0; j < mainPatterns.count(); j++)
15651 		{
15652 			if (mainPatterns[j] != temp)
15653 			{
15654 				QStringList subPatterns;
15655 				subPatterns = getUsedPatternsHelper(mainPatterns[j], subPatterns);
15656 				if (subPatterns.contains(temp))
15657 					m_ScMW->patternsDependingOnThis.prepend(mainPatterns[j]);
15658 			}
15659 		}
15660 		m_ScMW->patternsDependingOnThis.prepend(temp);
15661 	}
15662 	 // #12753: We cannot replace currently edited symbol
15663 	if (symbolEditMode())
15664 		m_ScMW->patternsDependingOnThis.prepend(getEditedSymbol());
15665 	allItems.clear();
15666 
15667 	ScPattern pat = ScPattern();
15668 	pat.setDoc(this);
15669 	double minx =  std::numeric_limits<double>::max();
15670 	double miny =  std::numeric_limits<double>::max();
15671 	double maxx = -std::numeric_limits<double>::max();
15672 	double maxy = -std::numeric_limits<double>::max();
15673 	double x1, x2, y1, y2;
15674 	currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
15675 	minx = qMin(minx, x1);
15676 	miny = qMin(miny, y1);
15677 	maxx = qMax(maxx, x2);
15678 	maxy = qMax(maxy, y2);
15679 	pat.pattern = currItem->DrawObj_toImage(qMin(qMax(maxx - minx, maxy - miny), 500.0));
15680 	pat.width = maxx - minx;
15681 	pat.height = maxy - miny;
15682 	pat.items.append(currItem);
15683 	// #11274 : OwnPage is not meaningful for pattern items
15684 	// We set consequently pattern item's OwnPage to -1
15685 	QList<PageItem*> patternItems = pat.items;
15686 	while (patternItems.count() > 0)
15687 	{
15688 		PageItem* patItem = patternItems.takeAt(0);
15689 		if (patItem->isGroup())
15690 			patternItems += patItem->groupItemList;
15691 		patItem->OwnPage = -1;
15692 	}
15693 	if (docPatterns.contains(patternName))
15694 		docPatterns.remove(patternName);
15695 	addPattern(patternName, pat);
15696 	int d = -1;
15697 	double sx = minx;
15698 	double sy = miny;
15699 	if (currItem->isGroupChild())
15700 	{
15701 		sx = currItem->gXpos;
15702 		sy = currItem->gYpos;
15703 		d = currItem->parentGroup()->groupItemList.indexOf(currItem);
15704 	}
15705 	else
15706 		d = Items->indexOf(currItem);
15707 	currItem->gXpos = currItem->xPos() - minx;
15708 	currItem->gYpos = currItem->yPos() - miny;
15709 	currItem->setXYPos(currItem->gXpos, currItem->gYpos, true);
15710 	int z = itemAdd(PageItem::Symbol, PageItem::Rectangle, sx, sy, maxx - minx, maxy - miny, 0, CommonStrings::None, CommonStrings::None);
15711 	PageItem* groupItem = Items->takeAt(z);
15712 	groupItem->setPattern(patternName);
15713 	groupItem->Parent = currItem->Parent;
15714 	if (currItem->isGroupChild())
15715 		currItem->parentGroup()->groupItemList.replace(d, groupItem);
15716 	else
15717 		Items->replace(d, groupItem);
15718 	/* #11365 will be fixed once undo here is fixed
15719 	if (UndoManager::undoEnabled())
15720 	{
15721 		ScItemState<QPair<PageItem*, PageItem*> > *is = new ScItemState<QPair<PageItem*, PageItem*> >("Convert Item");
15722 		is->set("CONVERT_ITEM_TO_SYMBOL");
15723 		is->setItem(qMakePair(currItem, groupItem));
15724 		is->setDescription(patternName);
15725 		//Undo target rests with the Page for object specific undo
15726 		UndoObject *target = Pages->at(0);
15727 		if (groupItem->OwnPage > -1)
15728 			target = Pages->at(groupItem->OwnPage);
15729 		undoManager->action(target, is);
15730 	}*/
15731 	m_Selection->delaySignalsOff();
15732 	/*if (activeTransaction)
15733 		activeTransaction.commit();*/
15734 }
15735 
15736 //CB-->Doc
15737 //Fix size/move item calls
15738 //CB TODO Use the selection loop properly
itemSelection_AdjustFrametoImageSize(Selection * customSelection)15739 void ScribusDoc::itemSelection_AdjustFrametoImageSize( Selection *customSelection)
15740 {
15741 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15742 	assert(itemSelection != nullptr);
15743 	int selectedItemCount = itemSelection->count();
15744 	if (selectedItemCount == 0)
15745 		return;
15746 
15747 	UndoTransaction activeTransaction;
15748 	if (UndoManager::undoEnabled())
15749 		activeTransaction = m_undoManager->beginTransaction(Um::SelectionGroup,
15750 															Um::IGroup,
15751 															Um::AdjustFrameToImage, "", Um::IResize);
15752 	for (int i = 0; i < selectedItemCount; ++i)
15753 	{
15754 		PageItem *currItem = itemSelection->itemAt(i);
15755 		if (!currItem)
15756 			continue;
15757 		if (!currItem->isImageFrame() || !currItem->imageIsAvailable)
15758 			continue;
15759 
15760 		double w = currItem->OrigW * currItem->imageXScale();
15761 		double h = currItem->OrigH * currItem->imageYScale();
15762 		double x = currItem->imageXOffset() * currItem->imageXScale();
15763 		double y = currItem->imageYOffset() * currItem->imageYScale();
15764 
15765 		// m determines the position of the upper left corner of the image relative to
15766 		// the current position of the item.
15767 		QTransform m = QTransform().rotate(currItem->rotation());
15768 		double newRotation = currItem->rotation();
15769 		if (currItem->imageFlippedH() && currItem->imageFlippedV())
15770 		{
15771 			newRotation += currItem->imageRotation();
15772 			// Inner rotation happens around the lower right corner. m already contains the item rotation.
15773 			// Next we have to translate to the rotation point. For flipped images the offsets are subtracted from
15774 			// the opposite edge. Then we have to adjust for the inner rotation. Finally, we can translate to
15775 			// to the upper left corner of the image. The transformations in the other cases happen analogously.
15776 			m.translate(currItem->width() - x, currItem->height() - y).rotate(currItem->imageRotation()).translate(-w, -h);
15777 		}
15778 		else if (currItem->imageFlippedH() && !currItem->imageFlippedV())
15779 		{
15780 			newRotation -= currItem->imageRotation();
15781 			// Inner rotation happens around the upper right corner.
15782 			m.translate(currItem->width() - x, y).rotate(-currItem->imageRotation()).translate(-w, 0);
15783 		}
15784 		else if (!currItem->imageFlippedH() && currItem->imageFlippedV())
15785 		{
15786 			newRotation -= currItem->imageRotation();
15787 			// Inner rotation happens around the lower left corner.
15788 			m.translate(x, currItem->height() - y).rotate(-currItem->imageRotation()).translate(0, -h);
15789 		}
15790 		else
15791 		{
15792 			/* !FlippedH and !FlippedV */
15793 			newRotation += currItem->imageRotation();
15794 			// Inner rotation happens already around the upper left corner.
15795 			m.translate(x, y);
15796 		}
15797 		currItem->setRotation(newRotation);
15798 		currItem->setImageRotation(0);
15799 
15800 		sizeItem(w, h, currItem);
15801 		QPointF imageUpperLeft = m.map(QPointF(0, 0));
15802 		moveItem(imageUpperLeft.x(), imageUpperLeft.y(), currItem);
15803 		currItem->setImageXYOffset(0.0, 0.0);
15804 	}
15805 	if (activeTransaction)
15806 		activeTransaction.commit();
15807 	regionsChanged()->update(QRectF());
15808 	changed();
15809 	itemSelection->itemAt(0)->emitAllToGUI();
15810 }
itemSelection_AdjustImagetoFrameSize(Selection * customSelection)15811 void ScribusDoc::itemSelection_AdjustImagetoFrameSize( Selection *customSelection)
15812 {
15813 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15814 	assert(itemSelection != nullptr);
15815 	int selectedItemCount = itemSelection->count();
15816 	if (selectedItemCount == 0)
15817 		return;
15818 
15819 	for (int i = 0; i < selectedItemCount; ++i)
15820 	{
15821 		PageItem *currItem = itemSelection->itemAt(i);
15822 		if (currItem != nullptr)
15823 		{
15824 			if (currItem->isImageFrame() && currItem->imageIsAvailable)
15825 				currItem->setImageScalingMode(false, true);
15826 		}
15827 	}
15828 	regionsChanged()->update(QRectF());
15829 	changed();
15830 	itemSelection->itemAt(0)->emitAllToGUI();
15831 }
15832 
itemSelection_AdjustFrameHeightToText(Selection * customSelection)15833 void ScribusDoc::itemSelection_AdjustFrameHeightToText( Selection *customSelection)
15834 {
15835 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15836 	assert(itemSelection != nullptr);
15837 	int selectedItemCount = itemSelection->count();
15838 	if (selectedItemCount == 0)
15839 		return;
15840 
15841 	UndoTransaction trans;
15842 	if (UndoManager::undoEnabled())
15843 		trans = m_undoManager->beginTransaction(Um::Selection, Um::ITextFrame, Um::Resize,"", Um::IResize);
15844 	for (int i = 0; i < selectedItemCount; ++i)
15845 	{
15846 		PageItem *currItem = itemSelection->itemAt(i);
15847 		if (currItem != nullptr)
15848 		{
15849 			if (currItem->isTextFrame() && (currItem->itemText.length() > 0) && !currItem->isTableItem)
15850 				currItem ->asTextFrame()->setTextFrameHeight();
15851 		}
15852 	}
15853 	if (trans)
15854 		trans.commit();
15855 	regionsChanged()->update(QRectF());
15856 	changed();
15857 	itemSelection->itemAt(0)->emitAllToGUI();
15858 }
15859 
itemSelection_AdjustFrameToTable()15860 void ScribusDoc::itemSelection_AdjustFrameToTable()
15861 {
15862 	// TODO: Do this in an undo transaction?
15863 	int selectedItemCount = m_Selection->count();
15864 	if (selectedItemCount < 1)
15865 		return;
15866 	for (int i = 0; i < selectedItemCount; ++i)
15867 	{
15868 		PageItem *item = m_Selection->itemAt(i);
15869 		if (item && item->isTable())
15870 		{
15871 			dontResize = true;
15872 			item->asTable()->adjustFrameToTable();
15873 			dontResize = false;
15874 			setRedrawBounding(item);
15875 		}
15876 	}
15877 
15878 	regionsChanged()->update(QRectF());
15879 	changed();
15880 }
15881 
itemSelection_AdjustTableToFrame()15882 void ScribusDoc::itemSelection_AdjustTableToFrame()
15883 {
15884 	// TODO: Do this in an undo transaction?
15885 	int selectedItemCount = m_Selection->count();
15886 	if (selectedItemCount < 1)
15887 		return;
15888 	for (int i = 0; i < selectedItemCount; ++i)
15889 	{
15890 		PageItem *item = m_Selection->itemAt(i);
15891 		if (item && item->isTable())
15892 		{
15893 			dontResize = true;
15894 			item->asTable()->adjustTableToFrame();
15895 			dontResize = false;
15896 			setRedrawBounding(item);
15897 		}
15898 	}
15899 
15900 	regionsChanged()->update(QRectF());
15901 	changed();
15902 }
15903 
15904 
15905 
itemSelection_SetColorProfile(const QString & profileName,Selection * customSelection)15906 void ScribusDoc::itemSelection_SetColorProfile(const QString & profileName, Selection * customSelection)
15907 {
15908 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15909 	assert(itemSelection != nullptr);
15910 	int selectedItemCount = itemSelection->count();
15911 	if (selectedItemCount == 0)
15912 		return;
15913 	//TODO Add Undo
15914 	m_updateManager.setUpdatesDisabled();
15915 	for (int i = 0; i < selectedItemCount; ++i)
15916 	{
15917 		PageItem *currItem = itemSelection->itemAt(i);
15918 		if (currItem && currItem->itemType() == PageItem::ImageFrame)
15919 		{
15920 			currItem->ImageProfile = profileName;
15921 			currItem->UseEmbedded = profileName.startsWith("Embedded");
15922 			loadPict(currItem->Pfile, currItem, true);
15923 			currItem->update();
15924 		}
15925 	}
15926 	m_updateManager.setUpdatesEnabled();
15927 	changed();
15928 }
15929 
itemSelection_SetRenderIntent(int intentIndex,Selection * customSelection)15930 void ScribusDoc::itemSelection_SetRenderIntent(int intentIndex, Selection * customSelection)
15931 {
15932 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15933 	assert(itemSelection != nullptr);
15934 	int selectedItemCount = itemSelection->count();
15935 	if (selectedItemCount == 0)
15936 		return;
15937 	//TODO Add Undo
15938 	m_updateManager.setUpdatesDisabled();
15939 	for (int i = 0; i < selectedItemCount; ++i)
15940 	{
15941 		PageItem *currItem = itemSelection->itemAt(i);
15942 		if (currItem && currItem->itemType() == PageItem::ImageFrame)
15943 		{
15944 			currItem->ImageIntent = (eRenderIntent) intentIndex;
15945 			loadPict(currItem->Pfile, currItem, true);
15946 			currItem->update();
15947 		}
15948 	}
15949 	m_updateManager.setUpdatesEnabled();
15950 	changed();
15951 }
15952 
itemSelection_SetCompressionMethod(int cmIndex,Selection * customSelection)15953 void ScribusDoc::itemSelection_SetCompressionMethod(int cmIndex, Selection * customSelection)
15954 {
15955 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15956 	assert(itemSelection != nullptr);
15957 	int selectedItemCount = itemSelection->count();
15958 	if (selectedItemCount == 0)
15959 		return;
15960 	//TODO Add Undo
15961 	for (int i = 0; i < selectedItemCount; ++i)
15962 	{
15963 		PageItem *currItem = itemSelection->itemAt(i);
15964 		if (currItem && currItem->itemType() == PageItem::ImageFrame)
15965 		{
15966 			if ((currItem->OverrideCompressionMethod = cmIndex >= 0))
15967 				currItem->CompressionMethodIndex = cmIndex;
15968 		}
15969 	}
15970 }
15971 
itemSelection_SetCompressionQuality(int cqIndex,Selection * customSelection)15972 void ScribusDoc::itemSelection_SetCompressionQuality(int cqIndex, Selection * customSelection)
15973 {
15974 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
15975 	assert(itemSelection != nullptr);
15976 	int selectedItemCount = itemSelection->count();
15977 	if (selectedItemCount == 0)
15978 		return;
15979 	//TODO Add Undo
15980 	for (int i = 0; i < selectedItemCount; ++i)
15981 	{
15982 		PageItem *currItem = itemSelection->itemAt(i);
15983 		if (currItem && currItem->itemType() == PageItem::ImageFrame)
15984 		{
15985 			if ((currItem->OverrideCompressionQuality = cqIndex >= 0))
15986 				currItem->CompressionQualityIndex = cqIndex;
15987 		}
15988 	}
15989 }
15990 
getDocItemNames(PageItem::ItemType itemType)15991 QHash<PageItem*, QString> ScribusDoc::getDocItemNames(PageItem::ItemType itemType)
15992 {
15993 	QHash<PageItem*, QString> namesMap;
15994 	QList<PageItem*> allItems;
15995 	int docItemsCount = DocItems.count();
15996 	for (int i = 0; i < docItemsCount; ++i)
15997 	{
15998 		PageItem* ite = DocItems.at(i);
15999 		if (ite->isGroup())
16000 			allItems = ite->getAllChildren();
16001 		else
16002 			allItems.append(ite);
16003 		for (int ii = 0; ii < allItems.count(); ii++)
16004 		{
16005 			ite = allItems.at(ii);
16006 			if (ite->itemType() == itemType && ite->nextInChain() == nullptr && !ite->isAutoFrame())
16007 				namesMap.insert(ite, ite->itemName());
16008 		}
16009 		allItems.clear();
16010 	}
16011 	return namesMap;
16012 }
16013 
serializer()16014 Serializer *ScribusDoc::serializer()
16015 {
16016 	if (!m_serializer)
16017 		m_serializer = new Serializer (*this);
16018 	Q_ASSERT(m_serializer);
16019 	return m_serializer;
16020 }
16021 
textSerializer()16022 Serializer *ScribusDoc::textSerializer()
16023 {
16024 	if (!m_tserializer) {
16025 		m_tserializer = new Serializer (*this);
16026 		StoryText::desaxeRules("/", *m_tserializer, "SCRIBUSTEXT");
16027 		m_tserializer->addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
16028 	}
16029 	Q_ASSERT(m_tserializer);
16030 	return m_tserializer;
16031 }
16032 
textCanvasPosition(PageItem * item,int textPos,QPointF & canvasPos)16033 bool ScribusDoc::textCanvasPosition(PageItem* item, int textPos, QPointF& canvasPos)
16034 {
16035 	canvasPos = QPointF();
16036 
16037 	if (!item->isTextFrame() && !item->isPathText() && !item->isNoteFrame())
16038 		return false;
16039 
16040 	PageItem *charFrame = item->frameOfChar(textPos);
16041 	if (!charFrame)
16042 		return false;
16043 
16044 	QLineF charPos = charFrame->textLayout.positionToPoint(textPos);
16045 
16046 	QTransform itemTransform = charFrame->getTransform();
16047 	if (item->imageFlippedH())
16048 	{
16049 		itemTransform.translate(item->width(), 0);
16050 		itemTransform.scale(-1, 1);
16051 	}
16052 	if (item->imageFlippedV())
16053 	{
16054 		itemTransform.translate(0, item->height());
16055 		itemTransform.scale(1, -1);
16056 	}
16057 	canvasPos = itemTransform.map(QPointF(charPos.x1(), charPos.y1()));
16058 
16059 	return true;
16060 }
16061 
setRotationMode(int val)16062 void ScribusDoc::setRotationMode(int val)
16063 {
16064 	if (m_rotMode == val)
16065 		return;
16066 	m_rotMode = val;
16067 }
16068 
setPageSetFirstPage(int layout,int fp)16069 void ScribusDoc::setPageSetFirstPage(int layout, int fp)
16070 {
16071 	m_docPrefsData.pageSets[layout].FirstPage=fp;
16072 }
16073 
setNewPrefs(const ApplicationPrefs & prefsData,const ApplicationPrefs & oldPrefsData,bool resizePages,bool resizeMasterPages,bool resizePageMargins,bool resizeMasterPageMargins)16074 void ScribusDoc::setNewPrefs(const ApplicationPrefs& prefsData, const ApplicationPrefs& oldPrefsData, bool resizePages, bool resizeMasterPages, bool resizePageMargins, bool resizeMasterPageMargins)
16075 {
16076 	m_docPrefsData=prefsData;
16077 	double topDisplacement = prefsData.displayPrefs.scratch.top() - oldPrefsData.displayPrefs.scratch.top();
16078 	double leftDisplacement = prefsData.displayPrefs.scratch.left() - oldPrefsData.displayPrefs.scratch.left();
16079 	applyPrefsPageSizingAndMargins(resizePages, resizeMasterPages, resizePageMargins, resizeMasterPageMargins);
16080 
16081 	int docItemsCount = MasterItems.count();
16082 	for (int ite = 0; ite < docItemsCount; ++ite)
16083 	{
16084 		PageItem *item = MasterItems.at(ite);
16085 		item->moveBy(leftDisplacement, topDisplacement);
16086 		item->setRedrawBounding();
16087 	}
16088 
16089 //	bool viewToRecalcPictureRes = (m_docPrefsData.itemToolPrefs.imageLowResType==oldPrefsData.itemToolPrefs.imageLowResType);
16090 
16091 	restartAutoSaveTimer();
16092 
16093 /*	FIXME: scribus determines dict by charstyle now, so this setting should go into the doc's default charstyle
16094 		currDoc->docHyphenator->slotNewDict(ScMW->GetLang(tabHyphenator->language->currentText()));
16095 */
16096 
16097 	docHyphenator->slotNewSettings(m_docPrefsData.hyphPrefs.Automatic, m_docPrefsData.hyphPrefs.AutoCheck);
16098 	docHyphenator->ignoredWords = m_docPrefsData.hyphPrefs.ignoredWords;
16099 	docHyphenator->specialWords = m_docPrefsData.hyphPrefs.specialWords;
16100 	if (ScCore->haveCMS())
16101 	{
16102 		bool cmsChanged = (
16103 					(m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile != oldPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile) ||
16104 					(m_docPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile != oldPrefsData.colorPrefs.DCMSset.DefaultImageCMYKProfile) ||
16105 					(m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile != oldPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile) ||
16106 					(m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorCMYKProfile != oldPrefsData.colorPrefs.DCMSset.DefaultSolidColorCMYKProfile) ||
16107 					(m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile != oldPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile) ||
16108 					(m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors != oldPrefsData.colorPrefs.DCMSset.DefaultIntentColors) ||
16109 					(m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages != oldPrefsData.colorPrefs.DCMSset.DefaultIntentImages) ||
16110 					(m_docPrefsData.colorPrefs.DCMSset.SoftProofOn != oldPrefsData.colorPrefs.DCMSset.SoftProofOn) ||
16111 					(m_docPrefsData.colorPrefs.DCMSset.SoftProofFullOn != oldPrefsData.colorPrefs.DCMSset.SoftProofFullOn) ||
16112 					(m_docPrefsData.colorPrefs.DCMSset.GamutCheck != oldPrefsData.colorPrefs.DCMSset.GamutCheck) ||
16113 					(m_docPrefsData.colorPrefs.DCMSset.BlackPoint != oldPrefsData.colorPrefs.DCMSset.BlackPoint) ||
16114 					(m_docPrefsData.colorPrefs.DCMSset.CMSinUse != oldPrefsData.colorPrefs.DCMSset.CMSinUse)
16115 					);
16116 		if (cmsChanged)
16117 		{
16118 			m_ScMW->setStatusBarInfoText( tr("Adjusting Colors"));
16119 			m_ScMW->mainWindowProgressBar->reset();
16120 			int cc = PageColors.count() + MasterItems.count() + DocItems.count() + FrameItems.count();
16121 			m_ScMW->mainWindowProgressBar->setMaximum(cc);
16122 			qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
16123 			bool newCM  = m_docPrefsData.colorPrefs.DCMSset.CMSinUse;
16124 			bool updCol = false;
16125 			m_docPrefsData.colorPrefs.DCMSset.CMSinUse = oldPrefsData.colorPrefs.DCMSset.CMSinUse;
16126 			CloseCMSProfiles();
16127 			m_docPrefsData.colorPrefs.DCMSset.CMSinUse = newCM;
16128 			HasCMS = m_docPrefsData.colorPrefs.DCMSset.CMSinUse;
16129 			SoftProofing = m_docPrefsData.colorPrefs.DCMSset.SoftProofOn;
16130 			Gamut = m_docPrefsData.colorPrefs.DCMSset.GamutCheck;
16131 			IntentColors = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
16132 			IntentImages = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
16133 			if (!m_docPrefsData.colorPrefs.DCMSset.CMSinUse)
16134 			{
16135 				HasCMS = false;
16136 				if	(oldPrefsData.colorPrefs.DCMSset.CMSinUse)
16137 				{
16138 					SetDefaultCMSParams();
16139 					updCol = true;
16140 				}
16141 			}
16142 			else if ( OpenCMSProfiles(ScCore->InputProfiles, ScCore->InputProfilesCMYK, ScCore->MonitorProfiles, ScCore->PrinterProfiles) )
16143 			{
16144 				HasCMS = true;
16145 				m_docPrefsData.pdfPrefs.SComp = m_docPrefsData.colorPrefs.DCMSset.ComponentsInput2;
16146 				m_docPrefsData.pdfPrefs.SolidProf = m_docPrefsData.colorPrefs.DCMSset.DefaultSolidColorRGBProfile;
16147 				m_docPrefsData.pdfPrefs.ImageProf = m_docPrefsData.colorPrefs.DCMSset.DefaultImageRGBProfile;
16148 				m_docPrefsData.pdfPrefs.PrintProf = m_docPrefsData.colorPrefs.DCMSset.DefaultPrinterProfile;
16149 				m_docPrefsData.pdfPrefs.Intent  = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentColors;
16150 				m_docPrefsData.pdfPrefs.Intent2 = m_docPrefsData.colorPrefs.DCMSset.DefaultIntentImages;
16151 				updCol = true;
16152 			}
16153 			else
16154 			{
16155 				SetDefaultCMSParams();
16156 				HasCMS = false;
16157 			}
16158 			if (updCol)
16159 			{
16160 				m_ScMW->recalcColors();
16161 				RecalcPictures(&ScCore->InputProfiles, &ScCore->InputProfilesCMYK, m_ScMW->mainWindowProgressBar);
16162 			}
16163 			m_ScMW->mainWindowProgressBar->setValue(cc);
16164 			qApp->restoreOverrideCursor();
16165 			m_ScMW->setStatusBarInfoText("");
16166 			m_ScMW->mainWindowProgressBar->reset();
16167 		}
16168 	}
16169 	QStringList uf(UsedFonts.keys());
16170 	QMap<QString,int>::Iterator it3;
16171 	UsedFonts.clear();
16172 	QStringList::Iterator it3a;
16173 	QStringList::Iterator it3aend=uf.end();
16174 	for (it3a = uf.begin(); it3a != it3aend; ++it3a)
16175 		AddFont(*it3a);
16176 
16177 	int itemCount=Items->count();
16178 	for (int i=0; i<itemCount; ++i)
16179 	{
16180 		if (Items->at(i)->itemType() == PageItem::ImageFrame)
16181 			Items->at(i)->setImageVisible(m_docPrefsData.guidesPrefs.showPic);
16182 	}
16183 
16184 	bool   mustInvalidateAll = false;
16185 	mustInvalidateAll |= (oldPrefsData.guidesPrefs.valueBaselineGrid  != prefsData.guidesPrefs.valueBaselineGrid);
16186 	mustInvalidateAll |= (oldPrefsData.guidesPrefs.offsetBaselineGrid != prefsData.guidesPrefs.offsetBaselineGrid);
16187 	mustInvalidateAll |= (oldPrefsData.typoPrefs != prefsData.typoPrefs);
16188 	mustInvalidateAll |= (oldPrefsData.docSectionMap != prefsData.docSectionMap);
16189 
16190 	if (mustInvalidateAll)
16191 		this->invalidateAll();
16192 }
16193 
applyPrefsPageSizingAndMargins(bool resizePages,bool resizeMasterPages,bool resizePageMargins,bool resizeMasterPageMargins)16194 void ScribusDoc::applyPrefsPageSizingAndMargins(bool resizePages, bool resizeMasterPages, bool resizePageMargins, bool resizeMasterPageMargins)
16195 {
16196 	for (int i = 0; i < Pages->count(); ++i)
16197 	{
16198 		ScPage *pp = Pages->at(i);
16199 		if (resizePages)
16200 		{
16201 			pp->setInitialWidth(pageWidth());
16202 			pp->setInitialHeight(pageHeight());
16203 			pp->setHeight(pageHeight());
16204 			pp->setWidth(pageWidth());
16205 			pp->setSize(pageSize());
16206 			pp->setOrientation(pageOrientation());
16207 		}
16208 		if (resizePageMargins)
16209 		{
16210 			pp->initialMargins = m_docPrefsData.docSetupPrefs.margins;
16211 			pp->marginPreset = m_docPrefsData.docSetupPrefs.marginPreset;
16212 		}
16213 		else
16214 		if (resizeMasterPageMargins)
16215 		{
16216 			//CB #6796: find the master page (*mp) for the current page (*pp)
16217 			//check if *pp's margins are the same as the *mp's current margins
16218 			//apply new margins if same
16219 			const int masterPageNumber = MasterNames[pp->masterPageName()];
16220 			const ScPage* mp = MasterPages.at(masterPageNumber);
16221 			if (pp->initialMargins.left() == mp->initialMargins.left() &&
16222 				pp->initialMargins.top() == mp->initialMargins.top() &&
16223 				pp->initialMargins.right() == mp->initialMargins.right() &&
16224 				pp->initialMargins.bottom() == mp->initialMargins.bottom())
16225 			{
16226 				pp->initialMargins = m_docPrefsData.docSetupPrefs.margins;
16227 				pp->marginPreset = m_docPrefsData.docSetupPrefs.marginPreset;
16228 			}
16229 		}
16230 	}
16231 	for (int i = 0; i < MasterPages.count(); ++i)
16232 	{
16233 		ScPage *pp = MasterPages.at(i);
16234 		if (resizeMasterPages)
16235 		{
16236 			pp->setInitialWidth(pageWidth());
16237 			pp->setInitialHeight(pageHeight());
16238 			pp->setHeight(pageHeight());
16239 			pp->setWidth(pageWidth());
16240 			pp->setSize(pageSize());
16241 			pp->setOrientation(pageOrientation());
16242 		}
16243 		if (resizeMasterPageMargins)
16244 		{
16245 			pp->initialMargins=m_docPrefsData.docSetupPrefs.margins;
16246 			pp->marginPreset=m_docPrefsData.docSetupPrefs.marginPreset;
16247 		}
16248 		pp->setXOffset(scratch()->left());
16249 		pp->setYOffset(scratch()->top());
16250 	}
16251 }
16252 
documentFileName() const16253 QString ScribusDoc::documentFileName() const
16254 {
16255 	return m_documentFileName;
16256 }
16257 
setDocumentFileName(const QString & documentFileName)16258 void ScribusDoc::setDocumentFileName(const QString& documentFileName)
16259 {
16260 	m_documentFileName = documentFileName;
16261 }
16262 
itemSelection_UnlinkTextFrameAndCutText(Selection * customSelection)16263 void ScribusDoc::itemSelection_UnlinkTextFrameAndCutText( Selection *customSelection)
16264 {
16265     Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
16266 	assert(itemSelection != nullptr);
16267 	int selectedItemCount = itemSelection->count();
16268 	if (selectedItemCount == 0)
16269 		return;
16270 
16271 	for (int i = 0; i < selectedItemCount; ++i)
16272 	{
16273 		PageItem *currItem = itemSelection->itemAt(i);
16274 		if (!currItem || !currItem->isTextFrame())
16275 			continue;
16276 		if (currItem->nextInChain() || currItem->prevInChain())
16277 			currItem->unlinkWithText();
16278 	}
16279 	regionsChanged()->update(QRectF());
16280 	changed();
16281 	itemSelection->itemAt(0)->emitAllToGUI();
16282 }
16283 
itemSelection_UnWeld()16284 void ScribusDoc::itemSelection_UnWeld()
16285 {
16286 	PageItem *currItem;
16287 	for (int i = 0; i < m_Selection->count(); ++i)
16288 	{
16289 		currItem = m_Selection->itemAt(i);
16290 		if (currItem->isWelded())
16291 		{
16292 			currItem->unWeld();
16293 			changed();
16294 		}
16295 	}
16296 	regionsChanged()->update(QRectF());
16297 }
16298 
itemSelection_Weld()16299 void ScribusDoc::itemSelection_Weld()
16300 {
16301 	if (m_Selection->count() != 2)
16302 		return;
16303 	PageItem * master = m_Selection->itemAt(1);
16304 	PageItem * selItem = m_Selection->itemAt(0);
16305 	selItem->weldTo(master);
16306 	changed();
16307 	regionsChanged()->update(QRectF());
16308 }
16309 
itemSelection_EditWeld()16310 void ScribusDoc::itemSelection_EditWeld()
16311 {
16312 	m_ScMW->view->requestMode(modeEditWeldPoint);
16313 }
16314 
addToInlineFrames(PageItem * item)16315 int ScribusDoc::addToInlineFrames(PageItem *item)
16316 {
16317 	QRandomGenerator* randGen = QRandomGenerator::global();
16318 
16319 	int fIndex = randGen->bounded(RAND_MAX);
16320 	while (FrameItems.contains(fIndex))
16321 		fIndex = randGen->bounded(RAND_MAX);
16322 	item->inlineCharID = fIndex;
16323 
16324 	double lw = item->visualLineWidth() / 2.0;
16325 	item->setXYPos(lw, lw, true);
16326 	FrameItems.insert(fIndex, item);
16327 	return fIndex;
16328 }
16329 
removeInlineFrame(int fIndex)16330 void ScribusDoc::removeInlineFrame(int fIndex)
16331 {
16332 	for (PageItemIterator it(this, PageItemIterator::IterateAll); *it; ++it)
16333 	{
16334 		PageItem* currItem = *it;
16335 		if (currItem->isGroup() || currItem->isTable())
16336 			continue;
16337 		checkItemForFrames(currItem, fIndex);
16338 	}
16339 
16340 	PageItem* it = FrameItems.take(fIndex);
16341 	delete it;
16342 
16343 	changed();
16344 	regionsChanged()->update(QRect());
16345 }
16346 
16347 
checkItemForFrames(PageItem * it,int fIndex)16348 void ScribusDoc::checkItemForFrames(PageItem *it, int fIndex)
16349 {
16350 	if (!it->isTextFrame() && !it->isPathText())
16351 		return;
16352 	QList<int> deleteList;
16353 
16354 	int start = 0;
16355 	int stop  = it->itemText.length();
16356 	for (int e = start; e < stop; ++e)
16357 	{
16358 		if (it->itemText.hasObject(e))
16359 		{
16360 			if (it->itemText.object(e).getInlineCharID() == fIndex)
16361 				deleteList.prepend(e);
16362 		}
16363 	}
16364 	for (int a = 0; a < deleteList.count(); a++)
16365 	{
16366 		it->itemText.removeChars(deleteList[a], 1);
16367 	}
16368 	it->invalid = true;
16369 }
16370 
hasPreflightErrors()16371 bool ScribusDoc::hasPreflightErrors()
16372 {
16373 	return (
16374 			(pageErrors.count() != 0) ||
16375 			(docItemErrors.count() != 0) ||
16376 			(masterItemErrors.count() != 0) ||
16377 			(docLayerErrors.count() != 0)
16378 			);
16379 }
16380 
itemResizeToMargin(PageItem * item,int direction)16381 void ScribusDoc::itemResizeToMargin(PageItem* item, int direction)
16382 {
16383 	//FIX ME: for now avoid for rotated items
16384 	if (item->rotation() != 0)
16385 		return;
16386 	Canvas::FrameHandle fh = (Canvas::FrameHandle) direction;
16387 	ScPage *currPage = Pages->at(item->OwnPage);
16388 	QTransform transform;
16389 	transform.translate(item->xPos(), item->yPos());
16390 	double inX = transform.dx() - m_currentPage->xOffset();
16391 	double inY = transform.dy() - m_currentPage->yOffset();
16392 	if (fh == Canvas::NORTH || fh == Canvas::NORTHWEST || fh == Canvas::NORTHEAST)
16393 	{
16394 		double top = currPage->topMargin();
16395 		double dY = inY - top;
16396 		item->moveBy(0, -dY);
16397 		item->setHeight(item->height() + dY);
16398 	}
16399 	if (fh == Canvas::SOUTH || fh == Canvas::SOUTHWEST || fh == Canvas::SOUTHEAST)
16400 	{
16401 		double bottom = currPage->height() - currPage->bottomMargin();
16402 		double dY = bottom - (inY + item->height());
16403 		item->setHeight(item->height() + dY);
16404 	}
16405 	if (fh == Canvas::EAST || fh == Canvas::NORTHEAST || fh == Canvas::SOUTHEAST)
16406 	{
16407 		double right = currPage->width() - currPage->rightMargin();
16408 		double dX = right - (inX + item->width());
16409 		item->setWidth(item->width() + dX);
16410 	}
16411 	if (fh == Canvas::WEST || fh == Canvas::NORTHWEST || fh == Canvas::SOUTHWEST)
16412 	{
16413 		double left = currPage->leftMargin();
16414 		double dX = inX - left;
16415 		item->moveBy(-dX, 0);
16416 		item->setWidth(item->width() + dX);
16417 	}
16418 
16419 	item->updateClip();
16420 	item->invalid = true;
16421 	changed();
16422 	regionsChanged()->update(QRect());
16423 }
16424 
restartAutoSaveTimer()16425 void ScribusDoc::restartAutoSaveTimer()
16426 {
16427 	autoSaveTimer->stop();
16428 	if (m_docPrefsData.docSetupPrefs.AutoSave)
16429 		autoSaveTimer->start(m_docPrefsData.docSetupPrefs.AutoSaveTime);
16430 	emit updateAutoSaveClock();
16431 }
16432 
slotAutoSave()16433 void ScribusDoc::slotAutoSave()
16434 {
16435 	if (!isModified())
16436 		return;
16437 	autoSaveTimer->stop();
16438 	QString base = tr("Document");
16439 	QString path = m_docPrefsData.pathPrefs.documents;
16440 	QString fileName;
16441 	if (hasName)
16442 	{
16443 		QFileInfo fi(m_documentFileName);
16444 		base = fi.baseName();
16445 		path = fi.absolutePath();
16446 	}
16447 	QDateTime dat = QDateTime::currentDateTime();
16448 	if ((!m_docPrefsData.docSetupPrefs.AutoSaveLocation) && (!m_docPrefsData.docSetupPrefs.AutoSaveDir.isEmpty()))
16449 		path = m_docPrefsData.docSetupPrefs.AutoSaveDir;
16450 	fileName = QDir::cleanPath(path + "/" + base + QString("_autosave_%1.sla").arg(dat.toString("dd_MM_yyyy_hh_mm")));
16451 	FileLoader fl(fileName);
16452 	if (fl.saveFile(fileName, this, nullptr))
16453 	{
16454 		scMW()->statusBar()->showMessage( tr("File %1 autosaved").arg(base), 5000);
16455 		if (autoSaveFiles.count() >= m_docPrefsData.docSetupPrefs.AutoSaveCount)
16456 		{
16457 			QFile f(autoSaveFiles.first());
16458 			f.remove();
16459 			autoSaveFiles.removeFirst();
16460 		}
16461 		autoSaveFiles.append(fileName);
16462 	}
16463 	if (m_docPrefsData.docSetupPrefs.AutoSave)
16464 		autoSaveTimer->start(m_docPrefsData.docSetupPrefs.AutoSaveTime);
16465 }
16466 
setupNumerations()16467 void ScribusDoc::setupNumerations()
16468 {
16469 	QList<NumStruct*> numList = numerations.values();
16470 	while (!numList.isEmpty())
16471 		delete numList.takeFirst();
16472 	numerations.clear();
16473 
16474 	Numeration num;
16475 	NumStruct * numS = nullptr;
16476 	for (int i = 0; i < m_docParagraphStyles.count(); ++i)
16477 	{
16478 		ParagraphStyle &style = m_docParagraphStyles[i];
16479 		if (!style.hasNum())
16480 			continue;
16481 
16482 		const QString& name = style.numName();
16483 		if (numerations.contains(name))
16484 			numS = numerations.value(name);
16485 		else
16486 		{
16487 			numS = new NumStruct;
16488 			numS->m_name = name;
16489 		}
16490 		num.numFormat = (NumFormat) style.numFormat();
16491 		num.prefix = style.numPrefix();
16492 		num.suffix = style.numSuffix();
16493 		num.range = (NumerationRange) style.numRestart();
16494 		num.start = style.numStart();
16495 		int level = style.numLevel();
16496 		if (level >= numS->m_counters.count())
16497 		{
16498 			for (int i = numS->m_counters.count(); i <= level; ++i)
16499 			{
16500 				numS->m_nums.insert(i, num);
16501 				numS->m_counters.insert(i, 0);
16502 			}
16503 		}
16504 		numS->m_nums.replace(level, num);
16505 		numS->m_counters.replace(level, num.start -1);
16506 		numS->m_lastlevel = -1;
16507 		numerations.insert(numS->m_name, numS);
16508 	}
16509 
16510 	if (!numerations.contains("default"))
16511 	{
16512 		//create default numeration
16513 		numS = new NumStruct;
16514 		numS->m_name = "default";
16515 		Numeration newNum;
16516 		newNum.suffix = ".";
16517 		numS->m_nums.insert(0, newNum);
16518 		numS->m_counters.insert(0, 0);
16519 		numS->m_lastlevel = -1;
16520 		numerations.insert("default", numS);
16521 	}
16522 
16523 	flag_NumUpdateRequest = false;
16524 	if (orgNumNames != numerations.keys())
16525 	{
16526 		orgNumNames = numerations.keys();
16527 		flag_NumUpdateRequest = true;
16528 	}
16529 	flag_Renumber = true;
16530 }
16531 
getNumberStr(const QString & numName,int level,bool reset,const ParagraphStyle & style)16532 QString ScribusDoc::getNumberStr(const QString& numName, int level, bool reset, const ParagraphStyle &style)
16533 {
16534 	Q_ASSERT(numerations.contains(numName));
16535 	NumStruct * numS = numerations.value(numName, (NumStruct*) nullptr);
16536 	if (!numS)
16537 		return QString();
16538 	numS->m_lastlevel = level;
16539 	if (level >= numS->m_nums.count())
16540 		return QString();
16541 
16542 	Numeration& num = numS->m_nums[level];
16543 	num.numFormat = (NumFormat) style.numFormat();
16544 	num.start = style.numStart();
16545 	num.prefix = style.numPrefix();
16546 	num.suffix = style.numSuffix();
16547 
16548 	int currNum = numS->m_counters.at(level);
16549 	if (reset)
16550 		currNum = numS->m_nums[level].start -1;
16551 	++currNum;
16552 	setNumerationCounter(numName, level, currNum);
16553 
16554 	QString result;
16555 	for (int i=0; i <= level; ++i)
16556 	{
16557 		const Numeration& num = numS->m_nums.at(i);
16558 		result.append(num.prefix);
16559 		result.append(num.numString(numS->m_counters.at(i)));
16560 		result.append(num.suffix);
16561 	}
16562 	return result;
16563 }
16564 
setNumerationCounter(const QString & numName,int level,int number)16565 void ScribusDoc::setNumerationCounter(const QString& numName, int level, int number)
16566 {
16567 	if (!numerations.contains(numName))
16568 		return;
16569 	NumStruct* numS = numerations.value(numName);
16570 	if (!numS)
16571 		return;
16572 	if (level > numS->m_counters.count())
16573 		numS->m_counters.insert(level, number);
16574 	else
16575 		numS->m_counters.replace(level, number);
16576 }
16577 
updateLocalNums(StoryText & itemText)16578 int ScribusDoc::updateLocalNums(StoryText& itemText)
16579 {
16580 	int firstInvalidChar = -1;
16581 	QVector<Numeration> nums;
16582 	QList<int> counters;
16583 
16584 	for (int pos = 0; pos < itemText.length(); ++pos)
16585 	{
16586 		if (pos != 0 && itemText.text(pos - 1) != SpecialChars::PARSEP)
16587 			continue;
16588 
16589 		const ParagraphStyle& style = itemText.paragraphStyle(pos);
16590 		if (!style.hasNum() || (style.numName() != "<local block>"))
16591 			continue;
16592 
16593 		Mark* mark = itemText.mark(pos);
16594 		if (mark == nullptr)
16595 		{
16596 			BulNumMark* bnMark = new BulNumMark;
16597 			itemText.insertMark(bnMark, pos);
16598 			CharStyle emptyCS;
16599 			itemText.setCharStyle(pos, 1, emptyCS);
16600 			mark = itemText.mark(pos);
16601 		}
16602 		if (!mark->isType(MARKBullNumType))
16603 			continue;
16604 
16605 		int level = style.numLevel();
16606 		while (counters.count() < (level + 1))
16607 		{
16608 			counters.append(0);
16609 			Numeration num((NumFormat) style.numFormat());
16610 			num.prefix = style.numPrefix();
16611 			num.suffix = style.numSuffix();
16612 			num.start = style.numStart();
16613 			nums.append(num);
16614 		}
16615 		Numeration num = nums.at(level);
16616 		num.prefix = style.numPrefix();
16617 		num.suffix = style.numSuffix();
16618 		// num.range = NSRstory; Shouldn't we add this or num.range = (NumerationRange) style.numRestart() ?
16619 		num.start = style.numStart();
16620 		num.numFormat = (NumFormat) style.numFormat();
16621 		nums.replace(level, num);
16622 		int count = counters.at(level);
16623 		bool reset = false;
16624 		if (pos == 0)
16625 			reset = true;
16626 		else if (pos > 0)
16627 		{
16628 			ParagraphStyle prevStyle;
16629 			prevStyle = itemText.paragraphStyle(pos - 1);
16630 			reset = !prevStyle.hasNum()
16631 					|| prevStyle.numName() != "<local block>"
16632 					|| prevStyle.numLevel() < level
16633 					|| prevStyle.numFormat() != style.numFormat();
16634 		}
16635 		if ((level == 0) && (style.numFormat() != (int) num.numFormat))
16636 		{
16637 			reset = true;
16638 			counters.clear();
16639 			counters.append(0);
16640 			nums.clear();
16641 			nums.append(num);
16642 		}
16643 		if (reset)
16644 			count = style.numStart();
16645 		else
16646 			count++;
16647 		counters.replace(level, count);
16648 		//nums.insert(level, num);
16649 		QString result;
16650 		for (int i = 0; i <= level; ++i)
16651 		{
16652 			result.append(nums.at(i).prefix);
16653 			result.append(getStringFromNum(nums.at(i).numFormat, counters.at(i)));
16654 			result.append(nums.at(i).suffix);
16655 		}
16656 		if (mark->getString() != result)
16657 		{
16658 			mark->setString(result);
16659 			if (firstInvalidChar < 0)
16660 				firstInvalidChar = pos;
16661 		}
16662 	}
16663 	return firstInvalidChar;
16664 }
16665 
updateNumbers(bool updateNumerations)16666 void ScribusDoc::updateNumbers(bool updateNumerations)
16667 {
16668 	struct ItemPosInfo
16669 	{
16670 		PageItem* item;
16671 		double xPos; // Absolute x position in document
16672 		double yPos; // Absolute y position in document
16673 	};
16674 
16675 	if (updateNumerations)
16676 		//after styles change reset all numerations settings
16677 		setupNumerations();
16678 
16679 	// Collect all text frames including those placed inside groups;
16680 	QVector<ItemPosInfo> allTextFramePos;
16681 	allTextFramePos.reserve(100);
16682 
16683 	QStack<QList<PageItem*> > itemsStack;
16684 	itemsStack.push(DocItems);
16685 
16686 	while (!itemsStack.isEmpty())
16687 	{
16688 		QList<PageItem*> itemList = itemsStack.pop();
16689 		for (int i = 0; i < itemList.count(); ++i)
16690 		{
16691 			PageItem* item = itemList.at(i);
16692 			if (item->isGroup())
16693 			{
16694 				itemsStack.push(item->asGroupFrame()->groupItemList);
16695 				continue;
16696 			}
16697 			if (!item->isTextFrame())
16698 				continue;
16699 			if (item->prevInChain() != nullptr)
16700 				continue;
16701 
16702 			ItemPosInfo itemPos { item, item->xPos(), item->yPos() };
16703 			if (item->Parent)
16704 			{
16705 				QTransform itemTrans = item->getTransform();
16706 				QPointF itemPoint = itemTrans.map(QPointF(0.0, 0.0));
16707 				itemPos.xPos = itemPoint.x();
16708 				itemPos.yPos = itemPoint.y();
16709 			}
16710 			allTextFramePos.append(itemPos);
16711 		}
16712 	}
16713 
16714 	// Start items by y position, x ascending
16715 	// Note : this will have to be changed once we support document binding on the right
16716 	std::stable_sort(allTextFramePos.begin(), allTextFramePos.end(), [](const ItemPosInfo & pos1, const ItemPosInfo & pos2) -> bool
16717 	{
16718 		if (pos1.yPos < pos2.yPos)
16719 			return true;
16720 		if (pos1.yPos == pos2.yPos)
16721 			return (pos1.xPos < pos2.xPos);
16722 		return false;
16723 	});
16724 
16725 	// Reset ALL counters
16726 	QList<NumStruct*> numerationValues = numerations.values();
16727 	for (NumStruct * numS : qAsConst(numerationValues))
16728 		for (int l = 0; l < numS->m_nums.count(); ++l)
16729 			numS->m_counters[l] = numS->m_nums[l].start - 1;
16730 
16731 	// Renumbering for doc range
16732 	for (int i = 0; i < allTextFramePos.count(); ++i)
16733 	{
16734 		PageItem* item = allTextFramePos.at(i).item;
16735 
16736 		// Reset stories range counters
16737 		for (NumStruct * numS : qAsConst(numerationValues))
16738 			for (int l = 0; l < numS->m_nums.count(); ++l)
16739 				if (numS->m_nums[l].range == NSRstory)
16740 					numS->m_counters[l] = numS->m_nums[l].start - 1;
16741 
16742 		int pos = 0;
16743 		if (item->itemText.length() <= 0)
16744 			continue;
16745 		int firstInvalidChar1 = -1;
16746 
16747 		while (pos < item->itemText.length())
16748 		{
16749 			if ((pos == 0) || (item->itemText.text(pos - 1) == SpecialChars::PARSEP))
16750 			{
16751 				const ParagraphStyle& style = item->itemText.paragraphStyle(pos);
16752 				if (style.hasNum() && style.numName() != "<local block>")
16753 				{
16754 					if (!numerations.contains(style.numName()))
16755 					{
16756 						ParagraphStyle newStyle;
16757 						newStyle.setNumName("<local block>");
16758 						Selection tempSelection(this, false);
16759 						tempSelection.addItem(item, true);
16760 						itemSelection_ApplyParagraphStyle(newStyle, &tempSelection);
16761 						continue;
16762 					}
16763 
16764 					Mark* mark = item->itemText.mark(pos);
16765 					NumStruct* numStyle = numerations.value(style.numName());
16766 					bool resetNums = false;
16767 					if (numStyle->m_lastlevel == -1)
16768 						resetNums = true;
16769 					else if (style.numOther())
16770 					{
16771 						ParagraphStyle preStyle = item->itemText.paragraphStyle(pos -1);
16772 						//reset counter if prev style hasn't numeration or has other numeration
16773 						if (!preStyle.hasNum() || (preStyle.numName() != style.numName()))
16774 							resetNums = true;
16775 					}
16776 					else if (style.numHigher() && (style.numLevel() > numStyle->m_lastlevel))
16777 						resetNums = true;
16778 
16779 					QString prefixStr = getNumberStr(style.numName(), style.numLevel(), resetNums, style);
16780 					numStyle->m_lastlevel = style.numLevel();
16781 					if (mark == nullptr)
16782 					{
16783 						BulNumMark* bnMark = new BulNumMark;
16784 						item->itemText.insertMark(bnMark, pos);
16785 						CharStyle emptyCS;
16786 						item->itemText.setCharStyle(pos, 1, emptyCS);
16787 						mark = item->itemText.mark(pos);
16788 					}
16789 					if (mark && mark->getString() != prefixStr)
16790 					{
16791 						mark->setString(prefixStr);
16792 						if (firstInvalidChar1 < 0)
16793 							firstInvalidChar1 = pos;
16794 					}
16795 				}
16796 				if (item->itemText.text(pos) == SpecialChars::PARSEP)
16797 					++pos;
16798 				else
16799 					pos = item->itemText.nextParagraph(pos) + 1;
16800 			}
16801 		}
16802 
16803 		// Update local numbering
16804 		int firstInvalidChar2 = updateLocalNums(item->itemText);
16805 
16806 		int firstInvalidChar = -1;
16807 		if (firstInvalidChar1 >= 0 && firstInvalidChar2 >=0)
16808 			firstInvalidChar = qMin(firstInvalidChar1, firstInvalidChar2);
16809 		else
16810 			firstInvalidChar = (firstInvalidChar1 >= 0) ? firstInvalidChar1 : firstInvalidChar2;
16811 
16812 		if (firstInvalidChar >= 0)
16813 		{
16814 			if (item->isTextFrame())
16815 				item->asTextFrame()->invalidateLayout(firstInvalidChar);
16816 			else
16817 				item->invalidateLayout();
16818 		}
16819 	}
16820 
16821 	flag_Renumber = false;
16822 }
16823 
marksLabelsList(MarkType type)16824 QStringList ScribusDoc::marksLabelsList(MarkType type)
16825 {
16826 	QStringList nameList;
16827 	for (int i = 0; i < m_docMarksList.count(); ++i)
16828 	{
16829 		Mark* m = m_docMarksList.at(i);
16830 		if (m == nullptr)
16831 			continue;
16832 		if ((m != nullptr) && m->isType(type))
16833 			nameList.append(m->label);
16834 	}
16835 	return nameList;
16836 }
16837 
getMark(const QString & l,MarkType t)16838 Mark* ScribusDoc::getMark(const QString& l, MarkType t)
16839 {
16840 	for (Mark* mrk : qAsConst(m_docMarksList))
16841 	{
16842 		if ((mrk != nullptr) && (mrk->label == l) && mrk->isType(t))
16843 			return mrk;
16844 	}
16845 	return nullptr;
16846 }
16847 
newMark(Mark * mrk)16848 Mark *ScribusDoc::newMark(Mark* mrk)
16849 {
16850 	Mark* newMrk = new Mark();
16851 	if (mrk != nullptr)
16852 		*newMrk = *mrk;
16853 	m_docMarksList.append(newMrk);
16854 	return newMrk;
16855 }
16856 
newNote(NotesStyle * noteStyle)16857 TextNote *ScribusDoc::newNote(NotesStyle* noteStyle)
16858 {
16859 	TextNote* newNote = new TextNote(noteStyle);
16860 	m_docNotesList.append(newNote);
16861 	setNotesChanged(true);
16862 	return newNote;
16863 }
16864 
findMarkItem(const Mark * mrk,PageItem * & lastItem) const16865 PageItem* ScribusDoc::findMarkItem(const Mark* mrk, PageItem* &lastItem) const
16866 {
16867 	PageItemIterator it(DocItems, PageItemIterator::IterateInGroups);
16868 	if (lastItem != nullptr)
16869 		it.movePast(lastItem);
16870 
16871 	for (PageItem* item = *it;  item != nullptr; item = it.next())
16872 	{
16873 		if (!item || !item->isTextFrame() || (item->itemText.length() <= 0))
16874 			continue;
16875 		if (item->prevInChain() != nullptr)
16876 			continue;
16877 	//	for (int j = item->firstInFrame(); j <= item->lastInFrame(); ++j)
16878 		for (int j = 0; j < item->itemText.length(); ++j)
16879 		{
16880 			if (item->itemText.hasMark(j, mrk))
16881 			{
16882 				lastItem = item;
16883 				return item;
16884 			}
16885 		}
16886 	}
16887 	lastItem = nullptr;
16888 	return nullptr;
16889 }
16890 
findMarkCPos(const Mark * mrk,PageItem * & currItem,int start) const16891 int ScribusDoc::findMarkCPos(const Mark* mrk, PageItem* &currItem, int start) const
16892 {
16893 	if (currItem == nullptr)
16894 		currItem = findFirstMarkItem(mrk);
16895 	if (currItem == nullptr)
16896 	{
16897 		PageItemIterator it(DocItems, PageItemIterator::IterateInGroups);
16898 		for (PageItem* item = *it;  item != nullptr; item = it.next())
16899 		{
16900 			if (!item->isTextFrame() || (item->prevInChain() != nullptr))
16901 				continue;
16902 			int pos = item->itemText.findMark(mrk);
16903 			if (pos >= 0)
16904 			{
16905 				currItem = item;
16906 				return pos;
16907 			}
16908 		}
16909 		return -1;
16910 	}
16911 	Q_ASSERT(currItem->isTextFrame());
16912 
16913 	int markPos = currItem->itemText.findMark(mrk, start);
16914 	return markPos;
16915 }
16916 
isMarkUsed(const Mark * mrk,bool visible) const16917 bool ScribusDoc::isMarkUsed(const Mark* mrk, bool visible) const
16918 {
16919 	PageItemIterator it(DocItems, PageItemIterator::IterateInGroups);
16920 	for (PageItem* currItem = *it;  currItem != nullptr; currItem = it.next())
16921 	{
16922 		if (!currItem->isTextFrame() || (currItem->itemText.length() <= 0))
16923 			continue;
16924 		// Check in whole itemText only for first frames in chain
16925 		if (!visible && currItem->prevInChain() != nullptr)
16926 			continue;
16927 
16928 		int i = visible ? currItem->firstInFrame() : 0;
16929 		int end = visible ? (currItem->lastInFrame() + 1) : currItem->itemText.length();
16930 		for (; i < end; ++i)
16931 		{
16932 			if (currItem->itemText.hasMark(i, mrk))
16933 				return true;
16934 		}
16935 	}
16936 	return false;
16937 }
16938 
setCursor2MarkPos(const Mark * mark)16939 void ScribusDoc::setCursor2MarkPos(const Mark *mark)
16940 {
16941 	if (mark == nullptr)
16942 		return;
16943 	PageItem* item = nullptr;
16944 	if (mark->isType(MARKNoteFrameType) || mark->isType(MARKNoteMasterType))
16945 		item = mark->getItemPtr();
16946 	if (item == nullptr)
16947 		item = getItemFromName(mark->getItemName());
16948 	if (item == nullptr)
16949 		item = findFirstMarkItem(mark);
16950 	if (item == nullptr)
16951 		return;
16952 
16953 	int cursorPos = findMarkCPos(mark, item);
16954 	if (cursorPos > -1)
16955 	{
16956 		scMW()->deselectAll();
16957 		scMW()->selectItemFromOutlines(item, true, cursorPos + 1);
16958 	}
16959 }
16960 
eraseMark(Mark * mrk,bool fromText,PageItem * item,bool force)16961 bool ScribusDoc::eraseMark(Mark *mrk, bool fromText, PageItem *item, bool force)
16962 {
16963 	bool found = false;
16964 	if (fromText)
16965 	{
16966 		if (item != nullptr)
16967 		{
16968 			int markPos = findMarkCPos(mrk, item);
16969 			while (markPos > -1)
16970 			{
16971 				if (mrk->isType(MARKNoteFrameType) && markPos > 1 && item->itemText.text(markPos -1) == SpecialChars::PARSEP)
16972 					item->itemText.removeChars(markPos - 1, 2);
16973 				else
16974 					item->itemText.removeChars(markPos, 1);
16975 				found = true;
16976 				markPos = findMarkCPos(mrk, item);
16977 			}
16978 		}
16979 		else
16980 		{
16981 			//find and delete all mark`s apperences in text
16982 			int markPos = -1;
16983 			PageItem* lastItem = nullptr;
16984 			item = findMarkItem(mrk, lastItem);
16985 			while (item != nullptr)
16986 			{
16987 				markPos = findMarkCPos(mrk, item);
16988 				while (markPos > -1)
16989 				{
16990 					item->itemText.removeChars(markPos, 1);
16991 					markPos = findMarkCPos(mrk, item);
16992 				}
16993 				found = true;
16994 				item->asTextFrame()->invalidateLayout(false);
16995 				item = findMarkItem(mrk, lastItem);
16996 			}
16997 		}
16998 	}
16999 
17000 	//remove mark references
17001 	for (int i = 0; i < m_docMarksList.count(); ++i)
17002 	{
17003 		Mark* m = m_docMarksList.at(i);
17004 		if (m == nullptr)
17005 			continue;
17006 		if (m->isType(MARK2MarkType))
17007 		{
17008 			QString l;
17009 			MarkType t;
17010 			m->getMark(l, t);
17011 			if (mrk == getMark(l, t))
17012 			{
17013 				setUndoDelMark(m);
17014 				eraseMark(m, true, nullptr, true);
17015 			}
17016 		}
17017 	}
17018 
17019 	//erase mark from marksMap
17020 	if (mrk->isUnique() || force)
17021 	{
17022 		m_docMarksList.removeOne(mrk);
17023 		delete mrk;
17024 	}
17025 	return found;
17026 }
17027 
setUndoDelMark(Mark * mrk)17028 void ScribusDoc::setUndoDelMark(Mark *mrk)
17029 {
17030 	//used by MarksManager
17031 	if (UndoManager::undoEnabled())
17032 	{
17033 		ScItemsState* ims = new ScItemsState(Um::DeleteMark, "", Um::IDelete);
17034 		if (mrk->isUnique())
17035 		{
17036 			ims->set("MARK", QString("delete"));
17037 			PageItem* master = findFirstMarkItem(mrk);
17038 			if (master->isNoteFrame())
17039 				ims->set("noteframeName", master->getUName());
17040 			else
17041 				ims->insertItem("inItem", master);
17042 			ims->set("at", findMarkCPos(mrk, master));
17043 			if (mrk->isType(MARK2MarkType))
17044 			{
17045 				QString dName;
17046 				MarkType dType;
17047 				mrk->getMark(dName, dType);
17048 				ims->set("dName", dName);
17049 				ims->set("dType", (int) dType);
17050 			}
17051 			if (mrk->isType(MARK2ItemType))
17052 				ims->insertItem("itemPtr", mrk->getItemPtr());
17053 		}
17054 		else
17055 		{
17056 			ims->set("MARK", QString("delNonUnique"));
17057 			int markPos = -1;
17058 			PageItem* lastItem = nullptr;
17059 			//find all mark insertions
17060 			PageItem* item = findMarkItem(mrk, lastItem);
17061 			while (item != nullptr)
17062 			{
17063 				int num = 0; //shift of insertion position for undo
17064 				markPos = findMarkCPos(mrk, item);
17065 				while (markPos > -1)
17066 				{
17067 					ims->insertItemPos.append(QPair<void*, int>((void*) item, markPos - num)); //-num as while undo text will be shorter (without marks)
17068 					//++num;
17069 					markPos = findMarkCPos(mrk, item, markPos + 1);
17070 				}
17071 				item = findMarkItem(mrk, lastItem);
17072 			}
17073 		}
17074 		ims->set("ETEA", mrk->label);
17075 		ims->set("label", mrk->label);
17076 		ims->set("type", (int) mrk->getType());
17077 		ims->set("strtxt", mrk->getString());
17078 		m_undoManager->action(this, ims);
17079 	}
17080 }
17081 
invalidateVariableTextFrames(Mark * mrk,bool forceUpdate)17082 bool ScribusDoc::invalidateVariableTextFrames(Mark* mrk, bool forceUpdate)
17083 {
17084 	if (!mrk->isType(MARKVariableTextType))
17085 		return false;
17086 	bool found = false;
17087 	PageItem* lastItem = nullptr;
17088 	PageItem* mItem = findMarkItem(mrk, lastItem);
17089 	while (mItem != nullptr)
17090 	{
17091 		found = true;
17092 		mItem->asTextFrame()->invalidateLayout(false);
17093 		if (forceUpdate)
17094 			mItem->layout();
17095 		mItem = findMarkItem(mrk, lastItem);
17096 	}
17097 	return found;
17098 }
17099 
17100 //update strings (page number) for marks pointed to anchors and items
17101 //and update marks list in Marks Manager
updateMarks(bool updateNotesMarks)17102 bool ScribusDoc::updateMarks(bool updateNotesMarks)
17103 {
17104 	if (updateNotesMarks && !notesList().isEmpty())
17105 	{
17106 		for (PageItem* item : qAsConst(DocItems))
17107 		{
17108 			if (!item->isTextFrame() || item->isNoteFrame())
17109 				continue;
17110 			if (item->prevInChain() != nullptr)
17111 				continue;
17112 			item = item->lastInChain();
17113 			int pos = item->lastInFrame() + 1;
17114 			if (pos >= item->itemText.length())
17115 				continue;
17116 			for (int i = pos; i < item->itemText.length(); ++i)
17117 			{
17118 				if (item->itemText.hasMark(i) && item->itemText.mark(i)->isNoteType())
17119 				{
17120 					TextNote * note = item->itemText.mark(i)->getNotePtr();
17121 					note->setNoteMark(nullptr);
17122 					note->masterMark()->setItemPtr(item);
17123 					note->masterMark()->setItemName(item->itemName());
17124 				}
17125 			}
17126 		}
17127 	}
17128 	if (m_docMarksList.isEmpty())
17129 	{
17130 		if ((!notesList().isEmpty() || notesChanged()) && updateNotesMarks && !isLoading())
17131 			return notesFramesUpdate();
17132 		return false;
17133 	}
17134 	Q_ASSERT(m_docMarksList.removeAll(nullptr) == 0);
17135 
17136 	bool docWasChanged = false;
17137 
17138 	if (!isLoading())
17139 	{
17140 		//run for variable text (invalidate frames with variable text)
17141 		for (Mark* mrk : qAsConst(m_docMarksList))
17142 		{
17143 			if (mrk->isType(MARKVariableTextType))
17144 			{
17145 				if (invalidateVariableTextFrames(mrk, false))
17146 					docWasChanged = true;
17147 			}
17148 			else if (mrk->isUnique())
17149 			{
17150 				PageItem* mItem = findFirstMarkItem(mrk);
17151 				mrk->OwnPage =(mItem != nullptr) ? mItem->OwnPage : -1;
17152 				mrk->setItemName((mItem != nullptr) ? mItem->itemName() : QString(""));
17153 			}
17154 		}
17155 	}
17156 
17157 	//update marks for foot/endnotes
17158 	if (updateNotesMarks)
17159 	{
17160 		//update notes numbers
17161 		for (int i=0; i < m_docNotesStylesList.count(); ++i)
17162 		{
17163 			NotesStyle* noteStyle = m_docNotesStylesList.at(i);
17164 			//update nums
17165 			if (updateNotesNums(noteStyle))
17166 			{
17167 				//refresh endnotes content
17168 				if (flag_updateEndNotes || isLoading())
17169 					updateEndnotesFrames(noteStyle);
17170 			}
17171 			if (flag_updateEndNotes)
17172 				updateEndnotesFrames(noteStyle);
17173 			updateNotesFramesStyles(noteStyle);
17174 		}
17175 		docWasChanged = notesFramesUpdate();
17176 	}
17177 
17178 	//for all marks
17179 	for (Mark* mrk : qAsConst(m_docMarksList))
17180 	{
17181 		//set mark page number
17182 		PageItem* mItem = findFirstMarkItem(mrk);
17183 		if (mItem != nullptr)
17184 			mrk->OwnPage = mItem->OwnPage;
17185 		else
17186 			mrk->OwnPage = -1;
17187 		if (mrk->isType(MARK2ItemType))
17188 		{
17189 			if (mrk->getItemPtr() != nullptr)
17190 			{
17191 				mrk->setString(getSectionPageNumberForPageIndex(mrk->getItemPtr()->OwnPage));
17192 				if (mItem != nullptr)
17193 				{
17194 					mItem->asTextFrame()->invalidateLayout(false);
17195 					docWasChanged = true;
17196 				}
17197 			}
17198 			else
17199 				mrk->clearString();
17200 		}
17201 		else if (mrk->isType(MARK2MarkType))
17202 		{
17203 			QString l;
17204 			MarkType t;
17205 			mrk->getMark(l, t);
17206 			Mark* destMark = getMark(l, t);
17207 			if (destMark != nullptr)
17208 			{
17209 				PageItem* dItem = findFirstMarkItem(destMark);
17210 				if (dItem != nullptr)
17211 				{
17212 					destMark->OwnPage = dItem->OwnPage;
17213 					mrk->setString(getSectionPageNumberForPageIndex(destMark->OwnPage));
17214 					if (mItem != nullptr)
17215 					{
17216 						mItem->asTextFrame()->invalidateLayout(false);
17217 						docWasChanged = true;
17218 					}
17219 				}
17220 				else
17221 				{
17222 					destMark->OwnPage = -1;
17223 					mrk->clearString();
17224 					docWasChanged = true;
17225 				}
17226 			}
17227 			else
17228 			{
17229 				mrk->clearString();
17230 				docWasChanged = true;
17231 			}
17232 		}
17233 	}
17234 	return docWasChanged;
17235 }
17236 
newNotesStyle(const NotesStyle & noteStyle)17237 NotesStyle* ScribusDoc::newNotesStyle(const NotesStyle& noteStyle)
17238 {
17239 	QString nsName = noteStyle.name();
17240 
17241 	//if doc is loading overwrite current set
17242 	NotesStyle* newNS = getNotesStyle(nsName);
17243 	if (isLoading() && (newNS != nullptr))
17244 		*newNS = noteStyle;
17245 	else
17246 	{
17247 		//add new notes style
17248 		if (!validateNSet(noteStyle))
17249 			return nullptr;
17250 		newNS = new NotesStyle();
17251 		*newNS = noteStyle;
17252 		QStringList nsNames;
17253 		for (int i = 0; i< m_docNotesStylesList.count(); ++i)
17254 			nsNames.append(m_docNotesStylesList.at(i)->name());
17255 		getUniqueName(nsName, nsNames, "_");
17256 		newNS->setName(nsName);
17257 		m_docNotesStylesList.append(newNS);
17258 		if (m_undoManager->undoEnabled())
17259 		{
17260 			SimpleState* ss = new SimpleState(UndoManager::NewNotesStyle);
17261 			ss->set("NSTYLE", QString("new"));
17262 			undoSetNotesStyle(ss, newNS);
17263 			m_undoManager->action(this, ss);
17264 		}
17265 	}
17266 	return newNS;
17267 }
17268 
renameNotesStyle(NotesStyle * noteStyle,const QString & newName)17269 void ScribusDoc::renameNotesStyle(NotesStyle* noteStyle, const QString& newName)
17270 {
17271 	for (Mark* mrk : qAsConst(m_docMarksList))
17272 		mrk->label.replace("_" + noteStyle->name()+ "_", "_" + newName + "_");
17273 	noteStyle->setName(newName);
17274 }
17275 
deleteNotesStyle(const QString & nsName)17276 void ScribusDoc::deleteNotesStyle(const QString& nsName)
17277 {
17278 	NotesStyle* noteStyle = getNotesStyle(nsName);
17279 	assert(noteStyle != nullptr);
17280 	//do not delete default notes style
17281 	if (noteStyle == m_docNotesStylesList.at(0))
17282 		return;
17283 	UndoTransaction activeTransaction;
17284 	if (UndoManager::undoEnabled())
17285 		activeTransaction = m_undoManager->beginTransaction(Um::DeleteNotesStyle, Um::IDelete, Um::Delete, "", Um::IDelete);
17286 	QList<TextNote*> toDel;
17287 	//search for notes to deleting
17288 	for (TextNote* note : qAsConst(m_docNotesList))
17289 	{
17290 		if (note->notesStyle() == noteStyle)
17291 			toDel.append(note);
17292 	}
17293 	//deleting notes
17294 	QList<PageItem*> master2Update;
17295 	if (!toDel.isEmpty())
17296 	{
17297 		while (!toDel.isEmpty())
17298 		{
17299 			TextNote* note = toDel.takeFirst();
17300 			master2Update.append(findFirstMarkItem(note->masterMark()));
17301 			setUndoDelNote(note);
17302 			deleteNote(note);
17303 		}
17304 		while (!master2Update.isEmpty())
17305 			master2Update.takeFirst()->layout();
17306 	}
17307 	if (activeTransaction)
17308 	{
17309 		//undo is enabled
17310 		SimpleState* ss = new SimpleState(UndoManager::DeleteNotesStyle);
17311 		ss->set("NSTYLE", QString("delete"));
17312 		undoSetNotesStyle(ss, noteStyle);
17313 		m_undoManager->action(this, ss);
17314 
17315 		activeTransaction.commit();
17316 	}
17317 	flag_updateMarksLabels = true;
17318 	if (noteStyle->isEndNotes())
17319 		flag_updateEndNotes = true;
17320 	notesFramesUpdate();
17321 	m_docNotesStylesList.removeOne(noteStyle);
17322 	scMW()->emitUpdateRequest(reqMarksUpdate);
17323 	delete noteStyle;
17324 }
17325 
undoSetNotesStyle(SimpleState * ss,NotesStyle * noteStyle)17326 void ScribusDoc::undoSetNotesStyle(SimpleState* ss, NotesStyle *noteStyle)
17327 {
17328 	ss->set("name", noteStyle->name());
17329 	ss->set("start", noteStyle->start());
17330 	ss->set("endNotes", noteStyle->isEndNotes());
17331 	ss->set("numFormat", (int) noteStyle->getType());
17332 	ss->set("range", (int) noteStyle->range());
17333 	ss->set("prefix", noteStyle->prefix());
17334 	ss->set("suffix", noteStyle->suffix());
17335 	ss->set("autoH", noteStyle->isAutoNotesHeight());
17336 	ss->set("autoW", noteStyle->isAutoNotesWidth());
17337 	ss->set("autoWeld", noteStyle->isAutoWeldNotesFrames());
17338 	ss->set("autoRemove", noteStyle->isAutoRemoveEmptyNotesFrames());
17339 	ss->set("superMaster", noteStyle->isSuperscriptInMaster());
17340 	ss->set("superNote", noteStyle->isSuperscriptInNote());
17341 	ss->set("marksChStyle", noteStyle->marksChStyle());
17342 	ss->set("notesParStyle", noteStyle->notesParStyle());
17343 }
17344 
getNotesStyle(const QString & nsName)17345 NotesStyle* ScribusDoc::getNotesStyle(const QString& nsName)
17346 {
17347 	for (int i=0; i < m_docNotesStylesList.count(); ++i)
17348 	{
17349 		if (m_docNotesStylesList.at(i)->name() == nsName)
17350 			return m_docNotesStylesList.at(i);
17351 	}
17352 	return nullptr;
17353 }
17354 
deleteNote(TextNote * note)17355 void ScribusDoc::deleteNote(TextNote* note)
17356 {
17357 	if (note == nullptr)
17358 		return;
17359 	PageItem_NoteFrame* nF = nullptr;
17360 	if (note->noteMark() != nullptr)
17361 	{
17362 		if (note->noteMark()->getItemPtr() != nullptr)
17363 			nF = note->noteMark()->getItemPtr()->asNoteFrame();
17364 		if (nF == nullptr)
17365 			nF = findFirstMarkItem(note->noteMark())->asNoteFrame();
17366 	}
17367 	PageItem* master = note->masterMark()->getItemPtr();
17368 	if (nF != nullptr)
17369 	{
17370 		nF->removeNote(note);
17371 		nF->invalid = true;
17372 		master->invalid = true;
17373 		if (nF->notesList().isEmpty() && nF->isAutoNoteFrame())
17374 		{
17375 			nF->deleteIt = true;
17376 			master->asTextFrame()->removeNoteFrame(nF);
17377 		}
17378 	}
17379 	if (note->masterMark() != nullptr)
17380 		eraseMark(note->masterMark(), true, master);
17381 	if (note->noteMark() != nullptr)
17382 		eraseMark(note->noteMark(), true, nF);
17383 	m_docNotesList.removeOne(note);
17384 	setNotesChanged(true);
17385 	if (note->isEndNote())
17386 		flag_updateEndNotes = true;
17387 	delete note;
17388 }
17389 
setUndoDelNote(TextNote * note)17390 void ScribusDoc::setUndoDelNote(TextNote *note)
17391 {
17392 	if (UndoManager::undoEnabled())
17393 	{
17394 		ScItemsState* ims = new ScItemsState(Um::DeleteNote,"",Um::IDelete);
17395 		ims->set("DELETE_NOTE");
17396 		PageItem* master = note->masterMark()->getItemPtr();
17397 		int pos = findMarkCPos(note->masterMark(), master);
17398 		Q_ASSERT(pos > -1);
17399 		Q_ASSERT(master);
17400 		ims->insertItem("inItem", master);
17401 		ims->set("at", pos);
17402 		ims->set("noteTXT", note->saxedText());
17403 		ims->set("nStyle", note->notesStyle()->name());
17404 		if (!note->notesStyle()->isAutoRemoveEmptyNotesFrames())
17405 			ims->insertItem("noteframe", note->noteMark()->getItemPtr());
17406 		m_undoManager->action(this, ims);
17407 	}
17408 }
17409 
updateItemNotesNums(PageItem_TextFrame * frame,NotesStyle * nStyle,int & num)17410 void ScribusDoc::updateItemNotesNums(PageItem_TextFrame* frame, NotesStyle* nStyle, int &num)
17411 {
17412 	//update marks strings in master text and in notes frame (only numbers!)
17413 	//check if notes should be added or removed from notes frame
17414 	int noteNum = num;
17415 	int index = 0;
17416 	bool doUpdate = false;
17417 
17418 	for (int pos = frame->firstInFrame(); pos <= frame->lastInFrame(); ++pos)
17419 	{
17420 		Mark* mark = frame->itemText.mark(pos);
17421 		if (frame->itemText.hasMark(pos) && mark->isType(MARKNoteMasterType))
17422 		{
17423 			if (mark->getNotePtr() == nullptr)
17424 				continue;
17425 			if (mark->getNotePtr()->notesStyle() == nStyle)
17426 			{
17427 				QString numStr = nStyle->prefix() + nStyle->numString(noteNum) + nStyle->suffix();
17428 				QString mStr = mark->getString();
17429 				QString label = mark->label;
17430 				if ((mStr != numStr) || flag_updateMarksLabels || flag_updateEndNotes)
17431 				{
17432 					doUpdate = true;
17433 					mark->setString(numStr);
17434 					label = "NoteMark_" + nStyle->name();
17435 					if (nStyle->range() == NSRstory)
17436 						label += " in " + frame->firstInChain()->itemName();
17437 					label += "_" + QString::number(noteNum);
17438 					mark->label = label;
17439 				}
17440 				TextNote* note = mark->getNotePtr();
17441 				note->setNum(noteNum);
17442 				note->masterMark()->setItemPtr(frame);
17443 				if (note->noteMark() != nullptr)
17444 				{
17445 					note->noteMark()->setString(numStr);
17446 					label = label.replace("NoteMark","NoteFrameMark");
17447 					note->noteMark()->label = label;
17448 				}
17449 				++index;
17450 				++noteNum;
17451 			}
17452 		}
17453 	}
17454 	PageItem_NoteFrame* nF = nullptr;
17455 	if (nStyle->isEndNotes())
17456 		nF = endNoteFrame(nStyle);
17457 	else
17458 		nF = frame->itemNoteFrame(nStyle);
17459 
17460 	if (doUpdate)
17461 	{
17462 		frame->invalidateLayout(false);
17463 		if ((nF != nullptr) && !nF->deleteIt)
17464 		{
17465 			if (nStyle->isEndNotes())
17466 				m_docEndNotesFramesChanged.append(nF);
17467 			else
17468 				nF->invalidateLayout(true);
17469 		}
17470 	}
17471 	num = noteNum;
17472 	if (!nStyle->isEndNotes() && (index == 0) && (nF != nullptr) && nF->isAutoNoteFrame())
17473 		nF->deleteIt = true;
17474 }
17475 
updateNotesNums(NotesStyle * nStyle)17476 bool ScribusDoc::updateNotesNums(NotesStyle *nStyle)
17477 {
17478 	bool docWasChanged = false;
17479 	flag_restartMarksRenumbering = false;
17480 	flag_updateEndNotes = false;
17481 	PageItem_NoteFrame* endNF = nullptr;
17482 	if (nStyle->isEndNotes() && nStyle->range() == NSRdocument)
17483 	{
17484 		endNF = endNoteFrame(nStyle);
17485 		if (endNF != nullptr)
17486 			clearNotesInFrameList(endNF);
17487 	}
17488 	flag_layoutNotesFrames = false;  //do not layout notes frames while counting notes
17489 	int num, i;
17490 	int itemsCount = Items->count();
17491 	if (nStyle->range() == NSRdocument)
17492 	{
17493 		//FIX ME: how to change frames order on page? and what about reverse page order?
17494 		num = nStyle->start();
17495 		for (int page = 0; page < Pages->count(); ++page)
17496 		{
17497 			for (i = 0; i < itemsCount; ++i)
17498 			{
17499 				PageItem* currItem = Items->at(i);
17500 				if ((currItem->OwnPage == page) && currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0))
17501 				{
17502 					if (!currItem->asTextFrame()->isValidChainFromBegin())
17503 					{
17504 						currItem->layout();
17505 						if (flag_restartMarksRenumbering)
17506 						{
17507 							//restart whole update as items was changed
17508 							if (endNF != nullptr)
17509 								clearNotesInFrameList(endNF);
17510 							page = -1;
17511 							itemsCount = Items->count();
17512 							num = nStyle->start();
17513 							docWasChanged = true;
17514 							flag_restartMarksRenumbering = false;
17515 							break;
17516 						}
17517 					}
17518 					if (nStyle->isEndNotes() || currItem->asTextFrame()->hasNoteFrame(nStyle, false))
17519 						updateItemNotesNums(currItem->asTextFrame(), nStyle, num);
17520 					if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid)
17521 						docWasChanged = true;
17522 					if (currItem->invalid)
17523 					{
17524 						currItem->layout();
17525 						docWasChanged = true;
17526 					}
17527 				}
17528 			}
17529 		}
17530 		if ((num == nStyle->start()) && nStyle->isEndNotes())
17531 		{
17532 			PageItem_NoteFrame* nF = endNoteFrame(nStyle);
17533 			if (nF != nullptr && nF->isAutoNoteFrame())
17534 				nF->deleteIt = true;
17535 		}
17536 	}
17537 	else if (nStyle->range() == NSRstory)
17538 	{
17539 		for (i = 0; i < itemsCount; ++i)
17540 		{
17541 			PageItem* currItem = Items->at(i);
17542 			if (currItem == nullptr)
17543 				continue;
17544 			if (currItem->isTextFrame() && !currItem->isNoteFrame() && (currItem->itemText.length() > 0))
17545 			{
17546 				if (nStyle->isEndNotes())
17547 				{
17548 					endNF = endNoteFrame(nStyle, (void*) currItem);
17549 					if (endNF != nullptr)
17550 						clearNotesInFrameList(endNF);
17551 				}
17552 				if (!currItem->asTextFrame()->isValidChainFromBegin())
17553 				{
17554 					currItem->layout();
17555 					if (flag_restartMarksRenumbering)
17556 					{
17557 						//restart whole update as items was changed
17558 						if (endNF != nullptr)
17559 							clearNotesInFrameList(endNF);
17560 						i = -1;
17561 						itemsCount = Items->count();
17562 						docWasChanged = true;
17563 						flag_restartMarksRenumbering = false;
17564 						continue;
17565 					}
17566 				}
17567 				//restart numeration for all first frames of story chain
17568 				if (currItem->prevInChain() == nullptr)
17569 				{
17570 					num = nStyle->start();
17571 					PageItem* nextItem = currItem;
17572 					while (nextItem != nullptr)
17573 					{
17574 						if (nStyle->isEndNotes() || nextItem->asTextFrame()->hasNoteFrame(nStyle, false))
17575 							updateItemNotesNums(nextItem->asTextFrame(), nStyle, num);
17576 						nextItem = nextItem->nextInChain();
17577 					}
17578 				}
17579 				if (currItem->asTextFrame()->hasNoteFrame(nStyle, false) && currItem->asTextFrame()->itemNoteFrame(nStyle)->invalid)
17580 					docWasChanged = true;
17581 				if (currItem->invalid)
17582 				{
17583 					currItem->layout();
17584 					docWasChanged = true;
17585 				}
17586 			}
17587 		}
17588 	}
17589 	flag_layoutNotesFrames = true;
17590 	return docWasChanged;
17591 }
17592 
updateEndNotesNums()17593 bool ScribusDoc::updateEndNotesNums()
17594 {
17595 	bool docWasChanged = false;
17596 	for (NotesStyle* ns : qAsConst(m_docNotesStylesList))
17597 	{
17598 		if (ns->isEndNotes())
17599 		{
17600 			if (updateNotesNums(ns))
17601 				docWasChanged = true;
17602 		}
17603 	}
17604 	return docWasChanged;
17605 }
17606 
updateNotesFramesStyles(NotesStyle * nStyle)17607 void ScribusDoc::updateNotesFramesStyles(NotesStyle *nStyle)
17608 {
17609 	for (int i=0; i<Items->count(); ++i)
17610 	{
17611 		PageItem* item = Items->at(i);
17612 		if (item->isNoteFrame() && (item->asNoteFrame()->notesStyle() == nStyle) && !item->asNoteFrame()->deleteIt)
17613 		{
17614 			ParagraphStyle newStyle;
17615 			if (nStyle->notesParStyle().isEmpty() || (nStyle->notesParStyle() == tr("No Style")))
17616 			{
17617 				if (nStyle->isEndNotes())
17618 					//set default doc style
17619 					newStyle.setParent(paragraphStyles()[0].name());
17620 				else
17621 				{
17622 					if (item->asNoteFrame()->masterFrame() != nullptr)
17623 					{
17624 						//set back style from master frame
17625 						newStyle.setParent(item->asNoteFrame()->masterFrame()->itemText.defaultStyle().parent());
17626 						newStyle.applyStyle(item->asNoteFrame()->masterFrame()->currentStyle());
17627 					}
17628 					else
17629 						newStyle.setParent(item->itemText.defaultStyle().parent());
17630 				}
17631 			}
17632 			else
17633 				newStyle.setParent(nStyle->notesParStyle());
17634 			item->itemText.setDefaultStyle(newStyle);
17635 			item->asTextFrame()->invalidateLayout(true);
17636 		}
17637 	}
17638 }
17639 
updateItemNotesFramesStyles(PageItem * item,const ParagraphStyle & newStyle)17640 void ScribusDoc::updateItemNotesFramesStyles(PageItem* item, const ParagraphStyle& newStyle)
17641 {
17642 	if (!item->isTextFrame() || item->isNoteFrame())
17643 		return;
17644 
17645 	item = item->firstInChain();
17646 	while (item != nullptr)
17647 	{
17648 		auto noteFrameList = item->asTextFrame()->notesFramesList();
17649 		for (PageItem_NoteFrame* noteFrame :  qAsConst(noteFrameList))
17650 		{
17651 			NotesStyle* nSet = noteFrame->notesStyle();
17652 			if (nSet->isEndNotes())
17653 				continue;
17654 			if (nSet->notesParStyle().isEmpty() || (nSet->notesParStyle() == tr("No Style")))
17655 			{
17656 				noteFrame->itemText.setDefaultStyle(newStyle);
17657 				//nF->itemText.applyCharStyle(0, nF->itemText.length(), newStyle.charStyle());
17658 			}
17659 			setNotesChanged(true);
17660 		}
17661 		item = item->nextInChain();
17662 	}
17663 }
17664 
listNotesFrames(NotesStyle * noteStyle)17665 QList<PageItem_NoteFrame *> ScribusDoc::listNotesFrames(NotesStyle *noteStyle)
17666 {
17667 	QList<PageItem_NoteFrame *> list;
17668 	for (PageItem* item : qAsConst(DocItems))
17669 	{
17670 		if (item->isNoteFrame() && item->asNoteFrame()->notesStyle() == noteStyle)
17671 			list.append(item->asNoteFrame());
17672 	}
17673 	return list;
17674 }
17675 
page4EndNotes(NotesStyle * noteStyle,PageItem * item)17676 const ScPage *ScribusDoc::page4EndNotes(NotesStyle *noteStyle, PageItem* item)
17677 {
17678 	ScPage* scP = nullptr;
17679 	if (noteStyle->range() == NSRdocument)
17680 		scP = DocPages.last();
17681 	else if (item != nullptr)
17682 	{
17683 		if (noteStyle->range() == NSRstory)
17684 			scP = DocPages.at(item->lastInChain()->OwnPage);
17685 	}
17686 
17687 	return scP;
17688 }
17689 
notesFramesUpdate()17690 bool ScribusDoc::notesFramesUpdate()
17691 {
17692 	bool removeEmptyNF = false;
17693 	bool docWasChanged = false;
17694 	int end = 0;
17695 	do {
17696 		setNotesChanged(false);
17697 		end = Items->count();
17698 		for (int i = 0; i < end; ++i)
17699 		{
17700 			PageItem* item = Items->at(i);
17701 			if (!item->isTextFrame())
17702 				continue;
17703 			if (item->isNoteFrame())
17704 			{
17705 				if (item->asNoteFrame()->notesList().isEmpty())
17706 				{
17707 					if (item->isAutoNoteFrame())
17708 						item->asNoteFrame()->deleteIt = true;
17709 				}
17710 				else
17711 				{
17712 					if (item->asNoteFrame()->isEndNotesFrame())
17713 						updateEndNotesFrameContent(item->asNoteFrame());
17714 					else
17715 					{
17716 						if (item->itemText.length() == 0 && !item->asNoteFrame()->notesList().isEmpty())
17717 							item->asNoteFrame()->updateNotes(item->asNoteFrame()->notesList(), true);
17718 						item->invalid = true;
17719 						item->layout();
17720 					}
17721 				}
17722 				if (item->asNoteFrame()->deleteIt)
17723 					removeEmptyNF = true;
17724 			}
17725 			if (end != Items->count())
17726 			{
17727 				end = Items->count();
17728 				setNotesChanged(true);
17729 			}
17730 			docWasChanged = docWasChanged || notesChanged();
17731 			if (notesChanged())
17732 				break;
17733 		}
17734 	} while (notesChanged());
17735 
17736 	if (removeEmptyNF)
17737 	{
17738 		end = Items->count();
17739 		QList<PageItem*> tmplist;
17740 		for (int i = 0; i < end; ++i)
17741 		{
17742 			PageItem* item = Items->at(i);
17743 			if (item->isAutoNoteFrame() && item->asNoteFrame()->deleteIt)
17744 				tmplist.append(item);
17745 		}
17746 		for (PageItem* item : tmplist)
17747 		{
17748 			if (item->asNoteFrame()->masterFrame())
17749 				item->asNoteFrame()->masterFrame()->invalid = true;
17750 			delNoteFrame(item->asNoteFrame());
17751 		}
17752 		docWasChanged = true;
17753 	}
17754 	return docWasChanged;
17755 }
17756 
updateNotesFramesSettings(NotesStyle * noteStyle)17757 void ScribusDoc::updateNotesFramesSettings(NotesStyle *noteStyle)
17758 {
17759 	QList<PageItem_NoteFrame*> noteFramesList = listNotesFrames(noteStyle);
17760 	for (PageItem_NoteFrame* nF : qAsConst(noteFramesList))
17761 	{
17762 		if (nF->isWelded() && !noteStyle->isAutoWeldNotesFrames())
17763 			nF->unWeld();
17764 		if (!nF->isWelded() && noteStyle->isAutoWeldNotesFrames())
17765 		{
17766 			nF->setYPos(nF->masterFrame()->yPos() + nF->masterFrame()->height());
17767 			nF->setXPos(nF->masterFrame()->xPos());
17768 			nF->addWelded(nF->masterFrame());
17769 			nF->masterFrame()->addWelded(nF);
17770 			nF->masterFrame()->setWeldPoint(0, nF->masterFrame()->height(), nF);
17771 			nF->setWeldPoint(0,0, nF->masterFrame());
17772 			nF->invalidateLayout(false);
17773 		}
17774 		nF->setSizeVLocked(noteStyle->isAutoNotesHeight());
17775 		nF->setSizeHLocked(noteStyle->isAutoNotesWidth());
17776 		nF->setSizeLocked(noteStyle->isAutoNotesHeight() && noteStyle->isAutoNotesWidth());
17777 		if (noteStyle->isAutoNotesHeight() || noteStyle->isAutoNotesWidth())
17778 			nF->invalidateLayout(false);
17779 	}
17780 }
17781 
updateEndnotesFrames(NotesStyle * nStyle,bool invalidate)17782 void ScribusDoc::updateEndnotesFrames(NotesStyle* nStyle, bool invalidate)
17783 {
17784 	if (m_docEndNotesFramesMap.isEmpty())
17785 		return;
17786 	if (nStyle == nullptr)
17787 	{
17788 		int nsCount = m_docNotesStylesList.count();
17789 		for (int i=0; i < nsCount; ++i)
17790 			updateEndnotesFrames(m_docNotesStylesList.at(i));
17791 	}
17792 	else if (nStyle->isEndNotes())
17793 	{
17794 		auto noteFrameList = listNotesFrames(nStyle);
17795 		for (PageItem_NoteFrame* nF : qAsConst(noteFrameList))
17796 			updateEndNotesFrameContent(nF);
17797 	}
17798 	flag_updateEndNotes = false;
17799 }
17800 
17801 //for sorting purpose
ascendingSort(TextNote * nt1,TextNote * nt2)17802 bool ascendingSort(TextNote* nt1, TextNote* nt2) { return nt1->num() < nt2->num(); }
17803 
updateEndNotesFrameContent(PageItem_NoteFrame * nF,bool invalidate)17804 void ScribusDoc::updateEndNotesFrameContent(PageItem_NoteFrame *nF, bool invalidate)
17805 {
17806 	QList<TextNote*> nList;
17807 	for (PageItem* item : qAsConst(DocItems))
17808 	{
17809 		if (item->isTextFrame() && !item->isNoteFrame())
17810 		{
17811 			QList<TextNote*> nL = item->asTextFrame()->notesList(nF);
17812 			if (!nL.isEmpty())
17813 				nList.append(nL);
17814 			if (invalidate)
17815 				item->invalid = true;
17816 		}
17817 	}
17818 
17819 	if (nList.isEmpty())
17820 	{
17821 		if (nF->isAutoNoteFrame())
17822 		{
17823 			nF->deleteIt = true;
17824 			m_docNotesInFrameMap.remove(nF);
17825 			delNoteFrame(nF);
17826 		}
17827 	}
17828 	else
17829 	{
17830 		NotesStyle* currNS = nF->notesStyle();
17831 		if (currNS->isAutoNotesHeight() || currNS->isAutoNotesWidth())
17832 			nF->invalidateLayout(false);
17833 		std::sort(nList.begin(), nList.end(), ascendingSort);
17834 		if (nList == m_docNotesInFrameMap.value(nF))
17835 			return;
17836 
17837 		nF->updateNotes(nList);
17838 		nF->invalid = true;
17839 		nF->layout();
17840 		//layout all endnotes frames with same range
17841 		for (NotesStyle* noteStyle : qAsConst(m_docNotesStylesList))
17842 		{
17843 			if ((noteStyle != currNS) && (noteStyle->isEndNotes() && noteStyle->range() == currNS->range()))
17844 			{
17845 				auto noteFrameList = listNotesFrames(noteStyle);
17846 				for (PageItem_NoteFrame* noteFrame : qAsConst(noteFrameList))
17847 					noteFrame->layout();
17848 			}
17849 		}
17850 		m_docNotesInFrameMap.insert(nF, nList);
17851 	}
17852 }
17853 
updateChangedEndNotesFrames()17854 void ScribusDoc::updateChangedEndNotesFrames()
17855 {
17856 	while (!m_docEndNotesFramesChanged.isEmpty())
17857 	{
17858 		PageItem_NoteFrame* nF = m_docEndNotesFramesChanged.first();
17859 		m_docEndNotesFramesChanged.removeAll(nF);
17860 		updateEndNotesFrameContent(nF);
17861 		if (nF->deleteIt && nF->isAutoNoteFrame())
17862 			delNoteFrame(nF);
17863 	}
17864 }
17865 
createNoteFrame(PageItem_TextFrame * inFrame,NotesStyle * nStyle,int index)17866 PageItem_NoteFrame *ScribusDoc::createNoteFrame(PageItem_TextFrame *inFrame, NotesStyle *nStyle, int index)
17867 {
17868 	PageItem_NoteFrame* nF = new PageItem_NoteFrame(inFrame, nStyle);
17869 	if (nStyle->isEndNotes())
17870 		m_docEndNotesFramesMap.insert(nF, rangeItem());
17871 	m_docNotesInFrameMap.insert(nF, QList<TextNote*>());
17872 	if (index > -1)
17873 		DocItems.insert(index, nF);
17874 	else
17875 		DocItems.append(nF);
17876 	return nF;
17877 }
17878 
createNoteFrame(NotesStyle * nStyle,double x,double y,double w,double h,double w2,const QString & fill,const QString & outline)17879 PageItem_NoteFrame *ScribusDoc::createNoteFrame(NotesStyle *nStyle, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
17880 {
17881 	PageItem_NoteFrame* nF = new PageItem_NoteFrame(nStyle, this, x, y, w, h, w2, fill, outline);
17882 	if (nStyle->isEndNotes())
17883 		m_docEndNotesFramesMap.insert(nF, rangeItem());
17884 	m_docNotesInFrameMap.insert(nF, QList<TextNote*>());
17885 	DocItems.append(nF);
17886 	return nF;
17887 }
17888 
delNoteFrame(PageItem_NoteFrame * nF,bool removeMarks,bool forceDeletion)17889 void ScribusDoc::delNoteFrame(PageItem_NoteFrame* nF, bool removeMarks, bool forceDeletion)
17890 {
17891 	Q_ASSERT(nF != nullptr);
17892 
17893 	//for all notes in noteFrame set notes marks to null
17894 	for (TextNote* n : nF->notesList())
17895 		n->setNoteMark(nullptr);
17896 
17897 	if (nF->itemText.length() > 0 && removeMarks)
17898 		nF->removeMarksFromText(false);
17899 
17900 	if (appMode == modeEdit && nF->isSelected())
17901 	{
17902 		view()->deselectItems(true);
17903 		if (!nF->isEndNotesFrame())
17904 			view()->selectItem(nF->masterFrame());
17905 	}
17906 	if (m_docEndNotesFramesMap.contains(nF))
17907 	{
17908 		m_docEndNotesFramesMap.remove(nF);
17909 		m_docEndNotesFramesChanged.removeAll(nF);
17910 		for (TextNote* note : nF->notesList())
17911 		{
17912 			PageItem* masterMarkItem = note->masterMark()->getItemPtr();
17913 			masterMarkItem->asTextFrame()->removeNoteFrame(nF);
17914 			masterMarkItem->invalid = true;
17915 		}
17916 	}
17917 	else if (nF->masterFrame() != nullptr)
17918 	{
17919 		nF->masterFrame()->removeNoteFrame(nF);
17920 		nF->masterFrame()->invalid = true;
17921 	}
17922 	m_docNotesInFrameMap.remove(nF);
17923 
17924 	nF->dropLinks();
17925 	if (nF->isWelded())
17926 		nF->unWeld(!nF->isAutoNoteFrame());
17927 	//delete marks pointed to that item
17928 	for (int a=0; a < m_docMarksList.count(); ++a)
17929 	{
17930 		Mark* m = m_docMarksList.at(a);
17931 		Q_ASSERT(m != nullptr);
17932 		if (m->isType(MARK2ItemType) && (m->getItemPtr() == nF))
17933 		{
17934 			setUndoDelMark(m);
17935 			eraseMark(m, true);
17936 		}
17937 	}
17938 	m_Selection->delaySignalsOn();
17939 	if (m_Selection->findItem(nF)!=-1)
17940 	{
17941 		if (appMode == modeEdit)
17942 			view()->requestMode(modeNormal);
17943 		m_Selection->removeItem(nF);
17944 		if (m_Selection->isEmpty() && nF->masterFrame())
17945 			m_Selection->addItem(nF->masterFrame());
17946 	}
17947 	m_Selection->delaySignalsOff();
17948 
17949 	Items->removeOne(nF);
17950 
17951 	QList<PageItem*> allItems = *Items;
17952 	while (allItems.count() > 0)
17953 	{
17954 		PageItem* item = allItems.takeFirst();
17955 		if (item->isGroup() || item->isTable())
17956 		{
17957 			allItems = item->getChildren() + allItems;
17958 			continue;
17959 		}
17960 		if (item->isTextFrame())
17961 			item->asTextFrame()->removeNoteFrame(nF);
17962 	}
17963 	setNotesChanged(true);
17964 	if (forceDeletion)
17965 		delete nF;
17966 }
17967 
validateNSet(const NotesStyle & noteStyle,QString newName)17968 bool ScribusDoc::validateNSet(const NotesStyle& noteStyle, QString newName)
17969 {
17970 	//check if chosen numbering type is available with chosen range, prefix and suffix
17971 	QString errStr;
17972 	for (NotesStyle* NS2 : qAsConst(m_docNotesStylesList))
17973 	{
17974 		if (newName.isEmpty())
17975 			//hack for validate nset while its name will change
17976 			newName = noteStyle.name();
17977 		if (newName == NS2->name())
17978 			continue;
17979 		if (noteStyle.range() == NS2->range())
17980 		{
17981 			if ((noteStyle.getType() == NS2->getType()) && (noteStyle.prefix() == NS2->prefix()) && (noteStyle.suffix() == NS2->suffix()))
17982 				errStr.append(tr("%1 note style has document as range and provide same numbering style as set %2").arg(noteStyle.name(), NS2->name()) + "\n");
17983 		}
17984 	}
17985 
17986 	if (!errStr.isEmpty() && ScCore->usingGUI())
17987 	{
17988 		ScMessageBox::warning(this->scMW(), QObject::tr("Unacceptable settings for note style"), "<qt>"+ errStr +"</qt>");
17989 		return false;
17990 	}
17991 	return true;
17992 }
17993 
invalidateNoteFrames(NotesStyle * nStyle)17994 void ScribusDoc::invalidateNoteFrames(NotesStyle *nStyle)
17995 {
17996 	auto noteFrameList = listNotesFrames(nStyle);
17997 	for (PageItem_NoteFrame* noteFrame : qAsConst(noteFrameList))
17998 		noteFrame->invalid = true;
17999 }
18000 
invalidateMasterFrames(NotesStyle * nStyle)18001 void ScribusDoc::invalidateMasterFrames(NotesStyle *nStyle)
18002 {
18003 	QList<PageItem*> toInvalidate;
18004 	for (TextNote* note : qAsConst(m_docNotesList))
18005 	{
18006 		if (note->notesStyle() == nStyle)
18007 			toInvalidate.append(note->masterMark()->getItemPtr());
18008 	}
18009 	while (!toInvalidate.isEmpty())
18010 		toInvalidate.takeFirst()->invalid = true;
18011 }
18012 
endNoteFrame(NotesStyle * nStyle,PageItem_TextFrame * master)18013 PageItem_NoteFrame *ScribusDoc::endNoteFrame(NotesStyle *nStyle, PageItem_TextFrame *master)
18014 {
18015 	if (nStyle->range() == NSRdocument)
18016 		return endNoteFrame(nStyle);
18017 	if (nStyle->range() == NSRstory)
18018 		return endNoteFrame(nStyle, master->firstInChain());
18019 	return nullptr;
18020 }
18021 
endNoteFrame(NotesStyle * nStyle,void * item)18022 PageItem_NoteFrame* ScribusDoc::endNoteFrame(NotesStyle *nStyle, void* item)
18023 {
18024 	if (m_docEndNotesFramesMap.isEmpty())
18025 		return nullptr;
18026 	if ((nStyle->range() != NSRdocument) && (item == nullptr))
18027 		return nullptr;
18028 
18029 	QMap<PageItem_NoteFrame*, rangeItem>::Iterator it = m_docEndNotesFramesMap.begin();
18030 	QMap<PageItem_NoteFrame*, rangeItem>::Iterator end = m_docEndNotesFramesMap.end();
18031 
18032 	while (it != end)
18033 	{
18034 		PageItem_NoteFrame* nF = it.key();
18035 		rangeItem rItem = it.value();
18036 
18037 		if (nF->notesStyle() == nStyle)
18038 		{
18039 			if ((nStyle->range() == NSRdocument) || (item == rItem.P))
18040 				return nF;
18041 		}
18042 		++it;
18043 	}
18044 	return nullptr;
18045 }
18046 
18047 /* Functions for PDF Form Actions */
18048 
SubmitForm()18049 void ScribusDoc::SubmitForm()
18050 {
18051 }
18052 
ImportData()18053 void ScribusDoc::ImportData()
18054 {
18055 }
18056 
ResetFormFields()18057 void ScribusDoc::ResetFormFields()
18058 {
18059 	for (PageItemIterator it(this, PageItemIterator::IterateInDocDefaults); *it; ++it)
18060 	{
18061 		PageItem* currItem = *it;
18062 		if (!currItem->isAnnotation())
18063 			continue;
18064 
18065 		if ((currItem->annotation().Type() == Annotation::RadioButton) || (currItem->annotation().Type() == Annotation::Checkbox))
18066 			it->annotation().setCheckState(it->annotation().IsChk());
18067 		currItem->annotation().setOnState(false);
18068 		currItem->annotation().setOpen(false);
18069 		if (currItem->annotation().Type() == Annotation::Text)
18070 			currItem->asTextFrame()->setTextAnnotationOpen(false);
18071 		currItem->update();
18072 	}
18073 
18074 	changed();
18075 	regionsChanged()->update(QRect());
18076 }
18077