diff options
author | Kevin Smith <git@kismith.co.uk> | 2009-08-09 07:41:27 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2009-08-09 07:41:27 (GMT) |
commit | 89034baf34d913daae0d53d0468885c603762d8a (patch) | |
tree | 8a94b6119eae3e1f6970ee53f57118fcbd116af5 | |
parent | 6f4fa16b1ddb0633771423a8e8d9520864ffb95d (diff) | |
parent | f948f047401021f3afc8a015991fc81e7d69d6ce (diff) | |
download | swift-89034baf34d913daae0d53d0468885c603762d8a.zip swift-89034baf34d913daae0d53d0468885c603762d8a.tar.bz2 |
Replace dummy roster with Qt Model/View driven one.
Merge branch 'roster'
* roster:
Group expandedness in roster persists between roster changes.
Plumbing in place for roster group expansion. \nDoesn't work.
Conditional includes to get the QtSoundPlayer to compile on Ubuntu.
Roster clicks now open chats again.
Roster now includes avatars.
Resize avatars to 32pix in Roster, change alignments to be relative, do item hiding.
Sort out the alignments in the roster.
Render status text italicised, and selection colours.
Now render an ugly default icon and default status text in the roster.
Use a (boring) delegate for roster rendering.
Clear down some of the cruft from RosterItem.
Removing RosterItem and including in QtTreeWidgetItem.
Removing the dummy title from the roster.
The new roster now renders (badly) the contents.
Begin to assage Swift model into Qt Model/View.
35 files changed, 636 insertions, 142 deletions
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 77e531e..0f654e4 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -109,8 +109,11 @@ void MainController::handleConnected() { delete nickResolver_; nickResolver_ = new NickResolver(xmppRoster); + delete avatarManager_; + avatarManager_ = new AvatarManager(client_, client_, avatarStorage_, this); + delete rosterController_; - rosterController_ = new RosterController(xmppRoster, mainWindowFactory_, treeWidgetFactory_); + rosterController_ = new RosterController(xmppRoster, avatarManager_, mainWindowFactory_, treeWidgetFactory_); rosterController_->onStartChatRequest.connect(boost::bind(&MainController::handleChatRequest, this, _1)); rosterController_->onJoinMUCRequest.connect(boost::bind(&MainController::handleJoinMUCRequest, this, _1, _2)); rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2)); @@ -123,9 +126,6 @@ void MainController::handleConnected() { clientVersionResponder_ = new SoftwareVersionResponder(CLIENT_NAME, CLIENT_VERSION, client_); loginWindow_->morphInto(rosterController_->getWindow()); - delete avatarManager_; - avatarManager_ = new AvatarManager(client_, client_, avatarStorage_, this); - DiscoInfo discoInfo; discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); capsInfo_ = boost::shared_ptr<CapsInfo>(new CapsInfo(CapsInfoGenerator(CLIENT_NODE).generateCapsInfo(discoInfo))); diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp index c447602..3662241 100644 --- a/Swift/Controllers/RosterController.cpp +++ b/Swift/Controllers/RosterController.cpp @@ -9,6 +9,7 @@ #include "Swiften/EventLoop/MainEventLoop.h" #include "Swiften/Roster/Roster.h" #include "Swiften/Roster/SetPresence.h" +#include "Swiften/Roster/SetAvatar.h" #include "Swiften/Roster/OfflineRosterFilter.h" #include "Swiften/Roster/OpenChatRosterAction.h" #include "Swiften/Roster/TreeWidgetFactory.h" @@ -19,9 +20,11 @@ namespace Swift { /** * The controller does not gain ownership of these parameters. */ -RosterController::RosterController(boost::shared_ptr<XMPPRoster> xmppRoster, MainWindowFactory* mainWindowFactory, TreeWidgetFactory* treeWidgetFactory) +RosterController::RosterController(boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, TreeWidgetFactory* treeWidgetFactory) : xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), treeWidgetFactory_(treeWidgetFactory), mainWindow_(mainWindowFactory_->createMainWindow()), roster_(new Roster(mainWindow_->getTreeWidget(), treeWidgetFactory_)), offlineFilter_(new OfflineRosterFilter()) { roster_->addFilter(offlineFilter_); + avatarManager_ = avatarManager; + avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1, _2)); mainWindow_->onStartChatRequest.connect(boost::bind(&RosterController::handleStartChatRequest, this, _1)); mainWindow_->onJoinMUCRequest.connect(boost::bind(&RosterController::handleJoinMUCRequest, this, _1, _2)); mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2)); @@ -72,6 +75,11 @@ void RosterController::handleIncomingPresence(boost::shared_ptr<Presence> presen roster_->applyOnItems(SetPresence(presence)); } +void RosterController::handleAvatarChanged(const JID& jid, const String& hash) { + String path = avatarManager_->getAvatarPath(jid).string(); + roster_->applyOnItems(SetAvatar(jid, path)); +} + void RosterController::handleStartChatRequest(const JID& contact) { onStartChatRequest(contact); } diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h index 945b068..f9f2258 100644 --- a/Swift/Controllers/RosterController.h +++ b/Swift/Controllers/RosterController.h @@ -5,6 +5,7 @@ #include "Swiften/Base/String.h" #include "Swiften/Elements/Presence.h" #include "Swiften/Roster/UserRosterAction.h" +#include "Swiften/Avatars/AvatarManager.h" #include <boost/signals.hpp> #include <boost/shared_ptr.hpp> @@ -20,7 +21,7 @@ namespace Swift { class RosterController { public: - RosterController(boost::shared_ptr<XMPPRoster> xmppRoster, MainWindowFactory *mainWindowFactory, TreeWidgetFactory *treeWidgetFactory); + RosterController(boost::shared_ptr<XMPPRoster> xmppRoster, AvatarManager* avatarManager, MainWindowFactory *mainWindowFactory, TreeWidgetFactory *treeWidgetFactory); ~RosterController(); void showRosterWindow(); MainWindow* getWindow() {return mainWindow_;}; @@ -28,6 +29,7 @@ namespace Swift { boost::signal<void (const JID&, const String&)> onJoinMUCRequest; boost::signal<void (StatusShow::Type, const String&)> onChangeStatusRequest; void handleIncomingPresence(boost::shared_ptr<Presence> presence); + void handleAvatarChanged(const JID& jid, const String& hash); private: void handleOnJIDAdded(const JID &jid); @@ -42,6 +44,7 @@ namespace Swift { MainWindow* mainWindow_; Roster* roster_; OfflineRosterFilter* offlineFilter_; + AvatarManager* avatarManager_; }; } #endif diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 6328156..2e08adb 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -1,7 +1,7 @@ #include "QtChatWindow.h" #include "QtSwiftUtil.h" -#include "QtTreeWidget.h" -#include "QtTreeWidgetFactory.h" +#include "Roster/QtTreeWidget.h" +#include "Roster/QtTreeWidgetFactory.h" #include "QtChatView.h" #include "MessageSnippet.h" #include "SystemMessageSnippet.h" diff --git a/Swift/QtUI/QtChatWindowFactory.cpp b/Swift/QtUI/QtChatWindowFactory.cpp index 927447c..47c943f 100644 --- a/Swift/QtUI/QtChatWindowFactory.cpp +++ b/Swift/QtUI/QtChatWindowFactory.cpp @@ -3,7 +3,7 @@ #include "QtChatTabs.h" #include "QtChatWindow.h" #include "QtSwiftUtil.h" -#include "QtTreeWidgetFactory.h" +#include "Roster/QtTreeWidgetFactory.h" namespace Swift { diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index a9ffc51..fffd478 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -2,8 +2,8 @@ #include "QtJoinMUCDialog.h" #include "QtSwiftUtil.h" -#include "QtTreeWidgetFactory.h" -#include "QtTreeWidget.h" +#include "Roster/QtTreeWidgetFactory.h" +#include "Roster/QtTreeWidget.h" #include "QtStatusWidget.h" #include <QBoxLayout> diff --git a/Swift/QtUI/QtMainWindowFactory.cpp b/Swift/QtUI/QtMainWindowFactory.cpp index 288d182..9594ade 100644 --- a/Swift/QtUI/QtMainWindowFactory.cpp +++ b/Swift/QtUI/QtMainWindowFactory.cpp @@ -1,6 +1,6 @@ #include "QtMainWindowFactory.h" #include "QtMainWindow.h" -#include "QtTreeWidgetFactory.h" +#include "Roster/QtTreeWidgetFactory.h" namespace Swift { diff --git a/Swift/QtUI/QtSoundPlayer.cpp b/Swift/QtUI/QtSoundPlayer.cpp index 5dd3db3..4aa6b8e 100644 --- a/Swift/QtUI/QtSoundPlayer.cpp +++ b/Swift/QtUI/QtSoundPlayer.cpp @@ -1,8 +1,12 @@ #include "QtSoundPlayer.h" +#ifdef Q_WS_X11 +#include "mediaobject.h" +#include "audiooutput.h" +#else #include <phonon/MediaObject> #include <phonon/AudioOutput> - +#endif namespace Swift{ @@ -33,4 +37,4 @@ void QtSoundPlayer::handleFinished() { messageReceived_->stop(); } -}
\ No newline at end of file +} diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index e1fac9c..00efc17 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -3,7 +3,7 @@ #include "QtLoginWindowFactory.h" #include "QtChatWindowFactory.h" #include "QtMainWindowFactory.h" -#include "QtTreeWidgetFactory.h" +#include "Roster/QtTreeWidgetFactory.h" #include "QtSystemTray.h" #include "QtSoundPlayer.h" diff --git a/Swift/QtUI/QtTreeWidget.cpp b/Swift/QtUI/QtTreeWidget.cpp deleted file mode 100644 index 66c653e..0000000 --- a/Swift/QtUI/QtTreeWidget.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "QtTreeWidget.h" - -#include "Swiften/Base/Platform.h" -#include "Swiften/Roster/OpenChatRosterAction.h" - -namespace Swift { - -QtTreeWidget::QtTreeWidget(QWidget* parent) : QTreeWidget(parent) { - setHeaderHidden(true); -#ifdef SWIFT_PLATFORM_MACOSX - setAlternatingRowColors(true); -#endif - setAnimated(true); - setIndentation(0); - setRootIsDecorated(true); - connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(handleItemActivated(QTreeWidgetItem*, int))); -} - -void QtTreeWidget::handleItemActivated(QTreeWidgetItem* item, int column) { - QtTreeWidgetItem* qtItem = dynamic_cast<QtTreeWidgetItem*>(item); - if (qtItem) { - qtItem->performUserAction(boost::shared_ptr<UserRosterAction>(new OpenChatRosterAction())); - } -} - -void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const { -} - -} diff --git a/Swift/QtUI/QtTreeWidget.h b/Swift/QtUI/QtTreeWidget.h deleted file mode 100644 index e1d83de..0000000 --- a/Swift/QtUI/QtTreeWidget.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SWIFT_QtTreeWidget_H -#define SWIFT_QtTreeWidget_H - -#include <QTreeWidget> - -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidget.h" - -namespace Swift { - -class QtTreeWidget : public QTreeWidget, public TreeWidget { - Q_OBJECT - public: - QtTreeWidget(QWidget* parent = 0); - - private slots: - void handleItemActivated(QTreeWidgetItem*, int); - - private: - void drawBranches(QPainter*, const QRect&, const QModelIndex&) const; -}; - -} -#endif - diff --git a/Swift/QtUI/QtTreeWidgetItem.cpp b/Swift/QtUI/QtTreeWidgetItem.cpp deleted file mode 100644 index e69de29..0000000 --- a/Swift/QtUI/QtTreeWidgetItem.cpp +++ /dev/null diff --git a/Swift/QtUI/QtTreeWidgetItem.h b/Swift/QtUI/QtTreeWidgetItem.h deleted file mode 100644 index 34ad93c..0000000 --- a/Swift/QtUI/QtTreeWidgetItem.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef SWIFT_QtTreeWidgetItem_H -#define SWIFT_QtTreeWidgetItem_H - -#include <QColor> - -#include "Swiften/Base/String.h" -#include "Swiften/Roster/TreeWidgetFactory.h" -#include "Swiften/Roster/TreeWidget.h" -#include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidget.h" -#include "Swift/QtUI/QtSwiftUtil.h" - -namespace Swift { - -class QtTreeWidgetItem : public QTreeWidgetItem, public TreeWidgetItem { - public: - QtTreeWidgetItem(QTreeWidget* parent) : QTreeWidgetItem(parent) { - } - - QtTreeWidgetItem(QTreeWidgetItem* parent) : QTreeWidgetItem(parent) { - } - - void setText(const String& text) { - QTreeWidgetItem::setText(0, P2QSTRING(text)); - } - - void setTextColor(unsigned long color) { - QTreeWidgetItem::setTextColor(0, QColor( - ((color & 0xFF0000)>>16), - ((color & 0xFF00)>>8), - (color & 0xFF))); - } - - void setBackgroundColor(unsigned long color) { - QTreeWidgetItem::setBackgroundColor(0, QColor( - ((color & 0xFF0000)>>16), - ((color & 0xFF00)>>8), - (color & 0xFF))); - } - - void setExpanded(bool b) { - treeWidget()->setItemExpanded(this, b); - } - - void hide() { - setHidden(true); - } - - void show() { - setHidden(false); - } -}; - -} -#endif - diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp new file mode 100644 index 0000000..18b28d2 --- /dev/null +++ b/Swift/QtUI/Roster/QtTreeWidget.cpp @@ -0,0 +1,53 @@ +#include "Roster/QtTreeWidget.h" + +#include "Swiften/Base/Platform.h" +#include "Swiften/Roster/OpenChatRosterAction.h" + +namespace Swift { + +QtTreeWidget::QtTreeWidget(QWidget* parent) : QTreeView(parent) { + treeRoot_ = new QtTreeWidgetItem(NULL); + model_ = new RosterModel(); + model_->setRoot(treeRoot_); + setModel(model_); + delegate_ = new RosterDelegate(); + setItemDelegate(delegate_); + setHeaderHidden(true); +#ifdef SWIFT_PLATFORM_MACOSX + setAlternatingRowColors(true); +#endif + 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(handleItemExpanded(const QModelIndex&, bool))); +} + +QtTreeWidget::~QtTreeWidget() { + delete model_; + delete delegate_; +} + +QtTreeWidgetItem* QtTreeWidget::getRoot() { + return treeRoot_; +} + +void QtTreeWidget::handleItemActivated(const QModelIndex& index) { + QtTreeWidgetItem* qtItem = static_cast<QtTreeWidgetItem*>(index.internalPointer()); + if (qtItem) { + qtItem->performUserAction(boost::shared_ptr<UserRosterAction>(new OpenChatRosterAction())); + } +} + +void QtTreeWidget::handleItemExpanded(const QModelIndex& index, bool expanded) { + setExpanded(index, expanded); +} + +void QtTreeWidget::drawBranches(QPainter*, const QRect&, const QModelIndex&) const { +} + +void QtTreeWidget::show() { + QWidget::show(); +} + +} diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h new file mode 100644 index 0000000..8c76d60 --- /dev/null +++ b/Swift/QtUI/Roster/QtTreeWidget.h @@ -0,0 +1,36 @@ +#ifndef SWIFT_QtTreeWidget_H +#define SWIFT_QtTreeWidget_H + +#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" + +namespace Swift { + +class QtTreeWidget : public QTreeView, public TreeWidget { + Q_OBJECT + public: + QtTreeWidget(QWidget* parent = 0); + ~QtTreeWidget(); + void show(); + QtTreeWidgetItem* getRoot(); + private slots: + void handleItemActivated(const QModelIndex&); + void handleItemExpanded(const QModelIndex&, bool expanded); + private: + void drawBranches(QPainter*, const QRect&, const QModelIndex&) const; + RosterModel* model_; + RosterDelegate* delegate_; + QtTreeWidgetItem* treeRoot_; + +}; + +} +#endif + diff --git a/Swift/QtUI/QtTreeWidgetFactory.cpp b/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp index e69de29..e69de29 100644 --- a/Swift/QtUI/QtTreeWidgetFactory.cpp +++ b/Swift/QtUI/Roster/QtTreeWidgetFactory.cpp diff --git a/Swift/QtUI/QtTreeWidgetFactory.h b/Swift/QtUI/Roster/QtTreeWidgetFactory.h index e0140d2..db20044 100644 --- a/Swift/QtUI/QtTreeWidgetFactory.h +++ b/Swift/QtUI/Roster/QtTreeWidgetFactory.h @@ -4,8 +4,8 @@ #include "Swiften/Roster/TreeWidgetFactory.h" #include "Swiften/Roster/TreeWidget.h" #include "Swiften/Roster/TreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidgetItem.h" -#include "Swift/QtUI/QtTreeWidget.h" +#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" +#include "Swift/QtUI/Roster/QtTreeWidget.h" namespace Swift { @@ -21,13 +21,20 @@ class QtTreeWidgetFactory : public TreeWidgetFactory { TreeWidgetItem* createTreeWidgetItem(TreeWidgetItem* item) { QtTreeWidgetItem* qtItem = dynamic_cast<QtTreeWidgetItem*>(item); assert(qtItem); - return new QtTreeWidgetItem(qtItem); + QtTreeWidgetItem* newItem = new QtTreeWidgetItem(qtItem); + qtItem->addChild(newItem); + return newItem; } TreeWidgetItem* createTreeWidgetItem(TreeWidget* item) { - QtTreeWidget* qtItem = dynamic_cast<QtTreeWidget*>(item); - assert(qtItem); - return new QtTreeWidgetItem(qtItem); + 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; } }; diff --git a/Swift/QtUI/Roster/QtTreeWidgetItem.cpp b/Swift/QtUI/Roster/QtTreeWidgetItem.cpp new file mode 100644 index 0000000..1b77b26 --- /dev/null +++ b/Swift/QtUI/Roster/QtTreeWidgetItem.cpp @@ -0,0 +1,136 @@ +#include "Swift/QtUI/Roster/QtTreeWidgetItem.h" +#include "Swift/QtUI/Roster/QtTreeWidget.h" + +#include <qdebug.h> + +namespace Swift { + +QtTreeWidgetItem::QtTreeWidgetItem(QtTreeWidgetItem* parentItem) : QObject(), textColor_(0,0,0), backgroundColor_(255,255,255) { + parent_ = parentItem; + shown_ = true; + expanded_ = true; +} + +void QtTreeWidgetItem::setText(const String& text) { + displayName_ = P2QSTRING(text); +} + +void QtTreeWidgetItem::setStatusText(const String& text) { + statusText_ = P2QSTRING(text); +} + +void QtTreeWidgetItem::setAvatarPath(const String& path) { + qDebug() << "Setting avatar to " << P2QSTRING(path); + avatar_ = QIcon(P2QSTRING(path)); +} + +void QtTreeWidgetItem::setTextColor(unsigned long color) { + textColor_ = QColor( + ((color & 0xFF0000)>>16), + ((color & 0xFF00)>>8), + (color & 0xFF)); +} + +void QtTreeWidgetItem::setBackgroundColor(unsigned long color) { + backgroundColor_ = QColor( + ((color & 0xFF0000)>>16), + ((color & 0xFF00)>>8), + (color & 0xFF)); +} + +void QtTreeWidgetItem::setExpanded(bool b) { + expanded_ = true; + emit changed(this); +} + +void QtTreeWidgetItem::hide() { + shown_ = false; + emit changed(this); +} + +void QtTreeWidgetItem::show() { + shown_ = true; + emit changed(this); +} + +bool QtTreeWidgetItem::isShown() { + return isContact() ? shown_ : shownChildren_.size() > 0; +} + +QWidget* QtTreeWidgetItem::getCollapsedRosterWidget() { + QWidget* widget = new QWidget(); + + return widget; +} + +QWidget* QtTreeWidgetItem::getExpandedRosterWidget() { + QWidget* widget = new QWidget(); + + return widget; +} + +QtTreeWidgetItem::~QtTreeWidgetItem() { + qDeleteAll(children_); +} + +QtTreeWidgetItem* QtTreeWidgetItem::getParentItem() { + return parent_; +} + +void QtTreeWidgetItem::addChild(QtTreeWidgetItem* child) { + children_.append(child); + connect(child, SIGNAL(changed(QtTreeWidgetItem*)), this, SLOT(handleChanged(QtTreeWidgetItem*))); + handleChanged(child); +} + +void QtTreeWidgetItem::handleChanged(QtTreeWidgetItem* child) { + shownChildren_.clear(); + for (int i = 0; i < children_.size(); i++) { + if (children_[i]->isShown()) { + shownChildren_.append(children_[i]); + } + } + emit changed(child); +} + +int QtTreeWidgetItem::rowCount() { + //qDebug() << "Returning size of " << children_.size() << " for item " << displayName_; + return shownChildren_.size(); +} + +int QtTreeWidgetItem::rowOf(QtTreeWidgetItem* item) { + return shownChildren_.indexOf(item); +} + +int QtTreeWidgetItem::row() { + return parent_ ? parent_->rowOf(this) : 0; +} + +QtTreeWidgetItem* QtTreeWidgetItem::getItem(int row) { + //qDebug() << "Returning row " << row << " from item " << displayName_; + Q_ASSERT(row >= 0); + Q_ASSERT(row < rowCount()); + return shownChildren_[row]; +} + + +QVariant QtTreeWidgetItem::data(int role) { + switch (role) { + case Qt::DisplayRole: return displayName_; + case Qt::TextColorRole: return textColor_; + case Qt::BackgroundColorRole: return backgroundColor_; + case StatusTextRole: return statusText_; + case AvatarRole: return avatar_; + default: return QVariant(); + } +} + +bool QtTreeWidgetItem::isContact() { + return children_.size() == 0; +} + +bool QtTreeWidgetItem::isExpanded() { + return expanded_; +} + +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/QtTreeWidgetItem.h b/Swift/QtUI/Roster/QtTreeWidgetItem.h new file mode 100644 index 0000000..73da92f --- /dev/null +++ b/Swift/QtUI/Roster/QtTreeWidgetItem.h @@ -0,0 +1,70 @@ +#ifndef SWIFT_QtTreeWidgetItem_H +#define SWIFT_QtTreeWidgetItem_H + +#include <QColor> +#include <QVariant> + +#include "Swiften/Base/String.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/QtSwiftUtil.h" + + +namespace Swift { + enum RosterRoles { + StatusTextRole = Qt::UserRole, + AvatarRole = Qt::UserRole + 1 + }; + +class QtTreeWidget; +class QtTreeWidgetItem : public QObject, public TreeWidgetItem { + Q_OBJECT + public: + ~QtTreeWidgetItem(); + void addChild(QtTreeWidgetItem* child); + QtTreeWidgetItem* getParentItem(); + int rowCount(); + int rowOf(QtTreeWidgetItem* item); + int row(); + QtTreeWidgetItem* getItem(int row); + QVariant data(int role); + QtTreeWidgetItem(QtTreeWidgetItem* parentItem); + void setText(const String& text); + void setAvatarPath(const String& path); + void setStatusText(const String& text); + void setTextColor(unsigned long color); + void setBackgroundColor(unsigned long color); + void setExpanded(bool b); + void hide(); + void show(); + bool isShown(); + bool isContact(); + bool isExpanded(); + + QWidget* getCollapsedRosterWidget(); + QWidget* getExpandedRosterWidget(); + + signals: + void changed(QtTreeWidgetItem*); + private slots: + void handleChanged(QtTreeWidgetItem* item); + private: + QList<QtTreeWidgetItem*> children_; + QList<QtTreeWidgetItem*> shownChildren_; + QtTreeWidgetItem* parent_; + QString displayName_; + QString statusText_; + QColor textColor_; + QColor backgroundColor_; + QVariant avatar_; + bool shown_; + bool expanded_; +}; + +} +#endif + diff --git a/Swift/QtUI/Roster/Roster.pri b/Swift/QtUI/Roster/Roster.pri new file mode 100644 index 0000000..bc14889 --- /dev/null +++ b/Swift/QtUI/Roster/Roster.pri @@ -0,0 +1,12 @@ +SOURCES += $$PWD/RosterDelegate.cpp \ +# $$PWD/RosterItem.cpp \ + $$PWD/RosterModel.cpp \ + $$PWD/QtTreeWidget.cpp \ + $$PWD/QtTreeWidgetItem.cpp + +HEADERS += $$PWD/RosterDelegate.h \ +# $$PWD/RosterItem.h \ + $$PWD/RosterModel.h \ + $$PWD/QtTreeWidget.h \ + $$PWD/QtTreeWidgetFactory.h \ + $$PWD/QtTreeWidgetItem.h diff --git a/Swift/QtUI/Roster/Roster.pro b/Swift/QtUI/Roster/Roster.pro new file mode 100644 index 0000000..be0cff3 --- /dev/null +++ b/Swift/QtUI/Roster/Roster.pro @@ -0,0 +1,18 @@ +include(Roster.pri) +SOURCES += main.cpp + +DEPENDPATH += ../. ../../.. ../../../3rdParty/Boost +INCLUDEPATH += ../. ../../.. ../../../3rdParty/Boost + +DEFINES += BOOST_SIGNALS_NAMESPACE=bsignals BOOST_ALL_NO_LIB + +exists(../config.pri) { + LIBS += ../../Controllers/Controllers.a ../../../Swiften/Swiften.a + include(../config.pri) +} + +mac { + DEFINES += SWIFT_PLATFORM_MACOSX +} + +RESOURCES += ../Swift.qrc
\ No newline at end of file diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp new file mode 100644 index 0000000..b05bbb1 --- /dev/null +++ b/Swift/QtUI/Roster/RosterDelegate.cpp @@ -0,0 +1,67 @@ +#include "RosterDelegate.h" + +#include <QPainter> +#include <QColor> +#include <QBrush> +#include <QFontMetrics> +#include <qdebug.h> + +#include "QtTreeWidgetItem.h" + +namespace Swift { +QSize RosterDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index ) const { + QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); + if (item && !item->isContact()) { + return QStyledItemDelegate::sizeHint(option, index); + } + //Doesn't work, yay! FIXME: why? + QSize size = (option.state & QStyle::State_Selected) ? QSize(150, 80) : QSize(150, avatarSize_ + margin_ * 2); + //qDebug() << "Returning size" << size; + return size; +} + +void RosterDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { + QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); + if (item && !item->isContact()) { + QStyledItemDelegate::paint(painter, option, index); + return; + } + //qDebug() << "painting" << index.data(Qt::DisplayRole).toString(); + painter->save(); + //QStyledItemDelegate::paint(painter, option, index); + //initStyleOption(option, index); + QRect fullRegion(option.rect); + if ( option.state & QStyle::State_Selected ) { + painter->fillRect(fullRegion, option.palette.highlight()); + painter->setPen(option.palette.highlightedText().color()); + } + QRect avatarRegion(QPoint(margin_, fullRegion.top() + margin_), QSize(avatarSize_, avatarSize_)); + QIcon icon = index.data(AvatarRole).isValid() && !index.data(AvatarRole).value<QIcon>().isNull() + ? index.data(AvatarRole).value<QIcon>() + : QIcon(":/icons/avatar.png"); + icon.paint(painter, avatarRegion, Qt::AlignVCenter | Qt::AlignHCenter); + + QFont nameFont = painter->font(); + QFont statusFont = painter->font(); + + painter->setFont(nameFont); + QRect textRegion(fullRegion.adjusted(avatarSize_ + margin_ * 2, 0, 0, 0)); + + QFontMetrics nameMetrics(nameFont); + int nameHeight = nameMetrics.height() + margin_; + QRect nameRegion(textRegion.adjusted(0, margin_, 0, 0)); + QColor nameColor = index.data(Qt::TextColorRole).value<QColor>(); + painter->setPen(QPen(nameColor)); + painter->drawText(nameRegion, Qt::AlignTop, index.data(Qt::DisplayRole).toString()); + + statusFont.setStyle(QFont::StyleItalic); + statusFont.setPointSize(10); + painter->setFont(statusFont); + painter->setPen(QPen(QColor(160,160,160))); + QRect statusTextRegion(textRegion.adjusted(0, nameHeight, 0, 0)); + painter->drawText(statusTextRegion, Qt::AlignTop, index.data(StatusTextRole).toString()); + + painter->restore(); +} + +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/RosterDelegate.h b/Swift/QtUI/Roster/RosterDelegate.h new file mode 100644 index 0000000..4a4ad6b --- /dev/null +++ b/Swift/QtUI/Roster/RosterDelegate.h @@ -0,0 +1,14 @@ +#pragma once + +#import <QStyledItemDelegate> + +namespace Swift { + class RosterDelegate : public QStyledItemDelegate { + public: + QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + private: + static const int avatarSize_ = 32; + static const int margin_ = 4; + }; +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp new file mode 100644 index 0000000..1df2117 --- /dev/null +++ b/Swift/QtUI/Roster/RosterModel.cpp @@ -0,0 +1,71 @@ +#include "RosterModel.h" + +namespace Swift { + +RosterModel::RosterModel() { +} + +RosterModel::~RosterModel() { + delete tree_; +} + +void RosterModel::setRoot(QtTreeWidgetItem* root) { + tree_ = root; + connect(tree_, SIGNAL(changed(QtTreeWidgetItem*)), this, SLOT(handleItemChanged(QtTreeWidgetItem*))); +} + + +void RosterModel::handleItemChanged(QtTreeWidgetItem* item) { + if (!item->isShown()) { + return; + } + Q_ASSERT(item); + QModelIndex modelIndex = index(item); + Q_ASSERT(modelIndex.isValid()); + emit itemExpanded(modelIndex, item->isExpanded()); + emit dataChanged(modelIndex, modelIndex); + emit layoutChanged(); +} + +int RosterModel::columnCount(const QModelIndex& parent) const { + Q_UNUSED(parent); + return 1; +} + +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(); +} + +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(); +} + +QModelIndex RosterModel::index(QtTreeWidgetItem* item) const { + return createIndex(item->row(), 0, item); +} + +QModelIndex RosterModel::parent(const QModelIndex& index) const { + if (!index.isValid()) { + return QModelIndex(); + } + + QtTreeWidgetItem* item = static_cast<QtTreeWidgetItem*>(index.internalPointer()); + Q_ASSERT(item); + + QtTreeWidgetItem* parentItem = item->getParentItem(); + return parentItem == tree_ ? QModelIndex() : createIndex(parentItem->row(), 0, parentItem); + +} + +int RosterModel::rowCount(const QModelIndex& parent) const { + QtTreeWidgetItem* item = parent.isValid() ? static_cast<QtTreeWidgetItem*>(parent.internalPointer()) : tree_; + Q_ASSERT(item); + + return item->rowCount(); +} + +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h new file mode 100644 index 0000000..fc9b1f3 --- /dev/null +++ b/Swift/QtUI/Roster/RosterModel.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Swift/QtUI/Roster/QtTreeWidgetItem.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_; +}; + +}
\ No newline at end of file diff --git a/Swift/QtUI/Roster/main.cpp b/Swift/QtUI/Roster/main.cpp new file mode 100644 index 0000000..660dce9 --- /dev/null +++ b/Swift/QtUI/Roster/main.cpp @@ -0,0 +1,35 @@ +#include <QtGui> +#include "QtTreeWidget.h" +#include "QtTreeWidgetFactory.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + //Swift::RosterModel model; + + //QTreeView view; + //view.setModel(&model); + //view.setWindowTitle("A roster"); + //view.show(); + + Swift::QtTreeWidgetFactory treeWidgetFactory; + Swift::QtTreeWidget* tree = dynamic_cast<Swift::QtTreeWidget*>(treeWidgetFactory.createTreeWidget()); + tree->show(); + for (int i = 0; i < 500; i++) { + Swift::QtTreeWidgetItem* group = dynamic_cast<Swift::QtTreeWidgetItem*>(treeWidgetFactory.createTreeWidgetItem(tree)); + group->setText("People"); + group->setBackgroundColor(0xBBBBBB); + Swift::QtTreeWidgetItem* item1 = dynamic_cast<Swift::QtTreeWidgetItem*>(treeWidgetFactory.createTreeWidgetItem(group)); + Swift::QtTreeWidgetItem* item2 = dynamic_cast<Swift::QtTreeWidgetItem*>(treeWidgetFactory.createTreeWidgetItem(group)); + Swift::QtTreeWidgetItem* item3 = dynamic_cast<Swift::QtTreeWidgetItem*>(treeWidgetFactory.createTreeWidgetItem(group)); + Swift::QtTreeWidgetItem* item4 = dynamic_cast<Swift::QtTreeWidgetItem*>(treeWidgetFactory.createTreeWidgetItem(group)); + item1->setText("Remko"); + item2->setText("Kevin"); + item3->setText("Cath"); + item4->setText("KimTypo"); + item4->setText("Kim"); + } + + return app.exec(); +}
\ No newline at end of file diff --git a/Swift/QtUI/Swift.pro b/Swift/QtUI/Swift.pro index 0af8216..7c36c07 100644 --- a/Swift/QtUI/Swift.pro +++ b/Swift/QtUI/Swift.pro @@ -55,9 +55,6 @@ HEADERS += \ QtSettingsProvider.h \ QtStatusWidget.h \ QtSwift.h \ - QtTreeWidget.h \ - QtTreeWidgetFactory.h \ - QtTreeWidgetItem.h \ QtChatView.h \ QtChatTabs.h \ QtSoundPlayer.h \ @@ -79,7 +76,6 @@ SOURCES += \ QtSettingsProvider.cpp \ QtStatusWidget.cpp \ QtSwift.cpp \ - QtTreeWidget.cpp \ QtChatView.cpp \ QtChatTabs.cpp \ QtSoundPlayer.cpp \ @@ -91,6 +87,8 @@ SOURCES += \ FORMS += QtJoinMUCDialog.ui +include(Roster/Roster.pri) + RESOURCES += Swift.qrc DefaultTheme.qrc win32 { diff --git a/Swift/resources/icons/avatar.png b/Swift/resources/icons/avatar.png Binary files differindex 00374a6..4b932b0 100644 --- a/Swift/resources/icons/avatar.png +++ b/Swift/resources/icons/avatar.png diff --git a/Swiften/Avatars/AvatarManager.h b/Swiften/Avatars/AvatarManager.h index 984ce19..3ac4433 100644 --- a/Swiften/Avatars/AvatarManager.h +++ b/Swiften/Avatars/AvatarManager.h @@ -32,7 +32,7 @@ namespace Swift { void handlePresenceReceived(boost::shared_ptr<Presence>); void handleVCardReceived(const JID& from, const String& hash, boost::shared_ptr<VCard>, const boost::optional<Error>&); void setAvatarHash(const JID& from, const String& hash); - JID getAvatarJID(const JID& o) const; + JID getAvatarJID(const JID& o) const; private: StanzaChannel* stanzaChannel_; diff --git a/Swiften/Roster/ContactRosterItem.cpp b/Swiften/Roster/ContactRosterItem.cpp index f38b0f7..2f2f787 100644 --- a/Swiften/Roster/ContactRosterItem.cpp +++ b/Swiften/Roster/ContactRosterItem.cpp @@ -34,6 +34,14 @@ void ContactRosterItem::setStatusShow(StatusShow::Type show) { widget_->setTextColor(colour); } +void ContactRosterItem::setStatusText(const String& status) { + widget_->setStatusText(status); +} + +void ContactRosterItem::setAvatarPath(const String& path) { + widget_->setAvatarPath(path); +} + const JID& ContactRosterItem::getJID() const { return jid_; } diff --git a/Swiften/Roster/ContactRosterItem.h b/Swiften/Roster/ContactRosterItem.h index 20f9f65..f1810aa 100644 --- a/Swiften/Roster/ContactRosterItem.h +++ b/Swiften/Roster/ContactRosterItem.h @@ -23,6 +23,8 @@ class ContactRosterItem : public RosterItem { StatusShow::Type getStatusShow(); void setStatusShow(StatusShow::Type show); + void setStatusText(const String& status); + void setAvatarPath(const String& path); const JID& getJID() const; void show(); void hide(); diff --git a/Swiften/Roster/Roster.cpp b/Swiften/Roster/Roster.cpp index 61c0286..b51d8eb 100644 --- a/Swiften/Roster/Roster.cpp +++ b/Swiften/Roster/Roster.cpp @@ -39,7 +39,7 @@ GroupRosterItem* Roster::getGroup(const String& groupName) { } GroupRosterItem* group = new GroupRosterItem(groupName, treeWidget_, widgetFactory_); children_.push_back(group); - items_.push_back(group); + items_.push_back(group); return group; } @@ -49,7 +49,7 @@ void Roster::handleUserAction(boost::shared_ptr<UserRosterAction> action) { void Roster::addContact(const JID& jid, const String& name, const String& group) { ContactRosterItem *item = new ContactRosterItem(jid, name, getGroup(group), widgetFactory_); - items_.push_back(item); + items_.push_back(item); item->onUserAction.connect(boost::bind(&Roster::handleUserAction, this, _1)); filterItem(item); diff --git a/Swiften/Roster/SetAvatar.h b/Swiften/Roster/SetAvatar.h new file mode 100644 index 0000000..7bc9c37 --- /dev/null +++ b/Swiften/Roster/SetAvatar.h @@ -0,0 +1,33 @@ +#ifndef SWIFTEN_SetAvatar_H +#define SWIFTEN_SetAvatar_H + +#include "Swiften/Elements/Presence.h" +#include "Swiften/JID/JID.h" +#include "Swiften/Roster/RosterItemOperation.h" +#include "Swiften/Roster/ContactRosterItem.h" + +namespace Swift { + +class RosterItem; + +class SetAvatar : public RosterItemOperation { + public: + SetAvatar(const JID& jid, const String& path, JID::CompareType compareType = JID::WithoutResource) : jid_(jid), path_(path), compareType_(compareType) { + } + + virtual void operator() (RosterItem* item) const { + ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); + if (contact && contact->getJID().equals(jid_, compareType_)) { + contact->setAvatarPath(path_); + } + } + + private: + JID jid_; + String path_; + JID::CompareType compareType_; +}; + +} +#endif + diff --git a/Swiften/Roster/SetPresence.h b/Swiften/Roster/SetPresence.h index aa36a52..a18ae6d 100644 --- a/Swiften/Roster/SetPresence.h +++ b/Swiften/Roster/SetPresence.h @@ -20,8 +20,10 @@ class SetPresence : public RosterItemOperation { if (contact && contact->getJID().equals(presence_->getFrom(), compareType_)) { if (presence_->getType() != Presence::Available) { contact->setStatusShow(StatusShow::None); + contact->setStatusText(presence_->getStatus()); } else { contact->setStatusShow(presence_->getShow()); + contact->setStatusText(presence_->getStatus()); } } } diff --git a/Swiften/Roster/TreeWidgetItem.h b/Swiften/Roster/TreeWidgetItem.h index 5a96a41..4e20050 100644 --- a/Swiften/Roster/TreeWidgetItem.h +++ b/Swiften/Roster/TreeWidgetItem.h @@ -13,6 +13,8 @@ class TreeWidgetItem { public: virtual ~TreeWidgetItem() {} virtual void setText(const String& text) = 0; + virtual void setStatusText(const String& text) = 0; + virtual void setAvatarPath(const String& path) = 0; virtual void setExpanded(bool b) = 0; virtual void setTextColor(unsigned long color) = 0; virtual void setBackgroundColor(unsigned long color) = 0; |