diff --git a/src/acbf/AcbfBookinfo.cpp b/src/acbf/AcbfBookinfo.cpp index 8eb4275..c4506d8 100644 --- a/src/acbf/AcbfBookinfo.cpp +++ b/src/acbf/AcbfBookinfo.cpp @@ -1,485 +1,536 @@ /* * Copyright (C) 2015 Dan Leinir Turthra Jensen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #include "AcbfBookinfo.h" #include "AcbfAuthor.h" #include "AcbfContentrating.h" #include "AcbfDatabaseref.h" #include "AcbfLanguage.h" #include "AcbfPage.h" #include "AcbfSequence.h" #include #include #include using namespace AdvancedComicBookFormat; class BookInfo::Private { public: Private() : coverPage(0) {} QList author; QHash title; QHash genre; QList characters; QHash annotation; QHash keywords; Page* coverPage; QList languages; QList sequence; QList databaseRef; QList contentRating; }; BookInfo::BookInfo(Metadata* parent) : QObject(parent) , d(new Private) { qRegisterMetaType("BookInfo*"); d->coverPage = new Page(metadata()->document()); d->coverPage->setIsCoverPage(true); } BookInfo::~BookInfo() { delete d; } Metadata * BookInfo::metadata() { return qobject_cast(parent()); } void BookInfo::toXml(QXmlStreamWriter* writer) { writer->writeStartElement("book-info"); Q_FOREACH(Author* author, d->author) { author->toXml(writer); } QHashIterator titles(d->title); while(titles.hasNext()) { titles.next(); writer->writeStartElement("book-title"); writer->writeAttribute("lang", titles.key()); writer->writeCharacters(titles.value()); writer->writeEndElement(); } QHashIterator genres(d->genre); while(genres.hasNext()) { genres.next(); writer->writeStartElement("genre"); writer->writeAttribute("match", QString::number(genres.value())); writer->writeCharacters(genres.key()); writer->writeEndElement(); } writer->writeStartElement("characters"); writer->writeCharacters(""); Q_FOREACH(const QString& character, d->characters) { writer->writeStartElement("name"); writer->writeCharacters(character); writer->writeEndElement(); } writer->writeEndElement(); QHashIterator annotations(d->annotation); while(annotations.hasNext()) { annotations.next(); writer->writeStartElement("annotation"); writer->writeAttribute("lang", annotations.key()); Q_FOREACH(const QString& paragraph, annotations.value()) { writer->writeStartElement("p"); writer->writeCharacters(paragraph); writer->writeEndElement(); } writer->writeEndElement(); } QHashIterator keywords(d->keywords); while(keywords.hasNext()) { keywords.next(); writer->writeStartElement("keywords"); writer->writeAttribute("lang", keywords.key()); writer->writeCharacters(keywords.value().join(',')); writer->writeEndElement(); } d->coverPage->toXml(writer); writer->writeStartElement("languages"); Q_FOREACH(Language* language, d->languages) { language->toXml(writer); } writer->writeEndElement(); Q_FOREACH(Sequence* sequence, d->sequence) { sequence->toXml(writer); } Q_FOREACH(DatabaseRef* ref, d->databaseRef) { ref->toXml(writer); } Q_FOREACH(ContentRating* rating, d->contentRating) { rating->toXml(writer); } writer->writeEndElement(); } bool BookInfo::fromXml(QXmlStreamReader *xmlReader) { while(xmlReader->readNextStartElement()) { if(xmlReader->name() == "author") { Author* newAuthor = new Author(metadata()); if(!newAuthor->fromXml(xmlReader)) { return false; } d->author.append(newAuthor); } else if(xmlReader->name() == "book-title") { QString language = xmlReader->attributes().value("lang").toString(); d->title[language] = xmlReader->readElementText(QXmlStreamReader::IncludeChildElements); } else if(xmlReader->name() == "genre") { int match = xmlReader->attributes().value("match").toInt(); d->genre[xmlReader->readElementText(QXmlStreamReader::IncludeChildElements)] = match; } else if(xmlReader->name() == "characters") { while(xmlReader->readNextStartElement()) { if(xmlReader->name() == "name") { d->characters.append(xmlReader->readElementText(QXmlStreamReader::IncludeChildElements)); } else { xmlReader->skipCurrentElement(); } } qDebug() << "Created character entries, we now have" << d->characters.count() << "characters"; } else if(xmlReader->name() == "annotation") { QString language = xmlReader->attributes().value("lang").toString(); QStringList paragraphs; while(xmlReader->readNextStartElement()) { if(xmlReader->name() == "p") { paragraphs.append(xmlReader->readElementText(QXmlStreamReader::IncludeChildElements)); } else { xmlReader->skipCurrentElement(); } } d->annotation[language] = paragraphs; } else if(xmlReader->name() == "keywords") { QString language = xmlReader->attributes().value("lang").toString(); d->keywords[language] = xmlReader->readElementText(QXmlStreamReader::IncludeChildElements).split(','); } else if(xmlReader->name() == "coverpage") { if(!d->coverPage->fromXml(xmlReader)) { return false; } } else if(xmlReader->name() == "languages") { while(xmlReader->readNextStartElement()) { if(xmlReader->name() == "text-layer") { Language* newLanguage = new Language(this); newLanguage->fromXml(xmlReader); d->languages.append(newLanguage); } else { xmlReader->skipCurrentElement(); } } } else if(xmlReader->name() == "sequence") { Sequence* newSequence = new Sequence(this); newSequence->fromXml(xmlReader); d->sequence.append(newSequence); } else if(xmlReader->name() == "databaseref") { DatabaseRef* newDatabaseRef = new DatabaseRef(this); newDatabaseRef->fromXml(xmlReader); d->databaseRef.append(newDatabaseRef); } else if(xmlReader->name() == "content-rating") { ContentRating* newContentRating = new ContentRating(this); newContentRating->fromXml(xmlReader); d->contentRating.append(newContentRating); } else { qWarning() << Q_FUNC_INFO << "currently unsupported subsection:" << xmlReader->name(); xmlReader->skipCurrentElement(); } } if (xmlReader->hasError()) { qWarning() << Q_FUNC_INFO << "Failed to read ACBF XML document at token" << xmlReader->name() << "(" << xmlReader->lineNumber() << ":" << xmlReader->columnNumber() << ") The reported error was:" << xmlReader->errorString(); } qDebug() << Q_FUNC_INFO << "Created book information for the book with the titles" << d->title.values();; return !xmlReader->hasError(); } -QList BookInfo::author() +QList BookInfo::author() { return d->author; } +QStringList BookInfo::authorNames() const +{ + QStringList names; + for(Author* author : d->author) { + names.append(author->displayName()); + } + return names; +} + +Author * BookInfo::getAuthor(int index) const +{ + return d->author.at(index); +} + +void BookInfo::addAuthor(QString activity, QString language, QString firstName, QString middleName, QString lastName, QString nickName, QString homePage, QString email) +{ + Author* author = new Author(metadata()); + author->setActivity(activity); + author->setLanguage(language); + author->setFirstName(firstName); + author->setMiddleName(middleName); + author->setLastName(lastName); + author->setNickName(nickName); + author->setHomePage(homePage); + author->setEmail(email); + d->author.append(author); + emit authorsChanged(); +} + +void BookInfo::setAuthor(int index, QString activity, QString language, QString firstName, QString middleName, QString lastName, QString nickName, QString homePage, QString email) +{ + Author* author = d->author.at(index); + author->setActivity(activity); + author->setLanguage(language); + author->setFirstName(firstName); + author->setMiddleName(middleName); + author->setLastName(lastName); + author->setNickName(nickName); + author->setHomePage(homePage); + author->setEmail(email); + emit authorsChanged(); +} + +void BookInfo::removeAuthor(int index) +{ + d->author.removeAt(index); + emit authorsChanged(); +} + void BookInfo::addAuthor(Author* author) { d->author.append(author); + emit authorsChanged(); } void BookInfo::removeAuthor(Author* author) { d->author.removeAll(author); + emit authorsChanged(); } QStringList BookInfo::titleForAllLanguages() { return d->title.values(); } QStringList BookInfo::titleLanguages() { return d->title.keys(); } QString BookInfo::title(QString language) { if(language.isEmpty()) { language = "en"; } return d->title.value(language); } void BookInfo::setTitle(QString title, QString language) { // Don't allow removal of the default title, just everything else if(title.isEmpty() && !language.isEmpty()) { d->title.remove(language); } else { d->title[language] = title; } emit titleChanged(); } QHash BookInfo::genre() { return d->genre; } QStringList BookInfo::genres() const { return d->genre.keys(); } int BookInfo::genrePercentage(QString genre) const { return d->genre[genre]; } void BookInfo::setGenre(QString genre, int matchPercentage) { bool emitNewGenre = !d->genre.contains(genre); d->genre[genre] = matchPercentage; if(emitNewGenre) { emit genresChanged(); } } void BookInfo::removeGenre(QString genre) { d->genre.remove(genre); emit genresChanged(); } QStringList BookInfo::availableGenres() { QStringList genres; genres << "science_fiction"; genres << "fantasy"; genres << "adventure"; genres << "horror"; genres << "mystery"; genres << "crime"; genres << "military"; // (war ...) genres << "real_life"; genres << "superhero"; // (e.g. Superman, Spiderman … or Super Villains) genres << "humor"; genres << "western"; genres << "manga"; genres << "politics"; genres << "caricature"; genres << "sports"; genres << "history"; // (historical comics) genres << "biography"; // (biographical comics) genres << "education"; // (education and science) genres << "computer"; // (computers related) genres << "religion"; genres << "romance"; genres << "children"; genres << "non-fiction"; genres << "adult"; genres << "alternative"; // (abstract, underground ...) genres << "other"; return genres; } QStringList BookInfo::characters() { return d->characters; } void BookInfo::addCharacter(QString name) { d->characters.append(name); emit charactersChanged(); } void BookInfo::removeCharacter(QString name) { d->characters.removeAll(name); emit charactersChanged(); } QList BookInfo::annotationsForAllLanguage() { return d->annotation.values(); } QStringList BookInfo::annotationLanguages() { return d->annotation.keys(); } QStringList BookInfo::annotation(QString language) { return d->annotation.value(language); } void BookInfo::setAnnotation(QStringList annotation, QString language) { d->annotation[language] = annotation; } QHash BookInfo::keywordsForAllLanguage() { return d->keywords; } QStringList BookInfo::keywords(QString language) { return d->keywords.value(language); } void BookInfo::setKeywords(QStringList keywords, QString language) { d->keywords[language] = keywords; } Page * BookInfo::coverpage() { return d->coverPage; } void BookInfo::setCoverpage(Page* newCover) { d->coverPage = newCover; } QList BookInfo::languages() { return d->languages; } void BookInfo::addLanguage(Language* language) { d->languages.append(language); } void BookInfo::removeLanguage(Language* language) { d->languages.removeAll(language); } QList BookInfo::sequence() { return d->sequence; } void BookInfo::addSequence(Sequence* sequence) { d->sequence.append(sequence); } void BookInfo::removeSequence(Sequence* sequence) { d->sequence.removeAll(sequence); } QList BookInfo::databaseRef() { return d->databaseRef; } void BookInfo::addDatabaseRef(DatabaseRef* databaseRef) { d->databaseRef.append(databaseRef); } void BookInfo::removeDatabaseRef(DatabaseRef* databaseRef) { d->databaseRef.removeAll(databaseRef); } QList BookInfo::contentRating() { return d->contentRating; } void BookInfo::addContentRating(ContentRating* contentRating) { d->contentRating.append(contentRating); } void BookInfo::removeContentRating(ContentRating* contentRating) { d->contentRating.removeAll(contentRating); } diff --git a/src/acbf/AcbfBookinfo.h b/src/acbf/AcbfBookinfo.h index 93d432d..6cd9940 100644 --- a/src/acbf/AcbfBookinfo.h +++ b/src/acbf/AcbfBookinfo.h @@ -1,108 +1,115 @@ /* * Copyright (C) 2015 Dan Leinir Turthra Jensen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) version 3, or any * later version accepted by the membership of KDE e.V. (or its * successor approved by the membership of KDE e.V.), which shall * act as a proxy defined in Section 6 of version 3 of the license. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * */ #ifndef ACBFBOOKINFO_H #define ACBFBOOKINFO_H #include "AcbfMetadata.h" #include namespace AdvancedComicBookFormat { class Author; class Page; class Language; class Sequence; class DatabaseRef; class ContentRating; class ACBF_EXPORT BookInfo : public QObject { Q_OBJECT + Q_PROPERTY(QStringList authorNames READ authorNames NOTIFY authorsChanged) Q_PROPERTY(QStringList titleLanguages READ titleLanguages NOTIFY titleChanged) Q_PROPERTY(QStringList genres READ genres NOTIFY genresChanged) Q_PROPERTY(QStringList characters READ characters NOTIFY charactersChanged) public: explicit BookInfo(Metadata* parent = 0); virtual ~BookInfo(); Metadata* metadata(); void toXml(QXmlStreamWriter *writer); bool fromXml(QXmlStreamReader *xmlReader); QList author(); + QStringList authorNames() const; + Q_INVOKABLE Author* getAuthor(int index) const; + Q_INVOKABLE void addAuthor(QString activity, QString language, QString firstName, QString middleName, QString lastName, QString nickName, QString homePage, QString email); + Q_INVOKABLE void setAuthor(int index, QString activity, QString language, QString firstName, QString middleName, QString lastName, QString nickName, QString homePage, QString email); + Q_INVOKABLE void removeAuthor(int index); void addAuthor(Author* author); void removeAuthor(Author* author); + Q_SIGNAL void authorsChanged(); Q_INVOKABLE QStringList titleForAllLanguages(); Q_INVOKABLE QStringList titleLanguages(); Q_INVOKABLE QString title(QString language = ""); Q_INVOKABLE void setTitle(QString title, QString language = ""); Q_SIGNAL void titleChanged(); Q_INVOKABLE QHash genre(); Q_INVOKABLE QStringList genres() const; Q_INVOKABLE int genrePercentage(QString genre) const; Q_INVOKABLE void setGenre(QString genre, int matchPercentage = 100); Q_INVOKABLE void removeGenre(QString genre); Q_SIGNAL void genresChanged(); Q_INVOKABLE static QStringList availableGenres(); Q_INVOKABLE QStringList characters(); Q_INVOKABLE void addCharacter(QString name); Q_INVOKABLE void removeCharacter(QString name); Q_SIGNAL void charactersChanged(); Q_INVOKABLE QList annotationsForAllLanguage(); Q_INVOKABLE QStringList annotationLanguages(); Q_INVOKABLE QStringList annotation(QString language = ""); // empty string means "default language", as (un)defined by the specification... Q_INVOKABLE void setAnnotation(QStringList annotation, QString language = ""); QHash keywordsForAllLanguage(); QStringList keywords(QString language = ""); void setKeywords(QStringList keywords, QString language = ""); Page* coverpage(); void setCoverpage(Page* newCover); QList languages(); void addLanguage(Language* language); void removeLanguage(Language* language); QList sequence(); void addSequence(Sequence* sequence); void removeSequence(Sequence* sequence); QList databaseRef(); void addDatabaseRef(DatabaseRef* databaseRef); void removeDatabaseRef(DatabaseRef* databaseRef); QList contentRating(); void addContentRating(ContentRating* contentRating); void removeContentRating(ContentRating* contentRating); private: class Private; Private* d; }; } #endif//ACBFBOOKINFO_H