File indexing completed on 2024-05-12 05:10:10

0001 /***************************************************************************
0002     Copyright (C) 2024 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #include <config.h>
0026 
0027 #include "filereaderbook.h"
0028 #include "../fieldformat.h"
0029 #include "../images/imagefactory.h"
0030 #include "../core/netaccess.h"
0031 
0032 #include <KLocalizedString>
0033 #include <KFileItem>
0034 
0035 #include <QPixmap>
0036 #include <QIcon>
0037 
0038 namespace {
0039   static const int FILE_PREVIEW_SIZE = 128;
0040 }
0041 
0042 using Tellico::FileReaderBook;
0043 
0044 class FileReaderBook::Private {
0045 public:
0046   Private() {}
0047 
0048   // cache the icon image ids to avoid repeated creation of Data::Image objects
0049   QHash<QString, QString> iconImageId;
0050 };
0051 
0052 FileReaderBook::FileReaderBook(const QUrl& url_) : FileReaderMetaData(url_), d(new Private) {
0053 }
0054 
0055 FileReaderBook::~FileReaderBook() = default;
0056 
0057 bool FileReaderBook::populate(Data::EntryPtr entry, const KFileItem& item) {
0058   // reads pdf and ebooks
0059   if(item.mimetype() != QLatin1String("application/pdf") &&
0060      item.mimetype() != QLatin1String("application/epub+zip") &&
0061      item.mimetype() != QLatin1String("application/fb2+zip") &&
0062      item.mimetype() != QLatin1String("application/fb2+xml") &&
0063      item.mimetype() != QLatin1String("application/x-mobipocket-ebook")) {
0064     return false;
0065   }
0066 #ifndef HAVE_KFILEMETADATA
0067   return false;
0068 #else
0069   bool isEmpty = true;
0070   QStringList authors, publishers, genres, keywords;
0071   const auto props = properties(item);
0072   for(auto it = props.constBegin(); it != props.constEnd(); ++it) {
0073     const QString value = it.value().toString();
0074     if(value.isEmpty()) continue;
0075     switch(it.key()) {
0076       case KFileMetaData::Property::Title:
0077         isEmpty = false; // require a title or author
0078         entry->setField(QStringLiteral("title"), value);
0079         break;
0080 
0081       case KFileMetaData::Property::Author:
0082         isEmpty = false; // require a title or author
0083         authors += value;
0084         break;
0085 
0086       case KFileMetaData::Property::Publisher:
0087         publishers += value;
0088         break;
0089 
0090       case KFileMetaData::Property::Subject:
0091         keywords += value;
0092         break;
0093 
0094       case KFileMetaData::Property::Genre:
0095         genres += value;
0096         break;
0097 
0098       case KFileMetaData::Property::ReleaseYear:
0099         entry->setField(QStringLiteral("pub_year"), value);
0100         break;
0101 
0102       // is description usually the plot or just comments?
0103       case KFileMetaData::Property::Description:
0104         entry->setField(QStringLiteral("plot"), value);
0105         break;
0106 
0107       case KFileMetaData::Property::PageCount:
0108         entry->setField(QStringLiteral("pages"), value);
0109         break;
0110 
0111       default:
0112         if(!value.isEmpty()) {
0113 //          myDebug() << "skipping" << it.key() << it.value();
0114         }
0115         break;
0116     }
0117   }
0118 
0119   if(isEmpty) return false;
0120 
0121   if(!authors.isEmpty()) {
0122     entry->setField(QStringLiteral("author"), authors.join(FieldFormat::delimiterString()));
0123   }
0124   if(!publishers.isEmpty()) {
0125     entry->setField(QStringLiteral("publisher"), publishers.join(FieldFormat::delimiterString()));
0126   }
0127   if(!genres.isEmpty()) {
0128     entry->setField(QStringLiteral("genre"), genres.join(FieldFormat::delimiterString()));
0129   }
0130   if(!keywords.isEmpty()) {
0131     entry->setField(QStringLiteral("keyword"), keywords.join(FieldFormat::delimiterString()));
0132   }
0133 
0134   const QString url = QStringLiteral("url");
0135   if(!entry->collection()->hasField(url)) {
0136     Data::FieldPtr f(new Data::Field(url, i18n("URL"), Data::Field::URL));
0137     f->setCategory(i18n("Personal"));
0138     entry->collection()->addField(f);
0139   }
0140   entry->setField(url, item.url().url());
0141   entry->setField(QStringLiteral("binding"), i18n("E-Book"));
0142 
0143   const QString cover = QStringLiteral("cover");
0144   QPixmap pixmap;
0145   if(useFilePreview()) {
0146     pixmap = Tellico::NetAccess::filePreview(item, FILE_PREVIEW_SIZE);
0147   }
0148   if(pixmap.isNull()) {
0149     if(d->iconImageId.contains(item.iconName())) {
0150       entry->setField(cover, d->iconImageId.value(item.iconName()));
0151     } else {
0152       pixmap = QIcon::fromTheme(item.iconName()).pixmap(QSize(FILE_PREVIEW_SIZE, FILE_PREVIEW_SIZE));
0153       const QString id = ImageFactory::addImage(pixmap, QStringLiteral("PNG"));
0154       if(!id.isEmpty()) {
0155         entry->setField(cover, id);
0156         d->iconImageId.insert(item.iconName(), id);
0157       }
0158     }
0159   } else {
0160     const QString id = ImageFactory::addImage(pixmap, QStringLiteral("PNG"));
0161     if(!id.isEmpty()) {
0162       entry->setField(cover, id);
0163     }
0164   }
0165 
0166 #endif
0167   return true;
0168 }