diff --git a/src/controls/Dialog.qml b/src/controls/Dialog.qml index f72c5f9..72d512d 100644 --- a/src/controls/Dialog.qml +++ b/src/controls/Dialog.qml @@ -1,279 +1,278 @@ /* * 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.5 import QtQuick.Controls 2.10 import QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami import QtGraphicalEffects 1.0 Maui.Popup { id: control property string message : "" property string title: "" property string acceptText: "Yes" property string rejectText: "No" property bool defaultButtons: true property bool confirmationDialog: false default property alias content : _pageContent.data property alias acceptButton : _acceptButton property alias rejectButton : _rejectButton property alias textEntry : _textEntry property alias entryField: _textEntry.visible property alias page : _page property alias footBar : _page.footBar property alias headBar: _page.headBar property alias closeButton: _closeButton signal accepted() signal rejected() clip: false closePolicy: Popup.NoAutoClose | Popup.CloseOnEscape maxWidth: Maui.Style.unit * 300 - maxHeight: (_pageContent.implicitHeight * 1.2) + ( _page.footBar.height + _defaultButtonsLayout.implicitHeight ) + Maui.Style.space.huge + _page.padding + maxHeight: (_pageContent.implicitHeight * 1.2) + ( _page.footBar.height + _defaultButtonsLayout.implicitHeight ) + Maui.Style.space.huge + _page.margins widthHint: 0.9 heightHint: 0.9 Maui.Badge { id: _closeButton color: hovered || pressed ? Kirigami.Theme.negativeTextColor : Kirigami.Theme.backgroundColor property int position : Maui.App.leftWindowControls.includes("X") ? Qt.AlignLeft : Qt.AlignRight Maui.X { height: Maui.Style.iconSizes.tiny width: height anchors.centerIn: parent color: Kirigami.Theme.textColor } border.color: Kirigami.Theme.textColor anchors { verticalCenter: parent.top horizontalCenter: _closeButton.position === Qt.AlignLeft ? parent.left : parent.right horizontalCenterOffset: control.width === control.parent.width ? _closeButton.width : 0 } z: control.z+999 onClicked: close() } ColumnLayout { anchors.fill: parent spacing: 0 Maui.Page { id: _page Layout.fillWidth: true Layout.fillHeight: true footBar.visible: footBar.count > 1 headBar.visible: headBar.count > 1 + padding: 0 ColumnLayout { id: _pageContent anchors.fill: parent spacing: Maui.Style.space.medium Label { visible: title.length > 0 Layout.fillWidth: true Layout.alignment: Qt.AlignCenter color: Kirigami.Theme.textColor text: title font.weight: Font.Thin font.bold: true font.pointSize:Maui.Style.fontSizes.huge elide: Qt.ElideRight wrapMode: Text.Wrap } Kirigami.ScrollablePage { id: _scrollable visible: message.length > 0 Layout.preferredHeight: Math.min(_scrollable.contentHeight, 500) Layout.fillWidth: true Layout.alignment: Qt.AlignCenter Kirigami.Theme.backgroundColor: "transparent" padding: 0 leftPadding: padding rightPadding: padding topPadding: padding bottomPadding: padding Label { id: body width: parent.width padding: 0 text: message textFormat : TextEdit.AutoText color: Kirigami.Theme.textColor font.pointSize:Maui.Style.fontSizes.default wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere elide: Text.ElideLeft verticalAlignment: Qt.AlignVCenter } } Maui.TextField { id: _textEntry visible: false Layout.fillWidth: true Layout.alignment: Qt.AlignCenter focus: visible onAccepted: control.accepted() } - - } /* * layer.enabled: control.background.radius * layer.samples: 4 * layer.effect: OpacityMask * { * maskSource: Item * { * width: _page.width * height: _page.height * * Rectangle * { * anchors.centerIn: parent * width: _page.width * height: _page.height * radius: control.background.radius } } }*/ } Kirigami.Separator { Layout.fillWidth: true } RowLayout { id: _defaultButtonsLayout spacing: 0 Layout.fillWidth: true Layout.preferredHeight: Maui.Style.toolBarHeightAlt - Maui.Style.space.medium Layout.maximumHeight: Maui.Style.toolBarHeightAlt - Maui.Style.space.medium visible: defaultButtons Button { Layout.fillWidth: true Layout.fillHeight: true id: _rejectButton text: control.rejectText background: Rectangle { color: _rejectButton.hovered || _rejectButton.down || _rejectButton.pressed ? "#da4453" : Kirigami.Theme.backgroundColor } contentItem: Label { text: _rejectButton.text color: _rejectButton.hovered || _rejectButton.down || _rejectButton.pressed ? "#fafafa" : Kirigami.Theme.textColor horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter } /*property color color : Kirigami.Theme.negativeBackgroundColor * property alias text : _rejectLabel.text * * Rectangle * { * anchors.fill: parent * color: _rejectButton.color * Kirigami.Theme.textColor: Kirigami.Theme.negativeTextColor * Label * { * id: _rejectLabel * anchors.fill: parent * anchors.margins: Maui.Style.space.small * text: _rejectButton.text * color: "#fafafa" } } */ onClicked: rejected() } Kirigami.Separator { Layout.fillHeight: true } Button { Layout.fillWidth: true Layout.fillHeight: true text: acceptText id: _acceptButton background: Rectangle { color: _acceptButton.hovered || _acceptButton.down || _acceptButton.pressed ? "#26c6da" : Kirigami.Theme.backgroundColor } contentItem: Label { text: _acceptButton.text color: _acceptButton.hovered || _acceptButton.down || _acceptButton.pressed ? "#fafafa" : Kirigami.Theme.textColor horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter } onClicked: accepted() } } } } diff --git a/src/controls/labs/AltBrowser.qml b/src/controls/labs/AltBrowser.qml index 74fdee4..ab7cc86 100644 --- a/src/controls/labs/AltBrowser.qml +++ b/src/controls/labs/AltBrowser.qml @@ -1,126 +1,128 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.3 import org.kde.kirigami 2.7 as Kirigami import org.kde.mauikit 1.0 as Maui Maui.Page { id: control readonly property alias currentView : viewLoader.item enum ViewType { Grid, List } property int viewType: AltBrowser.ViewType.List property int currentIndex : -1 property Component listDelegate : null property Component gridDelegate : null property var model : null property bool enableLassoSelection: false property alias holder : _holder readonly property alias gridView : private_.gridView readonly property alias listView : private_.listView + flickable: viewLoader.item ? viewLoader.item.flickable : null + QtObject { //before loading the view we use a dummy representation of the possible views, in order to store the properties data. Once the actual view has been loaded then the exposed properties are changed from the dummy representation to the actual view loaded, this allows to preserve and use the bindings for the actual view. The dummy representations are within a private object and exposed as readonly properties to avoid those being changed externally id: private_ property Maui.GridView gridView : Maui.GridView { id: _dummyGridView } property Maui.ListBrowser listView : Maui.ListBrowser { id: _dummyListBrowser } } Loader { id: viewLoader anchors.fill: parent focus: true sourceComponent: switch(control.viewType) { case AltBrowser.ViewType.Grid: return gridViewComponent case AltBrowser.ViewType.List: return listViewComponent } onLoaded: { if(control.currentView) { switch(control.viewType) { case AltBrowser.ViewType.Grid: { private_.gridView = control.currentView private_.listView = _dummyListBrowser break } case AltBrowser.ViewType.List: { private_.listView = control.currentView private_.gridView = _dummyGridView break } } } } } Maui.Holder { id: _holder anchors.fill: parent } Component { id: gridViewComponent Maui.GridView { currentIndex: control.currentIndex model: control.model delegate: control.gridDelegate enableLassoSelection: control.enableLassoSelection cellHeight: _dummyGridView.cellHeight cellWidth: _dummyGridView.cellWidth itemSize: _dummyGridView.itemSize margins: _dummyGridView.margins topMargin: _dummyGridView.topMargin adaptContent: true } } Component { id: listViewComponent Maui.ListBrowser { currentIndex: control.currentIndex model: control.model delegate: control.listDelegate enableLassoSelection: control.enableLassoSelection itemSize: _dummyListBrowser.itemSize // section: _dummyListBrowser.section margins: _dummyListBrowser.margins spacing: _dummyListBrowser.spacing topMargin: _dummyListBrowser.topMargin } } } diff --git a/src/controls/labs/Page.qml b/src/controls/labs/Page.qml index b1f6971..64e0cc8 100644 --- a/src/controls/labs/Page.qml +++ b/src/controls/labs/Page.qml @@ -1,554 +1,554 @@ /* * Copyright 2019 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 QtQuick.Layouts 1.3 import org.kde.mauikit 1.0 as Maui import org.kde.kirigami 2.7 as Kirigami import QtQuick.Layouts 1.3 import QtGraphicalEffects 1.0 Pane { id: control focus: true padding: 0 leftPadding: control.padding rightPadding: control.padding topPadding: control.padding bottomPadding: control.padding default property alias content: _content.data property alias headerBackground : _headerBackground readonly property alias internalHeight : _content.height property Flickable flickable : null property int footerPositioning : Kirigami.Settings.isMobile && flickable ? ListView.PullBackHeader : ListView.InlineFooter property int headerPositioning : Kirigami.Settings.isMobile && flickable ? ListView.PullBackHeader : ListView.InlineHeader property string title property int margins: 0 property int leftMargin : margins property int rightMargin: margins property int topMargin: margins property int bottomMargin: margins property bool altHeader : false property bool autoHideHeader : false - onAutoHideHeaderChanged: header.opacity = 1 - property bool floatingHeader : false + + property bool floatingHeader : control.flickable ? !control.flickable.atYBeginning : false property bool showTitle : true Kirigami.Theme.colorSet: Kirigami.Theme.View signal goBackTriggered() signal goForwardTriggered() background: Rectangle { color: Kirigami.Theme.backgroundColor } onFlickableChanged: returnToBounds() Connections { target: control.flickable ? control.flickable : null enabled: control.flickable && ((control.header && control.headerPositioning === ListView.PullBackHeader) || (control.footer && control.footerPositioning === ListView.PullBackFooter)) property int oldContentY property bool updatingContentY: false onContentYChanged: { _headerAnimation.enabled = false if(!control.flickable.dragging && control.flickable.atYBeginning) { control.returnToBounds() } if (updatingContentY || !control.flickable || !control.flickable.dragging) { oldContentY = control.flickable.contentY; return; //TODO: merge //if moves but not dragging, just update oldContentY } if(control.flickable.contentHeight < control.height) { return } var oldFHeight var oldHHeight if (control.footer && control.footerPositioning === ListView.PullBackFooter) { oldFHeight = control.footer.height control.footer.height = Math.max(0, Math.min(control.footer.implicitHeight, control.footer.height + oldContentY - control.flickable.contentY)); } if (control.header && control.headerPositioning === ListView.PullBackHeader) { oldHHeight = control.header.height control.header.height = Math.max(0, Math.min(control.header.implicitHeight, control.header.height + oldContentY - control.flickable.contentY)); } //if the implicitHeight is changed, use that to simulate scroll if ((control.footer && oldFHeight !== control.footer.height) || ( control.header && oldHHeight !== control.header.height)) { updatingContentY = true if(control.header && oldHHeight !== control.header.height) control.flickable.contentY -= (oldHHeight - control.header.height) updatingContentY = false } else { oldContentY = control.flickable.contentY } } onMovementEnded: { _headerAnimation.enabled = true if (control.headerPositioning === ListView.PullBackHeader && control.header) { if (control.header.height >= (control.header.implicitHeight/2) || control.flickable.atYBeginning ) { control.header.height = control.header.implicitHeight } else { control.header.height = 0 } } if (control.footerPositioning === ListView.PullBackFooter && control.footer) { if (control.footer.height >= (control.footer.implicitHeight/2) || control.flickable.atYEnd) { if(control.flickable.atYEnd) { control.footer.height = control.footer.implicitHeight control.flickable.contentY = control.flickable.contentHeight - control.flickable.height oldContentY = control.flickable.contentY }else { control.footer.height = control.footer.implicitHeight } } else { control.footer.height = 0 } } } } property alias headBar : _headBar property alias footBar: _footBar property Item header : Maui.ToolBar { id: _headBar width: visible ? parent.width : 0 height: visible ? implicitHeight : 0 Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.Window /** to not break the visible binding just check the count state of the header and act upon it **/ readonly property bool hide : visibleCount === 0 onHideChanged: { if(hide) { pullBackHeader() }else { pullDownHeader() } } Behavior on height { id: _headerAnimation enabled: false NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } // Label // { // id: _counterLabel // text: _headBar.visibleCount + " - " + _headBar.count // color: "yellow" // visible: _headBar.visibleCount > 0 // } Behavior on opacity { NumberAnimation { duration: Kirigami.Units.longDuration easing.type: Easing.InOutQuad } } Component { id: _titleComponent Label { text: control.title elide : Text.ElideRight font.bold : false font.weight: Font.Bold color : Kirigami.Theme.textColor font.pointSize: Maui.Style.fontSizes.big horizontalAlignment : Text.AlignHCenter verticalAlignment : Text.AlignVCenter } } middleContent: Loader { visible: item Layout.fillWidth: sourceComponent === _titleComponent Layout.fillHeight: sourceComponent === _titleComponent sourceComponent: control.title && control.showTitle ? _titleComponent : null } background: Rectangle { id: _headerBackground color: _headBar.Kirigami.Theme.backgroundColor Kirigami.Separator { id: _border opacity: 0.6 color: Qt.darker(parent.color, 2) anchors.left: parent.left anchors.right: parent.right } Kirigami.Separator { id: _border2 opacity: 0.4 color: Qt.lighter(parent.color, 2.5) anchors.left: parent.left anchors.right: parent.right anchors.bottomMargin: 1 } FastBlur { anchors.fill: parent visible: control.floatingHeader && !altHeader opacity: 0.2 transparentBorder: false source: ShaderEffectSource { // cullMode: ShaderEffect.FrontFaceCulling // hideSource: true samples : 0 recursive: true sourceItem: _content sourceRect: Qt.rect(0, 0-control.topMargin, headBar.width, headBar.height) // textureSize: Qt.size(headBar.width,headBar.height) } radius: 64 } } } property Item footer : Maui.ToolBar { id: _footBar visible: _footBar.visibleCount > 0 position: ToolBar.Footer width: visible ? parent.width : 0 height: visible ? implicitHeight : 0 } Item { id: _headerContent anchors.left: parent.left anchors.right: parent.right height: header && header.visible ? header.height : 0 data: header - z: _content.z+1 + z: _content.z+9999 } states: [ State { when: !altHeader AnchorChanges { target: _headerContent anchors.top: parent.top anchors.bottom: undefined } AnchorChanges { target: _border anchors.top: undefined anchors.bottom: parent.bottom } AnchorChanges { target: _border2 anchors.top: undefined anchors.bottom: parent.bottom } PropertyChanges { target: _layout anchors.topMargin: control.floatingHeader ? 0 : _headerContent.height anchors.bottomMargin: 0 } PropertyChanges { target: _headBar position: ToolBar.Header } }, State { when: altHeader AnchorChanges { target: _headerContent anchors.top: undefined anchors.bottom: parent.bottom } AnchorChanges { target: _border anchors.top: parent.top anchors.bottom: undefined } AnchorChanges { target: _border2 anchors.top: parent.top anchors.bottom: undefined } PropertyChanges { target: _layout anchors.topMargin: 0 anchors.bottomMargin: _headerContent.height } PropertyChanges { target: _headBar position: ToolBar.Footer } } ] // transitions: Transition { // // smoothly reanchor myRect and move into new position // AnchorAnimation { duration: 1000 } // } ColumnLayout { id: _layout anchors.fill: parent spacing: 0 Item { id: _content Layout.fillHeight: true Layout.fillWidth: true Layout.margins: control.margins Layout.leftMargin: control.leftMargin Layout.rightMargin: control.rightMargin Layout.topMargin: control.topMargin Layout.bottomMargin: control.bottomMargin } Item { id: _footerContent Layout.fillWidth: true Layout.preferredHeight: footer && footer.visible ? footer.height : 0 data: footer ? [footer] : [] } } Timer { id: _timer interval: 1000 onTriggered: { if(control.autoHideHeader) { pullBackHeader() } stop() } } Item { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: control.height * 0.1 z: _content.z + 9999 visible: control.autoHideHeader && !control.altHeader && !Kirigami.Settings.isMobile HoverHandler { target: parent acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus onHoveredChanged: { if(!control.autoHideHeader) { return } if(!hovered) { _timer.start() }else { pullDownHeader() _timer.stop() } } } } // Item // { // anchors.fill: parent // anchors.topMargin: header.height // anchors.bottomMargin: footer.height // z: _content.z + 9999 // // TapHandler // { // target: parent // enabled: control.autoHideHeader && !control.altHeader // // grabPermissions: PointerHandler.TakeOverForbidden | PointerHandler.ApprovesTakeOverByHandlersOfSameType | PointerHandler.CanTakeOverFromAnything // // onSingleTapped: // { // if(!control.autoHideHeader) // { // return // } // console.log("Pgae tapped") // header.visible = !header.visible // } // } // } Keys.onBackPressed: { control.goBackTriggered(); } Shortcut { sequence: "Forward" onActivated: control.goForwardTriggered(); } Shortcut { sequence: StandardKey.Forward onActivated: control.goForwardTriggered(); } Shortcut { sequence: StandardKey.Back onActivated: control.goBackTriggered(); } function returnToBounds() { if(control.header) { control.header.height = control.header.implicitHeight } if(control.footer) { control.footer.height = control.footer.implicitHeight } } function pullBackHeader() { _headerAnimation.enabled = true header.height= 0 } function pullDownHeader() { _headerAnimation.enabled = true header.height= header.implicitHeight } }