summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
authorRichard Maudsley <richard.maudsley@isode.com>2014-05-02 15:57:31 (GMT)
committerSwift Review <review@swift.im>2014-05-26 19:33:36 (GMT)
commitbf3739c75fcb312a99608488c8741e2ffc15ca1e (patch)
tree0eb8697735f82bc33e2e8e59770f7ecfe4bbc8ac /Swift
parentd9bd353dc90008bd8d723630ec9c037a3c1f5ad2 (diff)
downloadswift-contrib-bf3739c75fcb312a99608488c8741e2ffc15ca1e.zip
swift-contrib-bf3739c75fcb312a99608488c8741e2ffc15ca1e.tar.bz2
Allow bookmarking of MUCs from cog menu.
Change-Id: I55f696c98598ec9bfd1ac13a2abd3c1ee2b1e9fa
Diffstat (limited to 'Swift')
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp9
-rw-r--r--Swift/Controllers/Chat/MUCController.h3
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h5
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h3
-rw-r--r--Swift/QtUI/QtAddBookmarkWindow.cpp6
-rw-r--r--Swift/QtUI/QtAddBookmarkWindow.h3
-rw-r--r--Swift/QtUI/QtBookmarkDetailWindow.cpp26
-rw-r--r--Swift/QtUI/QtBookmarkDetailWindow.h5
-rw-r--r--Swift/QtUI/QtChatWindow.cpp10
-rw-r--r--Swift/QtUI/QtChatWindow.h1
10 files changed, 64 insertions, 7 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index df99368..cb2616c 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -61,70 +61,71 @@ MUCController::MUCController (
IQRouter* iqRouter,
ChatWindowFactory* chatWindowFactory,
PresenceOracle* presenceOracle,
AvatarManager* avatarManager,
UIEventStream* uiEventStream,
bool useDelayForLatency,
TimerFactory* timerFactory,
EventController* eventController,
EntityCapsProvider* entityCapsProvider,
XMPPRoster* roster,
HistoryController* historyController,
MUCRegistry* mucRegistry,
HighlightManager* highlightManager,
ChatMessageParser* chatMessageParser,
bool isImpromptu,
AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider,
VCardManager* vcardManager) :
ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0), isImpromptu_(isImpromptu), isImpromptuAlreadyConfigured_(false) {
parting_ = true;
joined_ = false;
lastWasPresence_ = false;
shouldJoinOnReconnect_ = true;
doneGettingHistory_ = false;
events_ = uiEventStream;
xmppRoster_ = roster;
roster_ = new Roster(false, true);
rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithResource);
completer_ = new TabComplete();
chatWindow_->setRosterModel(roster_);
chatWindow_->setTabComplete(completer_);
chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
chatWindow_->onOccupantSelectionChanged.connect(boost::bind(&MUCController::handleWindowOccupantSelectionChanged, this, _1));
chatWindow_->onOccupantActionSelected.connect(boost::bind(&MUCController::handleActionRequestedOnOccupant, this, _1, _2));
chatWindow_->onChangeSubjectRequest.connect(boost::bind(&MUCController::handleChangeSubjectRequest, this, _1));
+ chatWindow_->onBookmarkRequest.connect(boost::bind(&MUCController::handleBookmarkRequest, this));
chatWindow_->onConfigureRequest.connect(boost::bind(&MUCController::handleConfigureRequest, this, _1));
chatWindow_->onConfigurationFormCancelled.connect(boost::bind(&MUCController::handleConfigurationCancelled, this));
chatWindow_->onDestroyRequest.connect(boost::bind(&MUCController::handleDestroyRoomRequest, this));
chatWindow_->onInviteToChat.connect(boost::bind(&MUCController::handleInvitePersonToThisMUCRequest, this, _1));
chatWindow_->onGetAffiliationsRequest.connect(boost::bind(&MUCController::handleGetAffiliationsRequest, this));
chatWindow_->onChangeAffiliationsRequest.connect(boost::bind(&MUCController::handleChangeAffiliationsRequest, this, _1));
muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1));
muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1));
muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1));
muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1));
muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3));
muc_->onRoleChangeFailed.connect(boost::bind(&MUCController::handleOccupantRoleChangeFailed, this, _1, _2, _3));
muc_->onAffiliationListReceived.connect(boost::bind(&MUCController::handleAffiliationListReceived, this, _1, _2));
muc_->onConfigurationFailed.connect(boost::bind(&MUCController::handleConfigurationFailed, this, _1));
muc_->onConfigurationFormReceived.connect(boost::bind(&MUCController::handleConfigurationFormReceived, this, _1));
highlighter_->setMode(Highlighter::MUCMode);
highlighter_->setNick(nick_);
if (timerFactory) {
loginCheckTimer_ = boost::shared_ptr<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
loginCheckTimer_->start();
}
if (isImpromptu) {
muc_->onUnlocked.connect(boost::bind(&MUCController::handleRoomUnlocked, this));
chatWindow_->convertToMUC(ChatWindow::ImpromptuMUC);
} else {
muc_->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3));
muc_->onOccupantAffiliationChanged.connect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3));
chatWindow_->convertToMUC(ChatWindow::StandardMUC);
chatWindow_->setName(muc->getJID().getNode());
}
setOnline(true);
if (avatarManager_ != NULL) {
avatarChangedConnection_ = (avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1)));
}
@@ -767,70 +768,78 @@ std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart
}
else {
eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% has joined then left the chat") : QT_TRANSLATE_NOOP("", "%1% has entered then left the room"));
}
break;
case PartThenJoin:
if (sorted[i].size() > 1) {
eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% have left then returned to the chat") : QT_TRANSLATE_NOOP("", "%1% have left then returned to the room"));
}
else {
eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% has left then returned to the chat") : QT_TRANSLATE_NOOP("", "%1% has left then returned to the room"));
}
break;
}
populatedEvents.push_back(static_cast<JoinPart>(i));
eventStrings[i] = str(boost::format(eventString) % names);
}
}
for (size_t i = 0; i < populatedEvents.size(); i++) {
if (i > 0) {
if (i < populatedEvents.size() - 1) {
result += ", ";
} else {
result += QT_TRANSLATE_NOOP("", " and ");
}
}
result += eventStrings[populatedEvents[i]];
}
return result;
}
void MUCController::handleChangeSubjectRequest(const std::string& subject) {
muc_->changeSubject(subject);
}
+void MUCController::handleBookmarkRequest() {
+ const JID jid = muc_->getJID();
+ MUCBookmark bookmark(jid, jid.toBare().toString());
+ bookmark.setPassword(password_);
+ bookmark.setNick(nick_);
+ chatWindow_->showBookmarkWindow(bookmark);
+}
+
void MUCController::handleConfigureRequest(Form::ref form) {
if (form) {
muc_->configureRoom(form);
}
else {
muc_->requestConfigurationForm();
}
}
void MUCController::handleConfigurationFailed(ErrorPayload::ref error) {
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Room configuration failed: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(chatMessageParser_->parseMessageBody(errorMessage));
}
void MUCController::handleOccupantRoleChangeFailed(ErrorPayload::ref error, const JID&, MUCOccupant::Role) {
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Occupant role change failed: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(chatMessageParser_->parseMessageBody(errorMessage));
}
void MUCController::configureAsImpromptuRoom(Form::ref form) {
muc_->configureRoom(buildImpromptuRoomConfiguration(form));
isImpromptuAlreadyConfigured_ = true;
onImpromptuConfigCompleted();
}
void MUCController::handleConfigurationFormReceived(Form::ref form) {
if (isImpromptu_) {
if (!isImpromptuAlreadyConfigured_) {
configureAsImpromptuRoom(form);
}
} else {
chatWindow_->showRoomConfigurationForm(form);
}
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 317f579..e78ff77 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -1,37 +1,37 @@
/*
- * Copyright (c) 2010-2013 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <set>
#include <string>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/signals/connection.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Network/Timer.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/JID/JID.h>
#include <Swiften/MUC/MUC.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swift/Controllers/Roster/RosterItem.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class StanzaChannel;
class IQRouter;
class ChatWindowFactory;
class Roster;
class AvatarManager;
class UIEventStream;
class TimerFactory;
class TabComplete;
class XMPPRoster;
@@ -61,70 +61,71 @@ namespace Swift {
static std::string generateJoinPartString(const std::vector<NickJoinPart>& joinParts, bool isImpromptu);
static std::string concatenateListOfNames(const std::vector<NickJoinPart>& joinParts);
bool isJoined();
const std::string& getNick();
bool isImpromptu() const;
std::map<std::string, JID> getParticipantJIDs() const;
void sendInvites(const std::vector<JID>& jids, const std::string& reason) const;
protected:
void preSendMessageRequest(boost::shared_ptr<Message> message);
bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
std::string senderDisplayNameFromMessage(const JID& from);
boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const;
void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>, const HighlightAction&);
void cancelReplaces();
void logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming);
private:
void setAvailableRoomActions(const MUCOccupant::Affiliation& affiliation, const MUCOccupant::Role& role);
void clearPresenceQueue();
void addPresenceMessage(const std::string& message);
void handleWindowOccupantSelectionChanged(ContactRosterItem* item);
void handleActionRequestedOnOccupant(ChatWindow::OccupantAction, ContactRosterItem* item);
void handleWindowClosed();
void handleAvatarChanged(const JID& jid);
void handleOccupantJoined(const MUCOccupant& occupant);
void handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType type, const std::string& reason);
void handleOccupantPresenceChange(boost::shared_ptr<Presence> presence);
void handleOccupantRoleChanged(const std::string& nick, const MUCOccupant& occupant,const MUCOccupant::Role& oldRole);
void handleOccupantAffiliationChanged(const std::string& nick, const MUCOccupant::Affiliation& affiliation,const MUCOccupant::Affiliation& oldAffiliation);
void handleJoinComplete(const std::string& nick);
void handleJoinFailed(boost::shared_ptr<ErrorPayload> error);
void handleJoinTimeoutTick();
void handleChangeSubjectRequest(const std::string&);
+ void handleBookmarkRequest();
std::string roleToGroupName(MUCOccupant::Role role);
std::string roleToSortName(MUCOccupant::Role role);
JID nickToJID(const std::string& nick);
std::string roleToFriendlyName(MUCOccupant::Role role);
void receivedActivity();
bool messageTargetsMe(boost::shared_ptr<Message> message);
void updateJoinParts();
bool shouldUpdateJoinParts();
void dayTicked() {clearPresenceQueue();}
void processUserPart();
void handleBareJIDCapsChanged(const JID& jid);
void handleConfigureRequest(Form::ref);
void handleConfigurationFailed(ErrorPayload::ref);
void handleConfigurationFormReceived(Form::ref);
void handleDestroyRoomRequest();
void handleInvitePersonToThisMUCRequest(const std::vector<JID>& jidsToInvite);
void handleConfigurationCancelled();
void handleOccupantRoleChangeFailed(ErrorPayload::ref, const JID&, MUCOccupant::Role);
void handleGetAffiliationsRequest();
void handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids);
void handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes);
void handleInviteToMUCWindowDismissed();
void handleInviteToMUCWindowCompleted();
void handleUIEvent(boost::shared_ptr<UIEvent> event);
void addRecentLogs();
void checkDuplicates(boost::shared_ptr<Message> newMessage);
void setNick(const std::string& nick);
void setImpromptuWindowTitle();
void handleRoomUnlocked();
void configureAsImpromptuRoom(Form::ref form);
Form::ref buildImpromptuRoomConfiguration(Form::ref roomConfigurationForm);
private:
MUC::ref muc_;
UIEventStream* events_;
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 771872a..096a59a 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -1,56 +1,57 @@
/*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <vector>
#include <string>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Elements/SecurityLabelsCatalog.h>
#include <Swiften/Elements/ChatState.h>
#include <Swiften/Elements/Form.h>
#include <Swiften/Elements/MUCOccupant.h>
+#include <Swiften/MUC/MUCBookmark.h>
#include <Swift/Controllers/HighlightManager.h>
namespace Swift {
class AvatarManager;
class TreeWidget;
class Roster;
class TabComplete;
class RosterItem;
class ContactRosterItem;
class FileTransferController;
class UserSearchWindow;
class ChatWindow {
public:
class ChatMessagePart {
public:
virtual ~ChatMessagePart() {}
};
class ChatMessage {
public:
ChatMessage() {}
ChatMessage(const std::string& text) {
append(boost::make_shared<ChatTextMessagePart>(text));
}
void append(const boost::shared_ptr<ChatMessagePart>& part) {
parts_.push_back(part);
}
const std::vector<boost::shared_ptr<ChatMessagePart> >& getParts() const {
return parts_;
}
private:
@@ -116,93 +117,95 @@ namespace Swift {
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
virtual void setFileTransferStatus(std::string, const 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 = true, bool isImpromptu = false, bool isContinuation = false) = 0;
virtual std::string addWhiteboardRequest(bool senderIsSelf) = 0;
virtual void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state) = 0;
// message receipts
virtual void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state) = 0;
virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const std::string& name) = 0;
virtual void show() = 0;
virtual void activate() = 0;
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
virtual void setSecurityLabelsEnabled(bool enabled) = 0;
virtual void setCorrectionEnabled(Tristate enabled) = 0;
virtual void setUnreadMessageCount(int count) = 0;
virtual void convertToMUC(MUCType mucType) = 0;
// virtual TreeWidget *getTreeWidget() = 0;
virtual void setSecurityLabelsError() = 0;
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() = 0;
virtual void setInputEnabled(bool enabled) = 0;
virtual void setRosterModel(Roster* model) = 0;
virtual void setTabComplete(TabComplete* completer) = 0;
virtual void replaceLastMessage(const ChatMessage& message) = 0;
virtual void setAckState(const std::string& id, AckState state) = 0;
virtual void flash() = 0;
virtual void setSubject(const std::string& subject) = 0;
virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) = 0;
virtual void setAvailableRoomActions(const std::vector<RoomAction> &actions) = 0;
virtual void setBlockingState(BlockingState state) = 0;
virtual void setCanInitiateImpromptuChats(bool supportsImpromptu) = 0;
+ virtual void showBookmarkWindow(const MUCBookmark& bookmark) = 0;
/**
* Set an alert on the window.
* @param alertText Description of alert (required).
* @param buttonText Button text to use (optional, no button is shown if empty).
*/
virtual void setAlert(const std::string& alertText, const std::string& buttonText = "") = 0;
/**
* Removes an alert.
*/
virtual void cancelAlert() = 0;
/**
* Actions that can be performed on the selected occupant.
*/
virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) = 0;
/**
* A room configuration has been requested, show the form.
* If the form is cancelled, must emit onConfigurationFormCancelled().
*/
virtual void showRoomConfigurationForm(Form::ref) = 0;
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest;
boost::signal<void ()> onSendCorrectionMessageRequest;
boost::signal<void ()> onUserTyping;
boost::signal<void ()> onUserCancelsTyping;
boost::signal<void ()> onAlertButtonClicked;
boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged;
boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
boost::signal<void (const std::string&)> onChangeSubjectRequest;
+ boost::signal<void ()> onBookmarkRequest;
boost::signal<void (Form::ref)> onConfigureRequest;
boost::signal<void ()> onDestroyRequest;
boost::signal<void (const std::vector<JID>&)> onInviteToChat;
boost::signal<void ()> onConfigurationFormCancelled;
boost::signal<void ()> onGetAffiliationsRequest;
boost::signal<void (MUCOccupant::Affiliation, const JID&)> onSetAffiliationRequest;
boost::signal<void (const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes)> onChangeAffiliationsRequest;
boost::signal<void ()> onLogCleared;
// File transfer related
boost::signal<void (std::string /* id */)> onFileTransferCancel;
boost::signal<void (std::string /* id */, std::string /* description */)> onFileTransferStart;
boost::signal<void (std::string /* id */, std::string /* path */)> onFileTransferAccept;
boost::signal<void (std::string /* path */)> onSendFileRequest;
//Whiteboard related
boost::signal<void ()> onWhiteboardSessionAccept;
boost::signal<void ()> onWhiteboardSessionCancel;
boost::signal<void ()> onWhiteboardWindowShow;
// Blocking Command related
boost::signal<void ()> onBlockUserRequest;
boost::signal<void ()> onUnblockUserRequest;
};
}
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 8aa645d..c2e2c9f 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -1,37 +1,37 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/shared_ptr.hpp>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swiften/Base/foreach.h>
namespace Swift {
class MockChatWindow : public ChatWindow {
public:
MockChatWindow() : labelsEnabled_(false) {}
virtual ~MockChatWindow();
virtual std::string addMessage(const 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*/) {
lastMessageBody_ = bodyFromMessage(message); return "id";}
virtual std::string addAction(const 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*/) {return "id";}
virtual void addSystemMessage(const ChatMessage& /*message*/, Direction /*direction*/) {}
virtual void addPresenceMessage(const ChatMessage& /*message*/, Direction /*direction*/) {}
virtual void addErrorMessage(const ChatMessage& /*message*/) {}
virtual void replaceMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
virtual void replaceWithAction(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
virtual void replaceLastMessage(const ChatMessage& /*message*/) {}
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; }
virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { }
virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { }
@@ -39,55 +39,56 @@ namespace Swift {
virtual void setMessageReceiptState(const std::string &/* id */, ReceiptState /* state */) { }
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {}
virtual void setName(const std::string& name) {name_ = name;}
virtual void show() {}
virtual void activate() {}
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;}
virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;}
virtual void setUnreadMessageCount(int /*count*/) {}
virtual void convertToMUC(MUCType /*mucType*/) {}
virtual void setSecurityLabelsError() {}
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() {return label_;}
virtual void setInputEnabled(bool /*enabled*/) {}
virtual void setRosterModel(Roster* roster) { roster_ = roster; }
Roster* getRosterModel() { return roster_; }
virtual void setTabComplete(TabComplete*) {}
void setAckState(const std::string& /*id*/, AckState /*state*/) {}
virtual void flash() {}
virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {}
virtual void cancelAlert() {}
virtual void setCorrectionEnabled(Tristate /*enabled*/) {}
void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {}
void setSubject(const std::string& /*subject*/) {}
virtual void showRoomConfigurationForm(Form::ref) {}
virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool = true, bool = false, bool = false) {}
virtual std::string addWhiteboardRequest(bool) {return "";}
virtual void setWhiteboardSessionStatus(std::string, const ChatWindow::WhiteboardSessionState){}
virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {}
virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}
virtual void setBlockingState(BlockingState) {}
virtual void setCanInitiateImpromptuChats(bool /*supportsImpromptu*/) {}
+ virtual void showBookmarkWindow(const MUCBookmark& /*bookmark*/) {}
std::string bodyFromMessage(const ChatMessage& message) {
boost::shared_ptr<ChatTextMessagePart> text;
foreach (boost::shared_ptr<ChatMessagePart> part, message.getParts()) {
if ((text = boost::dynamic_pointer_cast<ChatTextMessagePart>(part))) {
return text->text;
}
}
return "";
}
std::string name_;
std::string lastMessageBody_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;
SecurityLabelsCatalog::Item label_;
Roster* roster_;
};
}
diff --git a/Swift/QtUI/QtAddBookmarkWindow.cpp b/Swift/QtUI/QtAddBookmarkWindow.cpp
index 675ea03..230f2ed 100644
--- a/Swift/QtUI/QtAddBookmarkWindow.cpp
+++ b/Swift/QtUI/QtAddBookmarkWindow.cpp
@@ -1,27 +1,31 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtAddBookmarkWindow.h"
#include <qdebug.h>
namespace Swift {
QtAddBookmarkWindow::QtAddBookmarkWindow(UIEventStream* eventStream) : eventStream_(eventStream) {
}
+QtAddBookmarkWindow::QtAddBookmarkWindow(UIEventStream* eventStream, const MUCBookmark& bookmark) : eventStream_(eventStream) {
+ createFormFromBookmark(bookmark);
+}
+
bool QtAddBookmarkWindow::commit() {
boost::optional<MUCBookmark> bookmark = createBookmarkFromForm();
if (bookmark) {
eventStream_->send(boost::shared_ptr<UIEvent>(new AddMUCBookmarkUIEvent(*bookmark)));
return true;
}
else {
return false;
}
}
}
diff --git a/Swift/QtUI/QtAddBookmarkWindow.h b/Swift/QtUI/QtAddBookmarkWindow.h
index f026cc3..c0dc214 100644
--- a/Swift/QtUI/QtAddBookmarkWindow.h
+++ b/Swift/QtUI/QtAddBookmarkWindow.h
@@ -1,23 +1,24 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "QtBookmarkDetailWindow.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h"
namespace Swift {
class QtAddBookmarkWindow : public QtBookmarkDetailWindow {
Q_OBJECT
public:
QtAddBookmarkWindow(UIEventStream* eventStream);
+ QtAddBookmarkWindow(UIEventStream* eventStream, const MUCBookmark& bookmark);
bool commit();
private:
UIEventStream* eventStream_;
};
}
diff --git a/Swift/QtUI/QtBookmarkDetailWindow.cpp b/Swift/QtUI/QtBookmarkDetailWindow.cpp
index ae84b4b..3e501f2 100644
--- a/Swift/QtUI/QtBookmarkDetailWindow.cpp
+++ b/Swift/QtUI/QtBookmarkDetailWindow.cpp
@@ -1,52 +1,76 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtBookmarkDetailWindow.h"
#include "QtSwiftUtil.h"
#include <QMessageBox>
namespace Swift {
QtBookmarkDetailWindow::QtBookmarkDetailWindow(QWidget* parent) : QDialog(parent) {
setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
//connect(buttons_, SIGNAL(accepted()), SLOT(accept()));
//connect(buttons_, SIGNAL(rejected()), SLOT(reject()));
}
void QtBookmarkDetailWindow::accept() {
if (commit()) {
QDialog::accept();
}
}
boost::optional<MUCBookmark> QtBookmarkDetailWindow::createBookmarkFromForm() {
//check room
//check bookmarkName
JID room(Q2PSTRING(room_->text()));
if (!room.isValid() || room.getNode().empty() || !room.getResource().empty()) {
QMessageBox::warning(this, tr("Bookmark not valid"), tr("You must specify a valid room address (e.g. someroom@rooms.example.com)."));
return boost::optional<MUCBookmark>();
}
std::string name(Q2PSTRING(name_->text()));
if (name.empty()) {
name = room.toString();
}
MUCBookmark bookmark(room, name);
std::string nick(Q2PSTRING(nick_->text()));
std::string password(Q2PSTRING(password_->text()));
bookmark.setAutojoin(autojoin_->isChecked());
if (!nick.empty()) {
bookmark.setNick(nick);
}
if (!password.empty()) {
bookmark.setPassword(password);
}
return bookmark;
}
+void QtBookmarkDetailWindow::createFormFromBookmark(const MUCBookmark& bookmark) {
+ if (bookmark.getRoom().isValid()) {
+ room_->setText(P2QSTRING(bookmark.getRoom().toString()));
+ }
+
+ if (!bookmark.getName().empty()) {
+ name_->setText(P2QSTRING(bookmark.getName()));
+ }
+
+ if (bookmark.getNick()) {
+ nick_->setText(P2QSTRING((*bookmark.getNick())));
+ }
+
+ if (bookmark.getPassword()) {
+ password_->setText(P2QSTRING((*bookmark.getPassword())));
+ }
+
+ if (bookmark.getAutojoin()) {
+ autojoin_->setCheckState(Qt::Checked);
+ } else {
+ autojoin_->setCheckState(Qt::Unchecked);
+ }
+}
+
}
diff --git a/Swift/QtUI/QtBookmarkDetailWindow.h b/Swift/QtUI/QtBookmarkDetailWindow.h
index fd2b7b4..b223719 100644
--- a/Swift/QtUI/QtBookmarkDetailWindow.h
+++ b/Swift/QtUI/QtBookmarkDetailWindow.h
@@ -1,29 +1,32 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "ui_QtBookmarkDetailWindow.h"
#include <boost/optional.hpp>
#include <QDialog>
#include "Swiften/MUC/MUCBookmark.h"
namespace Swift {
class QtBookmarkDetailWindow : public QDialog, protected Ui::QtBookmarkDetailWindow {
Q_OBJECT
public:
QtBookmarkDetailWindow(QWidget* parent = NULL);
virtual bool commit() = 0;
boost::optional<MUCBookmark> createBookmarkFromForm();
+ protected:
+ void createFormFromBookmark(const MUCBookmark& bookmark);
+
public slots:
void accept();
};
}
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index d3cce6d..f58c11b 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -14,70 +14,71 @@
#include <QApplication>
#include <QBoxLayout>
#include <QCloseEvent>
#include <QComboBox>
#include <QFileDialog>
#include <QFileInfo>
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QMimeData>
#include <QPushButton>
#include <QSplitter>
#include <QString>
#include <QTextDocument>
#include <QTextEdit>
#include <QTime>
#include <QToolButton>
#include <QUrl>
#include <QMimeData>
#include <Swiften/Base/Log.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swift/Controllers/Roster/Roster.h>
#include <Swift/Controllers/Roster/RosterItem.h>
#include <Swift/Controllers/Settings/SettingsProvider.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
#include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h>
#include <SwifTools/TabComplete.h>
#include <Swift/QtUI/Roster/QtOccupantListWidget.h>
+#include <Swift/QtUI/QtAddBookmarkWindow.h>
#include <Swift/QtUI/QtPlainChatView.h>
#include <Swift/QtUI/QtSettingsProvider.h>
#include <Swift/QtUI/QtScaledAvatarCache.h>
#include <Swift/QtUI/QtTextEdit.h>
#include <Swift/QtUI/QtUISettingConstants.h>
#include <Swift/QtUI/QtUtilities.h>
#include <Swift/QtUI/QtWebKitChatView.h>
namespace Swift {
QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream, SettingsProvider* settings) : QtTabbable(), contact_(contact), eventStream_(eventStream), blockingState_(BlockingUnsupported), isMUC_(false), supportsImpromptuChat_(false) {
settings_ = settings;
unreadCount_ = 0;
inputEnabled_ = true;
completer_ = NULL;
affiliationEditor_ = NULL;
theme_ = theme;
isCorrection_ = false;
labelModel_ = NULL;
correctionEnabled_ = Maybe;
updateTitleWithUnreadCount();
#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_);
@@ -595,135 +596,144 @@ void QtChatWindow::handleActionButtonClicked() {
if (availableRoomActions_.empty()) {
if (blockingState_ == IsBlocked) {
unblock = contextMenu.addAction(tr("Unblock"));
} else if (blockingState_ == IsUnblocked) {
block = contextMenu.addAction(tr("Block"));
}
if (supportsImpromptuChat_) {
invite = contextMenu.addAction(tr("Invite person to this chat…"));
}
} else {
foreach(ChatWindow::RoomAction availableAction, availableRoomActions_)
{
if (impromptu_) {
// hide options we don't need in impromptu chats
if (availableAction == ChatWindow::ChangeSubject ||
availableAction == ChatWindow::Configure ||
availableAction == ChatWindow::Affiliations ||
availableAction == ChatWindow::Destroy) {
continue;
}
}
switch(availableAction)
{
case ChatWindow::ChangeSubject: changeSubject = contextMenu.addAction(tr("Change subject…")); break;
case ChatWindow::Configure: configure = contextMenu.addAction(tr("Configure room…")); break;
case ChatWindow::Affiliations: affiliations = contextMenu.addAction(tr("Edit affiliations…")); break;
case ChatWindow::Destroy: destroy = contextMenu.addAction(tr("Destroy room")); break;
case ChatWindow::Invite: invite = contextMenu.addAction(tr("Invite person to this room…")); break;
}
}
}
+ QAction* bookmark = contextMenu.addAction(tr("Add boomark..."));
+
QAction* result = contextMenu.exec(QCursor::pos());
if (result == NULL) {
/* Skip processing. Note that otherwise, because the actions could be null they could match */
}
else if (result == changeSubject) {
bool ok;
QString subject = QInputDialog::getText(this, tr("Change room subject"), tr("New subject:"), QLineEdit::Normal, subject_->text(), &ok);
if (ok) {
onChangeSubjectRequest(Q2PSTRING(subject));
}
}
else if (result == configure) {
onConfigureRequest(Form::ref());
}
else if (result == affiliations) {
if (!affiliationEditor_) {
onGetAffiliationsRequest();
affiliationEditor_ = new QtAffiliationEditor(this);
connect(affiliationEditor_, SIGNAL(accepted()), this, SLOT(handleAffiliationEditorAccepted()));
}
affiliationEditor_->show();
}
else if (result == destroy) {
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Confirm room destruction"));
msgBox.setText(tr("Are you sure you want to destroy the room?"));
msgBox.setInformativeText(tr("This will destroy the room."));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
if (msgBox.exec() == QMessageBox::Yes) {
onDestroyRequest();
}
}
else if (result == invite) {
onInviteToChat(std::vector<JID>());
}
else if (result == block) {
onBlockUserRequest();
}
else if (result == unblock) {
onUnblockUserRequest();
+ } else if (result == bookmark) {
+ onBookmarkRequest();
}
}
void QtChatWindow::handleAffiliationEditorAccepted() {
onChangeAffiliationsRequest(affiliationEditor_->getChanges());
}
void QtChatWindow::setAffiliations(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids) {
if (!affiliationEditor_) return;
affiliationEditor_->setAffiliations(affiliation, jids);
}
void QtChatWindow::setAvailableRoomActions(const std::vector<RoomAction>& actions) {
availableRoomActions_ = actions;
}
void QtChatWindow::setBlockingState(BlockingState state) {
blockingState_ = state;
}
void QtChatWindow::setCanInitiateImpromptuChats(bool supportsImpromptu) {
supportsImpromptuChat_ = supportsImpromptu;
}
+void QtChatWindow::showBookmarkWindow(const MUCBookmark& bookmark) {
+ QtAddBookmarkWindow* window = new QtAddBookmarkWindow(eventStream_, bookmark);
+ window->show();
+}
+
void QtChatWindow::showRoomConfigurationForm(Form::ref form) {
if (mucConfigurationWindow_) {
delete mucConfigurationWindow_.data();
}
mucConfigurationWindow_ = new QtMUCConfigurationWindow(form);
mucConfigurationWindow_->onFormComplete.connect(boost::bind(boost::ref(onConfigureRequest), _1));
mucConfigurationWindow_->onFormCancelled.connect(boost::bind(boost::ref(onConfigurationFormCancelled)));
}
void QtChatWindow::handleAppendedToLog() {
if (lastLineTracker_.getShouldMoveLastLine()) {
/* should this be queued? */
messageLog_->addLastSeenLine();
}
if (isWidgetSelected()) {
onAllMessagesRead();
}
}
void QtChatWindow::addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct, bool isImpromptu, bool isContinuation) {
handleAppendedToLog();
messageLog_->addMUCInvitation(senderName, jid, reason, password, direct, isImpromptu, isContinuation);
}
std::string QtChatWindow::addMessage(const 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) {
handleAppendedToLog();
return messageLog_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time, highlight);
}
std::string QtChatWindow::addAction(const 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) {
handleAppendedToLog();
return messageLog_->addAction(message, senderName, senderIsSelf, label, avatarPath, time, highlight);
}
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 5a4fe95..de7e45e 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -96,70 +96,71 @@ namespace Swift {
std::string addWhiteboardRequest(bool senderIsSelf);
void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state);
void show();
void activate();
void setUnreadMessageCount(int count);
void convertToMUC(MUCType mucType);
// TreeWidget *getTreeWidget();
void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels);
void setSecurityLabelsEnabled(bool enabled);
void setSecurityLabelsError();
SecurityLabelsCatalog::Item getSelectedSecurityLabel();
void setName(const std::string& name);
void setInputEnabled(bool enabled);
QtTabbable::AlertType getWidgetAlertState();
void setContactChatState(ChatState::ChatStateType state);
void setRosterModel(Roster* roster);
void setTabComplete(TabComplete* completer);
int getCount();
void replaceLastMessage(const ChatMessage& message);
void setAckState(const std::string& id, AckState state);
// message receipts
void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state);
void flash();
QByteArray getSplitterState();
virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions);
void setSubject(const std::string& subject);
void showRoomConfigurationForm(Form::ref);
void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true, bool isImpromptu = false, bool isContinuation = false);
void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&);
void setAvailableRoomActions(const std::vector<RoomAction>& actions);
void setBlockingState(BlockingState state);
virtual void setCanInitiateImpromptuChats(bool supportsImpromptu);
+ virtual void showBookmarkWindow(const MUCBookmark& bookmark);
public slots:
void handleChangeSplitterState(QByteArray state);
void handleFontResized(int fontSizeSteps);
void setAlert(const std::string& alertText, const std::string& buttonText = "");
void cancelAlert();
void setCorrectionEnabled(Tristate enabled);
signals:
void geometryChanged();
void splitterMoved();
void fontResized(int);
protected slots:
void qAppFocusChanged(QWidget* old, QWidget* now);
void closeEvent(QCloseEvent* event);
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
protected:
void showEvent(QShowEvent* event);
private slots:
void handleLogCleared();
void returnPressed();
void handleInputChanged();
void handleCursorPositionChanged();
void handleKeyPressEvent(QKeyEvent* event);
void handleSplitterMoved(int pos, int index);
void handleAlertButtonClicked();
void handleActionButtonClicked();
void handleAffiliationEditorAccepted();