1 /***************************************************************************
2 * Copyright (C) 2005 by Jorge Cuadrado *
3 * kuadrosxx@gmail.com *
4 * Copyright (C) 2006 by David Cuadrado *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
23 #include "paintarea.h"
25 #include "private/paintarearotator.h"
27 #include <QGraphicsScene>
28 #include <QMouseEvent>
29 #include <QGraphicsSceneMouseEvent>
30 #include <QGraphicsRectItem>
32 #include <QApplication>
34 #include <QStyleOptionGraphicsItem>
40 #include "photogram.h"
41 #include <dgraphics/algorithm.h>
43 #include <dcore/config.h>
44 #include <dcore/debug.h>
45 #include <dgui/application.h>
47 #include <dgui/commandhistory.h>
48 #include <dgui/action.h>
49 #include <dgui/actionmanager.h>
50 #include <dgui/iconloader.h>
54 #include <model/scene.h>
55 #include <model/layer.h>
56 #include <model/frame.h>
57 #include <model/object.h>
58 #include <model/library.h>
60 #include <item/group.h>
61 #include <item/serializer.h>
62 #include "yamf/item/tweenerstep.h"
63 #include "yamf/item/tweener.h"
65 #include "model/command/base.h"
66 #include "model/command/groupitem.h"
67 #include "model/command/ungroupitem.h"
68 #include "model/command/modifyitem.h"
69 #include "model/command/modifysymbol.h"
70 #include "model/command/sendtobackitem.h"
71 #include "model/command/bringtofrontitem.h"
72 #include "model/command/sendbackwardsitem.h"
73 #include "model/command/bringforwardsitem.h"
74 #include "model/command/manager.h"
75 #include "yamf/model/command/additemfilter.h"
77 #include "yamf/model/libraryitem.h"
78 #include "yamf/model/audiolayer.h"
80 #include "yamf/effect/factory.h"
81 #include "yamf/effect/filter.h"
83 #include <drawing/abstracttool.h>
84 #include <private/addsymboldialog.h>
92 #include <QGLFramebufferObject>
94 class GLDevice
: public QGLWidget
97 GLDevice() : QGLWidget()
106 glDisable(GL_DEPTH_TEST
);
111 struct YAMF::Drawing::PaintArea::Private
113 Private(YAMF::Drawing::PaintArea
*paintArea
, Model::Project
*const project
) : paintArea(paintArea
), project(project
), lastScaleFactor(1.0)
117 DGui::CommandHistory
*history
;
119 YAMF::Drawing::PaintArea
*paintArea
;
126 YAMF::Drawing::Private::PaintAreaRotator
*rotator
;
127 Photogram
*photogram
;
129 struct FramePosition
{
135 struct ItemProperties
{
140 QList
<ItemProperties
> properties
;
144 DGui::ActionManager actionManager
;
146 Model::Project
*const project
;
148 double lastScaleFactor
;
150 QToolBar
*toolsConfigBar
;
151 QToolBar
*effectsConfigBar
;
155 Item::TweenerStep
*step
;
157 QList
<RecordStep
> steps
;
162 void PaintArea::Private::recordIt()
164 Model::Object
*recorded
= photogram
->recorded();
166 int currentPos
= paintArea
->currentFrame()->visualIndex();
167 int objectPos
= recorded
->frame()->visualIndex();
170 record
.step
= new Item::TweenerStep(currentPos
-objectPos
);
172 record
.step
->setPosition(recorded
->item()->pos());
181 * Construye un area de trabajo relacionada con el proyecto @p project.
183 PaintArea::PaintArea(Model::Project
*const project
, QWidget
* parent
) : QGraphicsView(parent
), d(new Private(this, project
) )
185 d
->history
= new DGui::CommandHistory( project
->commandManager()->stack(), this);
187 d
->photogram
= new Photogram(this);
192 d
->rotator
= new YAMF::Drawing::Private::PaintAreaRotator(this, this);
194 d
->drawingRect
= QRectF(QPointF(0,0), QSizeF( 500, 400 ) ); // FIXME: configurable
196 d
->photogram
->setSceneRect(d
->drawingRect
);
197 setScene(d
->photogram
);
201 setUseOpenGL( false );
202 setInteractive ( true );
206 setCurrentFrame(-1, -1, -1);
208 d
->origin
= mapToScene(QPoint(0, 0));
213 d
->toolsConfigBar
= new QToolBar(tr("Configure tool"), this);
215 d
->effectsConfigBar
= new QToolBar(tr("Configure effects"), this);
220 * Guarda en la configuracion el estado de las propiedades del area de dibujo.
222 void PaintArea::saveState()
224 DCore::Config
*config
= dApp
->config( "PaintArea" );
226 config
->setValue("render_hints", int(renderHints()));
227 config
->setValue("show_grid", d
->drawGrid
);
234 * Recupera de la configuracion el estado de las propiedades del area de dibujo.
236 void PaintArea::restoreState()
238 DCore::Config
*config
= dApp
->config( "PaintArea" );
240 int renderHints
= config
->value("render_hints", int(this->renderHints())).toInt();
241 setRenderHints(QPainter::RenderHints(renderHints
));
243 bool showGrid
= config
->value("show_grid", false).toBool();
244 setDrawGrid(showGrid
);
252 PaintArea::~PaintArea()
254 d
->toolsConfigBar
->clear();
262 * Crea las acciones relacionadas con el area de dibujo.
264 void PaintArea::createActions()
266 addAction( d
->history
->undoAction() );
267 addAction( d
->history
->redoAction() );
269 connect(d
->project
->commandManager(), SIGNAL(historyChanged()), this, SLOT(onHistoryChanged()));
271 QAction
*remove
= new QAction(DGui::IconLoader::self()->load("edit-delete.svg"), tr("Delete"), this);
272 remove
->setShortcut(QKeySequence::Delete
);
273 connect(remove
, SIGNAL(triggered()), this, SLOT(removeSelectedObjects()));
276 QAction
*selectAll
= new QAction(DGui::IconLoader::self()->load("select-all.svg"), tr("Select all"), this);
277 selectAll
->setShortcut(QKeySequence::SelectAll
);
278 connect(selectAll
, SIGNAL(triggered()), this, SLOT(selectAllObjects()));
279 addAction(selectAll
);
281 QAction
*copy
= new QAction( DGui::IconLoader::self()->load("edit-copy.svg"), tr("Copy"), this);
282 copy
->setShortcut(QKeySequence::Copy
);
283 connect(copy
, SIGNAL(triggered()), this, SLOT(copySelectedObjects()));
286 QAction
*paste
= new QAction(DGui::IconLoader::self()->load("edit-paste.svg"), tr("Paste"), this);
287 paste
->setShortcut(QKeySequence::Paste
);
288 connect(paste
, SIGNAL(triggered()), this, SLOT(pasteObjects()));
291 QAction
*cut
= new QAction(DGui::IconLoader::self()->load("edit-cut.svg"), tr("Cut"), this);
292 cut
->setShortcut(QKeySequence::Cut
);
293 connect(cut
, SIGNAL(triggered()), this, SLOT(cutSelectedObjects()));
297 d
->actionManager
.add(selectAll
, "selectall", "edit");
298 d
->actionManager
.addSeparator("edit");
299 d
->actionManager
.add(cut
, "cut", "edit");
300 d
->actionManager
.add(copy
, "copy", "edit");
301 d
->actionManager
.add(paste
, "paste", "edit");
302 d
->actionManager
.addSeparator("edit");
303 d
->actionManager
.add(remove
, "remove", "edit");
307 QAction
*group
= new QAction(DGui::IconLoader::self()->load("object-group.svg"), tr("Group"), this);
308 group
->setShortcut(Qt::CTRL
+ Qt::Key_G
);
309 connect(group
, SIGNAL(triggered()), this, SLOT(groupSelectedObjects()));
310 d
->actionManager
.add(group
, "group", "object");
313 QAction
*ungroup
= new QAction(DGui::IconLoader::self()->load("object-ungroup.svg"), tr("Ungroup"), this);
314 ungroup
->setShortcut(Qt::CTRL
+ Qt::SHIFT
+ Qt::Key_G
);
315 connect(ungroup
, SIGNAL(triggered()), this, SLOT(ungroupSelectedObject()));
316 d
->actionManager
.add(ungroup
, "ungroup", "object");
319 QAction
*sendToBack
= new QAction(DGui::IconLoader::self()->load("object-send-to-back.svg"), tr("Send to back"), this);
320 sendToBack
->setShortcut(Qt::Key_Home
);
321 connect(sendToBack
, SIGNAL(triggered()), this, SLOT(sendToBackSelectedObjects()));
322 d
->actionManager
.add(sendToBack
, "sendtoback", "object-order");
323 addAction(sendToBack
);
325 QAction
*bringToFront
= new QAction(DGui::IconLoader::self()->load("object-bring-to-front.svg"), tr("Bring to front"), this);
326 bringToFront
->setShortcut(Qt::Key_End
);
327 connect(bringToFront
, SIGNAL(triggered()), this, SLOT(bringToFrontSelectedObjects()));
328 d
->actionManager
.add(bringToFront
, "bringtofront", "object-order");
329 addAction(bringToFront
);
331 QAction
*sendBackwards
= new QAction(DGui::IconLoader::self()->load("object-send-backwards.svg"), tr("Send backwards"), this);
332 sendBackwards
->setShortcut(Qt::Key_PageDown
);
333 connect(sendBackwards
, SIGNAL(triggered()), this, SLOT(sendBackwardsSelectedObjects()));
334 d
->actionManager
.add(sendBackwards
, "sendbackwards", "object-order");
335 addAction(sendBackwards
);
337 QAction
*bringForwards
= new QAction(DGui::IconLoader::self()->load("object-bring-forwards.svg"), tr("Bring forwards"), this);
338 bringForwards
->setShortcut(Qt::Key_PageUp
);
339 connect(bringForwards
, SIGNAL(triggered()), this, SLOT(bringForwardsSelectedObjects()));
340 d
->actionManager
.add(bringForwards
, "bringforwards", "object-order");
341 addAction(bringForwards
);
345 QAction
*addToLibrary
= new QAction(DGui::IconLoader::self()->load("object-bring-forwards.svg"), tr("Add to library..."), this);
346 connect(addToLibrary
, SIGNAL(triggered()), this, SLOT(addToLibrary()));
347 d
->actionManager
.add(addToLibrary
, "addtolibrary", "library");
348 addAction(addToLibrary
);
350 QAction
*applySymbol
= new QAction(DGui::IconLoader::self()->load(""), tr("Apply to symbol..."), this);
351 connect(applySymbol
, SIGNAL(triggered()), this, SLOT(applyCurrentSymbol()));
352 d
->actionManager
.add(applySymbol
, "applysymbol", "library");
356 QAction
*recordItem
= new QAction(DGui::IconLoader::self()->load("media-record.svg"), tr("Record item"), this);
357 connect(recordItem
, SIGNAL(triggered()), this, SLOT(recordItem()));
358 d
->actionManager
.add(recordItem
, "recorditem", "item");
360 QAction
*stopRecordItem
= new QAction(DGui::IconLoader::self()->load("media-playback-stop.svg"), tr("Stop to record item"), this);
361 connect(stopRecordItem
, SIGNAL(triggered()), this, SLOT(stopRecordItem()));
362 d
->actionManager
.add(stopRecordItem
, "stoprecorditem", "item");
367 * Si @p use es verdadero permite que la animación se vea con antialiasing y si es false desactiva el antialiasing.
369 void PaintArea::setAntialiasing(bool use
)
372 if ( QGLWidget
*gl
= dynamic_cast<QGLWidget
*>(viewport() ) )
374 gl
->setUpdatesEnabled(false); // works better
375 gl
->setFormat(QGLFormat(QGL::SampleBuffers
| QGL::HasOverlay
/*| QGL::DirectRendering | QGL::AccumBuffer | QGL::Rgba */));
376 gl
->setUpdatesEnabled(true);
380 setRenderHint(QPainter::Antialiasing
, use
);
381 setRenderHint(QPainter::TextAntialiasing
, use
);
386 * Si @p opengl es verdadero activa el uso de openGl para dibujar el fotograma.
388 void PaintArea::setUseOpenGL(bool opengl
)
390 D_FUNCINFO
<< opengl
;
392 QCursor
cursor(Qt::ArrowCursor
);
395 cursor
= viewport()->cursor();
401 setViewport(new GLDevice());
405 // setViewport( new KTImageDevice() );
409 dWarning() << tr("OpenGL isn't supported");
412 // to restore the cursor.
415 viewport()->setCursor(cursor
);
416 viewport()->setAcceptDrops(true);
422 * Si @p draw es verdadero activa el dibujo de una grilla guia en el area, y si es falso la desactiva.
423 * Por defecto no se dibuja la grilla.
425 void PaintArea::setDrawGrid(bool draw
)
428 // resetCachedContent();
429 viewport()->update();
434 * Se asigna la herramienta @p tool como la herramienta actual.
436 void PaintArea::setTool(AbstractTool
*tool
)
438 if ( !scene() ) return;
440 QCursor cursor
= tool
->action()->cursor();
441 if( (!cursor
.pixmap().isNull() && cursor
.mask() != 0 && cursor
.shape() == Qt::BitmapCursor
&& cursor
.bitmap() != 0 ) || cursor
.shape() != Qt::BitmapCursor
)
442 viewport()->setCursor(cursor
);
444 d
->toolsConfigBar
->clear();
445 tool
->setupConfigBar(d
->toolsConfigBar
);
447 d
->photogram
->setTool(tool
);
452 * Retorna si esta activo el dibujo de la grilla.
454 bool PaintArea::drawGrid() const
459 void PaintArea::mousePressEvent( QMouseEvent
* event
)
461 if ( !canPaint() ) return;
463 QGraphicsItem
*item
= d
->photogram
->itemAt( mapToScene(event
->pos()) );
465 d
->effectsConfigBar
->clear();
468 if( YAMF::Effect::Filter
*filter
= dynamic_cast<YAMF::Effect::Filter
*>(item
) )
470 filter
->setupConfigBar(d
->effectsConfigBar
);
474 if ( event
->buttons() == Qt::RightButton
)
477 QMenu
*menu
= this->createMenu();
483 QMenu
*effects
= menu
->addMenu(tr("Effects"));
485 QAction
*blur
= effects
->addAction(tr("Blur"));
486 blur
->setData("blur");
488 QAction
*swirl
= effects
->addAction(tr("Swirl"));
489 swirl
->setData("swirl");
491 connect(effects
, SIGNAL(triggered(QAction
*)), this, SLOT(applyFilter(QAction
*)));
494 item
->setFlag(QGraphicsItem::ItemIsSelectable
, true);
495 item
->setSelected(true);
497 menu
->addAction(d
->actionManager
.find("recorditem", "item"));
500 if( d
->photogram
->recorded() )
502 menu
->addAction(d
->actionManager
.find("stoprecorditem", "item"));
505 menu
->addSeparator();
507 if( qgraphicsitem_cast
<Model::LibraryItem
*>(item
) )
509 menu
->addAction(d
->actionManager
.find("applysymbol", "library"));
513 menu
->addAction(d
->actionManager
.find("addtolibrary", "library"));
516 menu
->addSeparator();
520 menu
->exec(event
->globalPos());
526 d
->photogram
->aboutToMousePress();
527 QGraphicsView::mousePressEvent(event
);
530 foreach(QGraphicsItem
*item
, d
->photogram
->selectedItems() )
532 if( item
->flags() & QGraphicsItem::ItemIsMovable
)
534 Private::ItemProperties prop
;
538 doc
.appendChild(Item::Serializer::properties(item
, doc
));
540 prop
.properties
= doc
.toString();
541 d
->properties
<< prop
;
546 void PaintArea::mouseMoveEvent( QMouseEvent
* event
)
548 if ( !canPaint()) return;
551 if( !d
->photogram
->isDrawing() && event
->buttons() == Qt::LeftButton
&& (event
->modifiers () == (Qt::ShiftModifier
| Qt::ControlModifier
)))
553 setUpdatesEnabled(false);
555 QGraphicsView::DragMode dragMode
= this->dragMode();
556 setDragMode(QGraphicsView::NoDrag
);
558 QPointF p1
= event
->pos();
559 QPointF p2
= d
->drawingRect
.center();
561 d
->rotator
->rotateTo( (int)(-(180*DGraphics::Algorithm::angleForPos(p1
,p2
))/M_PI
) );
563 setDragMode(dragMode
);
565 setUpdatesEnabled(true);
569 QGraphicsView::mouseMoveEvent(event
);
571 if( !d
->photogram
->mouseGrabberItem() && d
->photogram
->isDrawing() ) // HACK
573 QGraphicsSceneMouseEvent
mouseEvent(QEvent::GraphicsSceneMouseMove
);
574 mouseEvent
.setWidget(viewport());
576 mouseEvent
.setPos( event
->pos() );
577 mouseEvent
.setScenePos(mapToScene(event
->pos()));
579 mouseEvent
.setScreenPos(event
->globalPos());
580 mouseEvent
.setButtons(event
->buttons());
581 mouseEvent
.setButton(event
->button());
582 mouseEvent
.setModifiers(event
->modifiers());
583 mouseEvent
.setAccepted(false);
584 d
->photogram
->mouseMoved(&mouseEvent
);
588 emit
cursorMoved( mapToScene( event
->pos() ) );
591 void PaintArea::mouseReleaseEvent(QMouseEvent
*event
)
593 QGraphicsView::mouseReleaseEvent(event
);
595 if( ! d
->photogram
->mouseGrabberItem() && d
->photogram
->isDrawing() ) // HACK
597 QGraphicsSceneMouseEvent
mouseEvent(QEvent::GraphicsSceneMouseRelease
);
598 mouseEvent
.setWidget(viewport());
599 mouseEvent
.setPos( event
->pos() );
600 mouseEvent
.setScenePos(mapToScene(event
->pos()));
601 mouseEvent
.setScreenPos(event
->globalPos());
602 mouseEvent
.setButtons(event
->buttons());
603 mouseEvent
.setButton(event
->button());
604 mouseEvent
.setModifiers(event
->modifiers());
605 mouseEvent
.setAccepted(false);
606 // QApplication::sendEvent(d->photogram, &mouseEvent);
607 d
->photogram
->mouseReleased(&mouseEvent
);
611 Model::Object
*recorded
= d
->photogram
->recorded();
612 QGraphicsItem
*ritem
= 0;
615 ritem
= recorded
->item();
618 foreach(Private::ItemProperties prop
, d
->properties
)
620 if(currentFrame()->logicalIndexOf(prop
.item
) > -1 || ritem
== prop
.item
)
623 doc
.appendChild(Item::Serializer::properties(prop
.item
, doc
));
626 if( prop
.item
== ritem
)
630 else if( doc
.toString() != prop
.properties
)
632 Command::ModifyItem
*current
= new Command::ModifyItem( prop
.item
, prop
.properties
, currentFrame() );
633 addCommand( current
);
638 d
->properties
.clear();
643 void PaintArea::tabletEvent( QTabletEvent
* event
)
645 QGraphicsView::tabletEvent(event
);
649 * Función reimplementada para dibujar el fondo del area de dibujo, mostrando el area que va a aparecer en la animación y la grilla si esta activa la opción.
651 void PaintArea::drawBackground(QPainter
*painter
, const QRectF
&rect
)
653 QGraphicsView::drawBackground(painter
, rect
);
655 if( ! currentFrame() ) return;
659 bool hasAntialiasing
= painter
->renderHints() & QPainter::Antialiasing
;
661 painter
->setRenderHint(QPainter::Antialiasing
, false);
663 painter
->setPen( QPen(QColor(0,0,0,180), 3) );
665 painter
->fillRect( d
->drawingRect
, Qt::white
);
666 painter
->drawRect( d
->drawingRect
);
668 QPointF origin
= painter
->matrix().map(QPoint(0, 0));
670 if( origin
!= d
->origin
)
673 emit
originChanged( d
->origin
);
678 int sx
= (int)painter
->matrix().m11();
679 int sy
= (int)painter
->matrix().m22();
681 painter
->resetMatrix();
682 painter
->scale(sx
, sy
);
683 painter
->setPen( QPen(QColor(0,0,180, 50), 1) );
685 for(int i
= 0; i
< qMax(width(), height()); i
+= 10 )
687 painter
->drawLine(i
, 0, i
, height() );
688 painter
->drawLine(0, i
, width(), i
);
692 painter
->setRenderHint(QPainter::Antialiasing
, hasAntialiasing
);
700 * Función reimplementada para mostrar si el frame actual esta bloqueado.
702 void PaintArea::drawForeground( QPainter
*painter
, const QRectF
&rect
)
704 if ( Model::Frame
*frame
= currentFrame() )
706 if ( frame
->isLocked() )
708 painter
->fillRect(rect
, QColor(201,201,201, 200));
710 painter
->setFont(QFont("Arial", 30) );
711 QFontMetricsF
fm(painter
->font());
712 QString text
= tr("Locked");
714 painter
->drawText(QPointF(d
->photogram
->sceneRect().topRight().x() - fm
.width(text
), (d
->photogram
->sceneRect().topRight().y() + fm
.height()) / 2), text
);
721 * Retorna verdadero si se puede dibujar sobre el area de dibujo y falso si no.
723 bool PaintArea::canPaint() const
727 Model::Frame
*frame
= currentFrame();
731 return !frame
->isLocked() && !frame
->layer()->isLocked();
740 * Centra la vista del fotograma.
742 void PaintArea::centerDrawingArea()
744 centerOn(d
->drawingRect
.center());
750 void PaintArea::onHistoryChanged()
752 if( Model::Scene
*scene
= d
->photogram
->scene() )
754 if( scene
->logicalIndex() < 0 )
755 d
->photogram
->setCurrentScene(0);
758 d
->photogram
->drawCurrentPhotogram();
759 viewport()->update();
765 void PaintArea::applyFilter(QAction
*act
)
767 QList
<QGraphicsItem
*> selected
= d
->photogram
->selectedItems();
769 if( selected
.isEmpty() ) return;
771 QGraphicsItem
*item
= selected
.first();
772 QString filter
= act
->data().toString();
773 Model::Frame
*frame
= currentFrame();
775 if( frame
&& item
&& !filter
.isEmpty())
777 Model::Object
*object
= frame
->graphic(frame
->logicalIndexOf(item
));
781 YAMF::Effect::Filter
*effect
= YAMF::Effect::Factory::create(filter
);
783 d
->effectsConfigBar
->clear();
784 effect
->setupConfigBar(d
->effectsConfigBar
);
787 YAMF::Command::AddItemFilter
*cmd
= new YAMF::Command::AddItemFilter(object
, effect
);
793 void PaintArea::wheelEvent(QWheelEvent
*event
)
795 if(event
->modifiers () == Qt::ControlModifier
)
797 scaleView(pow(( double)2, -event
->delta() / 240.0));
801 QGraphicsView::wheelEvent(event
);
805 bool PaintArea::viewportEvent(QEvent
*e
)
807 bool ret
= QGraphicsView::viewportEvent(e
);
809 if( e
->type() == QEvent::Show
)
811 if( d
->photogram
->items().isEmpty() )
813 d
->photogram
->drawCurrentPhotogram();
822 * Escala la vista sobre el fotograma en un factor @p scaleFactor.
824 void PaintArea::scaleView(double scaleFactor
)
826 qreal factor
= matrix().scale(scaleFactor
, scaleFactor
).mapRect(QRectF(0, 0, 1, 1)).width();
827 if (factor
< 0.07 || factor
> 100)
831 d
->lastScaleFactor
*= scaleFactor
;
832 scale(scaleFactor
, scaleFactor
);
834 emit
scaled(d
->lastScaleFactor
);
839 * Hace aumento sobre el fotograma actual en un porcentaje @p percent.
841 void PaintArea::setZoom(int percent
)
843 double factor
= (double)percent
/ 100.0;
845 if( factor
== d
->lastScaleFactor
) return;
847 double restoreFactor
= 1.0/d
->lastScaleFactor
;
849 if( d
->lastScaleFactor
> 1.0 )
851 scale(restoreFactor
, restoreFactor
);
853 else if ( d
->lastScaleFactor
< 1.0)
855 scale(restoreFactor
, restoreFactor
);
858 d
->lastScaleFactor
= factor
;
860 scale(factor
, factor
);
867 * Rota la vista sobre el fotograma.
869 void PaintArea::setRotationAngle(int angle
)
871 rotate(angle
- d
->angle
);
877 * Retorna el manejador de brochas del area de dibujo.
879 BrushManager
*PaintArea::brushManager() const
881 return d
->photogram
->brushManager();
886 * Retorna el area en la cual va aparecer en la animación.
888 QRectF
PaintArea::drawingRect() const
890 return d
->drawingRect
;
895 * Retorna el fotograma actual.
897 Photogram
*PaintArea::photogram() const
904 * Cambia el frame actual.
906 void PaintArea::setCurrentFrame(int sceneIndex
, int layerIndex
, int frameIndex
)
908 // dfDebug << "scene = " << sceneIndex << " layer = " << layerIndex << "frame = " << frameIndex;
909 Model::Scene
*scene
= d
->project
->scene(sceneIndex
);
913 d
->photogram
->setCurrentScene(scene
);
914 d
->photogram
->setCurrent(frameIndex
);
915 d
->framePosition
.layer
= layerIndex
;
916 d
->framePosition
.frame
= frameIndex
;
918 d
->photogram
->drawCurrentPhotogram();
919 viewport()->update();
924 * Retorna el proyecto asociado al area de dibujo.
926 Model::Project
*PaintArea::project() const
933 * Retorna la escena actual.
935 Model::Scene
*PaintArea::currentScene() const
937 return d
->photogram
->scene();
942 * Retorna la capa actual.
944 Model::Layer
*PaintArea::currentLayer() const
946 Model::Scene
*scene
= d
->photogram
->scene();
950 return scene
->layer(d
->framePosition
.layer
);
959 * Retorna el frame actual.
961 Model::Frame
*PaintArea::currentFrame() const
963 Model::Layer
*layer
= currentLayer();
967 return layer
->frame(d
->framePosition
.frame
);
978 void PaintArea::addCommand(Command::Base
*command
)
980 d
->project
->commandManager()->addCommand(command
);
985 * Retorna la historia de comandos
988 DGui::CommandHistory
*PaintArea::history() const
995 * Retorna la acción que permite remover los elementos seleccionados en el area.
998 QAction
*PaintArea::removeAction()
1000 return d
->actionManager
.find("remove", "edit");
1005 * Retorna la acción que permite agrupar los elementos seleccionados en el area.
1008 QAction
*PaintArea::groupAction()
1010 return d
->actionManager
.find("group", "object");
1015 * Retorna la acción que permite des-agrupar los elementos seleccionados en el area.
1018 QAction
*PaintArea::ungroupAction()
1020 return d
->actionManager
.find("ungroup", "object");
1025 * Retorna la acción que permite enviar al fondo los elementos seleccionados en el area.
1028 QAction
*PaintArea::sendToBackAction()
1030 return d
->actionManager
.find( "sendtoback", "object-order");
1035 * Retorna la acción que permite enviar al frente los elementos seleccionados en el area.
1038 QAction
*PaintArea::bringToFrontAction()
1040 return d
->actionManager
.find( "bringtofront", "object-order");
1046 * Retorna la acción que permite enviar hacia atras una unidad los elementos seleccionados en el area.
1049 QAction
*PaintArea::sendBackwardsAction()
1051 return d
->actionManager
.find( "sendbackwards", "object-order");
1056 * Retorna la acción que permite enviar hacia adelante una unidad los elementos seleccionados en el area.
1058 QAction
*PaintArea::bringForwardsAction()
1060 return d
->actionManager
.find( "bringforwards", "object-order");
1065 * Retorna la acción que permite copiar los elementos seleccionados en el area.
1067 QAction
*PaintArea::copyAction()
1069 return d
->actionManager
.find( "copy", "edit");
1074 * Retorna la acción que permite pegar los elementos que estan en el portapapeles en el area.
1076 QAction
*PaintArea::pasteAction()
1078 return d
->actionManager
.find( "paste", "edit");
1083 * Retorna la acción que permite cortar los elementos seleccionados en el area.
1085 QAction
*PaintArea::cutAction()
1087 return d
->actionManager
.find( "cut", "edit");
1092 * Retorna la acción que permite seleccionar todos los elementos en el area.
1094 QAction
*PaintArea::selectAllAction()
1096 return d
->actionManager
.find("selectall", "edit");
1101 * Crea el menu contextual de el area de dibujo.
1103 QMenu
*PaintArea::createMenu()
1105 QMenu
*menu
= new QMenu(tr("Drawing area"), this);
1107 Command::Manager
*manager
= d
->project
->commandManager();
1109 menu
->addAction(d
->history
->undoAction()->icon(), d
->history
->undoAction()->text(), d
->history
, SLOT(undo()))->setEnabled(d
->history
->undoAction()->isEnabled());
1110 menu
->addAction(d
->history
->redoAction()->icon(), d
->history
->redoAction()->text(), d
->history
, SLOT(redo()))->setEnabled(d
->history
->redoAction()->isEnabled());
1112 menu
->addSeparator();
1113 d
->actionManager
.setupMenu(menu
, "edit", false);
1114 menu
->addSeparator();
1116 QMenu
*order
= new QMenu(tr("Order"));
1117 d
->actionManager
.setupMenu(order
, "object-order");
1119 menu
->addMenu (order
);
1120 menu
->addSeparator();
1122 if ( AbstractTool
*tool
= d
->photogram
->currentTool() )
1124 if( QMenu
*toolMenu
= tool
->menu() )
1126 menu
->addSeparator();
1127 menu
->addMenu(toolMenu
);
1136 * Retorna la barra de herramientas que provee la interfaz grafica para la configuración de las herramientas.
1138 QToolBar
*PaintArea::toolsConfigBar() const
1140 return d
->toolsConfigBar
;
1145 * Retorna la barra de herramientas que provee la interfaz grafica para la configuración de los efectos.
1147 QToolBar
*PaintArea::effectsConfigBar() const
1149 return d
->effectsConfigBar
;
1152 void PaintArea::checkActions()
1154 if(! scene()->selectedItems().isEmpty())
1156 d
->actionManager
.setEnabled("object-order", true);
1157 d
->actionManager
.find("remove", "edit")->setEnabled(true);
1158 d
->actionManager
.find("cut", "edit")->setEnabled(true);
1159 d
->actionManager
.find("copy", "edit")->setEnabled(true);
1160 d
->actionManager
.find("addtolibrary", "library")->setEnabled(true);
1164 d
->actionManager
.setEnabled("object-order", false);
1165 d
->actionManager
.find("remove", "edit")->setEnabled(false);
1166 d
->actionManager
.find("cut", "edit")->setEnabled(false);
1167 d
->actionManager
.find("copy", "edit")->setEnabled(false);
1168 d
->actionManager
.find("addtolibrary", "library")->setEnabled(false);
1171 QString xml
= QApplication::clipboard()->mimeData()->data("yamf-graphics");
1172 if ( !xml
.isEmpty() )
1174 d
->actionManager
.find("paste", "edit")->setEnabled(true);
1178 d
->actionManager
.find("paste", "edit")->setEnabled(false);
1184 * Remueve los elementos seleccionados.
1186 void PaintArea::removeSelectedObjects()
1188 QList
<QGraphicsItem
*> items
= d
->photogram
->selectedItems();
1189 if( items
.count() > 0 )
1191 currentFrame()->removeItems(items
);
1192 this->checkActions();
1199 * Agrupa los elementos seleccionados.
1201 void PaintArea::groupSelectedObjects()
1203 QList
<QGraphicsItem
*> items
= d
->photogram
->selectedItems();
1204 if( items
.count() > 0 )
1206 addCommand(new Command::GroupItem(items
, currentFrame()));
1212 * Desagrupa los elementos seleccionados.
1214 void PaintArea::ungroupSelectedObject()
1216 QList
<QGraphicsItem
*> items
= d
->photogram
->selectedItems();
1217 QList
<Item::Group
*> groups
;
1219 Model::Frame
*frame
= currentFrame();
1221 foreach(QGraphicsItem
*item
, items
)
1223 if( Item::Group
*group
= qgraphicsitem_cast
<Item::Group
*>(item
) )
1225 addCommand(new Command::UngroupItem(group
, currentFrame()));
1232 * Envia atras los elementos seleccionados.
1234 void PaintArea::sendToBackSelectedObjects()
1236 QList
<QGraphicsItem
*> items
= photogram()->selectedItems();
1238 DGraphics::Algorithm::sort(items
, DGraphics::Algorithm::ZAxis
);
1240 Model::Frame
*frame
= currentFrame();
1241 foreach(QGraphicsItem
*item
, items
)
1243 addCommand(new Command::SendToBackItem(frame
->graphic(item
)));
1249 * Trae adelante los elementos seleccionados.
1251 void PaintArea::bringToFrontSelectedObjects()
1253 QList
<QGraphicsItem
*> items
= photogram()->selectedItems();
1255 DGraphics::Algorithm::sort(items
, DGraphics::Algorithm::ZAxis
);
1257 QList
<QGraphicsItem
*>::iterator it
= items
.end();
1259 Model::Frame
*frame
= currentFrame();
1261 while(it
!= items
.begin())
1264 addCommand(new Command::BringToFrontItem(frame
->graphic(*it
)));
1270 * Envia atras una unidad los elementos seleccionados.
1272 void PaintArea::sendBackwardsSelectedObjects()
1274 QList
<QGraphicsItem
*> items
= photogram()->selectedItems();
1276 DGraphics::Algorithm::sort(items
, DGraphics::Algorithm::ZAxis
);
1278 Model::Frame
*frame
= currentFrame();
1279 foreach(QGraphicsItem
*item
, items
)
1281 addCommand(new Command::SendBackwardsItem(frame
->graphic(item
)));
1288 * Trae al frente una unidad los elementos seleccionados.
1290 void PaintArea::bringForwardsSelectedObjects()
1292 QList
<QGraphicsItem
*> items
= photogram()->selectedItems();
1294 DGraphics::Algorithm::sort(items
, DGraphics::Algorithm::ZAxis
);
1296 QList
<QGraphicsItem
*>::iterator it
= items
.end();
1298 Model::Frame
*frame
= currentFrame();
1300 while(it
!= items
.begin())
1303 addCommand(new Command::BringForwardsItem(frame
->graphic(*it
)));
1309 * Copia los elementos seleccionados.
1311 void PaintArea::copySelectedObjects()
1313 QList
<QGraphicsItem
*> selecteds
= scene()->selectedItems();
1316 QDomElement root
= orig
.createElement("yamf-graphics");
1318 foreach(QGraphicsItem
*item
, selecteds
)
1320 int index
= currentFrame()->logicalIndexOf( item
);
1324 Model::Object
*graphic
= currentFrame()->graphic(index
);
1325 root
.appendChild(graphic
->toXml( orig
));
1329 orig
.appendChild(root
);
1331 QMimeData
*mimeData
= new QMimeData
;
1333 mimeData
->setData("yamf-graphics", orig
.toString().toLocal8Bit());
1334 //TODO: image/svg+xml
1335 QApplication::clipboard()->setMimeData( mimeData
);
1340 * Pega los elementos en el portapapeles.
1342 void PaintArea::pasteObjects()
1344 if( !currentFrame() ) return;
1346 const QMimeData
*mimeData
= QApplication::clipboard()->mimeData();
1348 QString xml
= mimeData
->data("yamf-graphics");
1351 if(!doc
.setContent(xml
))
1356 // TODO: image/svg+xml
1358 QDomElement docElem
= doc
.documentElement();
1359 QDomNode n
= docElem
.firstChild();
1363 QDomElement e
= n
.toElement();
1367 QTextStream
ts(&xml
);
1370 Model::Object
*object
= new Model::Object(currentFrame());
1371 object
->fromXml(xml
);
1373 currentFrame()->addObject(object
);
1375 n
= n
.nextSibling();
1377 d
->photogram
->drawCurrentPhotogram();
1382 * Corta los elementos seleccionados.
1384 void PaintArea::cutSelectedObjects()
1386 copySelectedObjects();
1387 removeSelectedObjects();
1392 * Selecciona todos los elementos en el area.
1394 void PaintArea::selectAllObjects()
1396 foreach(QGraphicsItem
*item
, photogram()->items() )
1398 item
->setFlag(QGraphicsItem::ItemIsSelectable
);
1399 item
->setSelected(true);
1405 * Añade lso elementos seleccionados a la biblioteca de objetos.
1407 void PaintArea::addToLibrary()
1409 QList
<QGraphicsItem
*> selecteds
= scene()->selectedItems();
1411 if ( selecteds
.isEmpty() )
1413 DGui::Osd::self()->display(tr("No items selected"), DGui::Osd::Error
);
1417 YAMF::Drawing::Private::AddSymbolDialog addSymbolDialog
;
1419 YAMF::Model::Library
*library
= d
->project
->library();
1421 QList
<QGraphicsItem
*> symbols
;
1423 foreach(QGraphicsItem
*item
, selecteds
)
1425 if( YAMF::Common::AbstractSerializable
*serializable
= dynamic_cast<YAMF::Common::AbstractSerializable
*>(item
) )
1427 addSymbolDialog
.addSymbol(item
);
1431 if( addSymbolDialog
.exec() == QDialog::Accepted
)
1433 for(int i
= 0; i
< addSymbolDialog
.symbolCount(); i
++)
1435 library
->addItemSymbol(addSymbolDialog
.symbol(i
), addSymbolDialog
.symbolName(i
));
1440 void PaintArea::applyCurrentSymbol()
1442 if( d
->photogram
->selectedItems().count() > 0 )
1444 if( Model::LibraryItem
*libraryItem
= qgraphicsitem_cast
<Model::LibraryItem
*>( d
->photogram
->selectedItems().first()) )
1446 YAMF::Command::ModifySymbol
*cmd
= new YAMF::Command::ModifySymbol(libraryItem
);
1455 * Añade un simbolo de la biblioteca identificado con @p id a el area .
1457 void PaintArea::addSymbol(const QString
&id
)
1459 YAMF::Model::LibraryObject
*object
= d
->project
->library()->findObject(id
);
1468 * Añade un simbolo @p object de la biblioteca a el area .
1470 void PaintArea::addSymbol(YAMF::Model::LibraryObject
*object
)
1472 YAMF::Model::Frame
*frame
= currentFrame();
1473 YAMF::Model::Scene
*scene
= currentScene();
1475 switch(object
->type())
1477 case YAMF::Model::LibraryObject::Sound
:
1479 Model::LibrarySoundObject
*soundObject
= dynamic_cast<Model::LibrarySoundObject
*>(object
);
1482 YAMF::Model::AudioLayer
*layer
= scene
->createAudioLayer();
1483 layer
->fromSymbol(soundObject
);
1487 case YAMF::Model::LibraryObject::Svg
:
1488 case YAMF::Model::LibraryObject::Item
:
1489 case YAMF::Model::LibraryObject::Image
:
1490 case YAMF::Model::LibraryObject::Text
:
1494 YAMF::Model::LibraryItem
*item
= new YAMF::Model::LibraryItem(object
);
1495 frame
->addItem(item
);
1505 void PaintArea::recordItem()
1507 Model::Frame
*frame
= currentFrame();
1509 if( frame
&& d
->photogram
->selectedItems().count() > 0 )
1511 QGraphicsItem
*item
= d
->photogram
->selectedItems().first();
1513 int logicalIndex
= frame
->logicalIndexOf(item
);
1515 if( logicalIndex
> -1 )
1517 d
->photogram
->recordObject(frame
->graphic(logicalIndex
));
1527 void PaintArea::stopRecordItem()
1529 Model::Object
*object
= d
->photogram
->recorded();
1530 Model::Frame
*frame
= currentFrame();
1532 int framePos
= frame
->visualIndex();
1533 int objectPos
= object
->frame()->visualIndex();
1535 if( object
&& framePos
> objectPos
)
1537 int stepsCount
= framePos
- objectPos
;
1539 Item::Tweener
*tweener
= new Item::Tweener(stepsCount
, object
);
1541 foreach(Private::RecordStep rs
, d
->steps
)
1543 tweener
->addStep(*rs
.step
);
1547 object
->setTweener(tweener
);
1550 d
->photogram
->recordObject(0);