Root/Software/sie_cg/arrow.cpp

1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the examples of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <QtGui>
43
44#include "arrow.h"
45#include "diagramscene.h"
46#include <math.h>
47
48const qreal Pi = 3.14;
49
50Arrow::Arrow(DiagramTextItem *startItem, DiagramTextItem *endItem,
51         QGraphicsItem *parent, QGraphicsScene *scene)
52    : QGraphicsPathItem(parent, scene)
53{
54    myStartItem = startItem;
55    myEndItem = endItem;
56    arrowSize = 5;
57    moving=0;
58    myColor = Qt::black;
59    setPen(QPen(myColor, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
60    myOwnerScene = scene;
61    lineItem *newLine= new lineItem(QPointF(0,0),QPointF(0,0),this);
62    myOwnerScene->addItem(newLine);
63    addLine(newLine);
64    //setFlag(QGraphicsItem::ItemIsMovable, true);
65    setFlag(QGraphicsItem::ItemIsSelectable, true);
66}
67
68void Arrow::removeLine(lineItem *line)
69{
70    int index = myLines.indexOf(line);
71    int cIndex = myCLines.indexOf(line);
72    if(cIndex!=-1) index = cIndex; //Prevent segmentation fault
73
74    if (index != -1){
75        //Adjust the corners
76        if(myLines.count()>1)
77        {
78            if(index==0)
79            {
80                myCorners.removeAt(0);
81                myOwnerScene->removeItem(myCLines.at(0));
82                myCLines.removeAt(0);
83            }
84            else if(index>0)
85            {
86                myCorners.removeAt(index-1);
87                myOwnerScene->removeItem(myCLines.at(index-1));
88                myCLines.removeAt(index-1);
89            }
90        }
91        myLines.removeAt(index);
92    }
93
94    //If lines is empty the arrow is removed
95    if (myLines.isEmpty())
96    {
97        this->startItem()->ownerItem()->removeArrow(this);
98        this->endItem()->ownerItem()->removeArrow(this);
99        this->myOwnerScene->removeItem(this);
100    }
101}
102
103void Arrow::removeLines()
104{
105    foreach (lineItem *line, myLines) {
106        scene()->removeItem(line);
107        delete line;
108    }
109    foreach (lineItem *line, myCLines) {
110        scene()->removeItem(line);
111        delete line;
112    }
113}
114
115bool Arrow::addLine(lineItem *line)
116{
117        myLines.append(line);
118        return 1;
119}
120
121QRectF Arrow::boundingRect() const
122{
123    qreal extra = (pen().width() + arrowSize*2) / 2.0;
124
125    return QGraphicsPathItem::boundingRect()
126           .normalized()
127           .adjusted(-extra, -extra, extra, extra);
128}
129
130QPainterPath Arrow::shape() const
131{
132    QPainterPath path = QGraphicsPathItem::shape();
133    return path; //FIXME, Arrow heads must to be include
134}
135
136void Arrow::updatePosition()
137{
138    QPainterPath myPath;
139    myPath.moveTo(myStartItem->ownerItem()->pos()+myStartItem->offset()+
140                  QPointF(arrowSize,0));
141    if(!myCorners.isEmpty())
142        foreach(QPointF corner, myCorners){
143            myPath.lineTo(corner);
144        }
145    myPath.lineTo(myEndItem->ownerItem()->pos()+myEndItem->offset()-
146                  QPointF(arrowSize,0));
147
148    setPath(myPath);
149
150}
151//! [3]
152
153void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
154          QWidget *)
155{
156    QPen myPen = pen();
157    myPen.setColor(myColor);
158    painter->setPen(myPen);
159    painter->setBrush(myColor);
160
161    QPointF endPos=myEndItem->ownerItem()->pos()+myEndItem->offset()-
162                   QPointF(arrowSize,0);
163    QPointF startPos=myStartItem->ownerItem()->pos()+myStartItem->offset()+
164                     QPointF(arrowSize,0);
165
166    if(myCorners.isEmpty())
167    {
168        myLines.first()->setLine(QLineF(startPos,endPos));
169    }
170    else
171    {
172        myLines.first()->setLine(QLineF(startPos,myCorners.first()));
173        for(int i=0; i<myCorners.count()-1;i++)
174          myLines.at(i+1)->setLine(QLineF(myCorners.at(i),myCorners.at(i+1)));
175        myLines.last()->setLine(QLineF(myCorners.last(),endPos));
176    }
177
178    //Drawing arrow selected
179    for(int i=0; i<myLines.count();i++)
180        if (isSelected())
181        {
182            painter->setPen(QPen(Qt::gray, 2, Qt::SolidLine));
183            QLineF myLine = myLines.at(i)->line();
184            painter->drawLine(myLine);
185            foreach (lineItem *line, myLines) { line->setColor(Qt::gray);}
186            foreach (lineItem *line, myCLines) { line->setColor(Qt::gray);}
187        }
188        else
189        {
190            foreach (lineItem *line, myLines) { line->setColor(myColor);}
191            foreach (lineItem *line, myCLines) { line->setColor(myColor);}
192        }
193
194    //End arrow head
195    QPointF arrowP1=QPointF(endPos+QPointF(0,arrowSize));
196    QPointF arrowP2=QPointF(endPos+QPointF(0,-arrowSize));
197
198    arrowHeadEnd.clear();
199    arrowHeadEnd << endPos+QPointF(arrowSize,0) << arrowP1 << arrowP2;
200
201    painter->drawPolygon(arrowHeadEnd);
202    //Start arrow head
203    arrowP1=QPointF(startPos+QPointF(-arrowSize,arrowSize));
204    arrowP2=QPointF(startPos+QPointF(-arrowSize,-arrowSize));
205
206    arrowHeadStart.clear();
207    arrowHeadStart << startPos << arrowP1 << arrowP2;
208    painter->drawPolygon(arrowHeadStart);
209
210    //Set visible corners
211    bool anySelected = 0;
212
213    foreach(lineItem *line,myLines){ if(line->isSelected())anySelected=1;}
214    foreach(lineItem *line,myCLines){ if(line->isSelected())anySelected=1;}
215    if(isSelected()) anySelected=1;
216
217    if(anySelected)
218        setVisibleCorners(1);
219    else
220        setVisibleCorners(0);
221}
222
223void Arrow::createCorner(QPointF cornerPos, lineItem *inLine)
224{
225    createCorner(cornerPos,myLines.indexOf(inLine));
226}
227
228void Arrow::createCorner(QPointF cornerPos, int index)
229{
230    if (index != -1)
231    {
232            myCorners.insert(index,cornerPos);
233            lineItem *newLine= new lineItem(QPointF(0,0),QPointF(0,0),this);
234            myOwnerScene->addItem(newLine);
235            newLine->setZValue(this->zValue());
236            addLine(newLine);
237            newLine= new lineItem(cornerPos+QPointF(-0.5,-0.5) ,
238                                  cornerPos+QPointF(0.5,0.5),this,6,1);
239            myOwnerScene->addItem(newLine);
240            newLine->setZValue(this->zValue()+0.1);
241            myCLines.insert(index,newLine);
242    }
243}
244
245void Arrow::moveCorner(QPointF cornerPos, lineItem *inLine)
246{
247    int index = myCLines.indexOf(inLine);
248
249    if (index != -1)
250    {
251            cornerPos=mapFromItem(inLine,cornerPos);
252            myCorners.replace(index,cornerPos);
253            updatePosition();
254    }
255}
256
257void Arrow::setVisibleCorners(bool visible)
258{
259    foreach (lineItem *line, myCLines) {
260        line->setVisible(visible);
261    }
262}
263
264void Arrow::setSelectedLines(bool sel)
265{
266    foreach (lineItem *line, myCLines) {
267        line->setSelected(sel);
268    }
269    foreach (lineItem *line, myLines) {
270        line->setSelected(sel);
271    }
272}
273
274QDomElement Arrow::toXml(QDomDocument &document,
275                          QHash<int , DiagramItem *> DiagramsID) const
276{
277        QDomElement diagramArrow = document.createElement("Arrow");
278
279        //Set attibutes; startItem
280        diagramArrow.setAttribute("start-x",startOffset().x());
281        diagramArrow.setAttribute("start-y",startOffset().y());
282        diagramArrow.setAttribute("start-Owner",
283                                  DiagramsID.key(startOwner()));
284        diagramArrow.setAttribute("start-ID",this->startItem()->textID());
285
286        //Set attibutes; endItem
287        diagramArrow.setAttribute("end-x",endOffset().x());
288        diagramArrow.setAttribute("end-y",endOffset().y());
289        diagramArrow.setAttribute("end-Owner",
290                                  DiagramsID.key(endOwner()));
291        diagramArrow.setAttribute("end-ID",this->endItem()->textID());
292
293        diagramArrow.setAttribute("color",myColor.name());
294
295        //Corners list
296        int i=0;
297        if(!myCorners.isEmpty())
298        {
299            QDomElement arrowCorners = document.createElement("arrowCorners");
300            foreach(QPointF corner, myCorners)
301            {
302                QDomElement arrowCorner = document.createElement("arrowCorner");
303                arrowCorner.setAttribute("x",corner.x());
304                arrowCorner.setAttribute("y",corner.y());
305                i++;
306                arrowCorners.appendChild(arrowCorner);
307            }
308
309            diagramArrow.appendChild(arrowCorners);
310        }
311        return (diagramArrow);
312}
313
314void Arrow::snapToGrid(QGraphicsSceneMouseEvent *event)
315{
316    //TODO implement polygon drag
317    QPointF diffPos= event->scenePos()-previousPos;
318    //Update corners:
319    for(int i=0; i < myCorners.count();i++)
320    {
321        myCLines.at(i)->setLine(QLineF(myCLines.at(i)->line().p1()+diffPos,
322                                       myCLines.at(i)->line().p2()+diffPos));
323        QPointF itemPos = myCLines.at(i)->line().p1()+QPointF(0.5,0.5);
324        moveCorner(itemPos,myCLines.at(i));
325    }
326    updatePosition();
327}
328
329void Arrow::mousePressEvent(QGraphicsSceneMouseEvent *event)
330{
331    //if(this->isSelected())
332    {
333        previousPos = event->scenePos();
334        moving=1;
335    }
336    setSelectedLines(false);
337    positionChanged=0;
338    qobject_cast<DiagramScene *>(myOwnerScene)->saveUndo();
339
340    QGraphicsPathItem::mousePressEvent(event);
341}
342
343void Arrow::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
344{
345    if(moving && isSelected())
346    {
347        snapToGrid(event);
348        previousPos = event->scenePos();
349    }
350    moving=0;
351
352    if(!positionChanged)
353        qobject_cast<DiagramScene *>(myOwnerScene)->removeLastUndo();
354    else
355        qobject_cast<DiagramScene *>(myOwnerScene)->clearRedo();
356
357    QGraphicsPathItem::mouseReleaseEvent(event);
358}
359
360void Arrow::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
361{
362    if(moving && isSelected())
363    {
364        snapToGrid(event);
365        previousPos = event->scenePos();
366        positionChanged=1;
367    }
368    QGraphicsPathItem::mouseMoveEvent(event);
369}
370

Archive Download this file

Branches:
master



interactive