diff options
-rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 55 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.h | 2 | ||||
-rw-r--r-- | Swift/Controllers/UIInterfaces/ChatWindow.h | 3 | ||||
-rw-r--r-- | Swift/Controllers/UnitTest/MockChatWindow.h | 1 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 28 | ||||
-rw-r--r-- | Swift/QtUI/QtChatWindow.h | 2 |
6 files changed, 79 insertions, 12 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index fd37d27..52cd262 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -80,18 +80,19 @@ MUCController::MUCController ( 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_->onOccupantAffiliationChanged.connect(boost::bind(&MUCController::handleOccupantAffiliationChanged, 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(); } @@ -109,26 +110,33 @@ MUCController::~MUCController() { 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); + MUCOccupant::Affiliation affiliation = muc_->getOccupant(getNick()).getAffiliation(); + MUCOccupant::Role role = muc_->getOccupant(getNick()).getRole(); + if (role == MUCOccupant::Moderator) + { + if (affiliation == MUCOccupant::Admin || affiliation == MUCOccupant::Owner) { + actions.push_back(ChatWindow::Ban); + } + actions.push_back(ChatWindow::Kick); + actions.push_back(ChatWindow::MakeModerator); + actions.push_back(ChatWindow::MakeParticipant); + actions.push_back(ChatWindow::MakeVisitor); + } // Add contact is available only if the real JID is also available if (muc_->getOccupant(item->getJID().getResource()).getRealJID()) { actions.push_back(ChatWindow::AddContact); } } chatWindow_->setAvailableOccupantActions(actions); } void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction action, ContactRosterItem* item) { @@ -253,18 +261,20 @@ void MUCController::handleJoinFailed(boost::shared_ptr<ErrorPayload> error) { 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; chatWindow_->addSystemMessage(joinMessage); clearPresenceQueue(); shouldJoinOnReconnect_ = true; setEnabled(true); + MUCOccupant occupant = muc_->getOccupant(nick); + setAvailableRoomActions(occupant.getAffiliation(), occupant.getRole()); onUserJoined(); } void MUCController::handleAvatarChanged(const JID& jid) { if (parting_ || !jid.equals(toJID_, JID::WithoutResource)) { return; } std::string path = avatarManager_->getAvatarPath(jid).string(); roster_->applyOnItems(SetAvatar(jid, path, JID::WithResource)); @@ -313,18 +323,41 @@ void MUCController::handleOccupantJoined(const MUCOccupant& occupant) { handleAvatarChanged(jid); } } void MUCController::addPresenceMessage(const std::string& message) { lastWasPresence_ = true; chatWindow_->addPresenceMessage(message); } + +void MUCController::setAvailableRoomActions(const MUCOccupant::Affiliation& affiliation, const MUCOccupant::Role& role) +{ + std::vector<ChatWindow::RoomAction> actions; + + if (role <= MUCOccupant::Participant) { + actions.push_back(ChatWindow::ChangeSubject); + } + if (affiliation == MUCOccupant::Owner) { + actions.push_back(ChatWindow::Configure); + } + if (affiliation <= MUCOccupant::Admin) { + actions.push_back(ChatWindow::Affiliations); + } + if (affiliation == MUCOccupant::Owner) { + actions.push_back(ChatWindow::Destroy); + } + if (role <= MUCOccupant::Visitor) { + actions.push_back(ChatWindow::Invite); + } + chatWindow_->setAvailableRoomActions(actions); +} + void MUCController::clearPresenceQueue() { lastWasPresence_ = false; joinParts_.clear(); } std::string MUCController::roleToFriendlyName(MUCOccupant::Role role) { switch (role) { case MUCOccupant::Moderator: return QT_TRANSLATE_NOOP("", "moderator"); case MUCOccupant::Participant: return QT_TRANSLATE_NOOP("", "participant"); @@ -404,18 +437,28 @@ void MUCController::handleOccupantRoleChanged(const std::string& nick, const MUC roster_->removeContactFromGroup(jid, roleToGroupName(oldRole)); JID realJID; if (occupant.getRealJID()) { realJID = occupant.getRealJID().get(); } std::string group(roleToGroupName(occupant.getRole())); roster_->addContact(jid, realJID, nick, group, avatarManager_->getAvatarPath(jid).string()); roster_->getGroup(group)->setManualSort(roleToSortName(occupant.getRole())); chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "%1% is now a %2%")) % nick % roleToFriendlyName(occupant.getRole()))); + if (nick == nick_) { + setAvailableRoomActions(occupant.getAffiliation(), occupant.getRole()); + } +} + +void MUCController::handleOccupantAffiliationChanged(const std::string& nick, const MUCOccupant::Affiliation& affiliation, const MUCOccupant::Affiliation& oldAffiliation) +{ + if (nick == nick_) { + setAvailableRoomActions(affiliation, muc_->getOccupant(nick_).getRole()); + } } std::string MUCController::roleToGroupName(MUCOccupant::Role role) { std::string result; switch (role) { case MUCOccupant::Moderator: result = QT_TRANSLATE_NOOP("", "Moderators"); break; case MUCOccupant::Participant: result = QT_TRANSLATE_NOOP("", "Participants"); break; case MUCOccupant::Visitor: result = QT_TRANSLATE_NOOP("", "Visitors"); break; case MUCOccupant::NoRole: result = QT_TRANSLATE_NOOP("", "Occupants"); break; diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 16dcb99..6906f81 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -57,28 +57,30 @@ namespace Swift { protected: void preSendMessageRequest(boost::shared_ptr<Message> message); 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 setAvailableRoomActions(const MUCOccupant::Affiliation& affiliation, const MUCOccupant::Role& role); 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 handleOccupantAffiliationChanged(const std::string& nick, const MUCOccupant::Affiliation& affiliation,const MUCOccupant::Affiliation& oldAffiliation); 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(); diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index acf2381..e7246c6 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -29,18 +29,19 @@ namespace Swift { class ContactRosterItem; class FileTransferController; class ChatWindow { public: enum AckState {Pending, Received, Failed}; enum ReceiptState {ReceiptRequested, ReceiptReceived}; enum Tristate {Yes, No, Maybe}; enum OccupantAction {Kick, Ban, MakeModerator, MakeParticipant, MakeVisitor, AddContact}; + enum RoomAction {ChangeSubject, Configure, Affiliations, Destroy, Invite}; 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. @@ -75,19 +76,19 @@ namespace Swift { 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; - + virtual void setAvailableRoomActions(const std::vector<RoomAction> &actions) = 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. */ diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h index ce012c6..dab1e90 100644 --- a/Swift/Controllers/UnitTest/MockChatWindow.h +++ b/Swift/Controllers/UnitTest/MockChatWindow.h @@ -46,18 +46,19 @@ namespace Swift { 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*/, bool = true) {}; virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {} + virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}; std::string name_; std::string lastMessageBody_; std::vector<SecurityLabelsCatalog::Item> labels_; bool labelsEnabled_; SecurityLabelsCatalog::Item label_; }; } diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index dc89c21..c6519ba 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -726,23 +726,36 @@ void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction> } void QtChatWindow::setSubject(const std::string& subject) { //subject_->setVisible(!subject.empty()); subject_->setText(P2QSTRING(subject)); } 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* changeSubject = NULL; + QAction* configure = NULL; + QAction* affiliations = NULL; + QAction* destroy = NULL; + QAction* invite = NULL; + + foreach(ChatWindow::RoomAction availableAction, availableRoomActions_) + { + switch(availableAction) + { + case ChatWindow::ChangeSubject: changeSubject = contextMenu.addAction(tr("Change subject")); break; + case ChatWindow::Configure: configure = contextMenu.addAction(tr("Configure room")); break; + case ChatWindow::Affiliations: affiliations = contextMenu.addAction(tr("Edit affiliations")); break; + case ChatWindow::Destroy: destroy = contextMenu.addAction(tr("Destroy room")); break; + case ChatWindow::Invite: invite = contextMenu.addAction(tr("Invite person to this room")); break; + } + } + QAction* result = contextMenu.exec(QCursor::pos()); if (result == changeSubject) { bool ok; QString subject = QInputDialog::getText(this, tr("Change room subject"), tr("New subject:"), QLineEdit::Normal, subject_->text(), &ok); if (ok) { onChangeSubjectRequest(Q2PSTRING(subject)); } } else if (result == configure) { @@ -779,18 +792,23 @@ void QtChatWindow::handleActionButtonClicked() { void QtChatWindow::handleAffiliationEditorAccepted() { onChangeAffiliationsRequest(affiliationEditor_->getChanges()); } void QtChatWindow::setAffiliations(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids) { if (!affiliationEditor_) return; affiliationEditor_->setAffiliations(affiliation, jids); } +void QtChatWindow::setAvailableRoomActions(const std::vector<RoomAction> &actions) +{ + availableRoomActions_ = actions; +} + void QtChatWindow::showRoomConfigurationForm(Form::ref form) { 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))); } diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h index 9203068..189a12a 100644 --- a/Swift/QtUI/QtChatWindow.h +++ b/Swift/QtUI/QtChatWindow.h @@ -73,18 +73,19 @@ namespace Swift { void setMessageReceiptState(const std::string& id, ChatWindow::ReceiptState state); void flash(); QByteArray getSplitterState(); virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions); void setSubject(const std::string& subject); void showRoomConfigurationForm(Form::ref); void addMUCInvitation(const JID& jid, const std::string& reason, const std::string& password, bool direct = true); void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&); + void setAvailableRoomActions(const std::vector<RoomAction> &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: @@ -157,11 +158,12 @@ namespace Swift { QSplitter *logRosterSplitter_; Tristate correctionEnabled_; QString alertStyleSheet_; std::map<QString, QString> descriptions; QtFileTransferJSBridge* fileTransferJS; QPointer<QtMUCConfigurationWindow> mucConfigurationWindow_; QPointer<QtAffiliationEditor> affiliationEditor_; int idCounter_; SettingsProvider* settings_; + std::vector<ChatWindow::RoomAction> availableRoomActions_; }; } |