diff options
| author | Richard Maudsley <richard.maudsley@isode.com> | 2014-05-02 09:19:23 (GMT) | 
|---|---|---|
| committer | Swift Review <review@swift.im> | 2014-07-09 09:03:34 (GMT) | 
| commit | acac7962ba04c083377f62f4265ecc754176f74e (patch) | |
| tree | fa2db718854d10c76e81fc54b0b1f2b33a12963f | |
| parent | 8ab7ca17fdde8f8fb62a0c574478aa2c4c01a9bc (diff) | |
| download | swift-contrib-acac7962ba04c083377f62f4265ecc754176f74e.zip swift-contrib-acac7962ba04c083377f62f4265ecc754176f74e.tar.bz2 | |
Refactor AdHoc forms.
Test-Information:
Check that forms still open properly and can be submitted and canceled. Check that error message is displayed if disconnected when a form is open.
Change-Id: I23e35730b0decdfb5cf0592fc7234bf4643b6127
| -rw-r--r-- | Swift/Controllers/AdHocController.cpp | 31 | ||||
| -rw-r--r-- | Swift/Controllers/AdHocController.h | 28 | ||||
| -rw-r--r-- | Swift/Controllers/AdHocManager.cpp | 20 | ||||
| -rw-r--r-- | Swift/Controllers/AdHocManager.h | 50 | ||||
| -rw-r--r-- | Swift/Controllers/MainController.cpp | 5 | ||||
| -rw-r--r-- | Swift/Controllers/SConscript | 1 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/AdHocCommandWindow.h | 6 | ||||
| -rw-r--r-- | Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h | 9 | ||||
| -rw-r--r-- | Swift/QtUI/QtAdHocCommandWindow.cpp | 28 | ||||
| -rw-r--r-- | Swift/QtUI/QtAdHocCommandWindow.h | 3 | ||||
| -rw-r--r-- | Swift/QtUI/QtUIFactory.cpp | 6 | ||||
| -rw-r--r-- | Swift/QtUI/QtUIFactory.h | 4 | 
12 files changed, 149 insertions, 42 deletions
| diff --git a/Swift/Controllers/AdHocController.cpp b/Swift/Controllers/AdHocController.cpp new file mode 100644 index 0000000..c017120 --- /dev/null +++ b/Swift/Controllers/AdHocController.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2014 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <boost/bind.hpp> +#include <Swift/Controllers/AdHocController.h> +#include <Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h> + +namespace Swift { + +AdHocController::AdHocController(AdHocCommandWindowFactory* factory, boost::shared_ptr<OutgoingAdHocCommandSession> command) { +	window_ = factory->createAdHocCommandWindow(command); +	window_->onClosing.connect(boost::bind(&AdHocController::handleWindowClosed, this)); +} + +AdHocController::~AdHocController() { +	window_->onClosing.disconnect(boost::bind(&AdHocController::handleWindowClosed, this)); +	delete window_; +} + +void AdHocController::setOnline(bool online) { +	window_->setOnline(online); +} + +void AdHocController::handleWindowClosed() { +	onDeleting(); +} + +} diff --git a/Swift/Controllers/AdHocController.h b/Swift/Controllers/AdHocController.h new file mode 100644 index 0000000..910756f --- /dev/null +++ b/Swift/Controllers/AdHocController.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010-2014 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <Swiften/AdHoc/OutgoingAdHocCommandSession.h> + +namespace Swift { + +class AdHocCommandWindowFactory; +class AdHocCommandWindow; + +class AdHocController { +public: +	AdHocController(AdHocCommandWindowFactory* factory, boost::shared_ptr<OutgoingAdHocCommandSession> command); +	~AdHocController(); +	boost::signal<void ()> onDeleting; +	void setOnline(bool online); +private: +	void handleWindowClosed(); +	AdHocCommandWindow* window_; +}; + +} diff --git a/Swift/Controllers/AdHocManager.cpp b/Swift/Controllers/AdHocManager.cpp index e926138..59e139b 100644 --- a/Swift/Controllers/AdHocManager.cpp +++ b/Swift/Controllers/AdHocManager.cpp @@ -1,70 +1,86 @@  /* - * 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.   */  #include <Swift/Controllers/AdHocManager.h>  #include <boost/bind.hpp>  #include <boost/shared_ptr.hpp>  #include <boost/smart_ptr/make_shared.hpp>  #include <Swiften/Base/foreach.h>  #include <Swiften/Queries/IQRouter.h>  #include <Swiften/AdHoc/OutgoingAdHocCommandSession.h>  #include <Swift/Controllers/UIInterfaces/MainWindow.h>  #include <Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h>  #include <Swift/Controllers/UIEvents/UIEventStream.h>  #include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h>  namespace Swift {  AdHocManager::AdHocManager(const JID& jid, AdHocCommandWindowFactory* factory, IQRouter* iqRouter, UIEventStream* uiEventStream, MainWindow* mainWindow) : jid_(jid) {  	iqRouter_ = iqRouter;  	uiEventStream_ = uiEventStream;  	mainWindow_ = mainWindow;  	factory_ = factory;  	uiEventStream_->onUIEvent.connect(boost::bind(&AdHocManager::handleUIEvent, this, _1));  }  AdHocManager::~AdHocManager() {  	uiEventStream_->onUIEvent.disconnect(boost::bind(&AdHocManager::handleUIEvent, this, _1)); +	for (size_t i = 0; i < controllers_.size(); ++i) { +		controllers_[i]->onDeleting.disconnect(boost::bind(&AdHocManager::removeController, this, controllers_[i])); +	} +} + +void AdHocManager::removeController(boost::shared_ptr<AdHocController> controller) { +	controller->onDeleting.disconnect(boost::bind(&AdHocManager::removeController, this, controller)); +	controllers_.erase(std::find(controllers_.begin(), controllers_.end(), controller));  }  void AdHocManager::setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info) {  	if (iqRouter_->isAvailable() && info->hasFeature(DiscoInfo::CommandsFeature)) {  		if (discoItemsRequest_) {  			discoItemsRequest_->onResponse.disconnect(boost::bind(&AdHocManager::handleServerDiscoItemsResponse, this, _1, _2));  			discoItemsRequest_.reset();  		}  		discoItemsRequest_ = GetDiscoItemsRequest::create(JID(jid_.getDomain()), DiscoInfo::CommandsFeature, iqRouter_);  		discoItemsRequest_->onResponse.connect(boost::bind(&AdHocManager::handleServerDiscoItemsResponse, this, _1, _2));  		discoItemsRequest_->send();  	} else {  		mainWindow_->setAvailableAdHocCommands(std::vector<DiscoItems::Item>());  	} +} +void AdHocManager::setOnline(bool online) { +	foreach (boost::shared_ptr<AdHocController> controller, controllers_) { +		controller->setOnline(online); +	}  }  void AdHocManager::handleServerDiscoItemsResponse(boost::shared_ptr<DiscoItems> items, ErrorPayload::ref error) {  	std::vector<DiscoItems::Item> commands;  	if (!error) {  		foreach (DiscoItems::Item item, items->getItems()) {  			if (item.getNode() != "http://isode.com/xmpp/commands#test") {  				commands.push_back(item);  			}  		}  	}  	mainWindow_->setAvailableAdHocCommands(commands);  }  void AdHocManager::handleUIEvent(boost::shared_ptr<UIEvent> event) {  	boost::shared_ptr<RequestAdHocUIEvent> adHocEvent = boost::dynamic_pointer_cast<RequestAdHocUIEvent>(event);  	if (adHocEvent) { -		factory_->createAdHocCommandWindow(boost::make_shared<OutgoingAdHocCommandSession>(adHocEvent->getCommand().getJID(), adHocEvent->getCommand().getNode(), iqRouter_)); +		boost::shared_ptr<OutgoingAdHocCommandSession> command = boost::make_shared<OutgoingAdHocCommandSession>(adHocEvent->getCommand().getJID(), adHocEvent->getCommand().getNode(), iqRouter_); +		boost::shared_ptr<AdHocController> controller = boost::make_shared<AdHocController>(factory_, command); +		controller->onDeleting.connect(boost::bind(&AdHocManager::removeController, this, controller)); +		controllers_.push_back(controller);  	}  }  } diff --git a/Swift/Controllers/AdHocManager.h b/Swift/Controllers/AdHocManager.h index 47b03cd..b2c34c5 100644 --- a/Swift/Controllers/AdHocManager.h +++ b/Swift/Controllers/AdHocManager.h @@ -1,40 +1,44 @@  /* - * 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.   */ -#pragma once - -#include <boost/shared_ptr.hpp>  #include <vector>  #include <Swiften/Base/boost_bsignals.h>  #include <Swiften/JID/JID.h>  #include <Swiften/Elements/DiscoInfo.h>  #include <Swiften/Elements/DiscoItems.h>  #include <Swiften/Elements/ErrorPayload.h>  #include <Swiften/Disco/GetDiscoItemsRequest.h> +#include <Swiften/Client/Client.h>  #include <Swift/Controllers/UIEvents/UIEvent.h> +#include <Swift/Controllers/AdHocController.h>  namespace Swift { -	class IQRouter; -	class MainWindow; -	class UIEventStream; -	class AdHocCommandWindowFactory; -	class AdHocManager { -		public: -			AdHocManager(const JID& jid, AdHocCommandWindowFactory* factory, IQRouter* iqRouter, UIEventStream* uiEventStream, MainWindow* mainWindow); -			~AdHocManager(); -			void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info); -		private: -			void handleUIEvent(boost::shared_ptr<UIEvent> event); -			void handleServerDiscoItemsResponse(boost::shared_ptr<DiscoItems>, ErrorPayload::ref error); -			JID jid_; -			IQRouter* iqRouter_; -			UIEventStream* uiEventStream_; -			MainWindow* mainWindow_; -			AdHocCommandWindowFactory* factory_; -			GetDiscoItemsRequest::ref discoItemsRequest_; -	}; +class IQRouter; +class MainWindow; +class UIEventStream; +class AdHocCommandWindowFactory; +class AdHocManager { +public: +	AdHocManager(const JID& jid, AdHocCommandWindowFactory* factory, IQRouter* iqRouter, UIEventStream* uiEventStream, MainWindow* mainWindow); +	~AdHocManager(); +	void removeController(boost::shared_ptr<AdHocController> contoller); +	void setServerDiscoInfo(boost::shared_ptr<DiscoInfo> info); +	void setOnline(bool online); +private: +	void handleServerDiscoItemsResponse(boost::shared_ptr<DiscoItems>, ErrorPayload::ref error); +	void handleUIEvent(boost::shared_ptr<UIEvent> event); +	boost::signal<void (const AdHocController&)> onControllerComplete; +	JID jid_; +	IQRouter* iqRouter_; +	UIEventStream* uiEventStream_; +	MainWindow* mainWindow_; +	AdHocCommandWindowFactory* factory_; +	GetDiscoItemsRequest::ref discoItemsRequest_; +	std::vector<boost::shared_ptr<AdHocController> > controllers_; +}; +  } diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index f16f8ad..79b7502 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -390,71 +390,71 @@ void MainController::handleConnected() {  #endif  #ifdef SWIFT_EXPERIMENTAL_WB  		discoInfo.addFeature(DiscoInfo::WhiteboardFeature);  #endif  		discoInfo.addFeature(DiscoInfo::MessageDeliveryReceiptsFeature);  		client_->getDiscoManager()->setCapsNode(CLIENT_NODE);  		client_->getDiscoManager()->setDiscoInfo(discoInfo);  		userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithRoster_, client_->getAvatarManager(), client_->getPresenceOracle());  		userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, client_->getVCardManager(), uiFactory_, client_->getIQRouter(), rosterController_, contactSuggesterWithoutRoster_, client_->getAvatarManager(), client_->getPresenceOracle());  		adHocManager_ = new AdHocManager(JID(boundJID_.getDomain()), uiFactory_, client_->getIQRouter(), uiEventStream_, rosterController_->getWindow());  		chatsManager_->onImpromptuMUCServiceDiscovered.connect(boost::bind(&UserSearchController::setCanInitiateImpromptuMUC, userSearchControllerChat_, _1));  	}  	loginWindow_->setIsLoggingIn(false);  	client_->requestRoster();  	GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(JID(boundJID_.getDomain()), client_->getIQRouter());  	discoInfoRequest->onResponse.connect(boost::bind(&MainController::handleServerDiscoInfoResponse, this, _1, _2));  	discoInfoRequest->send();  	client_->getVCardManager()->requestOwnVCard();  	rosterController_->setJID(boundJID_);  	rosterController_->setEnabled(true);  	rosterController_->getWindow()->setStreamEncryptionStatus(client_->isStreamEncrypted());  	profileController_->setAvailable(true);  	contactEditController_->setAvailable(true);  	/* Send presence later to catch all the incoming presences. */  	sendPresence(statusTracker_->getNextPresence());  	/* Enable chats last of all, so rejoining MUCs has the right sent presence */  	assert(chatsManager_);  	chatsManager_->setOnline(true); - +	adHocManager_->setOnline(true);  }  void MainController::handleEventQueueLengthChange(int count) {  	dock_->setNumberOfPendingMessages(count);  }  void MainController::reconnectAfterError() {  	if (reconnectTimer_) {  		reconnectTimer_->stop();  	}  	performLoginFromCachedCredentials();  }  void MainController::handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText) {  	boost::shared_ptr<Presence> presence(new Presence());  	if (show == StatusShow::None) {  		// Note: this is misleading, None doesn't mean unavailable on the wire.  		presence->setType(Presence::Unavailable);  		resetPendingReconnects();  		myStatusLooksOnline_ = false;  		offlineRequested_ = true;  	}  	else {  		offlineRequested_ = false;  		presence->setShow(show);  	}  	presence->setStatus(statusText);  	statusTracker_->setRequestedPresence(presence);  	if (presence->getType() != Presence::Unavailable) {  		profileSettings_->storeInt("lastShow", presence->getShow());  		profileSettings_->storeString("lastStatus", presence->getStatus());  	}  	if (presence->getType() != Presence::Unavailable && !client_->isAvailable()) {  		performLoginFromCachedCredentials();  	} else { @@ -570,70 +570,73 @@ void MainController::performLoginFromCachedCredentials() {  		client_->onConnected.connect(boost::bind(&MainController::handleConnected, this));  		client_->setSoftwareVersion(CLIENT_NAME, buildVersion);  		client_->getVCardManager()->onVCardChanged.connect(boost::bind(&MainController::handleVCardReceived, this, _1, _2));  		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, client_->getMUCRegistry(), client_->getAvatarManager(), client_->getNickResolver(), client_->getPresenceOracle(), networkFactories_->getTimerFactory());  		presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));  		eventNotifier_ = new EventNotifier(eventController_, notifier_, client_->getAvatarManager(), client_->getNickResolver());  		eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));  		if (certificate_ && !certificate_->isNull()) {  			client_->setCertificate(certificate_);  		}  		boost::shared_ptr<Presence> presence(new Presence());  		presence->setShow(static_cast<StatusShow::Type>(profileSettings_->getIntSetting("lastShow", StatusShow::Online)));  		presence->setStatus(profileSettings_->getStringSetting("lastStatus"));  		statusTracker_->setRequestedPresence(presence);  	} else {  		/* In case we're in the middle of another login, make sure they don't overlap */  		client_->disconnect();  	}  	systemTrayController_->setConnecting();  	if (rosterController_) {  		rosterController_->getWindow()->setConnecting();  	}  	ClientOptions clientOptions = clientOptions_;  	bool eagle = settings_->getSetting(SettingConstants::FORGET_PASSWORDS);  	clientOptions.forgetPassword = eagle;  	clientOptions.useTLS = eagle ? ClientOptions::RequireTLS : clientOptions_.useTLS;  	client_->connect(clientOptions);  }  void MainController::handleDisconnected(const boost::optional<ClientError>& error) {  	if (rosterController_) {  		rosterController_->getWindow()->setStreamEncryptionStatus(false);  	} +	if (adHocManager_) { +		adHocManager_->setOnline(false); +	}  	if (settings_->getSetting(SettingConstants::FORGET_PASSWORDS)) {  		purgeCachedCredentials();  	}  	if (quitRequested_) {  		resetClient();  		loginWindow_->quit();  	}  	else if (error) {  		std::string message;  		std::string certificateErrorMessage;  		bool forceSignout = false;  		switch(error->getType()) {  			case ClientError::UnknownError: message = QT_TRANSLATE_NOOP("", "Unknown Error"); break;  			case ClientError::DomainNameResolveError: message = QT_TRANSLATE_NOOP("", "Unable to find server"); break;  			case ClientError::ConnectionError: message = QT_TRANSLATE_NOOP("", "Error connecting to server"); break;  			case ClientError::ConnectionReadError: message = QT_TRANSLATE_NOOP("", "Error while receiving server data"); break;  			case ClientError::ConnectionWriteError: message = QT_TRANSLATE_NOOP("", "Error while sending data to the server"); break;  			case ClientError::XMLError: message = QT_TRANSLATE_NOOP("", "Error parsing server data"); break;  			case ClientError::AuthenticationFailedError: message = QT_TRANSLATE_NOOP("", "Login/password invalid"); break;  			case ClientError::CompressionFailedError: message = QT_TRANSLATE_NOOP("", "Error while compressing stream"); break;  			case ClientError::ServerVerificationFailedError: message = QT_TRANSLATE_NOOP("", "Server verification failed"); break;  			case ClientError::NoSupportedAuthMechanismsError: message = QT_TRANSLATE_NOOP("", "Authentication mechanisms not supported"); break;  			case ClientError::UnexpectedElementError: message = QT_TRANSLATE_NOOP("", "Unexpected response"); break;  			case ClientError::ResourceBindError: message = QT_TRANSLATE_NOOP("", "Error binding resource"); break;  			case ClientError::SessionStartError: message = QT_TRANSLATE_NOOP("", "Error starting session"); break;  			case ClientError::StreamError: message = QT_TRANSLATE_NOOP("", "Stream error"); break;  			case ClientError::TLSError: message = QT_TRANSLATE_NOOP("", "Encryption error"); break;  			case ClientError::ClientCertificateLoadError: message = QT_TRANSLATE_NOOP("", "Error loading certificate (Invalid password?)"); break;  			case ClientError::ClientCertificateError: message = QT_TRANSLATE_NOOP("", "Certificate not authorized"); break;  			case ClientError::CertificateCardRemoved: message = QT_TRANSLATE_NOOP("", "Certificate card removed"); forceSignout = true; break;  			case ClientError::UnknownCertificateError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Unknown certificate"); break;  			case ClientError::CertificateExpiredError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate has expired"); break;  			case ClientError::CertificateNotYetValidError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is not yet valid"); break;  			case ClientError::CertificateSelfSignedError: certificateErrorMessage = QT_TRANSLATE_NOOP("", "Certificate is self-signed"); break; diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript index e911a3a..4c71268 100644 --- a/Swift/Controllers/SConscript +++ b/Swift/Controllers/SConscript @@ -25,70 +25,71 @@ if env["SCONS_STAGE"] == "build" :  			"Chat/ChatController.cpp",  			"Chat/ChatControllerBase.cpp",  			"Chat/ChatsManager.cpp",  			"Chat/MUCController.cpp",  			"Chat/MUCSearchController.cpp",  			"Chat/UserSearchController.cpp",  			"Chat/ChatMessageParser.cpp",  			"ContactSuggester.cpp",  			"MainController.cpp",  			"ProfileController.cpp",  			"ShowProfileController.cpp",  			"ContactEditController.cpp",  			"FileTransfer/FileTransferController.cpp",  			"FileTransfer/FileTransferOverview.cpp",  			"FileTransfer/FileTransferProgressInfo.cpp",  			"Roster/RosterController.cpp",  			"Roster/RosterGroupExpandinessPersister.cpp",  			"Roster/ContactRosterItem.cpp",  			"Roster/GroupRosterItem.cpp",  			"Roster/RosterItem.cpp",  			"Roster/Roster.cpp",  			"Roster/RosterVCardProvider.cpp",  			"Roster/TableRoster.cpp",  			"EventWindowController.cpp",  			"SoundEventController.cpp",  			"SystemTrayController.cpp",  			"XMLConsoleController.cpp",  			"HistoryViewController.cpp",  			"HistoryController.cpp",  			"FileTransferListController.cpp",  			"BlockListController.cpp",  			"StatusTracker.cpp",  			"PresenceNotifier.cpp",  			"EventNotifier.cpp",  			"AdHocManager.cpp", +			"AdHocController.cpp",  			"XMPPEvents/EventController.cpp",  			"UIEvents/UIEvent.cpp",  			"UIInterfaces/XMLConsoleWidget.cpp",  			"UIInterfaces/ChatListWindow.cpp",  			"PreviousStatusStore.cpp",  			"ProfileSettingsProvider.cpp",  			"Settings/SettingsProviderHierachy.cpp",  			"Settings/XMLSettingsProvider.cpp",  			"Storages/CertificateStorageFactory.cpp",  			"Storages/CertificateStorage.cpp",  			"Storages/CertificateFileStorage.cpp",  			"Storages/CertificateMemoryStorage.cpp",  			"Storages/AvatarFileStorage.cpp",  			"Storages/FileStorages.cpp",  			"Storages/RosterFileStorage.cpp",  			"Storages/CapsFileStorage.cpp",  			"Storages/VCardFileStorage.cpp",  			"StatusUtil.cpp",  			"Translator.cpp",  			"XMPPURIController.cpp",  			"ChatMessageSummarizer.cpp",  			"SettingConstants.cpp",  			"WhiteboardManager.cpp",  			"StatusCache.cpp",  			"HighlightAction.cpp",  			"HighlightEditorController.cpp",  			"HighlightManager.cpp",  			"HighlightRule.cpp",  			"Highlighter.cpp",  			"ContactsFromXMPPRoster.cpp",  			"ContactProvider.cpp",  			"Contact.cpp"  		])  	env.Append(UNITTEST_SOURCES = [ diff --git a/Swift/Controllers/UIInterfaces/AdHocCommandWindow.h b/Swift/Controllers/UIInterfaces/AdHocCommandWindow.h index 835defe..07319c2 100644 --- a/Swift/Controllers/UIInterfaces/AdHocCommandWindow.h +++ b/Swift/Controllers/UIInterfaces/AdHocCommandWindow.h @@ -1,14 +1,18 @@  /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */  #pragma once +#include <Swiften/Base/boost_bsignals.h> +  namespace Swift {  	class AdHocCommandWindow {  		public:  			virtual ~AdHocCommandWindow() {} +			virtual void setOnline(bool /*online*/) {} +			boost::signal<void ()> onClosing;  	};  } diff --git a/Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h b/Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h index ae77180..eeefa2d 100644 --- a/Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h +++ b/Swift/Controllers/UIInterfaces/AdHocCommandWindowFactory.h @@ -1,22 +1,19 @@  /* - * 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.   */  #pragma once  #include <Swift/Controllers/UIInterfaces/AdHocCommandWindow.h>  #include <Swiften/AdHoc/OutgoingAdHocCommandSession.h>  namespace Swift { +class AdHocCommandWindow;  	class AdHocCommandWindowFactory {  		public:  			virtual ~AdHocCommandWindowFactory() {} -			/** -			 * The UI should deal with the lifetime of this window (i.e. DeleteOnClose), -			 * so the result isn't returned. -			 */ -			virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) = 0; +			virtual AdHocCommandWindow* createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) = 0;  	};  } diff --git a/Swift/QtUI/QtAdHocCommandWindow.cpp b/Swift/QtUI/QtAdHocCommandWindow.cpp index 5d87031..5f99dba 100644 --- a/Swift/QtUI/QtAdHocCommandWindow.cpp +++ b/Swift/QtUI/QtAdHocCommandWindow.cpp @@ -1,93 +1,113 @@  /* - * 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.   */ -#include <Swift/QtUI/QtAdHocCommandWindow.h> -  #include <boost/bind.hpp>  #include <QBoxLayout> +#include <Swift/QtUI/QtAdHocCommandWindow.h>  #include <Swift/QtUI/QtFormWidget.h> -#include <Swiften/Elements/Command.h>  #include <Swift/QtUI/QtSwiftUtil.h> +#include <Swiften/Base/format.h> +#include <Swiften/Elements/Command.h>  const int FormLayoutIndex = 1;  namespace Swift {  QtAdHocCommandWindow::QtAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) : command_(command) {  	formWidget_ = NULL;  	setAttribute(Qt::WA_DeleteOnClose);  	command->onNextStageReceived.connect(boost::bind(&QtAdHocCommandWindow::handleNextStageReceived, this, _1));  	command->onError.connect(boost::bind(&QtAdHocCommandWindow::handleError, this, _1));  	command->start();  	layout_ = new QBoxLayout(QBoxLayout::TopToBottom, this);  	layout_->setContentsMargins(0,0,0,0);  	layout_->setSpacing(2);  	label_ = new QLabel(this);  	label_->setTextFormat(Qt::PlainText);  	layout_->addWidget(label_); + +	errorLabel_ = new QLabel(this); +	errorLabel_->setText(QString("<b>%1</b>").arg(tr("Unable to complete the command because you have been disconnected"))); +	errorLabel_->setVisible(false); +	errorLabel_->setFrameStyle(QFrame::Box|QFrame::Sunken); +	layout_->addWidget(errorLabel_); +  	QWidget* buttonsWidget = new QWidget(this);  	layout_->addWidget(buttonsWidget);  	QBoxLayout* buttonsLayout = new QBoxLayout(QBoxLayout::LeftToRight, buttonsWidget);  	cancelButton_ = new QPushButton(tr("Cancel"), buttonsWidget);  	buttonsLayout->addWidget(cancelButton_);  	connect(cancelButton_, SIGNAL(clicked()), this, SLOT(handleCancelClicked()));  	backButton_ = new QPushButton(tr("Back"), buttonsWidget);  	buttonsLayout->addWidget(backButton_);  	connect(backButton_, SIGNAL(clicked()), this, SLOT(handlePrevClicked()));  	nextButton_ = new QPushButton(tr("Next"), buttonsWidget);  	buttonsLayout->addWidget(nextButton_);  	connect(nextButton_, SIGNAL(clicked()), this, SLOT(handleNextClicked()));  	completeButton_ = new QPushButton(tr("Complete"), buttonsWidget);  	buttonsLayout->addWidget(completeButton_);  	connect(completeButton_, SIGNAL(clicked()), this, SLOT(handleCompleteClicked()));  	nextButton_->setEnabled(false);  	backButton_->setEnabled(false);  	completeButton_->setEnabled(false); +  	actions_[Command::Next] = nextButton_;  	actions_[Command::Prev] = backButton_;  	actions_[Command::Complete] = completeButton_;  	actions_[Command::Cancel] = cancelButton_;  }  QtAdHocCommandWindow::~QtAdHocCommandWindow() { +} + +void QtAdHocCommandWindow::setOnline(bool online) { +	if (!online) { +		nextButton_->setEnabled(false); +		backButton_->setEnabled(false); +		completeButton_->setEnabled(false); +		errorLabel_->setVisible(true); +	} +} +void QtAdHocCommandWindow::closeEvent(QCloseEvent*) { +	onClosing();  }  void QtAdHocCommandWindow::handleCancelClicked() {  	command_->cancel();  	close();  }  void QtAdHocCommandWindow::handlePrevClicked() {  	command_->goBack();  }  void QtAdHocCommandWindow::handleNextClicked() {  	command_->goNext(formWidget_ ? formWidget_->getCompletedForm() : Form::ref());  }  void QtAdHocCommandWindow::handleCompleteClicked() {  	command_->complete(formWidget_ ? formWidget_->getCompletedForm() : Form::ref());  }  void QtAdHocCommandWindow::handleNextStageReceived(Command::ref command) {  	QString notes;  	foreach (Command::Note note, command->getNotes()) {  		if (!notes.isEmpty()) {  			notes += "\n";  		}  		QString qNote(P2QSTRING(note.note));  		switch (note.type) {  			case Command::Note::Error: notes += tr("Error: %1").arg(qNote); break;  			case Command::Note::Warn: notes += tr("Warning: %1").arg(qNote); break;  			case Command::Note::Info: notes += qNote; break;  		}  	}  	label_->setText(notes);  	if (command->getForm()) {  		setForm(command->getForm()); diff --git a/Swift/QtUI/QtAdHocCommandWindow.h b/Swift/QtUI/QtAdHocCommandWindow.h index d42a77d..0e398af 100644 --- a/Swift/QtUI/QtAdHocCommandWindow.h +++ b/Swift/QtUI/QtAdHocCommandWindow.h @@ -1,48 +1,51 @@  /*   * Copyright (c) 2010-2012 Kevin Smith   * Licensed under the GNU General Public License v3.   * See Documentation/Licenses/GPLv3.txt for more information.   */  #pragma once  #include <QWidget>  #include <QPushButton>  #include <QLabel>  #include <Swift/Controllers/UIInterfaces/AdHocCommandWindow.h>  #include <Swiften/AdHoc/OutgoingAdHocCommandSession.h>  class QBoxLayout;  namespace Swift {  	class QtFormWidget;  	class QtAdHocCommandWindow : public QWidget, public AdHocCommandWindow {  		Q_OBJECT  		public:  			QtAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command);  			virtual ~QtAdHocCommandWindow(); +			virtual void setOnline(bool online);  		private: +			void closeEvent(QCloseEvent* event);  			void handleNextStageReceived(Command::ref command);  			void handleError(ErrorPayload::ref error);  			void setForm(Form::ref);  			void setNoForm(bool andHide);  			void setAvailableActions(Command::ref commandResult);  		private slots:  			void handleCancelClicked();  			void handlePrevClicked();  			void handleNextClicked();  			void handleCompleteClicked();  		private:  			boost::shared_ptr<OutgoingAdHocCommandSession> command_;  			QtFormWidget* formWidget_;  			Form::ref form_;  			QLabel* label_; +			QLabel* errorLabel_;  			QPushButton* backButton_;  			QPushButton* nextButton_;  			QPushButton* completeButton_;  			QPushButton* cancelButton_;  			std::map<Command::Action, QPushButton*> actions_;  			QBoxLayout* layout_;  	};  } diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index e5db22d..afd2a9e 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -1,37 +1,37 @@  /* - * 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.   */  #include <Swift/QtUI/QtUIFactory.h>  #include <QSplitter>  #include <Swift/QtUI/QtXMLConsoleWidget.h>  #include <Swift/QtUI/QtChatTabs.h>  #include <Swift/QtUI/QtMainWindow.h>  #include <Swift/QtUI/QtLoginWindow.h>  #include <Swift/QtUI/QtSystemTray.h>  #include <Swift/QtUI/QtSettingsProvider.h>  #include <Swift/QtUI/QtMainWindow.h>  #include <Swift/QtUI/QtChatWindow.h>  #include <Swift/QtUI/QtJoinMUCWindow.h>  #include <Swift/QtUI/QtChatWindowFactory.h>  #include <Swift/QtUI/QtSwiftUtil.h>  #include <Swift/QtUI/MUCSearch/QtMUCSearchWindow.h>  #include <Swift/QtUI/UserSearch/QtUserSearchWindow.h>  #include <Swift/QtUI/QtProfileWindow.h>  #include <Swift/QtUI/QtContactEditWindow.h>  #include <Swift/QtUI/QtAdHocCommandWindow.h>  #include <Swift/QtUI/QtFileTransferListWidget.h>  #include <Swift/QtUI/QtHighlightEditorWidget.h>  #include <Swift/QtUI/Whiteboard/QtWhiteboardWindow.h>  #include <Swift/Controllers/Settings/SettingsProviderHierachy.h>  #include <Swift/QtUI/QtUISettingConstants.h>  #include <Swift/QtUI/QtHistoryWindow.h>  #include <Swiften/Whiteboard/WhiteboardSession.h>  #include <Swift/QtUI/QtSingleWindow.h>  #include <Swift/QtUI/QtBlockListEditorWindow.h>  namespace Swift { @@ -140,40 +140,40 @@ ChatWindow* QtUIFactory::createChatWindow(const JID& contact, UIEventStream* eve  }  void QtUIFactory::handleChatWindowFontResized(int size) {  	chatFontSize = size;  	settings->storeSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE, size);  }  UserSearchWindow* QtUIFactory::createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups) {  	return new QtUserSearchWindow(eventStream, type, groups, qtOnlySettings);  }  JoinMUCWindow* QtUIFactory::createJoinMUCWindow(UIEventStream* uiEventStream) {  	return new QtJoinMUCWindow(uiEventStream);  }  ProfileWindow* QtUIFactory::createProfileWindow() {  	return new QtProfileWindow();  }  ContactEditWindow* QtUIFactory::createContactEditWindow() {  	return new QtContactEditWindow();  }  WhiteboardWindow* QtUIFactory::createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession) {  	return new QtWhiteboardWindow(whiteboardSession);  }  HighlightEditorWidget* QtUIFactory::createHighlightEditorWidget() {  	return new QtHighlightEditorWidget();  }  BlockListEditorWidget *QtUIFactory::createBlockListEditorWidget() {  	return new QtBlockListEditorWindow();  } -void QtUIFactory::createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) { -	new QtAdHocCommandWindow(command); +AdHocCommandWindow* QtUIFactory::createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command) { +	return new QtAdHocCommandWindow(command);  }  } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 662c78e..721aa76 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -1,77 +1,77 @@  /* - * 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.   */  #pragma once  #include <QObject>  #include <QPointer>  #include <Swift/Controllers/UIInterfaces/UIFactory.h>  class QSplitter;  namespace Swift {  	class QtSettingsProvider;  	class SettingsProviderHierachy;  	class QtChatTabs;  	class QtSystemTray;  	class QtLoginWindow;  	class QtMainWindow;  	class QtChatTheme;  	class QtChatWindowFactory;  	class QtChatWindow;  	class TimerFactory;  	class historyWindow_;  	class WhiteboardSession;  	class StatusCache;  	class QtSingleWindow;  	class QtUIFactory : public QObject, public UIFactory {  			Q_OBJECT  		public:  			QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist);  			virtual XMLConsoleWidget* createXMLConsoleWidget();  			virtual HistoryWindow* createHistoryWindow(UIEventStream*);  			virtual MainWindow* createMainWindow(UIEventStream* eventStream);  			virtual LoginWindow* createLoginWindow(UIEventStream* eventStream);  			virtual EventWindow* createEventWindow();  			virtual ChatListWindow* createChatListWindow(UIEventStream*);  			virtual MUCSearchWindow* createMUCSearchWindow();  			virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream);  			virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream, const std::set<std::string>& groups);  			virtual JoinMUCWindow* createJoinMUCWindow(UIEventStream* uiEventStream);  			virtual ProfileWindow* createProfileWindow();  			virtual ContactEditWindow* createContactEditWindow();  			virtual FileTransferListWidget* createFileTransferListWidget();  			virtual WhiteboardWindow* createWhiteboardWindow(boost::shared_ptr<WhiteboardSession> whiteboardSession);  			virtual HighlightEditorWidget* createHighlightEditorWidget();  			virtual BlockListEditorWidget* createBlockListEditorWidget(); -			virtual void createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command); +			virtual AdHocCommandWindow* createAdHocCommandWindow(boost::shared_ptr<OutgoingAdHocCommandSession> command);  		private slots:  			void handleLoginWindowGeometryChanged();  			void handleChatWindowFontResized(int);  			void handleHistoryWindowFontResized(int);  		private:  			SettingsProviderHierachy* settings;  			QtSettingsProvider* qtOnlySettings;  			QtChatTabs* tabs;  			QtSingleWindow* netbookSplitter;  			QtSystemTray* systemTray;  			QtChatWindowFactory* chatWindowFactory;  			TimerFactory* timerFactory_;  			QtMainWindow* lastMainWindow;  			QtLoginWindow* loginWindow;  			StatusCache* statusCache;  			std::vector<QPointer<QtChatWindow> > chatWindows;  			bool startMinimized;  			int chatFontSize;  			int historyFontSize_;  			bool emoticonsExist_;  	};  } | 
 Swift
 Swift