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 page.cpp - description
9 -------------------
10 begin : Sat Apr 7 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 <QDebug>
25 #include <QPixmap>
26
27 #include "appmodehelper.h"
28 #include "scpage.h"
29 #include "scribus.h"
30 #include "scribusdoc.h"
31 #include "scribusview.h"
32 #include "selection.h"
33 #include "undomanager.h"
34 #include "undostate.h"
35
36 #include "ui/guidemanager.h"
37 #include "ui/nodeeditpalette.h"
38
ScPage(const double x,const double y,const double b,const double h)39 ScPage::ScPage(const double x, const double y, const double b, const double h) :
40 UndoObject(QObject::tr("Page")),
41 SingleObservable<ScPage>(nullptr),
42 Margins(40,40,40,40),
43 initialMargins(40,40,40,40),
44 undoManager(UndoManager::instance()),
45 m_xOffset(x),
46 m_yOffset(y),
47 m_width(b),
48 m_height(h),
49 m_initialWidth(b),
50 m_initialHeight(h)
51 {
52 guides.setPage(this);
53 }
54
~ScPage()55 ScPage::~ScPage()
56 {
57 // Clean up any modified template items (unused)
58 // for (PageItem *currItem = FromMaster.first(); currItem; currItem = FromMaster.next())
59 // {
60 // if (currItem->ChangedMasterItem)
61 // {
62 // FromMaster.remove(currItem);
63 // delete currItem;
64 // }
65 // }
66 FromMaster.clear();
67 }
68
bleedRect() const69 QRectF ScPage::bleedRect() const
70 {
71 QRectF pageRect(m_xOffset, m_yOffset, m_width, m_height);
72 if (m_Doc)
73 {
74 MarginStruct pageBleeds;
75 m_Doc->getBleeds(this, pageBleeds);
76 double totalWidth = m_width + pageBleeds.left() + pageBleeds.right();
77 double totalHeight = m_height + pageBleeds.bottom() + pageBleeds.top();
78 pageRect = QRectF(m_xOffset - pageBleeds.left(), m_yOffset - pageBleeds.top(), totalWidth, totalHeight);
79 }
80 return pageRect;
81 }
82
trimRect() const83 QRectF ScPage::trimRect() const
84 {
85 QRectF pageRect(m_xOffset, m_yOffset, m_width, m_height);
86 return pageRect;
87 }
88
setDocument(ScribusDoc * doc)89 void ScPage::setDocument(ScribusDoc *doc)
90 {
91 m_Doc=doc;
92 setMassObservable(doc? doc->pagesChanged() : nullptr);
93 }
94
setPageNr(int pageNr)95 void ScPage::setPageNr(int pageNr)
96 {
97 m_pageNr = pageNr;
98 if (m_pageName.isEmpty())
99 setUName(QString(QObject::tr("Page") + " %1").arg(m_Doc->FirstPnum + m_pageNr));
100 else
101 setUName(m_pageName);
102 }
103
setPageName(const QString & newName)104 void ScPage::setPageName(const QString& newName)
105 {
106 m_pageName = newName;
107 if (!newName.isEmpty())
108 setUName(QObject::tr("Master Page ") + newName);
109 }
110
resetPageName()111 void ScPage::resetPageName()
112 {
113 m_pageName.clear();
114 }
115
setMasterPageName(const QString & newName)116 void ScPage::setMasterPageName(const QString& newName)
117 {
118 m_masterPageName = newName;
119 }
120
setMasterPageNameNormal()121 void ScPage::setMasterPageNameNormal()
122 {
123 m_masterPageName = CommonStrings::trMasterPageNormal;
124 }
125
clearMasterPageName()126 void ScPage::clearMasterPageName()
127 {
128 m_masterPageName.clear();
129 }
130
setSize(const QString & newSize)131 void ScPage::setSize(const QString& newSize)
132 {
133 m_pageSize = newSize;
134 }
135
restore(UndoState * state,bool isUndo)136 void ScPage::restore(UndoState* state, bool isUndo)
137 {
138 auto* ss = dynamic_cast<SimpleState*>(state);
139 if (!ss)
140 return;
141 if (ss->contains("ADD_V"))
142 {
143 double position = ss->getDouble("ADD_V");
144 if (isUndo)
145 guides.deleteVertical(position, GuideManagerCore::Standard);//removeXGuide(position);
146 else
147 guides.addVertical(position, GuideManagerCore::Standard);//addXGuide(position);
148 m_Doc->scMW()->guidePalette->setupGui();
149 }
150 else if (ss->contains("ADD_H"))
151 {
152 double position = ss->getDouble("ADD_H");
153 if (isUndo)
154 guides.deleteHorizontal(position, GuideManagerCore::Standard);//removeYGuide(position);
155 else
156 guides.addHorizontal(position, GuideManagerCore::Standard);//addYGuide(position);
157 m_Doc->scMW()->guidePalette->setupGui();
158 }
159 else if (ss->contains("REMOVE_V"))
160 {
161 double position = ss->getDouble("REMOVE_V");
162 if (isUndo)
163 guides.addVertical(position, GuideManagerCore::Standard);//addXGuide(position);
164 else
165 guides.deleteVertical(position, GuideManagerCore::Standard);//removeXGuide(position);
166 m_Doc->scMW()->guidePalette->setupGui();
167 }
168 else if (ss->contains("REMOVE_H"))
169 {
170 double position = ss->getDouble("REMOVE_H");
171 if (isUndo)
172 guides.addHorizontal(position, GuideManagerCore::Standard);//addYGuide(position);
173 else
174 guides.deleteHorizontal(position, GuideManagerCore::Standard);//removeYGuide(position);
175 m_Doc->scMW()->guidePalette->setupGui();
176 }
177 else if (ss->contains("MOVE_H_FROM"))
178 {
179 double from = ss->getDouble("MOVE_H_FROM");
180 double to = ss->getDouble("MOVE_H_TO");
181 if (isUndo)
182 {
183 guides.deleteHorizontal(to, GuideManagerCore::Standard);//removeYGuide(position);
184 guides.addHorizontal(from, GuideManagerCore::Standard);//addYGuide(position);
185 }
186 else
187 {
188 guides.deleteHorizontal(from, GuideManagerCore::Standard);//removeYGuide(position);
189 guides.addHorizontal(to, GuideManagerCore::Standard);//addYGuide(position);
190 }
191 m_Doc->scMW()->guidePalette->setupGui();
192 }
193 else if (ss->contains("MOVE_V_FROM"))
194 {
195 double from = ss->getDouble("MOVE_V_FROM");
196 double to = ss->getDouble("MOVE_V_TO");
197 if (isUndo)
198 {
199 guides.deleteVertical(to, GuideManagerCore::Standard);//removeXGuide(position);
200 guides.addVertical(from, GuideManagerCore::Standard);//removeXGuide(position);
201 }
202 else
203 {
204 guides.deleteVertical(from, GuideManagerCore::Standard);//removeXGuide(position);
205 guides.addVertical(to, GuideManagerCore::Standard);//removeXGuide(position);
206 }
207 m_Doc->scMW()->guidePalette->setupGui();
208 }
209 // automatic guides
210 else if (ss->contains("REMOVE_HA_GAP"))
211 {
212 if (isUndo)
213 {
214 guides.setHorizontalAutoCount(ss->getInt("REMOVE_HA_COUNT"));
215 guides.setHorizontalAutoGap(ss->getDouble("REMOVE_HA_GAP"));
216 guides.setHorizontalAutoRefer(ss->getInt("REMOVE_HA_REFER"));
217 }
218 else
219 {
220 guides.setHorizontalAutoCount(0);
221 guides.setHorizontalAutoGap(0.0);
222 guides.setHorizontalAutoRefer(0);
223 }
224 m_Doc->scMW()->guidePalette->setupGui();
225 }
226 else if (ss->contains("REMOVE_VA_GAP"))
227 {
228 if (isUndo)
229 {
230 guides.setVerticalAutoCount(ss->getInt("REMOVE_VA_COUNT"));
231 guides.setVerticalAutoGap(ss->getDouble("REMOVE_VA_GAP"));
232 guides.setVerticalAutoRefer(ss->getInt("REMOVE_VA_REFER"));
233 }
234 else
235 {
236 guides.setVerticalAutoCount(0);
237 guides.setVerticalAutoGap(0.0);
238 guides.setVerticalAutoRefer(0);
239 }
240 m_Doc->scMW()->guidePalette->setupGui();
241 }
242 else if (ss->contains("CREATE_ITEM"))
243 restorePageItemCreation(dynamic_cast<ScItemState<PageItem*>*>(ss), isUndo);
244 else if (ss->contains("DELETE_ITEM"))
245 restorePageItemDeletion(dynamic_cast<ScItemState< QList<PageItem*> >*>(ss), isUndo);
246 else if (ss->contains("CONVERT_ITEM"))
247 restorePageItemConversion(dynamic_cast<ScItemState<QPair<PageItem*, PageItem*> >*>(ss), isUndo);
248 else if (ss->contains("CONVERT_ITEM_TO_SYMBOL"))
249 restorePageItemConversionToSymbol(dynamic_cast<ScItemState<QPair<PageItem*, PageItem*> >*>(ss), isUndo);
250 else if (ss->contains("PAGE_ATTRS"))
251 restorePageAttributes(ss, isUndo);
252 }
253
restorePageAttributes(SimpleState * state,bool isUndo)254 void ScPage::restorePageAttributes(SimpleState *state, bool isUndo)
255 {
256 int left_old = state->getInt("LEFT_OLD");
257 QString name_old = state->get("NAME_OLD");
258 int orientation_old = state->getInt("ORIENTATION_OLD");
259 QString size_old =state->get("SIZE_OLD");
260 double width_old = state->getDouble("WIDTH_OLD");
261 double height_old = state->getDouble("HEIGHT_OLD");
262 double init_height_old = state->getDouble("INIT_HEIGHT_OLD");
263 double init_width_old = state->getDouble("INIT_WIDTH_OLD");
264 double init_margin_top_old = state->getDouble("INIT_MARGINTOP_OLD");
265 double init_margin_bottom_old = state->getDouble("INIT_MARGINBOTTOM_OLD");
266 double init_margin_right_old = state->getDouble("INIT_MARGINRIGHT_OLD");
267 double init_margin_left_old = state->getDouble("INIT_MARGINLEFT_OLD");
268 double margin_top_old = state->getDouble("MARGINTOP_OLD");
269 double margin_bottom_old = state->getDouble("MARGINBOTTOM_OLD");
270 int margin_preset_old = state->getInt("MARGINPRESET_OLD");
271 int left = state->getInt("LEFT");
272 QString name = state->get("NAME");
273 int orientation = state->getInt("ORIENTATION");
274 QString size =state->get("SIZE");
275 double width = state->getDouble("WIDTH");
276 double height = state->getDouble("HEIGHT");
277 double init_height = state->getDouble("INIT_HEIGHT");
278 double init_width = state->getDouble("INIT_WIDTH");
279 double init_margin_top = state->getDouble("INIT_MARGINTOP");
280 double init_margin_bottom = state->getDouble("INIT_MARGINBOTTOM");
281 double init_margin_right = state->getDouble("INIT_MARGINRIGHT");
282 double init_margin_left = state->getDouble("INIT_MARGINLEFT");
283 double margin_top = state->getDouble("MARGINTOP");
284 double margin_bottom = state->getDouble("MARGINBOTTOM");
285 int margin_preset = state->getInt("MARGINPRESET");
286 double horizontal_autogap_old = state->getDouble("HORIZONTAL_AUTOGAP");
287 double vertical_autogap_old = state->getDouble("VERTICAL_AUTOGAP");
288 double horizontal_autocount_old = state->getDouble("HORIZONTAL_AUTOCOUNT");
289 double vertical_autocount_old = state->getDouble("VERTICAL_AUTOCOUNT");
290 double horizontal_autorefer_old = state->getDouble("HORIZONTAL_AUTOREFER");
291 double vertical_autorefer_old = state->getDouble("VERTICAL_AUTOREFER");
292 double horizontal_autogap = state->getDouble("HORIZONTAL_AUTOGAP");
293 double vertical_autogap = state->getDouble("VERTICAL_AUTOGAP");
294 double horizontal_autocount = state->getDouble("HORIZONTAL_AUTOCOUNT");
295 double vertical_autocount = state->getDouble("VERTICAL_AUTOCOUNT");
296 double horizontal_autorefer = state->getDouble("HORIZONTAL_AUTOREFER");
297 double vertical_autorefer = state->getDouble("VERTICAL_AUTOREFER");
298
299 if (isUndo)
300 {
301 this->LeftPg = left_old;
302 this->setPageName(name_old);
303 this->m_pageSize = size_old;
304 this->setOrientation(orientation_old);
305 this->setWidth(width_old);
306 this->setHeight(height_old);
307 this->setInitialHeight(init_height_old);
308 this->setInitialWidth(init_width_old);
309 this->initialMargins.setTop(init_margin_top_old);
310 this->initialMargins.setBottom(init_margin_bottom_old);
311 this->initialMargins.setLeft(init_margin_left_old);
312 this->initialMargins.setRight(init_margin_right_old);
313 this->marginPreset = margin_preset_old;
314 this->Margins.setTop(margin_top_old);
315 this->Margins.setBottom(margin_bottom_old);
316 this->guides.setHorizontalAutoGap(horizontal_autogap_old);
317 this->guides.setVerticalAutoGap(vertical_autogap_old);
318 this->guides.setHorizontalAutoCount(horizontal_autocount_old);
319 this->guides.setVerticalAutoCount(vertical_autocount_old);
320 this->guides.setHorizontalAutoRefer(horizontal_autorefer_old);
321 this->guides.setVerticalAutoRefer(vertical_autorefer_old);
322 }
323 else
324 {
325 this->LeftPg = left;
326 this->setPageName(name);
327 this->m_pageSize = size;
328 this->setOrientation(orientation);
329 this->setWidth(width);
330 this->setHeight(height);
331 this->setInitialHeight(init_height);
332 this->setInitialWidth(init_width);
333 this->initialMargins.setTop(init_margin_top);
334 this->initialMargins.setBottom(init_margin_bottom);
335 this->initialMargins.setLeft(init_margin_left);
336 this->initialMargins.setRight(init_margin_right);
337 this->marginPreset = margin_preset;
338 this->Margins.setTop(margin_top);
339 this->Margins.setBottom(margin_bottom);
340 this->guides.setHorizontalAutoGap(horizontal_autogap);
341 this->guides.setVerticalAutoGap(vertical_autogap);
342 this->guides.setHorizontalAutoCount(horizontal_autocount);
343 this->guides.setVerticalAutoCount(vertical_autocount);
344 this->guides.setHorizontalAutoRefer(horizontal_autorefer);
345 this->guides.setVerticalAutoRefer(vertical_autorefer);
346 }
347 }
348
restorePageItemCreation(ScItemState<PageItem * > * state,bool isUndo)349 void ScPage::restorePageItemCreation(ScItemState<PageItem*> *state, bool isUndo)
350 {
351 if (!state)
352 return;
353 int stateCode = state->transactionCode;
354 PageItem *ite = state->getItem();
355 bool oldMPMode = m_Doc->masterPageMode();
356 m_Doc->setMasterPageMode(!ite->OnMasterPage.isEmpty());
357 if (m_Doc->inAnEditMode())
358 m_Doc->view()->requestMode(modeNormal);
359 m_Doc->m_Selection->delaySignalsOn();
360 if (isUndo)
361 {
362 if (m_Doc->m_Selection->findItem(ite)!=-1)
363 {
364 if (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable)
365 m_Doc->view()->requestMode(modeNormal);
366 m_Doc->m_Selection->removeItem(ite);
367 }
368 if ((stateCode == 0) || (stateCode == 1))
369 m_Doc->view()->deselectItems(true);
370 Selection tmpSelection(m_Doc, false);
371 tmpSelection.addItem(ite);
372 m_Doc->itemSelection_DeleteItem(&tmpSelection);
373 }
374 else
375 {
376 if ((stateCode == 0) || (stateCode == 1))
377 m_Doc->view()->deselectItems(true);
378 m_Doc->Items->append(ite);
379 ite->OwnPage = m_Doc->OnPage(ite);
380 }
381 if ((stateCode == 0) || (stateCode == 2))
382 update();
383 m_Doc->setMasterPageMode(oldMPMode);
384 m_Doc->m_Selection->delaySignalsOff();
385 }
386
restorePageItemDeletion(ScItemState<QList<PageItem * >> * state,bool isUndo)387 void ScPage::restorePageItemDeletion(ScItemState< QList<PageItem*> > *state, bool isUndo)
388 {
389 if (!state)
390 return;
391
392 int stateCode = state->transactionCode;
393 QList<PageItem*> itemList = state->getItem();
394 int id = state->getInt("ITEMID");
395 int id2 = state->getInt("ID");
396 if (itemList.count() <= 0)
397 return;
398 m_Doc->view()->deselectItems(true);
399 bool oldMPMode = m_Doc->masterPageMode();
400 m_Doc->setMasterPageMode(!itemList.at(0)->OnMasterPage.isEmpty());
401 if (m_Doc->appMode == modeEditClip) // switch off from edit shape
402 m_Doc->scMW()->nodePalette->EndEdit();
403 m_Doc->m_Selection->delaySignalsOn();
404 if (isUndo)
405 {
406 //CB #3373 reinsert at old position and renumber items
407 PageItem* oldItem = itemList.at(id2);
408 if (oldItem->Parent && oldItem->Parent->isGroup())
409 oldItem->Parent->asGroupFrame()->groupItemList.insert(id, oldItem);
410 else
411 m_Doc->Items->insert(id, oldItem);
412 m_Doc->m_Selection->addItems(itemList);
413 }
414 else
415 {
416 Selection tmpSelection(m_Doc, false);
417 PageItem* ite = itemList.at(id2);
418 if (m_Doc->m_Selection->findItem(ite) != -1)
419 {
420 if (m_Doc->appMode == modeEdit || m_Doc->appMode == modeEditTable)
421 m_Doc->view()->requestMode(modeNormal);
422 m_Doc->m_Selection->removeItem(ite);
423 }
424 tmpSelection.addItem(ite);
425 m_Doc->itemSelection_DeleteItem(&tmpSelection);
426 }
427 if ((stateCode == 0) || (stateCode == 2))
428 update();
429 m_Doc->setMasterPageMode(oldMPMode);
430 m_Doc->m_Selection->delaySignalsOff();
431 }
432
restorePageItemConversion(ScItemState<QPair<PageItem *,PageItem * >> * state,bool isUndo)433 void ScPage::restorePageItemConversion(ScItemState<QPair<PageItem*, PageItem*> >* state, bool isUndo)
434 {
435 if (!state)
436 return;
437
438 PageItem *oldItem = state->getItem().first;
439 PageItem *newItem = state->getItem().second;
440 bool oldMPMode = m_Doc->masterPageMode();
441 m_Doc->setMasterPageMode(!oldItem->OnMasterPage.isEmpty());
442 if (isUndo)
443 {
444 m_Doc->Items->replace(m_Doc->Items->indexOf(newItem), oldItem);
445 oldItem->updatePolyClip();
446 m_Doc->adjustItemSize(oldItem);
447 m_Doc->m_Selection->replaceItem(newItem, oldItem);
448 }
449 else
450 {
451 m_Doc->Items->replace(m_Doc->Items->indexOf(oldItem), newItem);
452 m_Doc->m_Selection->replaceItem(oldItem, newItem);
453 }
454 m_Doc->setMasterPageMode(oldMPMode);
455 }
456
restorePageItemConversionToSymbol(ScItemState<QPair<PageItem *,PageItem * >> * state,bool isUndo)457 void ScPage::restorePageItemConversionToSymbol(ScItemState<QPair<PageItem*, PageItem*> >* state, bool isUndo)
458 {
459 //#11365... this code is not finished and broken... fixing will fix 11365
460 if (!state)
461 return;
462
463 PageItem *oldItem = state->getItem().first;
464 PageItem *newItem = state->getItem().second;
465 QString patternName = state->getDescription();
466 bool oldMPMode = m_Doc->masterPageMode();
467 m_Doc->setMasterPageMode(!oldItem->OnMasterPage.isEmpty());
468 if (isUndo)
469 {
470 m_Doc->Items->replace(m_Doc->Items->indexOf(newItem), oldItem);
471 oldItem->updatePolyClip();
472 m_Doc->adjustItemSize(oldItem);
473 if (m_Doc->docPatterns.contains(patternName))
474 m_Doc->removePattern(patternName);
475 m_Doc->m_Selection->replaceItem(newItem, oldItem);
476 }
477 else
478 {
479 m_Doc->Items->replace(m_Doc->Items->indexOf(oldItem), newItem);
480 m_Doc->m_Selection->replaceItem(oldItem, newItem);
481 }
482 m_Doc->setMasterPageMode(oldMPMode);
483 }
484
setXOffset(const double newCanvasXOffset)485 void ScPage::setXOffset(const double newCanvasXOffset)
486 {
487 m_xOffset = newCanvasXOffset;
488 }
489
setYOffset(const double newCanvasYOffset)490 void ScPage::setYOffset(const double newCanvasYOffset)
491 {
492 m_yOffset = newCanvasYOffset;
493 }
494
setWidth(const double newWidth)495 void ScPage::setWidth(const double newWidth)
496 {
497 m_width = newWidth;
498 }
499
setHeight(const double newHeight)500 void ScPage::setHeight(const double newHeight)
501 {
502 m_height = newHeight;
503 }
504
setInitialWidth(const double newInitialWidth)505 void ScPage::setInitialWidth(const double newInitialWidth)
506 {
507 m_initialWidth = newInitialWidth;
508 }
509
setInitialHeight(const double newInitialHeight)510 void ScPage::setInitialHeight(const double newInitialHeight)
511 {
512 m_initialHeight = newInitialHeight;
513 }
514
setOrientation(int ori)515 void ScPage::setOrientation(int ori)
516 {
517 m_orientation = ori;
518 }
519
setPageSectionNumber(const QString & newPageSectionNumber)520 void ScPage::setPageSectionNumber(const QString& newPageSectionNumber)
521 {
522 m_pageSectionNumber=newPageSectionNumber;
523 }
524
copySizingProperties(ScPage * sourcePage,const MarginStruct & pageMargins)525 void ScPage::copySizingProperties(ScPage* sourcePage, const MarginStruct& pageMargins)
526 {
527 if (sourcePage == nullptr)
528 return;
529 m_pageSize = sourcePage->m_pageSize;
530 m_orientation = sourcePage->m_orientation;
531 m_width = sourcePage->m_width;
532 m_height = sourcePage->m_height;
533 m_initialWidth = sourcePage->m_initialWidth;
534 m_initialHeight = sourcePage->m_initialHeight;
535
536 Margins = pageMargins;
537 // #8859 do not get initialMargins from pageMargins otherwise
538 // margins may be inverted when applying master pages
539 initialMargins = sourcePage->initialMargins;
540 }
541