Warning, /graphics/peruse/src/app/qml/listcomponents/BookTile.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.12 as QtControls 0024 0025 import org.kde.kirigami 2.14 as Kirigami 0026 0027 /** 0028 * @brief small window with book information. 0029 * 0030 * This shows a bit of information about the book and gives a 0031 * selector with the other books in the series. 0032 * 0033 * It pops up after finishing a book in Book, and when pressing long 0034 * on a BookTileTall item in BookShelf. 0035 * 0036 */ 0037 Item { 0038 id: root; 0039 property bool selected: false; 0040 property alias title: bookTitle.text; 0041 property var author: []; 0042 property string publisher; 0043 property alias filename: bookFile.text; 0044 property alias thumbnail: coverImage.source; 0045 property int categoryEntriesCount; 0046 property string currentPage; 0047 property string totalPages; 0048 property var description: []; 0049 property string comment: peruseConfig.getFilesystemProperty(root.filename, "comment"); 0050 property var tags: peruseConfig.getFilesystemProperty(root.filename, "tags").split(","); 0051 property int rating: peruseConfig.getFilesystemProperty(root.filename, "rating"); 0052 signal bookSelected(string fileSelected, int currentPage); 0053 signal bookDeleteRequested(string fileSelected); 0054 0055 property int neededHeight: bookCover.height;// + bookAuthorLabel.height + bookFile.height + Kirigami.Units.smallSpacing * 4; 0056 property bool showCommentTags: neededHeight > bookTitle.height + bookAuthorLabel.height 0057 + bookPublisherLabel.height + ratingContainer.height 0058 + tagsContainer.height + commentContainer.height + deleteButton.height + Kirigami.Units.smallSpacing * 7; 0059 visible: height > 1; 0060 enabled: visible; 0061 clip: true; 0062 0063 onRatingChanged: { 0064 if (peruseConfig.getFilesystemProperty(root.filename, "rating") !== rating) { 0065 contentList.setBookData(root.filename, "rating", rating); 0066 peruseConfig.setFilesystemProperty(root.filename, "rating", rating); 0067 } 0068 } 0069 onTagsChanged: { 0070 if (tags.join(",") !== peruseConfig.getFilesystemProperty(root.filename, "tags")) { 0071 contentList.setBookData(root.filename, "tags", tags.join(",")); 0072 peruseConfig.setFilesystemProperty(root.filename, "tags", tags.join(",")); 0073 } 0074 } 0075 onCommentChanged: { 0076 contentList.setBookData(root.filename, "comment", comment); 0077 peruseConfig.setFilesystemProperty(root.filename, "comment", comment); 0078 } 0079 0080 onFilenameChanged: { 0081 comment = peruseConfig.getFilesystemProperty(root.filename, "comment"); 0082 tags = peruseConfig.getFilesystemProperty(root.filename, "tags").split(","); 0083 rating = peruseConfig.getFilesystemProperty(root.filename, "rating"); 0084 ratingRow.potentialRating = rating; 0085 } 0086 0087 Rectangle { 0088 anchors.fill: parent; 0089 color: Kirigami.Theme.highlightColor; 0090 opacity: root.selected ? 1 : 0; 0091 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration; } } 0092 } 0093 Item { 0094 id: bookCover; 0095 anchors { 0096 top: parent.top; 0097 left: parent.left; 0098 } 0099 width: root.width / 3; 0100 height: width * 1.5; 0101 Kirigami.Icon { 0102 id: coverImage; 0103 anchors { 0104 fill: parent; 0105 margins: Kirigami.Units.largeSpacing; 0106 } 0107 source: root.thumbnail === "Unknown role" ? "" : root.thumbnail; 0108 placeholder: "application-vnd.oasis.opendocument.text"; 0109 fallback: "paint-unknown" 0110 } 0111 MouseArea { 0112 anchors.fill: parent; 0113 onClicked: root.bookSelected(root.filename, root.currentPage); 0114 } 0115 } 0116 Kirigami.Heading { 0117 id: bookTitle; 0118 anchors { 0119 top: parent.top; 0120 leftMargin: Kirigami.Units.smallSpacing; 0121 left: bookCover.right; 0122 right: parent.right; 0123 } 0124 maximumLineCount: 1; 0125 elide: Text.ElideMiddle; 0126 font.weight: Font.Bold; 0127 MouseArea { 0128 anchors.fill: parent; 0129 onClicked: root.bookSelected(root.filename, root.currentPage); 0130 } 0131 Rectangle { 0132 anchors { 0133 left: parent.left; 0134 top: parent.baseline; 0135 topMargin: 2; 0136 } 0137 height: 2; 0138 width: parent.paintedWidth; 0139 color: Kirigami.Theme.linkColor; 0140 } 0141 } 0142 QtControls.Label { 0143 id: bookAuthorLabel; 0144 anchors { 0145 top: bookTitle.bottom; 0146 left: bookCover.right; 0147 leftMargin: Kirigami.Units.smallSpacing; 0148 } 0149 width: paintedWidth; 0150 text: i18nc("Label for authors", "Author(s)"); 0151 font.weight: Font.Bold; 0152 } 0153 QtControls.Label { 0154 id: bookAuthor; 0155 anchors { 0156 top: bookTitle.bottom; 0157 left: bookAuthorLabel.right; 0158 leftMargin: Kirigami.Units.smallSpacing; 0159 right: parent.right; 0160 } 0161 elide: Text.ElideRight; 0162 text: (typeof root.author !== "undefined" && root.author.length > 0) ? root.author.join(", ") : "(unknown)"; 0163 opacity: (text === "(unknown)" || text === "") ? 0.3 : 1; 0164 } 0165 QtControls.Label { 0166 id: bookPublisherLabel; 0167 anchors { 0168 top: bookAuthorLabel.bottom; 0169 left: bookCover.right; 0170 leftMargin: Kirigami.Units.smallSpacing; 0171 } 0172 width: paintedWidth; 0173 text: i18nc("Label for publisher", "Publisher"); 0174 font.weight: Font.Bold; 0175 } 0176 QtControls.Label { 0177 id: bookPublisher; 0178 anchors { 0179 top: bookAuthor.bottom; 0180 left: bookPublisherLabel.right; 0181 leftMargin: Kirigami.Units.smallSpacing; 0182 right: parent.right; 0183 } 0184 elide: Text.ElideRight; 0185 text: root.publisher === "" ? "(unknown)" : root.publisher; 0186 opacity: (text === "(unknown)" || text === "") ? 0.3 : 1; 0187 } 0188 QtControls.Label { 0189 id: bookFile; 0190 anchors { 0191 top: bookPublisherLabel.bottom; 0192 left: bookCover.right; 0193 leftMargin: Kirigami.Units.smallSpacing; 0194 right: parent.right; 0195 } 0196 elide: Text.ElideMiddle; 0197 opacity: 0.3; 0198 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 0.8; 0199 maximumLineCount: 1; 0200 } 0201 Item { 0202 id: ratingContainer; 0203 anchors { 0204 top: bookFile.bottom; 0205 left: bookCover.right; 0206 right: parent.right; 0207 margins: Kirigami.Units.smallSpacing; 0208 } 0209 Row { 0210 id: ratingRow; 0211 QtControls.Label { 0212 width: paintedWidth; 0213 text: i18nc("label for rating widget","Rating"); 0214 height: Kirigami.Units.iconSizes.medium; 0215 font.weight: Font.Bold; 0216 anchors.rightMargin: Kirigami.Units.smallSpacing; 0217 } 0218 property int potentialRating: root.rating; 0219 Repeater{ 0220 model: 5; 0221 Item { 0222 0223 height: Kirigami.Units.iconSizes.medium; 0224 width: Kirigami.Units.iconSizes.medium; 0225 0226 Kirigami.Icon { 0227 source: "rating"; 0228 opacity: (ratingRow.potentialRating-2)/2 >= index? 1.0: 0.3; 0229 anchors.fill:parent; 0230 0231 MouseArea { 0232 anchors.fill: parent; 0233 hoverEnabled: true; 0234 onEntered: { 0235 if (ratingRow.potentialRating === (index+1)*2) { 0236 ratingRow.potentialRating = ratingRow.potentialRating-1; 0237 } else { 0238 ratingRow.potentialRating = (index+1)*2; 0239 } 0240 } 0241 onExited: { 0242 ratingRow.potentialRating = root.rating; 0243 } 0244 onClicked: root.rating === ratingRow.potentialRating? 0245 root.rating = ratingRow.potentialRating-1 : 0246 root.rating = ratingRow.potentialRating; 0247 } 0248 0249 } 0250 Kirigami.Icon { 0251 source: "rating"; 0252 height: parent.height/2; 0253 clip: true; 0254 anchors.centerIn: parent; 0255 width: height; 0256 visible: ratingRow.potentialRating === (index*2)+1; 0257 } 0258 } 0259 } 0260 } 0261 0262 height: childrenRect.height; 0263 } 0264 Item { 0265 id: tagsContainer; 0266 height: childrenRect.height; 0267 visible: root.showCommentTags; 0268 anchors { 0269 top: ratingContainer.bottom; 0270 left: bookCover.right; 0271 right: parent.right; 0272 margins: Kirigami.Units.smallSpacing; 0273 } 0274 QtControls.Label { 0275 text: i18nc("label for tags field","Tags"); 0276 height: tagField.height; 0277 font.weight: Font.Bold; 0278 id: tagsLabel; 0279 } 0280 QtControls.TextField { 0281 id: tagField; 0282 anchors{ 0283 leftMargin: Kirigami.Units.smallSpacing; 0284 left: tagsLabel.right; 0285 top: parent.top; 0286 right: parent.right; 0287 } 0288 width: {parent.width - tagsLabel.width - Kirigami.Units.smallSpacing;} 0289 0290 text: root.tags.length !== 0? root.tags.join(", "): ""; 0291 placeholderText: i18nc("Placeholder tag field", "(No tags)"); 0292 onEditingFinished: { 0293 var tags = text.split(","); 0294 for (var i in tags) { 0295 tags[i] = tags[i].trim(); 0296 } 0297 root.tags = tags; 0298 } 0299 } 0300 } 0301 Item { 0302 id: commentContainer; 0303 height: childrenRect.height; 0304 visible: root.showCommentTags; 0305 anchors { 0306 top: tagsContainer.bottom; 0307 left: bookCover.right; 0308 right: parent.right; 0309 margins: Kirigami.Units.smallSpacing; 0310 } 0311 QtControls.Label { 0312 text: i18nc("label for comment field","Comment"); 0313 height: tagField.height; 0314 font.weight: Font.Bold; 0315 id: commentLabel; 0316 } 0317 QtControls.TextField { 0318 id: commentField; 0319 anchors{ 0320 leftMargin: Kirigami.Units.smallSpacing; 0321 left: commentLabel.right; 0322 top: parent.top; 0323 right: parent.right; 0324 } 0325 width: parent.width - commentLabel.width - Kirigami.Units.smallSpacing; 0326 0327 text: root.comment !== ""? root.comment: ""; 0328 placeholderText: i18nc("Placeholder comment field", "(No comment)"); 0329 onEditingFinished: { 0330 root.comment = text; 0331 } 0332 } 0333 } 0334 Item { 0335 id: descriptionContainer; 0336 anchors { 0337 top: root.showCommentTags ? commentContainer.bottom : ratingContainer.bottom; 0338 left: bookCover.right; 0339 right: parent.right; 0340 bottom: deleteBase.top; 0341 margins: Kirigami.Units.smallSpacing; 0342 } 0343 QtControls.Label { 0344 anchors.fill: parent; 0345 verticalAlignment: Text.AlignTop; 0346 text: (typeof root.description !== "undefined" && root.description.length !== 0) ? 0347 root.description.join("\n\n"): 0348 i18nc("Placeholder text for the book description field when no description is set", "(no description available for this book)"); 0349 wrapMode: Text.WrapAtWordBoundaryOrAnywhere 0350 opacity: (typeof root.description !== "undefined" && root.description.length !== 0) ? 1.0: 0.3; 0351 } 0352 } 0353 Item { 0354 id: deleteBase; 0355 anchors { 0356 left: bookCover.right; 0357 leftMargin: Kirigami.Units.smallSpacing; 0358 right: parent.right; 0359 bottom: parent.bottom; 0360 } 0361 height: deleteButton.height + Kirigami.Units.smallSpacing * 2; 0362 Behavior on height { NumberAnimation { duration: applicationWindow().animationDuration; easing.type: Easing.InOutQuad; } } 0363 states: [ 0364 State { 0365 name: "confirmDelete"; 0366 PropertyChanges { target: deleteButton; opacity: 0; } 0367 PropertyChanges { target: deleteConfirmBase; opacity: 1; } 0368 PropertyChanges { target: deleteBase; height: deleteConfirmBase.height; } 0369 } 0370 ] 0371 QtControls.Button { 0372 id: deleteButton; 0373 text: i18nc("Spawn inline dialog box to confirm permanent removal of this book", "Delete from Device"); 0374 anchors { 0375 bottom: parent.bottom; 0376 right: parent.right; 0377 margins: Kirigami.Units.smallSpacing; 0378 } 0379 // iconName: "edit-delete"; 0380 onClicked: deleteBase.state = "confirmDelete"; 0381 Behavior on opacity { NumberAnimation { duration: applicationWindow().animationDuration; easing.type: Easing.InOutQuad; } } 0382 } 0383 Rectangle { 0384 id: deleteConfirmBase; 0385 opacity: 0; 0386 width: parent.width; 0387 Behavior on opacity { NumberAnimation { duration: applicationWindow().animationDuration; easing.type: Easing.InOutQuad; } } 0388 height: yesDelete.height + confirmDeleteLabel.height + Kirigami.Units.largeSpacing * 2 + Kirigami.Units.smallSpacing; 0389 color: Kirigami.Theme.backgroundColor; 0390 QtControls.Label { 0391 id: confirmDeleteLabel; 0392 anchors { 0393 top: parent.top; 0394 topMargin: Kirigami.Units.largeSpacing; 0395 left: parent.left; 0396 right: parent.right; 0397 } 0398 height: paintedHeight; 0399 wrapMode: Text.WordWrap; 0400 horizontalAlignment: Text.AlignHCenter; 0401 text: i18nc("Dialog text for delete book dialog", "Are you sure you want to delete this from your device?"); 0402 } 0403 QtControls.Button { 0404 id: yesDelete; 0405 anchors { 0406 top: confirmDeleteLabel.bottom; 0407 topMargin: Kirigami.Units.smallSpacing; 0408 right: parent.horizontalCenter; 0409 rightMargin: (Kirigami.Units.smallSpacing) / 2; 0410 } 0411 text: i18nc("Confirmation button for book delete dialog", "Yes, Really Delete"); 0412 // iconName: "dialog-ok"; 0413 onClicked: {root.bookDeleteRequested(root.filename); deleteBase.state = "";} 0414 } 0415 QtControls.Button { 0416 anchors { 0417 top: confirmDeleteLabel.bottom; 0418 topMargin: Kirigami.Units.smallSpacing; 0419 left: parent.horizontalCenter; 0420 leftMargin: (Kirigami.Units.smallSpacing) / 2; 0421 } 0422 text: i18nc("Cancellation button or book delete dialog", "No, Cancel Delete"); 0423 // iconName: "dialog-cancel"; 0424 onClicked: deleteBase.state = ""; 0425 } 0426 } 0427 } 0428 }