From b2f58c4f3eb93e3a32062670df5eb6682aed273a Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Fri, 7 Oct 2011 15:09:27 +0100 Subject: Allow affiliation editing in MUCs. Resolves: #986 Resolves: #988 diff --git a/.subl/swift.sublime-project b/.subl/swift.sublime-project index 5746207..1d637c4 100644 --- a/.subl/swift.sublime-project +++ b/.subl/swift.sublime-project @@ -5,7 +5,7 @@ { "path": "..", "folder_exclude_patterns": ["tmp", ".sconf_temp", ".settings", "Swift.app", "3rdParty"], - "file_exclude_patterns": [".cproject", ".project", ".sconsign.dblite", "*~", "config.log", "*.o"] + "file_exclude_patterns": ["moc_*", ".cproject", ".project", ".sconsign.dblite", "*~", "config.log", "*.o"] } ], "settings": diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index e413d92..30e85ad 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -77,6 +77,8 @@ MUCController::MUCController ( chatWindow_->onConfigurationFormCancelled.connect(boost::bind(&MUCController::handleConfigurationCancelled, this)); chatWindow_->onDestroyRequest.connect(boost::bind(&MUCController::handleDestroyRoomRequest, this)); chatWindow_->onInvitePersonToThisMUCRequest.connect(boost::bind(&MUCController::handleInvitePersonToThisMUCRequest, this, _1, _2)); + chatWindow_->onGetAffiliationsRequest.connect(boost::bind(&MUCController::handleGetAffiliationsRequest, this)); + chatWindow_->onChangeAffiliationsRequest.connect(boost::bind(&MUCController::handleChangeAffiliationsRequest, this, _1)); 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)); @@ -86,6 +88,7 @@ MUCController::MUCController ( muc_->onConfigurationFailed.connect(boost::bind(&MUCController::handleConfigurationFailed, this, _1)); muc_->onConfigurationFormReceived.connect(boost::bind(&MUCController::handleConfigurationFormReceived, this, _1)); muc_->onRoleChangeFailed.connect(boost::bind(&MUCController::handleOccupantRoleChangeFailed, this, _1, _2, _3)); + muc_->onAffiliationListReceived.connect(boost::bind(&MUCController::handleAffiliationListReceived, this, _1, _2)); if (timerFactory) { loginCheckTimer_ = boost::shared_ptr(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS)); loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this)); @@ -114,6 +117,7 @@ void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item /* FIXME: all of these should be conditional */ if (item) { actions.push_back(ChatWindow::Kick); + actions.push_back(ChatWindow::Ban); actions.push_back(ChatWindow::MakeModerator); actions.push_back(ChatWindow::MakeParticipant); actions.push_back(ChatWindow::MakeVisitor); @@ -124,6 +128,7 @@ void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction action, ContactRosterItem* item) { switch (action) { case ChatWindow::Kick: muc_->kickOccupant(item->getJID());break; + case ChatWindow::Ban: muc_->changeAffiliation(item->getJID(), MUCOccupant::Outcast);break; case ChatWindow::MakeModerator: muc_->changeOccupantRole(item->getJID(), MUCOccupant::Moderator);break; case ChatWindow::MakeParticipant: muc_->changeOccupantRole(item->getJID(), MUCOccupant::Participant);break; case ChatWindow::MakeVisitor: muc_->changeOccupantRole(item->getJID(), MUCOccupant::Visitor);break; @@ -201,7 +206,7 @@ void MUCController::handleJoinFailed(boost::shared_ptr error) { break; case ErrorPayload::NotAuthorized: errorMessage += ": "; - errorMessage += QT_TRANSLATE_NOOP("", "A password needed"); + errorMessage += QT_TRANSLATE_NOOP("", "A password is needed"); break; case ErrorPayload::RegistrationRequired: errorMessage += ": "; @@ -630,4 +635,23 @@ void MUCController::handleInvitePersonToThisMUCRequest(const JID& jid, const std muc_->invitePerson(jid, reason); } +void MUCController::handleGetAffiliationsRequest() { + muc_->requestAffiliationList(MUCOccupant::Owner); + muc_->requestAffiliationList(MUCOccupant::Admin); + muc_->requestAffiliationList(MUCOccupant::Member); + muc_->requestAffiliationList(MUCOccupant::Outcast); +} + +typedef std::pair AffiliationChangePair; + +void MUCController::handleChangeAffiliationsRequest(const std::vector >& changes) { + foreach (const AffiliationChangePair& change, changes) { + muc_->changeAffiliation(change.second, change.first); + } +} + +void MUCController::handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector& jids) { + chatWindow_->setAffiliations(affiliation, jids); +} + } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 19d3f66..16dcb99 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -95,6 +95,9 @@ namespace Swift { void handleInvitePersonToThisMUCRequest(const JID& jid, const std::string& reason); void handleConfigurationCancelled(); void handleOccupantRoleChangeFailed(ErrorPayload::ref, const JID&, MUCOccupant::Role); + void handleGetAffiliationsRequest(); + void handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector& jids); + void handleChangeAffiliationsRequest(const std::vector >& changes); private: MUC::ref muc_; diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 4a93b42..6fce7a0 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Swift { @@ -32,7 +33,7 @@ namespace Swift { public: enum AckState {Pending, Received, Failed}; enum Tristate {Yes, No, Maybe}; - enum OccupantAction {Kick, MakeModerator, MakeParticipant, MakeVisitor}; + enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor}; enum FileTransferState {WaitingForAccept, Negotiating, Transferring, Canceled, Finished, FTFailed}; ChatWindow() {} virtual ~ChatWindow() {}; @@ -75,6 +76,7 @@ namespace Swift { virtual void setAckState(const std::string& id, AckState state) = 0; virtual void flash() = 0; virtual void setSubject(const std::string& subject) = 0; + virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector&) = 0; /** * Set an alert on the window. @@ -112,6 +114,9 @@ namespace Swift { boost::signal onDestroyRequest; boost::signal onInvitePersonToThisMUCRequest; boost::signal onConfigurationFormCancelled; + boost::signal onGetAffiliationsRequest; + boost::signal onSetAffiliationRequest; + boost::signal >& changes)> onChangeAffiliationsRequest; // File transfer related boost::signal onFileTransferCancel; diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index 7b90a57..7e31179 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -49,6 +49,7 @@ namespace Swift { void setSubject(const std::string& /*subject*/) {} virtual void showRoomConfigurationForm(Form::ref) {} virtual void addMUCInvitation(const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/) {}; + virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector&) {} std::string name_; std::string lastMessageBody_; diff --git a/Swift/QtUI/QtAffiliationEditor.cpp b/Swift/QtUI/QtAffiliationEditor.cpp new file mode 100644 index 0000000..ed03c23 --- /dev/null +++ b/Swift/QtUI/QtAffiliationEditor.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "QtAffiliationEditor.h" + +#include +#include + +#include "QtSwiftUtil.h" + + +namespace Swift { +QtAffiliationEditor::QtAffiliationEditor(QWidget* parent) : QDialog(parent){ + ui_.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + connect(ui_.affiliation, SIGNAL(currentIndexChanged(int)), this, SLOT(handleCurrentIndexChanged(int))); + connect(ui_.addJID, SIGNAL(clicked()), this, SLOT(handleAddClicked())); + connect(ui_.removeJID, SIGNAL(clicked()), this, SLOT(handleRemoveClicked())); +} + +QtAffiliationEditor::~QtAffiliationEditor() { + +} + +void QtAffiliationEditor::setAffiliations(MUCOccupant::Affiliation affiliation, const std::vector& jids) { + affiliations_[affiliation] = jids; + if (affiliationFromIndex(ui_.affiliation->currentIndex()) == affiliation) { + handleCurrentIndexChanged(ui_.affiliation->currentIndex()); + } +} + +const std::vector >& QtAffiliationEditor::getChanges() const { + return changes_; +} + +void QtAffiliationEditor::handleCurrentIndexChanged(int index) { + ui_.list->clear(); + foreach (const JID& jid, affiliations_[affiliationFromIndex(index)]) { + ui_.list->addItem(P2QSTRING(jid.toString())); + } +} + +void QtAffiliationEditor::handleAddClicked() { + bool ok = false; + JID jid = JID(Q2PSTRING(QInputDialog::getText(this, tr("Add User"), tr("Added User's Address:"), QLineEdit::Normal, "", &ok))); + if (ok && jid.isValid()) { + //FIXME: validation + MUCOccupant::Affiliation affiliation = affiliationFromIndex(ui_.affiliation->currentIndex()); + changes_.push_back(ChangePair(affiliation, jid)); + ui_.list->addItem(P2QSTRING(jid.toString())); + affiliations_[affiliation].push_back(jid); + } +} + +void QtAffiliationEditor::handleRemoveClicked() { + QListWidgetItem* item = ui_.list->currentItem(); + if (item) { + JID jid(Q2PSTRING(item->text())); + changes_.push_back(ChangePair(MUCOccupant::NoAffiliation, jid)); + std::vector& jids = affiliations_[affiliationFromIndex(ui_.affiliation->currentIndex())]; + jids.erase(std::remove(jids.begin(), jids.end(), jid), jids.end()); + handleCurrentIndexChanged(ui_.affiliation->currentIndex()); + } +} + +MUCOccupant::Affiliation QtAffiliationEditor::affiliationFromIndex(int affiliation) { + switch (affiliation) { + case 0: return MUCOccupant::Owner; + case 1: return MUCOccupant::Admin; + case 2: return MUCOccupant::Member; + case 3: return MUCOccupant::Outcast; + default: return MUCOccupant::Outcast; + } +} + +} \ No newline at end of file diff --git a/Swift/QtUI/QtAffiliationEditor.h b/Swift/QtUI/QtAffiliationEditor.h new file mode 100644 index 0000000..913b2cc --- /dev/null +++ b/Swift/QtUI/QtAffiliationEditor.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include +#include + +#include +#include + +#include +#include + +namespace Swift { + class QtAffiliationEditor : public QDialog { + Q_OBJECT + public: + QtAffiliationEditor(QWidget* parent = NULL); + ~QtAffiliationEditor(); + void setAffiliations(MUCOccupant::Affiliation, const std::vector& jids); + const std::vector >& getChanges() const; + private slots: + void handleCurrentIndexChanged(int); + void handleAddClicked(); + void handleRemoveClicked(); + private: + typedef std::pair ChangePair; + MUCOccupant::Affiliation affiliationFromIndex(int affiliation); + Ui::QtAffiliationEditor ui_; + std::map > affiliations_; + std::vector changes_; + }; +} \ No newline at end of file diff --git a/Swift/QtUI/QtAffiliationEditor.ui b/Swift/QtUI/QtAffiliationEditor.ui new file mode 100644 index 0000000..1447884 --- /dev/null +++ b/Swift/QtUI/QtAffiliationEditor.ui @@ -0,0 +1,146 @@ + + + QtAffiliationEditor + + + + 0 + 0 + 575 + 466 + + + + Dialog + + + + + + + + + + + + + + Affiliation: + + + + + + + + Owner + + + + + Administrator + + + + + Member + + + + + Outcast (Banned) + + + + + + + + + + + + + + + + + Add User + + + + + + + Remove User + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + QtAffiliationEditor + accept() + + + 224 + 444 + + + 157 + 274 + + + + + buttonBox + rejected() + QtAffiliationEditor + reject() + + + 292 + 450 + + + 286 + 274 + + + + + diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 7e47f4d..0635496 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -53,6 +53,7 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt unreadCount_ = 0; inputEnabled_ = true; completer_ = NULL; + affiliationEditor_ = NULL; theme_ = theme; isCorrection_ = false; correctionEnabled_ = Maybe; @@ -165,8 +166,8 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt QtChatWindow::~QtChatWindow() { delete fileTransferJS; - if (mucConfigurationWindow) { - delete mucConfigurationWindow.data(); + if (mucConfigurationWindow_) { + delete mucConfigurationWindow_.data(); } } @@ -341,7 +342,7 @@ void QtChatWindow::setCorrectionEnabled(Tristate enabled) { SecurityLabelsCatalog::Item QtChatWindow::getSelectedSecurityLabel() { assert(labelsWidget_->isEnabled()); - assert(labelsWidget_->currentIndex() >= 0 && labelsWidget_->currentIndex() < availableLabels_.size()); + assert(labelsWidget_->currentIndex() >= 0 && static_cast(labelsWidget_->currentIndex()) < availableLabels_.size()); return availableLabels_[labelsWidget_->currentIndex()]; } @@ -371,8 +372,13 @@ void QtChatWindow::qAppFocusChanged(QWidget* /*old*/, QWidget* /*now*/) { void QtChatWindow::setInputEnabled(bool enabled) { inputEnabled_ = enabled; - if (!enabled && mucConfigurationWindow) { - delete mucConfigurationWindow.data(); + if (!enabled) { + if (mucConfigurationWindow_) { + delete mucConfigurationWindow_.data(); + } + if (affiliationEditor_) { + delete affiliationEditor_.data(); + } } } @@ -704,6 +710,7 @@ void QtChatWindow::handleActionButtonClicked() { QMenu contextMenu; QAction* changeSubject = contextMenu.addAction(tr("Change subject")); QAction* configure = contextMenu.addAction(tr("Configure room")); + QAction* affiliations = contextMenu.addAction(tr("Edit affiliations")); QAction* destroy = contextMenu.addAction(tr("Destroy room")); QAction* invite = contextMenu.addAction(tr("Invite person to this room")); QAction* result = contextMenu.exec(QCursor::pos()); @@ -717,6 +724,14 @@ void QtChatWindow::handleActionButtonClicked() { else if (result == configure) { onConfigureRequest(Form::ref()); } + else if (result == affiliations) { + if (!affiliationEditor_) { + onGetAffiliationsRequest(); + affiliationEditor_ = new QtAffiliationEditor(this); + connect(affiliationEditor_, SIGNAL(accepted()), this, SLOT(handleAffiliationEditorAccepted())); + } + affiliationEditor_->show(); + } else if (result == destroy) { onDestroyRequest(); } @@ -729,13 +744,22 @@ void QtChatWindow::handleActionButtonClicked() { } } +void QtChatWindow::handleAffiliationEditorAccepted() { + onChangeAffiliationsRequest(affiliationEditor_->getChanges()); +} + +void QtChatWindow::setAffiliations(MUCOccupant::Affiliation affiliation, const std::vector& jids) { + if (!affiliationEditor_) return; + affiliationEditor_->setAffiliations(affiliation, jids); +} + void QtChatWindow::showRoomConfigurationForm(Form::ref form) { - if (mucConfigurationWindow) { - delete mucConfigurationWindow.data(); + if (mucConfigurationWindow_) { + delete mucConfigurationWindow_.data(); } - mucConfigurationWindow = new QtMUCConfigurationWindow(form); - mucConfigurationWindow->onFormComplete.connect(boost::bind(boost::ref(onConfigureRequest), _1)); - mucConfigurationWindow->onFormCancelled.connect(boost::bind(boost::ref(onConfigurationFormCancelled))); + mucConfigurationWindow_ = new QtMUCConfigurationWindow(form); + mucConfigurationWindow_->onFormComplete.connect(boost::bind(boost::ref(onConfigureRequest), _1)); + mucConfigurationWindow_->onFormCancelled.connect(boost::bind(boost::ref(onConfigurationFormCancelled))); } void QtChatWindow::addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password) { diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 8dfe767..e546f12 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -8,6 +8,7 @@ #include #include +#include #include @@ -73,6 +74,7 @@ namespace Swift { void setSubject(const std::string& subject); void showRoomConfigurationForm(Form::ref); void addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password); + void setAffiliations(MUCOccupant::Affiliation, const std::vector&); public slots: void handleChangeSplitterState(QByteArray state); @@ -111,6 +113,7 @@ namespace Swift { void handleFileTransferSetDescription(QString id); void handleFileTransferStart(QString id); void handleFileTransferAccept(QString id, QString filename); + void handleAffiliationEditorAccepted(); private: void updateTitleWithUnreadCount(); @@ -153,6 +156,7 @@ namespace Swift { QString alertStyleSheet_; std::map descriptions; QtFileTransferJSBridge* fileTransferJS; - QPointer mucConfigurationWindow; + QPointer mucConfigurationWindow_; + QPointer affiliationEditor_; }; } diff --git a/Swift/QtUI/Roster/QtOccupantListWidget.cpp b/Swift/QtUI/Roster/QtOccupantListWidget.cpp index 3ee0b7d..3f66585 100644 --- a/Swift/QtUI/Roster/QtOccupantListWidget.cpp +++ b/Swift/QtUI/Roster/QtOccupantListWidget.cpp @@ -45,6 +45,7 @@ void QtOccupantListWidget::contextMenuEvent(QContextMenuEvent* event) { QString text = "Error: missing string"; switch (availableAction) { case ChatWindow::Kick: text = tr("Kick user"); break; + case ChatWindow::Ban: text = tr("Kick and ban user"); break; case ChatWindow::MakeModerator: text = tr("Make moderator"); break; case ChatWindow::MakeParticipant: text = tr("Make participant"); break; case ChatWindow::MakeVisitor: text = tr("Remove voice"); break; diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 82e4490..71dc59f 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -84,8 +84,8 @@ sources = [ "QtTabWidget.cpp", "QtTextEdit.cpp", "QtXMLConsoleWidget.cpp", - "QtFileTransferListWidget.cpp", - "QtFileTransferListItemModel.cpp", + "QtFileTransferListWidget.cpp", + "QtFileTransferListItemModel.cpp", "QtAdHocCommandWindow.cpp", "QtUtilities.cpp", "QtBookmarkDetailWindow.cpp", @@ -137,6 +137,7 @@ sources = [ "qrc_Swift.cc", "QtFileTransferJSBridge.cpp", "QtMUCConfigurationWindow.cpp", + "QtAffiliationEditor.cpp", ] myenv["SWIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "swift") @@ -173,6 +174,7 @@ myenv.Uic4("UserSearch/QtUserSearchFirstPage.ui") myenv.Uic4("UserSearch/QtUserSearchFieldsPage.ui") myenv.Uic4("UserSearch/QtUserSearchResultsPage.ui") myenv.Uic4("QtBookmarkDetailWindow.ui") +myenv.Uic4("QtAffiliationEditor.ui") myenv.Uic4("QtJoinMUCWindow.ui") myenv.Qrc("DefaultTheme.qrc") myenv.Qrc("Swift.qrc") diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index 204fdcc..824ced1 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -241,6 +241,9 @@ void MUC::kickOccupant(const JID& jid) { changeOccupantRole(jid, MUCOccupant::NoRole); } +/** + * Call with the room JID, not the real JID. + */ void MUC::changeOccupantRole(const JID& jid, MUCOccupant::Role role) { MUCAdminPayload::ref mucPayload = boost::make_shared(); MUCItem item; @@ -259,6 +262,51 @@ void MUC::handleOccupantRoleChangeResponse(MUCAdminPayload::ref /*unused*/, Erro } } +void MUC::requestAffiliationList(MUCOccupant::Affiliation affiliation) { + MUCAdminPayload::ref mucPayload = boost::make_shared(); + MUCItem item; + item.affiliation = affiliation; + mucPayload->addItem(item); + GenericRequest* request = new GenericRequest(IQ::Get, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUC::handleAffiliationListResponse, this, _1, _2, affiliation)); + request->send(); +} + +/** + * Must be called with the real JID, not the room JID. + */ +void MUC::changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation) { + MUCAdminPayload::ref mucPayload = boost::make_shared(); + MUCItem item; + item.affiliation = affiliation; + item.realJID = jid; + mucPayload->addItem(item); + GenericRequest* request = new GenericRequest(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUC::handleAffiliationChangeResponse, this, _1, _2, jid, affiliation)); + request->send(); +} + +void MUC::handleAffiliationListResponse(MUCAdminPayload::ref payload, ErrorPayload::ref error, MUCOccupant::Affiliation affiliation) { + if (error) { + onAffiliationListFailed(error); + } + else { + std::vector jids; + foreach (MUCItem item, payload->getItems()) { + if (item.realJID) { + jids.push_back(*item.realJID); + } + } + onAffiliationListReceived(affiliation, jids); + } +} + +void MUC::handleAffiliationChangeResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid, MUCOccupant::Affiliation affiliation) { + if (error) { + onAffiliationChangeFailed(error, jid, affiliation); + } +} + void MUC::changeSubject(const std::string& subject) { Message::ref message = boost::make_shared(); message->setSubject(subject); diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index d855033..1070c69 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -58,6 +58,8 @@ namespace Swift { bool hasOccupant(const std::string& nick); void kickOccupant(const JID& jid); void changeOccupantRole(const JID& jid, MUCOccupant::Role role); + void requestAffiliationList(MUCOccupant::Affiliation); + void changeAffiliation(const JID& jid, MUCOccupant::Affiliation affiliation); void changeSubject(const std::string& subject); void requestConfigurationForm(); void configureRoom(Form::ref); @@ -67,17 +69,21 @@ namespace Swift { void invitePerson(const JID& person, const std::string& reason = ""); void setCreateAsReservedIfNew() {createAsReservedIfNew = true;} void setPassword(const boost::optional& password); + public: boost::signal onJoinComplete; boost::signal onJoinFailed; boost::signal onRoleChangeFailed; + boost::signal onAffiliationChangeFailed; boost::signal onConfigurationFailed; + boost::signal onAffiliationListFailed; boost::signal onOccupantPresenceChange; boost::signal onOccupantRoleChanged; boost::signal onOccupantAffiliationChanged; boost::signal onOccupantJoined; boost::signal onOccupantLeft; boost::signal onConfigurationFormReceived; + boost::signal&)> onAffiliationListReceived; /* boost::signal onInfoResult; */ /* boost::signal onItemsResult; */ @@ -96,6 +102,8 @@ namespace Swift { void internalJoin(const std::string& nick); void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref); void handleOccupantRoleChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Role); + void handleAffiliationChangeResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&, MUCOccupant::Affiliation); + void handleAffiliationListResponse(MUCAdminPayload::ref, ErrorPayload::ref, MUCOccupant::Affiliation); void handleConfigurationFormReceived(MUCOwnerPayload::ref, ErrorPayload::ref); void handleConfigurationResultReceived(MUCOwnerPayload::ref, ErrorPayload::ref); -- cgit v0.10.2-6-g49f6