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-2012 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 #include "CutToTriggerSegmentCommand.h"
19
20 #include "base/BaseProperties.h"
21 #include "base/Clipboard.h"
22 #include "base/Composition.h"
23 #include "base/Event.h"
24 #include "base/NotationTypes.h"
25 #include "base/Segment.h"
26 #include "base/SegmentNotationHelper.h"
27 #include "base/TriggerSegment.h"
28 #include "commands/edit/EraseCommand.h"
29 #include "document/BasicCommand.h"
30 #include "gui/editors/notation/NotationProperties.h"
31 #include "gui/editors/notation/NoteStyle.h"
32 #include "gui/editors/notation/NoteStyleFactory.h"
33 #include "misc/Strings.h"
34
35 #include <QString>
36
37 namespace Rosegarden
38 {
39
40 CutToTriggerSegmentCommand::
CutToTriggerSegmentCommand(EventSelection * selection,Composition & comp,QString name,int basePitch,int baseVelocity,NoteStyleName noteStyle,bool retune,std::string timeAdjust,Mark mark)41 CutToTriggerSegmentCommand(EventSelection * selection,
42 Composition &comp,
43 QString name,
44 int basePitch,
45 int baseVelocity,
46 NoteStyleName noteStyle,
47 bool retune,
48 std::string timeAdjust,
49 Mark mark)
50 : BasicSelectionCommand(tr("Make Ornament"), *selection, true),
51 m_paster(&comp, selection, name, basePitch, baseVelocity),
52 m_selection(selection),
53 m_time(selection->getStartTime()),
54 m_duration(selection->getTotalDuration()),
55 m_noteStyle(noteStyle),
56 m_retune(retune),
57 m_timeAdjust(timeAdjust),
58 m_mark(mark)
59 {}
60
61 void
execute()62 CutToTriggerSegmentCommand::execute()
63 {
64 // Create the trigger segment rec. This has to be done first
65 // because we can't know the trigger segment id until then
66 // (really, until m_paster has executed at least once)
67 m_paster.execute();
68
69 // Now take advantage of BasicCommand facilities, so that we only
70 // have to define modifySegment.
71 BasicCommand::execute();
72 }
73 void
unexecute()74 CutToTriggerSegmentCommand::unexecute()
75 {
76 // Do this in reverse order from execute, just to be safe.
77 BasicCommand::unexecute();
78 m_paster.unexecute();
79 }
80
81 // modifySegment just deals with the effects on the segment that
82 // selection was in, the trigger segment is managed separately by
83 // m_paster.
84 void
modifySegment()85 CutToTriggerSegmentCommand::modifySegment()
86 {
87 using namespace BaseProperties;
88
89 // This is only possible the first time, before selection's
90 // contents evaporate due to the erasing. This requires that we
91 // use bruteForceRedo = true.
92 EraseCommand::eraseInSegment(m_selection);
93
94 /* Adapted from InsertTriggerNoteCommand */
95
96 const TriggerSegmentId id = m_paster.getTriggerSegmentId();
97 // Insert via a model event, so as to apply the note style.
98 // This is a subset of the work done by NoteInsertionCommand
99
100 Event *e = new Event(Note::EventType, m_time, m_duration);
101
102 // Set the properties that every tied note has.
103 // makeThisNoteViable will give these to every tied note.
104 e->set<Int>(PITCH, m_paster.getBasePitch());
105 e->set<Int>(VELOCITY, m_paster.getBaseVelocity());
106 e->set<Bool>(TRIGGER_EXPAND, true);
107
108 if (m_noteStyle != NoteStyleFactory::DefaultStyle) {
109 e->set<String>(NotationProperties::NOTE_STYLE, qstrtostr(m_noteStyle));
110 }
111
112 Segment &s(getSegment());
113 Segment::iterator i = s.insert(e);
114 SegmentNotationHelper(s).makeThisNoteViable(i);
115 s.normalizeRests(m_time, m_time + m_duration);
116
117 // Now set the properties that only the trigger note has.
118 e->set<Int>(TRIGGER_SEGMENT_ID, id);
119 e->set<Bool>(TRIGGER_SEGMENT_RETUNE, m_retune);
120 e->set<String>(TRIGGER_SEGMENT_ADJUST_TIMES, m_timeAdjust);
121
122 if (m_mark != Marks::NoMark) {
123 Marks::addMark(*e, m_mark, true);
124 }
125
126
127 // Update references to this new ornament
128 TriggerSegmentRec *rec =
129 s.getComposition()->getTriggerSegmentRec(id);
130
131 if (rec)
132 { rec->updateReferences(); }
133 }
134
135 }
136