modify abstracttool iface
[yamf.git] / yamf / drawing / photogram.cpp
bloba6a1d9411efa0af69b0096ccabd9d3d882d085fc
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 "photogram.h"
23 #include <QGraphicsItem>
24 #include <QGraphicsView>
25 #include <QStyleOptionGraphicsItem>
26 #include <QGraphicsSceneMouseEvent>
27 #include <QKeyEvent>
28 #include <QSet>
30 #include <model/scene.h>
31 #include <model/layer.h>
32 #include <model/frame.h>
33 #include <model/object.h>
35 #include "item/group.h"
38 #include <drawing/abstracttool.h>
39 #include <drawing/brushmanager.h>
40 #include <drawing/paintarea.h>
42 #include "item/tweener.h"
44 #include <dcore/debug.h>
46 #include <private/guide.h>
48 namespace YAMF {
49 namespace Drawing {
51 struct Photogram::Private
53 Private() : tool(0), scene(0), position(0), isDrawing(false) {}
55 AbstractTool *tool;
56 Model::Scene *scene;
57 struct OnionSkin
59 int previous;
60 int next;
61 QHash<QGraphicsItem *, double> opacityMap;
62 } onionSkin;
64 int position;
66 bool isDrawing;
67 BrushManager *brushManager;
68 PaintArea *paintArea;
70 QList<YAMF::Drawing::Private::Guide *> guides;
73 /**
74 * @~spanish
75 * Construye un fotograma.
77 Photogram::Photogram(PaintArea *parent) : QGraphicsScene(parent), d(new Private)
79 d->paintArea = parent;
81 setItemIndexMethod(QGraphicsScene::NoIndex);
83 d->onionSkin.next = 0;
84 d->onionSkin.previous = 0;
85 d->isDrawing = false;
87 setBackgroundBrush(Qt::gray);
89 d->brushManager = new BrushManager(this);
93 /**
94 * Destructor
96 Photogram::~Photogram()
98 D_END;
100 clearFocus();
101 clearSelection();
103 foreach( QGraphicsView *view, this->views() )
105 view->setScene(0);
108 foreach(QGraphicsItem *item, items())
110 removeItem(item);
113 delete d->tool;
114 delete d;
118 * @~spanish
119 * Asigna @p pos como la posición del fotograma.
121 void Photogram::setCurrent(int pos)
123 d->position = pos;
127 * @~spanish
128 * Dibuja el fotograma actual.
130 void Photogram::drawCurrentPhotogram()
132 drawPhotogram( d->position );
138 * @~spanish
139 * Función reimplementada para proveer la funcionalidad de papel cebolla.
141 void Photogram::drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[], QWidget *widget)
143 for (int i = 0; i < numItems; ++i)
145 QGraphicsItem *item = items[i];
146 painter->save();
147 painter->setMatrix(item->sceneMatrix(), true);
149 if ( d->onionSkin.opacityMap.contains(item) )
151 painter->setOpacity( d->onionSkin.opacityMap[item] );
154 item->paint(painter, &options[i], widget);
156 painter->restore();
162 * @~spanish
163 * Dibuja el fotograma de la posición @p photogram.
165 void Photogram::drawPhotogram(int photogram)
167 if ( photogram < 0 || !d->scene ) return;
170 if( d->tool )
171 d->tool->aboutToChangePhotogram(this);
173 clean();
175 bool valid = false;
177 foreach(Model::Layer *layer, d->scene->layers().values())
179 if ( layer->isVisible() )
181 if( d->onionSkin.previous > 0 )
183 double opacityFactor = 0.5 / (double)qMin(layer->frames().count(),d->onionSkin.previous);
185 double opacity = 0.6;
187 for(int frameIndex = photogram-1; frameIndex > photogram-d->onionSkin.previous-1; frameIndex-- )
189 Model::Frame * frame = layer->frame(frameIndex);
190 if(frame)
192 addFrame( frame, opacity );
194 opacity -= opacityFactor;
198 if ( d->onionSkin.next > 0 )
200 double opacityFactor = 0.5 / (double)qMin(layer->frames().count(), d->onionSkin.next);
201 double opacity = 0.6;
203 for(int frameIndex = photogram+1; frameIndex < photogram+d->onionSkin.next+1; frameIndex++ )
205 Model::Frame * frame = layer->frame(frameIndex);
206 if(frame)
208 addFrame( frame, opacity );
210 opacity -= opacityFactor;
214 Model::Frame *frame = layer->frame( photogram );
216 if( frame )
218 valid = true;
219 addFrame(frame);
224 if( valid )
226 foreach(Model::Object *obj, d->scene->alwaysVisible() )
228 if( obj->frame()->isVisible() )
230 addItem(obj->item());
234 foreach(Model::Object *object, d->scene->tweeningObjects())
236 if(object->frame()->layer()->isVisible() )
238 int origin = object->frame()->visualIndex();
240 if( Item::Tweener *tweener = object->tweener() )
242 if( origin < photogram && photogram <= origin+tweener->frames() )
244 tweener->setStep(0);
245 int step = photogram - origin;
247 tweener->setStep(step);
249 addGraphicObject(object);
255 update();
258 if( d->tool )
260 d->tool->photogramChanged(this);
265 * @~spanish
266 * Añade el frame al fotograma,si este es visible.
268 void Photogram::addFrame(Model::Frame *frame, double opacity )
270 if ( frame->isVisible() )
272 foreach(Model::Object *object, frame->graphics().values() )
274 addGraphicObject(object, opacity);
280 * @~spanish
281 * Añade el objeto grafico @p object al fotograma, con un factor de opacidad @p opacity.
283 void Photogram::addGraphicObject(Model::Object *object, double opacity)
285 QGraphicsItem *item = object->item();
287 if( item )
289 d->onionSkin.opacityMap.insert(item, opacity);
291 if ( Item::Group *group = qgraphicsitem_cast<Item::Group *>(item) )
293 group->recoverChilds();
296 if( ! qgraphicsitem_cast<Item::Group *>(item->parentItem()))
298 addItem(item);
304 * @~spanish
305 * Limpia el fotograma.
307 void Photogram::clean()
309 d->onionSkin.opacityMap.clear();
311 foreach(QGraphicsItem *item, items() )
313 if ( item->scene() == this )
315 removeItem(item);
319 foreach(YAMF::Drawing::Private::Guide *guide, d->guides )
321 addItem(guide);
326 * @~spanish
327 * Asigna los papel cebolla hacia adelante del fotograma.
329 void Photogram::setNextOnionSkinCount(int n)
331 d->onionSkin.next = n;
332 drawCurrentPhotogram();
336 * @~spanish
337 * Asigna los papel cebolla hacia atras del fotograma.
339 void Photogram::setPreviousOnionSkinCount(int n)
341 d->onionSkin.previous = n;
343 drawCurrentPhotogram();
347 * @~spanish
348 * Asigna la scena actual del fotograma.
350 void Photogram::setCurrentScene(Model::Scene *scene)
352 qDeleteAll(d->guides);
353 d->guides.clear();
355 clean();
356 d->scene = scene;
358 drawCurrentPhotogram();
362 * @~spanish
363 * Asigna la visibilidad del layer que esta en la posición @p layerIndex a @p visible.
365 void Photogram::setLayerVisible(int layerIndex, bool visible)
367 if( !d->scene ) return;
369 if( Model::Layer *layer = d->scene->layer(layerIndex) )
371 layer->setVisible(visible);
376 * @~spanish
377 * Retorna la escena del fotograma.
379 Model::Scene *Photogram::scene() const
381 return d->scene;
385 * @~spanish
386 * Asigna @p tool como la herramienta actual.
388 void Photogram::setTool(AbstractTool *tool)
390 drawCurrentPhotogram();
391 if(d->tool)
393 if(d->tool->type() == AbstractTool::Selection )
395 foreach(YAMF::Drawing::Private::Guide *guide, d->guides)
397 guide->setFlag( QGraphicsItem::ItemIsMovable, false );
398 guide->setEnabledSyncCursor(true);
401 d->tool->aboutToChangeTool();
404 d->tool = tool;
405 if(tool->type() == AbstractTool::Selection )
407 foreach(YAMF::Drawing::Private::Guide *guide, d->guides)
409 guide->setFlag( QGraphicsItem::ItemIsMovable, true );
410 guide->setEnabledSyncCursor(false);
413 d->tool->init(this);
418 * @~spanish
419 * Retorna la herramienta actual.
421 AbstractTool *Photogram::currentTool() const
423 return d->tool;
428 * @~spanish
429 * Función reimplementada para informar a la herramienta actual del evento de presionado de un boton del mouse.
431 void Photogram::mousePressEvent(QGraphicsSceneMouseEvent *event)
433 QGraphicsScene::mousePressEvent(event);
435 d->isDrawing = false;
437 if( event->buttons() == Qt::LeftButton && (event->modifiers () == (Qt::ShiftModifier | Qt::ControlModifier)))
440 else if (d->tool )
442 // if( d->tool->type() == AbstractTool::Brush && event->isAccepted() ) return;
444 if( d->position > -1 )
446 if ( event->buttons() == Qt::LeftButton )
448 d->isDrawing = true;
449 d->tool->press(event);
456 * @~spanish
457 * Función reimplementada para informar a la herramienta actual del evento de movimiento del mouse.
459 void Photogram::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
461 QGraphicsScene::mouseMoveEvent(event);
462 mouseMoved(event);
465 * @~spanish
466 * Función que informa a la herramienta actual del movimiento del mouse.
468 void Photogram::mouseMoved(QGraphicsSceneMouseEvent *event)
470 // d->inputInformation->updateFromMouseEvent( event );
472 if (d->tool /*&& d->isDrawing*/ )
474 d->tool->move(event);
479 * @~spanish
480 * Función reimplementada para informar a la herramienta actual del evento de liberación de un boton del mouse.
482 void Photogram::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
484 QGraphicsScene::mouseReleaseEvent(event);
485 mouseReleased(event);
489 * @~spanish
490 * Función que informa a la herramienta actual de liberación de un boton del mouse.
492 void Photogram::mouseReleased(QGraphicsSceneMouseEvent *event)
494 // d->inputInformation->updateFromMouseEvent( event );
496 if ( d->tool && d->isDrawing )
498 d->tool->release(event);
499 // drawCurrentPhotogram(); FIXME esto borra los nodos
502 d->isDrawing = false;
506 * @~spanish
507 * Función reimplementada para informar a la herramienta actual del evento de doble click.
509 void Photogram::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
511 QGraphicsScene::mouseDoubleClickEvent(event);
513 // d->inputInformation->updateFromMouseEvent( event );
515 if(d->tool)
517 d->tool->doubleClick( event);
522 * @~spanish
523 * Función reimplementada para informar a la herramienta actual del evento de preción de una tecla.
525 void Photogram::keyPressEvent(QKeyEvent *event)
527 if ( d->tool )
529 d->tool->keyPressEvent(event);
531 if ( event->isAccepted() )
533 return;
537 QGraphicsScene::keyPressEvent(event);
542 * @~spanish
543 * Función reimplementada para la creación de lineas guias.
545 void Photogram::dragEnterEvent ( QGraphicsSceneDragDropEvent * event )
547 if (event->mimeData()->hasFormat("yamf-ruler"))
549 event->acceptProposedAction();
550 YAMF::Drawing::Private::Guide *guide = 0;
551 if(event->mimeData()->data("yamf-ruler") == "verticalLine")
553 guide = new YAMF::Drawing::Private::Guide(Qt::Vertical, this);
554 guide->setPos(event->scenePos());
556 else
558 guide = new YAMF::Drawing::Private::Guide(Qt::Horizontal, this);
559 guide->setPos(event->scenePos());
562 if(guide)
564 d->guides << guide;
570 * @~spanish
571 * Función reimplementada para la creación de lineas guias.
573 void Photogram::dragLeaveEvent ( QGraphicsSceneDragDropEvent * event)
575 if (event->mimeData()->hasFormat("yamf-ruler"))
577 removeItem(d->guides.last());
578 delete d->guides.takeLast();
583 * @~spanish
584 * Función reimplementada para la creación de lineas guias.
586 void Photogram::dragMoveEvent ( QGraphicsSceneDragDropEvent * event )
588 if (event->mimeData()->hasFormat("yamf-ruler"))
590 if(!d->guides.isEmpty())
592 d->guides.last()->setPos(event->scenePos());
598 * @~spanish
599 * Función reimplementada para la creación de lineas guias.
601 void Photogram::dropEvent ( QGraphicsSceneDragDropEvent * event )
603 Q_UNUSED(event);
604 if(d->tool)
606 if(d->tool->type() == AbstractTool::Selection )
608 d->guides.last()->setEnabledSyncCursor(false);
609 d->guides.last()->setFlag( QGraphicsItem::ItemIsMovable, true );
615 bool Photogram::event(QEvent *e)
617 return QGraphicsScene::event(e);
621 * @~spanish
622 * Retorna verdadero si se esta dibujando.
624 bool Photogram::isDrawing() const
626 return d->isDrawing;
631 * @~spanish
632 * Retorna el manejador de brochas del photograma.
634 BrushManager *Photogram::brushManager() const
636 return d->brushManager;
640 * @~spanish
641 * Evita la selección de elementos que estan en el papel cebolla.
643 void Photogram::aboutToMousePress()
645 QHash<QGraphicsItem *, double>::iterator it = d->onionSkin.opacityMap.begin();
647 while(it != d->onionSkin.opacityMap.end() )
649 if( it.value() != 1.0 )
651 it.key()->setAcceptedMouseButtons(Qt::NoButton);
652 it.key()->setFlag(QGraphicsItem::ItemIsSelectable, false);
654 else
656 it.key()->setAcceptedMouseButtons( Qt::LeftButton | Qt::RightButton | Qt::MidButton | Qt::XButton1 | Qt::XButton2 );
659 ++it;