diff --git a/Scribus.pro b/Scribus.pro index f097e699f..f8d5b56e6 100644 --- a/Scribus.pro +++ b/Scribus.pro @@ -1010,6 +1010,7 @@ FORMS += scribus/ui/aboutplugins.ui \ scribus/ui/actionsearchdialog.ui \ scribus/ui/aligndistribute.ui \ scribus/ui/annot.ui \ + scribus/ui/applytemplatedialog.ui \ scribus/ui/arcvectorbase.ui \ scribus/ui/arcwidgetbase.ui \ scribus/ui/charselect.ui \ diff --git a/scribus/scribus.cpp b/scribus/scribus.cpp index f7d0ffbd8..985e8dbf4 100644 --- a/scribus/scribus.cpp +++ b/scribus/scribus.cpp @@ -7617,40 +7617,115 @@ void ScribusMainWindow::ApplyMasterPage() return; QString masterPageName(dia->getMasterPageName()); - int pageSelection = dia->getPageSelection(); //0=current, 1=even, 2=odd, 3=all - if (pageSelection == 0) //current page only - Apply_MasterPage(masterPageName, doc->currentPage()->pageNr(), false); + auto pageSelection = dia->getPageSelection(); //0=current, 1=even, 2=odd, 3=all + int moveItemsAnchor = dia->getMoveItemsAnchor(); + // TODO: is it worth to create this function? if yes, where should this function be added? + // (or does it already exist and i did not find it?) (pageitem.h (as moveByPage)? scpage.h? + auto moveAllPageItems = [this](ScPage* page, double dx, double dy) { + UndoTransaction activeTransaction; + if (UndoManager::undoEnabled()) + // TODO: not sure that the values passed to the transaction are the good ones + activeTransaction = m_undoManager->beginTransaction(Um::ItemsInvolved, Um::IMove, Um::Move, "", Um::IMove); + for (PageItem* pageItem: doc->DocItems) { + if (pageItem->OwnPage == page->pageNr()) { + pageItem->moveBy(dx, dy); + } + } + if (activeTransaction) + activeTransaction.commit(); + }; + + /// \param moveItemsAnchor must be 1 or 2 + /// \return the reference margin for the left and right pages according to the left / inside or right / outside "anchoring" + auto getRelevantMarginsByAnchor = [this](const MarginStruct& margins, int moveItemsAnchor) -> std::array { + if (doc->pagePositioning() == 0) + { + // single page + if (moveItemsAnchor == 1) + return {margins.left(), margins.left()}; + else if (moveItemsAnchor == 2) + return {margins.right(), margins.right()}; + } + else + { + // double page + if (moveItemsAnchor == 1) + // use inside margins + return {margins.right(), margins.left()}; + else if (moveItemsAnchor == 2) + // use outside margins + return {margins.left(), margins.right()}; + } + return {0.0, 0.0}; + }; + + std::array masterPageMarginsForAnchor {0, 0}; + + if (moveItemsAnchor != 0) + masterPageMarginsForAnchor = getRelevantMarginsByAnchor(doc->MasterPages.at(doc->MasterNames[masterPageName])->Margins, moveItemsAnchor); + + int startPage, endPage; + if (pageSelection == PageSelection::currentPage) { + startPage = doc->currentPage()->pageNr(); + endPage = startPage + 1; + } + else if (dia->usingRange()) + { + startPage = dia->getFromPage() - 1; // page indexes start from 0, not 1 + endPage = dia->getToPage(); + } else { - int startPage, endPage; - if (dia->usingRange()) + startPage = 0; + endPage = doc->DocPages.count(); + } + + UndoTransaction activeTransaction; + if (UndoManager::undoEnabled()) + // TODO: not sure that the values passed to the transaction are the good ones + activeTransaction = m_undoManager->beginTransaction(Um::ItemsInvolved, Um::IMove, Um::Move, "", Um::IMove); + + auto currentPage = doc->currentPage(); + for (int i = startPage; i < endPage; i++) // don't try to increment +2 for odd / even + { + // the input page number starts from 1, i starts from 0: the even / odd checks are inversed + if (i % 2 == 0) { - startPage = dia->getFromPage()-1; //Pages start from 0, not 1 - endPage = dia->getToPage(); + if (pageSelection == PageSelection::evenPages) + continue; // ignore even indexes (odd pages) if the selection was even pages } else { - startPage = pageSelection==1 ? 1 : 0; //if even, startPage is 1 (real page 2) - endPage = doc->DocPages.count(); + if (pageSelection == PageSelection::oddPages) + continue; // ignore odd indexes (even pages) if the selection was odd pages } - for (int pageNum = startPage; pageNum < endPage; ++pageNum)// +=pageStep) + Apply_MasterPage(masterPageName, i, false); + if (moveItemsAnchor != 0) { - //Increment by 1 and not 2 even for even/odd application as user - //can select to eg apply to even pages with a single odd page selected - if (pageSelection == 1 && (pageNum %2 != 0)) //Even, %2!=0 as 1st page is numbered 0 - Apply_MasterPage(masterPageName, pageNum, false); - else if (pageSelection == 2 && (pageNum %2 == 0)) //Odd, %2==0 as 1st page is numbered 0 - Apply_MasterPage(masterPageName, pageNum, false); - else if (pageSelection == 3) //All - Apply_MasterPage(masterPageName, pageNum, false); + auto pageMarginsForAnchor = getRelevantMarginsByAnchor(doc->DocPages.at(i)->Margins, moveItemsAnchor); + // for single page use moveItemsAnchor + // for double pages use left if is odd (with first page offset) xor is left/inside + bool isLeftPage = (doc->pageSets()[doc->pagePositioning()].FirstPage + i) % 2 == 0; + bool isReferenceMarginOnTheLeft = doc->pagePositioning() == 0 ? + moveItemsAnchor == 1 : + (isLeftPage) != (moveItemsAnchor == 1); // xor: one of both, but not both or neither + // right margin (1) if isLeftPage xor isReferenceMarginOnTheLeft, left margin otherwise (0) + double masterPageMargin = masterPageMarginsForAnchor[isLeftPage != isReferenceMarginOnTheLeft ? 1 : 0]; + double pageOldMargin = pageMarginsForAnchor[isLeftPage != isReferenceMarginOnTheLeft ? 1 : 0]; + + moveAllPageItems(doc->DocPages.at(i), masterPageMargin - pageOldMargin, 0); } } + doc->setCurrentPage(currentPage); + + if (activeTransaction) + activeTransaction.commit(); view->reformPages(); view->DrawNew(); pagePalette->rebuild(); // #9476 : call setupPage with false arg to setup only guidePalette GUI - // Otherwise setupPage() will apply guides to current page, doesn't need that, + // Otherwise setupPage() will apply guides to current page, doesn't need that, // Apply_MasterPage() has already done it guidePalette->setupPage(false); } diff --git a/scribus/ui/applytemplatedialog.cpp b/scribus/ui/applytemplatedialog.cpp index 075997b1b..7cb7d8916 100644 --- a/scribus/ui/applytemplatedialog.cpp +++ b/scribus/ui/applytemplatedialog.cpp @@ -32,13 +32,6 @@ for which a new license (GPL+exception) is in place. #include "scribusdoc.h" #include "iconmanager.h" -enum { - CurrentPage, - EvenPages, - OddPages, - AllPages -}; - /* * Constructs a ApplyMasterPageDialog as a child of 'parent', with the * name 'name' and widget flags set to 'f'. @@ -48,78 +41,10 @@ enum { */ ApplyMasterPageDialog::ApplyMasterPageDialog( QWidget* parent ) : QDialog( parent ) { - setModal(true); - setWindowTitle( tr( "Apply Master Page" )); - setWindowIcon(IconManager::instance().loadIcon("AppIcon.png")); - ApplyMasterPageDialogLayout = new QVBoxLayout(this); - ApplyMasterPageDialogLayout->setContentsMargins(9, 9, 9, 9); - ApplyMasterPageDialogLayout->setSpacing(6); - - templateNameLayout = new QHBoxLayout; - templateNameLayout->setContentsMargins(0, 0, 0, 0); - templateNameLayout->setSpacing(6); - - masterPageLabel = new QLabel( this ); - templateNameLayout->addWidget( masterPageLabel ); - spacer2 = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); - templateNameLayout->addItem( spacer2 ); - - masterPageComboBox = new QComboBox(this); - masterPageComboBox->setEditable(false); - templateNameLayout->addWidget( masterPageComboBox ); - ApplyMasterPageDialogLayout->addLayout( templateNameLayout ); - - applyToPageButtonGroup = new QGroupBox(this); - applyToPageButtonGroup->setMinimumSize( QSize( 250, 0 ) ); - applyToPageButtonGroupLayout = new QVBoxLayout(applyToPageButtonGroup); - applyToPageButtonGroupLayout->setSpacing(6); - applyToPageButtonGroupLayout->setContentsMargins(9, 9, 9, 9); - - currentPageRadioButton = new QRadioButton( applyToPageButtonGroup ); - currentPageRadioButton->setChecked( true ); - applyToPageButtonGroupLayout->addWidget( currentPageRadioButton ); - - evenPagesRadioButton = new QRadioButton( applyToPageButtonGroup ); - applyToPageButtonGroupLayout->addWidget( evenPagesRadioButton ); - - oddPagesRadioButton = new QRadioButton( applyToPageButtonGroup ); - applyToPageButtonGroupLayout->addWidget( oddPagesRadioButton ); - - allPagesRadioButton = new QRadioButton( applyToPageButtonGroup ); - applyToPageButtonGroupLayout->addWidget( allPagesRadioButton ); - - rangeLayout = new QHBoxLayout; - rangeLayout->setSpacing(6); - rangeLayout->setContentsMargins(0, 0, 0, 0); - - useRangeCheckBox = new QCheckBox( applyToPageButtonGroup ); - useRangeCheckBox->setEnabled( false ); - rangeLayout->addWidget( useRangeCheckBox ); - - fromPageSpinBox = new ScrSpinBox( applyToPageButtonGroup ); - fromPageSpinBox->setEnabled( false ); - fromPageSpinBox->setMinimum( 1 ); - fromPageSpinBox->setDecimals(0); + setupUi(this); + setSizePolicy( QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); fromPageSpinBox->setSuffix(""); - rangeLayout->addWidget( fromPageSpinBox ); - - toPageLabel = new QLabel( applyToPageButtonGroup ); - rangeLayout->addWidget( toPageLabel ); - - toPageSpinBox = new ScrSpinBox( applyToPageButtonGroup ); - toPageSpinBox->setEnabled( false ); - toPageSpinBox->setMinimum( 1 ); - toPageSpinBox->setDecimals(0); toPageSpinBox->setSuffix(""); - rangeLayout->addWidget( toPageSpinBox ); - spacer3 = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); - rangeLayout->addItem( spacer3 ); - applyToPageButtonGroupLayout->addLayout( rangeLayout ); - ApplyMasterPageDialogLayout->addWidget( applyToPageButtonGroup ); - - buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - ApplyMasterPageDialogLayout->addWidget(buttonBox); - languageChange(); resize( QSize(268, 230).expandedTo(minimumSizeHint()) ); // signals and slots connections @@ -132,9 +57,7 @@ ApplyMasterPageDialog::ApplyMasterPageDialog( QWidget* parent ) : QDialog( paren connect( toPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( checkRangeTo() ) ); connect(buttonBox, &QDialogButtonBox::accepted, this, &ApplyMasterPageDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &ApplyMasterPageDialog::reject); - - // buddies - masterPageLabel->setBuddy( masterPageComboBox ); + connect(moveItemsCheckBox, &QCheckBox::toggled, this, &ApplyMasterPageDialog::enableItemsSelectable); } void ApplyMasterPageDialog::setup(ScribusDoc *doc, const QString& Nam) @@ -158,6 +81,18 @@ void ApplyMasterPageDialog::setup(ScribusDoc *doc, const QString& Nam) fromPageSpinBox->setValue(doc->currentPage()->pageNr() + 1); toPageSpinBox->setMaximum(docPagesCount); toPageSpinBox->setValue(docPagesCount); + + moveItemsAnchorComboBox->clear(); + if (doc->pagePositioning() != 0) // facing pages + { + moveItemsAnchorComboBox->addItem(tr("Inside"), 1); + moveItemsAnchorComboBox->addItem(tr("Outside"), 2); + } + else + { + moveItemsAnchorComboBox->addItem(tr("Left"), 1); + moveItemsAnchorComboBox->addItem(tr("Right"), 2); + } } @@ -168,15 +103,15 @@ QString ApplyMasterPageDialog::getMasterPageName() } -int ApplyMasterPageDialog::getPageSelection() +PageSelection ApplyMasterPageDialog::getPageSelection() { if (currentPageRadioButton->isChecked()) - return CurrentPage; + return PageSelection::currentPage; if (evenPagesRadioButton->isChecked()) - return EvenPages; + return PageSelection::evenPages; if (oddPagesRadioButton->isChecked()) - return OddPages; - return AllPages; + return PageSelection::oddPages; + return PageSelection::allPages; } void ApplyMasterPageDialog::checkRangeFrom() @@ -218,6 +153,13 @@ void ApplyMasterPageDialog::singleSelectable() toPageSpinBox->setEnabled(false); } +void ApplyMasterPageDialog::enableItemsSelectable(bool enabled) +{ + moveItemsAnchorComboBox->setEnabled(enabled); + moveItemsMarginLabel->setEnabled(enabled); +} + + bool ApplyMasterPageDialog::usingRange() { @@ -240,31 +182,16 @@ int ApplyMasterPageDialog::getToPage() return -1; } -void ApplyMasterPageDialog::changeEvent(QEvent *e) +/** + * \return 0 if no change is required, + * 1 if it moves according to the left / inside margins, + * 2 if it moves according to the right maring + */ +int ApplyMasterPageDialog::getMoveItemsAnchor() { - if (e->type() == QEvent::LanguageChange) + if (!moveItemsCheckBox->isChecked()) { - languageChange(); + return 0; } - else - QWidget::changeEvent(e); -} - -void ApplyMasterPageDialog::languageChange() -{ - setWindowTitle( tr( "Apply Master Page" ) ); - masterPageLabel->setText( tr( "&Master Page:" ) ); - applyToPageButtonGroup->setTitle( tr( "Apply to" ) ); - currentPageRadioButton->setText( tr( "Current &Page" ) ); - currentPageRadioButton->setShortcut( QKeySequence( tr( "Alt+P" ) ) ); - evenPagesRadioButton->setText( tr( "&Even Pages" ) ); - evenPagesRadioButton->setShortcut( QKeySequence( tr( "Alt+E" ) ) ); - oddPagesRadioButton->setText( tr( "O&dd Pages" ) ); - oddPagesRadioButton->setShortcut( QKeySequence( tr( "Alt+D" ) ) ); - allPagesRadioButton->setText( tr( "&All Pages" ) ); - allPagesRadioButton->setShortcut( QKeySequence( tr( "Alt+A" ) ) ); - useRangeCheckBox->setText( tr( "&Within Range" ) ); - useRangeCheckBox->setShortcut( QKeySequence( tr( "Alt+W" ) ) ); - useRangeCheckBox->setToolTip( "" + tr( "Apply the selected master page to even, odd or all pages within the following range") + "" ); - toPageLabel->setText( tr( "to" ) ); + return moveItemsAnchorComboBox->currentData().toInt(); } diff --git a/scribus/ui/applytemplatedialog.h b/scribus/ui/applytemplatedialog.h index 71dd7fef4..98b324aa0 100644 --- a/scribus/ui/applytemplatedialog.h +++ b/scribus/ui/applytemplatedialog.h @@ -15,6 +15,8 @@ for which a new license (GPL+exception) is in place. #ifndef APPLYMASTERPAGEDIALOG_H #define APPLYMASTERPAGEDIALOG_H +#include "ui_applytemplatedialog.h" + #include #include #include @@ -35,7 +37,14 @@ class QRadioButton; class QSpacerItem; class QVBoxLayout; -class SCRIBUS_API ApplyMasterPageDialog : public QDialog +enum class PageSelection { + currentPage, + evenPages, + oddPages, + allPages +}; + +class SCRIBUS_API ApplyMasterPageDialog : public QDialog, Ui::ApplyMasterPageDialog { Q_OBJECT @@ -43,38 +52,13 @@ public: ApplyMasterPageDialog( QWidget* parent = nullptr ); ~ApplyMasterPageDialog() = default; - QLabel* masterPageLabel { nullptr }; - QComboBox* masterPageComboBox { nullptr }; - QGroupBox* applyToPageButtonGroup { nullptr }; - QRadioButton* currentPageRadioButton { nullptr }; - QRadioButton* evenPagesRadioButton { nullptr }; - QRadioButton* oddPagesRadioButton { nullptr }; - QRadioButton* allPagesRadioButton { nullptr }; - QCheckBox* useRangeCheckBox { nullptr }; - ScrSpinBox* fromPageSpinBox { nullptr }; - QLabel* toPageLabel { nullptr }; - ScrSpinBox* toPageSpinBox { nullptr }; - virtual void setup(ScribusDoc* doc, const QString& Nam); virtual QString getMasterPageName(); - virtual int getPageSelection(); + virtual PageSelection getPageSelection(); virtual bool usingRange(); virtual int getFromPage(); virtual int getToPage(); - -protected: - QVBoxLayout* ApplyMasterPageDialogLayout { nullptr }; - QHBoxLayout* templateNameLayout { nullptr }; - QSpacerItem* spacer2 { nullptr }; - QVBoxLayout* applyToPageButtonGroupLayout { nullptr }; - QHBoxLayout* rangeLayout { nullptr }; - QSpacerItem* spacer3 { nullptr }; - QDialogButtonBox* buttonBox { nullptr }; - - void changeEvent(QEvent *e) override; - -protected slots: - virtual void languageChange(); + virtual int getMoveItemsAnchor(); private slots: virtual void checkRangeFrom(); @@ -82,7 +66,7 @@ private slots: virtual void enableRange( bool enabled ); virtual void rangeSelectable(); virtual void singleSelectable(); - + virtual void enableItemsSelectable(bool enabled); }; #endif // APPLYMASTERPAGEDIALOG_H