1 /***************************************************************************
2 * Copyright (C) 2006 by David Cuadrado *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
23 #include <QGraphicsItem>
25 #include <dcore/debug.h>
37 #include <dgraphics/algorithm.h>
38 #include <dgraphics/pathhelper.h>
40 #include "serializer.h"
45 struct Builder::Private
49 QString loading
;//brush or pen
51 QStack
<Group
*> groups
;
52 QStack
<QGraphicsItem
*> objects
;
54 bool addToGroup
, isLoading
;
65 Builder::Builder() : DCore::XmlParserBase(), d(new Private
)
68 d
->addToGroup
= false;
85 * Retorna verdad si se esta cargando un �tem compuesto(grupo) o falso de lo contrario.
88 bool Builder::addingToGroup() const
95 * Si se esta cargando un �tem compuesto, esta funci�n agrupara el ultimo item cargado al grupo que se esta cargando.
97 void Builder::addCurrentToGroup()
99 d
->groups
.last()->addToGroup(d
->objects
.last());
104 * Si se esta cargando un �tem compuesto, Esta funci�n coloca el �tem @p item en la pila de items para agrupar en el �tem que se esta cargando.
106 void Builder::push(QGraphicsItem
*item
)
113 * Si se esta cargando un �tem compuesto, Esta funci�n retira de la pila el �tem que ya fue agrupado al �tem que se esta cargando.
122 * Crea el �tem a construir a partir de la ra�z del documento.
124 QGraphicsItem
* Builder::createItem(const QString
&root
)
126 QGraphicsItem
* item
= 0;
127 if ( root
== "path" )
131 else if ( root
== "rect" )
135 else if ( root
== "ellipse" )
139 else if ( root
== "button" )
143 else if ( root
== "text" )
147 else if ( root
== "line" )
151 else if ( root
== "polygon" )
155 else if ( root
== "group" )
165 * Analiza etiquetas de apertura del documento XML, para extraer las propiedades del �tem.
167 bool Builder::startTag( const QString
& qname
, const QXmlAttributes
& atts
)
169 D_FUNCINFOX("items") << qname
;
170 if ( qname
== "path" )
172 QString data
= atts
.value("data");
175 data
= atts
.value("d");
178 QPainterPath path
= DGraphics::PathHelper::fromString( data
);
182 QGraphicsItem
*item
= createItem(qname
);
183 qgraphicsitem_cast
<Path
*>(item
)->setPath(path
);
185 d
->objects
.push(item
);
190 d
->item
= createItem( qname
);
192 qgraphicsitem_cast
<Path
*>(d
->item
)->setPath(path
);
194 d
->objects
.push(d
->item
);
197 else if ( qname
== "rect" )
199 QRectF
rect(atts
.value("x").toDouble(), atts
.value("y").toDouble(), atts
.value("width").toDouble(), atts
.value("height").toDouble() );
203 Rect
*item
= qgraphicsitem_cast
<Rect
*>(createItem(qname
));
207 d
->objects
.push(item
);
212 d
->item
= createItem( qname
);
213 qgraphicsitem_cast
<Rect
*>(d
->item
)->setRect(rect
);
215 d
->objects
.push(d
->item
);
218 else if ( qname
== "ellipse" )
220 double rx
= atts
.value("rx").toDouble();
221 double ry
= atts
.value("ry").toDouble();
222 double cx
= atts
.value("cx").toDouble();
223 double cy
= atts
.value("cy").toDouble();
225 QRectF
rect(QPointF(cx
-rx
, cy
-ry
), QSizeF(2 * rx
, 2 * ry
));
229 Ellipse
*item
= qgraphicsitem_cast
<Ellipse
*>(createItem(qname
));
232 d
->objects
.push(item
);
237 d
->item
= createItem( qname
);
239 qgraphicsitem_cast
<Ellipse
*>(d
->item
)->setRect(rect
);
241 d
->objects
.push(d
->item
);
245 else if ( qname
== "button" )
249 d
->item
= createItem( qname
);
250 d
->objects
.push(d
->item
);
255 // d->groups.last()->addToGroup( createItem( qname ) );
258 else if ( qname
== "text" )
260 double width
= atts
.value("width").toDouble();
261 QColor
textColor(atts
.value("text-color"));
262 QString text
= atts
.value("data");
266 Text
*item
= qgraphicsitem_cast
<Text
*>(createItem( qname
));
268 item
->setTextWidth(width
);
269 item
->setDefaultTextColor(textColor
);
270 item
->setPlainText(text
);
272 d
->objects
.push(item
);
277 d
->item
= createItem( qname
);
279 Text
*item
= qgraphicsitem_cast
<Text
*>(d
->item
);
281 item
->setTextWidth(width
);
282 item
->setDefaultTextColor(textColor
);
283 item
->setPlainText(text
);
285 d
->objects
.push(d
->item
);
288 // setReadText(true);
289 // d->textReaded = "";
291 else if ( qname
== "line" )
293 QLineF
line(atts
.value("x1").toDouble(), atts
.value("y1").toDouble(), atts
.value("x2").toDouble(), atts
.value("y2").toDouble());
297 Line
*item
= qgraphicsitem_cast
<Line
*>(createItem(qname
));
300 d
->objects
.push(item
);
305 d
->item
= createItem( qname
);
307 qgraphicsitem_cast
<Line
*>(d
->item
)->setLine(line
);
308 d
->objects
.push(d
->item
);
311 else if( qname
== "polygon")
313 QRectF
rect(atts
.value("x").toDouble(), atts
.value("y").toDouble(), atts
.value("width").toDouble(), atts
.value("height").toDouble() );
315 int corners
= atts
.value("corners").toInt();
316 double start
= atts
.value("start").toDouble();
320 Polygon
*item
= qgraphicsitem_cast
<Polygon
*>(createItem(qname
));
322 item
->setCorners(corners
);
323 item
->setStart(start
);
326 d
->objects
.push(item
);
331 d
->item
= createItem( qname
);
333 qgraphicsitem_cast
<Polygon
*>(d
->item
)->setCorners(corners
);
334 qgraphicsitem_cast
<Polygon
*>(d
->item
)->setStart(start
);
335 qgraphicsitem_cast
<Polygon
*>(d
->item
)->setRect(rect
);
337 d
->objects
.push(d
->item
);
340 else if ( qname
== "group" )
344 Group
*group
= qgraphicsitem_cast
<Group
*>( createItem(qname
) );
346 d
->groups
.push(group
);
347 d
->objects
.push(group
);
352 d
->item
= createItem( qname
);
353 d
->groups
.push(qgraphicsitem_cast
<Group
*>(d
->item
));
354 d
->objects
.push(d
->item
);
357 d
->addToGroup
= true;
362 if ( qname
== "properties" && !d
->objects
.isEmpty() )
364 Serializer::loadProperties( d
->objects
.last(), atts
);
366 else if ( qname
== "brush" )
369 Serializer::loadBrush( brush
, atts
);
371 if ( currentTag() == "pen" )
374 QPen pen
= itemPen();
381 setItemBrush( brush
);
384 else if ( qname
== "pen" )
388 Serializer::loadPen( pen
, atts
);
391 else if ( qname
== "font" )
395 Serializer::loadFont( font
, atts
);
397 if ( Text
*text
= qgraphicsitem_cast
<Text
*>(d
->objects
.last()) )
400 text
->setPlainText(text
->toPlainText());
403 else if(qname
== "stop")
407 QColor
c(atts
.value("color"));
408 c
.setAlpha(atts
.value("alpha").toInt());
409 d
->gradient
->setColorAt ( atts
.value("value").toDouble(), c
);
412 else if(qname
== "gradient")
414 d
->gradient
= Serializer::createGradient( atts
);
422 * Analiza el texto del documento XML, para extraer las propiedades del �tem.
425 void Builder::text ( const QString
& ch
)
432 * Analiza etiquetas de cierre del documento XML, para extraer las propiedades del �tem.
434 bool Builder::endTag(const QString
& qname
)
436 D_FUNCINFOX("items") << qname
;
437 if ( qname
== "path" )
441 d
->groups
.last()->addToGroup(d
->objects
.last());
445 else if ( qname
== "rect" )
449 d
->groups
.last()->addToGroup(d
->objects
.last());
453 else if ( qname
== "ellipse" )
457 d
->groups
.last()->addToGroup(d
->objects
.last());
461 else if( qname
== "line" )
465 d
->groups
.last()->addToGroup(d
->objects
.last());
469 else if ( qname
== "button" )
473 d
->groups
.last()->addToGroup(d
->objects
.last());
477 else if ( qname
== "text" )
481 d
->groups
.last()->addToGroup(d
->objects
.last());
485 else if ( qname
== "group" )
488 d
->addToGroup
= !d
->groups
.isEmpty();
492 d
->groups
.last()->addToGroup(d
->objects
.last());
497 else if( qname
== "gradient")
499 if(d
->loading
== "brush")
501 setItemGradient(*d
->gradient
, true);
505 setItemGradient(*d
->gradient
, false);
510 dWarning("items") << "Unhandled: " << qname
;
521 * Pone el estilo de linea al �tem que se esta construyendo actualmente.
523 void Builder::setItemPen(const QPen
&pen
)
525 if(d
->objects
.isEmpty() ) return;
527 if(QGraphicsLineItem
*line
= qgraphicsitem_cast
<QGraphicsLineItem
*>(d
->objects
.last()) )
531 else if ( QAbstractGraphicsShapeItem
*shape
= qgraphicsitem_cast
<QAbstractGraphicsShapeItem
*>(d
->objects
.last() ) )
540 * Pone la brocha al �tem que se esta construyendo actualmente.
542 void Builder::setItemBrush(const QBrush
&brush
)
544 if(d
->objects
.isEmpty() ) return;
546 if ( QAbstractGraphicsShapeItem
*shape
= qgraphicsitem_cast
<QAbstractGraphicsShapeItem
*>(d
->objects
.last() ) )
548 shape
->setBrush(brush
);
556 * Pone un degradado al relleno o al estilo de linea dependiendo del valor de @p brush, al �tem que se esta construyendo actualmente.
558 void Builder::setItemGradient(const QGradient
& gradient
, bool brush
)
560 if(d
->objects
.isEmpty() ) return;
562 QBrush
gBrush(gradient
);
563 if ( QAbstractGraphicsShapeItem
*shape
= qgraphicsitem_cast
<QAbstractGraphicsShapeItem
*>(d
->objects
.last() ) )
567 gBrush
.setMatrix(shape
->brush().matrix());
568 shape
->setBrush( gBrush
);
572 gBrush
.setMatrix(shape
->pen().brush().matrix());
573 QPen pen
= shape
->pen();
574 pen
.setBrush(gBrush
);
578 else if(QGraphicsLineItem
*line
= qgraphicsitem_cast
<QGraphicsLineItem
*>(d
->objects
.last()) )
580 gBrush
.setMatrix(line
->pen().brush().matrix());
581 QPen pen
= line
->pen();
582 pen
.setBrush(gBrush
);
590 * Obtiene el estilo de linea del �tem que se esta construyendo actualmente.
592 QPen
Builder::itemPen() const
594 if( ! d
->objects
.isEmpty() )
596 if(QGraphicsLineItem
*line
= qgraphicsitem_cast
<QGraphicsLineItem
*>(d
->objects
.last()) )
600 else if ( QAbstractGraphicsShapeItem
*shape
= qgraphicsitem_cast
<QAbstractGraphicsShapeItem
*>(d
->objects
.last() ) )
605 return QPen(Qt::transparent
, 1);
611 * Obtiene el relleno del �tem que se esta construyendo actualmente.
614 QBrush
Builder::itemBrush() const
616 if( ! d
->objects
.isEmpty() )
618 if ( QAbstractGraphicsShapeItem
*shape
= qgraphicsitem_cast
<QAbstractGraphicsShapeItem
*>(d
->objects
.last() ) )
620 return shape
->brush();
623 return Qt::transparent
;
628 * Retorna verdad si se le asigna exitosamente los datos que contiene el documento @p xml al @p item. o falso de lo contrario.
630 bool Builder::loadItem(QGraphicsItem
*item
, const QString
&xml
)
636 bool ok
= parse(xml
);
638 d
->isLoading
= false;
644 * Pone el �tem en el cual se van a cargar los datos del documento xml.
646 void Builder::setItem(QGraphicsItem
*item
)
653 * Retorna el �tem que se esta construyendo actualmente.
655 QGraphicsItem
*Builder::item() const
663 * Retorna un �tem construido a partir de documento @p xml.
665 QGraphicsItem
*Builder::create(const QString
&xml
)
667 if( loadItem(0, xml
) )