diff options
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 24 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.h | 1 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 3 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 2 | ||||
| -rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 6 | ||||
| -rw-r--r-- | Swift/QtUI/QtChatWindow.h | 2 |
7 files changed, 35 insertions, 5 deletions
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index ecb9288..f8f30ff 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -1,57 +1,58 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Swift/Controllers/Chat/ChatControllerBase.h" #include <sstream> #include <map> #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/algorithm/string.hpp> #include <Swift/Controllers/Intl.h> #include <Swiften/Base/format.h> #include <Swiften/Base/String.h> #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Elements/Delay.h> #include <Swiften/Elements/MUCInvitationPayload.h> +#include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Base/foreach.h> #include <Swift/Controllers/XMPPEvents/EventController.h> #include <Swiften/Disco/EntityCapsProvider.h> #include <Swift/Controllers/UIInterfaces/ChatWindow.h> #include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h> #include <Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h> #include <Swiften/Avatars/AvatarManager.h> namespace Swift { ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), timerFactory_(timerFactory), entityCapsProvider_(entityCapsProvider) { chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream); chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this)); chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2)); entityCapsProvider_->onCapsChanged.connect(boost::bind(&ChatControllerBase::handleCapsChanged, this, _1)); setOnline(stanzaChannel->isAvailable() && iqRouter->isAvailable()); createDayChangeTimer(); } ChatControllerBase::~ChatControllerBase() { delete chatWindow_; } void ChatControllerBase::handleCapsChanged(const JID& jid) { if (jid.compare(toJID_, JID::WithoutResource) == 0) { handleBareJIDCapsChanged(jid); } } void ChatControllerBase::createDayChangeTimer() { if (timerFactory_) { boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); boost::posix_time::ptime midnight(now.date() + boost::gregorian::days(1)); long millisecondsUntilMidnight = (midnight - now).total_milliseconds(); dateChangeTimer_ = boost::shared_ptr<Timer>(timerFactory_->createTimer(millisecondsUntilMidnight)); @@ -149,70 +150,74 @@ void ChatControllerBase::handleSecurityLabelsCatalogResponse(boost::shared_ptr<S void ChatControllerBase::showChatWindow() { chatWindow_->show(); } void ChatControllerBase::activateChatWindow() { chatWindow_->activate(); } std::string ChatControllerBase::addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, const boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) { if (boost::starts_with(message, "/me ")) { return chatWindow_->addAction(String::getSplittedAtFirst(message, ' ').second, senderName, senderIsSelf, label, avatarPath, time); } else { return chatWindow_->addMessage(message, senderName, senderIsSelf, label, avatarPath, time); } } bool ChatControllerBase::isFromContact(const JID& from) { return from.toBare() == toJID_.toBare(); } void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) { preHandleIncomingMessage(messageEvent); if (messageEvent->isReadable() && !messageEvent->getConcluded()) { unreadMessages_.push_back(messageEvent); } boost::shared_ptr<Message> message = messageEvent->getStanza(); std::string body = message->getBody(); if (message->isError()) { std::string errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't send message: %1%")) % getErrorMessage(message->getPayload<ErrorPayload>())); chatWindow_->addErrorMessage(errorMessage); } else if (messageEvent->getStanza()->getPayload<MUCInvitationPayload>()) { handleMUCInvitation(messageEvent->getStanza()); return; } + else if (messageEvent->getStanza()->getPayload<MUCUserPayload>() && messageEvent->getStanza()->getPayload<MUCUserPayload>()->getInvite()) { + handleMediatedMUCInvitation(messageEvent->getStanza()); + return; + } else { if (!messageEvent->isReadable()) { return; } showChatWindow(); JID from = message->getFrom(); std::vector<boost::shared_ptr<Delay> > delayPayloads = message->getPayloads<Delay>(); for (size_t i = 0; useDelayForLatency_ && i < delayPayloads.size(); i++) { if (!delayPayloads[i]->getFrom()) { continue; } boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time(); std::ostringstream s; s << "The following message took " << (now - delayPayloads[i]->getStamp()).total_milliseconds() / 1000.0 << " seconds to be delivered from " << delayPayloads[i]->getFrom()->toString() << "."; chatWindow_->addSystemMessage(std::string(s.str())); } boost::shared_ptr<SecurityLabel> label = message->getPayload<SecurityLabel>(); // Determine the timestamp boost::posix_time::ptime timeStamp = boost::posix_time::microsec_clock::universal_time(); boost::optional<boost::posix_time::ptime> messageTimeStamp = getMessageTimestamp(message); if (messageTimeStamp) { timeStamp = *messageTimeStamp; } onActivity(body); boost::shared_ptr<Replace> replace = message->getPayload<Replace>(); if (replace) { std::string body = message->getBody(); // Should check if the user has a previous message std::map<JID, std::string>::iterator lastMessage; lastMessage = lastMessagesUIID_.find(from); if (lastMessage != lastMessagesUIID_.end()) { chatWindow_->replaceMessage(body, lastMessagesUIID_[from], timeStamp); } @@ -234,36 +239,55 @@ std::string ChatControllerBase::getErrorMessage(boost::shared_ptr<ErrorPayload> } else { switch (error->getCondition()) { case ErrorPayload::BadRequest: return QT_TRANSLATE_NOOP("", "Bad request"); break; case ErrorPayload::Conflict: return QT_TRANSLATE_NOOP("", "Conflict"); break; case ErrorPayload::FeatureNotImplemented: return QT_TRANSLATE_NOOP("", "This feature is not implemented"); break; case ErrorPayload::Forbidden: return QT_TRANSLATE_NOOP("", "Forbidden"); break; case ErrorPayload::Gone: return QT_TRANSLATE_NOOP("", "Recipient can no longer be contacted"); break; case ErrorPayload::InternalServerError: return QT_TRANSLATE_NOOP("", "Internal server error"); break; case ErrorPayload::ItemNotFound: return QT_TRANSLATE_NOOP("", "Item not found"); break; case ErrorPayload::JIDMalformed: return QT_TRANSLATE_NOOP("", "JID Malformed"); break; case ErrorPayload::NotAcceptable: return QT_TRANSLATE_NOOP("", "Message was rejected"); break; case ErrorPayload::NotAllowed: return QT_TRANSLATE_NOOP("", "Not allowed"); break; case ErrorPayload::NotAuthorized: return QT_TRANSLATE_NOOP("", "Not authorized"); break; case ErrorPayload::PaymentRequired: return QT_TRANSLATE_NOOP("", "Payment is required"); break; case ErrorPayload::RecipientUnavailable: return QT_TRANSLATE_NOOP("", "Recipient is unavailable"); break; case ErrorPayload::Redirect: return QT_TRANSLATE_NOOP("", "Redirect"); break; case ErrorPayload::RegistrationRequired: return QT_TRANSLATE_NOOP("", "Registration required"); break; case ErrorPayload::RemoteServerNotFound: return QT_TRANSLATE_NOOP("", "Recipient's server not found"); break; case ErrorPayload::RemoteServerTimeout: return QT_TRANSLATE_NOOP("", "Remote server timeout"); break; case ErrorPayload::ResourceConstraint: return QT_TRANSLATE_NOOP("", "The server is low on resources"); break; case ErrorPayload::ServiceUnavailable: return QT_TRANSLATE_NOOP("", "The service is unavailable"); break; case ErrorPayload::SubscriptionRequired: return QT_TRANSLATE_NOOP("", "A subscription is required"); break; case ErrorPayload::UndefinedCondition: return QT_TRANSLATE_NOOP("", "Undefined condition"); break; case ErrorPayload::UnexpectedRequest: return QT_TRANSLATE_NOOP("", "Unexpected request"); break; } } return defaultMessage; } void ChatControllerBase::handleMUCInvitation(Message::ref message) { MUCInvitationPayload::ref invite = message->getPayload<MUCInvitationPayload>(); chatWindow_->addMUCInvitation(invite->getJID(), invite->getReason(), invite->getPassword()); } +void ChatControllerBase::handleMediatedMUCInvitation(Message::ref message) { + MUCUserPayload::Invite invite = *message->getPayload<MUCUserPayload>()->getInvite(); + JID from; + if (invite.from.isValid()) { + from = invite.from; + } + std::string reason; + if (!invite.reason.empty()) { + reason = invite.reason; + } + std::string password; + if (message->getPayload<MUCUserPayload>()->getPassword()) { + password = *message->getPayload<MUCUserPayload>()->getPassword(); + } + chatWindow_->addMUCInvitation(from, reason, password, false); +} + + + } diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h index f1ecfe8..e1034d6 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.h +++ b/Swift/Controllers/Chat/ChatControllerBase.h @@ -51,55 +51,56 @@ namespace Swift { /** Used for determining when something is recent.*/ boost::signal<void (const std::string& /*activity*/)> onActivity; boost::signal<void ()> onUnreadCountChanged; int getUnreadCount(); const JID& getToJID() {return toJID_;} void handleCapsChanged(const JID& jid); protected: ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, TimerFactory* timerFactory, EntityCapsProvider* entityCapsProvider); /** * Pass the Message appended, and the stanza used to send it. */ virtual void postSendMessage(const std::string&, boost::shared_ptr<Stanza>) {}; virtual std::string senderDisplayNameFromMessage(const JID& from) = 0; virtual bool isIncomingMessageFromMe(boost::shared_ptr<Message>) = 0; virtual void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {}; virtual void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>) {}; virtual void preSendMessageRequest(boost::shared_ptr<Message>) {}; virtual bool isFromContact(const JID& from); virtual boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message>) const = 0; virtual void dayTicked() {}; virtual void handleBareJIDCapsChanged(const JID& jid) = 0; std::string getErrorMessage(boost::shared_ptr<ErrorPayload>); virtual void setContactIsReceivingPresence(bool /* isReceivingPresence */) {} private: IDGenerator idGenerator_; std::string lastSentMessageStanzaID_; void createDayChangeTimer(); void handleSendMessageRequest(const std::string &body, bool isCorrectionMessage); void handleAllMessagesRead(); void handleSecurityLabelsCatalogResponse(boost::shared_ptr<SecurityLabelsCatalog>, ErrorPayload::ref error); void handleDayChangeTick(); void handleMUCInvitation(Message::ref message); + void handleMediatedMUCInvitation(Message::ref message); protected: JID selfJID_; std::vector<boost::shared_ptr<MessageEvent> > unreadMessages_; StanzaChannel* stanzaChannel_; IQRouter* iqRouter_; ChatWindowFactory* chatWindowFactory_; ChatWindow* chatWindow_; JID toJID_; bool labelsEnabled_; std::map<JID, std::string> lastMessagesUIID_; PresenceOracle* presenceOracle_; AvatarManager* avatarManager_; bool useDelayForLatency_; EventController* eventController_; boost::shared_ptr<Timer> dateChangeTimer_; TimerFactory* timerFactory_; EntityCapsProvider* entityCapsProvider_; }; } diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 61c3208..ff00bc1 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -1,66 +1,67 @@ /* * Copyright (c) 2010-2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include "Swift/Controllers/Chat/ChatsManager.h" #include <boost/bind.hpp> #include <boost/algorithm/string.hpp> #include <Swiften/Base/foreach.h> #include <Swift/Controllers/Chat/ChatController.h> #include <Swift/Controllers/Chat/ChatControllerBase.h> #include <Swift/Controllers/Chat/MUCSearchController.h> #include <Swift/Controllers/XMPPEvents/EventController.h> #include <Swift/Controllers/Chat/MUCController.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/AddMUCBookmarkUIEvent.h> #include <Swift/Controllers/UIEvents/RemoveMUCBookmarkUIEvent.h> #include <Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h> #include <Swift/Controllers/UIEvents/ToggleRequestDeliveryReceiptsUIEvent.h> #include <Swift/Controllers/UIInterfaces/ChatListWindowFactory.h> #include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h> #include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h> #include <Swiften/Presence/PresenceSender.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/MUC/MUCManager.h> #include <Swiften/Elements/ChatState.h> +#include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Elements/DeliveryReceipt.h> #include <Swiften/Elements/DeliveryReceiptRequest.h> #include <Swiften/MUC/MUCBookmarkManager.h> #include <Swift/Controllers/FileTransfer/FileTransferController.h> #include <Swift/Controllers/FileTransfer/FileTransferOverview.h> #include <Swift/Controllers/ProfileSettingsProvider.h> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Elements/MUCInvitationPayload.h> #include <Swiften/Roster/XMPPRoster.h> namespace Swift { typedef std::pair<JID, ChatController*> JIDChatControllerPair; typedef std::pair<JID, MUCController*> JIDMUCControllerPair; #define RECENT_CHATS "recent_chats" ChatsManager::ChatsManager( JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* settings, @@ -542,71 +543,71 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional if (nickMaybe) { bookmark.setNick(*nickMaybe); } mucBookmarkManager_->addBookmark(bookmark); } std::map<JID, MUCController*>::iterator it = mucControllers_.find(mucJID); if (it != mucControllers_.end()) { it->second->rejoin(); } else { std::string nick = (nickMaybe && !(*nickMaybe).empty()) ? nickMaybe.get() : nickResolver_->jidToNick(jid_); MUC::ref muc = mucManager->createMUC(mucJID); if (createAsReservedIfNew) { muc->setCreateAsReservedIfNew(); } MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_); mucControllers_[mucJID] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); controller->onUserJoined.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), "", true)); controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), _1, true)); controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller)); handleChatActivity(mucJID.toBare(), "", true); } mucControllers_[mucJID]->showChatWindow(); } void ChatsManager::handleSearchMUCRequest() { mucSearchController_->openSearchWindow(); } void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) { JID jid = message->getFrom(); boost::shared_ptr<MessageEvent> event(new MessageEvent(message)); - bool isInvite = message->getPayload<MUCInvitationPayload>(); + bool isInvite = message->getPayload<MUCInvitationPayload>() || (message->getPayload<MUCUserPayload>() && message->getPayload<MUCUserPayload>()->getInvite()); if (!event->isReadable() && !message->getPayload<ChatState>() && !message->getPayload<DeliveryReceipt>() && !message->getPayload<DeliveryReceiptRequest>() && !isInvite && !message->hasSubject()) { return; } // Try to deliver it to a MUC if (message->getType() == Message::Groupchat || message->getType() == Message::Error || (isInvite && message->getType() == Message::Normal)) { std::map<JID, MUCController*>::iterator i = mucControllers_.find(jid.toBare()); if (i != mucControllers_.end()) { i->second->handleIncomingMessage(event); return; } else if (message->getType() == Message::Groupchat) { //FIXME: Error handling - groupchat messages from an unknown muc. return; } } //if not a mucroom getChatControllerOrCreate(jid)->handleIncomingMessage(event); } void ChatsManager::handleMUCSelectedAfterSearch(const JID& muc) { if (joinMUCWindow_) { joinMUCWindow_->setMUC(muc.toString()); } } void ChatsManager::handleMUCBookmarkActivated(const MUCBookmark& mucBookmark) { uiEventStream_->send(boost::make_shared<JoinMUCUIEvent>(mucBookmark.getRoom(), mucBookmark.getPassword(), mucBookmark.getNick())); } void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) { ChatController* chatController = getChatControllerOrCreate(ftc->getOtherParty()); chatController->handleNewFileTransferController(ftc); chatController->activateChatWindow(); diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index fd99514..fe7b6bf 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -24,71 +24,71 @@ namespace Swift { class AvatarManager; class TreeWidget; class Roster; class TabComplete; class RosterItem; class ContactRosterItem; class FileTransferController; class ChatWindow { public: enum AckState {Pending, Received, Failed}; enum ReceiptState {ReceiptRequested, ReceiptReceived}; enum Tristate {Yes, No, Maybe}; enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor}; enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed}; ChatWindow() {} virtual ~ChatWindow() {}; /** Add message to window. * @return id of added message (for acks). */ virtual 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) = 0; /** Adds action to window. * @return id of added message (for acks); */ virtual 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) = 0; virtual void addSystemMessage(const std::string& message) = 0; virtual void addPresenceMessage(const std::string& message) = 0; virtual void addErrorMessage(const std::string& message) = 0; virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) = 0; // 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 JID& jid, const std::string& reason, const std::string& password) = 0; + virtual void addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password, bool direct = true) = 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() = 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 std::string& 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; /** * 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; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 5e43549..cc54763 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -18,46 +18,46 @@ namespace Swift { virtual 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&) {lastMessageBody_ = message; return "";}; virtual void addSystemMessage(const std::string& /*message*/) {}; virtual void addErrorMessage(const std::string& /*message*/) {}; virtual void addPresenceMessage(const std::string& /*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*/) { }; 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() {}; virtual void setSecurityLabelsError() {}; virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() {return label_;} virtual void setInputEnabled(bool /*enabled*/) {}; virtual void setRosterModel(Roster* /*roster*/) {}; virtual void setTabComplete(TabComplete*) {}; virtual void replaceLastMessage(const std::string&) {}; virtual void replaceMessage(const std::string&, const std::string&, const boost::posix_time::ptime&) {}; 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 JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/) {}; + virtual void addMUCInvitation(const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool direct = true) {}; virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {} std::string name_; std::string lastMessageBody_; std::vector<SecurityLabelsCatalog::Item> labels_; bool labelsEnabled_; SecurityLabelsCatalog::Item label_; }; } diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 88f326f..ed8e632 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -763,60 +763,64 @@ void QtChatWindow::handleActionButtonClicked() { 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) { bool ok; QString jid = QInputDialog::getText(this, tr("Enter person's address"), tr("Address:"), QLineEdit::Normal, "", &ok); if (ok) { onInvitePersonToThisMUCRequest(JID(Q2PSTRING(jid)), ""); } } } 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::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::addMUCInvitation(const JID& jid, const std::string& reason, const std::string& /*password*/) { +void QtChatWindow::addMUCInvitation(const JID& jid, const std::string& reason, const std::string& /*password*/, bool direct) { bool accepted = false; QMessageBox msgBox; + //FIXME: horrid modal untranslated popup. Fix before release. msgBox.setText(QString("You have been invited to the room %1 by %2.").arg(P2QSTRING(jid.toString())).arg(contact_)); QString reasonString; if (!reason.empty()) { reasonString = QString("\"%1\"").arg(P2QSTRING(reason)); } + if (!direct) { + reasonString += QString("(%1 may not have really sent this invitation)").arg(P2QSTRING(jid.toString())); + } msgBox.setInformativeText(QString("Accept invitation from %1 to enter %2?\n%3").arg(contact_).arg(P2QSTRING(jid.toString())).arg(reasonString)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Yes: accepted = true; break; default: break; } if (accepted) { eventStream_->send(boost::make_shared<JoinMUCUIEvent>(jid)); } } } diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 55e929d..4f997c0 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -45,71 +45,71 @@ namespace Swift { 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(); void activate(); void setUnreadMessageCount(int count); void convertToMUC(); // 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 std::string& 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 JID& jid, const std::string& reason, const std::string& password); + void addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password, bool direct = true); void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&); 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 returnPressed(); void handleInputChanged(); void handleKeyPressEvent(QKeyEvent* event); void handleSplitterMoved(int pos, int index); void handleAlertButtonClicked(); void handleActionButtonClicked(); |
Swift