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