1 //=============================================================================
2 //  MuseScore
3 //  Linux Music Score Editor
4 //
5 //  Copyright (C) 2002-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 "editstaff.h"
21 
22 #include "editdrumset.h"
23 #include "editpitch.h"
24 #include "editstafftype.h"
25 #include "editstringdata.h"
26 #include "icons.h"
27 #include "libmscore/instrtemplate.h"
28 #include "libmscore/measure.h"
29 #include "libmscore/part.h"
30 #include "libmscore/score.h"
31 #include "libmscore/staff.h"
32 #include "libmscore/stringdata.h"
33 #include "libmscore/text.h"
34 #include "libmscore/undo.h"
35 #include "libmscore/utils.h"
36 #include "musescore.h"
37 #include "seq.h"
38 #include "selinstrument.h"
39 
40 namespace Ms {
41 
42 //---------------------------------------------------------
43 //   EditStaff
44 //---------------------------------------------------------
45 
EditStaff(Staff * s,const Fraction & tick,QWidget * parent)46 EditStaff::EditStaff(Staff* s, const Fraction& tick, QWidget* parent)
47    : QDialog(parent)
48       {
49       setObjectName("EditStaff");
50       setupUi(this);
51       setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
52       setModal(true);
53 
54       staff = nullptr;
55       setStaff(s, tick);
56 
57       MuseScore::restoreGeometry(this);
58 
59       connect(buttonBox,            SIGNAL(clicked(QAbstractButton*)), SLOT(bboxClicked(QAbstractButton*)));
60       connect(changeInstrument,     SIGNAL(clicked()),            SLOT(showInstrumentDialog()));
61       connect(changeStaffType,      SIGNAL(clicked()),            SLOT(showStaffTypeDialog()));
62       connect(minPitchASelect,      SIGNAL(clicked()),            SLOT(minPitchAClicked()));
63       connect(maxPitchASelect,      SIGNAL(clicked()),            SLOT(maxPitchAClicked()));
64       connect(minPitchPSelect,      SIGNAL(clicked()),            SLOT(minPitchPClicked()));
65       connect(maxPitchPSelect,      SIGNAL(clicked()),            SLOT(maxPitchPClicked()));
66       connect(editStringData,       SIGNAL(clicked()),            SLOT(editStringDataClicked()));
67       connect(lines,                SIGNAL(valueChanged(int)),    SLOT(numOfLinesChanged()));
68       connect(lineDistance,         SIGNAL(valueChanged(double)), SLOT(lineDistanceChanged()));
69       connect(showClef,             SIGNAL(clicked()),            SLOT(showClefChanged()));
70       connect(showTimesig,          SIGNAL(clicked()),            SLOT(showTimeSigChanged()));
71       connect(showBarlines,         SIGNAL(clicked()),            SLOT(showBarlinesChanged()));
72       connect(invisible,            SIGNAL(clicked()),            SLOT(invisibleChanged()));
73       connect(nextButton,           SIGNAL(clicked()),            SLOT(gotoNextStaff()));
74       connect(previousButton,       SIGNAL(clicked()),            SLOT(gotoPreviousStaff()));
75 
76       connect(iList,                SIGNAL(currentIndexChanged(int)),  SLOT(transpositionChanged()));
77 
78       nextButton->setIcon(*icons[int(Icons::arrowDown_ICON)]);
79       previousButton->setIcon(*icons[int(Icons::arrowUp_ICON)]);
80       minPitchASelect->setIcon(*icons[int(Icons::edit_ICON)]);
81       maxPitchASelect->setIcon(*icons[int(Icons::edit_ICON)]);
82       minPitchPSelect->setIcon(*icons[int(Icons::edit_ICON)]);
83       maxPitchPSelect->setIcon(*icons[int(Icons::edit_ICON)]);
84 
85       addAction(getAction("help"));  // why is this needed?
86       }
87 
88 //---------------------------------------------------------
89 //   setStaff
90 //---------------------------------------------------------
91 
setStaff(Staff * s,const Fraction & tick)92 void EditStaff::setStaff(Staff* s, const Fraction& tick)
93       {
94       if (staff != nullptr)
95             delete staff;
96 
97       orgStaff = s;
98       Part* part        = orgStaff->part();
99       instrument        = *part->instrument(tick);
100       Score* score      = part->score();
101       staff             = new Staff(score);
102       StaffType* stt = staff->setStaffType(Fraction(0,1), *orgStaff->staffType(Fraction(0,1)));
103       stt->setSmall(orgStaff->staffType(Fraction(0,1))->small());
104       stt->setInvisible(orgStaff->staffType(Fraction(0,1))->invisible());
105       staff->setUserDist(orgStaff->userDist());
106       stt->setColor(orgStaff->staffType(Fraction(0,1))->color());
107       staff->setPart(part);
108       staff->setCutaway(orgStaff->cutaway());
109       staff->setHideWhenEmpty(orgStaff->hideWhenEmpty());
110       staff->setShowIfEmpty(orgStaff->showIfEmpty());
111       stt->setUserMag(orgStaff->staffType(Fraction(0,1))->userMag());
112       staff->setHideSystemBarLine(orgStaff->hideSystemBarLine());
113       staff->setMergeMatchingRests(orgStaff->mergeMatchingRests());
114 
115       // get tick range for instrument
116       auto i = part->instruments()->upper_bound(tick.ticks());
117       if (i == part->instruments()->end())
118             _tickEnd = Fraction(-1,1);
119       else
120             _tickEnd = Fraction::fromTicks(i->first);
121       --i;
122       if (i == part->instruments()->begin())
123             _tickStart = Fraction(-1, 1);
124       else
125             _tickStart = Fraction::fromTicks(i->first);
126 
127       // set dlg controls
128       spinExtraDistance->setValue(s->userDist() / score->spatium());
129       invisible->setChecked(staff->invisible(Fraction(0,1)));
130       small->setChecked(stt->small());
131       color->setColor(stt->color());
132       partName->setText(part->partName());
133       cutaway->setChecked(staff->cutaway());
134       hideMode->setCurrentIndex(int(staff->hideWhenEmpty()));
135       showIfEmpty->setChecked(staff->showIfEmpty());
136       hideSystemBarLine->setChecked(staff->hideSystemBarLine());
137       mergeMatchingRests->setChecked(staff->mergeMatchingRests());
138       mag->setValue(stt->userMag() * 100.0);
139       updateStaffType();
140       updateInstrument();
141       updateNextPreviousButtons();
142       }
143 
144 //---------------------------------------------------------
145 //   hideEvent
146 //---------------------------------------------------------
147 
hideEvent(QHideEvent * ev)148 void EditStaff::hideEvent(QHideEvent* ev)
149       {
150       MuseScore::saveGeometry(this);
151       QWidget::hideEvent(ev);
152       }
153 
154 //---------------------------------------------------------
155 //   updateStaffType
156 //---------------------------------------------------------
157 
updateStaffType()158 void EditStaff::updateStaffType()
159       {
160       const StaffType* staffType = staff->staffType(Fraction(0,1));
161       lines->setValue(staffType->lines());
162       lineDistance->setValue(staffType->lineDistance().val());
163       showClef->setChecked(staffType->genClef());
164       showTimesig->setChecked(staffType->genTimesig());
165       showBarlines->setChecked(staffType->showBarlines());
166       invisible->setChecked(staffType->invisible());
167       staffGroupName->setText(qApp->translate("Staff type group name", staffType->groupName()));
168       }
169 
170 //---------------------------------------------------------
171 //   updateInstrument
172 //---------------------------------------------------------
173 
updateInstrument()174 void EditStaff::updateInstrument()
175       {
176       updateInterval(instrument.transpose());
177 
178       QList<StaffName>& snl = instrument.shortNames();
179       QString df = snl.isEmpty() ? "" : snl[0].name();
180       shortName->setPlainText(df);
181 
182       QList<StaffName>& lnl = instrument.longNames();
183       df = lnl.isEmpty() ? "" : lnl[0].name();
184 
185       longName->setPlainText(df);
186 
187       if (partName->text() == instrumentName->text())    // Updates part name if no custom name has been set before
188             partName->setText(instrument.trackName());
189 
190       instrumentName->setText(instrument.trackName());
191 
192       _minPitchA = instrument.minPitchA();
193       _maxPitchA = instrument.maxPitchA();
194       _minPitchP = instrument.minPitchP();
195       _maxPitchP = instrument.maxPitchP();
196       minPitchA->setText(midiCodeToStr(_minPitchA));
197       maxPitchA->setText(midiCodeToStr(_maxPitchA));
198       minPitchP->setText(midiCodeToStr(_minPitchP));
199       maxPitchP->setText(midiCodeToStr(_maxPitchP));
200       singleNoteDynamics->setChecked(instrument.singleNoteDynamics());
201 
202       // only show string data controls if instrument has strings
203       int numStr = instrument.stringData() ? instrument.stringData()->strings() : 0;
204       stringDataFrame->setVisible(numStr > 0);
205       numOfStrings->setText(QString::number(numStr));
206 
207       // show transp_PreferSharpFlat if instrument isn't non-transposing or octave-transposing
208       bool showPreferSharpFlat = (iList->currentIndex() != 0) && (iList->currentIndex() != 25);
209       transp_PreferSharpFlat->setVisible(showPreferSharpFlat);
210       preferSharpFlat->setCurrentIndex(int(orgStaff->part()->preferSharpFlat()));
211       }
212 
213 //---------------------------------------------------------
214 //   updateInterval
215 //---------------------------------------------------------
216 
updateInterval(const Interval & iv)217 void EditStaff::updateInterval(const Interval& iv)
218       {
219       int diatonic  = iv.diatonic;
220       int chromatic = iv.chromatic;
221 
222       int oct = chromatic / 12;
223       if (oct < 0)
224             oct = -oct;
225 
226       bool upFlag = true;
227       if (chromatic < 0 || diatonic < 0) {
228             upFlag    = false;
229             chromatic = -chromatic;
230             diatonic  = -diatonic;
231             }
232       chromatic %= 12;
233       diatonic  %= 7;
234 
235       int interval = searchInterval(diatonic, chromatic);
236       if (interval == -1) {
237             qDebug("EditStaff: unknown interval %d %d", diatonic, chromatic);
238             interval = 0;
239             }
240       iList->setCurrentIndex(interval);
241       up->setChecked(upFlag);
242       down->setChecked(!upFlag);
243       octave->setValue(oct);
244       }
245 
246 //---------------------------------------------------------
247 //   updateNextPreviousButtons
248 //---------------------------------------------------------
249 
updateNextPreviousButtons()250 void EditStaff::updateNextPreviousButtons()
251       {
252       int staffIdx = orgStaff->idx();
253 
254       nextButton->setEnabled(staffIdx < (orgStaff->score()->nstaves() - 1));
255       previousButton->setEnabled(staffIdx != 0);
256       }
257 
258 //---------------------------------------------------------
259 //   gotoNextStaff
260 //---------------------------------------------------------
261 
gotoNextStaff()262 void EditStaff::gotoNextStaff()
263       {
264       Staff* nextStaff = orgStaff->score()->staff(orgStaff->idx() + 1);
265       if (nextStaff)
266             {
267             setStaff(nextStaff, _tickStart);
268             }
269       }
270 
271 //---------------------------------------------------------
272 //   gotoPreviousStaff
273 //---------------------------------------------------------
274 
gotoPreviousStaff()275 void EditStaff::gotoPreviousStaff()
276       {
277       Staff* prevStaff = orgStaff->score()->staff(orgStaff->idx() - 1);
278       if (prevStaff)
279             {
280             setStaff(prevStaff, _tickStart);
281             }
282       }
283 
284 //---------------------------------------------------------
285 //   bboxClicked
286 //---------------------------------------------------------
287 
bboxClicked(QAbstractButton * button)288 void EditStaff::bboxClicked(QAbstractButton* button)
289       {
290       QDialogButtonBox::ButtonRole br = buttonBox->buttonRole(button);
291       switch(br) {
292             case QDialogButtonBox::ApplyRole:
293                   apply();
294                   break;
295 
296             case QDialogButtonBox::AcceptRole:
297                   apply();
298                   // fall through
299 
300             case QDialogButtonBox::RejectRole:
301                   close();
302                   if (staff != nullptr)
303                         delete staff;
304                   break;
305 
306             default:
307                   qDebug("EditStaff: unknown button %d", int(br));
308                   break;
309             }
310       }
311 
312 //---------------------------------------------------------
313 //   apply
314 //---------------------------------------------------------
315 
apply()316 void EditStaff::apply()
317       {
318       Score* score  = orgStaff->score();
319       Part* part    = orgStaff->part();
320 
321       QString sn = shortName->toPlainText();
322       QString ln = longName->toPlainText();
323       if (!Text::validateText(sn) || !Text::validateText(ln)) {
324             QMessageBox msgBox;
325             msgBox.setText(tr("The instrument name is invalid."));
326             msgBox.exec();
327             return;
328             }
329       shortName->setPlainText(sn);  // show the fixed text
330       longName->setPlainText(ln);
331 
332       int intervalIdx = iList->currentIndex();
333       bool upFlag     = up->isChecked();
334 
335       Interval interval  = intervalList[intervalIdx];
336       interval.diatonic  += octave->value() * 7;
337       interval.chromatic += octave->value() * 12;
338 
339       if (!upFlag)
340             interval.flip();
341       instrument.setTranspose(interval);
342 
343       bool preferSharpFlatChanged = (part->preferSharpFlat() != PreferSharpFlat(preferSharpFlat->currentIndex()));
344       // instrument becomes non/octave-transposing, preferSharpFlat isn't useful anymore
345       if ((iList->currentIndex() == 0) || (iList->currentIndex() == 25))
346             part->undoChangeProperty(Pid::PREFER_SHARP_FLAT, int(PreferSharpFlat::DEFAULT));
347       else
348             part->undoChangeProperty(Pid::PREFER_SHARP_FLAT, int(PreferSharpFlat(preferSharpFlat->currentIndex())));
349 
350       instrument.setMinPitchA(_minPitchA);
351       instrument.setMaxPitchA(_maxPitchA);
352       instrument.setMinPitchP(_minPitchP);
353       instrument.setMaxPitchP(_maxPitchP);
354 
355       instrument.setShortName(sn);
356       instrument.setLongName(ln);
357 
358       instrument.setSingleNoteDynamics(singleNoteDynamics->isChecked());
359 
360       bool inv       = invisible->isChecked();
361       ClefTypeList clefType = orgStaff->defaultClefType();
362       qreal userDist = spinExtraDistance->value();
363       bool ifEmpty   = showIfEmpty->isChecked();
364       bool hideSystemBL = hideSystemBarLine->isChecked();
365       bool mergeRests = mergeMatchingRests->isChecked();
366       bool cutAway      = cutaway->isChecked();
367       Staff::HideMode hideEmpty = Staff::HideMode(hideMode->currentIndex());
368 
369       QString newPartName = partName->text().simplified();
370 
371       bool instrumentFieldChanged = !(instrument == *part->instrument(_tickStart));
372       if (instrumentFieldChanged && _tickStart == Fraction(-1, 1))
373             clefType = instrument.clefType(orgStaff->rstaff());
374 
375       Interval v1 = instrument.transpose();
376       Interval v2 = part->instrument(_tickStart)->transpose();
377 
378       if (instrumentFieldChanged || part->partName() != newPartName) {
379             // instrument has changed
380 
381             if (_tickStart == Fraction(-1, 1)) {
382                   // change instrument and part name globally
383                   score->undo(new ChangePart(part, new Instrument(instrument), newPartName));
384                   }
385             else {
386                   // change part name globally, instrument locally if possible
387                   if (part->partName() != newPartName)
388                         score->undo(new ChangePart(part, new Instrument(*part->instrument()), newPartName));  //tick?
389                   if (instrumentFieldChanged) {
390                         Segment* s = score->tick2segment(_tickStart, true, SegmentType::ChordRest);
391                         const std::vector<Element*> elist = s ? s->findAnnotations(ElementType::INSTRUMENT_CHANGE, part->startTrack(), part->endTrack()) : std::vector<Element*>();
392                         if (elist.size())
393                               for (Element* e : elist) // Change instrument in all Instrument Changes (for linked staves)
394                                     score->undo(new ChangeInstrument(toInstrumentChange(e), new Instrument(instrument)));
395                         else
396                               score->undo(new ChangePart(part, new Instrument(instrument), newPartName));
397                         }
398                   }
399             emit instrumentChanged();
400 
401             if (v1 != v2)
402                   score->transpositionChanged(part, v2, _tickStart, _tickEnd);
403             }
404 
405       if (preferSharpFlatChanged)
406             score->transpositionChanged(part, v2, _tickStart, _tickEnd);
407 
408       orgStaff->undoChangeProperty(Pid::MAG, mag->value() / 100.0);
409       orgStaff->undoChangeProperty(Pid::STAFF_COLOR, color->color());
410       orgStaff->undoChangeProperty(Pid::SMALL, small->isChecked());
411 
412       if (inv != orgStaff->invisible(Fraction(0,1))
413          || clefType != orgStaff->defaultClefType()
414          || userDist != orgStaff->userDist()
415          || cutAway != orgStaff->cutaway()
416          || hideEmpty != orgStaff->hideWhenEmpty()
417          || ifEmpty != orgStaff->showIfEmpty()
418          || hideSystemBL != orgStaff->hideSystemBarLine()
419          || mergeRests != orgStaff->mergeMatchingRests()
420          ) {
421             score->undo(new ChangeStaff(orgStaff, inv, clefType, userDist * score->spatium(), hideEmpty, ifEmpty, cutAway, hideSystemBL, mergeRests));
422             }
423 
424       if ( !(*orgStaff->staffType(Fraction(0,1)) == *staff->staffType(Fraction(0,1))) ) {
425             // updateNeeded |= (orgStaff->staffGroup() == StaffGroup::TAB || staff->staffGroup() == StaffGroup::TAB);
426             score->undo(new ChangeStaffType(orgStaff, *staff->staffType(Fraction(0,1))));
427             }
428 
429       score->update();
430       score->masterScore()->updateChannel();
431       staff->score()->masterScore()->rebuildAndUpdateExpressive(MuseScore::synthesizer("Fluid"));
432       }
433 
434 //---------------------------------------------------------
435 //   Slots
436 //---------------------------------------------------------
437 
minPitchAClicked()438 void EditStaff::minPitchAClicked()
439       {
440       int         newCode;
441       EditPitch ep(this, instrument.minPitchA());
442       ep.setWindowModality(Qt::WindowModal);
443       if ( (newCode = ep.exec()) != -1) {
444             minPitchA->setText(midiCodeToStr(newCode));
445             _minPitchA = newCode;
446             }
447       }
448 
maxPitchAClicked()449 void EditStaff::maxPitchAClicked()
450       {
451       int         newCode;
452       EditPitch ep(this, instrument.maxPitchA());
453       ep.setWindowModality(Qt::WindowModal);
454       if ( (newCode = ep.exec()) != -1) {
455             maxPitchA->setText(midiCodeToStr(newCode));
456             _maxPitchA = newCode;
457             }
458       }
459 
minPitchPClicked()460 void EditStaff::minPitchPClicked()
461       {
462       int         newCode;
463       EditPitch ep(this, instrument.minPitchP());
464       ep.setWindowModality(Qt::WindowModal);
465       if ( (newCode = ep.exec()) != -1) {
466             minPitchP->setText(midiCodeToStr(newCode));
467             _minPitchP = newCode;
468             }
469       }
470 
maxPitchPClicked()471 void EditStaff::maxPitchPClicked()
472       {
473       int         newCode;
474       EditPitch ep(this, instrument.maxPitchP());
475       ep.setWindowModality(Qt::WindowModal);
476       if ( (newCode = ep.exec()) != -1) {
477             maxPitchP->setText(midiCodeToStr(newCode));
478             _maxPitchP = newCode;
479             }
480       }
481 
lineDistanceChanged()482 void EditStaff::lineDistanceChanged()
483       {
484       staff->staffType(Fraction(0,1))->setLineDistance(Spatium(lineDistance->value()));
485       }
486 
numOfLinesChanged()487 void EditStaff::numOfLinesChanged()
488       {
489       staff->staffType(Fraction(0,1))->setLines(lines->value());
490       }
491 
showClefChanged()492 void EditStaff::showClefChanged()
493       {
494       staff->staffType(Fraction(0,1))->setGenClef(showClef->checkState() == Qt::Checked);
495       }
496 
showTimeSigChanged()497 void EditStaff::showTimeSigChanged()
498       {
499       staff->staffType(Fraction(0,1))->setGenTimesig(showTimesig->checkState() == Qt::Checked);
500       }
501 
showBarlinesChanged()502 void EditStaff::showBarlinesChanged()
503       {
504       staff->staffType(Fraction(0,1))->setShowBarlines(showBarlines->checkState() == Qt::Checked);
505       }
506 
invisibleChanged()507 void EditStaff::invisibleChanged()
508       {
509       staff->staffType(Fraction(0,1))->setInvisible(invisible->checkState() == Qt::Checked);
510       }
511 
transpositionChanged()512 void EditStaff::transpositionChanged()
513       {
514       // non-transposing or octave-transposing instrument
515       // don't show transp_preferSharpFlat
516       if ((iList->currentIndex() == 0) || (iList->currentIndex() == 25))
517             transp_PreferSharpFlat->setVisible(false);
518       else
519             transp_PreferSharpFlat->setVisible(true);
520       }
521 
522 //---------------------------------------------------------
523 //   showInstrumentDialog
524 //---------------------------------------------------------
525 
showInstrumentDialog()526 void EditStaff::showInstrumentDialog()
527       {
528       SelectInstrument si(&instrument, this);
529       si.setWindowModality(Qt::WindowModal);
530       if (si.exec()) {
531             instrument = Instrument::fromTemplate(si.instrTemplate());
532             const StaffType* staffType = si.instrTemplate()->staffTypePreset;
533             if (!staffType)
534                   staffType = StaffType::getDefaultPreset(StaffGroup::STANDARD);
535             staff->setStaffType(Fraction(0,1), *staffType);
536             updateStaffType();
537             updateInstrument();
538             }
539       }
540 
541 //---------------------------------------------------------
542 //   editStringDataClicked
543 //---------------------------------------------------------
544 
editStringDataClicked()545 void EditStaff::editStringDataClicked()
546       {
547       int                     frets = instrument.stringData()->frets();
548       QList<instrString>      stringList = instrument.stringData()->stringList();
549 
550       EditStringData* esd = new EditStringData(this, &stringList, &frets);
551       esd->setWindowModality(Qt::WindowModal);
552       if (esd->exec()) {
553             StringData stringData(frets, stringList);
554 
555             // update instrument pitch ranges as necessary
556             if (stringList.size() > 0) {
557                   // get new string range bottom and top
558                   // as we have to choose an int size, INT16 are surely beyond midi pitch limits
559                   int oldHighestStringPitch     = INT16_MIN;
560                   int highestStringPitch        = INT16_MIN;
561                   int lowestStringPitch         = INT16_MAX;
562                   for (const instrString& str : stringList) {
563                         if (str.pitch > highestStringPitch) highestStringPitch = str.pitch;
564                         if (str.pitch < lowestStringPitch)  lowestStringPitch  = str.pitch;
565                         }
566                   // get old string range bottom
567                   for (const instrString& str : instrument.stringData()->stringList())
568                         if (str.pitch > oldHighestStringPitch) oldHighestStringPitch = str.pitch;
569                   // if there were no string, arbitrarely set old top to maxPitchA
570                   if (oldHighestStringPitch == INT16_MIN)
571                         oldHighestStringPitch = instrument.maxPitchA();
572 
573                   // range bottom is surely the pitch of the lowest string
574                   instrument.setMinPitchA(lowestStringPitch);
575                   instrument.setMinPitchP(lowestStringPitch);
576                   // range top should keep the same interval with the highest string it has now
577                   instrument.setMaxPitchA(instrument.maxPitchA() + highestStringPitch - oldHighestStringPitch);
578                   instrument.setMaxPitchP(instrument.maxPitchP() + highestStringPitch - oldHighestStringPitch);
579                   // update dlg controls
580                   minPitchA->setText(midiCodeToStr(instrument.minPitchA()));
581                   maxPitchA->setText(midiCodeToStr(instrument.maxPitchA()));
582                   minPitchP->setText(midiCodeToStr(instrument.minPitchP()));
583                   maxPitchP->setText(midiCodeToStr(instrument.maxPitchP()));
584                   // if no longer there is any string, leave everything as it is now
585                   }
586 
587             // update instrument data and dlg controls
588             instrument.setStringData(stringData);
589             numOfStrings->setText(QString::number(stringData.strings()));
590             }
591       }
592 
593 //---------------------------------------------------------
594 //   midiCodeToStr
595 //    Converts a MIDI numeric pitch code to human-readable note name
596 //---------------------------------------------------------
597 
598 static const char* g_cNoteName[] = {
599       QT_TRANSLATE_NOOP("editstaff", "C"),
600       QT_TRANSLATE_NOOP("editstaff", "C♯"),
601       QT_TRANSLATE_NOOP("editstaff", "D"),
602       QT_TRANSLATE_NOOP("editstaff", "E♭"),
603       QT_TRANSLATE_NOOP("editstaff", "E"),
604       QT_TRANSLATE_NOOP("editstaff", "F"),
605       QT_TRANSLATE_NOOP("editstaff", "F♯"),
606       QT_TRANSLATE_NOOP("editstaff", "G"),
607       QT_TRANSLATE_NOOP("editstaff", "A♭"),
608       QT_TRANSLATE_NOOP("editstaff", "A"),
609       QT_TRANSLATE_NOOP("editstaff", "B♭"),
610       QT_TRANSLATE_NOOP("editstaff", "B")
611       };
612 
midiCodeToStr(int midiCode)613 QString EditStaff::midiCodeToStr(int midiCode)
614       {
615       return QString("%1 %2").arg(qApp->translate("editstaff", g_cNoteName[midiCode % 12])).arg(midiCode / 12 - 1);
616       }
617 
618 //---------------------------------------------------------
619 //   showStaffTypeDialog
620 //---------------------------------------------------------
621 
showStaffTypeDialog()622 void EditStaff::showStaffTypeDialog()
623       {
624       EditStaffType editor(this, staff);
625       editor.setWindowModality(Qt::WindowModal);
626       if (editor.exec()) {
627             staff->setStaffType(Fraction(0,1), *editor.getStaffType());
628             updateStaffType();
629             }
630       }
631 }
632 
633