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 }