summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2011-10-11 17:17:42 (GMT)
committerKevin Smith <git@kismith.co.uk>2011-10-11 17:23:28 (GMT)
commita6375f56f0df8853914955d3a4b3f6cde8f0f88b (patch)
tree4b14f6a8d4a4f9e9f19da8d786b58466330a6142 /Swift
parentf48dc68662988b6eeb6544c2425c179b1f9b973d (diff)
downloadswift-contrib-a6375f56f0df8853914955d3a4b3f6cde8f0f88b.zip
swift-contrib-a6375f56f0df8853914955d3a4b3f6cde8f0f88b.tar.bz2
Fix DOM element finding for message correction
Diffstat (limited to 'Swift')
-rw-r--r--Swift/QtUI/QtChatView.cpp3
-rw-r--r--Swift/QtUI/QtChatWindow.cpp10
-rw-r--r--Swift/QtUI/QtChatWindow.h4
3 files changed, 11 insertions, 6 deletions
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index 97ce992..1c3dd37 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -144,70 +144,73 @@ void QtChatView::replaceLastMessage(const QString& newMessage) {
QWebElement replace = lastElement_.findFirst("span.swift_message");
assert(!replace.isNull());
QString old = lastElement_.toOuterXml();
replace.setInnerXml(ChatSnippet::escape(newMessage));
}
void QtChatView::replaceLastMessage(const QString& newMessage, const QString& note) {
rememberScrolledToBottom();
replaceLastMessage(newMessage);
QWebElement replace = lastElement_.findFirst("span.swift_time");
assert(!replace.isNull());
replace.setInnerXml(ChatSnippet::escape(note));
}
QString QtChatView::getLastSentMessage() {
return lastElement_.toPlainText();
}
void QtChatView::addToJSEnvironment(const QString& name, QObject* obj) {
webView_->page()->currentFrame()->addToJavaScriptWindowObject(name, obj);
}
void QtChatView::replaceMessage(const QString& newMessage, const QString& id, const QDateTime& editTime) {
rememberScrolledToBottom();
QWebElement message = document_.findFirst("#" + id);
if (!message.isNull()) {
QWebElement replaceContent = message.findFirst("span.swift_message");
assert(!replaceContent.isNull());
QString old = replaceContent.toOuterXml();
replaceContent.setInnerXml(ChatSnippet::escape(newMessage));
QWebElement replaceTime = message.findFirst("span.swift_time");
assert(!replaceTime.isNull());
old = replaceTime.toOuterXml();
replaceTime.setInnerXml(ChatSnippet::escape(tr("%1 edited").arg(ChatSnippet::timeToEscapedString(editTime))));
}
+ else {
+ qWarning() << "Trying to replace element with id " << id << " but it's not there.";
+ }
}
void QtChatView::copySelectionToClipboard() {
if (!webPage_->selectedText().isEmpty()) {
webPage_->triggerAction(QWebPage::Copy);
}
}
void QtChatView::setAckXML(const QString& id, const QString& xml) {
QWebElement message = document_.findFirst("#" + id);
/* Deliberately not asserting here, so that when we start expiring old messages it won't hit us */
if (message.isNull()) return;
QWebElement ackElement = message.findFirst("span.swift_ack");
assert(!ackElement.isNull());
ackElement.setInnerXml(xml);
}
void QtChatView::rememberScrolledToBottom() {
isAtBottom_ = webPage_->mainFrame()->scrollBarValue(Qt::Vertical) == webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical);
}
void QtChatView::scrollToBottom() {
isAtBottom_ = true;
webPage_->mainFrame()->setScrollBarValue(Qt::Vertical, webPage_->mainFrame()->scrollBarMaximum(Qt::Vertical));
webView_->update(); /* Work around redraw bug in some versions of Qt. */
}
void QtChatView::handleFrameSizeChanged() {
if (isAtBottom_) {
scrollToBottom();
}
}
void QtChatView::handleLinkClicked(const QUrl& url) {
QDesktopServices::openUrl(url);
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 0635496..6b6dedf 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -19,70 +19,71 @@
#include "QtScaledAvatarCache.h"
#include "SwifTools/TabComplete.h"
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include "QtFileTransferJSBridge.h"
#include <boost/cstdint.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <QLabel>
#include <QMessageBox>
#include <QInputDialog>
#include <QApplication>
#include <QBoxLayout>
#include <QCloseEvent>
#include <QComboBox>
#include <QFileInfo>
#include <QLineEdit>
#include <QSplitter>
#include <QString>
#include <QTextEdit>
#include <QTime>
#include <QUrl>
#include <QPushButton>
#include <QFileDialog>
#include <QMenu>
#include <QDebug>
namespace Swift {
QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream) : QtTabbable(), contact_(contact), previousMessageWasSelf_(false), previousMessageWasSystem_(false), previousMessageWasPresence_(false), previousMessageWasFileTransfer_(false), eventStream_(eventStream) {
unreadCount_ = 0;
+ idCounter_ = 0;
inputEnabled_ = true;
completer_ = NULL;
affiliationEditor_ = NULL;
theme_ = theme;
isCorrection_ = false;
correctionEnabled_ = Maybe;
updateTitleWithUnreadCount();
QtSettingsProvider settings;
#ifdef SWIFT_EXPERIMENTAL_FT
setAcceptDrops(true);
#endif
alertStyleSheet_ = "background: rgb(255, 255, 153); color: black";
QBoxLayout *layout = new QBoxLayout(QBoxLayout::TopToBottom, this);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(2);
alertWidget_ = new QWidget(this);
QHBoxLayout* alertLayout = new QHBoxLayout(alertWidget_);
layout->addWidget(alertWidget_);
alertLabel_ = new QLabel(this);
alertLayout->addWidget(alertLabel_);
alertButton_ = new QPushButton(this);
connect (alertButton_, SIGNAL(clicked()), this, SLOT(handleAlertButtonClicked()));
alertLayout->addWidget(alertButton_);
QPalette palette = alertWidget_->palette();
palette.setColor(QPalette::Window, QColor(Qt::yellow));
palette.setColor(QPalette::WindowText, QColor(Qt::black));
alertWidget_->setStyleSheet(alertStyleSheet_);
alertLabel_->setStyleSheet(alertStyleSheet_);
alertWidget_->hide();
QBoxLayout* subjectLayout = new QBoxLayout(QBoxLayout::LeftToRight);
@@ -422,147 +423,147 @@ void QtChatWindow::updateTitleWithUnreadCount() {
setWindowTitle(contact_);
}
emit titleUpdated();
}
std::string QtChatWindow::addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) {
return addMessage(message, senderName, senderIsSelf, label, avatarPath, "", time);
}
std::string QtChatWindow::addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time) {
if (isWidgetSelected()) {
onAllMessagesRead();
}
QString scaledAvatarPath = QtScaledAvatarCache(32).getScaledAvatarPath(avatarPath.c_str());
QString htmlString;
if (label) {
htmlString = QString("<span style=\"border: thin dashed grey; padding-left: .5em; padding-right: .5em; color: %1; background-color: %2; font-size: 90%; margin-right: .5em; \">").arg(Qt::escape(P2QSTRING(label->getForegroundColor()))).arg(Qt::escape(P2QSTRING(label->getBackgroundColor())));
htmlString += QString("%3</span> ").arg(Qt::escape(P2QSTRING(label->getDisplayMarking())));
}
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML)));
messageHTML.replace("\n","<br/>");
QString styleSpanStart = style == "" ? "" : "<span style=\"" + style + "\">";
QString styleSpanEnd = style == "" ? "" : "</span>";
htmlString += styleSpanStart + messageHTML + styleSpanEnd;
bool appendToPrevious = !previousMessageWasFileTransfer_ && !previousMessageWasSystem_ && !previousMessageWasPresence_ && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_ && previousSenderName_ == P2QSTRING(senderName)));
if (lastLineTracker_.getShouldMoveLastLine()) {
/* should this be queued? */
messageLog_->addLastSeenLine();
/* if the line is added we should break the snippet */
appendToPrevious = false;
}
QString qAvatarPath = scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded();
- std::string id = id_.generateID();
+ std::string id = "id" + boost::lexical_cast<std::string>(idCounter_++);
messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id))));
previousMessageWasSelf_ = senderIsSelf;
previousSenderName_ = P2QSTRING(senderName);
previousMessageWasSystem_ = false;
previousMessageWasPresence_ = false;
previousMessageWasFileTransfer_ = false;
return id;
}
void QtChatWindow::flash() {
emit requestFlash();
}
void QtChatWindow::setAckState(std::string const& id, ChatWindow::AckState state) {
QString xml;
switch (state) {
case ChatWindow::Pending: xml = "<img src='qrc:/icons/throbber.gif' alt='" + tr("This message has not been received by your server yet.") + "'/>"; break;
case ChatWindow::Received: xml = ""; break;
case ChatWindow::Failed: xml = "<img src='qrc:/icons/error.png' alt='" + tr("This message may not have been transmitted.") + "'/>"; break;
}
messageLog_->setAckXML(P2QSTRING(id), xml);
}
int QtChatWindow::getCount() {
return unreadCount_;
}
std::string QtChatWindow::addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) {
return addMessage(" *" + message + "*", senderName, senderIsSelf, label, avatarPath, "font-style:italic ", time);
}
std::string formatSize(const boost::uintmax_t bytes) {
static const char *siPrefix[] = {"k", "M", "G", "T", "P", "E", "Z", "Y", NULL};
int power = 0;
double engBytes = bytes;
while (engBytes >= 1000) {
++power;
engBytes = engBytes / 1000.0;
}
return str( boost::format("%.1lf %sB") % engBytes % (power > 0 ? siPrefix[power-1] : "") );
}
std::string QtChatWindow::addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) {
qDebug() << "addFileTransfer";
- std::string ft_id = id_.generateID();
+ std::string ft_id = "ft" + boost::lexical_cast<std::string>(idCounter_++);
std::string htmlString;
if (senderIsSelf) {
// outgoing
htmlString = "Send file: " + filename + " ( " + formatSize(sizeInBytes) + ") </br>" +
"<div id='" + ft_id + "'>" +
"<input id='discard' type='submit' value='Cancel' onclick='filetransfer.cancel(\"" + ft_id + "\");' />" +
"<input id='description' type='submit' value='Set Description' onclick='filetransfer.setDescription(\"" + ft_id + "\");' />" +
"<input id='send' type='submit' value='Send' onclick='filetransfer.sendRequest(\"" + ft_id + "\");' />" +
"</div>";
} else {
// incoming
htmlString = "Receiving file: " + filename + " ( " + formatSize(sizeInBytes) + ") </br>" +
"<div id='" + ft_id + "'>" +
"<input id='discard' type='submit' value='Cancel' onclick='filetransfer.cancel(\"" + ft_id + "\");' />" +
"<input id='accept' type='submit' value='Accept' onclick='filetransfer.acceptRequest(\"" + ft_id + "\", \"" + filename + "\");' />" +
"</div>";
}
//addMessage(message, senderName, senderIsSelf, boost::shared_ptr<SecurityLabel>(), "", boost::posix_time::second_clock::local_time());
bool appendToPrevious = !previousMessageWasFileTransfer_ && !previousMessageWasSystem_ && !previousMessageWasPresence_ && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_ && previousSenderName_ == P2QSTRING(senderName)));
if (lastLineTracker_.getShouldMoveLastLine()) {
/* should this be queued? */
messageLog_->addLastSeenLine();
/* if the line is added we should break the snippet */
appendToPrevious = false;
}
QString qAvatarPath = "qrc:/icons/avatar.png";
- std::string id = id_.generateID();
+ std::string id = "ftmessage" + boost::lexical_cast<std::string>(idCounter_++);
messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(QString::fromStdString(htmlString), Qt::escape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id))));
return ft_id;
}
void QtChatWindow::setFileTransferProgress(std::string id, const int percentageDone) {
messageLog_->setFileTransferProgress(QString::fromStdString(id), percentageDone);
}
void QtChatWindow::setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg) {
messageLog_->setFileTransferStatus(QString::fromStdString(id), state, QString::fromStdString(msg));
}
void QtChatWindow::handleFileTransferCancel(QString id) {
qDebug() << "QtChatWindow::handleFileTransferCancel(" << id << ")";
onFileTransferCancel(Q2PSTRING(id));
}
void QtChatWindow::handleFileTransferSetDescription(QString id) {
bool ok = false;
QString text = QInputDialog::getText(this, tr("File transfer description"),
tr("Description:"), QLineEdit::Normal, "", &ok);
if (ok) {
descriptions[id] = text;
}
}
void QtChatWindow::handleFileTransferStart(QString id) {
qDebug() << "QtChatWindow::handleFileTransferStart(" << id << ")";
QString text = descriptions.find(id) == descriptions.end() ? QString() : descriptions[id];
onFileTransferStart(Q2PSTRING(id), Q2PSTRING(text));
}
@@ -581,70 +582,73 @@ void QtChatWindow::addErrorMessage(const std::string& errorMessage) {
}
QString errorMessageHTML(Qt::escape(P2QSTRING(errorMessage)));
errorMessageHTML.replace("\n","<br/>");
messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet("<span class=\"error\">" + errorMessageHTML + "</span>", QDateTime::currentDateTime(), false, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = true;
previousMessageWasPresence_ = false;
previousMessageWasFileTransfer_ = false;
}
void QtChatWindow::addSystemMessage(const std::string& message) {
if (isWidgetSelected()) {
onAllMessagesRead();
}
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML)));
messageHTML.replace("\n","<br/>");
messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = true;
previousMessageWasPresence_ = false;
previousMessageWasFileTransfer_ = false;
}
void QtChatWindow::replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) {
if (!id.empty()) {
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML)));
messageHTML.replace("\n","<br/>");
messageLog_->replaceMessage(messageHTML, P2QSTRING(id), B2QDATE(time));
}
+ else {
+ qWarning() << "Trying to replace a message with no id";
+ }
}
void QtChatWindow::addPresenceMessage(const std::string& message) {
if (isWidgetSelected()) {
onAllMessagesRead();
}
QString messageHTML(Qt::escape(P2QSTRING(message)));
messageHTML = P2QSTRING(Linkify::linkify(Q2PSTRING(messageHTML)));
messageHTML.replace("\n","<br/>");
messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new SystemMessageSnippet(messageHTML, QDateTime::currentDateTime(), false, theme_)));
previousMessageWasSelf_ = false;
previousMessageWasSystem_ = false;
previousMessageWasPresence_ = true;
}
void QtChatWindow::returnPressed() {
if (!inputEnabled_) {
return;
}
messageLog_->scrollToBottom();
lastSentMessage_ = QString(input_->toPlainText());
onSendMessageRequest(Q2PSTRING(input_->toPlainText()), isCorrection_);
inputClearing_ = true;
input_->clear();
cancelCorrection();
inputClearing_ = false;
}
void QtChatWindow::handleInputChanged() {
if (inputClearing_) {
return;
}
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index e546f12..0c64f02 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -1,53 +1,51 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/QtUI/QtMUCConfigurationWindow.h>
#include <Swift/QtUI/QtAffiliationEditor.h>
#include <QtTabbable.h>
#include <SwifTools/LastLineTracker.h>
-#include <Swiften/Base/IDGenerator.h>
-
#include <map>
#include <QPointer>
class QTextEdit;
class QLineEdit;
class QComboBox;
class QLabel;
class QSplitter;
class QPushButton;
namespace Swift {
class QtChatView;
class QtOccupantListWidget;
class QtChatTheme;
class TreeWidget;
class QtTextEdit;
class UIEventStream;
class QtFileTransferJSBridge;
class QtChatWindow : public QtTabbable, public ChatWindow {
Q_OBJECT
public:
QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream);
~QtChatWindow();
std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
std::string addAction(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time);
void addSystemMessage(const std::string& message);
void addPresenceMessage(const std::string& message);
void addErrorMessage(const std::string& errorMessage);
void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time);
// File transfer related stuff
std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes);
void setFileTransferProgress(std::string id, const int percentageDone);
void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg);
void show();
@@ -118,45 +116,45 @@ namespace Swift {
private:
void updateTitleWithUnreadCount();
void tabComplete();
void beginCorrection();
void cancelCorrection();
std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time);
void handleOccupantSelectionChanged(RosterItem* item);
int unreadCount_;
bool contactIsTyping_;
LastLineTracker lastLineTracker_;
QString contact_;
QString lastSentMessage_;
QtChatView* messageLog_;
QtChatTheme* theme_;
QtTextEdit* input_;
QComboBox* labelsWidget_;
QtOccupantListWidget* treeWidget_;
QLabel* correctingLabel_;
QLabel* alertLabel_;
QWidget* alertWidget_;
QPushButton* alertButton_;
TabComplete* completer_;
QLineEdit* subject_;
QPushButton* actionButton_;
std::vector<SecurityLabelsCatalog::Item> availableLabels_;
bool isCorrection_;
bool previousMessageWasSelf_;
bool previousMessageWasSystem_;
bool previousMessageWasPresence_;
bool previousMessageWasFileTransfer_;
QString previousSenderName_;
bool inputClearing_;
UIEventStream* eventStream_;
bool inputEnabled_;
- IDGenerator id_;
QSplitter *logRosterSplitter_;
Tristate correctionEnabled_;
QString alertStyleSheet_;
std::map<QString, QString> descriptions;
QtFileTransferJSBridge* fileTransferJS;
QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_;
QPointer<QtAffiliationEditor> affiliationEditor_;
+ int idCounter_;
};
}