]> git.sesse.net Git - kdenlive/blob - src/onmonitoritems/onmonitorrectitem.cpp
5188be8fadaee2dd9edc01c4b6d313f13e315ad1
[kdenlive] / src / onmonitoritems / onmonitorrectitem.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 #include "onmonitorrectitem.h"
21 #include "kdenlivesettings.h"
22
23 #include <QGraphicsSceneMouseEvent>
24 #include <QPainter>
25 #include <QStyleOptionGraphicsItem>
26 #include <QCursor>
27 #include <QGraphicsView>
28
29 OnMonitorRectItem::OnMonitorRectItem(const QRectF &rect, double dar, QGraphicsItem* parent) :
30         QGraphicsRectItem(rect, parent),
31         m_dar(dar),
32         m_modified(false),
33         m_view(NULL)
34 {
35     setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
36
37     QPen framepen(Qt::SolidLine);
38     framepen.setColor(Qt::yellow);
39     setPen(framepen);
40     setBrush(Qt::transparent);
41     setAcceptHoverEvents(true);
42 }
43
44 rectActions OnMonitorRectItem::getMode(QPointF pos)
45 {
46     // Item mapped coordinates
47     QPolygonF pol(rect().normalized());
48
49     QPainterPath top(pol.at(0));
50     top.lineTo(pol.at(1));
51     QPainterPath bottom(pol.at(2));
52     bottom.lineTo(pol.at(3));
53     QPainterPath left(pol.at(0));
54     left.lineTo(pol.at(3));
55     QPainterPath right(pol.at(1));
56     right.lineTo(pol.at(2));
57
58     QPainterPath mouseArea;
59     qreal size = 8;
60     if (getView())
61         size /= m_view->matrix().m11();
62     mouseArea.addRect(pos.x() - size / 2, pos.y() - size / 2, size, size);
63
64     // Check for collisions between the mouse and the borders
65     if (mouseArea.contains(pol.at(0)))
66         return ResizeTopLeft;
67     else if (mouseArea.contains(pol.at(2)))
68         return ResizeBottomRight;
69     else if (mouseArea.contains(pol.at(1)))
70         return ResizeTopRight;
71     else if (mouseArea.contains(pol.at(3)))
72         return ResizeBottomLeft;
73     else if (top.intersects(mouseArea))
74         return ResizeTop;
75     else if (bottom.intersects(mouseArea))
76         return ResizeBottom;
77     else if (right.intersects(mouseArea))
78         return ResizeRight;
79     else if (left.intersects(mouseArea))
80         return ResizeLeft;
81     else if (rect().normalized().contains(pos))
82         return Move;
83     else
84         return NoAction;
85 }
86
87 void OnMonitorRectItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
88 {
89     event->accept();
90
91     m_lastPoint = event->scenePos();
92     m_oldRect = rect().normalized();
93     m_mode = getMode(event->pos());
94 }
95
96 void OnMonitorRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
97 {
98     /*if (event->buttons() != Qt::NoButton && (event->screenPos() - m_screenClickPoint).manhattanLength() < QApplication::startDragDistance()) {
99      *   event->accept();
100      *   return;
101     }*/
102
103     if (event->buttons() & Qt::LeftButton) {
104         QRectF r = rect().normalized();
105         QPointF p = pos();
106         QPointF mousePos = event->scenePos();
107         QPointF mousePosInRect = event->pos();
108         QPointF diff = mousePos - m_lastPoint;
109         m_lastPoint = mousePos;
110
111         switch (m_mode) {
112         case ResizeTopLeft:
113             if (mousePos.x() < p.x() + r.height() && mousePos.y() < p.y() + r.height()) {
114                 r.adjust(0, 0, -mousePosInRect.x(), -mousePosInRect.y());
115                 setPos(mousePos);
116                 m_modified = true;
117             }
118             break;
119         case ResizeTop:
120             if (mousePos.y() < p.y() + r.height()) {
121                 r.setBottom(r.height() - mousePosInRect.y());
122                 setPos(QPointF(p.x(), mousePos.y()));
123                 m_modified = true;
124             }
125             break;
126         case ResizeTopRight:
127             if (mousePos.x() > p.x() && mousePos.y() < p.y() + r.height()) {
128                 r.setBottomRight(QPointF(mousePosInRect.x(), r.bottom() - mousePosInRect.y()));
129                 setPos(QPointF(p.x(), mousePos.y()));
130                 m_modified = true;
131             }
132             break;
133         case ResizeLeft:
134             if (mousePos.x() < p.x() + r.width()) {
135                 r.setRight(r.width() - mousePosInRect.x());
136                 setPos(QPointF(mousePos.x(), p.y()));
137                 m_modified = true;
138             }
139             break;
140         case ResizeRight:
141             if (mousePos.x() > p.x()) {
142                 r.setRight(mousePosInRect.x());
143                 m_modified = true;
144             }
145             break;
146         case ResizeBottomLeft:
147             if (mousePos.x() < p.x() + r.width() && mousePos.y() > p.y()) {
148                 r.setBottomRight(QPointF(r.width() - mousePosInRect.x(), mousePosInRect.y()));
149                 setPos(QPointF(mousePos.x(), p.y()));
150                 m_modified = true;
151             }
152             break;
153         case ResizeBottom:
154             if (mousePos.y() > p.y()) {
155                 r.setBottom(mousePosInRect.y());
156                 m_modified = true;
157             }
158             break;
159         case ResizeBottomRight:
160             if (mousePos.x() > p.x() && mousePos.y() > p.y()) {
161                 r.setBottomRight(mousePosInRect);
162                 m_modified = true;
163             }
164             break;
165         case Move:
166             moveBy(diff.x(), diff.y());
167             m_modified = true;
168             break;
169         default:
170             break;
171         }
172
173         // Keep aspect ratio
174         if (event->modifiers() == Qt::ControlModifier) {
175             // compare to rect during mouse press: 
176             // if we subtract rect() we'll get a whole lot of flickering
177             // because of diffWidth > diffHeight changing all the time
178             int diffWidth = qAbs(r.width() - m_oldRect.width());
179             int diffHeight = qAbs(r.height() - m_oldRect.height());
180
181             if (diffHeight != 0 || diffWidth != 0) {
182                 if (diffWidth > diffHeight)
183                     r.setBottom(r.width() / m_dar);
184                 else
185                     r.setRight(r.height() * m_dar);
186
187                 // the rect's position changed
188                 if (p - pos() != QPointF()) {
189                     if (diffWidth > diffHeight) {
190                         if (m_mode != ResizeBottomLeft)
191 #if QT_VERSION >= 0x040600
192                             setY(p.y() - r.height() + rect().normalized().height());
193 #else
194                             setPos(x(), p.y() - r.height() + rect().normalized().height());
195 #endif
196                     } else {
197                         if (m_mode != ResizeTopRight)
198 #if QT_VERSION >= 0x040600
199                             setX(p.x() - r.width() + rect().normalized().width());
200 #else
201                             setPos(p.x() - r.width() + rect().normalized().width(), y());
202 #endif
203                     }
204                 }
205             }
206         }
207
208         setRect(r);
209     }
210
211     if (m_modified) {
212         event->accept();
213         if (KdenliveSettings::monitorscene_directupdate()) {
214             emit changed();
215             m_modified = false;
216         }
217     } else {
218         event->ignore();
219     }
220 }
221
222 void OnMonitorRectItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
223 {
224     if (m_modified) {
225         m_modified = false;
226         emit changed();
227     }
228     event->accept();
229 }
230
231 void OnMonitorRectItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
232 {
233     switch (getMode(event->pos())) {
234     case ResizeTopLeft:
235     case ResizeBottomRight:
236         setCursor(QCursor(Qt::SizeFDiagCursor));
237         break;
238     case ResizeTopRight:
239     case ResizeBottomLeft:
240         setCursor(QCursor(Qt::SizeBDiagCursor));
241         break;
242     case ResizeTop:
243     case ResizeBottom:
244         setCursor(QCursor(Qt::SizeVerCursor));
245         break;
246     case ResizeLeft:
247     case ResizeRight:
248         setCursor(QCursor(Qt::SizeHorCursor));
249         break;
250     case Move:
251         setCursor(QCursor(Qt::OpenHandCursor));
252         break;
253     default:
254         unsetCursor();
255         break;
256     }
257 }
258
259 void OnMonitorRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
260 {
261     Q_UNUSED(widget);
262
263     painter->setPen(pen());
264     painter->drawRect(option->rect);
265
266     if (isEnabled()) {
267         double handleSize = 6 / painter->matrix().m11();
268         double halfHandleSize = handleSize / 2;
269         painter->fillRect(-halfHandleSize, -halfHandleSize, handleSize, handleSize, QColor(Qt::yellow));
270         painter->fillRect(option->rect.width() - halfHandleSize, -halfHandleSize, handleSize, handleSize, QColor(Qt::yellow));
271         painter->fillRect(option->rect.width() - halfHandleSize, option->rect.height() - halfHandleSize, handleSize, handleSize, QColor(Qt::yellow));
272         painter->fillRect(-halfHandleSize, option->rect.height() - halfHandleSize, handleSize, handleSize, QColor(Qt::yellow));
273     }
274 }
275
276 bool OnMonitorRectItem::getView()
277 {
278     if (m_view)
279         return true;
280
281     if (scene() && scene()->views().count()) {
282         m_view = scene()->views()[0];
283         return true;
284     } else {
285         return false;
286     }
287 }
288
289 #include "onmonitorrectitem.moc"