Freeciv21
Develop your civilization from humble roots to a global empire
tooltips.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  part of Freeciv21. Freeciv21 is free software: you can redistribute it
4  and/or modify it under the terms of the GNU General Public License as
5  published by the Free Software Foundation, either version 3 of the
6  License, or (at your option) any later version. You should have received
7  a copy of the GNU General Public License along with Freeciv21. If not,
8  see https://www.gnu.org/licenses/.
9  */
10 
11 // Qt
12 #include <QAbstractItemView>
13 #include <QHelpEvent>
14 #include <QModelIndex>
15 #include <QToolTip>
16 // utility
17 #include "fcintl.h"
18 #include "support.h"
19 // common
20 #include "helpdata.h"
21 // client
22 #include "client_main.h"
23 #include "climisc.h"
24 #include "fc_client.h"
25 #include "movement.h"
26 #include "tooltips.h"
27 
28 extern QString split_text(const QString &text, bool cut);
29 extern QString cut_helptext(const QString &text);
30 
34 bool fc_tooltip::eventFilter(QObject *obj, QEvent *ev)
35 {
36  QHelpEvent *help_event;
37  QString item_tooltip;
38  QRect rect;
39 
40  if (ev->type() == QEvent::ToolTip) {
41  QAbstractItemView *view =
42  qobject_cast<QAbstractItemView *>(obj->parent());
43 
44  if (!view) {
45  return false;
46  }
47 
48  help_event = static_cast<QHelpEvent *>(ev);
49  QPoint pos = help_event->pos();
50  QModelIndex index = view->indexAt(pos);
51 
52  if (!index.isValid()) {
53  return false;
54  }
55 
56  item_tooltip = view->model()->data(index, Qt::ToolTipRole).toString();
57  rect = view->visualRect(index);
58  rect.setX(rect.x() + help_event->globalPos().x());
59  rect.setY(rect.y() + help_event->globalPos().y());
60 
61  if (!item_tooltip.isEmpty()) {
62  QToolTip::showText(help_event->globalPos(), item_tooltip, view, rect);
63  } else {
64  QToolTip::hideText();
65  }
66 
67  return true;
68  }
69 
70  return false;
71 }
72 
76 QString bold(const QString &text) { return QString("<b>" + text + "</b>"); }
77 
82 QString get_tooltip_improvement(const impr_type *building,
83  struct city *pcity, bool ext)
84 {
85  QString def_str;
86  QString upkeep;
87  QString s1, s2, str;
88  const char *req = skip_intl_qualifier_prefix(_("?tech:None"));
89 
90  if (pcity != nullptr) {
91  upkeep = QString::number(city_improvement_upkeep(pcity, building));
92  } else {
93  upkeep = QString::number(building->upkeep);
94  }
95  requirement_vector_iterate(&building->obsolete_by, pobs)
96  {
97  if (pobs->source.kind == VUT_ADVANCE) {
98  req = advance_name_translation(pobs->source.value.advance);
99  break;
100  }
101  }
103  s2 = QString(req);
104  str = _("Obsolete by:");
105  str = str + " " + s2;
106  def_str = "<p style='white-space:pre'><b>"
107  + QString(improvement_name_translation(building)).toHtmlEscaped()
108  + "</b>\n";
109  if (pcity != nullptr) {
110  def_str += QString(_("Cost: %1, Upkeep: %2\n"))
111  .arg(impr_build_shield_cost(pcity, building))
112  .arg(upkeep)
113  .toHtmlEscaped();
114  } else {
116  nullptr, building);
117 
118  def_str += QString(_("Cost Estimate: %1, Upkeep: %2\n"))
119  .arg(cost_est)
120  .arg(upkeep)
121  .toHtmlEscaped();
122  }
123  if (s1.compare(s2) != 0) {
124  def_str = def_str + str.toHtmlEscaped() + "\n";
125  }
126  def_str = def_str + "\n";
127  if (ext) {
128  char buffer[8192];
129 
130  str = helptext_building(buffer, sizeof(buffer), client.conn.playing,
131  nullptr, building, client_current_nation_set());
132  str = cut_helptext(str);
133  str = split_text(str, true);
134  str = str.trimmed();
135  def_str = def_str + str.toHtmlEscaped();
136  }
137  return def_str;
138 }
139 
144 QString get_tooltip_unit(const struct unit_type *utype, bool ext)
145 {
146  QString def_str;
147  QString obsolete_str;
148  QString str;
149  const struct unit_type *obsolete;
150  struct advance *tech;
151 
152  def_str = "<b>" + QString(utype_name_translation(utype)).toHtmlEscaped()
153  + "</b>\n";
154  obsolete = utype->obsoleted_by;
155  if (obsolete) {
156  tech = obsolete->require_advance;
157  obsolete_str = QStringLiteral("</td></tr><tr><td colspan=\"3\">");
158  if (tech && tech != advance_by_number(0)) {
159  /* TRANS: this and nearby literal strings are interpreted
160  * as (Qt) HTML */
161  obsolete_str = obsolete_str
162  + QString(_("Obsoleted by %1 (%2)."))
163  .arg(utype_name_translation(obsolete),
165  .toHtmlEscaped();
166  } else {
167  obsolete_str = obsolete_str
168  + QString(_("Obsoleted by %1."))
169  .arg(utype_name_translation(obsolete))
170  .toHtmlEscaped();
171  }
172  }
173  def_str +=
174  "<table width=\"100\%\"><tr><td>" + bold(QString(_("Attack:"))) + " "
175  + QString::number(utype->attack_strength).toHtmlEscaped()
176  + QStringLiteral("</td><td>") + bold(QString(_("Defense:"))) + " "
177  + QString::number(utype->defense_strength).toHtmlEscaped()
178  + QStringLiteral("</td><td>") + bold(QString(_("Move:"))) + " "
179  + QString(move_points_text(utype->move_rate, true)).toHtmlEscaped()
180  + QStringLiteral("</td></tr><tr><td>") + bold(QString(_("Cost:")))
181  + " "
182  + QString::number(utype_build_shield_cost_base(utype)).toHtmlEscaped()
183  + QStringLiteral("</td><td colspan=\"2\">")
184  + bold(QString(_("Basic Upkeep:"))) + " "
185  + QString(helptext_unit_upkeep_str(utype)).toHtmlEscaped()
186  + QStringLiteral("</td></tr><tr><td>") + bold(QString(_("Hitpoints:")))
187  + " " + QString::number(utype->hp).toHtmlEscaped()
188  + QStringLiteral("</td><td>") + bold(QString(_("FirePower:"))) + " "
189  + QString::number(utype->firepower).toHtmlEscaped()
190  + QStringLiteral("</td><td>") + bold(QString(_("Vision:"))) + " "
191  + QString::number(static_cast<int>(sqrt(
192  static_cast<double>(utype->vision_radius_sq))))
193  .toHtmlEscaped()
194  + obsolete_str
195  + QStringLiteral("</td></tr></table><p style='white-space:pre'>");
196  if (ext) {
197  char buffer[8192];
198  char buf2[1];
199 
200  buf2[0] = '\0';
201  str = helptext_unit(buffer, sizeof(buffer), client.conn.playing, buf2,
202  utype, client_current_nation_set());
203  str = cut_helptext(str);
204  str = split_text(str, true);
205  str = str.trimmed().toHtmlEscaped();
206  def_str = def_str + str;
207  }
208 
209  return def_str;
210 };
211 
215 QString get_tooltip(const QVariant &qvar)
216 {
217  QString str, def_str, ret_str;
218  QStringList sl;
219  char buffer[8192];
220  char buf2[1];
221  struct universal *target;
222 
223  buf2[0] = '\0';
224  target = reinterpret_cast<universal *>(qvar.value<void *>());
225 
226  if (target == nullptr) {
227  } else if (VUT_UTYPE == target->kind) {
228  def_str = get_tooltip_unit(target->value.utype);
229  str = helptext_unit(buffer, sizeof(buffer), client.conn.playing, buf2,
231  } else {
232  if (!improvement_has_flag(target->value.building, IF_GOLD)) {
233  def_str = get_tooltip_improvement(target->value.building);
234  }
235 
236  str = helptext_building(buffer, sizeof(buffer), client.conn.playing,
237  nullptr, target->value.building,
239  }
240 
241  // Remove all lines from help which has '*' in first 3 chars
242  ret_str = cut_helptext(str);
243  ret_str = split_text(ret_str, true);
244  ret_str = ret_str.trimmed();
245  ret_str = def_str + ret_str.toHtmlEscaped();
246 
247  return ret_str;
248 }
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Return the upkeep (gold) needed each turn to upkeep the given improvement in the given city.
Definition: city.cpp:1202
bool eventFilter(QObject *obj, QEvent *event) override
Event filter for catching tooltip events.
Definition: tooltips.cpp:34
struct civclient client
struct nation_set * client_current_nation_set()
Returns the nation set in use.
Definition: climisc.cpp:1190
const char * skip_intl_qualifier_prefix(const char *str)
Some strings are ambiguous for translation.
Definition: fcintl.cpp:39
#define _(String)
Definition: fcintl.h:50
char * helptext_unit(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct unit_type *utype, const nation_set *nations_to_show)
Append misc dynamic text for units.
Definition: helpdata.cpp:1639
char * helptext_unit_upkeep_str(const struct unit_type *utype)
Returns pointer to static string with eg: "1 shield, 1 unhappy".
Definition: helpdata.cpp:4611
char * helptext_building(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct impr_type *pimprove, const nation_set *nations_to_show)
FIXME: Also, in principle these could be auto-generated once, inserted into pitem->text,...
Definition: helpdata.cpp:1181
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
Returns the number of shields it takes to build this improvement.
bool improvement_has_flag(const struct impr_type *pimprove, enum impr_flag_id flag)
Return TRUE if the impr has this flag otherwise FALSE.
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
int impr_estimate_build_shield_cost(const struct player *pplayer, const struct tile *ptile, const struct impr_type *pimprove)
Returns estimate of the number of shields it takes to build this improvement.
const char * move_points_text(int mp, bool reduce)
Simple version of move_points_text_full() – render positive movement points as text without any prefi...
Definition: movement.cpp:856
#define requirement_vector_iterate_end
Definition: requirements.h:80
#define requirement_vector_iterate(req_vec, preq)
Definition: requirements.h:78
Definition: tech.h:113
Definition: city.h:291
struct connection conn
Definition: client_main.h:89
struct player * playing
Definition: connection.h:142
int upkeep
Definition: improvement.h:69
struct requirement_vector obsolete_by
Definition: improvement.h:67
int defense_strength
Definition: unittype.h:480
int firepower
Definition: unittype.h:490
const struct unit_type * obsoleted_by
Definition: unittype.h:494
int vision_radius_sq
Definition: unittype.h:487
int move_rate
Definition: unittype.h:481
struct advance * require_advance
Definition: unittype.h:484
int hp
Definition: unittype.h:489
int attack_strength
Definition: unittype.h:479
enum universals_n kind
Definition: fc_types.h:740
universals_u value
Definition: fc_types.h:739
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Definition: tech.cpp:94
const char * advance_name_translation(const struct advance *padvance)
Return the (translated) name of the given advance/technology.
Definition: tech.cpp:274
QString bold(const QString &text)
'text' is assumed to have already been HTML-escaped if necessary
Definition: tooltips.cpp:76
QString cut_helptext(const QString &text)
Remove some text from given text(help text) to show as tooltip.
Definition: optiondlg.cpp:87
QString split_text(const QString &text, bool cut)
Splits long text to 80 characters.
Definition: optiondlg.cpp:45
QString get_tooltip_improvement(const impr_type *building, struct city *pcity, bool ext)
Returns improvement properties to append in tooltip ext is used to get extra info from help.
Definition: tooltips.cpp:82
QString get_tooltip(const QVariant &qvar)
Returns shortened help for given universal ( stored in qvar )
Definition: tooltips.cpp:215
QString get_tooltip_unit(const struct unit_type *utype, bool ext)
Returns unit properties to append in tooltip ext is used to get extra info from help.
Definition: tooltips.cpp:144
const struct unit_type * utype
Definition: fc_types.h:585
const struct impr_type * building
Definition: fc_types.h:579
int utype_build_shield_cost_base(const struct unit_type *punittype)
Returns the number of shields this unit type represents.
Definition: unittype.cpp:1168
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256