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

0001 // SPDX-FileCopyrightText: 2021 Felipe Kinoshita <kinofhek@gmail.com>
0002 // SPDX-FileCopyrightText: 2023 Michael Lang <criticaltemp@protonmail.com>
0003 // SPDX-License-Identifier: LGPL-2.0-or-later
0004 
0005 import QtQuick 2.15
0006 import QtQuick.Controls 2.15 as QQC2
0007 import QtQuick.Layouts 1.15
0008 import org.kde.kirigami 2.19 as Kirigami
0009 
0010 import org.kde.angelfish 1.0
0011 
0012 RowLayout {
0013     id: tabsComponent
0014     spacing: 0
0015 
0016     Shortcut {
0017         sequences: ["Ctrl+Tab", "Ctrl+PgDown"]
0018         onActivated: {
0019             if (listview.currentIndex != listview.count -1) {
0020                 tabs.currentIndex++;
0021             } else {
0022                 tabs.currentIndex = 0;
0023             }
0024         }
0025     }
0026     Shortcut {
0027         sequences: ["Ctrl+Shift+Tab", "Ctrl+PgUp"]
0028         onActivated: {
0029             if (listview.currentIndex === 0) {
0030                 tabs.currentIndex = listview.count - 1;
0031             } else {
0032                 tabs.currentIndex--;
0033             }
0034         }
0035     }
0036 
0037     Shortcut {
0038         sequence: "Ctrl+W"
0039         onActivated: {
0040             tabs.tabsModel.closeTab(listview.currentIndex);
0041         }
0042     }
0043 
0044     Shortcut {
0045         sequence: "Ctrl+1"
0046         onActivated: {
0047             if (listview.currentIndex !== 0) {
0048                 tabs.currentIndex = 0;
0049             }
0050         }
0051     }
0052     Shortcut {
0053         sequence: "Ctrl+2"
0054         onActivated: {
0055             if (listview.currentIndex !== 1) {
0056                 tabs.currentIndex = 1;
0057             }
0058         }
0059     }
0060     Shortcut {
0061         sequence: "Ctrl+3"
0062         onActivated: {
0063             if (listview.currentIndex !== 2) {
0064                 tabs.currentIndex = 2;
0065             }
0066         }
0067     }
0068     Shortcut {
0069         sequence: "Ctrl+4"
0070         onActivated: {
0071             if (listview.currentIndex !== 3) {
0072                 tabs.currentIndex = 3;
0073             }
0074         }
0075     }
0076     Shortcut {
0077         sequence: "Ctrl+5"
0078         onActivated: {
0079             if (listview.currentIndex !== 4) {
0080                 tabs.currentIndex = 4;
0081             }
0082         }
0083     }
0084     Shortcut {
0085         sequence: "Ctrl+6"
0086         onActivated: {
0087             if (listview.currentIndex !== 5) {
0088                 tabs.currentIndex = 5;
0089             }
0090         }
0091     }
0092     Shortcut {
0093         sequence: "Ctrl+7"
0094         onActivated: {
0095             if (listview.currentIndex !== 6) {
0096                 tabs.currentIndex = 6;
0097             }
0098         }
0099     }
0100     Shortcut {
0101         sequence: "Ctrl+8"
0102         onActivated: {
0103             if (listview.currentIndex !== 7) {
0104                 tabs.currentIndex = 7;
0105             }
0106         }
0107     }
0108     Shortcut {
0109         sequence: "Ctrl+9"
0110         onActivated: {
0111             if (listview.currentIndex !== listview.count - 1) {
0112                 tabs.currentIndex = listview.count - 1;
0113             }
0114         }
0115     }
0116 
0117     ListView {
0118         id: listview
0119         visible: Settings.showTabBar || listview.count > 1
0120         Layout.fillWidth: true
0121         Layout.preferredHeight: footerItem.height
0122         model: tabs.model
0123         orientation: ListView.Horizontal
0124         currentIndex: tabs.currentIndex
0125         interactive: false
0126         boundsBehavior: Flickable.StopAtBounds
0127         headerPositioning: ListView.OverlayHeader
0128         header: Rectangle {
0129             z: 3
0130             height: parent.height
0131             width: listview.tabScroll ? height : 0
0132             color: Kirigami.Theme.backgroundColor
0133 
0134             QQC2.ToolButton {
0135                 visible: listview.tabScroll
0136                 enabled: !listview.atXBeginning
0137                 icon.name: "arrow-left"
0138                 onClicked: listview.flick(1000, 0)
0139                 onDoubleClicked: listview.flick(5000, 0)
0140             }
0141         }
0142 
0143         WheelHandler {
0144             acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
0145             onWheel: listview.flick(event.angleDelta.y * 10, 0)
0146         }
0147 
0148         property int baseWidth: Kirigami.Units.gridUnit * 14
0149         property real tabWidth: baseWidth * Math.min(Math.max(listview.width / (baseWidth * (listview.count + 1)), 0.4), 1)
0150         property bool tabScroll: listview.tabWidth * listview.count > listview.width
0151 
0152         delegate: QQC2.ItemDelegate {
0153             id: control
0154 
0155             required property int index
0156 
0157             highlighted: ListView.isCurrentItem
0158 
0159             width: listview.tabWidth
0160             height: tabsComponent.height
0161 
0162             onClicked: {
0163                 tabs.currentIndex = control.index;
0164             }
0165 
0166             background: Rectangle {
0167                 implicitHeight: Kirigami.Units.gridUnit * 3 + Kirigami.Units.smallSpacing * 2
0168                 color: control.highlighted ? Qt.lighter(Kirigami.Theme.backgroundColor, 1.1)
0169                     : (control.hovered ? Qt.darker(Kirigami.Theme.backgroundColor, 1.05)
0170                     : Kirigami.Theme.backgroundColor)
0171                 Behavior on color { ColorAnimation { duration: Kirigami.Units.shortDuration } }
0172 
0173                 QQC2.ToolSeparator {
0174                     anchors.top: parent.top
0175                     anchors.bottom: parent.bottom
0176                     anchors.right: parent.right
0177                     orientation: Qt.Vertical
0178                 }
0179 
0180                 QQC2.ToolSeparator {
0181                     visible: index === 0
0182                     anchors.top: parent.top
0183                     anchors.bottom: parent.bottom
0184                     anchors.left: parent.left
0185                     orientation: Qt.Vertical
0186                 }
0187 
0188                 MouseArea {
0189                     anchors.fill: parent
0190 
0191                     acceptedButtons: Qt.AllButtons
0192 
0193                     onClicked: (mouse) => {
0194                         if (mouse.button === Qt.MiddleButton) {
0195                             tabs.tabsModel.closeTab(control.index);
0196                         } else if (mouse.button === Qt.RightButton) {
0197                             tabMenu.index = control.index
0198                             if (tabMenu.visible) {
0199                                 tabMenu.close()
0200                             } else {
0201                                 tabMenu.popup(control)
0202                             }
0203                         }
0204                     }
0205                 }
0206             }
0207 
0208             contentItem: RowLayout {
0209                 id: layout
0210                 spacing: Kirigami.Units.smallSpacing
0211 
0212                 Kirigami.Icon {
0213                     id: tabIcon
0214                     Layout.alignment: Qt.AlignLeft
0215                     Layout.preferredWidth: Kirigami.Units.iconSizes.small
0216                     Layout.preferredHeight: width
0217                     source: tabs.itemAt(control.index).icon
0218                 }
0219 
0220                 QQC2.Label {
0221                     id: titleLabel
0222                     Layout.fillWidth: true
0223                     Layout.alignment: Qt.AlignLeft
0224                     Layout.leftMargin: Kirigami.Units.smallSpacing
0225                     Layout.rightMargin: Kirigami.Units.smallSpacing
0226                     text: tabs.itemAt(control.index).readerMode ?
0227                         i18n("Reader Mode: %1", tabs.itemAt(model.index).readerTitle)
0228                         : tabs.itemAt(control.index).title
0229                     elide: Text.ElideRight
0230                     horizontalAlignment: Text.AlignLeft
0231                 }
0232 
0233                 QQC2.AbstractButton {
0234                     visible: control.highlighted || control.width > Kirigami.Units.gridUnit * 8
0235                     Layout.alignment: Qt.AlignRight
0236                     Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
0237                     Layout.preferredHeight: width
0238                     onClicked: tabs.tabsModel.closeTab(model.index)
0239 
0240                     background: Rectangle {
0241                         anchors.fill: parent
0242                         radius: height / 2
0243                         color: hoverHandler.hovered ? control.background.color : Kirigami.Theme.disabledTextColor
0244                         border.width: 4
0245                         border.color: control.background.color
0246                     }
0247 
0248                     contentItem: Kirigami.Icon {
0249                         source: "tab-close-symbolic"
0250                         color: hoverHandler.hovered ? Kirigami.Theme.negativeTextColor : control.background.color
0251                         anchors.centerIn: parent
0252                         implicitWidth: parent.width
0253                         implicitHeight: width
0254                     }
0255 
0256                     QQC2.ToolTip.visible: hoverHandler.hovered
0257                     QQC2.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
0258                     QQC2.ToolTip.text: i18n("Close tab")
0259 
0260                     HoverHandler {
0261                         id: hoverHandler
0262                         acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0263                     }
0264                 }
0265 
0266                 QQC2.ToolTip.visible: hoverHandlerTab.hovered
0267                 QQC2.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
0268                 QQC2.ToolTip.text: titleLabel.text
0269 
0270                 HoverHandler {
0271                     id: hoverHandlerTab
0272                     acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0273                 }
0274             }
0275         }
0276         footerPositioning: listview.tabScroll ? ListView.OverlayFooter : ListView.InlineFooter
0277         footer: Rectangle {
0278             z: 3
0279             height: row.height
0280             width: row.width
0281             color: Kirigami.Theme.backgroundColor
0282 
0283             Row {
0284                 id: row
0285                 QQC2.ToolButton {
0286                     visible: listview.tabScroll
0287                     enabled: !listview.atXEnd
0288                     icon.name: "arrow-right"
0289                     onClicked: listview.flick(-1000, 0)
0290                     onDoubleClicked: listview.flick(-5000, 0)
0291                 }
0292                 QQC2.ToolButton {
0293                     icon.name: "list-add"
0294                     onClicked: tabs.tabsModel.newTab(Settings.newTabUrl)
0295 
0296                     QQC2.ToolTip.visible: hoverHandler.hovered
0297                     QQC2.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
0298                     QQC2.ToolTip.text: i18n("Open a new tab")
0299 
0300                     HoverHandler {
0301                         id: hoverHandler
0302                         acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0303                     }
0304                 }
0305 
0306             }
0307         }
0308         add: Transition {
0309             NumberAnimation { property: "opacity"; from: 0; to: 1; duration: Kirigami.Units.longDuration; easing.type: Easing.InQuad }
0310         }
0311         remove: Transition {
0312             NumberAnimation { property: "opacity"; to: 0; duration: Kirigami.Units.longDuration; easing.type: Easing.OutQuad }
0313         }
0314     }
0315 
0316     Rectangle {
0317         Layout.alignment: Qt.AlignRight
0318         z: 3
0319         height: listview.footerItem.height
0320         width: height
0321         color: Kirigami.Theme.backgroundColor
0322 
0323         QQC2.ToolButton {
0324             id: menuButton
0325             icon.name: "arrow-down"
0326             down: menu.visible
0327             onPressed: menu.visible ? menu.close() : menu.popup(tabsComponent.width, tabsComponent.y + menuButton.height)
0328 
0329             QQC2.ToolTip.visible: hoverHandler.hovered
0330             QQC2.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
0331             QQC2.ToolTip.text: i18n("List all tabs")
0332 
0333             HoverHandler {
0334                 id: hoverHandler
0335                 acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
0336             }
0337         }
0338     }
0339 
0340     QQC2.Menu {
0341         id: menu
0342         Instantiator {
0343             model: tabs.model
0344             onObjectAdded: (index, object) => menu.insertItem(index, object)
0345             onObjectRemoved: (index, object) => menu.removeItem(object)
0346             delegate: QQC2.MenuItem {
0347                 icon.name: tabs.itemAt(model.index).icon
0348                 text: tabs.itemAt(model.index).title
0349                 onTriggered: {
0350                     tabs.currentIndex = model.index;
0351                     menu.close();
0352                 }
0353             }
0354         }
0355     }
0356 
0357     QQC2.Menu {
0358         id: tabMenu
0359         property int index
0360 
0361         Kirigami.Action {
0362             text: i18n("New Tab")
0363             icon.name: "list-add"
0364             shortcut: "Ctrl+T"
0365             onTriggered: tabs.tabsModel.newTab(Settings.newTabUrl)
0366         }
0367 
0368         QQC2.MenuSeparator {}
0369 
0370         Kirigami.Action {
0371             text: i18n("Reload Tab")
0372             icon.name: "view-refresh"
0373             shortcut: "Ctrl+R"
0374             onTriggered: {
0375                 currentWebView.reload();
0376             }
0377         }
0378         Kirigami.Action {
0379             text: i18n("Duplicate Tab")
0380             icon.name: "tab-duplicate"
0381             onTriggered: tabs.tabsModel.newTab(currentWebView.url)
0382         }
0383 
0384         QQC2.MenuSeparator {}
0385 
0386         Kirigami.Action {
0387             text: i18n("Bookmark Tab")
0388             icon.name: urlObserver.bookmarked ? "rating" : "rating-unrated"
0389             shortcut: "Ctrl+D"
0390             onTriggered: {
0391                 const request = {
0392                     url: currentWebView.url,
0393                     title: currentWebView.title,
0394                     icon: currentWebView.icon
0395                 }
0396                 BrowserManager.addBookmark(request)
0397             }
0398         }
0399 
0400         QQC2.MenuSeparator {}
0401 
0402         Kirigami.Action {
0403             text: i18n("Close Tab")
0404             icon.name: "tab-close"
0405             onTriggered: tabs.tabsModel.closeTab(tabMenu.index)
0406         }
0407     }
0408 }