Logo Search packages:      
Sourcecode: kdesdk-kde4 version File versions  Download package

umlview.cpp

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   copyright (C) 2002-2007                                               *
 *   Umbrello UML Modeller Authors <uml-devel@uml.sf.net>                  *
 ***************************************************************************/

// own header
#include "umlview.h"

// system includes
#include <climits>
#include <math.h>

// include files for Qt
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVector>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <QtGui/QPrinter>
#include <QtGui/QColor>
#include <QtGui/QMatrix>
#include <q3paintdevicemetrics.h>

//Added by qt3to4:
#include <QHideEvent>
#include <QCloseEvent>
#include <QDropEvent>
#include <QShowEvent>
#include <QDragEnterEvent>
#include <QMouseEvent>

//kde include files
#include <ktemporaryfile.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <kcursor.h>
#include <kfiledialog.h>
#include <kinputdialog.h>
#include <klocale.h>
#include <kdebug.h>

// application specific includes
#include "umlviewimageexporter.h"
#include "listpopupmenu.h"
#include "uml.h"
#include "umldoc.h"
#include "umlobject.h"
#include "docwindow.h"
#include "assocrules.h"
#include "umlrole.h"
#include "umlviewcanvas.h"
#include "dialogs/classoptionspage.h"
#include "dialogs/umlviewdialog.h"
#include "clipboard/idchangelog.h"
#include "clipboard/umldragdata.h"
#include "widget_factory.h"
#include "floatingtextwidget.h"
#include "classifierwidget.h"
#include "classifier.h"
#include "packagewidget.h"
#include "package.h"
#include "folder.h"
#include "componentwidget.h"
#include "nodewidget.h"
#include "artifactwidget.h"
#include "datatypewidget.h"
#include "enumwidget.h"
#include "entitywidget.h"
#include "actorwidget.h"
#include "usecasewidget.h"
#include "notewidget.h"
#include "boxwidget.h"
#include "associationwidget.h"
#include "objectwidget.h"
#include "messagewidget.h"
#include "statewidget.h"
#include "signalwidget.h"
#include "forkjoinwidget.h"
#include "activitywidget.h"
#include "objectnodewidget.h"
#include "pinwidget.h"
#include "seqlinewidget.h"
#include "uniqueid.h"
#include "umllistviewitemlist.h"
#include "umllistviewitem.h"
#include "umllistview.h"
#include "umlobjectlist.h"
#include "association.h"
#include "attribute.h"
#include "model_utils.h"
#include "object_factory.h"
#include "umlwidget.h"
#include "toolbarstatefactory.h"
#include "cmds.h"
#include "entity.h"
#include "foreignkeyconstraint.h"

// control the manual DoubleBuffering of QCanvas
// with a define, so that this memory X11 effect can
// be tested more easily
#define MANUAL_CONTROL_DOUBLE_BUFFERING

// static members
const int UMLView::defaultCanvasSize = 1300;

using namespace Uml;


// constructor
00116 UMLView::UMLView(UMLFolder *parentFolder) : Q3CanvasView(UMLApp::app()->getMainViewWidget()) {
    init();
    m_pDoc = UMLApp::app()->getDocument();
    m_pFolder = parentFolder;
}

00122 void UMLView::init() {
    // Initialize loaded/saved data
    m_nID = Uml::id_None;
    m_pDoc = NULL;
    m_Documentation = "";
    m_Type = dt_Undefined;
    m_bUseSnapToGrid = false;
    m_bUseSnapComponentSizeToGrid = false;
    m_bShowSnapGrid = false;
    m_nSnapX = 10;
    m_nSnapY = 10;
    m_nZoom = 100;
    m_nCanvasWidth = UMLView::defaultCanvasSize;
    m_nCanvasHeight = UMLView::defaultCanvasSize;
    m_nCollaborationId = 0;

    // Initialize other data
    //m_AssociationList.setAutoDelete( true );
    //m_WidgetList.setAutoDelete( true );
    //m_MessageList.setAutoDelete( true );

    //Setup up booleans
    m_bChildDisplayedDoc = false;
    m_bPaste = false;
    m_bActivated = false;
    m_bCreateObject = false;
    m_bDrawSelectedOnly = false;
    m_bPopupShowing = false;
    m_bStartedCut = false;
    //clear pointers
    m_PastePoint = QPoint(0, 0);
    m_pIDChangesLog = 0;
    m_pMenu = 0;

    m_pImageExporter = new UMLViewImageExporter(this);

    //setup graphical items
    viewport() -> setBackgroundMode( Qt::NoBackground );
    setCanvas( new UMLViewCanvas( this ) );
    // don't set the quite frequent update rate for each
    // diagram, as that causes also an update of invisible
    // diagrams, which can cost high CPU load for many
    // diagrams.
    // Instead: set the updatePeriod to 20 on Show event,
    //          and switch update back off on Hide event
    canvas() -> setUpdatePeriod( -1 );
    resizeContents(defaultCanvasSize, defaultCanvasSize);
    canvas() -> resize(defaultCanvasSize, defaultCanvasSize);
    setAcceptDrops(true);
    viewport() -> setAcceptDrops(true);
    setDragAutoScroll(false);

    viewport() -> setMouseTracking(false);

    //setup signals
    connect( this, SIGNAL(sigRemovePopupMenu()), this, SLOT(slotRemovePopupMenu() ) );
    connect( UMLApp::app(), SIGNAL( sigCutSuccessful() ),
             this, SLOT( slotCutSuccessful() ) );

    // Create the ToolBarState factory. This class is not a singleton, because it
    // needs a pointer to this object.
    m_pToolBarStateFactory = new ToolBarStateFactory();
    m_pToolBarState = m_pToolBarStateFactory->getState(WorkToolBar::tbb_Arrow, this);

}

00188 UMLView::~UMLView() {
    delete m_pImageExporter;

    if(m_pIDChangesLog) {
        delete    m_pIDChangesLog;
        m_pIDChangesLog = 0;
    }

    // before we can delete the QCanvas, all widgets must be explicitly
    // removed
    // otherwise the implicit remove of the contained widgets will cause
    // events which would demand a valid connected QCanvas
    // ==> this causes umbrello to crash for some - larger?? - projects
    // first avoid all events, which would cause some update actions
    // on deletion of each removed widget
    blockSignals( true );
    removeAllWidgets();

    delete m_pToolBarStateFactory;
    m_pToolBarStateFactory = NULL;

    // Qt Doc for QCanvasView::~QCanvasView () states:
    // "Destroys the canvas view. The associated canvas is not deleted."
    // we should do it now
    delete canvas();
}

00215 QString UMLView::getName() const {
    return m_Name;
}

00219 void UMLView::setName(const QString &name) {
    m_Name = name;
}

00223 int UMLView::generateCollaborationId() {
    return ++m_nCollaborationId;
}

00227 void UMLView::print(QPrinter *pPrinter, QPainter & pPainter) {
    int height, width;
    //get the size of the page
    pPrinter->setFullPage( true );
    Q3PaintDeviceMetrics metrics(pPrinter);
    QFontMetrics fm = pPainter.fontMetrics(); // use the painter font metrics, not the screen fm!
    int fontHeight  = fm.lineSpacing();
    uint left, right, top, bottom;
    // fetch printer margins individual for all four page sides, as at least top and bottom are not the same
    pPrinter->margins ( &top, &left, &bottom, &right );
    // give a little extra space at each side
    left += 2;
    right += 2;
    top += 2;
    bottom += 2;

    if(pPrinter->orientation() == QPrinter::Landscape) {
        // we are printing in LANDSCAPE --> swap marginX and marginY
        uint right_old = right;
        // the DiagramRight side is printed at PrintersTop
        right = top;
        // the DiagramTop side is printed at PrintersLeft
        top = left;
        // the DiagramLeft side is printed at PrintersBottom
        left = bottom;
        // the DiagramBottom side is printed at PrintersRight
        bottom = right_old;
    }

    // The printer will probably use a different font with different font metrics,
    // force the widgets to update accordingly on paint
    forceUpdateWidgetFontMetrics(&pPainter);

    width = metrics.width() - left - right;
    height = metrics.height() - top - bottom;

    //get the smallest rect holding the diagram
    QRect rect = getDiagramRect();
    //now draw to printer

#if 0
    int offsetX = 0, offsetY = 0, widthX = 0, heightY = 0;
    // respect the margin
    pPainter.translate(marginX, marginY);

    // clip away everything outside of the margin
    pPainter.setClipRect(marginX, marginY,
                         width, metrics.height() - marginY * 2);

    //loop until all of the picture is printed
    int numPagesX = (int)ceil((double)rect.width()/(double)width);
    int numPagesY = (int)ceil((double)rect.height()/(double)height);
    int page = 0;

    // print the canvas to multiple pages
    for (int pageY = 0; pageY < numPagesY; ++pageY) {
        // tile vertically
        offsetY = pageY * height + rect.y();
        heightY = (pageY + 1) * height > rect.height()
                  ? rect.height() - pageY * height
                  : height;
        for (int pageX = 0; pageX < numPagesX; ++pageX) {
            // tile horizontally
            offsetX = pageX * width + rect.x();
            widthX = (pageX + 1) * width > rect.width()
                     ? rect.width() - pageX * width
                     : width;

            // make sure the part of the diagram is painted at the correct
            // place in the printout
            pPainter.translate(-offsetX,-offsetY);
            getDiagram(QRect(offsetX, offsetY,widthX, heightY),
                       pPainter);
            // undo the translation so the coordinates for the painter
            // correspond to the page again
            pPainter.translate(offsetX,offsetY);

            //draw foot note
            QString string = i18n("Diagram: %2 Page %1", page + 1, getName());
            QColor textColor(50, 50, 50);
            pPainter.setPen(textColor);
            pPainter.drawLine(0, height + 2, width, height + 2);
            pPainter.drawText(0, height + 4, width, fontHeight, Qt::AlignLeft, string);

            if(pageX+1 < numPagesX || pageY+1 < numPagesY) {
                pPrinter -> newPage();
                page++;
            }
        }
    }
#else
    // be gentle - as described in Qt-Doc "The Coordinate System"
    pPainter.save();

    int diagramHeight = rect.height();
    // + 4+fontHeight between diagram and footline as space-buffer
    // + 2            between line and foot-text
    // + 1            for foot-line
    // + fontHeight   for foot-text
    // ==============
    // (2*fontHeight) + 7
    int footHeight;
    int footTop;
    int drawHeight;
    bool isFooter = getOptionState().generalState.footerPrinting;
    if (isFooter)
    {
        footHeight = (2*fontHeight) + 7;
        footTop    = rect.y() + diagramHeight  + 4+fontHeight;
        drawHeight = diagramHeight  + footHeight;
    }
    else
    {
        footHeight = 0;
        footTop    = rect.y() + diagramHeight;
        drawHeight = diagramHeight;
    }

    // set window of painter to dimensions of diagram
    // set window to viewport relation so that x:y isn't changed
    double dScaleX = (double)rect.width()/ (double)width;
    double dScaleY = (double)drawHeight/ (double)height;
    // select the scaling factor so that the larger dimension
    // fits on the printer page -> use the larger scaling factor
    // -> the virtual diagram window has some additional space at the
    // shorter dimension
    double dScaleUse = ( dScaleX > dScaleY )?dScaleX:dScaleY;

    int windowWidth  = (int)ceil(dScaleUse*width);
    int windowHeight = (int)ceil(dScaleUse*height);
#ifdef DEBUG_PRINTING
    uDebug() << "drawHeight: " << drawHeight << ", width: " << rect.width()
              << "\nPageHeight: " << height << ", PageWidht: " << width
              << "\nScaleY: " << dScaleY << ", ScaleX: " << dScaleX
              << "\ndScaleUse: " << dScaleUse
              << "\nVirtualSize: Width: " << windowWidth << ", Height: " << windowHeight
              << "\nFoot Top: " << footTop
              << endl;
#endif
    // set virtual drawing area window - where diagram fits 100% in
    pPainter.setWindow( rect.x(), rect.y(), windowWidth, windowHeight );

    // set viewport - the physical mapping
    // --> Qt's QPainter will map all drawed elements from diagram area ( window )
    //     to printer area ( viewport )
    pPainter.setViewport( left, top, width, height );

    // get Diagram
    getDiagram(QRect(rect.x(), rect.y(), windowWidth, diagramHeight), pPainter);

    if (isFooter)
    {
        //draw foot note
        QString string = i18n("Diagram: %2 Page %1", 1, getName());
        QColor textColor(50, 50, 50);
        pPainter.setPen(textColor);
        pPainter.drawLine(rect.x(), footTop    , windowWidth, footTop);
        pPainter.drawText(rect.x(), footTop + 3, windowWidth, fontHeight, Qt::AlignLeft, string);
    }
    // now restore scaling
    pPainter.restore();

#endif
    // next painting will most probably be to a different device (i.e. the screen)
    forceUpdateWidgetFontMetrics(0);
}

00394 void UMLView::setupNewWidget(UMLWidget *w) {
    w->setX( m_Pos.x() );
    w->setY( m_Pos.y() );
    w->setVisible( true );
    w->setActivated();
    w->setFont( getFont() );
    w->slotColorChanged( getID() );
    w->slotLineWidthChanged( getID() );
    resizeCanvasToItems();
    m_WidgetList.append( w );
    m_pDoc->setModified();

    UMLApp::app()->executeCommand(new cmdCreateWidget(this, w));
}

00409 void UMLView::contentsMouseReleaseEvent(QMouseEvent* ome) {
    m_pToolBarState->mouseRelease(ome);
}

00413 void UMLView::slotToolBarChanged(int c) {
    m_pToolBarState->cleanBeforeChange();
    m_pToolBarState = m_pToolBarStateFactory->getState((WorkToolBar::ToolBar_Buttons)c, this);
    m_pToolBarState->init();

    m_bPaste = false;
}

00421 void UMLView::showEvent(QShowEvent* /*se*/) {

# ifdef MANUAL_CONTROL_DOUBLE_BUFFERING
    //uWarning() << "Show Event for " << getName();
    canvas()->setDoubleBuffering( true );
    // as the diagram gets now visible again,
    // the update of the diagram elements shall be
    // at the normal value of 20
    canvas()-> setUpdatePeriod( 20 );
# endif

    UMLApp* theApp = UMLApp::app();
    WorkToolBar* tb = theApp->getWorkToolBar();
    connect(tb,SIGNAL(sigButtonChanged(int)), this, SLOT(slotToolBarChanged(int)));
    connect(this,SIGNAL(sigResetToolBar()), tb, SLOT(slotResetToolBar()));
    connect(m_pDoc, SIGNAL(sigObjectCreated(UMLObject *)),
            this, SLOT(slotObjectCreated(UMLObject *)));
    connect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
            UMLApp::app()->getDocWindow(), SLOT(slotAssociationRemoved(AssociationWidget*)));
    connect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)),
            UMLApp::app()->getDocWindow(), SLOT(slotWidgetRemoved(UMLWidget*)));
    resetToolbar();

}

00446 void UMLView::hideEvent(QHideEvent* /*he*/) {
    UMLApp* theApp = UMLApp::app();
    WorkToolBar* tb = theApp->getWorkToolBar();
    disconnect(tb,SIGNAL(sigButtonChanged(int)), this, SLOT(slotToolBarChanged(int)));
    disconnect(this,SIGNAL(sigResetToolBar()), tb, SLOT(slotResetToolBar()));
    disconnect(m_pDoc, SIGNAL(sigObjectCreated(UMLObject *)), this, SLOT(slotObjectCreated(UMLObject *)));
    disconnect(this, SIGNAL(sigAssociationRemoved(AssociationWidget*)),
               UMLApp::app()->getDocWindow(), SLOT(slotAssociationRemoved(AssociationWidget*)));
    disconnect(this, SIGNAL(sigWidgetRemoved(UMLWidget*)),
               UMLApp::app()->getDocWindow(), SLOT(slotWidgetRemoved(UMLWidget*)));

# ifdef MANUAL_CONTROL_DOUBLE_BUFFERING
    //uWarning() << "Hide Event for " << getName();
    canvas()->setDoubleBuffering( false );
    // a periodic update of all - also invisible - diagrams
    // can cause a very high CPU load if more than 100diagrams
    // are inside a project - and this without any need
    // => switch the update off for hidden diagrams
    canvas()-> setUpdatePeriod( -1 );
# endif
}

void UMLView::slotObjectCreated(UMLObject* o) {
    m_bPaste = false;
    //check to see if we want the message
    //may be wanted by someone else e.g. list view

    if (!m_bCreateObject)  {
        return;
    }

    UMLWidget* newWidget = Widget_Factory::createWidget(this, o);

    if (newWidget == NULL)
        return;

    newWidget->setVisible( true );
    newWidget->setActivated();
    newWidget->setFont( getFont() );
    newWidget->slotColorChanged( getID() );
    newWidget->slotLineWidthChanged( getID() );
    newWidget->updateComponentSize();

    if (m_Type == Uml::dt_Sequence) {
        // Set proper position on the sequence line widget which is
        // attached to the object widget.
        ObjectWidget *ow = dynamic_cast<ObjectWidget*>(newWidget);
        if (ow)
            ow->moveEvent(NULL);
    }
    m_bCreateObject = false;
    m_WidgetList.append(newWidget);

    switch (o->getBaseType()) {
    case ot_Actor:
    case ot_UseCase:
    case ot_Class:
    case ot_Package:
    case ot_Component:
    case ot_Node:
    case ot_Artifact:
    case ot_Interface:
    case ot_Enum:
    case ot_Entity:
    case ot_Datatype:
    case ot_Category:
        createAutoAssociations(newWidget);
        // We need to invoke createAutoAttributeAssociations()
        // on all other widgets again because the newly created
        // widget might saturate some latent attribute assocs.
        foreach (UMLWidget* w,  m_WidgetList ) {
            if (w != newWidget) {
                createAutoAttributeAssociations(w);

                if ( o->getBaseType() == ot_Entity )
                  createAutoConstraintAssociations(w);
            }
        }
        break;
    default:
        break;
    }
    resizeCanvasToItems();
}

void UMLView::slotObjectRemoved(UMLObject * o) {
    m_bPaste = false;
    Uml::IDType id = o->getID();

    foreach ( UMLWidget* obj, m_WidgetList ) {
        if(obj -> getID() != id)
            continue;
        removeWidget(obj);
        break;
    }
}

00543 void UMLView::dragEnterEvent(QDragEnterEvent *e) {
    UMLDragData::LvTypeAndID_List tidList;
    if(!UMLDragData::getClip3TypeAndID(e->mimeData(), tidList)) {
        return;
    }
    UMLDragData::LvTypeAndID_It tidIt(tidList);
    UMLDragData::LvTypeAndID * tid = tidIt.current();
    if (!tid) {
        uDebug() << "UMLDragData::getClip3TypeAndID returned empty list" << endl;
        return;
    }
    ListView_Type lvtype = tid->type;
    Uml::IDType id = tid->id;

    Diagram_Type diagramType = getType();

    UMLObject* temp = 0;
    //if dragging diagram - might be a drag-to-note
    if (Model_Utils::typeIsDiagram(lvtype)) {
        e->accept();
        return;
    }
    //can't drag anything onto state/activity diagrams
    if( diagramType == dt_State || diagramType == dt_Activity) {
        e->ignore();
        return;
    }
    //make sure can find UMLObject
    if( !(temp = m_pDoc->findObjectById(id) ) ) {
        uDebug() << "object " << ID2STR(id) << " not found";
        e->ignore();
        return;
    }
    //make sure dragging item onto correct diagram
    // concept - class,seq,coll diagram
    // actor,usecase - usecase diagram
    Object_Type ot = temp->getBaseType();
    bool bAccept = true;
    switch (diagramType) {
        case dt_UseCase:
            if ((widgetOnDiagram(id) && ot == ot_Actor) ||
                (ot != ot_Actor && ot != ot_UseCase))
                bAccept = false;
            break;
        case dt_Class:
            if (widgetOnDiagram(id) ||
                (ot != ot_Class &&
                 ot != ot_Package &&
                 ot != ot_Interface &&
                 ot != ot_Enum &&
                 ot != ot_Datatype)) {
                bAccept = false;
            }
            break;
        case dt_Sequence:
        case dt_Collaboration:
            if (ot != ot_Class &&
                ot != ot_Interface &&
                ot != ot_Actor)
                bAccept = false;
            break;
        case dt_Deployment:
            if (widgetOnDiagram(id))
                bAccept = false;
            else if (ot != ot_Interface &&
                     ot != ot_Package &&
                     ot != ot_Component &&
                     ot != ot_Class &&
                     ot != ot_Node)
                bAccept = false;
            else if (ot == ot_Package &&
                     temp->getStereotype() != "subsystem")
                bAccept = false;
            break;
        case dt_Component:
            if (widgetOnDiagram(id) ||
                (ot != ot_Interface &&
                 ot != ot_Package &&
                 ot != ot_Component &&
                 ot != ot_Artifact &&
                 ot != ot_Class))
                bAccept = false;
            if (ot == ot_Class && !temp->getAbstract())
                bAccept = false;
            break;
        case dt_EntityRelationship:
            if (ot != ot_Entity && ot != ot_Category)
                bAccept = false;
            break;
        default:
            break;
    }
    if ( bAccept ) {
       e->accept();
    } else {
       e->ignore();
    }
}

00642 void UMLView::dragMoveEvent( QDragMoveEvent* e ) {
    e->accept();
}


00647 void UMLView::dropEvent(QDropEvent *e) {
    UMLDragData::LvTypeAndID_List tidList;
    if( !UMLDragData::getClip3TypeAndID(e->mimeData(), tidList) ) {
        return;
    }
    UMLDragData::LvTypeAndID_It tidIt(tidList);
    UMLDragData::LvTypeAndID * tid = tidIt.current();
    if (!tid) {
        uDebug() << "UMLDragData::getClip3TypeAndID returned empty list" << endl;
        return;
    }
    ListView_Type lvtype = tid->type;
    Uml::IDType id = tid->id;

    if (Model_Utils::typeIsDiagram(lvtype)) {
        bool breakFlag = false;
        UMLWidget* w = 0;
        foreach ( w ,  m_WidgetList ) {
            if (w->getBaseType() == Uml::wt_Note && w->onWidget(e->pos())) {
                breakFlag = true;
                break;
            }
        }
        if ( breakFlag ) {
            NoteWidget *note = static_cast<NoteWidget*>(w);
            note->setDiagramLink(id);
        }
        return;
    }
    UMLObject* o = m_pDoc->findObjectById(id);
    if( !o ) {
        uDebug() << "object id=" << ID2STR(id) << " not found" << endl;
        return;
    }
    m_bCreateObject = true;
    m_Pos = (e->pos() * 100 ) / m_nZoom;

    slotObjectCreated(o);

    m_pDoc -> setModified(true);
}

00689 ObjectWidget * UMLView::onWidgetLine( const QPoint &point ) {
    foreach ( UMLWidget* obj, m_WidgetList ) {
        ObjectWidget *ow = dynamic_cast<ObjectWidget*>(obj);
        if (ow == NULL)
            continue;
        SeqLineWidget *pLine = ow->getSeqLine();
        if (pLine == NULL) {
            uError() << "SeqLineWidget of " << ow->getName()
                << " (id=" << ID2STR(ow->getLocalID()) << ") is NULL" << endl;
            continue;
        }
        if (pLine->onWidget(point))
            return ow;
    }
    return 0;
}

00706 ObjectWidget * UMLView::onWidgetDestructionBox( const QPoint &point ){

    foreach ( UMLWidget* obj,  m_WidgetList ) {
        ObjectWidget *ow = dynamic_cast<ObjectWidget*>(obj);
        if (ow == NULL)
            continue;
        SeqLineWidget *pLine = ow->getSeqLine();
        if (pLine == NULL) {
            uError() << "SeqLineWidget of " << ow->getName()
                << " (id=" << ID2STR(ow->getLocalID()) << ") is NULL" << endl;
            continue;
        }
        if (pLine->onDestructionBox(point))
            return ow;
    }
    return 0;
}

00724 UMLWidget *UMLView::getWidgetAt(const QPoint& p) {
    int relativeSize = 10000;  // start with an arbitrary large number
    UMLWidget  *retObj = NULL;
    UMLWidgetListIt it(m_WidgetList);
    foreach ( UMLWidget* obj,  m_WidgetList ) {
        const int s = obj->onWidget(p);
        if (!s)
            continue;
        if (s < relativeSize) {
            relativeSize = s;
            retObj = obj;
        }
    }
    return retObj;
}

00740 void UMLView::checkMessages(ObjectWidget * w) {
    if(getType() != dt_Sequence)
        return;

    MessageWidgetListIt it( m_MessageList );
    foreach ( MessageWidget *obj , m_MessageList ) {
        if(! obj -> contains(w))
            continue;
        //make sure message doesn't have any associations
        removeAssociations(obj);
        obj -> cleanup();
        //make sure not in selected list
        m_SelectedList.removeAll(obj);
        m_MessageList.removeAll(obj);
        delete obj;
    }
}

00758 bool UMLView::widgetOnDiagram(Uml::IDType id) {

    foreach ( UMLWidget *obj, m_WidgetList ) {
        if(id == obj -> getID())
            return true;
    }

    foreach ( UMLWidget *obj , m_MessageList ) {
        if(id == obj -> getID())
            return true;
    }

    return false;
}

00773 void UMLView::contentsMouseMoveEvent(QMouseEvent* ome) {
    m_pToolBarState->mouseMove(ome);
}

// search both our UMLWidget AND MessageWidget lists
00778 UMLWidget * UMLView::findWidget( Uml::IDType id ) {

    foreach ( UMLWidget* obj, m_WidgetList ) {
        // object widgets are special..the widget id is held by 'localId' attribute (crappy!)
        if( obj -> getBaseType() == wt_Object ) {
            if( static_cast<ObjectWidget *>( obj ) -> getLocalID() == id )
                return obj;
        } else if( obj -> getID() == id ) {
            return obj;
        }
    }

    foreach ( UMLWidget* obj, m_MessageList ) {
        if( obj -> getID() == id )
            return obj;
    }

    return 0;
}



00800 AssociationWidget * UMLView::findAssocWidget( Uml::IDType id ) {

    foreach ( AssociationWidget* obj ,m_AssociationList ) {
        UMLAssociation* umlassoc = obj -> getAssociation();
        if ( umlassoc && umlassoc->getID() == id ) {
            return obj;
        }
    }
    return 0;
}

00811 AssociationWidget * UMLView::findAssocWidget(UMLWidget *pWidgetA,
                                             UMLWidget *pWidgetB, const QString& roleNameB) {
    foreach ( AssociationWidget* assoc, m_AssociationList ) {
        const Association_Type testType = assoc->getAssocType();
        if (testType != Uml::at_Association &&
            testType != Uml::at_UniAssociation &&
            testType != Uml::at_Composition &&
            testType != Uml::at_Aggregation &&
            testType != Uml::at_Relationship)
            continue;
        if (pWidgetA->getID() == assoc->getWidgetID(A) &&
            pWidgetB->getID() == assoc->getWidgetID(B) &&
            assoc->getRoleName(Uml::B) == roleNameB)
            return assoc;
    }
    return 0;
}


00830 AssociationWidget * UMLView::findAssocWidget(Uml::Association_Type at,
        UMLWidget *pWidgetA, UMLWidget *pWidgetB) {

    foreach ( AssociationWidget* assoc, m_AssociationList ) {
        Association_Type testType = assoc->getAssocType();
        if (testType != at)
            continue;
        if (pWidgetA->getID() == assoc->getWidgetID(A) &&
                pWidgetB->getID() == assoc->getWidgetID(B))
            return assoc;
    }
    return 0;
}

00844 void UMLView::removeWidget(UMLWidget * o) {
    if(!o)
        return;

    emit sigWidgetRemoved(o);

    removeAssociations(o);

    Widget_Type t = o->getBaseType();
    if(getType() == dt_Sequence && t == wt_Object)
        checkMessages( static_cast<ObjectWidget*>(o) );

    o -> cleanup();
    m_SelectedList.removeAll(o);
    disconnect( this, SIGNAL( sigRemovePopupMenu() ), o, SLOT( slotRemovePopupMenu() ) );
    disconnect( this, SIGNAL( sigClearAllSelected() ), o, SLOT( slotClearAllSelected() ) );
    disconnect( this, SIGNAL(sigColorChanged(Uml::IDType)), o, SLOT(slotColorChanged(Uml::IDType)));
    if (t == wt_Message) {
        m_MessageList.removeAll(static_cast<MessageWidget*>(o));
    } else
        m_WidgetList.removeAll(o);
    delete o;
    m_pDoc->setModified();
}

00869 bool UMLView::getUseFillColor() const {
    return m_Options.uiState.useFillColor;
}

00873 void UMLView::setUseFillColor(bool ufc) {
    m_Options.uiState.useFillColor = ufc;
}

00877 QColor UMLView::getFillColor() const {
    return m_Options.uiState.fillColor;
}

00881 void UMLView::setFillColor(const QColor &color) {
    m_Options.uiState.fillColor = color;
    emit sigColorChanged( getID() );
    canvas()->setAllChanged();
}

00887 QColor UMLView::getLineColor() const {
    return m_Options.uiState.lineColor;
}

00891 void UMLView::setLineColor(const QColor &color) {
    m_Options.uiState.lineColor = color;
    emit sigColorChanged( getID() );
    canvas() -> setAllChanged();
}

00897 uint UMLView::getLineWidth() const {
    return m_Options.uiState.lineWidth;
}

00901 void UMLView::setLineWidth(uint width) {
    m_Options.uiState.lineWidth = width;
    emit sigLineWidthChanged( getID() );
    canvas() -> setAllChanged();
}

00907 void UMLView::contentsMouseDoubleClickEvent(QMouseEvent* ome) {
    m_pToolBarState->mouseDoubleClick(ome);
}

00911 QRect UMLView::getDiagramRect() {
    int startx, starty, endx, endy;
    startx = starty = INT_MAX;
    endx = endy = 0;


    foreach ( UMLWidget* obj, m_WidgetList ) {
        if (! obj->isVisible())
            continue;
        int objEndX = obj -> getX() + obj -> getWidth();
        int objEndY = obj -> getY() + obj -> getHeight();
        int objStartX = obj -> getX();
        int objStartY = obj -> getY();
        if (startx >= objStartX)
            startx = objStartX;
        if (starty >= objStartY)
            starty = objStartY;
        if(endx <= objEndX)
            endx = objEndX;
        if(endy <= objEndY)
            endy = objEndY;
    }
    //if seq. diagram, make sure print all of the lines
    if (getType() == dt_Sequence ) {
        foreach ( UMLWidget* obj, m_WidgetList) {
            ObjectWidget *ow = dynamic_cast<ObjectWidget*>(obj);
            if (ow == NULL)
                continue;
            int y = ow->getEndLineY();
            if (endy < y)
                endy = y;
        }
    }

    /* now we need another look at the associations, because they are no
     * UMLWidgets */

    QRect rect;

    foreach ( AssociationWidget* assoc_obj, m_AssociationList ) {
        /* get the rectangle around all segments of the assoc */
        rect = assoc_obj->getAssocLineRectangle();

        if (startx >= rect.x())
            startx = rect.x();
        if (starty >= rect.y())
            starty = rect.y();
        if (endx <= rect.x() + rect.width())
            endx = rect.x() + rect.width();
        if (endy <= rect.y() + rect.height())
            endy = rect.y() + rect.height();
    }

    /* Margin causes problems of black border around the edge
       // Margin:
       startx -= 24;
       starty -= 20;
       endx += 24;
       endy += 20;
    */

    return QRect(startx, starty,  endx - startx, endy - starty);
}

00975 void UMLView::setSelected(UMLWidget * w, QMouseEvent * /*me*/) {
    //only add if wasn't in list
    if(!m_SelectedList.removeAll(w))
        m_SelectedList.append(w);
    int count = m_SelectedList.count();
    //only call once - if we select more, no need to keep clearing  window

    // if count == 1, widget will update the doc window with their data when selected
    if( count == 2 )
        updateDocumentation( true );//clear doc window

    /* selection changed, we have to make sure the copy and paste items
     * are correctly enabled/disabled */
    UMLApp::app()->slotCopyChanged();
}

00991 void UMLView::clearSelected() {
    m_SelectedList.clear();
    emit sigClearAllSelected();
    //m_pDoc -> enableCutCopy(false);
}

//TODO Only used in MLApp::handleCursorKeyReleaseEvent
00998 void UMLView::moveSelectedBy(int dX, int dY) {
    foreach (UMLWidget *w ,  m_SelectedList )
        w->moveBy(dX, dY);
}

01003 void UMLView::selectionUseFillColor(bool useFC) {

    foreach( UMLWidget* temp  ,  m_SelectedList )
        temp -> setUseFillColour(useFC);
}

01009 void UMLView::selectionSetFont( const QFont &font )
{

    foreach( UMLWidget* temp  ,  m_SelectedList )
        temp -> setFont( font );
}

01016 void UMLView::selectionSetLineColor( const QColor &color )
{
    UMLApp::app()->BeginMacro("Change Line Color");
    UMLWidget * temp = 0;
    foreach ( temp ,  m_SelectedList ) {
        temp->setLineColor(color);
        temp->setUsesDiagramLineColour(false);
    }
    AssociationWidgetList assoclist = getSelectedAssocs();
    foreach (AssociationWidget *aw , assoclist ) {
        aw->setLineColor(color);
        aw->setUsesDiagramLineColour(false);
    }
    UMLApp::app()->EndMacro();
}

01032 void UMLView::selectionSetLineWidth( uint width )
{

    foreach ( UMLWidget* temp , m_SelectedList ) {
        temp->setLineWidth(width);
        temp->setUsesDiagramLineWidth(false);
    }
    AssociationWidgetList assoclist = getSelectedAssocs();
    foreach (AssociationWidget *aw , assoclist ) {
        aw->setLineWidth(width);
        aw->setUsesDiagramLineWidth(false);
    }
}


01047 void UMLView::selectionSetFillColor( const QColor &color )
{
    UMLApp::app()->BeginMacro("Change Fill Color");

    foreach (UMLWidget* temp ,  m_SelectedList ) {
        temp -> setFillColour( color );
        temp -> setUsesDiagramFillColour(false);
    }
    UMLApp::app()->EndMacro();
}

01058 void UMLView::selectionToggleShow(int sel)
{
    // loop through all selected items
    foreach (UMLWidget *temp , m_SelectedList ) {
        Widget_Type type = temp->getBaseType();
        ClassifierWidget *cw = dynamic_cast<ClassifierWidget*>(temp);

        // toggle the show setting sel
        switch (sel)
        {
            // some setting are only available for class, some for interface and some
            // for both
        case ListPopupMenu::mt_Show_Attributes_Selection:
            if (type == wt_Class)
                cw -> toggleShowAtts();
            break;
        case ListPopupMenu::mt_Show_Operations_Selection:
            if (cw)
                cw -> toggleShowOps();
            break;
        case ListPopupMenu::mt_Visibility_Selection:
            if (cw)
                cw -> toggleShowVisibility();
            break;
        case ListPopupMenu::mt_DrawAsCircle_Selection:
            if (type == wt_Interface)
                cw -> toggleDrawAsCircle();
            break;
        case ListPopupMenu::mt_Show_Operation_Signature_Selection:
            if (cw)
                cw -> toggleShowOpSigs();
            break;
        case ListPopupMenu::mt_Show_Attribute_Signature_Selection:
            if (type == wt_Class)
                cw -> toggleShowAttSigs();
            break;
        case ListPopupMenu::mt_Show_Packages_Selection:
            if (cw)
                cw -> toggleShowPackage();
            break;
        case ListPopupMenu::mt_Show_Stereotypes_Selection:
            if (type == wt_Class)
                cw -> toggleShowStereotype();
            break;
        case ListPopupMenu::mt_Show_Public_Only_Selection:
            if (cw)
                cw -> toggleShowPublicOnly();
            break;
        default:
            break;
        } // switch (sel)
    }
}

01112 void UMLView::deleteSelection()
{
    /*
       Don't delete text widget that are connect to associations as these will
       be cleaned up by the associations.
    */


    foreach( UMLWidget* temp ,  m_SelectedList )
    {
        if( temp -> getBaseType() == wt_Text &&
                ((FloatingTextWidget *)temp) -> getRole() != tr_Floating )
        {
            // Porting from Q3PtrList to QList
            //m_SelectedList.remove(); // remove advances the iterator to the next position,
            //m_SelectedList.prev();      // let's allow for statement do the advancing
            m_SelectedList.removeAt( m_SelectedList.indexOf( temp ) );
            temp -> hide();

         } else {
            removeWidget(temp);
        }

    }

    // Delete any selected associations.

    foreach ( AssociationWidget* assocwidget, m_AssociationList ) {
        if( assocwidget-> getSelected() )
            removeAssoc(assocwidget);
        // MARK
    }

    /* we also have to remove selected messages from sequence diagrams */


    /* loop through all messages and check the selection state */
    foreach (MessageWidget* cur_msgWgt , m_MessageList )
    {
        if (cur_msgWgt->getSelected() == true)
        {
            removeWidget(cur_msgWgt);  // Remove message - it is selected.
        }
    }

    // sometimes we miss one widget, so call this function again to remove it as
    // well
    if (m_SelectedList.count() != 0)
        deleteSelection();

    //make sure list empty - it should be anyway, just a check.
    m_SelectedList.clear();
}

01166 void UMLView::selectAll()
{
    selectWidgets(0, 0, canvas()->width(), canvas()->height());
}

01171 Uml::IDType UMLView::getLocalID() {
    m_nLocalID = UniqueID::gen();
    return m_nLocalID;
}

01176 bool UMLView::isSavedInSeparateFile() {
    if (getOptionState().generalState.tabdiagrams) {
        // Umbrello currently does not support external folders
        // when tabbed diagrams are enabled.
        return false;
    }
    const QString msgPrefix("UMLView::isSavedInSeparateFile(" + getName() + "): ");
    UMLListView *listView = UMLApp::app()->getListView();
    UMLListViewItem *lvItem = listView->findItem(m_nID);
    if (lvItem == NULL) {
        uError() << msgPrefix
                  << "listView->findUMLObject(this) returns false" << endl;
        return false;
    }
    UMLListViewItem *parentItem = dynamic_cast<UMLListViewItem*>( lvItem->parent() );
    if (parentItem == NULL) {
        uError() << msgPrefix
                  << "parent item in listview is not a UMLListViewItem (?)" << endl;
        return false;
    }
    const Uml::ListView_Type lvt = parentItem->getType();
    if (! Model_Utils::typeIsFolder(lvt))
        return false;
    UMLFolder *modelFolder = dynamic_cast<UMLFolder*>(parentItem->getUMLObject());
    if (modelFolder == NULL) {
        uError() << msgPrefix
                  << "parent model object is not a UMLFolder (?)" << endl;
        return false;
    }
    QString folderFile = modelFolder->getFolderFile();
    return !folderFile.isEmpty();
}

01209 void UMLView::contentsMousePressEvent(QMouseEvent* ome) {
    m_pToolBarState->mousePress(ome);
    //TODO should be managed by widgets when are selected. Right now also has some
    //problems, such as clicking on a widget, and clicking to move that widget shows
    //documentation of the diagram instead of keeping the widget documentation.
    //When should diagram documentation be shown? When clicking on an empty
    //space in the diagram with arrow tool?
    if (!m_bChildDisplayedDoc) {
      UMLApp::app() -> getDocWindow() -> showDocumentation( this, true );
    }
    m_bChildDisplayedDoc = false;
}

01222 void UMLView::makeSelected (UMLWidget * uw) {
    if (uw == NULL)
        return;
    uw -> setSelected(true);
    m_SelectedList.removeAll(uw);  // make sure not in there
    m_SelectedList.append(uw);
}

01230 void UMLView::selectWidgetsOfAssoc (AssociationWidget * a) {
    if (!a)
        return;
    a -> setSelected(true);
    //select the two widgets
    makeSelected( a->getWidget(A) );
    makeSelected( a->getWidget(B) );
    //select all the text
    makeSelected( a->getMultiWidget(A) );
    makeSelected( a->getMultiWidget(B) );
    makeSelected( a->getRoleWidget(A) );
    makeSelected( a->getRoleWidget(B) );
    makeSelected( a->getChangeWidget(A) );
    makeSelected( a->getChangeWidget(B) );
}

01246 void UMLView::selectWidgets(int px, int py, int qx, int qy) {
    clearSelected();

    QRect rect;
    if(px <= qx) {
        rect.setLeft(px);
        rect.setRight(qx);
    } else {
        rect.setLeft(qx);
        rect.setRight(px);
    }
    if(py <= qy) {
        rect.setTop(py);
        rect.setBottom(qy);
    } else {
        rect.setTop(qy);
        rect.setBottom(py);
    }


    foreach ( UMLWidget* temp , m_WidgetList ) {
        int x = temp -> getX();
        int y = temp -> getY();
        int w = temp -> getWidth();
        int h = temp -> getHeight();
        QRect rect2(x, y, w, h);

        //see if any part of widget is in the rectangle
        if( !rect.intersects(rect2) )
            continue;
        //if it is text that is part of an association then select the association
        //and the objects that are connected to it.
        if (temp -> getBaseType() == wt_Text) {
            FloatingTextWidget *ft = static_cast<FloatingTextWidget*>(temp);
            Text_Role t = ft -> getRole();
            LinkWidget *lw = ft->getLink();
            MessageWidget * mw = dynamic_cast<MessageWidget*>(lw);
            if (mw) {
                makeSelected( mw );
                makeSelected( mw->getWidget(A) );
                makeSelected( mw->getWidget(B) );
            } else if (t != tr_Floating) {
                AssociationWidget * a = dynamic_cast<AssociationWidget*>(lw);
                if (a)
                    selectWidgetsOfAssoc( a );
            }
        } else if(temp -> getBaseType() == wt_Message) {
            MessageWidget *mw = static_cast<MessageWidget*>(temp);
            makeSelected( mw -> getWidget(A) );
            makeSelected( mw -> getWidget(B) );
        }
        if(temp -> isVisible()) {
            makeSelected( temp );
        }
    }
    selectAssociations( true );

    //now do the same for the messagewidgets

    foreach ( MessageWidget*w , m_MessageList ) {
        if ( w -> getWidget(A) -> getSelected() &&
                w -> getWidget(B) -> getSelected() ) {
            makeSelected( w );
        }//end if
    }//end foreach
}

01313 void  UMLView::getDiagram(const QRect &rect, QPixmap & diagram) {
    QPixmap pixmap(rect.x() + rect.width(), rect.y() + rect.height());
    QPainter painter(&pixmap);
    getDiagram(canvas()->rect(),painter);
    bitBlt(&diagram, QPoint(0, 0), &pixmap, rect);
}

01320 void  UMLView::getDiagram(const QRect &area, QPainter & painter) {
    //TODO unselecting and selecting later doesn't work now as the selection is
    //cleared in UMLViewImageExporter. Check if the anything else than the
    //following is needed and, if it works, remove the clearSelected in
    //UMLViewImageExporter and UMLViewImageExporterModel

    foreach ( UMLWidget* widget , m_SelectedList ) {
        widget->setSelected(false);
    }
    AssociationWidgetList selectedAssociationsList = getSelectedAssocs();

    foreach ( AssociationWidget* association , selectedAssociationsList ) {
        association->setSelected(false);
    }

    // we don't want to get the grid
    bool showSnapGrid = getShowSnapGrid();
    setShowSnapGrid(false);

    canvas()->drawArea(area, &painter);

    setShowSnapGrid(showSnapGrid);

    canvas()->setAllChanged();
    //select again
    foreach ( UMLWidget* widget , m_SelectedList ) {
        widget->setSelected( true );
    }
    foreach ( AssociationWidget* association , selectedAssociationsList ) {
        association->setSelected(true);
    }

    return;
}

01355 UMLViewImageExporter* UMLView::getImageExporter() {
    return m_pImageExporter;
}

01359 void UMLView::slotActivate() {
    m_pDoc->changeCurrentView(getID());
}

01363 UMLObjectList UMLView::getUMLObjects() {
    UMLObjectList list;
    foreach (UMLWidget* w,  m_WidgetList ) {

        switch (w->getBaseType()) //use switch for easy future expansion
        {
        case wt_Actor:
        case wt_Class:
        case wt_Interface:
        case wt_Package:
        case wt_Component:
        case wt_Node:
        case wt_Artifact:
        case wt_UseCase:
        case wt_Object:
            list.append( w->getUMLObject() );
            break;
        default:
            break;
        }
    }
    return list;
}

01387 void UMLView::activate() {

    //Activate Regular widgets then activate  messages
    foreach ( UMLWidget* obj , m_WidgetList ) {
        //If this UMLWidget is already activated or is a MessageWidget then skip it
        if(obj->isActivated() || obj->getBaseType() == wt_Message)
            continue;

        if (obj->activate()) {
            obj->setVisible(true);
        } else {
            m_WidgetList.removeAll(obj);
            delete obj;
        }
    }//end foreach

    //Activate Message widgets
    foreach ( UMLWidget* obj , m_MessageList ) {
        //If this MessageWidget is already activated then skip it
        if(obj->isActivated())
            continue;

        obj->activate(m_pDoc->getChangeLog());
        obj->setVisible( true );

    }//end foreach

    // Activate all association widgets

    foreach ( AssociationWidget* aw , m_AssociationList ) {
        if (aw->activate()) {
            if (m_PastePoint.x() != 0) {
                int x = m_PastePoint.x() - m_Pos.x();
                int y = m_PastePoint.y() - m_Pos.y();
                aw->moveEntireAssoc(x, y);
            }
        } else {
            m_AssociationList.removeAll(aw);
            delete  aw;
        }
    }
}

01430 int UMLView::getSelectCount(bool filterText) const {
    if (!filterText)
        return m_SelectedList.count();
    int counter = 0;
    const UMLWidget * temp = 0;
    foreach ( temp, m_SelectedList ) {
        if (temp->getBaseType() == wt_Text) {
            const FloatingTextWidget *ft = static_cast<const FloatingTextWidget*>(temp);
            if (ft->getRole() == tr_Floating)
                counter++;
        } else {
            counter++;
        }
    }
    return counter;
}


01448 bool UMLView::getSelectedWidgets(UMLWidgetList &WidgetList, bool filterText /*= true*/) {
    foreach ( UMLWidget* temp, m_SelectedList ) {
        if (filterText && temp->getBaseType() == wt_Text) {
            const FloatingTextWidget *ft = static_cast<const FloatingTextWidget*>(temp);
            if (ft->getRole() == tr_Floating)
                WidgetList.append(temp);
        } else {
            WidgetList.append(temp);
        }
    }//end for
    return true;
}

01461 AssociationWidgetList UMLView::getSelectedAssocs() {
    AssociationWidgetList assocWidgetList;

    foreach ( AssociationWidget* assocwidget, m_AssociationList) {
        if( assocwidget -> getSelected() )
            assocWidgetList.append(assocwidget);
    }
    return assocWidgetList;
}

01471 bool UMLView::addWidget( UMLWidget * pWidget , bool isPasteOperation ) {
    if( !pWidget ) {
        return false;
    }
    Widget_Type type = pWidget->getBaseType();
    if (isPasteOperation) {
        if (type == Uml::wt_Message)
            m_MessageList.append(static_cast<MessageWidget*>(pWidget));
        else
            m_WidgetList.append(pWidget);
        return true;
    }
    if (!isPasteOperation && findWidget(pWidget->getID())) {
        uError() << "Not adding (id=" << ID2STR(pWidget->getID())
                  << "/type=" << type << "/name=" << pWidget->getName()
                  << ") because it is already there" << endl;
        return false;
    }
    IDChangeLog * log = m_pDoc -> getChangeLog();
    if( isPasteOperation && (!log || !m_pIDChangesLog)) {
        uError()<<" Cant addWidget to view in paste op because a log is not open"<<endl;
        return false;
    }
    int wX = pWidget -> getX();
    int wY = pWidget -> getY();
    bool xIsOutOfRange = (wX <= 0 || wX >= FloatingTextWidget::restrictPositionMax);
    bool yIsOutOfRange = (wY <= 0 || wY >= FloatingTextWidget::restrictPositionMax);
    if (xIsOutOfRange || yIsOutOfRange) {
        QString name = pWidget->getName();
        if (name.isEmpty()) {
            FloatingTextWidget *ft = dynamic_cast<FloatingTextWidget*>(pWidget);
            if (ft)
                name = ft->getDisplayText();
        }
        uDebug() << name << " type=" << pWidget->getBaseType() << "): position ("
            << wX << "," << wY << ") is out of range" << endl;
        if (xIsOutOfRange) {
            pWidget->setX(0);
            wX = 0;
        }
        if (yIsOutOfRange) {
            pWidget->setY(0);
            wY = 0;
        }
    }
    if( wX < m_Pos.x() )
        m_Pos.setX( wX );
    if( wY < m_Pos.y() )
        m_Pos.setY( wY );

    //see if we need a new id to match object
    switch( type ) {

    case wt_Class:
    case wt_Package:
    case wt_Component:
    case wt_Node:
    case wt_Artifact:
    case wt_Interface:
    case wt_Enum:
    case wt_Entity:
    case wt_Datatype:
    case wt_Actor:
    case wt_UseCase:
    case wt_Category:
        {
            Uml::IDType id = pWidget -> getID();
            Uml::IDType newID = log->findNewID( id );
            if( newID == Uml::id_None ) {  // happens after a cut
                if (id == Uml::id_None)
                    return false;
                newID = id; //don't stop paste
            } else
                pWidget -> setID( newID );
            UMLObject * pObject = m_pDoc -> findObjectById( newID );
            if( !pObject ) {
                uDebug() << "addWidget: Can't find UMLObject for id "
                          << ID2STR(newID) << endl;
                return false;
            }
            pWidget -> setUMLObject( pObject );
            //make sure it doesn't already exist.
            if (findWidget(newID)) {
                uDebug() << "Not adding (id=" << ID2STR(pWidget->getID())
                          << "/type=" << pWidget->getBaseType()
                          << "/name=" << pWidget->getName()
                          << ") because it is already there" << endl;
                delete pWidget; // Not nice but if _we_ don't do it nobody else will
                return true;//don't stop paste just because widget found.
            }
            m_WidgetList.append( pWidget );
        }
        break;

    case wt_Message:
    case wt_Note:
    case wt_Box:
    case wt_Text:
    case wt_State:
    case wt_Activity:
    case wt_ObjectNode:
        {
            Uml::IDType newID = m_pDoc->assignNewID( pWidget->getID() );
            pWidget->setID(newID);
            if (type != wt_Message) {
                m_WidgetList.append( pWidget );
                return true;
            }
            // CHECK
            // Handling of wt_Message:
            MessageWidget *pMessage = static_cast<MessageWidget *>( pWidget );
            if (pMessage == NULL) {
                uDebug() << "pMessage is NULL";
                return false;
            }
            ObjectWidget *objWidgetA = pMessage -> getWidget(A);
            ObjectWidget *objWidgetB = pMessage -> getWidget(B);
            Uml::IDType waID = objWidgetA -> getLocalID();
            Uml::IDType wbID = objWidgetB -> getLocalID();
            Uml::IDType newWAID = m_pIDChangesLog ->findNewID( waID );
            Uml::IDType newWBID = m_pIDChangesLog ->findNewID( wbID );
            if( newWAID == Uml::id_None || newWBID == Uml::id_None ) {
                uDebug() << "Error with ids : " << ID2STR(newWAID)
                          << " " << ID2STR(newWBID) << endl;
                return false;
            }
            // Assumption here is that the A/B objectwidgets and the textwidget
            // are pristine in the sense that we may freely change their local IDs.
            objWidgetA -> setLocalID( newWAID );
            objWidgetB -> setLocalID( newWBID );
            FloatingTextWidget *ft = pMessage->getFloatingTextWidget();
            if (ft == NULL)
                uDebug() << "FloatingTextWidget of Message is NULL";
            else if (ft->getID() == Uml::id_None)
                ft->setID( UniqueID::gen() );
            else {
                Uml::IDType newTextID = m_pDoc->assignNewID( ft->getID() );
                ft->setID( newTextID );
            }
            m_MessageList.append( pMessage );
        }
        break;

    case wt_Object:
        {
            ObjectWidget* pObjectWidget = static_cast<ObjectWidget*>(pWidget);
            if (pObjectWidget == NULL) {
                uDebug() << "pObjectWidget is NULL";
                return false;
            }
            Uml::IDType nNewLocalID = getLocalID();
            Uml::IDType nOldLocalID = pObjectWidget -> getLocalID();
            m_pIDChangesLog->addIDChange( nOldLocalID, nNewLocalID );
            pObjectWidget -> setLocalID( nNewLocalID );
            UMLObject *pObject = m_pDoc->findObjectById(pWidget->getID());
            if( !pObject ) {
                uDebug() << "Cannot find UMLObject";
                return false;
            }
            pWidget -> setUMLObject( pObject );
            m_WidgetList.append( pWidget );
        }
        break;

    case wt_Precondition:
        {
            ObjectWidget* pObjectWidget = static_cast<ObjectWidget*>(pWidget);
            if (pObjectWidget == NULL) {
                uDebug() << "pObjectWidget is NULL";
                return false;
            }
            Uml::IDType newID = log->findNewID( pWidget -> getID() );
            if (newID == Uml::id_None) {
                return false;
            }
            pObjectWidget -> setID( newID );
            Uml::IDType nNewLocalID = getLocalID();
            Uml::IDType nOldLocalID = pObjectWidget -> getLocalID();
            m_pIDChangesLog->addIDChange( nOldLocalID, nNewLocalID );
            pObjectWidget -> setLocalID( nNewLocalID );
            UMLObject *pObject = m_pDoc -> findObjectById( newID );
            if( !pObject ) {
                uDebug() << "Cannot find UMLObject";
                return false;
            }
            pWidget -> setUMLObject( pObject );
            m_WidgetList.append( pWidget );
        }
        break;

    case wt_Pin:
    case wt_CombinedFragment:
    case wt_Signal:
        {
            ObjectWidget* pObjectWidget = static_cast<ObjectWidget*>(pWidget);
            if (pObjectWidget == NULL) {
                uDebug() << "pObjectWidget is NULL";
                return false;
            }
            Uml::IDType newID = log->findNewID( pWidget -> getID() );
            if (newID == Uml::id_None) {
                return false;
            }
            pObjectWidget -> setID( newID );
            Uml::IDType nNewLocalID = getLocalID();
            Uml::IDType nOldLocalID = pObjectWidget -> getLocalID();
            m_pIDChangesLog->addIDChange( nOldLocalID, nNewLocalID );
            pObjectWidget -> setLocalID( nNewLocalID );
            UMLObject *pObject = m_pDoc -> findObjectById( newID );
            if( !pObject ) {
                uDebug() << "Cannot find UMLObject";
                return false;
            }
            pWidget -> setUMLObject( pObject );
            m_WidgetList.append( pWidget );
        }
        break;

    default:
        uDebug() << "Trying to add an invalid widget type";
        return false;
        break;
    }

    return true;
}

// Add the association, and its child widgets to this view
01699 bool UMLView::addAssociation(AssociationWidget* pAssoc , bool isPasteOperation) {

    if (!pAssoc) {
        return false;
    }
    const Association_Type type = pAssoc->getAssocType();

    if( isPasteOperation )
    {
        IDChangeLog * log = m_pDoc -> getChangeLog();

        if(!log )
            return false;

        Uml::IDType ida = Uml::id_None, idb = Uml::id_None;
        if( getType() == dt_Collaboration || getType() == dt_Sequence ) {
            //check local log first
            ida = m_pIDChangesLog->findNewID( pAssoc->getWidgetID(A) );
            idb = m_pIDChangesLog->findNewID( pAssoc->getWidgetID(B) );
            //if either is still not found and assoc type is anchor
            //we are probably linking to a notewidet - else an error
            if( ida == Uml::id_None && type == at_Anchor )
                ida = log->findNewID(pAssoc->getWidgetID(A));
            if( idb == Uml::id_None && type == at_Anchor )
                idb = log->findNewID(pAssoc->getWidgetID(B));
        } else {
            Uml::IDType oldIdA = pAssoc->getWidgetID(A);
            Uml::IDType oldIdB = pAssoc->getWidgetID(B);
            ida = log->findNewID( oldIdA );
            if (ida == Uml::id_None) {  // happens after a cut
                if (oldIdA == Uml::id_None)
                    return false;
                ida = oldIdA;
            }
            idb = log->findNewID( oldIdB );
            if (idb == Uml::id_None) {  // happens after a cut
                if (oldIdB == Uml::id_None)
                    return false;
                idb = oldIdB;
            }
        }
        if(ida == Uml::id_None || idb == Uml::id_None) {
            return false;
        }
        // cant do this anymore.. may cause problem for pasting
        //      pAssoc->setWidgetID(ida, A);
        //      pAssoc->setWidgetID(idb, B);
        pAssoc->setWidget(findWidget(ida), A);
        pAssoc->setWidget(findWidget(idb), B);
    }

    UMLWidget * pWidgetA = findWidget(pAssoc->getWidgetID(A));
    UMLWidget * pWidgetB = findWidget(pAssoc->getWidgetID(B));
    //make sure valid widget ids
    if (!pWidgetA || !pWidgetB) {
        return false;
    }

    //make sure valid
    if (!isPasteOperation && !m_pDoc->loading() &&
        !AssocRules::allowAssociation(type, pWidgetA, pWidgetB, false)) {
        uWarning() << "allowAssociation returns false " << "for AssocType " << type << endl;
        return false;
    }

    //make sure there isn't already the same assoc

    foreach( AssociationWidget* assocwidget, m_AssociationList ) {
        if( *pAssoc == *assocwidget )
            // this is nuts. Paste operation wants to know if 'true'
            // for duplicate, but loadFromXMI needs 'false' value
            return (isPasteOperation? true: false);
    }

    m_AssociationList.append(pAssoc);

    FloatingTextWidget *ft[5] = { pAssoc->getNameWidget(),
                            pAssoc->getRoleWidget(A),
                            pAssoc->getRoleWidget(B),
                            pAssoc->getMultiWidget(A),
                            pAssoc->getMultiWidget(B) };
    for (int i = 0; i < 5; i++) {
        FloatingTextWidget *flotxt = ft[i];
        if (flotxt) {
            flotxt->updateComponentSize();
            addWidget(flotxt);
        }
    }

    return true;
}

01791 void UMLView::activateAfterLoad(bool bUseLog) {
    if (m_bActivated)
        return;
    if( bUseLog ) {
        beginPartialWidgetPaste();
    }

    //now activate them all
    activate();

    if( bUseLog ) {
        endPartialWidgetPaste();
    }
    resizeCanvasToItems();
    setZoom( getZoom() );
    m_bActivated = true;
}

void UMLView::beginPartialWidgetPaste() {
    delete m_pIDChangesLog;
    m_pIDChangesLog = 0;

    m_pIDChangesLog = new IDChangeLog();
    m_bPaste = true;
}

void UMLView::endPartialWidgetPaste() {
    delete    m_pIDChangesLog;
    m_pIDChangesLog = 0;

    m_bPaste = false;
}

01824 void UMLView::removeAssoc(AssociationWidget* pAssoc) {
    if(!pAssoc)
        return;

    emit sigAssociationRemoved(pAssoc);

    pAssoc->cleanup();
    m_AssociationList.removeAll(pAssoc);
    delete pAssoc;
    m_pDoc->setModified();
}

01836 void UMLView::removeAssocInViewAndDoc(AssociationWidget* a) {
    // For umbrello 1.2, UMLAssociations can only be removed in two ways:
    // 1. Right click on the assocwidget in the view and select Delete
    // 2. Go to the Class Properties page, select Associations, right click
    //    on the association and select Delete
    if(!a)
        return;
    if (a->getAssocType() == at_Containment) {
        UMLObject *objToBeMoved = a->getWidget(B)->getUMLObject();
        if (objToBeMoved != NULL) {
            UMLListView *lv = UMLApp::app()->getListView();
            lv->moveObject( objToBeMoved->getID(),
                            Model_Utils::convert_OT_LVT(objToBeMoved),
                            lv->theLogicalView() );
            // UMLListView::moveObject() will delete the containment
            // AssociationWidget via UMLView::updateContainment().
        } else {
            uDebug() << "removeAssocInViewAndDoc(containment): "
                      << "objB is NULL" << endl;
        }
    } else {
        // Remove assoc in doc.
        m_pDoc->removeAssociation(a->getAssociation());
        // Remove assoc in view.
        removeAssoc(a);
    }
}

/** Removes all the associations related to Widget */
01865 void UMLView::removeAssociations(UMLWidget* Widget) {

    foreach( AssociationWidget* assocwidget, m_AssociationList ) {
        if(assocwidget->contains(Widget)) {
            removeAssoc(assocwidget);
        }
    }
}

01874 void UMLView::selectAssociations(bool bSelect) {

    foreach( AssociationWidget* assocwidget, m_AssociationList ) {
        if(bSelect &&
                assocwidget->getWidget(A) && assocwidget->getWidget(A)->getSelected() &&
                assocwidget->getWidget(B) && assocwidget->getWidget(B)->getSelected() ) {
            assocwidget->setSelected(true);
        } else {
            assocwidget->setSelected(false);
        }
    }//end foreach
}

01887 void UMLView::getWidgetAssocs(UMLObject* Obj, AssociationWidgetList & Associations) {
    if( ! Obj )
        return;

    foreach( AssociationWidget* assocwidget, m_AssociationList ) {
        if (assocwidget->getWidget(A)->getUMLObject() == Obj ||
                assocwidget->getWidget(B)->getUMLObject() == Obj)
            Associations.append(assocwidget);
    }//end foreach

}

01899 void UMLView::closeEvent ( QCloseEvent * e ) {
    QWidget::closeEvent(e);
}

01903 void UMLView::removeAllAssociations() {
    //Remove All association widgets

    foreach( AssociationWidget* assocwidget, m_AssociationList ){
        removeAssoc(assocwidget);
    }

    // Porting to QList from QPtrList which doesn't support autodelete
    //m_AssociationList.clear();
    while ( !m_AssociationList.empty() ) {
        delete m_AssociationList.takeFirst();
    }
}


01918 void UMLView::removeAllWidgets() {
    // Remove widgets.

    foreach ( UMLWidget* temp , m_WidgetList) {
        // I had to take this condition back in, else umbrello
        // crashes on exit. Still to be analyzed.  --okellogg
        if( !( temp -> getBaseType() == wt_Text &&
                ((FloatingTextWidget *)temp)-> getRole() != tr_Floating ) ) {
            removeWidget( temp );
        }
    }
    // Porting to QList from QPtrList which doesn't support autodelete
    //m_WidgetList.clear();
    while ( !m_WidgetList.empty() ) {
        delete m_WidgetList.takeFirst();
    }

}

01937 void UMLView::showDocumentation( UMLObject * object, bool overwrite ) {
    UMLApp::app() -> getDocWindow() -> showDocumentation( object, overwrite );
    m_bChildDisplayedDoc = true;
}

01942 void UMLView::showDocumentation( UMLWidget * widget, bool overwrite ) {
    UMLApp::app() -> getDocWindow() -> showDocumentation( widget, overwrite );
    m_bChildDisplayedDoc = true;
}

01947 void UMLView::showDocumentation( AssociationWidget * widget, bool overwrite ) {
    UMLApp::app() -> getDocWindow() -> showDocumentation( widget, overwrite );
    m_bChildDisplayedDoc = true;
}

01952 void UMLView::updateDocumentation( bool clear ) {
    UMLApp::app() -> getDocWindow() -> updateDocumentation( clear );
}

01956 void UMLView::updateContainment(UMLCanvasObject *self) {
    if (self == NULL)
        return;
    // See if the object has a widget representation in this view.
    // While we're at it, also see if the new parent has a widget here.
    UMLWidget *selfWidget = NULL, *newParentWidget = NULL;
    UMLPackage *newParent = self->getUMLPackage();
    foreach (UMLWidget* w, m_WidgetList ) {
        UMLObject *o = w->getUMLObject();
        if (o == self)
            selfWidget = w;
        else if (newParent != NULL && o == newParent)
            newParentWidget = w;
    }
    if (selfWidget == NULL)
        return;
    // Remove possibly obsoleted containment association.
    foreach (AssociationWidget* a, m_AssociationList) {
        if (a->getAssocType() != Uml::at_Containment)
            continue;
        // Container is at role A, containee at B.
        // We only look at association for which we are B.
        UMLWidget *wB = a->getWidget(B);
        UMLObject *roleBObj = wB->getUMLObject();
        if (roleBObj != self)
            continue;
        UMLWidget *wA = a->getWidget(A);
        UMLObject *roleAObj = wA->getUMLObject();
        if (roleAObj == newParent) {
            // Wow, all done. Great!
            return;
        }
        removeAssoc(a);  // AutoDelete is true
        // It's okay to break out because there can only be a single
        // containing object.
        break;
    }
    if (newParentWidget == NULL)
        return;
    // Create the new containment association.
    AssociationWidget *a = new AssociationWidget(this, newParentWidget,
                           Uml::at_Containment, selfWidget);
    a->calculateEndingPoints();
    a->setActivated(true);
    m_AssociationList.append(a);
}

02003 void UMLView::createAutoAssociations( UMLWidget * widget ) {
    if (widget == NULL ||
        (m_Type != Uml::dt_Class &&
         m_Type != Uml::dt_Component &&
         m_Type != Uml::dt_Deployment
         && m_Type != Uml::dt_EntityRelationship))
         return;
    // Recipe:
    // If this widget has an underlying UMLCanvasObject then
    //   for each of the UMLCanvasObject's UMLAssociations
    //     if umlassoc's "other" role has a widget representation on this view then
    //       if the AssocWidget does not already exist then
    //         if the assoc type is permitted in the current diagram type then
    //           create the AssocWidget
    //         end if
    //       end if
    //     end if
    //   end loop
    //   Do createAutoAttributeAssociations()
    //   if this object is capable of containing nested objects then
    //     for each of the object's containedObjects
    //       if the containedObject has a widget representation on this view then
    //         if the containedWidget is not physically located inside this widget
    //           create the containment AssocWidget
    //         end if
    //       end if
    //     end loop
    //   end if
    //   if the UMLCanvasObject has a parentPackage then
    //     if the parentPackage has a widget representation on this view then
    //       create the containment AssocWidget
    //     end if
    //   end if
    // end if
    UMLObject *tmpUmlObj = widget->getUMLObject();
    if (tmpUmlObj == NULL)
        return;
    UMLCanvasObject *umlObj = dynamic_cast<UMLCanvasObject*>(tmpUmlObj);
    if (umlObj == NULL)
        return;
    const UMLAssociationList& umlAssocs = umlObj->getAssociations();

    Uml::IDType myID = umlObj->getID();
    foreach ( UMLAssociation* assoc , umlAssocs ) {
        UMLCanvasObject *other = NULL;
        UMLObject *roleAObj = assoc->getObject(A);
        if (roleAObj == NULL) {
            uDebug() << "createAutoAssociations: roleA object is NULL at UMLAssoc "
                      << ID2STR(assoc->getID()) << endl;
            continue;
        }
        UMLObject *roleBObj = assoc->getObject(B);
        if (roleBObj == NULL) {
            uDebug() << "createAutoAssociations: roleB object is NULL at UMLAssoc "
                      << ID2STR(assoc->getID()) << endl;
            continue;
        }
        if (roleAObj->getID() == myID) {
            other = static_cast<UMLCanvasObject*>(roleBObj);
        } else if (roleBObj->getID() == myID) {
            other = static_cast<UMLCanvasObject*>(roleAObj);
        } else {
            uDebug() << "createAutoAssociations: Can't find own object "
                      << ID2STR(myID) << " in UMLAssoc "
                      << ID2STR(assoc->getID()) << endl;
            continue;
        }
        // Now that we have determined the "other" UMLObject, seek it in
        // this view's UMLWidgets.
        Uml::IDType otherID = other->getID();

        bool breakFlag = false;
        UMLWidget* pOtherWidget = 0;
        foreach ( pOtherWidget ,  m_WidgetList) {
            if (pOtherWidget->getID() == otherID) {
                breakFlag = true;
                break;
            }
        }
        if (!breakFlag)
            continue;
        // Both objects are represented in this view:
        // Assign widget roles as indicated by the UMLAssociation.
        UMLWidget *widgetA, *widgetB;
        if (myID == roleAObj->getID()) {
            widgetA = widget;
            widgetB = pOtherWidget;
        } else {
            widgetA = pOtherWidget;
            widgetB = widget;
        }
        // Check that the assocwidget does not already exist.
        Uml::Association_Type assocType = assoc->getAssocType();
        AssociationWidget * assocwidget = findAssocWidget(assocType, widgetA, widgetB);
        if (assocwidget) {
            assocwidget->calculateEndingPoints();  // recompute assoc lines
            continue;
        }
        // Check that the assoc is allowed.
        if (!AssocRules::allowAssociation(assocType, widgetA, widgetB, false)) {
            uDebug() << "createAutoAssociations: not transferring assoc "
                      << "of type " << assocType << endl;
            continue;
        }
        // Create the AssociationWidget.
        assocwidget = new AssociationWidget( this );
        assocwidget->setWidget(widgetA, A);
        assocwidget->setWidget(widgetB, B);
        assocwidget->setAssocType(assocType);
        assocwidget->setUMLObject(assoc);
        // Call calculateEndingPoints() before setting the FloatingTexts
        // because their positions are computed according to the
        // assocwidget line positions.
        assocwidget->calculateEndingPoints();
        assocwidget->syncToModel();
        assocwidget->setActivated(true);
        if (! addAssociation(assocwidget))
            delete assocwidget;
    }

    createAutoAttributeAssociations(widget);

    if ( m_Type == Uml::dt_EntityRelationship ) {
        createAutoConstraintAssociations(widget);
    }

    // if this object is capable of containing nested objects then
    Uml::Object_Type t = umlObj->getBaseType();
    if (t == ot_Package || t == ot_Class || t == ot_Interface || t == ot_Component) {
        // for each of the object's containedObjects
        UMLPackage *umlPkg = static_cast<UMLPackage*>(umlObj);
        UMLObjectList lst = umlPkg->containedObjects();
        foreach (UMLObject* obj,  lst ) {
            // if the containedObject has a widget representation on this view then
            Uml::IDType id = obj->getID();
            foreach (UMLWidget *w , m_WidgetList ) {
                if (w->getID() != id)
                    continue;
                // if the containedWidget is not physically located inside this widget
                if (widget->rect().contains(w->rect()))
                    continue;
                // create the containment AssocWidget
                AssociationWidget *a = new AssociationWidget(this, widget,
                                       at_Containment, w);
                a->calculateEndingPoints();
                a->setActivated(true);
                if (! addAssociation(a))
                    delete a;
            }
        }
    }
    // if the UMLCanvasObject has a parentPackage then
    UMLPackage *parent = umlObj->getUMLPackage();
    if (parent == NULL)
        return;
    // if the parentPackage has a widget representation on this view then
    Uml::IDType pkgID = parent->getID();

    bool breakFlag = false;
    UMLWidget* pWidget = 0;
    foreach ( pWidget , m_WidgetList ) {
        if (pWidget->getID() == pkgID) {
            breakFlag = true;
            break;
        }
    }
    if (!breakFlag || pWidget->rect().contains(widget->rect()))
        return;
    // create the containment AssocWidget
    AssociationWidget *a = new AssociationWidget(this, pWidget, at_Containment, widget);
    a->calculateEndingPoints();
    a->setActivated(true);
    if (! addAssociation(a))
        delete a;
}

02179 void UMLView::createAutoAttributeAssociations(UMLWidget *widget) {
    if (widget == NULL || m_Type != Uml::dt_Class || !m_Options.classState.showAttribAssocs)
        return;

    // Pseudocode:
    //   if the underlying model object is really a UMLClassifier then
    //     for each of the UMLClassifier's UMLAttributes
    //       if the attribute type has a widget representation on this view then
    //         if the AssocWidget does not already exist then
    //           if the current diagram type permits compositions then
    //             create a composition AssocWidget
    //           end if
    //         end if
    //       end if
    //       if the attribute type is a Datatype then
    //         if the Datatype is a reference (pointer) type then
    //           if the referenced type has a widget representation on this view then
    //             if the AssocWidget does not already exist then
    //               if the current diagram type permits aggregations then
    //                 create an aggregation AssocWidget from the ClassifierWidget to the
    //                                                 widget of the referenced type
    //               end if
    //             end if
    //           end if
    //         end if
    //       end if
    //     end loop
    //   end if
    //
    // Implementation:
    UMLObject *tmpUmlObj = widget->getUMLObject();
    if (tmpUmlObj == NULL)
        return;
    // if the underlying model object is really a UMLClassifier then
    if (tmpUmlObj->getBaseType() == Uml::ot_Datatype) {
        UMLClassifier *dt = static_cast<UMLClassifier*>(tmpUmlObj);
        while (dt->originType() != NULL) {
            tmpUmlObj = dt->originType();
            if (tmpUmlObj->getBaseType() != Uml::ot_Datatype)
                break;
            dt = static_cast<UMLClassifier*>(tmpUmlObj);
        }
    }
    if (tmpUmlObj->getBaseType() != Uml::ot_Class)
        return;
    UMLClassifier * klass = static_cast<UMLClassifier*>(tmpUmlObj);
    // for each of the UMLClassifier's UMLAttributes
    UMLAttributeList attrList = klass->getAttributeList();
    foreach (UMLAttribute* attr, attrList ) {
        createAutoAttributeAssociation(attr->getType(), attr, widget);
        /*
         * The following code from attachment 19935 of http://bugs.kde.org/140669
         * creates Aggregation/Composition to the template parameters.
         * The current solution uses Dependency instead, see handling of template
         * instantiation at Import_Utils::createUMLObject().
        UMLClassifierList templateList = attr->getTemplateParams();
        for (UMLClassifierListIt it(templateList); it.current(); ++it) {
            createAutoAttributeAssociation(it,attr,widget);
        }
         */
    }
}

02242 void UMLView::createAutoAttributeAssociation(UMLClassifier *type, UMLAttribute *attr,
                                             UMLWidget *widget /*, UMLClassifier * klass*/) {
    if (type == NULL) {
        // uDebug() << klass->getName() << ": type is NULL for "
        //     << "attribute " << attr->getName() << endl;
        return;
    }
    Uml::Association_Type assocType = Uml::at_Composition;
    UMLWidget *w = findWidget( type->getID() );
    AssociationWidget *aw = NULL;
    // if the attribute type has a widget representation on this view
    if (w) {
        aw = findAssocWidget(widget, w, attr->getName());
        if ( aw == NULL &&
               // if the current diagram type permits compositions
               AssocRules::allowAssociation(assocType, widget, w, false) ) {
            // Create a composition AssocWidget, or, if the attribute type is
            // stereotyped <<CORBAInterface>>, create a UniAssociation widget.
            if (type->getStereotype() == "CORBAInterface")
                assocType = at_UniAssociation;
            AssociationWidget *a = new AssociationWidget (this, widget, assocType, w, attr);
            a->calculateEndingPoints();
            a->setVisibility(attr->getVisibility(), B);
            /*
            if (assocType == at_Aggregation || assocType == at_UniAssociation)
            a->setMulti("0..1", B);
            */
            a->setRoleName(attr->getName(), B);
            a->setActivated(true);
            if (! addAssociation(a))
                delete a;
        }
    }
    // if the attribute type is a Datatype then
    if (type->getBaseType() == ot_Datatype) {
        UMLClassifier *dt = static_cast<UMLClassifier*>(type);
        // if the Datatype is a reference (pointer) type
        if (dt->isReference()) {
            //Uml::Association_Type assocType = Uml::at_Composition;
            UMLClassifier *c = dt->originType();
            UMLWidget *w = c ? findWidget( c->getID() ) : 0;
            // if the referenced type has a widget representation on this view
            if (w) {
                aw = findAssocWidget(widget, w, attr->getName());
                if (aw == NULL &&
                    // if the current diagram type permits aggregations
                    AssocRules::allowAssociation(at_Aggregation, widget, w, false)) {
                    // create an aggregation AssocWidget from the ClassifierWidget
                    // to the widget of the referenced type
                    AssociationWidget *a = new AssociationWidget
                            (this, widget, at_Aggregation, w, attr);
                    a->calculateEndingPoints();
                    a->setVisibility(attr->getVisibility(), B);
                    //a->setChangeability(true, B);
                    a->setMulti("0..1", B);
                    a->setRoleName(attr->getName(), B);
                    a->setActivated(true);
                    if (! addAssociation(a))
                        delete a;
                }
            }
        }
    }
}

void UMLView::createAutoConstraintAssociations(UMLWidget *widget) {
    if (widget == NULL || m_Type != Uml::dt_EntityRelationship)
        return;

    // Pseudocode:
    //   if the underlying model object is really a UMLEntity then
    //     for each of the UMLEntity's UMLForeignKeyConstraint's
    //       if the attribute type has a widget representation on this view then
    //         if the AssocWidget does not already exist then
    //           if the current diagram type permits relationships then
    //             create a relationship AssocWidget
    //           end if
    //         end if
    //       end if

    UMLObject *tmpUmlObj = widget->getUMLObject();
    if (tmpUmlObj == NULL)
        return;
    // check if the underlying model object is really a UMLEntity
    UMLCanvasObject *umlObj = dynamic_cast<UMLCanvasObject*>(tmpUmlObj);
    if (umlObj == NULL)
        return;
     // finished checking whether this widget has a UMLCanvas Object

    if (tmpUmlObj->getBaseType() != Uml::ot_Entity)
        return;
    UMLEntity *entity = static_cast<UMLEntity*>(tmpUmlObj);

    // for each of the UMLEntity's UMLForeignKeyConstraints
    UMLClassifierListItemList constrList = entity->getFilteredList(Uml::ot_ForeignKeyConstraint);

    foreach (UMLClassifierListItem* cli, constrList ) {
        UMLEntityConstraint *eConstr = static_cast<UMLEntityConstraint*>( cli );

        UMLForeignKeyConstraint* fkc = static_cast<UMLForeignKeyConstraint*>(eConstr);
        if( fkc == NULL ){
            return;
        }

        UMLEntity* refEntity = fkc->getReferencedEntity();
        if( refEntity == NULL ){
            return;
        }

        createAutoConstraintAssociation(refEntity , fkc , widget);

    }
}

void UMLView::createAutoConstraintAssociation(UMLEntity* refEntity, UMLForeignKeyConstraint* fkConstraint, UMLWidget* widget){

    if (refEntity == NULL) {
         return;
    }

    Uml::Association_Type assocType = Uml::at_Relationship;
    UMLWidget *w = findWidget( refEntity->getID() );
    AssociationWidget *aw = NULL;

    if (w) {
        aw = findAssocWidget(widget, w, fkConstraint->getName());
        if ( aw == NULL &&
               // if the current diagram type permits relationships
               AssocRules::allowAssociation(assocType, widget, w, false) ) {

            AssociationWidget *a = new AssociationWidget (this, widget, assocType, w);
            a->setUMLObject(fkConstraint);
            a->calculateEndingPoints();
            //a->setVisibility(attr->getVisibility(), B);
            a->setRoleName(fkConstraint->getName(), B);
            a->setActivated(true);
            if (! addAssociation(a))
                delete a;
        }
    }

}


02386 void UMLView::findMaxBoundingRectangle(const FloatingTextWidget* ft, int& px, int& py, int& qx, int& qy)
{
    if (ft == NULL || !ft->isVisible())
        return;

    int x = ft -> getX();
    int y = ft -> getY();
    int x1 = x + ft -> getWidth() - 1;
    int y1 = y + ft -> getHeight() - 1;

    if (px == -1 || x < px)
        px = x;
    if (py == -1 || y < py)
        py = y;
    if (qx == -1 || x1 > qx)
        qx = x1;
    if (qy == -1 || y1 > qy)
        qy = y1;
}

02406 void UMLView::copyAsImage(QPixmap*& pix) {
    //get the smallest rect holding the diagram
    QRect rect = getDiagramRect();
    QPixmap diagram( rect.width(), rect.height() );

    //only draw what is selected
    m_bDrawSelectedOnly = true;
    selectAssociations(true);
    getDiagram(rect, diagram);

    //now get the selection cut
    int px = -1, py = -1, qx = -1, qy = -1;

    //first get the smallest rect holding the widgets
    foreach (UMLWidget* temp , m_SelectedList ) {
        int x = temp -> getX();
        int y = temp -> getY();
        int x1 = x + temp -> width() - 1;
        int y1 = y + temp -> height() - 1;
        if(px == -1 || x < px) {
            px = x;
        }
        if(py == -1 || y < py) {
            py = y;
        }
        if(qx == -1 || x1 > qx) {
            qx = x1;
        }
        if(qy == -1 || y1 > qy) {
            qy = y1;
        }
    }

    //also take into account any text lines in assocs or messages

    //get each type of associations
    //This needs to be reimplemented to increase the rectangle
    //if a part of any association is not included
    foreach ( AssociationWidget *a , m_AssociationList ) {

        if (! a->getSelected())
            continue;
        const FloatingTextWidget* multiA = const_cast<FloatingTextWidget*>(a->getMultiWidget(A));
        const FloatingTextWidget* multiB = const_cast<FloatingTextWidget*>(a->getMultiWidget(B));
        const FloatingTextWidget* roleA = const_cast<FloatingTextWidget*>(a->getRoleWidget(A));
        const FloatingTextWidget* roleB = const_cast<FloatingTextWidget*>(a->getRoleWidget(B));
        const FloatingTextWidget* changeA = const_cast<FloatingTextWidget*>(a->getChangeWidget(A));
        const FloatingTextWidget* changeB = const_cast<FloatingTextWidget*>(a->getChangeWidget(B));
        findMaxBoundingRectangle(multiA, px, py, qx, qy);
        findMaxBoundingRectangle(multiB, px, py, qx, qy);
        findMaxBoundingRectangle(roleA, px, py, qx, qy);
        findMaxBoundingRectangle(roleB, px, py, qx, qy);
        findMaxBoundingRectangle(changeA, px, py, qx, qy);
        findMaxBoundingRectangle(changeB, px, py, qx, qy);
    }//end foreach

    QRect imageRect;  //area with respect to getDiagramRect()
    //i.e. all widgets on the canvas.  Was previously with
    //respect to whole canvas

    imageRect.setLeft( px - rect.left() );
    imageRect.setTop( py - rect.top() );
    imageRect.setRight( qx - rect.left() );
    imageRect.setBottom( qy - rect.top() );

    pix = new QPixmap(imageRect.width(), imageRect.height());
    bitBlt(pix, QPoint(0, 0), &diagram, imageRect);
    m_bDrawSelectedOnly = false;
}

02476 void UMLView::setMenu() {
    slotRemovePopupMenu();
    ListPopupMenu::Menu_Type menu = ListPopupMenu::mt_Undefined;
    switch ( getType() ) {
    case dt_Class:
        menu = ListPopupMenu::mt_On_Class_Diagram;
        break;

    case dt_UseCase:
        menu = ListPopupMenu::mt_On_UseCase_Diagram;
        break;

    case dt_Sequence:
        menu = ListPopupMenu::mt_On_Sequence_Diagram;
        break;

    case dt_Collaboration:
        menu = ListPopupMenu::mt_On_Collaboration_Diagram;
        break;

    case dt_State:
        menu = ListPopupMenu::mt_On_State_Diagram;
        break;

    case dt_Activity:
        menu = ListPopupMenu::mt_On_Activity_Diagram;
        break;

    case dt_Component:
        menu = ListPopupMenu::mt_On_Component_Diagram;
        break;

    case dt_Deployment:
        menu = ListPopupMenu::mt_On_Deployment_Diagram;
        break;

    case dt_EntityRelationship:
        menu = ListPopupMenu::mt_On_EntityRelationship_Diagram;
        break;

    default:
        uWarning() << "unknown diagram type " << getType();
        menu = ListPopupMenu::mt_Undefined;
        break;
    }//end switch
    if (menu != ListPopupMenu::mt_Undefined) {
        // uDebug() << "create popup for Menu_Type " << menu;
        m_pMenu = new ListPopupMenu(this, menu, this);
        connect(m_pMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotMenuSelection(QAction*)));
        m_pMenu->popup( mapToGlobal( contentsToViewport(worldMatrix().map(m_Pos)) ) );
    }
}

02529 void UMLView::slotRemovePopupMenu() {
    if (m_pMenu) {
        disconnect(m_pMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotMenuSelection(QAction*)));
        delete m_pMenu;
        m_pMenu = 0;
    }
}

02537 void UMLView::slotMenuSelection(QAction* action) {
    ListPopupMenu::Menu_Type sel = ListPopupMenu::mt_Undefined;
    if (m_pMenu != NULL) {  // popup from this class
        sel = m_pMenu->getMenuType(action);
    }
    else {  // popup from umldoc
        sel = m_pDoc->getPopupMenuSelection(action);
    }
    switch (sel) {
    case ListPopupMenu::mt_Undo:
        UMLApp::app()->undo();
        break;

    case ListPopupMenu::mt_Redo:
        UMLApp::app()->redo();
        break;

    case ListPopupMenu::mt_Clear:
        clearDiagram();
        break;

    case ListPopupMenu::mt_Export_Image:
        m_pImageExporter->exportView();
        break;

    case ListPopupMenu::mt_FloatText:
        {
            FloatingTextWidget* ft = new FloatingTextWidget(this);
            ft->changeTextDlg();
            //if no text entered delete
            if(!FloatingTextWidget::isTextValid(ft->getText())) {
                delete ft;
            } else {
                ft->setID(UniqueID::gen());
                setupNewWidget(ft);
            }
        }
        break;

    case ListPopupMenu::mt_UseCase:
        m_bCreateObject = true;
        Object_Factory::createUMLObject( ot_UseCase );
        break;

    case ListPopupMenu::mt_Actor:
        m_bCreateObject = true;
        Object_Factory::createUMLObject( ot_Actor );
        break;

    case ListPopupMenu::mt_Class:
    case ListPopupMenu::mt_Object:
        m_bCreateObject = true;
        Object_Factory::createUMLObject( ot_Class);
        break;

    case ListPopupMenu::mt_Package:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Package);
        break;

    case ListPopupMenu::mt_Component:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Component);
        break;

    case ListPopupMenu::mt_Node:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Node);
        break;

    case ListPopupMenu::mt_Artifact:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Artifact);
        break;

    case ListPopupMenu::mt_Interface:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Interface);
        break;

    case ListPopupMenu::mt_Enum:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Enum);
        break;

    case ListPopupMenu::mt_Entity:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Entity);
        break;

    case ListPopupMenu::mt_Category:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Category);
        break;

    case ListPopupMenu::mt_Datatype:
        m_bCreateObject = true;
        Object_Factory::createUMLObject(ot_Datatype);
        break;

    case ListPopupMenu::mt_Cut:
        //FIXME make this work for diagram's right click menu
        if ( m_SelectedList.count() &&
                UMLApp::app()->editCutCopy(true) ) {
            deleteSelection();
            m_pDoc->setModified(true);
        }
        break;

    case ListPopupMenu::mt_Copy:
        //FIXME make this work for diagram's right click menu
        m_SelectedList.count() && UMLApp::app()->editCutCopy(true);
        break;

    case ListPopupMenu::mt_Paste:
        m_PastePoint = m_Pos;
        m_Pos.setX( 2000 );
        m_Pos.setY( 2000 );
        UMLApp::app()->slotEditPaste();

        m_PastePoint.setX( 0 );
        m_PastePoint.setY( 0 );
        break;

    case ListPopupMenu::mt_Initial_State:
        {
            StateWidget* state = new StateWidget( this, StateWidget::Initial );
            setupNewWidget( state );
        }
        break;

    case ListPopupMenu::mt_End_State:
        {
            StateWidget* state = new StateWidget( this, StateWidget::End );
            setupNewWidget( state );
        }
        break;

    case ListPopupMenu::mt_State:
        {
            bool ok = false;
            QString name = KInputDialog::getText( i18n("Enter State Name"),
                                                  i18n("Enter the name of the new state:"),
                                                  i18n("new state"), &ok, UMLApp::app() );
            if ( ok ) {
                StateWidget* state = new StateWidget( this );
                state->setName( name );
                setupNewWidget( state );
            }
        }
        break;

    case ListPopupMenu::mt_Initial_Activity:
        {
            ActivityWidget* activity = new ActivityWidget( this, ActivityWidget::Initial );
            setupNewWidget(activity);
        }
        break;


    case ListPopupMenu::mt_End_Activity:
        {
            ActivityWidget* activity = new ActivityWidget( this, ActivityWidget::End );
            setupNewWidget(activity);
        }
        break;

    case ListPopupMenu::mt_Branch:
        {
            ActivityWidget* activity = new ActivityWidget( this, ActivityWidget::Branch );
            setupNewWidget(activity);
        }
        break;

    case ListPopupMenu::mt_Activity:
        {
            bool ok = false;
            QString name = KInputDialog::getText( i18n("Enter Activity Name"),
                                                  i18n("Enter the name of the new activity:"),
                                                  i18n("new activity"), &ok, UMLApp::app() );
            if ( ok ) {
                ActivityWidget* activity = new ActivityWidget( this, ActivityWidget::Normal );
                activity->setName( name );
                setupNewWidget(activity);
            }
        }
        break;

    case ListPopupMenu::mt_SnapToGrid:
        toggleSnapToGrid();
        m_pDoc->setModified();
        break;

    case ListPopupMenu::mt_ShowSnapGrid:
        toggleShowGrid();
        m_pDoc->setModified();
        break;

    case ListPopupMenu::mt_Properties:
        if (showPropDialog() == true)
            m_pDoc->setModified();
        break;

    case ListPopupMenu::mt_Delete:
        m_pDoc->removeDiagram( getID() );
        break;

    case ListPopupMenu::mt_Rename:
        {
            bool ok = false;
            QString name = KInputDialog::getText( i18n("Enter Diagram Name"),
                                                  i18n("Enter the new name of the diagram:"),
                                                  getName(), &ok, UMLApp::app() );
            if (ok) {
                setName(name);
                m_pDoc->signalDiagramRenamed(this);
            }
        }
        break;

    default:
        uWarning() << "unknown ListPopupMenu::Menu_Type " << sel;
        break;
    }
}

02763 void UMLView::slotCutSuccessful() {
    if( m_bStartedCut ) {
        deleteSelection();
        m_bStartedCut = false;
    }
}

02770 void UMLView::slotShowView() {
    m_pDoc -> changeCurrentView( getID() );
}

02774 QPoint UMLView::getPastePoint() {
    QPoint point = m_PastePoint;
    point.setX( point.x() - m_Pos.x() );
    point.setY( point.y() - m_Pos.y() );
    return point;
}

02781 void UMLView::resetPastePoint() {
    m_PastePoint = m_Pos;
}

02785 int UMLView::snappedX (int x) {
    if (getSnapToGrid()) {
        int gridX = getSnapX();
        int modX = x % gridX;
        x -= modX;
        if (modX >= gridX / 2)
            x += gridX;
    }
    return x;
}

02796 int UMLView::snappedY (int y) {
    if (getSnapToGrid()) {
        int gridY = getSnapY();
        int modY = y % gridY;
        y -= modY;
        if (modY >= gridY / 2)
            y += gridY;
    }
    return y;
}

02807 bool UMLView::showPropDialog() {
    UMLViewDialog dlg( this, this );
    if( dlg.exec() ) {
        return true;
    }
    return false;
}


02816 QFont UMLView::getFont() const {
    return m_Options.uiState.font;
}

02820 void UMLView::setFont(QFont font, bool changeAllWidgets /* = false */) {
    m_Options.uiState.font = font;
    if (!changeAllWidgets)
        return;
    foreach (UMLWidget* w, m_WidgetList ) {
        w->setFont(font);
    }
}

02829 void UMLView::setClassWidgetOptions( ClassOptionsPage * page ) {


    foreach ( UMLWidget* pWidget , m_WidgetList ) {
        Uml::Widget_Type wt = pWidget->getBaseType();
        if (wt == Uml::wt_Class || wt == Uml::wt_Interface) {
            page -> setWidget( static_cast<ClassifierWidget *>(pWidget) );
            page -> updateUMLWidget();
        }
    }
}


02842 void UMLView::checkSelections() {
    UMLWidget * pWA = 0, * pWB = 0;
    //check messages
    foreach ( UMLWidget *pTemp , m_SelectedList ) {
        if( pTemp->getBaseType() == wt_Message && pTemp -> getSelected() ) {
            MessageWidget * pMessage = static_cast<MessageWidget *>( pTemp );
            pWA = pMessage -> getWidget(A);
            pWB = pMessage -> getWidget(B);
            if( !pWA -> getSelected() ) {
                pWA -> setSelectedFlag( true );
                m_SelectedList.append( pWA );
            }
            if( !pWB -> getSelected() ) {
                pWB -> setSelectedFlag( true );
                m_SelectedList.append( pWB );
            }
        }//end if
    }//end for
    //check Associations

    foreach ( AssociationWidget *pAssoc , m_AssociationList ) {
        if( pAssoc -> getSelected() ) {
            pWA = pAssoc -> getWidget(A);
            pWB = pAssoc -> getWidget(B);
            if( !pWA -> getSelected() ) {
                pWA -> setSelectedFlag( true );
                m_SelectedList.append( pWA );
            }
            if( !pWB -> getSelected() ) {
                pWB -> setSelectedFlag( true );
                m_SelectedList.append( pWB );
            }
        }//end if
    }//end foreach
}

02878 bool UMLView::checkUniqueSelection()
{
    // if there are no selected items, we return true
    if (m_SelectedList.count() <= 0)
        return true;

    // get the first item and its base type
    UMLWidget * pTemp = (UMLWidget *) m_SelectedList.first();
    Widget_Type tmpType = pTemp -> getBaseType();

    // check all selected items, if they have the same BaseType
    foreach ( pTemp , m_SelectedList ) {
        if( pTemp->getBaseType() != tmpType)
        {
            return false; // the base types are different, the list is not unique
        }
    } // for ( through all selected items )

    return true; // selected items are unique
}

02899 void UMLView::clearDiagram() {
    if( KMessageBox::Continue == KMessageBox::warningContinueCancel( this, i18n("You are about to delete "
            "the entire diagram.\nAre you sure?"),
            i18n("Delete Diagram?"),KGuiItem( i18n("&Delete"), "edit-delete") ) ) {
        removeAllWidgets();
    }
}

02907 void UMLView::toggleSnapToGrid() {
    setSnapToGrid( !getSnapToGrid() );
}

02911 void UMLView::toggleSnapComponentSizeToGrid() {
    setSnapComponentSizeToGrid( !getSnapComponentSizeToGrid() );
}

02915 void UMLView::toggleShowGrid() {
    setShowSnapGrid( !getShowSnapGrid() );
}

02919 void UMLView::setSnapToGrid(bool bSnap) {
    m_bUseSnapToGrid = bSnap;
    emit sigSnapToGridToggled( getSnapToGrid() );
}

02924 void UMLView::setSnapComponentSizeToGrid(bool bSnap) {
    m_bUseSnapComponentSizeToGrid = bSnap;
    updateComponentSizes();
    emit sigSnapComponentSizeToGridToggled( getSnapComponentSizeToGrid() );
}

02930 bool UMLView::getShowSnapGrid() const {
    return m_bShowSnapGrid;
}

02934 void UMLView::setShowSnapGrid(bool bShow) {
    m_bShowSnapGrid = bShow;
    canvas()->setAllChanged();
    emit sigShowGridToggled( getShowSnapGrid() );
}

02940 bool UMLView::getShowOpSig() const {
    return m_Options.classState.showOpSig;
}

02944 void UMLView::setShowOpSig(bool bShowOpSig) {
    m_Options.classState.showOpSig = bShowOpSig;
}

02948 void UMLView::setZoom(int zoom) {
    if (zoom < 10) {
        zoom = 10;
    } else if (zoom > 500) {
        zoom = 500;
    }

    QMatrix wm;
    wm.scale(zoom/100.0,zoom/100.0);
    setWorldMatrix(wm);

    m_nZoom = currentZoom();
    resizeCanvasToItems();
}

02963 int UMLView::currentZoom() {
    return (int)(worldMatrix().m11()*100.0);
}

void UMLView::zoomIn() {
    QMatrix wm = worldMatrix();
    wm.scale(1.5,1.5); // adjust zooming step here
    setZoom( (int)(wm.m11()*100.0) );
}

void UMLView::zoomOut() {
    QMatrix wm = worldMatrix();
    wm.scale(2.0/3.0, 2.0/3.0); //adjust zooming step here
    setZoom( (int)(wm.m11()*100.0) );
}

02979 void UMLView::fileLoaded() {
    setZoom( getZoom() );
    resizeCanvasToItems();
}

02984 void UMLView::setCanvasSize(int width, int height) {
    setCanvasWidth(width);
    setCanvasHeight(height);
    canvas()->resize(width, height);
}

02990 void UMLView::resizeCanvasToItems() {
    QRect canvasSize = getDiagramRect();
    int canvasWidth = canvasSize.right() + 5;
    int canvasHeight = canvasSize.bottom() + 5;

    //Find out the bottom right visible pixel and size to at least that
    int contentsX, contentsY;
    int contentsWMX, contentsWMY;
    viewportToContents(viewport()->width(), viewport()->height(), contentsX, contentsY);
    inverseWorldMatrix().map(contentsX, contentsY, &contentsWMX, &contentsWMY);

    if (canvasWidth < contentsWMX) {
        canvasWidth = contentsWMX;
    }

    if (canvasHeight < contentsWMY) {
        canvasHeight = contentsWMY;
    }

    setCanvasSize(canvasWidth, canvasHeight);
}

03012 void UMLView::show() {
    QWidget::show();
    resizeCanvasToItems();
}

03017 void UMLView::updateComponentSizes() {
    // update sizes of all components

    foreach ( UMLWidget *obj , m_WidgetList ) {
        obj->updateComponentSize();
    }
}

/**
 * Force the widget font metrics to be updated next time
 * the widgets are drawn.
 * This is necessary because the widget size might depend on the
 * font metrics and the font metrics might change for different
 * QPainter, i.e. font metrics for Display font and Printer font are
 * usually different.
 * Call this when you change the QPainter.
 */
03034 void UMLView::forceUpdateWidgetFontMetrics(QPainter * painter) {

    foreach ( UMLWidget *obj , m_WidgetList ) {
        obj->forceUpdateFontMetrics(painter);
    }
}

03041 void UMLView::saveToXMI( QDomDocument & qDoc, QDomElement & qElement ) {
    QDomElement viewElement = qDoc.createElement( "diagram" );
    viewElement.setAttribute( "xmi.id", ID2STR(m_nID) );
    viewElement.setAttribute( "name", getName() );
    viewElement.setAttribute( "type", m_Type );
    viewElement.setAttribute( "documentation", m_Documentation );
    //optionstate uistate
    viewElement.setAttribute( "fillcolor", m_Options.uiState.fillColor.name() );
    viewElement.setAttribute( "linecolor", m_Options.uiState.lineColor.name() );
    viewElement.setAttribute( "linewidth", m_Options.uiState.lineWidth );
    viewElement.setAttribute( "usefillcolor", m_Options.uiState.useFillColor );
    viewElement.setAttribute( "font", m_Options.uiState.font.toString() );
    //optionstate classstate
    viewElement.setAttribute( "showattsig", m_Options.classState.showAttSig );
    viewElement.setAttribute( "showatts", m_Options.classState.showAtts);
    viewElement.setAttribute( "showopsig", m_Options.classState.showOpSig );
    viewElement.setAttribute( "showops", m_Options.classState.showOps );
    viewElement.setAttribute( "showpackage", m_Options.classState.showPackage );
    viewElement.setAttribute( "showattribassocs", m_Options.classState.showAttribAssocs );
    viewElement.setAttribute( "showscope", m_Options.classState.showVisibility );
    viewElement.setAttribute( "showstereotype", m_Options.classState.showStereoType );
    //misc
    viewElement.setAttribute( "localid", ID2STR(m_nLocalID) );
    viewElement.setAttribute( "showgrid", m_bShowSnapGrid );
    viewElement.setAttribute( "snapgrid", m_bUseSnapToGrid );
    viewElement.setAttribute( "snapcsgrid", m_bUseSnapComponentSizeToGrid );
    viewElement.setAttribute( "snapx", m_nSnapX );
    viewElement.setAttribute( "snapy", m_nSnapY );
    viewElement.setAttribute( "zoom", m_nZoom );
    viewElement.setAttribute( "canvasheight", m_nCanvasHeight );
    viewElement.setAttribute( "canvaswidth", m_nCanvasWidth );
    //now save all the widgets


    QDomElement widgetElement = qDoc.createElement( "widgets" );
    foreach ( UMLWidget *widget , m_WidgetList ) {
        // Having an exception is bad I know, but gotta work with
        // system we are given.
        // We DON'T want to record any text widgets which are belonging
        // to associations as they are recorded later in the "associations"
        // section when each owning association is dumped. -b.t.
        if ((widget->getBaseType() != wt_Text && widget->getBaseType() != wt_FloatingDashLine ) ||
                static_cast<FloatingTextWidget*>(widget)->getLink() == NULL)
            widget->saveToXMI( qDoc, widgetElement );
    }
    viewElement.appendChild( widgetElement );
    //now save the message widgets
    QDomElement messageElement = qDoc.createElement( "messages" );
    foreach( UMLWidget* widget , m_MessageList ) {
        widget -> saveToXMI( qDoc, messageElement );
    }
    viewElement.appendChild( messageElement );
    //now save the associations
    QDomElement assocElement = qDoc.createElement( "associations" );
    if ( m_AssociationList.count() ) {
        // We guard against ( m_AssociationList.count() == 0 ) because
        // this code could be reached as follows:
        //  ^  UMLView::saveToXMI()
        //  ^  UMLDoc::saveToXMI()
        //  ^  UMLDoc::addToUndoStack()
        //  ^  UMLDoc::setModified()
        //  ^  UMLDoc::createDiagram()
        //  ^  UMLDoc::newDocument()
        //  ^  UMLApp::newDocument()
        //  ^  main()
        //
        AssociationWidgetListIt a_it( m_AssociationList );
        AssociationWidget * assoc = 0;
        foreach( assoc , m_AssociationList ) {
            assoc -> saveToXMI( qDoc, assocElement );
        }
    }
    viewElement.appendChild( assocElement );
    qElement.appendChild( viewElement );
}

03117 bool UMLView::loadFromXMI( QDomElement & qElement ) {
    QString id = qElement.attribute( "xmi.id", "-1" );
    m_nID = STR2ID(id);
    if( m_nID == Uml::id_None )
        return false;
    setName( qElement.attribute( "name", "" ) );
    QString type = qElement.attribute( "type", "0" );
    m_Documentation = qElement.attribute( "documentation", "" );
    QString localid = qElement.attribute( "localid", "0" );
    //optionstate uistate
    QString font = qElement.attribute( "font", "" );
    if (!font.isEmpty()) {
        m_Options.uiState.font.fromString( font );
        m_Options.uiState.font.setUnderline(false);
    }
    QString fillcolor = qElement.attribute( "fillcolor", "" );
    QString linecolor = qElement.attribute( "linecolor", "" );
    QString linewidth = qElement.attribute( "linewidth", "" );
    QString usefillcolor = qElement.attribute( "usefillcolor", "0" );
    m_Options.uiState.useFillColor = (bool)usefillcolor.toInt();
    //optionstate classstate
    QString temp = qElement.attribute( "showattsig", "0" );
    m_Options.classState.showAttSig = (bool)temp.toInt();
    temp = qElement.attribute( "showatts", "0" );
    m_Options.classState.showAtts = (bool)temp.toInt();
    temp = qElement.attribute( "showopsig", "0" );
    m_Options.classState.showOpSig = (bool)temp.toInt();
    temp = qElement.attribute( "showops", "0" );
    m_Options.classState.showOps = (bool)temp.toInt();
    temp = qElement.attribute( "showpackage", "0" );
    m_Options.classState.showPackage = (bool)temp.toInt();
    temp = qElement.attribute( "showattribassocs", "0" );
    m_Options.classState.showAttribAssocs = (bool)temp.toInt();
    temp = qElement.attribute( "showscope", "0" );
    m_Options.classState.showVisibility = (bool)temp.toInt();
    temp = qElement.attribute( "showstereotype", "0" );
    m_Options.classState.showStereoType = (bool)temp.toInt();
    //misc
    QString showgrid = qElement.attribute( "showgrid", "0" );
    m_bShowSnapGrid = (bool)showgrid.toInt();

    QString snapgrid = qElement.attribute( "snapgrid", "0" );
    m_bUseSnapToGrid = (bool)snapgrid.toInt();

    QString snapcsgrid = qElement.attribute( "snapcsgrid", "0" );
    m_bUseSnapComponentSizeToGrid = (bool)snapcsgrid.toInt();

    QString snapx = qElement.attribute( "snapx", "10" );
    m_nSnapX = snapx.toInt();

    QString snapy = qElement.attribute( "snapy", "10" );
    m_nSnapY = snapy.toInt();

    QString zoom = qElement.attribute( "zoom", "100" );
    m_nZoom = zoom.toInt();

    QString height = qElement.attribute( "canvasheight", QString("%1").arg(UMLView::defaultCanvasSize) );
    m_nCanvasHeight = height.toInt();

    QString width = qElement.attribute( "canvaswidth", QString("%1").arg(UMLView::defaultCanvasSize) );
    m_nCanvasWidth = width.toInt();

    int nType = type.toInt();
    if (nType == -1 || nType >= 400) {
        // Pre 1.5.5 numeric values
        // Values of "type" were changed in 1.5.5 to merge with Settings::Diagram
        switch (nType) {
            case 400:
                m_Type = Uml::dt_UseCase;
                break;
            case 401:
                m_Type = Uml::dt_Collaboration;
                break;
            case 402:
                m_Type = Uml::dt_Class;
                break;
            case 403:
                m_Type = Uml::dt_Sequence;
                break;
            case 404:
                m_Type = Uml::dt_State;
                break;
            case 405:
                m_Type = Uml::dt_Activity;
                break;
            case 406:
                m_Type = Uml::dt_Component;
                break;
            case 407:
                m_Type = Uml::dt_Deployment;
                break;
            case 408:
                m_Type = Uml::dt_EntityRelationship;
                break;
            default:
                m_Type = Uml::dt_Undefined;
                break;
        }
    } else {
        m_Type = (Uml::Diagram_Type)nType;
    }
    if( !fillcolor.isEmpty() )
        m_Options.uiState.fillColor = QColor( fillcolor );
    if( !linecolor.isEmpty() )
        m_Options.uiState.lineColor = QColor( linecolor );
    if( !linewidth.isEmpty() )
        m_Options.uiState.lineWidth = linewidth.toInt();
    m_nLocalID = STR2ID(localid);

    QDomNode node = qElement.firstChild();
    bool widgetsLoaded = false, messagesLoaded = false, associationsLoaded = false;
    while (!node.isNull()) {
        QDomElement element = node.toElement();
        if (!element.isNull()) {
            if (element.tagName() == "widgets")
                widgetsLoaded = loadWidgetsFromXMI( element );
            else if (element.tagName() == "messages")
                messagesLoaded = loadMessagesFromXMI( element );
            else if (element.tagName() == "associations")
                associationsLoaded = loadAssociationsFromXMI( element );
        }
        node = node.nextSibling();
    }

    if (!widgetsLoaded) {
        uWarning() << "failed umlview load on widgets";
        return false;
    }
    if (!messagesLoaded) {
        uWarning() << "failed umlview load on messages";
        return false;
    }
    if (!associationsLoaded) {
        uWarning() << "failed umlview load on associations";
        return false;
    }
    return true;
}

bool UMLView::loadWidgetsFromXMI( QDomElement & qElement ) {
    UMLWidget* widget = 0;
    QDomNode node = qElement.firstChild();
    QDomElement widgetElement = node.toElement();
    while( !widgetElement.isNull() ) {
        widget = loadWidgetFromXMI(widgetElement);
        if (widget) {
            m_WidgetList.append( widget );
            // In the interest of best-effort loading, in case of a
            // (widget == NULL) we still go on.
            // The individual widget's loadFromXMI method should
            // already have generated an error message to tell the
            // user that something went wrong.
        }
        node = widgetElement.nextSibling();
        widgetElement = node.toElement();
    }

    return true;
}

03277 UMLWidget* UMLView::loadWidgetFromXMI(QDomElement& widgetElement) {

    if ( !m_pDoc ) {
        uWarning() << "m_pDoc is NULL";
        return 0L;
    }

    QString tag  = widgetElement.tagName();
    QString idstr  = widgetElement.attribute( "xmi.id", "-1" );
    UMLWidget* widget = Widget_Factory::makeWidgetFromXMI(tag, idstr, this);

    if (widget == NULL)
        return NULL;
    if (!widget->loadFromXMI(widgetElement)) {
        widget->cleanup();
        delete widget;
        return 0;
    }
    return widget;
}

bool UMLView::loadMessagesFromXMI( QDomElement & qElement ) {
    MessageWidget * message = 0;
    QDomNode node = qElement.firstChild();
    QDomElement messageElement = node.toElement();
    while( !messageElement.isNull() ) {
        QString tag = messageElement.tagName();
        if (tag == "messagewidget" ||
                tag == "UML:MessageWidget" ) {  // for bkwd compatibility
            message = new MessageWidget(this, sequence_message_asynchronous,
                                        Uml::id_Reserved);
            if( !message -> loadFromXMI( messageElement ) ) {
                delete message;
                return false;
            }
            m_MessageList.append( message );
            FloatingTextWidget *ft = message->getFloatingTextWidget();
            if (ft)
                m_WidgetList.append( ft );
            else if (message->getSequenceMessageType() != sequence_message_creation)
                uDebug() << "ft is NULL for message " << ID2STR(message->getID()) << endl;
        }
        node = messageElement.nextSibling();
        messageElement = node.toElement();
    }
    return true;
}

bool UMLView::loadAssociationsFromXMI( QDomElement & qElement ) {
    QDomNode node = qElement.firstChild();
    QDomElement assocElement = node.toElement();
    int countr = 0;
    while( !assocElement.isNull() ) {
        QString tag = assocElement.tagName();
        if (tag == "assocwidget" ||
                tag == "UML:AssocWidget") {  // for bkwd compatibility
            countr++;
            AssociationWidget *assoc = new AssociationWidget(this);
            if( !assoc->loadFromXMI( assocElement ) ) {
                uError() << "couldn't loadFromXMI association widget:"
                          << assoc << ", bad XMI file? Deleting from umlview."
                          << endl;
                delete assoc;
                /* return false;
                   Returning false here is a little harsh when the
                   rest of the diagram might load okay.
                 */
            } else {
                if(!addAssociation(assoc, false))
                {
                    uError()<<"Couldnt addAssociation("<<assoc<<") to umlview, deleting."<<endl;
                    //               assoc->cleanup();
                    delete assoc;
                    //return false; // soften error.. may not be that bad
                }
            }
        }
        node = assocElement.nextSibling();
        assocElement = node.toElement();
    }
    return true;
}

03360 void UMLView::addObject(UMLObject *object)
{
    m_bCreateObject = true;
    if (m_pDoc->addUMLObject(object))
        m_pDoc->signalUMLObjectCreated(object);  // m_bCreateObject is reset by slotObjectCreated()
    else
        m_bCreateObject = false;
}

bool UMLView::loadUisDiagramPresentation(QDomElement & qElement) {
    for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
        QDomElement elem = node.toElement();
        QString tag = elem.tagName();
        if (! Uml::tagEq(tag, "Presentation")) {
            uError() << "ignoring unknown UisDiagramPresentation tag "
                      << tag << endl;
            continue;
        }
        QDomNode n = elem.firstChild();
        QDomElement e = n.toElement();
        QString idStr;
        int x = 0, y = 0, w = 0, h = 0;
        while (!e.isNull()) {
            tag = e.tagName();
            uDebug() << "Presentation: tag = " << tag;
            if (Uml::tagEq(tag, "Presentation.geometry")) {
                QDomNode gnode = e.firstChild();
                QDomElement gelem = gnode.toElement();
                QString csv = gelem.text();
                QStringList dim = csv.split(",");
                x = dim[0].toInt();
                y = dim[1].toInt();
                w = dim[2].toInt();
                h = dim[3].toInt();
            } else if (Uml::tagEq(tag, "Presentation.style")) {
                // TBD
            } else if (Uml::tagEq(tag, "Presentation.model")) {
                QDomNode mnode = e.firstChild();
                QDomElement melem = mnode.toElement();
                idStr = melem.attribute("xmi.idref", "");
            } else {
                uDebug() << "ignoring tag " << tag << endl;
            }
            n = n.nextSibling();
            e = n.toElement();
        }
        Uml::IDType id = STR2ID(idStr);
        UMLObject *o = m_pDoc->findObjectById(id);
        if (o == NULL) {
            uError() << "Cannot find object for id " << idStr << endl;
        } else {
            Uml::Object_Type ot = o->getBaseType();
            uDebug() << "Create widget for model object of type " << ot;
            UMLWidget *widget = NULL;
            switch (ot) {
            case Uml::ot_Class:
                widget = new ClassifierWidget(this, static_cast<UMLClassifier*>(o));
                break;
            case Uml::ot_Association:
                {
                    UMLAssociation *umla = static_cast<UMLAssociation*>(o);
                    Uml::Association_Type at = umla->getAssocType();
                    UMLObject* objA = umla->getObject(Uml::A);
                    UMLObject* objB = umla->getObject(Uml::B);
                    if (objA == NULL || objB == NULL) {
                        uError() << "intern err 1" << endl;
                        return false;
                    }
                    UMLWidget *wA = findWidget(objA->getID());
                    UMLWidget *wB = findWidget(objB->getID());
                    if (wA != NULL && wB != NULL) {
                        AssociationWidget *aw =
                            new AssociationWidget(this, wA, at, wB, umla);
                        aw->syncToModel();
                        m_AssociationList.append(aw);
                    } else {
                        uError() << "cannot create assocwidget from ("
                                  << wA << ", " << wB << ")" << endl;
                    }
                    break;
                }
            case Uml::ot_Role:
                {
                    //UMLRole *robj = static_cast<UMLRole*>(o);
                    //UMLAssociation *umla = robj->getParentAssociation();
                    // @todo properly display role names.
                    //       For now, in order to get the role names displayed
                    //       simply delete the participating diagram objects
                    //       and drag them from the list view to the diagram.
                    break;
                }
            default:
                uError() << "Cannot create widget of type " << ot << endl;
            }
            if (widget) {
                uDebug() << "Widget: x=" << x << ", y=" << y
                          << ", w=" << w << ", h=" << h << endl;
                widget->setX(x);
                widget->setY(y);
                widget->setSize(w, h);
                m_WidgetList.append(widget);
            }
        }
    }
    return true;
}

03467 bool UMLView::loadUISDiagram(QDomElement & qElement) {
    QString idStr = qElement.attribute( "xmi.id", "" );
    if (idStr.isEmpty())
        return false;
    m_nID = STR2ID(idStr);
    UMLListViewItem *ulvi = NULL;
    for (QDomNode node = qElement.firstChild(); !node.isNull(); node = node.nextSibling()) {
        if (node.isComment())
            continue;
        QDomElement elem = node.toElement();
        QString tag = elem.tagName();
        if (tag == "uisDiagramName") {
            setName( elem.text() );
            if (ulvi)
                ulvi->setText( getName() );
        } else if (tag == "uisDiagramStyle") {
            QString diagramStyle = elem.text();
            if (diagramStyle != "ClassDiagram") {
                uError() << "diagram style " << diagramStyle << " is not yet implemented" << endl;
                continue;
            }
            m_pDoc->setMainViewID(m_nID);
            m_Type = Uml::dt_Class;
            UMLListView *lv = UMLApp::app()->getListView();
            ulvi = new UMLListViewItem( lv->theLogicalView(), getName(),
                                        Uml::lvt_Class_Diagram, m_nID );
        } else if (tag == "uisDiagramPresentation") {
            loadUisDiagramPresentation(elem);
        } else if (tag != "uisToolName") {
            uDebug() << "ignoring tag " << tag;
        }
    }
    return true;
}


03503 void UMLView::alignLeft() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestX = getSmallestX(widgetList);

    foreach ( UMLWidget *widget , widgetList) {
        widget->setX(smallestX);
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03517 void UMLView::alignRight() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;
    int biggestX = getBiggestX(widgetList);

    foreach ( UMLWidget *widget , widgetList) {
        widget->setX(biggestX - widget->getWidth());
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03530 void UMLView::alignTop() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestY = getSmallestY(widgetList);

    foreach ( UMLWidget *widget , widgetList ) {
        widget->setY(smallestY);
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03544 void UMLView::alignBottom() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;
    int biggestY = getBiggestY(widgetList);

    foreach ( UMLWidget *widget , widgetList ) {
        widget->setY(biggestY - widget->getHeight());
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03557 void UMLView::alignVerticalMiddle() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestX = getSmallestX(widgetList);
    int biggestX = getBiggestX(widgetList);
    int middle = int((biggestX - smallestX) / 2) + smallestX;

    foreach ( UMLWidget *widget , widgetList ) {
        widget->setX(middle - int(widget->getWidth() / 2));
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03573 void UMLView::alignHorizontalMiddle() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestY = getSmallestY(widgetList);
    int biggestY = getBiggestY(widgetList);
    int middle = int((biggestY - smallestY) / 2) + smallestY;

    foreach ( UMLWidget *widget , widgetList ) {
        widget->setY(middle - int(widget->getHeight() / 2));
        widget->adjustAssocs(widget->getX(),widget->getY());
    }
}

03589 void UMLView::alignVerticalDistribute() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestY = getSmallestY(widgetList);
    int biggestY = getBiggestY(widgetList);
    int heightsSum = getHeightsSum(widgetList);
    int distance = int(((biggestY - smallestY) - heightsSum) / (widgetList.count()-1.0) + 0.5);

    sortWidgetList(widgetList, hasWidgetSmallerY);

    int i = 1;
    UMLWidget* widgetPrev = NULL;
    foreach ( UMLWidget *widget , widgetList) {
        if ( i == 1 ) {
           widgetPrev = widget;
        } else {
            widget->setY(widgetPrev->getY() + widgetPrev->getHeight() + distance);
            widget->adjustAssocs(widget->getX(),widget->getY());
            widgetPrev = widget;
        }
        i++;
    }
}

03616 void UMLView::alignHorizontalDistribute() {
    UMLWidgetList widgetList;
    getSelectedWidgets( widgetList );
    if ( widgetList.isEmpty() )
        return;

    int smallestX = getSmallestX(widgetList);
    int biggestX = getBiggestX(widgetList);
    int widthsSum = getWidthsSum(widgetList);
    int distance = int(((biggestX - smallestX) - widthsSum) / (widgetList.count()-1.0) + 0.5);

    sortWidgetList(widgetList, hasWidgetSmallerX);

    int i = 1;
    UMLWidget* widgetPrev = NULL;
    foreach ( UMLWidget *widget ,  widgetList ) {
        if ( i == 1 ) {
           widgetPrev = widget;
        } else {
           widget->setX(widgetPrev->getX() + widgetPrev->getWidth() + distance);
           widget->adjustAssocs(widget->getX(),widget->getY());
           widgetPrev = widget;
        }
        i++;
    }

}

03644 bool UMLView::hasWidgetSmallerX(const UMLWidget* widget1, const UMLWidget* widget2) {
    return widget1->getX() < widget2->getX();
}

03648 bool UMLView::hasWidgetSmallerY(const UMLWidget* widget1, const UMLWidget* widget2) {
    return widget1->getY() < widget2->getY();
}

03652 int UMLView::getSmallestX(const UMLWidgetList &widgetList) {
    UMLWidgetListIt it(widgetList);

    int smallestX = 0;

    int i = 1;
    foreach ( UMLWidget *widget ,  widgetList ) {
        if ( i == 1 ) {
            smallestX = widget->getX();
        } else {
            if (smallestX > widget->getX())
               smallestX = widget->getX();
        }
        i++;
    }

    return smallestX;
}

03671 int UMLView::getSmallestY(const UMLWidgetList &widgetList) {

    if ( widgetList.isEmpty() )
        return -1;

    int smallestY = 0;

    int i = 1;
    foreach ( UMLWidget *widget ,  widgetList ) {
        if ( i == 1 ) {
            smallestY = widget->getY();
        } else {
            if (smallestY > widget->getY())
               smallestY = widget->getY();
        }
        i++;
    }

    return smallestY;
}

03692 int UMLView::getBiggestX(const UMLWidgetList &widgetList) {
    if ( widgetList.isEmpty() )
        return -1;

    int biggestX = 0;

    int i = 1;
    foreach ( UMLWidget *widget , widgetList ) {
        if ( i == 1 ) {
            biggestX = widget->getX();
            biggestX += widget->getWidth();
        } else {
            if (biggestX < widget->getX() + widget->getWidth())
               biggestX = widget->getX() + widget->getWidth();
        }
        i++;
    }

    return biggestX;
}

03713 int UMLView::getBiggestY(const UMLWidgetList &widgetList) {

    if ( widgetList.isEmpty() )
        return -1;

    int biggestY = 0;

    int i = 1;
    foreach ( UMLWidget *widget , widgetList ) {
        if ( i == 1 ) {
            biggestY = widget->getY();
            biggestY += widget->getHeight();
        } else {
            if (biggestY < widget->getY() + widget->getHeight())
               biggestY = widget->getY() + widget->getHeight();
        }
        i++;
    }

    return biggestY;
}

03735 int UMLView::getHeightsSum(const UMLWidgetList &widgetList) {
    int heightsSum = 0;


    foreach ( UMLWidget *widget , widgetList ) {
        heightsSum += widget->getHeight();
    }

    return heightsSum;
}

03746 int UMLView::getWidthsSum(const UMLWidgetList &widgetList) {
    int widthsSum = 0;

    foreach ( UMLWidget *widget , widgetList ) {
        widthsSum += widget->getWidth();
    }

    return widthsSum;
}

template<typename Compare>
03757 void UMLView::sortWidgetList(UMLWidgetList &widgetList, Compare comp) {
    QVector<UMLWidget*> widgetVector;

    for (UMLWidgetList::iterator it=widgetList.begin(); it != widgetList.end(); ++it) {
        widgetVector.push_back(*it);
    }
    qSort(widgetVector.begin(), widgetVector.end(), comp);

    widgetList.clear();

    for (QVector<UMLWidget*>::iterator it=widgetVector.begin(); it != widgetVector.end(); ++it) {
        widgetList.append(*it);
    }
}

#include "umlview.moc"

Generated by  Doxygen 1.6.0   Back to index