Modified text and path XML format
[yamf.git] / yamf / item / builder.cpp
blob25a42c7d7cbffdd6c7ad16e8aa7d0bacbaa1dea3
1 /***************************************************************************
2 * Copyright (C) 2006 by David Cuadrado *
3 * krawek@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
21 #include "builder.h"
23 #include <QGraphicsItem>
25 #include <dcore/debug.h>
27 #include "path.h"
28 #include "pixmap.h"
29 #include "text.h"
30 #include "button.h"
31 #include "rect.h"
32 #include "ellipse.h"
33 #include "line.h"
34 #include "group.h"
35 #include "polygon.h"
37 #include <dgraphics/algorithm.h>
38 #include <dgraphics/pathhelper.h>
40 #include "serializer.h"
42 namespace YAMF {
43 namespace Item {
45 struct Builder::Private
47 QGraphicsItem *item;
48 QGradient *gradient;
49 QString loading;//brush or pen
51 QStack<Group *> groups;
52 QStack<QGraphicsItem *> objects;
54 bool addToGroup, isLoading;
56 QString textReaded;
60 /**
61 * @~spanish
62 * Constructor
63 * @return
65 Builder::Builder() : DCore::XmlParserBase(), d(new Private)
67 d->item = 0;
68 d->addToGroup = false;
69 d->isLoading = false;
73 /**
74 * @~spanish
75 * Destructor
76 * @return
78 Builder::~Builder()
80 delete d;
83 /**
84 * @~spanish
85 * Retorna verdad si se esta cargando un �tem compuesto(grupo) o falso de lo contrario.
86 * @return
88 bool Builder::addingToGroup() const
90 return d->addToGroup;
93 /**
94 * @~spanish
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());
103 * @~spanish
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)
108 d->objects << item;
112 * @~spanish
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.
115 void Builder::pop()
117 d->objects.pop();
121 * @~spanish
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" )
129 item = new Path;
131 else if ( root == "rect" )
133 item = new Rect;
135 else if ( root == "ellipse" )
137 item = new Ellipse;
139 else if ( root == "button" )
141 item = new Button;
143 else if ( root == "text" )
145 item = new Text;
147 else if ( root == "line" )
149 item = new Line;
151 else if ( root == "polygon" )
153 item = new Polygon;
155 else if ( root == "group" )
157 item = new Group;
160 return item;
164 * @~spanish
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");
173 if( data.isNull() )
175 data = atts.value("d");
178 QPainterPath path = DGraphics::PathHelper::fromString( data );
180 if ( d->addToGroup )
182 QGraphicsItem *item = createItem(qname);
183 qgraphicsitem_cast<Path *>(item)->setPath(path);
185 d->objects.push(item);
187 else
189 if ( !d->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() );
201 if( d->addToGroup )
203 Rect *item = qgraphicsitem_cast<Rect *>(createItem(qname));
204 item->setRect(rect);
207 d->objects.push(item);
209 else
211 if ( !d->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 ));
227 if( d->addToGroup )
229 Ellipse *item = qgraphicsitem_cast<Ellipse *>(createItem(qname));
230 item->setRect(rect);
232 d->objects.push(item);
234 else
236 if ( !d->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" )
247 if ( !d->item )
249 d->item = createItem( qname );
250 d->objects.push(d->item);
253 if( d->addToGroup )
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");
264 if( d->addToGroup )
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);
274 else
276 if ( !d->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());
295 if( d->addToGroup )
297 Line *item = qgraphicsitem_cast<Line *>(createItem(qname));
298 item->setLine(line);
300 d->objects.push(item);
302 else
304 if ( !d->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();
318 if( d->addToGroup )
320 Polygon *item = qgraphicsitem_cast<Polygon *>(createItem(qname));
322 item->setCorners(corners);
323 item->setStart(start);
324 item->setRect(rect);
326 d->objects.push(item);
328 else
330 if ( !d->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" )
342 if( d->addToGroup )
344 Group *group = qgraphicsitem_cast<Group *>( createItem(qname) );
346 d->groups.push(group);
347 d->objects.push(group);
349 else
351 if ( !d->item )
352 d->item = createItem( qname );
353 d->groups.push(qgraphicsitem_cast<Group *>(d->item));
354 d->objects.push(d->item);
357 d->addToGroup = true;
360 //////////
362 if ( qname == "properties" && !d->objects.isEmpty() )
364 Serializer::loadProperties( d->objects.last(), atts);
366 else if ( qname == "brush" )
368 QBrush brush;
369 Serializer::loadBrush( brush, atts);
371 if ( currentTag() == "pen" )
373 d->loading = "pen";
374 QPen pen = itemPen();
375 pen.setBrush(brush);
376 setItemPen( pen );
378 else
380 d->loading = qname;
381 setItemBrush( brush );
384 else if ( qname == "pen" )
386 QPen pen;
387 d->loading = qname;
388 Serializer::loadPen( pen, atts);
389 setItemPen( pen );
391 else if ( qname == "font" )
393 QFont font;
395 Serializer::loadFont( font, atts);
397 if ( Text *text = qgraphicsitem_cast<Text *>(d->objects.last()) )
399 text->setFont(font);
400 text->setPlainText(text->toPlainText());
403 else if(qname == "stop")
405 if(d->gradient)
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);
417 return true;
421 * @~spanish
422 * Analiza el texto del documento XML, para extraer las propiedades del �tem.
425 void Builder::text ( const QString & ch )
427 d->textReaded += ch;
431 * @~spanish
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" )
439 if(d->addToGroup)
441 d->groups.last()->addToGroup(d->objects.last());
443 d->objects.pop();
445 else if ( qname == "rect" )
447 if(d->addToGroup)
449 d->groups.last()->addToGroup(d->objects.last());
451 d->objects.pop();
453 else if ( qname == "ellipse" )
455 if(d->addToGroup)
457 d->groups.last()->addToGroup(d->objects.last());
459 d->objects.pop();
461 else if( qname == "line" )
463 if(d->addToGroup)
465 d->groups.last()->addToGroup(d->objects.last());
467 d->objects.pop();
469 else if ( qname == "button" )
471 if(d->addToGroup)
473 d->groups.last()->addToGroup(d->objects.last());
475 d->objects.pop();
477 else if ( qname == "text" )
479 if(d->addToGroup)
481 d->groups.last()->addToGroup(d->objects.last());
483 d->objects.pop();
485 else if ( qname == "group" )
487 d->groups.pop();
488 d->addToGroup = !d->groups.isEmpty();
490 if(d->addToGroup)
492 d->groups.last()->addToGroup(d->objects.last());
495 d->objects.pop();
497 else if( qname == "gradient")
499 if(d->loading == "brush")
501 setItemGradient(*d->gradient, true);
503 else
505 setItemGradient(*d->gradient, false);
508 else
510 dWarning("items") << "Unhandled: " << qname;
513 return true;
519 * @internal
520 * @~spanish
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()) )
529 line->setPen(pen);
531 else if ( QAbstractGraphicsShapeItem *shape = qgraphicsitem_cast<QAbstractGraphicsShapeItem *>(d->objects.last() ) )
533 shape->setPen(pen);
538 * @internal
539 * @~spanish
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);
554 * @internal
555 * @~spanish
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() ) )
565 if(brush)
567 gBrush.setMatrix(shape->brush().matrix());
568 shape->setBrush( gBrush );
570 else
572 gBrush.setMatrix(shape->pen().brush().matrix());
573 QPen pen = shape->pen();
574 pen.setBrush(gBrush);
575 shape->setPen(pen);
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);
583 line->setPen(pen);
588 * @internal
589 * @~spanish
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()) )
598 return line->pen();
600 else if ( QAbstractGraphicsShapeItem *shape = qgraphicsitem_cast<QAbstractGraphicsShapeItem *>(d->objects.last() ) )
602 return shape->pen();
605 return QPen(Qt::transparent, 1);
609 * @internal
610 * @~spanish
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;
627 * @~spanish
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)
632 d->item = item;
634 d->isLoading = true;
636 bool ok = parse(xml);
638 d->isLoading = false;
639 return ok;
643 * @~spanish
644 * Pone el �tem en el cual se van a cargar los datos del documento xml.
646 void Builder::setItem(QGraphicsItem *item)
648 d->item = item;
652 * @~spanish
653 * Retorna el �tem que se esta construyendo actualmente.
655 QGraphicsItem *Builder::item() const
657 return d->item;
662 * @~spanish
663 * Retorna un �tem construido a partir de documento @p xml.
665 QGraphicsItem *Builder::create(const QString &xml)
667 if( loadItem(0, xml) )
669 return d->item;
672 return 0;