From 580d3d49ea3df7bb1c00cb1052203d17ccaa9a8e Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 19 Mar 2010 09:17:18 +0000
Subject: Start of event viewer.

Creates a basic event viewer framework, and plugs it into the Swift controllers, so that messages are displayed (in a very ugly way). Still a long way to go.

diff --git a/Swift/Controllers/EventController.cpp b/Swift/Controllers/EventController.cpp
index 5141cc1..3849aa7 100644
--- a/Swift/Controllers/EventController.cpp
+++ b/Swift/Controllers/EventController.cpp
@@ -3,18 +3,23 @@
 #include <boost/bind.hpp>
 #include <algorithm>
 
+
 namespace Swift {
 
-void EventController::handleIncomingEvent(boost::shared_ptr<MessageEvent> event) {
-	if (event->isReadable()) {
-		events_.push_back(event);
-		event->onRead.connect(boost::bind(&EventController::handleEventRead, this, event));
+EventController::EventController() {
+}
+
+void EventController::handleIncomingEvent(boost::shared_ptr<Event> sourceEvent) {
+	boost::shared_ptr<MessageEvent> messageEvent = boost::dynamic_pointer_cast<MessageEvent>(sourceEvent);
+	if (messageEvent && messageEvent->isReadable()) {
+		events_.push_back(sourceEvent);
+		messageEvent->onConclusion.connect(boost::bind(&EventController::handleEventConcluded, this, messageEvent));
 		onEventQueueLengthChange(events_.size());
-		onEventQueueEventAdded(event);
+		onEventQueueEventAdded(sourceEvent);
 	}
 }
 
-void EventController::handleEventRead(boost::shared_ptr<MessageEvent> event) {
+void EventController::handleEventConcluded(boost::shared_ptr<Event> event) {
 	events_.erase(std::remove(events_.begin(), events_.end(), event), events_.end());
 	onEventQueueLengthChange(events_.size());
 }
diff --git a/Swift/Controllers/EventController.h b/Swift/Controllers/EventController.h
index c5c924b..482be58 100644
--- a/Swift/Controllers/EventController.h
+++ b/Swift/Controllers/EventController.h
@@ -6,18 +6,20 @@
 #include <boost/shared_ptr.hpp>
 #include <vector>
 
+#include "Swiften/Events/Event.h"
 #include "Swiften/Events/MessageEvent.h"
 
 namespace Swift {
 	class EventController {
 		public:
-			void handleIncomingEvent(boost::shared_ptr<MessageEvent> event);
+			EventController();
+			void handleIncomingEvent(boost::shared_ptr<Event> sourceEvent);
 			boost::signal<void (int)> onEventQueueLengthChange;
-			boost::signal<void (boost::shared_ptr<MessageEvent>)> onEventQueueEventAdded;
+			boost::signal<void (boost::shared_ptr<Event>)> onEventQueueEventAdded;
 
 		private:
-			void handleEventRead(boost::shared_ptr<MessageEvent> event);
-			std::vector<boost::shared_ptr<MessageEvent> > events_;
+			void handleEventConcluded(boost::shared_ptr<Event> event);
+			std::vector<boost::shared_ptr<Event> > events_;
 	};
 }
 #endif
diff --git a/Swift/Controllers/EventWindowController.cpp b/Swift/Controllers/EventWindowController.cpp
new file mode 100644
index 0000000..4bc5c22
--- /dev/null
+++ b/Swift/Controllers/EventWindowController.cpp
@@ -0,0 +1,18 @@
+#include "Swift/Controllers/EventWindowController.h"
+
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+EventWindowController::EventWindowController(EventController* eventController, EventWindowFactory* windowFactory) {
+	eventController_ = eventController;
+	windowFactory_ = windowFactory;
+	window_ = windowFactory_->createEventWindow();
+	eventController_->onEventQueueEventAdded.connect(boost::bind(&EventWindowController::handleEventQueueEventAdded, this, _1));
+}
+
+void EventWindowController::handleEventQueueEventAdded(boost::shared_ptr<Event> event) {
+	window_->addEvent(event, true);
+}
+
+}
diff --git a/Swift/Controllers/EventWindowController.h b/Swift/Controllers/EventWindowController.h
new file mode 100644
index 0000000..0c06f49
--- /dev/null
+++ b/Swift/Controllers/EventWindowController.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "Swift/Controllers/UIInterfaces/EventWindowFactory.h"
+#include "Swift/Controllers/UIInterfaces/EventWindow.h"
+#include "Swift/Controllers/EventController.h"
+
+
+namespace Swift {
+
+	class EventWindowController {
+		public:
+			EventWindowController(EventController* eventController, EventWindowFactory* windowFactory);
+		private:
+			void handleEventQueueEventAdded(boost::shared_ptr<Event> event);
+
+			EventController* eventController_;
+			EventWindowFactory* windowFactory_;
+			EventWindow* window_;
+	};
+
+}
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index cbfb065..d013f5f 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -11,8 +11,10 @@
 #include "Swift/Controllers/UIInterfaces/ChatWindowFactory.h"
 #include "Swift/Controllers/Chat/ChatsManager.h"
 #include "Swift/Controllers/EventController.h"
+#include "Swift/Controllers/EventWindowController.h"
 #include "Swift/Controllers/UIInterfaces/LoginWindow.h"
 #include "Swift/Controllers/UIInterfaces/LoginWindowFactory.h"
+#include "Swift/Controllers/UIInterfaces/EventWindowFactory.h"
 #include "Swift/Controllers/MainWindow.h"
 #include "Swift/Controllers/MainWindowFactory.h"
 #include "Swift/Controllers/Chat/MUCController.h"
@@ -53,18 +55,20 @@ static const String CLIENT_VERSION = "0.3";
 static const String CLIENT_NODE = "http://swift.im";
 
 
-MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory)
+MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory)
 		: timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), client_(NULL), presenceSender_(NULL), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), xmppRosterController_(NULL), rosterController_(NULL), loginWindow_(NULL), clientVersionResponder_(NULL), nickResolver_(NULL), discoResponder_(NULL) {
 	application_ = application;
 	presenceOracle_ = NULL;
 	avatarManager_ = NULL;
 	chatsManager_ = NULL;
+	eventController_ = NULL;
+	eventWindowFactory_ = eventWindowFactory;
 	uiEventStream_ = new UIEventStream();
 
 	avatarStorage_ = new AvatarFileStorage(application_->getAvatarDir());
-
 	eventController_ = new EventController();
 	eventController_->onEventQueueLengthChange.connect(boost::bind(&MainController::handleEventQueueLengthChange, this, _1));
+
 	systemTrayController_ = new SystemTrayController(eventController_, systemTray);
 	soundEventController_ = new SoundEventController(eventController_, soundPlayer, settings->getBoolSetting("playSounds", true));
 	loginWindow_ = loginWindowFactory_->createLoginWindow(uiEventStream_);
@@ -89,6 +93,7 @@ MainController::~MainController() {
 	delete avatarStorage_;
 	delete xmlConsoleController_;
 	delete uiEventStream_;
+	delete eventController_;
 	resetClient();
 }
 
@@ -103,6 +108,8 @@ void MainController::resetClient() {
 	nickResolver_ = NULL;
 	delete avatarManager_;
 	avatarManager_ = NULL;
+	delete eventWindowController_;
+	eventWindowController_ = NULL;
 	delete rosterController_;
 	rosterController_ = NULL;
 	delete xmppRosterController_;
@@ -126,26 +133,29 @@ void MainController::handleConnected() {
 		xmppRoster_ = boost::shared_ptr<XMPPRoster>(new XMPPRoster());
 		presenceOracle_ = new PresenceOracle(client_);
 		nickResolver_ = new NickResolver(xmppRoster_);		
-		chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_);
-
 		lastSentPresence_ = boost::shared_ptr<Presence>();
 
 		client_->onPresenceReceived.connect(boost::bind(&MainController::handleIncomingPresence, this, _1));
 
+		chatsManager_ = new ChatsManager(jid_, client_, client_, eventController_, chatWindowFactory_, treeWidgetFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_);
+		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
+
 		avatarManager_ = new AvatarManager(client_, client_, avatarStorage_, chatsManager_);
+
 		chatsManager_->setAvatarManager(avatarManager_);
 
-		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
 
 		rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, treeWidgetFactory_, nickResolver_);
-		rosterController_->onStartChatRequest.connect(boost::bind(&ChatsManager::handleChatRequest, chatsManager_, _1));
-		rosterController_->onJoinMUCRequest.connect(boost::bind(&ChatsManager::handleJoinMUCRequest, chatsManager_, _1, _2));
 		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
 		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
+				rosterController_->onStartChatRequest.connect(boost::bind(&ChatsManager::handleChatRequest, chatsManager_, _1));
+		rosterController_->onJoinMUCRequest.connect(boost::bind(&ChatsManager::handleJoinMUCRequest, chatsManager_, _1, _2));
 
 		xmppRosterController_ = new XMPPRosterController(client_, xmppRoster_);
 		xmppRosterController_->requestRoster();
 
+		eventWindowController_ = new EventWindowController(eventController_, eventWindowFactory_);
+
 		clientVersionResponder_ = new SoftwareVersionResponder(CLIENT_NAME, CLIENT_VERSION, client_);
 		loginWindow_->morphInto(rosterController_->getWindow());
 
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index b6a1254..63be284 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -49,10 +49,12 @@ namespace Swift {
 	class XMLConsoleController;
 	class UIEventStream;
 	class XMLConsoleWidgetFactory;
+	class EventWindowFactory;
+	class EventWindowController;
 
 	class MainController {
 		public:
-			MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory* treeWidgetFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory);
+			MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory* treeWidgetFactory, EventWindowFactory* eventWindowFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer, XMLConsoleWidgetFactory* xmlConsoleWidgetFactory);
 			~MainController();
 
 
@@ -86,6 +88,7 @@ namespace Swift {
 			MainWindowFactory* mainWindowFactory_;
 			LoginWindowFactory* loginWindowFactory_;
 			TreeWidgetFactory* treeWidgetFactory_;
+			EventWindowFactory* eventWindowFactory_;
 			SettingsProvider *settings_;
 			Application* application_;
 			AvatarStorage* avatarStorage_;
@@ -93,6 +96,7 @@ namespace Swift {
 			XMPPRosterController* xmppRosterController_;
 			RosterController* rosterController_;
 			EventController* eventController_;
+			EventWindowController* eventWindowController_;
 			LoginWindow* loginWindow_;
 			SoftwareVersionResponder* clientVersionResponder_;
 			NickResolver* nickResolver_;
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index 6bd742b..bd2c16e 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -17,6 +17,7 @@ myenv.StaticLibrary("SwiftControllers", [
 		"XMPPRosterController.cpp",
 		"Chat/MUCController.cpp",
 		"EventController.cpp",
+		"EventWindowController.cpp",
 		"SoundEventController.cpp",
 		"SystemTrayController.cpp",
 		"XMLConsoleController.cpp",
diff --git a/Swift/Controllers/SoundEventController.cpp b/Swift/Controllers/SoundEventController.cpp
index d466842..392b4e9 100644
--- a/Swift/Controllers/SoundEventController.cpp
+++ b/Swift/Controllers/SoundEventController.cpp
@@ -9,12 +9,12 @@ namespace Swift {
 
 SoundEventController::SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, bool playSounds) {
 	eventController_ = eventController;
+	eventController_->onEventQueueEventAdded.connect(boost::bind(&SoundEventController::handleEventQueueEventAdded, this, _1));
 	soundPlayer_ = soundPlayer;
 	playSounds_ = playSounds;
-	eventController_->onEventQueueEventAdded.connect(boost::bind(&SoundEventController::handleEventQueueEventAdded, this, _1));
 }
 
-void SoundEventController::handleEventQueueEventAdded(boost::shared_ptr<MessageEvent>) {
+void SoundEventController::handleEventQueueEventAdded(boost::shared_ptr<Event>) {
 	if (playSounds_) soundPlayer_->playSound(SoundPlayer::MessageReceived);
 }
 
diff --git a/Swift/Controllers/SoundEventController.h b/Swift/Controllers/SoundEventController.h
index 9ac6f76..777e55f 100644
--- a/Swift/Controllers/SoundEventController.h
+++ b/Swift/Controllers/SoundEventController.h
@@ -2,7 +2,7 @@
 
 #include <boost/shared_ptr.hpp>
 
-#include "Swiften/Events/MessageEvent.h"
+#include "Swiften/Events/Event.h"
 
 namespace Swift {
 	class EventController;
@@ -12,7 +12,7 @@ namespace Swift {
 			SoundEventController(EventController* eventController, SoundPlayer* soundPlayer, bool playSounds);
 			void setPlaySounds(bool playSounds);
 		private:
-			void handleEventQueueEventAdded(boost::shared_ptr<MessageEvent> event);
+			void handleEventQueueEventAdded(boost::shared_ptr<Event> event);
 			EventController* eventController_;
 			SoundPlayer* soundPlayer_;
 			bool playSounds_;
diff --git a/Swift/Controllers/SystemTrayController.cpp b/Swift/Controllers/SystemTrayController.cpp
index 0fdd4b5..dfa10c6 100644
--- a/Swift/Controllers/SystemTrayController.cpp
+++ b/Swift/Controllers/SystemTrayController.cpp
@@ -8,8 +8,8 @@
 namespace Swift {
 
 SystemTrayController::SystemTrayController(EventController* eventController, SystemTray* systemTray) {
-	eventController_ = eventController;
 	systemTray_ = systemTray;
+	eventController_ = eventController;
 	eventController_->onEventQueueLengthChange.connect(boost::bind(&SystemTrayController::handleEventQueueLengthChange, this, _1));
 }
 
diff --git a/Swift/Controllers/SystemTrayController.h b/Swift/Controllers/SystemTrayController.h
index 6d2aa31..7eb2365 100644
--- a/Swift/Controllers/SystemTrayController.h
+++ b/Swift/Controllers/SystemTrayController.h
@@ -6,8 +6,7 @@ namespace Swift {
 
 	class SystemTrayController {
 		public:
-			SystemTrayController(EventController* eventController, SystemTray* systemTray);
-
+		SystemTrayController(EventController* eventController, SystemTray* systemTray);
 		private:
 			void handleEventQueueLengthChange(int length);
 
diff --git a/Swift/Controllers/UIInterfaces/EventWindow.h b/Swift/Controllers/UIInterfaces/EventWindow.h
new file mode 100644
index 0000000..6cc5bbd
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/EventWindow.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "boost/shared_ptr.hpp"
+#include "Swiften/Events/Event.h"
+
+namespace Swift {
+	class EventWindow {
+		public:
+			virtual void addEvent(boost::shared_ptr<Event> event, bool active) = 0;
+			virtual void removeEvent(boost::shared_ptr<Event> event) = 0;
+	};
+}
diff --git a/Swift/Controllers/UIInterfaces/EventWindowFactory.h b/Swift/Controllers/UIInterfaces/EventWindowFactory.h
new file mode 100644
index 0000000..3dcc30a
--- /dev/null
+++ b/Swift/Controllers/UIInterfaces/EventWindowFactory.h
@@ -0,0 +1,17 @@
+#pragma once
+
+namespace Swift {
+	class EventWindow;
+
+	class EventWindowFactory {
+		public:
+			virtual ~EventWindowFactory() {};
+			/**
+			 * Transfers ownership of result.
+			 */
+			virtual EventWindow* createEventWindow() = 0;
+
+	};
+}
+
+
diff --git a/Swift/QtUI/EventViewer/EventDelegate.cpp b/Swift/QtUI/EventViewer/EventDelegate.cpp
index 8b13789..fe8f70c 100644
--- a/Swift/QtUI/EventViewer/EventDelegate.cpp
+++ b/Swift/QtUI/EventViewer/EventDelegate.cpp
@@ -1 +1,10 @@
+#include "EventDelegate.h"
+
+namespace Swift {
+
+EventDelegate::EventDelegate() : QStyledItemDelegate() {
+
+}
+
+}
 
diff --git a/Swift/QtUI/EventViewer/EventDelegate.h b/Swift/QtUI/EventViewer/EventDelegate.h
index 8b13789..cae49af 100644
--- a/Swift/QtUI/EventViewer/EventDelegate.h
+++ b/Swift/QtUI/EventViewer/EventDelegate.h
@@ -1 +1,12 @@
+#pragma once
+
+#include <QStyledItemDelegate>
+
+namespace Swift {
+	class EventDelegate : public QStyledItemDelegate {
+		Q_OBJECT
+		public:
+			EventDelegate();
+	};
+}
 
diff --git a/Swift/QtUI/EventViewer/EventModel.cpp b/Swift/QtUI/EventViewer/EventModel.cpp
index a3d5406..ffe2110 100644
--- a/Swift/QtUI/EventViewer/EventModel.cpp
+++ b/Swift/QtUI/EventViewer/EventModel.cpp
@@ -1,20 +1,66 @@
 #include "EventModel.h"
 
+#include <qdebug>
+
 namespace Swift {
 EventModel::EventModel() {
 	
 }
 
 EventModel::~EventModel() {
-	
+	foreach (QtEvent* event, activeEvents_) {
+		delete event;
+	}
+	foreach (QtEvent* event, inactiveEvents_) {
+		delete event;
+	}
+}
+
+QVariant EventModel::data(const QModelIndex& index, int role) const {
+	if (!index.isValid()) {
+		return QVariant();
+	}
+	int row = index.row();
+	QtEvent* item = index.row() < activeEvents_.size() ? activeEvents_[row] : inactiveEvents_[row - activeEvents_.size()];
+	QVariant result = item ? item->data(role) : QVariant();
+	qDebug() << "Asked for data of " << index << ", " << role << " returning " << result;
+	return result;
 }
 
-QVariant EventModel::data(const QModelIndex& /*index*/, int /*role*/) const {
-	return QVariant();
+int EventModel::rowCount(const QModelIndex& parent) const {
+	/* Invalid parent = root, valid parent = child, and we're a list not a tree.*/
+	int count = parent.isValid() ? 0 : activeEvents_.size() + inactiveEvents_.size();
+	return count;
 }
 
-int EventModel::rowCount(const QModelIndex& /*parent*/) const {
-	return 0;
+void EventModel::addEvent(boost::shared_ptr<Event> event, bool active) {
+	qDebug() << " Adding Event";
+	if (active) {
+		activeEvents_.push_front(new QtEvent(event, active));
+		emit dataChanged(createIndex(0, 0), createIndex(1, 0));
+	} else {
+		inactiveEvents_.push_front(new QtEvent(event, active));
+		emit dataChanged(createIndex(activeEvents_.size() -1, 0), createIndex(activeEvents_.size(), 0));
+	}
+	emit layoutChanged();
+}
+
+void EventModel::removeEvent(boost::shared_ptr<Event> event) {
+	for (int i = 0; i < activeEvents_.size(); i++) {
+		if (event == activeEvents_[i]->getEvent()) {
+			activeEvents_.removeAt(i);
+			emit dataChanged(createIndex(i - 1, 0), createIndex(i - 1, 0));
+			return;
+		}
+	}
+	for (int i = 0; i < inactiveEvents_.size(); i++) {
+		if (event == inactiveEvents_[i]->getEvent()) {
+			inactiveEvents_.removeAt(i);
+			emit dataChanged(createIndex(activeEvents_.size() + i - 1, 0), createIndex(activeEvents_.size() + i - 1, 0));
+			return;
+		}
+	}
+
 }
 
 }
diff --git a/Swift/QtUI/EventViewer/EventModel.h b/Swift/QtUI/EventViewer/EventModel.h
index 18195f1..bc54cf4 100644
--- a/Swift/QtUI/EventViewer/EventModel.h
+++ b/Swift/QtUI/EventViewer/EventModel.h
@@ -1,16 +1,27 @@
 #pragma once
 
+#include <boost/shared_ptr.hpp>
+
 #include <QAbstractListModel>
 #include <QList>
 
+#include "Swiften/Events/Event.h"
+
+#include "Swift/QtUI/EventViewer/QtEvent.h"
+
 namespace Swift {
 class EventModel : public QAbstractListModel {
 Q_OBJECT
 public:
 	EventModel();
 	~EventModel();
+	void addEvent(boost::shared_ptr<Event> event, bool active);
+	void removeEvent(boost::shared_ptr<Event> event);
 	QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
 	int rowCount(const QModelIndex& parent = QModelIndex()) const;
+private:
+	QList<QtEvent*> activeEvents_;
+	QList<QtEvent*> inactiveEvents_;
 };
 
 }
diff --git a/Swift/QtUI/EventViewer/EventView.pri b/Swift/QtUI/EventViewer/EventView.pri
new file mode 100644
index 0000000..017f498
--- /dev/null
+++ b/Swift/QtUI/EventViewer/EventView.pri
@@ -0,0 +1,11 @@
+SOURCES += $$PWD/EventDelegate.cpp \
+	$$PWD/EventModel.cpp \
+	$$PWD/EventView.cpp \
+	$$PWD/QtEventWindow.cpp \
+	$$PWD/QtEvent.cpp 
+
+HEADERS += $$PWD/EventDelegate.h \
+	$$PWD/EventModel.h \
+	$$PWD/EventView.h \
+	$$PWD/QtEventWindow.h \
+	$$PWD/QtEvent.h
diff --git a/Swift/QtUI/EventViewer/EventView.pro b/Swift/QtUI/EventViewer/EventView.pro
new file mode 100644
index 0000000..942f0ba
--- /dev/null
+++ b/Swift/QtUI/EventViewer/EventView.pro
@@ -0,0 +1,20 @@
+CONFIG -= app_bundle
+
+include(EventView.pri)
+SOURCES += main.cpp
+
+DEPENDPATH += ../. ../../.. ../../../3rdParty/Boost/src
+INCLUDEPATH += ../. ../../.. ../../../3rdParty/Boost/src
+
+DEFINES += BOOST_SIGNALS_NAMESPACE=bsignals BOOST_ALL_NO_LIB
+
+#LIBS += ../../Controllers/Controllers.a 
+LIBS += ../../../Swiften/libSwiften.a 
+LIBS += ../../../3rdParty/Boost/libBoost.a
+LIBS += ../../../3rdParty/LibIDN/libIDN.a
+
+mac {
+	DEFINES += SWIFT_PLATFORM_MACOSX
+}
+
+RESOURCES += ../Swift.qrc
diff --git a/Swift/QtUI/EventViewer/QtEvent.cpp b/Swift/QtUI/EventViewer/QtEvent.cpp
new file mode 100644
index 0000000..2dc1fb0
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEvent.cpp
@@ -0,0 +1,31 @@
+#include "Swift/QtUI/EventViewer/QtEvent.h"
+
+#include "Swiften/Events/MessageEvent.h"
+
+#include "Swift/QtUI/QtSwiftUtil.h"
+
+namespace Swift {
+
+QtEvent::QtEvent(boost::shared_ptr<Event> event, bool active) : event_(event) {
+	active_ = active;
+}
+
+QVariant QtEvent::data(int role) {
+ 	switch (role) {
+		case Qt::DisplayRole: return QVariant(text());
+		case Qt::TextColorRole: return active_ ? Qt::black : Qt::darkGray;
+		case Qt::BackgroundColorRole: return active_ ? Qt::white : Qt::lightGray;
+			/*case Qt::ToolTipRole: return isContact() ? toolTipString() : QVariant();
+	 	case StatusTextRole: return statusText_;
+		case AvatarRole: return avatar_;
+		case PresenceIconRole: return getPresenceIcon();*/
+	 	default: return QVariant();
+	}
+}
+
+QString QtEvent::text() {
+	boost::shared_ptr<MessageEvent> messageEvent = boost::dynamic_pointer_cast<MessageEvent>(event_);
+	return messageEvent ? P2QSTRING(messageEvent->getStanza()->getBody()) :  "Bob: ";
+}
+
+}
diff --git a/Swift/QtUI/EventViewer/QtEvent.h b/Swift/QtUI/EventViewer/QtEvent.h
new file mode 100644
index 0000000..7083c6e
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEvent.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include <QVariant>
+
+#include "Swiften/Events/Event.h"
+
+namespace Swift {
+	class QtEvent {
+		public:
+			QtEvent(boost::shared_ptr<Event> event, bool active);
+			QVariant data(int role);
+			boost::shared_ptr<Event> getEvent() { return event_; };
+		private:
+			QString text();
+			boost::shared_ptr<Event> event_;
+			bool active_;
+	};
+}
diff --git a/Swift/QtUI/EventViewer/QtEventWindow.cpp b/Swift/QtUI/EventViewer/QtEventWindow.cpp
new file mode 100644
index 0000000..fda957d
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEventWindow.cpp
@@ -0,0 +1,34 @@
+#include "Swift/QtUI/EventViewer/QtEventWindow.h"
+
+#include "Swiften/Base/Platform.h"
+
+namespace Swift {
+
+QtEventWindow::QtEventWindow(QWidget* parent) : QTreeView(parent) {
+	model_ = new EventModel();
+	setModel(model_);
+	delegate_ = new EventDelegate();
+	setItemDelegate(delegate_);
+	setHeaderHidden(true);
+#ifdef SWIFT_PLATFORM_MACOSX
+	setAlternatingRowColors(true);
+#endif
+	setAnimated(true);
+	setIndentation(0);
+	setRootIsDecorated(true);
+}
+
+QtEventWindow::~QtEventWindow() {
+	delete model_;
+	delete delegate_;
+}
+
+void QtEventWindow::addEvent(boost::shared_ptr<Event> event, bool active) {
+	model_->addEvent(event, active);
+}
+
+void QtEventWindow::removeEvent(boost::shared_ptr<Event> event) {
+	model_->removeEvent(event);
+}
+
+}
diff --git a/Swift/QtUI/EventViewer/QtEventWindow.h b/Swift/QtUI/EventViewer/QtEventWindow.h
new file mode 100644
index 0000000..cab50ef
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEventWindow.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "boost/shared_ptr.hpp"
+
+#include <QTreeView>
+
+#include "Swift/Controllers/UIInterfaces/EventWindow.h"
+#include "Swift/QtUI/EventViewer/EventView.h"
+#include "Swift/QtUI/EventViewer/EventModel.h"
+#include "Swift/QtUI/EventViewer/EventDelegate.h"
+
+namespace Swift {
+	class QtEventWindow : public QTreeView, public EventWindow {
+		Q_OBJECT
+		public:
+			QtEventWindow(QWidget* parent = 0);
+			~QtEventWindow();
+			void addEvent(boost::shared_ptr<Event> event, bool active);
+			void removeEvent(boost::shared_ptr<Event> event);
+		private:
+			EventModel* model_;
+			EventDelegate* delegate_;
+	};
+		
+}
+
diff --git a/Swift/QtUI/EventViewer/QtEventWindowFactory.cpp b/Swift/QtUI/EventViewer/QtEventWindowFactory.cpp
new file mode 100644
index 0000000..11c630b
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEventWindowFactory.cpp
@@ -0,0 +1,16 @@
+#include "Swift/QtUI/EventViewer/QtEventWindowFactory.h"
+
+#include "Swift/QtUI/QtMainWindowFactory.h"
+#include "Swift/QtUI/QtMainWindow.h"
+
+namespace Swift {
+
+QtEventWindowFactory::QtEventWindowFactory(QtMainWindowFactory* mainWindowFactory) {
+	mainWindowFactory_ = mainWindowFactory;
+}
+
+EventWindow* QtEventWindowFactory::createEventWindow() {
+	return ((QtMainWindow*)mainWindowFactory_->getLastCreatedWindow())->getEventWindow();
+}
+
+}
diff --git a/Swift/QtUI/EventViewer/QtEventWindowFactory.h b/Swift/QtUI/EventViewer/QtEventWindowFactory.h
new file mode 100644
index 0000000..6e41a86
--- /dev/null
+++ b/Swift/QtUI/EventViewer/QtEventWindowFactory.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "Swift/Controllers/UIInterfaces/EventWindowFactory.h"
+
+namespace Swift {
+	class QtMainWindowFactory;
+	class QtEventWindowFactory : public EventWindowFactory {
+		public:
+			QtEventWindowFactory(QtMainWindowFactory* mainWindowFactory);
+			virtual EventWindow* createEventWindow();
+		private:
+			QtMainWindowFactory* mainWindowFactory_;
+	};
+}
+
+	
diff --git a/Swift/QtUI/EventViewer/main.cpp b/Swift/QtUI/EventViewer/main.cpp
new file mode 100644
index 0000000..647010d
--- /dev/null
+++ b/Swift/QtUI/EventViewer/main.cpp
@@ -0,0 +1,20 @@
+#include <QtGui>
+#include "EventView.h"
+#include "EventModel.h"
+#include "QtEventWindow.h"
+
+#include "Swiften/Events/MessageEvent.h"
+
+int main(int argc, char *argv[])
+{
+		QApplication app(argc, argv);
+		Swift::QtEventWindow* viewer = new Swift::QtEventWindow();
+		viewer->show();
+		boost::shared_ptr<Swift::Message> message1(new Swift::Message());
+		message1->setBody("Oooh, shiny");
+		boost::shared_ptr<Swift::MessageEvent> event1(new Swift::MessageEvent(message1));
+		viewer->addEvent(boost::dynamic_pointer_cast<Swift::Event>(event1), true);
+		viewer->addEvent(boost::dynamic_pointer_cast<Swift::Event>(event1), false);
+		viewer->addEvent(boost::dynamic_pointer_cast<Swift::Event>(event1), false);
+		return app.exec();
+}
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 2dad2fd..10dcfa6 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -45,9 +45,9 @@ QtMainWindow::QtMainWindow(QtTreeWidgetFactory *treeWidgetFactory) : QWidget() {
 
 	tabs_->addTab(contactsTabWidget_, "Contacts");
 	
-	eventView_ = new EventView(this);
+	eventWindow_ = new QtEventWindow();
 	
-	tabs_->addTab(eventView_, "Events");
+	tabs_->addTab(eventWindow_, "Events");
 	
 	this->setLayout(mainLayout);
 	
@@ -72,6 +72,10 @@ QtMainWindow::QtMainWindow(QtTreeWidgetFactory *treeWidgetFactory) : QWidget() {
 	chatMenu->addAction(signOutAction);
 }
 
+QtEventWindow* QtMainWindow::getEventWindow() {
+	return eventWindow_;
+}
+
 void QtMainWindow::handleAddActionTriggered(bool checked) {
 	Q_UNUSED(checked);
 	QtAddContactDialog* addContact = new QtAddContactDialog(this);
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index 9f06dc8..ce3272a 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -5,7 +5,7 @@
 #include <QMenu>
 #include "Swift/Controllers/MainWindow.h"
 #include "Swift/QtUI/QtRosterHeader.h"
-#include "Swift/QtUI/EventViewer/EventView.h"
+#include "Swift/QtUI/EventViewer/QtEventWindow.h"
 
 #include <vector>
 
@@ -32,6 +32,7 @@ namespace Swift {
 			void setMyAvatarPath(const String& path);
 			void setMyStatusText(const String& status);
 			void setMyStatusType(const StatusShow::Type type);
+			QtEventWindow* getEventWindow();
 		private slots:
 			void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage);
 			void handleShowOfflineToggled(bool);
@@ -51,7 +52,7 @@ namespace Swift {
 			QTabWidget* tabs_;
 			QWidget* contactsTabWidget_;
 			QWidget* eventsTabWidget_;
-			EventView* eventView_;
+			QtEventWindow* eventWindow_;
 	};
 }
 
diff --git a/Swift/QtUI/QtMainWindowFactory.cpp b/Swift/QtUI/QtMainWindowFactory.cpp
index 9594ade..0794780 100644
--- a/Swift/QtUI/QtMainWindowFactory.cpp
+++ b/Swift/QtUI/QtMainWindowFactory.cpp
@@ -5,12 +5,17 @@
 namespace Swift {
 
 QtMainWindowFactory::QtMainWindowFactory(QtTreeWidgetFactory *treeWidgetFactory) : treeWidgetFactory_(treeWidgetFactory) {
-
+	lastWindow_ = NULL;
 }
 
 MainWindow* QtMainWindowFactory::createMainWindow() {
 	QtMainWindow* window = new QtMainWindow(treeWidgetFactory_);
+	lastWindow_ = window;
 	return window;
 }
 
+MainWindow* QtMainWindowFactory::getLastCreatedWindow() {
+	return lastWindow_;
+}
+
 }
diff --git a/Swift/QtUI/QtMainWindowFactory.h b/Swift/QtUI/QtMainWindowFactory.h
index 1e45b23..bd8342c 100644
--- a/Swift/QtUI/QtMainWindowFactory.h
+++ b/Swift/QtUI/QtMainWindowFactory.h
@@ -9,8 +9,10 @@ namespace Swift {
 		public:
 			QtMainWindowFactory(QtTreeWidgetFactory *treeWidgetFactory);
 			MainWindow* createMainWindow();
+			MainWindow* getLastCreatedWindow();
 		private:
 			QtTreeWidgetFactory *treeWidgetFactory_;
+			MainWindow* lastWindow_;
 	};
 }
 
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index be2d291..6c9dc11 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -9,6 +9,7 @@
 #include "QtSystemTray.h"
 #include "QtSoundPlayer.h"
 #include "QtXMLConsoleWidgetFactory.h"
+#include "EventViewer/QtEventWindowFactory.h"
 #include <boost/bind.hpp>
 #include <QSplitter>
 
@@ -51,12 +52,13 @@ QtSwift::QtSwift(bool netbookMode) : autoUpdater_(NULL) {
 	loginWindowFactory_ = new QtLoginWindowFactory(splitter_, systemTray_, settings_);
 	chatWindowFactory_ = new QtChatWindowFactory(treeWidgetFactory_, splitter_, settings_, tabs_);
 	rosterWindowFactory_ = new QtMainWindowFactory(treeWidgetFactory_);
+	eventWindowFactory_ = new QtEventWindowFactory(rosterWindowFactory_);
 	xmlConsoleWidgetFactory_ = new QtXMLConsoleWidgetFactory(tabs_);
 	soundPlayer_ = new QtSoundPlayer();
 	if (splitter_) {
 		splitter_->show();
 	}
-	mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, treeWidgetFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_);
+	mainController_ = new MainController(chatWindowFactory_, rosterWindowFactory_, loginWindowFactory_, treeWidgetFactory_, eventWindowFactory_, settings_, application_, systemTray_, soundPlayer_, xmlConsoleWidgetFactory_);
 
 	PlatformAutoUpdaterFactory autoUpdaterFactory;
 	if (autoUpdaterFactory.isSupported()) {
@@ -79,6 +81,7 @@ QtSwift::~QtSwift() {
 	delete soundPlayer_;
 	delete tabs_;
 	delete xmlConsoleWidgetFactory_;
+	delete eventWindowFactory_;
 }
 
 }
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index 0ba9926..5a3f9b3 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -21,6 +21,7 @@ namespace Swift {
 	class QtXMLConsoleWidgetFactory;
 	class QtSystemTray;
 	class QtSoundPlayer;
+	class QtEventWindowFactory;
 		
 	class QtSwift : public QObject {
 		Q_OBJECT
@@ -40,6 +41,7 @@ namespace Swift {
 			QSplitter* splitter_;
 			QtSoundPlayer* soundPlayer_;
 			QtChatTabs* tabs_;
+			QtEventWindowFactory* eventWindowFactory_;
 			Application* application_;
 			AutoUpdater* autoUpdater_;
 	};
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 49c45ea..f1a229a 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -79,9 +79,11 @@ sources = [
     "Roster/QtTreeWidget.cpp",
     "Roster/QtTreeWidgetItem.cpp",
     "Roster/RosterDelegate.cpp",
-    "EventViewer/EventView.cpp",
     "EventViewer/EventModel.cpp",
     "EventViewer/EventDelegate.cpp",
+    "EventViewer/QtEventWindowFactory.cpp",
+    "EventViewer/QtEventWindow.cpp",
+    "EventViewer/QtEvent.cpp",
     "QtRosterHeader.cpp",
     "qrc_DefaultTheme.cc",
     "qrc_Swift.cc",
diff --git a/Swiften/Events/Event.h b/Swiften/Events/Event.h
new file mode 100644
index 0000000..b4a71f6
--- /dev/null
+++ b/Swiften/Events/Event.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <boost/signals.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class Event {
+		public:
+			Event(){};
+			virtual ~Event() {};
+			boost::signal<void()> onConclusion;
+	};
+}
diff --git a/Swiften/Events/MessageEvent.h b/Swiften/Events/MessageEvent.h
index 412b199..0adfa82 100644
--- a/Swiften/Events/MessageEvent.h
+++ b/Swiften/Events/MessageEvent.h
@@ -3,17 +3,18 @@
 
 #include <cassert>
 
-#include "Swiften/Elements/Message.h"
-
 #include <boost/signals.hpp>
 #include <boost/shared_ptr.hpp>
 
+#include "Swiften/Events/Event.h"
+#include "Swiften/Elements/Message.h"
+
 namespace Swift {
-	class MessageEvent {
-			public:
-			MessageEvent(boost::shared_ptr<Message> stanza) : stanza_(stanza){}
+	class MessageEvent : public Event {
+		public:
+			MessageEvent(boost::shared_ptr<Message> stanza) : stanza_(stanza){};
+			virtual ~MessageEvent(){};
 			boost::shared_ptr<Message> getStanza() {return stanza_;}
-			boost::signal<void()> onRead;
 
 			bool isReadable() {
 				return getStanza()->isError() || !getStanza()->getBody().isEmpty();
@@ -21,7 +22,7 @@ namespace Swift {
 
 			void read() {
 				assert (isReadable());
-				onRead();
+				onConclusion();
 			}
 
 		private:
-- 
cgit v0.10.2-6-g49f6