diff options
author | Kevin Smith <git@kismith.co.uk> | 2010-05-06 08:00:44 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2010-05-06 10:49:49 (GMT) |
commit | 081fc03556708447610e9697a57235fa191a4f0d (patch) | |
tree | 505c8cc9129d2b44968d183a180f0ccddaa08810 /Swift/QtUI/Roster | |
parent | 8c53236875d2ca77f1b463449918458f6b424ab1 (diff) | |
download | swift-contrib-081fc03556708447610e9697a57235fa191a4f0d.zip swift-contrib-081fc03556708447610e9697a57235fa191a4f0d.tar.bz2 |
Rewrite of large amounts of roster code.
Now keeps widgets out of Swiften, keeps sorting inside Swiften,
and keeps track of presences to show the correct presence per
roster item.
Resolves: #316
Resolves: #81
Resolves: #239
Diffstat (limited to 'Swift/QtUI/Roster')
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.cpp | 121 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.h | 19 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidgetFactory.cpp | 6 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidgetFactory.h | 49 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterDelegate.cpp | 29 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterDelegate.h | 5 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterModel.cpp | 184 | ||||
-rw-r--r-- | Swift/QtUI/Roster/RosterModel.h | 58 |
8 files changed, 275 insertions, 196 deletions
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp index 9dabc81..97b055b 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.cpp +++ b/Swift/QtUI/Roster/QtTreeWidget.cpp @@ -7,7 +7,9 @@ #include "Roster/QtTreeWidget.h" #include "Swiften/Base/Platform.h" -#include "Swiften/Roster/OpenChatRosterAction.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swift/Controllers/UIEvents/UIEventStream.h" +#include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" #include <qdebug.h> #include <QMenu> @@ -15,26 +17,26 @@ namespace Swift { -QtTreeWidget::QtTreeWidget(QWidget* parent) : QTreeView(parent) { - treeRoot_ = new QtTreeWidgetItem(NULL); - model_ = new RosterModel(); - model_->setRoot(treeRoot_); +QtTreeWidget::QtTreeWidget(UIEventStream* eventStream, QWidget* parent) : QTreeView(parent) { + eventStream_ = eventStream; + model_ = new RosterModel(this); setModel(model_); - delegate_ = new RosterDelegate(); + delegate_ = new RosterDelegate(this); setItemDelegate(delegate_); setHeaderHidden(true); contextMenu_ = NULL; #ifdef SWIFT_PLATFORM_MACOSX setAlternatingRowColors(true); #endif + expandAll(); setAnimated(true); setIndentation(0); 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))); - connect(model_, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(handleDataChanged(const QModelIndex&, const QModelIndex&))); - connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); - connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); +// connect(model_, SIGNAL(itemExpanded(const QModelIndex&, bool)), this, SLOT(handleModelItemExpanded(const QModelIndex&, bool))); +// connect(model_, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(handleDataChanged(const QModelIndex&, const QModelIndex&))); +// connect(this, SIGNAL(expanded(const QModelIndex&)), this, SLOT(handleExpanded(const QModelIndex&))); +// connect(this, SIGNAL(collapsed(const QModelIndex&)), this, SLOT(handleCollapsed(const QModelIndex&))); } QtTreeWidget::~QtTreeWidget() { @@ -42,6 +44,11 @@ QtTreeWidget::~QtTreeWidget() { delete delegate_; } +void QtTreeWidget::setRosterModel(Roster* roster) { + model_->setRoster(roster); + expandAll(); +} + void QtTreeWidget::setContextMenu(QtContextMenu* contextMenu) { contextMenu_ = contextMenu; } @@ -51,9 +58,10 @@ QtTreeWidgetItem* QtTreeWidget::getRoot() { } void QtTreeWidget::handleItemActivated(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->performUserAction(boost::shared_ptr<UserRosterAction>(new OpenChatRosterAction())); + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact) { + eventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(contact->getJID()))); } } @@ -62,53 +70,52 @@ void QtTreeWidget::contextMenuEvent(QContextMenuEvent* event) { return; } QModelIndex index = indexAt(event->pos()); - QtTreeWidgetItem* qtItem = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - if (qtItem) { - contextMenu_->show(qtItem); - } -} - -void QtTreeWidget::handleExpanded(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->setExpanded(true); - } -} - -void QtTreeWidget::handleCollapsed(const QModelIndex& index) { - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (qtItem) { - qtItem->setExpanded(false); - } -} - -void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) { - if (this->isExpanded(index) == shouldExpand) { - return; - } - //setExpanded(index, shouldExpand); - if (shouldExpand) { - expand(index); - emit expanded(index); - } else { - collapse(index); - emit collapsed(index); + RosterItem* item = index.isValid() ? static_cast<RosterItem*>(index.internalPointer()) : NULL; + if (item) { + contextMenu_->show(item); } } -void QtTreeWidget::handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - Q_UNUSED(bottomRight); - //in our model, this is only thrown with topLeft == bottomRight - if (!topLeft.isValid()) { - return; - } - QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(topLeft.internalPointer()); - if (qtItem) { - setExpanded(topLeft, qtItem->isExpanded()); - //qDebug() << "Item changed, passing expanded state to view: " << qtItem->isExpanded() << " giving an expanded state of " << isExpanded(topLeft); - } - -} +//void QtTreeWidget::handleExpanded(const QModelIndex& index) { +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); +// if (qtItem) { +// qtItem->setExpanded(true); +// } +//} + +//void QtTreeWidget::handleCollapsed(const QModelIndex& index) { +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); +// if (qtItem) { +// qtItem->setExpanded(false); +// } +//} + +//void QtTreeWidget::handleModelItemExpanded(const QModelIndex& index, bool shouldExpand) { +// if (this->isExpanded(index) == shouldExpand) { +// return; +// } +// //setExpanded(index, shouldExpand); +// if (shouldExpand) { +// expand(index); +// emit expanded(index); +// } else { +// collapse(index); +// emit collapsed(index); +// } +//} + +// void QtTreeWidget::handleDataChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/) { +// //in our model, this is only thrown with topLeft == bottomRight +// if (!topLeft.isValid()) { +// return; +// } +// QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(topLeft.internalPointer()); +// if (qtItem) { +// setExpanded(topLeft, qtItem->isExpanded()); +// //qDebug() << "Item changed, passing expanded state to view: " << qtItem->isExpanded() << " giving an expanded state of " << isExpanded(topLeft); +// } + +// } void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const { } diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h index d6e6038..c03f2e2 100644 --- a/Swift/QtUI/Roster/QtTreeWidget.h +++ b/Swift/QtUI/Roster/QtTreeWidget.h @@ -9,31 +9,29 @@ #include <QTreeView> #include <QModelIndex> -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" #include "Swift/QtUI/Roster/QtTreeWidget.h" #include "Swift/QtUI/Roster/RosterModel.h" #include "Swift/QtUI/Roster/RosterDelegate.h" #include "Swift/QtUI/ContextMenus/QtContextMenu.h" namespace Swift { +class UIEventStream; -class QtTreeWidget : public QTreeView, public TreeWidget { +class QtTreeWidget : public QTreeView{ Q_OBJECT public: - QtTreeWidget(QWidget* parent = 0); + QtTreeWidget(UIEventStream* eventStream, QWidget* parent = 0); ~QtTreeWidget(); void show(); QtTreeWidgetItem* getRoot(); void setContextMenu(QtContextMenu* contextMenu); + void setRosterModel(Roster* roster); private slots: void handleItemActivated(const QModelIndex&); - void handleModelItemExpanded(const QModelIndex&, bool expanded); - void handleExpanded(const QModelIndex&); - void handleCollapsed(const QModelIndex&); - void handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); +// void handleModelItemExpanded(const QModelIndex&, bool expanded); +// void handleExpanded(const QModelIndex&); +// void handleCollapsed(const QModelIndex&); +// void handleDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); protected: void contextMenuEvent(QContextMenuEvent* event); @@ -43,6 +41,7 @@ class QtTreeWidget : public QTreeView, public TreeWidget { RosterDelegate* delegate_; QtTreeWidgetItem* treeRoot_; QtContextMenu* contextMenu_; + UIEventStream* eventStream_; }; } diff --git a/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp b/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp deleted file mode 100644 index d4a8e4b..0000000 --- a/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - diff --git a/Swift/QtUI/Roster/QtTreeWidgetFactory.h b/Swift/QtUI/Roster/QtTreeWidgetFactory.h deleted file mode 100644 index b72a508..0000000 --- a/Swift/QtUI/Roster/QtTreeWidgetFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#ifndef SWIFT_QtTreeWidgetFactory_H -#define SWIFT_QtTreeWidgetFactory_H - -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" -#include "Swift/QtUI/Roster/QtTreeWidget.h" - -namespace Swift { - -class QtTreeWidgetFactory : public TreeWidgetFactory { - public: - QtTreeWidgetFactory() { - } - - TreeWidget* createTreeWidget() { - return new QtTreeWidget(); - } - - TreeWidgetItem* createTreeWidgetItem(TreeWidgetItem* item) { - QtTreeWidgetItem* qtItem = dynamic_cast<QtTreeWidgetItem*>(item); - assert(qtItem); - QtTreeWidgetItem* newItem = new QtTreeWidgetItem(qtItem); - qtItem->addChild(newItem); - return newItem; - } - - TreeWidgetItem* createTreeWidgetItem(TreeWidget* item) { - QtTreeWidget* treeItem = dynamic_cast<QtTreeWidget*>(item); - assert(treeItem); - QtTreeWidgetItem* qtItem = treeItem->getRoot(); - QtTreeWidgetItem* newItem = new QtTreeWidgetItem(qtItem); - //qtItem->setItemWidget(newItem, 0, newItem->getCollapsedRosterWidget()); - qtItem->addChild(newItem); - newItem->setExpanded(true); - return newItem; - } -}; - -} -#endif - diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp index 0c12d6e..b7ba71b 100644 --- a/Swift/QtUI/Roster/RosterDelegate.cpp +++ b/Swift/QtUI/Roster/RosterDelegate.cpp @@ -15,11 +15,16 @@ #include <QPolygon> #include <qdebug.h> -#include "QtTreeWidgetItem.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swiften/Roster/GroupRosterItem.h" + +#include "QtTreeWidget.h" +#include "RosterModel.h" namespace Swift { -RosterDelegate::RosterDelegate() { +RosterDelegate::RosterDelegate(QtTreeWidget* tree) { + tree_ = tree; groupDelegate_ = new GroupItemDelegate(); } @@ -28,16 +33,14 @@ RosterDelegate::~RosterDelegate() { } QSize RosterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (!item || !item->isContact()) { + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + if (dynamic_cast<GroupRosterItem*>(item)) { return groupDelegate_->sizeHint(option, index); } return contactSizeHint(option, index); } -QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { - Q_UNUSED(option); - Q_UNUSED(index); +QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const { int heightByAvatar = avatarSize_ + common_.verticalMargin * 2; QFontMetrics nameMetrics(common_.nameFont); QFontMetrics statusMetrics(common_.detailFont); @@ -49,8 +52,8 @@ QSize RosterDelegate::contactSizeHint(const QStyleOptionViewItem& option, const } void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - if (item && !item->isContact()) { + RosterItem* item = static_cast<RosterItem*>(index.internalPointer()); + if (dynamic_cast<GroupRosterItem*>(item)) { paintGroup(painter, option, index); } else { paintContact(painter, option, index); @@ -58,15 +61,11 @@ void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option } void RosterDelegate::paintGroup(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QtTreeWidgetItem* item = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - if (item) { - groupDelegate_->paint(painter, option, index.data(Qt::DisplayRole).toString(), item->rowCount(), item->isExpanded()); + if (index.isValid()) { + groupDelegate_->paint(painter, option, index.data(Qt::DisplayRole).toString(), index.data(ChildCountRole).toInt(), tree_->isExpanded(index)); } } - - - void RosterDelegate::paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { //qDebug() << "painting" << index.data(Qt::DisplayRole).toString(); painter->save(); diff --git a/Swift/QtUI/Roster/RosterDelegate.h b/Swift/QtUI/Roster/RosterDelegate.h index 696ea03..e6a16f2 100644 --- a/Swift/QtUI/Roster/RosterDelegate.h +++ b/Swift/QtUI/Roster/RosterDelegate.h @@ -14,10 +14,10 @@ #include "DelegateCommons.h" namespace Swift { - class QtTreeWidgetItem; + class QtTreeWidget; class RosterDelegate : public QStyledItemDelegate { public: - RosterDelegate(); + RosterDelegate(QtTreeWidget* tree); ~RosterDelegate(); QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; @@ -27,6 +27,7 @@ namespace Swift { void paintContact(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; DelegateCommons common_; GroupItemDelegate* groupDelegate_; + QtTreeWidget* tree_; static const int avatarSize_; static const int presenceIconHeight_; static const int presenceIconWidth_; diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp index c4cf57e..408cc3e 100644 --- a/Swift/QtUI/Roster/RosterModel.cpp +++ b/Swift/QtUI/Roster/RosterModel.cpp @@ -6,74 +6,184 @@ #include "RosterModel.h" +#include <boost/bind.hpp> + +#include <QColor> +#include <QIcon> +#include <qdebug.h> + +#include "Swiften/Elements/StatusShow.h" +#include "Swiften/Roster/ContactRosterItem.h" +#include "Swiften/Roster/GroupRosterItem.h" + +#include "QtSwiftUtil.h" +#include "Swift/QtUI/Roster/QtTreeWidget.h" + namespace Swift { -RosterModel::RosterModel() { +RosterModel::RosterModel(QtTreeWidget* view) : view_(view) { + roster_ = NULL; } RosterModel::~RosterModel() { - delete tree_; } -void RosterModel::setRoot(QtTreeWidgetItem* root) { - tree_ = root; - connect(tree_, SIGNAL(changed(QtTreeWidgetItem*)), this, SLOT(handleItemChanged(QtTreeWidgetItem*))); +void RosterModel::setRoster(Roster* roster) { + roster_ = roster; + if (!roster_) return; + roster->onChildrenChanged.connect(boost::bind(&RosterModel::handleChildrenChanged, this, _1)); + roster->onDataChanged.connect(boost::bind(&RosterModel::handleDataChanged, this, _1)); + roster->onGroupAdded.connect(boost::bind(&RosterModel::handleGroupAdded, this, _1)); + emit layoutChanged(); } - -void RosterModel::handleItemChanged(QtTreeWidgetItem* item) { - if (!item->isShown()) { - return; - } +void RosterModel::handleGroupAdded(GroupRosterItem* group) { + view_->setExpanded(index(group), true); +} + +void RosterModel::handleChildrenChanged(GroupRosterItem* /*group*/) { + emit layoutChanged(); +} + +void RosterModel::handleDataChanged(RosterItem* item) { Q_ASSERT(item); QModelIndex modelIndex = index(item); - Q_ASSERT(modelIndex.isValid()); - emit itemExpanded(modelIndex, item->isExpanded()); - emit dataChanged(modelIndex, modelIndex); - emit dataChanged(parent(modelIndex), parent(modelIndex)); - emit layoutChanged(); + if (modelIndex.isValid()) { + //emit itemExpanded(modelIndex, item->isExpanded()); + emit dataChanged(modelIndex, modelIndex); + } } -int RosterModel::columnCount(const QModelIndex& parent) const { - Q_UNUSED(parent); +int RosterModel::columnCount(const QModelIndex& /*parent*/) const { return 1; } +RosterItem* RosterModel::getItem(const QModelIndex& index) const { + return index.isValid() ? static_cast<RosterItem*>(index.internalPointer()) : NULL; +} + QVariant RosterModel::data(const QModelIndex& index, int role) const { - QtTreeWidgetItem* item = index.isValid() ? static_cast<QtTreeWidgetItem*>(index.internalPointer()) : NULL; - return item ? item->data(role) : QVariant(); + RosterItem* item = getItem(index); + if (!item) return QVariant(); + + switch (role) { + case Qt::DisplayRole: return P2QSTRING(item->getDisplayName()); + case Qt::TextColorRole: return getTextColor(item); + case Qt::BackgroundColorRole: return getBackgroundColor(item); + case Qt::ToolTipRole: return getToolTip(item); + case StatusTextRole: return getStatusText(item); + case AvatarRole: return getAvatar(item); + case PresenceIconRole: return getPresenceIcon(item); + case ChildCountRole: return getChildCount(item); + default: return QVariant(); + } } -QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) const { - QtTreeWidgetItem* parentItem = parent.isValid() ? static_cast<QtTreeWidgetItem*>(parent.internalPointer()) : tree_; - Q_ASSERT(parentItem); - - return row < parentItem->rowCount() ? createIndex(row, column, parentItem->getItem(row)) : QModelIndex(); +int RosterModel::getChildCount(RosterItem* item) const { + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + return group ? group->getDisplayedChildren().size() : 0; } -QModelIndex RosterModel::index(QtTreeWidgetItem* item) const { - return createIndex(item->row(), 0, item); +QColor RosterModel::intToColor(int color) const { + return QColor( + ((color & 0xFF0000)>>16), + ((color & 0xFF00)>>8), + (color & 0xFF)); } -QModelIndex RosterModel::parent(const QModelIndex& index) const { - if (!index.isValid()) { - return QModelIndex(); +QColor RosterModel::getTextColor(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + int color = 0; + if (contact) { + switch (contact->getStatusShow()) { + case StatusShow::Online: color = 0x000000; break; + case StatusShow::Away: color = 0x336699; break; + case StatusShow::XA: color = 0x336699; break; + case StatusShow::FFC: color = 0x000000; break; + case StatusShow::DND: color = 0x990000; break; + case StatusShow::None: color = 0x7F7F7F;break; + } } + return intToColor(color); +} + +QColor RosterModel::getBackgroundColor(RosterItem* item) const { + return dynamic_cast<ContactRosterItem*>(item) ? intToColor(0xFFFFFF) : intToColor(0x969696); +} + +QString RosterModel::getToolTip(RosterItem* item) const { + return dynamic_cast<ContactRosterItem*>(item) ? P2QSTRING(item->getDisplayName()) + "\n" + getStatusText(item) : P2QSTRING(item->getDisplayName()); +} + +QIcon RosterModel::getAvatar(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return QIcon(); + String path = contact->getAvatarPath(); - QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); - Q_ASSERT(item); + return path.isEmpty() ? QIcon() : QIcon(P2QSTRING(path)); +} - QtTreeWidgetItem* parentItem = item->getParentItem(); - /* parentItem_ == NULL can happen during destruction.*/ - return parentItem == tree_ || parentItem == NULL ? QModelIndex() : createIndex(parentItem->row(), 0, parentItem); +QString RosterModel::getStatusText(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return ""; + return P2QSTRING(contact->getStatusText()); +} +QIcon RosterModel::getPresenceIcon(RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (!contact) return QIcon(); + 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"); +} + + +QModelIndex RosterModel::index(int row, int column, const QModelIndex& parent) const { + GroupRosterItem* parentItem; + if (!parent.isValid()) { + //top level + parentItem = roster_->getRoot(); + } else { + parentItem = dynamic_cast<GroupRosterItem*>(getItem(parent)); + if (!parentItem) return QModelIndex(); + } + return (size_t)row < parentItem->getDisplayedChildren().size() ? createIndex(row, column, parentItem->getDisplayedChildren()[row]) : QModelIndex(); +} + +QModelIndex RosterModel::index(RosterItem* item) const { + GroupRosterItem* parent = item->getParent(); + for (size_t i = 0; i < parent->getDisplayedChildren().size(); i++) { + if (parent->getDisplayedChildren()[i] == item) { + return createIndex(i, 0, item); + } + } + return QModelIndex(); +} + +QModelIndex RosterModel::parent(const QModelIndex& child) const { + if (!child.isValid()) { + return QModelIndex(); + } + + GroupRosterItem* parent = getItem(child)->getParent(); + return (parent != roster_->getRoot()) ? index(parent) : QModelIndex(); } int RosterModel::rowCount(const QModelIndex& parent) const { - QtTreeWidgetItem* item = parent.isValid() ? static_cast<QtTreeWidgetItem*>(parent.internalPointer()) : tree_; + if (!roster_) return 0; + RosterItem* item = parent.isValid() ? static_cast<RosterItem*>(parent.internalPointer()) : roster_->getRoot(); Q_ASSERT(item); - - return item->rowCount(); + GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item); + int count = group ? group->getDisplayedChildren().size() : 0; + qDebug() << "rowCount = " << count << " where parent.isValid() == " << parent.isValid() << ", group == " << (group ? P2QSTRING(group->getDisplayName()) : "*contact*"); + return count; } } diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h index 998f879..17fdd3e 100644 --- a/Swift/QtUI/Roster/RosterModel.h +++ b/Swift/QtUI/Roster/RosterModel.h @@ -6,30 +6,48 @@ #pragma once -#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" +#include "Swiften/Roster/Roster.h" #include <QAbstractItemModel> #include <QList> namespace Swift { -class RosterModel : public QAbstractItemModel { -Q_OBJECT -public: - RosterModel(); - ~RosterModel(); - void setRoot(QtTreeWidgetItem* tree); - 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(QtTreeWidgetItem* item) const; - QModelIndex parent(const QModelIndex& index) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const; -signals: - void itemExpanded(const QModelIndex& item, bool expanded); -private slots: - void handleItemChanged(QtTreeWidgetItem* item); -private: - QtTreeWidgetItem* tree_; -}; + enum RosterRoles { + StatusTextRole = Qt::UserRole, + AvatarRole = Qt::UserRole + 1, + PresenceIconRole = Qt::UserRole + 2, + StatusShowTypeRole = Qt::UserRole + 3, + ChildCountRole = Qt::UserRole + 4, + }; + class QtTreeWidget; + + class RosterModel : public QAbstractItemModel { + Q_OBJECT + public: + RosterModel(QtTreeWidget* view); + ~RosterModel(); + void setRoster(Roster* swiftRoster); + 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; + private: + void handleDataChanged(RosterItem* item); + void handleChildrenChanged(GroupRosterItem* item); + void handleGroupAdded(GroupRosterItem* group); + RosterItem* getItem(const QModelIndex& index) const; + QColor intToColor(int color) const; + QColor getTextColor(RosterItem* item) const; + QColor getBackgroundColor(RosterItem* item) const; + QString getToolTip(RosterItem* item) const; + QIcon getAvatar(RosterItem* item) const; + QString getStatusText(RosterItem* item) const; + QIcon getPresenceIcon(RosterItem* item) const; + int getChildCount(RosterItem* item) const; + Roster* roster_; + QtTreeWidget* view_; + }; } |