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