/* * Patchbay Canvas engine using QGraphicsView/Scene * Copyright (C) 2010-2012 Filipe Coelho * * 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 2 of the License, or * 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. * * For a full copy of the GNU General Public License see the COPYING file */ #include "patchscene.h" #include #include #include #include #include #include #include "patchcanvas.h" #include "canvasbox.h" using namespace PatchCanvas; PatchScene::PatchScene(QObject* parent, QGraphicsView* view) : QGraphicsScene(parent) { m_ctrl_down = false; m_mouse_down_init = false; m_mouse_rubberband = false; m_rubberband = addRect(QRectF(0, 0, 0, 0)); m_rubberband->setZValue(-1); m_rubberband->hide(); m_rubberband_selection = false; m_rubberband_orig_point = QPointF(0, 0); m_view = view; if (! m_view) qFatal("PatchCanvas::PatchScene() - invalid view"); } void PatchScene::fixScaleFactor() { qreal scale = m_view->transform().m11(); if (scale > 3.0) { m_view->resetTransform(); m_view->scale(3.0, 3.0); } else if (scale < 0.2) { m_view->resetTransform(); m_view->scale(0.2, 0.2); } emit scaleChanged(m_view->transform().m11()); } void PatchScene::updateTheme() { setBackgroundBrush(canvas.theme->canvas_bg); m_rubberband->setPen(canvas.theme->rubberband_pen); m_rubberband->setBrush(canvas.theme->rubberband_brush); } void PatchScene::zoom_fit() { qreal min_x, min_y, max_x, max_y; bool first_value = true; QList items_list = items(); if (items_list.count() > 0) { foreach (const QGraphicsItem* item, items_list) { if (item && item->isVisible() and item->type() == CanvasBoxType) { QPointF pos = item->scenePos(); QRectF rect = item->boundingRect(); if (first_value) min_x = pos.x(); else if (pos.x() < min_x) min_x = pos.x(); if (first_value) min_y = pos.y(); else if (pos.y() < min_y) min_y = pos.y(); if (first_value) max_x = pos.x()+rect.width(); else if (pos.x()+rect.width() > max_x) max_x = pos.x()+rect.width(); if (first_value) max_y = pos.y()+rect.height(); else if (pos.y()+rect.height() > max_y) max_y = pos.y()+rect.height(); first_value = false; } } if (first_value == false) { m_view->fitInView(min_x, min_y, abs(max_x-min_x), abs(max_y-min_y), Qt::KeepAspectRatio); fixScaleFactor(); } } } void PatchScene::zoom_in() { if (m_view->transform().m11() < 3.0) m_view->scale(1.2, 1.2); emit scaleChanged(m_view->transform().m11()); } void PatchScene::zoom_out() { if (m_view->transform().m11() > 0.2) m_view->scale(0.8, 0.8); emit scaleChanged(m_view->transform().m11()); } void PatchScene::zoom_reset() { m_view->resetTransform(); emit scaleChanged(1.0); } void PatchScene::keyPressEvent(QKeyEvent* event) { if (! m_view) return event->ignore(); if (event->key() == Qt::Key_Control) { m_ctrl_down = true; } else if (event->key() == Qt::Key_Home) { zoom_fit(); return event->accept(); } else if (m_ctrl_down) { if (event->key() == Qt::Key_Plus) { zoom_in(); return event->accept(); } else if (event->key() == Qt::Key_Minus) { zoom_out(); return event->accept(); } else if (event->key() == Qt::Key_1) { zoom_reset(); return event->accept(); } } QGraphicsScene::keyPressEvent(event); } void PatchScene::keyReleaseEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Control) m_ctrl_down = false; QGraphicsScene::keyReleaseEvent(event); } void PatchScene::mousePressEvent(QGraphicsSceneMouseEvent* event) { m_mouse_down_init = (event->button() == Qt::LeftButton); m_mouse_rubberband = false; QGraphicsScene::mousePressEvent(event); } void PatchScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (m_mouse_down_init) { m_mouse_down_init = false; m_mouse_rubberband = (selectedItems().count() == 0); } if (m_mouse_rubberband) { if (m_rubberband_selection == false) { m_rubberband->show(); m_rubberband_selection = true; m_rubberband_orig_point = event->scenePos(); } int x, y; QPointF pos = event->scenePos(); if (pos.x() > m_rubberband_orig_point.x()) x = m_rubberband_orig_point.x(); else x = pos.x(); if (pos.y() > m_rubberband_orig_point.y()) y = m_rubberband_orig_point.y(); else y = pos.y(); m_rubberband->setRect(x, y, abs(pos.x()-m_rubberband_orig_point.x()), abs(pos.y()-m_rubberband_orig_point.y())); return event->accept(); } QGraphicsScene::mouseMoveEvent(event); } void PatchScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { if (m_rubberband_selection) { QList items_list = items(); if (items_list.count() > 0) { foreach (QGraphicsItem* item, items_list) { if (item && item->isVisible() && item->type() == CanvasBoxType) { QRectF item_rect = item->sceneBoundingRect(); QPointF item_top_left = QPointF(item_rect.x(), item_rect.y()); QPointF item_bottom_right = QPointF(item_rect.x()+item_rect.width(), item_rect.y()+item_rect.height()); if (m_rubberband->contains(item_top_left) && m_rubberband->contains(item_bottom_right)) item->setSelected(true); } } m_rubberband->hide(); m_rubberband->setRect(0, 0, 0, 0); m_rubberband_selection = false; } } else { QList items_list = selectedItems(); foreach (QGraphicsItem* item, items_list) { if (item && item->isVisible() && item->type() == CanvasBoxType) { CanvasBox* citem = (CanvasBox*)item; citem->checkItemPos(); emit sceneGroupMoved(citem->getGroupId(), citem->getSplittedMode(), citem->scenePos()); } } if (items_list.count() > 1) canvas.scene->update(); } m_mouse_down_init = false; m_mouse_rubberband = false; QGraphicsScene::mouseReleaseEvent(event); } void PatchScene::wheelEvent(QGraphicsSceneWheelEvent* event) { if (! m_view) return event->ignore(); if (m_ctrl_down) { double factor = std::pow(1.41, (event->delta()/240.0)); m_view->scale(factor, factor); fixScaleFactor(); return event->accept(); } QGraphicsScene::wheelEvent(event); }