From 506d1621530a40d3e59f50f693587c3c4fd724f5 Mon Sep 17 00:00:00 2001 From: Kevin Smith <git@kismith.co.uk> Date: Thu, 23 Dec 2010 19:36:00 +0000 Subject: Turn the 'Find other users' into seperate add/chat menu items with a wizard. 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/RequestAddUserDialogUIEvent.h b/Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h new file mode 100644 index 0000000..bfa4a8b --- /dev/null +++ b/Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.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 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/UIEvents/RequestUserSearchUIEvent.h b/Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h deleted file mode 100644 index 1312a84..0000000 --- a/Swift/Controllers/UIEvents/RequestUserSearchUIEvent.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 RequestUserSearchUIEvent : 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> -- cgit v0.10.2-6-g49f6