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 <QDir>
24 : #include <QTimer>
25 : #include <QVBoxLayout>
26 : #include <limits>
27 :
28 : #include "timedialog.h"
29 :
30 : #include "translation.h"
31 :
32 : #include "palettewidget.h"
33 : #include "internal/palettecreator.h"
34 :
35 : #include "engraving/dom/dummyparent.h"
36 : #include "engraving/dom/factory.h"
37 : #include "engraving/dom/masterscore.h"
38 : #include "engraving/dom/timesig.h"
39 :
40 : using namespace mu::palette;
41 : using namespace mu::engraving;
42 :
43 0 : TimeEditor::TimeEditor(QWidget* parent)
44 0 : : QWidget(parent), muse::Contextable(muse::iocCtxForQWidget(this))
45 : {
46 0 : setupUi(this);
47 0 : }
48 :
49 0 : void TimeEditor::classBegin()
50 : {
51 0 : groups->classBegin();
52 :
53 0 : QLayout* l = new QVBoxLayout();
54 0 : l->setContentsMargins(0, 0, 0, 0);
55 0 : frame->setLayout(l);
56 :
57 0 : sp = new PaletteWidget(this, true /*setIocContext*/);
58 0 : sp->setPalette(PaletteCreator(iocContext()).newTimePalette());
59 0 : sp->setReadOnly(false);
60 0 : sp->setSelectable(true);
61 :
62 0 : ElementPtr el = sp->elementForCellAt(2);
63 :
64 0 : engravingRender()->layoutItem(el.get());
65 :
66 0 : connect(zNominal, &QSpinBox::editingFinished, this, &TimeEditor::zChanged);
67 0 : connect(nNominal, &QComboBox::currentIndexChanged, this, &TimeEditor::nChanged);
68 0 : connect(sp, &PaletteWidget::boxClicked, this, &TimeEditor::paletteChanged);
69 0 : connect(sp, &PaletteWidget::changed, this, &TimeEditor::setDirty);
70 0 : connect(addButton, &QPushButton::clicked, this, &TimeEditor::addClicked);
71 0 : connect(zText, &QLineEdit::textChanged, this, &TimeEditor::textChanged);
72 0 : connect(nText, &QLineEdit::textChanged, this, &TimeEditor::textChanged);
73 :
74 0 : _timePalette = new PaletteScrollArea(sp);
75 0 : QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
76 0 : _timePalette->setSizePolicy(policy);
77 0 : _timePalette->setRestrictHeight(false);
78 :
79 0 : l->addWidget(_timePalette);
80 :
81 0 : _dirty = false;
82 :
83 0 : if (configuration()->useFactorySettings() || !sp->readFromFile(configuration()->timeSignaturesDirPath().toQString())) {
84 0 : Fraction sig(4, 4);
85 0 : groups->setSig(sig, Groups::endings(sig), zText->text(), nText->text());
86 : }
87 0 : for (int i = 0; i < sp->actualCellCount(); ++i) { // cells can be changed
88 0 : sp->setCellReadOnly(i, false);
89 : }
90 :
91 0 : sp->setSelected(2);
92 0 : paletteChanged(2);
93 :
94 : //! NOTE: It is necessary for the correct start of navigation in the dialog
95 0 : setFocus();
96 0 : }
97 :
98 0 : bool TimeEditor::dirty() const
99 : {
100 0 : return _dirty;
101 : }
102 :
103 0 : bool TimeEditor::showTimePalette() const
104 : {
105 0 : return _timePalette->isVisible();
106 : }
107 :
108 : //---------------------------------------------------------
109 : // addClicked
110 : //---------------------------------------------------------
111 :
112 0 : void TimeEditor::addClicked()
113 : {
114 0 : auto ts = mu::engraving::Factory::makeTimeSig(paletteScoreProvider()->paletteScore()->dummy());
115 0 : ts->setSig(Fraction(zNominal->value(), denominator()));
116 0 : ts->setGroups(groups->groups());
117 :
118 : // check for special text
119 0 : if ((QString("%1").arg(zNominal->value()) != zText->text())
120 0 : || (QString("%1").arg(denominator()) != nText->text())) {
121 0 : ts->setNumeratorString(zText->text());
122 0 : ts->setDenominatorString(nText->text());
123 : }
124 : // extend palette:
125 0 : sp->appendElement(ts, "");
126 0 : sp->setSelected(sp->actualCellCount() - 1);
127 0 : _dirty = true;
128 :
129 0 : paletteProvider()->addCustomItemRequested().send(ts);
130 0 : }
131 :
132 : //---------------------------------------------------------
133 : // showTimePalette
134 : //---------------------------------------------------------
135 :
136 0 : void TimeEditor::setShowTimePalette(bool val)
137 : {
138 0 : _timePalette->setVisible(val);
139 0 : }
140 :
141 : //---------------------------------------------------------
142 : // save
143 : //---------------------------------------------------------
144 :
145 0 : void TimeEditor::save()
146 : {
147 0 : QDir dir;
148 0 : dir.mkpath(configuration()->timeSignaturesDirPath().toQString());
149 0 : sp->writeToFile(configuration()->timeSignaturesDirPath().toQString());
150 0 : }
151 :
152 : //---------------------------------------------------------
153 : // zChanged
154 : //---------------------------------------------------------
155 :
156 0 : void TimeEditor::zChanged()
157 : {
158 0 : int numerator = zNominal->value();
159 0 : int denominator = this->denominator();
160 :
161 0 : Fraction sig(numerator, denominator);
162 :
163 : // Update beam groups view
164 0 : groups->setSig(sig, Groups::endings(sig), zText->text(), nText->text());
165 0 : }
166 :
167 : //---------------------------------------------------------
168 : // nChanged
169 : //---------------------------------------------------------
170 :
171 0 : void TimeEditor::nChanged(int val)
172 : {
173 : Q_UNUSED(val);
174 0 : Fraction sig(zNominal->value(), denominator());
175 0 : groups->setSig(sig, Groups::endings(sig), zText->text(), nText->text());
176 0 : }
177 :
178 : //---------------------------------------------------------
179 : // denominator2Idx
180 : //---------------------------------------------------------
181 :
182 0 : int TimeEditor::denominator2Idx(int denominator) const
183 : {
184 0 : int val = 4;
185 0 : switch (denominator) {
186 0 : case 1: val = 0;
187 0 : break;
188 0 : case 2: val = 1;
189 0 : break;
190 0 : case 4: val = 2;
191 0 : break;
192 0 : case 8: val = 3;
193 0 : break;
194 0 : case 16: val = 4;
195 0 : break;
196 0 : case 32: val = 5;
197 0 : break;
198 0 : case 64: val = 6;
199 0 : break;
200 0 : case 128: val = 7;
201 0 : break;
202 : }
203 0 : return val;
204 : }
205 :
206 : //---------------------------------------------------------
207 : // denominator
208 : //---------------------------------------------------------
209 :
210 0 : int TimeEditor::denominator() const
211 : {
212 0 : int val = 4;
213 0 : switch (nNominal->currentIndex()) {
214 0 : case 0: val = 1;
215 0 : break;
216 0 : case 1: val = 2;
217 0 : break;
218 0 : case 2: val = 4;
219 0 : break;
220 0 : case 3: val = 8;
221 0 : break;
222 0 : case 4: val = 16;
223 0 : break;
224 0 : case 5: val = 32;
225 0 : break;
226 0 : case 6: val = 64;
227 0 : break;
228 0 : case 7: val = 128;
229 0 : break;
230 : }
231 0 : return val;
232 : }
233 :
234 : //---------------------------------------------------------
235 : // paletteChanged
236 : //---------------------------------------------------------
237 :
238 0 : void TimeEditor::paletteChanged(int idx)
239 : {
240 0 : ElementPtr element = sp->elementForCellAt(idx);
241 0 : const std::shared_ptr<TimeSig> timeSig = std::dynamic_pointer_cast<TimeSig>(element);
242 :
243 0 : if (!timeSig || !timeSig->isTimeSig()) {
244 0 : zNominal->setEnabled(false);
245 0 : nNominal->setEnabled(false);
246 0 : zText->setEnabled(false);
247 0 : nText->setEnabled(false);
248 0 : groups->setEnabled(false);
249 0 : addButton->setEnabled(false);
250 0 : return;
251 : }
252 :
253 0 : zNominal->setEnabled(true);
254 0 : nNominal->setEnabled(true);
255 0 : zText->setEnabled(true);
256 0 : nText->setEnabled(true);
257 0 : groups->setEnabled(true);
258 0 : addButton->setEnabled(true);
259 :
260 0 : Fraction sig(timeSig->sig());
261 0 : Groups g = timeSig->groups();
262 0 : if (g.empty()) {
263 0 : g = Groups::endings(sig);
264 : }
265 :
266 0 : zNominal->setValue(sig.numerator());
267 0 : nNominal->setCurrentIndex(denominator2Idx(sig.denominator()));
268 0 : zText->setText(timeSig->numeratorString());
269 0 : nText->setText(timeSig->denominatorString());
270 0 : groups->setSig(sig, g, zText->text(), nText->text());
271 0 : }
272 :
273 : //---------------------------------------------------------
274 : // textChanged
275 : //---------------------------------------------------------
276 :
277 0 : void TimeEditor::textChanged()
278 : {
279 0 : Fraction sig(zNominal->value(), denominator());
280 0 : groups->setSig(sig, Groups::endings(sig), zText->text(), nText->text());
281 0 : }
282 :
283 0 : void TimeEditor::setDirty()
284 : {
285 0 : _dirty = true;
286 0 : }
287 :
288 0 : TimeEditorDialog::TimeEditorDialog(QWidget* parent)
289 0 : : muse::ui::WidgetDialog(parent)
290 : {
291 0 : setWindowTitle(muse::qtrc("palette", "Time signatures"));
292 0 : setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
293 0 : }
294 :
295 0 : void TimeEditorDialog::classBegin()
296 : {
297 0 : m_timeEditor = new TimeEditor(this);
298 0 : m_timeEditor->classBegin();
299 :
300 0 : this->resize(m_timeEditor->size());
301 :
302 0 : QVBoxLayout* layout = new QVBoxLayout(this);
303 0 : layout->setContentsMargins(0, 0, 0, 0);
304 0 : layout->addWidget(m_timeEditor);
305 0 : }
306 :
307 0 : bool TimeEditorDialog::showTimePalette() const
308 : {
309 0 : return m_timeEditor->showTimePalette();
310 : }
311 :
312 0 : void TimeEditorDialog::setShowTimePalette(bool showTimePalette)
313 : {
314 0 : m_timeEditor->setShowTimePalette(showTimePalette);
315 0 : }
|