Warning, /graphics/peruse/src/app/qml/PeruseMain.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.15
0023
0024 import org.kde.kirigami 2.14 as Kirigami
0025 import QtQuick.Layouts 1.3
0026 import QtQuick.Controls 2.14 as QQC2
0027
0028 import org.kde.peruse 0.1 as Peruse
0029 import org.kde.contentlist 0.1
0030
0031 /**
0032 * @brief main application window.
0033 *
0034 * This splits the window in two sections:
0035 * - A section where you can select comics.
0036 * - A "global drawer" which can be used to switch between categories
0037 * and access settings and the open book dialog.
0038 *
0039 * The global drawer controls which is the main component on the left.
0040 * It initializes on WelcomePage. The category filters are each handled
0041 * by a BookShelf. The store page by Store and the settings by Settings.
0042 *
0043 * This also controls the bookViewer, which is a Book object where the
0044 * main reading of comics is done.
0045 *
0046 * There is also the PeruseContextDrawer, which is only accessible on the book
0047 * page and requires flicking in from the right.
0048 */
0049 Kirigami.ApplicationWindow {
0050 id: mainWindow;
0051
0052 property int animationDuration: 200
0053 property bool isLoading: true
0054 property bool bookOpen: mainWindow.pageStack.layers.currentItem.objectName === "bookViewer"
0055
0056 title: i18nc("@title:window the generic descriptive title of the application", "Comic Book Reader");
0057
0058 pageStack {
0059 defaultColumnWidth: Kirigami.Units.gridUnit * 30
0060 initialPage: welcomePage
0061 globalToolBar {
0062 canContainHandles: true
0063 style: Kirigami.ApplicationHeaderStyle.ToolBar
0064 showNavigationButtons: applicationWindow().pageStack.currentIndex > 0 ? Kirigami.ApplicationHeaderStyle.ShowBackButton : 0
0065 }
0066 }
0067
0068 function showBook(filename, currentPage) {
0069 if(bookOpen) {
0070 mainWindow.pageStack.layers.pop();
0071 }
0072 mainWindow.pageStack.layers.push(bookViewer, {
0073 focus: true,
0074 file: filename,
0075 currentPage: currentPage,
0076 });
0077 peruseConfig.bookOpened(filename);
0078 }
0079
0080 Peruse.BookListModel {
0081 id: contentList;
0082 contentModel: ContentList {
0083 autoSearch: false
0084
0085 onSearchStarted: { mainWindow.isLoading = true; }
0086 onSearchCompleted: { mainWindow.isLoading = false; }
0087
0088 ContentQuery {
0089 type: ContentQuery.Comics
0090 locations: peruseConfig.bookLocations
0091 }
0092 }
0093 onCacheLoadedChanged: {
0094 if(!cacheLoaded) {
0095 return;
0096 }
0097 contentList.contentModel.setKnownFiles(contentList.knownBookFiles());
0098 contentList.contentModel.startSearch()
0099 }
0100 }
0101
0102 Peruse.Config {
0103 id: peruseConfig;
0104 }
0105 function homeDir() {
0106 return peruseConfig.homeDir();
0107 }
0108
0109 contextDrawer: PeruseContextDrawer {
0110 id: contextDrawer;
0111 }
0112
0113 globalDrawer: Kirigami.OverlayDrawer {
0114 edge: Qt.application.layoutDirection === Qt.RightToLeft ? Qt.RightEdge : Qt.LeftEdge
0115 modal: Kirigami.Settings.isMobile || (applicationWindow().width < Kirigami.Units.gridUnit * 50 && !collapsed) // Only modal when not collapsed, otherwise collapsed won't show.
0116 z: modal ? Math.round(position * 10000000) : 100
0117 drawerOpen: !Kirigami.Settings.isMobile && enabled
0118 width: Kirigami.Units.gridUnit * 16
0119 Behavior on width {
0120 NumberAnimation {
0121 duration: Kirigami.Units.longDuration
0122 easing.type: Easing.InOutQuad
0123 }
0124 }
0125 Kirigami.Theme.colorSet: Kirigami.Theme.Window
0126
0127 handleClosedIcon.source: modal ? null : "sidebar-expand-left"
0128 handleOpenIcon.source: modal ? null : "sidebar-collapse-left"
0129 handleVisible: modal
0130 onModalChanged: if (!modal) {
0131 drawerOpen = true;
0132 }
0133
0134 leftPadding: 0
0135 rightPadding: 0
0136 topPadding: 0
0137 bottomPadding: 0
0138
0139 contentItem: ColumnLayout {
0140 spacing: 0
0141
0142 QQC2.ToolBar {
0143 Layout.fillWidth: true
0144 Layout.preferredHeight: mainWindow.pageStack.globalToolBar.preferredHeight
0145
0146 leftPadding: Kirigami.Units.smallSpacing
0147 rightPadding: Kirigami.Units.smallSpacing
0148 topPadding: Kirigami.Units.smallSpacing
0149 bottomPadding: Kirigami.Units.smallSpacing
0150
0151 contentItem: RowLayout {
0152 Kirigami.Heading {
0153 text: i18n("Peruse")
0154 Layout.fillWidth: true
0155 }
0156
0157 QQC2.ToolButton {
0158 icon.name: "go-home"
0159
0160 enabled: mainWindow.currentCategory !== "welcomePage";
0161 onClicked: if (changeCategory(welcomePage)) {
0162 pageStack.currentItem.updateRecent();
0163 }
0164
0165 QQC2.ToolTip.text: i18n("Show intro page")
0166 QQC2.ToolTip.visible: hovered
0167 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0168 }
0169 }
0170 }
0171
0172 QQC2.ButtonGroup {
0173 id: placeGroup
0174 }
0175
0176 QQC2.ScrollView {
0177 id: scrollView
0178
0179 Layout.fillHeight: true
0180 Layout.fillWidth: true
0181
0182 contentWidth: availableWidth
0183
0184 component PlaceItem : Kirigami.BasicListItem {
0185 id: item
0186 signal triggered;
0187 checkable: true
0188 Layout.fillWidth: true
0189 Keys.onDownPressed: nextItemInFocusChain().forceActiveFocus(Qt.TabFocusReason)
0190 Keys.onUpPressed: nextItemInFocusChain(false).forceActiveFocus(Qt.TabFocusReason)
0191 Accessible.role: Accessible.MenuItem
0192 highlighted: checked
0193 onToggled: if (checked) {
0194 item.triggered();
0195 }
0196 }
0197
0198 ColumnLayout {
0199 spacing: 1
0200 width: scrollView.width
0201 PlaceItem {
0202 text: i18nc("Switch to the listing page showing the most recently read books", "Home");
0203 icon: "go-home";
0204 checked: true
0205 QQC2.ButtonGroup.group: placeGroup
0206 onTriggered: {
0207 if (changeCategory(welcomePage)) {
0208 pageStack.currentItem.updateRecent();
0209 }
0210 }
0211 }
0212 PlaceItem {
0213 text: i18nc("Switch to the listing page showing the most recently discovered books", "Recently Added Books");
0214 icon: "appointment-new";
0215 QQC2.ButtonGroup.group: placeGroup
0216 onTriggered: changeCategory(bookshelfAdded);
0217 }
0218 PlaceItem {
0219 text: i18nc("Open a book from somewhere on disk (uses the open dialog, or a drilldown on touch devices)", "Open Other...");
0220 icon: "document-open";
0221 onClicked: openOther();
0222 QQC2.ButtonGroup.group: undefined
0223 checkable: false
0224 }
0225 Kirigami.ListSectionHeader {
0226 text: i18nc("Heading for switching to listing page showing items grouped by some properties", "Group By")
0227 }
0228 PlaceItem {
0229 text: i18nc("Switch to the listing page showing items grouped by title", "Title");
0230 icon: "view-media-title";
0231 onTriggered: changeCategory(bookshelfTitle);
0232 QQC2.ButtonGroup.group: placeGroup
0233 }
0234 PlaceItem {
0235 text: i18nc("Switch to the listing page showing items grouped by author", "Author");
0236 icon: "actor";
0237 onTriggered: changeCategory(bookshelfAuthor);
0238 QQC2.ButtonGroup.group: placeGroup
0239 }
0240 PlaceItem {
0241 text: i18nc("Switch to the listing page showing items grouped by series", "Series");
0242 icon: "edit-group";
0243 onTriggered: changeCategory(bookshelfSeries);
0244 QQC2.ButtonGroup.group: placeGroup
0245 }
0246 PlaceItem {
0247 text: i18nc("Switch to the listing page showing items grouped by publisher", "Publisher");
0248 icon: "view-media-publisher";
0249 onTriggered: changeCategory(bookshelfPublisher);
0250 QQC2.ButtonGroup.group: placeGroup
0251 }
0252 PlaceItem {
0253 text: i18nc("Switch to the listing page showing items grouped by keywords, characters or genres", "Keywords");
0254 icon: "tag";
0255 onTriggered: changeCategory(bookshelfKeywords);
0256 QQC2.ButtonGroup.group: placeGroup
0257 }
0258 PlaceItem {
0259 text: i18nc("Switch to the listing page showing items grouped by their filesystem folder", "Folder");
0260 icon: "tag-folder";
0261 onTriggered: changeCategory(bookshelfFolder);
0262 QQC2.ButtonGroup.group: placeGroup
0263 }
0264
0265 }
0266 }
0267
0268 Item {
0269 Layout.fillHeight: true
0270 }
0271
0272 QQC2.Label {
0273 Layout.fillWidth: true
0274 horizontalAlignment: Text.AlignHCenter;
0275 text: i18nc("shown with a throbber when searching for books on the device", "Please wait while we find your books...")
0276 visible: mainWindow.isLoading
0277 }
0278
0279 QQC2.BusyIndicator {
0280 Layout.fillWidth: true
0281 running: mainWindow.isLoading
0282 }
0283
0284 PlaceItem {
0285 text: i18nc("Open the settings page", "Settings");
0286 icon: "configure"
0287 onTriggered: changeCategory(settingsPage);
0288 QQC2.ButtonGroup.group: placeGroup
0289 }
0290
0291 PlaceItem {
0292 text: i18nc("Open the about page", "About");
0293 icon: "help-about"
0294 onTriggered: changeCategory(aboutPage);
0295 QQC2.ButtonGroup.group: placeGroup
0296 }
0297 }
0298 }
0299
0300 Component {
0301 id: welcomePage;
0302 WelcomePage {
0303 onBookSelected: mainWindow.showBook(filename, currentPage);
0304 }
0305 }
0306
0307 Component {
0308 id: bookViewer;
0309 Book {
0310 id: viewerRoot;
0311 onCurrentPageChanged: {
0312 contentList.setBookData(viewerRoot.file, "currentPage", viewerRoot.currentPage);
0313 }
0314 onTotalPagesChanged: {
0315 contentList.setBookData(viewerRoot.file, "totalPages", viewerRoot.totalPages);
0316 }
0317 }
0318 }
0319
0320 Component {
0321 id: bookshelfTitle;
0322 Bookshelf {
0323 model: contentList.titleCategoryModel;
0324 headerText: i18nc("Title of the page with books grouped by the title start letters", "Group by Title");
0325 onBookSelected: mainWindow.showBook(filename, currentPage);
0326 categoryName: "bookshelfTitle";
0327 }
0328 }
0329
0330 Component {
0331 id: bookshelfAdded;
0332 Bookshelf {
0333 model: contentList.newlyAddedCategoryModel;
0334 headerText: i18nc("Title of the page with all books ordered by which was added most recently", "Recently Added Books");
0335 sectionRole: "created";
0336 sectionCriteria: ViewSection.FullString;
0337 onBookSelected: mainWindow.showBook(filename, currentPage);
0338 categoryName: "bookshelfAdded";
0339 }
0340 }
0341
0342 Component {
0343 id: bookshelfSeries;
0344 Bookshelf {
0345 model: contentList.seriesCategoryModel;
0346 headerText: i18nc("Title of the page with books grouped by what series they are in", "Group by Series");
0347 onBookSelected: mainWindow.showBook(filename, currentPage);
0348 categoryName: "bookshelfSeries";
0349 }
0350 }
0351
0352 Component {
0353 id: bookshelfAuthor;
0354 Bookshelf {
0355 model: contentList.authorCategoryModel;
0356 headerText: i18nc("Title of the page with books grouped by author", "Group by Author");
0357 onBookSelected: mainWindow.showBook(filename, currentPage);
0358 categoryName: "bookshelfAuthor";
0359 }
0360 }
0361
0362 Component {
0363 id: bookshelfPublisher;
0364 Bookshelf {
0365 model: contentList.publisherCategoryModel;
0366 headerText: i18nc("Title of the page with books grouped by who published them", "Group by Publisher");
0367 onBookSelected: mainWindow.showBook(filename, currentPage);
0368 categoryName: "bookshelfPublisher";
0369 }
0370 }
0371
0372 Component {
0373 id: bookshelfKeywords;
0374 Bookshelf {
0375 model: contentList.keywordCategoryModel;
0376 headerText: i18nc("Title of the page with books grouped by keywords, character or genres", "Group by Keywords, Characters and Genres");
0377 onBookSelected: mainWindow.showBook(filename, currentPage);
0378 categoryName: "bookshelfKeywords";
0379 }
0380 }
0381
0382 Component {
0383 id: bookshelfFolder;
0384 Bookshelf {
0385 model: contentList.folderCategoryModel;
0386 headerText: i18nc("Title of the page with books grouped by what folder they are in", "Filter by Folder");
0387 onBookSelected: mainWindow.showBook(filename, currentPage);
0388 categoryName: "bookshelfFolder";
0389 }
0390 }
0391
0392 Component {
0393 id: bookshelf;
0394 Bookshelf {
0395 onBookSelected: mainWindow.showBook(filename, currentPage);
0396 }
0397 }
0398
0399 Component {
0400 id: storePage;
0401 Store {
0402 }
0403 }
0404
0405 Component {
0406 id: settingsPage;
0407 Settings {
0408 }
0409 }
0410
0411 Component {
0412 id: aboutPage
0413 About {
0414 }
0415 }
0416
0417 property string currentCategory: "welcomePage";
0418 property Component currentCategoryItem: welcomePage;
0419 function changeCategory(categoryItem) {
0420 if (categoryItem === mainWindow.currentCategoryItem) {
0421 return false;
0422 }
0423 // Clear all the way to the welcome page if we change the category...
0424 mainWindow.pageStack.clear();
0425 mainWindow.pageStack.push(categoryItem);
0426 currentCategory = mainWindow.pageStack.currentItem.categoryName;
0427 currentCategoryItem = categoryItem;
0428 if (PLASMA_PLATFORM.substring(0, 5) === "phone") {
0429 globalDrawer.close();
0430 }
0431 return true;
0432 }
0433
0434
0435 Component.onCompleted: {
0436 if (fileToOpen !== "") {
0437 mainWindow.showBook(fileToOpen, 0);
0438 }
0439 }
0440 }
0441