From 201e2a9a3a2d074166fb975277515a667e5cab4e Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Thu, 12 May 2011 18:51:41 +0100
Subject: Allow Chat Window Font resizing

Resolves: #812
Release-Notes: It is now possible to resize the font in the chat window conversations.

diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index d89f25f..e3fc2b3 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -24,7 +24,7 @@
 
 namespace Swift {
 
-QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent) {
+QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent), fontSizeSteps_(0) {
 	theme_ = theme;
 
 	QVBoxLayout* mainLayout = new QVBoxLayout(this);
@@ -35,6 +35,8 @@ QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent) {
 	connect(webView_, SIGNAL(loadFinished(bool)), SLOT(handleViewLoadFinished(bool)));
 	connect(webView_, SIGNAL(gotFocus()), SIGNAL(gotFocus()));
 	connect(webView_, SIGNAL(clearRequested()), SLOT(handleClearRequested()));
+	connect(webView_, SIGNAL(fontGrowRequested()), SLOT(increaseFontSize()));
+	connect(webView_, SIGNAL(fontShrinkRequested()), SLOT(decreaseFontSize()));
 #ifdef Q_WS_X11
 	/* To give a border on Linux, where it looks bad without */
 	QStackedWidget* stack = new QStackedWidget(this);
@@ -104,6 +106,14 @@ void QtChatView::addToDOM(boost::shared_ptr<ChatSnippet> snippet) {
 		newInsertPoint_.prependOutside(newElement);
 	}
 	lastElement_ = newElement;
+	if (fontSizeSteps_ != 0) {
+		double size = 1.0 + 0.2 * fontSizeSteps_;
+		QString sizeString(QString().setNum(size, 'g', 3) + "em");
+		const QWebElementCollection spans = lastElement_.findAll("span");
+		foreach (QWebElement span, spans) {
+			span.setStyleProperty("font-size", sizeString);
+		}
+	}
 }
 
 void QtChatView::addLastSeenLine() {
@@ -196,6 +206,31 @@ void QtChatView::handleViewLoadFinished(bool ok) {
 	viewReady_ = true;
 }
 
+void QtChatView::increaseFontSize(int numSteps) {
+	qDebug() << "Increasing";
+	fontSizeSteps_ += numSteps;
+	emit fontResized(fontSizeSteps_);
+}
+
+void QtChatView::decreaseFontSize() {
+	fontSizeSteps_--;
+	if (fontSizeSteps_ < 0) {
+		fontSizeSteps_ = 0;
+	}
+	emit fontResized(fontSizeSteps_);
+}
+
+void QtChatView::resizeFont(int fontSizeSteps) {
+	fontSizeSteps_ = fontSizeSteps;
+	double size = 1.0 + 0.2 * fontSizeSteps_;
+	QString sizeString(QString().setNum(size, 'g', 3) + "em");
+	qDebug() << "Setting to " << sizeString;
+	const QWebElementCollection spans = document_.findAll("span");
+	foreach (QWebElement span, spans) {
+		span.setStyleProperty("font-size", sizeString);
+	}
+}
+
 void QtChatView::resetView() {
 	lastElement_ = QWebElement();
 	QString pageHTML = theme_->getTemplate();
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 8b8d330..eda7e42 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -37,6 +37,7 @@ namespace Swift {
 
 		signals:
 			void gotFocus();
+			void fontResized(int);
 
 		public slots:
 			void copySelectionToClipboard();
@@ -44,6 +45,9 @@ namespace Swift {
 			void handleLinkClicked(const QUrl&);
 			void handleKeyPressEvent(QKeyEvent* event);
 			void resetView();
+			void increaseFontSize(int numSteps = 1);
+			void decreaseFontSize();
+			void resizeFont(int fontSizeSteps);
 
 		private slots:
 			void handleViewLoadFinished(bool);
@@ -60,7 +64,7 @@ namespace Swift {
 			bool isAtBottom_;
 			QtWebView* webView_;
 			QWebPage* webPage_;
-
+			int fontSizeSteps_;
 			QtChatTheme* theme_;
 			QWebElement newInsertPoint_;
 			QWebElement lineSeparator_;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 95aecb7..b2644b2 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -97,12 +97,17 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(qAppFocusChanged(QWidget*, QWidget*)));
 	connect(messageLog_, SIGNAL(gotFocus()), input_, SLOT(setFocus()));
 	resize(400,300);
+	connect(messageLog_, SIGNAL(fontResized(int)), this, SIGNAL(fontResized(int)));
 }
 
 QtChatWindow::~QtChatWindow() {
 
 }
 
+void QtChatWindow::handleFontResized(int fontSizeSteps) {
+	messageLog_->resizeFont(fontSizeSteps);
+}
+
 void QtChatWindow::setTabComplete(TabComplete* completer) {
 	completer_ = completer;
 }
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index cb87970..78d8f91 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -62,10 +62,12 @@ namespace Swift {
 
 		public slots:
 			void handleChangeSplitterState(QByteArray state);
+			void handleFontResized(int fontSizeSteps);
 
 		signals:
 			void geometryChanged();
 			void splitterMoved();
+			void fontResized(int);
 
 		protected slots:
 			void qAppFocusChanged(QWidget* old, QWidget* now);
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index 5c1f78d..ffbe3c0 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -25,9 +25,12 @@
 #include "QtContactEditWindow.h"
 #include "QtAdHocCommandWindow.h"
 
+#define CHATWINDOW_FONT_SIZE "chatWindowFontSize"
+
 namespace Swift {
 
 QtUIFactory::QtUIFactory(QtSettingsProvider* settings, QtChatTabs* tabs, QSplitter* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, bool startMinimized) : settings(settings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), lastMainWindow(NULL), loginWindow(NULL), startMinimized(startMinimized)  {
+	chatFontSize = settings->getIntSetting(CHATWINDOW_FONT_SIZE, 0);
 }
 
 XMLConsoleWidget* QtUIFactory::createXMLConsoleWidget() {
@@ -81,7 +84,26 @@ MUCSearchWindow* QtUIFactory::createMUCSearchWindow() {
 }
 
 ChatWindow* QtUIFactory::createChatWindow(const JID& contact, UIEventStream* eventStream) {
-	return chatWindowFactory->createChatWindow(contact, eventStream);
+	QtChatWindow* window = dynamic_cast<QtChatWindow*>(chatWindowFactory->createChatWindow(contact, eventStream));
+	chatWindows.push_back(window);
+	foreach (QtChatWindow* existingWindow, chatWindows) {
+		connect(window, SIGNAL(fontResized(int)), existingWindow, SLOT(handleFontResized(int)));
+		connect(existingWindow, SIGNAL(fontResized(int)), window, SLOT(handleFontResized(int)));
+	}
+	connect(window, SIGNAL(fontResized(int)), this, SLOT(handleChatWindowFontResized(int)));
+	connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(handleChatWindowDestroyed(QObject*)));
+	window->handleFontResized(chatFontSize);
+	return window;
+}
+
+void QtUIFactory::handleChatWindowFontResized(int size) {
+	chatFontSize = size;
+	settings->storeInt(CHATWINDOW_FONT_SIZE, size);
+}
+
+void QtUIFactory::handleChatWindowDestroyed(QObject* window) {
+	QtChatWindow* chatWindow = qobject_cast<QtChatWindow*>(window);
+	chatWindows.erase(std::remove(chatWindows.begin(), chatWindows.end(), chatWindow), chatWindows.end());
 }
 
 UserSearchWindow* QtUIFactory::createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups) {
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index 9ef228a..828f1b4 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -20,6 +20,7 @@ namespace Swift {
 	class QtMainWindow;
 	class QtChatTheme;
 	class QtChatWindowFactory;
+	class QtChatWindow;
 
 	class QtUIFactory : public QObject, public UIFactory {
 			Q_OBJECT
@@ -41,6 +42,8 @@ namespace Swift {
 
 		private slots:
 			void handleLoginWindowGeometryChanged();
+			void handleChatWindowDestroyed(QObject*);
+			void handleChatWindowFontResized(int);
 
 		private:
 			QtSettingsProvider* settings;
@@ -50,6 +53,8 @@ namespace Swift {
 			QtChatWindowFactory* chatWindowFactory;
 			QtMainWindow* lastMainWindow;
 			QtLoginWindow* loginWindow;
+			std::vector<QtChatWindow*> chatWindows;
 			bool startMinimized;
+			int chatFontSize;
 	};
 }
diff --git a/Swift/QtUI/QtWebView.cpp b/Swift/QtUI/QtWebView.cpp
index 9d12010..5d25071 100644
--- a/Swift/QtUI/QtWebView.cpp
+++ b/Swift/QtUI/QtWebView.cpp
@@ -59,6 +59,8 @@ void QtWebView::contextMenuEvent(QContextMenuEvent* ev) {
 
 	// Add our own custom actions
 	menu->addAction(tr("Clear"), this, SIGNAL(clearRequested()));
+	menu->addAction(tr("Increase font size"), this, SIGNAL(fontGrowRequested()));
+	menu->addAction(tr("Decrease font size"), this, SIGNAL(fontShrinkRequested()));
 
 	menu->exec(ev->globalPos());
 	delete menu;
diff --git a/Swift/QtUI/QtWebView.h b/Swift/QtUI/QtWebView.h
index fbd31e3..eb5a82d 100644
--- a/Swift/QtUI/QtWebView.h
+++ b/Swift/QtUI/QtWebView.h
@@ -22,6 +22,8 @@ namespace Swift {
 		signals:
 			void gotFocus();
 			void clearRequested();
+			void fontGrowRequested();
+			void fontShrinkRequested();
 
 		protected:
 			void focusInEvent(QFocusEvent* event);
-- 
cgit v0.10.2-6-g49f6