From 38b0cb785fea8eae5e48fae56440695fdfd10ee1 Mon Sep 17 00:00:00 2001
From: Tobias Markmann <tm@ayena.de>
Date: Mon, 29 Sep 2014 10:07:05 +0200
Subject: Disable online only actions when offline.

Disabling action, menu items and drag 'n' drop which require an online
connection when the user is offline.

Test-Information:
Checked by going offline and checking the relevant actions and menu items.

Change-Id: Iacfa2c9f815d3b9bbad9ca4c2d0d04f95ce9a9e4

diff --git a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
index 5fa264d..287c4b9 100644
--- a/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
+++ b/Swift/Controllers/Chat/UnitTest/MockChatListWindow.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Kevin Smith
+ * Copyright (c) 2011-2014 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -22,6 +22,7 @@ namespace Swift {
 			void setRecents(const std::list<ChatListWindow::Chat>& /*recents*/) {}
 			void setUnreadCount(int /*unread*/) {}
 			void clearBookmarks() {}
+			void setOnline(bool /*isOnline*/) {}
 	};
 
 }
diff --git a/Swift/Controllers/UIInterfaces/ChatListWindow.h b/Swift/Controllers/UIInterfaces/ChatListWindow.h
index f7eb151..5a7b527 100644
--- a/Swift/Controllers/UIInterfaces/ChatListWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatListWindow.h
@@ -89,6 +89,7 @@ namespace Swift {
 			virtual void setRecents(const std::list<Chat>& recents) = 0;
 			virtual void setUnreadCount(int unread) = 0;
 			virtual void clearBookmarks() = 0;
+			virtual void setOnline(bool isOnline) = 0;
 
 			boost::signal<void (const MUCBookmark&)> onMUCBookmarkActivated;
 			boost::signal<void (const Chat&)> onRecentActivated;
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.cpp b/Swift/QtUI/ChatList/QtChatListWindow.cpp
index 8e75f34..ea65dd6 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.cpp
+++ b/Swift/QtUI/ChatList/QtChatListWindow.cpp
@@ -29,7 +29,7 @@
 
 namespace Swift {
 
-QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent) {
+QtChatListWindow::QtChatListWindow(UIEventStream *uiEventStream, SettingsProvider* settings, QWidget* parent) : QTreeView(parent), isOnline_(false) {
 	eventStream_ = uiEventStream;
 	settings_ = settings;
 	bookmarksEnabled_ = false;
@@ -86,14 +86,14 @@ void QtChatListWindow::handleClicked(const QModelIndex& index) {
 
 void QtChatListWindow::setupContextMenus() {
 	mucMenu_ = new QMenu();
-	mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
-	mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark()));
-	mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark()));
+	onlineOnlyActions_ << mucMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
+	onlineOnlyActions_ << mucMenu_->addAction(tr("Edit Bookmark"), this, SLOT(handleEditBookmark()));
+	onlineOnlyActions_ << mucMenu_->addAction(tr("Remove Bookmark"), this, SLOT(handleRemoveBookmark()));
 	mucRecentsMenu_ = new QMenu();
-	mucRecentsMenu_->addAction(tr("Add to Bookmarks"), this, SLOT(handleAddBookmarkFromRecents()));
+	onlineOnlyActions_ << mucRecentsMenu_->addAction(tr("Add to Bookmarks"), this, SLOT(handleAddBookmarkFromRecents()));
 	mucRecentsMenu_->addAction(tr("Clear recents"), this, SLOT(handleClearRecentsRequested()));
 	emptyMenu_ = new QMenu();
-	emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
+	onlineOnlyActions_ << emptyMenu_->addAction(tr("Add New Bookmark"), this, SLOT(handleAddBookmark()));
 }
 
 void QtChatListWindow::handleItemActivated(const QModelIndex& index) {
@@ -143,6 +143,10 @@ void QtChatListWindow::setUnreadCount(int unread) {
 	emit onCountUpdated(unread);
 }
 
+void QtChatListWindow::setOnline(bool isOnline) {
+	isOnline_ = isOnline;
+}
+
 void QtChatListWindow::handleRemoveBookmark() {
 	ChatListMUCItem* mucItem = dynamic_cast<ChatListMUCItem*>(contextMenuItem_);
 	if (!mucItem) return;
@@ -182,6 +186,11 @@ void QtChatListWindow::contextMenuEvent(QContextMenuEvent* event) {
 	QModelIndex index = indexAt(event->pos());
 	ChatListItem* baseItem = index.isValid() ? static_cast<ChatListItem*>(index.internalPointer()) : NULL;
 	contextMenuItem_ = baseItem;
+
+	foreach(QAction* action, onlineOnlyActions_) {
+		action->setEnabled(isOnline_);
+	}
+
 	if (!baseItem) {
 		emptyMenu_->exec(QCursor::pos());
 		return;
diff --git a/Swift/QtUI/ChatList/QtChatListWindow.h b/Swift/QtUI/ChatList/QtChatListWindow.h
index 1cba3a4..823e6dc 100644
--- a/Swift/QtUI/ChatList/QtChatListWindow.h
+++ b/Swift/QtUI/ChatList/QtChatListWindow.h
@@ -28,6 +28,7 @@ namespace Swift {
 			void setRecents(const std::list<ChatListWindow::Chat>& recents);
 			void setUnreadCount(int unread);
 			void clearBookmarks();
+			virtual void setOnline(bool isOnline);
 
 		signals:
 			void onCountUpdated(int count);
@@ -56,6 +57,8 @@ namespace Swift {
 			QMenu* mucRecentsMenu_;
 			ChatListItem* contextMenuItem_;
 			SettingsProvider* settings_;
+			QList<QAction*> onlineOnlyActions_;
+			bool isOnline_;
 	};
 
 }
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index ed79dcc..68104b4 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -259,13 +259,17 @@ void QtChatWindow::handleKeyPressEvent(QKeyEvent* event) {
 	int key = event->key();
 	if (key == Qt::Key_Tab) {
 		tabComplete();
-	} else if ((key == Qt::Key_Up) && input_->toPlainText().isEmpty() && !(lastSentMessage_.isEmpty())) {
+	}
+	else if ((key == Qt::Key_Up) && input_->toPlainText().isEmpty() && !(lastSentMessage_.isEmpty())) {
 		beginCorrection();
-	} else if (key == Qt::Key_Down && isCorrection_ && input_->textCursor().atBlockEnd()) {
+	}
+	else if (key == Qt::Key_Down && isCorrection_ && input_->textCursor().atBlockEnd()) {
 		cancelCorrection();
-	} else if (key == Qt::Key_Down || key == Qt::Key_Up) {
+	}
+	else if (key == Qt::Key_Down || key == Qt::Key_Up) {
 		/* Drop */
-	} else {
+	}
+	else {
 		messageLog_->handleKeyPressEvent(event);
 	}
 }
@@ -274,7 +278,8 @@ void QtChatWindow::beginCorrection() {
 	boost::optional<AlertID> newCorrectingAlert;
 	if (correctionEnabled_ == ChatWindow::Maybe) {
 		newCorrectingAlert = addAlert(Q2PSTRING(tr("This chat may not support message correction. If you send a correction anyway, it may appear as a duplicate message")));
-	} else if (correctionEnabled_ == ChatWindow::No) {
+	}
+	else if (correctionEnabled_ == ChatWindow::No) {
 		newCorrectingAlert = addAlert(Q2PSTRING(tr("This chat does not support message correction.  If you send a correction anyway, it will appear as a duplicate message")));
 	}
 
@@ -330,7 +335,8 @@ void QtChatWindow::tabComplete() {
 	QTextCursor cursor;
 	if (tabCompleteCursor_.hasSelection()) {
 		cursor = tabCompleteCursor_;
-	} else {
+	}
+	else {
 		cursor = input_->textCursor();
 		while(cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor) && cursor.document()->characterAt(cursor.position() - 1) != ' ') { }
 	}
@@ -406,7 +412,8 @@ void QtChatWindow::setSecurityLabelsEnabled(bool enabled) {
 	if (enabled) {
 		labelsWidget_->setEnabled(true);
 		labelsWidget_->show();
-	} else {
+	}
+	else {
 		labelsWidget_->hide();
 	}
 }
@@ -498,7 +505,8 @@ void QtChatWindow::setName(const std::string& name) {
 void QtChatWindow::updateTitleWithUnreadCount() {
 	if (isWindow()) {
 		setWindowTitle(unreadCount_ > 0 ? QString("(%1) %2").arg(unreadCount_).arg(contact_) : contact_);
-	} else {
+	}
+	else {
 		setWindowTitle(contact_);
 	}
 	emit titleUpdated();
@@ -534,7 +542,8 @@ void QtChatWindow::handleInputChanged() {
 	}
 	if (input_->toPlainText().isEmpty()) {
 		onUserCancelsTyping();
-	} else {
+	}
+	else {
 		onUserTyping();
 	}
 }
@@ -574,14 +583,17 @@ void QtChatWindow::moveEvent(QMoveEvent*) {
 }
 
 void QtChatWindow::dragEnterEvent(QDragEnterEvent *event) {
-	if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) {
-		// TODO: check whether contact actually supports file transfer
-		if (!isMUC_) {
-			event->acceptProposedAction();
+	if (inputEnabled_) {
+		if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() == 1) {
+			// TODO: check whether contact actually supports file transfer
+			if (!isMUC_) {
+				event->acceptProposedAction();
+			}
 		}
-	} else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
-		if (isMUC_ || supportsImpromptuChat_) {
-			event->acceptProposedAction();
+		else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
+			if (isMUC_ || supportsImpromptuChat_) {
+				event->acceptProposedAction();
+			}
 		}
 	}
 }
@@ -590,13 +602,15 @@ void QtChatWindow::dropEvent(QDropEvent *event) {
 	if (fileTransferEnabled_ == ChatWindow::Yes && event->mimeData()->hasUrls()) {
 		if (event->mimeData()->urls().size() == 1) {
 			onSendFileRequest(Q2PSTRING(event->mimeData()->urls().at(0).toLocalFile()));
-		} else {
+		}
+		else {
 			std::string messageText(Q2PSTRING(tr("Sending of multiple files at once isn't supported at this time.")));
 			ChatMessage message;
 			message.append(boost::make_shared<ChatTextMessagePart>(messageText));
 			addSystemMessage(message, DefaultDirection);
 		}
-	} else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
+	}
+	else if (event->mimeData()->hasFormat("application/vnd.swift.contact-jid-list")) {
 		QByteArray dataBytes = event->mimeData()->data("application/vnd.swift.contact-jid-list");
 		QDataStream dataStream(&dataBytes, QIODevice::ReadOnly);
 		std::vector<JID> invites;
@@ -634,15 +648,20 @@ void QtChatWindow::handleActionButtonClicked() {
 	if (availableRoomActions_.empty()) {
 		if (blockingState_ == IsBlocked) {
 			unblock = contextMenu.addAction(tr("Unblock"));
-		} else if (blockingState_ == IsUnblocked) {
+			unblock->setEnabled(inputEnabled_);
+		}
+		else if (blockingState_ == IsUnblocked) {
 			block = contextMenu.addAction(tr("Block"));
+			block->setEnabled(inputEnabled_);
 		}
 
 		if (supportsImpromptuChat_) {
 			invite = contextMenu.addAction(tr("Invite person to this chat…"));
+			invite->setEnabled(inputEnabled_);
 		}
 
-	} else {
+	}
+	else {
 		foreach(ChatWindow::RoomAction availableAction, availableRoomActions_)
 		{
 			if (impromptu_) {
@@ -656,16 +675,32 @@ void QtChatWindow::handleActionButtonClicked() {
 			}
 			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;
+				case ChatWindow::ChangeSubject:
+					changeSubject = contextMenu.addAction(tr("Change subject…"));
+					changeSubject->setEnabled(inputEnabled_);
+					break;
+				case ChatWindow::Configure:
+					configure = contextMenu.addAction(tr("Configure room…"));
+					configure->setEnabled(inputEnabled_);
+					break;
+				case ChatWindow::Affiliations:
+					affiliations = contextMenu.addAction(tr("Edit affiliations…"));
+					affiliations->setEnabled(inputEnabled_);
+					break;
+				case ChatWindow::Destroy:
+					destroy = contextMenu.addAction(tr("Destroy room"));
+					destroy->setEnabled(inputEnabled_);
+					break;
+				case ChatWindow::Invite:
+					invite = contextMenu.addAction(tr("Invite person to this room…"));
+					invite->setEnabled(inputEnabled_);
+					break;
 			}
 		}
 	}
 
 	QAction* bookmark = contextMenu.addAction(tr("Add boomark..."));
+	bookmark->setEnabled(inputEnabled_);
 
 	QAction* result = contextMenu.exec(QCursor::pos());
 	if (result == NULL) {
@@ -708,7 +743,8 @@ void QtChatWindow::handleActionButtonClicked() {
 	}
 	else if (result == unblock) {
 		onUnblockUserRequest();
-	} else if (result == bookmark) {
+	}
+	else if (result == bookmark) {
 		onBookmarkRequest();
 	}
 }
diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp
index 1db8c77..52b6bcc 100644
--- a/Swift/QtUI/QtMainWindow.cpp
+++ b/Swift/QtUI/QtMainWindow.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -150,9 +150,11 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
 	QAction* editProfileAction = new QAction(tr("Edit &Profile…"), this);
 	connect(editProfileAction, SIGNAL(triggered()), SLOT(handleEditProfileAction()));
 	actionsMenu->addAction(editProfileAction);
+	onlineOnlyActions_ << editProfileAction;
 	QAction* joinMUCAction = new QAction(tr("Enter &Room…"), this);
 	connect(joinMUCAction, SIGNAL(triggered()), SLOT(handleJoinMUCAction()));
 	actionsMenu->addAction(joinMUCAction);
+	onlineOnlyActions_ << joinMUCAction;
 #ifdef SWIFT_EXPERIMENTAL_HISTORY
 	QAction* viewLogsAction = new QAction(tr("&View History…"), this);
 	connect(viewLogsAction, SIGNAL(triggered()), SLOT(handleViewLogsAction()));
@@ -161,25 +163,30 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
 	openBlockingListEditor_ = new QAction(tr("Edit &Blocking List…"), this);
 	connect(openBlockingListEditor_, SIGNAL(triggered()), SLOT(handleEditBlockingList()));
 	actionsMenu->addAction(openBlockingListEditor_);
+	onlineOnlyActions_ << openBlockingListEditor_;
 	openBlockingListEditor_->setVisible(false);
 	addUserAction_ = new QAction(tr("&Add Contact…"), this);
 	addUserAction_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D));
 	addUserAction_->setShortcutContext(Qt::ApplicationShortcut);
 	connect(addUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleAddUserActionTriggered(bool)));
 	actionsMenu->addAction(addUserAction_);
+	onlineOnlyActions_ << addUserAction_;
 	editUserAction_ = new QAction(tr("&Edit Selected Contact…"), this);
 	connect(editUserAction_, SIGNAL(triggered(bool)), treeWidget_, SLOT(handleEditUserActionTriggered(bool)));
 	actionsMenu->addAction(editUserAction_);
+	onlineOnlyActions_ << editUserAction_;
 	editUserAction_->setEnabled(false);
 	chatUserAction_ = new QAction(tr("Start &Chat…"), this);
 	chatUserAction_->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
 	chatUserAction_->setShortcutContext(Qt::ApplicationShortcut);
 	connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool)));
 	actionsMenu->addAction(chatUserAction_);
+	onlineOnlyActions_ << chatUserAction_;
 	if (enableAdHocCommandOnJID) {
 		otherAdHocAction_ = new QAction(tr("Run Other Command"), this);
 		connect(otherAdHocAction_, SIGNAL(triggered()), this, SLOT(handleOtherAdHocActionTriggered()));
 		actionsMenu->addAction(otherAdHocAction_);
+		onlineOnlyActions_ << otherAdHocAction_;
 	}
 	serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this);
 	actionsMenu->addMenu(serverAdHocMenu_);
@@ -196,7 +203,7 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr
 	QList< QAction* > generalMenuActions = loginMenus_.generalMenu->actions();
 	loginMenus_.generalMenu->insertAction(generalMenuActions.at(generalMenuActions.count()-2),toggleRequestDeliveryReceipts_);
 
-	treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QAction::setEnabled, editUserAction_, _1));
+	treeWidget_->onSomethingSelectedChanged.connect(boost::bind(&QtMainWindow::handleSomethingSelectedChanged, this, _1));
 
 	setAvailableAdHocCommands(std::vector<DiscoItems::Item>());
 	QAction* adHocAction = new QAction(tr("Collecting commands..."), this);
@@ -227,6 +234,11 @@ void QtMainWindow::handleEditBlockingList() {
 	uiEventStream_->send(boost::make_shared<RequestBlockListDialogUIEvent>());
 }
 
+void QtMainWindow::handleSomethingSelectedChanged(bool itemSelected) {
+	bool isOnline = addUserAction_->isEnabled();
+	editUserAction_->setEnabled(isOnline && itemSelected);
+}
+
 QtEventWindow* QtMainWindow::getEventWindow() {
 	return eventWindow_;
 }
@@ -348,6 +360,13 @@ void QtMainWindow::setMyStatusText(const std::string& status) {
 
 void QtMainWindow::setMyStatusType(StatusShow::Type type) {
 	meView_->setStatusType(type);
+	const bool online = (type != StatusShow::None);
+	treeWidget_->setOnline(online);
+	chatListWindow_->setOnline(online);
+	foreach (QAction *action, onlineOnlyActions_) {
+		action->setEnabled(online);
+	}
+	serverAdHocMenu_->setEnabled(online);
 }
 
 void QtMainWindow::setMyContactRosterItem(boost::shared_ptr<ContactRosterItem> contact) {
diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h
index 84fab15..ea92c79 100644
--- a/Swift/QtUI/QtMainWindow.h
+++ b/Swift/QtUI/QtMainWindow.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -78,6 +78,7 @@ namespace Swift {
 			void handleToggleRequestDeliveryReceipts(bool enabled);
 			void handleShowCertificateInfo();
 			void handleEditBlockingList();
+			void handleSomethingSelectedChanged(bool itemSelected);
 
 		private:
 			SettingsProvider* settings_;
@@ -104,5 +105,6 @@ namespace Swift {
 			UIEventStream* uiEventStream_;
 			std::vector<DiscoItems::Item> serverAdHocCommands_;
 			QList<QAction*> serverAdHocCommandActions_;
+			QList<QAction*> onlineOnlyActions_;
 	};
 }
diff --git a/Swift/QtUI/QtNameWidget.cpp b/Swift/QtUI/QtNameWidget.cpp
index 08e32f5..c172caa 100644
--- a/Swift/QtUI/QtNameWidget.cpp
+++ b/Swift/QtUI/QtNameWidget.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Remko Tronçon
+ * Copyright (c) 2010-2014 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -17,7 +17,7 @@
 
 namespace Swift {
 
-QtNameWidget::QtNameWidget(SettingsProvider* settings, QWidget *parent) : QWidget(parent), settings(settings) {
+QtNameWidget::QtNameWidget(SettingsProvider* settings, QWidget *parent) : QWidget(parent), settings(settings), isOnline_(false) {
 	QHBoxLayout* mainLayout = new QHBoxLayout(this);
 	mainLayout->setSpacing(0);
 	mainLayout->setContentsMargins(0,0,0,0);
@@ -41,6 +41,10 @@ void QtNameWidget::setJID(const QString& jid) {
 	updateText();
 }
 
+void QtNameWidget::setOnline(const bool isOnline) {
+	isOnline_ = isOnline;
+}
+
 void QtNameWidget::mousePressEvent(QMouseEvent* event) {
 	QMenu menu;
 	bool hasNick = !nick.isEmpty();
@@ -62,6 +66,7 @@ void QtNameWidget::mousePressEvent(QMouseEvent* event) {
 
 	QAction* editProfile = new QAction(tr("Edit Profile"), this);
 	menu.addAction(editProfile);
+	editProfile->setEnabled(isOnline_);
 
 	QAction* result = menu.exec(event->globalPos());
 	if (result == showAsJID) {
diff --git a/Swift/QtUI/QtNameWidget.h b/Swift/QtUI/QtNameWidget.h
index 3225879..460cc9a 100644
--- a/Swift/QtUI/QtNameWidget.h
+++ b/Swift/QtUI/QtNameWidget.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2014 Remko Tronçon
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -20,6 +20,7 @@ namespace Swift {
 
 			void setNick(const QString& text);
 			void setJID(const QString& jid);
+			void setOnline(const bool isOnline);
 
 		signals:
 			void onChangeNickRequest();
@@ -39,6 +40,7 @@ namespace Swift {
 			QtElidingLabel* textLabel;
 			QString jid;
 			QString nick;
+			bool isOnline_;
 	};
 }
 
diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp
index 69a0ef6..d5029ad 100644
--- a/Swift/QtUI/QtRosterHeader.cpp
+++ b/Swift/QtUI/QtRosterHeader.cpp
@@ -82,6 +82,14 @@ void QtRosterHeader::setStatusText(const QString& statusMessage) {
 
 void QtRosterHeader::setStatusType(StatusShow::Type type) {
 	statusWidget_->setStatusType(type);
+	if (type == StatusShow::None) {
+		nameWidget_->setOnline(false);
+		disconnect(avatarLabel_, SIGNAL(clicked()), this, SIGNAL(onEditProfileRequest()));
+	}
+	else {
+		nameWidget_->setOnline(true);
+		connect(avatarLabel_, SIGNAL(clicked()), this, SIGNAL(onEditProfileRequest()), Qt::UniqueConnection);
+	}
 }
 
 void QtRosterHeader::setConnecting() {
diff --git a/Swift/QtUI/Roster/QtRosterWidget.cpp b/Swift/QtUI/Roster/QtRosterWidget.cpp
index 4a3c9f3..8c296e5 100644
--- a/Swift/QtUI/Roster/QtRosterWidget.cpp
+++ b/Swift/QtUI/Roster/QtRosterWidget.cpp
@@ -60,33 +60,38 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
 	QMenu contextMenu;
 	if (ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item)) {
 		QAction* editContact = contextMenu.addAction(tr("Edit…"));
+		editContact->setEnabled(isOnline());
 		QAction* removeContact = contextMenu.addAction(tr("Remove"));
+		removeContact->setEnabled(isOnline());
 		QAction* showProfileForContact = contextMenu.addAction(tr("Show Profile"));
 
 		QAction* unblockContact = NULL;
 		if (contact->blockState() == ContactRosterItem::IsBlocked ||
 			contact->blockState() == ContactRosterItem::IsDomainBlocked) {
 			unblockContact = contextMenu.addAction(tr("Unblock"));
+			unblockContact->setEnabled(isOnline());
 		}
 
 		QAction* blockContact = NULL;
 		if (contact->blockState() == ContactRosterItem::IsUnblocked) {
 			blockContact = contextMenu.addAction(tr("Block"));
+			blockContact->setEnabled(isOnline());
 		}
 
 #ifdef SWIFT_EXPERIMENTAL_FT
 		QAction* sendFile = NULL;
 		if (contact->supportsFeature(ContactRosterItem::FileTransferFeature)) {
 			sendFile = contextMenu.addAction(tr("Send File"));
+			sendFile->setEnabled(isOnline());
 		}
 #endif
 #ifdef SWIFT_EXPERIMENTAL_WB
 		QAction* startWhiteboardChat = NULL;
 		if (contact->supportsFeature(ContactRosterItem::WhiteboardFeature)) {
 			startWhiteboardChat = contextMenu.addAction(tr("Start Whiteboard Chat"));
+			startWhiteboardChat->setEnabled(isOnline());
 		}
 #endif
-
 		QAction* result = contextMenu.exec(event->globalPos());
 		if (result == editContact) {
 			eventStream_->send(boost::make_shared<RequestContactEditorUIEvent>(contact->getJID()));
@@ -135,6 +140,9 @@ void QtRosterWidget::contextMenuEvent(QContextMenuEvent* event) {
 		if (P2QSTRING(group->getDisplayName()) == tr("Contacts")) {
 			renameGroupAction->setEnabled(false);
 		}
+		else {
+			renameGroupAction->setEnabled(isOnline());
+		}
 		QAction* result = contextMenu.exec(event->globalPos());
 		if (result == renameGroupAction) {
 			renameGroup(group);
diff --git a/Swift/QtUI/Roster/QtTreeWidget.cpp b/Swift/QtUI/Roster/QtTreeWidget.cpp
index 5333260..f296088 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.cpp
+++ b/Swift/QtUI/Roster/QtTreeWidget.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012 Kevin Smith
+ * Copyright (c) 2010-2014 Kevin Smith
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
@@ -252,4 +252,12 @@ JID QtTreeWidget::selectedJID() const {
 	return jidFromIndex(list[0]);
 }
 
+void QtTreeWidget::setOnline(bool isOnline) {
+	isOnline_ = isOnline;
+}
+
+bool QtTreeWidget::isOnline() const {
+	return isOnline_;
+}
+
 }
diff --git a/Swift/QtUI/Roster/QtTreeWidget.h b/Swift/QtUI/Roster/QtTreeWidget.h
index cf2f73e..12d34f5 100644
--- a/Swift/QtUI/Roster/QtTreeWidget.h
+++ b/Swift/QtUI/Roster/QtTreeWidget.h
@@ -36,6 +36,8 @@ class QtTreeWidget : public QTreeView {
 		void setMessageTarget(MessageTarget messageTarget);
 		JID jidFromIndex(const QModelIndex& index) const;
 		JID selectedJID() const;
+		void setOnline(bool isOnline);
+
 	public:
 		boost::signal<void (RosterItem*)> onSomethingSelectedChanged;
 
@@ -54,6 +56,7 @@ class QtTreeWidget : public QTreeView {
 		void dragMoveEvent(QDragMoveEvent* event);
 		bool event(QEvent* event);
 		QModelIndexList getSelectedIndexes() const;
+		bool isOnline() const;
 
 	private:
 		void drawBranches(QPainter*, const QRect&, const QModelIndex&) const;
@@ -71,6 +74,7 @@ class QtTreeWidget : public QTreeView {
 		SettingsProvider* settings_;
 		bool tooltipShown_;
 		MessageTarget messageTarget_;
+		bool isOnline_;
 };
 
 }
-- 
cgit v0.10.2-6-g49f6