diff --git a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml index fcbc594f..5b4a6c8a 100644 --- a/examples/gallerydata/contents/ui/gallery/MiscGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/MiscGallery.qml @@ -1,207 +1,211 @@ /* * Copyright 2016 Aleix Pol Gonzalez * * 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 Library 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.6 import QtQuick.Controls 2.1 as Controls import QtQuick.Layouts 1.2 import org.kde.kirigami 2.2 ScrollablePage { id: page title: "Misc controls" actions { main: Action { icon { name: "document-edit" color: Theme.negativeTextColor } text: "Main Action Text" } left: Action { icon { name: "go-previous" color: Theme.positiveTextColor } text: "Left Action Text" onTriggered: { showPassiveNotification("Left action triggered") } } right: Action { icon { name: "go-next" color: Theme.neutralTextColor } text: "Right Action Text" onTriggered: { showPassiveNotification("Right action triggered") } } contextualActions: [ Action { text:"Action for buttons" icon { name: "bookmarks" color: Theme.activeTextColor } onTriggered: showPassiveNotification("Action 1 clicked") }, Action { text:"Disabled Action" icon.name: "folder" enabled: false }, Action { text: "Action for Sheet" visible: sheet.sheetOpen } ] } header: Controls.ToolBar { RowLayout { anchors.verticalCenter: parent.verticalCenter Controls.ToolButton { text: "ToolButton" } Controls.ToolButton { text: "Menu" onClicked: menu.open(); Controls.Menu { id: menu y: parent.height Controls.MenuItem { checkable: true text: "Item1" } Controls.MenuItem { text: "Item2" } } } } } footer: Rectangle { color: Theme.backgroundColor height: Units.gridUnit * 3 Controls.TextField { topPadding: 0 bottomPadding: 0 leftPadding: Units.smallSpacing rightPadding: Units.smallSpacing anchors.fill: parent } Separator { anchors { top: parent.top left: parent.left right: parent.right } } } Controls.Dialog { id: dialog modal: true focus: true x: (page.width - width) / 2 y: page.height / 2 - height width: Math.min(page.width - Units.gridUnit * 4, Units.gridUnit * 20) standardButtons: Controls.Dialog.Ok title: "Title" Controls.Label { width: dialog.availableWidth text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id risus id augue euismod accumsan. Nunc vestibulum placerat bibendum. Morbi commodo auctor varius. Donec molestie euismod ultrices. Sed facilisis augue nec eros auctor." wrapMode: Label.Wrap } } ColumnLayout { anchors.centerIn: parent Controls.Button { Layout.alignment: Qt.AlignHCenter text: "Dialog" onClicked: dialog.open() } Controls.Dial { Layout.alignment: Qt.AlignHCenter } Controls.SpinBox { editable: true Layout.alignment: Qt.AlignHCenter } Controls.ComboBox { model: ["First", "Second", "Third"] Layout.alignment: Qt.AlignHCenter } Controls.GroupBox { title: "Title" Layout.alignment: Qt.AlignHCenter ColumnLayout { id: options Controls.RadioButton { text: "First" checked: true } Controls.RadioButton { text: "Second" checked: false } Controls.RadioButton { text: "Third" checked: false } } } Label { Layout.alignment: Qt.AlignHCenter - text: Settings.isMobile ? "We are in mobile device mode" : "We are in Desktop mode" + text: Settings.isMobile ? "We are in mobile device mode" : "We not in mobile mode" + } + Label { + Layout.alignment: Qt.AlignHCenter + text: Settings.isMobile ? "We are in tablet mode" : "We are not in tablet mode" } Column { Layout.alignment: Qt.AlignHCenter Controls.ItemDelegate { width: 300 text: "Delegate1" } Controls.ItemDelegate { width: 300 text: "Delegate2" } Controls.CheckDelegate { width: 300 text: "Delegate3" } Controls.SwitchDelegate { width: 300 text: "Delegate4" } Controls.RadioDelegate { width: 300 text: "Delegate5" } } } } diff --git a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml index 70a77c2c..d0317423 100644 --- a/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml +++ b/examples/gallerydata/contents/ui/gallery/TextFieldGallery.qml @@ -1,84 +1,80 @@ /* * Copyright 2015 Marco Martin * * 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 Library 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.0 import QtQuick.Controls 2.0 as Controls import QtQuick.Layouts 1.2 import org.kde.kirigami 2.3 as Kirigami Kirigami.ScrollablePage { id: page Layout.fillWidth: true implicitWidth: applicationWindow().width title: "Text fields" ColumnLayout { Kirigami.FormLayout { Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true width: page.width spacing: Units.smallSpacing Controls.TextField { placeholderText: "Search..." Kirigami.FormData.label: "Placeholder text:" } Controls.TextField { text: "Disabled" enabled: false Kirigami.FormData.label: "Disabled field:" } Controls.TextField { echoMode: TextInput.Password Kirigami.FormData.label: "Password:" } Controls.TextField { inputMask: "99999999" inputMethodHints: Qt.ImhDigitsOnly Kirigami.FormData.label: "Numbers:" } } Controls.Label { text: "Text area:" } - //this to make text selection work on Android - //QQC2 should do this by itself - MouseArea { + + Controls.TextArea { + id: field Layout.fillWidth: true - drag.filterChildren: Settings.isMobile - implicitHeight: field.implicitHeight + text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eu nisl ac nibh malesuada pretium ut sit amet libero. Nulla libero arcu, pharetra a dignissim nec, iaculis sit amet metus. Suspendisse quis justo efficitur, pharetra dui maximus, aliquam dolor. Vestibulum vel imperdiet turpis. Mauris ut leo mauris. Praesent ut libero sollicitudin, tincidunt nisi a, efficitur erat. Curabitur lacinia leo et tempor aliquam." + Layout.minimumWidth: Kirigami.Units.gridUnit * 12 + Layout.minimumHeight: Kirigami.Units.gridUnit * 12 + wrapMode: Controls.TextArea.WordWrap + //this to make text selection work on Android + //QQC2 should do this by itself onPressAndHold: { - field.forceActiveFocus(); - field.cursorPosition = field.positionAt(mouse.x, mouse.y); - field.selectWord(); - } - Controls.TextArea { - id: field - anchors.fill: parent - text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent eu nisl ac nibh malesuada pretium ut sit amet libero. Nulla libero arcu, pharetra a dignissim nec, iaculis sit amet metus. Suspendisse quis justo efficitur, pharetra dui maximus, aliquam dolor. Vestibulum vel imperdiet turpis. Mauris ut leo mauris. Praesent ut libero sollicitudin, tincidunt nisi a, efficitur erat. Curabitur lacinia leo et tempor aliquam." - Layout.minimumWidth: Kirigami.Units.gridUnit * 12 - Layout.minimumHeight: Kirigami.Units.gridUnit * 12 - wrapMode: Controls.TextArea.WordWrap + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); } } } } diff --git a/src/controls/BasicListItem.qml b/src/controls/BasicListItem.qml index 8b8ef01f..0c81fef5 100644 --- a/src/controls/BasicListItem.qml +++ b/src/controls/BasicListItem.qml @@ -1,82 +1,82 @@ /* * Copyright 2010 Marco Martin * * 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 Library 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 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 as QQC2 import org.kde.kirigami 2.2 /** * An item delegate for the primitive ListView component. * * It's intended to make all listviews look coherent. * It has a default icon and a label * */ AbstractListItem { id: listItem /** * string: bool * A single text label the list item will contain */ property alias label: listItem.text /** * icon: var * A single icon that will be displayed in the list item. * The icon can be a grouped property with name,size,color etc, as QtQuickControls2 icons are defined. * The icon can also be either a QIcon, a string name of a fdo compatible name, * or any url accepted by the Image element. */ property var icon /** * reserveSpaceForIcon: bool * If true, even when there is no icon the space will be reserved for it * It's useful in layouts where only some entries have an icon, * having the text all horizontally aligned */ property alias reserveSpaceForIcon: iconItem.visible default property alias _basicDefault: layout.children RowLayout { id: layout spacing: Units.smallSpacing*2 - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) Icon { id: iconItem source: listItem.icon && listItem.icon.hasOwnProperty && listItem.icon.hasOwnProperty("name") ? listItem.icon.name : listItem.icon Layout.minimumHeight: Units.iconSizes.smallMedium Layout.maximumHeight: Layout.minimumHeight Layout.minimumWidth: height selected: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || listItem.pressed) color: listItem.icon && listItem.icon.color && listItem.icon.color.a > 0 ? listItem.icon.color : Qt.rgba(0, 0, 0, 0) } QQC2.Label { id: labelItem text: listItem.text Layout.fillWidth: true color: layout.indicateActiveFocus && (listItem.highlighted || listItem.checked || listItem.pressed) ? listItem.activeTextColor : listItem.textColor elide: Text.ElideRight font: listItem.font } } } diff --git a/src/controls/private/ActionButton.qml b/src/controls/private/ActionButton.qml index e75267ef..bba237e7 100644 --- a/src/controls/private/ActionButton.qml +++ b/src/controls/private/ActionButton.qml @@ -1,471 +1,471 @@ /* * Copyright 2015 Marco Martin * * 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 Library 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.1 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 as Controls import QtGraphicalEffects 1.0 import org.kde.kirigami 2.2 import "../templates/private" Item { id: root Theme.colorSet: Theme.Button Theme.inherit: false anchors { left: parent.left right: parent.right bottom: parent.bottom bottomMargin: root.page.footer ? root.page.footer.height : 0 } //smallSpacing for the shadow height: button.height + Units.smallSpacing clip: true readonly property Page page: root.parent.page //either Action or QAction should work here readonly property QtObject action: root.page && root.page.mainAction && root.page.mainAction.enabled ? root.page.mainAction : null readonly property QtObject leftAction: root.page && root.page.leftAction && root.page.leftAction.enabled ? root.page.leftAction : null readonly property QtObject rightAction: root.page && root.page.rightAction && root.page.rightAction.enabled ? root.page.rightAction : null readonly property bool hasApplicationWindow: typeof applicationWindow !== "undefined" && applicationWindow readonly property bool hasGlobalDrawer: typeof globalDrawer !== "undefined" && globalDrawer readonly property bool hasContextDrawer: typeof contextDrawer !== "undefined" && contextDrawer transform: Translate { id: translateTransform y: mouseArea.internalVisibility ? 0 : button.height Behavior on y { NumberAnimation { duration: Units.longDuration easing.type: mouseArea.internalVisibility == true ? Easing.InQuad : Easing.OutQuad } } } onWidthChanged: button.x = root.width/2 - button.width/2 Item { id: button x: root.width/2 - button.width/2 anchors { bottom: parent.bottom bottomMargin: Units.smallSpacing } implicitWidth: implicitHeight + Units.iconSizes.smallMedium*2 + Units.gridUnit implicitHeight: Units.iconSizes.medium + Units.largeSpacing * 2 onXChanged: { if (mouseArea.pressed || edgeMouseArea.pressed || fakeContextMenuButton.pressed) { if (root.hasGlobalDrawer && globalDrawer.enabled && globalDrawer.modal) { globalDrawer.peeking = true; globalDrawer.visible = true; globalDrawer.position = Math.min(1, Math.max(0, (x - root.width/2 + button.width/2)/globalDrawer.contentItem.width + mouseArea.drawerShowAdjust)); } if (root.hasContextDrawer && contextDrawer.enabled && contextDrawer.modal) { contextDrawer.peeking = true; contextDrawer.visible = true; contextDrawer.position = Math.min(1, Math.max(0, (root.width/2 - button.width/2 - x)/contextDrawer.contentItem.width + mouseArea.drawerShowAdjust)); } } } MouseArea { id: mouseArea anchors.fill: parent visible: action != null || leftAction != null || rightAction != null property bool internalVisibility: (!root.hasApplicationWindow || (applicationWindow().controlsVisible && applicationWindow().height > root.height*2)) && (root.action === null || root.action.visible === undefined || root.action.visible) preventStealing: true drag { target: button //filterChildren: true axis: Drag.XAxis minimumX: root.hasContextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: root.hasGlobalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } property var downTimestamp; property int startX property int startMouseY property real drawerShowAdjust readonly property int currentThird: (3*mouseX)/width readonly property QtObject actionUnderMouse: { switch(currentThird) { case 0: return leftAction; case 1: return action; case 2: return rightAction; default: return null } } hoverEnabled: true - Controls.ToolTip.visible: containsMouse && !Settings.isMobile && actionUnderMouse + Controls.ToolTip.visible: containsMouse && !Settings.tabletMode && actionUnderMouse Controls.ToolTip.text: actionUnderMouse ? actionUnderMouse.text : "" Controls.ToolTip.delay: Units.toolTipDelay onPressed: { //search if we have a page to set to current if (root.hasApplicationWindow && applicationWindow().pageStack.currentIndex !== undefined && root.page.parent.level !== undefined) { //search the button parent's parent, that is the page parent //this will make the context drawer open for the proper page applicationWindow().pageStack.currentIndex = root.page.parent.level; } downTimestamp = (new Date()).getTime(); startX = button.x + button.width/2; startMouseY = mouse.y; drawerShowAdjust = 0; } onReleased: { if (root.hasGlobalDrawer) globalDrawer.peeking = false; if (root.hasContextDrawer) contextDrawer.peeking = false; //pixel/second var x = button.x + button.width/2; var speed = ((x - startX) / ((new Date()).getTime() - downTimestamp) * 1000); drawerShowAdjust = 0; //project where it would be a full second in the future if (root.hasContextDrawer && root.hasGlobalDrawer && globalDrawer.modal && x + speed > Math.min(root.width/4*3, root.width/2 + globalDrawer.contentItem.width/2)) { globalDrawer.open(); contextDrawer.close(); } else if (root.hasContextDrawer && x + speed < Math.max(root.width/4, root.width/2 - contextDrawer.contentItem.width/2)) { if (root.hasContextDrawer && contextDrawer.modal) { contextDrawer.open(); } if (root.hasGlobalDrawer && globalDrawer.modal) { globalDrawer.close(); } } else { if (root.hasGlobalDrawer && globalDrawer.modal) { globalDrawer.close(); } if (root.hasContextDrawer && contextDrawer.modal) { contextDrawer.close(); } } //Don't rely on native onClicked, but fake it here: //Qt.startDragDistance is not adapted to devices dpi in case //of Android, so consider the button "clicked" when: //*the button has been dragged less than a gridunit //*the finger is still on the button if (Math.abs((button.x + button.width/2) - startX) < Units.gridUnit && mouse.y > 0) { if (!actionUnderMouse) { return; } //if an action has been assigned, trigger it if (actionUnderMouse && actionUnderMouse.trigger) { actionUnderMouse.trigger(); } } } onPositionChanged: { drawerShowAdjust = Math.min(0.3, Math.max(0, (startMouseY - mouse.y)/(Units.gridUnit*15))); button.xChanged(); } onPressAndHold: { if (!actionUnderMouse) { return; } //if an action has been assigned, show a message like a tooltip - if (actionUnderMouse && actionUnderMouse.text && Settings.isMobile) { + if (actionUnderMouse && actionUnderMouse.text && Settings.tabletMode) { Controls.ToolTip.show(actionUnderMouse.text, 3000) } } Connections { target: root.hasGlobalDrawer ? globalDrawer : null onPositionChanged: { if ( globalDrawer && globalDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) { button.x = globalDrawer.contentItem.width * globalDrawer.position + root.width/2 - button.width/2; } } } Connections { target: root.hasContextDrawer ? globalDrawer : null onPositionChanged: { if (contextDrawer && contextDrawer.modal && !mouseArea.pressed && !edgeMouseArea.pressed && !fakeContextMenuButton.pressed) { button.x = root.width/2 - button.width/2 - contextDrawer.contentItem.width * contextDrawer.position; } } } Item { id: background anchors { fill: parent } Rectangle { id: buttonGraphics radius: width/2 anchors.centerIn: parent height: parent.height - Units.smallSpacing*2 width: height visible: root.action readonly property bool pressed: root.action && ((root.action == mouseArea.actionUnderMouse && mouseArea.pressed) || root.action.checked) property color baseColor: root.action && root.action.icon && root.action.icon.color && root.action.icon.color != undefined && root.action.icon.color.a > 0 ? root.action.icon.color : Theme.highlightColor color: pressed ? Qt.darker(baseColor, 1.3) : baseColor Icon { id: icon anchors.centerIn: parent width: Units.iconSizes.smallMedium height: width source: root.action && root.action.iconName ? root.action.iconName : "" selected: true } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Behavior on x { NumberAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } //left button Rectangle { id: leftButtonGraphics z: -1 anchors { left: parent.left //verticalCenter: parent.verticalCenter bottom: parent.bottom bottomMargin: Units.smallSpacing } radius: Units.devicePixelRatio*2 height: Units.iconSizes.smallMedium + Units.smallSpacing * 2 width: height + (root.action ? Units.gridUnit*2 : 0) visible: root.leftAction readonly property bool pressed: root.leftAction && ((mouseArea.actionUnderMouse == root.leftAction && mouseArea.pressed) || root.leftAction.checked) property color baseColor: root.leftAction && root.leftAction.icon && root.leftAction.icon.color && root.leftAction.icon.color != undefined && root.leftAction.icon.color.a > 0 ? root.leftAction.icon.color : Theme.highlightColor color: pressed ? baseColor : Theme.backgroundColor Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Icon { source: root.leftAction && root.leftAction.iconName ? root.leftAction.iconName : "" width: Units.iconSizes.smallMedium height: width selected: leftButtonGraphics.pressed anchors { left: parent.left verticalCenter: parent.verticalCenter margins: Units.smallSpacing * 2 } } } //right button Rectangle { id: rightButtonGraphics z: -1 anchors { right: parent.right //verticalCenter: parent.verticalCenter bottom: parent.bottom bottomMargin: Units.smallSpacing } radius: Units.devicePixelRatio*2 height: Units.iconSizes.smallMedium + Units.smallSpacing * 2 width: height + (root.action ? Units.gridUnit*2 : 0) visible: root.rightAction readonly property bool pressed: root.rightAction && ((mouseArea.actionUnderMouse == root.rightAction && mouseArea.pressed) || root.rightAction.checked) property color baseColor: root.rightAction && root.rightAction.icon && root.rightAction.icon.color && root.rightAction.icon.color != undefined && root.rightAction.icon.color.a > 0 ? root.rightAction.icon.color : Theme.highlightColor color: pressed ? baseColor : Theme.backgroundColor Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } Icon { source: root.rightAction && root.rightAction.iconName ? root.rightAction.iconName : "" width: Units.iconSizes.smallMedium height: width selected: rightButtonGraphics.pressed anchors { right: parent.right verticalCenter: parent.verticalCenter margins: Units.smallSpacing * 2 } } } } DropShadow { anchors.fill: background horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, mouseArea.pressed ? 0.6 : 0.4) source: background } } } MouseArea { id: fakeContextMenuButton anchors { right: edgeMouseArea.right bottom: edgeMouseArea.bottom } drag { target: button axis: Drag.XAxis minimumX: root.hasContextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: root.hasGlobalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } visible: root.page.actions && root.page.actions.contextualActions.length > 0 && (applicationWindow === undefined || applicationWindow().wideScreen) //using internal pagerow api && (root.page && root.page.parent ? root.page.parent.level < applicationWindow().pageStack.depth-1 : false) width: Units.iconSizes.medium + Units.smallSpacing*2 height: width Item { anchors { fill:parent margins: -Units.gridUnit } DropShadow { anchors.fill: handleGraphics horizontalOffset: 0 verticalOffset: Units.devicePixelRatio radius: Units.gridUnit /2 samples: 16 color: Qt.rgba(0, 0, 0, fakeContextMenuButton.pressed ? 0.6 : 0.4) source: handleGraphics } Rectangle { id: handleGraphics anchors.centerIn: parent color: fakeContextMenuButton.pressed ? Theme.highlightColor : Theme.backgroundColor width: Units.iconSizes.smallMedium + Units.smallSpacing * 2 height: width radius: Units.devicePixelRatio Icon { anchors.centerIn: parent width: Units.iconSizes.smallMedium selected: fakeContextMenuButton.pressed height: width source: "overflow-menu" } Behavior on color { ColorAnimation { duration: Units.longDuration easing.type: Easing.InOutQuad } } } } onPressed: { mouseArea.onPressed(mouse) } onReleased: { if (globalDrawer) { globalDrawer.peeking = false; } if (contextDrawer) { contextDrawer.peeking = false; } var pos = root.mapFromItem(fakeContextMenuButton, mouse.x, mouse.y); if (contextDrawer) { if (pos.x < root.width/2) { contextDrawer.open(); } else if (contextDrawer.drawerOpen && mouse.x > 0 && mouse.x < width) { contextDrawer.close(); } } if (globalDrawer) { if (globalDrawer.position > 0.5) { globalDrawer.open(); } else { globalDrawer.close(); } } if (containsMouse && (!globalDrawer || !globalDrawer.drawerOpen || !globalDrawer.modal) && (!contextDrawer || !contextDrawer.drawerOpen || !contextDrawer.modal)) { contextMenu.visible = !contextMenu.visible; } } Controls.Menu { id: contextMenu x: parent.width - width y: -height Repeater { model: root.page.actions.contextualActions delegate: BasicListItem { text: model.text icon: model.iconName backgroundColor: "transparent" visible: model.visible enabled: modelData.enabled checkable: modelData.checkable checked: modelData.checked separatorVisible: false onClicked: { modelData.trigger(); contextMenu.visible = false; } } } } } MouseArea { id: edgeMouseArea z:99 anchors { left: parent.left right: parent.right bottom: parent.bottom } drag { target: button //filterChildren: true axis: Drag.XAxis minimumX: root.hasContextDrawer && contextDrawer.enabled && contextDrawer.modal ? 0 : root.width/2 - button.width/2 maximumX: root.hasGlobalDrawer && globalDrawer.enabled && globalDrawer.modal ? root.width : root.width/2 - button.width/2 } height: Units.smallSpacing * 3 onPressed: mouseArea.onPressed(mouse) onPositionChanged: mouseArea.positionChanged(mouse) onReleased: mouseArea.released(mouse) } } diff --git a/src/controls/private/DefaultListItemBackground.qml b/src/controls/private/DefaultListItemBackground.qml index 6194772a..92a3d97f 100644 --- a/src/controls/private/DefaultListItemBackground.qml +++ b/src/controls/private/DefaultListItemBackground.qml @@ -1,59 +1,59 @@ /* * Copyright 2016 Marco Martin * * 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 Library 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.1 import org.kde.kirigami 2.2 Rectangle { id: background color: listItem.checked || listItem.highlighted || (listItem.supportsMouseEvents && listItem.pressed && !listItem.checked && !listItem.sectionDelegate) ? listItem.activeBackgroundColor : listItem.backgroundColor visible: listItem.ListView.view ? listItem.ListView.view.highlight === null : true Rectangle { id: internal - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (listItem.ListView.view ? listItem.ListView.view.activeFocus : false) anchors.fill: parent - visible: !Settings.isMobile && listItem.supportsMouseEvents + visible: !Settings.tabletMode && listItem.supportsMouseEvents color: listItem.activeBackgroundColor opacity: (listItem.hovered || listItem.highlighted) && !listItem.pressed ? (indicateActiveFocus ? 0.2 : 0.1 ) : 0 Behavior on opacity { NumberAnimation { duration: Units.longDuration } } } Behavior on color { ColorAnimation { duration: Units.longDuration } } readonly property bool _firstElement: typeof(index) !== "undefined" && index == 0 on_FirstElementChanged: { if (_firstElement) { var newObject = Qt.createQmlObject('import QtQuick 2.0; import org.kde.kirigami 2.2; Separator {anchors {left: parent.left; right: parent.right; bottom: parent.top} visible: listItem.separatorVisible}', background); } } Separator { anchors { left: parent.left right: parent.right bottom: parent.bottom } visible: listItem.separatorVisible } } diff --git a/src/controls/templates/AbstractCard.qml b/src/controls/templates/AbstractCard.qml index 36dec49e..2cfa887d 100644 --- a/src/controls/templates/AbstractCard.qml +++ b/src/controls/templates/AbstractCard.qml @@ -1,165 +1,165 @@ /* * Copyright 2018 Marco Martin * * 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 Library 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.6 import QtQuick.Layouts 1.2 import QtQuick.Templates 2.0 as T import org.kde.kirigami 2.3 as Kirigami /** * A AbstractCard is the base for cards. A Card is a visual object that serves * as an entry point for more detailed information. An abstractCard is empty, * providing just the look and the base properties and signals for an ItemDelegate. * It can be filled with any custom layout of items, its content is organized * in 3 properties: header, contentItem and footer. * Use this only when you need particular custom contents, for a standard layout * for cards, use the Card component. * * @see Card * @inherits QtQuick.Templates.ItemDelegate * @since 2.4 */ T.ItemDelegate { id: root /** * header: Item * This item serves as header, it will be put either on top if headerOrientation * is Qt.Vertical(default) or on the left if it's Qt.Horizontal */ property Item header /** * headerOrientation: Qt.Orientation * If Qt.Vertical the header will be positioned on top(default), * if Qt.Horizontal will be positioned on the left (or right if an RTL layout is used) */ property int headerOrientation: Qt.Vertical /** * footer: Item * This item serves as footer, and it will be positioned at the bottom of the card. */ property Item footer /** * showClickFeedback: bool * if true, when clicking or tapping on the card area, the card will be colored * to show a visual click feedback. * Use this if you want to do an action in the onClicked signal handler of the card. */ property bool showClickFeedback: false Layout.fillWidth: true implicitWidth: Math.max(background.implicitWidth, mainLayout.implicitWidth) + leftPadding + rightPadding implicitHeight: mainLayout.implicitHeight + topPadding + bottomPadding - hoverEnabled: !Kirigami.Settings.isMobile && showClickFeedback + hoverEnabled: !Kirigami.Settings.tabletMode && showClickFeedback //if it's in a CardLayout, try to expand horizontal cards to both columns Layout.columnSpan: headerOrientation == Qt.Horizontal && parent.hasOwnProperty("columns") ? parent.columns : 1 Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.View topPadding: Kirigami.Units.largeSpacing leftPadding: Kirigami.Units.largeSpacing bottomPadding: Kirigami.Units.largeSpacing rightPadding: Kirigami.Units.largeSpacing GridLayout { id: mainLayout rowSpacing: root.topPadding columnSpacing: root.leftPadding anchors { top: parent.top left: parent.left right: parent.right leftMargin: root.leftPadding topMargin: root.topPadding rightMargin: root.rightPadding //never anchor bottom, to not have binding loops } columns: headerOrientation == Qt.Vertical ? 1 : 2 function preferredHeight(item) { if (!item) { return 0; } if (item.Layout.preferredHeight > 0) { return item.Layout.preferredHeight; } return item.implicitHeight } Item { id: headerParent Layout.fillWidth: true Layout.fillHeight: root.headerOrientation == Qt.Horizontal Layout.rowSpan: root.headerOrientation == Qt.Vertical ? 1 : 2 Layout.preferredWidth: header ? header.implicitWidth : 0 Layout.preferredHeight: root.headerOrientation == Qt.Vertical ? mainLayout.preferredHeight(header) : -1 } Item { id: contentItemParent Layout.fillWidth: true Layout.preferredWidth: contentItem ? contentItem.implicitWidth : 0 Layout.preferredHeight: mainLayout.preferredHeight(contentItem) } Item { id: footerParent Layout.fillWidth: true Layout.preferredWidth: footer ? footer.implicitWidth : 0 Layout.preferredHeight: mainLayout.preferredHeight(footer) } } //BEGIN signal handlers onContentItemChanged: { if (!contentItem) { return; } contentItem.parent = contentItemParent; contentItem.anchors.fill = contentItemParent; } onHeaderChanged: { if (!header) { return; } header.parent = headerParent; header.anchors.fill = headerParent; } onFooterChanged: { if (!footer) { return; } //make the footer always looking it's at the bottom of the card footer.parent = footerParent; footer.anchors.left = footerParent.left; footer.anchors.top = footerParent.top; footer.anchors.right = footerParent.right; footer.anchors.topMargin = Qt.binding(function() {return (root.height - root.bottomPadding - root.topPadding) - (footerParent.y + footerParent.height)}); } Component.onCompleted: { contentItemChanged(); } //END signal handlers } diff --git a/src/controls/templates/AbstractListItem.qml b/src/controls/templates/AbstractListItem.qml index a18260f1..ad3a3e80 100644 --- a/src/controls/templates/AbstractListItem.qml +++ b/src/controls/templates/AbstractListItem.qml @@ -1,128 +1,128 @@ /* * Copyright 2010 Marco Martin * * 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 Library 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 2.010-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.0 import org.kde.kirigami 2.2 import QtQuick.Templates 2.0 as T2 /** * An item delegate for the primitive ListView component. * * It's intended to make all listviews look coherent. * * @inherit QtQuick.Templates.ItemDelegate */ T2.ItemDelegate { id: listItem /** * supportsMouseEvents: bool * Holds if the item emits signals related to mouse interaction. *TODO: remove * The default value is false. */ property bool supportsMouseEvents: hoverEnabled /** * containsMouse: bool * True when the user hovers the mouse over the list item * NOTE: on mobile touch devices this will be true only when pressed is also true * TODO: remove? */ property alias containsMouse: listItem.hovered /** * sectionDelegate: bool * If true the item will be a delegate for a section, so will look like a * "title" for the items under it. */ property bool sectionDelegate: false /** * separatorVisible: bool * True if the separator between items is visible * default: true */ property bool separatorVisible: true /** * textColor: color * Color for the text in the item * It is advised to leave the default value (Theme.textColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color property will have to be manually bound with this property */ property color textColor: Theme.textColor /** * backgroundColor: color * Color for the background of the item * It is advised to leave the default value (Theme.viewBackgroundColor) */ property color backgroundColor: "transparent" /** * activeTextColor: color * Color for the text in the item when pressed or selected * It is advised to leave the default value (Theme.highlightedTextColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color property will have to be manually bound with this property */ property color activeTextColor: Theme.highlightedTextColor /** * activeBackgroundColor: color * Color for the background of the item when pressed or selected * It is advised to leave the default value (Theme.highlightColor) */ property color activeBackgroundColor: Theme.highlightColor default property alias _default: listItem.contentItem Theme.colorGroup: internal.indicateActiveFocus ? Theme.Active : Theme.Inactive leftPadding: LayoutMirroring.enabled && internal.view && internal.view.T2.ScrollBar.vertical ? internal.view.T2.ScrollBar.vertical.width : Units.largeSpacing topPadding: Units.largeSpacing rightPadding: !LayoutMirroring.enabled && internal.view && internal.view.T2.ScrollBar.vertical ? internal.view.T2.ScrollBar.vertical.width : Units.largeSpacing bottomPadding: Units.largeSpacing implicitWidth: contentItem ? contentItem.implicitWidth : Units.gridUnit * 12 implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 5 width: parent ? parent.width : implicitWidth Layout.fillWidth: true opacity: enabled ? 1 : 0.6 height: visible ? implicitHeight : 0 hoverEnabled: true QtObject { id: internal property Flickable view: listItem.ListView.view || (listItem.parent ? listItem.parent.ListView.view : null) - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (view ? view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (view ? view.activeFocus : false) } Accessible.role: Accessible.ListItem } diff --git a/src/controls/templates/SwipeListItem.qml b/src/controls/templates/SwipeListItem.qml index ebee63e3..9a7a1eef 100644 --- a/src/controls/templates/SwipeListItem.qml +++ b/src/controls/templates/SwipeListItem.qml @@ -1,380 +1,380 @@ /* * Copyright 2010 Marco Martin * * 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 Library 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 2.010-1301, USA. */ import QtQuick 2.7 import QtQuick.Layouts 1.2 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.4 import "../private" import QtQuick.Templates 2.0 as T2 /** * An item delegate Intended to support extra actions obtainable * by uncovering them by dragging away the item with the handle * This acts as a container for normal list items. * Any subclass of AbstractListItem can be assigned as the contentItem property. * @code * ListView { * model: myModel * delegate: SwipeListItem { * QQC2.Label { * text: model.text * } * actions: [ * Action { * iconName: "document-decrypt" * onTriggered: print("Action 1 clicked") * }, * Action { * iconName: model.action2Icon * onTriggered: //do something * } * ] * } * * } * @endcode * * @inherit QtQuick.Templates.ItemDelegate */ T2.ItemDelegate { id: listItem //BEGIN properties /** * supportsMouseEvents: bool * Holds if the item emits signals related to mouse interaction. *TODO: remove * The default value is false. */ property alias supportsMouseEvents: listItem.hoverEnabled /** * containsMouse: bool * True when the user hover the mouse over the list item * NOTE: on mobile touch devices this will be true only when pressed is also true */ property alias containsMouse: listItem.hovered /** * sectionDelegate: bool * If true the item will be a delegate for a section, so will look like a * "title" for the items under it. */ property bool sectionDelegate: false /** * separatorVisible: bool * True if the separator between items is visible * default: true */ property bool separatorVisible: true /** * actions: list * Defines the actions for the list item: at most 4 buttons will * contain the actions for the item, that can be revealed by * sliding away the list item. */ property list actions /** * textColor: color * Color for the text in the item * * Note: if custom text elements are inserted in an AbstractListItem, * their color property will have to be manually bound with this property */ property color textColor: Theme.textColor /** * backgroundColor: color * Color for the background of the item */ property color backgroundColor: Theme.backgroundColor /** * activeTextColor: color * Color for the text in the item when pressed or selected * It is advised to leave the default value (Theme.highlightedTextColor) * * Note: if custom text elements are inserted in an AbstractListItem, * their color property will have to be manually bound with this property */ property color activeTextColor: Theme.highlightedTextColor /** * activeBackgroundColor: color * Color for the background of the item when pressed or selected * It is advised to leave the default value (Theme.highlightColor) */ property color activeBackgroundColor: Theme.highlightColor default property alias _default: listItem.contentItem Theme.colorGroup: behindItem.indicateActiveFocus ? Theme.Active : Theme.Inactive hoverEnabled: true implicitWidth: contentItem ? contentItem.implicitWidth : Units.gridUnit * 12 width: parent ? parent.width : implicitWidth implicitHeight: contentItem.implicitHeight + Units.smallSpacing * 5 leftPadding: Units.smallSpacing * 2 + (LayoutMirroring.enabled ? (handleMouse.visible ? handleMouse.width : 0) + handleMouse.anchors.rightMargin : 0) topPadding: Units.smallSpacing * 2 rightPadding: Units.smallSpacing * 2 + (LayoutMirroring.enabled ? 0 : (handleMouse.visible ? handleMouse.width : 0) + handleMouse.anchors.rightMargin) bottomPadding: Units.smallSpacing * 2 //END properties Item { id: behindItem parent: listItem z: -1 //TODO: a global "open" state enabled: background.x !== 0 - property bool indicateActiveFocus: listItem.pressed || Settings.isMobile || listItem.activeFocus || (view ? view.activeFocus : false) + property bool indicateActiveFocus: listItem.pressed || Settings.tabletMode || listItem.activeFocus || (view ? view.activeFocus : false) property Flickable view: listItem.ListView.view || listItem.parent.ListView.view anchors { fill: parent } Rectangle { id: shadowHolder color: Qt.darker(Theme.backgroundColor, 1.05); anchors.fill: parent } EdgeShadow { edge: Qt.TopEdge anchors { right: parent.right left: parent.left top: parent.top } } EdgeShadow { edge: LayoutMirroring.enabled ? Qt.RightEdge : Qt.LeftEdge x: LayoutMirroring.enabled ? listItem.background.x - width : (listItem.background.x + listItem.background.width) anchors { top: parent.top bottom: parent.bottom } } MouseArea { anchors.fill: parent preventStealing: true enabled: background.x != 0 onClicked: { positionAnimation.from = background.x; positionAnimation.to = 0; positionAnimation.running = true; } } Row { id: actionsLayout z: 1 - parent: Settings.isMobile ? behindItem : listItem - opacity: Settings.isMobile ? 1 : (listItem.hovered ? 1 : 0) + parent: Settings.tabletMode ? behindItem : listItem + opacity: Settings.tabletMode ? 1 : (listItem.hovered ? 1 : 0) Behavior on opacity { OpacityAnimator { duration: Units.longDuration easing.type: Easing.InOutQuad } } anchors { right: parent.right verticalCenter: parent.verticalCenter rightMargin: LayoutMirroring.enabled ? listItem.leftPadding : listItem.rightPadding } height: Math.min( parent.height / 1.5, Units.iconSizes.medium) width: childrenRect.width property bool exclusive: false property Item checkedButton spacing: Units.largeSpacing Repeater { model: { if (listItem.actions.length == 0) { return null; } else { return listItem.actions[0].text !== undefined && listItem.actions[0].trigger !== undefined ? listItem.actions : listItem.actions[0]; } } delegate: Icon { height: actionsLayout.height width: height source: modelData.iconName enabled: (modelData && modelData.enabled !== undefined) ? modelData.enabled : true; visible: (modelData && modelData.visible !== undefined) ? modelData.visible : true; MouseArea { id: actionMouse anchors { fill: parent; - margins: Settings.isMobile ? -Units.smallSpacing : 0; + margins: Settings.tabletMode ? -Units.smallSpacing : 0; } enabled: (modelData && modelData.enabled !== undefined) ? modelData.enabled : true; - hoverEnabled: !Settings.isMobile + hoverEnabled: !Settings.tabletMode onClicked: { if (modelData && modelData.trigger !== undefined) { modelData.trigger(); } positionAnimation.from = background.x; positionAnimation.to = 0; positionAnimation.running = true; } Controls.ToolTip.delay: 1000 Controls.ToolTip.timeout: 5000 - Controls.ToolTip.visible: (Settings.isMobile ? actionMouse.pressed : actionMouse.containsMouse) && Controls.ToolTip.text.length > 0 + Controls.ToolTip.visible: (Settings.tabletMode ? actionMouse.pressed : actionMouse.containsMouse) && Controls.ToolTip.text.length > 0 Controls.ToolTip.text: modelData.tooltip || modelData.text } } } } } MouseArea { id: handleMouse parent: listItem.background - visible: Settings.isMobile + visible: Settings.tabletMode z: 99 anchors { right: parent.right top: parent.top bottom: parent.bottom rightMargin: behindItem.view && behindItem.view.T2.ScrollBar && behindItem.view.T2.ScrollBar.vertical && behindItem.view.T2.ScrollBar.vertical.interactive ? behindItem.view.T2.ScrollBar.vertical.width : Units.smallSpacing } preventStealing: true width: height property var downTimestamp; property int startX property int startMouseX onClicked: { positionAnimation.from = background.x; if (listItem.background.x > -listItem.background.width/2) { positionAnimation.to = (LayoutMirroring.enabled ? -1 : +1) * (-listItem.width + height + handleMouse.anchors.rightMargin); } else { positionAnimation.to = 0; } positionAnimation.running = true; } onPressed: { downTimestamp = (new Date()).getTime(); startX = listItem.background.x; startMouseX = mouse.x; } onPositionChanged: { if (LayoutMirroring.enabled) { listItem.background.x = Math.max(0, Math.min(listItem.width - height, listItem.background.x - (startMouseX - mouse.x))); } else { listItem.background.x = Math.min(0, Math.max(-listItem.width + height, listItem.background.x - (startMouseX - mouse.x))); } } onReleased: { var speed = ((startX - listItem.background.x) / ((new Date()).getTime() - downTimestamp) * 1000); if (LayoutMirroring.enabled) { speed = -speed; } if (Math.abs(speed) < Units.gridUnit) { return; } if (speed > listItem.width/2) { positionAnimation.to = (LayoutMirroring.enabled ? -1 : +1) * (-listItem.width + height + handleMouse.anchors.rightMargin); } else { positionAnimation.to = 0; } positionAnimation.from = background.x; positionAnimation.running = true; } Icon { id: handleIcon anchors.verticalCenter: parent.verticalCenter selected: listItem.checked || (listItem.pressed && !listItem.checked && !listItem.sectionDelegate) width: Units.iconSizes.smallMedium height: width x: y source: (LayoutMirroring.enabled ? (listItem.background.x < listItem.background.width/2 ? "handle-right" : "handle-left") : (listItem.background.x < -listItem.background.width/2 ? "handle-right" : "handle-left")) } } NumberAnimation { id: positionAnimation property: "x" target: background duration: Units.longDuration easing.type: Easing.InOutQuad } //BEGIN signal handlers onContentItemChanged: { if (!contentItem) { return; } contentItem.parent = background; contentItem.anchors.top = background.top; contentItem.anchors.left = background.left; contentItem.anchors.right = background.right; contentItem.anchors.leftMargin = Qt.binding(function() {return listItem.leftPadding}); contentItem.anchors.rightMargin = Qt.binding(function() {return listItem.rightPadding}); contentItem.anchors.topMargin = Qt.binding(function() {return listItem.topPadding}); contentItem.z = 0; } Component.onCompleted: { //this will happen only once - if (Settings.isMobile && !swipeFilterConnection.swipeFilterItem) { + if (Settings.tabletMode && !swipeFilterConnection.swipeFilterItem) { var component = Qt.createComponent(Qt.resolvedUrl("../private/SwipeItemEventFilter.qml")); behindItem.view.parent.parent._swipeFilter = component.createObject(behindItem.view.parent.parent); } listItem.contentItemChanged(); } Connections { target: Settings onIsMobileChanged: { - if (Settings.isMobile) { + if (Settings.tabletMode) { if (!swipeFilterConnection.swipeFilterItem) { var component = Qt.createComponent(Qt.resolvedUrl("../private/SwipeItemEventFilter.qml")); listItem.ListView.view.parent.parent._swipeFilter = component.createObject(listItem.ListView.view.parent.parent); } } else { if (listItem.ListView.view.parent.parent._swipeFilter) { listItem.ListView.view.parent.parent._swipeFilter.destroy(); } } } } Connections { id: swipeFilterConnection readonly property QtObject swipeFilterItem: (behindItem.view && behindItem.view && behindItem.view.parent && behindItem.view.parent.parent) ? behindItem.view.parent.parent._swipeFilter : null readonly property bool enabled: swipeFilterItem ? swipeFilterItem.currentItem === listItem : false target: enabled ? swipeFilterItem : null onPeekChanged: listItem.background.x = -(listItem.background.width - listItem.background.height) * swipeFilterItem.peek onCurrentItemChanged: { if (!enabled) { positionAnimation.to = 0; positionAnimation.from = background.x; positionAnimation.running = true; } } } //END signal handlers Accessible.role: Accessible.ListItem } diff --git a/src/controls/templates/private/ScrollView.qml b/src/controls/templates/private/ScrollView.qml index 75522fcd..eed87c26 100644 --- a/src/controls/templates/private/ScrollView.qml +++ b/src/controls/templates/private/ScrollView.qml @@ -1,200 +1,200 @@ /* * Copyright 2016 Marco Martin * * 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 Library 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.0 import org.kde.kirigami 2.2 MouseArea { id: root default property Item contentItem property Flickable flickableItem //TODO: horizontalScrollBarPolicy is completely noop just for compatibility right now property int horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff property int verticalScrollBarPolicy: Qt.ScrollBarAsNeeded readonly property Item verticalScrollBar: flickableItem.ScrollBar.vertical ? flickableItem.ScrollBar.vertical : null onVerticalScrollBarPolicyChanged: { if (flickableItem.ScrollBar.vertical) { flickableItem.ScrollBar.vertical.visible = verticalScrollBarPolicy != Qt.ScrollBarAlwaysOff; } scrollBarCreationTimer.restart(); } onHorizontalScrollBarPolicyChanged: { if (flickableItem.ScrollBar.horizontal) { flickableItem.ScrollBar.horizontal.visible = horizontalScrollBarPolicy != Qt.ScrollBarAlwaysOff; } scrollBarCreationTimer.restart(); } - drag.filterChildren: !Settings.isMobile + drag.filterChildren: !Settings.tabletMode onPressed: { - if (Settings.isMobile) { + if (Settings.tabletMode) { return; } mouse.accepted = false; flickableItem.interactive = true; } onReleased: { - if (Settings.isMobile) { + if (Settings.tabletMode) { return; } mouse.accepted = false; flickableItem.interactive = false; } onWheel: { - if (Settings.isMobile || flickableItem.contentHeight 0) { y = flickableItem.height; } else if (y < 0) { y = -flickableItem.height; } } var minYExtent = flickableItem.topMargin - flickableItem.originY; var maxYExtent = flickableItem.height - (flickableItem.contentHeight + flickableItem.bottomMargin + flickableItem.originY); flickableItem.contentY = Math.min(-maxYExtent, Math.max(-minYExtent, flickableItem.contentY - y)); //this is just for making the scrollbar appear flickableItem.flick(0, 0); flickableItem.cancelFlick(); } Connections { target: flickableItem - enabled: !Settings.isMobile + enabled: !Settings.tabletMode onFlickEnded: flickableItem.interactive = false; onMovementEnded: flickableItem.interactive = false; } onContentItemChanged: { if (contentItem.hasOwnProperty("contentY")) { flickableItem = contentItem; if (typeof(flickableItem.keyNavigationEnabled) != "undefined") { flickableItem.keyNavigationEnabled = true; flickableItem.keyNavigationWraps = true; } contentItem.parent = flickableParent; } else { flickableItem = flickableComponent.createObject(flickableParent); contentItem.parent = flickableItem.contentItem; } //TODO: find a way to make flicking work on laptops with touch screen - flickableItem.interactive = Settings.isMobile; + flickableItem.interactive = Settings.tabletMode; flickableItem.anchors.fill = flickableParent; scrollBarCreationTimer.restart(); } Timer { id: scrollBarCreationTimer interval: 0 onTriggered: { //create or destroy the vertical scrollbar if ((!flickableItem.ScrollBar.vertical) && verticalScrollBarPolicy != Qt.ScrollBarAlwaysOff) { flickableItem.ScrollBar.vertical = verticalScrollComponent.createObject(root); } else if (flickableItem.ScrollBar.vertical && verticalScrollBarPolicy == Qt.ScrollBarAlwaysOff) { flickableItem.ScrollBar.vertical.destroy(); } //create or destroy the horizontal scrollbar if ((!flickableItem.ScrollBar.horizontal) && horizontalScrollBarPolicy != Qt.ScrollBarAlwaysOff) { flickableItem.ScrollBar.horizontal = horizontalScrollComponent.createObject(root); } else if (flickableItem.ScrollBar.horizontal && horizontalScrollBarPolicy == Qt.ScrollBarAlwaysOff) { flickableItem.ScrollBar.horizontal.destroy(); } } } MultiPointTouchArea { id: flickableParent anchors { fill: parent } clip: true mouseEnabled: false maximumTouchPoints: 1 property bool touchPressed: false onPressed: { touchPressed = true; flickableItem.interactive = true; } onReleased: touchPressed = false; onCanceled: touchPressed = false; } Component { id: flickableComponent Flickable { anchors { fill: parent } contentWidth: root.contentItem ? root.contentItem.width : 0 contentHeight: root.contentItem ? root.contentItem.height : 0 } } Component { id: verticalScrollComponent ScrollBar { z: flickableParent.z + 1 visible: root.contentItem.visible && size < 1 - interactive: !Settings.isMobile + interactive: !Settings.tabletMode //NOTE: use this instead of anchors as crashes on some Qt 5.8 checkouts height: parent.height - anchors.topMargin anchors { topMargin: parent.flickableItem.headerItem ? parent.flickableItem.headerItem.height : 0 right: parent.right top: parent.top } } } Component { id: horizontalScrollComponent ScrollBar { z: flickableParent.z + 1 visible: root.contentItem.visible && size < 1 - interactive: !Settings.isMobile + interactive: !Settings.tabletMode //NOTE: use this instead of anchors as crashes on some Qt 5.8 checkouts height: parent.height - anchors.topMargin anchors { left: parent.left right: parent.right bottom: parent.bottom } } } }