From 238ee0861cc2f9b0143bce986abbd15ce638c561 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Fri, 4 Oct 2013 15:20:53 +0100
Subject: Improve some access for screen readers.

Includes the start of a very ugly plain text chat log

Change-Id: I26b6d8f752164e4f8a12fe66aedc93af67345cca

diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index c8519b7..61c6f24 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -47,7 +47,7 @@ namespace Swift {
 			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState state, const std::string& msg = "") = 0;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct, bool isImpromptu, bool isContinuation) = 0;
 			virtual std::string addWhiteboardRequest(const QString& contact, bool senderIsSelf) = 0;
-			virtual void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) = 0;
+			virtual void setWhiteboardSessionStatus(const std::string& id, const ChatWindow::WhiteboardSessionState state) = 0;
 			virtual void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) = 0;
 
 			virtual void showEmoticons(bool show) = 0;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 49f57c9..bfa0663 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -45,6 +45,7 @@
 #include <SwifTools/TabComplete.h>
 
 #include <Swift/QtUI/Roster/QtOccupantListWidget.h>
+#include <Swift/QtUI/QtPlainChatView.h>
 #include <Swift/QtUI/QtSettingsProvider.h>
 #include <Swift/QtUI/QtScaledAvatarCache.h>
 #include <Swift/QtUI/QtTextEdit.h>
@@ -107,7 +108,12 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	logRosterSplitter_ = new QSplitter(this);
 	logRosterSplitter_->setAutoFillBackground(true);
 	layout->addWidget(logRosterSplitter_);
-	messageLog_ = new QtWebKitChatView(this, eventStream_, theme, this); // I accept that passing the ChatWindow in so that the view can call the signals is somewhat inelegant, but it saves a lot of boilerplate. This patch is unpleasant enough already. So let's fix this soon (it at least needs fixing by the time history is sorted), but not now.
+	if (settings_->getSetting(QtUISettingConstants::USE_PLAIN_CHATS)) {
+		messageLog_ = new QtPlainChatView(this);
+	}
+	else {
+		messageLog_ = new QtWebKitChatView(this, eventStream_, theme, this); // I accept that passing the ChatWindow in so that the view can call the signals is somewhat inelegant, but it saves a lot of boilerplate. This patch is unpleasant enough already. So let's fix this soon (it at least needs fixing by the time history is sorted), but not now.
+	}
 	logRosterSplitter_->addWidget(messageLog_);
 
 	treeWidget_ = new QtOccupantListWidget(eventStream_, settings_, this);
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index 188e55f..eeb4317 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -59,6 +59,8 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 	setWindowIcon(QIcon(":/logo-icon-16.png"));
 #endif
 	QtUtilities::setX11Resource(this, "Main");
+	setAccessibleName(tr("Swift Login Window"));
+	//setAccessibleDescription(tr("This window is used for providing credentials to log into your XMPP service"));
 
 	resize(200, 500);
 	setContentsMargins(0,0,0,0);
@@ -93,11 +95,14 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 	jidLabel->setText("<font size='-1'>" + tr("User address:") + "</font>");
 	layout->addWidget(jidLabel);
 
+
 	username_ = new QComboBox(this);
 	username_->setEditable(true);
 	username_->setWhatsThis(tr("User address - looks like someuser@someserver.com"));
 	username_->setToolTip(tr("User address - looks like someuser@someserver.com"));
 	username_->view()->installEventFilter(this);
+	username_->setAccessibleName(tr("User address (of the form someuser@someserver.com)"));
+	username_->setAccessibleDescription(tr("This is the user address that you'll be using to log in with"));
 	layout->addWidget(username_);
 	QLabel* jidHintLabel = new QLabel(this);
 	jidHintLabel->setText("<font size='-1' color='grey' >" + tr("Example: alice@wonderland.lit") + "</font>");
@@ -107,6 +112,8 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 
 	QLabel* passwordLabel = new QLabel();
 	passwordLabel->setText("<font size='-1'>" + tr("Password:") + "</font>");
+	passwordLabel->setAccessibleName(tr("User password"));
+	passwordLabel->setAccessibleDescription(tr("This is the password you'll use to log in to the XMPP service"));
 	layout->addWidget(passwordLabel);
 
 
@@ -129,6 +136,8 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 	certificateButton_->setIcon(QIcon(":/icons/certificate.png"));
 	certificateButton_->setToolTip(tr("Click if you have a personal certificate used for login to the service."));
 	certificateButton_->setWhatsThis(tr("Click if you have a personal certificate used for login to the service."));
+	certificateButton_->setAccessibleName(tr("Login with certificate"));
+	certificateButton_->setAccessibleDescription(tr("Click if you have a personal certificate used for login to the service."));
 
 	credentialsLayout->addWidget(certificateButton_);
 	connect(certificateButton_, SIGNAL(clicked(bool)), SLOT(handleCertficateChecked(bool)));
@@ -137,6 +146,7 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 	loginButton_->setText(tr("Connect"));
 	loginButton_->setAutoDefault(true);
 	loginButton_->setDefault(true);
+	loginButton_->setAccessibleName(tr("Connect now"));
 	layout->addWidget(loginButton_);
 
 	QLabel* connectionOptionsLabel = new QLabel(this);
diff --git a/Swift/QtUI/QtPlainChatView.cpp b/Swift/QtUI/QtPlainChatView.cpp
new file mode 100644
index 0000000..267b13b
--- /dev/null
+++ b/Swift/QtUI/QtPlainChatView.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swift/QtUI/QtPlainChatView.h>
+
+#include <QTextEdit>
+#include <QVBoxLayout>
+
+#include <Swiften/Base/foreach.h>
+
+#include <Swift/QtUI/ChatSnippet.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+#include <Swift/QtUI/QtUtilities.h>
+
+
+namespace Swift {
+
+QtPlainChatView::QtPlainChatView(QWidget* parent) : QtChatView(parent) {
+	QVBoxLayout* mainLayout = new QVBoxLayout(this);
+	mainLayout->setSpacing(0);
+	mainLayout->setContentsMargins(0,0,0,0);
+	log_ = new QTextEdit(this);
+	log_->setReadOnly(true);
+	mainLayout->addWidget(log_);
+}
+
+QtPlainChatView::~QtPlainChatView() {
+	
+}
+
+QString chatMessageToString(const ChatWindow::ChatMessage& message) {
+	QString result;
+	foreach (boost::shared_ptr<ChatWindow::ChatMessagePart> part, message.getParts()) {
+		boost::shared_ptr<ChatWindow::ChatTextMessagePart> textPart;
+		boost::shared_ptr<ChatWindow::ChatURIMessagePart> uriPart;
+		boost::shared_ptr<ChatWindow::ChatEmoticonMessagePart> emoticonPart;
+		boost::shared_ptr<ChatWindow::ChatHighlightingMessagePart> highlightPart;
+
+		if ((textPart = boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(part))) {
+			QString text = QtUtilities::htmlEscape(P2QSTRING(textPart->text));
+			text.replace("\n","<br/>");
+			result += text;
+			continue;
+		}
+		if ((uriPart = boost::dynamic_pointer_cast<ChatWindow::ChatURIMessagePart>(part))) {
+			QString uri = QtUtilities::htmlEscape(P2QSTRING(uriPart->target));
+			result += "<a href='" + uri + "' >" + uri + "</a>";
+			continue;
+		}
+		if ((emoticonPart = boost::dynamic_pointer_cast<ChatWindow::ChatEmoticonMessagePart>(part))) {
+			result += P2QSTRING(emoticonPart->alternativeText);
+			continue;
+		}
+		if ((highlightPart = boost::dynamic_pointer_cast<ChatWindow::ChatHighlightingMessagePart>(part))) {
+			//FIXME: Maybe do something here. Anything, really.
+			continue;
+		}
+	}
+	return result;
+}
+
+std::string QtPlainChatView::addMessage(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) {
+	QString text = "<p>";
+	if (label) {
+		text += P2QSTRING(label->getLabel()) + "<br/>";
+	}
+	QString name = senderIsSelf ? "you" : P2QSTRING(senderName);
+	text += QString(tr("At %1 %2 said:")).arg(ChatSnippet::timeToEscapedString(B2QDATE(time))).arg(name) + "<br/>";
+	text += chatMessageToString(message);
+	text += "</p>";
+	log_->append(text);
+	return "";
+};
+
+std::string QtPlainChatView::addAction(const ChatWindow::ChatMessage& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& /*avatarPath*/, const boost::posix_time::ptime& time, const HighlightAction& /*highlight*/) {
+	QString text = "<p>";
+	if (label) {
+		text += P2QSTRING(label->getLabel()) + "<br/>";
+	}
+	QString name = senderIsSelf ? "you" : P2QSTRING(senderName);
+	text += QString(tr("At %1 %2 ")).arg(ChatSnippet::timeToEscapedString(B2QDATE(time))).arg(name);
+	text += chatMessageToString(message);
+	text += "</p>";
+	log_->append(text);
+	return "";
+};
+
+
+}
diff --git a/Swift/QtUI/QtPlainChatView.h b/Swift/QtUI/QtPlainChatView.h
new file mode 100644
index 0000000..c475862
--- /dev/null
+++ b/Swift/QtUI/QtPlainChatView.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <QWidget>
+
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+
+#include <Swift/QtUI/QtChatView.h>
+
+class QTextEdit;
+
+namespace Swift {
+	class HighlightAction;
+	class SecurityLabel;
+
+	class QtPlainChatView : public QtChatView {
+		Q_OBJECT
+		public:
+			QtPlainChatView(QWidget* parent);
+			virtual ~QtPlainChatView();
+
+			/** Add message to window.
+			 * @return id of added message (for acks).
+			 */
+			virtual std::string addMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);
+			/** Adds action to window.
+			 * @return id of added message (for acks);
+			 */
+			virtual std::string addAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);
+
+			virtual void addSystemMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/) {};
+			virtual void addPresenceMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/) {};
+
+			virtual void addErrorMessage(const ChatWindow::ChatMessage& /*message*/) {};
+			virtual void replaceMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {};
+			virtual void replaceWithAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {};
+			virtual void replaceLastMessage(const ChatWindow::ChatMessage& /*message*/) {};
+			virtual void setAckState(const std::string& /*id*/, ChatWindow::AckState /*state*/) {};
+			
+			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/, const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) {return "";};
+			virtual void setFileTransferProgress(std::string, const int /*percentageDone*/) {};
+			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState /*state*/, const std::string& /*msg*/ = "") {};
+			virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool /*direct*/, bool /*isImpromptu*/, bool /*isContinuation*/) {};
+			virtual std::string addWhiteboardRequest(const QString& /*contact*/, bool /*senderIsSelf*/) {return "";};
+			virtual void setWhiteboardSessionStatus(const std::string& /*id*/, const ChatWindow::WhiteboardSessionState /*state*/) {};
+			virtual void setMessageReceiptState(const std::string& /*id*/, ChatWindow::ReceiptState /*state*/) {};
+
+			virtual void showEmoticons(bool /*show*/) {};
+			virtual void addLastSeenLine() {};
+
+		public slots:
+			virtual void resizeFont(int /*fontSizeSteps*/) {};
+			virtual void scrollToBottom() {};
+			virtual void handleKeyPressEvent(QKeyEvent* /*event*/) {};
+
+		private:
+			QTextEdit* log_;
+
+	};
+}
diff --git a/Swift/QtUI/QtUISettingConstants.cpp b/Swift/QtUI/QtUISettingConstants.cpp
index 68001d7..1ff3beb 100644
--- a/Swift/QtUI/QtUISettingConstants.cpp
+++ b/Swift/QtUI/QtUISettingConstants.cpp
@@ -15,4 +15,5 @@ const SettingsProvider::Setting<bool> QtUISettingConstants::SHOW_NICK_IN_ROSTER_
 const SettingsProvider::Setting<int> QtUISettingConstants::CHATWINDOW_FONT_SIZE("chatWindowFontSize", 0);
 const SettingsProvider::Setting<int> QtUISettingConstants::HISTORYWINDOW_FONT_SIZE("historyWindowFontSize", 0);
 const SettingsProvider::Setting<bool> QtUISettingConstants::SHOW_EMOTICONS("showEmoticons", true);
+const SettingsProvider::Setting<bool> QtUISettingConstants::USE_PLAIN_CHATS("plainChats", false);
 }
diff --git a/Swift/QtUI/QtUISettingConstants.h b/Swift/QtUI/QtUISettingConstants.h
index 8ac835f..31085c1 100644
--- a/Swift/QtUI/QtUISettingConstants.h
+++ b/Swift/QtUI/QtUISettingConstants.h
@@ -18,5 +18,6 @@ namespace Swift {
 			static const SettingsProvider::Setting<int> CHATWINDOW_FONT_SIZE;
 			static const SettingsProvider::Setting<int> HISTORYWINDOW_FONT_SIZE;
 			static const SettingsProvider::Setting<bool> SHOW_EMOTICONS;
+			static const SettingsProvider::Setting<bool> USE_PLAIN_CHATS;
 	};
 }
diff --git a/Swift/QtUI/QtWebKitChatView.cpp b/Swift/QtUI/QtWebKitChatView.cpp
index bc57de4..af21609 100644
--- a/Swift/QtUI/QtWebKitChatView.cpp
+++ b/Swift/QtUI/QtWebKitChatView.cpp
@@ -720,7 +720,7 @@ std::string QtWebKitChatView::addWhiteboardRequest(const QString& contact, bool
 	return Q2PSTRING(wb_id);
 }
 
-void QtWebKitChatView::setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) {
+void QtWebKitChatView::setWhiteboardSessionStatus(const std::string& id, const ChatWindow::WhiteboardSessionState state) {
 	setWhiteboardSessionStatus(P2QSTRING(id), state);
 }
 
diff --git a/Swift/QtUI/QtWebKitChatView.h b/Swift/QtUI/QtWebKitChatView.h
index 6bdaf96..bdb2a75 100644
--- a/Swift/QtUI/QtWebKitChatView.h
+++ b/Swift/QtUI/QtWebKitChatView.h
@@ -69,7 +69,7 @@ namespace Swift {
 			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState state, const std::string& msg = "") SWIFTEN_OVERRIDE;
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct, bool isImpromptu, bool isContinuation) SWIFTEN_OVERRIDE;
 			virtual std::string addWhiteboardRequest(const QString& contact, bool senderIsSelf) SWIFTEN_OVERRIDE;
-			virtual void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) SWIFTEN_OVERRIDE;
+			virtual void setWhiteboardSessionStatus(const std::string& id, const ChatWindow::WhiteboardSessionState state) SWIFTEN_OVERRIDE;
 			virtual void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) SWIFTEN_OVERRIDE;
 
 			virtual void showEmoticons(bool show) SWIFTEN_OVERRIDE;
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 6835872..5cfe81f 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -105,6 +105,7 @@ sources = [
     "QtChatWindow.cpp",
     "QtChatView.cpp",
     "QtWebKitChatView.cpp",
+    "QtPlainChatView.cpp",
     "QtChatTheme.cpp",
     "QtChatTabs.cpp",
     "QtSoundPlayer.cpp",
-- 
cgit v0.10.2-6-g49f6