1 /*
2 * wbnewpath.cpp - a class used for representing a path on the whiteboard
3 * while it's being drawn.
4 * Copyright (C) 2008 Joonas Govenius
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "wbnewpath.h"
23 #include "../sxe/sxesession.h"
24
25 #include <QGraphicsScene>
26 #include <QPainterPath>
27
WbNewPath(QGraphicsScene * s,QPointF startPos,int strokeWidth,const QColor & strokeColor,const QColor & fillColor)28 WbNewPath::WbNewPath(QGraphicsScene* s, QPointF startPos, int strokeWidth, const QColor &strokeColor, const QColor &fillColor) : WbNewItem(s) {
29 controlPoint_ = 0;
30
31 graphicsitem_.setZValue(std::numeric_limits<double>::max());
32
33 graphicsitem_.setBrush(QBrush(fillColor));
34 graphicsitem_.setPen(QPen(QBrush(strokeColor), strokeWidth));
35
36 scene->addItem(&graphicsitem_);
37
38 QPainterPath painterpath(startPos);
39 painterpath.setFillRule(Qt::WindingFill);
40 graphicsitem_.setPath(painterpath);
41 }
42
~WbNewPath()43 WbNewPath::~WbNewPath() {
44 if(controlPoint_) {
45 delete controlPoint_;
46 }
47 }
48
parseCursorMove(QPointF newPos)49 void WbNewPath::parseCursorMove(QPointF newPos) {
50 if(controlPoint_) {
51 QPainterPath painterpath = graphicsitem_.path();
52 // FIXME: the path should actually go through the "controlPoint_".
53 painterpath.quadTo(*controlPoint_, newPos);
54 graphicsitem_.setPath(painterpath);
55
56 delete controlPoint_;
57 controlPoint_ = 0;
58 }
59 else {
60 controlPoint_ = new QPointF(newPos);
61 }
62 }
63
serializeToSvg(QDomDocument * doc)64 QDomNode WbNewPath::serializeToSvg(QDomDocument *doc) {
65 if(controlPoint_) {
66 QPainterPath painterpath = graphicsitem_.path();
67 painterpath.lineTo(*controlPoint_);
68 graphicsitem_.setPath(painterpath);
69
70 delete controlPoint_;
71 controlPoint_ = 0;
72 }
73
74 // trim the generated SVG to remove unnecessary nested <g/>'s
75
76 // first find the <path/> element
77 QDomNode out = WbNewItem::serializeToSvg(doc);
78 QDomElement trimmed;
79 for(QDomNode n = out.firstChild(); !n.isNull(); n = n.nextSibling()) {
80 if(n.isElement()) {
81 if(n.nodeName() == "path") {
82 trimmed = n.toElement();
83 break;
84 } else {
85 trimmed = n.toElement().elementsByTagName("path").at(0).toElement();
86 if(!trimmed.isNull())
87 break;
88 }
89 }
90 }
91
92 if (!trimmed.isNull()) {
93 // copy relevant attributes from the parent <g/>
94 QDomNamedNodeMap parentAttr = trimmed.parentNode().toElement().attributes();
95 for(int i = parentAttr.length() - 1; i >= 0; i--) {
96 QString name = parentAttr.item(i).nodeName();
97 if((name == "stroke"
98 || name == "stroke-width"
99 || name == "stroke-linecap"
100 || name == "fill"
101 || name == "fill-opacity")
102 && !trimmed.hasAttribute(name))
103 trimmed.setAttributeNode(parentAttr.item(i).toAttr());
104 }
105
106 // add a unique 'id' attribute in anticipation of WbWidget's requirements
107 trimmed.setAttribute("id", "e" + SxeSession::generateUUID());
108 }
109
110 return trimmed;
111 }
112
graphicsItem()113 QGraphicsItem* WbNewPath::graphicsItem() {
114 return &graphicsitem_;
115 }
116