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 "PasteToTriggerSegmentCommand.h" 20 21 #include "base/Event.h" 22 #include "misc/Strings.h" 23 #include "misc/Debug.h" 24 #include "base/Clipboard.h" 25 #include "base/Composition.h" 26 #include "base/NotationTypes.h" 27 #include "base/Segment.h" 28 #include "base/TriggerSegment.h" 29 #include <QString> 30 31 32 namespace Rosegarden 33 { 34 35 /** PasteToTriggerSegmentCommand itself **/ 36 37 /** 38 PasteToTriggerSegmentCommand delegates essentially all of its work 39 to PasteToTriggerSegmentWorker so that its code can be shared with Q_DECLARE_TR_FUNCTIONS(Rosegarden::ChangeStyleCommand)40 CutToTriggerSegmentCommand, which can't be neatly derived from 41 PasteToTriggerSegmentCommand. 42 */ 43 44 PasteToTriggerSegmentCommand:: 45 PasteToTriggerSegmentCommand(Composition *composition, 46 Clipboard *clipboard, 47 QString label, 48 int basePitch, 49 int baseVelocity) : 50 NamedCommand(tr("Paste as New Triggered Segment")), 51 m_worker(composition, new Clipboard(*clipboard), 52 label, basePitch, baseVelocity) 53 { 54 // nothing else 55 } 56 57 PasteToTriggerSegmentCommand:: 58 ~PasteToTriggerSegmentCommand() 59 {} 60 61 void 62 PasteToTriggerSegmentCommand::execute() 63 { m_worker.execute(); } 64 65 void 66 PasteToTriggerSegmentCommand::unexecute() 67 { m_worker.unexecute(); } 68 69 /** PasteToTriggerSegmentWorker **/ 70 71 72 PasteToTriggerSegmentWorker::PasteToTriggerSegmentWorker(Composition *composition, 73 Clipboard *clipboard, 74 QString label, 75 int basePitch, 76 int baseVelocity) : 77 m_composition(composition), 78 m_clipboard(clipboard ? clipboard : new Clipboard), 79 m_label(label), 80 m_basePitch(basePitch), 81 m_baseVelocity(baseVelocity), 82 m_segment(nullptr), 83 m_detached(false) 84 { 85 // nothing else 86 } 87 88 PasteToTriggerSegmentWorker:: 89 PasteToTriggerSegmentWorker(Composition *composition, 90 const EventSelection * selection, 91 QString label, 92 int basePitch, 93 int baseVelocity) : 94 m_composition(composition), 95 m_clipboard(new Clipboard), 96 m_label(label), 97 m_basePitch(basePitch), 98 m_baseVelocity(baseVelocity), 99 m_segment(nullptr), 100 m_detached(false) 101 { 102 m_clipboard->newSegment(selection); 103 } 104 105 PasteToTriggerSegmentWorker::~PasteToTriggerSegmentWorker() 106 { 107 if (m_detached) 108 delete m_segment; 109 delete m_clipboard; 110 } 111 112 void 113 PasteToTriggerSegmentWorker::execute() 114 { 115 RG_DEBUG << "PasteToTriggerSegmentWorker::execute()"; 116 117 if (m_segment) { 118 // Not the first time executing. 119 120 RG_DEBUG << " - m_segment == TRUE"; 121 122 m_composition->addTriggerSegment(m_segment, m_id, m_basePitch, m_baseVelocity); 123 124 } else { 125 // The first time executing, so get values for m_segment, 126 // m_id. 127 128 RG_DEBUG << " - m_segment == FALSE"; 129 130 if (m_clipboard->isEmpty()) { 131 RG_DEBUG << " - Here's your problem. The clipboard is empty."; 132 return ; 133 } 134 135 m_segment = new Segment(); 136 137 RG_DEBUG << " - making a new m_segment"; 138 139 timeT earliestStartTime = 0; 140 timeT latestEndTime = 0; 141 142 for (Clipboard::iterator i = m_clipboard->begin(); 143 i != m_clipboard->end(); ++i) { 144 145 if (i == m_clipboard->begin() || 146 (*i)->getStartTime() < earliestStartTime) { 147 earliestStartTime = (*i)->getStartTime(); 148 } 149 150 if ((*i)->getEndMarkerTime() > latestEndTime) 151 latestEndTime = (*i)->getEndMarkerTime(); 152 } 153 154 for (Clipboard::iterator i = m_clipboard->begin(); 155 i != m_clipboard->end(); ++i) { 156 157 for (Segment::iterator si = (*i)->begin(); 158 (*i)->isBeforeEndMarker(si); ++si) { 159 if (!(*si)->isa(Note::EventRestType)) { 160 m_segment->insert 161 (new Event(**si, 162 (*si)->getAbsoluteTime() - earliestStartTime)); 163 } 164 } 165 } 166 167 if (m_label == "" && m_clipboard->isSingleSegment()) { 168 m_segment->setLabel(m_clipboard->getSingleSegment()->getLabel()); 169 } 170 else { 171 m_segment->setLabel(qstrtostr(m_label)); 172 } 173 174 TriggerSegmentRec *rec = 175 m_composition->addTriggerSegment(m_segment, m_basePitch, m_baseVelocity); 176 if (rec) 177 m_id = rec->getId(); 178 } 179 180 m_composition->getTriggerSegmentRec(m_id)->updateReferences(); 181 182 m_detached = false; 183 } 184 185 void 186 PasteToTriggerSegmentWorker::unexecute() 187 { 188 if (m_segment) 189 m_composition->detachTriggerSegment(m_id); 190 m_detached = true; 191 } 192 193 } 194