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;
-
 };
 
 

Reply via email to