1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2011 Werner Schweer
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 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENSE.GPL
11 //=============================================================================
12 
13 #include "libmscore/score.h"
14 #include "libmscore/chord.h"
15 #include "libmscore/note.h"
16 #include "libmscore/notedot.h"
17 #include "libmscore/beam.h"
18 #include "libmscore/stem.h"
19 #include "libmscore/hook.h"
20 #include "libmscore/tuplet.h"
21 #include "libmscore/staff.h"
22 #include "inspector.h"
23 #include "inspectorNote.h"
24 
25 namespace Ms {
26 
27 //---------------------------------------------------------
28 //   InspectorNote
29 //---------------------------------------------------------
30 
InspectorNote(QWidget * parent)31 InspectorNote::InspectorNote(QWidget* parent)
32    : InspectorElementBase(parent)
33       {
34       s.setupUi(addWidget());
35       c.setupUi(addWidget());
36       n.setupUi(addWidget());
37 
38       static const NoteHead::Scheme schemes[] = {
39             NoteHead::Scheme::HEAD_AUTO,
40             NoteHead::Scheme::HEAD_NORMAL,
41             NoteHead::Scheme::HEAD_PITCHNAME,
42             NoteHead::Scheme::HEAD_PITCHNAME_GERMAN,
43             NoteHead::Scheme::HEAD_SOLFEGE,
44             NoteHead::Scheme::HEAD_SOLFEGE_FIXED,
45             NoteHead::Scheme::HEAD_SHAPE_NOTE_4,
46             NoteHead::Scheme::HEAD_SHAPE_NOTE_7_AIKIN,
47             NoteHead::Scheme::HEAD_SHAPE_NOTE_7_FUNK,
48             NoteHead::Scheme::HEAD_SHAPE_NOTE_7_WALKER
49             };
50 
51       static const NoteHead::Group heads[] = {
52             NoteHead::Group::HEAD_NORMAL,
53             NoteHead::Group::HEAD_CROSS,
54             NoteHead::Group::HEAD_PLUS,
55             NoteHead::Group::HEAD_XCIRCLE,
56             NoteHead::Group::HEAD_WITHX,
57             NoteHead::Group::HEAD_TRIANGLE_UP,
58             NoteHead::Group::HEAD_TRIANGLE_DOWN,
59             NoteHead::Group::HEAD_SLASHED1,
60             NoteHead::Group::HEAD_SLASHED2,
61             NoteHead::Group::HEAD_DIAMOND,
62             NoteHead::Group::HEAD_DIAMOND_OLD,
63             NoteHead::Group::HEAD_CIRCLED,
64             NoteHead::Group::HEAD_CIRCLED_LARGE,
65             NoteHead::Group::HEAD_LARGE_ARROW,
66 
67             NoteHead::Group::HEAD_SLASH,
68             NoteHead::Group::HEAD_BREVIS_ALT,
69 
70             NoteHead::Group::HEAD_DO,
71             NoteHead::Group::HEAD_RE,
72             NoteHead::Group::HEAD_MI,
73             NoteHead::Group::HEAD_FA,
74             NoteHead::Group::HEAD_SOL,
75             NoteHead::Group::HEAD_LA,
76             NoteHead::Group::HEAD_TI
77             };
78 
79       //
80       // fix order of noteheads
81       //
82       for (auto head : heads)
83             n.noteHeadGroup->addItem(NoteHead::group2userName(head), int(head));
84 
85       for (auto scheme : schemes)
86             n.noteHeadScheme->addItem(NoteHead::scheme2userName(scheme), int(scheme));
87 
88       // noteHeadType starts at -1: correct values and count one item more (HEAD_AUTO)
89       for (int i = 0; i <= int(NoteHead::Type::HEAD_TYPES); ++i) {
90             n.noteHeadType->addItem(NoteHead::type2userName(NoteHead::Type(i - 1)));
91             n.noteHeadType->setItemData(i, i - 1);
92             }
93 
94       const std::vector<InspectorItem> iiList = {
95             { Pid::SMALL,          0, n.small,         n.resetSmall         },
96             { Pid::HEAD_SCHEME,    0, n.noteHeadScheme, n.resetNoteHeadScheme },
97             { Pid::HEAD_GROUP,     0, n.noteHeadGroup, n.resetNoteHeadGroup },
98             { Pid::HEAD_TYPE,      0, n.noteHeadType,  n.resetNoteHeadType  },
99             { Pid::MIRROR_HEAD,    0, n.mirrorHead,    n.resetMirrorHead    },
100             { Pid::PLAY,           0, n.play,          n.resetPlay          },
101             { Pid::TUNING,         0, n.tuning,        n.resetTuning        },
102             { Pid::VELO_TYPE,      0, n.velocityType,  n.resetVelocityType  },
103             { Pid::VELO_OFFSET,    0, n.velocity,      n.resetVelocity      },
104             { Pid::FIXED,          0, n.fixed,         n.resetFixed         },
105             { Pid::FIXED_LINE,     0, n.fixedLine,     n.resetFixedLine     },
106 
107             { Pid::OFFSET,         1, c.offset,        c.resetOffset        },
108             { Pid::SMALL,          1, c.small,         c.resetSmall         },
109             { Pid::NO_STEM,        1, c.stemless,      c.resetStemless      },
110             { Pid::STEM_DIRECTION, 1, c.stemDirection, c.resetStemDirection },
111 
112             { Pid::LEADING_SPACE,  2, s.leadingSpace,  s.resetLeadingSpace  },
113             };
114       const std::vector<InspectorPanel> ppList = {
115             { s.title, s.panel },
116             { c.title, c.panel },
117             { n.title, n.panel },
118             };
119       mapSignals(iiList, ppList);
120 
121       connect(n.noteHeadScheme, SIGNAL(currentIndexChanged(int)), SLOT(noteHeadSchemeChanged(int)));
122 
123       connect(n.dot1,     SIGNAL(clicked()),     SLOT(dot1Clicked()));
124       connect(n.dot2,     SIGNAL(clicked()),     SLOT(dot2Clicked()));
125       connect(n.dot3,     SIGNAL(clicked()),     SLOT(dot3Clicked()));
126       connect(n.dot4,     SIGNAL(clicked()),     SLOT(dot4Clicked()));
127       connect(n.hook,     SIGNAL(clicked()),     SLOT(hookClicked()));
128       connect(n.stem,     SIGNAL(clicked()),     SLOT(stemClicked()));
129       connect(n.beam,     SIGNAL(clicked()),     SLOT(beamClicked()));
130       connect(n.tuplet,   SIGNAL(clicked()),     SLOT(tupletClicked()));
131       }
132 
133 //---------------------------------------------------------
134 //   setElement
135 //---------------------------------------------------------
136 
setElement()137 void InspectorNote::setElement()
138       {
139       Note* note = toNote(inspector->element());
140 
141       int i = note->dots().size();
142       n.dot1->setEnabled(i > 0);
143       n.dot2->setEnabled(i > 1);
144       n.dot3->setEnabled(i > 2);
145       n.dot4->setEnabled(i > 3);
146       n.stem->setEnabled(note->chord()->stem());
147       n.hook->setEnabled(note->chord()->hook());
148       n.beam->setEnabled(note->chord()->beam());
149       n.tuplet->setEnabled(note->chord()->tuplet());
150 
151       InspectorElementBase::setElement();
152 
153       //must be placed after InspectorBase::setElement() cause the last one sets resetButton enability
154       if (note->staffType()->group() == StaffGroup::STANDARD)
155             noteHeadSchemeChanged(n.noteHeadScheme->currentIndex());
156       else {
157             n.noteHeadScheme->setEnabled(false);
158             n.resetNoteHeadScheme->setEnabled(false);
159             n.noteHeadGroup->setEnabled(false);
160             n.resetNoteHeadGroup->setEnabled(false);
161             }
162 
163       bool nograce = !note->chord()->isGrace();
164       s.leadingSpace->setEnabled(nograce);
165       s.resetLeadingSpace->setEnabled(nograce && s.leadingSpace->value());
166 
167       if (!n.fixed->isChecked())
168             n.fixedLine->setEnabled(false);
169       if (!n.play->isChecked())
170             n.playWidget->setVisible(false);
171       }
172 
173 //---------------------------------------------------------
174 //   noteHeadSchemeChanged
175 //---------------------------------------------------------
176 
noteHeadSchemeChanged(int index)177 void InspectorNote::noteHeadSchemeChanged(int index)
178       {
179       Note* note = toNote(inspector->element());
180       NoteHead::Scheme scheme = (index == 0 ? note->staffType()->noteHeadScheme() : NoteHead::Scheme(index - 1));
181       if (scheme == NoteHead::Scheme::HEAD_NORMAL) {
182             n.noteHeadGroup->setEnabled(true);
183             n.resetNoteHeadGroup->setEnabled(note->headGroup() != NoteHead::Group::HEAD_NORMAL);
184             }
185       else {
186             n.noteHeadGroup->setEnabled(false);
187             n.resetNoteHeadGroup->setEnabled(false);
188             }
189       }
190 
191 //---------------------------------------------------------
192 //   dot1Clicked
193 //---------------------------------------------------------
194 
dot1Clicked()195 void InspectorNote::dot1Clicked()
196       {
197       Note* note = toNote(inspector->element());
198       if (note == 0)
199             return;
200       if (note->dots().size() > 0) {
201             NoteDot* dot = note->dot(0);
202             dot->score()->select(dot);
203             dot->score()->update();
204             inspector->update();
205             }
206       }
207 
208 //---------------------------------------------------------
209 //   dot2Clicked
210 //---------------------------------------------------------
211 
dot2Clicked()212 void InspectorNote::dot2Clicked()
213       {
214       Note* note = toNote(inspector->element());
215       if (note == 0)
216             return;
217       if (note->dots().size() > 1) {
218             NoteDot* dot = note->dot(1);
219             dot->score()->select(dot);
220             dot->score()->update();
221             inspector->update();
222             }
223       }
224 
225 //---------------------------------------------------------
226 //   dot3Clicked
227 //---------------------------------------------------------
228 
dot3Clicked()229 void InspectorNote::dot3Clicked()
230       {
231       Note* note = toNote(inspector->element());
232       if (note == 0)
233             return;
234       if (note->dots().size() > 2) {
235             NoteDot* dot = note->dot(2);
236             dot->score()->select(dot);
237             dot->score()->update();
238             inspector->update();
239             }
240       }
241 
242 //---------------------------------------------------------
243 //   dot4Clicked
244 //---------------------------------------------------------
245 
dot4Clicked()246 void InspectorNote::dot4Clicked()
247       {
248       Note* note = toNote(inspector->element());
249       if (note == 0)
250             return;
251       if (note->dots().size() > 3) {
252             NoteDot* dot = note->dot(3);
253             dot->score()->select(dot);
254             dot->score()->update();
255             inspector->update();
256             }
257       }
258 
259 //---------------------------------------------------------
260 //   hookClicked
261 //---------------------------------------------------------
262 
hookClicked()263 void InspectorNote::hookClicked()
264       {
265       Note* note = toNote(inspector->element());
266       if (note == 0)
267             return;
268       Hook* hook = note->chord()->hook();
269       if (hook) {
270             note->score()->select(hook);
271             note->score()->update();
272             inspector->update();
273             }
274       }
275 
276 //---------------------------------------------------------
277 //   stemClicked
278 //---------------------------------------------------------
279 
stemClicked()280 void InspectorNote::stemClicked()
281       {
282       Note* note = toNote(inspector->element());
283       if (note == 0)
284             return;
285       Stem* stem = note->chord()->stem();
286       if (stem) {
287             note->score()->select(stem);
288             note->score()->update();
289             inspector->update();
290             }
291       }
292 
293 //---------------------------------------------------------
294 //   beamClicked
295 //---------------------------------------------------------
296 
beamClicked()297 void InspectorNote::beamClicked()
298       {
299       Note* note = toNote(inspector->element());
300       if (note == 0)
301             return;
302       Beam* beam = note->chord()->beam();
303       if (beam) {
304             note->score()->select(beam);
305             note->score()->update();
306             inspector->update();
307             }
308       }
309 
310 //---------------------------------------------------------
311 //   tupletClicked
312 //---------------------------------------------------------
313 
tupletClicked()314 void InspectorNote::tupletClicked()
315       {
316       Note* note = toNote(inspector->element());
317       if (note == 0)
318             return;
319       Tuplet* tuplet = note->chord()->tuplet();
320       if (tuplet) {
321             note->score()->select(tuplet);
322             note->score()->update();
323             inspector->update();
324             }
325       }
326 
327 }
328 
329