1 //=============================================================================
2 // MuseScore
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2010-2016 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 "drumtools.h"
21 #include "musescore.h"
22 #include "palette.h"
23 #include "libmscore/chord.h"
24 #include "libmscore/note.h"
25 #include "libmscore/drumset.h"
26 #include "libmscore/score.h"
27 #include "preferences.h"
28 #include "seq.h"
29 #include "editdrumset.h"
30 #include "libmscore/staff.h"
31 #include "libmscore/part.h"
32 #include "libmscore/stem.h"
33 #include "libmscore/mscore.h"
34 #include "libmscore/undo.h"
35
36 namespace Ms {
37
38 //---------------------------------------------------------
39 // DrumTools
40 //---------------------------------------------------------
41
DrumTools(QWidget * parent)42 DrumTools::DrumTools(QWidget* parent)
43 : QDockWidget(parent)
44 {
45 drumset = 0;
46 _score = 0;
47 setObjectName("drum-tools");
48 setAllowedAreas(Qt::DockWidgetAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea));
49
50 QWidget* w = new QWidget(this);
51 w->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
52 w->setMaximumHeight(100 * Palette::guiMag());
53 QHBoxLayout* layout = new QHBoxLayout;
54 w->setLayout(layout);
55
56 QVBoxLayout* layout1 = new QVBoxLayout;
57 layout1->setSpacing(6);
58 pitchName = new QLabel;
59 pitchName->setAlignment(Qt::AlignCenter);
60 pitchName->setWordWrap(true);
61 pitchName->setContentsMargins(25, 0, 25, 0);
62 layout1->addWidget(pitchName);
63
64 QHBoxLayout* buttonLayout = new QHBoxLayout;
65 buttonLayout->setContentsMargins(5, 5, 5, 5);
66 editButton = new QToolButton;
67 editButton->setMinimumWidth(175);
68 editButton->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
69 buttonLayout->addWidget(editButton);
70 layout1->addLayout(buttonLayout);
71 layout->addLayout(layout1);
72
73 drumPalette = new Palette;
74 drumPalette->setMag(0.8);
75 drumPalette->setSelectable(true);
76 drumPalette->setUseDoubleClickToActivate(true);
77 drumPalette->setGrid(28, 60);
78 PaletteScrollArea* sa = new PaletteScrollArea(drumPalette);
79 sa->setFocusPolicy(Qt::NoFocus);
80 layout->addWidget(sa);
81
82 setWidget(w);
83
84 w = new QWidget(this);
85 setTitleBarWidget(w);
86 titleBarWidget()->hide();
87 connect(editButton, SIGNAL(clicked()), SLOT(editDrumset()));
88 void boxClicked(int);
89 connect(drumPalette, SIGNAL(boxClicked(int)), SLOT(drumNoteSelected(int)));
90 retranslate();
91 drumPalette->setContextMenuPolicy(Qt::PreventContextMenu);
92 }
93
94 //---------------------------------------------------------
95 // updateDrumset
96 //---------------------------------------------------------
97
retranslate()98 void DrumTools::retranslate()
99 {
100 setWindowTitle(tr("Drumset Tools"));
101 editButton->setText(tr("Edit Drumset"));
102 drumPalette->setName(tr("Drumset"));
103 }
104
105 //---------------------------------------------------------
106 // updateDrumset
107 //---------------------------------------------------------
108
updateDrumset(const Drumset * ds)109 void DrumTools::updateDrumset(const Drumset* ds)
110 {
111 drumPalette->clear();
112 drumset = ds;
113 if (!drumset)
114 return;
115 double _spatium = gscore->spatium();
116 for (int pitch = 0; pitch < 128; ++pitch) {
117 if (!drumset->isValid(pitch))
118 continue;
119 bool up;
120 int line = drumset->line(pitch);
121 NoteHead::Group noteHead = drumset->noteHead(pitch);
122 int voice = drumset->voice(pitch);
123 Direction dir = drumset->stemDirection(pitch);
124 if (dir == Direction::UP)
125 up = true;
126 else if (dir == Direction::DOWN)
127 up = false;
128 else
129 up = line > 4;
130
131 Chord* chord = new Chord(gscore);
132 chord->setDurationType(TDuration::DurationType::V_QUARTER);
133 chord->setStemDirection(dir);
134 chord->setUp(up);
135 chord->setTrack(voice);
136 Stem* stem = new Stem(gscore);
137 stem->setLen((up ? -3.0 : 3.0) * _spatium);
138 chord->add(stem);
139 Note* note = new Note(gscore);
140 note->setMark(true);
141 note->setParent(chord);
142 note->setTrack(voice);
143 note->setPitch(pitch);
144 note->setTpcFromPitch();
145 note->setLine(line);
146 note->setPos(0.0, _spatium * .5 * line);
147 note->setHeadGroup(noteHead);
148 SymId noteheadSym = SymId::noteheadBlack;
149 if (noteHead == NoteHead::Group::HEAD_CUSTOM)
150 noteheadSym = drumset->noteHeads(pitch, NoteHead::Type::HEAD_QUARTER);
151 else
152 noteheadSym = note->noteHead(true, noteHead, NoteHead::Type::HEAD_QUARTER);
153
154 note->setCachedNoteheadSym(noteheadSym); // we use the cached notehead so we don't recompute it at each layout
155 chord->add(note);
156 int sc = drumset->shortcut(pitch);
157 QString shortcut;
158 if (sc)
159 shortcut = QChar(sc);
160 drumPalette->append(chord, qApp->translate("drumset", drumset->name(pitch).toUtf8().data()), shortcut);
161 }
162 }
163
164 //---------------------------------------------------------
165 // setDrumset
166 //---------------------------------------------------------
167
setDrumset(Score * s,Staff * st,const Drumset * ds)168 void DrumTools::setDrumset(Score* s, Staff* st, const Drumset* ds)
169 {
170 if (s == _score && staff == st && drumset == ds)
171 return;
172 _score = s;
173 staff = st;
174 //drumset = ds;
175 updateDrumset(ds);
176 }
177
178 //---------------------------------------------------------
179 // editDrumset
180 //---------------------------------------------------------
181
editDrumset()182 void DrumTools::editDrumset()
183 {
184 EditDrumset eds(drumset, this);
185 if (eds.exec()) {
186 ChordRest* cr = _score->getSelectedChordRest();
187 Fraction tick = cr ? cr->tick() : Fraction(0,1);
188 _score->startCmd();
189 _score->undo(new ChangeDrumset(staff->part()->instrument(tick), eds.drumset()));
190 mscore->updateDrumTools(eds.drumset());
191 if (_score->undoStack()->active()) {
192 _score->setLayoutAll();
193 _score->endCmd();
194 }
195 }
196 }
197
198 //---------------------------------------------------------
199 // drumNoteSelected
200 //---------------------------------------------------------
201
drumNoteSelected(int val)202 void DrumTools::drumNoteSelected(int val)
203 {
204 Element* element = drumPalette->element(val);
205 if (element && element->type() == ElementType::CHORD) {
206 Chord* ch = static_cast<Chord*>(element);
207 Note* note = ch->downNote();
208 int ticks = MScore::defaultPlayDuration;
209 int pitch = note->pitch();
210 seq->startNote(staff->part()->instrument()->channel(0)->channel(), pitch, 80, ticks, 0.0); //tick?
211
212 int track = (_score->inputState().track() / VOICES) * VOICES + element->track();
213 _score->inputState().setTrack(track);
214 _score->inputState().setDrumNote(pitch);
215
216 getAction("voice-1")->setChecked(element->voice() == 0);
217 getAction("voice-2")->setChecked(element->voice() == 1);
218 getAction("voice-3")->setChecked(element->voice() == 2);
219 getAction("voice-4")->setChecked(element->voice() == 3);
220
221 auto pitchCell = drumPalette->cellAt(val);
222 pitchName->setText(pitchCell->name);
223 }
224 }
225
selectedDrumNote()226 int DrumTools::selectedDrumNote()
227 {
228 int idx = drumPalette->getSelectedIdx();
229 if (idx < 0)
230 return -1;
231 Element* element = drumPalette->element(idx);
232 if (element && element->type() == ElementType::CHORD) {
233 Chord* ch = static_cast<Chord*>(element);
234 Note* note = ch->downNote();
235 auto pitchCell = drumPalette->cellAt(idx);
236 pitchName->setText(pitchCell->name);
237 return note->pitch();
238 }
239 else {
240 return -1;
241 }
242 }
243
changeEvent(QEvent * event)244 void DrumTools::changeEvent(QEvent *event)
245 {
246 QDockWidget::changeEvent(event);
247 if (event->type() == QEvent::LanguageChange)
248 retranslate();
249 }
250 }
251
252