Documentation
[yamf.git] / yamf / drawing / paintarea.cpp
blobc4f1cba622f75501d741fba8de9fd289e8ef62e1
1 /***************************************************************************
2 * Copyright (C) 2005 by Jorge Cuadrado *
3 * kuadrosxx@gmail.com *
4 * Copyright (C) 2006 by David Cuadrado *
5 * krawek@gmail.com *
6 * *
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. *
11 * *
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. *
16 * *
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>
31 #include <QPolygon>
32 #include <QApplication>
33 #include <QTimer>
34 #include <QStyleOptionGraphicsItem>
35 #include <QClipboard>
36 #include <QUndoStack>
37 #include <QMenu>
38 #include <QToolBar>
40 #include "photogram.h"
41 #include <dgraphics/algorithm.h>
43 #include <dcore/config.h>
44 #include <dcore/debug.h>
45 #include <dgui/application.h>
46 #include <dgui/osd.h>
47 #include <dgui/commandhistory.h>
48 #include <dgui/action.h>
49 #include <dgui/actionmanager.h>
50 #include <dgui/iconloader.h>
52 #include <cmath>
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>
86 namespace YAMF {
87 namespace Drawing {
89 #ifdef QT_OPENGL_LIB
91 #include <QGLWidget>
92 #include <QGLFramebufferObject>
94 class GLDevice : public QGLWidget
96 public:
97 GLDevice() : QGLWidget()
99 makeCurrent();
101 ~GLDevice() {};
103 protected:
104 void initializeGL()
106 glDisable(GL_DEPTH_TEST);
109 #endif
111 struct YAMF::Drawing::PaintArea::Private
113 Private(YAMF::Drawing::PaintArea *paintArea, Model::Project *const project) : paintArea(paintArea), project(project), lastScaleFactor(1.0)
117 YAMF::Drawing::PaintArea *paintArea;
119 QRectF drawingRect;
121 bool drawGrid;
122 double angle;
124 YAMF::Drawing::Private::PaintAreaRotator *rotator;
125 Photogram *photogram;
127 struct FramePosition {
128 int layer;
129 int frame;
130 } framePosition;
133 struct ItemProperties {
134 QGraphicsItem *item;
135 QString properties;
138 QList<ItemProperties> properties;
140 QPointF origin;
142 DGui::ActionManager actionManager;
144 Model::Project *const project;
146 double lastScaleFactor;
148 QToolBar *toolsConfigBar;
149 QToolBar *effectsConfigBar;
151 struct RecordStep
153 Item::TweenerStep *step;
155 QList<RecordStep> steps;
157 void recordIt();
160 void PaintArea::Private::recordIt()
162 Model::Object *recorded = photogram->recorded();
164 int currentPos = paintArea->currentFrame()->visualIndex();
165 int objectPos = recorded->frame()->visualIndex();
167 RecordStep record;
168 record.step = new Item::TweenerStep(currentPos-objectPos);
170 record.step->setPosition(recorded->item()->pos());
172 steps << record;
178 * @~spanish
179 * Construye un area de trabajo relacionada con el proyecto @p project.
181 PaintArea::PaintArea(Model::Project *const project, QWidget * parent) : QGraphicsView(parent), d(new Private(this, project) )
183 d->photogram = new Photogram(this);
185 d->drawGrid = false;
186 d->angle = 0;
188 d->rotator = new YAMF::Drawing::Private::PaintAreaRotator(this, this);
190 d->drawingRect = QRectF(QPointF(0,0), QSizeF( 500, 400 ) ); // FIXME: configurable
192 d->photogram->setSceneRect(d->drawingRect);
193 setScene(d->photogram);
195 centerDrawingArea();
197 setUseOpenGL( false );
198 setInteractive ( true );
200 restoreState();
202 setCurrentFrame(-1, -1, -1);
204 d->origin = mapToScene(QPoint(0, 0));
206 createActions();
207 checkActions();
209 d->toolsConfigBar = new QToolBar(tr("Configure tool"), this);
211 d->effectsConfigBar = new QToolBar(tr("Configure effects"), this);
215 * @~spanish
216 * Guarda en la configuracion el estado de las propiedades del area de dibujo.
218 void PaintArea::saveState()
220 DCore::Config *config = dApp->config( "PaintArea" );
222 config->setValue("render_hints", int(renderHints()));
223 config->setValue("show_grid", d->drawGrid);
225 config->endGroup();
229 * @~spanish
230 * Recupera de la configuracion el estado de las propiedades del area de dibujo.
232 void PaintArea::restoreState()
234 DCore::Config *config = dApp->config( "PaintArea" );
236 int renderHints = config->value("render_hints", int(this->renderHints())).toInt();
237 setRenderHints(QPainter::RenderHints(renderHints));
239 bool showGrid = config->value("show_grid", false).toBool();
240 setDrawGrid(showGrid);
242 config->endGroup();
246 * Destructor
248 PaintArea::~PaintArea()
250 d->toolsConfigBar->clear();
251 saveState();
252 delete d;
257 * @~spanish
258 * Crea las acciones relacionadas con el area de dibujo.
260 void PaintArea::createActions()
262 DGui::CommandHistory *history = d->project->commandManager()->history();
263 addAction( history->undoAction() );
264 addAction( history->redoAction() );
266 connect(d->project->commandManager(), SIGNAL(historyChanged()), this, SLOT(onHistoryChanged()));
268 QAction *remove = new QAction(DGui::IconLoader::self()->load("edit-delete.svg"), tr("Delete"), this);
269 remove->setShortcut(QKeySequence::Delete);
270 connect(remove, SIGNAL(triggered()), this, SLOT(removeSelectedObjects()));
271 addAction(remove);
273 QAction *selectAll = new QAction(DGui::IconLoader::self()->load("select-all.svg"), tr("Select all"), this);
274 selectAll->setShortcut(QKeySequence::SelectAll);
275 connect(selectAll, SIGNAL(triggered()), this, SLOT(selectAllObjects()));
276 addAction(selectAll);
278 QAction *copy = new QAction( DGui::IconLoader::self()->load("edit-copy.svg"), tr("Copy"), this);
279 copy->setShortcut(QKeySequence::Copy);
280 connect(copy, SIGNAL(triggered()), this, SLOT(copySelectedObjects()));
281 addAction(copy);
283 QAction *paste = new QAction(DGui::IconLoader::self()->load("edit-paste.svg"), tr("Paste"), this);
284 paste->setShortcut(QKeySequence::Paste);
285 connect(paste, SIGNAL(triggered()), this, SLOT(pasteObjects()));
286 addAction(paste);
288 QAction *cut = new QAction(DGui::IconLoader::self()->load("edit-cut.svg"), tr("Cut"), this);
289 cut->setShortcut(QKeySequence::Cut);
290 connect(cut, SIGNAL(triggered()), this, SLOT(cutSelectedObjects()));
291 addAction(cut);
294 d->actionManager.add(selectAll, "selectall", "edit");
295 d->actionManager.addSeparator("edit");
296 d->actionManager.add(cut, "cut", "edit");
297 d->actionManager.add(copy, "copy", "edit");
298 d->actionManager.add(paste, "paste", "edit");
299 d->actionManager.addSeparator("edit");
300 d->actionManager.add(remove, "remove", "edit");
302 /////////
304 QAction *group = new QAction(DGui::IconLoader::self()->load("object-group.svg"), tr("Group"), this);
305 group->setShortcut(Qt::CTRL + Qt::Key_G);
306 connect(group, SIGNAL(triggered()), this, SLOT(groupSelectedObjects()));
307 d->actionManager.add(group, "group", "object");
308 addAction(group);
310 QAction *ungroup = new QAction(DGui::IconLoader::self()->load("object-ungroup.svg"), tr("Ungroup"), this);
311 ungroup->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_G);
312 connect(ungroup, SIGNAL(triggered()), this, SLOT(ungroupSelectedObject()));
313 d->actionManager.add(ungroup, "ungroup", "object");
314 addAction(ungroup);
316 QAction *sendToBack = new QAction(DGui::IconLoader::self()->load("object-send-to-back.svg"), tr("Send to back"), this);
317 sendToBack->setShortcut(Qt::Key_Home);
318 connect(sendToBack, SIGNAL(triggered()), this, SLOT(sendToBackSelectedObjects()));
319 d->actionManager.add(sendToBack, "sendtoback", "object-order");
320 addAction(sendToBack);
322 QAction *bringToFront = new QAction(DGui::IconLoader::self()->load("object-bring-to-front.svg"), tr("Bring to front"), this);
323 bringToFront->setShortcut(Qt::Key_End);
324 connect(bringToFront, SIGNAL(triggered()), this, SLOT(bringToFrontSelectedObjects()));
325 d->actionManager.add(bringToFront, "bringtofront", "object-order");
326 addAction(bringToFront);
328 QAction *sendBackwards = new QAction(DGui::IconLoader::self()->load("object-send-backwards.svg"), tr("Send backwards"), this);
329 sendBackwards->setShortcut(Qt::Key_PageDown);
330 connect(sendBackwards, SIGNAL(triggered()), this, SLOT(sendBackwardsSelectedObjects()));
331 d->actionManager.add(sendBackwards, "sendbackwards", "object-order");
332 addAction(sendBackwards);
334 QAction *bringForwards = new QAction(DGui::IconLoader::self()->load("object-bring-forwards.svg"), tr("Bring forwards"), this);
335 bringForwards->setShortcut(Qt::Key_PageUp);
336 connect(bringForwards, SIGNAL(triggered()), this, SLOT(bringForwardsSelectedObjects()));
337 d->actionManager.add(bringForwards, "bringforwards", "object-order");
338 addAction(bringForwards);
340 // Library
342 QAction *addToLibrary = new QAction(DGui::IconLoader::self()->load("object-bring-forwards.svg"), tr("Add to library..."), this);
343 connect(addToLibrary, SIGNAL(triggered()), this, SLOT(addToLibrary()));
344 d->actionManager.add(addToLibrary, "addtolibrary", "library");
345 addAction(addToLibrary);
347 QAction *applySymbol = new QAction(DGui::IconLoader::self()->load(""), tr("Apply to symbol..."), this);
348 connect(applySymbol, SIGNAL(triggered()), this, SLOT(applyCurrentSymbol()));
349 d->actionManager.add(applySymbol, "applysymbol", "library");
351 // Item
353 QAction *recordItem = new QAction(DGui::IconLoader::self()->load("media-record.svg"), tr("Record item"), this);
354 connect(recordItem, SIGNAL(triggered()), this, SLOT(recordItem()));
355 d->actionManager.add(recordItem, "recorditem", "item");
357 QAction *stopRecordItem = new QAction(DGui::IconLoader::self()->load("media-playback-stop.svg"), tr("Stop to record item"), this);
358 connect(stopRecordItem, SIGNAL(triggered()), this, SLOT(stopRecordItem()));
359 d->actionManager.add(stopRecordItem, "stoprecorditem", "item");
363 * @~spanish
364 * Si @p use es verdadero permite que la animación se vea con antialiasing y si es false desactiva el antialiasing.
366 void PaintArea::setAntialiasing(bool use)
368 #ifdef QT_OPENGL_LIB
369 if ( QGLWidget *gl = dynamic_cast<QGLWidget *>(viewport() ) )
371 gl->setUpdatesEnabled(false); // works better
372 gl->setFormat(QGLFormat(QGL::SampleBuffers | QGL::HasOverlay /*| QGL::DirectRendering | QGL::AccumBuffer | QGL::Rgba */));
373 gl->setUpdatesEnabled(true);
375 #endif
377 setRenderHint(QPainter::Antialiasing, use);
378 setRenderHint(QPainter::TextAntialiasing, use);
382 * @~spanish
383 * Si @p opengl es verdadero activa el uso de openGl para dibujar el fotograma.
385 void PaintArea::setUseOpenGL(bool opengl)
387 D_FUNCINFO << opengl;
389 QCursor cursor(Qt::ArrowCursor);
390 if ( viewport() )
392 cursor = viewport()->cursor();
395 #ifdef QT_OPENGL_LIB
396 if ( opengl )
398 setViewport(new GLDevice());
400 else
402 // setViewport( new KTImageDevice() );
404 #else
405 Q_UNUSED(opengl);
406 dWarning() << tr("OpenGL isn't supported");
407 #endif
409 // to restore the cursor.
410 if ( viewport() )
412 viewport()->setCursor(cursor);
413 viewport()->setAcceptDrops(true);
418 * @~spanish
419 * Si @p draw es verdadero activa el dibujo de una grilla guia en el area, y si es falso la desactiva.
420 * Por defecto no se dibuja la grilla.
422 void PaintArea::setDrawGrid(bool draw)
424 d->drawGrid = draw;
425 // resetCachedContent();
426 viewport()->update();
430 * @~spanish
431 * Se asigna la herramienta @p tool como la herramienta actual.
433 void PaintArea::setTool(AbstractTool *tool )
435 if ( !scene() ) return;
437 QCursor cursor = tool->action()->cursor();
438 if( (!cursor.pixmap().isNull() && cursor.mask() != 0 && cursor.shape() == Qt::BitmapCursor && cursor.bitmap() != 0 ) || cursor.shape() != Qt::BitmapCursor )
439 viewport()->setCursor(cursor);
441 d->toolsConfigBar->clear();
442 tool->setupConfigBar(d->toolsConfigBar);
444 d->photogram->setTool(tool);
448 * @~spanish
449 * Retorna si esta activo el dibujo de la grilla.
451 bool PaintArea::drawGrid() const
453 return d->drawGrid;
456 void PaintArea::mousePressEvent( QMouseEvent * event )
458 if ( !canPaint() ) return;
460 QGraphicsItem *item = d->photogram->itemAt( mapToScene(event->pos()) );
462 d->effectsConfigBar->clear();
463 if( item )
465 if( YAMF::Effect::Filter *filter = dynamic_cast<YAMF::Effect::Filter *>(item) )
467 filter->setupConfigBar(d->effectsConfigBar);
471 if ( event->buttons() == Qt::RightButton )
474 QMenu *menu = this->createMenu();
476 if( item )
478 // Add effects
480 QMenu *effects = menu->addMenu(tr("Effects"));
482 QAction *blur = effects->addAction(tr("Blur"));
483 blur->setData("blur");
485 QAction *swirl = effects->addAction(tr("Swirl"));
486 swirl->setData("swirl");
488 connect(effects, SIGNAL(triggered(QAction *)), this, SLOT(applyFilter(QAction *)));
491 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
492 item->setSelected(true);
494 menu->addAction(d->actionManager.find("recorditem", "item"));
497 if( d->photogram->recorded() )
499 menu->addAction(d->actionManager.find("stoprecorditem", "item"));
502 menu->addSeparator();
504 if( qgraphicsitem_cast<Model::LibraryItem *>(item) )
506 menu->addAction(d->actionManager.find("applysymbol", "library"));
508 else
510 menu->addAction(d->actionManager.find("addtolibrary", "library"));
513 menu->addSeparator();
515 checkActions();
517 menu->exec(event->globalPos());
519 delete menu;
521 else
523 d->photogram->aboutToMousePress();
524 QGraphicsView::mousePressEvent(event);
527 foreach(QGraphicsItem *item , d->photogram->selectedItems() )
529 if( item->flags() & QGraphicsItem::ItemIsMovable )
531 Private::ItemProperties prop;
532 prop.item = item;
534 QDomDocument doc;
535 doc.appendChild(Item::Serializer::properties(item, doc));
537 prop.properties = doc.toString();
538 d->properties << prop;
543 void PaintArea::mouseMoveEvent( QMouseEvent * event )
545 if ( !canPaint()) return;
547 // Rotate
548 if( !d->photogram->isDrawing() && event->buttons() == Qt::LeftButton && (event->modifiers () == (Qt::ShiftModifier | Qt::ControlModifier)))
550 setUpdatesEnabled(false);
552 QGraphicsView::DragMode dragMode = this->dragMode();
553 setDragMode(QGraphicsView::NoDrag);
555 QPointF p1 = event->pos();
556 QPointF p2 = d->drawingRect.center();
558 d->rotator->rotateTo( (int)(-(180*DGraphics::Algorithm::angleForPos(p1,p2))/M_PI) );
560 setDragMode(dragMode);
562 setUpdatesEnabled(true);
564 else
566 QGraphicsView::mouseMoveEvent(event);
568 if( !d->photogram->mouseGrabberItem() && d->photogram->isDrawing() ) // HACK
570 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
571 mouseEvent.setWidget(viewport());
573 mouseEvent.setPos( event->pos() );
574 mouseEvent.setScenePos(mapToScene(event->pos()));
576 mouseEvent.setScreenPos(event->globalPos());
577 mouseEvent.setButtons(event->buttons());
578 mouseEvent.setButton(event->button());
579 mouseEvent.setModifiers(event->modifiers());
580 mouseEvent.setAccepted(false);
581 d->photogram->mouseMoved(&mouseEvent);
585 emit cursorMoved( mapToScene( event->pos() ) );
588 void PaintArea::mouseReleaseEvent(QMouseEvent *event)
590 QGraphicsView::mouseReleaseEvent(event);
592 if( ! d->photogram->mouseGrabberItem() && d->photogram->isDrawing() ) // HACK
594 QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
595 mouseEvent.setWidget(viewport());
596 mouseEvent.setPos( event->pos() );
597 mouseEvent.setScenePos(mapToScene(event->pos()));
598 mouseEvent.setScreenPos(event->globalPos());
599 mouseEvent.setButtons(event->buttons());
600 mouseEvent.setButton(event->button());
601 mouseEvent.setModifiers(event->modifiers());
602 mouseEvent.setAccepted(false);
603 // QApplication::sendEvent(d->photogram, &mouseEvent);
604 d->photogram->mouseReleased(&mouseEvent);
608 Model::Object *recorded = d->photogram->recorded();
609 QGraphicsItem *ritem = 0;
610 if( recorded )
612 ritem = recorded->item();
615 foreach(Private::ItemProperties prop, d->properties)
617 if(currentFrame()->logicalIndexOf(prop.item) > -1 || ritem == prop.item)
619 QDomDocument doc;
620 doc.appendChild(Item::Serializer::properties(prop.item, doc));
623 if( prop.item == ritem )
625 d->recordIt();
627 else if( doc.toString() != prop.properties )
629 Command::ModifyItem *current = new Command::ModifyItem( prop.item, prop.properties, currentFrame() );
630 addCommand( current );
635 d->properties.clear();
637 checkActions();
640 void PaintArea::tabletEvent( QTabletEvent * event )
642 QGraphicsView::tabletEvent(event );
646 * 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.
648 void PaintArea::drawBackground(QPainter *painter, const QRectF &rect)
650 QGraphicsView::drawBackground(painter, rect);
652 if( ! currentFrame() ) return;
654 painter->save();
656 bool hasAntialiasing = painter->renderHints() & QPainter::Antialiasing;
658 painter->setRenderHint(QPainter::Antialiasing, false);
660 painter->setPen( QPen(QColor(0,0,0,180), 3) );
662 painter->fillRect( d->drawingRect, Qt::white );
663 painter->drawRect( d->drawingRect );
665 QPointF origin = painter->matrix().map(QPoint(0, 0));
667 if( origin != d->origin )
669 d->origin = origin;
670 emit originChanged( d->origin );
673 if ( d->drawGrid )
675 int sx = (int)painter->matrix().m11();
676 int sy = (int)painter->matrix().m22();
678 painter->resetMatrix();
679 painter->scale(sx, sy);
680 painter->setPen( QPen(QColor(0,0,180, 50), 1) );
682 for(int i = 0; i < qMax(width(), height()); i+= 10 )
684 painter->drawLine(i, 0, i, height() );
685 painter->drawLine(0, i, width(), i );
689 painter->setRenderHint(QPainter::Antialiasing, hasAntialiasing);
692 painter->restore();
696 * @~spanish
697 * Función reimplementada para mostrar si el frame actual esta bloqueado.
699 void PaintArea::drawForeground( QPainter *painter, const QRectF &rect )
701 if ( Model::Frame *frame = currentFrame() )
703 if ( frame->isLocked() )
705 painter->fillRect(rect, QColor(201,201,201, 200));
707 painter->setFont(QFont("Arial", 30) );
708 QFontMetricsF fm(painter->font());
709 QString text = tr("Locked");
711 painter->drawText(QPointF(d->photogram->sceneRect().topRight().x() - fm.width(text), (d->photogram->sceneRect().topRight().y() + fm.height()) / 2), text);
717 * @~spanish
718 * Retorna verdadero si se puede dibujar sobre el area de dibujo y falso si no.
720 bool PaintArea::canPaint() const
722 if( d->photogram )
724 Model::Frame *frame = currentFrame();
726 if( frame )
728 return !frame->isLocked() && !frame->layer()->isLocked();
732 return false;
736 * @~spanish
737 * Centra la vista del fotograma.
739 void PaintArea::centerDrawingArea()
741 centerOn(d->drawingRect.center());
745 * @internal
747 void PaintArea::onHistoryChanged()
749 if( Model::Scene *scene = d->photogram->scene() )
751 if( scene->logicalIndex() < 0 )
752 d->photogram->setCurrentScene(0);
755 d->photogram->drawCurrentPhotogram();
756 viewport()->update();
760 * @internal
762 void PaintArea::applyFilter(QAction *act)
764 QList<QGraphicsItem *> selected = d->photogram->selectedItems();
766 if( selected.isEmpty() ) return;
768 QGraphicsItem *item = selected.first();
769 QString filter = act->data().toString();
770 Model::Frame *frame = currentFrame();
772 if( frame && item && !filter.isEmpty())
774 Model::Object *object = frame->graphic(frame->logicalIndexOf(item));
776 if( object )
778 YAMF::Effect::Filter *effect = YAMF::Effect::Factory::create(filter);
780 d->effectsConfigBar->clear();
781 effect->setupConfigBar(d->effectsConfigBar);
784 YAMF::Command::AddItemFilter *cmd = new YAMF::Command::AddItemFilter(object, effect);
785 addCommand(cmd);
790 void PaintArea::wheelEvent(QWheelEvent *event)
792 if(event->modifiers () == Qt::ControlModifier)
794 scaleView(pow(( double)2, -event->delta() / 240.0));
796 else
798 QGraphicsView::wheelEvent(event);
802 bool PaintArea::viewportEvent(QEvent *e)
804 bool ret = QGraphicsView::viewportEvent(e);
806 if( e->type() == QEvent::Show )
808 if( d->photogram->items().isEmpty() )
810 d->photogram->drawCurrentPhotogram();
814 return ret;
818 * @~spanish
819 * Escala la vista sobre el fotograma en un factor @p scaleFactor.
821 void PaintArea::scaleView(double scaleFactor)
823 qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
824 if (factor < 0.07 || factor > 100)
825 return;
828 d->lastScaleFactor *= scaleFactor;
829 scale(scaleFactor, scaleFactor);
831 emit scaled(d->lastScaleFactor);
835 * @~spanish
836 * Hace aumento sobre el fotograma actual en un porcentaje @p percent.
838 void PaintArea::setZoom(int percent)
840 double factor = (double)percent / 100.0;
842 if( factor == d->lastScaleFactor ) return;
844 double restoreFactor = 1.0/d->lastScaleFactor;
846 if( d->lastScaleFactor > 1.0 )
848 scale(restoreFactor, restoreFactor);
850 else if ( d->lastScaleFactor < 1.0)
852 scale(restoreFactor, restoreFactor);
855 d->lastScaleFactor = factor;
857 scale(factor, factor);
859 emit scaled(factor);
863 * @~spanish
864 * Rota la vista sobre el fotograma.
866 void PaintArea::setRotationAngle(int angle)
868 rotate(angle - d->angle );
869 d->angle = angle;
873 * @~spanish
874 * Retorna el manejador de brochas del area de dibujo.
876 BrushManager *PaintArea::brushManager() const
878 return d->photogram->brushManager();
882 * @~spanish
883 * Retorna el area en la cual va aparecer en la animación.
885 QRectF PaintArea::drawingRect() const
887 return d->drawingRect;
891 * @~spanish
892 * Retorna el fotograma actual.
894 Photogram *PaintArea::photogram() const
896 return d->photogram;
900 * @~spanish
901 * Cambia el frame actual.
903 void PaintArea::setCurrentFrame(int sceneIndex, int layerIndex, int frameIndex)
905 Model::Scene *scene = d->project->scene(sceneIndex);
906 // if( scene )
908 d->photogram->setCurrentScene(scene);
909 d->photogram->setCurrent(frameIndex);
910 d->framePosition.layer = layerIndex;
911 d->framePosition.frame = frameIndex;
913 d->photogram->drawCurrentPhotogram();
914 viewport()->update();
918 * @~spanish
919 * Retorna el proyecto asociado al area de dibujo.
921 Model::Project *PaintArea::project() const
923 return d->project;
927 * @~spanish
928 * Retorna la escena actual.
930 Model::Scene *PaintArea::currentScene() const
932 return d->photogram->scene();
936 * @~spanish
937 * Retorna la capa actual.
939 Model::Layer *PaintArea::currentLayer() const
941 Model::Scene *scene = d->photogram->scene();
943 if( scene )
945 return scene->layer(d->framePosition.layer);
949 return 0;
953 * @~spanish
954 * Retorna el frame actual.
956 Model::Frame *PaintArea::currentFrame() const
958 Model::Layer *layer = currentLayer();
960 if( layer )
962 return layer->frame(d->framePosition.frame);
966 return 0;
970 * @~spanish
973 void PaintArea::addCommand(Command::Base *command)
975 d->project->commandManager()->addCommand(command);
979 * @~spanish
980 * Retorna la acción que permite remover los elementos seleccionados en el area.
981 * @return
983 QAction *PaintArea::removeAction()
985 return d->actionManager.find("remove", "edit");
989 * @~spanish
990 * Retorna la acción que permite agrupar los elementos seleccionados en el area.
991 * @return
993 QAction *PaintArea::groupAction()
995 return d->actionManager.find("group", "object");
999 * @~spanish
1000 * Retorna la acción que permite des-agrupar los elementos seleccionados en el area.
1001 * @return
1003 QAction *PaintArea::ungroupAction()
1005 return d->actionManager.find("ungroup", "object");
1009 * @~spanish
1010 * Retorna la acción que permite enviar al fondo los elementos seleccionados en el area.
1011 * @return
1013 QAction *PaintArea::sendToBackAction()
1015 return d->actionManager.find( "sendtoback", "object-order");
1019 * @~spanish
1020 * Retorna la acción que permite enviar al frente los elementos seleccionados en el area.
1021 * @return
1023 QAction *PaintArea::bringToFrontAction()
1025 return d->actionManager.find( "bringtofront", "object-order");
1030 * @~spanish
1031 * Retorna la acción que permite enviar hacia atras una unidad los elementos seleccionados en el area.
1032 * @return
1034 QAction *PaintArea::sendBackwardsAction()
1036 return d->actionManager.find( "sendbackwards", "object-order");
1040 * @~spanish
1041 * Retorna la acción que permite enviar hacia adelante una unidad los elementos seleccionados en el area.
1043 QAction *PaintArea::bringForwardsAction()
1045 return d->actionManager.find( "bringforwards", "object-order");
1049 * @~spanish
1050 * Retorna la acción que permite copiar los elementos seleccionados en el area.
1052 QAction *PaintArea::copyAction()
1054 return d->actionManager.find( "copy", "edit");
1058 * @~spanish
1059 * Retorna la acción que permite pegar los elementos que estan en el portapapeles en el area.
1061 QAction *PaintArea::pasteAction()
1063 return d->actionManager.find( "paste", "edit");
1067 * @~spanish
1068 * Retorna la acción que permite cortar los elementos seleccionados en el area.
1070 QAction *PaintArea::cutAction()
1072 return d->actionManager.find( "cut", "edit");
1076 * @~spanish
1077 * Retorna la acción que permite seleccionar todos los elementos en el area.
1079 QAction *PaintArea::selectAllAction()
1081 return d->actionManager.find("selectall", "edit");
1085 * @~spanish
1086 * Crea el menu contextual de el area de dibujo.
1088 QMenu *PaintArea::createMenu()
1090 QMenu *menu = new QMenu(tr("Drawing area"), this);
1092 Command::Manager *manager = d->project->commandManager();
1093 DGui::CommandHistory *history = manager->history();
1095 menu->addAction(history->undoAction()->icon(), history->undoAction()->text(), history, SLOT(undo()))->setEnabled(history->undoAction()->isEnabled());
1096 menu->addAction(history->redoAction()->icon(), history->redoAction()->text(), history, SLOT(redo()))->setEnabled(history->redoAction()->isEnabled());
1098 menu->addSeparator();
1099 d->actionManager.setupMenu(menu, "edit", false);
1100 menu->addSeparator();
1102 QMenu *order = new QMenu(tr("Order"));
1103 d->actionManager.setupMenu(order, "object-order");
1105 menu->addMenu (order);
1106 menu->addSeparator();
1108 if ( AbstractTool *tool = d->photogram->currentTool() )
1110 if( QMenu *toolMenu = tool->menu() )
1112 menu->addSeparator();
1113 menu->addMenu(toolMenu);
1117 return menu;
1121 * @~spanish
1122 * Retorna la barra de herramientas que provee la interfaz grafica para la configuración de las herramientas.
1124 QToolBar *PaintArea::toolsConfigBar() const
1126 return d->toolsConfigBar;
1130 * @~spanish
1131 * Retorna la barra de herramientas que provee la interfaz grafica para la configuración de los efectos.
1133 QToolBar *PaintArea::effectsConfigBar() const
1135 return d->effectsConfigBar;
1138 void PaintArea::checkActions()
1140 if(! scene()->selectedItems().isEmpty())
1142 d->actionManager.setEnabled("object-order", true);
1143 d->actionManager.find("remove", "edit")->setEnabled(true);
1144 d->actionManager.find("cut", "edit")->setEnabled(true);
1145 d->actionManager.find("copy", "edit")->setEnabled(true);
1146 d->actionManager.find("addtolibrary", "library")->setEnabled(true);
1148 else
1150 d->actionManager.setEnabled("object-order", false);
1151 d->actionManager.find("remove", "edit")->setEnabled(false);
1152 d->actionManager.find("cut", "edit")->setEnabled(false);
1153 d->actionManager.find("copy", "edit")->setEnabled(false);
1154 d->actionManager.find("addtolibrary", "library")->setEnabled(false);
1157 QString xml = QApplication::clipboard()->mimeData()->data("yamf-graphics");
1158 if ( !xml.isEmpty() )
1160 d->actionManager.find("paste", "edit")->setEnabled(true);
1162 else
1164 d->actionManager.find("paste", "edit")->setEnabled(false);
1169 * @~spanish
1170 * Remueve los elementos seleccionados.
1172 void PaintArea::removeSelectedObjects()
1174 QList<QGraphicsItem *> items = d->photogram->selectedItems();
1175 if( items.count() > 0 )
1177 currentFrame()->removeItems(items);
1178 this->checkActions();
1184 * @~spanish
1185 * Agrupa los elementos seleccionados.
1187 void PaintArea::groupSelectedObjects()
1189 QList<QGraphicsItem *> items = d->photogram->selectedItems();
1190 if( items.count() > 0 )
1192 addCommand(new Command::GroupItem(items, currentFrame()));
1197 * @~spanish
1198 * Desagrupa los elementos seleccionados.
1200 void PaintArea::ungroupSelectedObject()
1202 QList<QGraphicsItem *> items = d->photogram->selectedItems();
1203 QList<Item::Group *> groups;
1205 foreach(QGraphicsItem *item, items)
1207 if( Item::Group *group = qgraphicsitem_cast<Item::Group *>(item) )
1209 addCommand(new Command::UngroupItem(group, currentFrame()));
1215 * @~spanish
1216 * Envia atras los elementos seleccionados.
1218 void PaintArea::sendToBackSelectedObjects()
1220 QList<QGraphicsItem *> items = photogram()->selectedItems();
1222 DGraphics::Algorithm::sort(items, DGraphics::Algorithm::ZAxis);
1224 foreach(QGraphicsItem *item, items )
1226 addCommand(new Command::SendToBackItem(item));
1231 * @~spanish
1232 * Trae adelante los elementos seleccionados.
1234 void PaintArea::bringToFrontSelectedObjects()
1236 QList<QGraphicsItem *> items = photogram()->selectedItems();
1238 DGraphics::Algorithm::sort(items, DGraphics::Algorithm::ZAxis);
1240 QList<QGraphicsItem *>::iterator it = items.end();
1242 while(it != items.begin())
1244 --it;
1245 addCommand(new Command::BringToFrontItem(*it));
1250 * @~spanish
1251 * Envia atras una unidad los elementos seleccionados.
1253 void PaintArea::sendBackwardsSelectedObjects()
1255 QList<QGraphicsItem *> items = photogram()->selectedItems();
1257 DGraphics::Algorithm::sort(items, DGraphics::Algorithm::ZAxis);
1259 foreach(QGraphicsItem *item, items )
1261 addCommand(new Command::SendBackwardsItem(item));
1267 * @~spanish
1268 * Trae al frente una unidad los elementos seleccionados.
1269 */void PaintArea::bringForwardsSelectedObjects()
1271 QList<QGraphicsItem *> items = photogram()->selectedItems();
1273 DGraphics::Algorithm::sort(items, DGraphics::Algorithm::ZAxis);
1275 QList<QGraphicsItem *>::iterator it = items.end();
1277 while(it != items.begin())
1279 --it;
1280 addCommand(new Command::BringForwardsItem(*it));
1285 * @~spanish
1286 * Copia los elementos seleccionados.
1288 void PaintArea::copySelectedObjects()
1290 QList<QGraphicsItem *> selecteds = scene()->selectedItems();
1292 QDomDocument orig;
1293 QDomElement root = orig.createElement("yamf-graphics");
1295 foreach(QGraphicsItem *item, selecteds)
1297 int index = currentFrame()->logicalIndexOf( item );
1299 if(index > -1)
1301 Model::Object *graphic = currentFrame()->graphic(index);
1302 root.appendChild(graphic->toXml( orig ));
1306 orig.appendChild(root);
1308 QMimeData *mimeData = new QMimeData;
1310 mimeData->setData("yamf-graphics", orig.toString().toLocal8Bit());
1311 //TODO: image/svg+xml
1312 QApplication::clipboard()->setMimeData( mimeData );
1316 * @~spanish
1317 * Pega los elementos en el portapapeles.
1319 void PaintArea::pasteObjects()
1321 if( !currentFrame() ) return;
1323 const QMimeData *mimeData = QApplication::clipboard()->mimeData();
1325 QString xml = mimeData->data("yamf-graphics");
1327 QDomDocument doc;
1328 if(!doc.setContent(xml))
1330 return;
1333 // TODO: image/svg+xml
1335 QDomElement docElem = doc.documentElement();
1336 QDomNode n = docElem.firstChild();
1338 while(!n.isNull())
1340 QDomElement e = n.toElement();
1341 if(!e.isNull())
1343 QString xml;
1344 QTextStream ts(&xml);
1345 ts << e;
1347 Model::Object *object = new Model::Object(currentFrame());
1348 object->fromXml(xml);
1350 currentFrame()->addObject(object);
1352 n = n.nextSibling();
1354 d->photogram->drawCurrentPhotogram();
1358 * @~spanish
1359 * Corta los elementos seleccionados.
1361 void PaintArea::cutSelectedObjects()
1363 copySelectedObjects();
1364 removeSelectedObjects();
1368 * @~spanish
1369 * Selecciona todos los elementos en el area.
1371 void PaintArea::selectAllObjects()
1373 foreach(QGraphicsItem *item, photogram()->items() )
1375 item->setFlag(QGraphicsItem::ItemIsSelectable);
1376 item->setSelected(true);
1381 * @~spanish
1382 * Añade lso elementos seleccionados a la biblioteca de objetos.
1384 void PaintArea::addToLibrary()
1386 QList<QGraphicsItem *> selecteds = scene()->selectedItems();
1388 if ( selecteds.isEmpty() )
1390 DGui::Osd::self()->display(tr("No items selected"), DGui::Osd::Error);
1391 return;
1394 YAMF::Drawing::Private::AddSymbolDialog addSymbolDialog;
1396 YAMF::Model::Library *library = d->project->library();
1398 QList<QGraphicsItem *> symbols;
1400 foreach(QGraphicsItem *item, selecteds)
1402 if( YAMF::Common::AbstractSerializable *serializable = dynamic_cast<YAMF::Common::AbstractSerializable *>(item) )
1404 addSymbolDialog.addSymbol(item);
1408 if( addSymbolDialog.exec() == QDialog::Accepted )
1410 for(int i = 0; i < addSymbolDialog.symbolCount(); i++)
1412 library->addItemSymbol(addSymbolDialog.symbol(i), addSymbolDialog.symbolName(i));
1417 void PaintArea::applyCurrentSymbol()
1419 if( d->photogram->selectedItems().count() > 0 )
1421 if( Model::LibraryItem *libraryItem = qgraphicsitem_cast<Model::LibraryItem *>( d->photogram->selectedItems().first()) )
1423 YAMF::Command::ModifySymbol *cmd = new YAMF::Command::ModifySymbol(libraryItem);
1425 addCommand(cmd);
1431 * @~spanish
1432 * Añade un simbolo de la biblioteca identificado con @p id a el area .
1434 void PaintArea::addSymbol(const QString &id)
1436 YAMF::Model::LibraryObject *object = d->project->library()->findObject(id);
1437 if( object )
1439 addSymbol(object);
1444 * @~spanish
1445 * Añade un simbolo @p object de la biblioteca a el area .
1447 void PaintArea::addSymbol(YAMF::Model::LibraryObject *object)
1449 YAMF::Model::Frame *frame = currentFrame();
1450 YAMF::Model::Scene *scene = currentScene();
1452 switch(object->type())
1454 case YAMF::Model::LibraryObject::Sound:
1456 Model::LibrarySoundObject *soundObject = dynamic_cast<Model::LibrarySoundObject *>(object);
1457 if ( scene != 0 )
1459 YAMF::Model::AudioLayer *layer = scene->createAudioLayer();
1460 layer->fromSymbol(soundObject);
1463 break;
1464 case YAMF::Model::LibraryObject::Svg:
1465 case YAMF::Model::LibraryObject::Item:
1466 case YAMF::Model::LibraryObject::Image:
1467 case YAMF::Model::LibraryObject::Text:
1469 if( frame != 0 )
1471 YAMF::Model::LibraryItem *item = new YAMF::Model::LibraryItem(object);
1472 frame->addItem(item);
1475 break;
1480 * @~spanish
1482 void PaintArea::recordItem()
1484 Model::Frame *frame = currentFrame();
1486 if( frame && d->photogram->selectedItems().count() > 0 )
1488 QGraphicsItem *item = d->photogram->selectedItems().first();
1490 int logicalIndex = frame->logicalIndexOf(item);
1492 if( logicalIndex > -1 )
1494 d->photogram->recordObject(frame->graphic(logicalIndex));
1496 d->recordIt();
1502 * @~spanish
1504 void PaintArea::stopRecordItem()
1506 Model::Object *object = d->photogram->recorded();
1507 Model::Frame *frame = currentFrame();
1509 int framePos = frame->visualIndex();
1510 int objectPos = object->frame()->visualIndex();
1512 if( object && framePos > objectPos )
1514 int stepsCount = framePos - objectPos;
1516 Item::Tweener *tweener = new Item::Tweener(stepsCount, object);
1518 foreach(Private::RecordStep rs, d->steps)
1520 tweener->addStep(*rs.step);
1521 delete rs.step;
1524 object->setTweener(tweener);
1527 d->photogram->recordObject(0);
1528 d->steps.clear();