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