]> granicus.if.org Git - nethack/commitdiff
Qt ynaq/yn#aq dialogs
authorPatR <rankin@nethack.org>
Sun, 4 Oct 2020 14:36:12 +0000 (07:36 -0700)
committerPatR <rankin@nethack.org>
Sun, 4 Oct 2020 14:36:12 +0000 (07:36 -0700)
When 'popup_dialog' is set, the Qt interface uses a popup window
for yn_function() calls and the dialog has a list of buttons, one
per potential choice.  It has been handling "yn?" and "ynq?"
questions differently from general request-one-char prompts, using
buttons "Yes", "No, and "Cancel" instead of showing individual
letters.  This extends that to "ynaq" and "yn#aq" questions and
labels 'q' reply as "Stop" instead of "Cancel" for those.  Also,
when player uses keyboard instead of mouse to answer, allow 'c'
as well as 'q' for cancel ones, 's' as well as 'q' for stop ones.

Prompt  Buttons
yn      [Yes ][ No ]
ynq     [ Yes  ][  No  ][Cancel]
ynaq    [Yes ][ No ][All ][Stop]
yn#aq   [Yes ]Count:______[ No ][All ][Stop]
rl      [ Left ][Right ]    //unchanged; included for completeness

(For contrast, when something specifies "ny" as the acceptable
choices, the buttons will just be [n][y].  Prompts for choosing
from a list of inventory letters can't accidentally match these
special cases as long as they're specified in alphabetical order.)

win/Qt/qt_yndlg.cpp
win/Qt/qt_yndlg.h

index 7ae167da23451f2c39b9fc8b77d06e94096ece24..d7b370a3283473b9a33724f3d9e226ecedfd60fc 100644 (file)
@@ -69,6 +69,7 @@ NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent, const QString &q,
             }
         }
     }
+    alt_answer[0] = alt_result[0] = '\0';
 }
 
 char NetHackQtYnDialog::Exec()
@@ -152,7 +153,10 @@ char NetHackQtYnDialog::Exec()
        QButtonGroup *bgroup = new QButtonGroup(group);
 
        int nchoices=ch.length();
-        bool is_ynq = (ch == QString("ynq")), // [ Yes  ][  No  ][Cancel]
+        bool is_ynaq = (ch == QString("ynaq") // [Yes ][ No ][All ][Stop]
+                        || ch == QString("yn#aq")
+                        || ch == altchoices), // alternate "yn#aq"
+             is_ynq = (ch == QString("ynq")), // [ Yes  ][  No  ][Cancel]
              is_yn  = (ch == QString("yn")),  // [Yes ][ No ]
              is_lr  = (ch == QString(lrq));   // [ Left ][Right ]
 
@@ -161,8 +165,8 @@ char NetHackQtYnDialog::Exec()
        const int extra=fontMetrics().height(); // Extra for group
        int x=margin, y=extra+margin;
         int butheight = fontMetrics().height() * 2 + 5,
-            butwidth = (butheight - 5)
-                       * ((is_ynq || is_lr) ? 3 : is_yn ? 2 : 1) + 5;
+            butwidth = (butheight - 5) * ((is_ynq || is_lr) ? 3
+                                          : (is_ynaq || is_yn) ? 2 : 1) + 5;
         if (butwidth == butheight) { // square, enough room for C or ^C
             // some characters will be labelled by name rather than by
             // keystroke so will need wider buttons
@@ -183,7 +187,9 @@ char NetHackQtYnDialog::Exec()
             if (ch[i] == '#' && allow_count)
                 continue; // don't show a button for '#'; has Count box instead
             QString button_name = QString(visctrl((char) ch[i].cell()));
-            if (is_yn || is_ynq || is_lr) {
+            if (is_yn || is_ynq || is_ynaq || is_lr) {
+                // FIXME: a better way to recognize which labels should
+                // use alterate text is needed
                 switch (ch[i].cell()) {
                 case 'y':
                     button_name = "Yes";
@@ -191,13 +197,28 @@ char NetHackQtYnDialog::Exec()
                 case 'n':
                     button_name = "No";
                     break;
+                case 'a':
+                    // the display of vanquished monsters uses "ynaq" for
+                    // convenience, where 'a' requests a sort-by menu;
+                    // show "sort" instead of "all" and allow player to
+                    // type either 'a' or 's' when not clicking on button
+                    if (question.contains(QString("vanquished?")))
+                        button_name = "Sort", AltChoice('s', 'a');
+                    else
+                        button_name = "All";
+                    break;
                 case 'q':
-                    // FIXME: sometimes the 'q' choice is ''cancel current
-                    // action'' but other times it is actually 'quit'.
-                    if (question.left(10) == QString("Dump core?"))
+                    // most 'q' replies are actually for "cancel" but
+                    // for "ynaq" (where "all" is a choice) it's "stop"
+                    // and for end of game disclosure it really is "quit"
+                    if (question.left(10) == QString("Dump core?")
+                        || (::g.program_state.gameover
+                            && question.left(11) == QString("Do you want")))
                         button_name = "Quit";
+                    else if (is_ynaq)
+                        button_name = "Stop", AltChoice('s', 'q');
                     else
-                        button_name = "Cancel";
+                        button_name = "Cancel", AltChoice('c', 'q');
                     break;
                 case 'l':
                     button_name = "Left";
@@ -286,7 +307,10 @@ char NetHackQtYnDialog::Exec()
         if (res == 0) {
             choice = is_lr ? '\033' : ch_esc ? ch_esc : def ? def : ' ';
         } else if (res == 1) {
-            choice = def ? def : ch_esc ? ch_esc : ' ';
+            if (keypress)
+                choice = keypress;
+            else
+                choice = def ? def : ch_esc ? ch_esc : ' ';
         } else if (res >= 1000) {
             choice = (char) ch[res - 1000].cell();
         }
@@ -319,23 +343,33 @@ char NetHackQtYnDialog::Exec()
     return keypress;
 }
 
+void NetHackQtYnDialog::AltChoice(char ans, char res)
+{
+    if (ans && !strchr(alt_answer, ans)) {
+        (void) strkitten(alt_answer, ans);
+        (void) strkitten(alt_result, res);
+    }
+}
+
 void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
 {
+    keypress = '\0';
     QString text(event->text());
-    if (text.isEmpty() && event->modifiers())
+    if (text.isEmpty())  /* && event->modifiers()) */
         return;
 
-    if (!choices || !*choices) {
-       if (!text.isEmpty()) {
-           keypress = text.toUcs4()[0];
-            this->done(1);
-       }
+    keypress = text.at(0).cell();
+    char *p = NULL;
+    if (*alt_answer && (p = strchr(alt_answer, keypress)) != 0)
+        keypress = alt_result[p - alt_answer];
+
+    if (!choices || !*choices || !keypress) {
+        this->done(1);
 
     } else {
-       int where = QString::fromLatin1(choices).indexOf(text);
+       int where = QString::fromLatin1(choices).indexOf(QChar(keypress));
 
-        if (where != -1 && allow_count
-            && strchr("#0123456789", text[0].cell())) {
+        if (allow_count && strchr("#0123456789", keypress)) {
             if (text == "#") {
                 // 0 will be preselected; typing anything replaces it
                 le->setText(QString("0"));
@@ -347,7 +381,18 @@ void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
             }
             // (don't know whether this actually does anything useful)
             le->setAttribute(Qt::WA_KeyboardFocusChange, true);
+            // this is definitely useful...
             le->setFocus(Qt::ActiveWindowFocusReason);
+            //
+            // TODO: 'No' is highlighted as default for result if player
+            // types <return>, but once count entry starts that should
+            // be changed because this LineEdit dialog has now become
+            // the defacto default.  We can't just turn off the default
+            // setting for the 'No' button because <return> only works
+            // if there is a default explicitly set.  Unfortunately the
+            // LineEdit widget isn't a viable candidate for that because
+            // it isn't a button.  [Maybe just highlight 'Yes' instead?]
+            //
 
        } else if (where != -1) {
             this->done(where + 1000);
index 04988635581e26714b9fae68528ede6b4a9e7939..cdbdc07109a704247627e6b594c81d94e72e22c0 100644 (file)
@@ -19,8 +19,12 @@ private:
         bool allow_count;
         QLineEdit *le;
 
+        // abritrary size; might need to be more sophisicated someday
+        char alt_answer[26 + 1], alt_result[26 + 1];
+
 protected:
        virtual void keyPressEvent(QKeyEvent*);
+        void AltChoice(char answer, char result);
 
 private slots:
        void doneItem(int);