]> git.sesse.net Git - kdenlive/blob - src/monitorscene.cpp
On-monitor effects:
[kdenlive] / src / monitorscene.cpp
1 /***************************************************************************
2  *   Copyright (C) 2010 by Till Theato (root@ttill.de)                     *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20
21 #include "monitorscene.h"
22 #include "renderer.h"
23 #include "kdenlivesettings.h"
24
25 #include <QGraphicsView>
26 #include <QGraphicsPixmapItem>
27 #include <QGraphicsSceneMouseEvent>
28
29 MonitorScene::MonitorScene(Render *renderer, QObject* parent) :
30         QGraphicsScene(parent),
31         m_renderer(renderer),
32         m_view(NULL),
33         m_selectedItem(NULL),
34         m_resizeMode(NoResize),
35         m_clickPoint(0, 0),
36         m_backgroundImage(QImage()),
37         m_enabled(true),
38         m_modified(false),
39         m_zoom(1.0)
40 {
41     setBackgroundBrush(QBrush(QColor(KdenliveSettings::window_background().name())));
42
43     QPen framepen(Qt::SolidLine);
44     framepen.setColor(Qt::red);
45
46     m_frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_renderer->renderWidth(), m_renderer->renderHeight()));
47     m_frameBorder->setPen(framepen);
48     m_frameBorder->setZValue(-2);
49     m_frameBorder->setBrush(Qt::transparent);
50     m_frameBorder->setFlags(0);
51     addItem(m_frameBorder);
52
53     m_lastUpdate.start();
54     m_background = new QGraphicsPixmapItem();
55     m_background->setZValue(-1);
56     m_background->setFlags(0);
57     m_background->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
58     m_background->setTransformationMode(Qt::FastTransformation);
59     QPixmap bg(m_renderer->renderWidth(), m_renderer->renderHeight());
60     bg.fill();
61     m_background->setPixmap(bg);
62     addItem(m_background);
63
64     //connect(m_renderer, SIGNAL(rendererPosition(int)), this, SLOT(slotUpdateBackground()));
65     connect(m_renderer, SIGNAL(frameUpdated(QImage)), this, SLOT(slotSetBackgroundImage(QImage)));
66 }
67
68 void MonitorScene::setUp()
69 {
70     if (views().count() > 0)
71         m_view = views().at(0);
72     else
73         m_view = NULL;
74
75     m_view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
76 }
77
78 void MonitorScene::resetProfile()
79 {
80     const QRectF border(0, 0, m_renderer->renderWidth(), m_renderer->renderHeight());
81     m_frameBorder->setRect(border);
82 }
83
84 void MonitorScene::setEnabled(bool enabled)
85 {
86     m_enabled = enabled;
87 }
88
89 void MonitorScene::slotUpdateBackground()
90 {
91     if (m_view && m_view->isVisible()) {
92         if (m_lastUpdate.elapsed() > 100) {
93             m_background->setPixmap(QPixmap::fromImage(m_backgroundImage, Qt::ThresholdDither));
94             m_lastUpdate.start();
95         }
96     }
97 }
98
99 void MonitorScene::slotSetDirectUpdate(bool directUpdate)
100 {
101     KdenliveSettings::setMonitorscene_directupdate(directUpdate);
102 }
103
104 void MonitorScene::slotSetBackgroundImage(const QImage &image)
105 {
106     if (m_view && m_view->isVisible()) {
107         m_backgroundImage = image;
108         slotUpdateBackground();
109     }
110 }
111
112
113 void MonitorScene::slotZoom(int value)
114 {
115     if (m_view) {
116         m_zoom = value / 100.0;
117         m_view->resetTransform();
118         m_view->scale(m_zoom, m_zoom);
119         emit zoomChanged(value);
120     }
121 }
122
123 void MonitorScene::slotZoomFit()
124 {
125     if (m_view) {
126         m_view->fitInView(m_frameBorder, Qt::KeepAspectRatio);
127         m_view->centerOn(m_frameBorder);
128         m_zoom = m_view->matrix().m11();
129         emit zoomChanged((int)(m_zoom * 100));
130     }
131 }
132
133 void MonitorScene::slotZoomOriginal()
134 {
135     slotZoom(100);
136     if (m_view)
137         m_view->centerOn(m_frameBorder);
138 }
139
140 void MonitorScene::slotZoomOut()
141 {
142     slotZoom(qMax(0, (int)(m_zoom * 100 - 1)));
143 }
144
145 void MonitorScene::slotZoomIn()
146 {
147     slotZoom(qMin(300, (int)(m_zoom * 100 + 1)));
148 }
149
150
151 resizeModes MonitorScene::getResizeMode(QGraphicsRectItem *item, QPoint pos)
152 {
153     if (!m_view)
154         return NoResize;
155
156     QRectF rect = item->rect().normalized();
157     // Item mapped coordinates
158     QPolygon pol = item->deviceTransform(m_view->viewportTransform()).map(rect).toPolygon();
159     QPainterPath top(pol.point(0));
160     top.lineTo(pol.point(1));
161     QPainterPath bottom(pol.point(2));
162     bottom.lineTo(pol.point(3));
163     QPainterPath left(pol.point(0));
164     left.lineTo(pol.point(3));
165     QPainterPath right(pol.point(1));
166     right.lineTo(pol.point(2));
167
168     QPainterPath mouseArea;
169     mouseArea.addRect(pos.x() - 4, pos.y() - 4, 8, 8);
170
171     // Check for collisions between the mouse and the borders
172     if (mouseArea.contains(pol.point(0)))
173         return TopLeft;
174     else if (mouseArea.contains(pol.point(2)))
175         return BottomRight;
176     else if (mouseArea.contains(pol.point(1)))
177         return TopRight;
178     else if (mouseArea.contains(pol.point(3)))
179         return BottomLeft;
180     else if (top.intersects(mouseArea))
181         return Top;
182     else if (bottom.intersects(mouseArea))
183         return Bottom;
184     else if (right.intersects(mouseArea))
185         return Right;
186     else if (left.intersects(mouseArea))
187         return Left;
188     else
189         return NoResize;
190 }
191
192 void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
193 {
194     if (!m_enabled)
195         return;
196
197     m_resizeMode = NoResize;
198     m_selectedItem = NULL;
199
200     m_clickPoint = event->scenePos();
201     QList<QGraphicsItem *> itemList = items(QRectF(m_clickPoint - QPoint(4, 4), QSizeF(4, 4)).toRect());
202
203     for (int i = 0; i < itemList.count(); ++i) {
204         if (itemList.at(i)->zValue() >= 0 && itemList.at(i)->flags() & QGraphicsItem::ItemIsMovable) {
205             m_selectedItem = itemList.at(i);
206             // Rect
207             if (itemList.at(i)->type() == 3) {
208                 m_resizeMode = getResizeMode((QGraphicsRectItem*)m_selectedItem, m_view->mapFromScene(m_clickPoint));
209                 break;
210             }
211         }
212     }
213
214     QGraphicsScene::mousePressEvent(event);
215 }
216
217 void MonitorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
218 {
219     if (!m_enabled) {
220         if (m_view)
221             m_view->setCursor(Qt::ArrowCursor);
222         return;
223     }
224
225     /*if (event->buttons() != Qt::NoButton && (event->screenPos() - m_screenClickPoint).manhattanLength() < QApplication::startDragDistance()) {
226         event->accept();
227         return;
228     }*/
229
230     QPointF mousePos = event->scenePos();
231
232     if (m_selectedItem && event->buttons() & Qt::LeftButton) {
233         // Rect
234         if (m_selectedItem->type() == 3) {
235             QGraphicsRectItem *item = static_cast <QGraphicsRectItem *>(m_selectedItem);
236             QRectF rect = item->rect().normalized();
237             QPointF pos = item->pos();
238             QPointF mousePosInRect = item->mapFromScene(mousePos);
239             switch (m_resizeMode) {
240             case TopLeft:
241                 if (mousePos.x() < pos.x() + rect.height() && mousePos.y() < pos.y() + rect.height()) {
242                     item->setRect(rect.adjusted(0, 0, -mousePosInRect.x(), -mousePosInRect.y()));
243                     item->setPos(mousePos);
244                     m_modified = true;
245                 }
246                 break;
247             case Top:
248                 if (mousePos.y() < pos.y() + rect.height()) {
249                     rect.setBottom(rect.height() - mousePosInRect.y());
250                     item->setRect(rect);
251                     item->setPos(QPointF(pos.x(), mousePos.y()));
252                     m_modified = true;
253                 }
254                 break;
255             case TopRight:
256                 if (mousePos.x() > pos.x() && mousePos.y() < pos.y() + rect.height()) {
257                     rect.setBottomRight(QPointF(mousePosInRect.x(), rect.bottom() - mousePosInRect.y()));
258                     item->setRect(rect);
259                     item->setPos(QPointF(pos.x(), mousePos.y()));
260                     m_modified = true;
261                 }
262                 break;
263             case Left:
264                 if (mousePos.x() < pos.x() + rect.width()) {
265                     rect.setRight(rect.width() - mousePosInRect.x());
266                     item->setRect(rect);
267                     item->setPos(QPointF(mousePos.x(), pos.y()));
268                     m_modified = true;
269                 }
270                 break;
271             case Right:
272                 if (mousePos.x() > pos.x()) {
273                     rect.setRight(mousePosInRect.x());
274                     item->setRect(rect);
275                     m_modified = true;
276                 }
277                 break;
278             case BottomLeft:
279                 if (mousePos.x() < pos.x() + rect.width() && mousePos.y() > pos.y()) {
280                     rect.setBottomRight(QPointF(rect.width() - mousePosInRect.x(), mousePosInRect.y()));
281                     item->setRect(rect);
282                     item->setPos(QPointF(mousePos.x(), pos.y()));
283                     m_modified = true;
284                 }
285                 break;
286             case Bottom:
287                 if (mousePos.y() > pos.y()) {
288                     rect.setBottom(mousePosInRect.y());
289                     item->setRect(rect);
290                     m_modified = true;
291                 }
292                 break;
293             case BottomRight:
294                 if (mousePos.x() > pos.x() && mousePos.y() > pos.y()) {
295                     rect.setBottomRight(mousePosInRect);
296                     item->setRect(rect);
297                     m_modified = true;
298                 }
299                 break;
300             default:
301                 QPointF diff = mousePos - m_clickPoint;
302                 m_clickPoint = mousePos;
303                 item->moveBy(diff.x(), diff.y());
304                 m_modified = true;
305                 break;
306             }
307         }
308     } else {
309         mousePos -= QPoint(4, 4);
310         bool itemFound = false;
311         QList<QGraphicsItem *> itemList = items(QRectF(mousePos, QSizeF(4, 4)).toRect());
312
313         foreach(const QGraphicsItem* item, itemList) {
314             if (item->zValue() >= 0 && item->flags() &QGraphicsItem::ItemIsMovable) {
315                 // Rect
316                 if (item->type() == 3) {
317                     if (m_view == NULL)
318                         continue;
319
320                     itemFound = true;
321
322                     switch (getResizeMode((QGraphicsRectItem*)item, m_view->mapFromScene(event->scenePos()))) {
323                     case TopLeft:
324                     case BottomRight:
325                         m_view->setCursor(Qt::SizeFDiagCursor);
326                         break;
327                     case TopRight:
328                     case BottomLeft:
329                         m_view->setCursor(Qt::SizeBDiagCursor);
330                         break;
331                     case Top:
332                     case Bottom:
333                         m_view->setCursor(Qt::SizeVerCursor);
334                         break;
335                     case Left:
336                     case Right:
337                         m_view->setCursor(Qt::SizeHorCursor);
338                         break;
339                     default:
340                         m_view->setCursor(Qt::OpenHandCursor);
341                     }
342                     break;
343                 }
344             }
345         }
346
347         if (!itemFound && m_view)
348             m_view->setCursor(Qt::ArrowCursor);
349
350         QGraphicsScene::mouseMoveEvent(event);
351     }
352     if (m_modified && KdenliveSettings::monitorscene_directupdate()) {
353         emit actionFinished();
354         m_modified = false;
355     }
356 }
357
358 void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
359 {
360     Q_UNUSED(event);
361
362     if (!m_enabled)
363         return;
364
365     if (m_modified) {
366         m_modified = false;
367         emit actionFinished();
368     }
369 }
370
371 void MonitorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
372 {
373     Q_UNUSED(event);
374
375     if (!m_enabled)
376         emit addKeyframe();
377 }
378
379
380 #include "monitorscene.moc"