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 
19 #include "ClefInsertionCommand.h"
20 
21 #include "misc/Strings.h"
22 #include "base/Event.h"
23 #include "base/NotationTypes.h"
24 #include "base/Segment.h"
25 #include "base/SegmentNotationHelper.h"
26 #include "base/BaseProperties.h"
27 #include "document/BasicCommand.h"
28 #include "base/Selection.h"
29 #include <QString>
30 
31 
32 namespace Rosegarden
33 {
34 
35 using namespace BaseProperties;
36 
ClefInsertionCommand(Segment & segment,timeT time,Clef clef,bool shouldChangeOctave,bool shouldTranspose)37 ClefInsertionCommand::ClefInsertionCommand(Segment &segment, timeT time,
38         Clef clef,
39         bool shouldChangeOctave,
40         bool shouldTranspose) :
41         BasicCommand(getThisGlobalName(&clef), segment, time,
42                      ((shouldChangeOctave || shouldTranspose) ?
43                       segment.getEndTime() : time + 1)),
44         m_clef(clef),
45         m_shouldChangeOctave(shouldChangeOctave),
46         m_shouldTranspose(shouldTranspose),
47         m_lastInsertedEvent(nullptr)
48 {
49     // nothing
50 }
51 
~ClefInsertionCommand()52 ClefInsertionCommand::~ClefInsertionCommand()
53 {
54     // nothing
55 }
56 
57 EventSelection *
getSubsequentSelection()58 ClefInsertionCommand::getSubsequentSelection()
59 {
60     EventSelection *selection = new EventSelection(getSegment());
61     selection->addEvent(getLastInsertedEvent());
62     return selection;
63 }
64 
65 QString
getThisGlobalName(Clef * clef)66 ClefInsertionCommand::getThisGlobalName(Clef *clef)
67 {
68     return getGlobalName(clef);
69 }
70 
71 QString
getGlobalName(Clef *)72 ClefInsertionCommand::getGlobalName(Clef *)
73 {
74     /* doesn't handle octave offset -- leave it for now
75         if (clef) {
76     	QString name(strtoqstr(clef->getClefType()));
77     	name = name.left(1).toUpper() + name.right(name.length()-1);
78     	return tr("Change to %1 Cle&f...").arg(name);
79         } else {
80     */
81     return tr("Add Cle&f Change...");
82     /*
83         }
84     */
85 }
86 
87 timeT
getRelayoutEndTime()88 ClefInsertionCommand::getRelayoutEndTime()
89 {
90     // Inserting a clef can change the y-coord of every subsequent note
91     return getSegment().getEndTime();
92 }
93 
94 void
modifySegment()95 ClefInsertionCommand::modifySegment()
96 {
97     SegmentNotationHelper helper(getSegment());
98     Clef oldClef(getSegment().getClefAtTime(getStartTime()));
99 
100     Segment::iterator i = getSegment().findTime(getStartTime());
101     while (getSegment().isBeforeEndMarker(i)) {
102         if ((*i)->getAbsoluteTime() > getStartTime()) {
103             break;
104         }
105         if ((*i)->isa(Clef::EventType)) {
106             getSegment().erase(i);
107             break;
108         }
109         ++i;
110     }
111 
112     i = helper.insertClef(getStartTime(), m_clef);
113     if (i != helper.segment().end())
114         m_lastInsertedEvent = *i;
115 
116     if (m_clef != oldClef) {
117 
118         int semitones = 0;
119 
120         if (m_shouldChangeOctave) {
121             semitones += 12 * (m_clef.getOctave() - oldClef.getOctave());
122         }
123         if (m_shouldTranspose) {
124             semitones -= m_clef.getPitchOffset() - oldClef.getPitchOffset();
125         }
126 
127         if (semitones != 0) {
128             while (i != helper.segment().end()) {
129                 if ((*i)->isa(Note::EventType)) {
130                     long pitch = 0;
131                     if ((*i)->get
132                             <Int>(PITCH, pitch)) {
133                         pitch += semitones;
134                         (*i)->set
135                         <Int>(PITCH, pitch);
136                     }
137                 } else if (*i != m_lastInsertedEvent && (*i)->isa(Clef::EventType)) {
138 		    // Stop changing octaves when next clef is encountered.
139 		    break;
140                 }
141                 ++i;
142             }
143         }
144     }
145 }
146 
ClefLinkInsertionCommand(Segment & segment,timeT time,Clef clef,bool shouldChangeOctave,bool shouldTranspose)147 ClefLinkInsertionCommand::ClefLinkInsertionCommand(Segment &segment,
148                                                    timeT time,
149                                                    Clef clef,
150                                                    bool shouldChangeOctave,
151                                                    bool shouldTranspose) :
152     ClefInsertionCommand(segment,time,clef,shouldChangeOctave,shouldTranspose)
153 {
154     setUpdateLinks(false);
155 };
156 
~ClefLinkInsertionCommand()157 ClefLinkInsertionCommand::~ClefLinkInsertionCommand()
158 {
159     // nothing
160 }
161 
162 QString
getThisGlobalName(Clef * clef)163 ClefLinkInsertionCommand::getThisGlobalName(Clef *clef)
164 {
165     return getGlobalName(clef);
166 }
167 
168 QString
getGlobalName(Clef *)169 ClefLinkInsertionCommand::getGlobalName(Clef */* clef */)
170 {
171     return tr("Add Cl&ef Change for linked segment...");
172 }
173 
174 void
modifySegment()175 ClefLinkInsertionCommand::modifySegment()
176 {
177     ClefInsertionCommand::modifySegment();
178     if (m_lastInsertedEvent && m_lastInsertedEvent->isa(Clef::EventType)) {
179         //add a property so this event is ignored when updating linked segs
180         m_lastInsertedEvent->set<Bool>(LINKED_SEGMENT_IGNORE_UPDATE, true);
181     }
182 }
183 
184 }
185