diff options
author | Kevin Smith <git@kismith.co.uk> | 2011-09-21 12:25:27 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2011-09-23 16:47:57 (GMT) |
commit | f9c432ca127d6e7d87b49d2fbf6aace34bea0e06 (patch) | |
tree | d7f069d3c48cc3d768e770df614fe87ade6f3902 /Swift | |
parent | 20d3385909a2f9d886e7e0781357b23474e9f8dc (diff) | |
download | swift-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.cpp | 18 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 5 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 9 | ||||
-rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 1 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 16 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.h | 8 | ||||
-rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 4 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtOccupantListWidget.cpp | 53 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtOccupantListWidget.h | 7 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtRosterWidget.cpp | 16 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtRosterWidget.h | 5 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.cpp | 15 | ||||
-rw-r--r-- | Swift/QtUI/Roster/QtTreeWidget.h | 4 |
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 @@ -23,6 +23,7 @@ #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> @@ -68,6 +69,8 @@ MUCController::MUCController ( 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)); @@ -97,6 +100,21 @@ MUCController::~MUCController() { 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; 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 @@ -19,11 +19,12 @@ #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; @@ -64,6 +65,8 @@ namespace Swift { 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); 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 @@ -22,11 +22,14 @@ namespace Swift { 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() {}; @@ -72,6 +75,10 @@ namespace Swift { */ 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; @@ -79,6 +86,8 @@ namespace Swift { 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 @@ -40,6 +40,7 @@ namespace Swift { 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; 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 @@ -7,7 +7,9 @@ #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" @@ -70,7 +72,7 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt 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); @@ -115,7 +117,8 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt 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)); } @@ -123,6 +126,9 @@ QtChatWindow::~QtChatWindow() { } +void QtChatWindow::handleOccupantSelectionChanged(RosterItem* item) { + onOccupantSelectionChanged(dynamic_cast<ContactRosterItem*>(item)); +} void QtChatWindow::handleFontResized(int fontSizeSteps) { messageLog_->resizeFont(fontSizeSteps); @@ -530,4 +536,8 @@ 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 @@ -23,8 +23,7 @@ class QPushButton; namespace Swift { class QtChatView; - class QtTreeWidget; - class QtTreeWidgetFactory; + class QtOccupantListWidget; class QtChatTheme; class TreeWidget; class QtTextEdit; @@ -60,6 +59,7 @@ namespace Swift { 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); @@ -88,13 +88,13 @@ namespace Swift { 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_; @@ -105,7 +105,7 @@ namespace Swift { QtChatTheme* theme_; QtTextEdit* input_; QComboBox* labelsWidget_; - QtTreeWidget* treeWidget_; + QtOccupantListWidget* treeWidget_; QLabel* correctingLabel_; QLabel* alertLabel_; QWidget* alertWidget_; 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 @@ -62,7 +62,7 @@ QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventS 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")); @@ -115,7 +115,7 @@ QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventS 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); 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 @@ -9,6 +9,7 @@ #include <QContextMenuEvent> #include <QMenu> +#include <QAction> #include <QInputDialog> #include "Swift/Controllers/Roster/ContactRosterItem.h" @@ -26,33 +27,33 @@ 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 @@ -8,6 +8,9 @@ #include "Swift/QtUI/Roster/QtTreeWidget.h" +#include "Swiften/Base/boost_bsignals.h" +#include "Swift/Controllers/UIInterfaces/ChatWindow.h" + namespace Swift { class QtOccupantListWidget : public QtTreeWidget { @@ -15,8 +18,12 @@ class QtOccupantListWidget : public QtTreeWidget { 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 @@ -81,20 +81,4 @@ void QtRosterWidget::renameGroup(GroupRosterItem* group) { } } -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 @@ -9,7 +9,6 @@ #include "Swift/QtUI/Roster/QtTreeWidget.h" namespace Swift { - class QtRosterWidget : public QtTreeWidget { Q_OBJECT public: @@ -17,12 +16,8 @@ class QtRosterWidget : public QtTreeWidget { 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 @@ -81,6 +81,21 @@ QModelIndexList QtTreeWidget::getSelectedIndexes() const { 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); 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 @@ -23,6 +23,7 @@ class QtTreeWidget : public QTreeView{ QtTreeWidgetItem* getRoot(); void setRosterModel(Roster* roster); Roster* getRoster() {return roster_;} + boost::signal<void (RosterItem*)> onSomethingSelectedChanged; private slots: void handleItemActivated(const QModelIndex&); @@ -35,7 +36,8 @@ class QtTreeWidget : public QTreeView{ 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_; |