diff options
| author | Richard Maudsley <richard.maudsley@isode.com> | 2014-05-06 13:08:57 (GMT) |
|---|---|---|
| committer | Swift Review <review@swift.im> | 2014-05-29 16:18:23 (GMT) |
| commit | b70a50f11da1ea57a0e89ff14882eed03944eb2a (patch) | |
| tree | bbe3d3f28104dcba7d276a7016da283665b8f326 /Swift | |
| parent | ab612d0f18ff545b4ebcb2bf2bb400996e751181 (diff) | |
| download | swift-contrib-b70a50f11da1ea57a0e89ff14882eed03944eb2a.zip swift-contrib-b70a50f11da1ea57a0e89ff14882eed03944eb2a.tar.bz2 | |
Right-click MUC in Recents to bookmark.
Change-Id: Idfb5907adf9bf53f0ac1f417dd57d49ecc897bb0
Diffstat (limited to 'Swift')
| -rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 17 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 4 | ||||
| -rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 1 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/ChatListWindow.h | 7 | ||||
| -rw-r--r-- | Swift/QtUI/ChatList/QtChatListWindow.cpp | 39 | ||||
| -rw-r--r-- | Swift/QtUI/ChatList/QtChatListWindow.h | 3 |
6 files changed, 57 insertions, 14 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 654f735..1698b4a 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -1,123 +1,129 @@ /* * Copyright (c) 2010-2014 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 <boost/smart_ptr/make_shared.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> +#include <boost/serialization/optional.hpp> #include <boost/serialization/vector.hpp> #include <boost/serialization/map.hpp> #include <boost/serialization/string.hpp> #include <boost/serialization/split_free.hpp> #include <Swiften/Base/foreach.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 <Swiften/Avatars/AvatarManager.h> #include <Swiften/Elements/MUCInvitationPayload.h> #include <Swiften/Roster/XMPPRoster.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/StanzaChannel.h> #include <Swiften/VCards/VCardManager.h> #include <Swift/Controllers/Chat/ChatController.h> #include <Swift/Controllers/Chat/ChatControllerBase.h> #include <Swift/Controllers/Chat/MUCSearchController.h> #include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h> #include <Swift/Controllers/XMPPEvents/EventController.h> #include <Swift/Controllers/Chat/MUCController.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/CreateImpromptuMUCUIEvent.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/InviteToMUCUIEvent.h> #include <Swift/Controllers/UIInterfaces/ChatListWindowFactory.h> #include <Swift/Controllers/UIInterfaces/JoinMUCWindow.h> #include <Swift/Controllers/UIInterfaces/JoinMUCWindowFactory.h> #include <Swift/Controllers/FileTransfer/FileTransferController.h> #include <Swift/Controllers/FileTransfer/FileTransferOverview.h> #include <Swift/Controllers/ProfileSettingsProvider.h> #include <Swift/Controllers/Settings/SettingsProvider.h> #include <Swift/Controllers/SettingConstants.h> #include <Swift/Controllers/WhiteboardManager.h> #include <Swift/Controllers/Chat/ChatMessageParser.h> #include <Swift/Controllers/Chat/UserSearchController.h> #include <Swiften/Disco/DiscoServiceWalker.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/Base/Log.h> +BOOST_CLASS_VERSION(Swift::ChatListWindow::Chat, 1) + namespace boost { namespace serialization { template<class Archive> void save(Archive& ar, const Swift::JID& jid, const unsigned int /*version*/) { std::string jidStr = jid.toString(); ar << jidStr; } template<class Archive> void load(Archive& ar, Swift::JID& jid, const unsigned int /*version*/) { std::string stringJID; ar >> stringJID; jid = Swift::JID(stringJID); } template<class Archive> inline void serialize(Archive& ar, Swift::JID& t, const unsigned int file_version){ split_free(ar, t, file_version); } - template<class Archive> void serialize(Archive& ar, Swift::ChatListWindow::Chat& chat, const unsigned int /*version*/) { + template<class Archive> void serialize(Archive& ar, Swift::ChatListWindow::Chat& chat, const unsigned int version) { ar & chat.jid; ar & chat.chatName; ar & chat.activity; ar & chat.isMUC; ar & chat.nick; ar & chat.impromptuJIDs; + if (version > 0) { + ar & chat.password; + } } } } 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* profileSettings, FileTransferOverview* ftOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController, WhiteboardManager* whiteboardManager, @@ -337,86 +343,91 @@ void ChatsManager::setupBookmarks() { mucBookmarkManager_->onBookmarksReady.connect(boost::bind(&ChatsManager::handleBookmarksReady, this)); mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&ChatsManager::handleMUCBookmarkAdded, this, _1)); mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&ChatsManager::handleMUCBookmarkRemoved, this, _1)); if (chatListWindow_) { chatListWindow_->setBookmarksEnabled(false); chatListWindow_->clearBookmarks(); } } } void ChatsManager::handleBookmarksReady() { if (chatListWindow_) { chatListWindow_->setBookmarksEnabled(true); } } void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) { std::map<JID, MUCController*>::iterator it = mucControllers_.find(bookmark.getRoom()); if (it == mucControllers_.end() && bookmark.getAutojoin()) { handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false, false ); } chatListWindow_->addMUCBookmark(bookmark); } void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) { chatListWindow_->removeMUCBookmark(bookmark); } ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity) { int unreadCount = 0; if (mucRegistry_->isMUC(jid)) { MUCController* controller = mucControllers_[jid.toBare()]; StatusShow::Type type = StatusShow::None; std::string nick = ""; + std::string password = ""; if (controller) { unreadCount = controller->getUnreadCount(); if (controller->isJoined()) { type = StatusShow::Online; } nick = controller->getNick(); + if (controller->getPassword()) { + password = *controller->getPassword(); + } + if (controller->isImpromptu()) { - ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick); + ChatListWindow::Chat chat = ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password); typedef std::pair<std::string, JID> StringJIDPair; std::map<std::string, JID> participants = controller->getParticipantJIDs(); chat.impromptuJIDs = participants; return chat; } } - return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick); + return ChatListWindow::Chat(jid, jid.toString(), activity, unreadCount, type, boost::filesystem::path(), true, nick, password); } else { ChatController* controller = getChatControllerIfExists(jid, false); if (controller) { unreadCount = controller->getUnreadCount(); } JID bareishJID = mucRegistry_->isMUC(jid.toBare()) ? jid : jid.toBare(); Presence::ref presence = presenceOracle_->getHighestPriorityPresence(bareishJID); StatusShow::Type type = presence ? presence->getShow() : StatusShow::None; boost::filesystem::path avatarPath = avatarManager_ ? avatarManager_->getAvatarPath(bareishJID) : boost::filesystem::path(); return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false); } } void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity, bool isMUC) { if (mucRegistry_->isMUC(jid.toBare()) && !isMUC) { /* Don't include PMs in MUC rooms.*/ return; } ChatListWindow::Chat chat = createChatListChatItem(jid, activity); /* FIXME: handle nick changes */ appendRecent(chat); handleUnreadCountChanged(NULL); saveRecents(); } void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) { int unreadTotal = 0; bool controllerIsMUC = dynamic_cast<MUCController*>(controller); bool isPM = controller && !controllerIsMUC && mucRegistry_->isMUC(controller->getToJID().toBare()); foreach (ChatListWindow::Chat& chatItem, recentChats_) { bool match = false; if (controller) { /* Matching MUC item */ match |= chatItem.isMUC == controllerIsMUC && chatItem.jid.toBare() == controller->getToJID().toBare(); /* Matching PM */ diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 4860fc8..6bc7067 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -211,70 +211,74 @@ void MUCController::handleBareJIDCapsChanged(const JID& /*jid*/) { } /** * Join the MUC if not already in it. */ void MUCController::rejoin() { if (parting_) { joined_ = false; parting_ = false; if (password_) { muc_->setPassword(*password_); } //FIXME: check for received activity #ifdef SWIFT_EXPERIMENTAL_HISTORY if (lastActivity_ == boost::posix_time::not_a_date_time && historyController_) { lastActivity_ = historyController_->getLastTimeStampFromMUC(selfJID_, toJID_); } #endif if (lastActivity_ == boost::posix_time::not_a_date_time) { muc_->joinAs(nick_); } else { muc_->joinWithContextSince(nick_, lastActivity_); } } } bool MUCController::isJoined() { return joined_; } const std::string& MUCController::getNick() { return nick_; } +const boost::optional<std::string> MUCController::getPassword() const { + return password_; +} + bool MUCController::isImpromptu() const { return isImpromptu_; } std::map<std::string, JID> MUCController::getParticipantJIDs() const { std::map<std::string, JID> participants; typedef std::pair<std::string, MUCOccupant> MUCOccupantPair; std::map<std::string, MUCOccupant> occupants = muc_->getOccupants(); foreach(const MUCOccupantPair& occupant, occupants) { if (occupant.first != nick_) { participants[occupant.first] = occupant.second.getRealJID().is_initialized() ? occupant.second.getRealJID().get().toBare() : JID(); } } return participants; } void MUCController::sendInvites(const std::vector<JID>& jids, const std::string& reason) const { foreach (const JID& jid, jids) { muc_->invitePerson(jid, reason, isImpromptu_); } } void MUCController::handleJoinTimeoutTick() { receivedActivity(); chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString())), ChatWindow::DefaultDirection); } void MUCController::receivedActivity() { if (loginCheckTimer_) { loginCheckTimer_->stop(); } } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index e78ff77..feffaba 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -30,70 +30,71 @@ namespace Swift { class IQRouter; class ChatWindowFactory; class Roster; class AvatarManager; class UIEventStream; class TimerFactory; class TabComplete; class XMPPRoster; class HighlightManager; class UIEvent; class VCardManager; class RosterVCardProvider; enum JoinPart {Join, Part, JoinThenPart, PartThenJoin}; struct NickJoinPart { NickJoinPart(const std::string& nick, JoinPart type) : nick(nick), type(type) {} std::string nick; JoinPart type; }; class MUCController : public ChatControllerBase { public: MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* roster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ChatMessageParser* chatMessageParser, bool isImpromptu, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, VCardManager* vcardManager); virtual ~MUCController(); boost::signal<void ()> onUserLeft; boost::signal<void ()> onUserJoined; boost::signal<void ()> onImpromptuConfigCompleted; virtual void setOnline(bool online); void rejoin(); static void appendToJoinParts(std::vector<NickJoinPart>& joinParts, const NickJoinPart& newEvent); 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(); + const boost::optional<std::string> getPassword() const; 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); diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h index 67cd0ff..38d8c3e 100644 --- a/Swift/Controllers/UIInterfaces/ChatListWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h @@ -1,96 +1,97 @@ /* - * Copyright (c) 2010-2011 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 <list> #include <set> #include <map> #include <boost/shared_ptr.hpp> #include <Swiften/MUC/MUCBookmark.h> #include <Swiften/Elements/StatusShow.h> #include <boost/filesystem/path.hpp> #include <Swiften/Base/foreach.h> #include <Swiften/Base/boost_bsignals.h> namespace Swift { class ChatListWindow { public: class Chat { public: Chat() : statusType(StatusShow::None), isMUC(false), unreadCount(0) {} - Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, const std::string& nick = "") - : jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), unreadCount(unreadCount), avatarPath(avatarPath) {} + Chat(const JID& jid, const std::string& chatName, const std::string& activity, int unreadCount, StatusShow::Type statusType, const boost::filesystem::path& avatarPath, bool isMUC, const std::string& nick = "", const boost::optional<std::string> password = boost::optional<std::string>()) + : jid(jid), chatName(chatName), activity(activity), statusType(statusType), isMUC(isMUC), nick(nick), password(password), unreadCount(unreadCount), avatarPath(avatarPath) {} /** Assume that nicks and other transient features aren't important for equality */ bool operator==(const Chat& other) const { if (impromptuJIDs.empty()) { return jid.toBare() == other.jid.toBare() && isMUC == other.isMUC; } else { /* compare the chat occupant lists */ typedef std::map<std::string, JID> JIDMap; foreach (const JIDMap::value_type& jid, impromptuJIDs) { bool found = false; foreach (const JIDMap::value_type& otherJID, other.impromptuJIDs) { if (jid.second.toBare() == otherJID.second.toBare()) { found = true; break; } } if (!found) { return false; } } return true; } } void setUnreadCount(int unread) { unreadCount = unread; } void setStatusType(StatusShow::Type type) { statusType = type; } void setAvatarPath(const boost::filesystem::path& path) { avatarPath = path; } std::string getImpromptuTitle() const { typedef std::pair<std::string, JID> StringJIDPair; std::string title; foreach(StringJIDPair pair, impromptuJIDs) { if (title.empty()) { title += pair.first; } else { title += ", " + pair.first; } } return title; } JID jid; std::string chatName; std::string activity; StatusShow::Type statusType; bool isMUC; std::string nick; + boost::optional<std::string> password; int unreadCount; boost::filesystem::path avatarPath; std::map<std::string, JID> impromptuJIDs; }; virtual ~ChatListWindow(); virtual void setBookmarksEnabled(bool enabled) = 0; virtual void addMUCBookmark(const MUCBookmark& bookmark) = 0; virtual void addWhiteboardSession(const ChatListWindow::Chat& chat) = 0; virtual void removeWhiteboardSession(const JID& jid) = 0; virtual void removeMUCBookmark(const MUCBookmark& bookmark) = 0; virtual void setRecents(const std::list<Chat>& recents) = 0; virtual void setUnreadCount(int unread) = 0; virtual void clearBookmarks() = 0; boost::signal<void (const MUCBookmark&)> onMUCBookmarkActivated; boost::signal<void (const Chat&)> onRecentActivated; boost::signal<void (const JID&)> onWhiteboardActivated; boost::signal<void ()> onClearRecentsRequested; }; } diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp index 7455fb5..210124b 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.cpp +++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp @@ -36,154 +36,177 @@ QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, SettingsProvide model_ = new ChatListModel(); setModel(model_); delegate_ = new ChatListDelegate(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); setItemDelegate(delegate_); setHeaderHidden(true); #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif expandAll(); setAnimated(true); setIndentation(0); setDragEnabled(true); setRootIsDecorated(true); setupContextMenus(); connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&))); connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleClicked(const QModelIndex&))); settings_->onSettingChanged.connect(boost::bind(&QtChatListWindow::handleSettingChanged, this, _1)); } QtChatListWindow::~QtChatListWindow() { settings_->onSettingChanged.disconnect(boost::bind(&QtChatListWindow::handleSettingChanged, this, _1)); delete model_; delete delegate_; delete mucMenu_; delete emptyMenu_; } void QtChatListWindow::handleSettingChanged(const std::string& setting) { if (setting == QtUISettingConstants::COMPACT_ROSTER.getKey()) { delegate_->setCompact(settings_->getSetting(QtUISettingConstants::COMPACT_ROSTER)); repaint(); } } +void QtChatListWindow::handleClearRecentsRequested() { + onClearRecentsRequested(); +} + void QtChatListWindow::setBookmarksEnabled(bool enabled) { bookmarksEnabled_ = enabled; } void QtChatListWindow::handleClicked(const QModelIndex& index) { ChatListGroupItem* item = dynamic_cast<ChatListGroupItem*>(static_cast<ChatListItem*>(index.internalPointer())); if (item) { setExpanded(index, !isExpanded(index)); } } void QtChatListWindow::setupContextMenus() { mucMenu_ = new QMenu(); mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark())); mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark())); mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark())); + mucRecentsMenu_ = new QMenu(); + mucRecentsMenu_->addAction(tr("Add to Bookmarks"), this, SLOT(handleAddBookmarkFromRecents())); + mucRecentsMenu_->addAction(tr("Clear recents"), this, SLOT(handleClearRecentsRequested())); emptyMenu_ = new QMenu(); emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark())); - } void QtChatListWindow::handleItemActivated(const QModelIndex& index) { ChatListItem* item = model_->getItemForIndex(index); if (ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(item)) { if (bookmarksEnabled_) { onMUCBookmarkActivated(mucItem->getBookmark()); } } else if (ChatListRecentItem* recentItem = dynamic_cast<ChatListRecentItem*>(item)) { if (!recentItem->getChat().isMUC || bookmarksEnabled_) { onRecentActivated(recentItem->getChat()); } } else if (ChatListWhiteboardItem* whiteboardItem = dynamic_cast<ChatListWhiteboardItem*>(item)) { if (!whiteboardItem->getChat().isMUC || bookmarksEnabled_) { eventStream_->send(boost::make_shared<ShowWhiteboardUIEvent>(whiteboardItem->getChat().jid)); } } } void QtChatListWindow::clearBookmarks() { model_->clearBookmarks(); } void QtChatListWindow::addMUCBookmark(const MUCBookmark& bookmark) { model_->addMUCBookmark(bookmark); } void QtChatListWindow::removeMUCBookmark(const MUCBookmark& bookmark) { model_->removeMUCBookmark(bookmark); } void QtChatListWindow::addWhiteboardSession(const ChatListWindow::Chat& chat) { model_->addWhiteboardSession(chat); } void QtChatListWindow::removeWhiteboardSession(const JID& jid) { model_->removeWhiteboardSession(jid); } void QtChatListWindow::setRecents(const std::list<ChatListWindow::Chat>& recents) { model_->setRecents(recents); } void QtChatListWindow::setUnreadCount(int unread) { emit onCountUpdated(unread); } void QtChatListWindow::handleRemoveBookmark() { ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(contextMenuItem_); if (!mucItem) return; eventStream_->send(boost::shared_ptr<UIEvent>(new RemoveMUCBookmarkUIEvent(mucItem->getBookmark()))); } +void QtChatListWindow::handleAddBookmarkFromRecents() { + ChatListRecentItem* item = dynamic_cast<ChatListRecentItem*>(contextMenuItem_); + if (item) { + const ChatListWindow::Chat& chat = item->getChat(); + MUCBookmark bookmark(chat.jid, chat.jid.toBare().toString()); + bookmark.setNick(chat.nick); + bookmark.setPassword(chat.password); + eventStream_->send(boost::shared_ptr<UIEvent>(new AddMUCBookmarkUIEvent(bookmark))); + } +} + void QtChatListWindow::handleAddBookmark() { (new QtAddBookmarkWindow(eventStream_))->show(); } void QtChatListWindow::handleEditBookmark() { ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(contextMenuItem_); if (!mucItem) return; QtEditBookmarkWindow* window = new QtEditBookmarkWindow(eventStream_, mucItem->getBookmark()); window->show(); } void QtChatListWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) { event->acceptProposedAction(); } } void QtChatListWindow::contextMenuEvent(QContextMenuEvent* event) { QModelIndex index = indexAt(event->pos()); ChatListItem* baseItem = index.isValid() ? static_cast<ChatListItem*>(index.internalPointer()) : NULL; contextMenuItem_ = baseItem; if (!baseItem) { emptyMenu_->exec(QCursor::pos()); return; } + ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(baseItem); if (mucItem) { if (!bookmarksEnabled_) { return; } mucMenu_->exec(QCursor::pos()); + return; } - else { - QMenu menu; - QAction* clearRecents = menu.addAction(tr("Clear recents")); - menu.addAction(clearRecents); - QAction* result = menu.exec(event->globalPos()); - if (result == clearRecents) { - onClearRecentsRequested(); + + ChatListRecentItem* recentItem = dynamic_cast<ChatListRecentItem*>(baseItem); + if (recentItem) { + const ChatListWindow::Chat& chat = recentItem->getChat(); + if (chat.isMUC) { + mucRecentsMenu_->exec(QCursor::pos()); + return; } } + + QMenu menu; + menu.addAction(tr("Clear recents"), this, SLOT(handleClearRecentsRequested())); + menu.exec(event->globalPos()); } } diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h index e218266..1cba3a4 100644 --- a/Swift/QtUI/ChatList/QtChatListWindow.h +++ b/Swift/QtUI/ChatList/QtChatListWindow.h @@ -4,55 +4,58 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <QTreeView> #include "Swift/Controllers/UIInterfaces/ChatListWindow.h" #include "Swift/Controllers/UIEvents/UIEventStream.h" #include "Swift/QtUI/ChatList/ChatListModel.h" #include "Swift/QtUI/ChatList/ChatListDelegate.h" namespace Swift { class SettingsProvider; class QtChatListWindow : public QTreeView, public ChatListWindow { Q_OBJECT public: QtChatListWindow(UIEventStream *uiEventStream, SettingsProvider* settings, QWidget* parent = NULL); virtual ~QtChatListWindow(); void addMUCBookmark(const MUCBookmark& bookmark); void removeMUCBookmark(const MUCBookmark& bookmark); void addWhiteboardSession(const ChatListWindow::Chat& chat); void removeWhiteboardSession(const JID& jid); void setBookmarksEnabled(bool enabled); void setRecents(const std::list<ChatListWindow::Chat>& recents); void setUnreadCount(int unread); void clearBookmarks(); signals: void onCountUpdated(int count); private slots: void handleItemActivated(const QModelIndex&); void handleAddBookmark(); void handleEditBookmark(); void handleRemoveBookmark(); + void handleAddBookmarkFromRecents(); void handleClicked(const QModelIndex& index); void handleSettingChanged(const std::string& setting); + void handleClearRecentsRequested(); protected: void dragEnterEvent(QDragEnterEvent* event); void contextMenuEvent(QContextMenuEvent* event); private: void setupContextMenus(); bool bookmarksEnabled_; UIEventStream* eventStream_; ChatListModel* model_; ChatListDelegate* delegate_; QMenu* mucMenu_; QMenu* emptyMenu_; + QMenu* mucRecentsMenu_; ChatListItem* contextMenuItem_; SettingsProvider* settings_; }; } |
Swift