File indexing completed on 2024-04-28 15:35:50

0001 // SPDX-FileCopyrightText: 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
0002 // SPDX-License-Identifier: LGPL-2.1-only or LGPL-3.0-only or LicenseRef-KDE-Accepted-LGPL
0003 
0004 #pragma once
0005 
0006 #include "categoryentriesmodel.h"
0007 #include "contentlist/contentlist.h"
0008 #include <QQmlParserStatus>
0009 
0010 /**
0011  * \brief Main catalogue model class.
0012  *
0013  * BookListModel extends CategoryEntriesModel, and is the main model that
0014  * handles book entries and the different categories that books can be in.
0015  *
0016  * It also extends QQmlParseStatus to ensure that the loading the cache of
0017  * books is postponed until the application UI has been painted at least once.
0018  *
0019  * BookListModel keeps track of which books there are, how they can be sorted
0020  * and how far the reader is in reading a specific book.
0021  *
0022  * It caches its entries in the BookDataBase.
0023  *
0024  * ContentModel is the model used to enable searching the collection, it is
0025  * typically a ContentList.
0026  */
0027 class BookListModel : public CategoryEntriesModel, public QQmlParserStatus
0028 {
0029     Q_OBJECT
0030     /// \brief count holds how many entries there are in the catalogue.
0031     Q_PROPERTY(int count READ count NOTIFY countChanged)
0032 
0033     /// \brief The content model is an abstract list model that holds data to search through.
0034     Q_PROPERTY(ContentList *contentModel READ contentModel WRITE setContentModel NOTIFY contentModelChanged)
0035 
0036     /// \brief The "newly added" category entries model manages the newly added entries.
0037     Q_PROPERTY(CategoryEntriesModel *newlyAddedCategoryModel READ newlyAddedCategoryModel NOTIFY newlyAddedCategoryModelChanged)
0038 
0039     /// \brief The "author" category entries model manages the sorting of entries by author.
0040     Q_PROPERTY(CategoryEntriesModel *authorCategoryModel READ authorCategoryModel NOTIFY authorCategoryModelChanged)
0041 
0042     /// \brief The "series" category entries model managed the sorting of entry by series.
0043     Q_PROPERTY(CategoryEntriesModel *seriesCategoryModel READ seriesCategoryModel NOTIFY seriesCategoryModelChanged)
0044 
0045     /// \brief The "publisher" category entries model managed the sorting of entry by publisher.
0046     Q_PROPERTY(QObject *publisherCategoryModel READ publisherCategoryModel NOTIFY publisherCategoryModelChanged)
0047 
0048     /// \brief The "keyword" category entries model managed the sorting of entry by keyword.
0049     Q_PROPERTY(QObject *keywordCategoryModel READ keywordCategoryModel NOTIFY keywordCategoryModelChanged)
0050     /**
0051      * \brief The "folder" category entries model managed the sorting of entry by file system folder.
0052      */
0053     Q_PROPERTY(QObject *folderCategoryModel READ folderCategoryModel NOTIFY folderCategoryModelChanged)
0054 
0055     /// \brief cacheLoaded holds whether the database cache has been loaded..
0056     Q_PROPERTY(bool cacheLoaded READ cacheLoaded NOTIFY cacheLoadedChanged)
0057     Q_INTERFACES(QQmlParserStatus)
0058 public:
0059     explicit BookListModel(QObject *parent = nullptr);
0060     ~BookListModel() override;
0061 
0062     /**
0063      * Inherited from QmlParserStatus, not implemented.
0064      */
0065     void classBegin() override{};
0066     /**
0067      * \brief triggers the loading of the cache.
0068      * Inherited from QmlParserStatus
0069      */
0070     void componentComplete() override;
0071 
0072     /// \brief Enum holding the different categories implemented.
0073     enum Grouping {
0074         GroupByNone = 0,
0075         GroupByRecentlyAdded,
0076         GroupByRecentlyRead,
0077         GroupByTitle,
0078         GroupByAuthor,
0079         GroupByPublisher,
0080     };
0081     Q_ENUM(Grouping)
0082 
0083     /// @return the contentModel. Used for searching.
0084     ContentList *contentModel() const;
0085 
0086     /// \brief set the ContentModel.
0087     /// @param newModel The new content model.
0088     void setContentModel(ContentList *newModel);
0089 
0090     /// @returns how many entries there are in the catalogue.
0091     int count() const;
0092 
0093     /// @return The categoryEntriesModel that manages the recently added entries.
0094     CategoryEntriesModel *newlyAddedCategoryModel() const;
0095 
0096     /// @return The categoryEntriesModel that manages the sorting of entries by author.
0097     CategoryEntriesModel *authorCategoryModel() const;
0098 
0099     /// \return The categoryEntriesModel that manages the sorting of entries by series.
0100     CategoryEntriesModel *seriesCategoryModel() const;
0101 
0102     /// \brief Returns the leaf model representing the series the entry with the
0103     /// passed URL is a part of
0104     ///
0105     /// Base assumption: A book is only part of one series. This is not always true,
0106     /// but not sure how to sensibly represent that.
0107     ///
0108     /// \param fileName the File Name of the entry to get the series of.
0109     Q_INVOKABLE CategoryEntriesModel *seriesModelForEntry(const QString &fileName);
0110 
0111     /// \return The categoryEntriesModel that manages the sorting of entries
0112     /// by publisher.
0113     CategoryEntriesModel *publisherCategoryModel() const;
0114 
0115     /// \return The categoryEntriesModel that manages the sorting of entries
0116     /// by keywords, names and genres.
0117     CategoryEntriesModel *keywordCategoryModel() const;
0118 
0119     /// \return The categoryEntriesModel that manages the sorting of entries by folder.
0120     CategoryEntriesModel *folderCategoryModel() const;
0121 
0122     /// \returns whether the cache is loaded from the database.
0123     bool cacheLoaded() const;
0124 
0125     /// \brief Update the data of a book at runtime
0126     ///
0127     /// This is used in to update totalPages and currentPage.
0128     ///
0129     /// \param fileName The filename to update the page for.
0130     /// \param property The property to update, can be "currentPage" or "totalPages".
0131     /// \param value The value to set it to.
0132     Q_INVOKABLE void setBookData(const QString &fileName, const QString &property, const QString &value);
0133 
0134     /// Delete a book from the model, and optionally delete the entry from file storage.
0135     /// \param fileName The filename of the book to remove.
0136     /// \param deleteFile Whether to also delete the file from the disk.
0137     Q_INVOKABLE void removeBook(const QString &fileName, bool deleteFile = false);
0138 
0139     /// \brief A list of the files currently known by the applications
0140     /// \returns a QStringList with paths to known books.
0141     Q_INVOKABLE QStringList knownBookFiles() const;
0142 
0143 Q_SIGNALS:
0144     /// \brief Fires when the seriesCategoryModel has changed or finished initializing.
0145     void seriesCategoryModelChanged();
0146     /// \brief Fires when the publisherCategoryModel has changed or finished initializing.
0147     void publisherCategoryModelChanged();
0148     /// \brief Fires when the folderCategoryModel has changed or finished initializing.
0149     void folderCategoryModelChanged();
0150     /// \brief Fires when the cache is done loading.
0151     void cacheLoadedChanged();
0152     /// \brief Fires when the newlyAddedCategoryModel has changed or finished
0153     /// initializing.
0154     void newlyAddedCategoryModelChanged();
0155     /// \brief Fires when the content model has changed.
0156     void contentModelChanged();
0157     /// \brief Fires when the keywordCategoryModel has changed or finished initializing.
0158     void keywordCategoryModelChanged();
0159     /// \brief Fires when the authorCategoryModel has changed or finished initializing.
0160     void authorCategoryModelChanged();
0161 
0162 private:
0163     class Private;
0164     std::unique_ptr<Private> d;
0165 
0166     Q_SLOT void contentModelItemsInserted(QModelIndex index, int first, int last);
0167 };