From 05d9e618e4c756e50b633448f0546614a645a13d Mon Sep 17 00:00:00 2001 From: Richard Maudsley Date: Mon, 19 May 2014 12:18:52 +0100 Subject: Add dialog to send AdHoc's to target specific JID's. Fix multi-item Form rendering. Test-Information: Use AdHoc bot that presents a multi-item form and check that it is rendered correctly. Check that entering invalid JID and node parameters in the dialog do not cause malfunction. Check that canceling the JID prompt closes the dialog without sending any server commands. Change-Id: I10e6f4c7eccd1a35c8c885d548994b5f57fdbf66 diff --git a/Swift/Controllers/AdHocManager.cpp b/Swift/Controllers/AdHocManager.cpp index 59e139b..b179ec6 100644 --- a/Swift/Controllers/AdHocManager.cpp +++ b/Swift/Controllers/AdHocManager.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,13 @@ void AdHocManager::handleUIEvent(boost::shared_ptr event) { controller->onDeleting.connect(boost::bind(&AdHocManager::removeController, this, controller)); controllers_.push_back(controller); } + boost::shared_ptr adHocJIDEvent = boost::dynamic_pointer_cast(event); + if (!!adHocJIDEvent) { + boost::shared_ptr command = boost::make_shared(adHocJIDEvent->getJID(), adHocJIDEvent->getNode(), iqRouter_); + boost::shared_ptr controller = boost::make_shared(factory_, command); + controller->onDeleting.connect(boost::bind(&AdHocManager::removeController, this, controller)); + controllers_.push_back(controller); + } } } diff --git a/Swift/Controllers/UIEvents/RequestAdHocWithJIDUIEvent.h b/Swift/Controllers/UIEvents/RequestAdHocWithJIDUIEvent.h new file mode 100644 index 0000000..2b1fcea --- /dev/null +++ b/Swift/Controllers/UIEvents/RequestAdHocWithJIDUIEvent.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014 Kevin Smith and Remko Tronçon + * 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 RequestAdHocWithJIDUIEvent : public UIEvent { + public: + RequestAdHocWithJIDUIEvent(const JID& jid, const std::string& node) : jid_(jid), node_(node) {} + JID getJID() const { return jid_; } + std::string getNode() const { return node_; } + private: + JID jid_; + std::string node_; + }; +} diff --git a/Swift/QtUI/QtAdHocCommandWithJIDWindow.cpp b/Swift/QtUI/QtAdHocCommandWithJIDWindow.cpp new file mode 100644 index 0000000..7f33f77 --- /dev/null +++ b/Swift/QtUI/QtAdHocCommandWithJIDWindow.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010-2014 Kevin Smith + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int FormLayoutIndex = 1; + +namespace Swift { +QtAdHocCommandWithJIDWindow::QtAdHocCommandWithJIDWindow(UIEventStream* uiEventStream) : uiEventStream_(uiEventStream) { + QVBoxLayout* hlayout = new QVBoxLayout(this); + + QLabel* jidLabel = new QLabel("JID:", this); + hlayout->addWidget(jidLabel); + jid_ = new QLineEdit(this); + hlayout->addWidget(jid_); + + QLabel* commandLabel = new QLabel("Command:", this); + hlayout->addWidget(commandLabel); + node_ = new QLineEdit(this); + hlayout->addWidget(node_); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(this); + QPushButton* rejectButton = buttonBox->addButton("Cancel", QDialogButtonBox::RejectRole); + connect(rejectButton, SIGNAL(clicked()), this, SLOT(handleRejectClick())); + QPushButton* acceptButton = buttonBox->addButton("Complete", QDialogButtonBox::AcceptRole); + connect(acceptButton, SIGNAL(clicked()), this, SLOT(handleAcceptClick())); + hlayout->addWidget(buttonBox); + + setLayout(hlayout); + show(); +} + +QtAdHocCommandWithJIDWindow::~QtAdHocCommandWithJIDWindow() { +} + +void QtAdHocCommandWithJIDWindow::handleAcceptClick() { + const JID jid = JID(Q2PSTRING(jid_->text())); + const std::string node = Q2PSTRING(node_->text()); + boost::shared_ptr event(new RequestAdHocWithJIDUIEvent(jid, node)); + uiEventStream_->send(event); + accept(); +} + +void QtAdHocCommandWithJIDWindow::handleRejectClick() { + reject(); +} + +} diff --git a/Swift/QtUI/QtAdHocCommandWithJIDWindow.h b/Swift/QtUI/QtAdHocCommandWithJIDWindow.h new file mode 100644 index 0000000..b168827 --- /dev/null +++ b/Swift/QtUI/QtAdHocCommandWithJIDWindow.h @@ -0,0 +1,32 @@ +/* + * 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 +#include + +#include + +class QBoxLayout; + +namespace Swift { + class UIEventStream; + class QtFormWidget; + class QtAdHocCommandWithJIDWindow : public QDialog { + Q_OBJECT + public: + QtAdHocCommandWithJIDWindow(UIEventStream* eventStream); + virtual ~QtAdHocCommandWithJIDWindow(); + public slots: + void handleAcceptClick(); + void handleRejectClick(); + private: + UIEventStream* uiEventStream_; + QLineEdit* jid_; + QLineEdit* node_; + }; +} diff --git a/Swift/QtUI/QtFormWidget.cpp b/Swift/QtUI/QtFormWidget.cpp index 874c8a1..b4840e9 100644 --- a/Swift/QtUI/QtFormWidget.cpp +++ b/Swift/QtUI/QtFormWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Kevin Smith + * Copyright (c) 2010-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -37,11 +37,27 @@ QtFormWidget::QtFormWidget(Form::ref form, QWidget* parent) : QWidget(parent), f thisLayout->addWidget(scrollArea); QWidget* scroll = new QWidget(this); QGridLayout* layout = new QGridLayout(scroll); - foreach (boost::shared_ptr field, form->getFields()) { - QWidget* widget = createWidget(field); - if (widget) { - layout->addWidget(new QLabel(field->getLabel().c_str(), this), row, 0); - layout->addWidget(widget, row++, 1); + const std::vector items = form->getItems(); + if (items.empty()) { /* single item forms */ + foreach (FormField::ref field, form->getFields()) { + QWidget* widget = createWidget(field, field->getType(), 0); + if (widget) { + layout->addWidget(new QLabel(field->getLabel().c_str(), this), row, 0); + layout->addWidget(widget, row++, 1); + } + } + } else { /* multi-item forms */ + const Form::FormItem& headers = form->getFields(); + for (size_t i = 0; i < items.size(); ++i) { + const Form::FormItem& item = items[i]; + assert(item.size() == headers.size()); + for (size_t j = 0; j < item.size(); ++j) { + QWidget* widget = createWidget(item[j], headers[j]->getType(), i); + if (widget) { + layout->addWidget(new QLabel(item[j]->getLabel().c_str(), this), row, 0); + layout->addWidget(widget, row++, 1); + } + } } } scrollArea->setWidget(scroll); @@ -83,50 +99,55 @@ QListWidget* QtFormWidget::createList(FormField::ref field) { return listWidget; } -QWidget* QtFormWidget::createWidget(FormField::ref field) { +QWidget* QtFormWidget::createWidget(FormField::ref field, const FormField::Type type, const size_t index) { QWidget* widget = NULL; - if (field->getType() == FormField::BooleanType) { + if (type == FormField::BooleanType) { QCheckBox* checkWidget = new QCheckBox(this); checkWidget->setCheckState(field->getBoolValue() ? Qt::Checked : Qt::Unchecked); widget = checkWidget; } - if (field->getType() == FormField::FixedType) { + if (type == FormField::FixedType) { QString value = field->getFixedValue().c_str(); widget = new QLabel(value, this); } - if (field->getType() == FormField::ListSingleType) { + if (type == FormField::ListSingleType) { widget = createList(field); } - if (field->getType() == FormField::TextMultiType) { + if (type == FormField::TextMultiType) { QString value = field->getTextMultiValue().c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(value); widget = textWidget; } - if (field->getType() == FormField::TextPrivateType) { + if (type == FormField::TextPrivateType) { QString value = field->getTextPrivateValue().c_str(); QLineEdit* lineWidget = new QLineEdit(value, this); lineWidget->setEchoMode(QLineEdit::Password); widget = lineWidget; } - if (field->getType() == FormField::TextSingleType) { + if (type == FormField::TextSingleType) { QString value = field->getTextSingleValue().c_str(); widget = new QLineEdit(value, this); } - if (field->getType() == FormField::JIDSingleType) { + if (type == FormField::JIDSingleType) { QString value = field->getJIDSingleValue().toString().c_str(); widget = new QLineEdit(value, this); } - if (field->getType() == FormField::JIDMultiType) { + if (type == FormField::JIDMultiType) { QString text = boost::join(field->getValues(), "\n").c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(text); widget = textWidget; } - if (field->getType() == FormField::ListMultiType) { + if (type == FormField::ListMultiType) { widget = createList(field); } - fields_[field->getName()] = widget; + std::string indexString; + if (index) { + /* for multi-item forms we need to distinguish between the different rows */ + indexString = boost::lexical_cast(index); + } + fields_[field->getName() + indexString] = widget; return widget; } diff --git a/Swift/QtUI/QtFormWidget.h b/Swift/QtUI/QtFormWidget.h index c7aae73..f58ff4b 100644 --- a/Swift/QtUI/QtFormWidget.h +++ b/Swift/QtUI/QtFormWidget.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Kevin Smith + * Copyright (c) 2011-2014 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -23,7 +23,7 @@ class QtFormWidget : public QWidget { Form::ref getCompletedForm(); void setEditable(bool editable); private: - QWidget* createWidget(FormField::ref field); + QWidget* createWidget(FormField::ref field, const FormField::Type type, const size_t index); QListWidget* createList(FormField::ref field); template void setEnabled(QWidget* rawWidget, bool editable); template void setEditable(QWidget* rawWidget, bool editable); diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 31a8234..1db8c77 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #if defined(SWIFTEN_PLATFORM_MACOSX) #include #elif defined(SWIFTEN_PLATFORM_WINDOWS) @@ -50,7 +51,7 @@ namespace Swift { -QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist) : QWidget(), MainWindow(false), loginMenus_(loginMenus) { +QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID) : QWidget(), MainWindow(false), loginMenus_(loginMenus) { uiEventStream_ = uiEventStream; settings_ = settings; setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); @@ -175,6 +176,11 @@ QtMainWindow::QtMainWindow(SettingsProvider* settings, UIEventStream* uiEventStr chatUserAction_->setShortcutContext(Qt::ApplicationShortcut); connect(chatUserAction_, SIGNAL(triggered(bool)), this, SLOT(handleChatUserActionTriggered(bool))); actionsMenu->addAction(chatUserAction_); + if (enableAdHocCommandOnJID) { + otherAdHocAction_ = new QAction(tr("Run Other Command"), this); + connect(otherAdHocAction_, SIGNAL(triggered()), this, SLOT(handleOtherAdHocActionTriggered())); + actionsMenu->addAction(otherAdHocAction_); + } serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this); actionsMenu->addMenu(serverAdHocMenu_); actionsMenu->addSeparator(); @@ -269,6 +275,10 @@ void QtMainWindow::handleChatUserActionTriggered(bool /*checked*/) { uiEventStream_->send(event); } +void QtMainWindow::handleOtherAdHocActionTriggered() { + new QtAdHocCommandWithJIDWindow(uiEventStream_); +} + void QtMainWindow::handleSignOutAction() { loginMenus_.generalMenu->removeAction(toggleRequestDeliveryReceipts_); onSignOutRequest(); diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index f1f6900..84fab15 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -39,7 +39,7 @@ namespace Swift { class QtMainWindow : public QWidget, public MainWindow { Q_OBJECT public: - QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist); + QtMainWindow(SettingsProvider*, UIEventStream* eventStream, QtLoginWindow::QtMenus loginMenus, StatusCache* statusCache, bool emoticonsExist, bool enableAdHocCommandOnJID); virtual ~QtMainWindow(); std::vector getMenus() {return menus_;} void setMyNick(const std::string& name); @@ -69,6 +69,7 @@ namespace Swift { void handleEditProfileAction(); void handleAddUserActionTriggered(bool checked); void handleChatUserActionTriggered(bool checked); + void handleOtherAdHocActionTriggered(); void handleAdHocActionTriggered(bool checked); void handleEventCountUpdated(int count); void handleChatCountUpdated(int count); @@ -87,6 +88,7 @@ namespace Swift { QAction* addUserAction_; QAction* editUserAction_; QAction* chatUserAction_; + QAction* otherAdHocAction_; QAction* showOfflineAction_; QAction* compactRosterAction_; QAction* showEmoticonsAction_; diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 183f64d..d2224ba 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -89,6 +89,7 @@ po::options_description QtSwift::getOptionsDescription() { ("latency-debug", "Use latency debugging (unsupported)") ("multi-account", po::value()->default_value(1), "Number of accounts to open windows for (unsupported)") ("start-minimized", "Don't show the login/roster window at startup") + ("enable-jid-adhocs", "Enable AdHoc commands to custom JID's.") #if QT_VERSION >= 0x040800 ("language", po::value(), "Use a specific language, instead of the system-wide one") #endif @@ -162,6 +163,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa Log::setLogLevel(Swift::Log::debug); } + bool enableAdHocCommandOnJID = options.count("enable-jid-adhocs") > 0; tabs_ = options.count("no-tabs") && !splitter_ ? NULL : new QtChatTabs(splitter_ != NULL); bool startMinimized = options.count("start-minimized") > 0; applicationPathProvider_ = new PlatformApplicationPathProvider(SWIFT_APPLICATION_NAME); @@ -210,7 +212,7 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa // Don't add the first tray (see note above) systemTrays_.push_back(new QtSystemTray()); } - QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), statusCache_, startMinimized, !emoticons.empty()); + QtUIFactory* uiFactory = new QtUIFactory(settingsHierachy_, qtSettings_, tabs_, splitter_, systemTrays_[i], chatWindowFactory_, networkFactories_.getTimerFactory(), statusCache_, startMinimized, !emoticons.empty(), enableAdHocCommandOnJID); uiFactories_.push_back(uiFactory); MainController* mainController = new MainController( &clientMainThreadCaller_, diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index afd2a9e..701170c 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -36,7 +36,7 @@ namespace Swift { -QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist) : settings(settings), qtOnlySettings(qtOnlySettings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(NULL), loginWindow(NULL), statusCache(statusCache), startMinimized(startMinimized), emoticonsExist_(emoticonsExist) { +QtUIFactory::QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID) : settings(settings), qtOnlySettings(qtOnlySettings), tabs(tabs), netbookSplitter(netbookSplitter), systemTray(systemTray), chatWindowFactory(chatWindowFactory), timerFactory_(timerFactory), lastMainWindow(NULL), loginWindow(NULL), statusCache(statusCache), startMinimized(startMinimized), emoticonsExist_(emoticonsExist), enableAdHocCommandOnJID_(enableAdHocCommandOnJID) { chatFontSize = settings->getSetting(QtUISettingConstants::CHATWINDOW_FONT_SIZE); historyFontSize_ = settings->getSetting(QtUISettingConstants::HISTORYWINDOW_FONT_SIZE); } @@ -81,7 +81,7 @@ FileTransferListWidget* QtUIFactory::createFileTransferListWidget() { } MainWindow* QtUIFactory::createMainWindow(UIEventStream* eventStream) { - lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_); + lastMainWindow = new QtMainWindow(settings, eventStream, loginWindow->getMenus(), statusCache, emoticonsExist_, enableAdHocCommandOnJID_); return lastMainWindow; } diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index 721aa76..4c50572 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -32,7 +32,7 @@ namespace Swift { 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); + QtUIFactory(SettingsProviderHierachy* settings, QtSettingsProvider* qtOnlySettings, QtChatTabs* tabs, QtSingleWindow* netbookSplitter, QtSystemTray* systemTray, QtChatWindowFactory* chatWindowFactory, TimerFactory* timerFactory, StatusCache* statusCache, bool startMinimized, bool emoticonsExist, bool enableAdHocCommandOnJID); virtual XMLConsoleWidget* createXMLConsoleWidget(); virtual HistoryWindow* createHistoryWindow(UIEventStream*); @@ -73,5 +73,6 @@ namespace Swift { int chatFontSize; int historyFontSize_; bool emoticonsExist_; + bool enableAdHocCommandOnJID_; }; } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 53dbea9..dd7d0c3 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -119,6 +119,7 @@ sources = [ "QtFileTransferListWidget.cpp", "QtFileTransferListItemModel.cpp", "QtAdHocCommandWindow.cpp", + "QtAdHocCommandWithJIDWindow.cpp", "QtUtilities.cpp", "QtBookmarkDetailWindow.cpp", "QtAddBookmarkWindow.cpp", -- cgit v0.10.2-6-g49f6