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