Example #1
0
QDebug operator<<(QDebug dbg, const QXmlStreamReader& reader)
{
    dbg.nospace() << "QXmlStreamReader(";
    if (reader.isStartElement()) {
        dbg.nospace() << "<";
        dbg.nospace() << reader.qualifiedName().toString().toLocal8Bit().constData();
        QString attrsString;
        const QXmlStreamAttributes& attrs = reader.attributes();
        for (int i = 0; i < attrs.count(); i++) {
            dbg.nospace() << " " << attrs[i].qualifiedName().toString().toLocal8Bit().constData();
            dbg.nospace() << "=";
            dbg.nospace() << attrs[i].value().toString();
        }
        if (reader.isEndElement()) {
            dbg.nospace() << "/>)";
        } else {
            dbg.nospace() << ">)";
        }
    } else if (reader.isEndElement()) {
        dbg.nospace() << "</" << reader.qualifiedName().toString().toLocal8Bit().constData() << ">)";
    } else if (reader.isCharacters()) {
        dbg.nospace() << "characters:" << reader.text() << ")";
    } else if (reader.isComment()) {
        dbg.nospace() << "<!-- " << reader.text().toString().toLocal8Bit().constData() << " -->)";
    } else if (reader.isCDATA()) {
        dbg.nospace() << "CDATA:" << reader.text() << ")";
    } else if (reader.isWhitespace()) {
        dbg.nospace() << "whitespace:" << reader.text() << ")";
    } else {
        dbg.nospace() << reader.tokenString() << reader.text();
    }
    return dbg.space();
}
Example #2
0
QVector<DkPackage> DkXmlUpdateChecker::parse(QXmlStreamReader& reader) const {

	QVector<DkPackage> packages;
	QString pName;

	while (!reader.atEnd()) {

		// e.g. <Name>nomacs</Name>
		if (reader.tokenType() == QXmlStreamReader::StartElement && reader.qualifiedName() == "Name") {
			reader.readNext();
			pName = reader.text().toString();
		}
		// e.g. <Version>3.0.0-3</Version>
		else if (reader.tokenType() == QXmlStreamReader::StartElement && reader.qualifiedName() == "Version") {
			reader.readNext();

			if (!pName.isEmpty()) {
				packages.append(DkPackage(pName, reader.text().toString()));
				pName = "";	// reset
			}
			else {
				qWarning() << "version: " << reader.text().toString() << "without a valid package name detected";
			}
		}

		reader.readNext();
	}

	return packages;
}
int CVBAOptions::fromXml(QXmlStreamReader& XmlReader) {
	/* Emulator-spezifische Optionen einlesen */
	while(!XmlReader.atEnd()) {
		XmlReader.readNext();
		
		if(XmlReader.isStartElement()) {
			if(XmlReader.qualifiedName().toString()=="commandline") {
				// Befehlszeile
				this->setEmuCommand(XmlReader.readElementText());
			}
			else if(XmlReader.qualifiedName().toString()=="fullscreen") {
				//Vollbildmodus
				if(XmlReader.readElementText()=="true") this->setFullscreen(true);
				else this->setFullscreen(false);
			}
			else if(XmlReader.qualifiedName().toString()=="scale") {
				//Fenstervergrößerung
				this->setScale(XmlReader.readElementText().toShort());
			}
		}
		else if(XmlReader.isEndElement() && XmlReader.qualifiedName().toString()=="options") {
			/* Abbruch, wenn Optionen zu Ende sind */
			break; // Ende der Optionenliste erreicht
		}
	}
	return 0;
}
bool KeeAgentSettings::fromXml(const QByteArray& ba)
{
    QXmlStreamReader reader;
    reader.addData(ba);

    if (reader.error() || !reader.readNextStartElement()) {
        return false;
    }

    if (reader.qualifiedName() != "EntrySettings") {
        return false;
    }

    while (!reader.error() && reader.readNextStartElement()) {
        if (reader.name() == "AllowUseOfSshKey") {
            m_allowUseOfSshKey = readBool(reader);
        } else if (reader.name() == "AddAtDatabaseOpen") {
            m_addAtDatabaseOpen = readBool(reader);
        } else if (reader.name() == "RemoveAtDatabaseClose") {
            m_removeAtDatabaseClose = readBool(reader);
        } else if (reader.name() == "UseConfirmConstraintWhenAdding") {
            m_useConfirmConstraintWhenAdding = readBool(reader);
        } else if (reader.name() == "UseLifetimeConstraintWhenAdding") {
            m_useLifetimeConstraintWhenAdding = readBool(reader);
        } else if (reader.name() == "LifetimeConstraintDuration") {
            m_lifetimeConstraintDuration = readInt(reader);
        } else if (reader.name() == "Location") {
            while (!reader.error() && reader.readNextStartElement()) {
                if (reader.name() == "SelectedType") {
                    reader.readNext();
                    m_selectedType = reader.text().toString();
                    reader.readNext();
                } else if (reader.name() == "AttachmentName") {
                    reader.readNext();
                    m_attachmentName = reader.text().toString();
                    reader.readNext();
                } else if (reader.name() == "SaveAttachmentToTempFile") {
                    m_saveAttachmentToTempFile = readBool(reader);
                } else if (reader.name() == "FileName") {
                    reader.readNext();
                    m_fileName = reader.text().toString();
                    reader.readNext();
                } else {
                    qWarning() << "Skipping location element" << reader.name();
                    reader.skipCurrentElement();
                }
            }
        } else {
            qWarning() << "Skipping element" << reader.name();
            reader.skipCurrentElement();
        }
    }

    return true;
}
void recurse(QXmlStreamReader & reader,
             QXmlStreamWriter & writer,
             char const * const path,
             Paths && ... paths)
{
    std::size_t mud = 0u;
    while (!reader.atEnd()) {
        switch (reader.readNext()) {

        case QXmlStreamReader::Invalid:
            readError(reader);

        case QXmlStreamReader::StartElement:
            if (mud) {
                ++mud;
                PASS;
            } else if (reader.qualifiedName() == path) {
                PASS;
                recurse(reader, writer, paths...);
            } else {
                ++mud;
                PASS;
            }
            break;
        case QXmlStreamReader::EndElement:
            if (mud) {
                --mud;
                PASS;
            } else {
                PASS;
                return;
            }
            break;
        default:
            PASS;
            break;
        };
    }
}
Example #6
0
void RSSManager::finished()
{
    FollowRedirectReply* reply = qobject_cast<FollowRedirectReply*> (sender());
    if (!reply) {
        return;
    }

    QString replyUrl;
    for (int i = 0; i < m_replies.count(); i++) {
        QPair<FollowRedirectReply*, QUrl> pair = m_replies.at(i);
        if (pair.first == reply) {
            replyUrl = pair.second.toString();
            break;
        }
    }

    if (replyUrl.isEmpty()) {
        return;
    }

    QString currentTag;
    QString linkString;
    QString titleString;

    QXmlStreamReader xml;
    xml.addData(reply->readAll());

    reply->deleteLater();

    int tabIndex = -1;
    for (int i = 0; i < ui->tabWidget->count(); i++) {
        if (replyUrl == ui->tabWidget->tabToolTip(i)) {
            tabIndex = i;
            break;
        }
    }

    if (tabIndex == -1) {
        return;
    }

    TreeWidget* treeWidget = qobject_cast<TreeWidget*>(ui->tabWidget->widget(tabIndex));
    if (!treeWidget) {
        return;
    }
    treeWidget->clear();

    while (!xml.atEnd()) {
        xml.readNext();
        if (xml.isStartElement()) {
            if (xml.name() == QLatin1String("item")) {
                linkString = xml.attributes().value("rss:about").toString();
            }
            currentTag = xml.qualifiedName().toString();
        }
        else if (xml.isEndElement()) {
            if (xml.qualifiedName() == QLatin1String("item")) {
                QTreeWidgetItem* item = new QTreeWidgetItem;
                item->setText(0, titleString);
                item->setIcon(0, QIcon(":/icons/other/feed.png"));
                item->setToolTip(0, linkString);
                treeWidget->addTopLevelItem(item);

                titleString.clear();
                linkString.clear();
            }
        }
        else if (xml.isCharacters() && !xml.isWhitespace()) {
            if (currentTag == QLatin1String("title")) {
                titleString = xml.text().toString();
            }
            else if (currentTag == QLatin1String("link")) {
                linkString += xml.text().toString();
            }
        }
    }

    if (treeWidget->topLevelItemCount() == 0) {
        QTreeWidgetItem* item = new QTreeWidgetItem;
        item->setText(0, tr("Error in fetching feed"));
        treeWidget->addTopLevelItem(item);
    }
}
Example #7
0
    QString read_item( const Outlook::_AppointmentItemPtr &item, QXmlStreamReader &reader, bool dump_exception )
    {
        TRACE(OutlookSyncPlugin) << "OutlookDatebookSync::read_item";

        Outlook::UserPropertiesPtr props = item->GetUserProperties();
        Q_ASSERT(props);

        // We need to clear the recurrence pattern now or we will fail to update recurring events
        if ( !dump_exception )
            item->ClearRecurrencePattern();

        enum State {
            Idle, When, Alarm, Repeat, Exception, Categories
        };
        State state = Idle;
        Outlook::RecurrencePatternPtr recpat = 0;

        QString key;
        QXmlStreamAttributes attributes;
        QString value;
        QStringList categories;
        bool utc = false;
        bool allday = false;
        while (!reader.atEnd()) {
            bool loop = true;
            switch(reader.readNext()) {
                case QXmlStreamReader::StartElement:
                    key = reader.qualifiedName().toString();
                    value = QString();
                    attributes = reader.attributes();
                    if ( key == "When" )
                        state = When;
                    if ( state == When && key == "StartDate" ) {
                        allday = true;
                    }
                    if ( state == When && key == "Start" ) {
                        allday = false;
                    }
                    if ( key == "Alarm" ) {
                        state = Alarm;
                        LOG() << "item->PutReminderSet" << false;
                        item->PutReminderSet( false );
                    }
                    if ( state == Alarm && key == "Type" || key == "Delay" ) {
                        // Outlook only wants to see alarms set on events in the future
                        // If we sync an event in the past with an alarm it will go off
                        // immediately, something that can be annoying when you do an
                        // initial sync with lots of events with alarms.
                        if ( date_to_qdatetime(item->GetStart()) > QDateTime::currentDateTime() ) {
                            LOG() << "item->PutReminderSet" << true;
                            item->PutReminderSet( true );
                        }
                    }
                    if ( !dump_exception ) {
                        if ( key == "Repeat" ) {
                            state = Repeat;
                        }
                        if ( state == Repeat && key == "Type" ) {
                            recpat = item->GetRecurrencePattern();
                            recpat->PutPatternStartDate( item->GetStart() );
                        }
                        if ( state == Repeat && key == "Exception" ) {
                            state = Exception;
                        }
                    }
                    if ( key == "Categories" )
                        state = Categories;
                    break;
                case QXmlStreamReader::Characters:
                    value += reader.text().toString();
                    break;
                case QXmlStreamReader::EndElement:
                    key = reader.qualifiedName().toString();
                    //LOG() << "key" << key << "value" << value;
                    READ_STRING(Description,Subject);
                    READ_STRING(Location,Location);
                    if ( key == "TimeZone" ) {
                        utc = ( !value.isEmpty() );
                    }
                    if ( state == When ) {
                        if ( allday ) {
                            item->PutAllDayEvent( true );
                            READ_DATE(StartDate,Start);
                            // We can't just read the end date because Outlook does it differently to Qtopia.
                            // Qtopia gives us something like "starts 7/10/08, ends 7/10/08" but Outlook
                            // expects "starts 7/10/08 00:00:00, ends 8/10/08 00:00:00".
                            // Simply add one day to the end date to get something Outlook won't barf over.
                            if ( key == "EndDate" ) {
                                QDate dt = stringToDate(value);
                                QDateTime actual( dt.addDays(1), QTime(0,0,0) );
                                LOG() << "item->PutEnd" << actual;
                                item->PutEnd( qdatetime_to_date(actual) );
                            }
                        } else {
                            item->PutAllDayEvent( false );
                            if ( key == "Start" ) {
                                QDateTime dt = stringToDateTime(value, utc);
                                if ( utc ) {
                                    dt.setTimeSpec( Qt::UTC );
                                    dt = dt.toLocalTime();
                                }
                                LOG() << "item->PutStart" << dt;
                                item->PutStart( qdatetime_to_date(dt) );
                            }
                            if ( key == "End" ) {
                                QDateTime dt = stringToDateTime(value, utc);
                                if ( utc ) {
                                    dt.setTimeSpec( Qt::UTC );
                                    dt = dt.toLocalTime();
                                }
                                LOG() << "item->PutEnd" << dt;
                                item->PutEnd( qdatetime_to_date(dt) );
                            }
                        }
                        if ( key == "When" )
                            state = Idle;
                    }
                    if ( state == Alarm ) {
                        READ_ENUM(Type,ReminderPlaySound,true,Audible);
                        READ_ENUM(Type,ReminderPlaySound,false,Visible);
                        READ_INT(Delay,ReminderMinutesBeforeStart);
                        if ( key == "Alarm" )
                            state = Idle;
                    }
                    if ( dump_exception == false && state == Repeat ) {
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursDaily,Daily,recpat);
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursWeekly,Weekly,recpat);
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursMonthly,MonthlyDate,recpat);
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursMonthNth,MonthlyDay,recpat);
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursMonthNth,MonthlyEndDay,recpat);
                        READ_ENUM_ITEM(Type,RecurrenceType,Outlook::olRecursYearly,Yearly,recpat);
                        if ( key == "Type" ) {
                            if ( value == "MonthlyEndDay" ) {
                                LOG() << "recpat->PutInstance" << 5;
                                recpat->PutInstance( 5 );
                            }
                        }

                        if ( key == "Frequency" ) {
                            int interval = QVariant(value).toInt();
                            if ( interval >= 12 && interval % 12 == 0 ) {
                                // since interval is bigger than 12 yet divisible by 12 this is more
                                // likely to be a YearNth which Qtopia Sync Agent sends down as a
                                // MonthNth with interval *= 12
                                recpat->PutRecurrenceType( Outlook::olRecursYearNth );
                            }
                            LOG() << "recpat->PutInterval" << interval;
                            recpat->PutInterval( interval );
                        }

                        if ( key == "Until" ) {
                            if ( value.isEmpty() ) {
                                LOG() << "recpat->PutNoEndDate" << true;
                                recpat->PutNoEndDate( true );
                            } else {
                                LOG() << "recpat->PutPatternEndDate" << QDateTime( stringToDate(value), QTime(0,0,0) );
                                recpat->PutPatternEndDate( qdatetime_to_date(QDateTime( stringToDate(value), QTime(0,0,0) )) );
                            }
                        }

                        // Outlook doesn't seem to support Nearest == false (so ignore it)

                        if ( key == "WeekMask" ) {
                            int mask = 0;
                            foreach( const QString &v, value.split(" ") ) {
                                if ( v == "Monday" ) mask |= Outlook::olMonday;
                                else if ( v == "Tuesday" ) mask |= Outlook::olTuesday;
                                else if ( v == "Wednesday" ) mask |= Outlook::olWednesday;
                                else if ( v == "Thursday" ) mask |= Outlook::olThursday;
                                else if ( v == "Friday" ) mask |= Outlook::olFriday;
                                else if ( v == "Saturday" ) mask |= Outlook::olSaturday;
                                else if ( v == "Sunday" ) mask |= Outlook::olSunday;
                            }
                            LOG() << "recpat->PutDayOfWeekMask" << mask;
                            recpat->PutDayOfWeekMask( (Outlook::OlDaysOfWeek)mask );
                        }

                        if ( key == "Repeat" )
                            state = Idle;
                    }

                    if ( dump_exception == false && state == Exception ) {
                        if ( key == "OriginalDate" ) {
                            QDate exceptionDate = stringToDate(value);
                            Outlook::_AppointmentItemPtr eitem = recpat->GetOccurrence( qdatetime_to_date(QDateTime( exceptionDate, QTime(0,0,0) )) );
                            QString entryid = read_item( eitem, reader, true );
                            if ( entryid.isEmpty() )
                                state = Repeat; // the delete case eats the closing Exception tag
                        }
                        if ( key == "Exception" ) {
                            state = Repeat;
                        }
                    }

                    READ_STRING(Notes,Body);
                    if ( state == Categories ) {
                        if ( key == "Category" )
                            categories << value;
                        if ( key == "Categories" ) {
                            LOG() << "item->PutCategories" << categories;
                            item->PutCategories( qstring_to_bstr(categories.join(", ")) );
                            state = Idle;
                        }
                    }
                    READ_CUSTOM(TimeZone,Qtopia Timezone);

                    if ( dump_exception && key == "Appointment" )
                        loop = false;
                    if ( dump_exception && key == "Exception" ) {
                        // Oops... no Appointment tag in an Exception tag
                        // That means we need to delete the existing exception
                        item->Delete();
                        return QString();
                    }
            }
void recurse(QXmlStreamReader & reader,
             QXmlStreamWriter & writer)
{
    std::size_t mud = 0u;
    QString locationFilename;
    unsigned long long locationLine = 0u;
    QString source;
    while (!reader.atEnd()) {
        switch (reader.readNext()) {

        case QXmlStreamReader::Invalid:
            readError(reader);

        case QXmlStreamReader::StartElement:
            if (mud) {
                ++mud;
                PASS;
            } else {
                if (reader.qualifiedName() == "location") {
                    auto const attrs(reader.attributes());
                    locationFilename = attrs.value("filename").toString();
                    locationLine = attrs.value("line").toULongLong();
                    ++mud;
                    PASS;
                } else if (reader.qualifiedName() == "source") {
                    PASS;
                    QString source(reader.readElementText());
                    if (source.contains(hasPotentialUnicodeEscape)) {
                        QString const oldSource(source);
                        if (!checkUnicodeEscape(source,
                                                locationFilename,
                                                locationLine))
                        {
                            std::cerr << inFilename << ": \""
                                      << source.toStdString() << "\" ("
                                      << locationFilename.toStdString() << ':'
                                      << locationLine << ") not substituted!"
                                      << std::endl;
                            assert(oldSource == source);
                        } else {
                            std::cerr << inFilename << ": \""
                                      << oldSource.toStdString() << "\" -> \""
                                      << source.toStdString() << "\" ("
                                      << locationFilename.toStdString() << ':'
                                      << locationLine << ") substituted."
                                      << std::endl;
                            assert(oldSource != source);
                        }
                    }
                    writer.writeCharacters(source);
                    writer.writeEndElement();
                } else {
                    ++mud;
                    PASS;
                }
            }
            break;
        case QXmlStreamReader::EndElement:
            if (mud) {
                --mud;
                PASS;
                break;
            } else {
                PASS;
                return;
            }
        default:
            PASS;
            break;
        };
    }
}
Example #9
0
std::unique_ptr<Template> Template::loadTemplateConfiguration(QXmlStreamReader& xml, Map& map, bool& open)
{
    Q_ASSERT(xml.name() == QLatin1String("template"));

    QXmlStreamAttributes attributes = xml.attributes();
    if (attributes.hasAttribute(QLatin1String("open")))
        open = (attributes.value(QLatin1String("open")) == QLatin1String("true"));

    QString path = attributes.value(QLatin1String("path")).toString();
    auto temp = templateForFile(path, &map);
    if (!temp)
        temp.reset(new TemplateImage(path, &map)); // fallback

    temp->setTemplateRelativePath(attributes.value(QLatin1String("relpath")).toString());
    if (attributes.hasAttribute(QLatin1String("name")))
        temp->template_file = attributes.value(QLatin1String("name")).toString();
    temp->is_georeferenced = (attributes.value(QLatin1String("georef")) == QLatin1String("true"));
    if (attributes.hasAttribute(QLatin1String("group")))
        temp->template_group = attributes.value(QLatin1String("group")).toInt();

    while (xml.readNextStartElement())
    {
        if (!temp->is_georeferenced && xml.name() == QLatin1String("transformations"))
        {
            temp->adjusted = (xml.attributes().value(QLatin1String("adjusted")) == QLatin1String("true"));
            temp->adjustment_dirty = (xml.attributes().value(QLatin1String("adjustment_dirty")) == QLatin1String("true"));
            int num_passpoints = xml.attributes().value(QLatin1String("passpoints")).toInt();
            Q_ASSERT(temp->passpoints.size() == 0);
            temp->passpoints.reserve(qMin(num_passpoints, 10)); // 10 is not a limit

            while (xml.readNextStartElement())
            {
                QStringRef role = xml.attributes().value(QLatin1String("role"));
                if (xml.name() == QLatin1String("transformation"))
                {
                    if (role == QLatin1String("active"))
                        temp->transform.load(xml);
                    else if (xml.attributes().value(QLatin1String("role")) == QLatin1String("other"))
                        temp->other_transform.load(xml);
                    else
                    {
                        qDebug() << xml.qualifiedName();
                        xml.skipCurrentElement(); // unsupported
                    }
                }
                else if (xml.name() == QLatin1String("passpoint"))
                {
                    temp->passpoints.push_back(PassPoint::load(xml));
                }
                else if (xml.name() == QLatin1String("matrix"))
                {
                    if (role == QLatin1String("map_to_template"))
                        temp->map_to_template.load(xml);
                    else if (role == QLatin1String("template_to_map"))
                        temp->template_to_map.load(xml);
                    else if (role == QLatin1String("template_to_map_other"))
                        temp->template_to_map_other.load(xml);
                    else
                    {
                        qDebug() << xml.qualifiedName();
                        xml.skipCurrentElement(); // unsupported
                    }
                }
                else
                {
                    qDebug() << xml.qualifiedName();
                    xml.skipCurrentElement(); // unsupported
                }
            }
        }
        else if (!temp->loadTypeSpecificTemplateConfiguration(xml))
        {
            temp.reset();
            break;
        }
    }

    if (temp && !temp->is_georeferenced)
    {
        // Fix template adjustment after moving objects during import (cf. #513)
        const auto offset = MapCoord::boundsOffset();
        if (!offset.isZero())
        {
            if (temp->template_to_map.getCols() == 3 && temp->template_to_map.getRows() == 3)
            {
                temp->template_to_map.set(0, 2, temp->template_to_map.get(0, 2) - offset.x / 1000.0);
                temp->template_to_map.set(1, 2, temp->template_to_map.get(1, 2) - offset.y / 1000.0);
                temp->template_to_map.invert(temp->map_to_template);
            }

            if (temp->template_to_map_other.getCols() == 3 && temp->template_to_map_other.getRows() == 3)
            {
                temp->template_to_map_other.set(0, 2, temp->template_to_map_other.get(0, 2) - offset.x / 1000.0);
                temp->template_to_map_other.set(1, 2, temp->template_to_map_other.get(1, 2) - offset.y / 1000.0);
            }
        }

        // Fix template alignment problems caused by grivation rounding since version 0.6
        const double correction = map.getGeoreferencing().getGrivationError();
        if (qAbs(correction) != 0.0
                && (qstrcmp(temp->getTemplateType(), "TemplateTrack") == 0
                    || qstrcmp(temp->getTemplateType(), "OgrTemplate") == 0) )
        {
            temp->setTemplateRotation(temp->getTemplateRotation() + Georeferencing::degToRad(correction));
        }
    }

    return temp;
}
bool EwsFindFolderResponse::parseRootFolder(QXmlStreamReader &reader)
{
    if (reader.namespaceUri() != ewsMsgNsUri || reader.name() != QStringLiteral("RootFolder")) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - expected %1 element (got %2).")
                        .arg(QStringLiteral("RootFolder")).arg(reader.qualifiedName().toString()));
    }

    if (!reader.attributes().hasAttribute(QStringLiteral("TotalItemsInView"))
        || !reader.attributes().hasAttribute(QStringLiteral("TotalItemsInView"))) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - missing attributes of %1 element.")
                                .arg(QStringLiteral("RootFolder")));
    }
    bool ok;
    unsigned totalItems = reader.attributes().value(QStringLiteral("TotalItemsInView")).toUInt(&ok);
    if (!ok) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - failed to read %1 attribute.")
                                        .arg(QStringLiteral("TotalItemsInView")));
    }

    if (!reader.readNextStartElement()) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - expected a child element in %1 element.")
                        .arg(QStringLiteral("RootFolder")));
    }

    if (reader.namespaceUri() != ewsTypeNsUri || reader.name() != QStringLiteral("Folders")) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - expected %1 element (got %2).")
                        .arg(QStringLiteral("Folders")).arg(reader.qualifiedName().toString()));
    }

    if (!reader.readNextStartElement()) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - expected a child element in %1 element.")
                        .arg(QStringLiteral("Folders")));
    }

    if (reader.namespaceUri() != ewsTypeNsUri) {
        return setErrorMsg(QStringLiteral("Failed to read EWS request - expected child element from types namespace."));
    }

    unsigned i = 0;
    for (i = 0; i < totalItems; i++) {
        EwsFolder *folder = readFolder(reader);
        reader.readNextStartElement();
        if (folder) {
            bool ok;
            int childCount = (*folder)[EwsFolderFieldChildFolderCount].toUInt(&ok);
            if (childCount > 0) {
                unsigned readCount = readChildFolders(*folder, childCount, reader);
                if (readCount == 0)
                    return false;
                i += readCount;
            }
            mFolders.append(*folder);
        }
    }

    // Finish the Folders element
    reader.skipCurrentElement();

    // Finish the RootFolder element
    reader.skipCurrentElement();

    return true;
}