summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2013-11-10 15:56:22 (GMT)
committerTobias Markmann <tm@ayena.de>2013-11-18 14:58:53 (GMT)
commit3f8ff1c0e154dcb9959906e6865053dbe975892f (patch)
tree494f84e2d36130cc14806a9c6828e4ed433fc8c7 /Swift/QtUI
parentd674359cdefae70f3cc1fa6439c96c82b508b5e9 (diff)
downloadswift-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.cpp16
-rw-r--r--Swift/QtUI/ChatList/ChatListWhiteboardItem.cpp16
-rw-r--r--Swift/QtUI/QtMainWindow.cpp17
-rw-r--r--Swift/QtUI/QtMainWindow.h14
-rw-r--r--Swift/QtUI/QtResourceHelper.cpp25
-rw-r--r--Swift/QtUI/QtResourceHelper.h17
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.cpp43
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.h11
-rw-r--r--Swift/QtUI/Roster/RosterModel.cpp45
-rw-r--r--Swift/QtUI/Roster/RosterModel.h7
-rw-r--r--Swift/QtUI/Roster/RosterTooltip.cpp158
-rw-r--r--Swift/QtUI/Roster/RosterTooltip.h27
-rw-r--r--Swift/QtUI/SConscript20
-rw-r--r--Swift/QtUI/UserSearch/ContactListModel.cpp17
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));
}
}