]> 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 <QtCore>
26 #include <QGraphicsView>
27 #include <QGraphicsPixmapItem>
28 #include <QGraphicsSceneMouseEvent>
29
30 MonitorScene::MonitorScene(Render *renderer, QObject* parent) :
31         QGraphicsScene(parent),
32         m_renderer(renderer),
33         m_view(NULL),
34         m_selectedItem(NULL),
35         m_resizeMode(NoResize),
36         m_clickPoint(0, 0)
37 {
38     setBackgroundBrush(QBrush(QColor(KdenliveSettings::window_background().name())));
39
40     QPen framepen(Qt::DotLine);
41     framepen.setColor(Qt::red);
42
43     m_frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_renderer->renderWidth(), m_renderer->renderHeight()));
44     m_frameBorder->setPen(framepen);
45     m_frameBorder->setZValue(-9);
46     m_frameBorder->setBrush(Qt::transparent);
47     m_frameBorder->setFlags(0);
48     addItem(m_frameBorder);
49
50     m_lastUpdate.start();
51     m_background = new QGraphicsPixmapItem();
52     m_background->setZValue(-10);
53     m_background->setFlags(0);
54     QPixmap bg(m_renderer->renderWidth(), m_renderer->renderHeight());
55     bg.fill();
56     m_background->setPixmap(bg);
57     addItem(m_background);
58
59     connect(m_renderer, SIGNAL(rendererPosition(int)), this, SLOT(slotUpdateBackground()));
60     connect(m_renderer, SIGNAL(frameUpdated(int)), this, SLOT(slotUpdateBackground()));
61 }
62
63 void MonitorScene::setUp()
64 {
65     if (views().count() > 0)
66         m_view = views().at(0);
67     else
68         m_view = NULL;
69     slotUpdateBackground();
70 }
71
72 void MonitorScene::slotUpdateBackground()
73 {
74     if (m_view && m_view->isVisible()) {
75         if (m_lastUpdate.elapsed() > 200) {
76             m_background->setPixmap(QPixmap::fromImage(m_renderer->extractFrame(m_renderer->seekFramePosition())));
77             m_view->fitInView(m_frameBorder, Qt::KeepAspectRatio);
78             m_view->centerOn(m_frameBorder);
79             m_lastUpdate.start();
80         }
81     }
82 }
83
84 resizeModes MonitorScene::getResizeMode(QGraphicsRectItem *item, QPoint pos)
85 {
86     if(!m_view)
87         return NoResize;
88
89     QRectF rect = item->rect().normalized();
90     // Item mapped coordinates
91     QPolygon pol = item->deviceTransform(m_view->viewportTransform()).map(rect).toPolygon();
92     QPainterPath top(pol.point(0));
93     top.lineTo(pol.point(1));
94     QPainterPath bottom(pol.point(2));
95     bottom.lineTo(pol.point(3));
96     QPainterPath left(pol.point(0));
97     left.lineTo(pol.point(3));
98     QPainterPath right(pol.point(1));
99     right.lineTo(pol.point(2));
100
101     QPainterPath mouseArea;
102     mouseArea.addRect(pos.x() - 4, pos.y() - 4, 8, 8);
103
104     // Check for collisions between the mouse and the borders
105     if (mouseArea.contains(pol.point(0)))
106         return TopLeft;
107     else if (mouseArea.contains(pol.point(2)))
108         return BottomRight;
109     else if (mouseArea.contains(pol.point(1)))
110         return TopRight;
111     else if (mouseArea.contains(pol.point(3)))
112         return BottomLeft;
113     else if (top.intersects(mouseArea))
114         return Top;
115     else if (bottom.intersects(mouseArea))
116         return Bottom;
117     else if (right.intersects(mouseArea))
118         return Right;
119     else if (left.intersects(mouseArea))
120         return Left;
121     else
122         return NoResize;
123 }
124
125 void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
126 {
127     m_resizeMode = NoResize;
128     m_selectedItem = NULL;
129
130     m_clickPoint = event->scenePos();
131     QList<QGraphicsItem *> itemList = items(QRectF(m_clickPoint - QPoint(4, 4), QSizeF(4, 4)).toRect());
132
133     for (int i = 0; i < itemList.count(); ++i) {
134         if (itemList.at(i)->zValue() >= 0 && itemList.at(i)->flags() & QGraphicsItem::ItemIsMovable) {
135             m_selectedItem = itemList.at(i);
136             // Rect
137             if (itemList.at(i)->type() == 3) {
138                 m_resizeMode = getResizeMode((QGraphicsRectItem*)m_selectedItem, m_view->mapFromScene(m_clickPoint));
139                 break;
140             }
141         }
142     }
143
144     QGraphicsScene::mousePressEvent(event);
145 }
146
147 void MonitorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
148 {
149     QPointF mousePos = event->scenePos();
150
151     if (m_selectedItem && event->buttons() & Qt::LeftButton) {
152         // Rect
153         if (m_selectedItem->type() == 3) {
154             QGraphicsRectItem *item = static_cast <QGraphicsRectItem *>(m_selectedItem);
155             QRectF rect = item->rect().normalized();
156             QPointF pos = item->pos();
157             QPointF mousePosInRect = item->mapFromScene(mousePos);
158             switch (m_resizeMode) {
159             case TopLeft:
160                 if (mousePos.x() < pos.x() + rect.height() && mousePos.y() < pos.y() + rect.height()) {
161                     item->setRect(rect.adjusted(0, 0, -mousePosInRect.x(), -mousePosInRect.y()));
162                     item->setPos(mousePos);
163                 }
164                 break;
165             case Top:
166                 if (mousePos.y() < pos.y() + rect.height()) {
167                     rect.setBottom(rect.height() - mousePosInRect.y());
168                     item->setRect(rect);
169                     item->setPos(QPointF(pos.x(), mousePos.y()));
170                 }
171                 break;
172             case TopRight:
173                 if (mousePos.x() > pos.x() && mousePos.y() < pos.y() + rect.height()) {
174                     rect.setBottomRight(QPointF(mousePosInRect.x(), rect.bottom() - mousePosInRect.y()));
175                     item->setRect(rect);
176                     item->setPos(QPointF(pos.x(), mousePos.y()));
177                 }
178                 break;
179             case Left:
180                 if (mousePos.x() < pos.x() + rect.width()) {
181                     rect.setRight(rect.width() - mousePosInRect.x());
182                     item->setRect(rect);
183                     item->setPos(QPointF(mousePos.x(), pos.y()));
184                 }
185                 break;
186             case Right:
187                 if (mousePos.x() > pos.x()) {
188                     rect.setRight(mousePosInRect.x());
189                     item->setRect(rect);
190                 }
191                 break;
192             case BottomLeft:
193                 if (mousePos.x() < pos.x() + rect.width() && mousePos.y() > pos.y()) {
194                     rect.setBottomRight(QPointF(rect.width() - mousePosInRect.x(), mousePosInRect.y()));
195                     item->setRect(rect);
196                     item->setPos(QPointF(mousePos.x(), pos.y()));
197                 }
198                 break;
199             case Bottom:
200                 if (mousePos.y() > pos.y()) {
201                     rect.setBottom(mousePosInRect.y());
202                     item->setRect(rect);
203                 }
204                 break;
205             case BottomRight:
206                 if (mousePos.x() > pos.x() && mousePos.y() > pos.y()) {
207                     rect.setBottomRight(mousePosInRect);
208                     item->setRect(rect);
209                 }
210                 break;
211             default:
212                 QPointF diff = mousePos - m_clickPoint;
213                 m_clickPoint = mousePos;
214                 item->moveBy(diff.x(), diff.y());
215                 break;
216             }
217         }
218     } else {
219         mousePos -= QPoint(4, 4);
220         bool itemFound = false;
221         QList<QGraphicsItem *> itemList = items(QRectF(mousePos, QSizeF(4, 4)).toRect());
222
223         foreach (const QGraphicsItem* item, itemList) {
224             if (item->zValue() >= 0 && item->flags() &QGraphicsItem::ItemIsMovable) {
225                 // Rect
226                 if (item->type() == 3) {
227                     if (m_view == NULL)
228                         continue;
229
230                     itemFound = true;
231
232                     switch (getResizeMode((QGraphicsRectItem*)item, m_view->mapFromScene(event->scenePos()))) {
233                     case TopLeft:
234                     case BottomRight:
235                         m_view->setCursor(Qt::SizeFDiagCursor);
236                         break;
237                     case TopRight:
238                     case BottomLeft:
239                         m_view->setCursor(Qt::SizeBDiagCursor);
240                         break;
241                     case Top:
242                     case Bottom:
243                         m_view->setCursor(Qt::SizeVerCursor);
244                         break;
245                     case Left:
246                     case Right:
247                         m_view->setCursor(Qt::SizeHorCursor);
248                         break;
249                     default:
250                         m_view->setCursor(Qt::OpenHandCursor);
251                     }
252                     break;
253                 }
254             }
255         }
256
257         if (!itemFound && m_view != NULL)
258             m_view->setCursor(Qt::ArrowCursor);
259
260         QGraphicsScene::mouseMoveEvent(event);
261     }
262 }
263
264 void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
265 {
266     QGraphicsScene::mouseReleaseEvent(event);
267     emit actionFinished();
268 }
269
270 #include "monitorscene.moc"