On Wednesday 11 June 2003 04:21 am, Chris Cannam wrote:
> What does this feature do? Is it another way of selecting things or
> something you do with things already selected?
Being able to move multiple segments on multiple tracks, or multiple segments
on a single track.
> It is already possible to move multiple segments, which doesn't help
> with my confusion. Your pics look nice, with that shaded rectangle
> thing, but they don't show what actual behaviour is involved. Maybe
> I just need to try it and see.
You can? Well, if not -- you can now. See attached patch.
This is really rough code (it could be much, much better. For instance, I
dont think pulling in QPtrList was such a good idea), and the multi guide
doesnt work yet, but everything else does.
Oh, and just for the record:
It was a pain in the fucking ass.
--
Levi Burton
http://www.puresimplicity.net/~ldb/
Index: segmenttool.cpp
===================================================================
RCS file: /cvsroot/rosegarden/gui/segmenttool.cpp,v
retrieving revision 1.26
diff -u -w -r1.26 segmenttool.cpp
--- segmenttool.cpp 7 Jun 2003 22:48:53 -0000 1.26
+++ segmenttool.cpp 11 Jun 2003 10:19:49 -0000
@@ -41,6 +41,7 @@
using Rosegarden::SnapGrid;
using Rosegarden::Note;
using Rosegarden::SegmentSelection;
+using Rosegarden::Segment;
//////////////////////////////////////////////////////////////////////
// Segment Tools
@@ -359,7 +360,8 @@
SegmentMover::SegmentMover(SegmentCanvas *c, RosegardenGUIDoc *d)
: SegmentTool(c, d),
m_foreGuide(new QCanvasRectangle(m_canvas->canvas())),
- m_topGuide(new QCanvasRectangle(m_canvas->canvas()))
+ m_topGuide(new QCanvasRectangle(m_canvas->canvas())),
+ m_multiGuide(new QCanvasRectangle(m_canvas->canvas()))
{
m_foreGuide->setPen(RosegardenGUIColours::MovementGuide);
m_foreGuide->setBrush(RosegardenGUIColours::MovementGuide);
@@ -369,6 +371,10 @@
m_topGuide->setBrush(RosegardenGUIColours::MovementGuide);
m_topGuide->hide();
+ m_multiGuide->setPen(RosegardenGUIColours::MovementGuide);
+ m_multiGuide->setBrush(Qt::NoBrush);
+ m_multiGuide->hide();
+
RG_DEBUG << "SegmentMover()\n";
}
@@ -382,9 +388,11 @@
SegmentItem *item = m_canvas->findSegmentClickedOn(e->pos());
if (item) {
+ SegmentSelection selection = m_canvas->getSelectedSegments();
+ m_clickPoint = e->pos();
+ if (selection.size() == 1) {
m_currentItem = item;
m_currentItemStartX = item->x();
- m_clickPoint = e->pos();
m_currentItem->showRepeatRect(false);
m_foreGuide->setX(int(m_canvas->grid().getRulerScale()->
@@ -401,36 +409,68 @@
m_foreGuide->show();
m_topGuide->show();
+ } else { // Multiple Selection
+ Segment *segment1, *segment2, *segment3, *segment4;
+ timeT earliestTime = 0, latestTime = 0;
+ TrackId lowTrack = 0, highTrack = 0;
- // Don't update until the move
- //
- //m_canvas->canvas()->update();
+ for (SegmentSelection::iterator it = selection.begin();
+ it != selection.end(); it++) {
+
+ if (it == selection.begin() ||
+ (*it)->getStartTime() < earliestTime) {
+ earliestTime = (*it)->getStartTime();
+ segment1 = dynamic_cast<Segment*>(*it);
}
+
+ if ((*it)->getEndTime() > latestTime) {
+ latestTime = (*it)->getEndMarkerTime();
+ segment2 = dynamic_cast<Segment*>(*it);
}
-void SegmentMover::handleMouseButtonRelease(QMouseEvent*)
-{
- if (m_currentItem)
- {
- Rosegarden::Composition &comp = m_doc->getComposition();
- Rosegarden::Track *track = comp.getTrackByPosition(
- m_currentItem->getTrackPosition());
+ if (it == selection.begin() ||
+ (*it)->getTrack() < lowTrack) {
+ lowTrack = (*it)->getTrack();
+ segment3 = dynamic_cast<Segment*>(*it);
+ }
- SegmentReconfigureCommand *command =
- new SegmentReconfigureCommand(i18n("Move Segment"));
+ if (it == selection.begin() ||
+ (*it)->getTrack() > highTrack) {
+ highTrack = (*it)->getTrack();
+ segment4 = dynamic_cast<Segment*>(*it);
+ }
- command->addSegment(m_currentItem->getSegment(),
- m_currentItem->getStartTime(),
- m_currentItem->getEndTime(),
- track->getId());
- addCommandToHistory(command);
- m_currentItem->showRepeatRect(true);
+ SegmentItem *currentItem =
+ m_canvas->getSegmentItem(dynamic_cast<Segment*>(*it));
- m_foreGuide->hide();
- m_topGuide->hide();
+ currentItem->setZ(-1); // 1 below m_multiGuide
+ currentItem->showRepeatRect(false);
+ m_currentItems.append(currentItem);
}
- m_currentItem = 0;
+ SegmentItem *item1, *item2, *item3, *item4;
+
+ item1 = m_canvas->getSegmentItem(segment1);
+ item2 = m_canvas->getSegmentItem(segment2);
+ item3 = m_canvas->getSegmentItem(segment3);
+ item4 = m_canvas->getSegmentItem(segment4);
+
+ m_multiGuide->setX(int(item1->x()));
+ m_multiGuide->setY(int(item3->y()));
+ m_multiGuide->setZ(0); // 1 above whats selected, 1 below whats not.
+
+ // This shouldn't have to change.
+ m_multiGuide->setSize(int(item2->x() + item2->width() - item1->x()),
+ int(item4->y() + item4->height() - item3->y()));
+
+ // this is here because we set m_currentItem to item1 and handle
+ // it separately in the case of a multi move.
+ m_currentItem = item1;
+ if (!m_currentItems.removeRef(item1)) std::cout << "didnt remove" << std::endl;
+ m_currentItemStartX = item1->x();
+ m_multiGuide->show();
+ }
+ }
}
int SegmentMover::handleMouseMove(QMouseEvent *e)
@@ -440,41 +480,111 @@
m_canvas->setSnapGrain(true);
int newX = e->x() - m_clickPoint.x() + int(m_currentItemStartX);
- //if (newX < 0) newX = 0;
int newY = e->y();
+
if (newY < 0) newY = 0;
+ // save the old start time
+ timeT oldStartTime = m_currentItem->getStartTime();
+
+ // calculate the new start time
timeT newStartTime = m_canvas->grid().snapX(newX);
- m_currentItem->setEndTime(m_currentItem->getEndTime() + newStartTime -
- m_currentItem->getStartTime());
+
+ // set the end time
+ m_currentItem->setEndTime(m_currentItem->getEndTime()
+ + newStartTime
+ - m_currentItem->getStartTime());
+ // set the start time
m_currentItem->setStartTime(newStartTime);
- TrackId track = m_canvas->grid().getYBin(newY);
+ // calculate the change
+ timeT deltaTime = newStartTime - oldStartTime;
+
+ // save the old track
+ TrackId oldTrack = m_currentItem->getSegment()->getTrack();
+
+ // calculate the new track
+ TrackId newTrack = m_canvas->grid().getYBin(newY);
+
+ // calculate the change
+ TrackId trackDelta = newTrack - oldTrack;
int nbTracks = m_doc->getComposition().getNbTracks();
- if (track >= ((unsigned int)nbTracks)) {
+ if (newTrack >= ((unsigned int)nbTracks)) {
// Make sure the item isn't dragged to below the last track
- track = nbTracks - 1;
+ newTrack = nbTracks - 1;
}
// Don't use proper TrackPosition yet - just visual position
// until the release.
//
- m_currentItem->setTrackPosition(track);
-
- m_foreGuide->setX(int(m_canvas->grid().getRulerScale()->
- getXForTime(newStartTime)) - 2);
+ m_currentItem->setTrackPosition(newTrack);
- m_topGuide->setY(m_canvas->grid().getYBinCoordinate(track));
+ // We have more work to do
+ if (m_currentItems.count() > 1) {
+ for (SegmentItem *currentItem = m_currentItems.first();
+ currentItem; currentItem = m_currentItems.next()) {
+ timeT newStart = currentItem->getStartTime() + deltaTime;
+ timeT duration = currentItem->getEndTime() - currentItem->getStartTime();
+ currentItem->setEndTime(newStart + duration);
+ currentItem->setStartTime(newStart);
+ currentItem->setTrackPosition(currentItem->getSegment()->getTrack()
+ + trackDelta);
+ }
+ // set multiGuide
+ } else {
+ m_foreGuide->setX(int(m_canvas->grid().getRulerScale()->getXForTime(newStartTime)) - 2);
+ m_topGuide->setY(m_canvas->grid().getYBinCoordinate(newTrack));
+ }
m_canvas->canvas()->update();
+ }
- return FollowHorizontal | FollowVertical;
+ return m_currentItem ? (FollowHorizontal | FollowVertical) : NoFollow;
}
- return NoFollow;
+void SegmentMover::handleMouseButtonRelease(QMouseEvent*)
+{
+ if (m_currentItem) {
+
+ SegmentReconfigureCommand *command =
+ new SegmentReconfigureCommand(i18n("Move Segment"));
+
+ // Add back the item we removed before, or in the
+ // case of a single move, simply add the one segment.
+ m_currentItems.append(m_currentItem);
+
+ SegmentReconfigureCommand::SegmentRecSet segmentRecSet;
+
+ for (SegmentItem *currentItem = m_currentItems.first();
+ currentItem; currentItem = m_currentItems.next()) {
+ SegmentReconfigureCommand::SegmentRec segmentRec;
+// Rosegarden::Track *track =
+// comp.getTrackByPosition(currentItem->getTrackPosition());
+ segmentRec.segment = currentItem->getSegment();
+ segmentRec.startTime = currentItem->getStartTime();
+ segmentRec.endTime = currentItem->getEndTime();
+ segmentRec.track = currentItem->getTrackPosition();
+ segmentRecSet.push_back(segmentRec);
+ currentItem->showRepeatRect(true);
+ }
+
+ command->addSegments(segmentRecSet);
+ addCommandToHistory(command);
+
+ if (m_currentItems.count() > 1)
+ m_multiGuide->hide();
+ else {
+ m_foreGuide->hide();
+ m_topGuide->hide();
}
+ }
+
+ m_currentItems.clear();
+ m_currentItem = 0;
+}
+
//////////////////////////////
// SegmentResizer
Index: segmenttool.h
===================================================================
RCS file: /cvsroot/rosegarden/gui/segmenttool.h,v
retrieving revision 1.9
diff -u -w -r1.9 segmenttool.h
--- segmenttool.h 27 Apr 2003 15:47:45 -0000 1.9
+++ segmenttool.h 11 Jun 2003 10:19:50 -0000
@@ -30,6 +30,7 @@
#include "Selection.h"
#include "edittool.h"
+#include "segmentcanvas.h"
class SegmentCanvas;
class RosegardenGUIDoc;
@@ -37,7 +38,7 @@
class SegmentItem;
class KCommand;
class QCanvasRectangle;
-class QPopupMenu; // LDB
+class QPopupMenu;
namespace Rosegarden { class RulerScale; }
@@ -174,10 +175,11 @@
QPoint m_clickPoint;
double m_currentItemStartX;
+ QPtrList<SegmentItem> m_currentItems;
QCanvasRectangle *m_foreGuide;
QCanvasRectangle *m_topGuide;
-
+ QCanvasRectangle *m_multiGuide;
};
/**
@@ -291,7 +293,6 @@
QCanvasRectangle *m_foreGuide;
QCanvasRectangle *m_topGuide;
-
};