From 14fd8e4363241e04b20da85dfc61e5f315e9b28d Mon Sep 17 00:00:00 2001 From: Richard Maudsley Date: Fri, 27 Jun 2014 17:06:49 +0100 Subject: Show own tooltip when hovering over roster header. Test-Information: Made combinations of presence/vcard/avatar changes and verified that the information in the tooltip was synchronized. Connect two clients and verify that the tooltip presence text reflects the local client presence only. Change-Id: I92af0f58f7045f3a15f2fae2f9cbc6e24a066923 diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index df137f4..f16f8ad 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -339,7 +339,7 @@ void MainController::handleConnected() { showProfileController_ = new ShowProfileController(client_->getVCardManager(), uiFactory_, uiEventStream_); ftOverview_ = new FileTransferOverview(client_->getFileTransferManager()); fileTransferListController_->setFileTransferOverview(ftOverview_); - rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_, client_->getClientBlockListManager(), client_->getVCardManager()); + rosterController_ = new RosterController(boundJID_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_, client_->getClientBlockListManager(), client_->getVCardManager()); 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)); @@ -411,6 +411,7 @@ void MainController::handleConnected() { client_->getVCardManager()->requestOwnVCard(); + rosterController_->setJID(boundJID_); rosterController_->setEnabled(true); rosterController_->getWindow()->setStreamEncryptionStatus(client_->isStreamEncrypted()); profileController_->setAvailable(true); diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index d2d024c..6bb5119 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -58,10 +58,9 @@ 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, FileTransferOverview* fileTransferOverview, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager) - : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), clientBlockListManager_(clientBlockListManager) { + : 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), ftOverview_(fileTransferOverview), clientBlockListManager_(clientBlockListManager) { assert(fileTransferOverview); iqRouter_ = iqRouter; - presenceOracle_ = presenceOracle; subscriptionManager_ = subscriptionManager; eventController_ = eventController; settings_ = settings; @@ -78,9 +77,11 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2)); presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1)); uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); - avatarManager_ = avatarManager; + + vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); - mainWindow_->setMyAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_))); + presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1)); + mainWindow_->setMyAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); mainWindow_->setMyJID(jid); @@ -91,6 +92,11 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata settings_->onSettingChanged.connect(boost::bind(&RosterController::handleSettingChanged, this, _1)); handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); + + ownContact_ = boost::make_shared(myJID_.toBare(), myJID_.toBare(), nickManager_->getOwnNick(), (GroupRosterItem*)0); + ownContact_->setVCard(vcardManager_->getVCard(myJID_.toBare())); + ownContact_->setAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); + mainWindow_->setMyContactRosterItem(ownContact_); } @@ -336,12 +342,26 @@ void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEven subscriptionManager_->cancelSubscription(event->getJID()); } +void RosterController::handleOwnVCardChanged(VCard::ref vcard) { + ownContact_->setVCard(vcard); + mainWindow_->setMyContactRosterItem(ownContact_); +} + void RosterController::handleAvatarChanged(const JID& jid) { boost::filesystem::path path = avatarManager_->getAvatarPath(jid); roster_->applyOnItems(SetAvatar(jid, path)); - if (jid.equals(myJID_, JID::WithoutResource)) { + if (jid.equals(myJID_, JID::WithResource)) { mainWindow_->setMyAvatarPath(pathToString(path)); } + ownContact_->setAvatarPath(pathToString(path)); + mainWindow_->setMyContactRosterItem(ownContact_); +} + +void RosterController::handlePresenceChanged(Presence::ref presence) { + if (presence->getFrom().equals(myJID_, JID::WithResource)) { + ownContact_->applyPresence(std::string(), presence); + mainWindow_->setMyContactRosterItem(ownContact_); + } } boost::optional RosterController::getItem(const JID& jid) const { diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h index 5b26fc7..d0c7024 100644 --- a/Swift/Controllers/Roster/RosterController.h +++ b/Swift/Controllers/Roster/RosterController.h @@ -50,10 +50,13 @@ namespace Swift { 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, FileTransferOverview* fileTransferOverview, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager); ~RosterController(); void showRosterWindow(); + void setJID(const JID& jid) { myJID_ = jid; } MainWindow* getWindow() {return mainWindow_;} boost::signal onChangeStatusRequest; boost::signal onSignOutRequest; + void handleOwnVCardChanged(VCard::ref vcard); void handleAvatarChanged(const JID& jid); + void handlePresenceChanged(Presence::ref presence); void setEnabled(bool enabled); boost::optional getItem(const JID&) const; @@ -93,6 +96,7 @@ namespace Swift { MainWindow* mainWindow_; Roster* roster_; OfflineRosterFilter* offlineFilter_; + VCardManager* vcardManager_; AvatarManager* avatarManager_; NickManager* nickManager_; NickResolver* nickResolver_; @@ -107,6 +111,7 @@ namespace Swift { FileTransferOverview* ftOverview_; ClientBlockListManager* clientBlockListManager_; RosterVCardProvider* rosterVCardProvider_; + boost::shared_ptr ownContact_; boost::bsignals::scoped_connection blockingOnStateChangedConnection_; boost::bsignals::scoped_connection blockingOnItemAddedConnection_; diff --git a/Swift/Controllers/UIInterfaces/MainWindow.h b/Swift/Controllers/UIInterfaces/MainWindow.h index c85106f..82750bf 100644 --- a/Swift/Controllers/UIInterfaces/MainWindow.h +++ b/Swift/Controllers/UIInterfaces/MainWindow.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace Swift { class Roster; @@ -33,6 +34,7 @@ namespace Swift { virtual void setMyAvatarPath(const std::string& path) = 0; virtual void setMyStatusText(const std::string& status) = 0; virtual void setMyStatusType(StatusShow::Type type) = 0; + virtual void setMyContactRosterItem(boost::shared_ptr contact) = 0; /** Must be able to cope with NULL to clear the roster */ virtual void setRosterModel(Roster* roster) = 0; virtual void setConnecting() = 0; diff --git a/Swift/Controllers/UnitTest/MockMainWindow.h b/Swift/Controllers/UnitTest/MockMainWindow.h index ff3fa4d..b56f352 100644 --- a/Swift/Controllers/UnitTest/MockMainWindow.h +++ b/Swift/Controllers/UnitTest/MockMainWindow.h @@ -20,6 +20,7 @@ namespace Swift { virtual void setMyAvatarPath(const std::string& /*path*/) {} virtual void setMyStatusText(const std::string& /*status*/) {} virtual void setMyStatusType(StatusShow::Type /*type*/) {} + virtual void setMyContactRosterItem(boost::shared_ptr /*contact*/) {} virtual void setAvailableAdHocCommands(const std::vector& /*commands*/) {} virtual void setConnecting() {} virtual void setStreamEncryptionStatus(bool /*tlsInPlaceAndValid*/) {} diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 1acc519..31a8234 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -340,6 +340,10 @@ void QtMainWindow::setMyStatusType(StatusShow::Type type) { meView_->setStatusType(type); } +void QtMainWindow::setMyContactRosterItem(boost::shared_ptr contact) { + meView_->setContactRosterItem(contact); +} + void QtMainWindow::setConnecting() { meView_->setConnecting(); } diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index c489a9e..f1f6900 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -47,6 +47,7 @@ namespace Swift { void setMyAvatarPath(const std::string& path); void setMyStatusText(const std::string& status); void setMyStatusType(StatusShow::Type type); + void setMyContactRosterItem(boost::shared_ptr contact); void setConnecting(); void setStreamEncryptionStatus(bool tlsInPlaceAndValid); void openCertificateDialog(const std::vector& chain); diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp index 2c8f244..69a0ef6 100644 --- a/Swift/QtUI/QtRosterHeader.cpp +++ b/Swift/QtUI/QtRosterHeader.cpp @@ -6,20 +6,23 @@ #include "QtRosterHeader.h" -#include -#include +#include +#include #include +#include +#include #include -#include -#include #include #include -#include +#include +#include +#include #include "QtStatusWidget.h" #include #include #include +#include #include "QtScaledAvatarCache.h" namespace Swift { @@ -89,6 +92,17 @@ void QtRosterHeader::setStreamEncryptionStatus(bool tlsInPlace) { securityInfoButton_->setVisible(tlsInPlace); } +bool QtRosterHeader::event(QEvent* event) { + if (event->type() == QEvent::ToolTip) { + QHelpEvent *helpEvent = static_cast(event); + QtScaledAvatarCache scaledAvatarCache(avatarSize_); + QString text = RosterTooltip::buildDetailedTooltip(contact_.get(), &scaledAvatarCache); + QToolTip::showText(helpEvent->globalPos(), text); + return true; + } + return QWidget::event(event); +} + void QtRosterHeader::setAvatar(const QString& path) { QString scaledAvatarPath = QtScaledAvatarCache(avatarSize_).getScaledAvatarPath(path); QPixmap avatar; @@ -105,6 +119,10 @@ void QtRosterHeader::setNick(const QString& nick) { nameWidget_->setNick(nick); } +void QtRosterHeader::setContactRosterItem(boost::shared_ptr contact) { + contact_ = contact; +} + void QtRosterHeader::setJID(const QString& jid) { nameWidget_->setJID(jid); } diff --git a/Swift/QtUI/QtRosterHeader.h b/Swift/QtUI/QtRosterHeader.h index ad19178..eafbc02 100644 --- a/Swift/QtUI/QtRosterHeader.h +++ b/Swift/QtUI/QtRosterHeader.h @@ -13,7 +13,9 @@ #include #include -#include "Swiften/Elements/StatusShow.h" +#include +#include +#include #include "QtTextEdit.h" @@ -34,11 +36,14 @@ namespace Swift { void setJID(const QString& jid); void setNick(const QString& nick); + void setContactRosterItem(boost::shared_ptr contact); void setStatusText(const QString& statusMessage); void setStatusType(StatusShow::Type type); void setConnecting(); void setStreamEncryptionStatus(bool tlsInPlace); + private: + bool event(QEvent* event); signals: void onChangeStatusRequest(StatusShow::Type showType, const QString &statusMessage); void onEditProfileRequest(); @@ -54,5 +59,6 @@ namespace Swift { QtStatusWidget* statusWidget_; QToolButton* securityInfoButton_; static const int avatarSize_; + boost::shared_ptr contact_; }; } -- cgit v0.10.2-6-g49f6