From aa0fd185d9895942ee2bc46b76110beba51d527d Mon Sep 17 00:00:00 2001 From: Till Theato Date: Sat, 7 Aug 2010 21:55:42 +0000 Subject: [PATCH] On-Monitor effects: - Implement resizing (on the monitor scene) - Fix crash when closing Kdenlive (still crashes when monitor scene is open): http://kdenlive.org/mantis/view.php?id=1734 svn path=/trunk/kdenlive/; revision=4685 --- src/geometrywidget.cpp | 5 +- src/mainwindow.cpp | 2 +- src/monitor.cpp | 13 ++- src/monitor.h | 1 + src/monitorscene.cpp | 205 ++++++++++++++++++++++++++++++++++++++--- src/monitorscene.h | 11 ++- 6 files changed, 218 insertions(+), 19 deletions(-) diff --git a/src/geometrywidget.cpp b/src/geometrywidget.cpp index db965cb3..9e7dc29a 100644 --- a/src/geometrywidget.cpp +++ b/src/geometrywidget.cpp @@ -23,6 +23,7 @@ #include "renderer.h" #include "monitorscene.h" +#include #include #include @@ -50,8 +51,8 @@ GeometryWidget::GeometryWidget(Monitor* monitor, int clipPos, QWidget* parent ): GeometryWidget::~GeometryWidget() { - m_monitor->slotEffectScene(false); - m_scene->disconnect(this); + if (m_monitor) + m_monitor->slotEffectScene(false); delete m_rect; delete m_geometry; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ce8ea7ee..2d26459d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -467,13 +467,13 @@ void MainWindow::queryQuit() if (queryClose()) { if (m_projectMonitor) m_projectMonitor->stop(); if (m_clipMonitor) m_clipMonitor->stop(); - delete m_effectStack; delete m_activeTimeline; #ifndef Q_WS_MAC // This sometimes causes crash on exit on OS X for some reason. delete m_projectMonitor; delete m_clipMonitor; #endif + delete m_effectStack; delete m_activeDocument; delete m_shortcutRemoveFocus; Mlt::Factory::close(); diff --git a/src/monitor.cpp b/src/monitor.cpp index 29e4772b..a39e7911 100644 --- a/src/monitor.cpp +++ b/src/monitor.cpp @@ -55,7 +55,8 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget m_isActive(false), m_scale(1), m_length(0), - m_dragStarted(false) + m_dragStarted(false), + m_delStage(false) { m_ui.setupUi(this); QVBoxLayout *layout = new QVBoxLayout; @@ -169,6 +170,7 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget m_effectScene = new MonitorScene(render); m_effectView = new QGraphicsView(m_effectScene, m_ui.video_frame); rendererBox->addWidget(m_effectView); + m_effectView->setMouseTracking(true); m_effectScene->setUp(); m_effectView->hide(); } @@ -178,12 +180,15 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget Monitor::~Monitor() { + m_delStage = true; delete m_ruler; delete m_timePos; delete m_overlay; + if (m_name == "project") { + delete m_effectView; + delete m_effectScene; + } delete m_monitorRefresh; - delete m_effectView; - delete m_effectScene; delete render; } @@ -834,7 +839,7 @@ QStringList Monitor::getZoneInfo() const void Monitor::slotEffectScene(bool show) { - if (m_name == "project") { + if (m_name == "project" && !m_delStage) { m_monitorRefresh->setVisible(!show); m_effectView->setVisible(show); if (show) diff --git a/src/monitor.h b/src/monitor.h index afdc611b..ecc2b750 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -129,6 +129,7 @@ private: QPoint m_DragStartPosition; MonitorScene *m_effectScene; QGraphicsView *m_effectView; + bool m_delStage; #ifdef Q_WS_MAC VideoGLWidget *m_glWidget; #endif diff --git a/src/monitorscene.cpp b/src/monitorscene.cpp index d0a51202..57fdefdd 100644 --- a/src/monitorscene.cpp +++ b/src/monitorscene.cpp @@ -22,17 +22,18 @@ #include "renderer.h" #include "kdenlivesettings.h" +#include #include #include -#include +#include MonitorScene::MonitorScene(Render *renderer, QObject* parent) : QGraphicsScene(parent), - m_renderer(renderer) -{ -} - -void MonitorScene::setUp() + m_renderer(renderer), + m_view(NULL), + m_selectedItem(NULL), + m_resizeMode(NoResize), + m_clickPoint(0, 0) { setBackgroundBrush(QBrush(QColor(KdenliveSettings::window_background().name()))); @@ -57,28 +58,210 @@ void MonitorScene::setUp() connect(m_renderer, SIGNAL(rendererPosition(int)), this, SLOT(slotUpdateBackground())); connect(m_renderer, SIGNAL(frameUpdated(int)), this, SLOT(slotUpdateBackground())); +} + +void MonitorScene::setUp() +{ + if (views().count() > 0) + m_view = views().at(0); + else + m_view = NULL; slotUpdateBackground(); } void MonitorScene::slotUpdateBackground() { - if (views().count() > 0 && views().at(0)->isVisible()) { + if (m_view && m_view->isVisible()) { if (m_lastUpdate.elapsed() > 200) { m_background->setPixmap(QPixmap::fromImage(m_renderer->extractFrame(m_renderer->seekFramePosition()))); - views().at(0)->fitInView(m_frameBorder, Qt::KeepAspectRatio); - views().at(0)->centerOn(m_frameBorder); + m_view->fitInView(m_frameBorder, Qt::KeepAspectRatio); + m_view->centerOn(m_frameBorder); m_lastUpdate.start(); } } } -void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent* event) +resizeModes MonitorScene::getResizeMode(QGraphicsRectItem *item, QPoint pos) +{ + if(!m_view) + return NoResize; + + QRectF rect = item->rect().normalized(); + // Item mapped coordinates + QPolygon pol = item->deviceTransform(m_view->viewportTransform()).map(rect).toPolygon(); + QPainterPath top(pol.point(0)); + top.lineTo(pol.point(1)); + QPainterPath bottom(pol.point(2)); + bottom.lineTo(pol.point(3)); + QPainterPath left(pol.point(0)); + left.lineTo(pol.point(3)); + QPainterPath right(pol.point(1)); + right.lineTo(pol.point(2)); + + QPainterPath mouseArea; + mouseArea.addRect(pos.x() - 4, pos.y() - 4, 8, 8); + + // Check for collisions between the mouse and the borders + if (mouseArea.contains(pol.point(0))) + return TopLeft; + else if (mouseArea.contains(pol.point(2))) + return BottomRight; + else if (mouseArea.contains(pol.point(1))) + return TopRight; + else if (mouseArea.contains(pol.point(3))) + return BottomLeft; + else if (top.intersects(mouseArea)) + return Top; + else if (bottom.intersects(mouseArea)) + return Bottom; + else if (right.intersects(mouseArea)) + return Right; + else if (left.intersects(mouseArea)) + return Left; + else + return NoResize; +} + +void MonitorScene::mousePressEvent(QGraphicsSceneMouseEvent *event) { + m_resizeMode = NoResize; + m_selectedItem = NULL; + + m_clickPoint = event->scenePos(); + QList itemList = items(QRectF(m_clickPoint - QPoint(4, 4), QSizeF(4, 4)).toRect()); + + for (int i = 0; i < itemList.count(); ++i) { + if (itemList.at(i)->zValue() >= 0 && itemList.at(i)->flags() & QGraphicsItem::ItemIsMovable) { + m_selectedItem = itemList.at(i); + // Rect + if (itemList.at(i)->type() == 3) { + m_resizeMode = getResizeMode((QGraphicsRectItem*)m_selectedItem, m_view->mapFromScene(m_clickPoint)); + break; + } + } + } + QGraphicsScene::mousePressEvent(event); } +void MonitorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF mousePos = event->scenePos(); + + if (m_selectedItem && event->buttons() & Qt::LeftButton) { + // Rect + if (m_selectedItem->type() == 3) { + QGraphicsRectItem *item = static_cast (m_selectedItem); + QRectF rect = item->rect().normalized(); + QPointF pos = item->pos(); + QPointF mousePosInRect = item->mapFromScene(mousePos); + switch (m_resizeMode) { + case TopLeft: + if (mousePos.x() < pos.x() + rect.height() && mousePos.y() < pos.y() + rect.height()) { + item->setRect(rect.adjusted(0, 0, -mousePosInRect.x(), -mousePosInRect.y())); + item->setPos(mousePos); + } + break; + case Top: + if (mousePos.y() < pos.y() + rect.height()) { + rect.setBottom(rect.height() - mousePosInRect.y()); + item->setRect(rect); + item->setPos(QPointF(pos.x(), mousePos.y())); + } + break; + case TopRight: + if (mousePos.x() > pos.x() && mousePos.y() < pos.y() + rect.height()) { + rect.setBottomRight(QPointF(mousePosInRect.x(), rect.bottom() - mousePosInRect.y())); + item->setRect(rect); + item->setPos(QPointF(pos.x(), mousePos.y())); + } + break; + case Left: + if (mousePos.x() < pos.x() + rect.width()) { + rect.setRight(rect.width() - mousePosInRect.x()); + item->setRect(rect); + item->setPos(QPointF(mousePos.x(), pos.y())); + } + break; + case Right: + if (mousePos.x() > pos.x()) { + rect.setRight(mousePosInRect.x()); + item->setRect(rect); + } + break; + case BottomLeft: + if (mousePos.x() < pos.x() + rect.width() && mousePos.y() > pos.y()) { + rect.setBottomRight(QPointF(rect.width() - mousePosInRect.x(), mousePosInRect.y())); + item->setRect(rect); + item->setPos(QPointF(mousePos.x(), pos.y())); + } + break; + case Bottom: + if (mousePos.y() > pos.y()) { + rect.setBottom(mousePosInRect.y()); + item->setRect(rect); + } + break; + case BottomRight: + if (mousePos.x() > pos.x() && mousePos.y() > pos.y()) { + rect.setBottomRight(mousePosInRect); + item->setRect(rect); + } + break; + default: + QPointF diff = mousePos - m_clickPoint; + m_clickPoint = mousePos; + item->moveBy(diff.x(), diff.y()); + break; + } + } + } else { + mousePos -= QPoint(4, 4); + bool itemFound = false; + QList itemList = items(QRectF(mousePos, QSizeF(4, 4)).toRect()); + + foreach (const QGraphicsItem* item, itemList) { + if (item->zValue() >= 0 && item->flags() &QGraphicsItem::ItemIsMovable) { + // Rect + if (item->type() == 3) { + if (m_view == NULL) + continue; + + itemFound = true; + + switch (getResizeMode((QGraphicsRectItem*)item, m_view->mapFromScene(event->scenePos()))) { + case TopLeft: + case BottomRight: + m_view->setCursor(Qt::SizeFDiagCursor); + break; + case TopRight: + case BottomLeft: + m_view->setCursor(Qt::SizeBDiagCursor); + break; + case Top: + case Bottom: + m_view->setCursor(Qt::SizeVerCursor); + break; + case Left: + case Right: + m_view->setCursor(Qt::SizeHorCursor); + break; + default: + m_view->setCursor(Qt::OpenHandCursor); + } + break; + } + } + } + + if (!itemFound && m_view != NULL) + m_view->setCursor(Qt::ArrowCursor); + + QGraphicsScene::mouseMoveEvent(event); + } +} -void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) +void MonitorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QGraphicsScene::mouseReleaseEvent(event); emit actionFinished(); diff --git a/src/monitorscene.h b/src/monitorscene.h index de9dbb0e..fe39c68f 100644 --- a/src/monitorscene.h +++ b/src/monitorscene.h @@ -24,9 +24,10 @@ #include #include -class QGraphicsPixmapItem; class Render; +enum resizeModes { NoResize, TopLeft, BottomLeft, TopRight, BottomRight, Left, Right, Top, Bottom }; + class MonitorScene : public QGraphicsScene { Q_OBJECT @@ -36,16 +37,24 @@ public: protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); public slots: void slotUpdateBackground(); private: + resizeModes getResizeMode(QGraphicsRectItem *item, QPoint pos); + Render *m_renderer; QGraphicsPixmapItem *m_background; QGraphicsRectItem *m_frameBorder; QTime m_lastUpdate; + QGraphicsView *m_view; + QGraphicsItem *m_selectedItem; + resizeModes m_resizeMode; + QPointF m_clickPoint; + signals: void actionFinished(); }; -- 2.39.2