On Wednesday 11 June 2003 05:47 am, Levi Burton wrote:

> Well.  I uh.  Well.  I sure feel stupid now.

Attached is a patch which is probably a better solution.  It is a fairly large 
patch, so beware.

I consolidated all the move code into the SegmentMover tool.  SegmentSelector 
now grabs a SegmentMover tool and dispatches events to it rather than 
handling the move logic in the SegmentSelector tool.

Also, I commented out the delete m_displatchTool code in the 
SegmentSelector::handleMouseButtonRelease() code which was causing problems 
(segfaults) when doing things like this:

SegmentMover* mover =               
dynamic_cast<SegmentResizer*>(getToolBox()->getTool(SegmentMover::ToolName));

It would actually segfault in the call to dynamic_cast.  A mystery to me, but 
not deleting the tool and just assigning the value 0 to it seems to have 
fixed the problem, although there could be ramifications i'm not aware of.

Also, the shift drag copy stuff doesnt seem to work now and I cannot figure 
out why.  I am sure it is something very simple.

I still think the move guides for multiple segments is weird.  Perhaps there 
should be fore, aft, top and bottom guides.  Also -- why are the guides 
QCanvasRectangles rather than QCanvasLines?

-- 
Levi Burton
http://www.puresimplicity.net/~ldb/
Index: segmenttool.cpp
===================================================================
RCS file: /cvsroot/rosegarden/gui/segmenttool.cpp,v
retrieving revision 1.26
diff -u -r1.26 segmenttool.cpp
--- segmenttool.cpp	7 Jun 2003 22:48:53 -0000	1.26
+++ segmenttool.cpp	13 Jun 2003 05:03:23 -0000
@@ -135,7 +135,9 @@
         m_currentItem = item;
         if (!item->isSelected()) {
 
-            SegmentSelector* selector = dynamic_cast<SegmentSelector*>(getToolBox()->getTool("segmentselector"));
+            SegmentSelector* selector = 
+                dynamic_cast<SegmentSelector*>
+                (getToolBox()->getTool(SegmentSelector::ToolName));
             selector->clearSelected();
             selector->slotSelectSegmentItem(item);
             emit selectedSegments(selector->getSelectedSegments());
@@ -260,7 +262,7 @@
 	// that the segment was created by this tool rather than by
 	// e.g. a simple file load
 	SegmentSelector* selector = dynamic_cast<SegmentSelector*>
-	    (getToolBox()->getTool("segmentselector"));
+	    (getToolBox()->getTool(SegmentSelector::ToolName));
 	Rosegarden::Segment *segment = command->getSegment();
 	SegmentItem *item = m_canvas->addSegmentItem(segment);
 
@@ -382,9 +384,19 @@
     SegmentItem *item = m_canvas->findSegmentClickedOn(e->pos());
 
     if (item) {
+        SegmentSelection selection = m_canvas->getSelectedSegments();
+
+        // There has to be a better way.
+        for (SegmentSelection::iterator it = selection.begin();
+             it != selection.end(); it++) {
+            SegmentItem *si = m_canvas->getSegmentItem((*it));
+            m_selectedItems.push_back
+                (SegmentItemPair(QPoint(int(si->x()), int(si->y())), si));
+        }
+        
         m_currentItem = item;
-	m_currentItemStartX = item->x();
-	m_clickPoint = e->pos();
+        m_currentItemStartX = item->x();
+        m_clickPoint = e->pos();
         m_currentItem->showRepeatRect(false);
 
         m_foreGuide->setX(int(m_canvas->grid().getRulerScale()->
@@ -408,72 +420,134 @@
     }
 }
 
+
 void SegmentMover::handleMouseButtonRelease(QMouseEvent*)
 {
-    if (m_currentItem)
-    {
-        Rosegarden::Composition &comp = m_doc->getComposition();
-        Rosegarden::Track *track = comp.getTrackByPosition(
-                m_currentItem->getTrackPosition());
 
-        SegmentReconfigureCommand *command =
-	    new SegmentReconfigureCommand(i18n("Move Segment"));
+    if ( m_currentItem->isSelected() ) {
+        SegmentItemList::iterator it;
 
-        command->addSegment(m_currentItem->getSegment(),
-                            m_currentItem->getStartTime(),
-                            m_currentItem->getEndTime(),
-                            track->getId());
-        addCommandToHistory(command);
-        m_currentItem->showRepeatRect(true);
+        SegmentReconfigureCommand::SegmentRecSet segmentRecSet;
 
+        bool haveChange = false;
+        
+        SegmentReconfigureCommand *command =
+            new SegmentReconfigureCommand
+            (m_selectedItems.size() == 1 ? i18n("Move Segment") :
+             i18n("Move Segments"));
+        
+        for (it = m_selectedItems.begin(); it != m_selectedItems.end(); it++) {
+            SegmentReconfigureCommand::SegmentRec segmentRec;
+            SegmentItem *item = it->second;
+            
+            Rosegarden::Composition &comp = m_doc->getComposition();
+            Rosegarden::Track *track = 
+                comp.getTrackByPosition(item->getTrackPosition());
+            
+            Rosegarden::TrackId trackId = track->getId();
+            
+            if (item->getStartTime() != item->getSegment()->getStartTime() ||
+                item->getEndTime()   != item->getSegment()->getEndMarkerTime() ||
+                trackId              != item->getSegment()->getTrack()) {
+                
+                segmentRec.segment = item->getSegment();
+                segmentRec.startTime = item->getStartTime();
+                segmentRec.endTime  = item->getEndTime();
+                segmentRec.track    = item->getTrackPosition();
+                segmentRecSet.push_back(segmentRec);
+                item->showRepeatRect(true);
+                
+                haveChange = true;
+            }
+        }
+        
+        if (haveChange) {
+            command->addSegments(segmentRecSet);
+            addCommandToHistory(command);
+        }
+        
         m_foreGuide->hide();
         m_topGuide->hide();
+        m_currentItem = 0;
+        m_selectedItems.clear();
+        m_canvas->canvas()->update();
     }
-
-    m_currentItem = 0;
 }
 
 int SegmentMover::handleMouseMove(QMouseEvent *e)
 {
-    if (m_currentItem) {
-
-	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;
-
-	timeT newStartTime = m_canvas->grid().snapX(newX);
-	m_currentItem->setEndTime(m_currentItem->getEndTime() + newStartTime -
-				  m_currentItem->getStartTime());
-	m_currentItem->setStartTime(newStartTime);
-
-	TrackId track = m_canvas->grid().getYBin(newY);
-
-        int nbTracks = m_doc->getComposition().getNbTracks();
-
-        if (track >= ((unsigned int)nbTracks)) {
-            // Make sure the item isn't dragged to below the last track
-            track = 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_topGuide->setY(m_canvas->grid().getYBinCoordinate(track));
+    m_canvas->setSnapGrain(true);
 
+    if (m_currentItem->isSelected()) {
+        int guideX = 0;
+        int guideY = 0;
+        
+        for (SegmentItemList::iterator it = m_selectedItems.begin();
+             it != m_selectedItems.end(); it++)
+            {
+                int x = e->pos().x() - m_clickPoint.x(),
+                    y = e->pos().y() - m_clickPoint.y();
+                
+                const int inertiaDistance = m_canvas->grid().getYSnap() / 3;
+                if (!m_passedInertiaEdge &&
+                    (x < inertiaDistance && x > -inertiaDistance) &&
+                    (y < inertiaDistance && y > -inertiaDistance)) {
+                    return false;
+                } else {
+                    m_passedInertiaEdge = true;
+                }
+                
+                
+                timeT newStartTime = m_canvas->grid().snapX(it->first.x() + x);
+                it->second->setEndTime(it->second->getEndTime() + newStartTime -
+                                       it->second->getStartTime());
+                it->second->setStartTime(newStartTime);
+                
+                TrackId track;
+                int newY=it->first.y() + y;
+                // Make sure we don't set a non-existing track
+                if (newY < 0) { newY = 0; }
+                track = m_canvas->grid().getYBin(newY);
+                
+                // Make sure we don't set a non-existing track (c'td)
+                // TODO: make this suck less. Either the tool should
+                // not allow it in the first place, or we automatically
+                // create new tracks - might make undo very tricky though
+                //
+                if (track >= TrackId(m_doc->getComposition().getNbTracks()))
+                    track  = TrackId(m_doc->getComposition().getNbTracks() - 1);
+                
+                if (it == m_selectedItems.begin()) {
+                    guideX = int(m_canvas->grid().getRulerScale()->
+                                 getXForTime(newStartTime));
+                    
+                    guideY = m_canvas->grid().getYBinCoordinate(track);
+                }
+                else
+                    {
+                        if (x < guideX)
+                            guideX = int(m_canvas->grid().getRulerScale()->
+                                         getXForTime(newStartTime));
+                        
+                        if (y < guideY)
+                            guideY = m_canvas->grid().getYBinCoordinate(track);
+                    }
+                
+                // This is during a "mover" so don't use the normalised (i.e.
+                // proper) TrackPosition value yet.
+                //
+                it->second->setTrackPosition(track);
+            }
+        
+        m_foreGuide->setX(guideX - 2);
+        m_topGuide->setY(guideY - 2);
+        
         m_canvas->canvas()->update();
-
-	return FollowHorizontal | FollowVertical;
     }
-
-    return NoFollow;
+    
+    m_passedInertiaEdge = false;
+    
+    return FollowHorizontal | FollowVertical;
 }
 
 //////////////////////////////
@@ -692,57 +766,42 @@
         if (threshold  == 0) threshold = 1;
         if (threshold > 10) threshold = 10;
 
-	if (!m_segmentAddMode &&
-	    SegmentResizer::cursorIsCloseEnoughToEdge(item, e, threshold)) {
-            SegmentResizer* resizer = dynamic_cast<SegmentResizer*>(getToolBox()->getTool(SegmentResizer::ToolName));
-            resizer->setEdgeThreshold(threshold);
-
-	    m_dispatchTool = resizer;
-            
-	    m_dispatchTool->handleMouseButtonPress(e);
-	    return;
-	}
-
+        if (!m_segmentAddMode &&
+            SegmentResizer::cursorIsCloseEnoughToEdge(item, e, threshold)) {
+            SegmentResizer* resizer = 
+                dynamic_cast<SegmentResizer*>(getToolBox()->getTool(SegmentResizer::ToolName));
+            if (resizer) {
+                resizer->setEdgeThreshold(threshold);
+                resizer->handleMouseButtonPress(e);
+                m_dispatchTool = resizer;
+                return;
+            }
+        }
 
         // Moving
-        //
-        m_currentItem = item;
-        m_clickPoint = e->pos();
-        slotSelectSegmentItem(m_currentItem);
-
-        m_foreGuide->setX(int(m_canvas->grid().getRulerScale()->
-                           getXForTime(item->getSegment()->getStartTime())) -2);
-        m_foreGuide->setY(0);
-        m_foreGuide->setZ(10);
-        m_foreGuide->setSize(2, m_canvas->canvas()->height());
-
-        m_topGuide->setX(0);
-        m_topGuide->setY(int(m_canvas->grid().getYBinCoordinate(
-                              item->getSegment()->getTrack())));
-        m_topGuide->setZ(10);
-        m_topGuide->setSize(m_canvas->canvas()->width(), 2);
-
-        m_foreGuide->show();
-        m_topGuide->show();
-
-        // Don't update until the move - lazy way of making sure the
-        // guides don't flash on while we're double clicking
-        //
-        //m_canvas->canvas()->update();
+        // dispatch to SegmentMover
+        m_dispatchTool = getToolBox()->getTool(SegmentMover::ToolName);
 
+        if (m_dispatchTool) {
+            m_currentItem = item;
+            m_clickPoint = e->pos();
+            slotSelectSegmentItem(m_currentItem);
+            m_dispatchTool->handleMouseButtonPress(e);
+            return;
+        }
+        
     } else {
 
-
         // Add on middle button - bounding box on rest
         //
-	if (e->button() == MidButton) {
-	    m_dispatchTool =  getToolBox()->getTool(SegmentPencil::ToolName);
+        if (e->button() == MidButton) {
+            m_dispatchTool =  getToolBox()->getTool(SegmentPencil::ToolName);
 
             if (m_dispatchTool)
                 m_dispatchTool->handleMouseButtonPress(e);
 
-	    return;
-	}
+            return;
+        }
         else {
             // do a bounding box
             QCanvasRectangle *rect  = m_canvas->getSelectionRectangle();
@@ -760,8 +819,6 @@
     // when the list is empty we're just unselecting.
     //
     emit selectedSegments(getSelectedSegments());
-
-    m_passedInertiaEdge = false;
 }
 
 SegmentSelection
@@ -825,11 +882,11 @@
     m_canvas->canvas()->update();
 
     if (m_dispatchTool) {
-	m_dispatchTool->handleMouseButtonRelease(e);
-	delete m_dispatchTool;
-	m_dispatchTool = 0;
-	m_canvas->setCursor(Qt::arrowCursor);
-	return;
+        m_dispatchTool->handleMouseButtonRelease(e);
+        //        delete m_dispatchTool;
+        m_dispatchTool = 0;
+        m_canvas->setCursor(Qt::arrowCursor);
+        return;
     }
 
     if (!m_currentItem) {
@@ -837,61 +894,20 @@
 
         if (rect) {
             rect->hide();
-	    m_canvas->canvas()->update();
+            m_canvas->canvas()->update();
         }
         return;
     }
 
     m_canvas->setCursor(Qt::arrowCursor);
 
-    if (m_currentItem->isSelected())
-    {
-	SegmentItemList::iterator it;
-
-	bool haveChange = false;
-
-	SegmentReconfigureCommand *command =
-	    new SegmentReconfigureCommand
-	    (m_selectedItems.size() == 1 ? i18n("Move Segment") :
-	                                   i18n("Move Segments"));
-
-	for (it = m_selectedItems.begin();
-	     it != m_selectedItems.end();
-	     it++)
-	{
-
-	    SegmentItem *item = it->second;
-
-            Rosegarden::Composition &comp = m_doc->getComposition();
-            Rosegarden::Track *track = 
-                comp.getTrackByPosition(item->getTrackPosition());
-
-            Rosegarden::TrackId trackId = track->getId();
-
-	    if (item->getStartTime() != item->getSegment()->getStartTime() ||
-		item->getEndTime()   != item->getSegment()->getEndMarkerTime() ||
-		trackId              != item->getSegment()->getTrack()) {
-
-		command->addSegment(item->getSegment(),
-				    item->getStartTime(),
-				    item->getEndTime(),
-				    trackId);
-
-		haveChange = true;
-	    }
-	}
-
-	if (haveChange) addCommandToHistory(command);
-
-	m_canvas->canvas()->update();
-    }
     
     // if we've just finished a quick copy then drop the Z level back
     if (m_segmentQuickCopyDone)
-    {
-        m_segmentQuickCopyDone = false;
-//        m_currentItem->setZ(2); // see SegmentItem::setSelected  --??
-    }
+        {
+            m_segmentQuickCopyDone = false;
+            //        m_currentItem->setZ(2); // see SegmentItem::setSelected  --??
+        }
 
     m_currentItem = 0;
 }
@@ -903,7 +919,7 @@
 SegmentSelector::handleMouseMove(QMouseEvent *e)
 {
     if (m_dispatchTool) {
-	return m_dispatchTool->handleMouseMove(e);
+        return m_dispatchTool->handleMouseMove(e);
     }
 
     if (!m_currentItem)  {
@@ -922,7 +938,7 @@
             if (h > 0) ++h; else --h;
 
             selectionRect->setSize(w, h);
-	    m_canvas->canvas()->update();
+            m_canvas->canvas()->update();
 
             // Get collisions and do selection
             //
@@ -936,14 +952,14 @@
 
             if (l.count()) {
                 for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
-                {
-                    if (SegmentItem *item = dynamic_cast<SegmentItem*>(*it))
                     {
-                        segCount++;
-                        slotSelectSegmentItem(item);
-                        newSelection.insert(item->getSegment());
+                        if (SegmentItem *item = dynamic_cast<SegmentItem*>(*it))
+                            {
+                                segCount++;
+                                slotSelectSegmentItem(item);
+                                newSelection.insert(item->getSegment());
+                            }
                     }
-                }
             }
 
             // Check for unselected items with this piece of crap
@@ -951,30 +967,30 @@
             bool found = false;
 
             for (SegmentSelection::const_iterator oIt = oldSelection.begin();
-                  oIt != oldSelection.end(); oIt++)
-            {
-                found = false;
-                for (SegmentSelection::const_iterator nIt = newSelection.begin();
-                     nIt != newSelection.end(); nIt++)
+                 oIt != oldSelection.end(); oIt++)
                 {
-                    if (*oIt == *nIt)
-                    {
-                        found = true;
-                        break;
-                    }
-                }
-                if (found == false)
-                {
-                    removeFromSelection(*oIt);
-                    m_canvas->getSegmentItem(*oIt)->
-                        setSelected(false, m_canvas->getSegmentBrush());
+                    found = false;
+                    for (SegmentSelection::const_iterator nIt = newSelection.begin();
+                         nIt != newSelection.end(); nIt++)
+                        {
+                            if (*oIt == *nIt)
+                                {
+                                    found = true;
+                                    break;
+                                }
+                        }
+                    if (found == false)
+                        {
+                            removeFromSelection(*oIt);
+                            m_canvas->getSegmentItem(*oIt)->
+                                setSelected(false, m_canvas->getSegmentBrush());
+                        }
                 }
-            }
 
             if (segCount)
-            {
-                emit selectedSegments(getSelectedSegments());
-            }
+                {
+                    emit selectedSegments(getSelectedSegments());
+                }
         }
         return FollowHorizontal | FollowVertical;
     }
@@ -982,112 +998,39 @@
     m_canvas->setCursor(Qt::sizeAllCursor);
 
     if (m_segmentCopyMode && !m_segmentQuickCopyDone)
-    {
-	KMacroCommand *mcommand = new KMacroCommand
-	    (SegmentQuickCopyCommand::getGlobalName());
-
-	SegmentItemList::iterator it;
-	for (it = m_selectedItems.begin();
-	     it != m_selectedItems.end();
-	     it++)
-	{
-	    SegmentQuickCopyCommand *command =
-		new SegmentQuickCopyCommand(it->second->getSegment());
-
-	    mcommand->addCommand(command);
-	}
-
-        addCommandToHistory(mcommand);
-
-//        Rosegarden::Segment *newSegment = command->getCopy();
+        {
+            KMacroCommand *mcommand = new KMacroCommand
+                (SegmentQuickCopyCommand::getGlobalName());
+
+            SegmentItemList::iterator it;
+            for (it = m_selectedItems.begin();
+                 it != m_selectedItems.end();
+                 it++)
+                {
+                    SegmentQuickCopyCommand *command =
+                        new SegmentQuickCopyCommand(it->second->getSegment());
 
-        // generate SegmentItem
-        //
-	m_canvas->updateAllSegmentItems();
-        m_segmentQuickCopyDone = true;
+                    mcommand->addCommand(command);
+                }
 
-        // Don't understand why swapping selected item is causing
-        // problem hereafter - so leaving this commented out.
-        //
-        //SegmentItem *newItem = m_canvas->getSegmentItem(newSegment);
-        //clearSelected();
-        //m_currentItem = newItem;
-        //m_currentItem->setZ(3); // bring it to the top
-        //slotSelectSegmentItem(newItem);
-    }
+            addCommandToHistory(mcommand);
 
-    m_canvas->setSnapGrain(true);
+            //        Rosegarden::Segment *newSegment = command->getCopy();
 
-    if (m_currentItem->isSelected())
-    {
-	SegmentItemList::iterator it;
-        int guideX = 0;
-        int guideY = 0;
-	
-	for (it = m_selectedItems.begin();
-	     it != m_selectedItems.end();
-	     it++)
-	{
-	    int x = e->pos().x() - m_clickPoint.x(),
-		y = e->pos().y() - m_clickPoint.y();
-
-	    const int inertiaDistance = m_canvas->grid().getYSnap() / 3;
-	    if (!m_passedInertiaEdge &&
-		(x < inertiaDistance && x > -inertiaDistance) &&
-		(y < inertiaDistance && y > -inertiaDistance)) {
-		return false;
-	    } else {
-		m_passedInertiaEdge = true;
-	    }
-
-
-	    timeT newStartTime = m_canvas->grid().snapX(it->first.x() + x);
-	    it->second->setEndTime(it->second->getEndTime() + newStartTime -
-				   it->second->getStartTime());
-	    it->second->setStartTime(newStartTime);
-
-	    TrackId track;
-            int newY=it->first.y() + y;
-            // Make sure we don't set a non-existing track
-            if (newY < 0) { newY = 0; }
-            track = m_canvas->grid().getYBin(newY);
-
-            // Make sure we don't set a non-existing track (c'td)
-            // TODO: make this suck less. Either the tool should
-            // not allow it in the first place, or we automatically
-            // create new tracks - might make undo very tricky though
+            // generate SegmentItem
             //
-            if (track >= TrackId(m_doc->getComposition().getNbTracks()))
-                track  = TrackId(m_doc->getComposition().getNbTracks() - 1);
-
-            if (it == m_selectedItems.begin())
-            {
-                guideX = int(m_canvas->grid().getRulerScale()->
-                    getXForTime(newStartTime));
-
-                guideY = m_canvas->grid().getYBinCoordinate(track);
-            }
-            else
-            {
-                if (x < guideX)
-                    guideX = int(m_canvas->grid().getRulerScale()->
-                        getXForTime(newStartTime));
+            m_canvas->updateAllSegmentItems();
+            m_segmentQuickCopyDone = true;
 
-                if (y < guideY)
-                    guideY = m_canvas->grid().getYBinCoordinate(track);
-            }
-
-            // This is during a "mover" so don't use the normalised (i.e.
-            // proper) TrackPosition value yet.
+            // Don't understand why swapping selected item is causing
+            // problem hereafter - so leaving this commented out.
             //
-	    it->second->setTrackPosition(track);
-	}
-
-        m_foreGuide->setX(guideX - 2);
-        m_topGuide->setY(guideY - 2);
-
-	m_canvas->canvas()->update();
-    }
+            //SegmentItem *newItem = m_canvas->getSegmentItem(newSegment);
+            //clearSelected();
+            //m_currentItem = newItem;
+            //m_currentItem->setZ(3); // bring it to the top
+            //slotSelectSegmentItem(newItem);
+        }
 
     return FollowHorizontal | FollowVertical;
 }
Index: segmenttool.h
===================================================================
RCS file: /cvsroot/rosegarden/gui/segmenttool.h,v
retrieving revision 1.9
diff -u -r1.9 segmenttool.h
--- segmenttool.h	27 Apr 2003 15:47:45 -0000	1.9
+++ segmenttool.h	13 Jun 2003 05:03:23 -0000
@@ -170,11 +170,15 @@
 protected:
     SegmentMover(SegmentCanvas*, RosegardenGUIDoc*);
 
+    typedef std::pair<QPoint, SegmentItem *> SegmentItemPair;
+    typedef std::vector<SegmentItemPair> SegmentItemList;
+
     //--------------- Data members ---------------------------------
 
     QPoint            m_clickPoint;
     double            m_currentItemStartX;
-
+    SegmentItemList   m_selectedItems;
+    bool              m_passedInertiaEdge;
     QCanvasRectangle *m_foreGuide;
     QCanvasRectangle *m_topGuide;
 
@@ -285,7 +289,7 @@
     bool m_segmentCopyMode;
     QPoint m_clickPoint;
     bool m_segmentQuickCopyDone;
-    bool m_passedInertiaEdge;
+
 
     SegmentTool *m_dispatchTool;
 

Reply via email to