Error: Double Dialog QML

I ran into a weird problem today when I was continuing one of the many projects I have. First of all, I love the way Dialogs have created in Sailfish. That’s why I like to use them whenever I can. There’s no reason to create a custom made dialog (like I actually did back in the old N9 times.. Ah, memories!).

However there were this one little issue I had and I thought I’m going to share it with you today.

I need two different Dialog QML components in one of my projects. Nothing unusual, right? But I had to open the other one as soon as the user makes the decision in the first one. This is the point where I encounter an error and the application looked, eh, bizarre.

In case you don’t know how to use Dialogs in Sailfish I recommend reading the reference manual (see here: Sailfish Silica Reference) and study – all of it.

var dialog_First = pageStack.push ( "../dialogs/First.qml", { "string_X": string_X })

dialog_First.accepted.connect ( function ( ) {
    // Something you want to do after user accepts ...
})

dialog_First.rejected.connect ( function ( ) {
    // ... or if he rejects it.
})

This is how you open your Dialog page from another QML, right? Well. Let’s assume that there is few options where the user should choose from. Now, right after user accepts makes his choise, you would like to open another Dialog which content is related to the first pick he made. Then the code would look like this.

var dialog_First = pageStack.push ( "../dialogs/First.qml", { "string_X": string_X })

dialog_First.accepted.connect ( function ( ) {
    var dialog_Second = pageStack.push ( "../dialogs/Second.qml", { "string_Y": string_Y })

    dialog_Second.accepted.connect ( function ( ) {
        // Oops, something's wrong?
    })
})

At first I’d like to point out that I deleted the rejected part because it’s not actually relative in this case at all. But this is something you would (maybe) normally do, right? However, something will go wrong here. You’ll get an error message which say

Warning: cannot pop while transition is in progress

and you can see two different pages merged together. How come something like this can happen?

Right after this error appeared and I saw this weird behaviour in my application I knew what was wrong and how to solve it. But let’s not go into that right away. The problem with this is that you’re not able to call another Dialog when the previous one is still in the middle of the transition (gosh, didn’t the error just say it?). I can see one positive and one negative about this kind of situation.

First of all it’s not a good thing if you actually think about it. That means (at least in this case) Sailfish can not automatically put something in hold and execute the command after it’s safe. You have to do it manually. This is something which I can not understand, because Sailfish SDK is, however, clever enough to tell you that.

But there is a silver lining… Because Sailfish doesn’t control this kind of behaviour automatically it gives you the full control over the situation. Therefore you’re able to manually create the waiting process in a way you want. For example, I took an advantage out of this and decided to load the required settings from the server while Sailfish is finishing the transition of the first Dialog. If Sailfish would’ve recognize the situation and automatically put the next task in hold and execute it as soon as possible, I would’ve have to load the settings after the second Dialog appears. Then the user would’ve had to look at an empty page (well of course there would’ve be a BusyIndicator QML component, but you get the point …).

So I solved this problem in a following way. I created a BusyIndicator QML and a Rectangle QML (this is used to fill the whole screen with a “Black” color and .50 opacity) components in a same page from where I load the Dialog. When the application recognizes that the user comes back from the first Dialog, it disables everything you last saw at that page, and enables the loading screen. Meanwhile the application processes the information it got from the Dialog. After the processing is ready, it automatically opens up the second Dialog.

You might think, why I didn’t use the Page QML components status: variable to check when it’s completely active? Because that looked too weird in my opinion. Think about it (or better yet, test it by yourself)… As soon as the first Dialog finishes its transition, another one begins. It doesn’t make any sense… Forth and back, forth and back. So that’s actually a second good thing why Sailfish doesn’t automatically put this in hold and execute it right after previous one.

onStatusChanged: {
    if ( page_Component.status === PageStatus.Active ) {
        var dialog_Second = pageStack.push ( "../dialogs/Second.qml", { "string_Y": string_Y })
 
        dialog_Second.accepted.connect ( function ( ) {
            // Oops, something's wrong?
        })
    }
}

I tried to find a way to smoothly open a new Dialog from another (but that the first Dialog would disappear) but I couldn’t find a decent answer or workaround for it. However, I’m still very happy with the result I got, but it’s a shame that there isn’t any native, Sailfish way to achieve this.

Leave a comment