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