1 /*
2  * Copyright (C) 2015 Dan Leinir Turthra Jensen <admin@leinir.dk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) version 3, or any
8  * later version accepted by the membership of KDE e.V. (or its
9  * successor approved by the membership of KDE e.V.), which shall
10  * act as a proxy defined in Section 6 of version 3 of the license.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef CATEGORYENTRIESMODEL_H
23 #define CATEGORYENTRIESMODEL_H
24 
25 #include <QAbstractListModel>
26 #include <QDateTime>
27 
28 class CategoryEntriesModel;
29 /**
30  * \brief A struct for an Entry to the Book Database.
31  */
32 struct BookEntry {
BookEntryBookEntry33     explicit BookEntry()
34         : totalPages(0)
35         , currentPage(0)
36         , rating(0)
37     {}
38     QString filename;
39     QString filetitle;
40     QString title;
41     QStringList genres;
42     QStringList keywords;
43     QStringList characters;
44     QStringList series;
45     QStringList seriesNumbers;
46     QStringList seriesVolumes;
47     QStringList author;
48     QString publisher;
49     QDateTime created;
50     QDateTime lastOpenedTime;
51     int totalPages;
52     int currentPage;
53     QString thumbnail;
54     QStringList description;
55     QString comment;
56     QStringList tags;
57     int rating;
58 };
59 
60 /**
61  * \brief Model to handle the filter categories.
62  *
63  * This model in specific handles which categories there are
64  * and which books are assigned to a category, if so, which.
65  *
66  * Used to handle sorting by author, title and so forth.
67  * Is extended by BookListModel.
68  *
69  * categories and book entries are both in the same model
70  * because there can be books that are not assigned categories.
71  * Similarly, categories can contain categories, like in the case
72  * of folder category.
73  */
74 class CategoryEntriesModel : public QAbstractListModel
75 {
76     Q_OBJECT
77     /**
78      * \brief count holds how many entries there are in the model - equivalent to rowCount, except as a property
79      */
80     Q_PROPERTY(int count READ count NOTIFY countChanged)
81 public:
82     explicit CategoryEntriesModel(QObject* parent = nullptr);
83     ~CategoryEntriesModel() override;
84 
85     /**
86      * \brief Extra roles for the book entry access.
87      */
88     enum Roles {
89         UnknownRole = Qt::UserRole,
90         FilenameRole = Qt::UserRole + 1, /// For getting a string with the full path to the book.
91         FiletitleRole, /// For getting a string with the basename of the book.
92         TitleRole, /// For getting a string with the proper title of the book.
93         SeriesRole, /// For getting a stringlist of series this book is part of.
94         SeriesNumbersRole, /// For getting a stringlist of numbers, which represent the sequence number the book has within each series.
95         SeriesVolumesRole, /// For getting a stringlist of numbers, which represent the volume number the book has within a series. This is optional.
96         AuthorRole, /// For getting a stringlist of all the authors.
97         PublisherRole, /// For getting a string with the publisher name.
98         CreatedRole, /// For getting the creation date of the book as a QDateTime.
99         LastOpenedTimeRole, /// For getting the last time the book was opened as a QDateTime.
100         TotalPagesRole, /// For getting the total amount of pages in this book.
101         CurrentPageRole, /// For getting the current page as an int.
102         CategoryEntriesModelRole, /// For getting the model of this category.
103         CategoryEntryCountRole, /// For getting the an int with the number of books within this category.
104         ThumbnailRole, /// For getting a thumbnail url for this book.
105         DescriptionRole, /// For getting a stringlist with a book description.
106         CommentRole, /// For getting a string with user assigned comment.
107         TagsRole, /// For getting a stringlist with user assigned tags.
108         RatingRole, /// For getting an int with the rating of the comic. This is gotten from KFileMeta and thus goes from 1-10 with 0 being no rating.
109         GenreRole, /// For getting a stringlist with genres assigned to this book.
110         KeywordRole, /// For getting a stringlist with keywords assigned to this book. Where tags are user assigned, keywords come from the book itself.
111         CharacterRole /// For getting a stringlist with names of characters in this book.
112     };
113     Q_ENUMS(Roles)
114 
115     /**
116      * @returns names for the extra roles defined.
117      */
118     QHash<int, QByteArray> roleNames() const override;
119     /**
120      * \brief Access the data inside the CategoryEntriesModel.
121      * @param index The QModelIndex at which you wish to access the data.
122      * @param role An enumerator of the type of data you want to access.
123      * Is extended by the Roles enum.
124      *
125      * @return a QVariant with the book entry's data.
126      */
127     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
128     /**
129      * @param parent The QModel index of the parent. This only counts for
130      * tree like page structures, and thus defaults to a freshly constructed
131      * QModelIndex. A wellformed QModelIndex will cause this function to return 0
132      * @returns the number of total rows(bookentries and categories) there are.
133      */
134     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
135 
136     /**
137      * @returns how many entries there are in the catalogue.
138      */
139     int count() const;
140     /**
141      * \brief Fires when the count has changed.
142      */
143     Q_SIGNAL void countChanged();
144 
145     /**
146      * \brief Add a book entry to the CategoryEntriesModel.
147      *
148      * @param entry The BookEntry to add.
149      * @param compareRole The role that determines the data to sort the entry into.
150      * Defaults to the Book title.
151      */
152     Q_INVOKABLE void append(BookEntry* entry, Roles compareRole = TitleRole);
153 
154     /**
155      * \brief Add a book entry to the model, using a fake book
156      *
157      * @param book The fake book (such as returned by get(int))
158      * @param compareRole The role that determines the data used to sort the entry (defaults to TitleRole)
159      */
160     Q_INVOKABLE void appendFakeBook(QObject* book, Roles compareRole = TitleRole);
161 
162     /**
163      * \brief Remove all entries from the model
164      */
165     Q_INVOKABLE void clear();
166 
167     /**
168      * \brief Add a book entry to a category.
169      *
170      * This also adds it to the model's list of entries.
171      */
172     void addCategoryEntry(const QString& categoryName, BookEntry* entry, Roles compareRole = TitleRole);
173 
174     /**
175      * @param index an integer index pointing at the desired book.
176      * @returns a QObject wrapper around a BookEntry struct for the given index.
177      */
178     Q_INVOKABLE QObject* get(int index);
179     /**
180      * @param index an integer index pointing at the desired book.
181      * @returns the BookEntry struct for the given index (owned by this model, do not delete)
182      */
183     Q_INVOKABLE BookEntry* getBookEntry(int index);
184     /**
185      * TODO: This is backwards... need to fox this to make get return the actual thing, not just a book, and create a getter for books...
186      * @return an entry object. This can be either a category or a book.
187      * @param index the index of the object.
188      */
189     Q_INVOKABLE QObject* getEntry(int index);
190     /**
191      * @return an entry object for the given filename. Used to get the recently
192      * read books.
193      * @param filename the filename associated with an entry object.
194      */
195     Q_INVOKABLE QObject* bookFromFile(QString filename);
196     /**
197      * @return an entry index for the given filename.
198      * @param filename the filename associated with an entry object.
199      */
200     Q_INVOKABLE int indexOfFile(QString filename);
201     /**
202      * @return whether the entry is a bookentry or a category entry.
203      * @param index the index of the entry.
204      */
205     Q_INVOKABLE bool indexIsBook(int index);
206     /**
207      * @return an integer with the total books in the model.
208      */
209     int bookCount() const;
210 
211     /**
212      * \brief Fires when a book entry is updated.
213      * @param entry The updated entry
214      *
215      * Used in the BookListModel::setBookData()
216      */
217     Q_SIGNAL void entryDataUpdated(BookEntry* entry);
218     /**
219      * \brief set a book entry as changed.
220      * @param entry The changed entry.
221      */
222     Q_SLOT void entryDataChanged(BookEntry* entry);
223     /**
224      * \brief Fires when a book entry is removed.
225      * @param entry The removed entry
226      */
227     Q_SIGNAL void entryRemoved(BookEntry* entry);
228     /**
229      * \brief Remove a book entry.
230      * @param entry The entry to remove.
231      */
232     Q_SLOT void entryRemove(BookEntry* entry);
233 
234     // This will iterate over all sub-models and find the model which contains the entry, or null if not found
235     QObject* leafModelForEntry(BookEntry* entry);
236 protected:
237     /**
238      * @return the name of the model.
239      */
240     const QString &name() const;
241     /**
242      * \brief set the name of the model.
243      * @param newName QString with the name.
244      */
245     void setName(const QString& newName);
246 private:
247     class Private;
248     Private* d;
249 };
250 
251 #endif//CATEGORYENTRIESMODEL_H
252