1 //=============================================================================
2 // MuseScore
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2008-2010 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "libmscore/score.h"
21 #include "stafftextproperties.h"
22 #include "libmscore/stafftext.h"
23 #include "libmscore/system.h"
24 #include "libmscore/staff.h"
25 #include "libmscore/segment.h"
26 #include "globals.h"
27 #include "musescore.h"
28
29 namespace Ms {
30
31
32 //---------------------------------------------------------
33 // initChannelCombo
34 //---------------------------------------------------------
35
initChannelCombo(QComboBox * cb,StaffTextBase * st)36 static void initChannelCombo(QComboBox* cb, StaffTextBase* st)
37 {
38 Part* part = st->staff()->part();
39 Fraction tick = static_cast<Segment*>(st->parent())->tick();
40 for (const Channel* a : part->instrument(tick)->channel()) {
41 QString name = a->name();
42 if (a->name().isEmpty())
43 name = Channel::DEFAULT_NAME;
44 cb->addItem(qApp->translate("InstrumentsXML", name.toUtf8().data()));
45 }
46 }
47
48 //---------------------------------------------------------
49 // StaffTextProperties
50 //---------------------------------------------------------
51
StaffTextProperties(const StaffTextBase * st,QWidget * parent)52 StaffTextProperties::StaffTextProperties(const StaffTextBase* st, QWidget* parent)
53 : QDialog(parent)
54 {
55 setObjectName("StaffTextProperties");
56 setupUi(this);
57 if (st->systemFlag()) {
58 setWindowTitle(tr("System Text Properties"));
59 tabWidget->removeTab(tabWidget->indexOf(tabAeolusStops)); // Aeolus settings for staff text only
60 //if (!enableExperimental) tabWidget->removeTab(tabWidget->indexOf(tabMIDIAction));
61 tabWidget->removeTab(tabWidget->indexOf(tabChangeChannel)); // Channel switching for staff text only
62 tabWidget->removeTab(tabWidget->indexOf(tabCapoSettings)); // Capos for staff text only
63 }
64 else {
65 setWindowTitle(tr("Staff Text Properties"));
66 //tabWidget->removeTab(tabWidget->indexOf(tabSwingSettings)); // Swing settings for system text only, could be disabled here, if desired
67 #ifndef AEOLUS
68 tabWidget->removeTab(tabWidget->indexOf(tabAeolusStops));
69 #endif
70 //if (!enableExperimental) tabWidget->removeTab(tabWidget->indexOf(tabMIDIAction));
71 }
72 setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
73 _staffText = static_cast<StaffTextBase*>(st->clone());
74
75 vb[0][0] = voice1_1;
76 vb[0][1] = voice1_2;
77 vb[0][2] = voice1_3;
78 vb[0][3] = voice1_4;
79
80 vb[1][0] = voice2_1;
81 vb[1][1] = voice2_2;
82 vb[1][2] = voice2_3;
83 vb[1][3] = voice2_4;
84
85 vb[2][0] = voice3_1;
86 vb[2][1] = voice3_2;
87 vb[2][2] = voice3_3;
88 vb[2][3] = voice3_4;
89
90 vb[3][0] = voice4_1;
91 vb[3][1] = voice4_2;
92 vb[3][2] = voice4_3;
93 vb[3][3] = voice4_4;
94
95 channelCombo[0] = channelCombo1;
96 channelCombo[1] = channelCombo2;
97 channelCombo[2] = channelCombo3;
98 channelCombo[3] = channelCombo4;
99
100 //---------------------------------------------------
101 // setup "switch channel"
102 //---------------------------------------------------
103
104 for (int i = 0; i < 4; ++i)
105 initChannelCombo(channelCombo[i], _staffText);
106
107 Part* part = _staffText->staff()->part();
108 Fraction tick = static_cast<Segment*>(st->parent())->tick();
109 int n = part->instrument(tick)->channel().size();
110 int rows = 0;
111 for (int voice = 0; voice < VOICES; ++voice) {
112 if (_staffText->channelName(voice).isEmpty())
113 continue;
114 for (int i = 0; i < n; ++i) {
115 const Channel* a = part->instrument(tick)->channel(i);
116 if (a->name() != _staffText->channelName(voice))
117 continue;
118 int row = 0;
119 for (row = 0; row < rows; ++row) {
120 if (channelCombo[row]->currentIndex() == i) {
121 vb[voice][row]->setChecked(true);
122 break;
123 }
124 }
125 if (row == rows) {
126 vb[voice][rows]->setChecked(true);
127 channelCombo[row]->setCurrentIndex(i);
128 ++rows;
129 }
130 break;
131 }
132 }
133 QSignalMapper* mapper = new QSignalMapper(this);
134 for (int row = 0; row < 4; ++row) {
135 for (int col = 0; col < 4; ++col) {
136 connect(vb[col][row], SIGNAL(clicked()), mapper, SLOT(map()));
137 mapper->setMapping(vb[col][row], (col << 8) + row);
138 }
139 }
140
141 if (_staffText->swing()) {
142 setSwingBox->setChecked(true);
143 if (_staffText->swingParameters()->swingUnit == MScore::division/2) {
144 swingBox->setEnabled(true);
145 swingEighth->setChecked(true);
146 swingBox->setValue(_staffText->swingParameters()->swingRatio);
147 }
148 else if (_staffText->swingParameters()->swingUnit == MScore::division/4) {
149 swingBox->setEnabled(true);
150 swingSixteenth->setChecked(true);
151 swingBox->setValue(_staffText->swingParameters()->swingRatio);
152 }
153 else if (_staffText->swingParameters()->swingUnit == 0) {
154 swingBox->setEnabled(false);
155 swingOff->setChecked(true);
156 swingBox->setValue(_staffText->swingParameters()->swingRatio);
157 }
158 }
159
160 connect(mapper, SIGNAL(mapped(int)), SLOT(voiceButtonClicked(int)));
161 connect(swingOff, SIGNAL(toggled(bool)), SLOT(setSwingControls(bool)));
162 connect(swingEighth, SIGNAL(toggled(bool)), SLOT(setSwingControls(bool)));
163 connect(swingSixteenth, SIGNAL(toggled(bool)), SLOT(setSwingControls(bool)));
164
165
166 //---------------------------------------------------
167 // setup capo
168 // Note that capo is stored as an int, where 0 = no change,
169 // 1 = remove capo, and everyother number (n) = pitch increase
170 // of n-1 semitones.
171 //---------------------------------------------------
172
173 if (_staffText->capo() != 0) {
174 setCapoBox->setChecked(true);
175 fretList->setCurrentIndex(_staffText->capo()-1);
176 }
177
178 //---------------------------------------------------
179 // setup midi actions
180 //---------------------------------------------------
181
182 QTreeWidgetItem* selectedItem = 0;
183 for (int i = 0; i < n; ++i) {
184 const Channel* a = part->instrument(tick)->channel(i);
185 QTreeWidgetItem* item = new QTreeWidgetItem(channelList);
186 item->setData(0, Qt::UserRole, i);
187 QString name = a->name();
188 if (a->name().isEmpty())
189 name = Channel::DEFAULT_NAME;
190 item->setText(0, qApp->translate("InstrumentsXML", name.toUtf8().data()));
191 item->setText(1, qApp->translate("InstrumentsXML", a->descr().toUtf8().data()));
192 if (i == 0)
193 selectedItem = item;
194 }
195 connect(channelList, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
196 SLOT(channelItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
197 connect(this, SIGNAL(accepted()), SLOT(saveValues()));
198 channelList->setCurrentItem(selectedItem);
199
200 //---------------------------------------------------
201 // setup aeolus stops
202 //---------------------------------------------------
203
204 changeStops->setChecked(_staffText->setAeolusStops());
205
206 for (int i = 0; i < 4; ++i) {
207 for (int k = 0; k < 16; ++k)
208 stops[i][k] = 0;
209 }
210 stops[0][0] = stop_3_0;
211 stops[0][1] = stop_3_1;
212 stops[0][2] = stop_3_2;
213 stops[0][3] = stop_3_3;
214 stops[0][4] = stop_3_4;
215 stops[0][5] = stop_3_5;
216 stops[0][6] = stop_3_6;
217 stops[0][7] = stop_3_7;
218 stops[0][8] = stop_3_8;
219 stops[0][9] = stop_3_9;
220 stops[0][10] = stop_3_10;
221 stops[0][11] = stop_3_11;
222
223 stops[1][0] = stop_2_0;
224 stops[1][1] = stop_2_1;
225 stops[1][2] = stop_2_2;
226 stops[1][3] = stop_2_3;
227 stops[1][4] = stop_2_4;
228 stops[1][5] = stop_2_5;
229 stops[1][6] = stop_2_6;
230 stops[1][7] = stop_2_7;
231 stops[1][8] = stop_2_8;
232 stops[1][9] = stop_2_9;
233 stops[1][10] = stop_2_10;
234 stops[1][11] = stop_2_11;
235 stops[1][12] = stop_2_12;
236
237 stops[2][0] = stop_1_0;
238 stops[2][1] = stop_1_1;
239 stops[2][2] = stop_1_2;
240 stops[2][3] = stop_1_3;
241 stops[2][4] = stop_1_4;
242 stops[2][5] = stop_1_5;
243 stops[2][6] = stop_1_6;
244 stops[2][7] = stop_1_7;
245 stops[2][8] = stop_1_8;
246 stops[2][9] = stop_1_9;
247 stops[2][10] = stop_1_10;
248 stops[2][11] = stop_1_11;
249 stops[2][12] = stop_1_12;
250 stops[2][13] = stop_1_13;
251 stops[2][14] = stop_1_14;
252 stops[2][15] = stop_1_15;
253
254 stops[3][0] = stop_p_0;
255 stops[3][1] = stop_p_1;
256 stops[3][2] = stop_p_2;
257 stops[3][3] = stop_p_3;
258 stops[3][4] = stop_p_4;
259 stops[3][5] = stop_p_5;
260 stops[3][6] = stop_p_6;
261 stops[3][7] = stop_p_7;
262 stops[3][8] = stop_p_8;
263 stops[3][9] = stop_p_9;
264 stops[3][10] = stop_p_10;
265 stops[3][11] = stop_p_11;
266 stops[3][12] = stop_p_12;
267 stops[3][13] = stop_p_13;
268 stops[3][14] = stop_p_14;
269 stops[3][15] = stop_p_15;
270
271 curTabIndex = tabWidget->currentIndex();
272 connect(tabWidget, SIGNAL(currentChanged(int)), SLOT(tabChanged(int)));
273
274 MuseScore::restoreGeometry(this);
275 }
276
277 //---------------------------------------------------------
278 // ~StaffTextProperties
279 //---------------------------------------------------------
280
~StaffTextProperties()281 StaffTextProperties::~StaffTextProperties()
282 {
283 delete _staffText;
284 }
285
286 //---------------------------------------------------------
287 // setSwingControls
288 //---------------------------------------------------------
289
setSwingControls(bool checked)290 void StaffTextProperties::setSwingControls(bool checked)
291 {
292 if (!checked)
293 return;
294 if (swingOff->isChecked())
295 swingBox->setEnabled(false);
296 else if (swingEighth->isChecked())
297 swingBox->setEnabled(true);
298 else if (swingSixteenth->isChecked())
299 swingBox->setEnabled(true);
300 }
301
302 //---------------------------------------------------------
303 // tabChanged
304 //---------------------------------------------------------
305
tabChanged(int tab)306 void StaffTextProperties::tabChanged(int tab)
307 {
308 if (tab == 2) {
309 for (int i = 0; i < 4; ++i) {
310 for (int k = 0; k < 16; ++k) {
311 if (stops[i][k])
312 stops[i][k]->setChecked(_staffText->getAeolusStop(i, k));
313 }
314 }
315 }
316 if (curTabIndex == 2) {
317 _staffText->setSetAeolusStops(changeStops->isChecked());
318 for (int i = 0; i < 4; ++i) {
319 for (int k = 0; k < 16; ++k) {
320 if (stops[i][k])
321 _staffText->setAeolusStop(i, k, stops[i][k]->isChecked());
322 }
323 }
324 }
325 curTabIndex = tab;
326 }
327
328 //---------------------------------------------------------
329 // voiceButtonClicked
330 //---------------------------------------------------------
331
voiceButtonClicked(int val)332 void StaffTextProperties::voiceButtonClicked(int val)
333 {
334 int ccol = val >> 8;
335 int crow = val & 0xff;
336 for (int row = 0; row < 4; ++row) {
337 if (row == crow)
338 continue;
339 vb[ccol][row]->setChecked(false);
340 }
341 }
342
343 //---------------------------------------------------------
344 // saveChannel
345 //---------------------------------------------------------
346
saveChannel(int channel)347 void StaffTextProperties::saveChannel(int channel)
348 {
349 QList<ChannelActions>* ca = _staffText->channelActions();
350 int n = ca->size();
351 for (int i = 0; i < n; ++i) {
352 ChannelActions* a = &(*ca)[i];
353 if (a->channel == channel) {
354 ca->removeAt(i);
355 break;
356 }
357 }
358
359 ChannelActions a;
360 a.channel = channel;
361
362 for (int i = 0; i < actionList->topLevelItemCount(); ++i) {
363 QTreeWidgetItem* item = actionList->topLevelItem(i);
364 if (item->isSelected())
365 a.midiActionNames.append(item->text(0));
366 }
367 ca->append(a);
368 }
369
370 //---------------------------------------------------------
371 // channelItemChanged
372 //---------------------------------------------------------
373
channelItemChanged(QTreeWidgetItem * item,QTreeWidgetItem * pitem)374 void StaffTextProperties::channelItemChanged(QTreeWidgetItem* item, QTreeWidgetItem* pitem)
375 {
376 if (pitem)
377 saveChannel(pitem->data(0, Qt::UserRole).toInt());
378 if (item == 0)
379 return;
380
381 actionList->clear();
382 Part* part = _staffText->staff()->part();
383
384 int channelIdx = item->data(0, Qt::UserRole).toInt();
385 Fraction tick = static_cast<Segment*>(_staffText->parent())->tick();
386 Channel* channel = part->instrument(tick)->channel(channelIdx);
387 QString channelName = channel->name();
388
389 for (const NamedEventList& e : part->instrument(tick)->midiActions()) {
390 QTreeWidgetItem* ti = new QTreeWidgetItem(actionList);
391 QString name = e.name;
392 if (e.name.isEmpty())
393 name = Channel::DEFAULT_NAME;
394 ti->setText(0, qApp->translate("InstrumentsXML", name.toUtf8().data()));
395 ti->setData(0, Qt::UserRole, name);
396 ti->setText(1, qApp->translate("InstrumentsXML", e.descr.toUtf8().data()));
397 }
398 for (const NamedEventList& e : channel->midiActions) {
399 QTreeWidgetItem* ti = new QTreeWidgetItem(actionList);
400 QString name = e.name;
401 if (e.name.isEmpty())
402 name = Channel::DEFAULT_NAME;
403 ti->setText(0, qApp->translate("InstrumentsXML", name.toUtf8().data()));
404 ti->setData(0, Qt::UserRole, name);
405 ti->setText(1, qApp->translate("InstrumentsXML", e.descr.toUtf8().data()));
406 }
407 for (const ChannelActions& ca : *_staffText->channelActions()) {
408 if (ca.channel == channelIdx) {
409 for (QString s : ca.midiActionNames) {
410 QList<QTreeWidgetItem*> items;
411 for (int i = 0; i < actionList->topLevelItemCount(); i++) {
412 QTreeWidgetItem* ti = actionList->topLevelItem(i);
413 if (ti->data(0, Qt::UserRole) == s) {
414 ti->setSelected(true);
415 }
416 }
417 }
418 }
419 }
420 }
421
422 //---------------------------------------------------------
423 // saveValues
424 //---------------------------------------------------------
425
saveValues()426 void StaffTextProperties::saveValues()
427 {
428 //
429 // save channel switches
430 //
431 Part* part = _staffText->staff()->part();
432 for (int voice = 0; voice < VOICES; ++voice) {
433 _staffText->setChannelName(voice, QString());
434 for (int row = 0; row < VOICES; ++row) {
435 if (vb[voice][row]->isChecked()) {
436 int idx = channelCombo[row]->currentIndex();
437 Fraction instrId = static_cast<Segment*>(_staffText->parent())->tick();
438 _staffText->setChannelName(voice, part->instrument(instrId)->channel(idx)->name());
439 break;
440 }
441 }
442 }
443
444 QTreeWidgetItem* pitem = channelList->currentItem();
445 if (pitem)
446 saveChannel(pitem->data(0, Qt::UserRole).toInt());
447
448 //
449 // save Aeolus stops
450 //
451 _staffText->setSetAeolusStops(changeStops->isChecked());
452 if (changeStops->isChecked()) {
453 for (int i = 0; i < 4; ++i) {
454 for (int k = 0; k < 16; ++k) {
455 if (stops[i][k])
456 _staffText->setAeolusStop(i, k, stops[i][k]->isChecked());
457 }
458 }
459 }
460 if (setSwingBox->isChecked()) {
461 _staffText->setSwing(true);
462 if (swingOff->isChecked()) {
463 _staffText->setSwingParameters(0, swingBox->value());
464 swingBox->setEnabled(false);
465 }
466 else if (swingEighth->isChecked()) {
467 _staffText->setSwingParameters(MScore::division/2, swingBox->value());
468 swingBox->setEnabled(true);
469 }
470 else if (swingSixteenth->isChecked()) {
471 _staffText->setSwingParameters(MScore::division/4, swingBox->value());
472 swingBox->setEnabled(true);
473 }
474 }
475
476 if (setCapoBox->isChecked())
477 _staffText->setCapo(fretList->currentIndex()+1);
478 else
479 _staffText->setCapo(0);
480 }
481
482 //---------------------------------------------------------
483 // hideEvent
484 //---------------------------------------------------------
485
hideEvent(QHideEvent * event)486 void StaffTextProperties::hideEvent(QHideEvent* event)
487 {
488 MuseScore::saveGeometry(this);
489 QWidget::hideEvent(event);
490 }
491
492 }
493
494