summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/Controllers')
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp26
-rw-r--r--Swift/Controllers/Chat/MUCController.h3
-rw-r--r--Swift/Controllers/UIInterfaces/ChatWindow.h7
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h1
4 files changed, 35 insertions, 2 deletions
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
@@ -45,117 +45,122 @@ MUCController::MUCController (
const JID& self,
MUC::ref muc,
const boost::optional<std::string>& password,
const std::string &nick,
StanzaChannel* stanzaChannel,
IQRouter* iqRouter,
ChatWindowFactory* chatWindowFactory,
PresenceOracle* presenceOracle,
AvatarManager* avatarManager,
UIEventStream* uiEventStream,
bool useDelayForLatency,
TimerFactory* timerFactory,
EventController* eventController,
EntityCapsProvider* entityCapsProvider) :
ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) {
parting_ = true;
joined_ = false;
lastWasPresence_ = false;
shouldJoinOnReconnect_ = true;
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));
chatWindow_->onChangeSubjectRequest.connect(boost::bind(&MUCController::handleChangeSubjectRequest, this, _1));
chatWindow_->onConfigureRequest.connect(boost::bind(&MUCController::handleConfigureRequest, this, _1));
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));
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));
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<Timer>(timerFactory->createTimer(MUC_JOIN_WARNING_TIMEOUT_MILLISECONDS));
loginCheckTimer_->onTick.connect(boost::bind(&MUCController::handleJoinTimeoutTick, this));
loginCheckTimer_->start();
}
chatWindow_->convertToMUC();
setOnline(true);
if (avatarManager_ != NULL) {
avatarChangedConnection_ = (avatarManager_->onAvatarChanged.connect(boost::bind(&MUCController::handleAvatarChanged, this, _1)));
}
handleBareJIDCapsChanged(muc->getJID());
}
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: 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);
}
chatWindow_->setAvailableOccupantActions(actions);
}
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;
}
}
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;
}
}
if (!any) {
support = ChatWindow::No;
}
chatWindow_->setCorrectionEnabled(support);
}
/**
* Join the MUC if not already in it.
*/
void MUCController::rejoin() {
if (parting_) {
joined_ = false;
parting_ = false;
if (password_) {
muc_->setPassword(*password_);
}
//FIXME: check for received activity
if (lastActivity_ == boost::posix_time::not_a_date_time) {
@@ -169,71 +174,71 @@ void MUCController::rejoin() {
bool MUCController::isJoined() {
return joined_;
}
const std::string& MUCController::getNick() {
return nick_;
}
void MUCController::handleJoinTimeoutTick() {
receivedActivity();
chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString()));
}
void MUCController::receivedActivity() {
if (loginCheckTimer_) {
loginCheckTimer_->stop();
}
}
void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) {
receivedActivity();
std::string errorMessage = QT_TRANSLATE_NOOP("", "Unable to enter this room");
std::string rejoinNick;
if (error) {
switch (error->getCondition()) {
case ErrorPayload::Conflict:
rejoinNick = nick_ + "_";
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Unable to enter this room as %1%, retrying as %2%")) % nick_ % rejoinNick);
break;
case ErrorPayload::JIDMalformed:
errorMessage += ": ";
errorMessage += QT_TRANSLATE_NOOP("", "No nickname specified");
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 += ": ";
errorMessage += QT_TRANSLATE_NOOP("", "Only members may enter");
break;
case ErrorPayload::Forbidden:
errorMessage += ": ";
errorMessage += QT_TRANSLATE_NOOP("", "You are banned from the room");
break;
case ErrorPayload::ServiceUnavailable:
errorMessage += ": ";
errorMessage += QT_TRANSLATE_NOOP("", "The room is full");
break;
case ErrorPayload::ItemNotFound:
errorMessage += ": ";
errorMessage += QT_TRANSLATE_NOOP("", "The room does not exist");
break;
default: break;
}
}
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Couldn't join room: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(errorMessage);
if (!rejoinNick.empty()) {
nick_ = rejoinNick;
parting_ = true;
rejoin();
}
}
void MUCController::handleJoinComplete(const std::string& nick) {
receivedActivity();
joined_ = true;
std::string joinMessage = str(format(QT_TRANSLATE_NOOP("", "You have entered room %1% as %2%.")) % toJID_.toString() % nick);
nick_ = nick;
@@ -598,36 +603,55 @@ void MUCController::handleConfigureRequest(Form::ref form) {
muc_->configureRoom(form);
}
else {
muc_->requestConfigurationForm();
}
}
void MUCController::handleConfigurationFailed(ErrorPayload::ref error) {
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Room configuration failed: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(errorMessage);
}
void MUCController::handleOccupantRoleChangeFailed(ErrorPayload::ref error, const JID&, MUCOccupant::Role) {
std::string errorMessage = getErrorMessage(error);
errorMessage = str(format(QT_TRANSLATE_NOOP("", "Occupant role change failed: %1%.")) % errorMessage);
chatWindow_->addErrorMessage(errorMessage);
}
void MUCController::handleConfigurationFormReceived(Form::ref form) {
chatWindow_->showRoomConfigurationForm(form);
}
void MUCController::handleConfigurationCancelled() {
muc_->cancelConfigureRoom();
}
void MUCController::handleDestroyRoomRequest() {
muc_->destroyRoom();
}
void MUCController::handleInvitePersonToThisMUCRequest(const JID& jid, const std::string& reason) {
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<MUCOccupant::Affiliation, JID> AffiliationChangePair;
+
+void MUCController::handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes) {
+ foreach (const AffiliationChangePair& change, changes) {
+ muc_->changeAffiliation(change.second, change.first);
+ }
+}
+
+void MUCController::handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector<JID>& 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
@@ -63,57 +63,60 @@ namespace Swift {
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();
void handleChangeSubjectRequest(const std::string&);
std::string roleToGroupName(MUCOccupant::Role role);
std::string roleToSortName(MUCOccupant::Role role);
JID nickToJID(const std::string& nick);
std::string roleToFriendlyName(MUCOccupant::Role role);
void receivedActivity();
bool messageTargetsMe(boost::shared_ptr<Message> message);
void updateJoinParts();
bool shouldUpdateJoinParts();
void dayTicked() {lastWasPresence_ = false;}
void processUserPart();
void handleBareJIDCapsChanged(const JID& jid);
void handleConfigureRequest(Form::ref);
void handleConfigurationFailed(ErrorPayload::ref);
void handleConfigurationFormReceived(Form::ref);
void handleDestroyRoomRequest();
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<JID>& jids);
+ void handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes);
private:
MUC::ref muc_;
UIEventStream* events_;
std::string nick_;
std::string desiredNick_;
Roster* roster_;
TabComplete* completer_;
bool parting_;
bool joined_;
bool lastWasPresence_;
bool shouldJoinOnReconnect_;
bool doneGettingHistory_;
boost::bsignals::scoped_connection avatarChangedConnection_;
boost::shared_ptr<Timer> loginCheckTimer_;
std::set<std::string> currentOccupants_;
std::vector<NickJoinPart> joinParts_;
boost::posix_time::ptime lastActivity_;
boost::optional<std::string> password_;
};
}
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
@@ -1,124 +1,129 @@
/*
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#ifndef SWIFTEN_CHATWINDOW_H
#define SWIFTEN_CHATWINDOW_H
#include <boost/optional.hpp>
#include "Swiften/Base/boost_bsignals.h"
#include <boost/shared_ptr.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <vector>
#include <string>
#include <Swiften/Elements/SecurityLabelsCatalog.h>
#include <Swiften/Elements/ChatState.h>
#include <Swiften/Elements/Form.h>
+#include <Swiften/Elements/MUCOccupant.h>
namespace Swift {
class AvatarManager;
class TreeWidget;
class Roster;
class TabComplete;
class RosterItem;
class ContactRosterItem;
class FileTransferController;
class ChatWindow {
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() {};
/** 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);
*/
virtual std::string addAction(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;
virtual void addSystemMessage(const std::string& message) = 0;
virtual void addPresenceMessage(const std::string& message) = 0;
virtual void addErrorMessage(const std::string& message) = 0;
virtual void replaceMessage(const std::string& message, const std::string& id, const boost::posix_time::ptime& time) = 0;
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
virtual void addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password) = 0;
virtual void setContactChatState(ChatState::ChatStateType state) = 0;
virtual void setName(const std::string& name) = 0;
virtual void show() = 0;
virtual void activate() = 0;
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) = 0;
virtual void setSecurityLabelsEnabled(bool enabled) = 0;
virtual void setCorrectionEnabled(Tristate enabled) = 0;
virtual void setUnreadMessageCount(int count) = 0;
virtual void convertToMUC() = 0;
// virtual TreeWidget *getTreeWidget() = 0;
virtual void setSecurityLabelsError() = 0;
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() = 0;
virtual void setInputEnabled(bool enabled) = 0;
virtual void setRosterModel(Roster* model) = 0;
virtual void setTabComplete(TabComplete* completer) = 0;
virtual void replaceLastMessage(const std::string& message) = 0;
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<JID>&) = 0;
/**
* Set an alert on the window.
* @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;
/**
* A room configuration has been requested, show the form.
* If the form is cancelled, must emit onConfigurationFormCancelled().
*/
virtual void showRoomConfigurationForm(Form::ref) = 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;
boost::signal<void (const std::string&)> onChangeSubjectRequest;
boost::signal<void (Form::ref)> onConfigureRequest;
boost::signal<void ()> onDestroyRequest;
boost::signal<void (const JID&, const std::string& /*reason*/)> onInvitePersonToThisMUCRequest;
boost::signal<void ()> onConfigurationFormCancelled;
+ boost::signal<void ()> onGetAffiliationsRequest;
+ boost::signal<void (MUCOccupant::Affiliation, const JID&)> onSetAffiliationRequest;
+ boost::signal<void (const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes)> onChangeAffiliationsRequest;
// File transfer related
boost::signal<void (std::string /* id */)> onFileTransferCancel;
boost::signal<void (std::string /* id */, std::string /* description */)> onFileTransferStart;
boost::signal<void (std::string /* id */, std::string /* path */)> onFileTransferAccept;
boost::signal<void (std::string /* path */)> onSendFileRequest;
};
}
#endif
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
@@ -17,44 +17,45 @@ namespace Swift {
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&) {lastMessageBody_ = message; return "";};
virtual std::string addAction(const std::string& message, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime&) {lastMessageBody_ = message; return "";};
virtual void addSystemMessage(const std::string& /*message*/) {};
virtual void addErrorMessage(const std::string& /*message*/) {};
virtual void addPresenceMessage(const std::string& /*message*/) {};
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/) { return 0; };
virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { };
virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { };
virtual void setContactChatState(ChatState::ChatStateType /*state*/) {};
virtual void setName(const std::string& name) {name_ = name;};
virtual void show() {};
virtual void activate() {};
virtual void setAvailableSecurityLabels(const std::vector<SecurityLabelsCatalog::Item>& labels) {labels_ = labels;};
virtual void setSecurityLabelsEnabled(bool enabled) {labelsEnabled_ = enabled;};
virtual void setUnreadMessageCount(int /*count*/) {};
virtual void convertToMUC() {};
virtual void setSecurityLabelsError() {};
virtual SecurityLabelsCatalog::Item getSelectedSecurityLabel() {return label_;}
virtual void setInputEnabled(bool /*enabled*/) {};
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*/) {}
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<JID>&) {}
std::string name_;
std::string lastMessageBody_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;
SecurityLabelsCatalog::Item label_;
};
}