/* * Copyright (c) 2012 Mateusz Piękos * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include "QtWhiteboardWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Swift { QtWhiteboardWindow::QtWhiteboardWindow(WhiteboardSession::ref whiteboardSession) : QWidget() { #ifndef Q_OS_MAC setWindowIcon(QIcon(":/logo-icon-16.png")); #endif layout = new QVBoxLayout(this); hLayout = new QHBoxLayout; sidebarLayout = new QVBoxLayout; toolboxLayout = new QGridLayout; scene = new QGraphicsScene(this); scene->setSceneRect(0, 0, 400, 400); graphicsView = new GView(scene, this); graphicsView->setMode(GView::Line); connect(graphicsView, SIGNAL(lastItemChanged(QGraphicsItem*, int, GView::Type)), this, SLOT(handleLastItemChanged(QGraphicsItem*, int, GView::Type))); connect(graphicsView, SIGNAL(itemDeleted(QString, int)), this, SLOT(handleItemDeleted(QString, int))); widthBox = new QSpinBox(this); connect(widthBox, SIGNAL(valueChanged(int)), this, SLOT(changeLineWidth(int))); connect(graphicsView, SIGNAL(lineWidthChanged(int)), widthBox, SLOT(setValue(int))); widthBox->setValue(1); moveUpButton = new QPushButton("Move Up", this); connect(moveUpButton, SIGNAL(clicked()), graphicsView, SLOT(moveUpSelectedItem())); moveDownButton = new QPushButton("Move Down", this); connect(moveDownButton, SIGNAL(clicked()), graphicsView, SLOT(moveDownSelectedItem())); strokeLayout = new QHBoxLayout; strokeColor = new ColorWidget; strokeLayout->addWidget(new QLabel("Stroke:")); strokeLayout->addWidget(strokeColor); connect(strokeColor, SIGNAL(clicked()), this, SLOT(showColorDialog())); connect(graphicsView, SIGNAL(lineColorChanged(QColor)), strokeColor, SLOT(setColor(QColor))); fillLayout = new QHBoxLayout; fillColor = new ColorWidget; fillLayout->addWidget(new QLabel("Fill:")); fillLayout->addWidget(fillColor); connect(fillColor, SIGNAL(clicked()), this, SLOT(showBrushColorDialog())); connect(graphicsView, SIGNAL(brushColorChanged(QColor)), fillColor, SLOT(setColor(QColor))); rubberButton = new QToolButton(this); rubberButton->setIcon(QIcon(":/icons/eraser.png")); rubberButton->setCheckable(true); rubberButton->setAutoExclusive(true); connect(rubberButton, SIGNAL(clicked()), this, SLOT(setRubberMode())); lineButton = new QToolButton(this); lineButton->setIcon(QIcon(":/icons/line.png")); lineButton->setCheckable(true); lineButton->setAutoExclusive(true); lineButton->setChecked(true); connect(lineButton, SIGNAL(clicked()), this, SLOT(setLineMode())); rectButton = new QToolButton(this); rectButton->setIcon(QIcon(":/icons/rect.png")); rectButton->setCheckable(true); rectButton->setAutoExclusive(true); connect(rectButton, SIGNAL(clicked()), this, SLOT(setRectMode())); circleButton = new QToolButton(this); circleButton->setIcon(QIcon(":/icons/circle.png")); circleButton->setCheckable(true); circleButton->setAutoExclusive(true); connect(circleButton, SIGNAL(clicked()), this, SLOT(setCircleMode())); handLineButton = new QToolButton(this); handLineButton->setIcon(QIcon(":/icons/handline.png")); handLineButton->setCheckable(true); handLineButton->setAutoExclusive(true); connect(handLineButton, SIGNAL(clicked()), this, SLOT(setHandLineMode())); textButton = new QToolButton(this); textButton->setIcon(QIcon(":/icons/text.png")); textButton->setCheckable(true); textButton->setAutoExclusive(true); connect(textButton, SIGNAL(clicked()), this, SLOT(setTextMode())); polygonButton = new QToolButton(this); polygonButton->setIcon(QIcon(":/icons/polygon.png")); polygonButton->setCheckable(true); polygonButton->setAutoExclusive(true); connect(polygonButton, SIGNAL(clicked()), this, SLOT(setPolygonMode())); selectButton = new QToolButton(this); selectButton->setIcon(QIcon(":/icons/cursor.png")); selectButton->setCheckable(true); selectButton->setAutoExclusive(true); connect(selectButton, SIGNAL(clicked()), this, SLOT(setSelectMode())); toolboxLayout->addWidget(rubberButton, 0, 0); toolboxLayout->addWidget(selectButton, 0, 1); toolboxLayout->addWidget(lineButton, 0, 2); toolboxLayout->addWidget(circleButton, 1, 0); toolboxLayout->addWidget(handLineButton, 1, 1); toolboxLayout->addWidget(rectButton, 1, 2); toolboxLayout->addWidget(textButton, 2, 0); toolboxLayout->addWidget(polygonButton, 2, 1); sidebarLayout->addLayout(toolboxLayout); sidebarLayout->addSpacing(30); sidebarLayout->addWidget(moveUpButton); sidebarLayout->addWidget(moveDownButton); sidebarLayout->addSpacing(40); sidebarLayout->addWidget(widthBox); sidebarLayout->addLayout(strokeLayout); sidebarLayout->addLayout(fillLayout); sidebarLayout->addStretch(); hLayout->addWidget(graphicsView); hLayout->addLayout(sidebarLayout); layout->addLayout(hLayout); this->setLayout(layout); setSession(whiteboardSession); } void QtWhiteboardWindow::handleWhiteboardOperationReceive(const WhiteboardOperation::ref operation) { WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); if (insertOp) { WhiteboardElementDrawingVisitor visitor(graphicsView, operation->getPos(), GView::New); insertOp->getElement()->accept(visitor); } WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(operation); if (updateOp) { WhiteboardElementDrawingVisitor visitor(graphicsView, operation->getPos(), GView::Update); updateOp->getElement()->accept(visitor); if (updateOp->getPos() != updateOp->getNewPos()) { graphicsView->move(graphicsView->getItem(P2QSTRING(updateOp->getElement()->getID())), updateOp->getNewPos()); } } WhiteboardDeleteOperation::ref deleteOp = boost::dynamic_pointer_cast(operation); if (deleteOp) { graphicsView->deleteItem(P2QSTRING(deleteOp->getElementID())); } } void QtWhiteboardWindow::changeLineWidth(int i) { graphicsView->setLineWidth(i); } void QtWhiteboardWindow::showColorDialog() { QColor color = QColorDialog::getColor(graphicsView->getLineColor(), 0, "Select pen color", QColorDialog::ShowAlphaChannel); if(color.isValid()) graphicsView->setLineColor(color); } void QtWhiteboardWindow::showBrushColorDialog() { QColor color = QColorDialog::getColor(graphicsView->getBrushColor(), 0, "Select brush color", QColorDialog::ShowAlphaChannel); if(color.isValid()) graphicsView->setBrushColor(color); } void QtWhiteboardWindow::setRubberMode() { graphicsView->setMode(GView::Rubber); } void QtWhiteboardWindow::setLineMode() { graphicsView->setMode(GView::Line); } void QtWhiteboardWindow::setRectMode() { graphicsView->setMode(GView::Rect); } void QtWhiteboardWindow::setCircleMode() { graphicsView->setMode(GView::Circle); } void QtWhiteboardWindow::setHandLineMode() { graphicsView->setMode(GView::HandLine); } void QtWhiteboardWindow::setTextMode() { graphicsView->setMode(GView::Text); } void QtWhiteboardWindow::setPolygonMode() { graphicsView->setMode(GView::Polygon); } void QtWhiteboardWindow::setSelectMode() { graphicsView->setMode(GView::Select); } void QtWhiteboardWindow::show() { QWidget::show(); } void QtWhiteboardWindow::setSession(WhiteboardSession::ref session) { graphicsView->clear(); whiteboardSession_ = session; whiteboardSession_->onOperationReceived.connect(boost::bind(&QtWhiteboardWindow::handleWhiteboardOperationReceive, this, _1)); whiteboardSession_->onRequestAccepted.connect(boost::bind(&QWidget::show, this)); whiteboardSession_->onSessionTerminated.connect(boost::bind(&QtWhiteboardWindow::handleSessionTerminate, this)); } void QtWhiteboardWindow::activateWindow() { QWidget::activateWindow(); } void QtWhiteboardWindow::setName(const std::string& name) { setWindowTitle(P2QSTRING(name)); } void QtWhiteboardWindow::handleLastItemChanged(QGraphicsItem* item, int pos, GView::Type type) { WhiteboardElement::ref el; QGraphicsLineItem* lineItem = qgraphicsitem_cast(item); if (lineItem != 0) { QLine line = lineItem->line().toLine(); QColor color = lineItem->pen().color(); WhiteboardLineElement::ref element = boost::make_shared(line.x1()+lineItem->pos().x(), line.y1()+lineItem->pos().y(), line.x2()+lineItem->pos().x(), line.y2()+lineItem->pos().y()); element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); element->setPenWidth(lineItem->pen().width()); element->setID(lineItem->data(100).toString().toStdString()); el = element; } FreehandLineItem* freehandLineItem = qgraphicsitem_cast(item); if (freehandLineItem != 0) { WhiteboardFreehandPathElement::ref element = boost::make_shared(); QColor color = freehandLineItem->pen().color(); std::vector > points; QVector::const_iterator it = freehandLineItem->points().constBegin(); for ( ; it != freehandLineItem->points().constEnd(); ++it) { points.push_back(std::pair( boost::numeric_cast(it->x()+item->pos().x()), boost::numeric_cast(it->y()+item->pos().y()))); } element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); element->setPenWidth(freehandLineItem->pen().width()); element->setPoints(points); element->setID(freehandLineItem->data(100).toString().toStdString()); el = element; } QGraphicsRectItem* rectItem = qgraphicsitem_cast(item); if (rectItem != 0) { QRectF rect = rectItem->rect(); WhiteboardRectElement::ref element = boost::make_shared(rect.x()+item->pos().x(), rect.y()+item->pos().y(), rect.width(), rect.height()); QColor penColor = rectItem->pen().color(); QColor brushColor = rectItem->brush().color(); element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); element->setPenWidth(rectItem->pen().width()); element->setID(rectItem->data(100).toString().toStdString()); el = element; } QGraphicsTextItem* textItem = qgraphicsitem_cast(item); if (textItem != 0) { QPointF point = textItem->pos(); WhiteboardTextElement::ref element = boost::make_shared(point.x(), point.y()); element->setText(textItem->toPlainText().toStdString()); element->setSize(textItem->font().pointSize()); QColor color = textItem->defaultTextColor(); element->setColor(WhiteboardColor(color.red(), color.green(), color.blue(), color.alpha())); element->setID(textItem->data(100).toString().toStdString()); el = element; } QGraphicsPolygonItem* polygonItem = qgraphicsitem_cast(item); if (polygonItem) { WhiteboardPolygonElement::ref element = boost::make_shared(); QPolygonF polygon = polygonItem->polygon(); std::vector > points; QVector::const_iterator it = polygon.begin(); for (; it != polygon.end(); ++it) { points.push_back(std::pair( boost::numeric_cast(it->x()+item->pos().x()), boost::numeric_cast(it->y()+item->pos().y()))); } element->setPoints(points); QColor penColor = polygonItem->pen().color(); QColor brushColor = polygonItem->brush().color(); element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); element->setPenWidth(polygonItem->pen().width()); element->setID(polygonItem->data(100).toString().toStdString()); el = element; } QGraphicsEllipseItem* ellipseItem = qgraphicsitem_cast(item); if (ellipseItem) { QRectF rect = ellipseItem->rect(); int cx = boost::numeric_cast(rect.x()+rect.width()/2 + item->pos().x()); int cy = boost::numeric_cast(rect.y()+rect.height()/2 + item->pos().y()); int rx = boost::numeric_cast(rect.width()/2); int ry = boost::numeric_cast(rect.height()/2); WhiteboardEllipseElement::ref element = boost::make_shared(cx, cy, rx, ry); QColor penColor = ellipseItem->pen().color(); QColor brushColor = ellipseItem->brush().color(); element->setPenColor(WhiteboardColor(penColor.red(), penColor.green(), penColor.blue(), penColor.alpha())); element->setBrushColor(WhiteboardColor(brushColor.red(), brushColor.green(), brushColor.blue(), brushColor.alpha())); element->setPenWidth(ellipseItem->pen().width()); element->setID(ellipseItem->data(100).toString().toStdString()); el = element; } if (type == GView::New) { WhiteboardInsertOperation::ref insertOp = boost::make_shared(); insertOp->setPos(pos); insertOp->setElement(el); whiteboardSession_->sendOperation(insertOp); } else { WhiteboardUpdateOperation::ref updateOp = boost::make_shared(); updateOp->setPos(pos); if (type == GView::Update) { updateOp->setNewPos(pos); } else if (type == GView::MoveUp) { updateOp->setNewPos(pos+1); } else if (type == GView::MoveDown) { updateOp->setNewPos(pos-1); } updateOp->setElement(el); whiteboardSession_->sendOperation(updateOp); } } void QtWhiteboardWindow::handleItemDeleted(QString id, int pos) { WhiteboardDeleteOperation::ref deleteOp = boost::make_shared(); deleteOp->setElementID(Q2PSTRING(id)); deleteOp->setPos(pos); whiteboardSession_->sendOperation(deleteOp); } void QtWhiteboardWindow::handleSessionTerminate() { hide(); } void QtWhiteboardWindow::closeEvent(QCloseEvent* event) { QMessageBox box(this); box.setText(tr("Closing window is equivalent closing the session. Are you sure you want to do this?")); box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); box.setIcon(QMessageBox::Question); if (box.exec() == QMessageBox::Yes) { whiteboardSession_->cancel(); } else { event->ignore(); } } }