diff options
author | Peter Burgess <pete.burgess@isode.com> | 2018-04-20 15:18:20 (GMT) |
---|---|---|
committer | Peter Burgess <pete.burgess@isode.com> | 2018-07-24 15:05:11 (GMT) |
commit | d3bbd300be4480c0a3b7285c91b3b27e82ca9c2f (patch) | |
tree | a86f47b56647363141523a7182cd84cd2551ef62 /Swift/QtUI | |
parent | 5b4a0ba19ae6994db6a193a231fd2486bff6f0ec (diff) | |
download | swift-d3bbd300be4480c0a3b7285c91b3b27e82ca9c2f.zip swift-d3bbd300be4480c0a3b7285c91b3b27e82ca9c2f.tar.bz2 |
Add a XEP-346 FDP Form Submission Dialog
A new form submission dialog that will discover nodes containing
fdp form templates in a given pubsub domain, and will present the form
to the user ready to be filled out and submitted.
Test-Infomation:
Personally tested the request for all node items, loading the
latest form from one of the discovered nodes, submitting a form
and checking it turns up on my mlink server using mlc, checked that
the submitted infomation is correct, what happens when an incorrect
domain is queried, what happens when a valid domain is queried but
it has no fdp nodes, and what happens when a form is requested from
an invalid node.
Unit tests written to test success and failure of the three controller
functions requestPubSubNodeData(), requestTemplateForm() and
testSubmitForm().
Change-Id: If8c57bb4e3120dd44d52f7332069eb18a14cb385
Diffstat (limited to 'Swift/QtUI')
-rw-r--r-- | Swift/QtUI/QtFdpFormSubmitWindow.cpp | 215 | ||||
-rw-r--r-- | Swift/QtUI/QtFdpFormSubmitWindow.h | 75 | ||||
-rw-r--r-- | Swift/QtUI/QtListWidget.cpp | 20 | ||||
-rw-r--r-- | Swift/QtUI/QtListWidget.h | 23 | ||||
-rw-r--r-- | Swift/QtUI/QtMainWindow.cpp | 12 | ||||
-rw-r--r-- | Swift/QtUI/QtMainWindow.h | 2 | ||||
-rw-r--r-- | Swift/QtUI/QtUIFactory.cpp | 5 | ||||
-rw-r--r-- | Swift/QtUI/QtUIFactory.h | 2 | ||||
-rw-r--r-- | Swift/QtUI/SConscript | 2 |
9 files changed, 356 insertions, 0 deletions
diff --git a/Swift/QtUI/QtFdpFormSubmitWindow.cpp b/Swift/QtUI/QtFdpFormSubmitWindow.cpp new file mode 100644 index 0000000..5719f87 --- /dev/null +++ b/Swift/QtUI/QtFdpFormSubmitWindow.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swift/QtUI/QtFdpFormSubmitWindow.h> + +#include <QCloseEvent> +#include <QHBoxLayout> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <QSpacerItem> +#include <QVBoxLayout> + +#include <Swift/QtUI/QtFormWidget.h> +#include <Swift/QtUI/QtListWidget.h> +#include <Swift/QtUI/QtSwiftUtil.h> + +namespace Swift { +QtFdpFormSubmitWindow::QtFdpFormSubmitWindow(QWidget* parent) : QDialog(parent), FdpFormSubmitWindow() { + layout_ = new QVBoxLayout(this); + subLayout_ = new QHBoxLayout(this); + + initNodeViewLayout(); + initFormLayout(); + subLayout_->addLayout(nodeViewLayout_); + subLayout_->addLayout(formLayout_); + subLayout_->setStretchFactor(nodeViewLayout_, 2); + subLayout_->setStretchFactor(formLayout_, 3); + layout_->addLayout(subLayout_); + + submitButton_ = new QPushButton(tr("Submit Form"), this); + submitButton_->setEnabled(false); + okButton_ = new QPushButton(tr("Ok"), this); + okButton_->hide(); + cancelButton_ = new QPushButton(tr("Cancel"), this); + connect(submitButton_, &QPushButton::clicked, this, &QtFdpFormSubmitWindow::handleSubmitClicked); + connect(okButton_, &QPushButton::clicked, this, &QWidget::close); + connect(cancelButton_, &QPushButton::clicked, this, &QWidget::close); + auto buttonSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + buttonLayout_ = new QHBoxLayout(this); + buttonLayout_->addItem(buttonSpacer); + buttonLayout_->addWidget(submitButton_); + buttonLayout_->addWidget(cancelButton_); + layout_->addLayout(buttonLayout_); + + setMinimumWidth(800); + setMinimumHeight(600); + + this->setWindowTitle(tr("FDP Form Submission")); +} + +QtFdpFormSubmitWindow::~QtFdpFormSubmitWindow() { +} + +void QtFdpFormSubmitWindow::closeEvent(QCloseEvent* event) { + event->ignore(); + onCloseEvent(); +} + +void QtFdpFormSubmitWindow::initNodeViewLayout() { + nodeViewLayout_ = new QVBoxLayout(this); + auto domainSearchLayout = new QHBoxLayout(this); + pubSubDomainEdit_ = new QLineEdit(this); + loadDomainButton_ = new QPushButton(tr("Load"), this); + pubSubNodeView_ = new QtListWidget(this); + pubSubDomainEdit_->setPlaceholderText(tr("Enter pubsub domain here")); + pubSubNodeView_->setMinimumWidth(300); + connect(loadDomainButton_, &QPushButton::clicked, this, &QtFdpFormSubmitWindow::handleLoadDomainButtonClicked); + connect(pubSubNodeView_, &QListWidget::itemDoubleClicked, this, &QtFdpFormSubmitWindow::handlePubSubNodeViewItemDoubleClicked); + domainSearchLayout->addWidget(pubSubDomainEdit_); + domainSearchLayout->addWidget(loadDomainButton_); + nodeViewLayout_->addLayout(domainSearchLayout); + nodeViewLayout_->addWidget(pubSubNodeView_); +} + +void QtFdpFormSubmitWindow::initFormLayout() { + formPlaceholder_ = new QLabel(tr("No form loaded")); + formPlaceholder_->setAlignment(Qt::AlignCenter); + formPlaceholder_->setMinimumWidth(200); + formPlaceholder_->setStyleSheet("QLabel { color : #AAAAAA; }"); + formLayout_ = new QVBoxLayout(this); + formLayout_->addWidget(formPlaceholder_, Qt::AlignCenter); +} + +void QtFdpFormSubmitWindow::show() { + QDialog::show(); +} + +void QtFdpFormSubmitWindow::raise() { + QDialog::raise(); +} + +void QtFdpFormSubmitWindow::addNode(const std::string& node, const std::string& nodeName) { + auto listItem = new QListWidgetItem(P2QSTRING(nodeName)); + listItem->setData(Qt::UserRole, P2QSTRING(node)); + pubSubNodeView_->addItem(listItem); +} + +void QtFdpFormSubmitWindow::clearNodeData() { + pubSubNodeView_->clear(); + pubSubNodeView_->setWordWrap(false); + disconnect(pubSubNodeView_, &QtListWidget::onResize, this, &QtFdpFormSubmitWindow::handleNodeListResize); +} + +void QtFdpFormSubmitWindow::setFormData(const std::shared_ptr<Form>& form) { + if (formWidget_) { + formLayout_->removeWidget(formWidget_); + formWidget_->deleteLater(); + formWidget_ = nullptr; + } + else if (!formPlaceholder_->isHidden()) { + formLayout_->removeWidget(formPlaceholder_); + formPlaceholder_->hide(); + } + formWidget_ = new QtFormWidget(form); + formWidget_->setEditable(true); + formLayout_->addWidget(formWidget_); + + if (!okButton_->isHidden()) { + buttonLayout_->removeWidget(okButton_); + okButton_->hide(); + } + if (submitButton_->isHidden()) { + buttonLayout_->insertWidget(1, submitButton_); + submitButton_->show(); + } + submitButton_->setEnabled(true); + cancelButton_->setEnabled(true); +} + +void QtFdpFormSubmitWindow::showNodePlaceholder(NodeError nodeError) { + pubSubNodeView_->clear(); + pubSubNodeView_->setWordWrap(true); + auto listItem = new QListWidgetItem; + auto placeholderText = P2QSTRING(getNodeErrorText(nodeError)); + listItem->setText(placeholderText); + listItem->setTextAlignment(Qt::AlignCenter); + listItem->setFlags(Qt::NoItemFlags); + listItem->setSizeHint(QSize(listItem->sizeHint().width(), pubSubNodeView_->height())); + connect(pubSubNodeView_, &QtListWidget::onResize, this, &QtFdpFormSubmitWindow::handleNodeListResize); + pubSubNodeView_->addItem(listItem); +} + +void QtFdpFormSubmitWindow::showFormPlaceholder(TemplateError templateError) { + if (formWidget_) { + formLayout_->removeWidget(formWidget_); + formWidget_->deleteLater(); + formWidget_ = nullptr; + } + auto placeholderText = P2QSTRING(getTemplateErrorText(templateError)); + formPlaceholder_->setText(placeholderText); + if (formPlaceholder_->isHidden()) { + formLayout_->addWidget(formPlaceholder_, Qt::AlignCenter); + formPlaceholder_->show(); + } + + if (!okButton_->isHidden()) { + buttonLayout_->removeWidget(okButton_); + okButton_->hide(); + } + if (submitButton_->isHidden()) { + buttonLayout_->insertWidget(1, submitButton_); + submitButton_->show(); + } + submitButton_->setEnabled(false); + cancelButton_->setEnabled(true); +} + +void QtFdpFormSubmitWindow::handleLoadDomainButtonClicked() { + std::string domainUri = Q2PSTRING(pubSubDomainEdit_->text()); + onRequestPubSubNodeData(domainUri); +} + +void QtFdpFormSubmitWindow::handlePubSubListViewTemplateSelected(const std::string& nodeName) { + onRequestTemplateForm(nodeName); +} + +void QtFdpFormSubmitWindow::handlePubSubNodeViewItemDoubleClicked(QListWidgetItem* item) { + handlePubSubListViewTemplateSelected(Q2PSTRING(item->data(Qt::UserRole).toString())); +} + +void QtFdpFormSubmitWindow::handleSubmitClicked() { + auto form = formWidget_->getCompletedForm(); + formWidget_->setDisabled(true); + submitButton_->setEnabled(false); + onSubmitForm(form); +} + +void QtFdpFormSubmitWindow::handleSubmitServerResponse(bool submissionSuccess) { + if (submissionSuccess) { + if (!submitButton_->isHidden()) { + buttonLayout_->removeWidget(submitButton_); + submitButton_->hide(); + } + if (okButton_->isHidden()) { + buttonLayout_->insertWidget(1, okButton_); + okButton_->show(); + } + cancelButton_->setEnabled(false); + } + else { + formWidget_->setDisabled(false); + submitButton_->setEnabled(true); + } +} + +void QtFdpFormSubmitWindow::handleNodeListResize() { + auto placeholderItem = pubSubNodeView_->item(0); + placeholderItem->setSizeHint(QSize(placeholderItem->sizeHint().width(), pubSubNodeView_->height())); +} + +} diff --git a/Swift/QtUI/QtFdpFormSubmitWindow.h b/Swift/QtUI/QtFdpFormSubmitWindow.h new file mode 100644 index 0000000..c178a5b --- /dev/null +++ b/Swift/QtUI/QtFdpFormSubmitWindow.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> + +#include <QDialog> + +#include <Swift/Controllers/UIInterfaces/FdpFormSubmitWindow.h> + +class QHBoxLayout; +class QLabel; +class QLineEdit; +class QListWidgetItem; +class QPushButton; +class QTextEdit; +class QVBoxLayout; + +namespace Swift { + + class Form; + class QtFormWidget; + class QtListWidget; + class QtPubSubNodeController; + + class QtFdpFormSubmitWindow : public QDialog, public FdpFormSubmitWindow { + Q_OBJECT + + public: + QtFdpFormSubmitWindow(QWidget* parent = nullptr); + virtual ~QtFdpFormSubmitWindow(); + + protected: + virtual void closeEvent(QCloseEvent* event) override; + + private: + void initNodeViewLayout(); + void initFormLayout(); + virtual void show() override; + virtual void raise() override; + virtual void addNode(const std::string& node, const std::string& nodeName) override; + virtual void clearNodeData() override; + virtual void setFormData(const std::shared_ptr<Form>& form) override; + virtual void showNodePlaceholder(NodeError nodeError) override; + virtual void showFormPlaceholder(TemplateError templateError) override; + virtual void handleSubmitServerResponse(bool submissionSuccess) override; + + private slots: + void handleLoadDomainButtonClicked(); + void handlePubSubListViewTemplateSelected(const std::string& nodeName); + void handlePubSubNodeViewItemDoubleClicked(QListWidgetItem* item); + void handleSubmitClicked(); + void handleNodeListResize(); + + private: + QVBoxLayout* layout_; + QHBoxLayout* subLayout_; + QHBoxLayout* buttonLayout_; + QVBoxLayout* nodeViewLayout_; + QVBoxLayout* formLayout_; + QLineEdit* pubSubDomainEdit_; + QPushButton* loadDomainButton_; + QtListWidget* pubSubNodeView_; + QLabel* formPlaceholder_; + QTextEdit* nodePlaceholderTextEdit_ = nullptr; + QtFormWidget* formWidget_ = nullptr; + QPushButton* cancelButton_; + QPushButton* submitButton_ = nullptr; + QPushButton* okButton_ = nullptr; + }; +} diff --git a/Swift/QtUI/QtListWidget.cpp b/Swift/QtUI/QtListWidget.cpp new file mode 100644 index 0000000..e35bbbb --- /dev/null +++ b/Swift/QtUI/QtListWidget.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swift/QtUI/QtListWidget.h> + +#include <QListWidget> + +namespace Swift { + +QtListWidget::QtListWidget(QWidget* parent) : QListWidget(parent) { +} + +void QtListWidget::resizeEvent(QResizeEvent*) { + emit onResize(); +} + +} diff --git a/Swift/QtUI/QtListWidget.h b/Swift/QtUI/QtListWidget.h new file mode 100644 index 0000000..b7380c4 --- /dev/null +++ b/Swift/QtUI/QtListWidget.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <QListWidget> + +namespace Swift { + +class QtListWidget : public QListWidget { + Q_OBJECT + public: + QtListWidget(QWidget* parent = nullptr); + protected: + virtual void resizeEvent(QResizeEvent*); + signals: + void onResize(); +}; + +} diff --git a/Swift/QtUI/QtMainWindow.cpp b/Swift/QtUI/QtMainWindow.cpp index 7eec8d1..92488ae 100644 --- a/Swift/QtUI/QtMainWindow.cpp +++ b/Swift/QtUI/QtMainWindow.cpp @@ -27,6 +27,7 @@ #include <Swift/Controllers/SettingConstants.h> #include <Swift/Controllers/UIEvents/JoinMUCUIEvent.h> +#include <Swift/Controllers/UIEvents/FdpFormSubmitWindowOpenUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAdHocUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestBlockListDialogUIEvent.h> @@ -199,6 +200,13 @@ QtMainWindow::QtMainWindow(Chattables& chattables, SettingsProvider* settings, U } serverAdHocMenu_ = new QMenu(tr("Run Server Command"), this); actionsMenu->addMenu(serverAdHocMenu_); + if (settings_->getSetting(SettingConstants::FUTURE)) { + actionsMenu->addSeparator(); + submitFormAction_ = new QAction(tr("Submit Form"), this); + connect(submitFormAction_, &QAction::triggered, this, &QtMainWindow::handleSubmitFormActionTriggered); + actionsMenu->addAction(submitFormAction_); + onlineOnlyActions_ << submitFormAction_; + } actionsMenu->addSeparator(); QAction* signOutAction = new QAction(tr("&Sign Out"), this); connect(signOutAction, SIGNAL(triggered()), SLOT(handleSignOutAction())); @@ -437,4 +445,8 @@ void QtMainWindow::setBlockingCommandAvailable(bool isAvailable) { openBlockingListEditor_->setVisible(isAvailable); } +void QtMainWindow::handleSubmitFormActionTriggered() { + uiEventStream_->send(std::make_shared<FdpFormSubmitWindowOpenUIEvent>()); +} + } diff --git a/Swift/QtUI/QtMainWindow.h b/Swift/QtUI/QtMainWindow.h index 0e7f290..b285831 100644 --- a/Swift/QtUI/QtMainWindow.h +++ b/Swift/QtUI/QtMainWindow.h @@ -81,6 +81,7 @@ namespace Swift { void handleShowCertificateInfo(); void handleEditBlockingList(); void handleSomethingSelectedChanged(bool itemSelected); + void handleSubmitFormActionTriggered(); private: Chattables& chattables_; @@ -110,5 +111,6 @@ namespace Swift { std::vector<DiscoItems::Item> serverAdHocCommands_; QList<QAction*> serverAdHocCommandActions_; QList<QAction*> onlineOnlyActions_; + QAction* submitFormAction_; }; } diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp index 2762d68..93fca5f 100644 --- a/Swift/QtUI/QtUIFactory.cpp +++ b/Swift/QtUI/QtUIFactory.cpp @@ -22,6 +22,7 @@ #include <Swift/QtUI/QtChatWindow.h> #include <Swift/QtUI/QtChatWindowFactory.h> #include <Swift/QtUI/QtContactEditWindow.h> +#include <Swift/QtUI/QtFdpFormSubmitWindow.h> #include <Swift/QtUI/QtFileTransferListWidget.h> #include <Swift/QtUI/QtHighlightNotificationConfigDialog.h> #include <Swift/QtUI/QtHistoryWindow.h> @@ -175,6 +176,10 @@ AdHocCommandWindow* QtUIFactory::createAdHocCommandWindow(std::shared_ptr<Outgoi return new QtAdHocCommandWindow(command); } +std::unique_ptr<FdpFormSubmitWindow> QtUIFactory::createFdpFormSubmitWindow() { + return std::make_unique<QtFdpFormSubmitWindow>(); +} + void QtUIFactory::showTabs() { if (!tabs_->isVisible()) { tabs_->show(); diff --git a/Swift/QtUI/QtUIFactory.h b/Swift/QtUI/QtUIFactory.h index ad8dc1f..04836fe 100644 --- a/Swift/QtUI/QtUIFactory.h +++ b/Swift/QtUI/QtUIFactory.h @@ -18,6 +18,7 @@ class QSplitter; namespace Swift { class AutoUpdater; class Chattables; + class FdpFormSubmitWindow; class QtChatTabs; class QtChatTheme; class QtChatWindow; @@ -54,6 +55,7 @@ namespace Swift { virtual HighlightEditorWindow* createHighlightEditorWindow(); virtual BlockListEditorWidget* createBlockListEditorWidget(); virtual AdHocCommandWindow* createAdHocCommandWindow(std::shared_ptr<OutgoingAdHocCommandSession> command); + virtual std::unique_ptr<FdpFormSubmitWindow> createFdpFormSubmitWindow(); private slots: void handleChatWindowFontResized(int); diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 535ccaf..a2ad9b1 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -177,6 +177,7 @@ sources = [ "QtEmojisSelector.cpp", "QtEmoticonsGrid.cpp", "QtExpandedListView.cpp", + "QtFdpFormSubmitWindow.cpp", "QtFileTransferListItemModel.cpp", "QtFileTransferListWidget.cpp", "QtFormResultItemModel.cpp", @@ -185,6 +186,7 @@ sources = [ "QtHistoryWindow.cpp", "QtJoinMUCWindow.cpp", "QtLineEdit.cpp", + "QtListWidget.cpp", "QtLoginWindow.cpp", "QtMainWindow.cpp", "QtMUCConfigurationWindow.cpp", |