1 /***************************************************************************
2 * Copyright (C) 2007 by Jorge Cuadrado *
3 * kuadrosxx@gmail.com *
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 <drawing/photogram.h>
24 #include <drawing/brushmanager.h>
25 #include <drawing/paintarea.h>
27 #include <dgraphics/patheditor.h>
28 #include <dgui/action.h>
29 #include <dgui/iconloader.h>
30 #include <dcore/debug.h>
32 #include <selection/private/contoureditor.h>
33 #include <model/command/editnodesitem.h>
35 #include <model/frame.h>
36 #include <item/path.h>
41 #include <QKeySequence>
42 #include <QGraphicsPathItem>
43 #include <QPainterPath>
45 #include <QGraphicsLineItem>
46 #include <QGraphicsView>
48 #include <QGraphicsSceneMouseEvent>
56 struct PolyLine::Private
61 Drawing::Tool::Private::ContourEditor
*editor
;
63 QPainterPath lastPart
;
65 YAMF::Item::Path
*item
;
66 PaintArea
* paintArea
;
69 QGraphicsLineItem
*line1
, *line2
;
71 QGraphicsPathItem
*line3
;
76 * Construye la herramienta para dibujar trazos rectos y curvilíneos.
78 PolyLine::PolyLine(QObject
*parent
): AbstractTool(parent
), d(new Private
)
85 d
->line1
= new QGraphicsLineItem(0,0,0,0);
86 d
->line1
->setPen ( QPen(Qt::red
) );
87 d
->line2
= new QGraphicsLineItem(0,0,0,0);
88 d
->line2
->setPen ( QPen(Qt::green
) );
90 d
->line3
= new QGraphicsPathItem();
92 d
->action
= new DGui::Action( DGui::IconLoader::self()->load("draw-path.svg"), tr("Poly line"), this);
93 d
->action
->setShortcut( QKeySequence(tr("")) );
100 PolyLine::~PolyLine()
107 * Inicializa la herramienta, evita que los items dentro de el fotograma se puedan mover o seleccionar.
109 void PolyLine::init(Photogram
*photogram
)
113 foreach(QGraphicsView
*view
, photogram
->views() )
115 view
->setDragMode ( QGraphicsView::NoDrag
);
117 Q_CHECK_PTR(view
->scene());
118 if ( QGraphicsScene
*sscene
= qobject_cast
<QGraphicsScene
*>(view
->scene()) )
120 foreach(QGraphicsItem
*item
, sscene
->items() )
122 item
->setFlag(QGraphicsItem::ItemIsSelectable
, false);
123 item
->setFlag(QGraphicsItem::ItemIsMovable
, false);
125 sscene
->addItem( d
->line1
);
126 sscene
->addItem( d
->line2
);
133 * Retorna el id de la herramienta.
135 QString
PolyLine::id() const
137 return tr("PolyLine");
142 * Función sobrecargada para implementar la creación de los trazos rectos y curvilíneos.
144 void PolyLine::press(const QGraphicsSceneMouseEvent
*input
)
146 d
->paintArea
= this->paintArea(); // FIXME
147 QGraphicsScene
*scene
= d
->paintArea
->scene();
148 if(scene
->items().contains(d
->line3
))
150 scene
->removeItem(d
->line3
);
153 BrushManager
*brushManager
= d
->paintArea
->brushManager();
155 scene
->clearSelection();
159 d
->path
= QPainterPath();
160 d
->path
.moveTo(input
->scenePos());
162 d
->item
= new YAMF::Item::Path();
163 d
->item
->setZValue(1000);
164 d
->editor
= new Drawing::Tool::Private::ContourEditor(d
->item
, scene
);
165 connect(d
->editor
, SIGNAL(nodeClicked()), this, SLOT(nodeChanged()));
166 scene
->addItem( d
->item
);
177 d
->path
.cubicTo(d
->center
, d
->center
, input
->scenePos());
179 d
->item
->setPath(d
->path
);
180 d
->paintArea
->brushManager()->map(d
->item
);
185 d
->path
.cubicTo(d
->center
, d
->right
, input
->scenePos());
187 d
->item
->setPath(d
->path
);
188 d
->paintArea
->brushManager()->map(d
->item
);
192 d
->center
= input
->scenePos();
194 d
->item
->setPen( brushManager
->pen() );
199 * Función sobrecargada para implementar la creación de los trazos rectos y curvilíneos.
201 void PolyLine::move(const QGraphicsSceneMouseEvent
*input
)
203 PaintArea
*paintArea
= this->paintArea();
204 QGraphicsScene
*scene
= paintArea
->scene();
207 if(input
->buttons() == Qt::NoButton
)
209 QPainterPath lastPart
;
211 lastPart
.moveTo(d
->center
);
215 // lastPart.lineTo(input->scenePos());
216 lastPart
.cubicTo(d
->center
, d
->center
, input
->scenePos());
220 lastPart
.cubicTo(d
->center
, d
->right
, input
->scenePos());
223 d
->line3
->setPath(lastPart
);
224 if(!scene
->items().contains(d
->line3
))
226 scene
->addItem(d
->line3
);
229 if(!scene
->items().contains(d
->line1
))
231 scene
->addItem( d
->line1
);
233 if(!scene
->items().contains(d
->line2
))
235 scene
->addItem( d
->line2
);
238 else if(d
->editor
&& d
->editor
->isSelected())
240 d
->path
= d
->item
->path();
242 else if(input
->buttons() == Qt::LeftButton
)
244 paintArea
->setDragMode(QGraphicsView::NoDrag
);
249 d
->right
= input
->scenePos();
251 d
->line2
->setLine(QLineF(d
->right
, d
->center
));
252 if(!scene
->items().contains(d
->line2
))
254 scene
->addItem( d
->line2
);
259 int index
= d
->path
.elementCount()-3;
261 if( d
->path
.elementAt(index
).type
== QPainterPath::CurveToElement
)
265 QPointF point
= d
->path
.elementAt(index
+1);
266 d
->path
.setElementPositionAt(index
, point
.x(), point
.y() );
269 QPointF mirror
= d
->center
- ( input
->scenePos() - d
->center
);
271 d
->path
.setElementPositionAt(index
+1, mirror
.x(), mirror
.y());
273 d
->line1
->setLine(QLineF(mirror
, d
->center
));
274 d
->line2
->setLine(QLineF(d
->right
, d
->center
));
276 if(!scene
->items().contains(d
->line1
))
278 scene
->addItem( d
->line1
);
280 if(!scene
->items().contains(d
->line2
))
282 scene
->addItem( d
->line2
);
287 d
->right
= input
->scenePos();
288 d
->item
->setPath(d
->path
);
289 paintArea
->brushManager()->map(d
->item
);
298 * Función sobrecargada para implementar la creación de los trazos rectos y curvilíneos.
300 void PolyLine::release(const QGraphicsSceneMouseEvent
*input
)
303 PaintArea
*paintArea
= this->paintArea();
305 d
->editor
->expandAllNodes ();
310 paintArea
->currentFrame()->addItem(d
->item
);
312 else if(!d
->editor
->isSelected())
314 int position
= paintArea
->currentFrame()->visualIndexOf(d
->item
);
318 paintArea
->addCommand(new Command::EditNodesItem(d
->item
, d
->editor
->oldPath(), paintArea
->currentFrame()));
326 * Función sobrecargada para implementar la creación de los trazos rectos y curvilíneos.
327 * termina de hacer el trazo.
329 void PolyLine::doubleClick(const QGraphicsSceneMouseEvent
*input
)
337 void PolyLine::keyPressEvent(QKeyEvent
*event
)
339 if(event
->key() == Qt::Key_Escape
)
348 * Retorna la acción que representa la herramienta.
350 DGui::Action
*PolyLine::action() const
357 * Retorna que la herramienta es de tipo Brush.
359 int PolyLine::type() const
361 return AbstractTool::Brush
;
366 * Función sobrecargada para terminar de crear el ítem, cuando se cambia la herramienta.
368 void PolyLine::aboutToChangeTool()
374 * Función sobrecargada para actualizar valores cuando hay un cambio en el fotograma.
376 void PolyLine::photogramChanged(Photogram
*const photogram
)
381 // d->path = d->item->path();
382 // d->editor->setItem(d->item);
383 if(!d
->item
->path().isEmpty())
387 // d->editor->expandAllNodes();
388 int size
= d
->item
->path().elementCount();
391 d
->center
= d
->item
->path().elementAt(size
-1);
398 * Termina de crear el trazo.
400 void PolyLine::endItem()
404 d
->path
= QPainterPath();
413 * Actualiza los valores cuando se modifican los nodos de trazo.
415 void PolyLine::nodeChanged()
419 int position
= d
->paintArea
->currentFrame()->visualIndexOf(d
->item
);
423 int size
= d
->item
->path().elementCount();
426 d
->center
= d
->item
->path().elementAt(size
-1);
428 d
->path
= d
->item
->path();
429 d
->paintArea
->addCommand(new Command::EditNodesItem(d
->item
, d
->editor
->oldPath(), d
->paintArea
->currentFrame()));