8import QtQuick.Controls as QQC2
10import QtQuick.Templates as T
11import org.kde.kirigami as Kirigami
139 property color
textColor: Kirigami.Theme.textColor
161 readonly
property bool actionsVisible: actionsLayout.hasVisibleActions
178 property list<T.Action>
actions
188 readonly
property alias
overlayWidth: overlayLoader.width
192 property ListView listView;
194 LayoutMirroring.childrenInherit:
true
197 implicitWidth: contentItem ? implicitContentWidth : Kirigami.Units.gridUnit * 12
198 width: parent ? parent.width : implicitWidth
199 implicitHeight: Math.max(Kirigami.Units.gridUnit * 2, implicitContentHeight) + topPadding + bottomPadding
201 padding: !listItem.alwaysVisibleActions && Kirigami.Settings.tabletMode ? Kirigami.Units.largeSpacing : Kirigami.Units.smallSpacing
203 leftPadding: padding * 2 + (mirrored ? overlayLoader.paddingOffset : 0)
204 rightPadding: padding * 2 + (mirrored ? 0 : overlayLoader.paddingOffset)
207 bottomPadding: padding
209 Keys.onTabPressed: (event) => {
210 if (actionsLayout.hasVisibleActions) {
211 actionsLayout.children[0].tabbedFromDelegate = true
212 actionsLayout.children[0].forceActiveFocus(Qt.TabFocusReason)
214 event.accepted = false
218 Keys.onPressed: (event) => {
219 if ((actionsLayout.hasVisibleActions && activeFocus && event.key ==
Qt.Key_Right &&
Qt.application.layoutDirection ==
Qt.LeftToRight) ||
220 (actionsLayout.hasVisibleActions && activeFocus && event.key ==
Qt.Key_Left &&
Qt.application.layoutDirection ==
Qt.RightToLeft)) {
221 for (var target = 0; target < actionsRep.count; target ++) {
222 if (actionsLayout.children[target].visible) {
226 if (target < actionsRep.count) {
227 actionsLayout.children[target].forceActiveFocus(
Qt.TabFocusReason)
228 event.accepted =
true
236 property Flickable view: listItem.ListView.view || (listItem.parent ? (listItem.parent.ListView.view || (listItem.parent instanceof Flickable ? listItem.parent : null)) : null)
238 function viewHasPropertySwipeFilter():
bool {
239 return view && view.parent && view.parent.parent &&
"_swipeFilter" in view.parent.parent;
242 readonly
property QtObject swipeFilterItem: (viewHasPropertySwipeFilter() && view.parent.parent._swipeFilter) ? view.parent.parent._swipeFilter : null
244 readonly property bool edgeEnabled: swipeFilterItem ? swipeFilterItem.currentItem === listItem || swipeFilterItem.currentItem === listItem.parent : false
248 if (listItem.alwaysVisibleActions || !Kirigami.Settings.tabletMode) {
251 if (viewHasPropertySwipeFilter() && Kirigami.Settings.tabletMode && !internal.view.parent.parent._swipeFilter) {
252 const component =
Qt.createComponent(
Qt.resolvedUrl(
"../private/SwipeItemEventFilter.qml"));
253 internal.view.parent.parent._swipeFilter = component.createObject(internal.view.parent.parent);
260 target: Kirigami.Settings
261 function onTabletModeChanged() {
262 if (!internal.viewHasPropertySwipeFilter()) {
265 if (Kirigami.Settings.tabletMode) {
266 if (!internal.swipeFilterItem) {
267 const component =
Qt.createComponent(
Qt.resolvedUrl(
"../private/SwipeItemEventFilter.qml"));
268 listItem.ListView.view.parent.parent._swipeFilter = component.createObject(listItem.ListView.view.parent.parent);
272 if (listItem.ListView.view.parent.parent._swipeFilter) {
273 listItem.ListView.view.parent.parent._swipeFilter.destroy();
284 readonly
property int paddingOffset: (visible ? width : 0) + Kirigami.Units.smallSpacing
285 readonly property var theAlias: anchors
286 function validate(want, defaultValue) {
287 const expectedLeftPadding = () => listItem.padding * 2 + (listItem.mirrored ? overlayLoader.paddingOffset : 0)
288 const expectedRightPadding = () => listItem.padding * 2 + (listItem.mirrored ? 0 : overlayLoader.paddingOffset)
291 `Don
't override the leftPadding or rightPadding on a SwipeListItem!\n` +
292 `This makes it impossible for me to adjust my layout as I need to for various usecases.\n` +
293 `I'll
try to fix the mistake
for you, but you should
remove your overrides from your app
's code entirely.\n` +
294 `If I can't fix the paddings, I
'll fall back to a default layout, but it'll be slightly incorrect and lacks\n` +
295 `adaptations needed
for touch screens and
right-to-
left languages, among other things.`
297 if (listItem.leftPadding != expectedLeftPadding() || listItem.rightPadding != expectedRightPadding()) {
298 listItem.leftPadding =
Qt.binding(expectedLeftPadding)
299 listItem.rightPadding =
Qt.binding(expectedRightPadding)
300 console.warn(warningText)
307 right: validate(listItem.mirrored ? undefined : (contentItem ? contentItem.right : undefined), contentItem ? contentItem.right : undefined)
308 rightMargin: validate(-paddingOffset, 0)
309 left: validate(!listItem.mirrored ? undefined : (contentItem ? contentItem.left : undefined), undefined)
310 leftMargin: validate(-paddingOffset, 0)
312 bottom: parent.bottom
314 LayoutMirroring.enabled: false
317 z: contentItem ? contentItem.z + 1 : 0
318 width: item ? item.implicitWidth : actionsLayout.implicitWidth
319 active: !listItem.alwaysVisibleActions && Kirigami.Settings.tabletMode
320 visible: listItem.actionsVisible && opacity > 0
322 sourceComponent: handleComponent
323 opacity: listItem.alwaysVisibleActions || Kirigami.Settings.tabletMode || listItem.hovered ? 1 : 0
324 Behavior on opacity {
327 duration: Kirigami.Units.veryShortDuration
328 easing.type: Easing.InOutQuad
341 implicitWidth: Kirigami.Units.iconSizes.smallMedium
343 preventStealing:
true
344 readonly
property real openPosition: (listItem.width - width - listItem.leftPadding * 2)/listItem.width
345 property real startX: 0
346 property real lastPosition: 0
347 property bool openIntention
349 onPressed: mouse => {
350 startX = mapToItem(listItem, 0, 0).x;
352 onClicked: mouse => {
353 if (Math.abs(mapToItem(listItem, 0, 0).x - startX) >
Qt.styleHints.startDragDistance) {
356 if (listItem.mirrored) {
357 if (listItem.swipe.position < 0.5) {
358 slideAnim.to = openPosition
363 if (listItem.swipe.position > -0.5) {
364 slideAnim.to = -openPosition
371 onPositionChanged: mouse => {
372 const pos = mapToItem(listItem, mouse.x, mouse.y);
374 if (listItem.mirrored) {
375 listItem.swipe.position = Math.max(0, Math.min(openPosition, (pos.x / listItem.width)));
376 openIntention = listItem.swipe.position > lastPosition;
378 listItem.swipe.position = Math.min(0, Math.max(-openPosition, (pos.x / (listItem.width -listItem.rightPadding) - 1)));
379 openIntention = listItem.swipe.position < lastPosition;
381 lastPosition = listItem.swipe.position;
383 onReleased: mouse => {
384 if (listItem.mirrored) {
386 slideAnim.to = openPosition
392 slideAnim.to = -openPosition
403 selected: listItem.checked || (listItem.down && !listItem.checked && !listItem.sectionDelegate)
404 source: (listItem.mirrored ? (listItem.background.x < listItem.background.width/2 ?
"overflow-menu-right" :
"overflow-menu-left") : (listItem.background.x < -listItem.background.width/2 ?
"overflow-menu-right" :
"overflow-menu-left"))
408 id: swipeFilterConnection
410 target: internal.edgeEnabled ? internal.swipeFilterItem : null
411 function onPeekChanged() {
412 if (!listItem.actionsVisible) {
416 if (listItem.mirrored) {
417 listItem.swipe.position = Math.max(0, Math.min(dragButton.openPosition, internal.swipeFilterItem.peek));
418 dragButton.openIntention = listItem.swipe.position > dragButton.lastPosition;
421 listItem.swipe.position = Math.min(0, Math.max(-dragButton.openPosition, -internal.swipeFilterItem.peek));
422 dragButton.openIntention = listItem.swipe.position < dragButton.lastPosition;
425 dragButton.lastPosition = listItem.swipe.position;
427 function onPressed(mouse) {
428 if (internal.edgeEnabled) {
429 dragButton.pressed(mouse);
432 function onClicked(mouse) {
433 if (Math.abs(listItem.background.x) < Kirigami.Units.gridUnit && internal.edgeEnabled) {
434 dragButton.clicked(mouse);
437 function onReleased(mouse) {
438 if (internal.edgeEnabled) {
439 dragButton.released(mouse);
442 function onCurrentItemChanged() {
443 if (!internal.edgeEnabled) {
454 id: actionsBackgroundDelegate
459 readonly
property Item contentItem: swipeBackground
464 bottom: parent.bottom
467 color: parent.pressed ?
Qt.darker(Kirigami.Theme.backgroundColor, 1.1) :
Qt.darker(Kirigami.Theme.backgroundColor, 1.05)
468 x: listItem.mirrored ? listItem.background.x - width : (listItem.background.x + listItem.background.width)
469 width: listItem.mirrored ? parent.width - (parent.width - x) : parent.width - x
472 onTapped: listItem.swipe.
close()
476 visible: background.x != 0
486 visible: background.x != 0
489 bottom: parent.bottom
494 visible: listItem.swipe.position != 0
502 LayoutMirroring.enabled: listItem.mirrored
506 bottom: parent.bottom
507 rightMargin: Kirigami.
Units.smallSpacing
509 visible: parent !== listItem
510 parent: !listItem.alwaysVisibleActions && Kirigami.Settings.tabletMode
511 ? listItem.swipe.leftItem?.contentItem || listItem.swipe.rightItem?.contentItem || listItem
514 property bool hasVisibleActions: false
515 property int indexInListView: index ?? -1
517 function updateVisibleActions(definitelyVisible: bool) {
518 hasVisibleActions = definitelyVisible || listItem.actions.some(isActionVisible);
521 function isActionVisible(action: T.Action): bool {
522 return (action instanceof Kirigami.
Action) ? action.visible : true;
527 model: listItem.actions
529 delegate: QQC2.ToolButton {
530 required
property T.Action modelData
531 required
property int index
533 property bool tabbedFromDelegate:
false
536 display: T.AbstractButton.IconOnly
537 visible: actionsLayout.isActionVisible(action)
539 onVisibleChanged: actionsLayout.updateVisibleActions(visible);
540 Component.onCompleted: actionsLayout.updateVisibleActions(visible);
541 Component.onDestruction: actionsLayout.updateVisibleActions(visible);
543 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
544 QQC2.ToolTip.visible: (Kirigami.Settings.tabletMode ? pressed : hovered) && QQC2.ToolTip.text.length > 0
545 QQC2.ToolTip.text: (action as Kirigami.
Action)?.tooltip ?? action?.text ??
""
552 Keys.onBacktabPressed: (
event) => {
553 if (tabbedFromDelegate) {
554 listItem.forceActiveFocus(
Qt.BacktabFocusReason)
556 event.accepted =
false
560 Keys.onPressed: (
event) => {
561 if ((
Qt.application.layoutDirection ==
Qt.LeftToRight &&
event.key ==
Qt.Key_Left) ||
562 (
Qt.application.layoutDirection ==
Qt.RightToLeft &&
event.key ==
Qt.Key_Right)) {
563 for (var target = index -1; target>=0; target--) {
564 if (target == -1 || actionsLayout.children[target].visible) {
569 listItem.forceActiveFocus(
Qt.BacktabFocusReason)
571 actionsLayout.children[target].tabbedFromDelegate = tabbedFromDelegate
572 actionsLayout.children[target].forceActiveFocus(
Qt.TabFocusReason)
574 event.accepted =
true
575 }
else if ((
Qt.application.layoutDirection ==
Qt.LeftToRight &&
event.key ==
Qt.Key_Right) ||
576 (
Qt.application.layoutDirection ==
Qt.RightToLeft &&
event.key ==
Qt.Key_Left)) {
578 for (var target = index +1; target<actionsRep.count; target++) {
579 if (actionsLayout.children[target].visible) {
583 if (target < (actionsRep.count)) {
584 actionsLayout.children[target].tabbedFromDelegate = tabbedFromDelegate
585 actionsLayout.children[target].forceActiveFocus(
Qt.TabFocusReason)
586 event.accepted =
true
591 Keys.onUpPressed: (
event) => {
592 if (listview && actionsLayout.indexInListView >= 0) {
593 listView.currentIndex = actionsLayout.indexInListView
595 event.accepted =
false
598 Keys.onDownPressed: (
event) => {
599 if (listView && actionsLayout.indexInListView >= 0) {
600 listView.currentIndex = actionsLayout.indexInListView
602 event.accepted =
false
605 onActiveFocusChanged: {
606 if (focus && listView) {
607 listView.positionViewAtIndex(actionsLayout.indexInListView, ListView.Contain)
609 tabbedFromDelegate =
false
613 Accessible.name: text
614 Accessible.description: (action as Kirigami.Action)?.tooltip ??
""
621 right: listItem.alwaysVisibleActions || listItem.mirrored || !Kirigami.Settings.tabletMode ? null : actionsBackgroundDelegate
622 left: listItem.alwaysVisibleActions || listItem.mirrored && Kirigami.Settings.tabletMode ? actionsBackgroundDelegate : null
626 duration: Kirigami.Units.longDuration
627 easing.type: Easing.InOutQuad
628 target: listItem.swipe
630 from: listItem.swipe.position
634 Component.onCompleted: {
636 for (var targetItem = listItem; (targetItem.ListView.view === null); targetItem = targetItem.parent) {
638 listView = targetItem.ListView.view
An item that represents an abstract Action.
color textColor
This property holds the color of the text in the item.
alias supportsMouseEvents
This property sets whether the item should emit signals related to mouse interaction.
bool separatorVisible
This property sets whether the separator is visible.
color activeBackgroundColor
This property holds the color of the background when the item is pressed or selected.
bool alwaysVisibleActions
This property sets whether actions behind this SwipeListItem will always be visible.
color activeTextColor
This property holds the color of the text when the item is pressed or selected.
bool alternatingBackground
This property sets whether instances of this list item will alternate between two colors,...
color alternateBackgroundColor
This property holds the background color to be used when background alternating is enabled.
alias containsMouse
This property tells whether the cursor is currently hovering over the item.
color backgroundColor
This property holds the background color of the list item.
alias overlayWidth
This property holds the width of the overlay.
bool sectionDelegate
This property sets whether this item is a section delegate.
bool actionsVisible
This property tells whether actions are visible and interactive.
listTAction actions
This property holds actions of the list item.
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
KEDUVOCDOCUMENT_EXPORT QStringList languages()
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)