diff options
author | Tobias Markmann <tm@ayena.de> | 2013-11-10 15:56:22 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2013-11-18 14:58:53 (GMT) |
commit | 3f8ff1c0e154dcb9959906e6865053dbe975892f (patch) | |
tree | 494f84e2d36130cc14806a9c6828e4ed433fc8c7 /Swift/QtUI | |
parent | d674359cdefae70f3cc1fa6439c96c82b508b5e9 (diff) | |
download | swift-3f8ff1c0e154dcb9959906e6865053dbe975892f.zip swift-3f8ff1c0e154dcb9959906e6865053dbe975892f.tar.bz2 |
Improve tooltips to include avatars, last seen and vcard information.
Change-Id: I3768d9891ba903c5e2ce8217de0b4413ce40bb9a
License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.
Diffstat (limited to 'Swift/QtUI')
-rw-r--r-- | Swift/QtUI/ChatList/ChatListRecentItem.cpp | 16 | ||||
-rw-r--r-- | Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp | 16 | ||||
-rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 17 | ||||
-rw-r--r-- | Swift/QtUI/QtMainWindow.h | 14 | ||||
-rw-r--r-- | Swift/QtUI/QtResourceHelper.cpp | 25 | ||||
-rw-r--r-- | Swift/QtUI/QtResourceHelper.h | 17 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.cpp | 43 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.h | 11 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterModel.cpp | 45 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterModel.h | 7 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterTooltip.cpp | 158 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterTooltip.h | 27 | ||||
-rw-r--r-- | Swift/QtUI/SConscript | 20 | ||||
-rw-r--r-- | Swift/QtUI/UserSearch/ContactListModel.cpp | 17 |
14 files changed, 338 insertions, 95 deletions
diff --git a/Swift/QtUI/ChatList/ChatListRecentItem.cpp b/Swift/QtUI/ChatList/ChatListRecentItem.cpp index e9ecec8..5497fdd 100644 --- a/Swift/QtUI/ChatList/ChatListRecentItem.cpp +++ b/Swift/QtUI/ChatList/ChatListRecentItem.cpp @@ -4,10 +4,11 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ -#include <Swift/QtUI/ChatList/ChatListRecentItem.h> +#include <Swiften/Base/Path.h> +#include <Swift/QtUI/ChatList/ChatListRecentItem.h> +#include <Swift/QtUI/QtResourceHelper.h> #include <Swift/QtUI/QtSwiftUtil.h> -#include <Swiften/Base/Path.h> namespace Swift { ChatListRecentItem::ChatListRecentItem(const ChatListWindow::Chat& chat, ChatListGroupItem* parent) : ChatListItem(parent), chat_(chat) { @@ -33,16 +34,7 @@ QVariant ChatListRecentItem::data(int role) const { } QIcon ChatListRecentItem::getPresenceIcon() const { - QString iconString; - switch (chat_.statusType) { - case StatusShow::Online: iconString = "online";break; - case StatusShow::Away: iconString = "away";break; - case StatusShow::XA: iconString = "away";break; - case StatusShow::FFC: iconString = "online";break; - case StatusShow::DND: iconString = "dnd";break; - case StatusShow::None: iconString = "offline";break; - } - return QIcon(":/icons/" + iconString + ".png"); + return QIcon(statusShowTypeToIconPath(chat_.statusType)); } } diff --git a/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp b/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp index 6791aa5..05bf6c2 100644 --- a/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp +++ b/Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp @@ -10,10 +10,11 @@ * See the COPYING file for more information. */ -#include <Swift/QtUI/ChatList/ChatListWhiteboardItem.h> +#include <Swiften/Base/Path.h> +#include <Swift/QtUI/ChatList/ChatListWhiteboardItem.h> #include <Swift/QtUI/QtSwiftUtil.h> -#include <Swiften/Base/Path.h> +#include <Swift/QtUI/QtResourceHelper.h> namespace Swift { ChatListWhiteboardItem::ChatListWhiteboardItem(const ChatListWindow::Chat& chat, ChatListGroupItem* parent) : ChatListItem(parent), chat_(chat) { @@ -39,16 +40,7 @@ namespace Swift { } QIcon ChatListWhiteboardItem::getPresenceIcon() const { - QString iconString; - switch (chat_.statusType) { - case StatusShow::Online: iconString = "online";break; - case StatusShow::Away: iconString = "away";break; - case StatusShow::XA: iconString = "away";break; - case StatusShow::FFC: iconString = "online";break; - case StatusShow::DND: iconString = "dnd";break; - case StatusShow::None: iconString = "offline";break; - } - return QIcon(":/icons/" + iconString + ".png"); + return QIcon(statusShowTypeToIconPath(chat_.statusType)); } } diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 6f87a88..af38d68 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ -#include "QtMainWindow.h" +#include <Swift/QtUI/QtMainWindow.h> #include <boost/optional.hpp> #include <boost/bind.hpp> @@ -21,11 +21,8 @@ #include <QAction> #include <QTabWidget> -#include <Swift/QtUI/QtSwiftUtil.h> -#include <Swift/QtUI/QtTabWidget.h> -#include <Swift/QtUI/QtSettingsProvider.h> -#include <Swift/QtUI/QtLoginWindow.h> -#include <Roster/QtRosterWidget.h> +#include <Swiften/Base/Platform.h> + #include <Swift/Controllers/UIEvents/RequestJoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestHistoryUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> @@ -34,10 +31,14 @@ #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h> #include <Swift/Controllers/UIEvents/RequestBlockListDialogUIEvent.h> -#include <Swift/QtUI/QtUISettingConstants.h> #include <Swift/Controllers/SettingConstants.h> -#include <Swiften/Base/Platform.h> +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swift/QtUI/QtTabWidget.h> +#include <Swift/QtUI/QtSettingsProvider.h> +#include <Swift/QtUI/QtLoginWindow.h> +#include <Swift/QtUI/Roster/QtRosterWidget.h> +#include <Swift/QtUI/QtUISettingConstants.h> #if defined(SWIFTEN_PLATFORM_MACOSX) #include <Swift/QtUI/CocoaUIHelpers.h> #elif defined(SWIFTEN_PLATFORM_WINDOWS) diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index 3e6e1d3..627cc17 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -6,16 +6,18 @@ #pragma once +#include <vector> + #include <QWidget> #include <QMenu> #include <QList> -#include "Swift/Controllers/UIInterfaces/MainWindow.h" -#include "Swift/QtUI/QtRosterHeader.h" -#include "Swift/QtUI/EventViewer/QtEventWindow.h" -#include "Swift/QtUI/ChatList/QtChatListWindow.h" -#include "Swift/QtUI/QtLoginWindow.h" -#include <vector> +#include <Swift/Controllers/UIInterfaces/MainWindow.h> + +#include <Swift/QtUI/QtRosterHeader.h> +#include <Swift/QtUI/EventViewer/QtEventWindow.h> +#include <Swift/QtUI/ChatList/QtChatListWindow.h> +#include <Swift/QtUI/QtLoginWindow.h> class QComboBox; class QLineEdit; diff --git a/Swift/QtUI/QtResourceHelper.cpp b/Swift/QtUI/QtResourceHelper.cpp new file mode 100644 index 0000000..f76c438 --- /dev/null +++ b/Swift/QtUI/QtResourceHelper.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swift/QtUI/QtResourceHelper.h> + +namespace Swift { + +QString statusShowTypeToIconPath(StatusShow::Type type) { + QString iconString; + switch (type) { + case StatusShow::Online: iconString = "online";break; + case StatusShow::Away: iconString = "away";break; + case StatusShow::XA: iconString = "away";break; + case StatusShow::FFC: iconString = "online";break; + case StatusShow::DND: iconString = "dnd";break; + case StatusShow::None: iconString = "offline";break; + } + return QString(":/icons/%1.png").arg(iconString); +} + +} + diff --git a/Swift/QtUI/QtResourceHelper.h b/Swift/QtUI/QtResourceHelper.h new file mode 100644 index 0000000..034a941 --- /dev/null +++ b/Swift/QtUI/QtResourceHelper.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QString> + +#include <Swiften/Elements/StatusShow.h> + +namespace Swift { + +QString statusShowTypeToIconPath(StatusShow::Type type); + +} diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp index 99f1f34..f9d3dd0 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.cpp +++ b/Swift/QtUI/Roster/QtTreeWidget.cpp @@ -4,27 +4,34 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ -#include "Roster/QtTreeWidget.h" +#include <Swift/QtUI/Roster/QtTreeWidget.h> #include <boost/smart_ptr/make_shared.hpp> #include <boost/bind.hpp> #include <QUrl> #include <QMimeData> +#include <QObject> +#include <QLabel> +#include <QTimer> +#include <QToolTip> #include <Swiften/Base/Platform.h> + #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIEvents/RequestChatUIEvent.h> #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> -#include <QtSwiftUtil.h> #include <Swift/Controllers/Settings/SettingsProvider.h> + #include <Swift/QtUI/QtUISettingConstants.h> +#include <QtSwiftUtil.h> + namespace Swift { -QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent) { +QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent), tooltipShown_(false) { eventStream_ = eventStream; settings_ = settings; model_ = new RosterModel(this); @@ -66,12 +73,25 @@ void QtTreeWidget::handleSettingChanged(const std::string& setting) { } } +void QtTreeWidget::handleRefreshTooltip() { + if (tooltipShown_) { + QPoint position = QCursor::pos(); + QModelIndex index = indexAt(mapFromGlobal(position)); + QToolTip::showText(position, model_->data(index, Qt::ToolTipRole).toString()); + } +} + void QtTreeWidget::setRosterModel(Roster* roster) { roster_ = roster; model_->setRoster(roster); expandAll(); } +void QtTreeWidget::refreshTooltip() { + // Qt needs some time to emit the events we need to detect tooltip's visibility correctly; 20 ms should be enough + QTimer::singleShot(20, this, SLOT(handleRefreshTooltip())); +} + QtTreeWidgetItem* QtTreeWidget::getRoot() { return treeRoot_; } @@ -161,6 +181,23 @@ void QtTreeWidget::dragMoveEvent(QDragMoveEvent* event) { QTreeView::dragMoveEvent(event); } +bool QtTreeWidget::event(QEvent* event) { + QChildEvent* childEvent = NULL; + if ((childEvent = dynamic_cast<QChildEvent*>(event))) { + if (childEvent->polished()) { + if (dynamic_cast<QLabel*>(childEvent->child())) { + tooltipShown_ = true; + } + } + else if (childEvent->removed()) { + if (childEvent->child()->objectName() == "qtooltip_label") { + tooltipShown_ = false; + } + } + } + return QAbstractItemView::event(event); +} + void QtTreeWidget::handleExpanded(const QModelIndex& index) { GroupRosterItem* item = dynamic_cast<GroupRosterItem*>(static_cast<RosterItem*>(index.internalPointer())); if (item) { diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h index 7c10a6a..8884a40 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.h +++ b/Swift/QtUI/Roster/QtTreeWidget.h @@ -11,8 +11,9 @@ #include <QDragEnterEvent> #include <QDropEvent> #include <QDragMoveEvent> -#include "Swift/QtUI/Roster/RosterModel.h" -#include "Swift/QtUI/Roster/RosterDelegate.h" + +#include <Swift/QtUI/Roster/RosterModel.h> +#include <Swift/QtUI/Roster/RosterDelegate.h> namespace Swift { class UIEventStream; @@ -27,6 +28,7 @@ class QtTreeWidget : public QTreeView{ QtTreeWidgetItem* getRoot(); void setRosterModel(Roster* roster); Roster* getRoster() {return roster_;} + void refreshTooltip(); boost::signal<void (RosterItem*)> onSomethingSelectedChanged; private slots: @@ -36,15 +38,19 @@ class QtTreeWidget : public QTreeView{ void handleCollapsed(const QModelIndex&); void handleClicked(const QModelIndex&); void handleSettingChanged(const std::string& setting); + void handleRefreshTooltip(); + protected: void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); void dragMoveEvent(QDragMoveEvent* event); + bool event(QEvent* event); protected: QModelIndexList getSelectedIndexes() const; private: void drawBranches(QPainter*, const QRect&, const QModelIndex&) const; + protected slots: virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous); protected: @@ -56,6 +62,7 @@ class QtTreeWidget : public QTreeView{ RosterDelegate* delegate_; QtTreeWidgetItem* treeRoot_; SettingsProvider* settings_; + bool tooltipShown_; }; } diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp index 3791ffa..16c6d7e 100644 --- a/Swift/QtUI/Roster/RosterModel.cpp +++ b/Swift/QtUI/Roster/RosterModel.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ -#include "RosterModel.h" +#include <Swift/QtUI/Roster/RosterModel.h> #include <boost/bind.hpp> @@ -13,22 +13,26 @@ #include <QMimeData> #include <qdebug.h> -#include "Swiften/Elements/StatusShow.h" -#include "Swift/Controllers/Roster/ContactRosterItem.h" -#include "Swift/Controllers/Roster/GroupRosterItem.h" -#include <Swift/Controllers/StatusUtil.h> +#include <Swiften/Elements/StatusShow.h> #include <Swiften/Base/Path.h> -#include "QtSwiftUtil.h" -#include "Swift/QtUI/Roster/QtTreeWidget.h" +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/Roster/GroupRosterItem.h> + +#include <Swift/QtUI/Roster/QtTreeWidget.h> +#include <Swift/QtUI/Roster/RosterTooltip.h> +#include <Swift/QtUI/QtResourceHelper.h> +#include <Swift/QtUI/QtSwiftUtil.h> namespace Swift { -RosterModel::RosterModel(QtTreeWidget* view) : view_(view) { - roster_ = NULL; +RosterModel::RosterModel(QtTreeWidget* view) : roster_(NULL), view_(view) { + const int tooltipAvatarSize = 96; // maximal suggested size according to XEP-0153 + cachedImageScaler_ = new QtScaledAvatarCache(tooltipAvatarSize); } RosterModel::~RosterModel() { + delete cachedImageScaler_; } void RosterModel::setRoster(Roster* roster) { @@ -63,6 +67,7 @@ void RosterModel::handleDataChanged(RosterItem* item) { QModelIndex modelIndex = index(item); if (modelIndex.isValid()) { emit dataChanged(modelIndex, modelIndex); + view_->refreshTooltip(); } } @@ -141,16 +146,7 @@ QString RosterModel::getToolTip(RosterItem* item) const { QString tip(P2QSTRING(item->getDisplayName())); ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); if (contact) { - if (contact->getDisplayJID().isValid()) { - tip += "\n" + P2QSTRING(contact->getDisplayJID().toBare().toString()); - } - tip += "\n " + P2QSTRING(statusShowTypeToFriendlyName(contact->getStatusShow())); - if (!getStatusText(item).isEmpty()) { - tip += ": " + getStatusText(item); - } - if (!contact->getIdleText().empty()) { - tip += "\n " + tr("Idle since ") + P2QSTRING(contact->getIdleText()); - } + return RosterTooltip::buildDetailedTooltip(contact, cachedImageScaler_); } return tip; } @@ -176,16 +172,7 @@ QIcon RosterModel::getPresenceIcon(RosterItem* item) const { return QIcon(":/icons/stop.png"); } - QString iconString; - switch (contact->getStatusShow()) { - case StatusShow::Online: iconString = "online";break; - case StatusShow::Away: iconString = "away";break; - case StatusShow::XA: iconString = "away";break; - case StatusShow::FFC: iconString = "online";break; - case StatusShow::DND: iconString = "dnd";break; - case StatusShow::None: iconString = "offline";break; - } - return QIcon(":/icons/" + iconString + ".png"); + return QIcon(statusShowTypeToIconPath(contact->getStatusShow())); } diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h index cae80c4..5397054 100644 --- a/Swift/QtUI/Roster/RosterModel.h +++ b/Swift/QtUI/Roster/RosterModel.h @@ -6,11 +6,13 @@ #pragma once -#include "Swift/Controllers/Roster/Roster.h" - #include <QAbstractItemModel> #include <QList> +#include <Swift/Controllers/Roster/Roster.h> + +#include <Swift/QtUI/QtScaledAvatarCache.h> + namespace Swift { enum RosterRoles { StatusTextRole = Qt::UserRole, @@ -56,5 +58,6 @@ namespace Swift { void reLayout(); Roster* roster_; QtTreeWidget* view_; + QtScaledAvatarCache* cachedImageScaler_; }; } diff --git a/Swift/QtUI/Roster/RosterTooltip.cpp b/Swift/QtUI/Roster/RosterTooltip.cpp new file mode 100644 index 0000000..edf9c99 --- /dev/null +++ b/Swift/QtUI/Roster/RosterTooltip.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include <Swift/QtUI/Roster/RosterTooltip.h> + +#include <QObject> +#include <QString> +#include <QApplication> + +#include <Swiften/Base/Path.h> + +#include <Swift/Controllers/Roster/ContactRosterItem.h> +#include <Swift/Controllers/StatusUtil.h> + +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swift/QtUI/QtScaledAvatarCache.h> +#include <Swift/QtUI/QtUtilities.h> +#include <Swift/QtUI/QtResourceHelper.h> + +using namespace QtUtilities; + +namespace Swift { + +QString RosterTooltip::buildDetailedTooltip(ContactRosterItem* contact, QtScaledAvatarCache* cachedImageScaler) { + QString tooltipTemplate; + if (QApplication::layoutDirection() == Qt::RightToLeft) { + tooltipTemplate = QString( + "<table style='white-space:pre'>" + "<tr>" + "<td>" + "<img src=\"%1\" />" + "</td>" + "<td>" + "<p style='font-size: 14px'>%3 %2</p>" + "<table><tr><td valign='middle'>%5</td><td valign='middle'>%4</td></tr></table>" + "%6" + "%7" + "%8" + "</td>" + "</tr>" + "</table>"); + } else { + tooltipTemplate = QString( + "<table style='white-space:pre'>" + "<tr>" + "<td>" + "<img src=\"%1\" />" + "</td>" + "<td>" + "<p style='font-size: 14px'>%2 %3</p>" + "<table><tr><td valign='middle'>%4</td><td valign='middle'>%5</td></tr></table>" + "%6" + "%7" + "%8" + "</td>" + "</tr>" + "</table>"); + } + // prepare tooltip + QString fullName = P2QSTRING(contact->getDisplayName()); + + QString vCardSummary; + VCard::ref vCard = contact->getVCard(); + if (vCard) { + fullName = P2QSTRING(vCard->getFullName()).trimmed(); + if (fullName.isEmpty()) { + fullName = (P2QSTRING(vCard->getGivenName()) + " " + P2QSTRING(vCard->getFamilyName())).trimmed(); + } + if (fullName.isEmpty()) { + fullName = P2QSTRING(contact->getDisplayName()); + } + vCardSummary = buildVCardSummary(vCard); + } else { + contact->onVCardRequested(); + } + + QString scaledAvatarPath = cachedImageScaler->getScaledAvatarPath(P2QSTRING(contact->getAvatarPath().empty() ? ":/icons/avatar.png" : pathToString(contact->getAvatarPath()))); + + QString bareJID = contact->getDisplayJID().toString().empty() ? "" : "( " + P2QSTRING(contact->getDisplayJID().toString()) + " )"; + + QString presenceIconTag = QString("<img src='%1' />").arg(statusShowTypeToIconPath(contact->getStatusShow())); + + QString statusMessage = contact->getStatusText().empty() ? QObject::tr("(No message)") : P2QSTRING(contact->getStatusText()); + + QString idleString = P2QSTRING(contact->getIdleText()); + if (!idleString.isEmpty()) { + idleString = QObject::tr("Idle since %1").arg(idleString); + idleString = htmlEscape(idleString) + "<br/>"; + } + + QString lastSeen = P2QSTRING(contact->getOfflineSinceText()); + if (!lastSeen.isEmpty()) { + lastSeen = QObject::tr("Last seen %1").arg(lastSeen); + lastSeen = htmlEscape(lastSeen) + "<br/>"; + } + + return tooltipTemplate.arg(scaledAvatarPath, htmlEscape(fullName), htmlEscape(bareJID), presenceIconTag, htmlEscape(statusMessage), idleString, lastSeen, vCardSummary); +} + +QString RosterTooltip::buildVCardSummary(VCard::ref vcard) { + QString summary; + summary = "<table>"; + + // star | name | content + QString currentBlock; + foreach (const VCard::Telephone& tel, vcard->getTelephones()) { + QString field = buildVCardField(tel.isPreferred, QObject::tr("Telephone"), htmlEscape(P2QSTRING(tel.number))); + if (tel.isPreferred) { + currentBlock = field; + break; + } + currentBlock += field; + } + summary += currentBlock; + + currentBlock = ""; + foreach (const VCard::EMailAddress& mail, vcard->getEMailAddresses()) { + QString field = buildVCardField(mail.isPreferred, QObject::tr("E-Mail"), htmlEscape(P2QSTRING(mail.address))); + if (mail.isPreferred) { + currentBlock = field; + break; + } + currentBlock += field; + } + summary += currentBlock; + + currentBlock = ""; + foreach (const VCard::Organization& org, vcard->getOrganizations()) { + QString field = buildVCardField(false, QObject::tr("Organization"), htmlEscape(P2QSTRING(org.name))); + currentBlock += field; + } + summary += currentBlock; + + currentBlock = ""; + foreach(const std::string& title, vcard->getTitles()) { + QString field = buildVCardField(false, QObject::tr("Title"), htmlEscape(P2QSTRING(title))); + currentBlock += field; + } + summary += currentBlock; + + summary += "</table>"; + return summary; +} + +QString RosterTooltip::buildVCardField(bool preferred, const QString& name, const QString& content) { + QString rowTemplate; + if (QApplication::layoutDirection() == Qt::RightToLeft) { + rowTemplate = QString("<tr><td>%3</td><td valign='middle'><strong>%2</strong></td><td valign='middle'>%1</td></tr>"); + } else { + rowTemplate = QString("<tr><td>%1</td><td valign='middle'><strong>%2</strong></td><td valign='middle'>%3</td></tr>"); + } + return rowTemplate.arg(preferred ? "<img src=':/icons/star-checked.png' />" : "", name, content); +} + +} diff --git a/Swift/QtUI/Roster/RosterTooltip.h b/Swift/QtUI/Roster/RosterTooltip.h new file mode 100644 index 0000000..37f5da2 --- /dev/null +++ b/Swift/QtUI/Roster/RosterTooltip.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <QString> + +#include <Swiften/Elements/VCard.h> + +namespace Swift { + +class ContactRosterItem; +class QtScaledAvatarCache; + +class RosterTooltip { + public: + static QString buildDetailedTooltip(ContactRosterItem* contact, QtScaledAvatarCache* cachedImageScaler); + + private: + static QString buildVCardSummary(VCard::ref vcard); + static QString buildVCardField(bool preferred, const QString& name, const QString& content); +}; + +} diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 5cfe81f..2303189 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -147,6 +147,7 @@ sources = [ "Roster/DelegateCommons.cpp", "Roster/QtRosterWidget.cpp", "Roster/QtOccupantListWidget.cpp", + "Roster/RosterTooltip.cpp", "EventViewer/EventModel.cpp", "EventViewer/EventDelegate.cpp", "EventViewer/TwoLineDelegate.cpp", @@ -163,9 +164,9 @@ sources = [ "MUCSearch/MUCSearchRoomItem.cpp", "MUCSearch/MUCSearchEmptyItem.cpp", "MUCSearch/MUCSearchDelegate.cpp", - "UserSearch/ContactListDelegate.cpp", - "UserSearch/ContactListModel.cpp", - "UserSearch/QtContactListWidget.cpp", + "UserSearch/ContactListDelegate.cpp", + "UserSearch/ContactListModel.cpp", + "UserSearch/QtContactListWidget.cpp", "UserSearch/QtSuggestingJIDInput.cpp", "UserSearch/QtUserSearchFirstPage.cpp", "UserSearch/QtUserSearchFirstMultiJIDPage.cpp", @@ -175,11 +176,11 @@ sources = [ "UserSearch/QtUserSearchWindow.cpp", "UserSearch/UserSearchModel.cpp", "UserSearch/UserSearchDelegate.cpp", - "Whiteboard/FreehandLineItem.cpp", - "Whiteboard/GView.cpp", - "Whiteboard/TextDialog.cpp", - "Whiteboard/QtWhiteboardWindow.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", @@ -189,7 +190,8 @@ sources = [ "QtMUCConfigurationWindow.cpp", "QtAffiliationEditor.cpp", "QtUISettingConstants.cpp", - "QtURLValidator.cpp" + "QtURLValidator.cpp", + "QtResourceHelper.cpp" ] # QtVCardWidget diff --git a/Swift/QtUI/UserSearch/ContactListModel.cpp b/Swift/QtUI/UserSearch/ContactListModel.cpp index 6523a4d..4c4a3ea 100644 --- a/Swift/QtUI/UserSearch/ContactListModel.cpp +++ b/Swift/QtUI/UserSearch/ContactListModel.cpp @@ -6,12 +6,14 @@ #include <Swift/QtUI/UserSearch/ContactListModel.h> -#include <Swift/QtUI/QtSwiftUtil.h> +#include <QMimeData> + #include <Swiften/Base/Path.h> #include <Swiften/Base/foreach.h> #include <Swiften/Elements/StatusShow.h> -#include <QMimeData> +#include <Swift/QtUI/QtSwiftUtil.h> +#include <Swift/QtUI/QtResourceHelper.h> namespace Swift { @@ -158,16 +160,7 @@ QVariant ContactListModel::dataForContact(const Contact& contact, int role) cons } QIcon ContactListModel::getPresenceIconForContact(const Contact& contact) const { - QString iconString; - switch (contact.statusType) { - case StatusShow::Online: iconString = "online";break; - case StatusShow::Away: iconString = "away";break; - case StatusShow::XA: iconString = "away";break; - case StatusShow::FFC: iconString = "online";break; - case StatusShow::DND: iconString = "dnd";break; - case StatusShow::None: iconString = "offline";break; - } - return QIcon(":/icons/" + iconString + ".png"); + return QIcon(statusShowTypeToIconPath(contact.statusType)); } } |