]> git.sesse.net Git - kdenlive/blob - src/monitorscene.cpp
rotoscoping: preserve point selection after mouse release
[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 "onmonitoritems/rotoscoping/bpointitem.h"
24 #include "onmonitoritems/rotoscoping/splineitem.h"
25 #include "kdenlivesettings.h"
26
27 #include <QGraphicsView>
28 #include <QGraphicsPixmapItem>
29 #include <QGraphicsSceneMouseEvent>
30
31
32 MonitorScene::MonitorScene(Render *renderer, QObject* parent) :
33         QGraphicsScene(parent),
34         m_renderer(renderer),
35         m_view(NULL),
36         m_backgroundImage(QImage()),
37         m_enabled(true),
38         m_zoom(1.0),
39         m_groupMove(false)
40 {
41     setBackgroundBrush(QBrush(QColor(KdenliveSettings::window_background().name())));
42
43     QPen framepen(Qt::DotLine);
44     framepen.setColor(Qt::red);
45
46     m_frameBorder = new QGraphicsRectItem(QRectF(0, 0, m_renderer->frameRenderWidth(), m_renderer->renderHeight()));
47     m_frameBorder->setPen(framepen);
48     m_frameBorder->setZValue(-1);
49     m_frameBorder->setBrush(Qt::transparent);
50     m_frameBorder->setFlags(0);
51     addItem(m_frameBorder);
52
53     m_lastUpdate = QTime::currentTime();
54     m_background = new QGraphicsPixmapItem();
55     m_background->setZValue(-2);
56     m_background->setFlags(0);
57     m_background->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
58     m_background->setTransformationMode(Qt::FastTransformation);
59     QPixmap bg(m_renderer->frameRenderWidth(), m_renderer->renderHeight());
60     bg.fill();
61     m_background->setPixmap(bg);
62     addItem(m_background);
63
64     connect(m_renderer, SIGNAL(frameUpdated(QImage)), this, SLOT(slotSetBackgroundImage(QImage)));
65 }
66
67 void MonitorScene::setUp()
68 {
69     if (views().count() > 0) {
70         m_view = views().at(0);
71         m_view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
72     } else {
73         m_view = NULL;
74     }
75 }
76
77 void MonitorScene::resetProfile()
78 {
79     const QRectF border(0, 0, m_renderer->frameRenderWidth(), m_renderer->renderHeight());
80     m_frameBorder->setRect(border);
81 }
82
83 void MonitorScene::setEnabled(bool enabled)
84 {
85     m_enabled = enabled;
86 }
87
88 void MonitorScene::slotUpdateBackground()
89 {
90     if (m_view && m_view->isVisible()) {
91         if (m_lastUpdate.msecsTo(QTime::currentTime()) > 50) {
92             m_background->setPixmap(QPixmap::fromImage(m_backgroundImage));
93             m_lastUpdate = QTime::currentTime();
94         }
95     }
96 }
97
98 void MonitorScene::slotSetBackgroundImage(const QImage &image)
99 {
100     if (m_view && m_view->isVisible()) {
101         m_backgroundImage = image;
102         slotUpdateBackground();
103     }
104 }
105
106 void MonitorScene::slotZoom(int value)
107 {
108     if (m_view) {
109         m_zoom = value / 100.0;
110         m_view->resetTransform();
111         m_view->scale(m_renderer->renderWidth() * m_zoom / m_renderer->frameRenderWidth(), m_zoom);
112         emit zoomChanged(value);
113     }
114 }
115
116 void MonitorScene::slotZoomFit()
117 {
118     if (m_view) {
119         int xzoom = 100 * m_view->viewport()->height() / m_renderer->renderHeight();
120         int yzoom = 100 * m_view->viewport()->width() / m_renderer->renderWidth();
121         slotZoom(qMin(xzoom, yzoom));
122         m_view->centerOn(m_frameBorder);
123     }
124 }
125
126 void MonitorScene::slotZoomOriginal()
127 {
128     slotZoom(100);
129     if (m_view)
130         m_view->centerOn(m_frameBorder);
131 }
132
133 void MonitorScene::slotZoomOut(int by)
134 {
135     slotZoom(qMax(0, (int)(m_zoom * 100 - by)));
136 }
137
138 void MonitorScene::slotZoomIn(int by)
139 {
140     slotZoom(qMin(300, (int)(m_zoom * 100 + by + 0.5)));
141 }
142
143 void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
144 {
145     QList <QGraphicsItem *> selected = selectedItems();
146
147     QGraphicsScene::mousePressEvent(event);
148
149     if (selected.count() != selectedItems().count()) {
150         // mouse click on item not in selection group
151         // -> select only this item
152         foreach (QGraphicsItem *item, selected)
153             item->setSelected(false);
154     }
155
156     if (event->isAccepted() && selectedItems().count() > 1) {
157         // multiple items selected + mouse pressed on an item
158         selected = selectedItems();
159         foreach (QGraphicsItem *item, selected) {
160             if (qgraphicsitem_cast<BPointItem*>(item)) {
161                 // works with rotoscoping only for now
162                 m_groupMove = true;
163                 m_lastPos = event->scenePos();
164                 return;
165             }
166         }
167     }
168
169     if (!event->isAccepted() && event->buttons() & Qt::LeftButton) {
170         if (event->modifiers() == Qt::ControlModifier)
171             m_view->setDragMode(QGraphicsView::ScrollHandDrag);
172         else if (event->modifiers() == Qt::ShiftModifier)
173             m_view->setDragMode(QGraphicsView::RubberBandDrag);
174     }
175 }
176
177 void MonitorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
178 {
179     if (m_groupMove) {
180         // we want to move multiple items
181         // rotoscoping only for now
182         QPointF diff =  event->scenePos() - m_lastPos;
183         if (diff != QPointF(0, 0)) {
184             m_lastPos = event->scenePos();
185             QList <QGraphicsItem *> selected = selectedItems();
186             int first = -1;
187             int i = 0;
188             foreach (QGraphicsItem *item, selected) {
189                 BPointItem *bpoint = qgraphicsitem_cast<BPointItem *>(item);
190                 if (bpoint) {
191                     if (first < 0)
192                         first = i;
193                     BPoint p = bpoint->getPoint();
194                     p.setP(p.p + diff);
195                     bpoint->setPoint(p);
196                 }
197                 ++i;
198             }
199
200             if (first >= 0) {
201                 QGraphicsItem *item = selected.at(first);
202                 if (item->parentItem()) {
203                     SplineItem *parent = qgraphicsitem_cast<SplineItem*>(item->parentItem());
204                     if (parent)
205                         parent->updateSpline(true);
206                 }
207             }
208         }
209     } else {
210         QGraphicsScene::mouseMoveEvent(event);
211     }
212 }
213
214 void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
215 {
216     if (m_groupMove) {
217         QList <QGraphicsItem *> selected = selectedItems();
218         foreach (QGraphicsItem *item, selected) {
219             if (qgraphicsitem_cast<BPointItem*>(item) && item->parentItem()) {
220                 SplineItem *parent = qgraphicsitem_cast<SplineItem*>(item->parentItem());
221                 if (parent) {
222                     parent->updateSpline(false);
223                     break;
224                 }
225             }
226         }
227         m_groupMove = false;
228     }
229     QGraphicsScene::mouseReleaseEvent(event);
230     m_view->setDragMode(QGraphicsView::NoDrag);
231 }
232 void MonitorScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
233 {
234     Q_UNUSED(event);
235
236     if (!m_enabled)
237         emit addKeyframe();
238 }
239
240 void MonitorScene::wheelEvent(QGraphicsSceneWheelEvent* event)
241 {
242     if (event->modifiers() == Qt::ControlModifier) {
243         if (event->delta() > 0)
244             slotZoomIn(5);
245         else
246             slotZoomOut(5);
247     } else {
248         QGraphicsScene::wheelEvent(event);
249     }
250
251     event->accept();
252 }
253
254 #include "monitorscene.moc"