/* * Copyright (c) 2012 Mateusz Piękos * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ /* * Copyright (c) 2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/QtUI/Whiteboard/GView.h> #include <Swift/QtUI/QtSwiftUtil.h> namespace Swift { GView::GView(QGraphicsScene* scene, QWidget* parent) : QGraphicsView(scene, parent), zValue(0), mousePressed(false), brush(QColor(Qt::white)), defaultBrush(QColor(Qt::white)), mode(GView::Select), lastItem(nullptr), selectionRect(nullptr), textDialog(nullptr) { } void GView::setLineWidth(int i) { pen.setWidth(i); if (selectionRect) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); lastItemChanged(item, items_.indexOf(item)+1, Update); } else { defaultPen.setWidth(i); } } void GView::setLineColor(QColor color) { pen.setColor(color); if (selectionRect) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); lastItemChanged(item, items_.indexOf(item)+1, Update); } else { defaultPen.setColor(color); } lineColorChanged(color); } QColor GView::getLineColor() { return pen.color(); } void GView::setBrushColor(QColor color) { brush.setColor(color); if (selectionRect) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); changePenAndBrush(selectionRect->data(1).value<QGraphicsItem*>(), pen, brush); lastItemChanged(item, items_.indexOf(item)+1, Update); } else { defaultBrush.setColor(color); } brushColorChanged(color); } QColor GView::getBrushColor() { return brush.color(); } void GView::setMode(Mode mode) { this->mode = mode; lastItem = nullptr; deselect(); } void GView::addItem(QGraphicsItem* item, QString id, int pos) { itemsMap_.insert(id, item); if (pos > items_.size()) { item->setZValue(zValue++); scene()->addItem(item); items_.append(item); } else { QGraphicsItem* temp = items_.at(pos-1); item->setZValue(temp->zValue()); scene()->addItem(item); item->stackBefore(temp); items_.insert(pos-1, item); } } void GView::clear() { scene()->clear(); items_.clear(); itemsMap_.clear(); lastItem = nullptr; selectionRect = nullptr; brush = QBrush(QColor(Qt::white)); defaultBrush = QBrush(QColor(Qt::white)); pen = QPen(); pen.setWidth(1); defaultPen = pen; lineWidthChanged(1); lineColorChanged(pen.color()); brushColorChanged(brush.color()); } QGraphicsItem* GView::getItem(QString id) { return itemsMap_.value(id); } void GView::deleteItem(QString id) { deselect(id); QGraphicsItem* item = itemsMap_.value(id); items_.removeOne(item); itemsMap_.remove(id); scene()->removeItem(item); delete item; } QString GView::getNewID() { return P2QSTRING(idGenerator.generateID()); } void GView::mouseMoveEvent(QMouseEvent* event) { if (!mousePressed) { return; } if (mode == Line) { QGraphicsLineItem* item = qgraphicsitem_cast<QGraphicsLineItem*>(lastItem); if(item != nullptr) { QLineF line = item->line(); line.setP1(this->mapToScene(event->pos())); item->setLine(line); } } else if (mode == Rect) { QGraphicsRectItem* item = qgraphicsitem_cast<QGraphicsRectItem*>(lastItem); if (item != nullptr) { QPointF beginPoint = item->data(0).toPointF(); QPointF newPoint = this->mapToScene(event->pos()); QRectF rect = item->rect(); if (beginPoint.x() <= newPoint.x() && beginPoint.y() <= newPoint.y()) { rect.setTopLeft(beginPoint); rect.setBottomRight(newPoint); } else if (beginPoint.x() > newPoint.x() && beginPoint.y() <= newPoint.y()) { rect.setTopRight(beginPoint); rect.setBottomLeft(newPoint); } else if (beginPoint.x() <= newPoint.x() && beginPoint.y() > newPoint.y()) { rect.setBottomLeft(beginPoint); rect.setTopRight(newPoint); } else if (beginPoint.x() > newPoint.x() && beginPoint.y() > newPoint.y()) { rect.setBottomRight(beginPoint); rect.setTopLeft(newPoint); } item->setRect(rect); } } else if (mode == Circle) { QGraphicsEllipseItem* item = qgraphicsitem_cast<QGraphicsEllipseItem*>(lastItem); QPainterPath path; QPointF beginPoint = item->data(0).toPointF(); QPointF newPoint = this->mapToScene(event->pos()); QRectF rect = item->rect(); if (beginPoint.x() <= newPoint.x() && beginPoint.y() <= newPoint.y()) { rect.setTopLeft(beginPoint); rect.setBottomRight(newPoint); } else if (beginPoint.x() > newPoint.x() && beginPoint.y() <= newPoint.y()) { rect.setTopRight(beginPoint); rect.setBottomLeft(newPoint); } else if (beginPoint.x() <= newPoint.x() && beginPoint.y() > newPoint.y()) { rect.setBottomLeft(beginPoint); rect.setTopRight(newPoint); } else if (beginPoint.x() > newPoint.x() && beginPoint.y() > newPoint.y()) { rect.setBottomRight(beginPoint); rect.setTopLeft(newPoint); } item->setRect(rect); } else if (mode == HandLine) { FreehandLineItem* item = qgraphicsitem_cast<FreehandLineItem*>(lastItem); if (item != nullptr) { QPointF newPoint = this->mapToScene(event->pos()); item->lineTo(newPoint); } } else if (mode == Polygon) { QGraphicsPolygonItem* item = qgraphicsitem_cast<QGraphicsPolygonItem*>(lastItem); QPointF newPoint = this->mapToScene(event->pos()); QPolygonF polygon = item->polygon(); polygon.erase(polygon.end()-1); polygon.append(newPoint); item->setPolygon(polygon); } else if (mode == Select) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); if (item != nullptr) { QPainterPath path; QPointF beginPoint = selectionRect->data(0).toPointF(); QPointF newPoint = this->mapToScene(event->pos()); item->setPos(beginPoint + newPoint); selectionRect->setPos(beginPoint + newPoint); } } } void GView::mousePressEvent(QMouseEvent *event) { mousePressed = true; deselect(); if (mode == Line) { QPointF point = this->mapToScene(event->pos()); QGraphicsItem* item = scene()->addLine(point.x(), point.y(), point.x(), point.y(), pen); QString id = getNewID(); item->setZValue(10000000); item->setData(100, id); item->setData(101, items_.size()); lastItem = item; } else if (mode == Rect) { QPointF point = this->mapToScene(event->pos()); QGraphicsRectItem* item = scene()->addRect(point.x(), point.y(), 0, 0, pen, brush); QString id = getNewID(); item->setZValue(10000000); item->setData(0, point); item->setData(100, id); item->setData(101, items_.size()); lastItem = item; } else if (mode == Rubber) { QPointF point = this->mapToScene(event->pos()); int w = pen.width(); QRectF rect(point.x()-w, point.y()-w, w*2, w*2); QList<QGraphicsItem*> list = scene()->items(rect); if (!list.isEmpty()) { QGraphicsItem* item = scene()->items(rect).first(); QString id = item->data(100).toString(); int pos = items_.indexOf(item)+1; itemDeleted(id, pos); deleteItem(id); } } else if (mode == Circle) { QPointF point = this->mapToScene(event->pos()); QGraphicsEllipseItem* item = scene()->addEllipse(point.x(), point.y(), 0, 0, pen, brush); QString id = getNewID(); item->setZValue(10000000); item->setData(0, point); item->setData(100, id); item->setData(101, items_.size()); lastItem = item; } else if (mode == HandLine) { QPointF point = this->mapToScene(event->pos()); FreehandLineItem* item = new FreehandLineItem; QString id = getNewID(); item->setPen(pen); item->setStartPoint(point); item->setZValue(10000000); item->setData(100, id); item->setData(101, items_.size()); scene()->addItem(item); lastItem = item; } else if (mode == Text) { QPointF point = this->mapToScene(event->pos()); QGraphicsTextItem* item = scene()->addText(""); QString id = getNewID(); item->setData(100, id); item->setData(101, items_.size()); item->setDefaultTextColor(pen.color()); textDialog = new TextDialog(item, this); connect(textDialog, SIGNAL(accepted(QGraphicsTextItem*)), this, SLOT(handleTextItemModified(QGraphicsTextItem*))); textDialog->setAttribute(Qt::WA_DeleteOnClose); textDialog->show(); item->setPos(point); lastItem = item; } else if (mode == Polygon) { QPointF point = this->mapToScene(event->pos()); QGraphicsPolygonItem* item = dynamic_cast<QGraphicsPolygonItem*>(lastItem); if (item == nullptr) { QPolygonF polygon; polygon.append(point); polygon.append(point); item = scene()->addPolygon(polygon, pen, brush); QString id = getNewID(); item->setZValue(10000000); item->setData(100, id); item->setData(101, items_.size()); lastItem = item; } else { QPolygonF polygon; polygon = item->polygon(); polygon.append(point); item->setPolygon(polygon); } } else if (mode == Select) { QPointF point = this->mapToScene(event->pos()); int w = pen.width(); if (w == 0) { w = 1; } QRectF rect(point.x()-w, point.y()-w, w*2, w*2); QList<QGraphicsItem*> list = scene()->items(rect); if (!list.isEmpty()) { QPen pen; pen.setColor(QColor(Qt::gray)); pen.setStyle(Qt::DashLine); QGraphicsItem *item = scene()->items(rect).first(); selectionRect = scene()->addRect(item->boundingRect(), pen); selectionRect->setZValue(1000000); selectionRect->setData(0, item->pos()-point); selectionRect->setPos(item->pos()); QVariant var(QVariant::UserType); var.setValue(item); selectionRect->setData(1, var); setActualPenAndBrushFromItem(item); } } } void GView::mouseReleaseEvent(QMouseEvent* /*event*/) { mousePressed = false; QGraphicsPolygonItem* polygon = dynamic_cast<QGraphicsPolygonItem*>(lastItem); if (polygon && polygon->polygon().size() >= 3) { lastItemChanged(polygon, items_.indexOf(polygon)+1, Update); } else if (lastItem) { zValue++; lastItem->setZValue(zValue++); items_.append(lastItem); itemsMap_.insert(lastItem->data(100).toString(), lastItem); lastItemChanged(lastItem, items_.size(), New); } else if (selectionRect){ QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); lastItemChanged(item, items_.indexOf(item)+1, Update); } } void GView::handleTextItemModified(QGraphicsTextItem* item) { lastItemChanged(item, item->data(101).toInt(), Update); } void GView::moveUpSelectedItem() { if (selectionRect) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); int pos = items_.indexOf(item); if (pos < items_.size()-1) { lastItemChanged(item, pos+1, MoveUp); move(item, pos+2); } } } void GView::moveDownSelectedItem() { if (selectionRect) { QGraphicsItem* item = selectionRect->data(1).value<QGraphicsItem*>(); int pos = items_.indexOf(item); if (pos > 0) { lastItemChanged(item, pos+1, MoveDown); move(item, pos); } } } void GView::move(QGraphicsItem* item, int npos) { int pos = items_.indexOf(item); QGraphicsItem* itemAfter = nullptr; if (npos-1 > pos) { if (npos == items_.size()) { item->setZValue(zValue++); } else { itemAfter = items_.at(npos); } items_.insert(npos, item); items_.removeAt(pos); } else if (npos-1 < pos) { itemAfter = items_.at(npos-1); items_.insert(npos-1, item); items_.removeAt(pos+1); } if (itemAfter) { item->setZValue(itemAfter->zValue()); item->stackBefore(itemAfter); } } void GView::changePenAndBrush(QGraphicsItem* item, QPen pen, QBrush brush) { QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); if (lineItem) { lineItem->setPen(pen); } FreehandLineItem* handLineItem = qgraphicsitem_cast<FreehandLineItem*>(item); if (handLineItem) { handLineItem->setPen(pen); } QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(item); if (rectItem) { rectItem->setPen(pen); rectItem->setBrush(brush); } QGraphicsTextItem* textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item); if (textItem) { textItem->setDefaultTextColor(pen.color()); } QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item); if (polygonItem) { polygonItem->setPen(pen); polygonItem->setBrush(brush); } QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); if (ellipseItem) { ellipseItem->setPen(pen); ellipseItem->setBrush(brush); } lineColorChanged(pen.color()); brushColorChanged(brush.color()); } void GView::setActualPenAndBrushFromItem(QGraphicsItem* item) { QGraphicsLineItem* lineItem = qgraphicsitem_cast<QGraphicsLineItem*>(item); if (lineItem) { pen = lineItem->pen(); } FreehandLineItem* handLineItem = qgraphicsitem_cast<FreehandLineItem*>(item); if (handLineItem) { pen = handLineItem->pen(); } QGraphicsRectItem* rectItem = qgraphicsitem_cast<QGraphicsRectItem*>(item); if (rectItem) { pen = rectItem->pen(); brush = rectItem->brush(); } QGraphicsTextItem* textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item); if (textItem) { pen.setColor(textItem->defaultTextColor()); } QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast<QGraphicsPolygonItem*>(item); if (polygonItem) { pen = polygonItem->pen(); brush = polygonItem->brush(); } QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast<QGraphicsEllipseItem*>(item); if (ellipseItem) { pen = ellipseItem->pen(); brush = ellipseItem->brush(); } lineWidthChanged(pen.width()); lineColorChanged(pen.color()); brushColorChanged(brush.color()); } void GView::deselect() { if (selectionRect != nullptr) { pen = defaultPen; brush = defaultBrush; scene()->removeItem(selectionRect); delete selectionRect; selectionRect = nullptr; lineWidthChanged(pen.width()); lineColorChanged(pen.color()); brushColorChanged(brush.color()); } } void GView::deselect(QString id) { if (selectionRect != nullptr) { QGraphicsItem* item = getItem(id); if (item && selectionRect->data(1).value<QGraphicsItem*>() == item) { pen = defaultPen; brush = defaultBrush; scene()->removeItem(selectionRect); delete selectionRect; selectionRect = nullptr; lineWidthChanged(pen.width()); lineColorChanged(pen.color()); brushColorChanged(brush.color()); } } } }