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

Gopala Krishna A krishna.ggk at gmail.com
Thu Jul 3 08:27:19 UTC 2008


SVN commit 827510 by gopala:

1) Implemented NewEnumWidget in terms of TextItems (hence enabling hover, tooltips for text inside enumwidget)
2) Fixed a bug in WidgetHandle (typo: had used minh instead of minw at 2 places)
3) Changed some test code for generating random gradients.



 M  +166 -99   newenumwidget.cpp  
 M  +10 -1     newenumwidget.h  
 M  +63 -16    test.cpp  
 M  +4 -0      test.h  
 M  +1 -0      textitem.cpp  
 M  +3 -3      widgethandle.cpp  


--- branches/work/soc-umbrello/umbrello/newenumwidget.cpp #827509:827510
@@ -26,14 +26,41 @@
 #include "widget_utils.h"
 #include "optionstate.h"
 #include "umlscene.h"
+#include "textitem.h"
 
+QBrush randHoverBrush()
+{
+    QLinearGradient grad(QPointF(0,0), QPointF(0, 1));
+    int r, g, b, a;
+    r = qrand() % 255;
+    g = qrand() % 255;
+    b = qrand() % 255;
+    a = 10 + qrand() % 245; // set minimum to atleast 10
+    grad.setColorAt(0, QColor(r, g, b, a));
+
+    r = qrand() % 255;
+    g = qrand() % 255;
+    b = qrand() % 255;
+    a = 10 + qrand() % 245; // set minimum to atleast 10
+    grad.setColorAt(1, QColor(r, g, b, a));
+
+    return QBrush(grad);
+}
+
 NewEnumWidget::NewEnumWidget(UMLObject* o) :
     NewUMLRectWidget(o),
-    m_showPackage(false)
+    m_showPackage(false),
+    m_stereoTypeItem(0),
+    m_nameItem(0)
 {
     m_baseType = Uml::wt_Enum;
 }
 
+NewEnumWidget::~NewEnumWidget()
+{
+    cleanup();
+}
+
 void NewEnumWidget::init()
 {
     if(umlScene()) {
@@ -65,68 +92,24 @@
                           const QStyleOptionGraphicsItem *option,
                           QWidget *widget)
 {
-    UMLClassifier *classifier = 0;
-    UMLClassifierListItemList list;
-
-    if(umlObject()) {
-        classifier = static_cast<UMLClassifier*>(umlObject());
-        list = classifier->getFilteredList(Uml::ot_EnumLiteral);
-    }
-
-    QFont fnt = NewUMLRectWidget::font();
-    // Get font metrics for max font type
-    fnt.setBold(true);
-    fnt.setItalic(true);
-    QFontMetricsF fm(fnt);
-    fnt.setItalic(false); // Reset italic.
-
-    qreal fontHeight  = fm.lineSpacing();
     const QSizeF sz = size();
     const QSizeF minSz = sizeHint(Qt::MinimumSize);
 
-    if(sz.height() > minSz.height()) {
-        fontHeight += (sz.height() - minSz.height()) / qreal(list.size() + 2);
-    }
+    // if(sz.height() > minSz.height()) {
+    //     fontHeight += (sz.height() - minSz.height()) / qreal(list.size() + 2);
+    // }
 
-    QRectF fontRect(ENUM_MARGIN, 0, sz.width() - ENUM_MARGIN * 2, fontHeight);
-
-
     painter->setPen(QPen(lineColor(), lineWidth()));
     painter->setBrush(brush());
     // First draw the outer rectangle with the pen and brush of this widget.
     painter->drawRect(rect());
-    painter->drawLine(QLineF(0, fontHeight * 2, sz.width() - 1, fontHeight * 2));
 
-    // Set the font pen and empty brush to draw the font.
-    painter->setPen(fontColor());
-    painter->setBrush(QBrush(Qt::NoBrush));
-    painter->setFont(fnt);
-
-    QString text = umlObject() ? umlObject()->getStereotype(true) : "<< >>";
-
-    painter->drawText(fontRect, Qt::AlignCenter, text);
-
-    bool italicNeeded = umlObject() ? umlObject()->getAbstract() : false;
-    fnt.setItalic(italicNeeded);
-    painter->setFont(fnt);
-    fontRect.moveTop(fontRect.top() + fontHeight);
-
-    QString nameText = name();
-    if(m_showPackage && umlObject()) {
-        nameText = umlObject()->getFullyQualifiedName();
+    if(m_nameItem) {
+        QPointF botLeft = m_nameItem->boundingRect().bottomLeft();
+        botLeft = m_nameItem->mapToParent(botLeft);
+        qreal y = botLeft.y();
+        painter->drawLine(QLineF(0, y, sz.width() - 1, y));
     }
-    painter->drawText(fontRect, Qt::AlignCenter, nameText);
-
-    qreal y = fontHeight * 2;
-    fnt.setBold(false);
-    fnt.setItalic(false);
-    painter->setFont(fnt);
-
-    foreach(UMLClassifierListItem* enumLiteral , list ) {
-        fontRect.moveTop(y);
-        painter->drawText(fontRect, Qt::AlignVCenter, enumLiteral->getName());
-        y += fontHeight;
-    }
 }
 
 bool NewEnumWidget::loadFromXMI( QDomElement & qElement )
@@ -149,67 +132,151 @@
 
 void NewEnumWidget::updateGeometry()
 {
-    calculateMinimumSize();
+    cleanup();
+    if(umlObject()) {
+        qreal maxWidth = 0;
+        UMLClassifier *classifier = static_cast<UMLClassifier*>(umlObject());
+
+        QBrush hoverBrush = randHoverBrush();
+        // Setup the steretype item first.
+
+        m_stereoTypeItem = new TextItem(umlObject()->getStereotype(true));
+        m_stereoTypeItem->setToolTip(m_stereoTypeItem->toPlainText());
+        m_stereoTypeItem->setDefaultTextColor(fontColor());
+        m_stereoTypeItem->setFont(font());
+        m_stereoTypeItem->setBold(true);
+        m_stereoTypeItem->setAcceptHoverEvents(true);
+        m_stereoTypeItem->setHoverBrush(hoverBrush);
+        m_stereoTypeItem->setAlignment(Qt::AlignCenter);
+        m_stereoTypeItem->adjustSize();
+
+        maxWidth = qMax(maxWidth, m_stereoTypeItem->boundingRect().width());
+
+        // Now setup the name item.
+
+        QString nameText = name();
+        if(m_showPackage) {
+            nameText = umlObject()->getFullyQualifiedName();
+        }
+        m_nameItem = new TextItem(nameText);
+        m_nameItem->setToolTip(m_nameItem->toPlainText());
+        m_nameItem->setDefaultTextColor(fontColor());
+        m_nameItem->setFont(font());
+        m_nameItem->setBold(true);
+        m_nameItem->setItalic(classifier->getAbstract());
+        m_nameItem->setAcceptHoverEvents(true);
+        m_nameItem->setHoverBrush(hoverBrush);
+        m_nameItem->setAlignment(Qt::AlignCenter);
+        m_nameItem->adjustSize();
+
+        maxWidth = qMax(maxWidth, m_nameItem->boundingRect().width());
+
+        // Now setup all the literals
+
+        foreach(UMLClassifierListItem* enumLiteral ,
+                classifier->getFilteredList(Uml::ot_EnumLiteral)) {
+            TextItem *literal = new TextItem(enumLiteral->getName());
+            literal->setToolTip(literal->toPlainText());
+            literal->setDefaultTextColor(fontColor());
+            literal->setFont(font());
+            literal->setAcceptHoverEvents(true);
+            literal->setHoverBrush(hoverBrush);
+            literal->setAlignment(Qt::AlignCenter);
+            literal->adjustSize();
+
+            m_enumLiteralItems.append(literal);
+            maxWidth = qMax(maxWidth, literal->boundingRect().width());
+        }
+
+        // Now align all these text items.
+        maxWidth = qMin(maxWidth, QFontMetricsF(font()).width('w') * 20);
+        maxWidth += ENUM_MARGIN * 2;
+        qreal y = 0;
+        QRectF newBound;
+
+        m_stereoTypeItem->setTextWidth(maxWidth);
+        m_stereoTypeItem->setParentItem(this);
+        m_stereoTypeItem->setPos(0, y);
+        y += m_stereoTypeItem->boundingRect().height();
+        newBound |= m_stereoTypeItem->sceneBoundingRect();
+
+        m_nameItem->setTextWidth(maxWidth);
+        if(umlScene()) {
+            umlScene()->addItem(m_nameItem);
+        }
+        m_nameItem->setParentItem(this);
+        m_nameItem->setPos(0, y);
+        y += m_nameItem->boundingRect().height();
+        newBound |= m_nameItem->sceneBoundingRect();
+
+        foreach(TextItem *literal, m_enumLiteralItems) {
+            literal->setTextWidth(maxWidth);
+            if(umlScene()) {
+                umlScene()->addItem(literal);
+            }
+            literal->setParentItem(this);
+            literal->setPos(0, y);
+            y += literal->boundingRect().height();
+            newBound |= literal->sceneBoundingRect();
+        }
+
+        m_minimumSize = newBound.size();
+    }
     NewUMLRectWidget::updateGeometry();
 }
 
-void NewEnumWidget::calculateMinimumSize()
+void NewEnumWidget::sizeHasChanged(const QSizeF& sz)
 {
-    if(!umlObject()) {
-        m_minimumSize.setWidth(100);
-        m_minimumSize.setHeight(100);
-        return;
-    }
+    const QSizeF minSz = sizeHint(Qt::MinimumSize);
 
-    qreal width, height;
-    QFont font = this->font();
-    font.setItalic(false);
-    font.setUnderline(false);
-    font.setBold(false);
-    const QFontMetricsF fm(font);
+    int visibleItems = 0;
 
-    const qreal fontHeight = fm.lineSpacing();
+    if(m_stereoTypeItem) {
+        m_stereoTypeItem->setTextWidth(sz.width());
+        ++visibleItems;
+    }
 
-    int lines = 1;//always have one line - for name
-    lines++; //for the stereotype
+    if(m_nameItem) {
+        m_nameItem->setTextWidth(sz.width());
+        ++visibleItems;
+    }
 
-    const int numberOfEnumLiterals = static_cast<UMLEnum*>(umlObject())->enumLiterals();
-    lines += numberOfEnumLiterals;
-
-    height = width = 0;
-    //set the height of the enum
-    if(numberOfEnumLiterals == 0) {
-        height += 0.5 * fontHeight; //no enum literals, so just add a bit of space
+    foreach(TextItem *literal, m_enumLiteralItems) {
+        literal->setTextWidth(sz.width());
+        ++visibleItems;
     }
 
-    height += lines * fontHeight;
-
-    font.setBold(true);
-    font.setItalic(true);
-    QString nameText = name();
-    if(m_showPackage && umlObject()) {
-        nameText = umlObject()->getFullyQualifiedName();
+    qreal spacing = 0;
+    if(sz.height() - minSz.height() > 0 && visibleItems != 0) {
+        spacing = (sz.height() - minSz.height()) / qreal(visibleItems);
     }
-    width = QFontMetricsF(font).boundingRect(nameText).width();
-    font.setItalic(false);
 
-    if(umlObject()) {
-        qreal w = QFontMetricsF(font).boundingRect(umlObject()->getStereotype(true)).width();
-        width = qMax(w, width);
+    if(spacing > 0) {
+        qreal y = 0;
+        if(m_stereoTypeItem) {
+            m_stereoTypeItem->setPos(0, y);
+            y += m_stereoTypeItem->boundingRect().height() + spacing;
+        }
 
-        UMLClassifier *classifier = static_cast<UMLClassifier*>(umlObject());
-        UMLClassifierListItemList list = classifier->getFilteredList(Uml::ot_EnumLiteral);
-        UMLClassifierListItem* listItem = 0;
+        if(m_nameItem) {
+            m_nameItem->setPos(0, y);
+            y += m_nameItem->boundingRect().height() + spacing;
+        }
 
-        foreach(listItem , list ) {
-            qreal w = fm.width(listItem->getName());
-            if(w > width)
-                width = w;
+        foreach(TextItem *literal, m_enumLiteralItems) {
+            literal->setPos(0, y);
+            y += literal->boundingRect().height() + spacing;
         }
     }
-    //allow for width margin
-    width += ENUM_MARGIN * 2;
+    NewUMLRectWidget::sizeHasChanged(sz);
+}
 
-    m_minimumSize.setWidth(width);
-    m_minimumSize.setHeight(height);
+void NewEnumWidget::cleanup()
+{
+    delete m_stereoTypeItem;
+    delete m_nameItem;
+    qDeleteAll(m_enumLiteralItems);
+
+    m_stereoTypeItem = m_nameItem = 0;
+    m_enumLiteralItems.clear();
 }
--- branches/work/soc-umbrello/umbrello/newenumwidget.h #827509:827510
@@ -24,6 +24,7 @@
 #include "newumlrectwidget.h"
 
 #define ENUM_MARGIN 5
+class TextItem;
 
 /**
  * @short A uml widget to visualize enum.
@@ -42,6 +43,8 @@
      */
     explicit NewEnumWidget(UMLObject* o);
 
+    ~NewEnumWidget();
+
     /**
      * Do some initialization which cannot be done inside constructor
      * as it involves calling virtual methods.
@@ -93,11 +96,17 @@
      */
     void updateGeometry();
 
+    void sizeHasChanged(const QSizeF& oldSize);
+
 private:
+    void cleanup();
+
     QSizeF m_minimumSize;
     bool m_showPackage;
 
-    void calculateMinimumSize();
+    TextItem *m_stereoTypeItem;
+    TextItem *m_nameItem;
+    QList<TextItem*> m_enumLiteralItems;
 };
 
 #endif // NEWENUMWIDGET_H
--- branches/work/soc-umbrello/umbrello/test.cpp #827509:827510
@@ -28,23 +28,29 @@
 #include <QtCore/QMetaObject>
 #include <QtCore/QMetaProperty>
 #include <QtCore/QTimerEvent>
+#include <QtCore/QTime>
+
 #include <kdebug.h>
 
 Test* Test::m_self = 0;
 
 struct TestPrivate
 {
-    TestPrivate() : scene(0), enumWidget(0)
-    {}
+    TestPrivate() : scene(0), enumWidget(0), enumObject(0), count(0)
+    {
+    }
 
     UMLScene *scene;
     QString xml;
     NewEnumWidget *enumWidget;
+    UMLEnum *enumObject;
+    int count;
 };
 
 Test::Test() :
     d(new TestPrivate)
 {
+    qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
 }
 
 Test* Test::self()
@@ -73,6 +79,7 @@
     uDebug() << "entered test";
 
     UMLEnum *en = new UMLEnum("Qt::SizeHint");
+    d->enumObject = en;
     en->createEnumLiteral("MinimumSize");
     en->createEnumLiteral("MaximumSize");
     en->createEnumLiteral("PreferredSize");
@@ -84,15 +91,8 @@
     wid->init();
     scene->addItem(wid);
     wid->setPos(40, 40);
-    QLinearGradient ling(QPointF(0, 0), QPointF(0, 1));
-    ling.setCoordinateMode(QGradient::ObjectBoundingMode);
 
-    QColor col1(Qt::darkGray);
-    QColor col2(Qt::lightGray);
-    ling.setColorAt(0, col1);
-    ling.setColorAt(1, col2);
-
-    wid->setBrush(QBrush(ling));
+    wid->setBrush(randomGradientBrush());
     wid->setSize(220, 120);
 
     QDomDocument doc("TEST");
@@ -104,7 +104,7 @@
 
     d->xml = doc.toString();
     d->enumWidget = wid;
-    wid->setBrush(Qt::darkYellow);
+    wid->setBrush(randomGradientBrush());
     uDebug() << "-------------------";
     uDebug() << d->xml;
     uDebug() << "-------------------";
@@ -115,15 +115,62 @@
     startTimer(3 * 1000);
 }
 
+QBrush Test::randomGradientBrush()
+{
+    QLinearGradient *gradient = new QLinearGradient();
+    gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
 
+    int h, s, v;
+    h = qrand() % 360;
+    s = qrand() % 255;
+    v = qrand() % 255;
+
+    QColor colorBottom = QColor::fromHsv(h, s, v);
+
+    colorBottom.toHsv().getHsv(&h, &s, &v);
+    int diff = 50;
+    if(v + diff <= 255) {
+        v += diff;
+    }
+    else {
+        v -= diff;
+    }
+
+    diff = 75;
+    if(s + diff <= 255) {
+        s += diff;
+    }
+    else {
+        s -= diff;
+    }
+    QColor colorTop = QColor::fromHsv(h, s, v);
+    gradient->setColorAt(0, colorTop);
+    gradient->setColorAt(1, colorBottom);
+
+    gradient->setStart(0, 0);
+    gradient->setFinalStop(0, 1);
+
+    QBrush retval(*gradient);
+    delete gradient;
+    return retval;
+}
+
 void Test::timerEvent(QTimerEvent *event)
 {
-    QDomDocument doc("TEST");
-    doc.setContent(d->xml);
+    if(d->count == 0) {
+        QDomDocument doc("TEST");
+        doc.setContent(d->xml);
 
-    QDomElement ele = doc.documentElement().firstChild().toElement();
-    d->enumWidget->loadFromXMI(ele);
-    killTimer(event->timerId());
+        QDomElement ele = doc.documentElement().firstChild().toElement();
+        d->enumWidget->loadFromXMI(ele);
+    }
+    else if(d->count < 8) {
+        d->enumObject->createEnumLiteral("MaximumSize" + QString::number(qrand() % 100));
+    }
+    else {
+        killTimer(event->timerId());
+    }
+    ++d->count;
 }
 
 #include "test.moc"
--- branches/work/soc-umbrello/umbrello/test.h #827509:827510
@@ -25,6 +25,8 @@
 // THIS IS USED TO ONLY TEST FEATURES OF THE PORT
 class UMLScene;
 class TestPrivate;
+class QBrush;
+
 class Test : public QObject
 {
     Q_OBJECT;
@@ -35,6 +37,8 @@
     static Test* self();
     static Test *m_self;
 
+    QBrush randomGradientBrush();
+
 protected:
     void timerEvent(QTimerEvent *event);
 
--- branches/work/soc-umbrello/umbrello/textitem.cpp #827509:827510
@@ -102,6 +102,7 @@
 
         p->drawRect(rect);
     }
+
     QGraphicsTextItem::paint(p, o, w);
 }
 
--- branches/work/soc-umbrello/umbrello/widgethandle.cpp #827509:827510
@@ -218,14 +218,14 @@
         }
 
         w = sp.x() - newRect.left();
-        if(w >= minh && w <= maxw) {
+        if(w >= minw && w <= maxw) {
             newRect.setRight(sp.x());
         }
         break;
 
     case rh_Right:
         w = sp.x() - newRect.left();
-        if(w >= minh && w <= maxw) {
+        if(w >= minw && w <= maxw) {
             newRect.setRight(sp.x());
         }
         break;
@@ -237,7 +237,7 @@
         }
 
         w = sp.x() - newRect.left();
-        if(w >= minh && w <= maxw) {
+        if(w >= minw && w <= maxw) {
             newRect.setRight(sp.x());
         }
         break;




More information about the umbrello-devel mailing list