summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-08-29 22:32:59 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-08-30 14:53:32 (GMT)
commitb9b535ffd46382c413504a1781400c1a554e04a8 (patch)
tree723b1e948930478e0324c374f74f1fabc88699ec /Swift
parent5546afc2bbf8ab0fd49647150da7a5f3df01deaf (diff)
downloadswift-b9b535ffd46382c413504a1781400c1a554e04a8.zip
swift-b9b535ffd46382c413504a1781400c1a554e04a8.tar.bz2
Render the Chat view directly with DOM commands, not javascript.
Tested locally, but it's conceivable there will be regressions.
Diffstat (limited to 'Swift')
-rw-r--r--Swift/QtUI/ChatSnippet.cpp10
-rw-r--r--Swift/QtUI/ChatSnippet.h2
-rw-r--r--Swift/QtUI/MessageSnippet.cpp14
-rw-r--r--Swift/QtUI/MessageSnippet.h4
-rw-r--r--Swift/QtUI/QtChatTheme.cpp67
-rw-r--r--Swift/QtUI/QtChatTheme.h40
-rw-r--r--Swift/QtUI/QtChatView.cpp112
-rw-r--r--Swift/QtUI/QtChatView.h22
-rw-r--r--Swift/QtUI/QtChatWindow.cpp13
-rw-r--r--Swift/QtUI/QtChatWindow.h10
-rw-r--r--Swift/QtUI/QtChatWindowFactory.cpp18
-rw-r--r--Swift/QtUI/QtChatWindowFactory.h6
-rw-r--r--Swift/QtUI/QtSwift.cpp5
-rw-r--r--Swift/QtUI/SConscript1
-rw-r--r--Swift/QtUI/SystemMessageSnippet.cpp8
-rw-r--r--Swift/QtUI/SystemMessageSnippet.h7
16 files changed, 260 insertions, 79 deletions
diff --git a/Swift/QtUI/ChatSnippet.cpp b/Swift/QtUI/ChatSnippet.cpp
index 5eb6268..2218c07 100644
--- a/Swift/QtUI/ChatSnippet.cpp
+++ b/Swift/QtUI/ChatSnippet.cpp
@@ -16,16 +16,6 @@ ChatSnippet::ChatSnippet(bool appendToPrevious) : appendToPrevious_(appendToPrev
ChatSnippet::~ChatSnippet() {
}
-QString ChatSnippet::loadTemplate(const QString& filename) {
- QFile file(filename);
- bool result = file.open(QIODevice::ReadOnly);
- Q_ASSERT(result);
- Q_UNUSED(result);
- QString content = file.readAll();
- file.close();
- return content;
-}
-
QString ChatSnippet::escape(const QString& original) {
QString result(original);
result.replace("%message%", "&#37;message&#37;");
diff --git a/Swift/QtUI/ChatSnippet.h b/Swift/QtUI/ChatSnippet.h
index 8a574c6..9345f61 100644
--- a/Swift/QtUI/ChatSnippet.h
+++ b/Swift/QtUI/ChatSnippet.h
@@ -7,6 +7,7 @@
#pragma once
#include <QString>
+#include "QtChatTheme.h"
namespace Swift {
class ChatSnippet {
@@ -22,7 +23,6 @@ namespace Swift {
}
protected:
- QString loadTemplate(const QString& file);
static QString escape(const QString&);
private:
diff --git a/Swift/QtUI/MessageSnippet.cpp b/Swift/QtUI/MessageSnippet.cpp
index 995248a..ebcc829 100644
--- a/Swift/QtUI/MessageSnippet.cpp
+++ b/Swift/QtUI/MessageSnippet.cpp
@@ -11,21 +11,21 @@
namespace Swift {
-MessageSnippet::MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious) : ChatSnippet(appendToPrevious) {
+MessageSnippet::MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme) : ChatSnippet(appendToPrevious) {
if (isIncoming) {
if (appendToPrevious) {
- content_ = loadTemplate(":/themes/Default/Incoming/NextContent.html");
+ content_ = theme->getIncomingNextContent();
}
else {
- content_ = loadTemplate(":/themes/Default/Incoming/Content.html");
+ content_ = theme->getIncomingContent();
}
}
else {
if (appendToPrevious) {
- content_ = loadTemplate(":/themes/Default/Outgoing/NextContent.html");
+ content_ = theme->getOutgoingNextContent();
}
else {
- content_ = loadTemplate(":/themes/Default/Outgoing/Content.html");
+ content_ = theme->getOutgoingContent();
}
}
@@ -35,4 +35,8 @@ MessageSnippet::MessageSnippet(const QString& message, const QString& sender, co
content_.replace("%userIconPath%", escape(iconURI));
}
+MessageSnippet::~MessageSnippet() {
+
+}
+
}
diff --git a/Swift/QtUI/MessageSnippet.h b/Swift/QtUI/MessageSnippet.h
index 8e624f8..4918c19 100644
--- a/Swift/QtUI/MessageSnippet.h
+++ b/Swift/QtUI/MessageSnippet.h
@@ -15,8 +15,8 @@ class QDateTime;
namespace Swift {
class MessageSnippet : public ChatSnippet {
public:
- MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious);
-
+ MessageSnippet(const QString& message, const QString& sender, const QDateTime& time, const QString& iconURI, bool isIncoming, bool appendToPrevious, QtChatTheme* theme);
+ virtual ~MessageSnippet();
const QString& getContent() const {
return content_;
}
diff --git a/Swift/QtUI/QtChatTheme.cpp b/Swift/QtUI/QtChatTheme.cpp
new file mode 100644
index 0000000..afcf665
--- /dev/null
+++ b/Swift/QtUI/QtChatTheme.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 Kevin Smith.
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "QtChatTheme.h"
+
+#include <QFile>
+#include <qdebug.h>
+
+namespace Swift {
+
+/**
+ * Load Adium themes, as http://trac.adium.im/wiki/CreatingMessageStyles
+ */
+QtChatTheme::QtChatTheme(const QString& themePath) : qrc_(themePath.isEmpty()), themePath_(qrc_ ? ":/themes/Default/" : themePath + "/Contents/Resources/") {
+ QString fileNames[EndMarker];
+ fileNames[Header] = "Header.html";
+ fileNames[Footer] = "Footer.html";
+ fileNames[Content] = "Content.html";
+ fileNames[Status] = "Status.html";
+ fileNames[Topic] = "Topic.html";
+ fileNames[FileTransferRequest] = "FileTransferRequest.html";
+ fileNames[IncomingContent] = "Incoming/Content.html";
+ fileNames[IncomingNextContent] = "Incoming/NextContent.html";
+ fileNames[IncomingContext] = "Incoming/Context.html";
+ fileNames[IncomingNextContext] = "Incoming/NextContext.html";
+ fileNames[OutgoingContent] = "Outgoing/Content.html";
+ fileNames[OutgoingNextContent] = "Outgoing/NextContent.html";
+ fileNames[OutgoingContext] = "Outgoing/Context.html";
+ fileNames[OutgoingNextContext] = "Outgoing/NextContext.html";
+ fileNames[Template] = "Template.html";
+ fileNames[MainCSS] = "main.css";
+ fileNames[TemplateDefault] = ":/themes/Template.html";
+ for (int i = 0; i < EndMarker; i++) {
+ QString source;
+ QFile sourceFile((i != TemplateDefault ? themePath_ : "") + fileNames[i]);
+ if (sourceFile.exists() && sourceFile.open(QIODevice::ReadOnly)) {
+ source = sourceFile.readAll();
+ sourceFile.close();
+ } else {
+ //qWarning() << "Couldn't load file " << sourceFile.fileName();
+ }
+ fileContents_.append(source);
+ }
+
+ /* Fallbacks */
+ if (fileContents_[Template].isEmpty()) fileContents_[Template] = fileContents_[TemplateDefault];
+ if (fileContents_[Status].isEmpty()) fileContents_[Status] = fileContents_[Content];
+ if (fileContents_[IncomingContent].isEmpty()) fileContents_[IncomingContent] = fileContents_[Content];
+ if (fileContents_[IncomingNextContent].isEmpty()) fileContents_[IncomingNextContent] = fileContents_[IncomingContent];
+ if (fileContents_[FileTransferRequest].isEmpty()) fileContents_[FileTransferRequest] = fileContents_[Status];
+ if (fileContents_[IncomingContext].isEmpty()) fileContents_[IncomingContext] = fileContents_[IncomingContent];
+ if (fileContents_[IncomingNextContext].isEmpty()) fileContents_[IncomingNextContext] = fileContents_[IncomingNextContent];
+ if (fileContents_[OutgoingContent].isEmpty()) fileContents_[OutgoingContent] = fileContents_[IncomingContent];
+ if (fileContents_[OutgoingContext].isEmpty()) fileContents_[OutgoingContext] = fileContents_[OutgoingContent];
+ if (fileContents_[OutgoingNextContent].isEmpty()) fileContents_[OutgoingNextContent] = fileContents_[OutgoingContent];
+ if (fileContents_[OutgoingNextContext].isEmpty()) fileContents_[OutgoingNextContext] = fileContents_[OutgoingNextContent];
+
+}
+
+QString QtChatTheme::getBase() {
+ return qrc_ ? "qrc" + themePath_ : "file://" + themePath_;
+}
+
+}
diff --git a/Swift/QtUI/QtChatTheme.h b/Swift/QtUI/QtChatTheme.h
new file mode 100644
index 0000000..199c66d
--- /dev/null
+++ b/Swift/QtUI/QtChatTheme.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 Kevin Smith.
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <QString>
+#include <QList>
+
+namespace Swift {
+ class QtChatTheme {
+ public:
+ QtChatTheme(const QString& themePath);
+ QString getHeader() {return fileContents_[Header];};
+ QString getFooter() {return fileContents_[Footer];};
+ QString getContent() {return fileContents_[Content];};
+ QString getStatus() {return fileContents_[Status];};
+ QString getTopic() {return fileContents_[Topic];};
+ QString getFileTransferRequest() {return fileContents_[FileTransferRequest];};
+ QString getIncomingContent() {return fileContents_[IncomingContent];};
+ QString getIncomingNextContent() {return fileContents_[IncomingNextContent];};
+ QString getIncomingContext() {return fileContents_[IncomingContext];};
+ QString getIncomingNextContext() {return fileContents_[IncomingNextContext];};
+ QString getOutgoingContent() {return fileContents_[OutgoingContent];};
+ QString getOutgoingNextContent() {return fileContents_[OutgoingNextContent];};
+ QString getOutgoingContext() {return fileContents_[OutgoingContext];};
+ QString getOutgoingNextContext() {return fileContents_[OutgoingNextContext];};
+ QString getTemplate() {return fileContents_[Template];}
+ QString getMainCSS() {return fileContents_[MainCSS];}
+ QString getBase();
+
+ private:
+ enum files {Header = 0, Footer, Content, Status, Topic, FileTransferRequest, IncomingContent, IncomingNextContent, IncomingContext, IncomingNextContext, OutgoingContent, OutgoingNextContent, OutgoingContext, OutgoingNextContext, Template, MainCSS, TemplateDefault, EndMarker};
+ bool qrc_;
+ QList<QString> fileContents_;
+ QString themePath_;
+ };
+}
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index 90b567f..1c4ed18 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -15,10 +15,13 @@
#include <QStackedWidget>
#include "QtWebView.h"
+#include "QtChatTheme.h"
+
namespace Swift {
-QtChatView::QtChatView(QWidget* parent) : QWidget(parent) {
+QtChatView::QtChatView(QtChatTheme* theme, QWidget* parent) : QWidget(parent) {
+ theme_ = theme;
QVBoxLayout* mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(0);
@@ -46,54 +49,79 @@ QtChatView::QtChatView(QWidget* parent) : QWidget(parent) {
webView_->setPage(webPage_);
connect(webPage_, SIGNAL(selectionChanged()), SLOT(copySelectionToClipboard()));
- QFile file(":/themes/Default/Template.html");
- bool result = file.open(QIODevice::ReadOnly);
- Q_ASSERT(result);
- Q_UNUSED(result);
- QString pageHTML = file.readAll();
+ viewReady_ = false;
+ QString pageHTML = theme_->getTemplate();
pageHTML.replace("==bodyBackground==", "background-color:#e3e3e3");
- pageHTML.replace(pageHTML.indexOf("%@"), 2, "qrc:/themes/Default/");
+ pageHTML.replace(pageHTML.indexOf("%@"), 2, theme_->getBase());
+ if (pageHTML.count("%@") > 3) {
+ pageHTML.replace(pageHTML.indexOf("%@"), 2, theme_->getMainCSS());
+ }
pageHTML.replace(pageHTML.indexOf("%@"), 2, "Variants/Blue on Green.css");
- pageHTML.replace(pageHTML.indexOf("%@"), 2, "");
- pageHTML.replace(pageHTML.indexOf("%@"), 2, "");
- file.close();
-
- viewReady_ = false;
+ pageHTML.replace(pageHTML.indexOf("%@"), 2, ""/*headerSnippet.getContent()*/);
+ pageHTML.replace(pageHTML.indexOf("%@"), 2, ""/*footerSnippet.getContent()*/);
webPage_->mainFrame()->setHtml(pageHTML);
+ document_ = webPage_->mainFrame()->documentElement();
+ QWebElement chatElement = document_.findFirst("#Chat");
+ newInsertPoint_ = chatElement.clone();
+ newInsertPoint_.setOuterXml("<div id='insert'/>");
+ chatElement.appendInside(newInsertPoint_);
+ if (newInsertPoint_.isNull()) {
+ qWarning() << "Warning, initial insert point element is null!";
+ }
}
void QtChatView::handleKeyPressEvent(QKeyEvent* event) {
webView_->keyPressEvent(event);
}
-void QtChatView::addMessage(const ChatSnippet& snippet) {
- //bool wasScrolledToBottom = isScrolledToBottom();
-
- QString content = snippet.getContent();
- content.replace("\\", "\\\\");
- content.replace("\"", "\\\"");
- content.replace("\n", "\\n");
- content.replace("\r", "");
- QString command;
- if (previousContinuationElementID_.isEmpty() || !snippet.getAppendToPrevious()) {
- command = "appendMessage(\"" + content + "\");";
- }
- else {
- command = "appendNextMessage(\"" + content + "\");";
- }
+void QtChatView::addMessage(boost::shared_ptr<ChatSnippet> snippet) {
if (viewReady_) {
- webPage_->mainFrame()->evaluateJavaScript(command);
- }
- else {
- queuedMessages_ += command;
+ addToDOM(snippet);
+ } else {
+ queuedSnippets_.append(snippet);
}
+// QString content = snippet.getContent();
+// content.replace("\\", "\\\\");
+// content.replace("\"", "\\\"");
+// content.replace("\n", "\\n");
+// content.replace("\r", "");
+// QString command;
+// if (previousContinuationElementID_.isEmpty() || !snippet.getAppendToPrevious()) {
+// command = "appendMessage(\"" + content + "\");";
+// }
+// else {
+// command = "appendNextMessage(\"" + content + "\");";
+// }
+// if (viewReady_) {
+// webPage_->mainFrame()->evaluateJavaScript(command);
+// }
+// else {
+// queuedMessages_ += command;
+// }
+//
+// previousContinuationElementID_ = snippet.getContinuationElementID();
- //qDebug() << webPage_->mainFrame()->toHtml();
- previousContinuationElementID_ = snippet.getContinuationElementID();
+}
- /*if (wasScrolledToBottom) {
- scrollToBottom();
- }*/
+QWebElement QtChatView::snippetToDOM(boost::shared_ptr<ChatSnippet> snippet) {
+ QWebElement newElement = newInsertPoint_.clone();
+ newElement.setInnerXml(snippet->getContent()); /* FIXME: Outer, surely? */
+ if (newElement.isNull()) {
+ qWarning() << "Warning, new element is null!";
+ }
+ return newElement;
+}
+
+void QtChatView::addToDOM(boost::shared_ptr<ChatSnippet> snippet) {
+ QWebElement newElement = snippetToDOM(snippet);
+ QWebElement continuationElement = lastElement_.findFirst("#insert");
+ if (snippet->getAppendToPrevious()) {
+ continuationElement.replace(newElement);
+ } else {
+ continuationElement.removeFromDocument();
+ newInsertPoint_.prependOutside(newElement);
+ }
+ lastElement_ = newElement;
}
void QtChatView::copySelectionToClipboard() {
@@ -114,11 +142,19 @@ void QtChatView::handleLinkClicked(const QUrl& url) {
QDesktopServices::openUrl(url);
}
+void QtChatView::addQueuedSnippets() {
+ for (int i = 0; i < queuedSnippets_.count(); i++) {
+ addToDOM(queuedSnippets_[i]);
+ }
+ queuedSnippets_.clear();
+}
+
void QtChatView::handleViewLoadFinished(bool ok) {
Q_ASSERT(ok);
viewReady_ = true;
- webPage_->mainFrame()->evaluateJavaScript(queuedMessages_);
- queuedMessages_.clear();
+ addQueuedSnippets();
+// webPage_->mainFrame()->evaluateJavaScript(queuedMessages_);
+// queuedMessages_.clear();
}
}
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index f60d049..3936c18 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -9,6 +9,10 @@
#include <QString>
#include <QWidget>
+#include <QList>
+#include <QWebElement>
+
+#include <boost/shared_ptr.hpp>
#include "ChatSnippet.h"
@@ -17,12 +21,13 @@ class QUrl;
namespace Swift {
class QtWebView;
+ class QtChatTheme;
class QtChatView : public QWidget {
Q_OBJECT
public:
- QtChatView(QWidget* parent);
+ QtChatView(QtChatTheme* theme, QWidget* parent);
- void addMessage(const ChatSnippet& snippet);
+ void addMessage(boost::shared_ptr<ChatSnippet> snippet);
bool isScrolledToBottom() const;
signals:
@@ -38,11 +43,22 @@ namespace Swift {
void handleViewLoadFinished(bool);
private:
+ void headerEncode();
+ void messageEncode();
+ void addQueuedSnippets();
+ void addToDOM(boost::shared_ptr<ChatSnippet> snippet);
+ QWebElement snippetToDOM(boost::shared_ptr<ChatSnippet> snippet);
+
bool viewReady_;
QtWebView* webView_;
QWebPage* webPage_;
QString previousContinuationElementID_;
- QString queuedMessages_;
+ QList<boost::shared_ptr<ChatSnippet> > queuedSnippets_;
+
+ QtChatTheme* theme_;
+ QWebElement newInsertPoint_;
+ QWebElement lastElement_;
+ QWebElement document_;
};
}
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index de681d5..73bf2c2 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -28,10 +28,11 @@
#include <QUrl>
namespace Swift {
-QtChatWindow::QtChatWindow(const QString &contact, UIEventStream* eventStream) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), eventStream_(eventStream) {
+QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), eventStream_(eventStream) {
unreadCount_ = 0;
inputEnabled_ = true;
completer_ = NULL;
+ theme_ = theme;
updateTitleWithUnreadCount();
QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
@@ -43,7 +44,7 @@ QtChatWindow::QtChatWindow(const QString &contact, UIEventStream* eventStream) :
logRosterSplitter->setAutoFillBackground(true);
layout->addWidget(logRosterSplitter);
- messageLog_ = new QtChatView(this);
+ messageLog_ = new QtChatView(theme, this);
logRosterSplitter->addWidget(messageLog_);
treeWidget_ = new QtTreeWidget(eventStream_);
@@ -267,7 +268,7 @@ void QtChatWindow::addMessage(const String &message, const String &senderName, b
bool appendToPrevious = !previousMessageWasSystem_ && !previousMessageWasPresence_ && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_ && previousSenderName_ == P2QSTRING(senderName)));
QString qAvatarPath = avatarPath.isEmpty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(P2QSTRING(avatarPath)).toEncoded();
- messageLog_->addMessage(MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious));
+ messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_)));
previousMessageWasSelf_ = senderIsSelf;
previousSenderName_ = P2QSTRING(senderName);
@@ -290,7 +291,7 @@ void QtChatWindow::addErrorMessage(const String& errorMessage) {
QString errorMessageHTML(Qt::escape(P2QSTRING(errorMessage)));
errorMessageHTML.replace("\n","<br/>");
- messageLog_->addMessage(SystemMessageSnippet(QString("<span class=\"error\">%1</span>").arg(errorMessageHTML), QDateTime::currentDateTime(),previousMessageWasSystem_));
+ messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(QString("<span class=\"error\">%1</span>").arg(errorMessageHTML), QDateTime::currentDateTime(),previousMessageWasSystem_, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = true;
@@ -304,7 +305,7 @@ void QtChatWindow::addSystemMessage(const String& message) {
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML.replace("\n","<br/>");
- messageLog_->addMessage(SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(),previousMessageWasSystem_));
+ messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(),previousMessageWasSystem_, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = true;
@@ -318,7 +319,7 @@ void QtChatWindow::addPresenceMessage(const String& message) {
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML.replace("\n","<br/>");
- messageLog_->addMessage(SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), previousMessageWasPresence_));
+ messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), previousMessageWasPresence_, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = false;
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 1770186..2b006d9 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -19,13 +19,14 @@ namespace Swift {
class QtChatView;
class QtTreeWidget;
class QtTreeWidgetFactory;
+ class QtChatTheme;
class TreeWidget;
class QtTextEdit;
class UIEventStream;
class QtChatWindow : public QtTabbable, public ChatWindow {
Q_OBJECT
public:
- QtChatWindow(const QString &contact, UIEventStream* eventStream);
+ QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream);
~QtChatWindow();
void addMessage(const String &message, const String &senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time);
void addAction(const String &message, const String &senderName, bool senderIsSelf, const boost::optional<SecurityLabel>& label, const String& avatarPath, const boost::posix_time::ptime& time);
@@ -74,10 +75,11 @@ namespace Swift {
int unreadCount_;
bool contactIsTyping_;
QString contact_;
- QtChatView *messageLog_;
+ QtChatView* messageLog_;
+ QtChatTheme* theme_;
QtTextEdit* input_;
- QComboBox *labelsWidget_;
- QtTreeWidget *treeWidget_;
+ QComboBox* labelsWidget_;
+ QtTreeWidget* treeWidget_;
TabComplete* completer_;
std::vector<SecurityLabel> availableLabels_;
bool previousMessageWasSelf_;
diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp
index 9787c2c..d146474 100644
--- a/Swift/QtUI/QtChatWindowFactory.cpp
+++ b/Swift/QtUI/QtChatWindowFactory.cpp
@@ -11,12 +11,15 @@
#include "QtChatTabs.h"
#include "QtChatWindow.h"
#include "QtSwiftUtil.h"
+#include "QtChatTheme.h"
+#include <qdebug.h>
namespace Swift {
-QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs) {
+QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath) : themePath_(themePath) {
settings_ = settings;
tabs_ = tabs;
+ theme_ = NULL;
if (splitter) {
splitter->addWidget(tabs_);
} else if (tabs_) {
@@ -28,8 +31,19 @@ QtChatWindowFactory::QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider
}
}
+QtChatWindowFactory::~QtChatWindowFactory() {
+ delete theme_;
+}
+
ChatWindow* QtChatWindowFactory::createChatWindow(const JID &contact,UIEventStream* eventStream) {
- QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), eventStream);
+ if (!theme_) {
+ theme_ = new QtChatTheme(themePath_);
+ if (theme_->getIncomingContent().isEmpty()) {
+ delete theme_;
+ theme_ = new QtChatTheme(""); /* Use the inbuilt theme */
+ }
+ }
+ QtChatWindow *chatWindow = new QtChatWindow(P2QSTRING(contact.toString()), theme_, eventStream);
if (tabs_) {
tabs_->addTab(chatWindow);
} else {
diff --git a/Swift/QtUI/QtChatWindowFactory.h b/Swift/QtUI/QtChatWindowFactory.h
index 4ffac88..0d47854 100644
--- a/Swift/QtUI/QtChatWindowFactory.h
+++ b/Swift/QtUI/QtChatWindowFactory.h
@@ -14,17 +14,21 @@
#include <QSplitter>
namespace Swift {
class QtChatTabs;
+ class QtChatTheme;
class UIEventStream;
class QtChatWindowFactory : public QObject, public ChatWindowFactory {
Q_OBJECT
public:
- QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs);
+ QtChatWindowFactory(QSplitter* splitter, QtSettingsProvider* settings, QtChatTabs* tabs, const QString& themePath);
+ ~QtChatWindowFactory();
ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream);
private slots:
void handleWindowGeometryChanged();
private:
+ QString themePath_;
QtSettingsProvider* settings_;
QtChatTabs* tabs_;
+ QtChatTheme* theme_;
};
}
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 0405681..e1f5e89 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -6,6 +6,8 @@
#include "QtSwift.h"
+#include <string>
+
#include "QtLoginWindowFactory.h"
#include "QtChatWindowFactory.h"
#include "QtLoginWindow.h"
@@ -13,6 +15,7 @@
#include "QtMainWindowFactory.h"
#include "QtSystemTray.h"
#include "QtSoundPlayer.h"
+#include "QtSwiftUtil.h"
#include "QtXMLConsoleWidgetFactory.h"
#include "ChatList/QtChatListWindowFactory.h"
#include "EventViewer/QtEventWindowFactory.h"
@@ -81,7 +84,7 @@ QtSwift::QtSwift(po::variables_map options) : autoUpdater_(NULL) {
applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME);
avatarStorage_ = new AvatarFileStorage(applicationPathProvider_->getAvatarDir());
vcardStorageFactory_ = new VCardFileStorageFactory(applicationPathProvider_->getDataDir());
- chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_);
+ chatWindowFactory_ = new QtChatWindowFactory(splitter_, settings_, tabs_, "");
soundPlayer_ = new QtSoundPlayer(applicationPathProvider_);
if (splitter_) {
splitter_->show();
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index f119397..9f08f4f 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -64,6 +64,7 @@ sources = [
"QtStatusWidget.cpp",
"QtSwift.cpp",
"QtChatView.cpp",
+ "QtChatTheme.cpp",
"QtChatTabs.cpp",
"QtSoundPlayer.cpp",
"QtSystemTray.cpp",
diff --git a/Swift/QtUI/SystemMessageSnippet.cpp b/Swift/QtUI/SystemMessageSnippet.cpp
index ba0ec1b..db57b1f 100644
--- a/Swift/QtUI/SystemMessageSnippet.cpp
+++ b/Swift/QtUI/SystemMessageSnippet.cpp
@@ -10,12 +10,16 @@
namespace Swift {
-SystemMessageSnippet::SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious) : ChatSnippet(appendToPrevious) {
- content_ = loadTemplate(":/themes/Default/Status.html");
+SystemMessageSnippet::SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme) : ChatSnippet(appendToPrevious) {
+ content_ = theme->getStatus();
content_.replace("%message%", escape(message));
content_.replace("%shortTime%", escape(time.toString("h:mm")));
content_.replace("%time%", escape(time.toString("h:mm")));
}
+SystemMessageSnippet::~SystemMessageSnippet() {
+
+}
+
}
diff --git a/Swift/QtUI/SystemMessageSnippet.h b/Swift/QtUI/SystemMessageSnippet.h
index 8342476..69d231f 100644
--- a/Swift/QtUI/SystemMessageSnippet.h
+++ b/Swift/QtUI/SystemMessageSnippet.h
@@ -15,11 +15,10 @@ class QDateTime;
namespace Swift {
class SystemMessageSnippet : public ChatSnippet {
public:
- SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious);
+ SystemMessageSnippet(const QString& message, const QDateTime& time, bool appendToPrevious, QtChatTheme* theme);
+ virtual ~SystemMessageSnippet();
- const QString& getContent() const {
- return content_;
- }
+ const QString& getContent() const {return content_;}
/*QString getContinuationElementID() const {
return "insert";