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

Gopala Krishna A krishna.ggk at gmail.com
Sun Jul 20 21:06:32 UTC 2008


SVN commit 835615 by gopala:

Ported EntityWidget using TextItem framework classes.


 M  +132 -156  entitywidget.cpp  
 M  +25 -45    entitywidget.h  
 M  +2 -2      widget_factory.cpp  


--- branches/work/soc-umbrello/umbrello/entitywidget.cpp #835614:835615
@@ -12,182 +12,170 @@
 // own header
 #include "entitywidget.h"
 
-// qt/kde includes
-#include <qpainter.h>
-#include <kdebug.h>
-
 // app includes
+#include "classifier.h"
+#include "classifierlistitem.h"
 #include "entity.h"
 #include "entityattribute.h"
-#include "uniqueconstraint.h"
 #include "foreignkeyconstraint.h"
-#include "classifier.h"
-#include "umlclassifierlistitemlist.h"
-#include "classifierlistitem.h"
-#include "umlview.h"
-#include "umldoc.h"
-#include "uml.h"
 #include "listpopupmenu.h"
 #include "object_factory.h"
+#include "textitem.h"
+#include "textitemgroup.h"
+#include "uml.h"
+#include "umlclassifierlistitemlist.h"
+#include "umldoc.h"
+#include "uniqueconstraint.h"
 
+// qt includes
+#include <QtGui/QPainter>
 
-EntityWidget::EntityWidget(UMLScene* scene, UMLObject* o): NewUMLRectWidget(scene, o) {
-    init();
+const qreal EntityWidget::Margin = 5.0;
+
+/**
+ * Constructs an EntityWidget.
+ *
+ * @param o The UMLObject this will be representing.
+ */
+EntityWidget::EntityWidget(UMLObject* o) :
+	NewUMLRectWidget(o)
+{
+    m_baseType = Uml::wt_Entity;
+	m_textItemGroup = new TextItemGroup(this);
 }
 
-void EntityWidget::init() {
-    NewUMLRectWidget::setBaseType(Uml::wt_Entity);
-    setSize(100, 30);
+/// Destructor
+EntityWidget::~EntityWidget()
+{
+	delete m_textItemGroup;
+}
 
-    //set defaults from m_pView
-    if (umlScene()) {
-        //check to see if correct
-        //const Settings::OptionState& ops = m_pView->getOptionState();
-    }
-    if (! UMLApp::app()->getDocument()->loading())
-        updateComponentSize();
+/// Reimplemented from NewUMLRectWidget::sizeHint
+QSizeF EntityWidget::sizeHint(Qt::SizeHint which)
+{
+	if(which == Qt::MinimumSize) {
+		return m_minimumSize;
+	}
+	return NewUMLRectWidget::sizeHint(which);
 }
 
-EntityWidget::~EntityWidget() {}
-
+/**
+ * Reimplemented from NewUMLRectWidget::paint
+ *
+ * Draws the entity as a rectangle with a box underneith with a list
+ * of literals
+ */
 void EntityWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
 {
-	QPainter &p = *painter;
-	qreal offsetX = 0, offsetY = 0;
+	painter->setPen(QPen(lineColor(), lineWidth()));
+	painter->setBrush(brush());
 
-    setPenFromSettings(p);
-    if(NewUMLRectWidget::getUseFillColour())
-        p.setBrush(NewUMLRectWidget::getFillColour());
-    else {
-        // [PORT] StyleOption
-        // p.setBrush( m_pView->viewport()->palette().color(QPalette::Background) );
-    }
+	painter->drawRect(rect());
 
-    const qreal w = getWidth();
-    const qreal h = getHeight();
+	// Now get the position to draw the line.
+    const TextItem *item = m_textItemGroup->textItemAt(NameItemIndex);
+    const QPointF bottomLeft = item->mapToParent(item->boundingRect().bottomLeft());
+    const qreal y = bottomLeft.y();
+    painter->drawLine(QLineF(0, y, size().width() - 1, y));
+}
 
-    const QFontMetrics &fm = getFontMetrics(FT_NORMAL);
-    qreal fontHeight  = fm.lineSpacing();
-    const QString name = this->getName();
+/**
+ * Reimplemented from NewUMLRectWidget::saveToXMI to save this widget
+ * info to the "entitywidget" XMI element.
+ */
+void EntityWidget::saveToXMI( QDomDocument& qDoc, QDomElement& qElement )
+{
+    QDomElement conceptElement = qDoc.createElement("entitywidget");
+    NewUMLRectWidget::saveToXMI(qDoc, conceptElement);
+    qElement.appendChild(conceptElement);
+}
 
-    p.drawRect(offsetX, offsetY, w, h);
-    p.setPen(QPen(Qt::black));
+/**
+ * Reimplemented from NewUMLRectWidget::updateGeometry to apply the
+ * properties and calculate minimum size for this widget.
+ */
+void EntityWidget::updateGeometry()
+{
+	if(umlObject()) {
+		UMLClassifier *classifier = static_cast<UMLClassifier*>(umlObject());
+        UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EntityAttribute);
+        int totalTextItems = list.size() + 2; // +2 because stereo text + name text.
 
-    QFont font = NewUMLRectWidget::getFont();
-    font.setBold(true);
-    p.setFont(font);
-    qreal y = 0;
-    if ( !umlObject()->getStereotype().isEmpty() ) {
-        p.drawText(offsetX + ENTITY_MARGIN, offsetY,
-                   w - ENTITY_MARGIN * 2,fontHeight,
-                   Qt::AlignCenter, umlObject()->getStereotype(true));
-        font.setItalic( umlObject()->getAbstract() );
-        p.setFont(font);
-        p.drawText(offsetX + ENTITY_MARGIN, offsetY + fontHeight,
-                   w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
-        font.setBold(false);
-        font.setItalic(false);
-        p.setFont(font);
-        y = fontHeight * 2;
-    } else {
-        font.setItalic( umlObject()->getAbstract() );
-        p.setFont(font);
-        p.drawText(offsetX + ENTITY_MARGIN, offsetY,
-                   w - ENTITY_MARGIN * 2, fontHeight, Qt::AlignCenter, name);
-        font.setBold(false);
-        font.setItalic(false);
-        p.setFont(font);
+		// Ensure there are appropriate number of textitems.
+        m_textItemGroup->ensureTextItemCount(totalTextItems);
 
-        y = fontHeight;
-    }
+        // Create a dummy item with the common properties set on
+        // it. We can then use TextItem::copyAttributesTo method to
+        // copy these common attributes, just to avoid some code
+        // duplication.
+        TextItem dummy("");
+        dummy.setDefaultTextColor(fontColor());
+        dummy.setFont(font());
+        dummy.setAlignment(Qt::AlignCenter);
+        dummy.setBackgroundBrush(Qt::NoBrush);
 
-    setPenFromSettings(p);
+		TextItem *stereo = m_textItemGroup->textItemAt(EntityWidget::StereotypeItemIndex);
+        stereo->setText(classifier->getStereotype(true));
+        dummy.copyAttributesTo(stereo);
+        stereo->setBold(true);
+		bool hideStereo = classifier->getStereotype(false).isEmpty();
+		stereo->setVisible(!hideStereo);
 
-    p.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y);
+        TextItem *nameItem = m_textItemGroup->textItemAt(EntityWidget::NameItemIndex);
+        nameItem->setText(name());
+        dummy.copyAttributesTo(nameItem);
+        nameItem->setBold(true);
+        nameItem->setItalic(classifier->getAbstract());
 
-    QFontMetrics fontMetrics(font);
-    UMLClassifier *classifier = (UMLClassifier*)umlObject();
-    UMLClassifierListItem* entityattribute = 0;
-    UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EntityAttribute);
-    foreach (entityattribute , list ) {
-        QString text = entityattribute->getName();
-        p.setPen( QPen(Qt::black) );
-        UMLEntityAttribute* casted = dynamic_cast<UMLEntityAttribute*>( entityattribute );
-        if( casted && casted->getIndexType() == Uml::Primary )
-        {
-            font.setUnderline( true );
-            p.setFont( font );
-            font.setUnderline( false );
+        int index = EntityWidget::EntityItemStartIndex;
+        foreach(UMLClassifierListItem* entityItem, list) {
+            TextItem *literal = m_textItemGroup->textItemAt(index);
+            literal->setText(entityItem->getName());
+            dummy.copyAttributesTo(literal);
+			UMLEntityAttribute* casted = dynamic_cast<UMLEntityAttribute*>(entityItem);
+			if( casted && casted->getIndexType() == Uml::Primary ) {
+				literal->setUnderline(true);
+			}
+            ++index;
         }
-        p.drawText(offsetX + ENTITY_MARGIN, offsetY + y,
-                   fontMetrics.width(text), fontHeight, Qt::AlignVCenter, text);
-        p.setFont( font );
-        y+=fontHeight;
-    }
 
-    if (isSelected()) {
-        drawSelected(&p, offsetX, offsetY);
+        m_minimumSize = m_textItemGroup->calculateMinimumSize();
+
+		// FIXME: The width doesn't function as expected if it is Margin * 2
+        m_minimumSize += QSizeF(EntityWidget::Margin * 3, EntityWidget::Margin * 2);
     }
+    NewUMLRectWidget::updateGeometry();
 }
 
-QSizeF EntityWidget::calculateSize() {
-    if (!umlObject()) {
-        return NewUMLRectWidget::calculateSize();
-    }
+/**
+ * Reimplemented from NewUMLRectWidget::sizeHasChanged to align and
+ * position the text items.
+ */
+void EntityWidget::sizeHasChanged(const QSizeF& oldSize)
+{
+	QSizeF groupSize = size();
+    groupSize -= QSizeF(EntityWidget::Margin * 2, EntityWidget::Margin * 2);
+    QPointF offset(EntityWidget::Margin, EntityWidget::Margin);
 
-    qreal width, height;
-    QFont font = NewUMLRectWidget::getFont();
-    font.setItalic(false);
-    font.setUnderline(false);
-    font.setBold(false);
-    const QFontMetrics fm(font);
+    m_textItemGroup->alignVertically(groupSize);
+    m_textItemGroup->setPos(offset);
 
-    const qreal fontHeight = fm.lineSpacing();
-
-    int lines = 1;//always have one line - for name
-    if ( !umlObject()->getStereotype().isEmpty() ) {
-        lines++;
-    }
-
-    const int numberOfEntityAttributes = ((UMLEntity*)umlObject())->entityAttributes();
-
-    height = width = 0;
-    //set the height of the entity
-
-    lines += numberOfEntityAttributes;
-    if (numberOfEntityAttributes == 0) {
-        height += fontHeight / 2; //no entity literals, so just add a bit of space
-    }
-
-    height += lines * fontHeight;
-
-    //now set the width of the concept
-    //set width to name to start with
-    // FIXME spaces to get round beastie with font width,
-    // investigate NewUMLRectWidget::getFontMetrics()
-    width = getFontMetrics(FT_BOLD_ITALIC).boundingRect(' ' + getName() + ' ').width();
-
-    const qreal w = getFontMetrics(FT_BOLD).boundingRect(umlObject()->getStereotype(true)).width();
-
-    width = w > width?w:width;
-
-    UMLClassifier* classifier = (UMLClassifier*)umlObject();
-    UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EntityAttribute);
-    UMLClassifierListItem* listItem = 0;
-    foreach (listItem , list ) {
-        qreal w = fm.width( listItem->getName() );
-        width = w > width?w:width;
-    }
-
-    //allow for width margin
-    width += ENTITY_MARGIN * 2;
-
-    return QSizeF(width, height);
+    NewUMLRectWidget::sizeHasChanged(oldSize);
 }
 
-void EntityWidget::slotMenuSelection(QAction* action) {
-    ListPopupMenu::Menu_Type sel = m_pMenu->getMenuType(action);
-    switch(sel) {
+/**
+ * Will be called when a menu selection has been made from the popup
+ * menu.
+ *
+ * @param action       The action that has been selected.
+ */
+void EntityWidget::slotMenuSelection(QAction* action)
+{
+	// The menu is passed in as parent of the action.
+	ListPopupMenu *menu = qobject_cast<ListPopupMenu*>(action->parent());
+	ListPopupMenu::Menu_Type sel = menu->getMenuType(action);
+
+	switch(sel) {
     case ListPopupMenu::mt_EntityAttribute:
         if (Object_Factory::createChildObject(static_cast<UMLClassifier*>(umlObject()),
                                               Uml::ot_EntityAttribute) )  {
@@ -230,16 +218,4 @@
 
 }
 
-void EntityWidget::saveToXMI( QDomDocument& qDoc, QDomElement& qElement ) {
-    QDomElement conceptElement = qDoc.createElement("entitywidget");
-    NewUMLRectWidget::saveToXMI(qDoc, conceptElement);
-    qElement.appendChild(conceptElement);
-}
-
-bool EntityWidget::loadFromXMI( QDomElement & qElement ) {
-    if ( !NewUMLRectWidget::loadFromXMI(qElement) ) {
-        return false;
-    }
-    return true;
-}
-
+#include "entitywidget.moc"
--- branches/work/soc-umbrello/umbrello/entitywidget.h #835614:835615
@@ -12,72 +12,52 @@
 #ifndef ENTITYWIDGET_H
 #define ENTITYWIDGET_H
 
-#include "umlwidget.h"
+#include "newumlrectwidget.h"
 
-class UMLView;
+// Forward declarations
+class TextItemGroup;
 
-#define ENTITY_MARGIN 5
-
 /**
  * Defines a graphical version of the entity.  Most of the functionality
  * will come from the @ref NewUMLRectWidget class from which class inherits from.
  *
  * @short A graphical version of an entity.
  * @author Jonathan Riddell
+ * @author Gopala Krishna (port using TextItems)
  * @see NewUMLRectWidget
  * Bugs and comments to uml-devel at lists.sf.net or http://bugs.kde.org
  */
 class EntityWidget : public NewUMLRectWidget
 {
+	Q_OBJECT
 public:
+	EntityWidget(UMLObject* o);
+	~EntityWidget();
 
-    /**
-     * Constructs an EntityWidget.
-     *
-     * @param view              The parent of this EntityWidget.
-     * @param o         The UMLObject this will be representing.
-     */
-    EntityWidget(UMLScene* scene, UMLObject* o);
+	QSizeF sizeHint(Qt::SizeHint which);
+	void paint(QPainter *p, const QStyleOptionGraphicsItem *item, QWidget *w);
 
-    /**
-     * Standard deconstructor.
-     */
-    ~EntityWidget();
-
-    /**
-     * Initializes key variables of the class.
-     */
-    void init();
-
-    /**
-     * Draws the entity as a rectangle with a box underneith with a list of literals
-     */
-    void paint(QPainter *p, const QStyleOptionGraphicsItem *item, QWidget *w);
-
-    /**
-     * Saves to the "entitywidget" XMI element.
-     */
+    // NewUMLRectWidget::loadFromXMI is used to load this widget.
     void saveToXMI(QDomDocument& qDoc, QDomElement& qElement);
 
-    /**
-     * Loads from an "entitywidget" XMI element.
-     */
-    bool loadFromXMI(QDomElement& qElement);
-
 protected:
-    /**
-     * Overrides method from NewUMLRectWidget.
-     */
-    QSizeF calculateSize();
+	void updateGeometry();
+	void sizeHasChanged(const QSizeF& oldSize);
 
-public slots:
-    /**
-     * Will be called when a menu selection has been made from the
-     * popup menu.
-     *
-     * @param action       The action that has been selected.
-     */
+public Q_SLOTS:
     void slotMenuSelection(QAction* action);
+
+private:
+	static const qreal Margin;
+	// Indices for text items in m_textItemGroup
+	enum {
+		StereotypeItemIndex,
+		NameItemIndex,
+		EntityItemStartIndex
+	};
+
+	QSizeF m_minimumSize;
+	TextItemGroup *m_textItemGroup;
 };
 
 #endif
--- branches/work/soc-umbrello/umbrello/widget_factory.cpp #835614:835615
@@ -107,7 +107,7 @@
         newWidget = new EnumWidget(static_cast<UMLEnum*>(o));
         break;
     case Uml::ot_Entity:
-        newWidget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
+        newWidget = new EntityWidget(static_cast<UMLEntity*>(o));
         break;
     case Uml::ot_Interface:
         if (diagramType == Uml::dt_Sequence || diagramType == Uml::dt_Collaboration) {
@@ -262,7 +262,7 @@
                 widget = new EnumWidget(static_cast<UMLEnum*>(o));
         } else if (tag == "entitywidget") {
             if (validateObjType(Uml::ot_Entity, o, id))
-                widget = new EntityWidget(scene, static_cast<UMLEntity*>(o));
+                widget = new EntityWidget(static_cast<UMLEntity*>(o));
         } else if (tag == "categorywidget") {
             if (validateObjType(Uml::ot_Category, o, id))
                 widget = new CategoryWidget(static_cast<UMLCategory*>(o));




More information about the umbrello-devel mailing list