Warning, /network/angelfish/src/contents/ui/Tabs.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2014-2015 Sebastian Kügler <sebas@kde.org>
0002 // SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
0003 // SPDX-FileCopyrightText: 2023 Michael Lang <criticaltemp@protonmail.com>
0004 // SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006 import QtQuick 2.15
0007 import QtQuick.Layouts 1.15
0008 import QtQuick.Controls 2.15 as QQC2
0009 
0010 import org.kde.kirigami 2.19 as Kirigami
0011 
0012 import org.kde.angelfish 1.0
0013 
0014 import "components"
0015 BottomDrawer {
0016     id: tabsRoot
0017     
0018     height: contents.implicitHeight + Kirigami.Units.largeSpacing
0019     width: applicationWindow().width
0020     edge: Qt.BottomEdge
0021     
0022     property int columns: width > 800 ? 4 : width > 600 ? 3 : 2
0023     property real ratio: webBrowser.height / webBrowser.width
0024     readonly property int itemWidth: webBrowser.width / columns - Kirigami.Units.smallSpacing * 2
0025     readonly property int itemHeight: (itemWidth * ratio + Kirigami.Units.gridUnit) * columns / 4
0026 
0027     Component.onCompleted: grid.currentIndex = tabs.currentIndex
0028 
0029     onOpened: grid.width = width // prevents gridview layout issues
0030     onClosed: {
0031         tabsSheetLoader.active = false // unload tabs when the sheet is closed
0032         interactive = false
0033     }
0034 
0035     headerContentItem: RowLayout {
0036         Layout.maximumWidth: tabsRoot.width - Kirigami.Units.smallSpacing * 2
0037         Layout.leftMargin: Kirigami.Units.smallSpacing
0038         Layout.rightMargin: Kirigami.Units.smallSpacing
0039         Layout.bottomMargin: Kirigami.Units.smallSpacing
0040         z: 1
0041         Kirigami.Heading {
0042             text: i18n("Tabs")
0043 
0044         }
0045         Item { Layout.fillWidth: true }
0046 
0047         QQC2.ToolButton {
0048             icon.name: "list-add"
0049             text: i18n("New Tab")
0050             onClicked: {
0051                 tabs.tabsModel.newTab("about:blank")
0052                 urlEntry.open();
0053                 tabsRoot.close();
0054             }
0055         }
0056     }
0057     drawerContentItem: QQC2.ScrollView {
0058         id: scrollView
0059         Layout.fillWidth: true
0060         Layout.minimumHeight: Kirigami.Units.gridUnit * 12
0061         Layout.preferredHeight: applicationWindow().height * 0.6
0062         Layout.bottomMargin: Kirigami.Units.smallSpacing
0063         Layout.topMargin: Kirigami.Units.largeSpacing
0064         QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
0065 
0066         GridView {
0067             id: grid
0068             model: tabs.model
0069             cellWidth: itemWidth + Kirigami.Units.largeSpacing
0070             cellHeight: itemHeight + Kirigami.Units.largeSpacing
0071 
0072             add: Transition {
0073                 NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: Kirigami.Units.shortDuration }
0074             }
0075             remove: Transition {
0076                 NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: Kirigami.Units.shortDuration }
0077             }
0078             displaced: Transition {
0079                 NumberAnimation { properties: "x,y"; duration: Kirigami.Units.longDuration; easing.type: Easing.InOutQuad}
0080             }
0081 
0082             delegate: QQC2.ItemDelegate {
0083                 id: gridItem
0084                 // taking care of spacing
0085                 width: grid.cellWidth
0086                 height: grid.cellHeight
0087                 padding: Kirigami.Units.smallSpacing + borderWidth
0088                 clip: true
0089 
0090                 property int sourceX: (index % (grid.width / grid.cellWidth)) * grid.cellWidth
0091                 property int borderWidth: 2
0092 
0093                 DragHandler {
0094                     id: dragHandler
0095                     target: parent
0096                     yAxis.enabled: false
0097                     xAxis.enabled: true
0098                     onActiveChanged: {
0099                         xAnimator.stop();
0100 
0101                         let rightThreshold = Math.min(gridItem.sourceX + grid.width * 0.5, grid.width + Kirigami.Units.gridUnit * 2);
0102                         let leftThreshold = Math.max(gridItem.sourceX - grid.width * 0.5, - Kirigami.Units.gridUnit * 2);
0103                         if (parent.x > rightThreshold) {
0104                             xAnimator.to = grid.width;
0105                         } else if (parent.x < leftThreshold) {
0106                             xAnimator.to = -grid.width;
0107                         } else {
0108                             xAnimator.to = gridItem.sourceX;
0109                         }
0110                         xAnimator.start();
0111                     }
0112                 }
0113                 NumberAnimation on x {
0114                     id: xAnimator
0115                     running: !dragHandler.active
0116                     duration: Kirigami.Units.longDuration
0117                     easing.type: Easing.InOutQuad
0118                     to: gridItem.sourceX
0119                     onFinished: {
0120                         if (to != gridItem.sourceX) { // close tab
0121                             tabs.tabsModel.closeTab(index);
0122                         }
0123                     }
0124                 }
0125 
0126                 onClicked: {
0127                     tabs.currentIndex = index;
0128                     tabsRoot.close();
0129                 }
0130 
0131                 background: Item {
0132                     anchors.centerIn: parent
0133                     width: itemWidth
0134                     height: itemHeight
0135                     Rectangle {
0136                         // border around a selected tile
0137                         anchors.fill: parent;
0138                         border.color: tabs.currentIndex === index ? Kirigami.Theme.highlightColor : Kirigami.Theme.disabledTextColor
0139                         border.width: borderWidth
0140                         color: "transparent"
0141                         opacity: tabs.currentIndex === index ? 1.0 : 0.2
0142                     }
0143 
0144                     Rectangle {
0145                         // selection indicator
0146                         anchors.fill: parent
0147                         color: gridItem.pressed ? Kirigami.Theme.highlightColor : "transparent"
0148                         opacity: 0.2
0149                     }
0150                 }
0151 
0152                 contentItem: Column {
0153                     anchors.horizontalCenter: parent.horizontalCenter
0154                     width: itemWidth - Kirigami.Units.smallSpacing
0155 
0156                     Kirigami.Theme.inherit: false
0157                     Kirigami.Theme.colorSet: Kirigami.Theme.Header
0158 
0159                     Rectangle {
0160                         anchors.horizontalCenter: parent.horizontalCenter
0161                         color: Kirigami.Theme.backgroundColor
0162                         width: itemWidth - Kirigami.Units.smallSpacing
0163                         height: Kirigami.Units.gridUnit * 1.5
0164 
0165                         RowLayout {
0166                             anchors.fill: parent
0167                             spacing: Kirigami.Units.smallSpacing
0168 
0169                             Image {
0170                                 Layout.leftMargin: 2
0171                                 Layout.alignment: Qt.AlignVCenter
0172                                 Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
0173                                 Layout.preferredWidth: height
0174                                 fillMode: Image.PreserveAspectFit
0175                                 sourceSize: Qt.size(Kirigami.Units.iconSizes.smallMedium, Kirigami.Units.iconSizes.smallMedium)
0176                                 source: tabs.itemAt(index) ? tabs.itemAt(index).icon : ""
0177                             }
0178 
0179                             QQC2.Label {
0180                                 Layout.alignment: Qt.AlignVCenter
0181                                 Layout.fillWidth: true
0182                                 color: Kirigami.Theme.textColor
0183                                 text: tabs.itemAt(index) ?
0184                                 tabs.itemAt(index).readerMode ?
0185                                 i18n("Reader Mode: %1", tabs.itemAt(index).readerTitle)
0186                                 : tabs.itemAt(index).title
0187                                 : ""
0188                                 font.pointSize: Kirigami.Theme.defaultFont.pointSize - 2
0189                                 elide: Text.ElideRight
0190                             }
0191 
0192                             QQC2.AbstractButton {
0193                                 Layout.alignment: Qt.AlignVCenter
0194                                 Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
0195                                 Layout.preferredWidth: height
0196                                 onClicked: tabs.tabsModel.closeTab(index)
0197 
0198                                 background: Rectangle {
0199                                     anchors.fill: parent
0200                                     radius: height / 2
0201                                     color: hoverHandler.hovered ? Kirigami.Theme.backgroundColor : Kirigami.Theme.disabledTextColor
0202                                     border.width: 6
0203                                     border.color: Kirigami.Theme.backgroundColor
0204                                 }
0205 
0206                                 contentItem: Kirigami.Icon {
0207                                     source: "tab-close-symbolic"
0208                                     color: hoverHandler.hovered ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.backgroundColor
0209                                     anchors.centerIn: parent
0210                                     implicitWidth: parent.width
0211                                     implicitHeight: width
0212                                 }
0213 
0214                                 QQC2.ToolTip.visible: hoverHandler.hovered
0215                                 QQC2.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
0216                                 QQC2.ToolTip.text: i18n("Close tab")
0217 
0218                                 HoverHandler {
0219                                     id: hoverHandler
0220                                     acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0221                                 }
0222                             }
0223                         }
0224                     }
0225 
0226                     Item {
0227                         id: tabItem
0228                         anchors.horizontalCenter: parent.horizontalCenter
0229                         width: itemWidth - Kirigami.Units.smallSpacing
0230                         height: itemHeight - Kirigami.Units.gridUnit * 1.5 - Kirigami.Units.smallSpacing
0231 
0232                         // ShaderEffectSource requires that corresponding WebEngineView is
0233                         // visible. Here, visibility is enabled while snapshot is taken and
0234                         // removed as soon as it is ready.
0235                         ShaderEffectSource {
0236                             id: shaderItem
0237 
0238                             live: false
0239                             anchors.fill: parent
0240                             sourceRect: Qt.rect(0, 0, sourceItem.width, height/width * sourceItem.width)
0241                             sourceItem: tabs.itemAt(index)
0242 
0243                             Component.onCompleted: {
0244                                 sourceItem.readyForSnapshot = true;
0245                                 scheduleUpdate();
0246                             }
0247                             onScheduledUpdateCompleted: sourceItem.readyForSnapshot = false
0248                         }
0249                     }
0250                 }
0251             }
0252         }
0253     }
0254 }
0255