diff --git a/src/controls/ApplicationWindow.qml b/src/controls/ApplicationWindow.qml index 271a77a..6a298ff 100644 --- a/src/controls/ApplicationWindow.qml +++ b/src/controls/ApplicationWindow.qml @@ -1,578 +1,597 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.12 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import QtQuick.Window 2.12 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui import org.kde.mauikit 1.1 as MauiLab import "private" as Private Window { id: root default property alias content : _content.data visible: true width: Screen.desktopAvailableWidth * (Kirigami.Settings.isMobile ? 1 : 0.4) height: Screen.desktopAvailableHeight * (Kirigami.Settings.isMobile ? 1 : 0.4) color: "transparent" flags: Maui.App.enableCSD ? Qt.FramelessWindowHint : Qt.Window property Maui.AbstractSideBar sideBar /***************************************************/ /******************** ALIASES *********************/ /*************************************************/ property alias flickable : _page.flickable property alias headBar : _page.headBar property alias footBar: _page.footBar property alias footer: _page.footer property alias header :_page.header property alias floatingHeader: _page.floatingHeader property alias floatingFooter: _page.floatingFooter property alias autoHideHeader: _page.autoHideHeader property alias autoHideFooter: _page.autoHideFooter property alias autoHideHeaderDelay: _page.autoHideHeaderDelay property alias autoHideFooterDelay: _page.autoHideFooterDelay property alias autoHideHeaderMargins: _page.autoHideHeaderMargins property alias autoHideFooterMargins: _page.autoHideFooterMargins property alias altHeader: _page.altHeader property alias margins : _page.margins property alias leftMargin : _page.leftMargin property alias rightMargin: _page.rightMargin property alias topMargin: _page.topMargin property alias bottomMargin: _page.bottomMargin property alias footerPositioning : _page.footerPositioning property alias headerPositioning : _page.headerPositioning property alias dialog: dialogLoader.item property alias menuButton : menuBtn property alias mainMenu : mainMenu.contentData property alias accounts: _accountsDialogLoader.item property var currentAccount: Maui.App.handleAccounts ? Maui.App.accounts.currentAccount : ({}) property alias notifyDialog: _notify property alias background : _page.background /***************************************************/ /*********************** UI ***********************/ /*************************************************/ property bool isWide : root.width >= Kirigami.Units.gridUnit * 30 /***************************************************/ /********************* COLORS *********************/ /*************************************************/ property color headBarBGColor: Kirigami.Theme.backgroundColor property color headBarFGColor: Kirigami.Theme.textColor /***************************************************/ /**************** READONLY PROPS ******************/ /*************************************************/ readonly property bool isMobile : Kirigami.Settings.isMobile readonly property bool isAndroid: Maui.Handy.isAndroid readonly property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation || Screen.primaryOrientation === Qt.InvertedPortraitOrientation /***************************************************/ /******************** SIGNALS *********************/ /*************************************************/ signal menuButtonClicked(); onClosing: { if(!Kirigami.Settings.isMobile) { const height = root.height const width = root.width const x = root.x const y = root.y Maui.FM.saveSettings("GEOMETRY", Qt.rect(x, y, width, height), "WINDOW") } - } - + } Kirigami.Theme.colorSet: Kirigami.Theme.View MauiLab.Page { id: _page anchors.fill: parent Kirigami.Theme.colorSet: root.Kirigami.Theme.colorSet headerBackground.color: Maui.App.enableCSD ? Qt.darker(Kirigami.Theme.backgroundColor, 1.1) : headBar.Kirigami.Theme.backgroundColor headBar.farLeftContent: Loader { id: _leftControlsLoader visible: active active: Maui.App.enableCSD && Maui.App.leftWindowControls.length Layout.preferredWidth: active ? implicitWidth : 0 Layout.fillHeight: true sourceComponent: MauiLab.WindowControls { order: Maui.App.leftWindowControls } } headBar.leftContent: ToolButton { id: menuBtn icon.name: "application-menu" checked: mainMenu.visible onClicked: { menuButtonClicked() mainMenu.visible ? mainMenu.close() : mainMenu.popup(parent, 0 , root.headBar.height ) } Menu { id: mainMenu modal: true z: 999 width: Maui.Style.unit * 250 Loader { id: _accountsMenuLoader width: parent.width * 0.9 anchors.horizontalCenter: parent.horizontalCenter active: Maui.App.handleAccounts sourceComponent: Maui.App.handleAccounts ? _accountsComponent : null } MenuItem { text: i18n("About") icon.name: "documentinfo" onTriggered: aboutDialog.open() } } } headBar.farRightContent: Loader { id: _rightControlsLoader visible: active active: Maui.App.enableCSD && Maui.App.rightWindowControls.length Layout.preferredWidth: active ? implicitWidth : 0 Layout.fillHeight: true sourceComponent: MauiLab.WindowControls { order: Maui.App.rightWindowControls } } Item { id: _content anchors.fill: parent Kirigami.Theme.inherit: false transform: Translate { x: root.sideBar && root.sideBar.collapsible && root.sideBar.collapsed ? root.sideBar.position * (root.sideBar.width - root.sideBar.collapsedSize) : 0 } anchors.leftMargin: root.sideBar ? ((root.sideBar.collapsible && root.sideBar.collapsed) ? root.sideBar.collapsedSize : (root.sideBar.width ) * root.sideBar.position) : 0 } background: Rectangle { id: _pageBackground color: Kirigami.Theme.backgroundColor radius: root.visibility === Window.Maximized || !Maui.App.enableCSD ? 0 : Maui.App.theme.borderRadius } layer.enabled: Maui.App.enableCSD layer.effect: OpacityMask { maskSource: Item { width: _page.width height: _page.height Rectangle { anchors.fill: parent radius: _pageBackground.radius } } } } Rectangle { visible: Maui.App.enableCSD z: ApplicationWindow.overlay.z + 9999 anchors.fill: parent radius: _pageBackground.radius - 0.5 color: "transparent" border.color: Qt.darker(Kirigami.Theme.backgroundColor, 2.7) opacity: 0.5 Rectangle { anchors.fill: parent anchors.margins: 1 color: "transparent" radius: parent.radius - 0.5 border.color: Qt.lighter(Kirigami.Theme.backgroundColor, 2) opacity: 0.8 } } + MouseArea + { + visible: Maui.App.enableCSD + height: 16 + width: height + anchors.bottom: parent.bottom + anchors.left: parent.left + cursorShape: Qt.SizeBDiagCursor + propagateComposedEvents: true + preventStealing: false + + onPressed: mouse.accepted = false + + DragHandler + { + grabPermissions: TapHandler.TakeOverForbidden + target: null + onActiveChanged: if (active) + { + root.startSystemResize(Qt.LeftEdge | Qt.BottomEdge); + } + } + } - - Rectangle + MouseArea { - height: 22 + visible: Maui.App.enableCSD + height: 16 width: height anchors.bottom: parent.bottom anchors.right: parent.right - color: "orange" + cursorShape: Qt.SizeFDiagCursor + propagateComposedEvents: true + preventStealing: false + + onPressed: mouse.accepted = false DragHandler { - id: resizeHandler grabPermissions: TapHandler.TakeOverForbidden target: null - onActiveChanged: if (active) { - const p = resizeHandler.centroid.position; - let e = 0; - if (p.x / width < 0.10) { e |= Qt.LeftEdge } - if (p.x / width > 0.90) { e |= Qt.RightEdge } - if (p.y / height < 0.10) { e |= Qt.TopEdge } - if (p.y / height > 0.90) { e |= Qt.BottomEdge } - console.log("RESIZING", e); - root.startSystemResize(e); + onActiveChanged: if (active) + { + root.startSystemResize(Qt.RightEdge | Qt.BottomEdge); } - } - + } } + Overlay.overlay.modal: Rectangle { color: Qt.rgba( root.Kirigami.Theme.backgroundColor.r, root.Kirigami.Theme.backgroundColor.g, root.Kirigami.Theme.backgroundColor.b, 0.7) Behavior on opacity { NumberAnimation { duration: 150 } } radius: Maui.App.enableCSD ? Maui.App.theme.borderRadius : 0 } Overlay.overlay.modeless: Rectangle { radius: Maui.App.enableCSD ? Maui.App.theme.borderRadius : 0 color: Qt.rgba( root.Kirigami.Theme.backgroundColor.r, root.Kirigami.Theme.backgroundColor.g, root.Kirigami.Theme.backgroundColor.b, 0.7) Behavior on opacity { NumberAnimation { duration: 150 } } } // onHeadBarBGColorChanged: // { // if(!isMobile && colorSchemeName.length > 0) // Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) // else if(isAndroid && headBar.position === ToolBar.Header) // Maui.Android.statusbarColor(headBarBGColor, false) // else if(isAndroid && headBar.position === ToolBar.Footer) // Maui.Android.statusbarColor(Kirigami.Theme.viewBackgroundColor, true) // // } // // onHeadBarFGColorChanged: // { // if(!isAndroid && !isMobile && colorSchemeName.length > 0 && headBar.position === ToolBar.Header) // Maui.KDE.setColorScheme(colorSchemeName, headBarBGColor, headBarFGColor) // else if(isAndroid && headBar.position === ToolBar.Header) // Maui.Android.statusbarColor(headBarBGColor, false) // else if(isAndroid && headBar.position === ToolBar.Footer) // Maui.Android.statusbarColor(Kirigami.Theme.viewBackgroundColor, true) // } /* * background: Rectangle * { * color: bgColor } */ Component { id: _accountsComponent ColumnLayout { visible: Maui.App.handleAccounts spacing: Maui.Style.space.medium Kirigami.Icon { visible: Maui.App.accounts.currentAccountIndex >= 0 source: "user-identity" Layout.preferredHeight: Maui.Style.iconSizes.large Layout.preferredWidth: Maui.Style.iconSizes.large Layout.alignment: Qt.AlignCenter Layout.margins: Maui.Style.space.medium } Label { visible: Maui.App.accounts.currentAccountIndex >= 0 text: currentAccount ? currentAccount.user : "" Layout.fillWidth: true horizontalAlignment: Qt.AlignHCenter elide: Text.ElideMiddle wrapMode: Text.NoWrap font.bold: true font.weight: Font.Bold } Kirigami.Separator { visible: _accountsListing.count > 0 Layout.fillWidth: true } ListBrowser { id: _accountsListing visible: _accountsListing.count > 0 Layout.fillWidth: true Layout.preferredHeight: Math.min(contentHeight, 300) spacing: Maui.Style.space.medium Kirigami.Theme.backgroundColor: "transparent" currentIndex: Maui.App.accounts.currentAccountIndex model: Maui.BaseModel { list: Maui.App.accounts } delegate: Maui.ListBrowserDelegate { iconSource: "amarok_artist" iconSizeHint: Maui.Style.iconSizes.medium label1.text: model.user label2.text: model.server width: _accountsListing.width height: Maui.Style.rowHeight * 1.2 leftPadding: Maui.Style.space.tiny rightPadding: Maui.Style.space.tiny onClicked: Maui.App.accounts.currentAccountIndex = index } Component.onCompleted: { if(_accountsListing.count > 0) Maui.App.accounts.currentAccountIndex = 0 } } Kirigami.Separator { visible: _accountsListing.count > 0 Layout.fillWidth: true } Button { Layout.margins: Maui.Style.space.small Layout.preferredHeight: implicitHeight Layout.alignment: Qt.AlignCenter text: i18n("Manage accounts") icon.name: "list-add-user" onClicked: { if(root.accounts) accounts.open() mainMenu.close() } } Kirigami.Separator { Layout.fillWidth: true } } } Private.AboutDialog { id: aboutDialog } Loader { id: _accountsDialogLoader active: Maui.App.handleAccounts source: "private/AccountsHelper.qml" } Maui.Dialog { id: _notify property var cb : ({}) property alias iconName : _notifyTemplate.iconSource property alias title : _notifyTemplate.label1 property alias body: _notifyTemplate.label2 verticalAlignment: Qt.AlignTop defaultButtons: _notify.cb !== null rejectButton.visible: false onAccepted: { if(_notify.cb) { _notify.cb() _notify.close() } } page.padding: Maui.Style.space.medium footBar.background: null maxHeight: Math.max(Maui.Style.iconSizes.large + Maui.Style.space.huge, (_notifyTemplate.implicitHeight)) + Maui.Style.space.big + footBar.height maxWidth: Kirigami.Settings.isMobile ? parent.width * 0.9 : Maui.Style.unit * 500 widthHint: 0.8 Timer { id: _notifyTimer onTriggered: { if(_mouseArea.containsPress || _mouseArea.containsMouse) return; _notify.close() } } onClosed: _notifyTimer.stop() Maui.ListItemTemplate { id: _notifyTemplate Layout.fillHeight: true Layout.fillWidth: true iconSizeHint: Maui.Style.iconSizes.huge label1.font.bold: true label1.font.weight: Font.Bold label1.font.pointSize: Maui.Style.fontSizes.big iconSource: "dialog-warning" MouseArea { id: _mouseArea Layout.fillHeight: true Layout.fillWidth: true hoverEnabled: true } } function show(callback) { _notify.cb = callback || null _notifyTimer.start() _notify.open() } } Loader { id: dialogLoader } Component.onCompleted: { if(isAndroid) { if(headBar.position === ToolBar.Footer) { Maui.Android.statusbarColor(Kirigami.Theme.backgroundColor, true) Maui.Android.navBarColor(headBar.visible ? headBar.Kirigami.Theme.backgroundColor : Kirigami.Theme.backgroundColor, true) } else { Maui.Android.statusbarColor(headBar.Kirigami.Theme.backgroundColor, true) Maui.Android.navBarColor(footBar.visible ? footBar.Kirigami.Theme.backgroundColor : Kirigami.Theme.backgroundColor, true) } } if(!Kirigami.Settings.isMobile) { const rect = Maui.FM.loadSettings("GEOMETRY", "WINDOW", Qt.rect(root.x, root.y, root.width, root.height)) root.x = rect.x root.y = rect.y root.width = rect.width root.height = rect.height } } function notify(icon, title, body, callback, timeout, buttonText) { _notify.iconName = icon || "emblem-warning" _notify.title.text = title _notify.body.text = body _notifyTimer.interval = timeout ? timeout : 2500 _notify.acceptButton.text = buttonText || qsTr ("Accept") _notify.show(callback) } function toggleMaximized() { if (root.visibility === Window.Maximized) { root.showNormal(); } else { root.showMaximized(); } } function window() { return _page; } } diff --git a/src/controls/GridView.qml b/src/controls/GridView.qml index 8dcd6f8..540e585 100644 --- a/src/controls/GridView.qml +++ b/src/controls/GridView.qml @@ -1,327 +1,331 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.9 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.9 as Kirigami import QtGraphicalEffects 1.0 Item { id: control property int itemSize: 0 property int itemWidth : itemSize property int itemHeight : itemSize onItemSizeChanged : { controlView.size_ = itemSize control.itemWidth = itemSize control.cellWidth = itemWidth if(adaptContent) control.adaptGrid() } property alias cellWidth: controlView.cellWidth property alias cellHeight: controlView.cellHeight property alias model : controlView.model property alias delegate : controlView.delegate property alias contentY: controlView.contentY property alias currentIndex : controlView.currentIndex property alias count : controlView.count property alias cacheBuffer : controlView.cacheBuffer property alias flickable : controlView property alias contentHeight: _scrollView.contentHeight property alias contentWidth: _scrollView.contentWidth property int topMargin: margins property int bottomMargin: margins property int rightMargin: margins property int leftMargin: margins property int margins: 0 property alias holder : _holder property bool adaptContent: true property bool enableLassoSelection : false property alias lassoRec : selectLayer property alias pinchEnabled : _pinchArea.enabled + property int verticalScrollBarPolicy: ScrollBar.AlwaysOn + property int horizontalScrollBarPolicy: ScrollBar.AlwaysOff + signal itemsSelected(var indexes) signal areaClicked(var mouse) signal areaRightClicked() signal keyPress(var event) Kirigami.Theme.colorSet: Kirigami.Theme.View focus: true Keys.enabled : true Keys.forwardTo : controlView Kirigami.WheelHandler { id: wheelHandler target: control.flickable } ScrollView { id: _scrollView focus: true width: parent.width height: parent.height contentWidth: controlView.width contentHeight: controlView.contentHeight - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - + ScrollBar.horizontal.policy: control.horizontalScrollBarPolicy + ScrollBar.vertical.policy: control.verticalScrollBarPolicy + GridView { id: controlView anchors.fill: parent anchors.rightMargin: Kirigami.Settings.isMobile ? 0 : parent.ScrollBar.vertical.visible ? parent.ScrollBar.vertical.width : 0 anchors.leftMargin: control.leftMargin anchors.bottomMargin: control.bottomMargin anchors.topMargin: control.topMargin anchors.margins: control.margins //nasty trick property int size_ Component.onCompleted: { controlView.size_ = control.itemWidth } flow: GridView.FlowLeftToRight clip: control.clip focus: true // topMargin: control.margins // bottomMargin: control.margins // leftMargin: control.margins // rightMargin: control.margins // cellWidth: control.itemWidth cellHeight: control.itemHeight boundsBehavior: !Kirigami.Settings.isMobile? Flickable.StopAtBounds : Flickable.OvershootBounds flickableDirection: Flickable.AutoFlickDirection snapMode: GridView.NoSnap highlightMoveDuration: 0 interactive: Kirigami.Settings.hasTransientTouchInput onWidthChanged: if(adaptContent) control.adaptGrid() onCountChanged: if(adaptContent) control.adaptGrid() keyNavigationEnabled : true keyNavigationWraps : true Keys.onPressed: control.keyPress(event) Maui.Holder { id: _holder anchors.fill : parent } PinchArea { id: _pinchArea anchors.fill: parent z: -1 onPinchFinished: { resizeContent(pinch.scale) } } MouseArea { id: _mouseArea z: -1 anchors.fill: parent propagateComposedEvents: false preventStealing: true acceptedButtons: Qt.RightButton | Qt.LeftButton onClicked: { control.areaClicked(mouse) control.forceActiveFocus() if(mouse.button === Qt.RightButton) { control.areaRightClicked() return } } onWheel: { if (wheel.modifiers & Qt.ControlModifier) { if (wheel.angleDelta.y != 0) { var factor = 1 + wheel.angleDelta.y / 600; control.resizeContent(factor) } }else wheel.accepted = false } onPositionChanged: { if(_mouseArea.pressed && control.enableLassoSelection && selectLayer.visible) { if(mouseX >= selectLayer.newX) { selectLayer.width = (mouseX + 10) < (control.x + control.width) ? (mouseX - selectLayer.x) : selectLayer.width; } else { selectLayer.x = mouseX < control.x ? control.x : mouseX; selectLayer.width = selectLayer.newX - selectLayer.x; } if(mouseY >= selectLayer.newY) { selectLayer.height = (mouseY + 10) < (control.y + control.height) ? (mouseY - selectLayer.y) : selectLayer.height; if(!controlView.atYEnd && mouseY > (control.y + control.height)) controlView.contentY += 10 } else { selectLayer.y = mouseY < control.y ? control.y : mouseY; selectLayer.height = selectLayer.newY - selectLayer.y; if(!controlView.atYBeginning && selectLayer.y === 0) controlView.contentY -= 10 } } } onPressed: { if (mouse.source !== Qt.MouseEventNotSynthesized) { mouse.accepted = false } if(control.enableLassoSelection && mouse.button === Qt.LeftButton ) { selectLayer.visible = true; selectLayer.x = mouseX; selectLayer.y = mouseY; selectLayer.newX = mouseX; selectLayer.newY = mouseY; selectLayer.width = 0 selectLayer.height = 0; } } onReleased: { if(mouse.button !== Qt.LeftButton || !control.enableLassoSelection || !selectLayer.visible) { mouse.accepted = false return; } if(selectLayer.y > controlView.contentHeight) { return selectLayer.reset(); } var lassoIndexes = [] const limitX = mouse.x === lassoRec.x ? lassoRec.x+lassoRec.width : mouse.x const limitY = mouse.y === lassoRec.y ? lassoRec.y+lassoRec.height : mouse.y for(var i =lassoRec.x; i < limitX; i+=(lassoRec.width/(controlView.cellWidth* 0.5))) { for(var y = lassoRec.y; y < limitY; y+=(lassoRec.height/(controlView.cellHeight * 0.5))) { const index = controlView.indexAt(i,y+controlView.contentY) if(!lassoIndexes.includes(index) && index>-1 && index< controlView.count) lassoIndexes.push(index) } } control.itemsSelected(lassoIndexes) selectLayer.reset() } } Maui.Rectangle { id: selectLayer property int newX: 0 property int newY: 0 height: 0 width: 0 x: 0 y: 0 visible: false color: Qt.rgba(control.Kirigami.Theme.highlightColor.r,control.Kirigami.Theme.highlightColor.g, control.Kirigami.Theme.highlightColor.b, 0.2) opacity: 0.7 borderColor: control.Kirigami.Theme.highlightColor borderWidth: 2 solidBorder: false function reset() { selectLayer.x = 0; selectLayer.y = 0; selectLayer.newX = 0; selectLayer.newY = 0; selectLayer.visible = false; selectLayer.width = 0; selectLayer.height = 0; } } } } function resizeContent(factor) { const newSize= control.itemSize * factor if(newSize > control.itemSize) { control.itemSize = newSize } else { if(newSize >= Maui.Style.iconSizes.small) control.itemSize = newSize } } function adaptGrid() { var fullWidth = controlView.width var realAmount = parseInt(fullWidth / controlView.size_, 10) var amount = parseInt(fullWidth / control.cellWidth, 10) var leftSpace = parseInt(fullWidth - ( realAmount * controlView.size_ ), 10) var size = Math.min(amount, realAmount) >= control.count ? Math.max(control.cellWidth, control.itemSize) : parseInt((controlView.size_) + (parseInt(leftSpace/realAmount, 10)), 10) control.cellWidth = size } } diff --git a/src/controls/ToolBar.qml b/src/controls/ToolBar.qml index 9da8410..8a1796d 100644 --- a/src/controls/ToolBar.qml +++ b/src/controls/ToolBar.qml @@ -1,378 +1,376 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.13 import QtQuick.Controls 2.13 import org.kde.kirigami 2.9 as Kirigami import org.kde.mauikit 1.2 as Maui import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 import "private" ToolBar { id: control property int preferredHeight: Maui.Style.toolBarHeight implicitHeight: preferredHeight implicitWidth: mainFlickable.contentWidth spacing: Maui.Style.space.small padding: 0 default property alias content : leftRowContent.data // property alias stickyRightContent : rightRowContent.sticky // property alias stickyLeftContent : leftRowContent.sticky // property alias stickyMiddleContent : middleRowContent.sticky property bool forceCenterMiddleContent : true property alias leftContent : leftRowContent.data property alias middleContent : middleRowContent.data property alias rightContent : rightRowContent.data property alias farLeftContent : farLeftRowContent.data property alias farRightContent : farRightRowContent.data property alias middleLayout : middleRowContent property alias leftLayout : leftRowContent property alias rightLayout : rightRowContent property alias layout : layout readonly property alias fits : _scrollView.fits property int margins: Maui.Style.space.medium readonly property int count : leftContent.length + middleContent.length + rightContent.length + farLeftContent.length + farRightContent.length readonly property int visibleCount : leftRowContent.visibleChildren.length + middleRowContent.visibleChildren.length + rightRowContent.visibleChildren.length + farLeftRowContent.visibleChildren.length + farRightRowContent.visibleChildren.length property bool flickable: true property bool strech : true property bool leftSretch: strech property bool rightSretch: strech property bool middleStrech: strech - + MouseArea { id: _rightFlickRec width: Maui.Style.iconSizes.medium height: parent.height visible: !mainFlickable.atXEnd && !control.fits && control.flickable hoverEnabled: true anchors { top: parent.top bottom: parent.bottom right: parent.right } z: 999 EdgeShadow { visible: true parent: parent edge: Qt.RightEdge anchors { right: parent.right top: parent.top bottom: parent.bottom } opacity: 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } } Maui.Triangle { visible: !Kirigami.Settings.isMobile anchors.centerIn: parent rotation: -135 color: _rightFlickRec.hovered ? control.Kirigami.Theme.highlightColor : control.Kirigami.Theme.textColor width: Maui.Style.iconSizes.tiny height: width } enabled: !mainFlickable.atXEnd opacity: enabled ? 1 : 0.4 onClicked: { if(!mainFlickable.atXEnd) { mainFlickable.contentX += Math.min( mainFlickable.contentWidth - mainFlickable.contentX, mainFlickable.contentWidth) } if(mainFlickable.atXEnd) { mainFlickable.returnToBounds() } } } MouseArea { id: _leftFlickRec width: Maui.Style.iconSizes.medium height: parent.height visible: !mainFlickable.atXBeginning && !control.fits && control.flickable hoverEnabled: true anchors { top: parent.top bottom: parent.bottom left: parent.left } z: 999 EdgeShadow { visible: true parent: parent edge: Qt.LeftEdge anchors { left: parent.left top: parent.top bottom: parent.bottom } opacity: 1 Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } } Maui.Triangle { visible: !Kirigami.Settings.isMobile anchors.centerIn: parent rotation: 45 color: _leftFlickRec.hovered ? control.Kirigami.Theme.highlightColor : control.Kirigami.Theme.textColor width: Maui.Style.iconSizes.tiny height: width } enabled: !mainFlickable.atXBeginning opacity: enabled ? 1 : 0.4 onClicked: { if(!mainFlickable.atXBeginning) mainFlickable.contentX -= control.height if(mainFlickable.atXBeginning) mainFlickable.returnToBounds() } } Kirigami.WheelHandler { id: wheelHandler target: mainFlickable } - - Item - { - anchors.fill: parent - - TapHandler - { - grabPermissions: TapHandler.CanTakeOverFromAnything - onTapped: if (tapCount === 2) root.toggleMaximized() - gesturePolicy: TapHandler.DragThreshold - } - - DragHandler - { - grabPermissions: TapHandler.CanTakeOverFromAnything - onActiveChanged: if (active) { root.startSystemMove(); } - } - } + + Item + { + anchors.fill: parent + + DragHandler + { + grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything + onActiveChanged: if (active) { root.startSystemMove(); } + } + + TapHandler + { + grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything + onTapped: if (tapCount === 2) root.toggleMaximized() + gesturePolicy: TapHandler.DragThreshold + } + } ScrollView { id: _scrollView property bool fits : mainFlickable.contentWidth < control.width onFitsChanged: mainFlickable.returnToBounds() height: control.implicitHeight width: control.width contentWidth: mainFlickable.contentWidth contentHeight: height states: [State { when: control.position === ToolBar.Header AnchorChanges { target: _scrollView anchors.top: undefined anchors.bottom: parent.bottom } }, State { when: control.position === ToolBar.Footer AnchorChanges { target: _scrollView anchors.top: parent.top anchors.bottom: undefined } } ] ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ScrollBar.vertical.policy: ScrollBar.AlwaysOff /* ScrollBar.horizontal: ScrollBar {parent: _scrollView; visible: false;} * ScrollBar.vertical: ScrollBar {parent: _scrollView; visible: false} */ Flickable { id: mainFlickable anchors.fill: parent anchors.leftMargin: control.margins anchors.rightMargin: control.margins flickableDirection: Flickable.HorizontalFlick interactive: !fits && Maui.Handy.isTouch contentWidth: layout.implicitWidth boundsBehavior: Kirigami.Settings.isMobile ? Flickable.DragOverBounds : Flickable.StopAtBounds clip: true RowLayout { id: layout width: mainFlickable.width height: mainFlickable.height spacing: control.spacing RowLayout { id: _leftContent Layout.fillHeight: true Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft spacing: farLeftRowContent.visibleChildren.length > 0 ? control.spacing : 0 RowLayout { id: farLeftRowContent spacing: control.spacing Layout.fillHeight: true Layout.fillWidth: visibleChildren.length > 0 Layout.minimumWidth: visibleChildren.length > 0 ? implicitWidth : 0 Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft } RowLayout { id: leftRowContent spacing: control.spacing Layout.fillHeight: true Layout.fillWidth: visibleChildren.length > 0 Layout.minimumWidth: visibleChildren.length > 0 ? implicitWidth : 0 Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft } } Item //helper to force center middle content { visible: control.forceCenterMiddleContent && control.leftSretch Layout.minimumWidth: 0 Layout.fillWidth: visible Layout.maximumWidth: visible ? Math.max(_rightContent.implicitWidth - _leftContent.implicitWidth, 0) : 0 } RowLayout { id: middleRowContent Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter spacing: visibleChildren.length > 1 ? control.spacing : 0 Layout.fillHeight: true Layout.minimumWidth: visibleChildren.length > 0 ? implicitWidth : 0 Layout.fillWidth: visibleChildren.length > 0 } Item //helper to force center middle content { visible: control.forceCenterMiddleContent && control.rightSretch Layout.minimumWidth: 0 Layout.fillWidth: visible Layout.maximumWidth: visible ? Math.max(_leftContent.implicitWidth-_rightContent.implicitWidth, 0) : 0 } RowLayout { id: _rightContent Layout.fillHeight: true Layout.fillWidth: true spacing: farRightRowContent.visibleChildren.length > 0 ? control.spacing : 0 Layout.alignment: Qt.AlignVCenter | Qt.AlignRight RowLayout { id: rightRowContent spacing: visibleChildren.length > 1 ? control.spacing : 0 Layout.fillHeight: true Layout.fillWidth: visibleChildren.length > 0 Layout.minimumWidth: visibleChildren.length > 0 ? implicitWidth : 0 Layout.alignment: Qt.AlignVCenter | Qt.AlignRight } RowLayout { id: farRightRowContent spacing: visibleChildren.length > 1 ? control.spacing : 0 Layout.fillHeight: true Layout.fillWidth: visibleChildren.length > 0 Layout.minimumWidth: visibleChildren.length > 0 ? implicitWidth : 0 Layout.alignment: Qt.AlignVCenter | Qt.AlignRight } } } } - } + } - - } diff --git a/src/kde/mauikde.h b/src/kde/mauikde.h index dc965c2..9f9773f 100644 --- a/src/kde/mauikde.h +++ b/src/kde/mauikde.h @@ -1,65 +1,74 @@ /* * Copyright 2018 Camilo Higuita * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MAUIKDE_H #define MAUIKDE_H #include #include #include #include "fmh.h" class MAUIKDE : public QObject { Q_OBJECT public: static MAUIKDE *qmlAttachedProperties(QObject *object); static MAUIKDE *instance() { static MAUIKDE kde; return &kde; } MAUIKDE(const MAUIKDE &) = delete; MAUIKDE &operator=(const MAUIKDE &) = delete; MAUIKDE(MAUIKDE &&) = delete; MAUIKDE &operator=(MAUIKDE &&) = delete; static FMH::MODEL_LIST getApps(); static FMH::MODEL_LIST getApps(const QString &groupStr); - static void launchApp(const QString &app); private: MAUIKDE(QObject *parent = nullptr); public slots: static QVariantList services(const QUrl &url); static QVariantList devices(); static bool sendToDevice(const QString &device, const QString &id, const QStringList &urls); static void openWithApp(const QString &exec, const QStringList &urls); static void attachEmail(const QStringList &urls); static void email(const QString &to = "", const QString &cc = "", const QString &bcc = "", const QString &subject = "", const QString &body = "", const QString &messageFile = "", const QStringList &urls = QStringList()); static void setColorScheme(const QString &schemeName, const QString &bg = QString(), const QString &fg = QString()); + + static QVariantList appsList() + { + return FMH::toMapList(getApps()); + } + static QVariantList appsList(const QString &groupStr) + { + return FMH::toMapList(getApps(groupStr)); + } + static void launchApp(const QString &app); }; QML_DECLARE_TYPEINFO(MAUIKDE, QML_HAS_ATTACHED_PROPERTIES) #endif // MAUIKDE_H