Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-137951

SwipeDelegate opening/closing algorithm does not consider change-of-direction or rapid-close

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.8.3, 6.9.1, 6.10.0 Beta1
    • Quick: Controls 2
    • None
    • Windows 10 22H2, MSVC 2022 x64

    Description

      SwipeDelegate has some logic to detect user intent: If the swipe has a high velocity, then the user probably intended to open the delegate, even if the swipe position didn't pass the halfway mark: https://github.com/qt/qtdeclarative/blob/v6.9.1/src/quicktemplates/qquickswipedelegate.cpp#L907-L915

      However, this "rapid swipe" detector only works when opening the delegate. It doesn't work when closing the delegate. It also doesn't detect if the user changes direction mid-swipe.

       

      Code

      pragma ComponentBehavior: Bound
      import QtQuick
      import QtQuick.Controls.Basic
      import QtTest
      
      Rectangle {
          id: root
          width: 800
          height: 600
      
          SwipeDelegate {
              id: sd
              anchors.fill: parent
              text: swipe.position.toFixed(2)
              //onTextChanged: console.log(text)
      
              readonly property real altWidth: width / 3
      
              swipe.left: Rectangle {
                  width: sd.altWidth
                  height: parent.height
                  color: "tomato"
              }
          }
      
          TestCase {
              id: testCase
      
              function test_rapidOpen() {
                  // Ensure it is initially closed
                  sd.swipe.close()
                  testCase.tryCompare(sd, "text", "0.00") // Can't find "swipe.position", so use "text" instead
                  testCase.wait(100) // The mouse press doesn't seem to register if we don't wait long enough
      
                  // Rapidly swipe open
                  testCase.mousePress(root, 0)
                  let nSegments = 5
                  for (let i = 0; i < nSegments; ++i) {
                      // The current logic always forces the delegate to open/close if the position goes past the halfway mark.
                      // We stay below the halfway mark to test the velocity threshold detector
                      let k = i/2
                      testCase.mouseMove(root, sd.altWidth * k/nSegments)
                      testCase.wait(10)
                  }
                  testCase.mouseRelease(root)
      
                  // Did the swipe delegate open as expected?
                  testCase.tryCompare(sd, "text", "1.00")
              }
      
              function test_rapidClose() {
                  // Ensure it is initially open
                  sd.swipe.open(SwipeDelegate.Left)
                  testCase.tryCompare(sd, "text", "1.00")
                  testCase.wait(100)
      
                  // Rapidly swipe close
                  testCase.mousePress(root, sd.altWidth)
                  let nSegments = 5
                  for (let i = 0; i < nSegments; ++i) {
                      let k = i/2
                      testCase.mouseMove(root, sd.altWidth * (1 - k/nSegments))
                      testCase.wait(10)
                  }
                  testCase.mouseRelease(root)
      
                  // Did the swipe delegate close as expected?
                  testCase.tryCompare(sd, "text", "0.00")
              }
      
              function test_changeMind() {
                  // Ensure it is initially closed
                  sd.swipe.close()
                  testCase.tryCompare(sd, "text", "0.00")
                  testCase.wait(100)
      
                  // Slowly start to open the swipe delegate...
                  testCase.mousePress(root, 0)
                  let nSegments = 100
                  for (let i = 0; i < nSegments; ++i) {
                      testCase.mouseMove(root, sd.altWidth * i/nSegments)
                      testCase.wait(10)
                  }
      
                  // ...changed mind. Swipe back rapidly and release to keep the swipe delegate closed.
                  nSegments = 5
                  for (let i = 0; i < nSegments; ++i) {
                      let k = i/2
                      testCase.mouseMove(root, sd.altWidth * (1 - k/nSegments))
                      testCase.wait(10)
                  }
                  testCase.mouseRelease(root)
      
                  // Did the swipe delegate stay closed as expected?
                  testCase.tryCompare(sd, "text", "0.00")
              }
          }
      }
      

       

      Outcomes

      • test_rapidOpen() passes
      • test_rapidClose() fails
      • test_changeMind() fails

       
      Notes

      Attachments

        Issue Links

          For Gerrit Dashboard: QTBUG-137951
          # Subject Branch Project Status CR V

          Activity

            People

              qt.team.quick.subscriptions Qt Quick and Widgets Team
              skoh-qt Sze Howe Koh
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There is 1 open Gerrit change