From 2680416456d722a4779322949f6ed230de3d422b Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Mon, 26 Sep 2011 15:27:49 +0100
Subject: Allow setting of room topics


diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index 19d7b4d..ca1509e 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -71,6 +71,7 @@ MUCController::MUCController (
 	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));
 	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));
@@ -341,6 +342,7 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes
 
 	if (!message->getSubject().empty() && message->getBody().empty()) {
 		chatWindow_->addSystemMessage(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject()));;
+		chatWindow_->setSubject(message->getSubject());
 		doneGettingHistory_ = true;
 	}
 
@@ -570,4 +572,8 @@ std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart
 	return result;
 }
 
+void MUCController::handleChangeSubjectRequest(const std::string& subject) {
+	muc_->changeSubject(subject);
+}
+
 }
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 39e5fa4..fc87738 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -76,6 +76,7 @@ namespace Swift {
 			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);
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index b90efd9..39fb7f8 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -71,6 +71,7 @@ namespace Swift {
 			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;
 			/**
 			 * Set an alert on the window.
 			 * @param alertText Description of alert (required).
@@ -95,6 +96,7 @@ namespace Swift {
 			boost::signal<void ()> onAlertButtonClicked;
 			boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged;
 			boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected;
+			boost::signal<void (const std::string&)> onChangeSubjectRequest;
 			
 			// File transfer related
 			boost::signal<void (std::string /* id */)> onFileTransferCancel;
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index b410c69..143e281 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -46,6 +46,7 @@ namespace Swift {
 			virtual void cancelAlert() {};
 			virtual void setCorrectionEnabled(Tristate /*enabled*/) {}
 			void setAvailableOccupantActions(const std::vector<OccupantAction>&/* actions*/) {}
+			void setSubject(const std::string& /*subject*/) {}
 
 			boost::signal<void ()> onClosed;
 			boost::signal<void ()> onAllMessagesRead;
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index fa039de..760e481 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -41,6 +41,7 @@
 #include <QUrl>
 #include <QPushButton>
 #include <QFileDialog>
+#include <QMenu>
 
 #include <QDebug>
 
@@ -80,6 +81,21 @@ QtChatWindow::QtChatWindow(const QString &contact, QtChatTheme* theme, UIEventSt
 	alertLabel_->setStyleSheet(alertStyleSheet_);
 	alertWidget_->hide();
 
+	QBoxLayout* subjectLayout = new QBoxLayout(QBoxLayout::LeftToRight);
+	subject_ = new QLineEdit(this);
+	subjectLayout->addWidget(subject_);
+	setSubject("");
+	subject_->setReadOnly(true);
+
+	actionButton_ = new QPushButton(tr("Actions"), this);
+	connect(actionButton_, SIGNAL(clicked()), this, SLOT(handleActionButtonClicked()));
+	subjectLayout->addWidget(actionButton_);
+
+	subject_->hide();
+	actionButton_->hide();
+
+	layout->addLayout(subjectLayout);
+
 	logRosterSplitter_ = new QSplitter(this);
 	logRosterSplitter_->setAutoFillBackground(true);
 	layout->addWidget(logRosterSplitter_);
@@ -330,11 +346,11 @@ void QtChatWindow::closeEvent(QCloseEvent* event) {
 void QtChatWindow::convertToMUC() {
 	setAcceptDrops(false);
 	treeWidget_->show();
+	subject_->show();
+	actionButton_->show();
 }
 
-void QtChatWindow::qAppFocusChanged(QWidget *old, QWidget *now) {
-	Q_UNUSED(old);
-	Q_UNUSED(now);
+void QtChatWindow::qAppFocusChanged(QWidget* /*old*/, QWidget* /*now*/) {
 	if (isWidgetSelected()) {
 		lastLineTracker_.setHasFocus(true);
 		input_->setFocus();
@@ -669,4 +685,22 @@ void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction>
 	treeWidget_->setAvailableOccupantActions(actions);
 }
 
+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* 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));
+		}
+	}
+}
+
 }
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index f0c078c..b8fa478 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -68,6 +68,7 @@ namespace Swift {
 			void flash();
 			QByteArray getSplitterState();
 			virtual void setAvailableOccupantActions(const std::vector<OccupantAction>& actions);
+			void setSubject(const std::string& subject);
 
 		public slots:
 			void handleChangeSplitterState(QByteArray state);
@@ -99,6 +100,7 @@ namespace Swift {
 			void handleKeyPressEvent(QKeyEvent* event);
 			void handleSplitterMoved(int pos, int index);
 			void handleAlertButtonClicked();
+			void handleActionButtonClicked();
 
 			
 			void handleFileTransferCancel(QString id);
@@ -129,6 +131,8 @@ namespace Swift {
 			QWidget* alertWidget_;
 			QPushButton* alertButton_;
 			TabComplete* completer_;
+			QLineEdit* subject_;
+			QPushButton* actionButton_;
 			std::vector<SecurityLabelsCatalog::Item> availableLabels_;
 			bool isCorrection_;
 			bool previousMessageWasSelf_;
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 4b3960f..59917f9 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -15,6 +15,7 @@
 #include <Swiften/Client/StanzaChannel.h>
 #include <Swiften/Queries/IQRouter.h>
 #include <Swiften/Elements/Form.h>
+#include <Swiften/Elements/Message.h>
 #include <Swiften/Elements/IQ.h>
 #include <Swiften/Elements/MUCUserPayload.h>
 #include <Swiften/Elements/MUCAdminPayload.h>
@@ -235,6 +236,14 @@ void MUC::handleKickResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref
 	}
 }
 
+void MUC::changeSubject(const std::string& subject) {
+	Message::ref message = boost::make_shared<Message>();
+	message->setSubject(subject);
+	message->setType(Message::Groupchat);
+	message->setTo(ownMUCJID.toBare());
+	stanzaChannel->sendMessage(message);
+}
+
 //FIXME: Recognise Topic changes
 
 //TODO: Invites(direct/mediated)
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 41dbc4a..26247c5 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -56,6 +56,7 @@ namespace Swift {
 			MUCOccupant getOccupant(const std::string& nick);
 			bool hasOccupant(const std::string& nick);
 			void kickUser(const JID& jid);
+			void changeSubject(const std::string& subject);
 		public:
 			boost::signal<void (const std::string& /*nick*/)> onJoinComplete;
 			boost::signal<void (ErrorPayload::ref)> onJoinFailed;
-- 
cgit v0.10.2-6-g49f6