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 #include "pagepalette_masterpages.h"
8
9 #include <QApplication>
10 #include <QCloseEvent>
11 #include <QCursor>
12 #include <QHBoxLayout>
13 #include <QInputDialog>
14 #include <QListWidget>
15 #include <QListWidgetItem>
16 #include <QMessageBox>
17 #include <QScopedPointer>
18 #include <QSpacerItem>
19 #include <QString>
20 #include <QStringList>
21 #include <QToolButton>
22 #include <QToolTip>
23 #include <QVBoxLayout>
24
25 #include "appmodes.h"
26 #include "canvasmode.h"
27 #include "commonstrings.h"
28 #include "iconmanager.h"
29 #include "mergedoc.h"
30 #include "newtemp.h"
31 #include "pagestructs.h"
32 #include "prefsmanager.h"
33 #include "scpage.h"
34 #include "scribus.h"
35 #include "scribusapp.h"
36 #include "scribusdoc.h"
37 #include "scribusview.h"
38 #include "scribusXml.h"
39 #include "selection.h"
40 #include "util.h"
41 #include "util_os.h"
42
43
PagePalette_MasterPages(QWidget * parent,ScribusView * pCurrentView,const QString & masterPageName)44 PagePalette_MasterPages::PagePalette_MasterPages( QWidget* parent, ScribusView *pCurrentView, const QString& masterPageName) : QWidget(parent)
45 {
46 m_doc = pCurrentView->m_doc;
47 m_view = pCurrentView;
48
49 setupUi(this);
50 iconSetChange();
51
52 masterPageListBox->setSelectionMode(QAbstractItemView::ExtendedSelection);
53 styleChange();
54 languageChange();
55
56 if (masterPageName.isEmpty())
57 m_currentPage = m_doc->MasterNames.begin().key();
58 else
59 m_currentPage = masterPageName;
60 updateMasterPageList(m_currentPage);
61 m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);
62
63 setMinimumSize(sizeHint());
64
65 // signals and slots connections
66 connect(ScQApp, SIGNAL(iconSetChanged()), this, SLOT(iconSetChange()));
67 connectSignals();
68 }
69
setView(ScribusView * view,const QString & masterPageName)70 void PagePalette_MasterPages::setView(ScribusView* view, const QString& masterPageName)
71 {
72 // ScribusView* oldView = m_view;
73 // QString oldPage = m_currentPage;
74
75 disconnectSignals();
76 m_view = view;
77 m_doc = m_view ? m_view->m_doc : nullptr;
78
79 if (!view)
80 {
81 this->setEnabled(false);
82 return;
83 }
84
85 if (masterPageName.isEmpty() && m_doc->masterPageMode())
86 m_currentPage = m_doc->currentPage()->pageName();
87 else if (masterPageName.isEmpty())
88 m_currentPage = m_doc->MasterNames.begin().key();
89 else
90 m_currentPage = masterPageName;
91
92 QString currentPageName;
93 if (m_doc->masterPageMode())
94 currentPageName = m_doc->currentPage()->pageName();
95 if (m_doc->masterPageMode() && m_currentPage != currentPageName)
96 m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);
97
98 this->setEnabled(m_doc->masterPageMode());
99 connectSignals();
100 }
101
connectSignals()102 void PagePalette_MasterPages::connectSignals()
103 {
104 connect(duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateMasterPage()));
105 connect(deleteButton , SIGNAL(clicked()), this, SLOT(deleteMasterPage()));
106 connect(newButton , SIGNAL(clicked()), this, SLOT(newMasterPage()));
107 connect(importButton , SIGNAL(clicked()), this, SLOT(importPage()));
108 connect(masterPageListBox, SIGNAL(itemClicked(QListWidgetItem*)),
109 this, SLOT(selectMasterPage(QListWidgetItem*)));
110 connect(masterPageListBox, SIGNAL(itemChanged(QListWidgetItem*)),
111 this, SLOT(renameMasterPage( QListWidgetItem*)));
112 connect(finishButton , SIGNAL(released()), this, SIGNAL(finished()));
113 }
114
disconnectSignals()115 void PagePalette_MasterPages::disconnectSignals()
116 {
117 disconnect(duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateMasterPage()));
118 disconnect(deleteButton , SIGNAL(clicked()), this, SLOT(deleteMasterPage()));
119 disconnect(newButton , SIGNAL(clicked()), this, SLOT(newMasterPage()));
120 disconnect(importButton , SIGNAL(clicked()), this, SLOT(importPage()));
121 disconnect(masterPageListBox, SIGNAL(itemClicked(QListWidgetItem*)),
122 this, SLOT(selectMasterPage(QListWidgetItem*)));
123 disconnect(masterPageListBox, SIGNAL(itemChanged(QListWidgetItem*)),
124 this, SLOT(renameMasterPage( QListWidgetItem*)));
125 disconnect(finishButton , SIGNAL(released()), this, SIGNAL(finished()));
126 }
127
iconSetChange()128 void PagePalette_MasterPages::iconSetChange()
129 {
130 IconManager& iconManager = IconManager::instance();
131
132 importButton->setIcon(iconManager.loadIcon("16/document-open.png"));
133 newButton->setIcon(iconManager.loadIcon("16/document-new.png"));
134 duplicateButton->setIcon(iconManager.loadIcon("16/edit-copy.png"));
135 deleteButton->setIcon(iconManager.loadIcon("16/edit-delete.png"));
136 }
137
languageChange()138 void PagePalette_MasterPages::languageChange()
139 {
140 setWindowTitle( tr( "Edit Master Pages" ) );
141 duplicateButton->setToolTip( tr( "Duplicate the selected master page" ) );
142 deleteButton->setToolTip( tr( "Delete the selected master page" ) );
143 newButton->setToolTip( tr( "Add a new master page" ) );
144 importButton->setToolTip( tr( "Import master pages from another document" ) );
145 }
146
styleChange()147 void PagePalette_MasterPages::styleChange()
148 {
149 PrefsManager& prefsManager = PrefsManager::instance();
150 if (prefsManager.appPrefs.uiPrefs.style=="Macintosh" || (os_is_osx() && prefsManager.appPrefs.uiPrefs.style==""))
151 finishButton->setMinimumHeight(32);
152 else
153 finishButton->setMinimumHeight(0);
154 }
155
deleteMasterPage()156 void PagePalette_MasterPages::deleteMasterPage()
157 {
158 bool forceDelete = false;
159
160 // allow to delete multiple pages in one step
161 foreach (QListWidgetItem * delItem, masterPageListBox->selectedItems())
162 {
163 m_currentPage = delItem->text();
164
165 if (isReservedName(m_currentPage))
166 continue;
167
168 QString extraWarn = "";
169
170 if (!forceDelete)
171 {
172 for (int i=0; i < m_doc->DocPages.count(); ++i )
173 {
174 if (m_doc->DocPages[i]->masterPageName() == m_currentPage)
175 extraWarn = tr("This master page is used at least once in the document.");
176 }
177 int exit = ScMessageBox::warning(this,
178 CommonStrings::trWarning,
179 tr("Do you really want to delete master page \"%1\"?").arg(m_currentPage)+"\n"+extraWarn,
180 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::Cancel,
181 QMessageBox::NoButton, // GUI default
182 QMessageBox::YesToAll); // batch default
183
184 if (exit == QMessageBox::YesToAll)
185 forceDelete = true;
186 if (exit == QMessageBox::No)
187 continue;
188 if (exit == QMessageBox::Cancel)
189 break;
190 }
191
192 if (m_doc->appMode == modeEditClip)
193 m_view->requestMode(submodeEndNodeEdit);
194 m_doc->scMW()->deletePage2(m_doc->MasterNames[m_currentPage]);
195 //<<CB TODO Move back into ScribusDoc::deleteMasterPage();
196 //This must happen after the pages have been reformed (view/doc)
197 m_doc->rebuildMasterNames();
198 // Fix up any pages that refer to the deleted master page
199 m_doc->replaceMasterPage(m_currentPage);
200 }
201
202 // set the 1st MP for the other slots
203 QMap<QString,int>::Iterator it = m_doc->MasterNames.begin();
204 m_currentPage = it.key();
205 updateMasterPageList(m_currentPage);
206 selectMasterPage(m_currentPage);
207 }
208
duplicateMasterPage()209 void PagePalette_MasterPages::duplicateMasterPage()
210 {
211 QString name = getUniqueName(m_currentPage, m_doc->MasterNames);
212 QScopedPointer<NewTm> dia(new NewTm(this, tr("&Name:"), tr("New Master Page"), m_doc, name));
213 if (!dia->exec())
214 return;
215
216 if (m_doc->appMode == modeEditClip)
217 m_view->requestMode(submodeEndNodeEdit);
218
219 name = dia->Answer->text();
220
221 if (name.isEmpty())
222 return;
223
224 name = getNonReservedName(name);
225 name = getUniqueName(name, m_doc->MasterNames);
226
227 // PrefsManager& prefsManager = PrefsManager::instance();
228 int inde = m_doc->MasterNames[m_currentPage];
229 int nr = m_doc->Pages->count();
230 ScPage* from = m_doc->Pages->at(inde);
231 ScPage* destination = m_doc->addMasterPage(nr, name);
232 if (m_doc->pagePositioning() != singlePage)
233 {
234 int lp = dia->Links->currentIndex();
235 if (lp == 0)
236 lp = 1;
237 else if (lp == static_cast<int>(dia->Links->count()-1))
238 lp = 0;
239 else
240 lp++;
241 destination->LeftPg = lp;
242 }
243 destination->initialMargins.setTop(from->initialMargins.top());
244 destination->initialMargins.setBottom(from->initialMargins.bottom());
245 if (m_doc->pageSets()[m_doc->pagePositioning()].Columns == 1)
246 {
247 destination->initialMargins.setLeft(from->initialMargins.left());
248 destination->initialMargins.setRight(from->initialMargins.right());
249 }
250 else
251 {
252 if (destination->LeftPg != from->LeftPg)
253 {
254 if (destination->LeftPg > 1)
255 {
256 destination->initialMargins.setRight(from->initialMargins.left());
257 destination->initialMargins.setLeft(from->initialMargins.left());
258 }
259 else
260 {
261 destination->initialMargins.setLeft(from->initialMargins.left());
262 destination->initialMargins.setRight(from->initialMargins.right());
263 }
264 }
265 else
266 {
267 destination->initialMargins.setLeft(from->initialMargins.left());
268 destination->initialMargins.setRight(from->initialMargins.right());
269 }
270 }
271 //#8321 : incorrect selection of master page on new mp creation/duplication
272 //m_doc->setCurrentPage(destination);
273 updateMasterPageList(name);
274 selectMasterPage(name);
275 uint oldItems = m_doc->Items->count();
276 uint end2 = m_doc->MasterItems.count();
277 int GrMax = m_doc->GroupCounter;
278 m_doc->m_Selection->clear();
279 if (oldItems>0)
280 {
281 ScLayers::iterator it;
282 m_doc->m_Selection->delaySignalsOn();
283 for (it = m_doc->Layers.begin(); it != m_doc->Layers.end(); ++it)
284 {
285 for (uint ite = 0; ite < oldItems; ++ite)
286 {
287 PageItem *itemToCopy = m_doc->Items->at(ite);
288 if (itemToCopy->OwnPage == inde && (it->ID == itemToCopy->m_layerID))
289 m_doc->m_Selection->addItem(itemToCopy, true);
290 }
291 if (m_doc->m_Selection->count() != 0)
292 {
293 ScriXmlDoc ss;
294 QString buffer = ss.writeElem(m_doc, m_doc->m_Selection);
295 ss.readElemToLayer(buffer, m_doc, destination->xOffset(), destination->yOffset(), false, true, it->ID);
296 m_doc->m_Selection->clear();
297 }
298 }
299 m_doc->m_Selection->clear();
300 m_doc->m_Selection->delaySignalsOff();
301 }
302 uint end3 = m_doc->MasterItems.count();
303 for (uint a = end2; a < end3; ++a)
304 {
305 PageItem *newItem = m_doc->MasterItems.at(a);
306 int masterPageIndex = m_doc->MasterNames[name];
307 newItem->setMasterPage(masterPageIndex, name);
308 }
309 from->guides.copy(&destination->guides);
310 m_doc->GroupCounter = GrMax + 1;
311 m_view->deselectItems(true);
312 m_doc->setLoading(false);
313 m_view->reformPages();
314 m_view->DrawNew();
315 }
316
newMasterPage()317 void PagePalette_MasterPages::newMasterPage()
318 {
319 int nr = m_doc->Pages->count();
320
321 QScopedPointer<NewTm> dia(new NewTm(this, tr("Name:"), tr("New MasterPage"), m_doc, tr("New Master Page %1").arg(nr)));
322 if (!dia->exec())
323 return;
324
325 if (m_doc->appMode == modeEditClip)
326 m_view->requestMode(submodeEndNodeEdit);
327
328 auto name = dia->Answer->text();
329
330 if (name.isEmpty())
331 return;
332
333 name = getNonReservedName(name);
334 name = getUniqueName(name, m_doc->MasterNames);
335
336 m_doc->setCurrentPage(m_doc->addMasterPage(nr, name));
337 if (m_doc->pagePositioning() != singlePage)
338 {
339 int lp = dia->Links->currentIndex();
340 if (lp == 0)
341 lp = 1;
342 else if (lp == static_cast<int>(dia->Links->count()-1))
343 lp = 0;
344 else
345 lp++;
346 m_doc->Pages->at(nr)->LeftPg = lp;
347 }
348 updateMasterPageList(name);
349 //#8321 : incorrect selection of master page on new mp creation/duplictation
350 //m_view->showMasterPage(m_doc->MasterNames[name]);
351 selectMasterPage(name);
352 m_view->reformPages();
353 }
354
importPage()355 void PagePalette_MasterPages::importPage()
356 {
357 QScopedPointer<MergeDoc> dia(new MergeDoc(this, true));
358 if (!dia->exec())
359 return;
360
361 if (m_doc->appMode == modeEditClip)
362 m_view->requestMode(submodeEndNodeEdit);
363
364 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
365 int nr = m_doc->Pages->count();
366
367 auto indexes = dia->getMasterPageIndexes();
368 QString lastName;
369 for (auto name: dia->getMasterPageNames())
370 {
371 name = getUniqueName(name, m_doc->MasterNames);
372 m_doc->setCurrentPage(m_doc->addMasterPage(nr, name));
373
374 nr++;
375 qApp->processEvents();
376
377 //CB TODO: If we are loading to a new name, we rely on doc->onpage in
378 //FileLoader::PasteItem as this call doesn't pass in the new destination page
379 m_doc->scMW()->loadPage(dia->getFromDoc(), indexes.first(), true, name);
380 qApp->processEvents();
381
382 indexes.removeFirst();
383 lastName = name;
384 }
385
386 updateMasterPageList(lastName);
387 m_view->showMasterPage(m_doc->MasterNames[lastName]);
388 qApp->restoreOverrideCursor();
389 }
390
selectMasterPage(QListWidgetItem * item)391 void PagePalette_MasterPages::selectMasterPage(QListWidgetItem *item)
392 {
393 m_currentPage = item->data(Qt::UserRole).toString();
394
395 bool deleteEnabled = true;
396 deleteEnabled &= (m_doc->MasterNames.count() > 1);
397 deleteEnabled &= (m_currentPage != CommonStrings::masterPageNormal);
398 deleteEnabled &= (m_currentPage != CommonStrings::trMasterPageNormal);
399 deleteButton->setEnabled(deleteEnabled);
400
401 if (m_doc->appMode == modeEditClip)
402 m_view->requestMode(submodeEndNodeEdit);
403 else if (m_doc->appMode == modeEdit || m_doc->appMode == modeEditGradientVectors)
404 m_view->requestMode(modeNormal);
405 m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);
406
407 this->setEnabled(true);
408 }
409
selectMasterPage(const QString & name)410 void PagePalette_MasterPages::selectMasterPage(const QString& name)
411 {
412 if (!m_doc || !m_view)
413 return;
414
415 m_currentPage.clear();
416 for (int i = 0; i < masterPageListBox->count(); ++i)
417 {
418 QListWidgetItem* item = masterPageListBox->item(i);
419 QString realPageName = item->data(Qt::UserRole).toString();
420 if (item->text() == name)
421 {
422 m_currentPage = realPageName;
423 break;
424 }
425 if (realPageName == name)
426 {
427 m_currentPage = name;
428 break;
429 }
430 }
431
432 if (m_currentPage.isEmpty())
433 m_currentPage = m_doc->MasterPages.at(0)->pageName();
434
435 bool deleteEnabled = true;
436 deleteEnabled &= (m_doc->MasterNames.count() > 1);
437 deleteEnabled &= (m_currentPage != CommonStrings::masterPageNormal);
438 deleteEnabled &= (m_currentPage != CommonStrings::trMasterPageNormal);
439 deleteButton->setEnabled(deleteEnabled);
440
441 if (m_doc->appMode == modeEditClip)
442 m_view->requestMode(submodeEndNodeEdit);
443 m_view->showMasterPage(m_doc->MasterNames[m_currentPage]);
444
445 this->setEnabled(true);
446 }
447
updateMasterPageList()448 void PagePalette_MasterPages::updateMasterPageList()
449 {
450 QString masterPageName = (m_doc->MasterNames.contains(m_currentPage)) ? m_currentPage : CommonStrings::masterPageNormal;
451 updateMasterPageList(masterPageName);
452 }
453
updateMasterPageList(QString masterPageName)454 void PagePalette_MasterPages::updateMasterPageList(QString masterPageName)
455 {
456 if (!m_doc || !m_view)
457 return;
458
459 masterPageListBox->clear();
460 for (QMap<QString,int>::Iterator it = m_doc->MasterNames.begin(); it != m_doc->MasterNames.end(); ++it)
461 {
462 QString mpName = it.key();
463
464 if (it.key() == CommonStrings::masterPageNormal)
465 mpName = CommonStrings::trMasterPageNormal;
466 QListWidgetItem* mpItem = new QListWidgetItem(mpName);
467
468 if (!isReservedName(mpName))
469 mpItem->setFlags(mpItem->flags() |= Qt::ItemIsEditable);
470 else
471 mpItem->setFlags(mpItem->flags() &= ~Qt::ItemIsEditable);
472
473 mpItem->setData(Qt::UserRole, it.key());
474 masterPageListBox->addItem(mpItem);
475 }
476 deleteButton->setEnabled(m_doc->MasterNames.count() != 1);
477 if (masterPageName == CommonStrings::masterPageNormal)
478 {
479 masterPageName = CommonStrings::trMasterPageNormal;
480 deleteButton->setEnabled(false);
481 }
482 QList<QListWidgetItem *> itL = masterPageListBox->findItems(masterPageName, Qt::MatchExactly);
483 if (itL.count() != 0)
484 itL.at(0)->setSelected(true);
485 }
486
renameMasterPage(QListWidgetItem * item)487 void PagePalette_MasterPages::renameMasterPage(QListWidgetItem * item)
488 {
489 QString oldName(item->data(Qt::UserRole).toString());
490 QString newName(item->text());
491
492 if (oldName == newName)
493 return;
494
495 // FIXME: the checks in the old version of this function
496 // and the ones in m_doc->renameMasterPage() did not match.
497 // we should move all MasterPage related code to a new masterpage.h
498 // file and remove code from scribusdoc.cpp and from here.
499 // at the end, the code below should be:
500 //
501 // if (m_doc->m_masterPage->rename(oldName, newName))
502 // {
503 // bool sigBlocked = masterPageListBox->blockSignals(true);
504 // item->setData(Qt::UserRole, newName);
505 // masterPageListBox->blockSignals(sigBlocked);
506 // updateMasterPageList(newName);
507 // }
508 // else
509 // {
510 // bool sigBlocked = masterPageListBox->blockSignals(true);
511 // item->setText(getTranslatedReservedName(oldName));
512 // masterPageListBox->blockSignals(sigBlocked);
513 // }
514
515 if (newName.isEmpty() || isReservedName(newName) ||
516 !m_doc->MasterNames.contains(oldName) ||
517 m_doc->MasterNames.contains(newName))
518 {
519 bool sigBlocked = masterPageListBox->blockSignals(true);
520 item->setText(oldName);
521 masterPageListBox->blockSignals(sigBlocked);
522 }
523 else
524 {
525 bool sigBlocked = masterPageListBox->blockSignals(true);
526 m_doc->renameMasterPage(oldName, newName);
527 item->setData(Qt::UserRole, newName);
528 masterPageListBox->blockSignals(sigBlocked);
529 updateMasterPageList(newName);
530 }
531 }
532
533
changeEvent(QEvent * e)534 void PagePalette_MasterPages::changeEvent(QEvent *e)
535 {
536 if (e->type() == QEvent::LanguageChange)
537 {
538 languageChange();
539 return;
540 }
541 if (e->type() == QEvent::StyleChange)
542 {
543 styleChange();
544 return;
545 }
546
547 QWidget::changeEvent(e);
548 }
549
550 // FIXME: move to a new masterpages.h
isReservedName(const QString & name) const551 bool PagePalette_MasterPages::isReservedName(const QString& name) const
552 {
553 return name == CommonStrings::masterPageNormal ||
554 name == CommonStrings::trMasterPageNormal ||
555 name == CommonStrings::masterPageNormalLeft ||
556 name == CommonStrings::trMasterPageNormalLeft ||
557 name == CommonStrings::masterPageNormalMiddle ||
558 name == CommonStrings::trMasterPageNormalMiddle ||
559 name == CommonStrings::masterPageNormalRight ||
560 name == CommonStrings::trMasterPageNormalRight;
561 }
562
563 // FIXME: move to a new masterpages.h
getNonReservedName(const QString & name) const564 QString PagePalette_MasterPages::getNonReservedName(const QString& name) const
565 {
566 const QStringList reservedNames = {
567 CommonStrings::masterPageNormal,
568 CommonStrings::trMasterPageNormal,
569 CommonStrings::trMasterPageNormalLeft,
570 CommonStrings::trMasterPageNormalMiddle,
571 CommonStrings::trMasterPageNormalRight
572 };
573 return getUniqueName(name, reservedNames);
574 }
575
576 // FIXME: move to a new masterpages.h
getTranslatedReservedName(const QString & name) const577 QString PagePalette_MasterPages::getTranslatedReservedName(const QString& name) const
578 {
579 if (name == CommonStrings::masterPageNormal)
580 return CommonStrings::trMasterPageNormal;
581 if (name == CommonStrings::masterPageNormalLeft)
582 return CommonStrings::trMasterPageNormalLeft;
583 if (name == CommonStrings::masterPageNormalMiddle)
584 return CommonStrings::trMasterPageNormalMiddle;
585 if (name == CommonStrings::masterPageNormalRight)
586 return CommonStrings::trMasterPageNormalRight;
587 return name;
588 }
589