on xenial help sign in
Showable: do nothing if requested action's animation is running

Currently, the following sequence can happen: - hide() is called when shown is false. Showable will call hideAnimation .restart() - Something binds into hideAnimation.running. That binding somehow calls into hide() again. - This time, Showable will skip hideAnimation.restart(), but will call hideAnimation.complete(). - That changes hideAnimation.running again, causing a binding loop. To prevent such sequence, if hide() is called while hideAnimation is running, assume that hiding is already in progress and do nothing. The same applies to show() and showAnimation as well.

commit1a9b7e13b7fa2d647858eed27b62d1836df1b093 authorRatchanan Srirattanamet <ratchanan@ubports.com> dateThu 9 Jan 2020, 01:55 (7 years ago) parentfd0f7e8
2 files changed+21−6
qml/Components/Showable.qml+8−6 tests/qmltests/Components/tst_Showable.qml+13
qml/Components/Showable.qml+8−6
@@ -74,6 +74,9 @@ Item {
7474 }
7575
7676 function __reallyShow() {
77+ if (showAnimation != undefined && showAnimation.running)
78+ return;
79+
7780 if (!available) {
7881 __skipShowAnimation = false;
7982 return false;
@@ -86,9 +89,7 @@ Item {
8689 }
8790
8891 if (showAnimation != undefined) {
89− if (!showAnimation.running) {
90− showAnimation.restart()
91− }
92+ showAnimation.restart()
9293 if (__skipShowAnimation || shown) {
9394 showAnimation.complete();
9495 }
@@ -107,6 +108,9 @@ Item {
107108 property var prepareToHide: function(){}
108109
109110 function hide() {
111+ if (hideAnimation != undefined && hideAnimation.running)
112+ return;
113+
110114 if (showAnimation != undefined && showAnimation.running) {
111115 showAnimation.stop()
112116 }
@@ -119,9 +123,7 @@ Item {
119123 }
120124
121125 if (hideAnimation != undefined) {
122− if (!hideAnimation.running) {
123− hideAnimation.restart()
124− }
126+ hideAnimation.restart()
125127 if (__skipHideAnimation || !shown) {
126128 hideAnimation.complete();
127129 }
tests/qmltests/Components/tst_Showable.qml+13
@@ -182,5 +182,18 @@ Item {
182182 compare(show1.showAnimation.running, false, "Showable should be done running after delayed showNow");
183183 compare(show1.opacity, 1.0, "Showable should be at end of animation after delayed showNow");
184184 }
185+
186+ // Test consecutive show()/hide() to not just complete the animation.
187+ function test_show_when_showing_hide_when_hiding() {
188+ init_test();
189+
190+ show1.show();
191+ show1.show();
192+ compare(show1.showAnimation.running, true);
193+
194+ show1.hide();
195+ show1.hide();
196+ compare(show1.hideAnimation.running, true);
197+ }
185198 }
186199}