1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rosegarden
5 A MIDI and audio sequencer and musical notation editor.
6 Copyright 2000-2021 the Rosegarden development team.
7
8 Other copyrights also apply to some parts of this work. Please
9 see the AUTHORS file and individual file headers for details.
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version. See the file
15 COPYING included with this distribution for more information.
16 */
17
18 #define RG_MODULE_STRING "[SimpleEventEditDialog]"
19
20 #include "SimpleEventEditDialog.h"
21 #include "base/BaseProperties.h"
22 #include "base/Event.h"
23 #include "base/MidiTypes.h"
24 #include "base/NotationTypes.h"
25 #include "document/RosegardenDocument.h"
26 #include "gui/editors/guitar/Chord.h"
27 #include "misc/Strings.h"
28 #include "misc/Debug.h"
29 #include "misc/ConfigGroups.h" // for LastUsedPathsConfigGroup
30 #include "PitchDialog.h"
31 #include "TimeDialog.h"
32 #include "gui/widgets/LineEdit.h"
33 #include "gui/widgets/FileDialog.h"
34 #include "sound/Midi.h"
35
36 #include <QComboBox>
37 #include <QDialog>
38 #include <QDialogButtonBox>
39 #include <QCheckBox>
40 #include <QFile>
41 #include <QGroupBox>
42 #include <QGridLayout>
43 #include <QLabel>
44 #include <QMessageBox>
45 #include <QPushButton>
46 #include <QSpinBox>
47 #include <QString>
48 #include <QWidget>
49 #include <QVBoxLayout>
50 #include <QLayout>
51 #include <QSettings>
52
53
54
55 namespace Rosegarden
56 {
57
SimpleEventEditDialog(QWidget * parent,RosegardenDocument * doc,const Event & event,bool inserting)58 SimpleEventEditDialog::SimpleEventEditDialog(QWidget *parent,
59 RosegardenDocument *doc,
60 const Event &event,
61 bool inserting) :
62 QDialog(parent),
63 m_event(event),
64 m_doc(doc),
65 m_type(event.getType()),
66 m_absoluteTime(event.getAbsoluteTime()),
67 m_duration(event.getDuration()),
68 m_modified(false)
69 {
70 setModal(true);
71 setWindowTitle(tr(inserting ?
72 tr("Insert Event").toStdString().c_str() :
73 tr("Edit Event").toStdString().c_str()));
74
75 QGridLayout *metagrid = new QGridLayout;
76 setLayout(metagrid);
77 QWidget *vbox = new QWidget(this);
78 QVBoxLayout *vboxLayout = new QVBoxLayout;
79 metagrid->addWidget(vbox, 0, 0);
80
81
82 QGroupBox *frame = new QGroupBox( tr("Event Properties"), vbox );
83 frame->setContentsMargins(5, 5, 5, 5);
84 QGridLayout *layout = new QGridLayout(frame);
85 layout->setSpacing(5);
86 vboxLayout->addWidget(frame);
87
88 layout->addWidget(new QLabel(tr("Event type:"), frame), 0, 0);
89
90 if (inserting) {
91
92 m_typeLabel = nullptr;
93
94 m_typeCombo = new QComboBox(frame);
95 layout->addWidget(m_typeCombo, 0, 1);
96
97 m_typeCombo->addItem(strtoqstr(Note::EventType));
98 m_typeCombo->addItem(strtoqstr(Controller::EventType));
99 m_typeCombo->addItem(strtoqstr(KeyPressure::EventType));
100 m_typeCombo->addItem(strtoqstr(ChannelPressure::EventType));
101 m_typeCombo->addItem(strtoqstr(ProgramChange::EventType));
102 m_typeCombo->addItem(strtoqstr(SystemExclusive::EventType));
103 m_typeCombo->addItem(strtoqstr(PitchBend::EventType));
104 m_typeCombo->addItem(strtoqstr(Indication::EventType));
105 m_typeCombo->addItem(strtoqstr(Text::EventType));
106 m_typeCombo->addItem(strtoqstr(Note::EventRestType));
107 m_typeCombo->addItem(strtoqstr(Clef::EventType));
108 m_typeCombo->addItem(strtoqstr(::Rosegarden::Key::EventType));
109 m_typeCombo->addItem(strtoqstr(Guitar::Chord::EventType));
110
111 // Connect up the combos
112 //
113 connect(m_typeCombo, SIGNAL(activated(int)),
114 SLOT(slotEventTypeChanged(int)));
115
116 } else {
117
118 m_typeCombo = nullptr;
119
120 m_typeLabel = new QLabel(frame);
121 layout->addWidget(m_typeLabel, 0, 1);
122 }
123
124 m_timeLabel = new QLabel(tr("Absolute time:"), frame);
125 layout->addWidget(m_timeLabel, 1, 0);
126 m_timeSpinBox = new QSpinBox(frame);
127 m_timeSpinBox->setMinimum(INT_MIN);
128 m_timeSpinBox->setMaximum(INT_MAX);
129 m_timeSpinBox->setSingleStep(Note(Note::Shortest).getDuration());
130 m_timeEditButton = new QPushButton(tr("edit"), frame);
131 layout->addWidget(m_timeSpinBox, 1, 1);
132 layout->addWidget(m_timeEditButton, 1, 2);
133
134 connect(m_timeSpinBox, SIGNAL(valueChanged(int)),
135 SLOT(slotAbsoluteTimeChanged(int)));
136 connect(m_timeEditButton, &QAbstractButton::released,
137 this, &SimpleEventEditDialog::slotEditAbsoluteTime);
138
139 m_durationLabel = new QLabel(tr("Duration:"), frame);
140 layout->addWidget(m_durationLabel, 2, 0);
141 m_durationSpinBox = new QSpinBox(frame);
142 m_durationSpinBox->setMinimum(0);
143 m_durationSpinBox->setMaximum(INT_MAX);
144 m_durationSpinBox->setSingleStep(Note(Note::Shortest).getDuration());
145 m_durationEditButton = new QPushButton(tr("edit"), frame);
146 layout->addWidget(m_durationSpinBox, 2, 1);
147 layout->addWidget(m_durationEditButton, 2, 2);
148
149 connect(m_durationSpinBox, SIGNAL(valueChanged(int)),
150 SLOT(slotDurationChanged(int)));
151 connect(m_durationEditButton, &QAbstractButton::released,
152 this, &SimpleEventEditDialog::slotEditDuration);
153
154 m_pitchLabel = new QLabel(tr("Pitch:"), frame);
155 layout->addWidget(m_pitchLabel, 3, 0);
156 m_pitchSpinBox = new QSpinBox(frame);
157 m_pitchEditButton = new QPushButton(tr("edit"), frame);
158 layout->addWidget(m_pitchSpinBox, 3, 1);
159 layout->addWidget(m_pitchEditButton, 3, 2);
160
161 connect(m_pitchSpinBox, SIGNAL(valueChanged(int)),
162 SLOT(slotPitchChanged(int)));
163 connect(m_pitchEditButton, &QAbstractButton::released,
164 this, &SimpleEventEditDialog::slotEditPitch);
165
166 m_pitchSpinBox->setMinimum(MidiMinValue);
167 m_pitchSpinBox->setMaximum(MidiMaxValue);
168
169 m_controllerLabel = new QLabel(tr("Controller name:"), frame);
170 m_controllerLabelValue = new QLabel(tr("<none>"), frame);
171 m_controllerLabelValue->setAlignment( Qt::AlignRight );
172
173 layout->addWidget(m_controllerLabel, 4, 0);
174 layout->addWidget(m_controllerLabelValue, 4, 1);
175
176 m_velocityLabel = new QLabel(tr("Velocity:"), frame);
177 layout->addWidget(m_velocityLabel, 5, 0);
178 m_velocitySpinBox = new QSpinBox(frame);
179 layout->addWidget(m_velocitySpinBox, 5, 1);
180
181 connect(m_velocitySpinBox, SIGNAL(valueChanged(int)),
182 SLOT(slotVelocityChanged(int)));
183
184 m_velocitySpinBox->setMinimum(MidiMinValue);
185 m_velocitySpinBox->setMaximum(MidiMaxValue);
186
187 m_metaLabel = new QLabel(tr("Meta string:"), frame);
188 layout->addWidget(m_metaLabel, 6, 0);
189 m_metaEdit = new LineEdit(frame);
190 layout->addWidget(m_metaEdit, 6, 1);
191
192 m_sysexLoadButton = new QPushButton(tr("Load data"), frame);
193 layout->addWidget(m_sysexLoadButton, 6, 2);
194 m_sysexSaveButton = new QPushButton(tr("Save data"), frame);
195 layout->addWidget(m_sysexSaveButton, 4, 2);
196
197 frame->setLayout(layout);
198
199 connect(m_metaEdit, &QLineEdit::textChanged,
200 this, &SimpleEventEditDialog::slotMetaChanged);
201 connect(m_sysexLoadButton, &QAbstractButton::released,
202 this, &SimpleEventEditDialog::slotSysexLoad);
203 connect(m_sysexSaveButton, &QAbstractButton::released,
204 this, &SimpleEventEditDialog::slotSysexSave);
205
206 m_notationGroupBox = new QGroupBox( tr("Notation Properties"), vbox );
207 m_notationGroupBox->setContentsMargins(5, 5, 5, 5);
208 layout = new QGridLayout(m_notationGroupBox);
209 layout->setSpacing(5);
210 vboxLayout->addWidget(m_notationGroupBox);
211 vbox->setLayout(vboxLayout);
212
213 m_lockNotationValues = new QCheckBox(tr("Lock to changes in performed values"), m_notationGroupBox);
214 layout->addWidget(m_lockNotationValues, 0, 0, 0- 0+1, 2-0+ 1);
215 m_lockNotationValues->setChecked(true);
216
217 connect(m_lockNotationValues, &QAbstractButton::released,
218 this, &SimpleEventEditDialog::slotLockNotationChanged);
219
220 m_notationTimeLabel = new QLabel(tr("Notation time:"), m_notationGroupBox);
221 layout->addWidget(m_notationTimeLabel, 1, 0);
222 m_notationTimeSpinBox = new QSpinBox(m_notationGroupBox);
223 m_notationTimeSpinBox->setMinimum(INT_MIN);
224 m_notationTimeSpinBox->setMaximum(INT_MAX);
225 m_notationTimeSpinBox->setSingleStep(Note(Note::Shortest).getDuration());
226 m_notationTimeEditButton = new QPushButton(tr("edit"), m_notationGroupBox);
227 layout->addWidget(m_notationTimeSpinBox, 1, 1);
228 layout->addWidget(m_notationTimeEditButton, 1, 2);
229
230 connect(m_notationTimeSpinBox, SIGNAL(valueChanged(int)),
231 SLOT(slotNotationAbsoluteTimeChanged(int)));
232 connect(m_notationTimeEditButton, &QAbstractButton::released,
233 this, &SimpleEventEditDialog::slotEditNotationAbsoluteTime);
234
235 m_notationDurationLabel = new QLabel(tr("Notation duration:"), m_notationGroupBox);
236 layout->addWidget(m_notationDurationLabel, 2, 0);
237 m_notationDurationSpinBox = new QSpinBox(m_notationGroupBox);
238 m_notationDurationSpinBox->setMinimum(0);
239 m_notationDurationSpinBox->setMaximum(INT_MAX);
240 m_notationDurationSpinBox->setSingleStep(Note(Note::Shortest).getDuration());
241 m_notationDurationEditButton = new QPushButton(tr("edit"), m_notationGroupBox);
242 layout->addWidget(m_notationDurationSpinBox, 2, 1);
243 layout->addWidget(m_notationDurationEditButton, 2, 2);
244
245 m_notationGroupBox->setLayout(layout);
246
247 connect(m_notationDurationSpinBox, SIGNAL(valueChanged(int)),
248 SLOT(slotNotationDurationChanged(int)));
249 connect(m_notationDurationEditButton, &QAbstractButton::released,
250 this, &SimpleEventEditDialog::slotEditNotationDuration);
251
252 setupForEvent();
253 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
254 metagrid->addWidget(buttonBox, 1, 0);
255 metagrid->setRowStretch(0, 10);
256 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
257 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
258 }
259
260 void
setupForEvent()261 SimpleEventEditDialog::setupForEvent()
262 {
263 using BaseProperties::PITCH;
264 using BaseProperties::VELOCITY;
265
266 if (m_typeCombo) {
267 m_typeCombo->blockSignals(true);
268 }
269 m_timeSpinBox->blockSignals(true);
270 m_notationTimeSpinBox->blockSignals(true);
271 m_durationSpinBox->blockSignals(true);
272 m_notationDurationSpinBox->blockSignals(true);
273 m_pitchSpinBox->blockSignals(true);
274 m_velocitySpinBox->blockSignals(true);
275 m_metaEdit->blockSignals(true);
276
277 m_pitchSpinBox->setMinimum(MidiMinValue);
278 m_pitchSpinBox->setMaximum(MidiMaxValue);
279
280 // Some common settings
281 //
282 m_durationLabel->setText(tr("Absolute time:"));
283 m_timeLabel->show();
284 m_timeSpinBox->show();
285 m_timeEditButton->show();
286 m_timeSpinBox->setValue(m_event.getAbsoluteTime());
287
288 m_durationLabel->setText(tr("Duration:"));
289 m_durationLabel->show();
290 m_durationSpinBox->show();
291 m_durationEditButton->show();
292 m_durationSpinBox->setValue(m_event.getDuration());
293
294 m_notationGroupBox->hide();
295
296 // satisfy an ancient feature request: if the performance and absolute
297 // durations differ or the performance and absolute start times differ, then
298 // this is a notation quantized note, and we set this checkbox off by
299 // default, because "This is ok for ordinary notes but for a
300 // notation-quantised note the note will likely already
301 // have different performance and notation durations (and
302 // probably different start times too) which makes the
303 // lock inappropriate."
304 m_lockNotationValues->setChecked(m_event.getDuration() == m_event.getNotationDuration() &&
305 m_event.getAbsoluteTime() == m_event.getNotationAbsoluteTime());
306
307 if (m_typeLabel)
308 m_typeLabel->setText(strtoqstr(m_event.getType()));
309
310 m_absoluteTime = m_event.getAbsoluteTime();
311 m_notationAbsoluteTime = m_event.getNotationAbsoluteTime();
312 m_duration = m_event.getDuration();
313 m_notationDuration = m_event.getNotationDuration();
314
315 m_sysexLoadButton->hide();
316 m_sysexSaveButton->hide();
317
318 if (m_type == Note::EventType) {
319 m_notationGroupBox->show();
320 m_notationTimeSpinBox->setValue(m_notationAbsoluteTime);
321 m_notationDurationSpinBox->setValue(m_notationDuration);
322
323 m_pitchLabel->show();
324 m_pitchLabel->setText(tr("Note pitch:"));
325 m_pitchSpinBox->show();
326 m_pitchEditButton->show();
327
328 m_controllerLabel->hide();
329 m_controllerLabelValue->hide();
330
331 m_velocityLabel->show();
332 m_velocityLabel->setText(tr("Note velocity:"));
333 m_velocitySpinBox->show();
334
335 m_metaLabel->hide();
336 m_metaEdit->hide();
337
338 try {
339 m_pitchSpinBox->setValue(m_event.get<Int>(PITCH));
340 } catch (const Event::NoData &) {
341 m_pitchSpinBox->setValue(60);
342 }
343
344 try {
345 m_velocitySpinBox->setValue(m_event.get<Int>(VELOCITY));
346 } catch (const Event::NoData &) {
347 m_velocitySpinBox->setValue(100);
348 }
349
350 if (m_typeCombo)
351 m_typeCombo->setCurrentIndex(0);
352
353 } else if (m_type == Controller::EventType) {
354
355 m_durationLabel->hide();
356 m_durationSpinBox->hide();
357 m_durationEditButton->hide();
358
359 m_pitchLabel->show();
360 m_pitchLabel->setText(tr("Controller number:"));
361 m_pitchSpinBox->show();
362 m_pitchEditButton->hide();
363
364 m_controllerLabel->show();
365 m_controllerLabelValue->show();
366 m_controllerLabel->setText(tr("Controller name:"));
367
368 m_velocityLabel->show();
369 m_velocityLabel->setText(tr("Controller value:"));
370 m_velocitySpinBox->show();
371
372 m_metaLabel->hide();
373 m_metaEdit->hide();
374
375 try {
376 m_pitchSpinBox->setValue(m_event.get<Int>
377 (Controller::NUMBER));
378 } catch (const Event::NoData &) {
379 m_pitchSpinBox->setValue(0);
380 }
381
382 try {
383 m_velocitySpinBox->setValue(m_event.get<Int>
384 (Controller::VALUE));
385 } catch (const Event::NoData &) {
386 m_velocitySpinBox->setValue(0);
387 }
388
389 if (m_typeCombo)
390 m_typeCombo->setCurrentIndex(1);
391
392 } else if (m_type == KeyPressure::EventType) {
393
394 m_durationLabel->hide();
395 m_durationSpinBox->hide();
396 m_durationEditButton->hide();
397
398 m_pitchLabel->show();
399 m_pitchLabel->setText(tr("Key pitch:"));
400 m_pitchSpinBox->show();
401 m_pitchEditButton->show();
402
403 m_controllerLabel->hide();
404 m_controllerLabelValue->hide();
405
406 m_velocityLabel->show();
407 m_velocityLabel->setText(tr("Key pressure:"));
408 m_velocitySpinBox->show();
409
410 m_metaLabel->hide();
411 m_metaEdit->hide();
412
413 try {
414 m_pitchSpinBox->setValue(m_event.get<Int>
415 (KeyPressure::PITCH));
416 } catch (const Event::NoData &) {
417 m_pitchSpinBox->setValue(0);
418 }
419
420 try {
421 m_velocitySpinBox->setValue(m_event.get<Int>
422 (KeyPressure::PRESSURE));
423 } catch (const Event::NoData &) {
424 m_velocitySpinBox->setValue(0);
425 }
426
427 if (m_typeCombo)
428 m_typeCombo->setCurrentIndex(2);
429
430 } else if (m_type == ChannelPressure::EventType) {
431
432 m_durationLabel->hide();
433 m_durationSpinBox->hide();
434 m_durationEditButton->hide();
435
436 m_pitchLabel->show();
437 m_pitchLabel->setText(tr("Channel pressure:"));
438 m_pitchSpinBox->show();
439 m_pitchEditButton->hide();
440
441 m_controllerLabel->hide();
442 m_controllerLabelValue->hide();
443
444 m_velocityLabel->hide();
445 m_velocitySpinBox->hide();
446
447 m_metaLabel->hide();
448 m_metaEdit->hide();
449
450 try {
451 m_pitchSpinBox->setValue(m_event.get<Int>
452 (ChannelPressure::PRESSURE));
453 } catch (const Event::NoData &) {
454 m_pitchSpinBox->setValue(0);
455 }
456
457 if (m_typeCombo)
458 m_typeCombo->setCurrentIndex(3);
459
460 } else if (m_type == ProgramChange::EventType) {
461
462 m_durationLabel->hide();
463 m_durationSpinBox->hide();
464 m_durationEditButton->hide();
465
466 m_pitchSpinBox->setMinimum(MidiMinValue + 1);
467 m_pitchSpinBox->setMaximum(MidiMaxValue + 1);
468
469 m_pitchLabel->show();
470 m_pitchLabel->setText(tr("Program change:"));
471 m_pitchSpinBox->show();
472 m_pitchEditButton->hide();
473
474 m_controllerLabel->hide();
475 m_controllerLabelValue->hide();
476
477 m_velocityLabel->hide();
478 m_velocitySpinBox->hide();
479
480 m_metaLabel->hide();
481 m_metaEdit->hide();
482
483 try {
484 m_pitchSpinBox->setValue(m_event.get<Int>
485 (ProgramChange::PROGRAM) + 1);
486 } catch (const Event::NoData &) {
487 m_pitchSpinBox->setValue(0);
488 }
489
490 if (m_typeCombo)
491 m_typeCombo->setCurrentIndex(4);
492
493 } else if (m_type == SystemExclusive::EventType) {
494
495 m_durationLabel->hide();
496 m_durationSpinBox->hide();
497 m_durationEditButton->hide();
498
499 m_pitchLabel->hide();
500 m_pitchSpinBox->hide();
501 m_pitchEditButton->hide();
502
503 m_controllerLabel->show();
504 m_controllerLabelValue->show();
505
506 m_velocityLabel->hide();
507 m_velocitySpinBox->hide();
508
509 m_metaLabel->show();
510 m_metaEdit->show();
511
512 m_sysexLoadButton->show();
513 m_sysexSaveButton->show();
514
515 m_controllerLabel->setText(tr("Data length:"));
516 m_metaLabel->setText(tr("Data:"));
517 try {
518 std::string datablock;
519 m_event.get<String>(SystemExclusive::DATABLOCK, datablock);
520 m_controllerLabelValue->setText(QString("%1").
521 arg(SystemExclusive::toRaw(datablock).length()));
522 m_metaEdit->setText(strtoqstr(datablock));
523 } catch (...) {
524 m_controllerLabelValue->setText("0");
525 }
526
527 if (m_typeCombo)
528 m_typeCombo->setCurrentIndex(5);
529
530 } else if (m_type == PitchBend::EventType) {
531
532 m_durationLabel->hide();
533 m_durationSpinBox->hide();
534 m_durationEditButton->hide();
535
536 m_pitchLabel->show();
537 m_pitchLabel->setText(tr("Pitchbend MSB:"));
538 m_pitchSpinBox->show();
539 m_pitchEditButton->hide();
540
541 m_controllerLabel->hide();
542 m_controllerLabelValue->hide();
543
544 m_velocityLabel->show();
545 m_velocityLabel->setText(tr("Pitchbend LSB:"));
546 m_velocitySpinBox->show();
547
548 m_metaLabel->hide();
549 m_metaEdit->hide();
550
551 try {
552 m_pitchSpinBox->setValue(m_event.get<Int>
553 (PitchBend::MSB));
554 } catch (const Event::NoData &) {
555 m_pitchSpinBox->setValue(0);
556 }
557
558 try {
559 m_velocitySpinBox->setValue(m_event.get<Int>
560 (PitchBend::LSB));
561 } catch (const Event::NoData &) {
562 m_velocitySpinBox->setValue(0);
563 }
564
565 if (m_typeCombo)
566 m_typeCombo->setCurrentIndex(6);
567
568 } else if (m_type == Indication::EventType) {
569
570 m_pitchLabel->hide();
571 m_pitchSpinBox->hide();
572 m_pitchEditButton->hide();
573
574 m_controllerLabel->hide();
575 m_controllerLabelValue->hide();
576
577 m_velocityLabel->hide();
578 m_velocitySpinBox->hide();
579
580 m_metaLabel->show();
581 m_metaEdit->show();
582 m_metaLabel->setText(tr("Indication:"));
583
584 try {
585 Indication ind(m_event);
586 m_metaEdit->setText(strtoqstr(ind.getIndicationType()));
587 m_durationSpinBox->setValue(ind.getIndicationDuration());
588 } catch (...) {
589 m_metaEdit->setText(tr("<none>"));
590 }
591
592 if (m_typeCombo)
593 m_typeCombo->setCurrentIndex(7);
594
595 } else if (m_type == Text::EventType) {
596
597 m_durationLabel->hide();
598 m_durationSpinBox->hide();
599 m_durationEditButton->hide();
600
601 m_pitchLabel->hide();
602 m_pitchSpinBox->hide();
603 m_pitchEditButton->hide();
604
605 m_controllerLabel->show();
606 m_controllerLabelValue->show();
607
608 m_velocityLabel->hide();
609 m_velocitySpinBox->hide();
610
611 m_metaLabel->show();
612 m_metaEdit->show();
613
614 m_controllerLabel->setText(tr("Text type:"));
615 m_metaLabel->setText(tr("Text:"));
616
617 // get the text event
618 try {
619 Text text(m_event);
620 m_controllerLabelValue->setText(strtoqstr(text.getTextType()));
621 m_metaEdit->setText(strtoqstr(text.getText()));
622 } catch (...) {
623 m_controllerLabelValue->setText(tr("<none>"));
624 m_metaEdit->setText(tr("<none>"));
625 }
626
627 if (m_typeCombo)
628 m_typeCombo->setCurrentIndex(8);
629
630 } else if (m_type == Note::EventRestType) {
631
632 m_pitchLabel->hide();
633 m_pitchSpinBox->hide();
634 m_pitchEditButton->hide();
635
636 m_controllerLabel->hide();
637 m_controllerLabelValue->hide();
638
639 m_velocityLabel->hide();
640 m_velocitySpinBox->hide();
641
642 m_metaLabel->hide();
643 m_metaEdit->hide();
644
645 if (m_typeCombo)
646 m_typeCombo->setCurrentIndex(9);
647
648 } else if (m_type == Clef::EventType) {
649
650 m_durationLabel->hide();
651 m_durationSpinBox->hide();
652 m_durationEditButton->hide();
653
654 m_pitchLabel->hide();
655 m_pitchSpinBox->hide();
656 m_pitchEditButton->hide();
657
658 m_controllerLabel->show();
659 m_controllerLabelValue->show();
660
661 m_controllerLabel->setText(tr("Clef type:"));
662
663 try {
664 Clef clef(m_event);
665 m_controllerLabelValue->setText(strtoqstr(clef.getClefType()));
666 } catch (...) {
667 m_controllerLabelValue->setText(tr("<none>"));
668 }
669
670 m_velocityLabel->hide();
671 m_velocitySpinBox->hide();
672
673 m_metaLabel->hide();
674 m_metaEdit->hide();
675
676 if (m_typeCombo)
677 m_typeCombo->setCurrentIndex(10);
678
679 } else if (m_type == ::Rosegarden::Key::EventType) {
680
681 m_durationLabel->hide();
682 m_durationSpinBox->hide();
683 m_durationEditButton->hide();
684
685 m_pitchLabel->hide();
686 m_pitchSpinBox->hide();
687 m_pitchEditButton->hide();
688
689 m_controllerLabel->show();
690 m_controllerLabelValue->show();
691
692 m_controllerLabel->setText(tr("Key name:"));
693
694 try {
695 ::Rosegarden::Key key(m_event);
696 m_controllerLabelValue->setText(strtoqstr(key.getName()));
697 } catch (...) {
698 m_controllerLabelValue->setText(tr("<none>"));
699 }
700
701 m_velocityLabel->hide();
702 m_velocitySpinBox->hide();
703
704 m_metaLabel->hide();
705 m_metaEdit->hide();
706
707 if (m_typeCombo)
708 m_typeCombo->setCurrentIndex(11);
709
710 } else if (m_type == Guitar::Chord::EventType) {
711
712 m_durationLabel->hide();
713 m_durationSpinBox->hide();
714 m_durationEditButton->hide();
715
716 m_pitchLabel->hide();
717 m_pitchSpinBox->hide();
718 m_pitchEditButton->hide();
719
720 m_controllerLabel->hide();
721 m_controllerLabelValue->hide();
722
723 m_velocityLabel->hide();
724 m_velocitySpinBox->hide();
725
726 m_metaLabel->hide();
727 m_metaEdit->hide();
728
729 // m_controllerLabel->setText(tr("Text type:"));
730 // m_metaLabel->setText(tr("Chord:"));
731
732 // get the fingering event
733 try {
734 Guitar::Chord chord( m_event );
735 } catch (...) {
736 // m_controllerLabelValue->setText(tr("<none>"));
737 // m_metaEdit->setText(tr("<none>"));
738 }
739
740 if (m_typeCombo)
741 m_typeCombo->setCurrentIndex(12);
742
743 } else {
744
745 m_durationLabel->setText(tr("Unsupported event type:"));
746 m_durationLabel->show();
747 m_durationSpinBox->hide();
748 m_durationEditButton->hide();
749
750 m_pitchLabel->hide();
751 m_pitchSpinBox->hide();
752 m_pitchEditButton->hide();
753
754 m_controllerLabel->hide();
755 m_controllerLabelValue->show();
756 m_controllerLabelValue->setText(strtoqstr(m_type));
757
758 m_velocityLabel->hide();
759 m_velocitySpinBox->hide();
760
761 m_metaLabel->hide();
762 m_metaEdit->hide();
763
764 if (m_typeCombo)
765 m_typeCombo->setEnabled(false);
766 }
767
768 if (m_typeCombo)
769 m_typeCombo->blockSignals(false);
770 m_timeSpinBox->blockSignals(false);
771 m_notationTimeSpinBox->blockSignals(false);
772 m_durationSpinBox->blockSignals(false);
773 m_notationDurationSpinBox->blockSignals(false);
774 m_pitchSpinBox->blockSignals(false);
775 m_velocitySpinBox->blockSignals(false);
776 m_metaEdit->blockSignals(false);
777
778 slotLockNotationChanged();
779 }
780
781 Event
getEvent()782 SimpleEventEditDialog::getEvent()
783 {
784 bool useSeparateNotationValues =
785 (m_event.getType() == Note::EventType);
786
787 if (m_typeCombo) {
788
789 int subordering = 0;
790 if (m_type == Indication::EventType) {
791 subordering = Indication::EventSubOrdering;
792 } else if (m_type == Clef::EventType) {
793 subordering = Clef::EventSubOrdering;
794 } else if (m_type == ::Rosegarden::Key::EventType) {
795 subordering = ::Rosegarden::Key::EventSubOrdering;
796 } else if (m_type == Text::EventType) {
797 subordering = Text::EventSubOrdering;
798 } else if (m_type == Note::EventRestType) {
799 subordering = Note::EventRestSubOrdering;
800 } else if (m_type == PitchBend::EventType) {
801 subordering = PitchBend::EventSubOrdering;
802 } else if (m_type == Controller::EventType) {
803 subordering = Controller::EventSubOrdering;
804 } else if (m_type == KeyPressure::EventType) {
805 subordering = KeyPressure::EventSubOrdering;
806 } else if (m_type == ChannelPressure::EventType) {
807 subordering = ChannelPressure::EventSubOrdering;
808 } else if (m_type == ProgramChange::EventType) {
809 subordering = ProgramChange::EventSubOrdering;
810 } else if (m_type == SystemExclusive::EventType) {
811 subordering = SystemExclusive::EventSubOrdering;
812 }
813
814 m_event = Event(m_type,
815 m_absoluteTime,
816 m_duration,
817 subordering,
818 (useSeparateNotationValues ?
819 m_notationAbsoluteTime : m_absoluteTime),
820 (useSeparateNotationValues ?
821 m_notationDuration : m_duration));
822
823 // ensure these are set on m_event correctly
824 slotPitchChanged(m_pitchSpinBox->value());
825 slotVelocityChanged(m_velocitySpinBox->value());
826 }
827
828 Event event(m_event,
829 m_absoluteTime,
830 m_duration,
831 m_event.getSubOrdering(),
832 (useSeparateNotationValues ?
833 m_notationAbsoluteTime : m_absoluteTime),
834 (useSeparateNotationValues ?
835 m_notationDuration : m_duration));
836
837 // Values from the pitch and velocity spin boxes should already
838 // have been set on m_event (and thus on event) by slotPitchChanged
839 // and slotVelocityChanged. Absolute time and duration were set in
840 // the event ctor above; that just leaves the meta values.
841
842 if (m_type == Indication::EventType) {
843
844 event.set<String>(Indication::IndicationTypePropertyName,
845 qstrtostr(m_metaEdit->text()));
846
847 } else if (m_type == Text::EventType) {
848
849 event.set<String>(Text::TextTypePropertyName,
850 qstrtostr(m_controllerLabelValue->text()));
851 event.set<String>(Text::TextPropertyName,
852 qstrtostr(m_metaEdit->text()));
853
854 } else if (m_type == Clef::EventType) {
855
856 event.set<String>(Clef::ClefPropertyName,
857 qstrtostr(m_controllerLabelValue->text()));
858
859 } else if (m_type == ::Rosegarden::Key::EventType) {
860
861 event.set<String>(::Rosegarden::Key::KeyPropertyName,
862 qstrtostr(m_controllerLabelValue->text()));
863
864 } else if (m_type == SystemExclusive::EventType) {
865
866 event.set<String>(SystemExclusive::DATABLOCK,
867 qstrtostr(m_metaEdit->text()));
868
869 }
870
871 return event;
872 }
873
874 void
slotEventTypeChanged(int value)875 SimpleEventEditDialog::slotEventTypeChanged(int value)
876 {
877 m_type = qstrtostr(m_typeCombo->itemText(value));
878 m_modified = true;
879
880 if (m_type != m_event.getType())
881 Event m_event(m_type, m_absoluteTime, m_duration);
882
883 setupForEvent();
884
885 // update whatever pitch and velocity correspond to
886 if (!m_pitchSpinBox->isHidden())
887 slotPitchChanged(m_pitchSpinBox->value());
888 if (!m_velocitySpinBox->isHidden())
889 slotVelocityChanged(m_velocitySpinBox->value());
890 }
891
892 void
slotAbsoluteTimeChanged(int value)893 SimpleEventEditDialog::slotAbsoluteTimeChanged(int value)
894 {
895 m_absoluteTime = value;
896
897 if (m_notationGroupBox->isHidden()) {
898 m_notationAbsoluteTime = value;
899 } else if (m_lockNotationValues->isChecked()) {
900 m_notationAbsoluteTime = value;
901 m_notationTimeSpinBox->setValue(value);
902 }
903
904 m_modified = true;
905 }
906
907 void
slotNotationAbsoluteTimeChanged(int value)908 SimpleEventEditDialog::slotNotationAbsoluteTimeChanged(int value)
909 {
910 m_notationAbsoluteTime = value;
911 m_modified = true;
912 }
913
914 void
slotDurationChanged(int value)915 SimpleEventEditDialog::slotDurationChanged(int value)
916 {
917 m_duration = value;
918
919 if (m_notationGroupBox->isHidden()) {
920 m_notationDuration = value;
921 } else if (m_lockNotationValues->isChecked()) {
922 m_notationDuration = value;
923 m_notationDurationSpinBox->setValue(value);
924 }
925
926 m_modified = true;
927 }
928
929 void
slotNotationDurationChanged(int value)930 SimpleEventEditDialog::slotNotationDurationChanged(int value)
931 {
932 m_notationDuration = value;
933 m_modified = true;
934 }
935
936 void
slotPitchChanged(int value)937 SimpleEventEditDialog::slotPitchChanged(int value)
938 {
939 m_modified = true;
940
941 if (m_type == Note::EventType) {
942 m_event.set<Int>(BaseProperties::PITCH, value);
943
944 } else if (m_type == Controller::EventType) {
945 m_event.set<Int>(Controller::NUMBER, value);
946
947 } else if (m_type == KeyPressure::EventType) {
948 m_event.set<Int>(KeyPressure::PITCH, value);
949
950 } else if (m_type == ChannelPressure::EventType) {
951 m_event.set<Int>(ChannelPressure::PRESSURE, value);
952
953 } else if (m_type == ProgramChange::EventType) {
954 if (value < 1)
955 value = 1;
956 m_event.set<Int>(ProgramChange::PROGRAM, value - 1);
957
958 } else if (m_type == PitchBend::EventType) {
959 m_event.set<Int>(PitchBend::MSB, value);
960 }
961 //!!!??? sysex?
962 }
963
964 void
slotVelocityChanged(int value)965 SimpleEventEditDialog::slotVelocityChanged(int value)
966 {
967 m_modified = true;
968
969 if (m_type == Note::EventType) {
970 m_event.set<Int>(BaseProperties::VELOCITY, value);
971
972 } else if (m_type == Controller::EventType) {
973 m_event.set<Int>(Controller::VALUE, value);
974
975 } else if (m_type == KeyPressure::EventType) {
976 m_event.set<Int>(KeyPressure::PRESSURE, value);
977
978 } else if (m_type == PitchBend::EventType) {
979 m_event.set<Int>(PitchBend::LSB, value);
980 }
981 }
982
983 void
slotMetaChanged(const QString &)984 SimpleEventEditDialog::slotMetaChanged(const QString &)
985 {
986 m_modified = true;
987 }
988
989 void
slotLockNotationChanged()990 SimpleEventEditDialog::slotLockNotationChanged()
991 {
992 bool enable = !m_lockNotationValues->isChecked();
993 m_notationTimeSpinBox->setEnabled(enable);
994 m_notationTimeEditButton->setEnabled(enable);
995 m_notationDurationSpinBox->setEnabled(enable);
996 m_notationDurationEditButton->setEnabled(enable);
997 }
998
999 void
slotEditAbsoluteTime()1000 SimpleEventEditDialog::slotEditAbsoluteTime()
1001 {
1002 TimeDialog dialog(this, tr("Edit Event Time"),
1003 &m_doc->getComposition(),
1004 m_timeSpinBox->value(),
1005 true);
1006 if (dialog.exec() == QDialog::Accepted) {
1007 m_timeSpinBox->setValue(dialog.getTime());
1008 }
1009 }
1010
1011 void
slotEditNotationAbsoluteTime()1012 SimpleEventEditDialog::slotEditNotationAbsoluteTime()
1013 {
1014 TimeDialog dialog(this, tr("Edit Event Notation Time"),
1015 &m_doc->getComposition(),
1016 m_notationTimeSpinBox->value(),
1017 true);
1018 if (dialog.exec() == QDialog::Accepted) {
1019 m_notationTimeSpinBox->setValue(dialog.getTime());
1020 }
1021 }
1022
1023 void
slotEditDuration()1024 SimpleEventEditDialog::slotEditDuration()
1025 {
1026 TimeDialog dialog(this, tr("Edit Duration"),
1027 &m_doc->getComposition(),
1028 m_timeSpinBox->value(),
1029 m_durationSpinBox->value(),
1030 1,
1031 true);
1032 if (dialog.exec() == QDialog::Accepted) {
1033 m_durationSpinBox->setValue(dialog.getTime());
1034 }
1035 }
1036
1037 void
slotEditNotationDuration()1038 SimpleEventEditDialog::slotEditNotationDuration()
1039 {
1040 TimeDialog dialog(this, tr("Edit Notation Duration"),
1041 &m_doc->getComposition(),
1042 m_notationTimeSpinBox->value(),
1043 m_notationDurationSpinBox->value(),
1044 1,
1045 true);
1046 if (dialog.exec() == QDialog::Accepted) {
1047 m_notationDurationSpinBox->setValue(dialog.getTime());
1048 }
1049 }
1050
1051 void
slotEditPitch()1052 SimpleEventEditDialog::slotEditPitch()
1053 {
1054 PitchDialog dialog(this, tr("Edit Pitch"), m_pitchSpinBox->value());
1055 if (dialog.exec() == QDialog::Accepted) {
1056 m_pitchSpinBox->setValue(dialog.getPitch());
1057 }
1058 }
1059
1060 void
slotSysexLoad()1061 SimpleEventEditDialog::slotSysexLoad()
1062 {
1063 QSettings settings;
1064 settings.beginGroup(LastUsedPathsConfigGroup);
1065 const QString pathKey = "load_sysex";
1066 QString directory = settings.value(pathKey, QDir::homePath()).toString();
1067
1068 QString name = FileDialog::getOpenFileName(
1069 this, // parent
1070 tr("Load System Exclusive data in File"), // caption
1071 directory, // dir
1072 tr("System exclusive files") + " (*.syx *.SYX)" + ";;" +
1073 tr("All files") + " (*)"); // filter
1074
1075 if (name.isNull())
1076 return ;
1077
1078 QFile file(name);
1079 file.open(QIODevice::ReadOnly);
1080 std::string s;
1081 char c;
1082
1083 // Discard leading bytes up to and including the first SysEx Start (F0).
1084 while (file.getChar(&c)) {
1085 if (c == static_cast<char>(MIDI_SYSTEM_EXCLUSIVE))
1086 break;
1087 }
1088 // Copy up to but not including SysEx End (F7).
1089 while (file.getChar(&c)) {
1090 if (c == static_cast<char>(MIDI_END_OF_EXCLUSIVE))
1091 break;
1092 s += c;
1093 }
1094
1095 file.close();
1096
1097 if (s.empty())
1098 QMessageBox::critical(this, tr("Rosegarden"), tr("Could not load SysEx file."));
1099
1100 m_metaEdit->setText(strtoqstr(SystemExclusive::toHex(s)));
1101
1102 // Write the directory to the settings
1103 QDir d = QFileInfo(name).dir();
1104 directory = d.canonicalPath();
1105 settings.setValue(pathKey, directory);
1106 settings.endGroup();
1107 }
1108
1109 void
slotSysexSave()1110 SimpleEventEditDialog::slotSysexSave()
1111 {
1112 QSettings settings;
1113 settings.beginGroup(LastUsedPathsConfigGroup);
1114 const QString pathKey = "save_sysex";
1115 QString directory = settings.value(pathKey, QDir::homePath()).toString();
1116
1117 QString name = FileDialog::getSaveFileName(
1118 this, // parent
1119 tr("Save System Exclusive data to..."), // caption
1120 directory, // dir
1121 "", // defaultName
1122 tr("System exclusive files") + " (*.syx *.SYX)" + ";;" +
1123 tr("All files") + " (*)"); // filter
1124 //tr("*.syx|System exclusive files (*.syx)")); // filter
1125 if (name.isNull())
1126 return;
1127
1128 QFile file(name);
1129 file.open(QIODevice::WriteOnly);
1130
1131 std::string datablock;
1132 m_event.get<String>(SystemExclusive::DATABLOCK, datablock);
1133 // Add SysEx and End SysEx status bytes.
1134 datablock = "F0 " + datablock + " F7";
1135 datablock = SystemExclusive::toRaw(datablock);
1136 file.write(datablock.c_str(),
1137 static_cast<qint64>(datablock.length()));
1138
1139 file.close();
1140
1141 // Write the directory to the settings
1142 QDir d = QFileInfo(name).dir();
1143 directory = d.canonicalPath();
1144 settings.setValue(pathKey, directory);
1145 settings.endGroup();
1146 }
1147
1148
1149 }
1150