File indexing completed on 2025-01-26 04:14:58
0001 /* 0002 * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; either 0007 * version 2.1 of the License, or (at your option) version 3, or any 0008 * later version accepted by the membership of KDE e.V. (or its 0009 * successor approved by the membership of KDE e.V.), which shall 0010 * act as a proxy defined in Section 6 of version 3 of the license. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 0019 * 0020 */ 0021 0022 #ifndef ARCHIVEBOOKMODEL_H 0023 #define ARCHIVEBOOKMODEL_H 0024 0025 #include "BookModel.h" 0026 #include <QMutex> 0027 /** 0028 * \brief Class to hold pages and metadata for archive based books. 0029 * 0030 * In particular, ArchiveBookModel handles CBZ and CBR files, reads 0031 * potential metadata and holds that into the acbfdata object. 0032 * 0033 * ArchiveBookModel extends BookModel, which handles the functions for 0034 * setting the current page, and returning basic metadata. 0035 */ 0036 class KArchiveFile; 0037 class ArchiveBookModel : public BookModel 0038 { 0039 Q_OBJECT 0040 Q_PROPERTY(QObject* qmlEngine READ qmlEngine WRITE setQmlEngine NOTIFY qmlEngineChanged) 0041 Q_PROPERTY(bool readWrite READ readWrite WRITE setReadWrite NOTIFY readWriteChanged) 0042 Q_PROPERTY(bool hasUnsavedChanges READ hasUnsavedChanges NOTIFY hasUnsavedChangesChanged) 0043 Q_PROPERTY(QStringList fileEntries READ fileEntries NOTIFY fileEntriesChanged) 0044 Q_PROPERTY(QStringList fileEntriesToDelete READ fileEntriesToDelete NOTIFY fileEntriesToDeleteChanged) 0045 public: 0046 explicit ArchiveBookModel(QObject* parent = nullptr); 0047 ~ArchiveBookModel() override; 0048 0049 /** 0050 * \brief Set the filename that points to the archive that describes this book. 0051 */ 0052 void setFilename(QString newFilename) override; 0053 0054 /** 0055 * The author name will be either the default bookmodel author name, or 0056 * if ACBF data is available, the first authorname in the list of ACBF authors. 0057 * 0058 * @return the author name as a QString. 0059 */ 0060 QString author() const override; 0061 /** 0062 * \brief Set the main author's nickname. 0063 * 0064 * If there is no ACBF data, this will set the author to BookModel's author. 0065 * If there is ACBF data, this will set the nickname entry on the name of the 0066 * first possible author. 0067 * 0068 * Preferably authors should be added by editing the author list in the bookinfo 0069 * of the ACBF metadata this book holds. 0070 * 0071 * @param newAuthor The main author's nickname. 0072 */ 0073 void setAuthor(QString newAuthor) override; 0074 /** 0075 * @return the name of the publisher as a QString. 0076 */ 0077 QString publisher() const override; 0078 /** 0079 * \brief Set the name of the publisher. 0080 * @param newPublisher QString with the name of the publisher. 0081 */ 0082 void setPublisher(QString newPublisher) override; 0083 /** 0084 * @return The proper title of this book as a QString. 0085 */ 0086 QString title() const override; 0087 /** 0088 * \brief Set the default title of this book. 0089 * @param newTitle The default title of this book as a QString. 0090 */ 0091 void setTitle(QString newTitle) override; 0092 0093 /** 0094 * @return a QQmlEngine associated with this book. 0095 * TODO: What is the QML engine and what is its purpose? 0096 * Used in the cbr.qml 0097 */ 0098 QObject* qmlEngine() const; 0099 /** 0100 * \brief Set the QML engine on this book. 0101 * @param newEngine A QQmlEngine object. 0102 */ 0103 void setQmlEngine(QObject* newEngine); 0104 /** 0105 * \brief Fires when a new QQmlEngine is set on this book. 0106 */ 0107 Q_SIGNAL void qmlEngineChanged(); 0108 0109 /** 0110 * Whether or not this model should function in read/write mode. As this is potentially very expensive, 0111 * this option is disabled by default and must be set explicitly to true. 0112 * @return Whether or not the model is read/write (true) or in read-only mode (false) 0113 */ 0114 bool readWrite() const; 0115 /** 0116 * Sets the readWrite option 0117 * @see readWrite() 0118 * @param newReadWrite Whether or not the model should be read/write (true) or in read-only mode (false) 0119 */ 0120 void setReadWrite(bool newReadWrite); 0121 /** 0122 * Fired when the read/write property changes 0123 */ 0124 Q_SIGNAL void readWriteChanged(); 0125 0126 /** 0127 * @return whether the book has been modified and has unsaved changes. 0128 * 0129 * Used in PeruseCreator to determine whether to enable the save dialog. 0130 */ 0131 bool hasUnsavedChanges() const; 0132 /** 0133 * \brief Set that the book has been modified. 0134 * @param isDirty whether the book has been modified. 0135 */ 0136 Q_INVOKABLE void setDirty(bool isDirty = true); 0137 /** 0138 * \brief Fires when there are unsaved changes. 0139 */ 0140 Q_SIGNAL void hasUnsavedChangesChanged(); 0141 0142 /** 0143 * A list of every file contained within the archive, not just the pages 0144 * @return A list of files relative to the archive root 0145 */ 0146 QStringList fileEntries() const; 0147 /** 0148 * Fired when the contents of the archive change 0149 */ 0150 Q_SIGNAL void fileEntriesChanged(); 0151 0152 /** 0153 * \brief Whether or not a specific file entry is referenced somewhere in the ACBF document. 0154 * @param fileEntry The archive filename for the entry you want checked 0155 * @return Whether the file is referenced or not. 0 if not, 1 if fully matched, 2 if partially matched 0156 * @see fileEntries() 0157 * @see markArchiveFileForDeletion(QString,bool) 0158 */ 0159 Q_INVOKABLE int fileEntryReferenced(const QString& fileEntry) const; 0160 0161 /** 0162 * \brief Whether or not an entry is a directory in the archive (as opposed to a file) 0163 * This becomes useful for distinguishing what should be done for things that are not actually 0164 * files (and consequently not really directly useful in a book, as you can't simply link to 0165 * a directory in the archive) 0166 * @param fileEntry The entry you wish to check 0167 * @return True if the entry passed in is a directory 0168 */ 0169 Q_INVOKABLE bool fileEntryIsDirectory(const QString& fileEntry) const; 0170 0171 /** 0172 * @brief The list of files currently marked for deletion 0173 * @return A list of files marked for deletion on the next save action 0174 */ 0175 QStringList fileEntriesToDelete() const; 0176 /** 0177 * Fired whenever the list of file entries which should be deleted changes 0178 */ 0179 Q_SIGNAL void fileEntriesToDeleteChanged(); 0180 /** 0181 * \brief Mark a file for removal from the archive 0182 * When saving the book, files marked for deletion will not be included in the new archive. 0183 * 0184 * @param archiveFile The filename of the file to be removed 0185 * @param markForDeletion Whether the archive file should be deleted or not 0186 */ 0187 Q_INVOKABLE void markArchiveFileForDeletion(const QString& archiveFile, bool markForDeletion = true); 0188 0189 /** 0190 * \brief Saves the archive back to disk 0191 * @return True if the save was successful 0192 */ 0193 Q_INVOKABLE bool saveBook(); 0194 0195 /** 0196 * \brief add a page to this book. 0197 * 0198 * This adds it to the ACBF metadata too. 0199 * 0200 * @param url The resource location of the page as an url. 0201 * @param title The title of the page. This is shown in a table of contents. 0202 */ 0203 void addPage(QString url, QString title) override; 0204 0205 /** 0206 * @brief removePage 0207 * remove the given page from the book by number. 0208 * @note This does not remove the file pointed to by the page 0209 * @see markArchiveFileForDeletion(QString,bool) 0210 * @param pageNumber the number of the page to remove. 0211 */ 0212 Q_INVOKABLE void removePage(int pageNumber) override; 0213 0214 /** 0215 * Adds a new page to the book archive on disk, by copying in the file 0216 * passed to the function. Optionally this can be done at a specific 0217 * position in the book. 0218 * 0219 * @param fileUrl The URL of the file to copy into the archive 0220 * @param insertAfter The index to insert the new page after. If invalid, insertion will be at the end 0221 */ 0222 Q_INVOKABLE void addPageFromFile(QString fileUrl, int insertAfter = -1); 0223 0224 /** 0225 * @brief Swap the two pages at the specified indices 0226 * 0227 * This will change the order in the archive file as well (that is, renaming the files inside the archive) 0228 * 0229 * @param swapThisIndex The index of the first page to be swapped 0230 * @param withThisIndex The index of the page you want the first to be swapped with 0231 */ 0232 Q_INVOKABLE void swapPages(int swapThisIndex, int withThisIndex) override; 0233 0234 /** 0235 * Creates a new book in the folder, with the given title and cover. 0236 * A filename will be constructed to fit the title, and which does not already exist in the 0237 * directory. 0238 * 0239 * @param folder the path to the folder to create this book in. 0240 * @param title The title of the book. 0241 * @param coverUrl A resource location pointing at the image that will be the coverpage. 0242 */ 0243 Q_INVOKABLE QString createBook(QString folder, QString title, QString coverUrl); 0244 0245 /** 0246 * Get the preview URL for an acbf item with the given ID. 0247 * @note If you are requesting a preview for an entry in the ACBF data, prepend the ID with a # symbol 0248 * @param id The ID of the item to get a preview URL for 0249 * @return The preview URL for the item with the given ID (this is NOT checked for validity, only constructed) 0250 */ 0251 Q_INVOKABLE QString previewForId(const QString& id) const; 0252 0253 /** 0254 * Get the family name for a font by its filename as stored in the ACBF data, or in the archive. 0255 * The font will be loaded on the first call of this function, and removed when the model 0256 * is destructed. 0257 * @param fontFileName The filename, in the acbf document or archive, of the font you wish to load 0258 * @return The first family name in the font, or an empty string if none was found 0259 */ 0260 Q_INVOKABLE QString fontFamilyName(const QString& fontFileName); 0261 0262 /** 0263 * Goes through a list of font families (such as that in a stylesheet) and returns the first one 0264 * available in the system. This function will also attempt to load any fonts that are in the 0265 * acbf data, or in the archive (using the fontFamilyName(QString) function) 0266 * @param fontList The ordered list of fonts to attempt to locate, in a fail-through fashion 0267 * @param The first font in the list that's available on the system. If none is found, an empty string is returned. 0268 */ 0269 Q_INVOKABLE QString firstAvailableFont(const QStringList& fontList); 0270 0271 friend class ArchiveImageRunnable; 0272 protected: 0273 const KArchiveFile* archiveFile(const QString& filePath) const; 0274 QMutex archiveMutex; 0275 0276 private: 0277 class Private; 0278 /** 0279 * @brief loadComicInfoXML 0280 * Loads ComicInfo.xml, this is an old file metadata type used by comicrack, and since then 0281 * written by other editors, amongst which a callibre plugin. 0282 * @param xmlDocument string with the archive value. 0283 * @param acbfData a pointer pointing to a acbfDocument. 0284 * @param entries a list of image entries, sorted. 0285 * @param filename the file name of the document, necessary for writing data to kfilemetadata. 0286 * @return whether the reading was successful. 0287 */ 0288 bool loadComicInfoXML(QString xmlDocument, QObject* acbfData, QStringList entries, QString filename); 0289 /** 0290 * @brief loads CoMet xmls, https://www.denvog.com/comet/comet-specification/ 0291 * @param xmlDocument string with the archive value. 0292 * @param acbfData a pointer pointing to a acbfDocument. 0293 * @param entries a list of image entries, sorted. 0294 * @param filename the file name of the document, necessary for writing data to kfilemetadata. 0295 * @return whether the reading was successful. 0296 */ 0297 bool loadCoMet(QStringList xmlDocuments, QObject* acbfData, QStringList entries, QString filename); 0298 Private* d; 0299 }; 0300 0301 #endif//ARCHIVEBOOKMODEL_H