diff --git a/app/widget/nodeview/CMakeLists.txt b/app/widget/nodeview/CMakeLists.txt index 00e78e7db..ee13270b6 100644 --- a/app/widget/nodeview/CMakeLists.txt +++ b/app/widget/nodeview/CMakeLists.txt @@ -23,6 +23,8 @@ set(OLIVE_SOURCES widget/nodeview/nodeviewedge.h widget/nodeview/nodeviewitem.cpp widget/nodeview/nodeviewitem.h + widget/nodeview/nodeviewminimap.cpp + widget/nodeview/nodeviewminimap.h widget/nodeview/nodeviewscene.cpp widget/nodeview/nodeviewscene.h widget/nodeview/nodeviewundo.cpp diff --git a/app/widget/nodeview/nodeview.cpp b/app/widget/nodeview/nodeview.cpp index 1b97a4c23..500d04684 100644 --- a/app/widget/nodeview/nodeview.cpp +++ b/app/widget/nodeview/nodeview.cpp @@ -64,6 +64,13 @@ NodeView::NodeView(QWidget *parent) : UpdateSceneBoundingRect(); connect(&scene_, &QGraphicsScene::changed, this, &NodeView::UpdateSceneBoundingRect); + + minimap_ = new NodeViewMiniMap(&scene_, this); + minimap_->show(); + connect(minimap_, &NodeViewMiniMap::Resized, this, &NodeView::RepositionMiniMap); + connect(minimap_, &NodeViewMiniMap::MoveToScenePoint, this, &NodeView::MoveToScenePoint); + connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &NodeView::UpdateViewportOnMiniMap); + connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &NodeView::UpdateViewportOnMiniMap); } NodeView::~NodeView() @@ -881,6 +888,13 @@ void NodeView::mouseReleaseEvent(QMouseEvent *event) super::mouseReleaseEvent(event); } +void NodeView::resizeEvent(QResizeEvent *event) +{ + super::resizeEvent(event); + + RepositionMiniMap(); +} + void NodeView::UpdateSelectionCache() { QVector current_selection = scene_.GetSelectedNodes(); @@ -1204,6 +1218,40 @@ void NodeView::CenterOnItemsBoundingRect() centerOn(scene_.itemsBoundingRect().center()); } +void NodeView::RepositionMiniMap() +{ + if (minimap_->isVisible()) { + int margin = fontMetrics().height(); + + int w = width() - minimap_->width() - margin; + int h = height() - minimap_->height() - margin; + + if (verticalScrollBar()->isVisible()) { + w -= verticalScrollBar()->width(); + } + + if (horizontalScrollBar()->isVisible()) { + h -= horizontalScrollBar()->height(); + } + + minimap_->move(w, h); + + UpdateViewportOnMiniMap(); + } +} + +void NodeView::UpdateViewportOnMiniMap() +{ + if (minimap_->isVisible()) { + minimap_->SetViewportRect(mapToScene(viewport()->rect())); + } +} + +void NodeView::MoveToScenePoint(const QPointF &pos) +{ + centerOn(pos); +} + void NodeView::AttachNodesToCursor(const QVector &nodes) { QVector items(nodes.size()); diff --git a/app/widget/nodeview/nodeview.h b/app/widget/nodeview/nodeview.h index 1ba86998c..6c02ae837 100644 --- a/app/widget/nodeview/nodeview.h +++ b/app/widget/nodeview/nodeview.h @@ -27,6 +27,7 @@ #include "node/graph.h" #include "node/nodecopypaste.h" #include "nodeviewedge.h" +#include "nodeviewminimap.h" #include "nodeviewscene.h" #include "widget/handmovableview/handmovableview.h" @@ -89,6 +90,8 @@ protected: virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void mouseReleaseEvent(QMouseEvent* event) override; + virtual void resizeEvent(QResizeEvent *event) override; + virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos) override; virtual bool event(QEvent *event) override; @@ -135,6 +138,8 @@ private: }; + NodeViewMiniMap *minimap_; + NodeGraph* graph_; struct AttachedItem { @@ -257,6 +262,12 @@ private slots: void CenterOnItemsBoundingRect(); + void RepositionMiniMap(); + + void UpdateViewportOnMiniMap(); + + void MoveToScenePoint(const QPointF &pos); + }; } diff --git a/app/widget/nodeview/nodeviewminimap.cpp b/app/widget/nodeview/nodeviewminimap.cpp new file mode 100644 index 000000000..9be32452a --- /dev/null +++ b/app/widget/nodeview/nodeviewminimap.cpp @@ -0,0 +1,141 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "nodeviewminimap.h" + +#include + +namespace olive { + +#define super QGraphicsView + +NodeViewMiniMap::NodeViewMiniMap(NodeViewScene *scene, QWidget *parent) : + super(parent), + resizing_(false) +{ + connect(scene, &QGraphicsScene::sceneRectChanged, this, &NodeViewMiniMap::SceneChanged); + setScene(scene); + + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setViewportUpdateMode(FullViewportUpdate); + + QMetaObject::invokeMethod(this, &NodeViewMiniMap::SetDefaultSize, Qt::QueuedConnection); + + resize_triangle_sz_ = fontMetrics().height() / 2; +} + +void NodeViewMiniMap::SetViewportRect(const QPolygonF &rect) +{ + viewport_rect_ = rect; + + viewport()->update(); +} + +void NodeViewMiniMap::drawForeground(QPainter *painter, const QRectF &rect) +{ + super::drawForeground(painter, rect); + + QColor viewport_color = palette().text().color(); + + // Draw resize triangle + painter->save(); + painter->resetTransform(); + + QPointF triangle[3] = {QPointF(0, 0), QPointF(resize_triangle_sz_, 0), QPointF(0, resize_triangle_sz_)}; + painter->setBrush(viewport_color); + painter->setPen(viewport_color); + painter->drawPolygon(triangle, 3); + + painter->restore(); + + // Draw viewport rectangle + viewport_color.setAlphaF(0.25); + painter->setBrush(viewport_color); + + painter->drawPolygon(viewport_rect_); +} + +void NodeViewMiniMap::resizeEvent(QResizeEvent *event) +{ + super::resizeEvent(event); + + emit Resized(); + + SceneChanged(sceneRect()); +} + +void NodeViewMiniMap::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (event->pos().x() <= resize_triangle_sz_ && event->pos().y() <= resize_triangle_sz_) { + // Resizing! + resizing_ = true; + resize_anchor_ = QCursor::pos(); + } else { + EmitMoveSignal(event); + } + } +} + +void NodeViewMiniMap::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + if (resizing_) { + QPointF movement = QCursor::pos() - resize_anchor_; + resize(QSize(width() - movement.x(), height() - movement.y())); + resize_anchor_ = QCursor::pos(); + } else { + EmitMoveSignal(event); + } + } +} + +void NodeViewMiniMap::mouseReleaseEvent(QMouseEvent *event) +{ + resizing_ = false; +} + +void NodeViewMiniMap::SceneChanged(const QRectF &bounding) +{ + double x_scale = double(this->width()) / bounding.width(); + double y_scale = double(this->height()) / bounding.height(); + + double min_scale = qMin(x_scale, y_scale); + + QTransform transform; + transform.scale(min_scale, min_scale); + + setTransform(transform); +} + +void NodeViewMiniMap::SetDefaultSize() +{ + if (parentWidget()) { + resize(parentWidget()->width()/4, parentWidget()->height()/4); + } +} + +void NodeViewMiniMap::EmitMoveSignal(QMouseEvent *event) +{ + emit MoveToScenePoint(mapToScene(event->pos())); +} + +} diff --git a/app/widget/nodeview/nodeviewminimap.h b/app/widget/nodeview/nodeviewminimap.h new file mode 100644 index 000000000..a63db1993 --- /dev/null +++ b/app/widget/nodeview/nodeviewminimap.h @@ -0,0 +1,74 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef NODEVIEWMINIMAP_H +#define NODEVIEWMINIMAP_H + +#include + +#include "nodeviewscene.h" + +namespace olive { + +class NodeViewMiniMap : public QGraphicsView +{ + Q_OBJECT +public: + NodeViewMiniMap(NodeViewScene *scene, QWidget *parent = nullptr); + +public slots: + void SetViewportRect(const QPolygonF &rect); + +signals: + void Resized(); + + void MoveToScenePoint(const QPointF &pos); + +protected: + virtual void drawForeground(QPainter *painter, const QRectF &rect) override; + + virtual void resizeEvent(QResizeEvent *event) override; + + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void mouseMoveEvent(QMouseEvent *event) override; + virtual void mouseReleaseEvent(QMouseEvent *event) override; + virtual void mouseDoubleClickEvent(QMouseEvent *event) override{} + +private slots: + void SceneChanged(const QRectF &bounding); + + void SetDefaultSize(); + +private: + void EmitMoveSignal(QMouseEvent *event); + + int resize_triangle_sz_; + + QPolygonF viewport_rect_; + + bool resizing_; + + QPoint resize_anchor_; + +}; + +} + +#endif // NODEVIEWMINIMAP_H