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