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