[Uml-devel] branches/work/soc-umbrello/umbrello

Gopala Krishna A krishna.ggk at gmail.com
Mon Dec 7 17:42:51 UTC 2009


SVN commit 1059926 by gopala:

* Ground work for better undo/redo system design.
* Use the new QGraphicsObject as base class instead of QObject and
  QGraphicsItem.


 M  +1 -1      expanderbox.cpp  
 M  +2 -2      expanderbox.h  
 M  +25 -9     umlscene.cpp  
 M  +9 -2      widgets/classifierwidget.cpp  
 M  +1 -1      widgets/classifierwidget.h  
 M  +51 -11    widgets/umlwidget.cpp  
 M  +1 -1      widgets/umlwidget.h  
 M  +36 -1     widgets/widgetbase.cpp  
 M  +18 -0     widgets/widgetbase.h  


--- branches/work/soc-umbrello/umbrello/expanderbox.cpp #1059925:1059926
@@ -30,7 +30,7 @@
  * \a expanded and parent item being \a parent.
  */
 ExpanderBox::ExpanderBox(bool expanded, QGraphicsItem *parent) :
-    QGraphicsItem(parent),
+    QGraphicsObject(parent),
     m_expanded(expanded),
     m_brush(Qt::NoBrush)
 {
--- branches/work/soc-umbrello/umbrello/expanderbox.h #1059925:1059926
@@ -23,7 +23,7 @@
 #include <QtCore/QObject>
 
 #include <QtGui/QBrush>
-#include <QtGui/QGraphicsItem>
+#include <QtGui/QGraphicsObject>
 #include <QtGui/QPen>
 
 /**
@@ -33,7 +33,7 @@
  * This can be used as GUI for the user to expand/deexpand
  * something. Currently this is used in ClassifierWidget.
  */
-class ExpanderBox : public QObject, public QGraphicsItem
+class ExpanderBox : public QGraphicsObject
 {
 Q_OBJECT
 public:
--- branches/work/soc-umbrello/umbrello/umlscene.cpp #1059925:1059926
@@ -540,6 +540,7 @@
     //check to see if we want the message
     //may be wanted by someone else e.g. list view
 
+    uDebug() << endl << endl << "called" << endl << endl;
     if (!m_bCreateObject)  {
         return;
     }
@@ -4160,9 +4161,11 @@
     qreal smallestX = WidgetList_Utils::getSmallestX(widgetList);
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(smallestX, widget->pos().y());
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4177,9 +4180,11 @@
     qreal biggestX = WidgetList_Utils::getBiggestX(widgetList);
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(biggestX - widget->width(), widget->pos().y());
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4195,9 +4200,11 @@
     qreal smallestY = WidgetList_Utils::getSmallestY(widgetList);
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(widget->pos().x(), smallestY);
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4212,9 +4219,11 @@
     qreal biggestY = WidgetList_Utils::getBiggestY(widgetList);
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(widget->pos().x(), biggestY - widget->height());
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4232,9 +4241,11 @@
     qreal middle = int((biggestX - smallestX) / 2) + smallestX;
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(middle - int(widget->width() / 2), widget->pos().y());
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4252,9 +4263,11 @@
     qreal middle = int((biggestY - smallestY) / 2) + smallestY;
 
     foreach(UMLWidget *widget , widgetList) {
+        widget->setUserChange(WidgetBase::PositionChange, true);
         widget->setPos(widget->pos().x(), middle - int(widget->height() / 2));
-        widget->adjustAssociations();
+        widget->setUserChange(WidgetBase::PositionChange, false);
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4280,12 +4293,14 @@
         if (i == 1) {
             widgetPrev = widget;
         } else {
+            widget->setUserChange(WidgetBase::PositionChange, true);
             widget->setPos(widgetPrev->pos().x(), widgetPrev->y() + widgetPrev->height() + distance);
-            widget->adjustAssociations();
+            widget->setUserChange(WidgetBase::PositionChange, false);
             widgetPrev = widget;
         }
         i++;
     }
+    //TODO: Push stored cmds to stack.
 }
 
 /**
@@ -4311,14 +4326,15 @@
         if (i == 1) {
             widgetPrev = widget;
         } else {
+            widget->setUserChange(WidgetBase::PositionChange, true);
             widget->setPos(widgetPrev->x() + widgetPrev->width() + distance,
                     widgetPrev->pos().y());
-            widget->adjustAssociations();
+            widget->setUserChange(WidgetBase::PositionChange, false);
             widgetPrev = widget;
         }
         i++;
     }
-
+    //TODO: Push stored cmds to stack.
 }
 
 void UMLScene::test()
--- branches/work/soc-umbrello/umbrello/widgets/classifierwidget.cpp #1059925:1059926
@@ -328,15 +328,22 @@
  *
  * @todo Implement this properly after implementing AssociationWidget.
  */
-void ClassifierWidget::adjustAssociations()
+void ClassifierWidget::adjustAssociations(bool userAdjustChange)
 {
-    UMLWidget::adjustAssociations();
+    UMLWidget::adjustAssociations(userAdjustChange);
 
     if (umlDoc()->loading() || m_classAssociationWidget == 0) {
         return;
     }
 
+    //TODO: Push undo command
+    if (userAdjustChange) {
+        m_classAssociationWidget->setUserChange(AssocAdjustChange, true);
+    }
     m_classAssociationWidget->associationLine()->calculateAssociationClassLine();
+    if (userAdjustChange) {
+        m_classAssociationWidget->setUserChange(AssocAdjustChange, false);
+    }
 }
 
 /**
--- branches/work/soc-umbrello/umbrello/widgets/classifierwidget.h #1059925:1059926
@@ -90,7 +90,7 @@
         return m_classAssociationWidget;
     }
     void setClassAssociationWidget(AssociationWidget *assocwidget);
-    virtual void adjustAssociations();
+    virtual void adjustAssociations(bool userAdjustChange);
 
     virtual bool loadFromXMI(QDomElement & qElement);
     virtual void saveToXMI(QDomDocument & qDoc, QDomElement & qElement);
--- branches/work/soc-umbrello/umbrello/widgets/umlwidget.cpp #1059925:1059926
@@ -244,11 +244,17 @@
  *
  * Subclasses can reimplement to fine tune this behvaior.
  */
-void UMLWidget::adjustAssociations()
+void UMLWidget::adjustAssociations(bool userChangeAdjust)
 {
     foreach (AssociationWidget *assoc,
             m_associationSpaceManager->associationWidgets()) {
+        if (userChangeAdjust) {
+            assoc->setUserChange(AssocAdjustChange, true);
+        }
         assoc->associationLine()->calculateEndPoints();
+        if (userChangeAdjust) {
+            assoc->setUserChange(AssocAdjustChange, false);
+        }
     }
     // m_associationSpaceManager->adjust();
     //TODO: Implement this once AssociationWidget's are implemented.
@@ -312,7 +318,7 @@
         if(m_widgetHandle) {
             m_widgetHandle->updateHandlePosition();
         }
-        adjustAssociations();
+        adjustAssociations(true);
         return QVariant();
     }
     else if(change == FontHasChanged) {
@@ -450,8 +456,38 @@
     e->setLastScenePos(m_mouseMoveEventStore->lastScenePos());
     e->setLastScreenPos(m_mouseMoveEventStore->lastScreenPos());
 
+    QList<QGraphicsItem*> selection = scene()->selectedItems();
+    if (beganMoveNow) {
+        foreach (QGraphicsItem *item, selection) {
+            if (item != this) {
+                if (item->parentItem() && item->parentItem()->isSelected()) {
+                    item->setSelected(false);
+                }
+            } else {
+                if (item->parentItem() && item->parentItem()->isSelected()) {
+                    item->parentItem()->setSelected(false);
+                }
+            }
+        }
+    }
+
+
+    foreach (QGraphicsItem *item, selection) {
+        WidgetBase *wid = qobject_cast<WidgetBase*>(item->toGraphicsObject());
+        if (wid) {
+            wid->setUserChange(PositionChange, true);
+        }
+    }
+
     WidgetBase::mouseMoveEvent(e);
 
+    foreach (QGraphicsItem *item, selection) {
+        WidgetBase *wid = qobject_cast<WidgetBase*>(item->toGraphicsObject());
+        if (wid) {
+            wid->setUserChange(PositionChange, false);
+        }
+    }
+
     m_mouseMoveEventStore->setLastPos(m_mouseMoveEventStore->pos());
     m_mouseMoveEventStore->setLastScenePos(m_mouseMoveEventStore->scenePos());
     m_mouseMoveEventStore->setLastScreenPos(m_mouseMoveEventStore->screenPos());
@@ -466,8 +502,11 @@
     umlScene()->setIsMouseMovingItems(false);
     WidgetBase::mouseReleaseEvent(event);
 
-    delete m_mouseMoveEventStore;
-    m_mouseMoveEventStore = 0;
+    if (m_mouseMoveEventStore) {
+        //TODO: Push cmds to stack.
+        delete m_mouseMoveEventStore;
+        m_mouseMoveEventStore = 0;
+    }
 }
 
 void UMLWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
@@ -494,22 +533,23 @@
             delete m_widgetHandle;
             m_widgetHandle = 0;
         }
-    } else if (change == QGraphicsItem::ItemPositionChange) {
-        // move all points of self associations before this widget is moved.
-        // normal adjusting is not enough for self association updation.
-        QPointF diff(value.toPointF() - pos());
+    } else if (change == QGraphicsItem::ItemPositionHasChanged) {
+        // adjust the association lines by new computations.
+        adjustAssociations(true);
+        // Move the self association widgets separately.
+        QPointF diff(pos() - m_itemPositionChangePos);
         foreach (AssociationWidget* assoc,
                 m_associationSpaceManager->associationWidgets()) {
             if (assoc->isSelf()) {
+                assoc->setUserChange(AssocAdjustChange, true);
+                //TODO: Push undo command
                 AssociationLine *line = assoc->associationLine();
                 for (int i = 0; i < line->count(); ++i) {
                     line->setPoint(i, line->point(i) + diff);
                 }
+                assoc->setUserChange(AssocAdjustChange, false);
             }
         }
-    } else if (change == QGraphicsItem::ItemPositionHasChanged) {
-        // adjust the association lines by new computations.
-        adjustAssociations();
     } else if (change == QGraphicsItem::ItemVisibleHasChanged) {
         foreach (TextItemGroup *grp, m_textItemGroups) {
             grp->updateVisibility();
--- branches/work/soc-umbrello/umbrello/widgets/umlwidget.h #1059925:1059926
@@ -151,7 +151,7 @@
     AssociationWidgetList associationWidgetList() const;
 
     virtual bool activate();
-    virtual void adjustAssociations();
+    virtual void adjustAssociations(bool userChangeAdjustAssoc);
 
     virtual void showPropertiesDialog();
 
--- branches/work/soc-umbrello/umbrello/widgets/widgetbase.cpp #1059925:1059926
@@ -643,6 +643,25 @@
     return isActivated();
 }
 
+bool WidgetBase::userChange(UserChangeType c) const
+{
+    return m_userChange.testFlag(c);
+}
+
+WidgetBase::UserChange WidgetBase::userChanges() const
+{
+    return m_userChange;
+}
+
+void WidgetBase::setUserChange(UserChangeType c, bool value)
+{
+    if (value) {
+        m_userChange = m_userChange & c;
+    } else {
+        m_userChange = m_userChange & ~c;
+    }
+}
+
 /**
  * A virtual method for the widget to display a property dialog box.
  * Subclasses should reimplment this appropriately.
@@ -1099,7 +1118,23 @@
  */
 QVariant WidgetBase::itemChange(GraphicsItemChange change, const QVariant& value)
 {
-    return QGraphicsItem::itemChange(change, value);
+    if (change == ItemPositionChange) {
+        m_itemPositionChangePos = pos();
+        if (userChange(PositionChange)) {
+            QPointF pt = value.toPointF();
+            pt = QPointF(qMax(pt.x(), qreal(0)), qMax(pt.y(), qreal(0)));
+            return QGraphicsObject::itemChange(change, pt);
+        }
+    }
+
+    if (change == ItemPositionHasChanged) {
+        if (userChange(PositionChange)) {
+            // TODO: Push move undo command
+
+        }
+    }
+
+    return QGraphicsObject::itemChange(change, value);
 }
 
 /**
--- branches/work/soc-umbrello/umbrello/widgets/widgetbase.h #1059925:1059926
@@ -84,6 +84,14 @@
         SizeHasChanged
     };
 
+    enum UserChangeType {
+        PositionChange = 0x1,
+        GeometryChange = 0x2,
+        AssocAdjustChange = 0x4
+    };
+    Q_DECLARE_FLAGS(UserChange, UserChangeType)
+
+
     explicit WidgetBase(UMLObject *object);
     virtual ~WidgetBase();
 
@@ -142,6 +150,10 @@
 
     virtual bool activate();
 
+    bool userChange(UserChangeType c) const;
+    UserChange userChanges() const;
+    void setUserChange(UserChangeType c, bool value = true);
+
     virtual void showPropertiesDialog();
 
     virtual bool loadFromXMI(QDomElement &qElement);
@@ -172,6 +184,8 @@
     QRectF m_boundingRect;
     QPainterPath m_shape;
 
+    QPointF m_itemPositionChangePos;
+
     /**
      * This acts like stash to temporarily store data in loadFromXMI, which
      * are then applied in the activation method.
@@ -205,6 +219,8 @@
     bool m_activated;
     WidgetInterfaceData *m_widgetInterfaceData;
 
+    UserChange m_userChange;
+
     bool m_usesDiagramLineColor:1;
     bool m_usesDiagramLineWidth:1;
     bool m_usesDiagramBrush:1;
@@ -231,6 +247,8 @@
 
 };
 
+Q_DECLARE_OPERATORS_FOR_FLAGS(WidgetBase::UserChange)
+
 /**
  * @return The bounding rectangle for this widget.
  * @see setBoundingRect




More information about the umbrello-devel mailing list