From 6fa74be208da4e963ad5943a03669c2c31f29256 Mon Sep 17 00:00:00 2001
From: Drew Fisher <drew.m.fisher@gmail.com>
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<AddImageAction*>(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<DrawLineAction*>(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<AddImageAction*>(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<int, QPointF>::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<QPointF> dragPath;
 	Shareboard* board;
+	QPointF lastPos;
 };
 
 #endif //__SHAREBOARDCANVAS_H__
-- 
2.39.5