View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0009414 | Scribus | User Interface | public | 2010-10-19 16:23 | 2026-09-21 13:14 |
| Reporter | subeditor | Assigned To | |||
| Priority | normal | Severity | feature | Reproducibility | N/A |
| Status | new | Resolution | open | ||
| Product Version | 1.3.8 | ||||
| Summary | 0009414: Enhancement for "Apply Master Page" dialog (mockup incl.) | ||||
| Description | Now users can apply only one master page at once. But facing pages are very common template, so users often need to apply at least two master pages at once. On the attached draft I suggest to give them such opportunity. | ||||
| Tags | mockup | ||||
| Attached Files | |||||
| Patch | No | ||||
| child of | 0003837 | acknowledged | Metabug: Master pages/Page templates |
|
|
Here is my redesign of the dialog (side-aware + section scope), a series of 2 patches. Best applied after the `mp-quick-apply-master-page-v1.19.patch` in 0017929, it does this: - Two separate combos, Left Pages and Right Pages — each independently settable, each defaulting to "No Change" so one side can be left untouched - Context/side-aware: each combo only lists masters valid for that page side — a master built for right-hand pages never appears in the Left combo, and vice versa. Same page-orientation rule Preflight already flags as an error, now enforced up front so a mismatch can't be selected in the first place - "No Change" entry reflects current state — shows the shared master name if uniform, or "(multiple)" if the pages in scope don't all share one - New By Section scope option, using Scribus's existing page-numbering sections, alongside the existing Current Page / All Pages / Within Range - Live page counts ("Affects: X left pages, Y right pages") update as scope or selections change, correctly asymmetric when only one side is set - Even/Odd removed — folded into the Left/Right combos, since side is what Even/Odd was really standing in for - Combos auto-size to fit long master/section names; captions and secondary text styled to read correctly in both Light and Dark themes; keyboard tab order corrected to follow the visual layout mp1-bulk-apply-side-aware-combos-v1.13.patch (23,125 bytes)
Index: scribus/ui/applytemplatedialog.h
===================================================================
--- scribus/ui/applytemplatedialog.h (revision 27861)
+++ scribus/ui/applytemplatedialog.h (working copy)
@@ -17,6 +17,7 @@
#include <QDialog>
#include <QDialogButtonBox>
+#include <QPair>
#include <QString>
#include "scribusapi.h"
@@ -24,15 +25,13 @@
#include "scpage.h"
#include "ui/scrspinbox.h"
-class QCheckBox;
class QComboBox;
class QEvent;
+class QGridLayout;
class QGroupBox;
class QHBoxLayout;
class QLabel;
-class QPushButton;
class QRadioButton;
-class QSpacerItem;
class QVBoxLayout;
class SCRIBUS_API ApplyMasterPageDialog : public QDialog
@@ -43,35 +42,40 @@
ApplyMasterPageDialog( QWidget* parent = nullptr );
~ApplyMasterPageDialog() = default;
- QLabel* masterPageLabel { nullptr };
- QComboBox* masterPageComboBox { nullptr };
+ QComboBox* leftMasterPageComboBox { nullptr };
+ QLabel* leftMasterPageCaption { nullptr };
+ QComboBox* rightMasterPageComboBox { nullptr };
+ QLabel* rightMasterPageCaption { nullptr };
QGroupBox* applyToPageButtonGroup { nullptr };
QRadioButton* currentPageRadioButton { nullptr };
- QRadioButton* evenPagesRadioButton { nullptr };
- QRadioButton* oddPagesRadioButton { nullptr };
QRadioButton* allPagesRadioButton { nullptr };
- QCheckBox* useRangeCheckBox { nullptr };
+ QRadioButton* withinRangeRadioButton { nullptr };
ScrSpinBox* fromPageSpinBox { nullptr };
QLabel* toPageLabel { nullptr };
ScrSpinBox* toPageSpinBox { nullptr };
+ QLabel* affectsLabel { nullptr };
- virtual void setup(ScribusDoc* doc, const QString& Nam);
- virtual QString getMasterPageName();
- virtual int getPageSelection();
- virtual bool usingRange();
- virtual int getFromPage();
- virtual int getToPage();
+ virtual void setup(ScribusDoc* doc);
+ virtual QString getLeftMasterPageName();
+ virtual QString getRightMasterPageName();
+ virtual int getStartPage() const;
+ virtual int getEndPage() const;
protected:
QVBoxLayout* ApplyMasterPageDialogLayout { nullptr };
- QHBoxLayout* templateNameLayout { nullptr };
- QSpacerItem* spacer2 { nullptr };
- QVBoxLayout* applyToPageButtonGroupLayout { nullptr };
- QHBoxLayout* rangeLayout { nullptr };
- QSpacerItem* spacer3 { nullptr };
+ QHBoxLayout* masterCombosLayout { nullptr };
+ QGridLayout* applyToPageButtonGroupLayout { nullptr };
QDialogButtonBox* buttonBox { nullptr };
-
+
+ ScribusDoc* m_doc { nullptr };
+ bool m_sideRestricted { true };
+
+ void styleCaption(QLabel* caption);
void changeEvent(QEvent *e) override;
+ void populateMasterCombo(QComboBox* combo, int wantedSide);
+ QString sideSummaryLabel(int wantedSide) const;
+ QPair<int, int> scopePageRange() const;
+ void refreshSummaries();
protected slots:
virtual void languageChange();
@@ -79,9 +83,10 @@
private slots:
virtual void checkRangeFrom();
virtual void checkRangeTo();
- virtual void enableRange( bool enabled );
virtual void rangeSelectable();
+ virtual void allPagesSelectable();
virtual void singleSelectable();
+ virtual void updateSummaries();
};
Index: scribus/ui/applytemplatedialog.cpp
===================================================================
--- scribus/ui/applytemplatedialog.cpp (revision 27861)
+++ scribus/ui/applytemplatedialog.cpp (working copy)
@@ -17,27 +17,19 @@
#include <QCheckBox>
#include <QComboBox>
#include <QEvent>
+#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QRadioButton>
-#include <QSpacerItem>
-#include <QSpinBox>
-#include <QToolTip>
+#include <QSet>
#include <QVBoxLayout>
#include "commonstrings.h"
#include "scpage.h"
#include "scribusdoc.h"
#include "iconmanager.h"
-
-enum {
- CurrentPage,
- EvenPages,
- OddPages,
- AllPages
-};
/*
* Constructs a ApplyMasterPageDialog as a child of 'parent', with the
@@ -55,128 +47,299 @@
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 );
+ masterCombosLayout = new QHBoxLayout;
+ masterCombosLayout->setContentsMargins(0, 0, 0, 0);
+ masterCombosLayout->setSpacing(12);
+
+ QVBoxLayout* leftComboLayout = new QVBoxLayout;
+ leftComboLayout->setSpacing(5);
+ leftMasterPageComboBox = new QComboBox(this);
+ leftMasterPageComboBox->setEditable(false);
+ leftMasterPageComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ leftMasterPageComboBox->setMaximumWidth(320);
+ leftComboLayout->addWidget(leftMasterPageComboBox);
+ leftMasterPageCaption = new QLabel(this);
+ styleCaption(leftMasterPageCaption);
+ leftComboLayout->addWidget(leftMasterPageCaption);
+ masterCombosLayout->addLayout(leftComboLayout);
+
+ QVBoxLayout* rightComboLayout = new QVBoxLayout;
+ rightComboLayout->setSpacing(5);
+ rightMasterPageComboBox = new QComboBox(this);
+ rightMasterPageComboBox->setEditable(false);
+ rightMasterPageComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ rightMasterPageComboBox->setMaximumWidth(320);
+ rightComboLayout->addWidget(rightMasterPageComboBox);
+ rightMasterPageCaption = new QLabel(this);
+ styleCaption(rightMasterPageCaption);
+ rightComboLayout->addWidget(rightMasterPageCaption);
+ masterCombosLayout->addLayout(rightComboLayout);
+
+ ApplyMasterPageDialogLayout->addLayout( masterCombosLayout );
applyToPageButtonGroup = new QGroupBox(this);
- applyToPageButtonGroup->setMinimumSize( QSize( 250, 0 ) );
- applyToPageButtonGroupLayout = new QVBoxLayout(applyToPageButtonGroup);
+ applyToPageButtonGroupLayout = new QGridLayout(applyToPageButtonGroup);
applyToPageButtonGroupLayout->setSpacing(6);
applyToPageButtonGroupLayout->setContentsMargins(9, 9, 9, 9);
+ applyToPageButtonGroupLayout->setColumnStretch(4, 1);
currentPageRadioButton = new QRadioButton( applyToPageButtonGroup );
currentPageRadioButton->setChecked( true );
- applyToPageButtonGroupLayout->addWidget( currentPageRadioButton );
-
- evenPagesRadioButton = new QRadioButton( applyToPageButtonGroup );
- applyToPageButtonGroupLayout->addWidget( evenPagesRadioButton );
-
- oddPagesRadioButton = new QRadioButton( applyToPageButtonGroup );
- applyToPageButtonGroupLayout->addWidget( oddPagesRadioButton );
+ applyToPageButtonGroupLayout->addWidget( currentPageRadioButton, 0, 0, 1, 4 );
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 );
+ applyToPageButtonGroupLayout->addWidget( allPagesRadioButton, 1, 0, 1, 4 );
+
+ withinRangeRadioButton = new QRadioButton( applyToPageButtonGroup );
+ applyToPageButtonGroupLayout->addWidget( withinRangeRadioButton, 2, 0 );
fromPageSpinBox = new ScrSpinBox( applyToPageButtonGroup );
fromPageSpinBox->setEnabled( false );
fromPageSpinBox->setMinimum( 1 );
fromPageSpinBox->setDecimals(0);
fromPageSpinBox->setSuffix("");
- rangeLayout->addWidget( fromPageSpinBox );
+ applyToPageButtonGroupLayout->addWidget( fromPageSpinBox, 2, 1 );
toPageLabel = new QLabel( applyToPageButtonGroup );
- rangeLayout->addWidget( toPageLabel );
+ toPageLabel->setAlignment( Qt::AlignCenter );
+ applyToPageButtonGroupLayout->addWidget( toPageLabel, 2, 2 );
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 );
+ applyToPageButtonGroupLayout->addWidget( toPageSpinBox, 2, 3 );
+
ApplyMasterPageDialogLayout->addWidget( applyToPageButtonGroup );
+
+ ApplyMasterPageDialogLayout->addSpacing(6);
+ affectsLabel = new QLabel(this);
+ ApplyMasterPageDialogLayout->addWidget(affectsLabel);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
ApplyMasterPageDialogLayout->addWidget(buttonBox);
languageChange();
- resize( QSize(268, 230).expandedTo(minimumSizeHint()) );
+ resize( QSize(420, 260).expandedTo(minimumSizeHint()) );
// signals and slots connections
- connect( useRangeCheckBox, SIGNAL( toggled(bool) ), this, SLOT( enableRange(bool) ) );
connect( currentPageRadioButton, SIGNAL( clicked() ), this, SLOT( singleSelectable() ) );
- connect( evenPagesRadioButton, SIGNAL( clicked() ), this, SLOT( rangeSelectable() ) );
- connect( oddPagesRadioButton, SIGNAL( clicked() ), this, SLOT( rangeSelectable() ) );
- connect( allPagesRadioButton, SIGNAL( clicked() ), this, SLOT( rangeSelectable() ) );
+ connect( allPagesRadioButton, SIGNAL( clicked() ), this, SLOT( allPagesSelectable() ) );
+ connect( withinRangeRadioButton, SIGNAL( clicked() ), this, SLOT( rangeSelectable() ) );
connect( fromPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( checkRangeFrom() ) );
connect( toPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( checkRangeTo() ) );
+ connect( currentPageRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
+ connect( allPagesRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
+ connect( withinRangeRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
+ connect( fromPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( updateSummaries() ) );
+ connect( toPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( updateSummaries() ) );
+ connect( leftMasterPageComboBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateSummaries() ) );
+ connect( rightMasterPageComboBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateSummaries() ) );
connect(buttonBox, &QDialogButtonBox::accepted, this, &ApplyMasterPageDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &ApplyMasterPageDialog::reject);
- // buddies
- masterPageLabel->setBuddy( masterPageComboBox );
-}
-
-void ApplyMasterPageDialog::setup(ScribusDoc *doc, const QString& Nam)
-{
- QString na = (Nam == CommonStrings::masterPageNormal) ? CommonStrings::trMasterPageNormal : Nam;
- QString in;
-
- int cc = 0;
- for (auto it = doc->MasterNames.cbegin(); it != doc->MasterNames.cend(); ++it)
- {
- in = (it.key() == CommonStrings::masterPageNormal) ? CommonStrings::trMasterPageNormal : it.key();
- masterPageComboBox->addItem(in, it.key());
- if (in == na)
- masterPageComboBox->setCurrentIndex(cc);
- ++cc;
- }
- const int docPagesCount = doc->Pages->count();
- if (docPagesCount < 2)
- evenPagesRadioButton->setEnabled(false);
+ // Tab order follows the visual top-to-bottom, left-to-right layout,
+ // which Qt's default (creation-order-within-parent) can't do here
+ // since the combos and the group box's controls have different parents.
+ setTabOrder(leftMasterPageComboBox, rightMasterPageComboBox);
+ setTabOrder(rightMasterPageComboBox, currentPageRadioButton);
+ setTabOrder(currentPageRadioButton, allPagesRadioButton);
+ setTabOrder(allPagesRadioButton, withinRangeRadioButton);
+ setTabOrder(withinRangeRadioButton, fromPageSpinBox);
+ setTabOrder(fromPageSpinBox, toPageSpinBox);
+ setTabOrder(toPageSpinBox, buttonBox->button(QDialogButtonBox::Ok));
+ setTabOrder(buttonBox->button(QDialogButtonBox::Ok), buttonBox->button(QDialogButtonBox::Cancel));
+}
+
+void ApplyMasterPageDialog::styleCaption(QLabel* caption)
+{
+ caption->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+
+ QFont capFont = caption->font();
+ if (capFont.pointSize() > 1)
+ capFont.setPointSize(capFont.pointSize() - 1);
+ caption->setFont(capFont);
+
+ // Blends the label's own text color at partial opacity so it reads as
+ // secondary/muted while staying legible in both Light and Dark themes.
+ QPalette pal = caption->palette();
+ QColor textColor = pal.color(QPalette::WindowText);
+ textColor.setAlpha(160);
+ pal.setColor(QPalette::WindowText, textColor);
+ caption->setPalette(pal);
+}
+
+void ApplyMasterPageDialog::populateMasterCombo(QComboBox* combo, int wantedSide)
+{
+ combo->clear();
+ combo->addItem(tr("No Change"), QString());
+ for (auto it = m_doc->MasterNames.cbegin(); it != m_doc->MasterNames.cend(); ++it)
+ {
+ const QString& mpName = it.key();
+ if (wantedSide != -1)
+ {
+ ScPage* masterPage = m_doc->MasterPages.at(it.value());
+ bool sideMatches = (wantedSide == 0) ? (masterPage->LeftPg == 1) : (masterPage->LeftPg == 0);
+ if (!sideMatches)
+ continue;
+ }
+ QString label = (mpName == CommonStrings::masterPageNormal) ? CommonStrings::trMasterPageNormal : mpName;
+ combo->addItem(label, mpName);
+ }
+}
+
+void ApplyMasterPageDialog::setup(ScribusDoc *doc)
+{
+ m_doc = doc;
+ m_sideRestricted = (doc->pagePositioning() != singlePage);
+
+ if (m_sideRestricted)
+ {
+ populateMasterCombo(leftMasterPageComboBox, 0);
+ populateMasterCombo(rightMasterPageComboBox, 1);
+ rightMasterPageComboBox->setVisible(true);
+ rightMasterPageCaption->setVisible(true);
+
+ // Keep both combos the same width (the wider of the two), so one
+ // side isn't visibly lopsided against the other as names change.
+ int matchedWidth = qMax(leftMasterPageComboBox->sizeHint().width(), rightMasterPageComboBox->sizeHint().width());
+ leftMasterPageComboBox->setMinimumWidth(matchedWidth);
+ rightMasterPageComboBox->setMinimumWidth(matchedWidth);
+ }
+ else
+ {
+ populateMasterCombo(leftMasterPageComboBox, -1);
+ rightMasterPageComboBox->setVisible(false);
+ rightMasterPageCaption->setVisible(false);
+ leftMasterPageComboBox->setMinimumWidth(0);
+ }
+
+ const int docPagesCount = doc->DocPages.count();
fromPageSpinBox->setMaximum(docPagesCount);
fromPageSpinBox->setValue(doc->currentPage()->pageNr() + 1);
toPageSpinBox->setMaximum(docPagesCount);
toPageSpinBox->setValue(docPagesCount);
-}
-
-
-QString ApplyMasterPageDialog::getMasterPageName()
-{
- int currentIndex = masterPageComboBox->currentIndex();
- return masterPageComboBox->itemData(currentIndex).toString();
-}
-
-
-int ApplyMasterPageDialog::getPageSelection()
-{
+
+ refreshSummaries();
+}
+
+
+QString ApplyMasterPageDialog::getLeftMasterPageName()
+{
+ return leftMasterPageComboBox->itemData(leftMasterPageComboBox->currentIndex()).toString();
+}
+
+QString ApplyMasterPageDialog::getRightMasterPageName()
+{
+ if (!m_sideRestricted)
+ return QString();
+ return rightMasterPageComboBox->itemData(rightMasterPageComboBox->currentIndex()).toString();
+}
+
+
+int ApplyMasterPageDialog::getStartPage() const
+{
+ return scopePageRange().first;
+}
+
+int ApplyMasterPageDialog::getEndPage() const
+{
+ return scopePageRange().second;
+}
+
+QPair<int, int> ApplyMasterPageDialog::scopePageRange() const
+{
+ int start, end;
if (currentPageRadioButton->isChecked())
- return CurrentPage;
- if (evenPagesRadioButton->isChecked())
- return EvenPages;
- if (oddPagesRadioButton->isChecked())
- return OddPages;
- return AllPages;
+ {
+ start = m_doc->currentPage()->pageNr();
+ end = start + 1;
+ }
+ else if (withinRangeRadioButton->isChecked())
+ {
+ start = static_cast<int>(fromPageSpinBox->value()) - 1;
+ end = static_cast<int>(toPageSpinBox->value());
+ }
+ else
+ {
+ start = 0;
+ end = m_doc->DocPages.count();
+ }
+ return qMakePair(start, end);
+}
+
+QString ApplyMasterPageDialog::sideSummaryLabel(int wantedSide) const
+{
+ QPair<int, int> range = scopePageRange();
+ int count = 0;
+ QSet<QString> names;
+ for (int i = range.first; i < range.second && i < m_doc->DocPages.count(); ++i)
+ {
+ if (i < 0)
+ continue;
+ if (wantedSide != -1)
+ {
+ PageLocation loc = m_doc->locationOfPage(i);
+ bool matches = (wantedSide == 0) ? (loc == LeftPage) : (loc == RightPage);
+ if (!matches)
+ continue;
+ }
+ ++count;
+ names.insert(m_doc->DocPages.at(i)->masterPageName());
+ }
+
+ if (count == 0)
+ return tr("No Change");
+ if (names.size() > 1)
+ return tr("No Change (multiple)");
+ QString only = *names.begin();
+ if (only.isEmpty())
+ return tr("No Change");
+ QString label = (only == CommonStrings::masterPageNormal) ? CommonStrings::trMasterPageNormal : only;
+ return tr("No Change (%1)").arg(label);
+}
+
+void ApplyMasterPageDialog::refreshSummaries()
+{
+ if (!m_doc)
+ return;
+
+ QPair<int, int> range = scopePageRange();
+ int leftCount = 0, rightCount = 0;
+ for (int i = range.first; i < range.second && i < m_doc->DocPages.count(); ++i)
+ {
+ if (i < 0)
+ continue;
+ if (!m_sideRestricted)
+ continue;
+ PageLocation loc = m_doc->locationOfPage(i);
+ if (loc == LeftPage)
+ ++leftCount;
+ else if (loc == RightPage)
+ ++rightCount;
+ }
+
+ if (m_sideRestricted)
+ {
+ leftMasterPageComboBox->setItemText(0, sideSummaryLabel(0));
+ rightMasterPageComboBox->setItemText(0, sideSummaryLabel(1));
+ affectsLabel->setText( tr("Affects: %1 left pages, %2 right pages").arg(leftCount).arg(rightCount) );
+ }
+ else
+ {
+ leftMasterPageComboBox->setItemText(0, sideSummaryLabel(-1));
+ int total = qMax(0, range.second - range.first);
+ affectsLabel->setText( tr("Affects: %1 pages").arg(total) );
+ }
+
+ bool hasChange = !getLeftMasterPageName().isEmpty() || (m_sideRestricted && !getRightMasterPageName().isEmpty());
+ if (QPushButton* okButton = buttonBox->button(QDialogButtonBox::Ok))
+ okButton->setEnabled(hasChange);
+}
+
+void ApplyMasterPageDialog::updateSummaries()
+{
+ refreshSummaries();
}
void ApplyMasterPageDialog::checkRangeFrom()
@@ -199,45 +362,22 @@
connect(toPageSpinBox, SIGNAL(valueChanged(double)), this, SLOT(checkRangeTo()));
}
-void ApplyMasterPageDialog::enableRange( bool enabled )
-{
- fromPageSpinBox->setEnabled(enabled);
- toPageSpinBox->setEnabled(enabled);
-}
-
void ApplyMasterPageDialog::rangeSelectable()
{
- useRangeCheckBox->setEnabled(true);
- enableRange(useRangeCheckBox->isChecked());
-}
-
-void ApplyMasterPageDialog::singleSelectable()
-{
- useRangeCheckBox->setEnabled(false);
+ fromPageSpinBox->setEnabled(true);
+ toPageSpinBox->setEnabled(true);
+}
+
+void ApplyMasterPageDialog::allPagesSelectable()
+{
fromPageSpinBox->setEnabled(false);
toPageSpinBox->setEnabled(false);
}
-
-bool ApplyMasterPageDialog::usingRange()
-{
- return useRangeCheckBox->isChecked();
-}
-
-
-int ApplyMasterPageDialog::getFromPage()
-{
- if (useRangeCheckBox->isChecked())
- return static_cast<int>(fromPageSpinBox->value());
- return -1;
-}
-
-
-int ApplyMasterPageDialog::getToPage()
-{
- if (useRangeCheckBox->isChecked())
- return static_cast<int>(toPageSpinBox->value());
- return -1;
+void ApplyMasterPageDialog::singleSelectable()
+{
+ fromPageSpinBox->setEnabled(false);
+ toPageSpinBox->setEnabled(false);
}
void ApplyMasterPageDialog::changeEvent(QEvent *e)
@@ -253,18 +393,15 @@
void ApplyMasterPageDialog::languageChange()
{
setWindowTitle( tr( "Apply Master Page" ) );
- masterPageLabel->setText( tr( "&Master Page:" ) );
+ leftMasterPageCaption->setText( tr( "Left Pages" ) );
+ rightMasterPageCaption->setText( tr( "Right Pages" ) );
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( "<qt>" + tr( "Apply the selected master page to even, odd or all pages within the following range") + "</qt>" );
+ withinRangeRadioButton->setText( tr( "&Within Range" ) );
+ withinRangeRadioButton->setShortcut( QKeySequence( tr( "Alt+W" ) ) );
+ withinRangeRadioButton->setToolTip( "<qt>" + tr( "Apply the selected master page(s) to the selected range") + "</qt>" );
toPageLabel->setText( tr( "to" ) );
}
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp (revision 27861)
+++ scribus/scribus.cpp (working copy)
@@ -7801,43 +7801,26 @@
Q_ASSERT(!doc->masterPageMode());
QScopedPointer<ApplyMasterPageDialog> dia(new ApplyMasterPageDialog(this));
- dia->setup(doc, doc->currentPage()->masterPageName());
+ dia->setup(doc);
if (!dia->exec())
return;
- QString masterPageName(dia->getMasterPageName());
- int pageSelection = dia->getPageSelection(); //0=current, 1=even, 2=odd, 3=all
-
- int startPage, endPage;
- if (pageSelection == 0)
- {
- startPage = doc->currentPage()->pageNr();
- endPage = doc->currentPage()->pageNr() + 1;
- }
- else if (dia->usingRange())
- {
- startPage = dia->getFromPage() - 1; //Pages start from 0, not 1
- endPage = dia->getToPage();
- }
- else
- {
- startPage = pageSelection == 1 ? 1 : 0; //if even, startPage is 1 (real page 2)
- endPage = doc->DocPages.count();
- }
+ QString leftMasterPageName(dia->getLeftMasterPageName());
+ QString rightMasterPageName(dia->getRightMasterPageName());
+ int startPage = dia->getStartPage();
+ int endPage = dia->getEndPage();
UndoTransaction trans;
if (UndoManager::undoEnabled() && (startPage + 1 < endPage))
- trans = m_undoManager->beginTransaction(QString(), nullptr, Um::ApplyMasterPage, masterPageName);
+ trans = m_undoManager->beginTransaction(QString(), nullptr, Um::ApplyMasterPage, QString());
for (int pageNum = startPage; pageNum < endPage; ++pageNum)
{
- //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
- continue;
- if (pageSelection == 2 && (pageNum % 2 != 0)) //Odd, %2==0 as 1st page is numbered 0
- continue;
- Apply_MasterPage(masterPageName, pageNum, false);
+ PageLocation pageLoc = doc->locationOfPage(pageNum);
+ if (pageLoc == LeftPage && !leftMasterPageName.isEmpty())
+ Apply_MasterPage(leftMasterPageName, pageNum, false);
+ else if (pageLoc == RightPage && !rightMasterPageName.isEmpty())
+ Apply_MasterPage(rightMasterPageName, pageNum, false);
}
if (trans)
mp2-bulk-apply-by-section-v1.09.patch (7,121 bytes)
Index: scribus/ui/applytemplatedialog.h
===================================================================
--- scribus/ui/applytemplatedialog.h (revision 27861)
+++ scribus/ui/applytemplatedialog.h (working copy)
@@ -17,6 +17,7 @@
#include <QDialog>
#include <QDialogButtonBox>
+#include <QList>
#include <QPair>
#include <QString>
@@ -53,6 +54,9 @@
ScrSpinBox* fromPageSpinBox { nullptr };
QLabel* toPageLabel { nullptr };
ScrSpinBox* toPageSpinBox { nullptr };
+ QRadioButton* bySectionRadioButton { nullptr };
+ QComboBox* sectionComboBox { nullptr };
+ QLabel* sectionSpanLabel { nullptr };
QLabel* affectsLabel { nullptr };
virtual void setup(ScribusDoc* doc);
@@ -69,6 +73,7 @@
ScribusDoc* m_doc { nullptr };
bool m_sideRestricted { true };
+ QList<QPair<int, int>> m_sectionRanges;
void styleCaption(QLabel* caption);
void changeEvent(QEvent *e) override;
@@ -86,6 +91,7 @@
virtual void rangeSelectable();
virtual void allPagesSelectable();
virtual void singleSelectable();
+ virtual void sectionSelectable();
virtual void updateSummaries();
};
Index: scribus/ui/applytemplatedialog.cpp
===================================================================
--- scribus/ui/applytemplatedialog.cpp (revision 27861)
+++ scribus/ui/applytemplatedialog.cpp (working copy)
@@ -111,6 +111,20 @@
toPageSpinBox->setSuffix("");
applyToPageButtonGroupLayout->addWidget( toPageSpinBox, 2, 3 );
+ bySectionRadioButton = new QRadioButton( applyToPageButtonGroup );
+ applyToPageButtonGroupLayout->addWidget( bySectionRadioButton, 3, 0 );
+
+ sectionComboBox = new QComboBox( applyToPageButtonGroup );
+ sectionComboBox->setEnabled( false );
+ sectionComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+ sectionComboBox->setMaximumWidth(320);
+ applyToPageButtonGroupLayout->addWidget( sectionComboBox, 3, 1, 1, 3 );
+
+ sectionSpanLabel = new QLabel( applyToPageButtonGroup );
+ styleCaption(sectionSpanLabel);
+ sectionSpanLabel->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
+ applyToPageButtonGroupLayout->addWidget( sectionSpanLabel, 3, 4 );
+
ApplyMasterPageDialogLayout->addWidget( applyToPageButtonGroup );
ApplyMasterPageDialogLayout->addSpacing(6);
@@ -126,13 +140,16 @@
connect( currentPageRadioButton, SIGNAL( clicked() ), this, SLOT( singleSelectable() ) );
connect( allPagesRadioButton, SIGNAL( clicked() ), this, SLOT( allPagesSelectable() ) );
connect( withinRangeRadioButton, SIGNAL( clicked() ), this, SLOT( rangeSelectable() ) );
+ connect( bySectionRadioButton, SIGNAL( clicked() ), this, SLOT( sectionSelectable() ) );
connect( fromPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( checkRangeFrom() ) );
connect( toPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( checkRangeTo() ) );
connect( currentPageRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
connect( allPagesRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
connect( withinRangeRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
+ connect( bySectionRadioButton, SIGNAL( clicked() ), this, SLOT( updateSummaries() ) );
connect( fromPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( updateSummaries() ) );
connect( toPageSpinBox, SIGNAL( valueChanged(double) ), this, SLOT( updateSummaries() ) );
+ connect( sectionComboBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateSummaries() ) );
connect( leftMasterPageComboBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateSummaries() ) );
connect( rightMasterPageComboBox, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateSummaries() ) );
connect(buttonBox, &QDialogButtonBox::accepted, this, &ApplyMasterPageDialog::accept);
@@ -147,7 +164,9 @@
setTabOrder(allPagesRadioButton, withinRangeRadioButton);
setTabOrder(withinRangeRadioButton, fromPageSpinBox);
setTabOrder(fromPageSpinBox, toPageSpinBox);
- setTabOrder(toPageSpinBox, buttonBox->button(QDialogButtonBox::Ok));
+ setTabOrder(toPageSpinBox, bySectionRadioButton);
+ setTabOrder(bySectionRadioButton, sectionComboBox);
+ setTabOrder(sectionComboBox, buttonBox->button(QDialogButtonBox::Ok));
setTabOrder(buttonBox->button(QDialogButtonBox::Ok), buttonBox->button(QDialogButtonBox::Cancel));
}
@@ -220,6 +239,22 @@
toPageSpinBox->setMaximum(docPagesCount);
toPageSpinBox->setValue(docPagesCount);
+ sectionComboBox->clear();
+ m_sectionRanges.clear();
+ for (auto it = doc->sections().cbegin(); it != doc->sections().cend(); ++it)
+ {
+ const DocumentSection& sec = it.value();
+ if (!sec.active)
+ continue;
+ QString label = sec.name.isEmpty() ? tr("Section %1").arg(sec.number + 1) : sec.name;
+ sectionComboBox->addItem(label);
+ m_sectionRanges.append(qMakePair(static_cast<int>(sec.fromindex), static_cast<int>(sec.toindex) + 1));
+ }
+ bool hasSections = !m_sectionRanges.isEmpty();
+ bySectionRadioButton->setEnabled(hasSections);
+ if (!hasSections)
+ sectionComboBox->addItem(tr("No sections defined"));
+
refreshSummaries();
}
@@ -254,6 +289,20 @@
{
start = m_doc->currentPage()->pageNr();
end = start + 1;
+ }
+ else if (bySectionRadioButton->isChecked())
+ {
+ int idx = sectionComboBox->currentIndex();
+ if (idx >= 0 && idx < m_sectionRanges.count())
+ {
+ start = m_sectionRanges.at(idx).first;
+ end = m_sectionRanges.at(idx).second;
+ }
+ else
+ {
+ start = 0;
+ end = 0;
+ }
}
else if (withinRangeRadioButton->isChecked())
{
@@ -332,6 +381,11 @@
affectsLabel->setText( tr("Affects: %1 pages").arg(total) );
}
+ if (bySectionRadioButton->isChecked() && range.second > range.first)
+ sectionSpanLabel->setText( tr("(Pages %1–%2 of %3)").arg(range.first + 1).arg(range.second).arg(m_doc->DocPages.count()) );
+ else
+ sectionSpanLabel->setText(QString());
+
bool hasChange = !getLeftMasterPageName().isEmpty() || (m_sideRestricted && !getRightMasterPageName().isEmpty());
if (QPushButton* okButton = buttonBox->button(QDialogButtonBox::Ok))
okButton->setEnabled(hasChange);
@@ -366,18 +420,28 @@
{
fromPageSpinBox->setEnabled(true);
toPageSpinBox->setEnabled(true);
+ sectionComboBox->setEnabled(false);
}
void ApplyMasterPageDialog::allPagesSelectable()
{
fromPageSpinBox->setEnabled(false);
toPageSpinBox->setEnabled(false);
+ sectionComboBox->setEnabled(false);
}
void ApplyMasterPageDialog::singleSelectable()
{
fromPageSpinBox->setEnabled(false);
toPageSpinBox->setEnabled(false);
+ sectionComboBox->setEnabled(false);
+}
+
+void ApplyMasterPageDialog::sectionSelectable()
+{
+ fromPageSpinBox->setEnabled(false);
+ toPageSpinBox->setEnabled(false);
+ sectionComboBox->setEnabled(true);
}
void ApplyMasterPageDialog::changeEvent(QEvent *e)
@@ -404,4 +468,6 @@
withinRangeRadioButton->setShortcut( QKeySequence( tr( "Alt+W" ) ) );
withinRangeRadioButton->setToolTip( "<qt>" + tr( "Apply the selected master page(s) to the selected range") + "</qt>" );
toPageLabel->setText( tr( "to" ) );
-}
+ bySectionRadioButton->setText( tr( "By &Section" ) );
+ bySectionRadioButton->setShortcut( QKeySequence( tr( "Alt+S" ) ) );
+}
|
|
|
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2010-10-19 16:23 | subeditor | New Issue | |
| 2010-10-19 16:23 | subeditor | File Added: Apply Master Pages Draft.png | |
| 2015-11-24 01:53 | Kunda | Patch | => No |
| 2015-11-24 01:53 | Kunda | Summary | Enchancement for "Apply Master Page" dialog => Enchancement for "Apply Master Page" dialog (mockup incl.) |
| 2016-04-05 22:23 | Kunda | Summary | Enchancement for "Apply Master Page" dialog (mockup incl.) => Enhancement for "Apply Master Page" dialog (mockup incl.) |
| 2016-04-05 22:24 | Kunda | Relationship added | child of 0003837 |
| 2016-04-05 22:24 | Kunda | Tag Attached: mockup | |
| 2026-09-21 13:13 | buttar | Note Added: 0054482 | |
| 2026-09-21 13:13 | buttar | File Added: mp1-bulk-apply-side-aware-combos-v1.13.patch | |
| 2026-09-21 13:13 | buttar | File Added: mp2-bulk-apply-by-section-v1.09.patch | |
| 2026-09-21 13:14 | buttar | Note Added: 0054483 | |
| 2026-09-21 13:14 | buttar | File Added: master-page-bulk-apply.png |