Warning, /graphics/peruse/src/app/qml/Bookshelf.qml is written in an unsupported language. File is not indexed.

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 import QtQuick 2.12
0023 import QtQuick.Controls 2.15 as QtControls
0024 import QtQuick.Layouts 1.2
0025 
0026 import org.kde.kirigami 2.14 as Kirigami
0027 
0028 import org.kde.peruse 0.1 as Peruse
0029 import "listcomponents" as ListComponents
0030 
0031 /**
0032  * @brief This lays out the books and categories.
0033  * 
0034  * It uses BookTileTall for the books and CategoryTileTall
0035  * for showing the categories. Categories can be selected to open
0036  * a new bookshelf from the right, showing the entries in that
0037  * subcategory. This is particularly in use with the folder category.
0038  * 
0039  * There is also access to the SearchBox, and it is possible to access
0040  * a BookTile by press+holding the thumbnail.
0041  * This holds information about the book.
0042  */
0043 Kirigami.ScrollablePage {
0044     id: root;
0045     property alias pageHeader: shelfList.header;
0046     title: headerText;
0047     property string categoryName: "bookshelf";
0048     objectName: "bookshelf";
0049     property QtObject model;
0050     /**
0051      * Allows you to override the default behaviour of searching inside the shelf (such as
0052      * for the welcome page where we want to search the global list)
0053      */
0054     property alias searchModel: searchFilterProxy.sourceModel;
0055     property string sectionRole: "title";
0056     property int sectionCriteria: ViewSection.FirstCharacter;
0057     signal bookSelected(string filename, int currentPage);
0058     property string headerText;
0059     property string searchText: ""
0060     property bool searching: searchText.length > 0
0061     property bool isSearching: searchFilterProxy.filterString.length > 0;
0062 
0063     function openBook(index) {
0064         applicationWindow().contextDrawer.close();
0065         var whatModel = isSearching ? searchFilterProxy.sourceModel : shelfList.model;
0066         var whatIndex = isSearching ? searchFilterProxy.sourceIndex(index) : index;
0067         if (whatModel) {
0068             if(whatModel.indexIsBook(whatIndex)) {
0069                 var book = whatModel.get(whatIndex);
0070                 root.bookSelected(book.readProperty("filename"), book.readProperty("currentPage"));
0071             }
0072             else {
0073                 var catEntry = whatModel.getEntry(whatIndex);
0074                 applicationWindow().pageStack.push(bookshelf, { focus: true, headerText: catEntry.readProperty("title"), model: catEntry.readProperty("entriesModel") });
0075             }
0076         }
0077     }
0078 
0079     function closeShelf() {
0080         applicationWindow().contextDrawer.close();
0081         applicationWindow().pageStack.pop();
0082     }
0083     property bool isCurrentContext: isCurrentPage && !applicationWindow().bookOpen
0084     property list<QtObject> mobileActions;
0085     property list<QtObject> desktopActions: [
0086         Kirigami.Action {
0087             text: i18nc("Navigate one page back", "Back");
0088             shortcut: bookDetails.sheetOpen ? "" : "Esc";
0089             iconName: "dialog-close";
0090             onTriggered: closeShelf();
0091             enabled: root.isCurrentContext && !Kirigami.Settings.isMobile && applicationWindow().pageStack.currentIndex > 0;
0092         },
0093         Kirigami.Action {
0094             text: i18nc("Open the book which is currently selected in the list", "Open Selected Book");
0095             shortcut: bookDetails.sheetOpen? "" : "Return";
0096             iconName: "document-open";
0097             onTriggered: openBook(shelfList.currentIndex);
0098             enabled: root.isCurrentContext && !Kirigami.Settings.isMobile;
0099         }
0100     ]
0101     actions {
0102         contextualActions: Kirigami.Settings.isMobile ? mobileActions : desktopActions;
0103         main: bookDetails.sheetOpen ? bookDetailsAction : mainShelfAction;
0104     }
0105     Kirigami.Action {
0106         id: mainShelfAction;
0107         text: i18nc("search in the list of books (not inside the books)", "Search Books");
0108         iconName: "system-search";
0109         onTriggered: searchBox.activate();
0110         enabled: root.isCurrentContext;
0111         displayComponent: Kirigami.SearchField {
0112             id: searchField
0113             focus: true
0114             placeholderText: i18nc("placeholder text for the search field", "Tap and type to search");
0115             onTextChanged: {
0116                 searchText = text
0117                 if(text.length > 0) {
0118                     searchTimer.start();
0119                 } else {
0120                     searchTimer.stop();
0121                     searchFilterProxy.filterString = "";
0122                 }
0123             }
0124             Timer {
0125                 id: searchTimer;
0126                 interval: 250;
0127                 repeat: false;
0128                 running: false;
0129                 onTriggered: searchFilterProxy.filterString = searchField.text;
0130             }
0131         }
0132     }
0133     Kirigami.Action {
0134         id: bookDetailsAction;
0135         text: i18nc("Closes the book details drawer", "Close");
0136         shortcut: bookDetails.sheetOpen ? "Esc" : "";
0137         iconName: "dialog-cancel";
0138         onTriggered: bookDetails.close();
0139         enabled: root.isCurrentContext;
0140     }
0141 
0142     GridView {
0143         id: shelfList;
0144         model: isSearching ? searchFilterProxy : root.model;
0145         Peruse.FilterProxy {
0146             id: searchFilterProxy;
0147             sourceModel: root.model;
0148         }
0149         keyNavigationEnabled: true;
0150         clip: true;
0151 
0152         Kirigami.PlaceholderMessage {
0153             id: placeholderMessage
0154             width: parent.width - (Kirigami.Units.gridUnit * 4)
0155             visible: shelfList.count === 0
0156             anchors.centerIn: parent
0157             text: i18nc("Placeholder Text when there are no comics in the library that match the filter", "No matches")
0158         }
0159 
0160         readonly property int scrollBarSpace: root.flickable.QtControls.ScrollBar.vertical ? root.flickable.QtControls.ScrollBar.vertical.width : 0
0161         readonly property int availableWidth: shelfList.width - scrollBarSpace - 4
0162         readonly property int implicitCellWidth: Kirigami.Units.gridUnit * 15
0163         cellWidth: Math.floor(availableWidth / Math.max(Math.floor(availableWidth / (implicitCellWidth + Kirigami.Units.gridUnit)), 2))
0164         cellHeight: Kirigami.Units.gridUnit * 13;
0165 
0166         currentIndex: -1;
0167 
0168         delegate: Item {
0169             height: shelfList.cellHeight;
0170             width: shelfList.cellWidth;
0171             ListComponents.CategoryTileTall {
0172                 id: categoryTile;
0173                 visible: height > 0;
0174                 height: model.categoryEntriesCount > 0 ? shelfList.cellHeight : 0;
0175                 width: parent.width;
0176                 count: model.categoryEntriesCount;
0177                 title: model.title;
0178                 entriesModel: model.categoryEntriesModel ? model.categoryEntriesModel : null;
0179                 selected: shelfList.currentIndex === index;
0180             }
0181             ListComponents.BookTileTall {
0182                 id: bookTile;
0183                 visible: height > 0;
0184                 height: model.categoryEntriesCount < 1 ? shelfList.cellHeight : 0;
0185                 width: parent.width;
0186                 author: model.author ? model.author : i18nc("used for the author data in book lists if author is empty", "(unknown)");
0187                 title: model.title;
0188                 filename: model.filename;
0189                 thumbnail: model.categoryEntriesCount < 1 ? model.thumbnail : "";
0190                 categoryEntriesCount: model.categoryEntriesCount;
0191                 currentPage: model.currentPage;
0192                 totalPages: model.totalPages;
0193                 onBookSelected: root.bookSelected(filename, currentPage);
0194                 selected: shelfList.currentIndex === index;
0195                 onPressAndHold: bookDetails.showBookInfo(model.index);
0196                 pressIndicator: true;
0197             }
0198         }
0199 
0200         Kirigami.OverlaySheet {
0201             id: bookDetails;
0202             function showBookInfo(index) {
0203                 var whatModel = isSearching ? searchFilterProxy.sourceModel : shelfList.model;
0204                 var whatIndex = isSearching ? searchFilterProxy.sourceIndex(index) : index;
0205                 currentBook = whatModel.getEntry(whatIndex);
0206                 open();
0207             }
0208             property QtObject currentBook: fakeBook;
0209             property QtObject fakeBook: Peruse.PropertyContainer {
0210                 property string author: "";
0211                 property string title: "";
0212                 property string filename: "";
0213                 property string publisher: "";
0214                 property string thumbnail: "";
0215                 property string currentPage: "0";
0216                 property string totalPages: "0";
0217                 property string comment: "";
0218             }
0219             ListComponents.BookTile {
0220                 id: detailsTile;
0221                 height: neededHeight;
0222                 width: shelfList.width - Kirigami.Units.largeSpacing * 2;
0223                 author: bookDetails.currentBook.readProperty("author");
0224                 publisher: bookDetails.currentBook.readProperty("publisher");
0225                 title: bookDetails.currentBook.readProperty("title");
0226                 filename: bookDetails.currentBook.readProperty("filename");
0227                 thumbnail: bookDetails.currentBook.readProperty("thumbnail");
0228                 categoryEntriesCount: 0;
0229                 currentPage: bookDetails.currentBook.readProperty("currentPage");
0230                 totalPages: bookDetails.currentBook.readProperty("totalPages");
0231                 description: bookDetails.currentBook.readProperty("description");
0232                 onBookSelected: {
0233                     bookDetails.close();
0234                     applicationWindow().showBook(fileSelected, currentPage);
0235                 }
0236                 onBookDeleteRequested: {
0237                     contentList.removeBook(fileSelected, true);
0238                     close();
0239                 }
0240             }
0241         }
0242     }
0243 }