summaryrefslogtreecommitdiff
path: root/muse2
diff options
context:
space:
mode:
Diffstat (limited to 'muse2')
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp159
-rw-r--r--muse2/muse/midiedit/ecanvas.cpp7
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp136
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp3
-rw-r--r--muse2/muse/part.cpp2
5 files changed, 139 insertions, 168 deletions
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();
}