From c5e6fd0f6dfbf18847b601668ba8c657d776da31 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Wed, 28 Aug 2013 00:49:49 +0200 Subject: operations are now replicated for all clones. minor cleanups. it compiles and seems to work again! :) --- muse2/muse/arranger/pcanvas.cpp | 13 +++------ muse2/muse/part.h | 3 +- muse2/muse/remote/pyapi.cpp | 4 +-- muse2/muse/song.cpp | 13 +++------ muse2/muse/song.h | 8 ++++-- muse2/muse/songfile.cpp | 4 +-- muse2/muse/undo.cpp | 58 +++++++++++++++++++++++++++++++------- muse2/muse/waveedit/wavecanvas.cpp | 1 - 8 files changed, 67 insertions(+), 37 deletions(-) diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index c3c3bcb8..a280d58b 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -353,7 +353,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& ntrack = tracks->size(); if (MusEGlobal::debugMsg) printf("PartCanvas::moveItem - add new track\n"); - dtrack = MusEGlobal::song->addTrack(operations, type); // Add at end of list. + dtrack = MusEGlobal::song->addTrack(type); // Add at end of list. Creates additional Undo entry. if (type == MusECore::Track::WAVE) { MusECore::WaveTrack* st = (MusECore::WaveTrack*) track; @@ -385,8 +385,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& MusECore::Part* dpart; bool clone = (t == MOVE_CLONE || (t == MOVE_COPY && spart->hasClones())); - // This increments aref count if cloned, and chains clones. - // It also gives the new part a new serial number. + // Gives the new part a new serial number. if (clone) dpart = spart->createNewClone(); else @@ -2756,13 +2755,9 @@ void PartCanvas::viewDropEvent(QDropEvent* event) if (!track) { // we need to create a track for this drop if (text.endsWith(".mpt", Qt::CaseInsensitive)) { - MusECore::Undo operations; - track = MusEGlobal::song->addTrack(operations, MusECore::Track::MIDI); // Add at end of list. - MusEGlobal::song->applyOperationGroup(operations); + track = MusEGlobal::song->addTrack(MusECore::Track::MIDI); // Add at end of list. } else { - MusECore::Undo operations; - track = MusEGlobal::song->addTrack(operations, MusECore::Track::WAVE); // Add at end of list. - MusEGlobal::song->applyOperationGroup(operations); + track = MusEGlobal::song->addTrack(MusECore::Track::WAVE); // Add at end of list. } } if (track->type() == MusECore::Track::WAVE && diff --git a/muse2/muse/part.h b/muse2/muse/part.h index e579e64d..02056a2d 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -109,8 +109,9 @@ class Part : public PosLen { bool isCloneOf(const Part*) const; bool hasClones() const { return _prevClone!=this || _nextClone!=this; } int nClones() const; - Part* prevClone() const { return _prevClone; } // FINDMICHJETZT DELETETHIS 2x + Part* prevClone() const { return _prevClone; } // FINDMICHJETZT make it const Part*! Part* nextClone() const { return _nextClone; } + Part* backupClone() const { return _backupClone; } void unchainClone(); void chainClone(Part* p); // *this is made a sibling of p! p is not touched (except for its clone-chain), whereas this->events will get altered diff --git a/muse2/muse/remote/pyapi.cpp b/muse2/muse/remote/pyapi.cpp index 7d03e36b..8f5abe06 100644 --- a/muse2/muse/remote/pyapi.cpp +++ b/muse2/muse/remote/pyapi.cpp @@ -1131,9 +1131,7 @@ bool Song::event(QEvent* _e) break; } case QPybridgeEvent::SONG_ADD_TRACK: { - MusECore::Undo operations; - MusEGlobal::song->addTrack(operations, (Track::TrackType)e->getP1()); // Add at end of list. - MusEGlobal::song->applyOperationGroup(operations); + MusEGlobal::song->addTrack((Track::TrackType)e->getP1()); // Add at end of list. break; } case QPybridgeEvent::SONG_CHANGE_TRACKNAME: { diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index b6d866e1..3cf1960d 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -216,9 +216,7 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt) if((Track::TrackType)n >= Track::AUDIO_SOFTSYNTH) return 0; - Undo operations; - Track* t = addTrack(operations, (Track::TrackType)n, insertAt); - applyOperationGroup(operations); + Track* t = addTrack((Track::TrackType)n, insertAt); if (t->isVisible()) { deselectTracks(); t->setSelected(true); @@ -236,7 +234,7 @@ Track* Song::addNewTrack(QAction* action, Track* insertAt) // If insertAt is valid, inserts before insertAt. Else at the end after all tracks. //--------------------------------------------------------- -Track* Song::addTrack(Undo& /*operations*/, Track::TrackType type, Track* insertAt) +Track* Song::addTrack(Track::TrackType type, Track* insertAt) { Track* track = 0; int lastAuxIdx = _auxs.size(); @@ -293,12 +291,9 @@ Track* Song::addTrack(Undo& /*operations*/, Track::TrackType type, Track* insert int idx = insertAt ? _tracks.index(insertAt) : -1; - insertTrack1(track, idx); // this and the below are replaced - msgInsertTrack(track, idx, true); // by the UndoOp-operation - insertTrack3(track, idx); // does nothing - // No, can't do this. insertTrack2 needs to be called now, not later, otherwise it sees + // Apply it *now*. insertTrack2 needs to be called now, not later, otherwise it sees // that the track may have routes, and reciprocates them, causing duplicate routes. - ///operations.push_back(UndoOp(UndoOp::AddTrack, idx, track)); + applyOperation(UndoOp(UndoOp::AddTrack, idx, track)); // Add default track <-> midiport routes. if(track->isMidiTrack()) diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 6410084f..bc1aa9a1 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -171,7 +171,11 @@ class Song : public QObject { Song(const char* name = 0); ~Song(); - bool applyOperationGroup(Undo& group, bool doUndo=true); // group may be changed! cleanOperationGroup is called on group! + /** It is not allowed nor checked(!) to AddPart a clone, and + * to AddEvent/DeleteEvent/ModifyEvent/SelectEvent events which + * would need to be replicated to the newly added clone part! + */ + bool applyOperationGroup(Undo& group, bool doUndo=true); // group may be changed! prepareOperationGroup is called on group! bool applyOperation(const UndoOp& op, bool doUndo=true); /** this sends emits a signal to each MidiEditor or whoever is interested. @@ -424,7 +428,7 @@ class Song : public QObject { void setQuantize(bool val); void panic(); void seqSignal(int fd); - Track* addTrack(Undo& operations, Track::TrackType type, Track* insertAt = 0); + Track* addTrack(Track::TrackType type, Track* insertAt = 0); Track* addNewTrack(QAction* action, Track* insertAt = 0); void duplicateTracks(); QString getScriptPath(int id, bool delivered); diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp index 9b52791a..680e4dcd 100644 --- a/muse2/muse/songfile.cpp +++ b/muse2/muse/songfile.cpp @@ -197,7 +197,7 @@ Part* Part::readFromXml(Xml& xml, Track* track, bool doClone, bool toTrack) { if(i->id == id) // Is a matching part found in the clone list? { - // This makes a clone, chains the part, and increases ref counts. + // Create a clone. It must still be added later in a operationgroup npart = track->newPart((Part*)i->cp, true); break; } @@ -242,7 +242,7 @@ Part* Part::readFromXml(Xml& xml, Track* track, bool doClone, bool toTrack) if(!doClone && !isclone) break; - // This makes a clone, chains the part, and increases ref counts. + // Create a clone. It must still be added later in a operationgroup npart = track->newPart((Part*)i->cp, true); break; } diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index b5ee3cec..fdb24dad 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -274,12 +274,10 @@ void Song::setUndoRedoText() } -void cleanOperationGroup(Undo& group) +void prepareOperationGroup(Undo& group) { - using std::set; - - set processed_tracks; - set processed_parts; + QSet deleted_tracks; + QSet deleted_parts; for (iUndoOp op=group.begin(); op!=group.end();) { @@ -288,21 +286,61 @@ void cleanOperationGroup(Undo& group) if (op->type==UndoOp::DeleteTrack) { - if (processed_tracks.find(op->track)!=processed_tracks.end()) + if (deleted_tracks.contains(op->track)) + { group.erase(op); + } else - processed_tracks.insert(op->track); + { + const PartList* pl = op->track->cparts(); + for (ciPart part = pl->begin(); part != pl->end(); part++) + if (!deleted_parts.contains(part->second)) + { + // they will be inserted between op and op_ + // because we set op=op_ below, the inserted + // elements will be skipped. + group.insert(op, UndoOp(UndoOp::DeletePart, part->second)); + deleted_parts.insert(part->second); + } + + deleted_tracks.insert(op->track); + } } else if (op->type==UndoOp::DeletePart) { - if (processed_parts.find(op->part)!=processed_parts.end()) + if (deleted_parts.contains(op->part)) group.erase(op); else - processed_parts.insert(op->part); + deleted_parts.insert(op->part); } op=op_; } + + // replicate Event modifications to keep clones up to date + for (iUndoOp op=group.begin(); op!=group.end(); op++) + { + if (op->type==UndoOp::AddEvent || op->type==UndoOp::DeleteEvent || op->type==UndoOp::ModifyEvent || op->type==UndoOp::SelectEvent) + { + for (const Part* it = op->part->nextClone(); it!=op->part; it=it->nextClone()) + { + UndoOp newop; + if (op->type==UndoOp::AddEvent) // we need to clone the event + newop = UndoOp(UndoOp::AddEvent, op->nEvent.clone(), it, op->doCtrls, op->doClones); + else if (op->type==UndoOp::DeleteEvent) + newop = UndoOp(UndoOp::DeleteEvent, it->events().findSimilar(op->nEvent)->second, it, op->doCtrls, op->doClones); + else if (op->type==UndoOp::ModifyEvent) + newop = UndoOp(UndoOp::ModifyEvent, op->nEvent.clone(), it->events().findSimilar(op->oEvent)->second, it, op->doCtrls, op->doClones); + else if (op->type==UndoOp::SelectEvent) + { + const Event& found = it->events().findSimilar(op->nEvent)->second; + newop= UndoOp(UndoOp::SelectEvent, found, op->selected, found.selected()); + } + + group.insert(op, newop); + } + } + } } bool Song::applyOperation(const UndoOp& op, bool doUndo) @@ -316,7 +354,7 @@ bool Song::applyOperationGroup(Undo& group, bool doUndo) { if (!group.empty()) { - cleanOperationGroup(group); + prepareOperationGroup(group); //this is a HACK! but it works :) (added by flo93) redoList->push_back(group); redo(); diff --git a/muse2/muse/waveedit/wavecanvas.cpp b/muse2/muse/waveedit/wavecanvas.cpp index 0ba0bdbc..db886bce 100644 --- a/muse2/muse/waveedit/wavecanvas.cpp +++ b/muse2/muse/waveedit/wavecanvas.cpp @@ -1477,7 +1477,6 @@ void WaveCanvas::newItem(MusEGui::CItem* item, bool noSnap) if (diff > 0)// part must be extended? { - //schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); schedule_resize_all_same_len_clone_parts(part, event.endFrame(), operations); printf("newItem: extending\n"); } -- cgit v1.2.1