Warning, /multimedia/kasts/src/qml/FeedListDelegate.qml is written in an unsupported language. File is not indexed.

0001 /**
0002  * SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
0003  * SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be>
0004  *
0005  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006  */
0007 
0008 import QtQuick
0009 import QtQuick.Controls as Controls
0010 import QtQuick.Layouts
0011 import QtQuick.Effects
0012 import QtQml.Models
0013 
0014 import org.kde.kirigami as Kirigami
0015 
0016 import org.kde.kasts
0017 
0018 Controls.ItemDelegate {
0019     id: feedDelegate
0020 
0021     property var countProperty: (kastsMainWindow.feedSorting === FeedsProxyModel.UnreadDescending || kastsMainWindow.feedSorting === FeedsProxyModel.UnreadAscending) ? feed.unreadEntryCount : ((kastsMainWindow.feedSorting === FeedsProxyModel.NewDescending || kastsMainWindow.feedSorting === FeedsProxyModel.NewAscending) ? feed.newEntryCount : ((kastsMainWindow.feedSorting === FeedsProxyModel.FavoriteDescending || kastsMainWindow.feedSorting === FeedsProxyModel.FavoriteAscending) ? feed.favoriteEntryCount : 0))
0022     property int cardSize: 0
0023     property int cardMargin: 0
0024     property int borderWidth: 1
0025     implicitWidth: cardSize + 2 * cardMargin
0026     implicitHeight: cardSize + 2 * cardMargin
0027 
0028     property QtObject listView: undefined
0029     property bool selected: false
0030     property bool isCurrentItem: false // to restore currentItem when model is resorted
0031     property string currentItemUrl: ""
0032     property int row: model ? model.row : -1
0033     property var activeBackgroundColor: Qt.lighter(Kirigami.Theme.highlightColor, 1.3)
0034     highlighted: selected
0035 
0036     Accessible.role: Accessible.Button
0037     Accessible.name: feed.name
0038     Accessible.onPressAction: {
0039          clicked();
0040     }
0041     Keys.onReturnPressed: clicked()
0042 
0043     // We need to update the "selected" status:
0044     // - if the selected indexes changes
0045     // - if our delegate moves
0046     // - if the model moves and the delegate stays in the same place
0047     function updateIsSelected() {
0048         selected = listView.selectionModel.rowIntersectsSelection(row);
0049     }
0050 
0051     onRowChanged: {
0052         updateIsSelected();
0053     }
0054 
0055     Component.onCompleted: {
0056         updateIsSelected();
0057     }
0058 
0059     background: Rectangle {
0060         // Background for highlighted / hovered / active items
0061         Rectangle {
0062             id: background
0063             anchors.fill: parent
0064             color: feedDelegate.checked || feedDelegate.highlighted || (feedDelegate.supportsMouseEvents && feedDelegate.pressed)
0065                 ? feedDelegate.activeBackgroundColor
0066                 : Kirigami.Theme.backgroundColor
0067 
0068             Rectangle {
0069                 id: internal
0070                 property bool indicateActiveFocus: feedDelegate.pressed || Kirigami.Settings.tabletMode || feedDelegate.activeFocus || (feedDelegate.ListView.view ? feedDelegate.ListView.view.activeFocus : false)
0071                 anchors.fill: parent
0072                 visible: !Kirigami.Settings.tabletMode && feedDelegate.hoverEnabled
0073                 color: feedDelegate.activeBackgroundColor
0074                 opacity: (feedDelegate.hovered || feedDelegate.highlighted || feedDelegate.activeFocus) && !feedDelegate.pressed ? 0.5 : 0
0075             }
0076         }
0077 
0078         Kirigami.ShadowedRectangle {
0079             anchors.fill: parent
0080             anchors.margins: cardMargin
0081             anchors.leftMargin: cardMargin
0082             color: Kirigami.Theme.backgroundColor
0083 
0084             radius: Kirigami.Units.smallSpacing
0085 
0086             shadow.size: Kirigami.Units.largeSpacing
0087             shadow.color: Qt.rgba(0.0, 0.0, 0.0, 0.15)
0088             shadow.yOffset: borderWidth * 2
0089 
0090             border.width: borderWidth
0091             border.color: Qt.tint(Kirigami.Theme.textColor, Qt.rgba(color.r, color.g, color.b, 0.6))
0092         }
0093     }
0094 
0095     contentItem: MouseArea {
0096         id: mouseArea
0097         anchors.fill: parent
0098         anchors.margins: cardMargin + borderWidth
0099         implicitWidth:  cardSize - 2 * borderWidth
0100         implicitHeight: cardSize  - 2 * borderWidth
0101 
0102         acceptedButtons: Qt.LeftButton | Qt.RightButton
0103         onClicked: (mouse) => {
0104             // Keep track of (currently) selected items
0105             var modelIndex = feedDelegate.listView.model.index(index, 0);
0106 
0107             if (feedDelegate.listView.selectionModel.isSelected(modelIndex) && mouse.button == Qt.RightButton) {
0108                 feedDelegate.listView.contextMenu.popup(null, mouse.x+1, mouse.y+1);
0109             } else if (mouse.modifiers & Qt.ShiftModifier) {
0110                 // Have to take a detour through c++ since selecting large sets
0111                 // in QML is extremely slow
0112                 feedDelegate.listView.selectionModel.select(feedDelegate.listView.model.createSelection(modelIndex.row, feedDelegate.listView.selectionModel.currentIndex.row), ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows);
0113             } else if (mouse.modifiers & Qt.ControlModifier) {
0114                 feedDelegate.listView.selectionModel.select(modelIndex, ItemSelectionModel.Toggle | ItemSelectionModel.Rows);
0115             } else if (mouse.button == Qt.LeftButton) {
0116                 feedDelegate.listView.currentIndex = index;
0117                 feedDelegate.listView.selectionModel.setCurrentIndex(modelIndex, ItemSelectionModel.ClearAndSelect | ItemSelectionModel.Rows);
0118                 feedDelegate.clicked();
0119             } else if (mouse.button == Qt.RightButton) {
0120                 // This item is right-clicked, but isn't selected
0121                 feedDelegate.listView.selectionForContextMenu = [modelIndex];
0122                 feedDelegate.listView.contextMenu.popup(null, mouse.x+1, mouse.y+1);
0123             }
0124         }
0125 
0126         onPressAndHold: {
0127             var modelIndex = feedDelegate.listView.model.index(index, 0);
0128             feedDelegate.listView.selectionModel.select(modelIndex, ItemSelectionModel.Toggle | ItemSelectionModel.Rows);
0129         }
0130 
0131         Connections {
0132             target: listView.selectionModel
0133             function onSelectionChanged() {
0134                 updateIsSelected();
0135             }
0136         }
0137 
0138         Connections {
0139             target: listView.model
0140             function onLayoutAboutToBeChanged() {
0141                 if (feedList.currentItem === feedDelegate) {
0142                     isCurrentItem = true;
0143                     currentItemUrl = feed.url;
0144                 } else {
0145                     isCurrentItem = false;
0146                     currentItemUrl = "";
0147                 }
0148             }
0149             function onLayoutChanged() {
0150                 updateIsSelected();
0151                 if (isCurrentItem) {
0152                     // yet another hack because "index" is still giving the old
0153                     // value here; so we have to manually find the new index.
0154                     for (var i = 0; i < feedList.model.rowCount(); i++) {
0155                         if (feedList.model.data(feedList.model.index(i, 0), FeedsModel.UrlRole) == currentItemUrl) {
0156                             feedList.currentIndex = i;
0157                         }
0158                     }
0159                 }
0160             }
0161         }
0162 
0163         ImageWithFallback {
0164             id: img
0165             anchors.fill: parent
0166             imageSource: feed.cachedImage
0167             imageTitle: feed.name
0168             isLoading: feed.refreshing
0169             absoluteRadius: Kirigami.Units.smallSpacing - borderWidth
0170         }
0171 
0172         Rectangle {
0173             id: countRectangle
0174             visible: countProperty > 0
0175             anchors.top: img.top
0176             anchors.right: img.right
0177             width: actionsButton.width
0178             height: actionsButton.height
0179             color: feedDelegate.activeBackgroundColor
0180             radius: Kirigami.Units.smallSpacing - 2 * borderWidth
0181         }
0182 
0183         Controls.Label {
0184             id: countLabel
0185             visible: countProperty > 0
0186             anchors.centerIn: countRectangle
0187             anchors.margins: Kirigami.Units.smallSpacing
0188             text: countProperty
0189             font.bold: true
0190             color: Kirigami.Theme.highlightedTextColor
0191         }
0192 
0193         Rectangle {
0194             id: actionsRectangle
0195             anchors.fill: actionsButton
0196             color: "black"
0197             opacity: 0.5
0198             radius: Kirigami.Units.smallSpacing - 2 * borderWidth
0199         }
0200 
0201         Controls.Button {
0202             id: actionsButton
0203             anchors.right: img.right
0204             anchors.bottom: img.bottom
0205             anchors.margins: 0
0206             padding: 0
0207             flat: true
0208             icon.name: "overflow-menu"
0209             icon.color: "white"
0210             onClicked: actionOverlay.open()
0211         }
0212     }
0213 
0214     onClicked: {
0215         lastFeed = feed.url
0216         if (pageStack.depth >  1)
0217             pageStack.pop();
0218         pageStack.push("qrc:/qt/qml/org/kde/kasts/qml/FeedDetailsPage.qml", {"feed": feed})
0219     }
0220 
0221     Controls.ToolTip.visible: hovered
0222     Controls.ToolTip.text: feed.name
0223     Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
0224 
0225     Kirigami.MenuDialog {
0226         id: actionOverlay
0227         // parent: applicationWindow().overlay
0228         showCloseButton: true
0229 
0230         title: feed.name
0231 
0232         actions: [
0233             Kirigami.Action {
0234                 onTriggered: {
0235                     while (pageStack.depth > 1)
0236                         pageStack.pop()
0237                     pageStack.push("qrc:/qt/qml/org/kde/kasts/qml/FeedDetailsPage.qml", {"feed": feed});
0238                 }
0239                 icon.name: "documentinfo"
0240                 text: i18n("Podcast Details")
0241             },
0242             Kirigami.Action {
0243                 onTriggered: {
0244                     if (feed.url === lastFeed)
0245                         while(pageStack.depth > 1)
0246                             pageStack.pop()
0247                     DataManager.removeFeed(feed)
0248                 }
0249                 icon.name: "delete"
0250                 text: i18n("Remove Podcast")
0251             }
0252         ]
0253     }
0254 }