]> git.sesse.net Git - kdenlive/blob - src/monitorscene.cpp
Add settings 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         m_modified(false),
39         m_directUpdate(false)
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     slotUpdateBackground(true);
78 }
79
80 void MonitorScene::setEnabled(bool enabled)
81 {
82     m_enabled = enabled;
83 }
84
85 void MonitorScene::slotUpdateBackground(bool fit)
86 {
87     if (m_view && m_view->isVisible()) {
88         if (m_lastUpdate.elapsed() > 200) {
89             m_background->setPixmap(QPixmap::fromImage(m_backgroundImage, Qt::ThresholdDither));
90             if (fit) {
91                 m_view->fitInView(m_frameBorder, Qt::KeepAspectRatio);
92                 m_view->centerOn(m_frameBorder);
93             }
94             m_lastUpdate.start();
95         }
96     }
97 }
98
99 void MonitorScene::slotSetDirectUpdate(bool directUpdate)
100 {
101     m_directUpdate = directUpdate;
102 }
103
104 bool MonitorScene::getDirectUpdate()
105 {
106     return m_directUpdate;
107 }
108
109 void MonitorScene::slotSetBackgroundImage(QImage image)
110 {
111     m_backgroundImage = image;
112     slotUpdateBackground();
113 }
114
115 resizeModes MonitorScene::getResizeMode(QGraphicsRectItem *item, QPoint pos)
116 {
117     if(!m_view)
118         return NoResize;
119
120     QRectF rect = item->rect().normalized();
121     // Item mapped coordinates
122     QPolygon pol = item->deviceTransform(m_view->viewportTransform()).map(rect).toPolygon();
123     QPainterPath top(pol.point(0));
124     top.lineTo(pol.point(1));
125     QPainterPath bottom(pol.point(2));
126     bottom.lineTo(pol.point(3));
127     QPainterPath left(pol.point(0));
128     left.lineTo(pol.point(3));
129     QPainterPath right(pol.point(1));
130     right.lineTo(pol.point(2));
131
132     QPainterPath mouseArea;
133     mouseArea.addRect(pos.x() - 4, pos.y() - 4, 8, 8);
134
135     // Check for collisions between the mouse and the borders
136     if (mouseArea.contains(pol.point(0)))
137         return TopLeft;
138     else if (mouseArea.contains(pol.point(2)))
139         return BottomRight;
140     else if (mouseArea.contains(pol.point(1)))
141         return TopRight;
142     else if (mouseArea.contains(pol.point(3)))
143         return BottomLeft;
144     else if (top.intersects(mouseArea))
145         return Top;
146     else if (bottom.intersects(mouseArea))
147         return Bottom;
148     else if (right.intersects(mouseArea))
149         return Right;
150     else if (left.intersects(mouseArea))
151         return Left;
152     else
153         return NoResize;
154 }
155
156 void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
157 {
158     if (!m_enabled)
159         return;
160
161     m_resizeMode = NoResize;
162     m_selectedItem = NULL;
163
164     m_clickPoint = event->scenePos();
165     QList<QGraphicsItem *> itemList = items(QRectF(m_clickPoint - QPoint(4, 4), QSizeF(4, 4)).toRect());
166
167     for (int i = 0; i < itemList.count(); ++i) {
168         if (itemList.at(i)->zValue() >= 0 && itemList.at(i)->flags() & QGraphicsItem::ItemIsMovable) {
169             m_selectedItem = itemList.at(i);
170             // Rect
171             if (itemList.at(i)->type() == 3) {
172                 m_resizeMode = getResizeMode((QGraphicsRectItem*)m_selectedItem, m_view->mapFromScene(m_clickPoint));
173                 break;
174             }
175         }
176     }
177
178     QGraphicsScene::mousePressEvent(event);
179 }
180
181 void MonitorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
182 {
183     if (!m_enabled)
184         return;
185
186     QPointF mousePos = event->scenePos();
187
188     if (m_selectedItem && event->buttons() & Qt::LeftButton) {
189         // Rect
190         if (m_selectedItem->type() == 3) {
191             QGraphicsRectItem *item = static_cast <QGraphicsRectItem *>(m_selectedItem);
192             QRectF rect = item->rect().normalized();
193             QPointF pos = item->pos();
194             QPointF mousePosInRect = item->mapFromScene(mousePos);
195             switch (m_resizeMode) {
196             case TopLeft:
197                 if (mousePos.x() < pos.x() + rect.height() && mousePos.y() < pos.y() + rect.height()) {
198                     item->setRect(rect.adjusted(0, 0, -mousePosInRect.x(), -mousePosInRect.y()));
199                     item->setPos(mousePos);
200                     m_modified = true;
201                 }
202                 break;
203             case Top:
204                 if (mousePos.y() < pos.y() + rect.height()) {
205                     rect.setBottom(rect.height() - mousePosInRect.y());
206                     item->setRect(rect);
207                     item->setPos(QPointF(pos.x(), mousePos.y()));
208                     m_modified = true;
209                 }
210                 break;
211             case TopRight:
212                 if (mousePos.x() > pos.x() && mousePos.y() < pos.y() + rect.height()) {
213                     rect.setBottomRight(QPointF(mousePosInRect.x(), rect.bottom() - mousePosInRect.y()));
214                     item->setRect(rect);
215                     item->setPos(QPointF(pos.x(), mousePos.y()));
216                     m_modified = true;
217                 }
218                 break;
219             case Left:
220                 if (mousePos.x() < pos.x() + rect.width()) {
221                     rect.setRight(rect.width() - mousePosInRect.x());
222                     item->setRect(rect);
223                     item->setPos(QPointF(mousePos.x(), pos.y()));
224                     m_modified = true;
225                 }
226                 break;
227             case Right:
228                 if (mousePos.x() > pos.x()) {
229                     rect.setRight(mousePosInRect.x());
230                     item->setRect(rect);
231                     m_modified = true;
232                 }
233                 break;
234             case BottomLeft:
235                 if (mousePos.x() < pos.x() + rect.width() && mousePos.y() > pos.y()) {
236                     rect.setBottomRight(QPointF(rect.width() - mousePosInRect.x(), mousePosInRect.y()));
237                     item->setRect(rect);
238                     item->setPos(QPointF(mousePos.x(), pos.y()));
239                     m_modified = true;
240                 }
241                 break;
242             case Bottom:
243                 if (mousePos.y() > pos.y()) {
244                     rect.setBottom(mousePosInRect.y());
245                     item->setRect(rect);
246                     m_modified = true;
247                 }
248                 break;
249             case BottomRight:
250                 if (mousePos.x() > pos.x() && mousePos.y() > pos.y()) {
251                     rect.setBottomRight(mousePosInRect);
252                     item->setRect(rect);
253                     m_modified = true;
254                 }
255                 break;
256             default:
257                 QPointF diff = mousePos - m_clickPoint;
258                 m_clickPoint = mousePos;
259                 item->moveBy(diff.x(), diff.y());
260                 m_modified = true;
261                 break;
262             }
263         }
264     } else {
265         mousePos -= QPoint(4, 4);
266         bool itemFound = false;
267         QList<QGraphicsItem *> itemList = items(QRectF(mousePos, QSizeF(4, 4)).toRect());
268
269         foreach (const QGraphicsItem* item, itemList) {
270             if (item->zValue() >= 0 && item->flags() &QGraphicsItem::ItemIsMovable) {
271                 // Rect
272                 if (item->type() == 3) {
273                     if (m_view == NULL)
274                         continue;
275
276                     itemFound = true;
277
278                     switch (getResizeMode((QGraphicsRectItem*)item, m_view->mapFromScene(event->scenePos()))) {
279                     case TopLeft:
280                     case BottomRight:
281                         m_view->setCursor(Qt::SizeFDiagCursor);
282                         break;
283                     case TopRight:
284                     case BottomLeft:
285                         m_view->setCursor(Qt::SizeBDiagCursor);
286                         break;
287                     case Top:
288                     case Bottom:
289                         m_view->setCursor(Qt::SizeVerCursor);
290                         break;
291                     case Left:
292                     case Right:
293                         m_view->setCursor(Qt::SizeHorCursor);
294                         break;
295                     default:
296                         m_view->setCursor(Qt::OpenHandCursor);
297                     }
298                     break;
299                 }
300             }
301         }
302
303         if (!itemFound && m_view)
304             m_view->setCursor(Qt::ArrowCursor);
305
306         QGraphicsScene::mouseMoveEvent(event);
307     }
308     if (m_modified && m_directUpdate) {
309         emit actionFinished();
310         m_modified = false;
311     }
312 }
313
314 void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
315 {
316     if (!m_enabled)
317         return;
318
319     QGraphicsScene::mouseReleaseEvent(event);
320     if (m_modified) {
321         m_modified = false;
322         emit actionFinished();
323     }
324 }
325
326 #include "monitorscene.moc"