From 9633b537bea22bc753ca8e3e0481fd38419524ae Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 28 Jun 2011 15:43:50 +0000 Subject: autoexpand now works properly also for moving notes --- muse2/muse/midiedit/dcanvas.cpp | 159 +++++++++++++++++--------------------- muse2/muse/midiedit/ecanvas.cpp | 7 +- muse2/muse/midiedit/prcanvas.cpp | 136 ++++++++++++++------------------ muse2/muse/midiedit/scoreedit.cpp | 3 +- muse2/muse/part.cpp | 2 - 5 files changed, 139 insertions(+), 168 deletions(-) (limited to 'muse2') diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index b19831a0..4b5c3ea9 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -104,9 +104,9 @@ Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp { if(editor->parts()->empty()) return Undo(); //return empty list - + PartsToChangeMap parts2change; - Undo operations; + Undo operations; for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) { @@ -153,85 +153,66 @@ Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp ip2c->second.xdiff = npartoffset; } } - + + bool forbidden=false; for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; int diff = ip2c->second.xdiff; - Part* newPart = opart->clone(); - - newPart->setLenTick(newPart->lenTick() + diff); - - // BUG FIX: #1650953 - // Added by T356. - // Fixes posted "select and drag past end of part - crashing" bug - for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) + if (opart->hasHiddenNotes()) { - if(ip->second == opart) - { - editor->parts()->erase(ip); - break; - } - } - - editor->parts()->add(newPart); - // Do port controller values but not clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, opart, newPart, true, false)); - - ip2c->second.npart = newPart; + forbidden=true; + break; + } + schedule_resize_all_same_len_clone_parts(opart, opart->lenTick() + diff, operations); + } + + + if (!forbidden) + { + std::vector< CItem* > doneList; + typedef std::vector< CItem* >::iterator iDoneList; + + for(iCItem ici = items.begin(); ici != items.end(); ++ici) + { + CItem* ci = ici->second; + + int x = ci->pos().x(); + int y = ci->pos().y(); + int nx = x + dx; + int ny = pitch2y(y2pitch(y) + dp); + QPoint newpos = raster(QPoint(nx, ny)); + selectItem(ci, true); + + iDoneList idl; + for(idl = doneList.begin(); idl != doneList.end(); ++idl) + // This compares EventBase pointers to see if they're the same... + if((*idl)->event() == ci->event()) + break; + + // Do not process if the event has already been processed (meaning it's an event in a clone part)... + if (idl == doneList.end()) + { + operations.push_back(moveItem(ci, newpos, dtype)); + doneList.push_back(ci); + } + ci->move(newpos); + + if(moving.size() == 1) + itemReleased(curItem, newpos); + + if(dtype == MOVE_COPY || dtype == MOVE_CLONE) + selectItem(ci, false); + } + + return operations; } - - iPartToChange icp = parts2change.find(curPart); - if(icp != parts2change.end()) - { - curPart = icp->second.npart; - curPartId = curPart->sn(); - } - - std::vector< CItem* > doneList; - typedef std::vector< CItem* >::iterator iDoneList; - - for(iCItem ici = items.begin(); ici != items.end(); ++ici) + else { - CItem* ci = ici->second; - - // If this item's part is in the parts2change list, change the item's part to the new part. - Part* pt = ci->part(); - iPartToChange ip2c = parts2change.find(pt); - if(ip2c != parts2change.end()) - ci->setPart(ip2c->second.npart); - - int x = ci->pos().x(); - int y = ci->pos().y(); - int nx = x + dx; - int ny = pitch2y(y2pitch(y) + dp); - QPoint newpos = raster(QPoint(nx, ny)); - selectItem(ci, true); - - iDoneList idl; - for(idl = doneList.begin(); idl != doneList.end(); ++idl) - // This compares EventBase pointers to see if they're the same... - if((*idl)->event() == ci->event()) - break; - - // Do not process if the event has already been processed (meaning it's an event in a clone part)... - if (idl == doneList.end()) - { - operations.push_back(moveItem(ci, newpos, dtype)); - doneList.push_back(ci); - } - ci->move(newpos); - - if(moving.size() == 1) { - itemReleased(curItem, newpos); - } - if(dtype == MOVE_COPY || dtype == MOVE_CLONE) - selectItem(ci, false); - } - - return operations; + return Undo(); //return empty list + } } //--------------------------------------------------------- @@ -261,9 +242,10 @@ UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype) //item->setPart(part); item->setEvent(newEvent); - // Added by T356. - if(((int)newEvent.endTick() - (int)part->lenTick()) > 0) - printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData()); + // Added by T356, removed by flo93: with operation groups, it happens that the + // part is too short right now, even if it's queued for being extended + //if(((int)newEvent.endTick() - (int)part->lenTick()) > 0) + // printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData()); if (dtype == MOVE_COPY || dtype == MOVE_CLONE) return UndoOp(UndoOp::AddEvent, newEvent, part, false, false); @@ -361,20 +343,23 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace) // Added by T356. Part* part = nevent->part(); - song->startUndo(); - int modified=SC_EVENT_MODIFIED; + Undo operations; int diff = event.endTick()-part->lenTick(); - if (diff > 0) {// too short part? extend it - Part* newPart = part->clone(); - newPart->setLenTick(newPart->lenTick()+diff); - // Indicate no undo, and do port controller values but not clone parts. - audio->msgChangePart(part, newPart, false, true, false); - modified=modified|SC_PART_MODIFIED; - part = newPart; // reassign + + if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed + { + operations.push_back(UndoOp(UndoOp::AddEvent,event, part, false, false)); + + if (diff > 0)// part must be extended? + { + schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); + printf("newItem: extending\n"); } - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(event, part, false, false, false); - song->endUndo(modified); + } + //else forbid action by not applying it + song->applyOperationGroup(operations); + songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary + //to remove "forbidden" events from the list again } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp index ef47e0d6..a829650c 100644 --- a/muse2/muse/midiedit/ecanvas.cpp +++ b/muse2/muse/midiedit/ecanvas.cpp @@ -416,7 +416,12 @@ void EventCanvas::endMoveItems(const QPoint& pos, DragType dragtype, int dir) Undo operations = moveCanvasItems(moving, dp, dx, dragtype); - song->applyOperationGroup(operations); + if (operations.empty()) + songChanged(SC_EVENT_MODIFIED); //this is a hack to force the canvas to repopulate + //itself. otherwise, if a moving operation was forbidden, + //the canvas would still show the movement + else + song->applyOperationGroup(operations); moving.clear(); updateSelection(); diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index 11a142e1..a659ad26 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -261,8 +261,8 @@ Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty if(editor->parts()->empty()) return Undo(); //return empty list - Undo operations; PartsToChangeMap parts2change; + Undo operations; for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) { @@ -310,84 +310,65 @@ Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty } } + bool forbidden=false; for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; int diff = ip2c->second.xdiff; - Part* newPart = opart->clone(); - - newPart->setLenTick(newPart->lenTick() + diff); - - // BUG FIX: #1650953 - // Added by T356. - // Fixes posted "select and drag past end of part - crashing" bug - for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip) + if (opart->hasHiddenNotes()) { - if(ip->second == opart) - { - editor->parts()->erase(ip); - break; - } - } - - editor->parts()->add(newPart); - // Do port controller values but not clone parts. - operations.push_back(UndoOp(UndoOp::ModifyPart, opart, newPart, true, false)); - - ip2c->second.npart = newPart; + forbidden=true; + break; + } + schedule_resize_all_same_len_clone_parts(opart, opart->lenTick() + diff, operations); + } + + + if (!forbidden) + { + std::vector< CItem* > doneList; + typedef std::vector< CItem* >::iterator iDoneList; + + for(iCItem ici = items.begin(); ici != items.end(); ++ici) + { + CItem* ci = ici->second; + + int x = ci->pos().x(); + int y = ci->pos().y(); + int nx = x + dx; + int ny = pitch2y(y2pitch(y) + dp); + QPoint newpos = raster(QPoint(nx, ny)); + selectItem(ci, true); + + iDoneList idl; + for(idl = doneList.begin(); idl != doneList.end(); ++idl) + // This compares EventBase pointers to see if they're the same... + if((*idl)->event() == ci->event()) + break; + + // Do not process if the event has already been processed (meaning it's an event in a clone part)... + if (idl == doneList.end()) + { + operations.push_back(moveItem(ci, newpos, dtype)); + doneList.push_back(ci); + } + ci->move(newpos); + + if(moving.size() == 1) + itemReleased(curItem, newpos); + + if(dtype == MOVE_COPY || dtype == MOVE_CLONE) + selectItem(ci, false); + } + + return operations; } - - iPartToChange icp = parts2change.find(curPart); - if(icp != parts2change.end()) - { - curPart = icp->second.npart; - curPartId = curPart->sn(); - } - - std::vector< CItem* > doneList; - typedef std::vector< CItem* >::iterator iDoneList; - - - for(iCItem ici = items.begin(); ici != items.end(); ++ici) + else { - CItem* ci = ici->second; - - // If this item's part is in the parts2change list, change the item's part to the new part. - Part* pt = ci->part(); - iPartToChange ip2c = parts2change.find(pt); - if(ip2c != parts2change.end()) - ci->setPart(ip2c->second.npart); - - int x = ci->pos().x(); - int y = ci->pos().y(); - int nx = x + dx; - int ny = pitch2y(y2pitch(y) + dp); - QPoint newpos = raster(QPoint(nx, ny)); - selectItem(ci, true); - - iDoneList idl; - for(idl = doneList.begin(); idl != doneList.end(); ++idl) - // This compares EventBase pointers to see if they're the same... - if((*idl)->event() == ci->event()) - break; - - // Do not process if the event has already been processed (meaning it's an event in a clone part)... - if (idl == doneList.end()) - { - operations.push_back(moveItem(ci, newpos, dtype)); - doneList.push_back(ci); - } - ci->move(newpos); - - if(moving.size() == 1) - itemReleased(curItem, newpos); - if(dtype == MOVE_COPY || dtype == MOVE_CLONE) - selectItem(ci, false); - } - - return operations; + return Undo(); //return empty list + } } //--------------------------------------------------------- @@ -427,9 +408,10 @@ UndoOp PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype) item->setEvent(newEvent); - // Added by T356. - if(((int)newEvent.endTick() - (int)part->lenTick()) > 0) - printf("PianoCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData()); + // Added by T356, removed by flo93: with operation groups, it happens that the + // part is too short right now, even if it's queued for being extended + //if(((int)newEvent.endTick() - (int)part->lenTick()) > 0) + // printf("PianoCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData()); if (dtype == MOVE_COPY || dtype == MOVE_CLONE) return UndoOp(UndoOp::AddEvent, newEvent, part, false, false); @@ -491,11 +473,13 @@ void PianoCanvas::newItem(CItem* item, bool noSnap) schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); printf("newItem: extending\n"); } + + song->applyOperationGroup(operations); } //else forbid action by not applying it - song->applyOperationGroup(operations); - songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary - //to remove "forbidden" events from the list again + else + songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary + //to remove "forbidden" events from the list again } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index c14c14fd..c2380539 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4456,8 +4456,7 @@ void staff_t::update_part_indices() * between, for example, when a cis is tied to a des * * CURRENT TODO - * o do autoexpand correctly in prcanvas.cpp, then port that to - * dcanvas.cpp, steprec.cpp and scoreedit.cpp + * o do autoexpand in steprec.cpp and scoreedit.cpp * * IMPORTANT TODO * o shrink a part from its beginning as well! watch out for clones! diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 9bb3431c..67cf441e 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -1179,7 +1179,5 @@ bool Part::hasHiddenNotes() if (ev->second.endTick() > lastNote) lastNote=ev->second.endTick(); - printf ("in hasHiddenNotes: lastNote=%i, lenTick=%i\n",lastNote, lenTick()); - return lastNote > lenTick(); } -- cgit v1.2.3