diff --git a/src/base/QXmppDataForm.cpp b/src/base/QXmppDataForm.cpp index 9894a59fe..f881e02a4 100644 --- a/src/base/QXmppDataForm.cpp +++ b/src/base/QXmppDataForm.cpp @@ -133,6 +133,40 @@ bool QXmppDataForm::Media::isNull() const return d->uris.empty(); } +void QXmppDataForm::Media::parse(const QDomElement &element) +{ + setHeight(element.attribute("height", "-1").toInt()); + setWidth(element.attribute("width", "-1").toInt()); + + QList > uris; + QDomElement uriElement = element.firstChildElement("uri"); + while (!uriElement.isNull()) { + uris.append(QPair(uriElement.attribute("type"), + uriElement.text())); + uriElement = uriElement.nextSiblingElement("uri"); + } + setUris(uris); +} + +void QXmppDataForm::Media::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("media"); + helperToXmlAddAttribute(writer, "xmlns", ns_media_element); + if (height() > 0) + helperToXmlAddAttribute(writer, "height", QString::number(height())); + if (width() > 0) + helperToXmlAddAttribute(writer, "width", QString::number(width())); + + QPair uri; + foreach(uri, uris()) { + writer->writeStartElement("uri"); + helperToXmlAddAttribute(writer, "type", uri.first); + writer->writeCharacters(uri.second); + writer->writeEndElement(); + } + writer->writeEndElement(); +} + class QXmppDataFormFieldPrivate : public QSharedData { public: @@ -309,6 +343,282 @@ void QXmppDataForm::Field::setValue(const QVariant &value) d->value = value; } +void QXmppDataForm::Field::parse(const QDomElement &element) +{ + /* field type */ + QXmppDataForm::Field::Type type = QXmppDataForm::Field::TextSingleField; + const QString typeStr = element.attribute("type"); + struct field_type *ptr; + for (ptr = field_types; ptr->str; ptr++) + { + if (typeStr == ptr->str) + { + type = ptr->type; + break; + } + } + setType(type); + + /* field attributes */ + setLabel(element.attribute("label")); + setKey(element.attribute("var")); + + /* field value(s) */ + if (type == QXmppDataForm::Field::BooleanField) + { + const QString valueStr = element.firstChildElement("value").text(); + setValue(valueStr == "1" || valueStr == "true"); + } + else if (type == QXmppDataForm::Field::ListMultiField || + type == QXmppDataForm::Field::JidMultiField || + type == QXmppDataForm::Field::TextMultiField) + { + QStringList values; + QDomElement valueElement = element.firstChildElement("value"); + while (!valueElement.isNull()) + { + values.append(valueElement.text()); + valueElement = valueElement.nextSiblingElement("value"); + } + setValue(values); + } + else + { + setValue(element.firstChildElement("value").text()); + } + + /* field media */ + QDomElement mediaElement = element.firstChildElement("media"); + if (!mediaElement.isNull()) { + Media media; + media.parse(mediaElement); + setMedia(media); + } + + /* field options */ + if (type == QXmppDataForm::Field::ListMultiField || + type == QXmppDataForm::Field::ListSingleField) + { + QList > options; + QDomElement optionElement = element.firstChildElement("option"); + while (!optionElement.isNull()) + { + options.append(QPair(optionElement.attribute("label"), + optionElement.firstChildElement("value").text())); + optionElement = optionElement.nextSiblingElement("option"); + } + setOptions(options); + } + + /* other properties */ + setDescription(element.firstChildElement("description").text()); + setRequired(!element.firstChildElement("required").isNull()); +} + +void QXmppDataForm::Field::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("field"); + + /* field type */ + const QXmppDataForm::Field::Type type = this->type(); + QString typeStr; + struct field_type *ptr; + for (ptr = field_types; ptr->str; ptr++) + { + if (type == ptr->type) + { + typeStr = ptr->str; + break; + } + } + writer->writeAttribute("type", typeStr); + + /* field attributes */ + helperToXmlAddAttribute(writer, "label", label()); + helperToXmlAddAttribute(writer, "var", key()); + + /* field value(s) */ + if (type == QXmppDataForm::Field::BooleanField) + { + helperToXmlAddTextElement(writer, "value", value().toBool() ? "1" : "0"); + } + else if (type == QXmppDataForm::Field::ListMultiField || + type == QXmppDataForm::Field::JidMultiField || + type == QXmppDataForm::Field::TextMultiField) + { + foreach (const QString &value, value().toStringList()) + helperToXmlAddTextElement(writer, "value", value); + } + else if (!value().isNull()) + { + helperToXmlAddTextElement(writer, "value", value().toString()); + } + + /* field media */ + Media media = this->media(); + if (!media.isNull()) { + media.toXml(writer); + } + + /* field options */ + if (type == QXmppDataForm::Field::ListMultiField || + type == QXmppDataForm::Field::ListSingleField) + { + QPair option; + foreach (option, options()) + { + writer->writeStartElement("option"); + helperToXmlAddAttribute(writer, "label", option.first); + helperToXmlAddTextElement(writer, "value", option.second); + writer->writeEndElement(); + } + } + + /* other properties */ + if (!description().isEmpty()) + helperToXmlAddTextElement(writer, "description", description()); + if (isRequired()) + helperToXmlAddTextElement(writer, "required", ""); + + writer->writeEndElement(); +} + +class QXmppDataFormItemPrivate : public QSharedData +{ +public: + QXmppDataFormItemPrivate(); + + QList fields; +}; + +QXmppDataFormItemPrivate::QXmppDataFormItemPrivate() +{ +} + +QXmppDataForm::Item::Item() + : d(new QXmppDataFormItemPrivate) +{ +} + +QXmppDataForm::Item::~Item() +{ +} + +QXmppDataForm::Item::Item(const QXmppDataForm::Item &other) + : d(other.d) +{ +} + +QXmppDataForm::Item& QXmppDataForm::Item::operator=(const QXmppDataForm::Item &other) +{ + d = other.d; + return *this; +} + +QList QXmppDataForm::Item::fields() const +{ + return d->fields; +} + +QList &QXmppDataForm::Item::fields() +{ + return d->fields; +} + +void QXmppDataForm::Item::setFields(const QList &fields) +{ + d->fields = fields; +} + +void QXmppDataForm::Item::parse(const QDomElement &element) +{ + QDomElement fieldElement = element.firstChildElement("field"); + while (!fieldElement.isNull()) + { + QXmppDataForm::Field field; + field.parse(fieldElement); + d->fields.append(field); + fieldElement = fieldElement.nextSiblingElement("field"); + } +} + +void QXmppDataForm::Item::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("item"); + foreach (const QXmppDataForm::Field &field, d->fields) { + field.toXml(writer); + } + writer->writeEndElement(); +} + +class QXmppDataFormReportedPrivate : public QSharedData +{ +public: + QXmppDataFormReportedPrivate(); + + QList fields; +}; + +QXmppDataFormReportedPrivate::QXmppDataFormReportedPrivate() +{ +} + +QXmppDataForm::Reported::Reported() + : d(new QXmppDataFormReportedPrivate) +{ +} + +QXmppDataForm::Reported::~Reported() +{ +} + +QXmppDataForm::Reported::Reported(const QXmppDataForm::Reported &other) + : d(other.d) +{ +} + +QXmppDataForm::Reported& QXmppDataForm::Reported::operator=(const QXmppDataForm::Reported &other) +{ + d = other.d; + return *this; +} + +QList QXmppDataForm::Reported::fields() const +{ + return d->fields; +} + +QList &QXmppDataForm::Reported::fields() +{ + return d->fields; +} + +void QXmppDataForm::Reported::setFields(const QList &fields) +{ + d->fields = fields; +} + +void QXmppDataForm::Reported::parse(const QDomElement &element) +{ + QDomElement fieldElement = element.firstChildElement("field"); + while (!fieldElement.isNull()) + { + QXmppDataForm::Field field; + field.parse(fieldElement); + d->fields.append(field); + fieldElement = fieldElement.nextSiblingElement("field"); + } +} + +void QXmppDataForm::Reported::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("reported"); + foreach (const QXmppDataForm::Field &field, d->fields) { + field.toXml(writer); + } + writer->writeEndElement(); +} + class QXmppDataFormPrivate : public QSharedData { public: @@ -316,6 +626,8 @@ class QXmppDataFormPrivate : public QSharedData QString instructions; QList fields; + QList items; + QXmppDataForm::Reported reported; QString title; QXmppDataForm::Type type; }; @@ -432,6 +744,31 @@ bool QXmppDataForm::isNull() const return d->type == QXmppDataForm::None; } +QList QXmppDataForm::items() const +{ + return d->items; +} + +QList &QXmppDataForm::items() +{ + return d->items; +} + +void QXmppDataForm::setItems(const QList &items) +{ + d->items = items; +} + +QXmppDataForm::Reported QXmppDataForm::reported() const +{ + return d->reported; +} + +void QXmppDataForm::setReported(const QXmppDataForm::Reported reported) +{ + d->reported = reported; +} + /// \cond void QXmppDataForm::parse(const QDomElement &element) { @@ -462,90 +799,25 @@ void QXmppDataForm::parse(const QDomElement &element) while (!fieldElement.isNull()) { QXmppDataForm::Field field; - - /* field type */ - QXmppDataForm::Field::Type type = QXmppDataForm::Field::TextSingleField; - const QString typeStr = fieldElement.attribute("type"); - struct field_type *ptr; - for (ptr = field_types; ptr->str; ptr++) - { - if (typeStr == ptr->str) - { - type = ptr->type; - break; - } - } - field.setType(type); - - /* field attributes */ - field.setLabel(fieldElement.attribute("label")); - field.setKey(fieldElement.attribute("var")); - - /* field value(s) */ - if (type == QXmppDataForm::Field::BooleanField) - { - const QString valueStr = fieldElement.firstChildElement("value").text(); - field.setValue(valueStr == "1" || valueStr == "true"); - } - else if (type == QXmppDataForm::Field::ListMultiField || - type == QXmppDataForm::Field::JidMultiField || - type == QXmppDataForm::Field::TextMultiField) - { - QStringList values; - QDomElement valueElement = fieldElement.firstChildElement("value"); - while (!valueElement.isNull()) - { - values.append(valueElement.text()); - valueElement = valueElement.nextSiblingElement("value"); - } - field.setValue(values); - } - else - { - field.setValue(fieldElement.firstChildElement("value").text()); - } - - /* field media */ - QDomElement mediaElement = fieldElement.firstChildElement("media"); - if (!mediaElement.isNull()) { - Media media; - media.setHeight(mediaElement.attribute("height", "-1").toInt()); - media.setWidth(mediaElement.attribute("width", "-1").toInt()); - - QList > uris; - QDomElement uriElement = mediaElement.firstChildElement("uri"); - while (!uriElement.isNull()) { - uris.append(QPair(uriElement.attribute("type"), - uriElement.text())); - uriElement = uriElement.nextSiblingElement("uri"); - } - media.setUris(uris); - field.setMedia(media); - } - - /* field options */ - if (type == QXmppDataForm::Field::ListMultiField || - type == QXmppDataForm::Field::ListSingleField) - { - QList > options; - QDomElement optionElement = fieldElement.firstChildElement("option"); - while (!optionElement.isNull()) - { - options.append(QPair(optionElement.attribute("label"), - optionElement.firstChildElement("value").text())); - optionElement = optionElement.nextSiblingElement("option"); - } - field.setOptions(options); - } - - /* other properties */ - field.setDescription(fieldElement.firstChildElement("description").text()); - field.setRequired(!fieldElement.firstChildElement("required").isNull()); - + field.parse(fieldElement); d->fields.append(field); - fieldElement = fieldElement.nextSiblingElement("field"); } + + QDomElement reportedElement = element.firstChildElement("reported"); + if (!reportedElement.isNull()) + { + d->reported.parse(reportedElement); + } + + QDomElement itemElement = element.firstChildElement("item"); + while (!itemElement.isNull()) + { + QXmppDataForm::Item item; + item.parse(itemElement); + d->items.append(item); + itemElement = itemElement.nextSiblingElement("item"); + } } void QXmppDataForm::toXml(QXmlStreamWriter *writer) const @@ -575,86 +847,15 @@ void QXmppDataForm::toXml(QXmlStreamWriter *writer) const writer->writeTextElement("instructions", d->instructions); foreach (const QXmppDataForm::Field &field, d->fields) { - writer->writeStartElement("field"); - - /* field type */ - const QXmppDataForm::Field::Type type = field.type(); - QString typeStr; - struct field_type *ptr; - for (ptr = field_types; ptr->str; ptr++) - { - if (type == ptr->type) - { - typeStr = ptr->str; - break; - } - } - writer->writeAttribute("type", typeStr); - - /* field attributes */ - helperToXmlAddAttribute(writer, "label", field.label()); - helperToXmlAddAttribute(writer, "var", field.key()); - - /* field value(s) */ - if (type == QXmppDataForm::Field::BooleanField) - { - helperToXmlAddTextElement(writer, "value", field.value().toBool() ? "1" : "0"); - } - else if (type == QXmppDataForm::Field::ListMultiField || - type == QXmppDataForm::Field::JidMultiField || - type == QXmppDataForm::Field::TextMultiField) - { - foreach (const QString &value, field.value().toStringList()) - helperToXmlAddTextElement(writer, "value", value); - } - else if (!field.value().isNull()) - { - helperToXmlAddTextElement(writer, "value", field.value().toString()); - } - - /* field media */ - Media media = field.media(); - if (!media.isNull()) { - writer->writeStartElement("media"); - helperToXmlAddAttribute(writer, "xmlns", ns_media_element); - if (media.height() > 0) - helperToXmlAddAttribute(writer, "height", QString::number(media.height())); - if (media.width() > 0) - helperToXmlAddAttribute(writer, "width", QString::number(media.width())); - - QPair uri; - foreach(uri, media.uris()) { - writer->writeStartElement("uri"); - helperToXmlAddAttribute(writer, "type", uri.first); - writer->writeCharacters(uri.second); - writer->writeEndElement(); - } - writer->writeEndElement(); - } - - /* field options */ - if (type == QXmppDataForm::Field::ListMultiField || - type == QXmppDataForm::Field::ListSingleField) - { - QPair option; - foreach (option, field.options()) - { - writer->writeStartElement("option"); - helperToXmlAddAttribute(writer, "label", option.first); - helperToXmlAddTextElement(writer, "value", option.second); - writer->writeEndElement(); - } - } + field.toXml(writer); + } - /* other properties */ - if (!field.description().isEmpty()) - helperToXmlAddTextElement(writer, "description", field.description()); - if (field.isRequired()) - helperToXmlAddTextElement(writer, "required", ""); + if (!d->reported.fields().isEmpty()) + d->reported.toXml(writer); - writer->writeEndElement(); + foreach (const QXmppDataForm::Item &item, d->items) { + item.toXml(writer); } - writer->writeEndElement(); } /// \endcond diff --git a/src/base/QXmppDataForm.h b/src/base/QXmppDataForm.h index b5136c68c..f064ec42b 100644 --- a/src/base/QXmppDataForm.h +++ b/src/base/QXmppDataForm.h @@ -32,6 +32,8 @@ class QXmppDataFormPrivate; class QXmppDataFormFieldPrivate; class QXmppDataFormMediaPrivate; +class QXmppDataFormItemPrivate; +class QXmppDataFormReportedPrivate; /// \brief The QXmppDataForm class represents a data form as defined by /// XEP-0004: Data Forms. @@ -64,6 +66,8 @@ class QXMPP_EXPORT QXmppDataForm bool isNull() const; + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *writer) const; private: QSharedDataPointer d; }; @@ -120,10 +124,50 @@ class QXMPP_EXPORT QXmppDataForm QVariant value() const; void setValue(const QVariant &value); + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *writer) const; private: QSharedDataPointer d; }; + class QXMPP_EXPORT Item + { + public: + Item(const QXmppDataForm::Item &other); + Item(); + ~Item(); + + QXmppDataForm::Item& operator=(const QXmppDataForm::Item &other); + + QList fields() const; + QList &fields(); + void setFields(const QList &fields); + + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *writer) const; + private: + QSharedDataPointer d; + }; + + class QXMPP_EXPORT Reported + { + public: + Reported(const QXmppDataForm::Reported &other); + Reported(); + ~Reported(); + + QXmppDataForm::Reported& operator=(const QXmppDataForm::Reported &other); + + QList fields() const; + QList &fields(); + void setFields(const QList &fields); + + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *writer) const; + private: + QSharedDataPointer d; + }; + /// This enum is used to describe a form's type. enum Type { @@ -160,6 +204,13 @@ class QXMPP_EXPORT QXmppDataForm bool isNull() const; + QList items() const; + QList &items(); + void setItems(const QList &items); + + Reported reported() const; + void setReported(const QXmppDataForm::Reported reported); + /// \cond void parse(const QDomElement &element); void toXml(QXmlStreamWriter *writer) const; diff --git a/tests/qxmppdataform/tst_qxmppdataform.cpp b/tests/qxmppdataform/tst_qxmppdataform.cpp index 829ef196d..1bf094dd5 100644 --- a/tests/qxmppdataform/tst_qxmppdataform.cpp +++ b/tests/qxmppdataform/tst_qxmppdataform.cpp @@ -34,6 +34,7 @@ private slots: void testSimple(); void testSubmit(); void testMedia(); + void testMultipleItems(); }; void tst_QXmppDataForm::testSimple() @@ -112,5 +113,88 @@ void tst_QXmppDataForm::testMedia() serializePacket(form, xml); } +void tst_QXmppDataForm::testMultipleItems() +{ + const QByteArray xml( + "" + "" + "" + "" + "" + "" + "" + "" + "" + "Zam@im-BestTaiwan.com.tw" + "" + "" + "Zam" + "" + "" + "Zam" + "" + "" + "Zam@BestTaiwan.com.tw" + "" + "" + ""); + + QXmppDataForm form; + parsePacket(form, xml); + + QCOMPARE(form.isNull(), false); + QCOMPARE(form.items().size(), 1); + + const QString KEY_JID = "jid"; + const QString KEY_USERNAME = "Username"; + const QString KEY_NAME = "Name"; + const QString KEY_EMAIL = "Email"; + /* reported tag test */ + QCOMPARE(form.reported().fields().size(), 4); + + QXmppDataForm::Field jidField = form.reported().fields().at(0); + QCOMPARE(jidField.key(), KEY_JID); + QCOMPARE(jidField.type(), QXmppDataForm::Field::JidSingleField); + QCOMPARE(jidField.label(), QString("JID")); + + QXmppDataForm::Field usernameField = form.reported().fields().at(1); + QCOMPARE(usernameField.key(), KEY_USERNAME); + QCOMPARE(usernameField.type(), QXmppDataForm::Field::TextSingleField); + QCOMPARE(usernameField.label(), QString("Username")); + + QXmppDataForm::Field nameField = form.reported().fields().at(2); + QCOMPARE(nameField.key(), KEY_NAME); + QCOMPARE(nameField.type(), QXmppDataForm::Field::TextSingleField); + QCOMPARE(nameField.label(), QString("Name")); + + QXmppDataForm::Field emailField = form.reported().fields().at(3); + QCOMPARE(emailField.key(), KEY_EMAIL); + QCOMPARE(emailField.type(), QXmppDataForm::Field::TextSingleField); + QCOMPARE(emailField.label(), QString("Email")); + + /* item tag test */ + QCOMPARE(form.items().size(), 1); + QXmppDataForm::Item item = form.items().at(0); + QCOMPARE(item.fields().size(), 4); + + QXmppDataForm::Field jidItemField = item.fields().at(0); + QCOMPARE(jidItemField.key(), KEY_JID); + QCOMPARE(jidItemField.value().toString(), QString("Zam@im-BestTaiwan.com.tw")); + + QXmppDataForm::Field usernameItemField = item.fields().at(1); + QCOMPARE(usernameItemField.key(), KEY_USERNAME); + QCOMPARE(usernameItemField.value().toString(), QString("Zam")); + + QXmppDataForm::Field nameItemField = item.fields().at(2); + QCOMPARE(nameItemField.key(), KEY_NAME); + QCOMPARE(nameItemField.value().toString(), QString("Zam")); + + QXmppDataForm::Field emailItemField = item.fields().at(3); + QCOMPARE(emailItemField.key(), KEY_EMAIL); + QCOMPARE(emailItemField.value().toString(), QString("Zam@BestTaiwan.com.tw")); + + serializePacket(form, xml); +} + QTEST_MAIN(tst_QXmppDataForm) #include "tst_qxmppdataform.moc"