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