summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp4
-rw-r--r--Swift/Controllers/Chat/ChatController.h3
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.cpp12
-rw-r--r--Swift/Controllers/Chat/ChatControllerBase.h6
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp100
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h72
-rw-r--r--Swift/Controllers/Chat/Chattables.cpp34
-rw-r--r--Swift/Controllers/Chat/Chattables.h47
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp5
-rw-r--r--Swift/Controllers/Chat/MUCController.h2
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp5
-rw-r--r--Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp7
-rw-r--r--Swift/Controllers/MainController.cpp9
-rw-r--r--Swift/Controllers/MainController.h4
-rw-r--r--Swift/Controllers/Roster/RosterController.cpp21
-rw-r--r--Swift/Controllers/Roster/RosterController.h6
-rw-r--r--Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp10
-rw-r--r--Swift/Controllers/SConscript1
-rw-r--r--Swift/Controllers/UIInterfaces/MainWindowFactory.h14
-rw-r--r--Swift/Controllers/UnitTest/MockMainWindowFactory.h4
-rw-r--r--Swift/QtUI/ChattablesModel.cpp52
-rw-r--r--Swift/QtUI/ChattablesModel.h28
-rw-r--r--Swift/QtUI/QtChatOverview.cpp66
-rw-r--r--Swift/QtUI/QtChatOverview.h28
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.cpp145
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.h57
-rw-r--r--Swift/QtUI/QtChatOverviewDelegate.cpp88
-rw-r--r--Swift/QtUI/QtChatOverviewDelegate.h23
-rw-r--r--Swift/QtUI/QtChatTabs.cpp3
-rw-r--r--Swift/QtUI/QtMainWindow.cpp23
-rw-r--r--Swift/QtUI/QtMainWindow.h46
-rw-r--r--Swift/QtUI/QtUIFactory.cpp4
-rw-r--r--Swift/QtUI/QtUIFactory.h3
-rw-r--r--Swift/QtUI/SConscript192
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.cpp23
-rw-r--r--Swift/QtUI/Trellis/QtDynamicGridLayout.h4
36 files changed, 945 insertions, 206 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 5f5f41d..e299d03 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -52,8 +52,8 @@ namespace Swift {
/**
* The controller does not gain ownership of the stanzaChannel, nor the factory.
*/
-ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings)
- : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, nickResolver, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider, settings), userWantsReceipts_(userWantsReceipts), clientBlockListManager_(clientBlockListManager) {
+ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings, Chattables& chattables)
+ : ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, contact, nickResolver, presenceOracle, avatarManager, useDelayForLatency, eventStream, eventController, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider, settings, chattables), userWantsReceipts_(userWantsReceipts), clientBlockListManager_(clientBlockListManager) {
isInMUC_ = isInMUC;
lastWasPresence_ = false;
chatStateNotifier_ = new ChatStateNotifier(stanzaChannel, contact, entityCapsProvider, timerFactory, 20000);
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 72acc27..716b3ed 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -30,7 +30,7 @@ namespace Swift {
class ChatController : public ChatControllerBase {
public:
- ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings);
+ ChatController(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &contact, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool isInMUC, bool useDelayForLatency, UIEventStream* eventStream, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, bool userWantsReceipts, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings, Chattables& chattables);
virtual ~ChatController() override;
virtual void setToJID(const JID& jid) override;
virtual void setAvailableServerFeatures(std::shared_ptr<DiscoInfo> info) override;
@@ -117,4 +117,3 @@ namespace Swift {
boost::optional<ChatWindow::AlertID> blockedContactAlert_;
};
}
-
diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp
index b1854d8..0e86d6c 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.cpp
+++ b/Swift/Controllers/Chat/ChatControllerBase.cpp
@@ -25,6 +25,7 @@
#include <Swiften/Queries/Requests/GetSecurityLabelsCatalogRequest.h>
#include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
#include <Swift/Controllers/Highlighting/HighlightManager.h>
#include <Swift/Controllers/Highlighting/Highlighter.h>
@@ -38,7 +39,7 @@
namespace Swift {
-ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry), chatMessageParser_(chatMessageParser), autoAcceptMUCInviteDecider_(autoAcceptMUCInviteDecider), eventStream_(eventStream), roomSecurityMarking_(""), previousMessageSecurityMarking_(""), settings_(settings) {
+ChatControllerBase::ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings, Chattables& chattables) : selfJID_(self), stanzaChannel_(stanzaChannel), iqRouter_(iqRouter), chatWindowFactory_(chatWindowFactory), toJID_(toJID), labelsEnabled_(false), presenceOracle_(presenceOracle), avatarManager_(avatarManager), useDelayForLatency_(useDelayForLatency), eventController_(eventController), entityCapsProvider_(entityCapsProvider), historyController_(historyController), mucRegistry_(mucRegistry), chatMessageParser_(chatMessageParser), autoAcceptMUCInviteDecider_(autoAcceptMUCInviteDecider), eventStream_(eventStream), roomSecurityMarking_(""), previousMessageSecurityMarking_(""), settings_(settings), chattables_(chattables) {
chatWindow_ = chatWindowFactory_->createChatWindow(toJID, eventStream);
chatWindow_->onAllMessagesRead.connect(boost::bind(&ChatControllerBase::handleAllMessagesRead, this));
chatWindow_->onSendMessageRequest.connect(boost::bind(&ChatControllerBase::handleSendMessageRequest, this, _1, _2));
@@ -188,8 +189,15 @@ ChatWindow::ChatMessage ChatControllerBase::buildChatWindowChatMessage(const std
}
void ChatControllerBase::updateMessageCount() {
- chatWindow_->setUnreadMessageCount(boost::numeric_cast<int>(unreadMessages_.size()));
+ int intCount = boost::numeric_cast<int>(unreadMessages_.size());
+ chatWindow_->setUnreadMessageCount(intCount);
+ auto baseJID = getBaseJID();
+ auto state = chattables_.getState(baseJID);
+ state.unreadCount = intCount;
+ chattables_.setState(baseJID, state);
+#ifndef NOT_YET
onUnreadCountChanged();
+#endif
}
std::string ChatControllerBase::addMessage(const ChatWindow::ChatMessage& chatMessage, const std::string& senderName, bool senderIsSelf, const std::shared_ptr<SecurityLabel> label, const boost::filesystem::path& avatarPath, const boost::posix_time::ptime& time) {
diff --git a/Swift/Controllers/Chat/ChatControllerBase.h b/Swift/Controllers/Chat/ChatControllerBase.h
index f635a46..9da4d88 100644
--- a/Swift/Controllers/Chat/ChatControllerBase.h
+++ b/Swift/Controllers/Chat/ChatControllerBase.h
@@ -37,11 +37,12 @@ namespace Swift {
class AutoAcceptMUCInviteDecider;
class AvatarManager;
class ChatMessageParser;
+ class Chattables;
class ChatWindowFactory;
class EntityCapsProvider;
class EventController;
- class HighlightManager;
class Highlighter;
+ class HighlightManager;
class IQRouter;
class NickResolver;
class StanzaChannel;
@@ -80,7 +81,7 @@ namespace Swift {
boost::signals2::signal<void(ChatWindow* /*window to reuse*/, const std::vector<JID>& /*invite people*/, const std::string& /*reason*/)> onConvertToMUC;
protected:
- ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings);
+ ChatControllerBase(const JID& self, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, const JID &toJID, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, bool useDelayForLatency, UIEventStream* eventStream, EventController* eventController, EntityCapsProvider* entityCapsProvider, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, std::shared_ptr<ChatMessageParser> chatMessageParser, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, SettingsProvider* settings, Chattables& chattables);
/**
* Pass the Message appended, and the stanza used to send it.
@@ -154,5 +155,6 @@ namespace Swift {
std::string roomSecurityMarking_;
std::string previousMessageSecurityMarking_;
SettingsProvider* settings_;
+ Chattables& chattables_;
};
}
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 81892fc..63fd677 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -34,6 +34,7 @@
#include <Swiften/VCards/VCardManager.h>
#include <Swift/Controllers/Chat/AutoAcceptMUCInviteDecider.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/ChatController.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swift/Controllers/Chat/ChatListWindowChatBoostSerialize.h>
@@ -66,7 +67,9 @@ namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
+#ifndef NOT_YET
#define RECENT_CHATS "recent_chats"
+#endif
ChatsManager::ChatsManager(
JID jid, StanzaChannel* stanzaChannel,
@@ -78,7 +81,9 @@ ChatsManager::ChatsManager(
PresenceOracle* presenceOracle,
PresenceSender* presenceSender,
UIEventStream* uiEventStream,
+#ifndef NOT_YET
ChatListWindowFactory* chatListWindowFactory,
+#endif
bool useDelayForLatency,
TimerFactory* timerFactory,
MUCRegistry* mucRegistry,
@@ -95,7 +100,8 @@ ChatsManager::ChatsManager(
HighlightManager* highlightManager,
ClientBlockListManager* clientBlockListManager,
const std::map<std::string, std::string>& emoticons,
- VCardManager* vcardManager) :
+ VCardManager* vcardManager,
+ Chattables& chattables) :
jid_(jid),
joinMUCWindowFactory_(joinMUCWindowFactory),
useDelayForLatency_(useDelayForLatency),
@@ -111,7 +117,8 @@ ChatsManager::ChatsManager(
highlightManager_(highlightManager),
emoticons_(emoticons),
clientBlockListManager_(clientBlockListManager),
- vcardManager_(vcardManager) {
+ vcardManager_(vcardManager),
+ chattables_(chattables) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
@@ -127,12 +134,12 @@ ChatsManager::ChatsManager(
profileSettings_ = profileSettings;
presenceOracle_->onPresenceChange.connect(boost::bind(&ChatsManager::handlePresenceChange, this, _1));
uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&ChatsManager::handleUIEvent, this, _1));
-
+#ifndef NOT_YET
chatListWindow_ = chatListWindowFactory->createChatListWindow(uiEventStream_);
chatListWindow_->onMUCBookmarkActivated.connect(boost::bind(&ChatsManager::handleMUCBookmarkActivated, this, _1));
chatListWindow_->onRecentActivated.connect(boost::bind(&ChatsManager::handleRecentActivated, this, _1));
chatListWindow_->onClearRecentsRequested.connect(boost::bind(&ChatsManager::handleClearRecentsRequested, this));
-
+#endif
joinMUCWindow_ = nullptr;
mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_);
mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
@@ -146,18 +153,22 @@ ChatsManager::ChatsManager(
roster_->onJIDUpdated.connect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
roster_->onRosterCleared.connect(boost::bind(&ChatsManager::handleRosterCleared, this));
+ chattables_.onActivated.connect(boost::bind(&ChatsManager::handleChattableActivated, this, _1));
+
settings_->onSettingChanged.connect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
userWantsReceipts_ = settings_->getSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS);
setupBookmarks();
+#ifndef NOT_YET
loadRecents();
-
+#endif
autoAcceptMUCInviteDecider_ = new AutoAcceptMUCInviteDecider(jid.getDomain(), roster_, settings_);
}
ChatsManager::~ChatsManager() {
settings_->onSettingChanged.disconnect(boost::bind(&ChatsManager::handleSettingChanged, this, _1));
+ chattables_.onActivated.disconnect(boost::bind(&ChatsManager::handleChattableActivated, this, _1));
roster_->onJIDAdded.disconnect(boost::bind(&ChatsManager::handleJIDAddedToRoster, this, _1));
roster_->onJIDRemoved.disconnect(boost::bind(&ChatsManager::handleJIDRemovedFromRoster, this, _1));
roster_->onJIDUpdated.disconnect(boost::bind(&ChatsManager::handleJIDUpdatedInRoster, this, _1));
@@ -176,6 +187,7 @@ ChatsManager::~ChatsManager() {
delete autoAcceptMUCInviteDecider_;
}
+#ifndef NOT_YET
void ChatsManager::saveRecents() {
std::stringstream serializeStream;
boost::archive::text_oarchive oa(serializeStream);
@@ -208,6 +220,7 @@ void ChatsManager::handleClearRecentsRequested() {
saveRecents();
handleUnreadCountChanged(nullptr);
}
+#endif
void ChatsManager::handleJIDAddedToRoster(const JID &jid) {
updatePresenceReceivingStateOnChatController(jid);
@@ -242,6 +255,7 @@ void ChatsManager::updatePresenceReceivingStateOnChatController(const JID &jid)
}
}
+#ifndef NOT_YET
ChatListWindow::Chat ChatsManager::updateChatStatusAndAvatarHelper(const ChatListWindow::Chat& chat) const {
ChatListWindow::Chat fixedChat = chat;
if (fixedChat.isMUC) {
@@ -309,6 +323,7 @@ void ChatsManager::loadRecents() {
}
handleUnreadCountChanged(nullptr);
}
+#endif
void ChatsManager::setupBookmarks() {
if (!mucBookmarkManager_) {
@@ -317,17 +332,21 @@ void ChatsManager::setupBookmarks() {
mucBookmarkManager_->onBookmarkAdded.connect(boost::bind(&ChatsManager::handleMUCBookmarkAdded, this, _1));
mucBookmarkManager_->onBookmarkRemoved.connect(boost::bind(&ChatsManager::handleMUCBookmarkRemoved, this, _1));
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(false);
chatListWindow_->clearBookmarks();
}
+#endif
}
}
void ChatsManager::handleBookmarksReady() {
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(true);
}
+#endif
}
void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) {
@@ -336,14 +355,20 @@ void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) {
if (it == mucControllers_.end() && bookmark.getAutojoin()) {
handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false, false );
}
+#ifndef NOT_YET
chatListWindow_->addMUCBookmark(bookmark);
+#endif
+ chattables_.addJID(bookmark.getRoom(), Chattables::State::Type::Room);
}
}
void ChatsManager::handleMUCBookmarkRemoved(const MUCBookmark& bookmark) {
+#ifndef NOT_YET
chatListWindow_->removeMUCBookmark(bookmark);
+#endif
}
+#ifndef NOT_YET
ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage) {
int unreadCount = 0;
if (mucRegistry_->isMUC(jid)) {
@@ -388,8 +413,10 @@ ChatListWindow::Chat ChatsManager::createChatListChatItem(const JID& jid, const
return ChatListWindow::Chat(bareishJID, nickResolver_->jidToNick(bareishJID), activity, unreadCount, type, avatarPath, false, privateMessage);
}
}
+#endif
void ChatsManager::handleChatActivity(const JID& jid, const std::string& activity, bool isMUC) {
+#ifndef NOT_YET
const bool privateMessage = mucRegistry_->isMUC(jid.toBare()) && !isMUC;
ChatListWindow::Chat chat = createChatListChatItem(jid, activity, privateMessage);
/* FIXME: handle nick changes */
@@ -405,13 +432,18 @@ void ChatsManager::handleChatActivity(const JID& jid, const std::string& activit
mucControllers_[jid]->setChatWindowTitle(chatListWindowIter->getTitle());
}
}
+#endif
}
void ChatsManager::handleChatClosed(const JID& /*jid*/) {
cleanupPrivateMessageRecents();
+#ifndef NOT_YET
chatListWindow_->setRecents(recentChats_);
+#endif
}
+#ifndef NOT_YET
+
void ChatsManager::handleUnreadCountChanged(ChatControllerBase* controller) {
int unreadTotal = 0;
bool controllerIsMUC = dynamic_cast<MUCController*>(controller);
@@ -445,7 +477,9 @@ boost::optional<ChatListWindow::Chat> ChatsManager::removeExistingChat(const Cha
return boost::optional<ChatListWindow::Chat>();
}
}
+#endif
+#ifndef NOT_YET
void ChatsManager::cleanupPrivateMessageRecents() {
/* if we leave a MUC and close a PM, remove it's recent chat entry */
const std::list<ChatListWindow::Chat> chats = recentChats_;
@@ -483,23 +517,32 @@ void ChatsManager::prependRecent(const ChatListWindow::Chat& chat) {
}
recentChats_.push_back(mergedChat);
}
+#endif
void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
std::map<JID, MUCController*>::iterator it;
for (it = mucControllers_.begin(); it != mucControllers_.end(); ++it) {
if ((*it).second == mucController) {
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (chat.isMUC && chat.jid == (*it).first) {
chat.statusType = StatusShow::None;
}
}
+#endif
+ const auto& jid = it->first;
+ auto state = chattables_.getState(jid);
+ state.status = StatusShow::None;
+ chattables_.setState(jid, state);
mucControllers_.erase(it);
delete mucController;
break;
}
}
cleanupPrivateMessageRecents();
+#ifndef NOT_YET
chatListWindow_->setRecents(recentChats_);
+#endif
}
void ChatsManager::handleSettingChanged(const std::string& settingPath) {
@@ -600,6 +643,7 @@ void ChatsManager::handleUIEvent(std::shared_ptr<UIEvent> event) {
}
}
+#ifndef NOT_YET
void ChatsManager::markAllRecentsOffline() {
for (ChatListWindow::Chat& chat : recentChats_) {
chat.setStatusType(StatusShow::None);
@@ -607,6 +651,7 @@ void ChatsManager::markAllRecentsOffline() {
chatListWindow_->setRecents(recentChats_);
}
+#endif
void ChatsManager::handleTransformChatToMUC(ChatController* chatController, ChatWindow* chatWindow, const std::vector<JID>& jidsToInvite, const std::string& reason) {
JID reuseChatInvite = chatController->getToJID();
@@ -629,7 +674,7 @@ void ChatsManager::handleTransformChatToMUC(ChatController* chatController, Chat
*/
void ChatsManager::handlePresenceChange(std::shared_ptr<Presence> newPresence) {
if (mucRegistry_->isMUC(newPresence->getFrom().toBare())) return;
-
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (newPresence->getFrom().toBare() == chat.jid.toBare() && !chat.isMUC) {
Presence::ref presence = presenceOracle_->getHighestPriorityPresence(chat.jid.toBare());
@@ -638,8 +683,9 @@ void ChatsManager::handlePresenceChange(std::shared_ptr<Presence> newPresence) {
break;
}
}
-
+#endif
//if (newPresence->getType() != Presence::Unavailable) return;
+
JID fullJID(newPresence->getFrom());
std::map<JID, ChatController*>::iterator it = chatControllers_.find(fullJID);
if (it == chatControllers_.end()) return;
@@ -654,21 +700,25 @@ void ChatsManager::setAvatarManager(AvatarManager* avatarManager) {
avatarManager_->onAvatarChanged.disconnect(boost::bind(&ChatsManager::handleAvatarChanged, this, _1));
}
avatarManager_ = avatarManager;
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (!chat.isMUC) {
chat.setAvatarPath(avatarManager_->getAvatarPath(chat.jid));
}
}
+#endif
avatarManager_->onAvatarChanged.connect(boost::bind(&ChatsManager::handleAvatarChanged, this, _1));
}
void ChatsManager::handleAvatarChanged(const JID& jid) {
+#ifndef NOT_YET
for (ChatListWindow::Chat& chat : recentChats_) {
if (!chat.isMUC && jid.toBare() == chat.jid.toBare()) {
chat.setAvatarPath(avatarManager_->getAvatarPath(jid));
break;
}
}
+#endif
}
void ChatsManager::setServerDiscoInfo(std::shared_ptr<DiscoInfo> info) {
@@ -705,10 +755,11 @@ void ChatsManager::setOnline(bool enabled) {
localMUCServiceFinderWalker_->onWalkComplete.connect(boost::bind(&ChatsManager::handleLocalServiceWalkFinished, this));
localMUCServiceFinderWalker_->beginWalk();
}
-
+#ifndef NOT_YET
if (chatListWindow_) {
chatListWindow_->setBookmarksEnabled(enabled);
}
+#endif
}
void ChatsManager::handleChatRequest(const std::string &contact) {
@@ -732,12 +783,14 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact)
ChatController* ChatsManager::createNewChatController(const JID& contact) {
assert(chatControllers_.find(contact) == chatControllers_.end());
std::shared_ptr<ChatMessageParser> chatMessageParser = std::make_shared<ChatMessageParser>(emoticons_, highlightManager_->getConfiguration(), ChatMessageParser::Mode::Chat); /* a message parser that knows this is a chat (not a room/MUC) */
- auto controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, timerFactory_, eventController_, entityCapsProvider_, userWantsReceipts_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, autoAcceptMUCInviteDecider_, settings_);
+ auto controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, timerFactory_, eventController_, entityCapsProvider_, userWantsReceipts_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, autoAcceptMUCInviteDecider_, settings_, chattables_);
chatControllers_[contact] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
controller->onWindowClosed.connect(boost::bind(&ChatsManager::handleChatClosed, this, contact));
+#ifndef NOT_YET
controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#endif
controller->onConvertToMUC.connect(boost::bind(&ChatsManager::handleTransformChatToMUC, this, controller, _1, _2, _3));
updatePresenceReceivingStateOnChatController(contact);
controller->setCanStartImpromptuChats(!localMUCServiceJID_.toString().empty());
@@ -821,7 +874,7 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
chatWindowFactoryAdapter = new SingleChatWindowFactoryAdapter(reuseChatwindow);
}
std::shared_ptr<ChatMessageParser> chatMessageParser = std::make_shared<ChatMessageParser>(emoticons_, highlightManager_->getConfiguration(), ChatMessageParser::Mode::GroupChat); /* a message parser that knows this is a room/MUC (not a chat) */
- controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, reuseChatwindow ? chatWindowFactoryAdapter : chatWindowFactory_, nickResolver_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, isImpromptu, autoAcceptMUCInviteDecider_, vcardManager_, mucBookmarkManager_, settings_);
+ controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, reuseChatwindow ? chatWindowFactoryAdapter : chatWindowFactory_, nickResolver_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser, isImpromptu, autoAcceptMUCInviteDecider_, vcardManager_, mucBookmarkManager_, settings_, chattables_);
if (chatWindowFactoryAdapter) {
/* The adapters are only passed to chat windows, which are deleted in their
* controllers' dtor, which are deleted in ChatManager's dtor. The adapters
@@ -835,7 +888,9 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
controller->onUserJoined.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), "", true));
controller->onUserNicknameChanged.connect(boost::bind(&ChatsManager::handleUserNicknameChanged, this, controller, _1, _2));
controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, mucJID.toBare(), _1, true));
- controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#ifndef NOT_YET
+ controller->onUnreadCountChanged.connect(boost::bind(&ChatsManager::handleUnreadCountChanged, this, controller));
+#endif
if (!stanzaChannel_->isAvailable()) {
/* When online, the MUC is added to the registry in MUCImpl::internalJoin. This method is not
* called when Swift is offline, so we add it here as only MUCs in the registry are rejoined
@@ -845,12 +900,12 @@ MUC::ref ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::opti
}
handleChatActivity(mucJID.toBare(), "", true);
}
-
+#ifndef NOT_YET
auto chatListWindowIter = std::find_if(recentChats_.begin(), recentChats_.end(), [&](const ChatListWindow::Chat& chatListWindow) { return mucJID == (chatListWindow.jid); });
if (chatListWindowIter != recentChats_.end() && (mucControllers_[mucJID]->isImpromptu() || !chatListWindowIter->impromptuJIDs.empty())) {
mucControllers_[mucJID]->setChatWindowTitle(chatListWindowIter->getTitle());
}
-
+#endif
mucControllers_[mucJID]->showChatWindow();
return muc;
}
@@ -1023,7 +1078,7 @@ void ChatsManager::handleWhiteboardStateChange(const JID& contact, const ChatWin
chatListWindow_->removeWhiteboardSession(contact.toBare());
}
}
-
+#ifndef NOT_YET
void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
if (chat.isMUC && !chat.impromptuJIDs.empty()) {
typedef std::pair<std::string, JID> StringJIDPair;
@@ -1043,6 +1098,19 @@ void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
}
}
+#endif
+
+void ChatsManager::handleChattableActivated(const JID& jid) {
+ auto state = chattables_.getState(jid);
+ if (state.type == Chattables::State::Type::Person) {
+ uiEventStream_->send(std::make_shared<RequestChatUIEvent>(jid));
+ }
+ else if (state.type == Chattables::State::Type::Room) {
+ //FIXME: Find bookmarks and do handleMUCBookmarkActivated things
+ uiEventStream_->send(std::make_shared<JoinMUCUIEvent>(jid, boost::optional<std::string>(), boost::optional<std::string>())); // Just a quick hack to reuse already open MUCs
+ }
+}
+
void ChatsManager::handleLocalServiceFound(const JID& service, std::shared_ptr<DiscoInfo> info) {
for (DiscoInfo::Identity identity : info->getIdentities()) {
if ((identity.getCategory() == "directory"
@@ -1068,17 +1136,21 @@ void ChatsManager::handleLocalServiceWalkFinished() {
onImpromptuMUCServiceDiscovered(impromptuMUCSupported);
}
+#ifndef NOT_YET
std::vector<ChatListWindow::Chat> ChatsManager::getRecentChats() const {
return std::vector<ChatListWindow::Chat>(recentChats_.begin(), recentChats_.end());
}
+#endif
std::vector<Contact::ref> Swift::ChatsManager::getContacts(bool withMUCNicks) {
std::vector<Contact::ref> result;
+#ifndef NOT_YET
for (ChatListWindow::Chat chat : recentChats_) {
if (!chat.isMUC) {
result.push_back(std::make_shared<Contact>(chat.chatName.empty() ? chat.jid.toString() : chat.chatName, chat.jid, chat.statusType, chat.avatarPath));
}
}
+#endif
if (withMUCNicks) {
/* collect MUC nicks */
typedef std::map<JID, MUCController*>::value_type Item;
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 6004347..0b85840 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -27,49 +27,52 @@
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
namespace Swift {
- class EventController;
+ class AutoAcceptMUCInviteDecider;
+ class AvatarManager;
class ChatController;
class ChatControllerBase;
- class MUCController;
- class MUCManager;
+ class ChatListWindowFactory;
+ class ChatMessageParser;
+ class Chattables;
+ class ClientBlockListManager;
+ class DirectedPresenceSender;
+ class DiscoServiceWalker;
+ class EntityCapsProvider;
+ class EventController;
+ class FileTransferController;
+ class FileTransferOverview;
+ class HighlightManager;
+ class HistoryController;
+ class IQRouter;
class JoinMUCWindow;
class JoinMUCWindowFactory;
+ class MUCBookmarkManager;
+ class MUCController;
+ class MUCManager;
+ class MUCSearchController;
+ class MUCSearchWindowFactory;
class NickResolver;
class PresenceOracle;
- class AvatarManager;
- class StanzaChannel;
- class IQRouter;
class PresenceSender;
- class MUCBookmarkManager;
- class ChatListWindowFactory;
- class TimerFactory;
- class EntityCapsProvider;
- class DirectedPresenceSender;
- class MUCSearchWindowFactory;
class ProfileSettingsProvider;
- class MUCSearchController;
- class FileTransferOverview;
- class FileTransferController;
- class XMPPRoster;
class SettingsProvider;
- class WhiteboardManager;
- class HistoryController;
- class HighlightManager;
- class ClientBlockListManager;
- class ChatMessageParser;
- class DiscoServiceWalker;
- class AutoAcceptMUCInviteDecider;
+ class StanzaChannel;
+ class TimerFactory;
class VCardManager;
+ class WhiteboardManager;
+ class XMPPRoster;
class ChatsManager : public ContactProvider {
public:
- 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, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, const std::map<std::string, std::string>& emoticons, VCardManager* vcardManager);
+ 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, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, const std::map<std::string, std::string>& emoticons, VCardManager* vcardManager, Chattables& chattables);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
void setServerDiscoInfo(std::shared_ptr<DiscoInfo> info);
void handleIncomingMessage(std::shared_ptr<Message> incomingMessage);
+#ifndef NOT_YET
std::vector<ChatListWindow::Chat> getRecentChats() const;
+#endif
virtual std::vector<Contact::ref> getContacts(bool withMUCNicks);
boost::signals2::signal<void (bool supportsImpromptu)> onImpromptuMUCServiceDiscovered;
@@ -86,7 +89,9 @@ namespace Swift {
};
private:
+#ifndef NOT_YET
ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity, bool privateMessage);
+#endif
void handleChatRequest(const std::string& contact);
void finalizeImpromptuJoin(MUC::ref muc, const std::vector<JID>& jidsToInvite, const std::string& reason, const boost::optional<JID>& reuseChatJID = boost::optional<JID>());
MUC::ref handleJoinMUCRequest(const JID& muc, const boost::optional<std::string>& password, const boost::optional<std::string>& nick, bool addAutoJoin, bool createAsReservedIfNew, bool isImpromptu, ChatWindow* reuseChatwindow = nullptr);
@@ -105,18 +110,25 @@ namespace Swift {
void handleNewFileTransferController(FileTransferController*);
void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);
void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);
+#ifndef NOT_YET
boost::optional<ChatListWindow::Chat> removeExistingChat(const ChatListWindow::Chat& chat);
+#endif
bool messageCausesSessionBinding(std::shared_ptr<Message> message);
void cleanupPrivateMessageRecents();
+#ifndef NOT_YET
void appendRecent(const ChatListWindow::Chat& chat);
void prependRecent(const ChatListWindow::Chat& chat);
+#endif
void setupBookmarks();
+#ifndef NOT_YET
void loadRecents();
void saveRecents();
void handleChatMadeRecent();
void handleMUCBookmarkActivated(const MUCBookmark&);
void handleRecentActivated(const ChatListWindow::Chat&);
void handleUnreadCountChanged(ChatControllerBase* controller);
+#endif
+ void handleChattableActivated(const JID& jid);
void handleAvatarChanged(const JID& jid);
void handleClearRecentsRequested();
void handleJIDAddedToRoster(const JID&);
@@ -126,12 +138,13 @@ namespace Swift {
void handleSettingChanged(const std::string& settingPath);
void markAllRecentsOffline();
void handleTransformChatToMUC(ChatController* chatController, ChatWindow* chatWindow, const std::vector<JID>& jidsToInvite, const std::string& reason);
-
void handleLocalServiceFound(const JID& service, std::shared_ptr<DiscoInfo> info);
void handleLocalServiceWalkFinished();
-
void updatePresenceReceivingStateOnChatController(const JID&);
+#ifndef NOT_YET
ChatListWindow::Chat updateChatStatusAndAvatarHelper(const ChatListWindow::Chat& chat) const;
+#endif
+
ChatController* getChatControllerOrFindAnother(const JID &contact);
@@ -156,7 +169,9 @@ namespace Swift {
UIEventStream* uiEventStream_;
MUCBookmarkManager* mucBookmarkManager_;
std::shared_ptr<DiscoInfo> serverDiscoInfo_;
+#ifndef NOT_YET
ChatListWindow* chatListWindow_;
+#endif
JoinMUCWindow* joinMUCWindow_;
boost::signals2::scoped_connection uiEventConnection_;
bool useDelayForLatency_;
@@ -165,7 +180,9 @@ namespace Swift {
EntityCapsProvider* entityCapsProvider_;
MUCManager* mucManager;
MUCSearchController* mucSearchController_;
+#ifndef NOT_YET
std::list<ChatListWindow::Chat> recentChats_;
+#endif
ProfileSettingsProvider* profileSettings_;
FileTransferOverview* ftOverview_;
XMPPRoster* roster_;
@@ -182,6 +199,7 @@ namespace Swift {
AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider_;
IDGenerator idGenerator_;
VCardManager* vcardManager_;
+ Chattables& chattables_;
std::map<JID, std::set<JID>> invitees_;
};
diff --git a/Swift/Controllers/Chat/Chattables.cpp b/Swift/Controllers/Chat/Chattables.cpp
new file mode 100644
index 0000000..b75e18d
--- /dev/null
+++ b/Swift/Controllers/Chat/Chattables.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/Controllers/Chat/Chattables.h>
+
+namespace Swift {
+
+const std::vector<JID>& Chattables::get() const {
+ return list_;
+}
+
+const Chattables::State& Chattables::getState(const JID& jid) const {
+ auto it = states_.find(jid);
+ return it != states_.end() ? it->second : unknown_;
+}
+
+void Chattables::addJID(const JID& jid, State::Type type) {
+ State state;
+ state.type = type;
+ state.jid = jid;
+ list_.push_back(jid);
+ states_[jid] = state;
+ onAdded(jid);
+}
+
+void Chattables::setState(const JID& jid, State state) {
+ states_[jid] = state;
+ onChanged(jid);
+}
+
+}
diff --git a/Swift/Controllers/Chat/Chattables.h b/Swift/Controllers/Chat/Chattables.h
new file mode 100644
index 0000000..c5c7b85
--- /dev/null
+++ b/Swift/Controllers/Chat/Chattables.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include <boost/signals2.hpp>
+
+#include <Swiften/Elements/StatusShow.h>
+#include <Swiften/JID/JID.h>
+
+namespace Swift {
+class Chattables {
+ public:
+ struct State {
+ enum class Type {Room, Person};
+ JID jid;
+ /// Empty for no name
+ std::string name;
+ int unreadCount = 0;
+ Type type;
+ StatusShow::Type status = StatusShow::None;
+ //avatar
+ //status
+ };
+ const std::vector<JID>& get() const;
+ const State& getState(const JID& jid) const;
+
+ void addJID(const JID& jid, State::Type type);
+ void setState(const JID& jid, State state);
+
+ boost::signals2::signal<void (const JID&)> onAdded;
+ boost::signals2::signal<void (const JID&)> onRemoved;
+ boost::signals2::signal<void (const JID&)> onChanged;
+ /// The UI has activated a chattable item (e.g. clicked in the roster)
+ boost::signals2::signal<void (const JID&)> onActivated;
+ private:
+ std::vector<JID> list_;
+ std::map<JID, State> states_;
+ State unknown_;
+};
+}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 139f425..071b919 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -100,8 +100,9 @@ MUCController::MUCController (
AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider,
VCardManager* vcardManager,
MUCBookmarkManager* mucBookmarkManager,
- SettingsProvider* settings) :
- ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), nickResolver, presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider, settings), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0), isImpromptu_(isImpromptu), isImpromptuAlreadyConfigured_(false), clientBlockListManager_(clientBlockListManager), mucBookmarkManager_(mucBookmarkManager) {
+ SettingsProvider* settings,
+ Chattables& chattables) :
+ ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), nickResolver, presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, entityCapsProvider, historyController, mucRegistry, highlightManager, chatMessageParser, autoAcceptMUCInviteDecider, settings, chattables), muc_(muc), nick_(nick), desiredNick_(nick), password_(password), renameCounter_(0), isImpromptu_(isImpromptu), isImpromptuAlreadyConfigured_(false), clientBlockListManager_(clientBlockListManager), mucBookmarkManager_(mucBookmarkManager) {
assert(avatarManager_);
parting_ = true;
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index afc524f..bd1148f 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -53,7 +53,7 @@ namespace Swift {
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, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* xmppRoster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, bool isImpromptu, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, VCardManager* vcardManager, MUCBookmarkManager* mucBookmarkManager, SettingsProvider* settings);
+ MUCController(const JID& self, MUC::ref muc, const boost::optional<std::string>& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider, XMPPRoster* xmppRoster, HistoryController* historyController, MUCRegistry* mucRegistry, HighlightManager* highlightManager, ClientBlockListManager* clientBlockListManager, std::shared_ptr<ChatMessageParser> chatMessageParser, bool isImpromptu, AutoAcceptMUCInviteDecider* autoAcceptMUCInviteDecider, VCardManager* vcardManager, MUCBookmarkManager* mucBookmarkManager, SettingsProvider* settings, Chattables& chattables);
virtual ~MUCController() override;
boost::signals2::signal<void ()> onUserLeft;
boost::signals2::signal<void ()> onUserJoined;
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 4a46b32..e0a7fe3 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -50,6 +50,7 @@
#include <Swift/Controllers/Chat/ChatController.h>
#include <Swift/Controllers/Chat/ChatsManager.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/Chat/UnitTest/MockChatListWindow.h>
#include <Swift/Controllers/EventNotifier.h>
@@ -207,7 +208,8 @@ public:
mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createChatListWindow).With(uiEventStream_).Return(chatListWindow_);
clientBlockListManager_ = new ClientBlockListManager(iqRouter_);
timerFactory_ = new DummyTimerFactory();
- manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, timerFactory_, mucRegistry_, entityCapsProvider_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, nullptr, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, vcardManager_);
+ chattables_ = std::make_unique<Chattables>();
+ manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, joinMUCWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, timerFactory_, mucRegistry_, entityCapsProvider_, mucManager_, mucSearchWindowFactory_, profileSettings_, ftOverview_, xmppRoster_, false, settings_, nullptr, wbManager_, highlightManager_, clientBlockListManager_, emoticons_, vcardManager_, *chattables_);
manager_->setAvatarManager(avatarManager_);
}
@@ -1764,6 +1766,7 @@ private:
int handledHighlightActions_;
std::set<std::string> soundsPlayed_;
DummyTimerFactory* timerFactory_;
+ std::unique_ptr<Chattables> chattables_;
};
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index 05ab3a7..3777ba6 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -6,6 +6,8 @@
#include <boost/algorithm/string.hpp>
+#include <memory>
+
#include <gtest/gtest.h>
#include <hippomocks.h>
@@ -31,6 +33,7 @@
#include <Swiften/VCards/VCardMemoryStorage.h>
#include <Swift/Controllers/Chat/ChatMessageParser.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/Chat/UserSearchController.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
@@ -82,7 +85,8 @@ class MUCControllerTest : public ::testing::Test {
nickResolver_ = new NickResolver(self_, xmppRoster_, vcardManager_, mucRegistry_);
clientBlockListManager_ = new ClientBlockListManager(iqRouter_);
mucBookmarkManager_ = new MUCBookmarkManager(iqRouter_);
- controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, nickResolver_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, nullptr, nullptr, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser_, false, nullptr, vcardManager_, mucBookmarkManager_, settings_);
+ chattables_ = std::make_unique<Chattables>();
+ controller_ = new MUCController (self_, muc_, boost::optional<std::string>(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, nickResolver_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_, nullptr, nullptr, mucRegistry_, highlightManager_, clientBlockListManager_, chatMessageParser_, false, nullptr, vcardManager_, mucBookmarkManager_, settings_, *chattables_);
}
void TearDown() {
@@ -238,6 +242,7 @@ class MUCControllerTest : public ::testing::Test {
ClientBlockListManager* clientBlockListManager_;
MUCBookmarkManager* mucBookmarkManager_;
XMPPRoster* xmppRoster_;
+ std::unique_ptr<Chattables> chattables_;
};
TEST_F(MUCControllerTest, testAddressedToSelf) {
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index b22e467..f678c0d 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -47,6 +47,7 @@
#include <Swift/Controllers/AdHocManager.h>
#include <Swift/Controllers/BlockListController.h>
#include <Swift/Controllers/BuildVersion.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Chat/ChatsManager.h>
#include <Swift/Controllers/Chat/MUCController.h>
#include <Swift/Controllers/Chat/UserSearchController.h>
@@ -277,6 +278,7 @@ void MainController::resetClient() {
blockListController_ = nullptr;
delete rosterController_;
rosterController_ = nullptr;
+ chattables_.reset();
delete eventNotifier_;
eventNotifier_ = nullptr;
delete presenceNotifier_;
@@ -348,7 +350,8 @@ void MainController::handleConnected() {
showProfileController_ = new ShowProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_);
ftOverview_ = new FileTransferOverview(client_->getFileTransferManager());
fileTransferListController_->setFileTransferOverview(ftOverview_);
- rosterController_ = new RosterController(boundJID_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), client_->getClientBlockListManager(), client_->getVCardManager());
+ chattables_ = std::make_unique<Chattables>();
+ rosterController_ = new RosterController(boundJID_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), client_->getClientBlockListManager(), client_->getVCardManager(), *chattables_);
rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
rosterController_->getWindow()->onShowCertificateRequest.connect(boost::bind(&MainController::handleShowCertificateRequest, this));
@@ -372,7 +375,7 @@ void MainController::handleConnected() {
historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), client_->getPresenceOracle(), uiFactory_);
chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_, whiteboardManager_, highlightManager_, client_->getClientBlockListManager(), emoticons_, client_->getVCardManager());
#else
- chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, nullptr, whiteboardManager_, highlightManager_, client_->getClientBlockListManager(), emoticons_, client_->getVCardManager());
+ chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, nullptr, whiteboardManager_, highlightManager_, client_->getClientBlockListManager(), emoticons_, client_->getVCardManager(), *chattables_);
#endif
contactsFromRosterProvider_ = new ContactsFromXMPPRoster(client_->getRoster(), client_->getAvatarManager(), client_->getPresenceOracle());
contactSuggesterWithoutRoster_->addContactProvider(chatsManager_);
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index cc3d45f..8b62415 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -33,6 +33,7 @@ namespace Swift {
class UIFactory;
class EventLoop;
class Client;
+ class Chattables;
class ChatController;
class ChatsManager;
class CertificateStorageFactory;
@@ -152,6 +153,7 @@ namespace Swift {
TogglableNotifier* notifier_;
PresenceNotifier* presenceNotifier_;
EventNotifier* eventNotifier_;
+ std::unique_ptr<Chattables> chattables_;
RosterController* rosterController_;
EventController* eventController_;
EventWindowController* eventWindowController_;
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index f5de801..90c5ce1 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -31,6 +31,7 @@
#include <Swiften/Roster/XMPPRosterItem.h>
#include <Swiften/VCards/VCardManager.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Intl.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
#include <Swift/Controllers/Roster/ItemOperations/AppearOffline.h>
@@ -49,6 +50,7 @@
#include <Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h>
#include <Swift/Controllers/UIEvents/RenameGroupUIEvent.h>
#include <Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIInterfaces/MainWindow.h>
#include <Swift/Controllers/UIInterfaces/MainWindowFactory.h>
#include <Swift/Controllers/XMPPEvents/ErrorEvent.h>
@@ -60,14 +62,16 @@ namespace Swift {
/**
* The controller does not gain ownership of these parameters.
*/
-RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager)
- : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), vcardManager_(vcardManager), avatarManager_(avatarManager), nickManager_(nickManager), nickResolver_(nickResolver), presenceOracle_(presenceOracle), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), clientBlockListManager_(clientBlockListManager) {
+RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager, Chattables& chattables)
+ : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(chattables, uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), vcardManager_(vcardManager), avatarManager_(avatarManager), nickManager_(nickManager), nickResolver_(nickResolver), presenceOracle_(presenceOracle), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), clientBlockListManager_(clientBlockListManager), chattables_(chattables) {
iqRouter_ = iqRouter;
subscriptionManager_ = subscriptionManager;
eventController_ = eventController;
settings_ = settings;
expandiness_ = new RosterGroupExpandinessPersister(roster_, settings);
+#ifndef NOT_YET
mainWindow_->setRosterModel(roster_);
+#endif
rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithoutResource);
changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2));
@@ -148,6 +152,11 @@ void RosterController::handleOnJIDAdded(const JID& jid) {
roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid));
}
applyAllPresenceTo(jid);
+
+ chattables_.addJID(jid, Chattables::State::Type::Person);
+ auto state = chattables_.getState(jid);
+ state.name = name;
+ chattables_.setState(jid, state);
}
void RosterController::applyAllPresenceTo(const JID& jid) {
@@ -329,13 +338,17 @@ void RosterController::handleIncomingPresence(Presence::ref newPresence) {
if (newPresence->getType() == Presence::Error) {
return;
}
- Presence::ref accountPresence = presenceOracle_->getAccountPresence(newPresence->getFrom().toBare());
+ auto bareFrom = newPresence->getFrom().toBare();
+ Presence::ref accountPresence = presenceOracle_->getAccountPresence(bareFrom);
if (!accountPresence) {
accountPresence = Presence::create();
accountPresence->setFrom(newPresence->getFrom());
accountPresence->setType(Presence::Unavailable);
}
roster_->applyOnItems(SetPresence(accountPresence));
+ auto state = chattables_.getState(bareFrom);
+ state.status = accountPresence->getShow();
+ chattables_.setState(bareFrom, state);
}
void RosterController::handleSubscriptionRequest(const JID& jid, const std::string& message) {
diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h
index ca2ecdc..d5a5671 100644
--- a/Swift/Controllers/Roster/RosterController.h
+++ b/Swift/Controllers/Roster/RosterController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -24,6 +24,7 @@
namespace Swift {
class AvatarManager;
+ class Chattables;
class ClientBlockListManager;
class EntityCapsProvider;
class EventController;
@@ -49,7 +50,7 @@ namespace Swift {
class RosterController {
public:
- RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager);
+ RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager, Chattables& chattables);
~RosterController();
void showRosterWindow();
void setJID(const JID& jid) { myJID_ = jid; }
@@ -112,6 +113,7 @@ namespace Swift {
UIEventStream* uiEventStream_;
EntityCapsProvider* entityCapsManager_;
ClientBlockListManager* clientBlockListManager_;
+ Chattables& chattables_;
RosterVCardProvider* rosterVCardProvider_;
std::shared_ptr<ContactRosterItem> ownContact_;
std::unique_ptr<FeatureOracle> featureOracle_;
diff --git a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
index 9b64def..0a9ea18 100644
--- a/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
+++ b/Swift/Controllers/Roster/UnitTest/RosterControllerTest.cpp
@@ -1,9 +1,11 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
+#include <memory>
+
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
@@ -32,6 +34,7 @@
#include <Swiften/VCards/VCardManager.h>
#include <Swiften/VCards/VCardMemoryStorage.h>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
#include <Swift/Controllers/Roster/Roster.h>
@@ -62,6 +65,7 @@ class RosterControllerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testRemoveResultsInUnavailablePresence);
CPPUNIT_TEST(testOwnContactInRosterPresence);
CPPUNIT_TEST(testMultiResourceFileTransferFeature);
+ //FIXME: All needs rewriting for new roster
CPPUNIT_TEST_SUITE_END();
public:
@@ -90,7 +94,8 @@ class RosterControllerTest : public CppUnit::TestFixture {
clientBlockListManager_ = new ClientBlockListManager(router_);
vcardStorage_ = new VCardMemoryStorage(crypto_);
vcardManager_ = new VCardManager(jid_, router_, vcardStorage_);
- rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, clientBlockListManager_, vcardManager_);
+ chattables_ = std::make_unique<Chattables>();
+ rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickManager_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_, entityCapsManager_, clientBlockListManager_, vcardManager_, *chattables_);
mainWindow_ = mainWindowFactory_->last;
capsInfoGenerator_ = std::make_unique<CapsInfoGenerator>("", crypto_);
}
@@ -476,6 +481,7 @@ class RosterControllerTest : public CppUnit::TestFixture {
VCardStorage* vcardStorage_;
VCardManager* vcardManager_;
std::unique_ptr<CapsInfoGenerator> capsInfoGenerator_;
+ std::unique_ptr<Chattables> chattables_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(RosterControllerTest);
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index bc5c2c0..0f50ac9 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -25,6 +25,7 @@ if env["SCONS_STAGE"] == "build" :
"AdHocController.cpp",
"AdHocManager.cpp",
"BlockListController.cpp",
+ "Chat/Chattables.cpp",
"Chat/ChatController.cpp",
"Chat/ChatControllerBase.cpp",
"Chat/ChatMessageParser.cpp",
diff --git a/Swift/Controllers/UIInterfaces/MainWindowFactory.h b/Swift/Controllers/UIInterfaces/MainWindowFactory.h
index c0110cf..af924e2 100644
--- a/Swift/Controllers/UIInterfaces/MainWindowFactory.h
+++ b/Swift/Controllers/UIInterfaces/MainWindowFactory.h
@@ -1,17 +1,15 @@
/*
- * Copyright (c) 2010 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
-#ifndef SWIFTEN_MainWindowFactory_H
-#define SWIFTEN_MainWindowFactory_H
-
-#include "Swiften/JID/JID.h"
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
+#pragma once
namespace Swift {
+ class Chattables;
class MainWindow;
+ class UIEventStream;
class MainWindowFactory {
public:
@@ -19,9 +17,7 @@ namespace Swift {
/**
* Transfers ownership of result.
*/
- virtual MainWindow* createMainWindow(UIEventStream* eventStream) = 0;
+ virtual MainWindow* createMainWindow(Chattables&, UIEventStream*) = 0;
};
}
-#endif
-
diff --git a/Swift/Controllers/UnitTest/MockMainWindowFactory.h b/Swift/Controllers/UnitTest/MockMainWindowFactory.h
index adf4fdf..331ca11 100644
--- a/Swift/Controllers/UnitTest/MockMainWindowFactory.h
+++ b/Swift/Controllers/UnitTest/MockMainWindowFactory.h
@@ -20,9 +20,7 @@ namespace Swift {
/**
* Transfers ownership of result.
*/
- virtual MainWindow* createMainWindow(UIEventStream*) {last = new MockMainWindow();return last;}
+ virtual MainWindow* createMainWindow(Chattables&, UIEventStream*) {last = new MockMainWindow();return last;}
MockMainWindow* last;
};
}
-
-
diff --git a/Swift/QtUI/ChattablesModel.cpp b/Swift/QtUI/ChattablesModel.cpp
new file mode 100644
index 0000000..d1257b9
--- /dev/null
+++ b/Swift/QtUI/ChattablesModel.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/ChattablesModel.h>
+
+#include <QDebug>
+
+#include <Swift/Controllers/Chat/Chattables.h>
+
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+
+ChattablesModel::ChattablesModel(Chattables& chattables, QObject* parent) : QAbstractListModel(parent), chattables_(chattables) {
+ //FIXME: scoped connections, do it properly not reset.
+ chattables_.onAdded.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+ chattables_.onRemoved.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+ chattables_.onChanged.connect([this](const JID& /*jid*/) {beginResetModel(); endResetModel();});
+}
+
+int ChattablesModel::rowCount(const QModelIndex& /*parent*/) const {
+ return chattables_.get().size();
+}
+
+QVariant ChattablesModel::data(const QModelIndex& index, int role) const {
+ //FIXME: Check validity
+ auto state = chattables_.getState(chattables_.get()[index.row()]);
+ if (role == Qt::DisplayRole) {
+ return P2QSTRING((state.name.empty() ? state.jid.toString() : state.name));
+ }
+ if (role == UnreadCountRole) {
+ return QString::number(state.unreadCount);
+ }
+ if (role == TypeRole) {
+ switch (state.type) {
+ case Chattables::State::Type::Room: return "ROOM";
+ case Chattables::State::Type::Person: return "PERSON";
+ }
+ }
+ if (role == StatusRole) {
+ return QVariant(static_cast<int>(state.status));
+ }
+ if (role == JIDRole) {
+ return P2QSTRING(state.jid.toString());
+ }
+ return QVariant();
+}
+
+}
diff --git a/Swift/QtUI/ChattablesModel.h b/Swift/QtUI/ChattablesModel.h
new file mode 100644
index 0000000..57073aa
--- /dev/null
+++ b/Swift/QtUI/ChattablesModel.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QAbstractListModel>
+
+namespace Swift {
+class Chattables;
+class ChattablesModel : public QAbstractListModel {
+ public:
+ enum ChattablesRoles {
+ UnreadCountRole = Qt::UserRole,
+ TypeRole = Qt::UserRole + 1,
+ StatusRole = Qt::UserRole + 2,
+ JIDRole = Qt::UserRole + 3
+ };
+ ChattablesModel(Chattables& chattables, QObject* parent);
+ int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
+ private:
+ Chattables& chattables_;
+};
+
+}
diff --git a/Swift/QtUI/QtChatOverview.cpp b/Swift/QtUI/QtChatOverview.cpp
new file mode 100644
index 0000000..76943e9
--- /dev/null
+++ b/Swift/QtUI/QtChatOverview.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverview.h>
+
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QPalette>
+#include <QVBoxLayout>
+
+#include <Swift/Controllers/Chat/Chattables.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/QtChatOverviewBundle.h>
+
+namespace Swift {
+
+QtChatOverview::QtChatOverview(Chattables& chattables, QWidget* parent) : QWidget(parent), chattables_(chattables) {
+ QPalette newPalette = palette();
+ newPalette.setColor(QPalette::Background, {38, 81, 112});
+ setAutoFillBackground(true);
+ newPalette.setColor(QPalette::Foreground, {255, 255, 255});
+ setPalette(newPalette);
+
+ auto mainLayout = new QVBoxLayout();
+ setLayout(mainLayout);
+
+ auto headerLayout = new QHBoxLayout();
+ mainLayout->addLayout(headerLayout);
+ auto allLabel = new QLabel(tr("All"), this);
+ allLabel->setStyleSheet("color: white;");
+ auto peopleLabel = new QLabel(tr("People"), this);
+ peopleLabel->setStyleSheet("color: white;");
+ auto roomsLabel = new QLabel(tr("Rooms"), this);
+ roomsLabel->setStyleSheet("color: white;");
+ headerLayout->addWidget(allLabel);
+ headerLayout->addWidget(peopleLabel);
+ headerLayout->addWidget(roomsLabel);
+
+ rootModel_ = new ChattablesModel(chattables_, this);
+
+ auto unreadBundle = new QtChatOverviewBundle(rootModel_, "UNREAD", true, this);
+ connect(unreadBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(unreadBundle);
+
+ auto peopleBundle = new QtChatOverviewBundle(rootModel_, "PEOPLE", false, this);
+ connect(peopleBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(peopleBundle);
+
+ auto roomsBundle = new QtChatOverviewBundle(rootModel_, "ROOMS", false, this);
+ connect(roomsBundle, SIGNAL(clicked(JID)), this, SLOT(handleItemClicked(JID)));
+ mainLayout->addWidget(roomsBundle);
+
+ mainLayout->addStretch();
+}
+
+QtChatOverview::~QtChatOverview() {}
+
+void QtChatOverview::handleItemClicked(JID jid) {
+ chattables_.onActivated(jid);
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverview.h b/Swift/QtUI/QtChatOverview.h
new file mode 100644
index 0000000..8cd7762
--- /dev/null
+++ b/Swift/QtUI/QtChatOverview.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QWidget>
+
+#include <Swiften/JID/JID.h>
+
+namespace Swift {
+ class Chattables;
+ class ChattablesModel;
+ class QtChatOverview : public QWidget {
+ Q_OBJECT
+ public:
+ QtChatOverview(Chattables&, QWidget* parent);
+ ~QtChatOverview() override;
+
+ private slots:
+ void handleItemClicked(JID jid);
+ private:
+ Chattables& chattables_;
+ ChattablesModel* rootModel_;
+ };
+}
diff --git a/Swift/QtUI/QtChatOverviewBundle.cpp b/Swift/QtUI/QtChatOverviewBundle.cpp
new file mode 100644
index 0000000..4e7c023
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewBundle.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverviewBundle.h>
+
+#include <QDebug>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QListView>
+#include <QPalette>
+#include <QSortFilterProxyModel>
+#include <QVBoxLayout>
+
+#include <Swiften/Elements/StatusShow.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/QtChatOverviewDelegate.h>
+#include <Swift/QtUI/QtClickableLabel.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
+
+namespace Swift {
+
+BundleFilter::BundleFilter(QObject* parent) : QSortFilterProxyModel(parent) {
+ sort(0, Qt::AscendingOrder);
+ setDynamicSortFilter(true);
+}
+
+void BundleFilter::addFilter(Filter filter) {
+ filters_.emplace(filter);
+ invalidateFilter();
+}
+
+bool BundleFilter::hasFilter(Filter filter) {
+ return filters_.count(filter) > 0;
+}
+
+void BundleFilter::removeFilter(Filter filter) {
+ filters_.erase(filter);
+ invalidateFilter();
+}
+
+bool BundleFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
+ auto row = sourceModel()->index(sourceRow, 0, sourceParent);
+ if (filters_.count(Filter::Unread)) {
+ if (row.data(ChattablesModel::UnreadCountRole).toInt() == 0) {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::People)) {
+ if (row.data(ChattablesModel::TypeRole).toString() != "PERSON") {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::Rooms)) {
+ if (row.data(ChattablesModel::TypeRole).toString() != "ROOM") {
+ return false;
+ }
+ }
+ if (filters_.count(Filter::Online)) {
+ if (static_cast<StatusShow::Type>(row.data(ChattablesModel::StatusRole).toInt()) == StatusShow::None) {
+ return false;
+ }
+ }
+ return true;
+}
+
+QtChatOverviewBundle::QtChatOverviewBundle(ChattablesModel* rootModel, QString name, bool hideWhenEmpty, QWidget* parent) : QWidget(parent), rootModel_(rootModel), hideWhenEmpty_(hideWhenEmpty) {
+ proxyModel_ = new BundleFilter(this);
+ if (name == "UNREAD") { // FIXME: Obviously needs a better approach
+ proxyModel_->addFilter(BundleFilter::Filter::Unread);
+ }
+ if (name == "PEOPLE") {
+ proxyModel_->addFilter(BundleFilter::Filter::People);
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ }
+ if (name == "ROOMS") {
+ proxyModel_->addFilter(BundleFilter::Filter::Rooms);
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ }
+ proxyModel_->setSourceModel(rootModel);
+
+
+ auto mainLayout = new QVBoxLayout();
+ setLayout(mainLayout);
+
+ auto headerLayout = new QHBoxLayout();
+ mainLayout->addLayout(headerLayout);
+ auto nameLabel = new QLabel(name, this);
+ nameLabel->setStyleSheet("color: white;");
+ headerLayout->addWidget(nameLabel);
+ headerLayout->addStretch();
+ if (!hideWhenEmpty) {
+ filterLabel_ = new QtClickableLabel(this);
+ filterLabel_->setText(tr("Online"));
+ filterLabel_->setStyleSheet("color: white;");
+ headerLayout->addWidget(filterLabel_);
+ connect(filterLabel_, SIGNAL(clicked()), this, SLOT(handleFilterClicked()));
+ }
+ listView_ = new QListView(this);
+ listView_->setModel(proxyModel_);
+ listView_->setFrameStyle(QFrame::NoFrame);
+ listView_->setItemDelegate(new QtChatOverviewDelegate(this));
+ connect(listView_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleItemClicked(const QModelIndex&)));
+ recalculateSize();
+ mainLayout->addWidget(listView_);
+ connect(proxyModel_, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
+ connect(proxyModel_, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
+ connect(proxyModel_, SIGNAL(modelReset()), this, SLOT(recalculateSize()));
+}
+
+QtChatOverviewBundle::~QtChatOverviewBundle() {}
+
+void QtChatOverviewBundle::recalculateSize() {
+ int totalHeight = 0;
+ for (int i = 0; i < proxyModel_->rowCount(); i++) {
+ totalHeight += listView_->sizeHintForRow(i);
+ }
+ listView_->setFixedHeight(totalHeight);
+ if (hideWhenEmpty_ && totalHeight == 0) {
+ hide();
+ }
+ else {
+ show();
+ }
+}
+
+void QtChatOverviewBundle::handleFilterClicked() {
+ if (proxyModel_->hasFilter(BundleFilter::Filter::Online)) {
+ proxyModel_->removeFilter(BundleFilter::Filter::Online);
+ filterLabel_->setText(tr("All"));
+ }
+ else {
+ proxyModel_->addFilter(BundleFilter::Filter::Online);
+ filterLabel_->setText(tr("Online"));
+ }
+}
+
+void QtChatOverviewBundle::handleItemClicked(const QModelIndex& index) {
+ clicked(JID(Q2PSTRING(index.data(ChattablesModel::JIDRole).toString())));
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverviewBundle.h b/Swift/QtUI/QtChatOverviewBundle.h
new file mode 100644
index 0000000..f469fea
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewBundle.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <set>
+
+#include <QSortFilterProxyModel>
+#include <QString>
+#include <QWidget>
+
+#include <Swiften/JID/JID.h>
+
+class QListView;
+
+namespace Swift {
+ class ChattablesModel;
+ class QtClickableLabel;
+
+ class BundleFilter : public QSortFilterProxyModel {
+ Q_OBJECT
+ public:
+ enum class Filter {Unread, People, Rooms, Online};
+ BundleFilter(QObject* parent);
+ void addFilter(Filter);
+ bool hasFilter(Filter);
+ void removeFilter(Filter);
+ protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const;
+ private:
+ std::set<Filter> filters_;
+ };
+
+ class QtChatOverviewBundle : public QWidget {
+ Q_OBJECT
+ public:
+ QtChatOverviewBundle(ChattablesModel*, QString name, bool hideWhenEmpty, QWidget* parent);
+ ~QtChatOverviewBundle() override;
+
+ signals:
+ void clicked(JID jid);
+
+ private slots:
+ void recalculateSize();
+ void handleFilterClicked();
+ void handleItemClicked(const QModelIndex&);
+ private:
+ ChattablesModel* rootModel_;
+ QListView* listView_;
+ BundleFilter* proxyModel_;
+ bool hideWhenEmpty_;
+ QtClickableLabel* filterLabel_ = nullptr;
+ };
+}
diff --git a/Swift/QtUI/QtChatOverviewDelegate.cpp b/Swift/QtUI/QtChatOverviewDelegate.cpp
new file mode 100644
index 0000000..919c23d
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewDelegate.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#include <Swift/QtUI/QtChatOverviewDelegate.h>
+
+#include <Swiften/Elements/StatusShow.h>
+
+#include <Swift/QtUI/ChattablesModel.h>
+#include <Swift/QtUI/Roster/DelegateCommons.h>
+
+namespace Swift {
+
+QtChatOverviewDelegate::QtChatOverviewDelegate(QObject* parent) : QItemDelegate(parent), nameFont(QApplication::font()) {
+
+}
+
+QtChatOverviewDelegate::~QtChatOverviewDelegate() {}
+
+QSize QtChatOverviewDelegate::sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const {
+ int heightByAvatar = DelegateCommons::avatarSize + DelegateCommons::verticalMargin * 2;
+ QFontMetrics nameMetrics(nameFont);
+ int sizeByText = 2 * DelegateCommons::verticalMargin + nameMetrics.height();
+ return QSize(150, sizeByText > heightByAvatar ? sizeByText : heightByAvatar);
+}
+
+void QtChatOverviewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
+ painter->save();
+ QRect fullRegion(option.rect);
+ const int statusCircleRadius = 3;
+ const int horizontalMargin = 4;
+
+ QColor bgColor(38, 81, 112);
+ QPen fontPen("white"); // FIXME
+
+ if (option.state & QStyle::State_Selected) {
+ //FIXME
+ }
+ painter->fillRect(fullRegion, bgColor);
+ painter->setPen(fontPen);
+
+ QFontMetrics nameMetrics(nameFont);
+ painter->setFont(nameFont);
+ QRect nameRegion(fullRegion.adjusted((horizontalMargin + statusCircleRadius) * 2, DelegateCommons::verticalMargin, 0, 0));
+ DelegateCommons::drawElidedText(painter, nameRegion, index.data(Qt::DisplayRole).toString());
+
+ const auto green = QColor(124, 243, 145);
+ const auto yellow = QColor(124, 243, 145); // FIXME: Yellow isn't green
+ const auto red = QColor(255,45,71);
+ const auto grey = QColor(159,159,159);
+ auto circleColour = grey;
+ auto status = static_cast<StatusShow::Type>(index.data(ChattablesModel::StatusRole).toInt());
+ switch (status) {
+ case StatusShow::Online: circleColour = green;break;
+ case StatusShow::FFC: circleColour = green;break;
+ case StatusShow::Away: circleColour = yellow;break;
+ case StatusShow::XA: circleColour = yellow;break;
+ case StatusShow::DND: circleColour = red;break;
+ case StatusShow::None: circleColour = grey;break;
+ }
+
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ int unreadCount = index.data(ChattablesModel::UnreadCountRole).toInt();
+ if (unreadCount > 0) {
+ int unreadCountSize = 16;
+ QRect unreadRect(fullRegion.right() - unreadCountSize - horizontalMargin, fullRegion.top() + (fullRegion.height() - unreadCountSize) / 2, unreadCountSize, unreadCountSize);
+ QPen pen(QColor("white"));
+ pen.setWidth(1);
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ painter->setPen(pen);
+ painter->drawEllipse(unreadRect);
+ painter->setBackgroundMode(Qt::TransparentMode);
+ painter->setPen(QColor("white"));
+ DelegateCommons::drawElidedText(painter, unreadRect, QString("%1").arg(unreadCount), Qt::AlignCenter);
+ }
+
+ painter->setPen(circleColour);
+ painter->setBrush(circleColour);
+ painter->drawEllipse(fullRegion.topLeft() + QPointF(horizontalMargin + 4, fullRegion.height() / 2), statusCircleRadius, statusCircleRadius);
+
+
+ painter->restore();
+}
+
+} // namespace Swift
diff --git a/Swift/QtUI/QtChatOverviewDelegate.h b/Swift/QtUI/QtChatOverviewDelegate.h
new file mode 100644
index 0000000..b00337d
--- /dev/null
+++ b/Swift/QtUI/QtChatOverviewDelegate.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QItemDelegate>
+#include <QFont>
+
+namespace Swift {
+ class QtChatOverviewDelegate : public QItemDelegate {
+ Q_OBJECT
+ public:
+ QtChatOverviewDelegate(QObject* parent);
+ ~QtChatOverviewDelegate() override;
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ private:
+ QFont nameFont;
+ };
+}
diff --git a/Swift/QtUI/QtChatTabs.cpp b/Swift/QtUI/QtChatTabs.cpp
index f4d0d46..7b81567 100644
--- a/Swift/QtUI/QtChatTabs.cpp
+++ b/Swift/QtUI/QtChatTabs.cpp
@@ -24,6 +24,7 @@
#include <Swiften/Base/Log.h>
#include <Swift/Controllers/ChatMessageSummarizer.h>
+#include <Swift/Controllers/SettingConstants.h>
#include <Swift/QtUI/QtSwiftUtil.h>
#include <Swift/QtUI/QtTabWidget.h>
@@ -39,7 +40,7 @@ QtChatTabs::QtChatTabs(bool singleWindow, SettingsProvider* settingsProvider, bo
#else
setAttribute(Qt::WA_ShowWithoutActivating);
#endif
- dynamicGrid_ = new QtDynamicGridLayout(this, trellisMode);
+ dynamicGrid_ = new QtDynamicGridLayout(settingsProvider->getSetting(SettingConstants::FUTURE), this, trellisMode);
connect(dynamicGrid_, SIGNAL(tabCloseRequested(int)), this, SLOT(handleTabCloseRequested(int)));
connect(dynamicGrid_, SIGNAL(onCurrentIndexChanged(int)), this, SLOT(handleCurrentTabIndexChanged(int)));
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 0c1dd97..cd38259 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -19,6 +19,7 @@
#include <QListWidgetItem>
#include <QMenuBar>
#include <QPushButton>
+#include <QScrollArea>
#include <QTabWidget>
#include <QToolBar>
@@ -35,6 +36,7 @@
#include <Swift/Controllers/UIEvents/RequestProfileEditorUIEvent.h>
#include <Swift/QtUI/QtAdHocCommandWithJIDWindow.h>
+#include <Swift/QtUI/QtChatOverview.h>
#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtSettingsProvider.h>
#include <Swift/QtUI/QtSwiftUtil.h>
@@ -52,7 +54,7 @@
namespace Swift {
-QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID) : QWidget(), MainWindow(false), loginMenus_(loginMenus) {
+QtMainWindow::QtMainWindow(Chattables& chattables, SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID) : QWidget(), MainWindow(false), chattables_(chattables), loginMenus_(loginMenus) {
uiEventStream_ = uiEventStream;
settings_ = settings;
setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
@@ -66,11 +68,18 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
connect(meView_, SIGNAL(onShowCertificateInfo()), this, SLOT(handleShowCertificateInfo()));
tabs_ = new QtTabWidget(this);
-#if QT_VERSION >= 0x040500
tabs_->setDocumentMode(true);
-#endif
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
+
+ if (settings->getSetting(SettingConstants::FUTURE)) {
+ chatOverview_ = new QtChatOverview(chattables, this);
+ auto overviewScroll = new QScrollArea(this);
+ overviewScroll->setWidgetResizable(true);
+ overviewScroll->setWidget(chatOverview_);
+ tabs_->addTab(overviewScroll, tr("&All"));
+ }
+
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_);
@@ -82,9 +91,7 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
contactTabLayout->addWidget(treeWidget_);
new QtFilterWidget(this, treeWidget_, uiEventStream_, contactTabLayout);
-
tabs_->addTab(contactsTabWidget_, tr("&Contacts"));
-
eventWindow_ = new QtEventWindow(uiEventStream_);
connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int)));
@@ -103,8 +110,11 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
tabs_->tabBar()->hide();
tabBarCombo_ = new QComboBox(this);
tabBarCombo_->setAccessibleName("Current View");
+ tabBarCombo_->addItem(tr("All"));
+#ifndef NOT_YET
tabBarCombo_->addItem(tr("Contacts"));
tabBarCombo_->addItem(tr("Chats"));
+#endif
tabBarCombo_->addItem(tr("Notices"));
tabBarCombo_->setCurrentIndex(tabs_->currentIndex());
mainLayout->addWidget(tabBarCombo_);
@@ -424,4 +434,3 @@ void QtMainWindow::setBlockingCommandAvailable(bool isAvailable) {
}
}
-
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index c46fdfc..0e7f290 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2016 Isode Limited.
+ * Copyright (c) 2010-2018 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -12,6 +12,7 @@
#include <QMenu>
#include <QWidget>
+#include <Swift/Controllers/Chat/Chattables.h>
#include <Swift/Controllers/UIInterfaces/MainWindow.h>
#include <Swift/QtUI/ChatList/QtChatListWindow.h>
@@ -19,44 +20,45 @@
#include <Swift/QtUI/QtLoginWindow.h>
#include <Swift/QtUI/QtRosterHeader.h>
+class QAction;
class QComboBox;
class QLineEdit;
-class QPushButton;
-class QToolBar;
-class QAction;
class QMenu;
+class QPushButton;
class QTabWidget;
+class QToolBar;
namespace Swift {
+ class QtChatOverview;
class QtRosterWidget;
- class TreeWidget;
- class UIEventStream;
class QtTabWidget;
- class SettingsProvider;
class QtUIPreferences;
+ class SettingsProvider;
class StatusCache;
+ class TreeWidget;
+ class UIEventStream;
class QtMainWindow : public QWidget, public MainWindow {
Q_OBJECT
public:
- QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID);
- virtual ~QtMainWindow();
+ QtMainWindow(Chattables&, SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID);
+ virtual ~QtMainWindow() override;
std::vector<QMenu*> getMenus() {return menus_;}
- void setMyNick(const std::string& name);
- void setMyJID(const JID& jid);
- void setMyAvatarPath(const std::string& path);
- void setMyStatusText(const std::string& status);
- void setMyStatusType(StatusShow::Type type);
- void setMyContactRosterItem(std::shared_ptr<ContactRosterItem> contact);
- void setConnecting();
- void setStreamEncryptionStatus(bool tlsInPlaceAndValid);
- void openCertificateDialog(const std::vector<Certificate::ref>& chain);
+ void setMyNick(const std::string& name) override;
+ void setMyJID(const JID& jid) override;
+ void setMyAvatarPath(const std::string& path) override;
+ void setMyStatusText(const std::string& status) override;
+ void setMyStatusType(StatusShow::Type type) override;
+ void setMyContactRosterItem(std::shared_ptr<ContactRosterItem> contact) override;
+ void setConnecting() override;
+ void setStreamEncryptionStatus(bool tlsInPlaceAndValid) override;
+ void openCertificateDialog(const std::vector<Certificate::ref>& chain) override;
static void openCertificateDialog(const std::vector<Certificate::ref>& chain, QWidget* parent);
QtEventWindow* getEventWindow();
QtChatListWindow* getChatListWindow();
- void setRosterModel(Roster* roster);
- void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands);
- void setBlockingCommandAvailable(bool isAvailable);
+ void setRosterModel(Roster* roster) override;
+ void setAvailableAdHocCommands(const std::vector<DiscoItems::Item>& commands) override;
+ void setBlockingCommandAvailable(bool isAvailable) override;
private slots:
void handleStatusChanged(StatusShow::Type showType, const QString &statusMessage);
void handleSettingChanged(const std::string& settingPath);
@@ -81,6 +83,7 @@ namespace Swift {
void handleSomethingSelectedChanged(bool itemSelected);
private:
+ Chattables& chattables_;
SettingsProvider* settings_;
QtLoginWindow::QtMenus loginMenus_;
std::vector<QMenu*> menus_;
@@ -98,6 +101,7 @@ namespace Swift {
QMenu* serverAdHocMenu_;
QtTabWidget* tabs_;
QComboBox* tabBarCombo_;
+ QtChatOverview* chatOverview_;
QWidget* contactsTabWidget_;
QWidget* eventsTabWidget_;
QtEventWindow* eventWindow_;
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index 583c477..7840b1b 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -86,8 +86,8 @@ FileTransferListWidget* QtUIFactory::createFileTransferListWidget() {
return widget;
}
-MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) {
- lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_);
+MainWindow* QtUIFactory::createMainWindow(Chattables& chattables, UIEventStream* eventStream) {
+ lastMainWindow = new QtMainWindow(chattables, settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_);
if (tabs) {
tabs->setViewMenu(lastMainWindow->getMenus()[0]);
}
diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h
index 9989101..9eeaa68 100644
--- a/Swift/QtUI/QtUIFactory.h
+++ b/Swift/QtUI/QtUIFactory.h
@@ -17,6 +17,7 @@ class QSplitter;
namespace Swift {
class AutoUpdater;
+ class Chattables;
class QtChatTabs;
class QtChatTabsBase;
class QtChatTheme;
@@ -39,7 +40,7 @@ namespace Swift {
~QtUIFactory();
virtual XMLConsoleWidget* createXMLConsoleWidget();
virtual HistoryWindow* createHistoryWindow(UIEventStream*);
- virtual MainWindow* createMainWindow(UIEventStream* eventStream);
+ virtual MainWindow* createMainWindow(Chattables& chattables, UIEventStream* eventStream);
virtual LoginWindow* createLoginWindow(UIEventStream* eventStream);
virtual EventWindow* createEventWindow();
virtual ChatListWindow* createChatListWindow(UIEventStream*);
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index 3755187..4ff2d81 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -110,131 +110,135 @@ myenv.WriteVal("DefaultTheme.qrc", myenv.Value(generateQRCTheme(myenv.Dir("#/Swi
sources = [
"main.cpp",
+ "ChatList/ChatListDelegate.cpp",
+ "ChatList/ChatListModel.cpp",
+ "ChatList/ChatListMUCItem.cpp",
+ "ChatList/ChatListRecentItem.cpp",
+ "ChatList/ChatListWhiteboardItem.cpp",
+ "ChatList/QtChatListWindow.cpp",
+ "ChattablesModel.cpp",
+ "ChatSnippet.cpp",
+ "EventViewer/EventDelegate.cpp",
+ "EventViewer/EventModel.cpp",
+ "EventViewer/QtEvent.cpp",
+ "EventViewer/QtEventWindow.cpp",
+ "EventViewer/TwoLineDelegate.cpp",
"FlowLayout.cpp",
+ "MessageSnippet.cpp",
+ "MUCSearch/MUCSearchDelegate.cpp",
+ "MUCSearch/MUCSearchEmptyItem.cpp",
+ "MUCSearch/MUCSearchModel.cpp",
+ "MUCSearch/MUCSearchRoomItem.cpp",
+ "MUCSearch/MUCSearchServiceItem.cpp",
+ "MUCSearch/QtLeafSortFilterProxyModel.cpp",
+ "MUCSearch/QtMUCSearchWindow.cpp",
+ "qrc_DefaultTheme.cc",
+ "qrc_Swift.cc",
"QtAboutWidget.cpp",
- "QtSpellCheckerWindow.cpp",
+ "QtAddBookmarkWindow.cpp",
+ "QtAdHocCommandWindow.cpp",
+ "QtAdHocCommandWithJIDWindow.cpp",
+ "QtAffiliationEditor.cpp",
"QtAvatarWidget.cpp",
- "QtUIFactory.cpp",
+ "QtBlockListEditorWindow.cpp",
+ "QtBookmarkDetailWindow.cpp",
+ "QtCachedImageScaler.cpp",
+ "QtChatOverview.cpp",
+ "QtChatOverviewBundle.cpp",
+ "QtChatOverviewDelegate.cpp",
+ "QtChatTabs.cpp",
+ "QtChatTabsBase.cpp",
+ "QtChatTabsShortcutOnlySubstitute.cpp",
+ "QtChatTheme.cpp",
+ "QtChatView.cpp",
+ "QtChatWindow.cpp",
"QtChatWindowFactory.cpp",
+ "QtChatWindowJSBridge.cpp",
+ "QtCheckBoxStyledItemDelegate.cpp",
"QtClickableLabel.cpp",
+ "QtClosableLineEdit.cpp",
+ "QtColorSelectionStyledItemDelegate.cpp",
+ "QtColorToolButton.cpp",
+ "QtConnectionSettingsWindow.cpp",
+ "QtContactEditWidget.cpp",
+ "QtContactEditWindow.cpp",
+ "QtEditBookmarkWindow.cpp",
+ "QtElidingLabel.cpp",
+ "QtEmojiCell.cpp",
+ "QtEmojisGrid.cpp",
+ "QtEmojisScroll.cpp",
+ "QtEmojisSelector.cpp",
+ "QtEmoticonsGrid.cpp",
+ "QtFileTransferListItemModel.cpp",
+ "QtFileTransferListWidget.cpp",
+ "QtFormResultItemModel.cpp",
+ "QtFormWidget.cpp",
+ "QtHighlightNotificationConfigDialog.cpp",
+ "QtHistoryWindow.cpp",
+ "QtJoinMUCWindow.cpp",
+ "QtLineEdit.cpp",
"QtLoginWindow.cpp",
"QtMainWindow.cpp",
- "QtProfileWindow.cpp",
- "QtBlockListEditorWindow.cpp",
+ "QtMUCConfigurationWindow.cpp",
"QtNameWidget.cpp",
+ "QtPlainChatView.cpp",
+ "QtProfileWindow.cpp",
+ "QtRecentEmojisGrid.cpp",
+ "QtResourceHelper.cpp",
+ "QtRosterHeader.cpp",
+ "QtScaledAvatarCache.cpp",
"QtSettingsProvider.cpp",
+ "QtSingleWindow.cpp",
+ "QtSoundPlayer.cpp",
+ "QtSoundSelectionStyledItemDelegate.cpp",
+ "QtSpellCheckerWindow.cpp",
+ "QtSpellCheckHighlighter.cpp",
"QtStatusWidget.cpp",
- "QtScaledAvatarCache.cpp",
+ "QtSubscriptionRequestWindow.cpp",
"QtSwift.cpp",
- "QtURIHandler.cpp",
- "QtChatWindow.cpp",
- "QtChatView.cpp",
- "QtWebKitChatView.cpp",
- "QtPlainChatView.cpp",
- "QtChatTheme.cpp",
- "QtChatTabs.cpp",
- "QtChatTabsBase.cpp",
- "QtChatTabsShortcutOnlySubstitute.cpp",
- "QtSoundPlayer.cpp",
"QtSystemTray.cpp",
- "QtCachedImageScaler.cpp",
"QtTabbable.cpp",
"QtTabWidget.cpp",
"QtTextEdit.cpp",
- "QtXMLConsoleWidget.cpp",
- "QtHistoryWindow.cpp",
- "QtFileTransferListWidget.cpp",
- "QtFileTransferListItemModel.cpp",
- "QtAdHocCommandWindow.cpp",
- "QtAdHocCommandWithJIDWindow.cpp",
+ "QtUIFactory.cpp",
+ "QtUISettingConstants.cpp",
+ "QtUpdateFeedSelectionDialog.cpp",
+ "QtURIHandler.cpp",
+ "QtURLValidator.cpp",
"QtUtilities.cpp",
- "QtBookmarkDetailWindow.cpp",
- "QtAddBookmarkWindow.cpp",
- "QtEditBookmarkWindow.cpp",
- "QtEmojisGrid.cpp",
- "QtEmojiCell.cpp",
- "QtEmojisScroll.cpp",
- "QtEmojisSelector.cpp",
- "QtRecentEmojisGrid.cpp",
- "QtEmoticonsGrid.cpp",
- "QtContactEditWindow.cpp",
- "QtContactEditWidget.cpp",
- "QtSingleWindow.cpp",
- "QtColorToolButton.cpp",
- "QtClosableLineEdit.cpp",
- "QtHighlightNotificationConfigDialog.cpp",
- "ChatSnippet.cpp",
- "MessageSnippet.cpp",
- "SystemMessageSnippet.cpp",
- "QtElidingLabel.cpp",
- "QtFormWidget.cpp",
- "QtFormResultItemModel.cpp",
- "QtLineEdit.cpp",
- "QtJoinMUCWindow.cpp",
- "QtConnectionSettingsWindow.cpp",
- "Roster/RosterModel.cpp",
- "Roster/QtTreeWidget.cpp",
- "Roster/RosterDelegate.cpp",
- "Roster/GroupItemDelegate.cpp",
+ "QtWebKitChatView.cpp",
+ "QtWebView.cpp",
+ "QtXMLConsoleWidget.cpp",
"Roster/DelegateCommons.cpp",
+ "Roster/GroupItemDelegate.cpp",
"Roster/QtFilterWidget.cpp",
- "Roster/QtRosterWidget.cpp",
"Roster/QtOccupantListWidget.cpp",
+ "Roster/QtRosterWidget.cpp",
+ "Roster/QtTreeWidget.cpp",
+ "Roster/RosterDelegate.cpp",
+ "Roster/RosterModel.cpp",
"Roster/RosterTooltip.cpp",
- "EventViewer/EventModel.cpp",
- "EventViewer/EventDelegate.cpp",
- "EventViewer/TwoLineDelegate.cpp",
- "EventViewer/QtEventWindow.cpp",
- "EventViewer/QtEvent.cpp",
- "ChatList/QtChatListWindow.cpp",
- "ChatList/ChatListModel.cpp",
- "ChatList/ChatListDelegate.cpp",
- "ChatList/ChatListMUCItem.cpp",
- "ChatList/ChatListRecentItem.cpp",
- "ChatList/ChatListWhiteboardItem.cpp",
- "MUCSearch/MUCSearchDelegate.cpp",
- "MUCSearch/MUCSearchEmptyItem.cpp",
- "MUCSearch/MUCSearchModel.cpp",
- "MUCSearch/MUCSearchRoomItem.cpp",
- "MUCSearch/MUCSearchServiceItem.cpp",
- "MUCSearch/QtLeafSortFilterProxyModel.cpp",
- "MUCSearch/QtMUCSearchWindow.cpp",
+ "SystemMessageSnippet.cpp",
+ "Trellis/QtDNDTabBar.cpp",
+ "Trellis/QtDynamicGridLayout.cpp",
+ "Trellis/QtGridSelectionDialog.cpp",
"UserSearch/ContactListDelegate.cpp",
"UserSearch/ContactListModel.cpp",
"UserSearch/QtContactListWidget.cpp",
"UserSearch/QtSuggestingJIDInput.cpp",
- "UserSearch/QtUserSearchFirstPage.cpp",
- "UserSearch/QtUserSearchFirstMultiJIDPage.cpp",
+ "UserSearch/QtUserSearchDetailsPage.cpp",
"UserSearch/QtUserSearchFieldsPage.cpp",
+ "UserSearch/QtUserSearchFirstMultiJIDPage.cpp",
+ "UserSearch/QtUserSearchFirstPage.cpp",
"UserSearch/QtUserSearchResultsPage.cpp",
- "UserSearch/QtUserSearchDetailsPage.cpp",
"UserSearch/QtUserSearchWindow.cpp",
- "UserSearch/UserSearchModel.cpp",
"UserSearch/UserSearchDelegate.cpp",
+ "UserSearch/UserSearchModel.cpp",
+ "Whiteboard/ColorWidget.cpp",
"Whiteboard/FreehandLineItem.cpp",
"Whiteboard/GView.cpp",
- "Whiteboard/TextDialog.cpp",
"Whiteboard/QtWhiteboardWindow.cpp",
- "Whiteboard/ColorWidget.cpp",
- "QtSubscriptionRequestWindow.cpp",
- "QtRosterHeader.cpp",
- "QtWebView.cpp",
- "qrc_DefaultTheme.cc",
- "qrc_Swift.cc",
- "QtChatWindowJSBridge.cpp",
- "QtMUCConfigurationWindow.cpp",
- "QtAffiliationEditor.cpp",
- "QtUISettingConstants.cpp",
- "QtURLValidator.cpp",
- "QtResourceHelper.cpp",
- "QtSpellCheckHighlighter.cpp",
- "QtUpdateFeedSelectionDialog.cpp",
- "Trellis/QtDynamicGridLayout.cpp",
- "Trellis/QtDNDTabBar.cpp",
- "Trellis/QtGridSelectionDialog.cpp",
- "QtCheckBoxStyledItemDelegate.cpp",
- "QtColorSelectionStyledItemDelegate.cpp",
- "QtSoundSelectionStyledItemDelegate.cpp"
+ "Whiteboard/TextDialog.cpp"
]
if env["PLATFORM"] == "win32" :
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
index 2509b3f..2402529 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.cpp
@@ -23,7 +23,7 @@
namespace Swift {
-QtDynamicGridLayout::QtDynamicGridLayout(QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(nullptr) {
+QtDynamicGridLayout::QtDynamicGridLayout(bool future, QWidget* parent, bool enableDND) : QWidget(parent), dndEnabled_(enableDND), movingTab_(nullptr), future_(future) {
gridLayout_ = new QGridLayout(this);
setContentsMargins(0,0,0,0);
setDimensions(QSize(1,1));
@@ -49,6 +49,9 @@ int QtDynamicGridLayout::addTab(QtTabbable* tab, const QString& title) {
tabWidget->addTab(tab, title);
}
tab->setEmphasiseFocus(getDimension().width() > 1 || getDimension().height() > 1);
+ if (future_) {
+ showHideFirstTabs(); // FIXME: Putting it here as a workaround until I work out why it doesn't work initially
+ }
return tabWidget ? indexOf(tab) : -1;
}
@@ -328,6 +331,24 @@ void QtDynamicGridLayout::setDimensions(const QSize& dim) {
setCurrentWidget(restoredWidget);
updateEmphasiseFocusOnTabs();
+
+ if (future_) {
+ showHideFirstTabs();
+ }
+}
+
+void QtDynamicGridLayout::showHideFirstTabs() {
+ int tmp;
+ auto firstTabs = indexToTabWidget(0, tmp);
+
+ if (firstTabs) {
+ if (gridLayout_->columnCount() == 1 && gridLayout_->rowCount() == 1) {
+ firstTabs->tabBar()->hide();
+ }
+ else {
+ firstTabs->tabBar()->show();
+ }
+ }
}
void QtDynamicGridLayout::updateEmphasiseFocusOnTabs() {
diff --git a/Swift/QtUI/Trellis/QtDynamicGridLayout.h b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
index 682ae41..f3a2e96 100644
--- a/Swift/QtUI/Trellis/QtDynamicGridLayout.h
+++ b/Swift/QtUI/Trellis/QtDynamicGridLayout.h
@@ -20,7 +20,7 @@ namespace Swift {
class QtDynamicGridLayout : public QWidget {
Q_OBJECT
public:
- explicit QtDynamicGridLayout(QWidget* parent = nullptr, bool enableDND = false);
+ explicit QtDynamicGridLayout(bool future, QWidget* parent = nullptr, bool enableDND = false);
virtual ~QtDynamicGridLayout();
QSize getDimension() const;
@@ -71,6 +71,7 @@ namespace Swift {
void moveTab(QtTabWidget* tabWidget, int oldIndex, int newIndex);
QtTabWidget* createDNDTabWidget(QWidget* parent);
void updateEmphasiseFocusOnTabs();
+ void showHideFirstTabs();
private:
QGridLayout *gridLayout_;
@@ -78,5 +79,6 @@ namespace Swift {
QHash<QString, QPoint> tabPositions_;
QtTabbable* movingTab_;
bool resizing_ = false;
+ bool future_ = false;
};
}