Qt popup_dialog's count entry
For Qt with 'popup_dialog' On, fix number entry when user types a digit (or '#') directly onto the dialog instead of clicking inside the Count box and then typing. Before, that first typed digit was starting out as selected, so typing the next digit replaced the selection instead of getting appended to the string of digits being constructed. Fixed by moving the relevant code to the KeyPress handler instead of re-executing the dialog. Also, if a keypress is just a modifier, ignore it. The next event should be the actual character. Prevents treating <shift> (and <caps lock>!) as useless dialog responses. Before this, attempting to type '#' to initiate a count wouldn't work because the <shift> part of shift+3 ended the dialog. Now '#' works (and is still optional; starting with a digit suffices).
This commit is contained in:
+3
-4
@@ -1,4 +1,4 @@
|
|||||||
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.317 $ $NHDT-Date: 1601595709 2020/10/01 23:41:49 $
|
NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.318 $ $NHDT-Date: 1601600393 2020/10/02 00:59:53 $
|
||||||
|
|
||||||
General Fixes and Modified Features
|
General Fixes and Modified Features
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
@@ -389,7 +389,6 @@ Qt: when selecting an extended command by typing its name, support <delete>
|
|||||||
Qt: switch to fixed-width font for menus
|
Qt: switch to fixed-width font for menus
|
||||||
Qt: don't disable [cancel] button when viewing inventory or other pick-none
|
Qt: don't disable [cancel] button when viewing inventory or other pick-none
|
||||||
menus; ESC works to dismiss those and [cancel] should be the same
|
menus; ESC works to dismiss those and [cancel] should be the same
|
||||||
Qt: bring status conditions up to 3.6 levels but new ones lack pictures
|
|
||||||
Qt: clicking on the window's Close button brought up a dialog offering
|
Qt: clicking on the window's Close button brought up a dialog offering
|
||||||
choices of "Save" and "Cancel"; picking Cancel sent nethack into an
|
choices of "Save" and "Cancel"; picking Cancel sent nethack into an
|
||||||
infinite loop with complaints about Qt's event loop already being
|
infinite loop with complaints about Qt's event loop already being
|
||||||
@@ -427,8 +426,8 @@ Qt: update message window's last message with player's response if it's a
|
|||||||
Qt: for line input, display the prompt+response in the message window
|
Qt: for line input, display the prompt+response in the message window
|
||||||
Qt: enable the popup_dialog WC option (result is a bit flakey but usable)
|
Qt: enable the popup_dialog WC option (result is a bit flakey but usable)
|
||||||
Qt: 3.6 catchup - show unexplored locations as unexplored rather than as stone
|
Qt: 3.6 catchup - show unexplored locations as unexplored rather than as stone
|
||||||
Qt: tried to honor 'showexp' but the value was unintentionally supressed by
|
Qt: tried to honor 'showexp' but the value was unintentionally suppressed by
|
||||||
[lack of] obsolete conditional EXP_ON_BOTL
|
[lack of definition for] obsolete conditional EXP_ON_BOTL
|
||||||
Qt: implement --More-- prompt to support MSGTYPE=stop
|
Qt: implement --More-- prompt to support MSGTYPE=stop
|
||||||
Qt+QSX: fix control key
|
Qt+QSX: fix control key
|
||||||
Qt+OSX: rename menu entry "nethack->Preferences..." for invoking nethack's
|
Qt+OSX: rename menu entry "nethack->Preferences..." for invoking nethack's
|
||||||
|
|||||||
+2
-2
@@ -956,7 +956,7 @@ void NetHackQtMainWindow::doQuit(bool)
|
|||||||
case 0:
|
case 0:
|
||||||
// quit -- bypass the prompting preformed by done2()
|
// quit -- bypass the prompting preformed by done2()
|
||||||
g.program_state.stopprint++;
|
g.program_state.stopprint++;
|
||||||
done(QUIT);
|
::done(QUIT);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
@@ -1260,7 +1260,7 @@ void NetHackQtMainWindow::closeEvent(QCloseEvent *e UNUSED)
|
|||||||
// quit -- bypass the prompting preformed by done2()
|
// quit -- bypass the prompting preformed by done2()
|
||||||
ok = 1;
|
ok = 1;
|
||||||
g.program_state.stopprint++;
|
g.program_state.stopprint++;
|
||||||
done(QUIT);
|
::done(QUIT);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-71
@@ -35,7 +35,9 @@ NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent, const QString &q,
|
|||||||
const char *ch, char df) :
|
const char *ch, char df) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
question(q), choices(ch), def(df),
|
question(q), choices(ch), def(df),
|
||||||
keypress('\033')
|
keypress('\033'),
|
||||||
|
allow_count(false),
|
||||||
|
le((QLineEdit *) NULL)
|
||||||
{
|
{
|
||||||
setWindowTitle("NetHack: Question");
|
setWindowTitle("NetHack: Question");
|
||||||
|
|
||||||
@@ -49,6 +51,7 @@ NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent, const QString &q,
|
|||||||
if (choices) {
|
if (choices) {
|
||||||
// special handling for wearing rings; prompt asks "right or left?"
|
// special handling for wearing rings; prompt asks "right or left?"
|
||||||
// but side-by-side buttons look better with [left][right] instead
|
// but side-by-side buttons look better with [left][right] instead
|
||||||
|
// (assumes that we're using left to right layout)
|
||||||
if (!strcmp(choices, "rl")) {
|
if (!strcmp(choices, "rl")) {
|
||||||
choices = lrq;
|
choices = lrq;
|
||||||
if (!def)
|
if (!def)
|
||||||
@@ -57,6 +60,7 @@ NetHackQtYnDialog::NetHackQtYnDialog(QWidget *parent, const QString &q,
|
|||||||
// if count is allowed, explicitly add the digits as valid
|
// if count is allowed, explicitly add the digits as valid
|
||||||
} else if (!strncmp(choices, "yn#", (size_t) 3)) {
|
} else if (!strncmp(choices, "yn#", (size_t) 3)) {
|
||||||
::yn_number = 0L;
|
::yn_number = 0L;
|
||||||
|
allow_count = true;
|
||||||
|
|
||||||
if (!strchr(choices, '9')) {
|
if (!strchr(choices, '9')) {
|
||||||
copynchars(altchoices, choices, BUFSZ - 1);
|
copynchars(altchoices, choices, BUFSZ - 1);
|
||||||
@@ -148,8 +152,7 @@ char NetHackQtYnDialog::Exec()
|
|||||||
QButtonGroup *bgroup = new QButtonGroup(group);
|
QButtonGroup *bgroup = new QButtonGroup(group);
|
||||||
|
|
||||||
int nchoices=ch.length();
|
int nchoices=ch.length();
|
||||||
bool allow_count = (ch.left(3) == QString("yn#")),
|
bool is_ynq = (ch == QString("ynq")), // [ Yes ][ No ][Cancel]
|
||||||
is_ynq = (ch == QString("ynq")), // [ Yes ][ No ][Cancel]
|
|
||||||
is_yn = (ch == QString("yn")), // [Yes ][ No ]
|
is_yn = (ch == QString("yn")), // [Yes ][ No ]
|
||||||
is_lr = (ch == QString(lrq)); // [ Left ][Right ]
|
is_lr = (ch == QString(lrq)); // [ Left ][Right ]
|
||||||
|
|
||||||
@@ -160,7 +163,7 @@ char NetHackQtYnDialog::Exec()
|
|||||||
int butheight = fontMetrics().height() * 2 + 5,
|
int butheight = fontMetrics().height() * 2 + 5,
|
||||||
butwidth = (butheight - 5)
|
butwidth = (butheight - 5)
|
||||||
* ((is_ynq || is_lr) ? 3 : is_yn ? 2 : 1) + 5;
|
* ((is_ynq || is_lr) ? 3 : is_yn ? 2 : 1) + 5;
|
||||||
if (butwidth == butheight) { // square, room for one character or ^c
|
if (butwidth == butheight) { // square, enough room for C or ^C
|
||||||
// some characters will be labelled by name rather than by
|
// some characters will be labelled by name rather than by
|
||||||
// keystroke so will need wider buttons
|
// keystroke so will need wider buttons
|
||||||
for (int i = 0; i < nchoices; ++i) {
|
for (int i = 0; i < nchoices; ++i) {
|
||||||
@@ -248,7 +251,6 @@ char NetHackQtYnDialog::Exec()
|
|||||||
connect(bgroup, SIGNAL(buttonClicked(int)), this, SLOT(doneItem(int)));
|
connect(bgroup, SIGNAL(buttonClicked(int)), this, SLOT(doneItem(int)));
|
||||||
|
|
||||||
QLabel *lb = 0;
|
QLabel *lb = 0;
|
||||||
QLineEdit *le = 0;
|
|
||||||
if (allow_count) {
|
if (allow_count) {
|
||||||
// put the Count widget in between [y] and [n][a][q]
|
// put the Count widget in between [y] and [n][a][q]
|
||||||
lb = new QLabel("Count:");
|
lb = new QLabel("Count:");
|
||||||
@@ -278,63 +280,24 @@ char NetHackQtYnDialog::Exec()
|
|||||||
// typing in digits followed by <return> is 'normal' operation.
|
// typing in digits followed by <return> is 'normal' operation.
|
||||||
// However, typing a digit without clicking first will set focus
|
// However, typing a digit without clicking first will set focus
|
||||||
// to the count widget with that typed digit preloaded.
|
// to the count widget with that typed digit preloaded.
|
||||||
// FIXME: Unfortunately, it will also be selected, so typing
|
|
||||||
// another digit replaces it instead of being the next digit in
|
|
||||||
// a multiple-digit number.
|
|
||||||
//
|
//
|
||||||
// Theoretically typing '#' does this to, with a 0 preloaded
|
exec();
|
||||||
// and intentionally selected, but the KeyPress bug (below) of
|
int res = result();
|
||||||
// treating <shift> as a complete response prevents use of
|
if (res == 0) {
|
||||||
// shift+3 from being used to generate '#'.
|
choice = is_lr ? '\033' : ch_esc ? ch_esc : def ? def : ' ';
|
||||||
//
|
} else if (res == 1) {
|
||||||
bool retry; // for digit + re-activate widget + rest of number
|
choice = def ? def : ch_esc ? ch_esc : ' ';
|
||||||
do {
|
} else if (res >= 1000) {
|
||||||
retry = false; // might have a second pass (but not a third)
|
choice = (char) ch[res - 1000].cell();
|
||||||
exec();
|
}
|
||||||
int res = result();
|
|
||||||
if (res == 0) {
|
|
||||||
choice = is_lr ? '\033' : ch_esc ? ch_esc : def ? def : ' ';
|
|
||||||
} else if (res == 1) {
|
|
||||||
choice = def ? def : ch_esc ? ch_esc : ' ';
|
|
||||||
} else if (res >= 1000) {
|
|
||||||
choice = (char) ch[res - 1000].cell();
|
|
||||||
|
|
||||||
if (allow_count && strchr("#0123456789", choice)) {
|
|
||||||
if (choice == '#') {
|
|
||||||
// 0 will be preselected; typing anything replaces it
|
|
||||||
le->insert(QString("0"));
|
|
||||||
} else {
|
|
||||||
#if 1
|
|
||||||
le->insert(QString(choice));
|
|
||||||
//
|
|
||||||
// FIXME: despite the documentation claiming that
|
|
||||||
// 'false' cancels any selection, the digit always
|
|
||||||
// starts out selected (from running exec() again?)
|
|
||||||
// so typing the next digit replaces it instead of
|
|
||||||
// being appended to it unless the player uses
|
|
||||||
// right-arrow to move the cursor.
|
|
||||||
//
|
|
||||||
le->end(false);
|
|
||||||
#else
|
|
||||||
// this also claims to cancel any selection and
|
|
||||||
// position the cursor after the text but actually
|
|
||||||
// leaves the digit selected, ready to be overwritten
|
|
||||||
le->setText(QString(choice));
|
|
||||||
le->setModified(true);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
// (don't know whether this actually does anything useful)
|
|
||||||
le->setAttribute(Qt::WA_KeyboardFocusChange, true);
|
|
||||||
le->setFocus(Qt::ActiveWindowFocusReason);
|
|
||||||
retry = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (retry);
|
|
||||||
|
|
||||||
// non-Null 'le' implies 'allow_count'; having a grayed-out '#'
|
// non-Null 'le' implies 'allow_count'; having a grayed-out '#'
|
||||||
// present in the QLineEdit widget doesn't affect its isEmpty() test
|
// present in the QLineEdit widget doesn't affect its isEmpty() test
|
||||||
if (le && !le->text().isEmpty()) {
|
if (le && !le->text().isEmpty()) {
|
||||||
::yn_number = le->text().toLong();
|
QString text(le->text());
|
||||||
|
if (text[0] == "#")
|
||||||
|
text = text.mid(1);
|
||||||
|
::yn_number = text.toLong();
|
||||||
choice = '#';
|
choice = '#';
|
||||||
}
|
}
|
||||||
keypress = choice;
|
keypress = choice;
|
||||||
@@ -358,24 +321,37 @@ char NetHackQtYnDialog::Exec()
|
|||||||
|
|
||||||
void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
|
void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// FIXME: on OSX (possibly elsewhere), this accepts <shift>
|
|
||||||
// (and even <caps lock>) as the entire response before the user
|
|
||||||
// has a chance to type any character to be shifted.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Don't want QDialog's Return/Esc behaviour
|
|
||||||
//RLC ...or do we?
|
|
||||||
QString text(event->text());
|
QString text(event->text());
|
||||||
if (choices == NULL || choices[0] == 0) {
|
if (text.isEmpty() && event->modifiers())
|
||||||
if (text != "") {
|
return;
|
||||||
|
|
||||||
|
if (!choices || !*choices) {
|
||||||
|
if (!text.isEmpty()) {
|
||||||
keypress = text.toUcs4()[0];
|
keypress = text.toUcs4()[0];
|
||||||
done(1);
|
this->done(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int where = QString::fromLatin1(choices).indexOf(text);
|
int where = QString::fromLatin1(choices).indexOf(text);
|
||||||
if (where != -1 && text != "#") {
|
|
||||||
done(where+1000);
|
if (where != -1 && allow_count
|
||||||
|
&& strchr("#0123456789", text[0].cell())) {
|
||||||
|
if (text == "#") {
|
||||||
|
// 0 will be preselected; typing anything replaces it
|
||||||
|
le->setText(QString("0"));
|
||||||
|
le->home(true);
|
||||||
|
} else {
|
||||||
|
// digit will not be preselected; typing another appends
|
||||||
|
le->setText(text);
|
||||||
|
le->end(false);
|
||||||
|
}
|
||||||
|
// (don't know whether this actually does anything useful)
|
||||||
|
le->setAttribute(Qt::WA_KeyboardFocusChange, true);
|
||||||
|
le->setFocus(Qt::ActiveWindowFocusReason);
|
||||||
|
|
||||||
|
} else if (where != -1) {
|
||||||
|
this->done(where + 1000);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
QDialog::keyPressEvent(event);
|
QDialog::keyPressEvent(event);
|
||||||
}
|
}
|
||||||
@@ -384,7 +360,7 @@ void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event)
|
|||||||
|
|
||||||
void NetHackQtYnDialog::doneItem(int i)
|
void NetHackQtYnDialog::doneItem(int i)
|
||||||
{
|
{
|
||||||
done(i+1000);
|
this->done(i + 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nethack_qt_
|
} // namespace nethack_qt_
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ private:
|
|||||||
const char* choices;
|
const char* choices;
|
||||||
char def;
|
char def;
|
||||||
char keypress;
|
char keypress;
|
||||||
|
bool allow_count;
|
||||||
|
QLineEdit *le;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void keyPressEvent(QKeyEvent*);
|
virtual void keyPressEvent(QKeyEvent*);
|
||||||
|
|||||||
Reference in New Issue
Block a user