Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "pagesettings.h"
24 :
25 : #include <QKeyEvent>
26 : #include <QPageSize>
27 :
28 : #include "engraving/dom/page.h"
29 : #include "engraving/dom/masterscore.h"
30 : #include "engraving/dom/mscore.h"
31 : #include "engraving/dom/excerpt.h"
32 : #include "engraving/style/pagestyle.h"
33 :
34 : #include "notation/inotation.h"
35 : #include "notation/inotationelements.h" // IWYU pragma: keep
36 : #include "notation/inotationstyle.h" // IWYU pragma: keep
37 : #include "notation/inotationundostack.h" // IWYU pragma: keep
38 :
39 : #include "ui/view/widgetstatestore.h"
40 :
41 : using namespace mu::notation;
42 : using namespace muse::ui;
43 : using namespace mu::engraving;
44 :
45 0 : PageSettings::PageSettings(QWidget* parent)
46 0 : : muse::ui::WidgetDialog(parent)
47 : {
48 0 : setObjectName("PageSettings");
49 0 : setupUi(this);
50 0 : setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
51 0 : setModal(true);
52 0 : }
53 :
54 0 : void PageSettings::componentComplete()
55 : {
56 0 : mmUnit = configuration()->metricUnit();
57 0 : _changeFlag = false;
58 :
59 0 : if (mmUnit) {
60 0 : mmButton->setChecked(true);
61 : } else {
62 0 : inchButton->setChecked(true);
63 : }
64 :
65 0 : for (int i = 0; i < QPageSize::LastPageSize; ++i) {
66 0 : pageGroup->addItem(QPageSize::name(QPageSize::PageSizeId(i)), i);
67 : }
68 :
69 0 : connect(mmButton, &QRadioButton::clicked, this, &PageSettings::mmClicked);
70 0 : connect(inchButton, &QRadioButton::clicked, this, &PageSettings::inchClicked);
71 0 : connect(buttonBox, &QDialogButtonBox::clicked, this, &PageSettings::buttonBoxClicked);
72 0 : connect(buttonApplyToAllParts, &QPushButton::clicked, this, &PageSettings::applyToAllParts);
73 0 : connect(portraitButton, &QRadioButton::clicked, this, &PageSettings::orientationClicked);
74 0 : connect(landscapeButton, &QRadioButton::clicked, this, &PageSettings::orientationClicked);
75 0 : connect(twosided, &QCheckBox::toggled, this, &PageSettings::twosidedToggled);
76 :
77 0 : connect(pageHeight, &QDoubleSpinBox::valueChanged,
78 0 : this, &PageSettings::pageHeightChanged);
79 0 : connect(pageWidth, &QDoubleSpinBox::valueChanged,
80 0 : this, &PageSettings::pageWidthChanged);
81 0 : connect(oddPageTopMargin, &QDoubleSpinBox::valueChanged,
82 0 : this, &PageSettings::otmChanged);
83 0 : connect(oddPageBottomMargin, &QDoubleSpinBox::valueChanged,
84 0 : this, &PageSettings::obmChanged);
85 0 : connect(oddPageLeftMargin, &QDoubleSpinBox::valueChanged,
86 0 : this, &PageSettings::olmChanged);
87 0 : connect(oddPageRightMargin, &QDoubleSpinBox::valueChanged,
88 0 : this, &PageSettings::ormChanged);
89 0 : connect(evenPageTopMargin, &QDoubleSpinBox::valueChanged,
90 0 : this, &PageSettings::etmChanged);
91 0 : connect(evenPageBottomMargin, &QDoubleSpinBox::valueChanged,
92 0 : this, &PageSettings::ebmChanged);
93 0 : connect(evenPageRightMargin, &QDoubleSpinBox::valueChanged,
94 0 : this, &PageSettings::ermChanged);
95 0 : connect(evenPageLeftMargin, &QDoubleSpinBox::valueChanged,
96 0 : this, &PageSettings::elmChanged);
97 0 : connect(spatiumEntry, &QDoubleSpinBox::valueChanged,
98 0 : this, &PageSettings::spatiumChanged);
99 :
100 0 : connect(pageGroup, &QComboBox::activated,
101 0 : this, &PageSettings::pageFormatSelected);
102 0 : connect(pageOffsetEntry, &QSpinBox::valueChanged,
103 0 : this, &PageSettings::pageOffsetChanged);
104 0 : }
105 :
106 0 : void PageSettings::showEvent(QShowEvent* event)
107 : {
108 0 : projectSession()->currentNotation()->undoStack()->prepareChanges(muse::TranslatableString("undoableAction", "Edit page settings"));
109 0 : updateValues();
110 :
111 0 : WidgetStateStore::restoreGeometry(this);
112 0 : QWidget::showEvent(event);
113 0 : }
114 :
115 0 : void PageSettings::hideEvent(QHideEvent* event)
116 : {
117 0 : WidgetStateStore::saveGeometry(this);
118 0 : QWidget::hideEvent(event);
119 0 : }
120 :
121 0 : void PageSettings::blockSignals(bool block)
122 : {
123 0 : for (auto w : { oddPageTopMargin, oddPageBottomMargin, oddPageLeftMargin, oddPageRightMargin,
124 0 : evenPageTopMargin, evenPageBottomMargin, evenPageLeftMargin, evenPageRightMargin, spatiumEntry,
125 0 : pageWidth, pageHeight }) {
126 0 : w->blockSignals(block);
127 : }
128 0 : pageOffsetEntry->blockSignals(block);
129 0 : pageGroup->blockSignals(block);
130 0 : }
131 :
132 0 : void PageSettings::setMarginsMax(double pw)
133 : {
134 0 : oddPageLeftMargin->setMaximum(pw);
135 0 : oddPageRightMargin->setMaximum(pw);
136 0 : evenPageLeftMargin->setMaximum(pw);
137 0 : evenPageRightMargin->setMaximum(pw);
138 0 : }
139 :
140 0 : Score* PageSettings::score() const
141 : {
142 0 : return projectSession()->currentNotation()->elements()->msScore();
143 : }
144 :
145 0 : double PageSettings::styleValueDouble(StyleId styleId) const
146 : {
147 0 : return projectSession()->currentNotation()->style()->styleValue(styleId).toDouble();
148 : }
149 :
150 0 : bool PageSettings::styleValueBool(StyleId styleId) const
151 : {
152 0 : return projectSession()->currentNotation()->style()->styleValue(styleId).toBool();
153 : }
154 :
155 0 : void PageSettings::setStyleValue(StyleId styleId, const PropertyValue& newValue) const
156 : {
157 0 : projectSession()->currentNotation()->style()->setStyleValue(styleId, newValue);
158 0 : }
159 :
160 : //---------------------------------------------------------
161 : // updateValues
162 : // set gui values from style
163 : //---------------------------------------------------------
164 :
165 0 : void PageSettings::updateValues()
166 : {
167 0 : bool mm = mmButton->isChecked();
168 :
169 0 : blockSignals(true);
170 :
171 0 : QString suffix;
172 : double singleStepSize;
173 : double singleStepScale;
174 0 : if (mm) {
175 0 : suffix = muse::qtrc("global", "mm");
176 0 : singleStepSize = 1.0;
177 0 : singleStepScale = 0.05;
178 : } else {
179 0 : suffix = muse::qtrc("global", "in", /*disambiguation*/ "abbreviation of inch");
180 0 : singleStepSize = 0.05;
181 0 : singleStepScale = 0.002;
182 : }
183 0 : for (auto w : { oddPageTopMargin, oddPageBottomMargin, oddPageLeftMargin, oddPageRightMargin, evenPageTopMargin,
184 0 : evenPageBottomMargin, evenPageLeftMargin, evenPageRightMargin, spatiumEntry, pageWidth, pageHeight }) {
185 0 : w->setSuffix(suffix);
186 0 : w->setSingleStep(singleStepSize);
187 : }
188 0 : spatiumEntry->setSingleStep(singleStepScale);
189 :
190 0 : double f = mm ? mu::engraving::INCH : 1.0;
191 :
192 0 : double w = styleValueDouble(Sid::pageWidth);
193 0 : double h = styleValueDouble(Sid::pageHeight);
194 0 : setMarginsMax(w * f);
195 :
196 0 : double pw = styleValueDouble(Sid::pagePrintableWidth);
197 0 : pageGroup->setCurrentIndex(int(QPageSize::id(QSizeF(w, h), QPageSize::Inch, QPageSize::FuzzyOrientationMatch)));
198 :
199 0 : oddPageTopMargin->setValue(styleValueDouble(Sid::pageOddTopMargin) * f);
200 0 : oddPageBottomMargin->setValue(styleValueDouble(Sid::pageOddBottomMargin) * f);
201 0 : oddPageLeftMargin->setValue(styleValueDouble(Sid::pageOddLeftMargin) * f);
202 0 : oddPageRightMargin->setValue((w - pw - styleValueDouble(Sid::pageOddLeftMargin)) * f);
203 :
204 0 : evenPageTopMargin->setValue(styleValueDouble(Sid::pageEvenTopMargin) * f);
205 0 : evenPageBottomMargin->setValue(styleValueDouble(Sid::pageEvenBottomMargin) * f);
206 0 : evenPageLeftMargin->setValue(styleValueDouble(Sid::pageEvenLeftMargin) * f);
207 0 : evenPageRightMargin->setValue((w - pw - styleValueDouble(Sid::pageEvenLeftMargin)) * f);
208 0 : pageHeight->setValue(h * f);
209 0 : pageWidth->setValue(w * f);
210 :
211 0 : double f1 = mm ? 1.0 / DPMM : 1.0 / DPI;
212 0 : spatiumEntry->setValue(score()->style().spatium() * f1);
213 :
214 0 : bool _twosided = styleValueBool(Sid::pageTwosided);
215 0 : evenPageTopMargin->setEnabled(_twosided);
216 0 : evenPageBottomMargin->setEnabled(_twosided);
217 0 : evenPageLeftMargin->setEnabled(_twosided);
218 0 : evenPageRightMargin->setEnabled(_twosided);
219 :
220 0 : if (twosided->isChecked()) {
221 0 : evenPageRightMargin->setValue(oddPageLeftMargin->value());
222 0 : evenPageLeftMargin->setValue(oddPageRightMargin->value());
223 : } else {
224 0 : evenPageRightMargin->setValue(oddPageRightMargin->value());
225 0 : evenPageLeftMargin->setValue(oddPageLeftMargin->value());
226 : }
227 :
228 0 : landscapeButton->setChecked(styleValueDouble(Sid::pageWidth) > styleValueDouble(Sid::pageHeight));
229 0 : portraitButton->setChecked(styleValueDouble(Sid::pageWidth) <= styleValueDouble(Sid::pageHeight));
230 :
231 0 : twosided->setChecked(_twosided);
232 :
233 0 : pageOffsetEntry->setValue(score()->pageNumberOffset() + 1);
234 :
235 0 : blockSignals(false);
236 0 : _changeFlag = true;
237 0 : }
238 :
239 0 : void PageSettings::inchClicked()
240 : {
241 0 : mmUnit = false;
242 0 : configuration()->setMetricUnit(false);
243 0 : updateValues();
244 0 : }
245 :
246 0 : void PageSettings::mmClicked()
247 : {
248 0 : mmUnit = true;
249 0 : configuration()->setMetricUnit(true);
250 0 : updateValues();
251 0 : }
252 :
253 : //---------------------------------------------------------
254 : // orientationClicked
255 : // swap width/height
256 : //---------------------------------------------------------
257 :
258 0 : void PageSettings::orientationClicked()
259 : {
260 0 : qreal w = styleValueDouble(Sid::pageWidth);
261 0 : qreal h = styleValueDouble(Sid::pageHeight);
262 :
263 0 : setStyleValue(Sid::pageWidth, h);
264 0 : setStyleValue(Sid::pageHeight, w);
265 :
266 0 : double f = mmUnit ? 1.0 / INCH : 1.0;
267 0 : setStyleValue(Sid::pagePrintableWidth, h - (oddPageLeftMargin->value() + oddPageRightMargin->value()) * f);
268 0 : updateValues();
269 0 : }
270 :
271 0 : void PageSettings::on_resetPageStyleButton_clicked()
272 : {
273 0 : score()->undoChangePageNumberOffset(0);
274 0 : projectSession()->currentNotation()->style()->resetStyleValues(pageStyles());
275 0 : updateValues();
276 0 : }
277 :
278 0 : void PageSettings::twosidedToggled(bool flag)
279 : {
280 0 : setStyleValue(Sid::pageTwosided, flag);
281 0 : updateValues();
282 0 : }
283 :
284 0 : void PageSettings::keyPressEvent(QKeyEvent* event)
285 : {
286 0 : if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
287 0 : return;
288 : }
289 0 : QDialog::keyPressEvent(event);
290 : }
291 :
292 0 : void PageSettings::buttonBoxClicked(QAbstractButton* button)
293 : {
294 0 : switch (buttonBox->buttonRole(button)) {
295 0 : case QDialogButtonBox::AcceptRole:
296 0 : accept();
297 0 : break;
298 0 : case QDialogButtonBox::RejectRole:
299 0 : reject();
300 0 : break;
301 0 : default:
302 0 : break;
303 : }
304 0 : }
305 :
306 0 : void PageSettings::accept()
307 : {
308 0 : projectSession()->currentNotation()->undoStack()->commitChanges();
309 0 : projectSession()->currentNotation()->style()->styleChanged().notify();
310 0 : QDialog::accept();
311 0 : }
312 :
313 0 : void PageSettings::reject()
314 : {
315 0 : projectSession()->currentNotation()->undoStack()->rollbackChanges();
316 0 : projectSession()->currentNotation()->style()->styleChanged().notify();
317 0 : QDialog::reject();
318 0 : }
319 :
320 0 : void PageSettings::applyToScore(Score* s)
321 : {
322 0 : double f = mmUnit ? 1.0 / INCH : 1.0;
323 0 : double f1 = mmUnit ? DPMM : DPI;
324 :
325 0 : std::unordered_map<Sid, PropertyValue> values;
326 0 : values.emplace(Sid::pageWidth, pageWidth->value() * f);
327 0 : values.emplace(Sid::pageHeight, pageHeight->value() * f);
328 0 : values.emplace(Sid::pagePrintableWidth, (pageWidth->value() - oddPageLeftMargin->value() - oddPageRightMargin->value()) * f);
329 0 : values.emplace(Sid::pageEvenTopMargin, evenPageTopMargin->value() * f);
330 0 : values.emplace(Sid::pageEvenBottomMargin, evenPageBottomMargin->value() * f);
331 0 : values.emplace(Sid::pageEvenLeftMargin, evenPageLeftMargin->value() * f);
332 0 : values.emplace(Sid::pageOddTopMargin, oddPageTopMargin->value() * f);
333 0 : values.emplace(Sid::pageOddBottomMargin, oddPageBottomMargin->value() * f);
334 0 : values.emplace(Sid::pageOddLeftMargin, oddPageLeftMargin->value() * f);
335 0 : values.emplace(Sid::pageTwosided, twosided->isChecked());
336 0 : values.emplace(Sid::spatium, spatiumEntry->value() * f1);
337 :
338 0 : s->undoChangeStyleValues(std::move(values));
339 0 : s->undoChangePageNumberOffset(pageOffsetEntry->value() - 1);
340 0 : }
341 :
342 0 : void PageSettings::applyToAllParts()
343 : {
344 0 : if (!_changeFlag) {
345 0 : return;
346 : }
347 0 : for (Excerpt* e : score()->masterScore()->excerpts()) {
348 0 : applyToScore(e->excerptScore());
349 : }
350 0 : _changeFlag = false;
351 : }
352 :
353 0 : void PageSettings::pageFormatSelected(int size)
354 : {
355 0 : if (size >= 0) {
356 0 : bool landscape = landscapeButton->isChecked();
357 0 : int id = pageGroup->currentData().toInt();
358 0 : QSizeF sz = QPageSize::size(QPageSize::PageSizeId(id), QPageSize::Inch);
359 :
360 0 : setStyleValue(Sid::pageWidth, landscape ? sz.height() : sz.width());
361 0 : setStyleValue(Sid::pageHeight, landscape ? sz.width() : sz.height());
362 :
363 0 : double f = mmUnit ? 1.0 / INCH : 1.0;
364 0 : setStyleValue(Sid::pagePrintableWidth,
365 0 : (landscape ? sz.height() : sz.width()) - (oddPageLeftMargin->value() + oddPageRightMargin->value()) * f);
366 0 : updateValues();
367 : }
368 0 : }
369 :
370 0 : void PageSettings::otmChanged(double val)
371 : {
372 0 : if (mmUnit) {
373 0 : val /= INCH;
374 : }
375 0 : setStyleValue(Sid::pageOddTopMargin, val);
376 0 : }
377 :
378 0 : void PageSettings::olmChanged(double val)
379 : {
380 0 : if (mmUnit) {
381 0 : val /= INCH;
382 : }
383 :
384 0 : if (twosided->isChecked()) {
385 0 : evenPageRightMargin->blockSignals(true);
386 0 : evenPageRightMargin->setValue(val * (mmUnit ? INCH : 1.0));
387 0 : evenPageRightMargin->blockSignals(false);
388 : } else {
389 0 : evenPageLeftMargin->blockSignals(true);
390 0 : evenPageLeftMargin->setValue(val * (mmUnit ? INCH : 1.0));
391 0 : evenPageLeftMargin->blockSignals(false);
392 : }
393 :
394 0 : setStyleValue(Sid::pageOddLeftMargin, val);
395 0 : setStyleValue(Sid::pagePrintableWidth, styleValueDouble(Sid::pageWidth) - styleValueDouble(Sid::pageEvenLeftMargin) - val);
396 0 : }
397 :
398 0 : void PageSettings::ormChanged(double val)
399 : {
400 0 : if (mmUnit) {
401 0 : val /= INCH;
402 : }
403 :
404 0 : if (twosided->isChecked()) {
405 0 : evenPageLeftMargin->blockSignals(true);
406 0 : evenPageLeftMargin->setValue(val * (mmUnit ? INCH : 1.0));
407 0 : setStyleValue(Sid::pageEvenLeftMargin, val);
408 0 : evenPageLeftMargin->blockSignals(false);
409 : } else {
410 0 : evenPageRightMargin->blockSignals(true);
411 0 : evenPageRightMargin->setValue(val * (mmUnit ? INCH : 1.0));
412 0 : evenPageRightMargin->blockSignals(false);
413 : }
414 0 : setStyleValue(Sid::pagePrintableWidth, styleValueDouble(Sid::pageWidth) - styleValueDouble(Sid::pageOddLeftMargin) - val);
415 0 : }
416 :
417 0 : void PageSettings::obmChanged(double val)
418 : {
419 0 : if (mmUnit) {
420 0 : val /= INCH;
421 : }
422 :
423 0 : setStyleValue(Sid::pageOddBottomMargin, val);
424 0 : }
425 :
426 0 : void PageSettings::etmChanged(double val)
427 : {
428 0 : if (mmUnit) {
429 0 : val /= INCH;
430 : }
431 :
432 0 : setStyleValue(Sid::pageEvenTopMargin, val);
433 0 : }
434 :
435 0 : void PageSettings::elmChanged(double val)
436 : {
437 0 : double f = mmUnit ? 1.0 / INCH : 1.0;
438 0 : val *= f;
439 :
440 0 : if (twosided->isChecked()) {
441 0 : oddPageRightMargin->blockSignals(true);
442 0 : oddPageRightMargin->setValue(val * (mmUnit ? INCH : 1.0));
443 0 : oddPageRightMargin->blockSignals(false);
444 : }
445 :
446 0 : setStyleValue(Sid::pageEvenLeftMargin, val);
447 0 : setStyleValue(Sid::pagePrintableWidth, styleValueDouble(Sid::pageWidth) - evenPageRightMargin->value() * f - val);
448 0 : }
449 :
450 0 : void PageSettings::ermChanged(double val)
451 : {
452 0 : if (mmUnit) {
453 0 : val /= INCH;
454 : }
455 :
456 0 : if (twosided->isChecked()) {
457 0 : oddPageLeftMargin->blockSignals(true);
458 0 : oddPageLeftMargin->setValue(val * (mmUnit ? INCH : 1.0));
459 0 : oddPageLeftMargin->blockSignals(false);
460 : }
461 :
462 0 : setStyleValue(Sid::pagePrintableWidth, styleValueDouble(Sid::pageWidth) - styleValueDouble(Sid::pageEvenLeftMargin) - val);
463 0 : setStyleValue(Sid::pageOddLeftMargin, val);
464 0 : }
465 :
466 0 : void PageSettings::ebmChanged(double val)
467 : {
468 0 : if (mmUnit) {
469 0 : val /= INCH;
470 : }
471 :
472 0 : setStyleValue(Sid::pageEvenBottomMargin, val);
473 0 : }
474 :
475 0 : void PageSettings::spatiumChanged(double val)
476 : {
477 0 : val *= mmUnit ? DPMM : DPI;
478 0 : setStyleValue(Sid::spatium, val); // this will also call Score::spatiumChanged()
479 0 : }
480 :
481 0 : void PageSettings::pageOffsetChanged(int val)
482 : {
483 0 : score()->undoChangePageNumberOffset(val - 1);
484 0 : projectSession()->currentNotation()->notationChanged().send(muse::RectF());
485 0 : }
486 :
487 0 : void PageSettings::pageHeightChanged(double val)
488 : {
489 0 : double val2 = pageWidth->value();
490 0 : if (mmUnit) {
491 0 : val /= INCH;
492 0 : val2 /= INCH;
493 : }
494 0 : pageGroup->setCurrentIndex(0); // custom
495 :
496 0 : setStyleValue(Sid::pageHeight, val);
497 0 : setStyleValue(Sid::pageWidth, val2);
498 0 : }
499 :
500 0 : void PageSettings::pageWidthChanged(double val)
501 : {
502 0 : setMarginsMax(val);
503 :
504 0 : double f = mmUnit ? 1.0 / INCH : 1.0;
505 0 : double val2 = pageHeight->value() * f;
506 0 : val *= f;
507 0 : pageGroup->setCurrentIndex(0); // custom
508 :
509 0 : setStyleValue(Sid::pageWidth, val);
510 0 : setStyleValue(Sid::pageHeight, val2);
511 0 : setStyleValue(Sid::pagePrintableWidth, val - (oddPageLeftMargin->value() + evenPageLeftMargin->value()) * f);
512 0 : }
|