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