1 /***************************************************************************
2 * Copyright (C) 2010 by Till Theato (root@ttill.de) *
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. *
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. *
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 ***************************************************************************/
20 #include "onmonitorcornersitem.h"
21 #include "kdenlivesettings.h"
25 #include <QGraphicsSceneMouseEvent>
27 #include <QStyleOptionGraphicsItem>
29 #include <QGraphicsView>
31 OnMonitorCornersItem::OnMonitorCornersItem(QGraphicsItem* parent) :
32 QGraphicsPolygonItem(parent)
34 , m_selectedCorner(-1)
38 setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
40 QPen framepen(Qt::SolidLine);
41 framepen.setColor(Qt::yellow);
43 setBrush(Qt::NoBrush);
44 setAcceptHoverEvents(true);
47 OnMonitorCornersItem::cornersActions OnMonitorCornersItem::getMode(QPointF pos, int *corner)
50 if (polygon().count() != 4)
53 QPainterPath mouseArea;
56 size /= m_view->matrix().m11();
57 mouseArea.addRect(pos.x() - size / 2, pos.y() - size / 2, size, size);
58 for (int i = 0; i < 4; ++i) {
59 if (mouseArea.contains(polygon().at(i))) {
64 if (KdenliveSettings::onmonitoreffects_cornersshowcontrols()) {
65 if (mouseArea.contains(getCentroid()))
69 for (int i = 0; i < 4; ++i) {
71 if (mouseArea.contains(QLineF(polygon().at(i), polygon().at(j)).pointAt(.5))) {
81 void OnMonitorCornersItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
83 m_mode = getMode(event->pos(), &m_selectedCorner);
84 m_lastPoint = event->scenePos();
86 if (m_mode == NoAction)
90 void OnMonitorCornersItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
92 /*if (event->buttons() != Qt::NoButton && (event->screenPos() - m_screenClickPoint).manhattanLength() < QApplication::startDragDistance()) {
97 if (event->buttons() & Qt::LeftButton) {
98 QPointF mousePos = mapFromScene(event->scenePos());
99 QPolygonF p = polygon();
102 p.replace(m_selectedCorner, mousePos);
106 p.translate(mousePos - m_lastPoint);
110 p[m_selectedCorner] += mousePos - m_lastPoint;
111 p[(m_selectedCorner + 1) % 4] += mousePos - m_lastPoint;
117 m_lastPoint = mousePos;
123 if (KdenliveSettings::monitorscene_directupdate()) {
132 void OnMonitorCornersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
141 void OnMonitorCornersItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
144 switch (getMode(event->pos(), &corner)) {
149 setCursor(QCursor(Qt::SizeAllCursor));
152 setCursor(QCursor(Qt::OpenHandCursor));
157 void OnMonitorCornersItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
159 painter->setPen(QPen(Qt::yellow, 1, Qt::SolidLine));
161 if (KdenliveSettings::onmonitoreffects_cornersshowlines())
162 QGraphicsPolygonItem::paint(painter, option, widget);
164 if (polygon().count() != 4)
167 double baseSize = 1 / painter->worldTransform().m11();
168 painter->setRenderHint(QPainter::Antialiasing);
169 painter->setBrush(QBrush(isEnabled() ? Qt::yellow : Qt::red));
170 double handleSize = 4 * baseSize;
171 for (int i = 0; i < 4; ++i)
172 painter->drawEllipse(polygon().at(i), handleSize, handleSize);
174 if (KdenliveSettings::onmonitoreffects_cornersshowcontrols() && isEnabled()) {
175 painter->setPen(QPen(Qt::red, 2, Qt::SolidLine));
176 double toolSize = 6 * baseSize;
178 QPointF c = getCentroid();
179 painter->drawLine(QLineF(c - QPointF(toolSize, toolSize), c + QPointF(toolSize, toolSize)));
180 painter->drawLine(QLineF(c - QPointF(-toolSize, toolSize), c + QPointF(-toolSize, toolSize)));
182 // move side tools (2 corners at once)
184 for (int i = 0; i < 4; ++i) {
186 QPointF m = QLineF(polygon().at(i), polygon().at(j)).pointAt(.5);
187 painter->drawRect(QRectF(-toolSize / 2., -toolSize / 2., toolSize, toolSize).translated(m));
192 QPointF OnMonitorCornersItem::getCentroid()
194 QList <QPointF> p = sortedClockwise();
197 * See: http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
202 for (i = 0; i < 4; ++i) {
204 A += p[j].x() * p[i].y() - p[i].x() * p[j].y();
209 double x = 0, y = 0, f;
210 for (i = 0; i < 4; ++i) {
212 f = (p[i].x() * p[j].y() - p[j].x() * p[i].y());
213 x += f * (p[i].x() + p[j].x());
214 y += f * (p[i].y() + p[j].y());
218 return QPointF(x, y);
221 QList <QPointF> OnMonitorCornersItem::sortedClockwise()
223 QList <QPointF> points = polygon().toList();
224 QPointF& a = points[0];
225 QPointF& b = points[1];
226 QPointF& c = points[2];
227 QPointF& d = points[3];
230 * http://stackoverflow.com/questions/242404/sort-four-points-in-clockwise-order
233 double abc = a.x() * b.y() - a.y() * b.x() + b.x() * c.y() - b.y() * c.x() + c.x() * a.y() - c.y() * a.x();
235 double acd = a.x() * c.y() - a.y() * c.x() + c.x() * d.y() - c.y() * d.x() + d.x() * a.y() - d.y() * a.x();
239 double abd = a.x() * b.y() - a.y() * b.x() + b.x() * d.y() - b.y() * d.x() + d.x() * a.y() - d.y() * a.x();
247 double acd = a.x() * c.y() - a.y() * c.x() + c.x() * d.y() - c.y() * d.x() + d.x() * a.y() - d.y() * a.x();
249 double abd = a.x() * b.y() - a.y() * b.x() + b.x() * d.y() - b.y() * d.x() + d.x() * a.y() - d.y() * a.x();
262 bool OnMonitorCornersItem::getView()
267 if (scene() && scene()->views().count()) {
268 m_view = scene()->views()[0];
275 #include "onmonitorcornersitem.moc"