What approach do you take for dialogs where an action is to be performed?



  • I am getting more indecisive as I write more code....

    This question is applicable to my Qt programming, but also to desktop UI programming in general even if I were not using Qt.

    My code is full of (modal) dialogs. This is fine as far as I'm concerned; mobiles are for wimps. I don't want a discussion on whether that bit is good or bad.

    Often a sub-dialog --- which will be invoked from a parent dialog or a window or whatever --- is needed to get a parameter or two from the user for the proposed action to be performed. The question is: where do you put the code for performing the final action, in the sub-dialog or back in the caller's code? These are the two obvious approaches:

    1. You can move the logic for performing the action out into the sub-dialog, to be invoked from there on its OK button.

    2. You can keep the action code in the caller, and have the sub-dialog just return the "OK" to the caller.

    With #1 there is nothing which has to be passed back from sub-dialog to caller about the choices for "parameters" made on the dialog. OTOH, the action logic tends to go into the dialog, which I'm sometimes not happy about.

    With #2 you need to get some value(s) back from the sub-dialog to be used by the caller. You have to keep the sub-dialog in existence so you can call some methods to get the bits & pieces out of it.

    Now, it seems "obvious" to me that if you have lots of parameters & possible actions you would go for #1, and if the sub-dialog is just an "Are you sure? Yes/No" you would use #2. But when it's "in-between" --- no choice of actions, just do it or don't do it, and say just one or two parameters --- the choice is not clear-cut, and I hate that!

    So.... Do people have a preferred approach or rule of thumb for this kind of situation? I know there is no "definitive answer", both have their pros & cons, that's why I am posting into Brainstorm....


  • Moderators

    Consider a third option:

    1. In order to keep GUI and business logic separated, send the data and dialog result to some controller object.


  • @sierdzio
    For the purposes of the question here, I see that as a variant of #2.

    When does your dialog close? Immediately after sending to the controller, unconditionally? The dialog requests a result from the controller? The controller sends a signal back to close the dialog?


  • Moderators

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    When does your dialog close? Immediately after sending to the controller, unconditionally? The dialog requests a result from the controller? The controller sends a signal back to close the dialog?

    Dialog closes when user clicks a button (OK, Close, Escape etc.). Handler for that button emits the relevant signal (accepted() or rejected()) with relevant data.



  • @sierdzio
    So in that case, if you close the dialog unconditionally on OK and then the "back-end"/controller/whatever reports an error during the action (I didn't like the file path you picked, or whatever), the dialog has gone and the user cannot correct an error. That is often not nice. This is why the decisions are so unclear to me....


  • Qt Champions 2017

    Would you give a simplistic concrete example? My brain doesn't handle theory that well (ironically).



  • @kshegunov

    1. A standalone dialog/window, named A, has a button on it to create a backup. It has the logic to do the backup, or that's elsewhere.

    2. Now I decide that actually I want to offer the user a couple of options to affect the backup ("Do you want to allow overwrite?", "What things to exclude?"). So I create a (modal) dialog, named B, with those couple of parameters. They will be passed to the backup routine.

    3. That gives two simple choices about how to implement:

    a. Move the code for backing up into dialog B. That dialog now does the backup when the user clicks OK or Proceed, and can access the user's choices easily to produce the parameters. The backup is happening from dialog B's OK button.

    b. Keep the backup happening in A. When user clicks OK in modal dialog B, it is dismissed but does nothing but accept(). A can still ask B for the parameters the user filled in (though you have to write functions to access them) while it constructs the parameters to make the backup. The backup is happening back in A, after dialog B has been dismissed.


  • Qt Champions 2017

    And you didn't like @sierdzio's suggestion because ...? What he said is what I'd usually employ, being lazy and all ... :)



  • @kshegunov
    Very briefly, I don't feel that answers the question I am trying to get at, as per my further questions to @sierdzio.

    Moving the action code into a controller does not obviate the decision as to who is responsible for invoking the controller to perform the action. Is that to be the OK button on the dialog which gathers further parameters, or is that to be in the caller of the dialog?

    There are two basic patterns possible with a modal dialog asking the user for some information required for an action:

    • The dialog itself gathers the information and calls for the action to be performed with those parameters when OK is clicked, in some shape or form. (The dialog is still open in this scenario.)

    • The dialog closes on-screen (but not in memory) and returns accept() to the caller when OK is clicked. The caller uses methods in the dialog to retrieve the parameters and the caller then invokes the action with those parameters, in some shape or form. (The dialog is closed this scenario.)

    I fret between which of the two approaches to use when.


  • Moderators

    I vote for the first option, then. Dialog sends a signal and waits for a reply or calls controller directly. It is closed when controller decides it can be closed.

    This is a more future-proof solution, I think, but it is a pain in the ass to implement.


  • Qt Champions 2017

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    The dialog itself gathers the information and calls for the action to be performed with those parameters when OK is clicked, in some shape or form. (The dialog is still open in this scenario.)

    That'd be the/my preferred and (the) flexible way to do it. Having a controller object however makes it a bit easier as both dialogs could be created, initialized and controlled from it, and the data you're working with kept in said object. This also lifts the need to actually derive from QDialog (twice).



  • @sierdzio, @kshegunov
    OK, we are now in business for the brainstorm! (If possible, can we ignore having a controller for the current purposes.)

    You are both going for the "dialog initiates action rather than returning to caller to do so". Now consider the following.

    Case #1:

    I have an action, let's say "do a backup" or "delete some files", but it really doesn't matter. When the user clicks a button to perform it, I want the code to check with the user that they are "sure".

    For this I almost certainly write an "Are you sure? Yes/No" dialog. It returns accept() or reject() to the caller. The caller still performs the action. This is the usual approach taken in, say, either the native or Qt level of putting up a "message box" for confirmation. Now, the OS or Qt function could instead have taken the approach of saying that the caller specifies a "callback function" (the backup routine) which the confirmation dialog invokes if the uses clicks Yes/OK/Proceed, but that tends not to be what is provided in this case.

    Case #2:

    Now I want to add to that confirmation dialog a checkbox parameter, like "Continue on error" or what-not. (Let's say it's my own dialog, not a system message box where I cannot do that.)

    • Either: I have to change code so that now the dialog invokes the action so that it can pass that parameter on to it;
    • Or: I allow it to still return accept() to the caller, the caller then has to query the (closed-but-still-in-memory) dialog to get the value of the parameter so that the caller can pass it on.

    Case #3:

    Finally, I now decide to put 10 extra "widget-parmeters" onto the dialog, to ask all sorts of things for the action. At this point it's such a pain to have to be able to pass all those parameters back to the caller that I probably do change the dialog to invoke the action with all these appropriate arguments itself instead of just returning accept().

    It's the middle case #2 that I fret over. There are are just one or maybe two widget-parameters on the dialog. I only have to provide one (or maybe two) method in the dialog to retrieve the extra parameter. I feel I'm between a rock and a hard place deciding which of the two approaches feels "best"....?


  • Qt Champions 2017

    Forgetting for a second the controllers, you'd want self-contained units (i.e. dialogs) and that applies to case #2 as well. What is "proper" is to have the dialog keep internally the kind of data the user has selected, be it checkboxes, text or w/e and then after the acceptance pull that from the outside. It doesn't really matter if the outside is another dialog or a widget, you'd still execute it the same way. This also means the validations and such should be done in the UI component itself, which can be really finicky as it may require injecting additional data from outside. The real problem is however that this requires a lot of boilerplate code (as you've already probably experienced), so it's somewhat exhausting to do for all dialogs and in all cases.

    That's where the "controller" object shines, as you can manage multiple dialogs (forms/ui elements) all together as a single unit, so you don't in fact need to transfer data between the different UI components - all is tidily collected in the controller; and it's the controller that initializes the UI so it puts the data directly to the UI, and does the validation.



  • @kshegunov
    Yes, but I will just say. Had I been paid a penny for my work, or had I written the code myself, I should be more disposed. As it is, I have inherited 50+ dialogs, no comments, and no time to rewrite anything. To abstract the data from the dialogs requires an awful lot of non-GUI classes to be written to represent the data. And given that Python has no type-checking, it's not a nice exercise....!


  • Qt Champions 2017

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    Had I been paid a penny for my work

    If you work for free, I have way too much on my plate ... :)

    To abstract the data from the dialogs requires an awful lot of non-GUI classes to be written to represent the data. And given that Python has no type-checking, it's not a nice exercise....!

    Perhaps, however that's how it should be done in the long run. If you only care about immediately getting it to work, then it doesn't really matter the approach you take, because it's going to end as patch, over patch, over patchwork. In the end it's going to be spaghetti all 'round, but that's how it is with no-planing-no-time-to-code-properly projects.



  • @kshegunov said in What approach do you take for dialogs where an action is to be performed?:

    Perhaps, however that's how it should be done in the long run. If you only care about immediately getting it to work, then it doesn't really matter the approach you take, because it's going to end as patch, over patch, over patchwork. In the end it's going to be spaghetti all 'round, but that's how it is with no-planing-no-time-to-code-properly projects.

    tell me about it, I have a legacy project, I'm working on, in my free time. After the first rough cleanup, I ended up deleteing 10000 lines of code (not commets because there are none x) ) out of mainwindow.cpp, and it's still 15000 lines long...

    Takes QtCreators completer up to 20 secs, when you type ui->

    [EDIT: Replies forked to https://forum.qt.io/topic/96617/usability-of-qt-creator-s-clang-code-model -- JKSH]


  • Moderators

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    It's the middle case #2 that I fret over. There are are just one or maybe two widget-parameters on the dialog. I only have to provide one (or maybe two) method in the dialog to retrieve the extra parameter.

    If it's only 2 parameters, just group them together with the button (e.g. inside a QGroupBox or QToolBox). Get rid of the second dialog altogether (or make it "Are you sure?" only). Now you don't need to pass parameters, and you don't need to agonize over where to put the logic.

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    This question is applicable to my Qt programming, but also to desktop UI programming in general even if I were not using Qt.

    My code is full of (modal) dialogs. This is fine as far as I'm concerned; mobiles are for wimps. I don't want a discussion on whether that bit is good or bad.

    Often a sub-dialog --- which will be invoked from a parent dialog or a window or whatever --- is needed to get a parameter or two from the user for the proposed action to be performed.

    Even for non-mobile GUIs, I'd recommend keeping things simple and have as few dialogs as possible. Multi-level dialog chains make life harder than it has to be.



  • @JKSH said in What approach do you take for dialogs where an action is to be performed?:

    If it's only 2 parameters, just group them together with the button (e.g. inside a QGroupBox or QToolBox). Get rid of the second dialog altogether

    Since you've written, I'll reply. Unfortunately not. Invoker is a page with multiple buttons, each one leading to an action/dialog. There is no room/clarity to start having that offer sub-options etc.


  • Moderators

    @JonB said in What approach do you take for dialogs where an action is to be performed?:

    Invoker is a page with multiple buttons, each one leading to an action/dialog. There is no room/clarity to start having that offer sub-options etc.

    Something like QToolBox can help. It can show every available "action", yet only expose the buttons + parameters of one action at any given time time.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.