summaryrefslogtreecommitdiffstats
path: root/Swift
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2011-09-21 12:25:27 (GMT)
committerKevin Smith <git@kismith.co.uk>2011-09-23 16:47:57 (GMT)
commitf9c432ca127d6e7d87b49d2fbf6aace34bea0e06 (patch)
treed7f069d3c48cc3d768e770df614fe87ade6f3902 /Swift
parent20d3385909a2f9d886e7e0781357b23474e9f8dc (diff)
downloadswift-contrib-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.zip
swift-contrib-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.tar.bz2
Add support for kicking people from MUCs.
This also introduces a new DOM-like parser structure, used for the MUC parsers. Partially Resolves: #689
Diffstat (limited to 'Swift')
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp18
-rw-r--r--Swift/Controllers/Chat/MUCController.h5
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h9
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h1
-rw-r--r--Swift/QtUI/QtChatWindow.cpp16
-rw-r--r--Swift/QtUI/QtChatWindow.h8
-rw-r--r--Swift/QtUI/QtMainWindow.cpp4
-rw-r--r--Swift/QtUI/Roster/QtOccupantListWidget.cpp53
-rw-r--r--Swift/QtUI/Roster/QtOccupantListWidget.h7
-rw-r--r--Swift/QtUI/Roster/QtRosterWidget.cpp16
-rw-r--r--Swift/QtUI/Roster/QtRosterWidget.h5
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.cpp15
-rw-r--r--Swift/QtUI/Roster/QtTreeWidget.h4
13 files changed, 103 insertions, 58 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index aa0a1e7..19d7b4d 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -17,18 +17,19 @@
#include <Swiften/Base/foreach.h>
#include <SwifTools/TabComplete.h>
#include <Swiften/Base/foreach.h>
#include <Swift/Controllers/XMPPEvents/EventController.h>
#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
#include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h>
#include <Swift/Controllers/UIEvents/UIEventStream.h>
#include <Swift/Controllers/UIEvents/RequestChatUIEvent.h>
#include <Swift/Controllers/Roster/GroupRosterItem.h>
+#include <Swift/Controllers/Roster/ContactRosterItem.h>
#include <Swiften/Avatars/AvatarManager.h>
#include <Swiften/Elements/Delay.h>
#include <Swiften/MUC/MUC.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swift/Controllers/Roster/Roster.h>
#include <Swift/Controllers/Roster/SetAvatar.h>
#include <Swift/Controllers/Roster/SetPresence.h>
#include <Swiften/Disco/EntityCapsProvider.h>
@@ -62,18 +63,20 @@ MUCController::MUCController (
doneGettingHistory_ = false;
events_ = uiEventStream;
roster_ = new Roster(false, true);
completer_ = new TabComplete();
chatWindow_->setRosterModel(roster_);
chatWindow_->setTabComplete(completer_);
chatWindow_->setName(muc->getJID().getNode());
chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
+ chatWindow_->onOccupantSelectionChanged.connect(boost::bind(&MUCController::handleWindowOccupantSelectionChanged, this, _1));
+ chatWindow_->onOccupantActionSelected.connect(boost::bind(&MUCController::handleActionRequestedOnOccupant, this, _1, _2));
muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1));
muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1));
muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1));
muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1));
muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3));
muc_->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3));
if (timerFactory) {
loginCheckTimer_ = boost::shared_ptr<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
@@ -91,18 +94,33 @@ MUCController::~MUCController() {
chatWindow_->setRosterModel(NULL);
delete roster_;
if (loginCheckTimer_) {
loginCheckTimer_->stop();
}
chatWindow_->setTabComplete(NULL);
delete completer_;
}
+void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item) {
+ std::vector<ChatWindow::OccupantAction> actions;
+ //FIXME
+ if (item) {
+ actions.push_back(ChatWindow::Kick);
+ }
+ chatWindow_->setAvailableOccupantActions(actions);
+}
+
+void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction action, ContactRosterItem* item) {
+ switch (action) {
+ case ChatWindow::Kick: muc_->kickUser(item->getJID());break;
+ }
+}
+
void MUCController::handleBareJIDCapsChanged(const JID& /*jid*/) {
ChatWindow::Tristate support = ChatWindow::Yes;
bool any = false;
foreach (const std::string& nick, currentOccupants_) {
DiscoInfo::ref disco = entityCapsProvider_->getCaps(toJID_.toBare().toString() + "/" + nick);
if (disco && disco->hasFeature(DiscoInfo::MessageCorrectionFeature)) {
any = true;
} else {
support = ChatWindow::Maybe;
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 3a79920..39e5fa4 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -13,23 +13,24 @@
#include <set>
#include <string>
#include <Swiften/Network/Timer.h>
#include <Swift/Controllers/Chat/ChatControllerBase.h>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/DiscoInfo.h>
#include <Swiften/JID/JID.h>
#include <Swiften/MUC/MUC.h>
#include <Swiften/Elements/MUCOccupant.h>
+#include <Swift/Controllers/Roster/RosterItem.h>
+#include <Swift/Controllers/UIInterfaces/ChatWindow.h>
namespace Swift {
class StanzaChannel;
class IQRouter;
- class ChatWindow;
class ChatWindowFactory;
class Roster;
class AvatarManager;
class UIEventStream;
class TimerFactory;
class TabComplete;
enum JoinPart {Join, Part, JoinThenPart, PartThenJoin};
@@ -58,18 +59,20 @@ namespace Swift {
bool isIncomingMessageFromMe(boost::shared_ptr<Message> message);
std::string senderDisplayNameFromMessage(const JID& from);
boost::optional<boost::posix_time::ptime> getMessageTimestamp(boost::shared_ptr<Message> message) const;
void preHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
void postHandleIncomingMessage(boost::shared_ptr<MessageEvent>);
private:
void clearPresenceQueue();
void addPresenceMessage(const std::string& message);
+ void handleWindowOccupantSelectionChanged(ContactRosterItem* item);
+ void handleActionRequestedOnOccupant(ChatWindow::OccupantAction, ContactRosterItem* item);
void handleWindowClosed();
void handleAvatarChanged(const JID& jid);
void handleOccupantJoined(const MUCOccupant& occupant);
void handleOccupantLeft(const MUCOccupant& occupant, MUC::LeavingType type, const std::string& reason);
void handleOccupantPresenceChange(boost::shared_ptr<Presence> presence);
void handleOccupantRoleChanged(const std::string& nick, const MUCOccupant& occupant,const MUCOccupant::Role& oldRole);
void handleJoinComplete(const std::string& nick);
void handleJoinFailed(boost::shared_ptr<ErrorPayload> error);
void handleJoinTimeoutTick();
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index e84116d..faef5c8 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -16,23 +16,26 @@
#include <string>
#include "Swiften/Elements/SecurityLabelsCatalog.h"
#include "Swiften/Elements/ChatState.h"
namespace Swift {
class AvatarManager;
class TreeWidget;
class Roster;
class TabComplete;
+ class RosterItem;
+ class ContactRosterItem;
class ChatWindow {
public:
enum AckState {Pending, Received, Failed};
enum Tristate {Yes, No, Maybe};
+ enum OccupantAction {Kick};
ChatWindow() {}
virtual ~ChatWindow() {};
/** Add message to window.
* @return id of added message (for acks).
*/
virtual std::string addMessage(const std::string& message, const std::string& senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const boost::posix_time::ptime& time) = 0;
/** Adds action to window.
* @return id of added message (for acks);
@@ -66,20 +69,26 @@ namespace Swift {
* @param alertText Description of alert (required).
* @param buttonText Button text to use (optional, no button is shown if empty).
*/
virtual void setAlert(const std::string& alertText, const std::string& buttonText = "") = 0;
/**
* Removes an alert.
*/
virtual void cancelAlert() = 0;
+ /**
+ * Actions that can be performed on the selected occupant.
+ */
+ virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) = 0;
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest;
boost::signal<void ()> onSendCorrectionMessageRequest;
boost::signal<void ()> onUserTyping;
boost::signal<void ()> onUserCancelsTyping;
boost::signal<void ()> onAlertButtonClicked;
+ boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged;
+ boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
};
}
#endif
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index 7d6828f..574248f 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -34,18 +34,19 @@ namespace Swift {
virtual void setRosterModel(Roster* /*roster*/) {};
virtual void setTabComplete(TabComplete*) {};
virtual void replaceLastMessage(const std::string&) {};
virtual void replaceMessage(const std::string&, const std::string&, const boost::posix_time::ptime&) {};
void setAckState(const std::string& /*id*/, AckState /*state*/) {};
virtual void flash() {};
virtual void setAlert(const std::string& /*alertText*/, const std::string& /*buttonText*/) {};
virtual void cancelAlert() {};
virtual void setCorrectionEnabled(Tristate /*enabled*/) {}
+ void setAvailableOccupantActions(const std::vector<OccupantAction>& actions) {}
boost::signal<void ()> onClosed;
boost::signal<void ()> onAllMessagesRead;
boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest;
std::string name_;
std::string lastMessageBody_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index a52d2de..a36bc32 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -1,19 +1,21 @@
/*
* Copyright (c) 2010-2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "QtChatWindow.h"
#include "QtSwiftUtil.h"
#include "Swift/Controllers/Roster/Roster.h"
-#include "Roster/QtTreeWidget.h"
+#include "Swift/Controllers/Roster/RosterItem.h"
+#include "Swift/Controllers/Roster/ContactRosterItem.h"
+#include "Roster/QtOccupantListWidget.h"
#include "SwifTools/Linkify.h"
#include "QtChatView.h"
#include "MessageSnippet.h"
#include "SystemMessageSnippet.h"
#include "QtTextEdit.h"
#include "QtSettingsProvider.h"
#include "QtScaledAvatarCache.h"
#include "SwifTools/TabComplete.h"
@@ -64,19 +66,19 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
alertLabel_->setStyleSheet(alertStyleSheet_);
alertWidget_->hide();
logRosterSplitter_ = new QSplitter(this);
logRosterSplitter_->setAutoFillBackground(true);
layout->addWidget(logRosterSplitter_);
messageLog_ = new QtChatView(theme, this);
logRosterSplitter_->addWidget(messageLog_);
- treeWidget_ = new QtTreeWidget(eventStream_);
+ treeWidget_ = new QtOccupantListWidget(eventStream_, this);
treeWidget_->hide();
logRosterSplitter_->addWidget(treeWidget_);
logRosterSplitter_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(logRosterSplitter_, SIGNAL(splitterMoved(int, int)), this, SLOT(handleSplitterMoved(int, int)));
QWidget* midBar = new QWidget(this);
layout->addWidget(midBar);
midBar->setAutoFillBackground(true);
QHBoxLayout *midBarLayout = new QHBoxLayout(midBar);
@@ -109,26 +111,30 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
connect(input_, SIGNAL(textChanged()), this, SLOT(handleInputChanged()));
setFocusProxy(input_);
logRosterSplitter_->setFocusProxy(input_);
midBar->setFocusProxy(input_);
messageLog_->setFocusProxy(input_);
connect(qApp, SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(qAppFocusChanged(QWidget*, QWidget*)));
connect(messageLog_, SIGNAL(gotFocus()), input_, SLOT(setFocus()));
resize(400,300);
connect(messageLog_, SIGNAL(fontResized(int)), this, SIGNAL(fontResized(int)));
-
+ treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QtChatWindow::handleOccupantSelectionChanged, this, _1));
+ treeWidget_->onOccupantActionSelected.connect(boost::bind(boost::ref(onOccupantActionSelected), _1, _2));
}
QtChatWindow::~QtChatWindow() {
}
+void QtChatWindow::handleOccupantSelectionChanged(RosterItem* item) {
+ onOccupantSelectionChanged(dynamic_cast<ContactRosterItem*>(item));
+}
void QtChatWindow::handleFontResized(int fontSizeSteps) {
messageLog_->resizeFont(fontSizeSteps);
}
void QtChatWindow::handleAlertButtonClicked() {
onAlertButtonClicked();
}
@@ -524,10 +530,14 @@ void QtChatWindow::resizeEvent(QResizeEvent*) {
void QtChatWindow::moveEvent(QMoveEvent*) {
emit geometryChanged();
}
void QtChatWindow::replaceLastMessage(const std::string& message) {
messageLog_->replaceLastMessage(P2QSTRING(Linkify::linkify(message)));
}
+void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction>& actions) {
+ treeWidget_->setAvailableOccupantActions(actions);
+}
+
}
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index bc1045d..d38e9c6 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -17,20 +17,19 @@
class QTextEdit;
class QLineEdit;
class QComboBox;
class QLabel;
class QSplitter;
class QPushButton;
namespace Swift {
class QtChatView;
- class QtTreeWidget;
- class QtTreeWidgetFactory;
+ class QtOccupantListWidget;
class QtChatTheme;
class TreeWidget;
class QtTextEdit;
class UIEventStream;
class QtChatWindow : public QtTabbable, public ChatWindow {
Q_OBJECT
public:
QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventStream* eventStream);
~QtChatWindow();
@@ -54,18 +53,19 @@ namespace Swift {
QtTabbable::AlertType getWidgetAlertState();
void setContactChatState(ChatState::ChatStateType state);
void setRosterModel(Roster* roster);
void setTabComplete(TabComplete* completer);
int getCount();
void replaceLastMessage(const std::string& message);
void setAckState(const std::string& id, AckState state);
void flash();
QByteArray getSplitterState();
+ virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions);
public slots:
void handleChangeSplitterState(QByteArray state);
void handleFontResized(int fontSizeSteps);
void setAlert(const std::string& alertText, const std::string& buttonText = "");
void cancelAlert();
void setCorrectionEnabled(Tristate enabled);
signals:
@@ -82,36 +82,36 @@ namespace Swift {
protected:
void showEvent(QShowEvent* event);
private slots:
void returnPressed();
void handleInputChanged();
void handleKeyPressEvent(QKeyEvent* event);
void handleSplitterMoved(int pos, int index);
void handleAlertButtonClicked();
-
private:
void updateTitleWithUnreadCount();
void tabComplete();
void beginCorrection();
void cancelCorrection();
std::string addMessage(const std::string &message, const std::string &senderName, bool senderIsSelf, boost::shared_ptr<SecurityLabel> label, const std::string& avatarPath, const QString& style, const boost::posix_time::ptime& time);
+ void handleOccupantSelectionChanged(RosterItem* item);
int unreadCount_;
bool contactIsTyping_;
LastLineTracker lastLineTracker_;
QString contact_;
QString lastSentMessage_;
QtChatView* messageLog_;
QtChatTheme* theme_;
QtTextEdit* input_;
QComboBox* labelsWidget_;
- QtTreeWidget* treeWidget_;
+ QtOccupantListWidget* treeWidget_;
QLabel* correctingLabel_;
QLabel* alertLabel_;
QWidget* alertWidget_;
QPushButton* alertButton_;
TabComplete* completer_;
std::vector<SecurityLabelsCatalog::Item> availableLabels_;
bool isCorrection_;
bool previousMessageWasSelf_;
bool previousMessageWasSystem_;
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 7c84773..9d35435 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -56,19 +56,19 @@ QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventS
tabs_->setTabPosition(QTabWidget::South);
mainLayout->addWidget(tabs_);
contactsTabWidget_ = new QWidget(this);
contactsTabWidget_->setContentsMargins(0, 0, 0, 0);
QBoxLayout *contactTabLayout = new QBoxLayout(QBoxLayout::TopToBottom, contactsTabWidget_);
contactsTabWidget_->setLayout(contactTabLayout);
contactTabLayout->setSpacing(0);
contactTabLayout->setContentsMargins(0, 0, 0, 0);
- treeWidget_ = new QtRosterWidget(uiEventStream_);
+ treeWidget_ = new QtRosterWidget(uiEventStream_, this);
contactTabLayout->addWidget(treeWidget_);
tabs_->addTab(contactsTabWidget_, tr("&Contacts"));
eventWindow_ = new QtEventWindow(uiEventStream_);
connect(eventWindow_, SIGNAL(onNewEventCountUpdated(int)), this, SLOT(handleEventCountUpdated(int)));
chatListWindow_ = new QtChatListWindow(uiEventStream_);
connect(chatListWindow_, SIGNAL(onCountUpdated(int)), this, SLOT(handleChatCountUpdated(int)));
@@ -109,19 +109,19 @@ QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventS
connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool)));
actionsMenu->addAction(chatUserAction_);
serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this);
actionsMenu->addMenu(serverAdHocMenu_);
actionsMenu->addSeparator();
QAction* signOutAction = new QAction(tr("&Sign Out"), this);
connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction()));
actionsMenu->addAction(signOutAction);
- connect(treeWidget_, SIGNAL(onSomethingSelectedChanged(bool)), editUserAction_, SLOT(setEnabled(bool)));
+ treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QAction::setEnabled, editUserAction_, _1));
setAvailableAdHocCommands(std::vector<DiscoItems::Item>());
QAction* adHocAction = new QAction(tr("Collecting commands..."), this);
adHocAction->setEnabled(false);
serverAdHocMenu_->addAction(adHocAction);
serverAdHocCommandActions_.append(adHocAction);
lastOfflineState_ = false;
uiEventStream_->onUIEvent.connect(boost::bind(&QtMainWindow::handleUIEvent, this, _1));
diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
index 2f992bf..cbda0f1 100644
--- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp
+++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp
@@ -3,57 +3,58 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Roster/QtOccupantListWidget.h"
#include <QContextMenuEvent>
#include <QMenu>
+#include <QAction>
#include <QInputDialog>
#include "Swift/Controllers/Roster/ContactRosterItem.h"
#include "Swift/Controllers/Roster/GroupRosterItem.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "QtSwiftUtil.h"
namespace Swift {
QtOccupantListWidget::QtOccupantListWidget(UIEventStream* eventStream, QWidget* parent) : QtTreeWidget(eventStream, parent) {
}
QtOccupantListWidget::~QtOccupantListWidget() {
}
+void QtOccupantListWidget::setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions) {
+ availableOccupantActions_ = actions;
+}
+
void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) {
-// QModelIndex index = indexAt(event->pos());
-// if (!index.isValid()) {
-// return;
-// }
-// RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
-// QMenu contextMenu;
-// if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
-// QAction* editContact = contextMenu.addAction(tr("Edit"));
-// QAction* removeContact = contextMenu.addAction(tr("Remove"));
-// QAction* result = contextMenu.exec(event->globalPos());
-// if (result == editContact) {
-// eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID()));
-// }
-// else if (result == removeContact) {
-// if (QtContactEditWindow::confirmContactDeletion(contact->getJID())) {
-// eventStream_->send(boost::make_shared<RemoveRosterItemUIEvent>(contact->getJID()));
-// }
-// }
-// }
-// else if (GroupRosterItem* group = dynamic_cast<GroupRosterItem*>(item)) {
-// QAction* renameGroupAction = contextMenu.addAction(tr("Rename"));
-// QAction* result = contextMenu.exec(event->globalPos());
-// if (result == renameGroupAction) {
-// renameGroup(group);
-// }
-// }
+ QModelIndex index = indexAt(event->pos());
+ if (!index.isValid()) {
+ return;
+ }
+ RosterItem* item = static_cast<RosterItem*>(index.internalPointer());
+ ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item);
+ if (contact) {
+ QMenu contextMenu;
+ std::map<QAction*, ChatWindow::OccupantAction> actions;
+ foreach (ChatWindow::OccupantAction availableAction, availableOccupantActions_) {
+ QString text = "Error: missing string";
+ switch (availableAction) {
+ case ChatWindow::Kick: text = tr("Kick user"); break;
+ }
+ QAction* action = contextMenu.addAction(text);
+ actions[action] = availableAction;
+ }
+ QAction* result = contextMenu.exec(event->globalPos());
+ if (result) {
+ onOccupantActionSelected(actions[result], contact);
+ }
+ }
}
}
diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.h b/Swift/QtUI/Roster/QtOccupantListWidget.h
index 5444210..ef29c00 100644
--- a/Swift/QtUI/Roster/QtOccupantListWidget.h
+++ b/Swift/QtUI/Roster/QtOccupantListWidget.h
@@ -2,22 +2,29 @@
* Copyright (c) 2011 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/QtUI/Roster/QtTreeWidget.h"
+#include "Swiften/Base/boost_bsignals.h"
+#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
+
namespace Swift {
class QtOccupantListWidget : public QtTreeWidget {
Q_OBJECT
public:
QtOccupantListWidget(UIEventStream* eventStream, QWidget* parent = 0);
virtual ~QtOccupantListWidget();
+ void setAvailableOccupantActions(const std::vector<ChatWindow::OccupantAction>& actions);
+ boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
protected:
void contextMenuEvent(QContextMenuEvent* event);
+ private:
+ std::vector<ChatWindow::OccupantAction> availableOccupantActions_;
};
}
diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp
index 79d7f67..923f977 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.cpp
+++ b/Swift/QtUI/Roster/QtRosterWidget.cpp
@@ -75,26 +75,10 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
void QtRosterWidget::renameGroup(GroupRosterItem* group) {
bool ok;
QString newName = QInputDialog::getText(NULL, tr("Rename group"), tr("Enter a new name for group '%1':").arg(P2QSTRING(group->getDisplayName())), QLineEdit::Normal, P2QSTRING(group->getDisplayName()), &ok);
if (ok) {
eventStream_->send(boost::make_shared<RenameGroupUIEvent>(group->getDisplayName(), Q2PSTRING(newName)));
}
}
-void QtRosterWidget::currentChanged(const QModelIndex& current, const QModelIndex& previous) {
- bool valid = false;
- QModelIndexList selectedIndexList = getSelectedIndexes();
- if (selectedIndexList.empty() || !selectedIndexList[0].isValid()) {
- /* I didn't quite understand why using current didn't seem to work here.*/
- }
- else if (current.isValid()) {
- RosterItem* item = static_cast<RosterItem*>(current.internalPointer());
- if (dynamic_cast<ContactRosterItem*>(item)) {
- valid = true;
- }
- }
- onSomethingSelectedChanged(valid);
- QTreeView::currentChanged(current, previous);
-}
-
}
diff --git a/Swift/QtUI/Roster/QtRosterWidget.h b/Swift/QtUI/Roster/QtRosterWidget.h
index 7781e07..f870237 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.h
+++ b/Swift/QtUI/Roster/QtRosterWidget.h
@@ -3,28 +3,23 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include "Swift/QtUI/Roster/QtTreeWidget.h"
namespace Swift {
-
class QtRosterWidget : public QtTreeWidget {
Q_OBJECT
public:
QtRosterWidget(UIEventStream* eventStream, QWidget* parent = 0);
virtual ~QtRosterWidget();
public slots:
void handleEditUserActionTriggered(bool checked);
- signals:
- void onSomethingSelectedChanged(bool);
protected:
void contextMenuEvent(QContextMenuEvent* event);
- protected slots:
- virtual void currentChanged(const QModelIndex& current, const QModelIndex& previous);
private:
void renameGroup(GroupRosterItem* group);
};
}
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 7de4028..96a078b 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -75,18 +75,33 @@ QModelIndexList QtTreeWidget::getSelectedIndexes() const {
if (ranges.at(i).left() == 0 && ranges.at(i).right() == right) {
for (int r = ranges.at(i).top(); r <= ranges.at(i).bottom(); ++r) {
selectedIndexList.append(ranges.at(i).model()->index(r, 0, parent));
}
}
}
return selectedIndexList;
}
+void QtTreeWidget::currentChanged(const QModelIndex& current, const QModelIndex& previous) {
+ RosterItem* item = NULL;
+ QModelIndexList selectedIndexList = getSelectedIndexes();
+ if (selectedIndexList.empty() || !selectedIndexList[0].isValid()) {
+ /* I didn't quite understand why using current didn't seem to work here.*/
+ }
+ else if (current.isValid()) {
+ item = static_cast<RosterItem*>(current.internalPointer());
+ item = dynamic_cast<ContactRosterItem*>(item);
+ }
+ onSomethingSelectedChanged(item);
+ QTreeView::currentChanged(current, previous);
+}
+
+
void QtTreeWidget::handleItemActivated(const QModelIndex& index) {
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())));
}
}
void QtTreeWidget::handleExpanded(const QModelIndex& index) {
diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h
index c45a1cd..1ad56d6 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.h
+++ b/Swift/QtUI/Roster/QtTreeWidget.h
@@ -17,31 +17,33 @@ class UIEventStream;
class QtTreeWidget : public QTreeView{
Q_OBJECT
public:
QtTreeWidget(UIEventStream* eventStream, QWidget* parent = 0);
~QtTreeWidget();
void show();
QtTreeWidgetItem* getRoot();
void setRosterModel(Roster* roster);
Roster* getRoster() {return roster_;}
+ boost::signal<void (RosterItem*)> onSomethingSelectedChanged;
private slots:
void handleItemActivated(const QModelIndex&);
void handleModelItemExpanded(const QModelIndex&, bool expanded);
void handleExpanded(const QModelIndex&);
void handleCollapsed(const QModelIndex&);
void handleClicked(const QModelIndex&);
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:
UIEventStream* eventStream_;
private:
RosterModel* model_;
Roster* roster_;
RosterDelegate* delegate_;
QtTreeWidgetItem* treeRoot_;
};