From 6fa74be208da4e963ad5943a03669c2c31f29256 Mon Sep 17 00:00:00 2001 From: Drew Fisher Date: Fri, 8 Oct 2010 09:55:49 -0700 Subject: [PATCH] Implement image insertion and placement, tool selection, and eraser. This commit add the remaining required functionality for the assignment. This code has gone from decent to somewhat ugly in a rather short timeframe, due to no longer thinking about where data belongs. --- connectionmanager.cpp | 1 + mainwindow.cpp | 39 +++++++++++++++++++++++++++++++++++---- mainwindow.h | 6 ++++++ shareboard.cpp | 26 +++++++++++++++++++++++++- shareboard.h | 6 ++++++ shareboardcanvas.cpp | 20 ++++++++++++++++++-- shareboardcanvas.h | 2 ++ 7 files changed, 93 insertions(+), 7 deletions(-) diff --git a/connectionmanager.cpp b/connectionmanager.cpp index 8908c44..36d7502 100644 --- a/connectionmanager.cpp +++ b/connectionmanager.cpp @@ -137,6 +137,7 @@ void ConnectionManager::haveData() { } case Action::AddImage: { + qDebug() << "Sending AddImage action!"; act = new AddImageAction(); AddImageAction* action = static_cast(act); qreal x = 0; diff --git a/mainwindow.cpp b/mainwindow.cpp index 5caf77a..727bd8e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -43,6 +43,13 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { QObject::connect(board, SIGNAL(indexChanged(int)), sliderWidget, SLOT(setValue(int))); QObject::connect(sliderWidget, SIGNAL(valueChanged(int)), board, SLOT(jumpToIndex(int))); + //QObject::connect(spinboxWidget, SIGNAL(valueChanged(int)), board, SLOT(setDrawState(int))); + //QObject::connect(spinboxWidget, SIGNAL(valueChanged(int)), this, SLOT(updateDrawState(int))); + QObject::connect(eraserAction, SIGNAL(triggered()), this, SLOT(useEraserTool())); + QObject::connect(imageAction, SIGNAL(triggered()), this, SLOT(useImageTool())); + QObject::connect(penAction, SIGNAL(triggered()), this, SLOT(usePenTool())); + + usePenTool(); statusBar()->showMessage("Ready"); } @@ -51,6 +58,25 @@ MainWindow::~MainWindow() { } +void MainWindow::useEraserTool() { + board->setDrawState(spinboxWidget->value() * -1); +} + +void MainWindow::usePenTool() { + board->setDrawState(spinboxWidget->value()); +} + +void MainWindow::useImageTool() { + QString fileName = QFileDialog::getOpenFileName(this, "Insert file:", ".", "Images (*.PNG *.png *.JPG *.jpg)"); + if(fileName.isEmpty() ) + return; + QImage im; + if (!im.load(fileName)) + return; + board->setInsertImage(im); + board->setDrawState(0); +} + void MainWindow::updateSliderRange(int newmax) { sliderWidget->setRange(0, newmax); } @@ -118,7 +144,10 @@ void MainWindow::marshallAction(Action* action) { case Action::DrawLine: // set the action's thickness, color { DrawLineAction* a = static_cast(action); - a->color = lineColor; + if(board->getDrawState() < 0 ) // This should probably all get reworked into MainWindow... + a->color = QColor(Qt::white); + else + a->color = lineColor; a->width = spinboxWidget->value(); } break; @@ -152,14 +181,14 @@ void MainWindow::createToolBars() { // Create some of the basic tool actions. // They should also be added to an exclusive tool group. QActionGroup* toolGroup = new QActionGroup(this); - QAction* penAction = new QAction(QIcon("icons/pen.png"), "Pen", this); - QAction* eraserAction = new QAction(QIcon("icons/eraser.png"), "Eraser", this); + penAction = new QAction(QIcon("icons/pen.png"), "Pen", this); + eraserAction = new QAction(QIcon("icons/eraser.png"), "Eraser", this); penAction->setChecked(true); toolGroup->addAction(penAction); toolGroup->addAction(eraserAction); // Create some other one-click actions that are not a part of the action group. - QAction* imageAction = new QAction(QIcon("icons/import_image.png"), "Import Image", this); + imageAction = new QAction(QIcon("icons/import_image.png"), "Import Image", this); clearAction = new QAction(QIcon("icons/clear.png"), "Clear", this); // Style @@ -176,6 +205,8 @@ void MainWindow::createToolBars() { QAction* restartAction = new QAction(QIcon("icons/rewind.png"), "Replay History", this); QAction* playAction = new QAction(QIcon("icons/play.png"), "Play", this); sliderWidget = new QSlider(Qt::Horizontal, this); + sliderWidget->setSingleStep(1); + sliderWidget->setPageStep(30); toolBar = addToolBar("Test"); toolBar->setMovable(false); diff --git a/mainwindow.h b/mainwindow.h index cb82b6a..31af80e 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -30,6 +30,9 @@ public slots: void clearBoard(); void marshallAction(Action* action); void updateSliderRange(int newmax); + void useEraserTool(); + void useImageTool(); + void usePenTool(); private: void createActions(); void createMenus(); @@ -42,6 +45,9 @@ private: QAction* quitAction; QAction* colorAction; QAction* clearAction; + QAction* imageAction; + QAction* penAction; + QAction* eraserAction; QSpinBox* spinboxWidget; QSlider* sliderWidget; ConnectionManager* connMan; diff --git a/shareboard.cpp b/shareboard.cpp index 5ecc324..4855461 100644 --- a/shareboard.cpp +++ b/shareboard.cpp @@ -30,6 +30,7 @@ Shareboard::Shareboard(QWidget* parent) : QWidget(parent) { QObject::connect(prompt, SIGNAL(connectToServer(QString, QString)), this, SIGNAL(connectToServer(QString, QString))); QObject::connect(canvas, SIGNAL(mouseMovedTo(QPointF)), this, SLOT(handleMouseMoved(QPointF))); QObject::connect(canvas, SIGNAL(segmentDrawn(QPointF,QPointF)), this, SLOT(handleSegmentDrawn(QPointF,QPointF))); + QObject::connect(canvas, SIGNAL(insertImage(QPointF)), this, SLOT(handleInsertImage(QPointF))); qDebug() << viewImage.rect(); } @@ -44,6 +45,10 @@ QImage Shareboard::view() { return viewImage; } +int Shareboard::getDrawState() { + return drawState; +} + void Shareboard::handleMouseMoved(QPointF pos) { MouseMoveAction* action = new MouseMoveAction(); action->userID = userID; @@ -63,6 +68,14 @@ void Shareboard::handleSegmentDrawn(QPointF start, QPointF end) { //qDebug() << "shareboard.cpp: segment drawn from" << start << "to" << end; } +void Shareboard::handleInsertImage(QPointF pos) { + AddImageAction* action = new AddImageAction(); + action->userID = userID; + action->topLeft = pos; + action->image = insertImage; + emit actionHappened(action); +} + void Shareboard::postAction(Action* action) { if(action->userID == userID) { delete localHistory[0]; @@ -140,7 +153,10 @@ void Shareboard::jumpToIndex(int index) { } break; case Action::AddImage: - //TODO Implement this + { + AddImageAction* a = static_cast(action); + p.drawImage(a->topLeft, a->image); + } case Action::UserChat: case Action::UserSynced: break; @@ -156,3 +172,11 @@ void Shareboard::jumpToIndex(int index) { canvas->update(); emit indexChanged(viewIndex); } + +void Shareboard::setDrawState(int newstate) { + drawState = newstate; +} + +void Shareboard::setInsertImage(QImage newimage) { + insertImage = newimage; +} diff --git a/shareboard.h b/shareboard.h index 28ab258..a7e9de7 100644 --- a/shareboard.h +++ b/shareboard.h @@ -19,10 +19,12 @@ class Shareboard : public QWidget { Shareboard(QWidget* parent = 0); ~Shareboard(); QImage view(); + int getDrawState(); public slots: void handleMouseMoved(QPointF pos); void handleSegmentDrawn(QPointF start, QPointF end); + void handleInsertImage(QPointF pos); void postAction(Action* action); void postLocalAction(Action* action); void switchToBoard(); @@ -30,6 +32,8 @@ class Shareboard : public QWidget { void setUserID(int id); void jumpToIndex(int index); //void jumpToTime(QDateTime time); + void setDrawState(int newstate); + void setInsertImage(QImage newimage); signals: void rangeChanged(int max); @@ -44,6 +48,8 @@ class Shareboard : public QWidget { History history; History localHistory; int userID; + int drawState; // if > 0, line width. If < 0, eraser size. If == 0, image tool. + QImage insertImage; // These items represent the present state of the view. QDateTime viewTime; QImage viewImage; diff --git a/shareboardcanvas.cpp b/shareboardcanvas.cpp index af45aeb..90e0474 100644 --- a/shareboardcanvas.cpp +++ b/shareboardcanvas.cpp @@ -24,6 +24,7 @@ void ShareboardCanvas::setModel(Shareboard* b) { void ShareboardCanvas::mouseMoveEvent(QMouseEvent* event) { // Send mouse move event to network thread emit mouseMovedTo(event->posF()); + lastPos = event->posF(); // If the button is down if(mouseDown) { emit segmentDrawn(dragPath.last(), event->posF()); @@ -35,6 +36,10 @@ void ShareboardCanvas::mouseMoveEvent(QMouseEvent* event) { void ShareboardCanvas::mousePressEvent(QMouseEvent* event) { if(event->button() & Qt::LeftButton) { + if(board->drawState == 0) { + emit insertImage(event->posF()); + return; + } mouseDown = true; dragPath.append(event->posF()); // We're starting a new drag path } @@ -55,12 +60,23 @@ void ShareboardCanvas::paintEvent(QPaintEvent* event) { QPainter p(this); // Paint the background from the saved state p.drawImage(0, 0, board->view()); - // Now paint our local changes on top of it + // Now paint our local changes on top of it (optional, will make things look snappier) - //p.set // Now paint the set of mouse cursors on top of that QMap::const_iterator i; for (i = board->viewCursors.constBegin(); i!=board->viewCursors.constEnd(); ++i) { + if(i.key() == board->userID) { + if( board->drawState < 0) {// Eraser mode + p.setPen(QColor(Qt::black)); + p.setBrush(QColor(Qt::white)); + p.drawEllipse(lastPos, qAbs(board->drawState), qAbs(board->drawState)); + //p.drawEllipse(i.value(), qAbs(board->drawState), qAbs(board->drawState)); + } + if( board->drawState == 0) { // Image mode + p.drawImage(lastPos, board->insertImage); + } + continue; + } QPen pen(QColor(255,0,0,50)); pen.setCapStyle(Qt::RoundCap); p.setPen(pen); diff --git a/shareboardcanvas.h b/shareboardcanvas.h index 3414580..bf008f3 100644 --- a/shareboardcanvas.h +++ b/shareboardcanvas.h @@ -23,10 +23,12 @@ public: signals: void mouseMovedTo(QPointF pos); void segmentDrawn(QPointF start, QPointF end); + void insertImage(QPointF pos); private: bool mouseDown; QVector dragPath; Shareboard* board; + QPointF lastPos; }; #endif //__SHAREBOARDCANVAS_H__ -- 2.39.2