summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI/Roster')
-rw-r--r--Swift/QtUI/Roster/DelegateCommons.cpp11
-rw-r--r--Swift/QtUI/Roster/DelegateCommons.h5
-rw-r--r--Swift/QtUI/Roster/QtOccupantListWidget.cpp1
-rw-r--r--Swift/QtUI/Roster/QtRosterWidget.cpp46
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.cpp4
-rw-r--r--Swift/QtUI/Roster/RosterDelegate.cpp4
-rw-r--r--Swift/QtUI/Roster/RosterModel.cpp67
-rw-r--r--Swift/QtUI/Roster/RosterModel.h5
8 files changed, 115 insertions, 28 deletions
diff --git a/Swift/QtUI/Roster/DelegateCommons.cpp b/Swift/QtUI/Roster/DelegateCommons.cpp
index a575cb0..776d90c 100644
--- a/Swift/QtUI/Roster/DelegateCommons.cpp
+++ b/Swift/QtUI/Roster/DelegateCommons.cpp
@@ -14,11 +14,13 @@ namespace Swift {
void DelegateCommons::drawElidedText(QPainter* painter, const QRect& region, const QString& text, int flags) {
QString adjustedText(painter->fontMetrics().elidedText(text, Qt::ElideRight, region.width(), Qt::TextShowMnemonic));
+ painter->setClipRect(region);
painter->drawText(region, flags, adjustedText.simplified());
+ painter->setClipping(false);
}
-void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount, bool compact) const {
- painter->save();
+void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, bool isIdle, int unreadCount, bool compact) const {
+ painter->save();
QRect fullRegion(option.rect);
if ( option.state & QStyle::State_Selected ) {
painter->fillRect(fullRegion, option.palette.highlight());
@@ -29,6 +31,7 @@ void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem
QRect presenceIconRegion(QPoint(farLeftMargin, fullRegion.top()), QSize(presenceIconWidth, fullRegion.height() - verticalMargin));
+ QRect idleIconRegion(QPoint(farLeftMargin, fullRegion.top()), QSize(presenceIconWidth*2, fullRegion.height() - verticalMargin));
int calculatedAvatarSize = presenceIconRegion.height();
//This overlaps the presenceIcon, so must be painted first
QRect avatarRegion(QPoint(presenceIconRegion.right() - presenceIconWidth / 2, presenceIconRegion.top()), QSize(calculatedAvatarSize, calculatedAvatarSize));
@@ -51,6 +54,10 @@ void DelegateCommons::paintContact(QPainter* painter, const QStyleOptionViewItem
//Paint the presence icon over the top of the avatar
presenceIcon.paint(painter, presenceIconRegion, Qt::AlignBottom | Qt::AlignHCenter);
+ if (isIdle) {
+ idleIcon.paint(painter, idleIconRegion, Qt::AlignBottom | Qt::AlignHCenter);
+ }
+
QFontMetrics nameMetrics(nameFont);
painter->setFont(nameFont);
int extraFontWidth = nameMetrics.width("H");
diff --git a/Swift/QtUI/Roster/DelegateCommons.h b/Swift/QtUI/Roster/DelegateCommons.h
index 8732598..0684410 100644
--- a/Swift/QtUI/Roster/DelegateCommons.h
+++ b/Swift/QtUI/Roster/DelegateCommons.h
@@ -17,7 +17,7 @@
namespace Swift {
class DelegateCommons {
public:
- DelegateCommons() : nameFont(QApplication::font()), detailFont(QApplication::font()) {
+ DelegateCommons() : nameFont(QApplication::font()), detailFont(QApplication::font()), idleIcon(QIcon(":/icons/zzz.png")) {
detailFontSizeDrop = nameFont.pointSize() >= 10 ? 2 : 0;
detailFont.setStyle(QFont::StyleItalic);
detailFont.setPointSize(nameFont.pointSize() - detailFontSizeDrop);
@@ -26,7 +26,7 @@ namespace Swift {
static void drawElidedText(QPainter* painter, const QRect& region, const QString& text, int flags = Qt::AlignTop);
QSize contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index, bool compact) const;
- void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, int unreadCount, bool compact) const;
+ void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QColor& nameColor, const QString& avatarPath, const QIcon& presenceIcon, const QString& name, const QString& statusText, bool isIdle, int unreadCount, bool compact) const;
int detailFontSizeDrop;
QFont nameFont;
@@ -38,5 +38,6 @@ namespace Swift {
static const int presenceIconHeight;
static const int presenceIconWidth;
static const int unreadCountSize;
+ QIcon idleIcon;
};
}
diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
index 5d26c46..12dc1e4 100644
--- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp
+++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
@@ -58,6 +58,7 @@ void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) {
case ChatWindow::MakeParticipant: text = tr("Make participant"); break;
case ChatWindow::MakeVisitor: text = tr("Remove voice"); break;
case ChatWindow::AddContact: text = tr("Add to contacts"); break;
+ case ChatWindow::ShowProfile: text = tr("Show profile"); break;
}
QAction* action = contextMenu.addAction(text);
actions[action] = availableAction;
diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp
index 1cf073b..6bf3989 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.cpp
+++ b/Swift/QtUI/Roster/QtRosterWidget.cpp
@@ -4,23 +4,25 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "Roster/QtRosterWidget.h"
+#include <Swift/QtUI/Roster/QtRosterWidget.h>
#include <QContextMenuEvent>
#include <QMenu>
#include <QInputDialog>
#include <QFileDialog>
-#include "Swift/Controllers/UIEvents/RequestContactEditorUIEvent.h"
-#include "Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h"
-#include "Swift/Controllers/UIEvents/RenameGroupUIEvent.h"
-#include "Swift/Controllers/UIEvents/SendFileUIEvent.h"
-#include "Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h"
-#include "QtContactEditWindow.h"
-#include "Swift/Controllers/Roster/ContactRosterItem.h"
-#include "Swift/Controllers/Roster/GroupRosterItem.h"
-#include "Swift/Controllers/UIEvents/UIEventStream.h"
-#include "QtSwiftUtil.h"
+#include <Swift/Controllers/UIEvents/RequestContactEditorUIEvent.h>
+#include <Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h>
+#include <Swift/Controllers/UIEvents/RenameGroupUIEvent.h>
+#include <Swift/Controllers/UIEvents/SendFileUIEvent.h>
+#include <Swift/Controllers/UIEvents/RequestWhiteboardUIEvent.h>
+#include <Swift/Controllers/UIEvents/ShowProfileForRosterItemUIEvent.h>
+#include <Swift/Controllers/UIEvents/RequestChangeBlockStateUIEvent.h>
+#include <Swift/QtUI/QtContactEditWindow.h>
+#include <Swift/Controllers/Roster/ContactRosterItem.h>
+#include <Swift/Controllers/Roster/GroupRosterItem.h>
+#include <Swift/Controllers/UIEvents/UIEventStream.h>
+#include <Swift/QtUI/QtSwiftUtil.h>
namespace Swift {
@@ -57,6 +59,18 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
QAction* editContact = contextMenu.addAction(tr("Edit…"));
QAction* removeContact = contextMenu.addAction(tr("Remove"));
+ QAction* showProfileForContact = contextMenu.addAction(tr("Show Profile"));
+
+ QAction* unblockContact = NULL;
+ if (contact->blockState() == ContactRosterItem::IsBlocked) {
+ unblockContact = contextMenu.addAction(tr("Unblock"));
+ }
+
+ QAction* blockContact = NULL;
+ if (contact->blockState() == ContactRosterItem::IsUnblocked) {
+ blockContact = contextMenu.addAction(tr("Block"));
+ }
+
#ifdef SWIFT_EXPERIMENTAL_FT
QAction* sendFile = NULL;
if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
@@ -69,6 +83,7 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
startWhiteboardChat = contextMenu.addAction(tr("Start Whiteboard Chat"));
}
#endif
+
QAction* result = contextMenu.exec(event->globalPos());
if (result == editContact) {
eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID()));
@@ -78,6 +93,15 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
eventStream_->send(boost::make_shared<RemoveRosterItemUIEvent>(contact->getJID()));
}
}
+ else if (result == showProfileForContact) {
+ eventStream_->send(boost::make_shared<ShowProfileForRosterItemUIEvent>(contact->getJID()));
+ }
+ else if (unblockContact && result == unblockContact) {
+ eventStream_->send(boost::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Unblocked, contact->getJID()));
+ }
+ else if (blockContact && result == blockContact) {
+ eventStream_->send(boost::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Blocked, contact->getJID()));
+ }
#ifdef SWIFT_EXPERIMENTAL_FT
else if (sendFile && result == sendFile) {
QString fileName = QFileDialog::getOpenFileName(this, tr("Send File"), "", tr("All Files (*);;"));
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 5fdf138..99f1f34 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -10,6 +10,7 @@
#include <boost/bind.hpp>
#include <QUrl>
+#include <QMimeData>
#include <Swiften/Base/Platform.h>
#include <Swift/Controllers/Roster/ContactRosterItem.h>
@@ -41,6 +42,7 @@ QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, SettingsProvider* setting
#ifdef SWIFT_EXPERIMENTAL_FT
setAcceptDrops(true);
#endif
+ setDragEnabled(true);
setRootIsDecorated(true);
connect(this, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleItemActivated(const QModelIndex&)));
connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool)));
@@ -156,7 +158,7 @@ void QtTreeWidget::dragMoveEvent(QDragMoveEvent* event) {
}
}
}
- event->ignore();
+ QTreeView::dragMoveEvent(event);
}
void QtTreeWidget::handleExpanded(const QModelIndex& index) {
diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp
index 7e6428b..aef588c 100644
--- a/Swift/QtUI/Roster/RosterDelegate.cpp
+++ b/Swift/QtUI/Roster/RosterDelegate.cpp
@@ -35,6 +35,7 @@ RosterDelegate::~RosterDelegate() {
void RosterDelegate::setCompact(bool compact) {
compact_ = compact;
+ emit sizeHintChanged(QModelIndex());
}
QSize RosterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const {
@@ -73,9 +74,10 @@ void RosterDelegate::paintContact(QPainter* painter, const QStyleOptionViewItem&
QIcon presenceIcon = index.data(PresenceIconRole).isValid() && !index.data(PresenceIconRole).value<QIcon>().isNull()
? index.data(PresenceIconRole).value<QIcon>()
: QIcon(":/icons/offline.png");
+ bool isIdle = index.data(IdleRole).isValid() ? index.data(IdleRole).toBool() : false;
QString name = index.data(Qt::DisplayRole).toString();
QString statusText = index.data(StatusTextRole).toString();
- common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, 0, compact_);
+ common_.paintContact(painter, option, nameColor, avatarPath, presenceIcon, name, statusText, isIdle, 0, compact_);
}
}
diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp
index 1fc20dd..3791ffa 100644
--- a/Swift/QtUI/Roster/RosterModel.cpp
+++ b/Swift/QtUI/Roster/RosterModel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Kevin Smith
+ * Copyright (c) 2010-2013 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -10,12 +10,14 @@
#include <QColor>
#include <QIcon>
+#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/Base/Path.h>
#include "QtSwiftUtil.h"
#include "Swift/QtUI/Roster/QtTreeWidget.h"
@@ -40,7 +42,8 @@ void RosterModel::setRoster(Roster* roster) {
void RosterModel::reLayout() {
//emit layoutChanged();
- reset();
+ beginResetModel();
+ endResetModel(); // TODO: Not sure if this isn't too early?
if (!roster_) {
return;
}
@@ -53,7 +56,7 @@ void RosterModel::reLayout() {
void RosterModel::handleChildrenChanged(GroupRosterItem* /*group*/) {
reLayout();
-}
+}
void RosterModel::handleDataChanged(RosterItem* item) {
Q_ASSERT(item);
@@ -63,6 +66,14 @@ void RosterModel::handleDataChanged(RosterItem* item) {
}
}
+Qt::ItemFlags RosterModel::flags(const QModelIndex& index) const {
+ Qt::ItemFlags flags = QAbstractItemModel::flags(index);
+ if (dynamic_cast<GroupRosterItem*>(getItem(index)) == NULL) {
+ flags |= Qt::ItemIsDragEnabled;
+ }
+ return flags;
+}
+
int RosterModel::columnCount(const QModelIndex& /*parent*/) const {
return 1;
}
@@ -84,7 +95,8 @@ QVariant RosterModel::data(const QModelIndex& index, int role) const {
case AvatarRole: return getAvatar(item);
case PresenceIconRole: return getPresenceIcon(item);
case ChildCountRole: return getChildCount(item);
- default: return QVariant();
+ case IdleRole: return getIsIdle(item);
+ default: return QVariant();
}
}
@@ -93,6 +105,11 @@ int RosterModel::getChildCount(RosterItem* item) const {
return group ? group->getDisplayedChildren().size() : 0;
}
+bool RosterModel::getIsIdle(RosterItem* item) const {
+ ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
+ return contact ? !contact->getIdleText().empty() : false;
+}
+
QColor RosterModel::intToColor(int color) const {
return QColor(
((color & 0xFF0000)>>16),
@@ -131,6 +148,9 @@ QString RosterModel::getToolTip(RosterItem* item) const {
if (!getStatusText(item).isEmpty()) {
tip += ": " + getStatusText(item);
}
+ if (!contact->getIdleText().empty()) {
+ tip += "\n " + tr("Idle since ") + P2QSTRING(contact->getIdleText());
+ }
}
return tip;
}
@@ -140,7 +160,7 @@ QString RosterModel::getAvatar(RosterItem* item) const {
if (!contact) {
return "";
}
- return QString(contact->getAvatarPath().c_str());
+ return P2QSTRING(pathToString(contact->getAvatarPath()));
}
QString RosterModel::getStatusText(RosterItem* item) const {
@@ -152,14 +172,18 @@ QString RosterModel::getStatusText(RosterItem* item) const {
QIcon RosterModel::getPresenceIcon(RosterItem* item) const {
ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
if (!contact) return QIcon();
+ if (contact->blockState() == ContactRosterItem::IsBlocked) {
+ 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;
+ 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");
}
@@ -215,4 +239,25 @@ int RosterModel::rowCount(const QModelIndex& parent) const {
return count;
}
+QMimeData* RosterModel::mimeData(const QModelIndexList& indexes) const {
+ QMimeData* data = QAbstractItemModel::mimeData(indexes);
+
+ ContactRosterItem *item = dynamic_cast<ContactRosterItem*>(getItem(indexes.first()));
+ if (item == NULL) {
+ return data;
+ }
+
+ QByteArray itemData;
+ QDataStream dataStream(&itemData, QIODevice::WriteOnly);
+
+ // jid, chatName, activity, statusType, avatarPath
+ dataStream << P2QSTRING(item->getJID().toString());
+ dataStream << P2QSTRING(item->getDisplayName());
+ dataStream << P2QSTRING(item->getStatusText());
+ dataStream << item->getSimplifiedStatusShow();
+ dataStream << P2QSTRING(item->getAvatarPath().string());
+ data->setData("application/vnd.swift.contact-jid", itemData);
+ return data;
+}
+
}
diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h
index bd34e9c..cae80c4 100644
--- a/Swift/QtUI/Roster/RosterModel.h
+++ b/Swift/QtUI/Roster/RosterModel.h
@@ -18,6 +18,7 @@ namespace Swift {
PresenceIconRole = Qt::UserRole + 2,
StatusShowTypeRole = Qt::UserRole + 3,
ChildCountRole = Qt::UserRole + 4,
+ IdleRole = Qt::UserRole + 5
};
class QtTreeWidget;
@@ -28,12 +29,15 @@ namespace Swift {
RosterModel(QtTreeWidget* view);
~RosterModel();
void setRoster(Roster* swiftRoster);
+ Qt::ItemFlags flags(const QModelIndex& index) const;
int columnCount(const QModelIndex& parent = QModelIndex()) const;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const;
QModelIndex index(RosterItem* item) const;
QModelIndex parent(const QModelIndex& index) const;
int rowCount(const QModelIndex& parent = QModelIndex()) const;
+ QMimeData* mimeData(const QModelIndexList& indexes) const;
+
signals:
void itemExpanded(const QModelIndex& item, bool expanded);
private:
@@ -48,6 +52,7 @@ namespace Swift {
QString getStatusText(RosterItem* item) const;
QIcon getPresenceIcon(RosterItem* item) const;
int getChildCount(RosterItem* item) const;
+ bool getIsIdle(RosterItem* item) const;
void reLayout();
Roster* roster_;
QtTreeWidget* view_;