Qt paperdoll - tool tips used to describe items
New for Qt, moving the mouse over one of the slots in the paperdoll inventory subset and letting it pause there will use Qt's tool tip mechanism to give a description of the item under the pointer, if there is one, or of what the slot would contain when there isn't. So "e - uncursed leather gloves (being worn)" or "no gloves" when the pointer is over the glove slot. If you do something with the keyboard to make the paperdoll change while the mouse is still hovering, you'll need to move the pointer slightly to have Qt recheck for tool tip at that spot. It may be feasible to force an immediate update, but I'm satisfied with how it's working. Interestingly, you can move pointer and hover while yn_function() has asked you to pick an inventory item and is waiting for an answer. Mostly useful for Take-off/Remove or #adjust.
This commit is contained in:
@@ -43,10 +43,25 @@ NetHackQtInvUsageWindow::NetHackQtInvUsageWindow(QWidget* parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
// needed to enable tool tips
|
||||
setMouseTracking(true);
|
||||
|
||||
for (int x = 0; x <= 2; ++x)
|
||||
for (int y = 0; y <= 5; ++y)
|
||||
tips[x][y] = NULL;
|
||||
}
|
||||
|
||||
void NetHackQtInvUsageWindow::drawWorn(QPainter& painter, obj* nhobj,
|
||||
int x, int y, bool canbe)
|
||||
NetHackQtInvUsageWindow::~NetHackQtInvUsageWindow()
|
||||
{
|
||||
for (int x = 0; x <= 2; ++x)
|
||||
for (int y = 0; y <= 5; ++y)
|
||||
if (tips[x][y])
|
||||
free((void *) tips[x][y]), tips[x][y] = NULL;
|
||||
}
|
||||
|
||||
void NetHackQtInvUsageWindow::drawWorn(QPainter &painter, obj *nhobj,
|
||||
int x, int y, // cell index, not pixels
|
||||
const char *alttip, bool canbe)
|
||||
{
|
||||
short int glyph;
|
||||
int border;
|
||||
@@ -54,16 +69,39 @@ void NetHackQtInvUsageWindow::drawWorn(QPainter& painter, obj* nhobj,
|
||||
if (nhobj) {
|
||||
border = BORDER_DEFAULT;
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
// color margin around cell containing item whose BUC state is known
|
||||
if (Role_if('P') && !Blind)
|
||||
nhobj->bknown = 1;
|
||||
if (nhobj->bknown)
|
||||
border = nhobj->cursed ? BORDER_CURSED
|
||||
: !nhobj->blessed ? BORDER_UNCURSED
|
||||
: BORDER_BLESSED;
|
||||
|
||||
// set up a tool tip describing the item that will be displayed here
|
||||
char *itmnam = xprname(nhobj, (char *) 0, nhobj->invlet, TRUE, 0L, 0L);
|
||||
if (tips[x][y] && strlen(itmnam) > strlen(tips[x][y]))
|
||||
free((void *) tips[x][y]), tips[x][y] = NULL;
|
||||
|
||||
if (tips[x][y])
|
||||
Strcpy(tips[x][y], itmnam);
|
||||
else
|
||||
tips[x][y] = dupstr(itmnam);
|
||||
#endif
|
||||
glyph = obj_to_glyph(nhobj, rn2_on_display_rng);
|
||||
} else {
|
||||
border = NO_BORDER;
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
// caller passes an alternative tool tip for empty cells
|
||||
if (tips[x][y] && (!alttip || strlen(alttip) > strlen(tips[x][y])))
|
||||
free((void *) tips[x][y]), tips[x][y] = NULL;
|
||||
|
||||
if (tips[x][y]) // above guarantees that test fails if alttip is Null
|
||||
Strcpy(tips[x][y], alttip);
|
||||
else if (alttip)
|
||||
tips[x][y] = dupstr(alttip);
|
||||
#else
|
||||
nhUse(alttip);
|
||||
#endif
|
||||
glyph = canbe ? cmap_to_glyph(S_room) : GLYPH_UNEXPLORED;
|
||||
}
|
||||
qt_settings->glyphs().drawBorderedCell(painter, glyph, x, y, border);
|
||||
@@ -92,51 +130,66 @@ void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
|
||||
qt_settings->doll_is_shown = false;
|
||||
if (!qt_settings->doll_is_shown)
|
||||
return;
|
||||
// set glyphs() for the paperdoll; might be different size than map's
|
||||
qt_settings->glyphs().setSize(qt_settings->dollWidth,
|
||||
qt_settings->dollHeight);
|
||||
|
||||
/* for drawWorn()'s use of obj->invlet */
|
||||
if (!flags.invlet_constant)
|
||||
reassign();
|
||||
#endif
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(this);
|
||||
|
||||
// Blanks
|
||||
drawWorn(painter, 0, 0, 5, false);
|
||||
drawWorn(painter, 0, 2, 5, false);
|
||||
if (u.twoweap) // empty alt weapon slot, show uswapwep in shield slot
|
||||
drawWorn(painter, 0, 0, 0, false);
|
||||
|
||||
// TODO: render differently if known to be non-removable (known cursed)
|
||||
drawWorn(painter, uarm, 1, 3); // Armour
|
||||
drawWorn(painter, uarmc, 1, 2); // Cloak
|
||||
drawWorn(painter, uarmh, 1, 0); // Helmet
|
||||
// shield slot varies depending upon weapon usage
|
||||
if (u.twoweap)
|
||||
drawWorn(painter, uswapwep, 0, 1); // Secondary weapon, in use
|
||||
else if (uwep && bimanual(uwep))
|
||||
drawWorn(painter, uwep, 0, 1); // Two-handed weapon shown twice
|
||||
// String argument is for a tool tip when the object in question is Null.
|
||||
//
|
||||
// left column
|
||||
/* uswapwep slot varies depending upon dual-wielding state;
|
||||
shown in shield slot when actively wielded, so uswapwep slot is empty
|
||||
then and an alternate tool tip is used to explain that emptiness */
|
||||
if (!u.twoweap)
|
||||
drawWorn(painter, uswapwep, 0, 0, "no alternate weapon");
|
||||
else
|
||||
drawWorn(painter, uarms, 0, 1); // Shield (might be blank)
|
||||
drawWorn(painter, uarmg, 0, 2); // Gloves
|
||||
drawWorn(painter, uarmf, 1, 5); // Shoes (feet)
|
||||
drawWorn(painter, uarmu, 1, 4); // Undershirt
|
||||
drawWorn(painter, uleft, 0, 3); // RingL
|
||||
drawWorn(painter, uright, 2, 3); // RingR
|
||||
drawWorn(painter, NULL, 0, 0, "secondary weapon is wielded");
|
||||
/* shield slot varies depending upon weapon usage;
|
||||
no alt tool tip is needed for first two cases because object will
|
||||
never be Null when the corresponding tests pass */
|
||||
if (u.twoweap)
|
||||
drawWorn(painter, uswapwep, 0, 1, NULL); // secondary weapon, in use
|
||||
else if (uwep && bimanual(uwep))
|
||||
drawWorn(painter, uwep, 0, 1, NULL); // two-handed uwep shown twice
|
||||
else
|
||||
drawWorn(painter, uarms, 0, 1, "no shield");
|
||||
drawWorn(painter, uarmg, 0, 2, "no gloves");
|
||||
drawWorn(painter, uleft, 0, 3, "no left ring");
|
||||
/* light source and leash aren't unique and don't have pointers defined */
|
||||
drawWorn(painter, find_tool(LEASH), 0, 4, "no leashes in use");
|
||||
drawWorn(painter, NULL, 0, 5, NULL, false); // always blank
|
||||
|
||||
drawWorn(painter, uwep, 2, 1); // Weapon
|
||||
drawWorn(painter, !u.twoweap ? uswapwep : NULL, 0, 0); // Alternate weapon
|
||||
drawWorn(painter, uquiver, 2, 2); // Quiver
|
||||
drawWorn(painter, uamul, 1, 1); // Amulet
|
||||
drawWorn(painter, ublindf, 2, 0); // Blindfold/Towel/Lenses
|
||||
// middle column; no unused slots
|
||||
drawWorn(painter, uarmh, 1, 0, "no helmet");
|
||||
drawWorn(painter, uamul, 1, 1, "no amulet");
|
||||
drawWorn(painter, uarmc, 1, 2, "no cloak");
|
||||
drawWorn(painter, uarm, 1, 3, "no suit");
|
||||
drawWorn(painter, uarmu, 1, 4, "no shirt");
|
||||
drawWorn(painter, uarmf, 1, 5, "no boots");
|
||||
|
||||
// light source and leash aren't unique and don't have pointers defined
|
||||
drawWorn(painter, find_tool(LEASH), 0, 4);
|
||||
// OIL_LAMP matches lit candles, lamps, lantern, and candelabrum (and will
|
||||
// also duplicate Sunsword when it is wielded and shown in the uwep slot)
|
||||
drawWorn(painter, find_tool(OIL_LAMP), 2, 4);
|
||||
// right column
|
||||
drawWorn(painter, ublindf, 2, 0, "no eyewear"); // blindfold/towel/lenses
|
||||
drawWorn(painter, uwep, 2, 1, "no weapon");
|
||||
drawWorn(painter, uquiver, 2, 2, "nothing readied for firing"); // quiver
|
||||
drawWorn(painter, uright, 2, 3, "no right ring");
|
||||
/* OIL_LAMP matches lit candles, lamps, lantern, and candelabrum
|
||||
(and might also duplicate Sunsword when it is wielded--hence lit--
|
||||
depending upon whether another light source precedes it in invent) */
|
||||
drawWorn(painter, find_tool(OIL_LAMP), 2, 4, "no active light sources");
|
||||
drawWorn(painter, NULL, 2, 5, NULL, false); // always blank
|
||||
|
||||
painter.end();
|
||||
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
// reset glyphs() to the ones being used for the map
|
||||
qt_settings->glyphs().setSize(qt_settings->tileWidth,
|
||||
qt_settings->tileHeight);
|
||||
#endif
|
||||
@@ -145,7 +198,7 @@ void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*)
|
||||
QSize NetHackQtInvUsageWindow::sizeHint(void) const
|
||||
{
|
||||
if (qt_settings) {
|
||||
int w = 0, h = 0;
|
||||
int w = 0, h = 1; // one pixel margin at top
|
||||
// 1+X+1: one pixel border surrounding each tile in the paper doll,
|
||||
// so +1 left and +1 right, also +1 above and +1 below
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
@@ -167,6 +220,56 @@ QSize NetHackQtInvUsageWindow::sizeHint(void) const
|
||||
}
|
||||
}
|
||||
|
||||
// ENHANCED_PAPERDOLL - called when a tool tip is triggered by hovering mouse
|
||||
bool NetHackQtInvUsageWindow::tooltip_event(QHelpEvent *tipevent)
|
||||
{
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
if (iflags.wc_ascii_map)
|
||||
qt_settings->doll_is_shown = false;
|
||||
if (!qt_settings->doll_is_shown) {
|
||||
tipevent->ignore();
|
||||
return false;
|
||||
}
|
||||
int wd = qt_settings->dollWidth,
|
||||
ht = qt_settings->dollHeight;
|
||||
|
||||
// inverse of drawBorderedCell();
|
||||
int yoffset = 1, // tiny extra margin at top
|
||||
ex = tipevent->pos().x(),
|
||||
ey = tipevent->pos().y() - yoffset,
|
||||
// KISS: treat 1-pixel margin around cells as part of enclosed cell
|
||||
cellx = ex / (wd + 2),
|
||||
celly = ey / (ht + 2);
|
||||
|
||||
const char *tip = (cellx >= 0 && cellx <= 2 && celly >= 0 && celly <= 5)
|
||||
? tips[cellx][celly] : NULL;
|
||||
if (tip && *tip) {
|
||||
QToolTip::showText(tipevent->globalPos(), QString(tip));
|
||||
} else {
|
||||
QToolTip::hideText();
|
||||
tipevent->ignore();
|
||||
}
|
||||
#else
|
||||
nhUse(tipevent);
|
||||
#endif /* ENHANCED_PAPERDOLL */
|
||||
return true;
|
||||
}
|
||||
|
||||
// ENHANCED_PAPERDOLL - event handler is necessary to support tool tips
|
||||
bool NetHackQtInvUsageWindow::event(QEvent *event)
|
||||
{
|
||||
#ifdef ENHANCED_PAPERDOLL
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
QHelpEvent *tipevent = static_cast <QHelpEvent *> (event);
|
||||
return tooltip_event(tipevent);
|
||||
}
|
||||
#endif
|
||||
// with this routine intercepting events, we need to pass along
|
||||
// paint and mouse-press events to have them handled
|
||||
return QWidget::event(event);
|
||||
|
||||
}
|
||||
|
||||
// ENHANCED_PAPERDOLL - clicking on the PaperDoll runs #seeall ('*')
|
||||
void NetHackQtInvUsageWindow::mousePressEvent(QMouseEvent *event UNUSED)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user