diff options
19 files changed, 541 insertions, 137 deletions
| diff --git a/Swift/Controllers/Chat/UserSearchController.cpp b/Swift/Controllers/Chat/UserSearchController.cpp index c3e40c8..886aa47 100644 --- a/Swift/Controllers/Chat/UserSearchController.cpp +++ b/Swift/Controllers/Chat/UserSearchController.cpp @@ -14,12 +14,13 @@  #include <Swift/Controllers/DiscoServiceWalker.h>  #include <Swift/Controllers/UIEvents/UIEventStream.h> -#include <Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h> +#include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h> +#include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h>  #include <Swift/Controllers/UIInterfaces/UserSearchWindow.h>  #include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h>  namespace Swift { -UserSearchController::UserSearchController(const JID& jid, UIEventStream* uiEventStream, UserSearchWindowFactory* factory, IQRouter* iqRouter) : jid_(jid) { +UserSearchController::UserSearchController(Type type, const JID& jid, UIEventStream* uiEventStream, UserSearchWindowFactory* factory, IQRouter* iqRouter) : type_(type), jid_(jid) {  	iqRouter_ = iqRouter;  	uiEventStream_ = uiEventStream;  	uiEventConnection_ = uiEventStream_->onUIEvent.connect(boost::bind(&UserSearchController::handleUIEvent, this, _1)); @@ -34,10 +35,17 @@ UserSearchController::~UserSearchController() {  }  void UserSearchController::handleUIEvent(boost::shared_ptr<UIEvent> event) { -	boost::shared_ptr<RequestUserSearchUIEvent> searchEvent = boost::dynamic_pointer_cast<RequestUserSearchUIEvent>(event); -	if (searchEvent) { +	bool handle = false; +	if (type_ == AddContact) { +		boost::shared_ptr<RequestAddUserDialogUIEvent> searchEvent = boost::dynamic_pointer_cast<RequestAddUserDialogUIEvent>(event); +		if (searchEvent) handle = true; +	} else { +		boost::shared_ptr<RequestChatWithUserDialogUIEvent> searchEvent = boost::dynamic_pointer_cast<RequestChatWithUserDialogUIEvent>(event); +		if (searchEvent) handle = true; +	} +	if (handle) {  		if (!window_) { -			window_ = factory_->createUserSearchWindow(uiEventStream_); +			window_ = factory_->createUserSearchWindow(type_ == AddContact ? UserSearchWindow::AddContact : UserSearchWindow::ChatToContact, uiEventStream_);  			window_->onFormRequested.connect(boost::bind(&UserSearchController::handleFormRequested, this, _1));  			window_->onSearchRequested.connect(boost::bind(&UserSearchController::handleSearch, this, _1, _2));  			window_->setSelectedService(JID(jid_.getDomain())); diff --git a/Swift/Controllers/Chat/UserSearchController.h b/Swift/Controllers/Chat/UserSearchController.h index 3ba3352..c54b8d5 100644 --- a/Swift/Controllers/Chat/UserSearchController.h +++ b/Swift/Controllers/Chat/UserSearchController.h @@ -38,7 +38,8 @@ namespace Swift {  	class UserSearchController {  		public: -			UserSearchController(const JID& jid, UIEventStream* uiEventStream, UserSearchWindowFactory* userSearchWindowFactory, IQRouter* iqRouter); +			enum Type {AddContact, StartChat}; +			UserSearchController(Type type, const JID& jid, UIEventStream* uiEventStream, UserSearchWindowFactory* userSearchWindowFactory, IQRouter* iqRouter);  			~UserSearchController();  		private:  			void handleUIEvent(boost::shared_ptr<UIEvent> event); @@ -48,6 +49,7 @@ namespace Swift {  			void handleFormResponse(boost::shared_ptr<SearchPayload> items, ErrorPayload::ref error, const JID& jid);  			void handleSearch(boost::shared_ptr<SearchPayload> fields, const JID& jid);  			void handleSearchResponse(boost::shared_ptr<SearchPayload> results, ErrorPayload::ref error, const JID& jid); +			Type type_;  			UIEventStream* uiEventStream_;  			UserSearchWindow* window_;  			UserSearchWindowFactory* factory_; diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp index 660c12f..ba8d944 100644 --- a/Swift/Controllers/MainController.cpp +++ b/Swift/Controllers/MainController.cpp @@ -99,7 +99,8 @@ MainController::MainController(  	chatsManager_ = NULL;  	eventWindowController_ = NULL;  	mucSearchController_ = NULL; -	userSearchController_ = NULL; +	userSearchControllerChat_ = NULL; +	userSearchControllerAdd_ = NULL;  	quitRequested_ = false;  	timeBeforeNextReconnect_ = -1; @@ -190,8 +191,10 @@ void MainController::resetClient() {  	statusTracker_ = NULL;  	delete profileSettings_;  	profileSettings_ = NULL; -	delete userSearchController_; -	userSearchController_ = NULL; +	delete userSearchControllerChat_; +	userSearchControllerChat_ = NULL; +	delete userSearchControllerAdd_; +	userSearchControllerAdd_ = NULL;  }  void MainController::handleUIEvent(boost::shared_ptr<UIEvent> event) { @@ -248,7 +251,8 @@ void MainController::handleConnected() {  		mucSearchController_ = new MUCSearchController(jid_, uiEventStream_, uiFactory_, client_->getIQRouter(), settings_, client_->getNickResolver()); -		userSearchController_ = new UserSearchController(jid_, uiEventStream_, uiFactory_, client_->getIQRouter()); +		userSearchControllerChat_ = new UserSearchController(UserSearchController::StartChat, jid_, uiEventStream_, uiFactory_, client_->getIQRouter()); +		userSearchControllerAdd_ = new UserSearchController(UserSearchController::AddContact, jid_, uiEventStream_, uiFactory_, client_->getIQRouter());  	}  	client_->requestRoster(); diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h index 8489f71..f6a269d 100644 --- a/Swift/Controllers/MainController.h +++ b/Swift/Controllers/MainController.h @@ -139,7 +139,8 @@ namespace Swift {  			boost::shared_ptr<ErrorEvent> lastDisconnectError_;  			bool useDelayForLatency_;  			MUCSearchController* mucSearchController_; -			UserSearchController* userSearchController_; +			UserSearchController* userSearchControllerChat_; +			UserSearchController* userSearchControllerAdd_;  			int timeBeforeNextReconnect_;  			Timer::ref reconnectTimer_;  			Timer::ref quitTimer_; diff --git a/Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h b/Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h index 1312a84..bfa4a8b 100644 --- a/Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h +++ b/Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h @@ -9,7 +9,7 @@  #include "Swift/Controllers/UIEvents/UIEvent.h"  namespace Swift { -	class RequestUserSearchUIEvent : public UIEvent { +	class RequestAddUserDialogUIEvent : public UIEvent {  	};  } diff --git a/Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h b/Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h new file mode 100644 index 0000000..7b967bc --- /dev/null +++ b/Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2010 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include "Swift/Controllers/UIEvents/UIEvent.h" + +namespace Swift { +	class RequestChatWithUserDialogUIEvent : public UIEvent { + +	}; +} diff --git a/Swift/Controllers/UIInterfaces/UserSearchWindow.h b/Swift/Controllers/UIInterfaces/UserSearchWindow.h index dda3409..e4a665b 100644 --- a/Swift/Controllers/UIInterfaces/UserSearchWindow.h +++ b/Swift/Controllers/UIInterfaces/UserSearchWindow.h @@ -18,6 +18,7 @@ namespace Swift {  	class UserSearchWindow {  		public: +			enum Type {AddContact, ChatToContact};  			virtual ~UserSearchWindow() {};  			virtual void clear() = 0; diff --git a/Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h b/Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h index 808c1db..88e0a07 100644 --- a/Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h +++ b/Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h @@ -14,6 +14,6 @@ namespace Swift {  		public:  			virtual ~UserSearchWindowFactory() {}; -			virtual UserSearchWindow* createUserSearchWindow(UIEventStream* eventStream) = 0; +			virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream) = 0;  	};  } diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 6e53258..7a84c59 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -24,7 +24,8 @@  #include "QtSwiftUtil.h"  #include "QtTabWidget.h"  #include "Roster/QtTreeWidget.h" -#include "Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h" +#include "Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h" +#include "Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h"  #include "Swift/Controllers/UIEvents/RequestMUCSearchUIEvent.h"  #include "Swift/Controllers/UIEvents/JoinMUCUIEvent.h"  #include "Swift/Controllers/UIEvents/ToggleShowOfflineUIEvent.h" @@ -84,9 +85,12 @@ QtMainWindow::QtMainWindow(QtSettingsProvider* settings, UIEventStream* uiEventS  	QAction* joinMUCAction = new QAction("Join Room", this);  	connect(joinMUCAction, SIGNAL(triggered()), SLOT(handleJoinMUCAction()));  	actionsMenu->addAction(joinMUCAction); -	otherUserAction_ = new QAction("Find Other Contact", this); -	connect(otherUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleOtherUserActionTriggered(bool))); -	actionsMenu->addAction(otherUserAction_); +	addUserAction_ = new QAction("Add Contact", this); +	connect(addUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleAddUserActionTriggered(bool))); +	actionsMenu->addAction(addUserAction_); +	chatUserAction_ = new QAction("Start Chat", this); +	connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool))); +	actionsMenu->addAction(chatUserAction_);  	QAction* signOutAction = new QAction("Sign Out", this);  	connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction()));  	actionsMenu->addAction(signOutAction); @@ -123,8 +127,13 @@ void QtMainWindow::handleEventCountUpdated(int count) {  	tabs_->setTabText(eventIndex, text);  } -void QtMainWindow::handleOtherUserActionTriggered(bool /*checked*/) { -	boost::shared_ptr<UIEvent> event(new RequestUserSearchUIEvent()); +void QtMainWindow::handleAddUserActionTriggered(bool /*checked*/) { +	boost::shared_ptr<UIEvent> event(new RequestAddUserDialogUIEvent()); +	uiEventStream_->send(event); +} + +void QtMainWindow::handleChatUserActionTriggered(bool /*checked*/) { +	boost::shared_ptr<UIEvent> event(new RequestChatWithUserDialogUIEvent());  	uiEventStream_->send(event);  } diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index 10cad66..27972cb 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -54,14 +54,16 @@ namespace Swift {  			void handleShowOfflineToggled(bool);  			void handleJoinMUCAction();  			void handleSignOutAction(); -			void handleOtherUserActionTriggered(bool checked); +			void handleAddUserActionTriggered(bool checked); +			void handleChatUserActionTriggered(bool checked);  			void handleEventCountUpdated(int count);  		private:  			std::vector<QMenu*> menus_;  			QtTreeWidget* treeWidget_;  			QtRosterHeader* meView_; -			QAction* otherUserAction_; +			QAction* addUserAction_; +			QAction* chatUserAction_;  			QAction* showOfflineAction_;  			QtTabWidget* tabs_;  			QWidget* contactsTabWidget_; diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 4f1bef5..25a508e 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -78,8 +78,8 @@ ChatWindow* QtUIFactory::createChatWindow(const JID& contact, UIEventStream* eve  	return chatWindowFactory->createChatWindow(contact, eventStream);  } -UserSearchWindow* QtUIFactory::createUserSearchWindow(UIEventStream* eventStream) { -	return new QtUserSearchWindow(eventStream); +UserSearchWindow* QtUIFactory::createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream) { +	return new QtUserSearchWindow(eventStream, type);  };  } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 5282b31..6ddc316 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -33,7 +33,7 @@ namespace Swift {  			virtual ChatListWindow* createChatListWindow(UIEventStream*);  			virtual MUCSearchWindow* createMUCSearchWindow(UIEventStream* eventStream);  			virtual ChatWindow* createChatWindow(const JID &contact, UIEventStream* eventStream); -			virtual UserSearchWindow* createUserSearchWindow(UIEventStream* eventStream); +			virtual UserSearchWindow* createUserSearchWindow(UserSearchWindow::Type type, UIEventStream* eventStream);  		private slots:  			void handleLoginWindowGeometryChanged(); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 0f08556..c0730dc 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -141,7 +141,10 @@ else :    swiftProgram = myenv.Program("swift", sources)  myenv.Uic4("MUCSearch/QtMUCSearchWindow.ui") -myenv.Uic4("UserSearch/QtUserSearchWindow.ui") +myenv.Uic4("UserSearch/QtUserSearchWizard.ui") +myenv.Uic4("UserSearch/QtUserSearchFirstPage.ui") +myenv.Uic4("UserSearch/QtUserSearchFieldsPage.ui") +myenv.Uic4("UserSearch/QtUserSearchResultsPage.ui")  myenv.Uic4("QtAddContactDialog.ui")  myenv.Uic4("QtBookmarkDetailWindow.ui")  myenv.Qrc("DefaultTheme.qrc") diff --git a/Swift/QtUI/UserSearch/QtUserSearchFieldsPage.ui b/Swift/QtUI/UserSearch/QtUserSearchFieldsPage.ui new file mode 100644 index 0000000..35f9830 --- /dev/null +++ b/Swift/QtUI/UserSearch/QtUserSearchFieldsPage.ui @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtUserSearchFieldsPage</class> + <widget class="QWizardPage" name="QtUserSearchFieldsPage"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>400</width> +    <height>300</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>WizardPage</string> +  </property> +  <layout class="QGridLayout" name="gridLayout"> +   <item row="0" column="0" colspan="2"> +    <widget class="QLabel" name="label_4"> +     <property name="text"> +      <string>Enter search terms</string> +     </property> +    </widget> +   </item> +   <item row="1" column="0"> +    <widget class="QLabel" name="nickInputLabel_"> +     <property name="text"> +      <string>Nickname:</string> +     </property> +    </widget> +   </item> +   <item row="1" column="1"> +    <widget class="QLineEdit" name="nickInput_"/> +   </item> +   <item row="2" column="0"> +    <widget class="QLabel" name="firstInputLabel_"> +     <property name="text"> +      <string>First name:</string> +     </property> +    </widget> +   </item> +   <item row="2" column="1"> +    <widget class="QLineEdit" name="firstInput_"/> +   </item> +   <item row="3" column="0"> +    <widget class="QLabel" name="lastInputLabel_"> +     <property name="text"> +      <string>Last name:</string> +     </property> +    </widget> +   </item> +   <item row="3" column="1"> +    <widget class="QLineEdit" name="lastInput_"/> +   </item> +   <item row="4" column="0"> +    <widget class="QLabel" name="emailInputLabel_"> +     <property name="text"> +      <string>E-Mail:</string> +     </property> +    </widget> +   </item> +   <item row="4" column="1"> +    <widget class="QLineEdit" name="emailInput_"/> +   </item> +   <item row="6" column="1"> +    <spacer name="verticalSpacer"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>40</height> +      </size> +     </property> +    </spacer> +   </item> +   <item row="5" column="0"> +    <widget class="QLabel" name="fetchingThrobber_"> +     <property name="text"> +      <string>TextLabel</string> +     </property> +    </widget> +   </item> +   <item row="5" column="1"> +    <widget class="QLabel" name="fetchingLabel_"> +     <property name="text"> +      <string>Fetching search fields</string> +     </property> +    </widget> +   </item> +  </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui new file mode 100644 index 0000000..cbf3831 --- /dev/null +++ b/Swift/QtUI/UserSearch/QtUserSearchFirstPage.ui @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtUserSearchFirstPage</class> + <widget class="QWizardPage" name="QtUserSearchFirstPage"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>400</width> +    <height>300</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>WizardPage</string> +  </property> +  <property name="title"> +   <string>Add a user</string> +  </property> +  <property name="subTitle"> +   <string>Add another user to your roster. If you know their JID you can add them directly, or you can search for them.</string> +  </property> +  <layout class="QVBoxLayout" name="verticalLayout"> +   <item> +    <widget class="QLabel" name="errorLabel_"> +     <property name="text"> +      <string><font color='red'>errorLabel_</font></string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QLabel" name="howLabel_"> +     <property name="text"> +      <string>howLabel_</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QRadioButton" name="byJID_"> +     <property name="text"> +      <string>I know their JID</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QRadioButton" name="byLocalSearch_"> +     <property name="text"> +      <string>I'd like to search my server</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QRadioButton" name="byRemoteSearch_"> +     <property name="text"> +      <string>I'd like to search another server</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QLabel" name="jidLabel_"> +     <property name="text"> +      <string>jidLabel_</string> +     </property> +    </widget> +   </item> +   <item> +    <widget class="QLineEdit" name="jid_"/> +   </item> +   <item> +    <widget class="QComboBox" name="service_"> +     <property name="editable"> +      <bool>true</bool> +     </property> +    </widget> +   </item> +   <item> +    <spacer name="verticalSpacer"> +     <property name="orientation"> +      <enum>Qt::Vertical</enum> +     </property> +     <property name="sizeHint" stdset="0"> +      <size> +       <width>20</width> +       <height>40</height> +      </size> +     </property> +    </spacer> +   </item> +  </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/UserSearch/QtUserSearchResultsPage.ui b/Swift/QtUI/UserSearch/QtUserSearchResultsPage.ui new file mode 100644 index 0000000..e7f7c90 --- /dev/null +++ b/Swift/QtUI/UserSearch/QtUserSearchResultsPage.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtUserSearchResultsPage</class> + <widget class="QWizardPage" name="QtUserSearchResultsPage"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>400</width> +    <height>300</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>WizardPage</string> +  </property> +  <layout class="QHBoxLayout" name="horizontalLayout"> +   <item> +    <widget class="QTreeView" name="results_"/> +   </item> +  </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp index c3038d8..b3b64b9 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp @@ -8,6 +8,8 @@  #include <qdebug.h>  #include <QModelIndex> +#include <QWizardPage> +#include <QMovie>  #include "Swift/Controllers/UIEvents/UIEventStream.h"  #include "Swift/Controllers/UIEvents/RequestChatUIEvent.h" @@ -18,7 +20,7 @@  namespace Swift { -QtUserSearchWindow::QtUserSearchWindow(UIEventStream* eventStream) { +QtUserSearchWindow::QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type) : type_(type) {  #ifndef Q_WS_MAC  	setWindowIcon(QIcon(":/logo-icon-16.png"));  #endif @@ -26,150 +28,240 @@ QtUserSearchWindow::QtUserSearchWindow(UIEventStream* eventStream) {  	setupUi(this);  	model_ = new UserSearchModel();  	delegate_ = new UserSearchDelegate(); -	results_->setModel(model_); -	results_->setItemDelegate(delegate_); -	results_->setHeaderHidden(true); +	firstPage_ = new QtUserSearchFirstPage(); +	connect(firstPage_->byJID_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange())); +	connect(firstPage_->byLocalSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange())); +	connect(firstPage_->byRemoteSearch_, SIGNAL(toggled(bool)), this, SLOT(handleFirstPageRadioChange())); +	fieldsPage_ = new QtUserSearchFieldsPage(); +	fieldsPage_->fetchingThrobber_->setMovie(new QMovie(":/icons/throbber.gif", QByteArray(), this)); +	fieldsPage_->fetchingThrobber_->movie()->stop(); +	resultsPage_ = new QtUserSearchResultsPage(); +	resultsPage_->results_->setModel(model_); +	resultsPage_->results_->setItemDelegate(delegate_); +	resultsPage_->results_->setHeaderHidden(true); +	setPage(1, firstPage_); +	setPage(2, fieldsPage_); +	setPage(3, resultsPage_); +  #ifdef SWIFT_PLATFORM_MACOSX -	results_->setAlternatingRowColors(true); +	resultsPage_->results_->setAlternatingRowColors(true);  #endif -	connect(service_, SIGNAL(activated(const QString&)), this, SLOT(handleGetForm())); -	connect(getSearchForm_, SIGNAL(clicked()), this, SLOT(handleGetForm())); -	//connect(user_, SIGNAL(returnPressed()), this, SLOT(handleJoin())); -	//connect(nickName_, SIGNAL(returnPressed()), room_, SLOT(setFocus())); -	connect(search_, SIGNAL(clicked()), this, SLOT(handleSearch())); - -	connect(results_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleSelected(const QModelIndex&))); -	connect(results_, SIGNAL(activated(const QModelIndex&)), this, SLOT(handleActivated(const QModelIndex&))); -	connect(buttonBox_, SIGNAL(accepted()), this, SLOT(handleOkClicked())); -	connect(buttonBox_, SIGNAL(rejected()), this, SLOT(handleCancelClicked())); -	/* When inputs change, check if OK is enabled */ -	connect(jid_, SIGNAL(textChanged(const QString&)), this, SLOT(enableCorrectButtons())); -	connect(nickName_, SIGNAL(textChanged(const QString&)), this, SLOT(enableCorrectButtons())); -	connect(startChat_, SIGNAL(stateChanged(int)), this, SLOT(enableCorrectButtons())); -	connect(addToRoster_, SIGNAL(stateChanged(int)), this, SLOT(enableCorrectButtons())); -	enableCorrectButtons(); +	connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(handleCurrentChanged(int))); +	connect(this, SIGNAL(accepted()), this, SLOT(handleAccepted())); +	clear();  }  QtUserSearchWindow::~QtUserSearchWindow() {  } -void QtUserSearchWindow::handleGetForm() { -	lastServiceJID_ = JID(Q2PSTRING(service_->currentText())); -	onFormRequested(lastServiceJID_); +void QtUserSearchWindow::handleCurrentChanged(int page) { +	qDebug() << "Next called, currently, was " << currentId() << ", " << lastPage_; +	if (page == 2 && lastPage_ == 1) { +		setError(""); +		/* next won't be called if JID is selected */ +		JID server = searchServer(); +		clearForm(); +		onFormRequested(server); +	} else if (page == 3 && lastPage_ == 2) { +		handleSearch(); +	} +	lastPage_ = page;  } -void QtUserSearchWindow::handleSearch() { -	boost::shared_ptr<SearchPayload> search(new SearchPayload()); -	if (nickInput_->isEnabled()) { -		search->setNick(Q2PSTRING(nickInput_->text())); -	} -	if (firstInput_->isEnabled()) { -		search->setFirst(Q2PSTRING(firstInput_->text())); -	} -	if (lastInput_->isEnabled()) { -		search->setLast(Q2PSTRING(lastInput_->text())); +JID QtUserSearchWindow::searchServer() { +	return firstPage_->byRemoteSearch_->isChecked() ? JID(Q2PSTRING(firstPage_->service_->currentText())) : myServer_; +} + +void QtUserSearchWindow::handleAccepted() { +	JID jid; +	if (!firstPage_->byJID_->isChecked()) { +		UserSearchResult* userItem = static_cast<UserSearchResult*>(resultsPage_->results_->currentIndex().internalPointer()); +		if (userItem) { /* Remember to leave this if we change to dynamic cast */ +			jid = userItem->getJID(); +		} +	} else { +		jid = JID(Q2PSTRING(firstPage_->jid_->text()));  	} -	if (emailInput_->isEnabled()) { -		search->setEMail(Q2PSTRING(emailInput_->text())); +	if (type_ == AddContact) { +		/* FIXME: allow specifying a nick */ +		boost::shared_ptr<UIEvent> event(new AddContactUIEvent(jid, jid.toString())); +		eventStream_->send(event); +	} else { +		boost::shared_ptr<UIEvent> event(new RequestChatUIEvent(jid)); +		eventStream_->send(event);  	} -	onSearchRequested(search, lastServiceJID_);  } -void QtUserSearchWindow::show() { -	clear(); -	enableCorrectButtons(); -	QWidget::show(); +int QtUserSearchWindow::nextId() const { +	switch (currentId()) { +		case 1: return firstPage_->byJID_->isChecked() ? -1 : 2; +		case 2: return 3; +		case 3: return -1; +		default: return -1; +	}  } -void QtUserSearchWindow::enableCorrectButtons() { -	bool enable = !jid_->text().isEmpty() && (startChat_->isChecked() || (addToRoster_->isChecked() && !nickName_->text().isEmpty())); -	buttonBox_->button(QDialogButtonBox::Ok)->setEnabled(enable); +void QtUserSearchWindow::handleFirstPageRadioChange() { +	if (firstPage_->byJID_->isChecked()) { +		firstPage_->jidLabel_->setText("What is their JID? (This has the form 'alice@wonderland.lit')"); +		firstPage_->jidLabel_->show(); +		firstPage_->service_->hide(); +		firstPage_->jid_->setText(""); +		firstPage_->jid_->show(); +		restart(); +	} else if (firstPage_->byRemoteSearch_->isChecked()) { +		firstPage_->jidLabel_->setText("Which server do you want to search? (This has the form 'wonderland.lit')"); +		firstPage_->jidLabel_->hide(); +		firstPage_->service_->show(); +		firstPage_->service_->setEditText(""); +		//firstPage_->jid_->setText(""); +		firstPage_->jid_->hide(); +		restart(); +	} else { +		firstPage_->jid_->hide(); +		firstPage_->jidLabel_->hide(); +		firstPage_->service_->hide(); +		restart(); +	}  } -void QtUserSearchWindow::handleOkClicked() { -	JID contact = JID(Q2PSTRING(jid_->text())); -	String nick = Q2PSTRING(nickName_->text()); -	if (addToRoster_->isChecked()) { -		boost::shared_ptr<UIEvent> event(new AddContactUIEvent(contact, nick)); -		eventStream_->send(event); +void QtUserSearchWindow::handleSearch() { +	boost::shared_ptr<SearchPayload> search(new SearchPayload()); +	if (fieldsPage_->nickInput_->isEnabled()) { +		search->setNick(Q2PSTRING(fieldsPage_->nickInput_->text()));  	} -	if (startChat_->isChecked()) { -		boost::shared_ptr<UIEvent> event(new RequestChatUIEvent(contact)); -		eventStream_->send(event); +	if (fieldsPage_->firstInput_->isEnabled()) { +		search->setFirst(Q2PSTRING(fieldsPage_->firstInput_->text())); +	} +	if (fieldsPage_->lastInput_->isEnabled()) { +		search->setLast(Q2PSTRING(fieldsPage_->lastInput_->text()));  	} -	hide(); +	if (fieldsPage_->emailInput_->isEnabled()) { +		search->setEMail(Q2PSTRING(fieldsPage_->emailInput_->text())); +	} +	onSearchRequested(search, searchServer());  } -void QtUserSearchWindow::handleCancelClicked() { -	hide(); +void QtUserSearchWindow::show() { +	clear(); +	QWidget::show();  } - +// +//void QtUserSearchWindow::enableCorrectButtons() { +//	bool enable = !jid_->text().isEmpty() && (startChat_->isChecked() || (addToRoster_->isChecked() && !nickName_->text().isEmpty())); +//	buttonBox_->button(QDialogButtonBox::Ok)->setEnabled(enable); +//} +// +//void QtUserSearchWindow::handleOkClicked() { +//	JID contact = JID(Q2PSTRING(jid_->text())); +//	String nick = Q2PSTRING(nickName_->text()); +//	if (addToRoster_->isChecked()) { +//		boost::shared_ptr<UIEvent> event(new AddContactUIEvent(contact, nick)); +//		eventStream_->send(event); +//	} +//	if (startChat_->isChecked()) { +//		boost::shared_ptr<UIEvent> event(new RequestChatUIEvent(contact)); +//		eventStream_->send(event); +//	} +//	hide(); +//} +// +//void QtUserSearchWindow::handleCancelClicked() { +//	hide(); +//} +//  void QtUserSearchWindow::addSavedServices(const std::vector<JID>& services) { -	service_->clear(); +	firstPage_->service_->clear();  	foreach (JID jid, services) { -		service_->addItem(P2QSTRING(jid.toString())); -	} -	service_->clearEditText(); -} - -void QtUserSearchWindow::setServerSupportsSearch(bool support) { -	if (!support) { -		stack_->setCurrentIndex(0); -		messageLabel_->setText("This service doesn't support searching for users."); -		search_->setEnabled(false); +		firstPage_->service_->addItem(P2QSTRING(jid.toString()));  	} +	firstPage_->service_->clearEditText();  }  void QtUserSearchWindow::setSearchFields(boost::shared_ptr<SearchPayload> fields) { +	fieldsPage_->fetchingThrobber_->hide(); +	fieldsPage_->fetchingThrobber_->movie()->stop(); +	fieldsPage_->fetchingLabel_->hide();  	bool enabled[8] = {fields->getNick(), fields->getNick(), fields->getFirst(), fields->getFirst(), fields->getLast(), fields->getLast(), fields->getEMail(), fields->getEMail()}; -	QWidget* widget[8] = {nickInputLabel_, nickInput_, firstInputLabel_, firstInput_, lastInputLabel_, lastInput_, emailInputLabel_, emailInput_}; +	QWidget* legacySearchWidgets[8] = {fieldsPage_->nickInputLabel_, fieldsPage_->nickInput_, fieldsPage_->firstInputLabel_, fieldsPage_->firstInput_, fieldsPage_->lastInputLabel_, fieldsPage_->lastInput_, fieldsPage_->emailInputLabel_, fieldsPage_->emailInput_};  	for (int i = 0; i < 8; i++) { -		widget[i]->setVisible(enabled[i]); -		widget[i]->setEnabled(enabled[i]); +		legacySearchWidgets[i]->setVisible(enabled[i]); +		legacySearchWidgets[i]->setEnabled(enabled[i]);  	} -	stack_->setCurrentIndex(1); -	search_->setEnabled(true);  } - -void QtUserSearchWindow::handleActivated(const QModelIndex& index) { -	if (!index.isValid()) { -		return; -	} -	UserSearchResult* userItem = static_cast<UserSearchResult*>(index.internalPointer()); -	if (userItem) { /* static cast, so always will be, but if we change to be like mucsearch, remember the check.*/ -		handleSelected(index); -		//handleJoin(); /* Don't do anything automatically on selection.*/ -	} -} - -void QtUserSearchWindow::handleSelected(const QModelIndex& current) { -	if (!current.isValid()) { -		return; -	} -	UserSearchResult* userItem = static_cast<UserSearchResult*>(current.internalPointer()); -	if (userItem) { /* Remember to leave this if we change to dynamic cast */ -		jid_->setText(P2QSTRING(userItem->getJID().toString())); -	} -} - +// +//void QtUserSearchWindow::handleActivated(const QModelIndex& index) { +//	if (!index.isValid()) { +//		return; +//	} +//	UserSearchResult* userItem = static_cast<UserSearchResult*>(index.internalPointer()); +//	if (userItem) { /* static cast, so always will be, but if we change to be like mucsearch, remember the check.*/ +//		handleSelected(index); +//		//handleJoin(); /* Don't do anything automatically on selection.*/ +//	} +//} +// +//void QtUserSearchWindow::handleSelected(const QModelIndex& current) { +//	if (!current.isValid()) { +//		return; +//	} +//	UserSearchResult* userItem = static_cast<UserSearchResult*>(current.internalPointer()); +//	if (userItem) { /* Remember to leave this if we change to dynamic cast */ +//		jid_->setText(P2QSTRING(userItem->getJID().toString())); +//	} +//} +//  void QtUserSearchWindow::setResults(const std::vector<UserSearchResult>& results) {  	model_->setResults(results);  }  void QtUserSearchWindow::setSelectedService(const JID& jid) { -	service_->setEditText(P2QSTRING(jid.toString())); +	myServer_ = jid; +} + +void QtUserSearchWindow::clearForm() { +	fieldsPage_->fetchingThrobber_->show(); +	fieldsPage_->fetchingThrobber_->movie()->start(); +	fieldsPage_->fetchingLabel_->show(); +	QWidget* legacySearchWidgets[8] = {fieldsPage_->nickInputLabel_, fieldsPage_->nickInput_, fieldsPage_->firstInputLabel_, fieldsPage_->firstInput_, fieldsPage_->lastInputLabel_, fieldsPage_->lastInput_, fieldsPage_->emailInputLabel_, fieldsPage_->emailInput_}; +	for (int i = 0; i < 8; i++) { +		legacySearchWidgets[i]->hide(); +	}  }  void QtUserSearchWindow::clear() { -	stack_->setCurrentIndex(0); -	messageLabel_->setText("Please choose a service to search, above"); +	firstPage_->errorLabel_->setVisible(false); +	firstPage_->howLabel_->setText(QString("How would you like to find the user to %1?").arg(type_ == AddContact ? "add" : "chat to")); +	firstPage_->byJID_->setChecked(true); +	clearForm();  	model_->clear(); -	search_->setEnabled(false); +	handleFirstPageRadioChange(); +	restart(); +	lastPage_ = 1; +} + +void QtUserSearchWindow::setError(const QString& error) { +	if (error.isEmpty()) { +		firstPage_->errorLabel_->hide(); +	} else { +		firstPage_->errorLabel_->setText(QString("<font color='red'>%1</font>").arg(error)); +		firstPage_->errorLabel_->show(); +		restart(); +		lastPage_ = 1; +	}  }  void QtUserSearchWindow::setSearchError(bool error) { -	//FIXME +	if (error) { +		setError("Error while searching"); +	} +} + +void QtUserSearchWindow::setServerSupportsSearch(bool support) { +	if (!support) { +		setError("This server doesn't support searching for users."); +	}  }  } diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.h b/Swift/QtUI/UserSearch/QtUserSearchWindow.h index dca321a..b4c4dc0 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.h +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.h @@ -6,9 +6,14 @@  #pragma once -#include "Swift/QtUI/UserSearch/ui_QtUserSearchWindow.h" +#include <QWizard> -#include "Swift/Controllers/UIInterfaces/UserSearchWindow.h" +#include <Swift/QtUI/UserSearch/ui_QtUserSearchWizard.h> +#include <Swift/QtUI/UserSearch/ui_QtUserSearchFirstPage.h> +#include <Swift/QtUI/UserSearch/ui_QtUserSearchFieldsPage.h> +#include <Swift/QtUI/UserSearch/ui_QtUserSearchResultsPage.h> + +#include <Swift/Controllers/UIInterfaces/UserSearchWindow.h>  namespace Swift { @@ -16,10 +21,35 @@ namespace Swift {  	class UserSearchDelegate;  	class UserSearchResult;  	class UIEventStream; -	class QtUserSearchWindow : public QWidget, public UserSearchWindow, private Ui::QtUserSearchWindow { + +	class QtUserSearchFirstPage : public QWizardPage, public Ui::QtUserSearchFirstPage { +		Q_OBJECT +		public: +			QtUserSearchFirstPage() { +				setupUi(this); +			} +	}; + +	class QtUserSearchFieldsPage : public QWizardPage, public Ui::QtUserSearchFieldsPage { +		Q_OBJECT +		public: +			QtUserSearchFieldsPage() { +				setupUi(this); +			} +	}; + +	class QtUserSearchResultsPage : public QWizardPage, public Ui::QtUserSearchResultsPage { +		Q_OBJECT +		public: +			QtUserSearchResultsPage() { +				setupUi(this); +			} +	}; + +	class QtUserSearchWindow : public QWizard, public UserSearchWindow, private Ui::QtUserSearchWizard {  		Q_OBJECT  		public: -			QtUserSearchWindow(UIEventStream* eventStream); +			QtUserSearchWindow(UIEventStream* eventStream, UserSearchWindow::Type type);  			virtual ~QtUserSearchWindow();  			virtual void addSavedServices(const std::vector<JID>& services); @@ -31,18 +61,25 @@ namespace Swift {  			virtual void setServerSupportsSearch(bool error);  			virtual void setSearchError(bool error);  			virtual void setSearchFields(boost::shared_ptr<SearchPayload> fields) ; +		protected: +			virtual int nextId() const;  		private slots: -			void handleGetForm(); -			void handleSelected(const QModelIndex& current); -			void handleSearch(); -			void handleActivated(const QModelIndex& index); -			void handleOkClicked(); -			void handleCancelClicked(); -			void enableCorrectButtons(); +			void handleFirstPageRadioChange(); +			virtual void handleCurrentChanged(int); +			virtual void handleAccepted();  		private: +			void clearForm(); +			void setError(const QString& error); +			JID searchServer(); +			void handleSearch(); +			UserSearchWindow::Type type_;  			UserSearchModel* model_;  			UserSearchDelegate* delegate_; +			QtUserSearchFirstPage* firstPage_; +			QtUserSearchFieldsPage* fieldsPage_; +			QtUserSearchResultsPage* resultsPage_;  			UIEventStream* eventStream_; -			JID lastServiceJID_; +			JID myServer_; +			int lastPage_;  	};  } diff --git a/Swift/QtUI/UserSearch/QtUserSearchWizard.ui b/Swift/QtUI/UserSearch/QtUserSearchWizard.ui new file mode 100644 index 0000000..d403b0b --- /dev/null +++ b/Swift/QtUI/UserSearch/QtUserSearchWizard.ui @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtUserSearchWizard</class> + <widget class="QWizard" name="QtUserSearchWizard"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>711</width> +    <height>524</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Find User</string> +  </property> + </widget> + <resources/> + <connections/> +</ui> | 
 Swift
 Swift