Re: Konsole confirmation dialog - non-compliant behavior

Tomaz Canabrava <[email protected]> Sat, 13 Dec 2025 21:08:57 +0100
Newsgroups gmane.comp.kde.devel.konsole
Message-ID <CACk01_zH_C1REepi8DsKcbPvt6wfW7Cm4NBD1rAmp=qTH6iPiA@mail.gmail.com>
--000000000000588a860645daf35e
Content-Type: text/plain; charset="UTF-8"

On Sat, 13 Dec 2025 at 20:15 Cristian S <[email protected]> wrote:

> I'm trying to figure out where this bug is coming from.
> I'm discussing these particular versions of Konsole and KWidgetsAddons as
> published on Debian Snapshots:
>
> #    konsole 20.12.1-1 (sources at
> http://snapshot.debian.org/package/konsole/4%3A20.12.1-1/#konsole_4:3a:20.12.1-1
> )
> #    kwidgetsaddons 5.78.0-2 (sources at
> http://snapshot.debian.org/package/kwidgetsaddons/5.78.0-2/#libkf5widgetsaddons5_5.78.0-2
> )
>

this is from 5 years ago, any chance you can update?


> The issue I'm trying to fix is with the confirmation dialogs shown for
> example by Konsole when trying to close a Konsole window containing a
> process or more  can updstill running in it.
>
> This confirmation dialog uses the KMessageBox widget from KWidgetsAddons.
> Looking in kwidgetsaddons-5.78.0/src/kmessagebox.h,  at line 409, I see
> this:
>
> ====================================
> /**
>  * Display a Yes/No/Cancel "warning" dialog with a listbox to show
> information
>  * to the user.
>  *
>  * @param parent  Parent widget.
>  * @param text    Message string.
>  * @param strlist List of strings to be written in the listbox. If the
>  *                list is empty, it doesn't show any listbox, working
>  *                as warningYesNoCancel.
>  * @param caption Message box title. The application name is added to
>  *                the title. The default title is i18n("Warning").
>  * @param buttonYes The text for the first button.
>  *                  The default is KStandardGuiItem::yes().
>  * @param buttonNo  The text for the second button.
>  *                  The default is KStandardGuiItem::no().
>  * @param buttonCancel  The text for the third button.
>  *                  The default is KStandardGuiItem::cancel().
>  * @param dontAskAgainName If provided, a checkbox is added with which
>  *                further questions can be turned off. If turned off
>  *                all questions will be automatically answered with the
>  *                last answer (either Yes or No).
>  *                The string is used to lookup and store the setting
>  *                in the applications config file.
>  *                The setting is stored in the "Notification Messages"
> group.
>  *                If @p dontAskAgainName starts with a ':' then the setting
>  *                is stored in the global config file.
>  * @param options  see Options
>  *
>  * @return  @p Yes is returned if the Yes-button is pressed. @p No is
> returned
>  *          if the No-button is pressed. @p Cancel is retunred if the
> Cancel-
>  *          button is pressed.
>  *
>  * To be used for questions "Do you want to save your changes?"
>  * The text should explain the implication of choosing 'No'.
>  *
>  * The default button is "Yes". Pressing "Esc" selects "Cancel"
>  */
> KWIDGETSADDONS_EXPORT ButtonCode warningYesNoCancelList(QWidget *parent,
>         const QString &text,
>         const QStringList &strlist,
>         const QString &caption = QString(),
>         const KGuiItem &buttonYes = KStandardGuiItem::yes(),
>         const KGuiItem &buttonNo = KStandardGuiItem::no(),
>         const KGuiItem &buttonCancel = KStandardGuiItem::cancel(),
>         const QString &dontAskAgainName = QString(),
>         Options options = Notify);
> ====================================
>
> So the description in the comment clearly says the default button is "Yes".
> I take this to mean "the leftmost button having the initial focus".
> Also note the order of these buttons is 1="Yes", 2="No", 3="Cancel".
>
> Now looking in konsole-20.12.1/src/MainWindow.cpp,  at line 620, I see
> this:
>
> ====================================
> result = KMessageBox::warningYesNoCancelList(this,
>     i18ncp("@info",
>     "There is a process running in this window. "
>     "Do you still want to quit?",
>     "There are %1 processes running in this window. "
>     "Do you still want to quit?",
>     processesRunning.count()),
>     processesRunning,
>     i18nc("@title", "Confirm Close"),
>     KGuiItem(i18nc("@action:button",
>         "Close &Window"),
>         QStringLiteral("window-close")),
>     KGuiItem(i18nc("@action:button",
>         "Close Current &Tab"),
>         QStringLiteral("tab-close")),
>     KStandardGuiItem::cancel(),
>     // don't ask again name is wrong but I can't update.
>     // this is not about tabs anymore. it's about empty tabs *or* splits.
>     QStringLiteral("CloseAllTabs"));
> ====================================
>
> So here, the first button is "Close Window" as "Yes", the second is "Close
> Current Tab" as "No" and the third is "Cancel" as "Cancel".
> So absolutely correct.
>
> Therefore "Close Window" should be shown as the leftmost button and having
> the initial focus.
>
> Yet, when actually running Konsole, the first (leftmost) button with
> initial focus is "Cancel", and "Close Window" is the rightmost button,
> which is exactly backwards from the stated behavior of KMessageBox.
>
> Now my opinion is that this is a bug from KWidgets/KMessageBox and not
> from Konsole, and I base this opinion on the fact that this behavior is
> common to other KDE programs, for instance Konqueror or KWrite.
> I attached to this message screenshots of these confirmation dialogs from
> Konsole and Konqueror for reference.
>
> My question for the readers of this message is: did any of the Konsole
> developers notice this backward behavior of the buttons in KMessageBox?
>
> Has anybody tried to figure out a way to fix this, and, if so, can they
> share their findings here?
>
> I just want to figure out how to get the buttons back in the correct order
> with the focus on the first.
> Maybe someone can suggest how to do this?
> Maybe reverse the order of the buttons in the warningYesNoCancelList()
> function call in konsole-20.12.1/src/MainWindow.cpp ?  Would that do it?
>

--000000000000588a860645daf35e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div><br></div><div><br><div class=3D"gmail_quote gmail_quote_container"><d=
iv dir=3D"ltr" class=3D"gmail_attr">On Sat, 13 Dec 2025 at 20:15 Cristian S=
 &lt;<a href=3D"mailto:[email protected]">[email protected]</a>&gt; wrote=
:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;border-left-width:1px;border-left-style:solid;padding-left:1ex;border-l=
eft-color:rgb(204,204,204)">
 =20
   =20
 =20
  <div bgcolor=3D"#FFFFFF" text=3D"#000000">
    I&#39;m trying to figure out where this bug is coming from.<br>
    I&#39;m discussing these particular versions of Konsole and
    KWidgetsAddons as published on Debian Snapshots:<br>
    <br>
    # =C2=A0=C2=A0 konsole 20.12.1-1 (sources at
<a href=3D"http://snapshot.debian.org/package/konsole/4%3A20.12.1-1/#konsol=
e_4:3a:20.12.1-1" target=3D"_blank">http://snapshot.debian.org/package/kons=
ole/4%3A20.12.1-1/#konsole_4:3a:20.12.1-1</a>)<br>
    #=C2=A0=C2=A0=C2=A0 kwidgetsaddons 5.78.0-2 (sources at
<a href=3D"http://snapshot.debian.org/package/kwidgetsaddons/5.78.0-2/#libk=
f5widgetsaddons5_5.78.0-2" target=3D"_blank">http://snapshot.debian.org/pac=
kage/kwidgetsaddons/5.78.0-2/#libkf5widgetsaddons5_5.78.0-2</a>)<br>
    </div></blockquote><div dir=3D"auto"><br></div><div dir=3D"auto">this i=
s from 5 years ago, any chance you can update?</div><div dir=3D"auto"><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bo=
rder-left-width:1px;border-left-style:solid;padding-left:1ex;border-left-co=
lor:rgb(204,204,204)"><div bgcolor=3D"#FFFFFF" text=3D"#000000" dir=3D"auto=
"><br>
    The issue I&#39;m trying to fix is with the confirmation dialogs shown
    for example by Konsole when trying to close a Konsole window
    containing a process or more =C2=A0can updstill running in it.<br>
    <br>
    This confirmation dialog uses the KMessageBox widget from
    KWidgetsAddons.<br>
    Looking in kwidgetsaddons-5.78.0/src/kmessagebox.h,=C2=A0 at line 409, =
I
    see this:<br>
    <br>
    =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
    <font face=3D"Courier New, Courier, monospace" style=3D"font-family:&qu=
ot;Courier New&quot;,Courier,monospace;color:rgb(0,0,0)">/**<br>
      =C2=A0* Display a Yes/No/Cancel &quot;warning&quot; dialog with a lis=
tbox to show
      information<br>
      =C2=A0* to the user.<br>
      =C2=A0*<br>
      =C2=A0* @param parent=C2=A0 Parent widget.<br>
      =C2=A0* @param text=C2=A0=C2=A0=C2=A0 Message string.<br>
      =C2=A0* @param strlist List of strings to be written in the listbox. =
If
      the<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 list is empty, it doesn&#39;t show any listb=
ox,
      working<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 as warningYesNoCancel.<br>
      =C2=A0* @param caption Message box title. The application name is add=
ed
      to<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 the title. The default title is i18n(&quot;W=
arning&quot;).<br>
      =C2=A0* @param buttonYes The text for the first button.<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 The default is KStandardGuiItem:=
:yes().<br>
      =C2=A0* @param buttonNo=C2=A0 The text for the second button.<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 The default is KStandardGuiItem:=
:no().<br>
      =C2=A0* @param buttonCancel=C2=A0 The text for the third button.<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 The default is KStandardGuiItem:=
:cancel().<br>
      =C2=A0* @param dontAskAgainName If provided, a checkbox is added with
      which<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 further questions can be turned off. If turn=
ed
      off<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 all questions will be automatically answered
      with the<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 last answer (either Yes or No).<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 The string is used to lookup and store the
      setting<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 in the applications config file.<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 The setting is stored in the &quot;Notificat=
ion
      Messages&quot; group.<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 If @p dontAskAgainName starts with a &#39;:&=
#39; then
      the setting<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 is stored in the global config file.<br>
      =C2=A0* @param options=C2=A0 see Options<br>
      =C2=A0*<br>
      =C2=A0* @return=C2=A0 @p Yes is returned if the Yes-button is pressed=
. @p No
      is returned<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if the =
No-button is pressed. @p Cancel is retunred if
      the Cancel-<br>
      =C2=A0*=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 button =
is pressed.<br>
      =C2=A0*<br>
      =C2=A0* To be used for questions &quot;Do you want to save your chang=
es?&quot;<br>
      =C2=A0* The text should explain the implication of choosing &#39;No&#=
39;.<br>
      =C2=A0*<br>
      =C2=A0* The default button is &quot;Yes&quot;. Pressing &quot;Esc&quo=
t; selects &quot;Cancel&quot;<br>
      =C2=A0*/<br>
      KWIDGETSADDONS_EXPORT ButtonCode warningYesNoCancelList(QWidget
      *parent,<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const QString &amp;text,<b=
r>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const QStringList &amp;str=
list,<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const QString &amp;caption=
 =3D QString(),<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const KGuiItem &amp;button=
Yes =3D KStandardGuiItem::yes(),<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const KGuiItem &amp;button=
No =3D KStandardGuiItem::no(),<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const KGuiItem &amp;button=
Cancel =3D
      KStandardGuiItem::cancel(),<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const QString &amp;dontAsk=
AgainName =3D QString(),<br>
      =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Options options =3D Notify=
);<br>
    </font>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<font face=3D"Courier New,
      Courier, monospace" style=3D"font-family:&quot;Courier New&quot;,Cour=
ier,monospace;color:rgb(0,0,0)"><font face=3D"sans-serif" style=3D"font-fam=
ily:sans-serif;color:rgb(0,0,0)"><br>
        <br>
        So the description in the comment clearly says the default
        button is &quot;Yes&quot;.<br>
        I take this to mean &quot;the leftmost button having the initial
        focus&quot;.<br>
        Also note the order of these buttons is 1=3D&quot;Yes&quot;, 2=3D&q=
uot;No&quot;,
        3=3D&quot;Cancel&quot;.<br>
        <br>
        Now looking in konsole-20.12.1/src/MainWindow.cpp,=C2=A0 at line 62=
0,
        I see this:<br>
        <br>
        =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
        <font face=3D"Courier New, Courier, monospace" style=3D"font-family=
:&quot;Courier New&quot;,Courier,monospace;color:rgb(0,0,0)">result =3D
          KMessageBox::warningYesNoCancelList(this,<br>
          =C2=A0=C2=A0=C2=A0 i18ncp(&quot;@info&quot;,<br>
          =C2=A0=C2=A0=C2=A0 &quot;There is a process running in this windo=
w. &quot;<br>
          =C2=A0=C2=A0=C2=A0 &quot;Do you still want to quit?&quot;,<br>
          =C2=A0=C2=A0=C2=A0 &quot;There are %1 processes running in this w=
indow. &quot;<br>
          =C2=A0=C2=A0=C2=A0 &quot;Do you still want to quit?&quot;,<br>
          =C2=A0=C2=A0=C2=A0 processesRunning.count()),<br>
          =C2=A0=C2=A0=C2=A0 processesRunning,<br>
          =C2=A0=C2=A0=C2=A0 i18nc(&quot;@title&quot;, &quot;Confirm Close&=
quot;),<br>
          =C2=A0=C2=A0=C2=A0 KGuiItem(i18nc(&quot;@action:button&quot;,<br>
          =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 &quot;Close &amp;Window&quo=
t;),<br>
          =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 QStringLiteral(&quot;window=
-close&quot;)),<br>
          =C2=A0=C2=A0=C2=A0 KGuiItem(i18nc(&quot;@action:button&quot;,<br>
          =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 &quot;Close Current &amp;Ta=
b&quot;),<br>
          =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 QStringLiteral(&quot;tab-cl=
ose&quot;)),<br>
          =C2=A0=C2=A0=C2=A0 KStandardGuiItem::cancel(),<br>
          =C2=A0=C2=A0=C2=A0 // don&#39;t ask again name is wrong but I can=
&#39;t update.<br>
          =C2=A0=C2=A0=C2=A0 // this is not about tabs anymore. it&#39;s ab=
out empty tabs
          *or* splits.<br>
          =C2=A0=C2=A0=C2=A0 QStringLiteral(&quot;CloseAllTabs&quot;));</fo=
nt><br>
      </font></font><font face=3D"Courier New, Courier, monospace" style=3D=
"font-family:&quot;Courier New&quot;,Courier,monospace;color:rgb(0,0,0)"><f=
ont face=3D"sans-serif" style=3D"font-family:sans-serif;color:rgb(0,0,0)">=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
      </font></font><br>
    So here, the first button is &quot;Close Window&quot; as &quot;Yes&quot=
;, the second is
    &quot;Close Current Tab&quot; as &quot;No&quot; and the third is &quot;=
Cancel&quot; as &quot;Cancel&quot;.<br>
    So absolutely correct.<br>
    <br>
    Therefore &quot;Close Window&quot; should be shown as the leftmost butt=
on and
    having the initial focus.<br>
    <br>
    Yet, when actually running Konsole, the first (leftmost) button with
    initial focus is &quot;Cancel&quot;, and &quot;Close Window&quot; is th=
e rightmost
    button, which is exactly backwards from the stated behavior of
    KMessageBox.<br>
    <br>
    Now my opinion is that this is a bug from KWidgets/KMessageBox and
    not from Konsole, and I base this opinion on the fact that this
    behavior is common to other KDE programs, for instance Konqueror or
    KWrite.<br>
    I attached to this message screenshots of these confirmation dialogs
    from Konsole and Konqueror for reference.<br>
    <br>
    My question for the readers of this message is: did any of the
    Konsole developers notice this backward behavior of the buttons in
    KMessageBox?<br>
    <br>
    Has anybody tried to figure out a way to fix this, and, if so, can
    they share their findings here?<br>
    <br>
    I just want to figure out how to get the buttons back in the correct
    order with the focus on the first.<br>
    Maybe someone can suggest how to do this?<br>
    Maybe reverse the order of the buttons in the
    warningYesNoCancelList() function call in <font face=3D"Courier New,
      Courier, monospace" style=3D"font-family:&quot;Courier New&quot;,Cour=
ier,monospace;color:rgb(0,0,0)"><font face=3D"sans-serif" style=3D"font-fam=
ily:sans-serif;color:rgb(0,0,0)">konsole-20.12.1/src/MainWindow.cpp</font><=
/font>
    ?=C2=A0 Would that do it?<br>
  </div>

</blockquote></div></div>

--000000000000588a860645daf35e--