From 00284e5f4445a7bbab482196901c5927ea7d5488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Thu, 22 Aug 2013 23:07:51 +0200 Subject: FormField element refactoring. This should make FormField easier to use. Change-Id: Ia5eeedcdb673e2fe5e38fd23d5ab00970178bc44 diff --git a/Swift/QtUI/QtFormResultItemModel.cpp b/Swift/QtUI/QtFormResultItemModel.cpp index b052334..8920128 100644 --- a/Swift/QtUI/QtFormResultItemModel.cpp +++ b/Swift/QtUI/QtFormResultItemModel.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + #include "QtFormResultItemModel.h" #include @@ -69,15 +75,16 @@ const std::string QtFormResultItemModel::getFieldValue(const Form::FormItem& ite foreach(FormField::ref field, item) { if (field->getName() == name) { std::string delimiter = ""; - if (boost::dynamic_pointer_cast(field)) { + if (field->getType() == FormField::TextMultiType) { delimiter = "\n"; - } else if (boost::dynamic_pointer_cast(field)) { + } + else if (field->getType() == FormField::JIDMultiType) { delimiter = ", "; - } else if (boost::dynamic_pointer_cast(field)) { + } + else if (field->getType() == FormField::ListMultiType) { delimiter = ", "; } - - return boost::algorithm::join(field->getRawValues(), delimiter); + return boost::algorithm::join(field->getValues(), delimiter); } } diff --git a/Swift/QtUI/QtFormWidget.cpp b/Swift/QtUI/QtFormWidget.cpp index 4216863..9b213cf 100644 --- a/Swift/QtUI/QtFormWidget.cpp +++ b/Swift/QtUI/QtFormWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2011 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -17,6 +17,8 @@ #include #include +#include +#include namespace Swift { @@ -54,18 +56,16 @@ QtFormWidget::~QtFormWidget() { QListWidget* QtFormWidget::createList(FormField::ref field) { QListWidget* listWidget = new QListWidget(this); listWidget->setSortingEnabled(false); - listWidget->setSelectionMode(boost::dynamic_pointer_cast(field) ? QAbstractItemView::MultiSelection : QAbstractItemView::SingleSelection); - boost::shared_ptr listMultiField = boost::dynamic_pointer_cast(field); - boost::shared_ptr listSingleField = boost::dynamic_pointer_cast(field); + listWidget->setSelectionMode(field->getType() == FormField::ListMultiType ? QAbstractItemView::MultiSelection : QAbstractItemView::SingleSelection); std::vector selected; foreach (FormField::Option option, field->getOptions()) { listWidget->addItem(option.label.c_str()); - if (listSingleField) { - selected.push_back(option.value == listSingleField->getValue()); + if (field->getType() == FormField::ListMultiType) { + selected.push_back(!field->getValues().empty() && option.value == field->getValues()[0]); } - else if (listMultiField) { + else if (field->getType() == FormField::ListMultiType) { std::string text = option.value; - selected.push_back(std::find(listMultiField->getValue().begin(), listMultiField->getValue().end(), text) != listMultiField->getValue().end()); + selected.push_back(std::find(field->getValues().begin(), field->getValues().end(), text) != field->getValues().end()); } } @@ -78,67 +78,47 @@ QListWidget* QtFormWidget::createList(FormField::ref field) { QWidget* QtFormWidget::createWidget(FormField::ref field) { QWidget* widget = NULL; - boost::shared_ptr booleanField = boost::dynamic_pointer_cast(field); - if (booleanField) { + if (field->getType() == FormField::BooleanType) { QCheckBox* checkWidget = new QCheckBox(this); - checkWidget->setCheckState(booleanField->getValue() ? Qt::Checked : Qt::Unchecked); + checkWidget->setCheckState(field->getBoolValue() ? Qt::Checked : Qt::Unchecked); widget = checkWidget; } - boost::shared_ptr fixedField = boost::dynamic_pointer_cast(field); - if (fixedField) { - QString value = fixedField->getValue().c_str(); + if (field->getType() == FormField::FixedType) { + QString value = field->getFixedValue().c_str(); widget = new QLabel(value, this); } - boost::shared_ptr listSingleField = boost::dynamic_pointer_cast(field); - if (listSingleField) { + if (field->getType() == FormField::ListSingleType) { widget = createList(field); } - boost::shared_ptr textMultiField = boost::dynamic_pointer_cast(field); - if (textMultiField) { - QString value = textMultiField->getValue().c_str(); + if (field->getType() == FormField::TextMultiType) { + QString value = field->getTextMultiValue().c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(value); widget = textWidget; } - boost::shared_ptr textPrivateField = boost::dynamic_pointer_cast(field); - if (textPrivateField) { - QString value = textPrivateField->getValue().c_str(); + if (field->getType() == FormField::TextPrivateType) { + QString value = field->getTextPrivateValue().c_str(); QLineEdit* lineWidget = new QLineEdit(value, this); lineWidget->setEchoMode(QLineEdit::Password); widget = lineWidget; } - boost::shared_ptr textSingleField = boost::dynamic_pointer_cast(field); - if (textSingleField) { - QString value = textSingleField->getValue().c_str(); + if (field->getType() == FormField::TextSingleType) { + QString value = field->getTextSingleValue().c_str(); widget = new QLineEdit(value, this); } - boost::shared_ptr jidSingleField = boost::dynamic_pointer_cast(field); - if (jidSingleField) { - QString value = jidSingleField->getValue().toString().c_str(); + if (field->getType() == FormField::JIDSingleType) { + QString value = field->getJIDSingleValue().toString().c_str(); widget = new QLineEdit(value, this); } - boost::shared_ptr jidMultiField = boost::dynamic_pointer_cast(field); - if (jidMultiField) { - QString text; - bool prev = false; - foreach (JID line, jidMultiField->getValue()) { - if (prev) { - text += "\n"; - } - prev = true; - text += line.toString().c_str(); - } + if (field->getType() == FormField::JIDMultiType) { + QString text = boost::join(field->getValues(), "\n").c_str(); QTextEdit* textWidget = new QTextEdit(this); textWidget->setPlainText(text); widget = textWidget; } - boost::shared_ptr listMultiField = boost::dynamic_pointer_cast(field); - if (listMultiField) { + if (field->getType() == FormField::ListMultiType) { widget = createList(field); } - boost::shared_ptr hiddenField = boost::dynamic_pointer_cast(field); - if (hiddenField) { - } fields_[field->getName()] = widget; return widget; } @@ -146,101 +126,51 @@ QWidget* QtFormWidget::createWidget(FormField::ref field) { Form::ref QtFormWidget::getCompletedForm() { Form::ref result(new Form(Form::SubmitType)); foreach (boost::shared_ptr field, form_->getFields()) { - boost::shared_ptr resultField; - boost::shared_ptr booleanField = boost::dynamic_pointer_cast(field); - if (booleanField) { - resultField = FormField::ref(BooleanFormField::create(qobject_cast(fields_[field->getName()])->checkState() == Qt::Checked)); + boost::shared_ptr resultField = boost::make_shared(field->getType()); + if (field->getType() == FormField::BooleanType) { + resultField->setBoolValue(qobject_cast(fields_[field->getName()])->checkState() == Qt::Checked); } - boost::shared_ptr fixedField = boost::dynamic_pointer_cast(field); - if (fixedField) { - resultField = FormField::ref(FixedFormField::create(fixedField->getValue())); + if (field->getType() == FormField::FixedType || field->getType() == FormField::HiddenType) { + resultField->addValue(field->getValues().empty() ? "" : field->getValues()[0]); } - boost::shared_ptr listSingleField = boost::dynamic_pointer_cast(field); - if (listSingleField) { + if (field->getType() == FormField::ListSingleType) { QListWidget* listWidget = qobject_cast(fields_[field->getName()]); if (listWidget->selectedItems().size() > 0) { int i = listWidget->row(listWidget->selectedItems()[0]); - resultField = FormField::ref(ListSingleFormField::create(field->getOptions()[i].value)); - } - else { - resultField = FormField::ref(ListSingleFormField::create()); + resultField->addValue(field->getOptions()[i].value); } } - boost::shared_ptr textMultiField = boost::dynamic_pointer_cast(field); - if (textMultiField) { + if (field->getType() == FormField::TextMultiType) { QTextEdit* widget = qobject_cast(fields_[field->getName()]); QString string = widget->toPlainText(); - if (string.isEmpty()) { - resultField = FormField::ref(TextMultiFormField::create()); - } - else { - resultField = FormField::ref(TextMultiFormField::create(Q2PSTRING(string))); - } - } - boost::shared_ptr textPrivateField = boost::dynamic_pointer_cast(field); - if (textPrivateField) { - QLineEdit* widget = qobject_cast(fields_[field->getName()]); - QString string = widget->text(); - if (string.isEmpty()) { - resultField = FormField::ref(TextPrivateFormField::create()); - } - else { - resultField = FormField::ref(TextPrivateFormField::create(Q2PSTRING(string))); + if (!string.isEmpty()) { + resultField->setTextMultiValue(Q2PSTRING(string)); } } - boost::shared_ptr textSingleField = boost::dynamic_pointer_cast(field); - if (textSingleField) { + if (field->getType() == FormField::TextPrivateType || field->getType() == FormField::TextSingleType || field->getType() == FormField::JIDSingleType) { QLineEdit* widget = qobject_cast(fields_[field->getName()]); QString string = widget->text(); - if (string.isEmpty()) { - resultField = FormField::ref(TextSingleFormField::create()); - } - else { - resultField = FormField::ref(TextSingleFormField::create(Q2PSTRING(string))); + if (!string.isEmpty()) { + resultField->addValue(Q2PSTRING(string)); } } - boost::shared_ptr jidSingleField = boost::dynamic_pointer_cast(field); - if (jidSingleField) { - QLineEdit* widget = qobject_cast(fields_[field->getName()]); - QString string = widget->text(); - JID jid(Q2PSTRING(string)); - if (string.isEmpty()) { - resultField = FormField::ref(JIDSingleFormField::create()); - } - else { - resultField = FormField::ref(JIDSingleFormField::create(jid)); - } - } - boost::shared_ptr jidMultiField = boost::dynamic_pointer_cast(field); - if (jidMultiField) { + if (field->getType() == FormField::JIDMultiType) { QTextEdit* widget = qobject_cast(fields_[field->getName()]); QString string = widget->toPlainText(); - if (string.isEmpty()) { - resultField = FormField::ref(JIDMultiFormField::create()); - } - else { + if (!string.isEmpty()) { QStringList lines = string.split("\n"); - std::vector value; foreach (QString line, lines) { - value.push_back(JID(Q2PSTRING(line))); + resultField->addValue(Q2PSTRING(line)); } - resultField = FormField::ref(JIDMultiFormField::create(value)); } } - boost::shared_ptr listMultiField = boost::dynamic_pointer_cast(field); - if (listMultiField) { + if (field->getType() == FormField::ListMultiType) { QListWidget* listWidget = qobject_cast(fields_[field->getName()]); - std::vector values; foreach (QListWidgetItem* item, listWidget->selectedItems()) { - values.push_back(field->getOptions()[listWidget->row(item)].value); + resultField->addValue(field->getOptions()[listWidget->row(item)].value); } - resultField = FormField::ref(ListMultiFormField::create(values)); - } - boost::shared_ptr hiddenField = boost::dynamic_pointer_cast(field); - if (hiddenField) { - resultField = FormField::ref(HiddenFormField::create(hiddenField->getValue())); } - resultField->setName(field->getName()); + field->setName(field->getName()); result->addField(resultField); } return result; diff --git a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp index 02b238e..73514fd 100644 --- a/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp +++ b/Swift/QtUI/UserSearch/QtUserSearchWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Kevin Smith + * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -179,12 +179,12 @@ JID QtUserSearchWindow::getContactJID() const { Form::FormItem item = dynamic_cast(model_)->getForm()->getItems().at(row); JID fallbackJid; foreach(FormField::ref field, item) { - if (boost::dynamic_pointer_cast(field)) { - jid = JID(field->getRawValues().at(0)); + if (field->getType() == FormField::JIDSingleType) { + jid = JID(field->getJIDSingleValue()); break; } if (field->getName() == "jid") { - fallbackJid = field->getRawValues().at(0); + fallbackJid = field->getValues()[0]; } } if (!jid.isValid()) { diff --git a/Swiften/Disco/CapsInfoGenerator.cpp b/Swiften/Disco/CapsInfoGenerator.cpp index cb93182..4332f76 100644 --- a/Swiften/Disco/CapsInfoGenerator.cpp +++ b/Swiften/Disco/CapsInfoGenerator.cpp @@ -49,7 +49,7 @@ CapsInfo CapsInfoGenerator::generateCapsInfo(const DiscoInfo& discoInfo) const { continue; } serializedCaps += field->getName() + "<"; - std::vector values(field->getRawValues()); + std::vector values(field->getValues()); std::sort(values.begin(), values.end()); foreach(const std::string& value, values) { serializedCaps += value + "<"; diff --git a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp index a1b1a7b..67d27c0 100644 --- a/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp +++ b/Swiften/Disco/UnitTest/CapsInfoGeneratorTest.cpp @@ -51,32 +51,25 @@ class CapsInfoGeneratorTest : public CppUnit::TestFixture { discoInfo.addFeature("http://jabber.org/protocol/muc"); Form::ref extension(new Form(Form::ResultType)); - FormField::ref field = HiddenFormField::create("urn:xmpp:dataforms:softwareinfo"); + FormField::ref field = boost::make_shared(FormField::HiddenType, "urn:xmpp:dataforms:softwareinfo"); field->setName("FORM_TYPE"); extension->addField(field); - std::vector ipVersions; - ipVersions.push_back("ipv6"); - ipVersions.push_back("ipv4"); - field = ListMultiFormField::create(ipVersions); - field->addRawValue("ipv6"); - field->addRawValue("ipv4"); + field = boost::make_shared(FormField::ListMultiType); + field->addValue("ipv6"); + field->addValue("ipv4"); field->setName("ip_version"); extension->addField(field); - field = TextSingleFormField::create("Psi"); - field->addRawValue("Psi"); + field = boost::make_shared(FormField::TextSingleType, "Psi"); field->setName("software"); extension->addField(field); - field = TextSingleFormField::create("0.11"); - field->addRawValue("0.11"); + field = boost::make_shared(FormField::TextSingleType, "0.11"); field->setName("software_version"); extension->addField(field); - field = TextSingleFormField::create("Mac"); + field = boost::make_shared(FormField::TextSingleType, "Mac"); field->setName("os"); - field->addRawValue("Mac"); extension->addField(field); - field = TextSingleFormField::create("10.5.1"); + field = boost::make_shared(FormField::TextSingleType, "10.5.1"); field->setName("os_version"); - field->addRawValue("10.5.1"); extension->addField(field); discoInfo.addExtension(extension); diff --git a/Swiften/Elements/Form.cpp b/Swiften/Elements/Form.cpp index cf9ecf6..c4ae410 100644 --- a/Swiften/Elements/Form.cpp +++ b/Swiften/Elements/Form.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ @@ -11,8 +11,10 @@ namespace Swift { std::string Form::getFormType() const { FormField::ref field = getField("FORM_TYPE"); - boost::shared_ptr f = boost::dynamic_pointer_cast(field); - return (f ? f->getValue() : ""); + if (field && field->getType() == FormField::HiddenType) { + return field->getValues().empty() ? "" : field->getValues()[0]; + } + return ""; } FormField::ref Form::getField(const std::string& name) const { diff --git a/Swiften/Elements/FormField.cpp b/Swiften/Elements/FormField.cpp new file mode 100644 index 0000000..27ced82 --- /dev/null +++ b/Swiften/Elements/FormField.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include + +#include +#include +#include + +using namespace Swift; + +FormField::~FormField() { +} + +std::string FormField::getTextMultiValue() const { + assert(type == TextMultiType || type == UnknownType); + return boost::algorithm::join(values, "\n"); +} + +void FormField::setTextMultiValue(const std::string& value) { + assert(type == TextMultiType || type == UnknownType); + values.clear(); + boost::split(values, value, boost::is_any_of("\n")); +} + +void FormField::setBoolValue(bool b) { + assert(type == BooleanType || type == UnknownType); + values.clear(); + values.push_back(b ? "1" : "0"); +} diff --git a/Swiften/Elements/FormField.h b/Swiften/Elements/FormField.h index fbd1ebe..26e70bb 100644 --- a/Swiften/Elements/FormField.h +++ b/Swiften/Elements/FormField.h @@ -1,12 +1,9 @@ /* - * Copyright (c) 2010 Remko Tronçon + * Copyright (c) 2010-2013 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ -// FIXME: We currently keep 2 values: the raw values, and the actual value. -// We should only store the raw values, and deduce the actual values from this - #pragma once #include @@ -20,7 +17,25 @@ namespace Swift { public: typedef boost::shared_ptr ref; - virtual ~FormField() {} + enum Type { + UnknownType, + BooleanType, + FixedType, + HiddenType, + ListSingleType, + TextMultiType, + TextPrivateType, + TextSingleType, + JIDSingleType, + JIDMultiType, + ListMultiType + }; + + FormField(Type type = UnknownType) : type(type), required(false) {} + FormField(Type type, const std::string& value) : type(type), required(false) { + addValue(value); + } + virtual ~FormField(); struct Option { Option(const std::string& label, const std::string& value) : label(label), value(value) {} @@ -48,67 +63,72 @@ namespace Swift { return options; } - const std::vector& getRawValues() const { - return rawValues; + const std::vector& getValues() const { + return values; } - void addRawValue(const std::string& value) { - rawValues.push_back(value); + void addValue(const std::string& value) { + values.push_back(value); } - protected: - FormField() : required(false) {} + Type getType() const { + return type; + } - private: - std::string name; - std::string label; - std::string description; - bool required; - std::vector