Commit ae7229a6 authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Port course resources to XML stream parser

parent 85c3dbc0
......@@ -96,7 +96,7 @@ std::vector<std::unique_ptr<Unit>> CourseParser::parseUnits(const QUrl &path)
if (xml.name() == "units") {
continue;
} else if (xml.name() == "unit") {
auto unit = parseUnit(xml, elementOk);
auto unit = parseUnit(xml, path, elementOk);
if (elementOk) {
units.push_back(std::move(unit));
}
......@@ -115,7 +115,7 @@ std::vector<std::unique_ptr<Unit>> CourseParser::parseUnits(const QUrl &path)
return units;
}
std::unique_ptr<Unit> CourseParser::parseUnit(QXmlStreamReader &xml, bool &ok)
std::unique_ptr<Unit> CourseParser::parseUnit(QXmlStreamReader &xml, const QUrl &path, bool &ok)
{
std::unique_ptr<Unit> unit(new Unit);
ok = true;
......@@ -133,6 +133,9 @@ std::unique_ptr<Unit> CourseParser::parseUnit(QXmlStreamReader &xml, bool &ok)
if (xml.name() == "id") {
unit->setId(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "foreignId") {
unit->setForeignId(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "title") {
unit->setTitle(parseElement(xml, elementOk));
ok &= elementOk;
......@@ -140,7 +143,7 @@ std::unique_ptr<Unit> CourseParser::parseUnit(QXmlStreamReader &xml, bool &ok)
// nothing to do
}
else if (xml.name() == "phrase") {
auto phrase = parsePhrase(xml, elementOk);
auto phrase = parsePhrase(xml, path, elementOk);
if (elementOk) {
unit->addPhrase(phrase);
}
......@@ -157,7 +160,7 @@ std::unique_ptr<Unit> CourseParser::parseUnit(QXmlStreamReader &xml, bool &ok)
return unit;
}
Phrase * CourseParser::parsePhrase(QXmlStreamReader &xml, bool &ok)
Phrase * CourseParser::parsePhrase(QXmlStreamReader &xml, const QUrl &path, bool &ok)
{
Phrase * phrase = new Phrase(nullptr);
ok = true;
......@@ -176,9 +179,20 @@ Phrase * CourseParser::parsePhrase(QXmlStreamReader &xml, bool &ok)
if (xml.name() == "id") {
phrase->setId(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "foreignId") {
phrase->setForeignId(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "text") {
phrase->setText(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "i18nText") {
phrase->seti18nText(parseElement(xml, elementOk));
ok &= elementOk;
} else if (xml.name() == "soundFile") {
phrase->setSound(QUrl::fromLocalFile(
path.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path()
+ '/' + parseElement(xml, elementOk)));
ok &= elementOk;
} else if (xml.name() == "type") {
const QString type = parseElement(xml, elementOk);
if (type == "word") {
......@@ -191,6 +205,16 @@ Phrase * CourseParser::parsePhrase(QXmlStreamReader &xml, bool &ok)
phrase->setType(Phrase::Paragraph);
}
ok &= elementOk;
} else if (xml.name() == "editState") {
const QString type = parseElement(xml, elementOk);
if (type == "translated") {
phrase->setEditState(Phrase::EditState::Translated);
} else if (type == "completed") {
phrase->setEditState(Phrase::EditState::Completed);
} else if (type == "unknown") {
phrase->setEditState(Phrase::EditState::Completed);
}
ok &= elementOk;
} else {
qCWarning(ARTIKULATE_PARSER()) << "Skipping unknown token" << xml.name();
}
......@@ -219,55 +243,6 @@ QString CourseParser::parseElement(QXmlStreamReader& xml, bool &ok)
return xml.text().toString();
}
Phrase * CourseParser::parsePhrase(QDomElement phraseNode, Unit* parentUnit)
{
const ICourse *course = parentUnit->course();
Q_ASSERT(course != nullptr);
Phrase *phrase = new Phrase(parentUnit);
phrase->setId(phraseNode.firstChildElement(QStringLiteral("id")).text());
phrase->setText(phraseNode.firstChildElement(QStringLiteral("text")).text());
phrase->seti18nText(phraseNode.firstChildElement(QStringLiteral("i18nText")).text());
phrase->setUnit(parentUnit);
if (!phraseNode.firstChildElement(QStringLiteral("soundFile")).text().isEmpty()) {
phrase->setSound(QUrl::fromLocalFile(
course->file().adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path()
+ '/' + phraseNode.firstChildElement(QStringLiteral("soundFile")).text())
);
}
phrase->setType(phraseNode.firstChildElement(QStringLiteral("type")).text());
phrase->setEditState(phraseNode.firstChildElement(QStringLiteral("editState")).text());
if (!phraseNode.firstChildElement(QStringLiteral("foreignId")).isNull()) {
phrase->setForeignId(phraseNode.firstChildElement(QStringLiteral("foreignId")).text());
}
// add phonemes
QList<Phoneme *> phonemes = course->language()->phonemes();
for (QDomElement phonemeID = phraseNode.firstChildElement(QStringLiteral("phonemes")).firstChildElement();
!phonemeID.isNull();
phonemeID = phonemeID.nextSiblingElement())
{
QString id = phonemeID.text();
if (id.isEmpty()) {
qCritical() << "Phoneme ID string is empty for phrase "<< phrase->id() <<", aborting.";
continue;
}
for (Phoneme *phoneme : phonemes) {
if (phoneme->id() == id) {
phrase->addPhoneme(phoneme);
break;
}
}
}
if (!phraseNode.firstChildElement(QStringLiteral("excluded")).isNull() &&
phraseNode.firstChildElement(QStringLiteral("excluded")).text() == QLatin1String("true"))
{
phrase->setExcluded(true);
}
return phrase;
}
QDomDocument CourseParser::serializedDocument(ICourse *course, bool trainingExport)
{
......
......@@ -60,16 +60,14 @@ public:
static std::vector<std::unique_ptr<Unit>> parseUnits(const QUrl &path);
static Phrase * parsePhrase(QDomElement phraseNode, Unit* parentUnit);
static QDomDocument serializedDocument(ICourse *course, bool trainingExport);
static QDomElement serializedPhrase(Phrase *phrase, QDomDocument &document);
static bool exportCourseToGhnsPackage(ICourse *course, const QString &exportPath);
private:
static std::unique_ptr<Unit> parseUnit(QXmlStreamReader &xml, bool &ok);
static Phrase * parsePhrase(QXmlStreamReader &xml, bool &ok);
static std::unique_ptr<Unit> parseUnit(QXmlStreamReader &xml, const QUrl &path, bool &ok);
static Phrase * parsePhrase(QXmlStreamReader &xml, const QUrl &path, bool &ok);
static QString parseElement(QXmlStreamReader &xml, bool &ok);
};
#endif
......@@ -76,47 +76,8 @@ void CourseResourcePrivate::loadCourse(CourseResource *parent)
return;
}
// load existing file
QXmlSchema schema = CourseParser::loadXmlSchema(QStringLiteral("course"));
if (!schema.isValid()) {
qCWarning(ARTIKULATE_CORE()) << "Scheme not valid, aborting";
return;
}
QDomDocument document = CourseParser::loadDomDocument(m_file, schema);
if (document.isNull()) {
qCWarning(ARTIKULATE_CORE()) << "Could not parse document " << m_file.toLocalFile() << ", aborting.";
return;
}
// load missing elements of course
// TODO usage of QDomElement is quite slow and should be exchanged with the QXmlParser in the future
QDomElement root(document.documentElement());
if (!root.firstChildElement(QStringLiteral("foreignId")).isNull()) {
m_foreignId = root.firstChildElement(QStringLiteral("foreignId")).text();
}
// create units
for (QDomElement unitNode = root.firstChildElement(QStringLiteral("units")).firstChildElement();
!unitNode.isNull();
unitNode = unitNode.nextSiblingElement())
{
std::unique_ptr<Unit> unit(new Unit);
unit->setId(unitNode.firstChildElement(QStringLiteral("id")).text());
unit->setCourse(parent);
unit->setTitle(unitNode.firstChildElement(QStringLiteral("title")).text());
if (!unitNode.firstChildElement(QStringLiteral("foreignId")).isNull()) {
unit->setForeignId(unitNode.firstChildElement(QStringLiteral("foreignId")).text());
}
// create phrases
for (QDomElement phraseNode = unitNode.firstChildElement(QStringLiteral("phrases")).firstChildElement();
!phraseNode.isNull();
phraseNode = phraseNode.nextSiblingElement())
{
unit->addPhrase(CourseParser::parsePhrase(phraseNode, unit.get())); // add to unit at last step to produce only one signal
//FIXME phrase does not cause unit signals that phonemes list is changed
}
auto units = CourseParser::parseUnits(m_file);
for (auto &unit : units) {
parent->addUnit(std::move(unit));
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment