Freeciv21
Develop your civilization from humble roots to a global empire
helpdlg.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2023 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 <QApplication>
13 #include <QGraphicsDropShadowEffect>
14 #include <QPainter>
15 #include <QProgressBar>
16 #include <QScreen>
17 #include <QScrollArea>
18 #include <QSplitter>
19 #include <QTreeWidget>
20 #include <QVBoxLayout>
21 // utility
22 #include "fcintl.h"
23 // common
24 #include "government.h"
25 #include "helpdata.h"
26 #include "movement.h"
27 #include "nation.h"
28 #include "specialist.h"
29 #include "terrain.h"
30 // client
31 #include "canvas.h"
32 #include "client_main.h"
33 #include "climisc.h"
34 #include "fc_client.h"
35 #include "fonts.h"
36 #include "helpdlg.h"
37 #include "tileset/tilespec.h"
38 #include "views/view_map_common.h"
39 
40 #define MAX_HELP_TEXT_SIZE 8192
41 #define REQ_LABEL_NEVER _("(Never)")
42 #define REQ_LABEL_NONE _("?tech:None")
43 static help_dialog *help_dlg = nullptr;
44 QPixmap *terrain_canvas(struct terrain *terrain,
45  const struct extra_type *resource = nullptr,
46  enum extra_cause cause = EC_COUNT);
47 
48 extern QList<const struct help_item *> *help_nodes;
49 
56 void popup_help_dialog_typed(const char *item, enum help_page_type htype)
57 {
58  int pos;
59  const help_item *topic;
60 
61  if (!help_dlg) {
62  help_dlg = new help_dialog();
63  }
64  topic = get_help_item_spec(item, htype, &pos);
65  if (pos >= 0) {
66  help_dlg->set_topic(topic);
67  }
68  help_dlg->setVisible(true);
69  help_dlg->activateWindow();
70 }
71 
76 {
77  if (help_dlg) {
78  help_dlg->setVisible(false);
79  help_dlg->deleteLater();
80  help_dlg = nullptr;
81  }
82 }
83 
88 {
89  if (help_dlg) {
91  }
92 }
93 
97 help_dialog::help_dialog(QWidget *parent) : qfc_dialog(parent)
98 {
99  QHBoxLayout *hbox;
100  QPushButton *but;
101  QTreeWidgetItem *first;
102  QVBoxLayout *layout;
103  QWidget *buttons;
104 
105  setWindowTitle(_("Freeciv21 Help Browser"));
106  history_pos = -1;
107  update_history = true;
108  layout = new QVBoxLayout(this);
109 
110  splitter = new QSplitter(this);
111  layout->addWidget(splitter, 10);
112 
113  tree_wdg = new QTreeWidget();
114  tree_wdg->setHeaderHidden(true);
115  make_tree();
116  splitter->addWidget(tree_wdg);
117 
119  connect(tree_wdg, &QTreeWidget::currentItemChanged, this,
120  &help_dialog::item_changed, Qt::QueuedConnection);
121  help_wdg->layout()->setContentsMargins(0, 0, 0, 0);
122  splitter->addWidget(help_wdg);
123 
124  buttons = new QWidget;
125  hbox = new QHBoxLayout;
126  prev_butt = new QPushButton(
127  style()->standardIcon(QStyle::QStyle::SP_ArrowLeft), (""));
128  connect(prev_butt, &QAbstractButton::clicked, this,
130  hbox->addWidget(prev_butt);
131  next_butt = new QPushButton(
132  style()->standardIcon(QStyle::QStyle::SP_ArrowRight), (""));
133  connect(next_butt, &QAbstractButton::clicked, this,
135  hbox->addWidget(next_butt);
136  hbox->addStretch(20);
137  but = new QPushButton(style()->standardIcon(QStyle::SP_DialogHelpButton),
138  _("About Qt"));
139  connect(but, &QPushButton::pressed, &QApplication::aboutQt);
140  hbox->addWidget(but, Qt::AlignRight);
141  but = new QPushButton(
142  style()->standardIcon(QStyle::SP_DialogDiscardButton), _("Close"));
143  connect(but, &QPushButton::pressed, this, &QWidget::close);
144  hbox->addWidget(but, Qt::AlignRight);
145  buttons->setLayout(hbox);
146  layout->addWidget(buttons, 0, Qt::AlignBottom);
147 
148  first = tree_wdg->topLevelItem(0);
149  if (first) {
150  tree_wdg->setCurrentItem(first);
151  }
152 }
153 
158 
162 void help_dialog::hideEvent(QHideEvent *event)
163 {
164  Q_UNUSED(event)
165  king()->qt_settings.help_geometry = saveGeometry();
166  king()->qt_settings.help_splitter1 = splitter->saveState();
167 }
168 
172 void help_dialog::showEvent(QShowEvent *event)
173 {
174  Q_UNUSED(event)
175 
176  if (!king()->qt_settings.help_geometry.isNull()) {
177  restoreGeometry(king()->qt_settings.help_geometry);
178  splitter->restoreState(king()->qt_settings.help_splitter1);
179  // Make sure the size isn't larger than the screen
180  resize(size().boundedTo(screen()->availableSize()));
181  } else {
182  auto rect = screen()->availableGeometry();
183  resize(qMax((rect.width() * 3) / 4, 1280),
184  qMax((rect.height() * 3) / 4, 800));
185  splitter->setSizes({rect.width() / 10, rect.width() / 3});
186  }
187 }
188 
192 void help_dialog::closeEvent(QCloseEvent *event)
193 {
194  Q_UNUSED(event)
195  king()->qt_settings.help_geometry = saveGeometry();
196  king()->qt_settings.help_splitter1 = splitter->saveState();
197 }
198 
203 {
204  char *title;
205  int dep;
206  int i;
207  QHash<int, QTreeWidgetItem *> hash;
208  QIcon icon;
209  QTreeWidgetItem *item;
210  const QPixmap *spite;
211  struct advance *padvance;
212  QPixmap *pcan;
213  struct extra_type *pextra;
214  struct government *gov;
215  struct impr_type *imp;
216  struct nation_type *nation;
217  struct terrain *pterrain;
218  struct unit_type *f_type;
219 
220  for (const auto *pitem : qAsConst(*help_nodes)) {
221  const char *s;
222  int last;
223  title = pitem->topic;
224  for (s = pitem->topic; *s == ' '; s++) {
225  // nothing
226  }
227 
228  item = new QTreeWidgetItem(QStringList(title));
229  topics_map[item] = pitem;
230  dep = s - pitem->topic;
231  hash.insert(dep, item);
232 
233  if (dep == 0) {
234  tree_wdg->addTopLevelItem(item);
235  } else {
236  last = dep - 1;
237  spite = nullptr;
238  icon = QIcon();
239 
240  switch (pitem->type) {
241  case HELP_EXTRA: {
242  pextra = extra_type_by_translated_name(s);
243  auto sprs = fill_basic_extra_sprite_array(tileset, pextra);
244  if (!sprs.empty()) {
245  QPixmap pix(*sprs.front().sprite);
246  QPainter p;
247  p.begin(&pix);
248  for (std::size_t i = 1; i < sprs.size(); ++i) {
249  p.drawPixmap(0, 0, *sprs[i].sprite);
250  }
251  icon = QIcon(pix);
252  }
253  } break;
254 
255  case HELP_GOVERNMENT:
257  spite = get_government_sprite(tileset, gov);
258  break;
259 
260  case HELP_IMPROVEMENT:
261  case HELP_WONDER:
263  spite = get_building_sprite(tileset, imp);
264  break;
265  case HELP_NATIONS:
266  nation = nation_by_translated_plural(s);
267  spite = get_nation_flag_sprite(tileset, nation);
268  break;
269  case HELP_TECH:
270  padvance = advance_by_translated_name(s);
271  if (padvance && !is_future_tech(i = advance_number(padvance))) {
272  spite = get_tech_sprite(tileset, i);
273  }
274  break;
275 
276  case HELP_TERRAIN:
277  pterrain = terrain_by_translated_name(s);
278  pcan = terrain_canvas(pterrain);
279  if (pcan) {
280  icon = QIcon(*pcan);
281  delete pcan;
282  }
283  break;
284 
285  case HELP_UNIT:
286  f_type = unit_type_by_translated_name(s);
287  if (f_type) {
288  spite = get_unittype_sprite(tileset, f_type, direction8_invalid());
289  }
290  break;
291 
292  default:
293  break;
294  }
295  if (spite) {
296  icon = QIcon(*spite);
297  }
298  if (!icon.isNull()) {
299  item->setIcon(0, icon);
300  }
301 
302  hash.value(last)->addChild(item);
303  }
304  }
305 }
306 
311 {
312  help_wdg->set_topic(topic);
313  // Reverse search of the item to select.
314  QHash<QTreeWidgetItem *, const help_item *>::const_iterator i =
315  topics_map.cbegin();
316  for (; i != topics_map.cend(); ++i) {
317  if (i.value() == topic) {
318  tree_wdg->setCurrentItem(i.key());
319  tree_wdg->expandItem(i.key());
320  break;
321  }
322  }
323 }
324 
329 {
330  QTreeWidgetItem *i;
331 
332  update_history = false;
333  if (history_pos < item_history.count()) {
334  history_pos++;
335  }
336  i = item_history.value(history_pos);
337  if (i != nullptr) {
338  tree_wdg->setCurrentItem(i);
339  }
340 }
341 
346 {
347  QTreeWidgetItem *i;
348 
349  update_history = false;
350  if (history_pos > 0) {
351  history_pos--;
352  }
353  i = item_history.value(history_pos);
354  if (i != nullptr) {
355  tree_wdg->setCurrentItem(i);
356  }
357 }
358 
363 {
364  if (history_pos == 0) {
365  prev_butt->setEnabled(false);
366  } else {
367  prev_butt->setEnabled(true);
368  }
369  if (history_pos >= item_history.size() - 1) {
370  next_butt->setEnabled(false);
371  } else {
372  next_butt->setEnabled(true);
373  }
374 }
375 
379 void help_dialog::item_changed(QTreeWidgetItem *item, QTreeWidgetItem *prev)
380 {
381  if (prev == item) {
382  return;
383  }
384 
386 
387  if (update_history) {
388  history_pos++;
389  item_history.append(item);
390  } else {
391  update_history = true;
392  }
393  update_buttons();
394 
395  // Collapse the subtree of 'prev' not needed to see 'item'
396  if (prev) {
397  auto item_parents = std::set<QTreeWidgetItem *>();
398  for (auto i = item; i != nullptr; i = i->parent()) {
399  item_parents.insert(i);
400  }
401  for (auto i = prev; i != nullptr; i = i->parent()) {
402  if (item_parents.count(i) == 0) {
403  tree_wdg->collapseItem(i);
404  }
405  }
406 
407  tree_wdg->expandItem(item);
408  }
409 }
410 
414 help_widget::help_widget(QWidget *parent)
415  : QWidget(parent), main_widget(nullptr), text_browser(nullptr),
416  bottom_panel(nullptr), info_panel(nullptr), splitter(nullptr),
417  info_layout(nullptr)
418 {
419  setup_ui();
420 }
421 
425 help_widget::help_widget(const help_item *topic, QWidget *parent)
426  : QWidget(parent), main_widget(nullptr), text_browser(nullptr),
427  bottom_panel(nullptr), info_panel(nullptr), splitter(nullptr),
428  info_layout(nullptr)
429 {
430  setup_ui();
431  set_topic(topic);
432 }
433 
438 {
439  // Nothing to do here
440 }
441 
446 {
447  QVBoxLayout *layout;
448  QHBoxLayout *group_layout;
449 
450  layout = new QVBoxLayout();
451  setLayout(layout);
452 
453  box_wdg = new QFrame(this);
454  layout->addWidget(box_wdg);
455  group_layout = new QHBoxLayout(box_wdg);
456  box_wdg->setLayout(group_layout);
457  box_wdg->setFrameShape(QFrame::StyledPanel);
458  box_wdg->setFrameShadow(QFrame::Raised);
459 
460  title_label = new QLabel(box_wdg);
461  title_label->setProperty(fonts::default_font, "true");
462  group_layout->addWidget(title_label);
463 
464  text_browser = new QTextBrowser(this);
465  text_browser->setProperty(fonts::help_text, "true");
466  layout->addWidget(text_browser);
468 
469  update_fonts();
470  splitter_sizes << 200 << 400;
471 }
472 
496 {
497  QWidget *right;
498 
499  layout()->removeWidget(main_widget);
500  main_widget->setParent(nullptr);
501 
502  if (bottom_panel) {
503  splitter = new QSplitter(Qt::Vertical);
504  splitter->addWidget(text_browser);
505  splitter->setStretchFactor(0, 100);
506  splitter->addWidget(bottom_panel);
507  splitter->setStretchFactor(1, 0);
508  right = splitter;
509  } else {
510  right = text_browser;
511  }
512 
513  if (info_panel) {
514  splitter = new QSplitter();
515  splitter->addWidget(info_panel);
516  splitter->setStretchFactor(0, 25);
517  splitter->addWidget(right);
518  splitter->setStretchFactor(1, 75);
519  splitter->setSizes(splitter_sizes);
521  info_panel->setLayout(info_layout);
522  } else {
523  main_widget = right;
524  }
525 
526  layout()->addWidget(main_widget);
527  qobject_cast<QVBoxLayout *>(layout())->setStretchFactor(main_widget, 100);
528 }
529 
534 {
535  QList<QWidget *> l;
536 
537  l = findChildren<QWidget *>();
538 
540  for (auto i : qAsConst(l)) {
541  if (i->property(fonts::help_label).isValid()) {
542  i->setFont(f);
543  }
544  }
546  for (auto i : qAsConst(l)) {
547  if (i->property(fonts::help_text).isValid()) {
548  i->setFont(f);
549  }
550  }
552  for (auto i : qAsConst(l)) {
553  if (i->property(fonts::default_font).isValid()) {
554  i->setFont(f);
555  }
556  }
557 }
558 
563 {
564  // Save the splitter sizes to avoid jumps
565  if (info_panel) {
566  splitter_sizes = splitter->sizes();
567  }
568  // Unparent the widget we want to keep
569  text_browser->setParent(nullptr);
570  // Delete everything else
571  if (text_browser != main_widget) {
572  main_widget->deleteLater();
573  }
574  // Reset pointers to defaults
576  bottom_panel = nullptr;
577  info_panel = nullptr;
578  splitter = nullptr;
579  info_layout = nullptr;
580 }
581 
586 {
587  info_panel = new QWidget();
588  info_layout = new QVBoxLayout();
589 }
590 
594 void help_widget::add_info_pixmap(const QPixmap *pm, bool shadow)
595 {
596  QLabel *label = new QLabel();
597  QGraphicsDropShadowEffect *effect;
598 
599  label->setAlignment(Qt::AlignHCenter);
600  label->setPixmap(*pm);
601 
602  if (shadow) {
603  effect = new QGraphicsDropShadowEffect(label);
604  effect->setBlurRadius(3);
605  effect->setOffset(0, 2);
606  label->setGraphicsEffect(effect);
607  }
608 
609  info_layout->addWidget(label);
610 }
611 
615 void help_widget::add_info_label(const QString &text)
616 {
617  QLabel *label = new QLabel(text);
618  label->setWordWrap(true);
619  label->setTextFormat(Qt::RichText);
620  label->setProperty(fonts::help_label, "true");
621  info_layout->addWidget(label);
622 }
623 
632 void help_widget::add_info_progress(const QString &text, int progress,
633  int min, int max, const QString &value)
634 {
635  QGridLayout *layout;
636  QLabel *label;
637  QProgressBar *bar;
638  QWidget *wdg;
639 
640  wdg = new QWidget();
641  layout = new QGridLayout(wdg);
642  layout->setContentsMargins(0, 0, 0, 0);
643  layout->setVerticalSpacing(0);
644 
645  label = new QLabel(text, wdg);
646  layout->addWidget(label, 0, 0);
647  label->setProperty(fonts::help_label, "true");
648  label = new QLabel(wdg);
649  if (value.isEmpty()) {
650  label->setNum(progress);
651  } else {
652  label->setText(value);
653  }
654  label->setProperty(fonts::help_label, "true");
655  layout->addWidget(label, 0, 1, Qt::AlignRight);
656 
657  bar = new QProgressBar(wdg);
658  bar->setMaximumHeight(4);
659  bar->setRange(min, max != min ? max : min + 1);
660  bar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
661  bar->setTextVisible(false);
662  bar->setValue(progress);
663  layout->addWidget(bar, 1, 0, 1, 2);
664 
665  info_layout->addWidget(wdg);
666 }
667 
668 static QLabel *set_properties(help_widget *hw)
669 {
670  QLabel *tb = new QLabel(hw);
671  tb->setProperty(fonts::help_label, "true");
672  tb->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
673  tb->setTextFormat(Qt::RichText);
674  return tb;
675 }
676 
681  enum unit_activity act,
682  const char *label)
683 {
684  struct universal for_terr;
685  enum extra_cause cause = activity_to_extra_cause(act);
686 
687  for_terr.kind = VUT_TERRAIN;
688  for_terr.value.terrain = pterr;
689 
690  extra_type_by_cause_iterate(cause, pextra)
691  {
692  if (pextra->buildable
693  && universal_fulfills_requirements(false, &(pextra->reqs),
694  &for_terr)) {
695  QLabel *tb;
696  QString str;
697 
698  tb = set_properties(this);
699  str = str + QString(label)
701  + QString(helptext_extra_for_terrain_str(pextra, pterr, act))
702  .toHtmlEscaped()
703  + "\n";
704  tb->setText(str.trimmed());
705  connect(tb, &QLabel::linkActivated, this,
707  info_layout->addWidget(tb);
708  }
709  }
711 }
712 
716 QString help_widget::link_me(const char *str, help_page_type hpt)
717 {
718  QString s;
719  s = QString(str).toHtmlEscaped().replace(QLatin1String(" "),
720  QLatin1String("&nbsp;"));
721  return " <a href=" + QString::number(hpt) + "," + s + ">" + s + "</a> ";
722 }
723 
728 {
729  info_layout->addSpacing(2 * info_layout->spacing());
730 }
731 
735 void help_widget::info_panel_done() { info_layout->addStretch(); }
736 
741 void help_widget::anchor_clicked(const QString &link)
742 {
743  QStringList sl;
744  int n;
745  QString st;
746  enum help_page_type type;
747 
748  sl = link.split(QStringLiteral(","));
749  n = sl.at(0).toInt();
750  type = static_cast<help_page_type>(n);
751  st = sl.at(1);
752  st = st.replace("\u00A0", QLatin1String(" "));
753 
754  if (strcmp(qUtf8Printable(st), REQ_LABEL_NEVER) != 0
755  && strcmp(qUtf8Printable(st),
757  != 0
758  && strcmp(qUtf8Printable(st),
760  != 0) {
761  popup_help_dialog_typed(qUtf8Printable(st), type);
762  }
763 }
764 
769 {
770  char *title = topic->topic;
771  for (; *title == ' '; ++title) {
772  // Do nothing
773  }
774  title_label->setTextFormat(Qt::PlainText);
775  title_label->setText(title);
776 
777  undo_layout();
778 
779  switch (topic->type) {
780  case HELP_ANY:
781  case HELP_EFFECT:
782  case HELP_MULTIPLIER:
783  case HELP_RULESET:
784  case HELP_TILESET:
785  case HELP_TEXT:
786  set_topic_other(topic, title);
787  break;
788  case HELP_EXTRA:
789  set_topic_extra(topic, title);
790  break;
791  case HELP_GOODS:
792  set_topic_goods(topic, title);
793  break;
794  case HELP_GOVERNMENT:
795  set_topic_government(topic, title);
796  break;
797  case HELP_IMPROVEMENT:
798  case HELP_WONDER:
799  set_topic_building(topic, title);
800  break;
801  case HELP_NATIONS:
802  set_topic_nation(topic, title);
803  break;
804  case HELP_SPECIALIST:
805  set_topic_specialist(topic, title);
806  break;
807  case HELP_TECH:
808  set_topic_tech(topic, title);
809  break;
810  case HELP_TERRAIN:
811  set_topic_terrain(topic, title);
812  break;
813  case HELP_UNIT:
814  set_topic_unit(topic, title);
815  break;
816  case HELP_LAST: // Just to avoid warning
817  break;
818  }
819 
820  do_layout();
821 }
822 
826 void help_widget::set_bottom_panel(QWidget *widget)
827 {
828  bottom_panel = widget;
829 }
830 
834 void help_widget::set_topic_other(const help_item *topic, const char *title)
835 {
836  Q_UNUSED(title)
837  if (topic->text) {
838  text_browser->setPlainText(topic->text);
839  } else {
840  text_browser->setPlainText(
841  QLatin1String("")); // Something better to do ?
842  }
843 }
844 
848 void help_widget::set_topic_unit(const help_item *topic, const char *title)
849 {
850  char buffer[MAX_HELP_TEXT_SIZE];
851  int upkeep, max_upkeep;
852  struct advance *tech;
853  const struct unit_type *obsolete;
854  struct unit_type *utype, *max_utype;
855  QString str;
856 
857  utype = unit_type_by_translated_name(title);
858  if (utype) {
859  helptext_unit(buffer, sizeof(buffer), client.conn.playing, topic->text,
860  utype, client_current_nation_set());
861  text_browser->setPlainText(buffer);
862 
863  // Create information panel
864  show_info_panel();
865  max_utype = uclass_max_values(utype->uclass);
866 
867  // Unit icon
869  get_unittype_sprite(tileset, utype, direction8_invalid()));
870 
871  add_info_progress(_("Attack:"), utype->attack_strength, 0,
872  max_utype->attack_strength);
873  add_info_progress(_("Defense:"), utype->defense_strength, 0,
874  max_utype->defense_strength);
875  add_info_progress(_("Moves:"), utype->move_rate, 0, max_utype->move_rate,
876  move_points_text(utype->move_rate, true));
877 
879 
880  add_info_progress(_("Hitpoints:"), utype->hp, 0, max_utype->hp);
882  utype_build_shield_cost_base(max_utype));
883  add_info_progress(_("Firepower:"), utype->firepower, 0,
884  max_utype->firepower);
886  _("Vision:"), static_cast<int>(std::sqrt(utype->vision_radius_sq)),
887  0, static_cast<int>(std::sqrt(max_utype->vision_radius_sq)));
888 
889  // Upkeep
890  upkeep = utype->upkeep[O_FOOD] + utype->upkeep[O_GOLD]
891  + utype->upkeep[O_LUXURY] + utype->upkeep[O_SCIENCE]
892  + utype->upkeep[O_SHIELD] + utype->upkeep[O_TRADE]
893  + utype->happy_cost;
894  max_upkeep = max_utype->upkeep[O_FOOD] + max_utype->upkeep[O_GOLD]
895  + max_utype->upkeep[O_LUXURY] + max_utype->upkeep[O_SCIENCE]
896  + max_utype->upkeep[O_SHIELD] + max_utype->upkeep[O_TRADE]
897  + max_utype->happy_cost;
898  add_info_progress(_("Basic upkeep:"), upkeep, 0, max_upkeep,
899  helptext_unit_upkeep_str(utype));
900 
902 
903  // Tech requirement
904  tech = utype->require_advance;
905  if (tech && tech != advance_by_number(0)) {
906  QLabel *tb;
907 
908  tb = set_properties(this);
909  // TRANS: this and similar literal strings interpreted as (Qt) HTML
910  str = _("Requires");
911  str = "<b>" + str + "</b> "
913  tb->setText(str.trimmed());
914  connect(tb, &QLabel::linkActivated, this,
916  info_layout->addWidget(tb);
917  } else {
918  add_info_label(_("No technology required."));
919  }
920 
921  // Obsolescence
922  obsolete = utype->obsoleted_by;
923  if (obsolete) {
924  tech = obsolete->require_advance;
925  if (tech && tech != advance_by_number(0)) {
926  QLabel *tb;
927 
928  str = _("Obsoleted by");
929  str = "<b>" + str + "</b> "
930  + link_me(utype_name_translation(obsolete), HELP_UNIT) + "("
932  tb = set_properties(this);
933  tb->setText(str.trimmed());
934  connect(tb, &QLabel::linkActivated, this,
936  info_layout->addWidget(tb);
937  } else {
939  // TRANS: Current unit obsoleted by other unit
940  QString(_("Obsoleted by %1."))
941  .arg(utype_name_translation(obsolete))
942  .toHtmlEscaped());
943  }
944  } else {
945  add_info_label(_("Never obsolete."));
946  }
947 
948  info_panel_done();
949 
950  delete max_utype;
951  } else {
952  set_topic_other(topic, title);
953  }
954 }
955 
960  const char *title)
961 {
962  char buffer[MAX_HELP_TEXT_SIZE];
963  int type, value;
964  struct impr_type *itype = improvement_by_translated_name(title);
965  char req_buf[512];
966  QString str, s1, s2;
967  QLabel *tb;
968 
969  if (itype) {
970  helptext_building(buffer, sizeof(buffer), client.conn.playing,
971  topic->text, itype, client_current_nation_set());
972  text_browser->setPlainText(buffer);
973  show_info_panel();
974  auto spr = get_building_sprite(tileset, itype);
975  if (spr) {
976  add_info_pixmap(spr);
977  }
978  str = _("Base Cost:");
979  str = "<b>" + str + "</b>" + " "
980  + QString::number(impr_base_build_shield_cost(itype))
981  .toHtmlEscaped();
982  add_info_label(str);
983  if (!is_great_wonder(itype)) {
984  str = _("Upkeep:");
985  str = "<b>" + str + "</b>" + " "
986  + QString::number(itype->upkeep).toHtmlEscaped();
987  add_info_label(str);
988  }
989 
990  requirement_vector_iterate(&itype->reqs, preq)
991  {
992  if (!preq->present) {
993  continue;
994  }
995  universal_extraction(&preq->source, &type, &value);
996  if (type == VUT_ADVANCE) {
997  s1 = link_me(universal_name_translation(&preq->source, req_buf,
998  sizeof(req_buf)),
999  HELP_TECH);
1000  } else if (type == VUT_GOVERNMENT) {
1001  s1 = link_me(universal_name_translation(&preq->source, req_buf,
1002  sizeof(req_buf)),
1003  HELP_GOVERNMENT);
1004  } else if (type == VUT_TERRAIN) {
1005  s1 = link_me(universal_name_translation(&preq->source, req_buf,
1006  sizeof(req_buf)),
1007  HELP_TERRAIN);
1008  }
1009  break;
1010  }
1012 
1013  if (!s1.isEmpty()) {
1014  str = _("Requirement:");
1015  str = "<b>" + str + "</b> " + s1;
1016  tb = set_properties(this);
1017  tb->setText(str.trimmed());
1018  connect(tb, &QLabel::linkActivated, this,
1020  info_layout->addWidget(tb);
1021  }
1022 
1024  {
1025  if (pobs->source.kind == VUT_ADVANCE) {
1026  s2 = link_me(advance_name_translation(pobs->source.value.advance),
1027  HELP_TECH);
1028  break;
1029  }
1030  }
1032 
1033  str = _("Obsolete by:");
1034  str = "<b>" + str + "</b> " + s2;
1035  if (!s2.isEmpty()) {
1036  tb = set_properties(this);
1037  tb->setText(str.trimmed());
1038  connect(tb, &QLabel::linkActivated, this,
1040  info_layout->addWidget(tb);
1041  }
1042  info_panel_done();
1043  } else {
1044  set_topic_other(topic, title);
1045  }
1046 }
1047 
1051 void help_widget::set_topic_tech(const help_item *topic, const char *title)
1052 {
1053  char buffer[MAX_HELP_TEXT_SIZE];
1054  QLabel *tb;
1055  struct advance *padvance = advance_by_translated_name(title);
1056  QString str;
1057 
1058  if (padvance) {
1059  int n = advance_number(padvance);
1060  if (!is_future_tech(n)) {
1061  show_info_panel();
1062  auto spr = get_tech_sprite(tileset, n);
1063  if (spr) {
1064  add_info_pixmap(spr);
1065  }
1066 
1067  for (const auto &pgov : governments) {
1068  requirement_vector_iterate(&pgov.reqs, preq)
1069  {
1070  if (VUT_ADVANCE == preq->source.kind
1071  && preq->source.value.advance == padvance) {
1072  tb = set_properties(this);
1073  str = _("Allows");
1074  str = "<b>" + str + "</b> "
1076  HELP_GOVERNMENT);
1077  tb->setText(str.trimmed());
1078  connect(tb, &QLabel::linkActivated, this,
1080  info_layout->addWidget(tb);
1081  }
1082  }
1084  };
1085 
1086  improvement_iterate(pimprove)
1087  {
1088  requirement_vector_iterate(&pimprove->reqs, preq)
1089  {
1090  if (VUT_ADVANCE == preq->source.kind
1091  && preq->source.value.advance == padvance) {
1092  str = _("Allows");
1093  str = "<b>" + str + "</b> "
1095  is_great_wonder(pimprove) ? HELP_WONDER
1096  : HELP_IMPROVEMENT);
1097  tb = set_properties(this);
1098  tb->setText(str.trimmed());
1099  connect(tb, &QLabel::linkActivated, this,
1101  info_layout->addWidget(tb);
1102  }
1103  }
1105 
1106  requirement_vector_iterate(&pimprove->obsolete_by, pobs)
1107  {
1108  if (pobs->source.kind == VUT_ADVANCE
1109  && pobs->source.value.advance == padvance) {
1110  str = _("Obsoletes");
1111  str = "<b>" + str + "</b> "
1113  is_great_wonder(pimprove) ? HELP_WONDER
1114  : HELP_IMPROVEMENT);
1115  tb = set_properties(this);
1116  tb->setText(str.trimmed());
1117  connect(tb, &QLabel::linkActivated, this,
1119  info_layout->addWidget(tb);
1120  }
1121  }
1123  }
1125 
1126  unit_type_iterate(punittype)
1127  {
1128  if (padvance != punittype->require_advance) {
1129  continue;
1130  }
1131  str = _("Allows");
1132  str = "<b>" + str + "</b> "
1133  + link_me(utype_name_translation(punittype), HELP_UNIT);
1134  tb = set_properties(this);
1135  tb->setText(str.trimmed());
1136  connect(tb, &QLabel::linkActivated, this,
1138  info_layout->addWidget(tb);
1139  }
1141 
1142  info_panel_done();
1143  helptext_advance(buffer, sizeof(buffer), client.conn.playing,
1144  topic->text, n, client_current_nation_set());
1145  text_browser->setPlainText(buffer);
1146  }
1147  } else {
1148  set_topic_other(topic, title);
1149  }
1150 }
1151 
1155 QPixmap *terrain_canvas(struct terrain *terrain,
1156  const struct extra_type *resource,
1157  enum extra_cause cause)
1158 {
1159  QPixmap *canvas;
1160  int canvas_y, i, width, height;
1161  struct extra_type *pextra;
1162 
1165  canvas_y = height - tileset_tile_height(tileset);
1166 
1167  canvas = new QPixmap(width, height);
1168  canvas->fill(Qt::transparent);
1169  for (i = 0; i < 3; ++i) {
1170  auto sprites =
1172  put_drawn_sprites(canvas, QPoint(0, canvas_y), sprites, false);
1173  }
1174 
1175  pextra = nullptr;
1176  if (cause != EC_COUNT) {
1177  extra_type_by_cause_iterate(cause, e)
1178  {
1179  pextra = e;
1180  break;
1181  }
1183  fc_assert_ret_val(pextra, nullptr);
1184  auto sprites = fill_basic_extra_sprite_array(tileset, pextra);
1185  put_drawn_sprites(canvas, QPoint(0, canvas_y), sprites, false);
1186  }
1187 
1188  if (resource != nullptr) {
1190  put_drawn_sprites(canvas, QPoint(0, canvas_y), sprites, false);
1191  }
1192 
1193  return canvas;
1194 }
1195 
1196 // helper for create_terrain_widget
1197 static QLabel *make_helplabel(const QString &title, const QString &tooltip,
1198  QHBoxLayout *layout)
1199 {
1200  QLabel *label;
1202  label = new QLabel(title);
1203  layout->addWidget(label, Qt::AlignVCenter);
1204  label->setProperty(fonts::default_font, "true");
1205  label->setToolTip(tooltip);
1206  label->setMaximumHeight(QFontMetrics(f).height() * 1.2);
1207  return label;
1208 }
1209 
1210 // helper for create_terrain_widget, creates label from sprite
1211 static void make_helppiclabel(QPixmap *spr, const QString &tooltip,
1212  QHBoxLayout *layout)
1213 {
1214  QLabel *label;
1215  QImage img;
1216  QImage cropped_img;
1217  QRect crop;
1218  QPixmap pix;
1219  QFontMetrics *fm;
1220  int isize;
1221 
1222  img = spr->toImage();
1223  crop = zealous_crop_rect(img);
1224  cropped_img = img.copy(crop);
1225  pix = QPixmap::fromImage(cropped_img);
1227  fm = new QFontMetrics(f);
1228  isize = fm->height() * 7 / 8;
1229  label = new QLabel();
1230  label->setPixmap(pix.scaledToHeight(isize));
1231  layout->addWidget(label, Qt::AlignBottom);
1232  label->setToolTip(tooltip);
1233 }
1234 
1239 QLayout *help_widget::create_terrain_widget(const QString &title,
1240  const QPixmap *image,
1241  const int &food, const int &sh,
1242  const int &eco,
1243  const QString &tooltip)
1244 {
1245  QGraphicsDropShadowEffect *effect;
1246  QLabel *label;
1247  QHBoxLayout *layout = new QHBoxLayout();
1248  QHBoxLayout *layout1 = new QHBoxLayout();
1249  QHBoxLayout *layout2 = new QHBoxLayout();
1250  QWidget *w1, *w2;
1251  w1 = new QWidget();
1252  w2 = new QWidget();
1253 
1254  label = new QLabel();
1255  effect = new QGraphicsDropShadowEffect(label);
1256  effect->setBlurRadius(3);
1257  effect->setOffset(0, 2);
1258  label->setGraphicsEffect(effect);
1259  label->setPixmap(*image);
1260  layout1->addWidget(label, Qt::AlignVCenter);
1261  w1->setLayout(layout1);
1262 
1263  make_helplabel(title, tooltip, layout2);
1264  make_helplabel((".:. "), tooltip, layout2);
1265  make_helplabel(_("Output becomes: "), tooltip, layout2);
1266  make_helplabel(QString::number(food), tooltip, layout2)
1267  ->setProperty("foodlab", "true");
1268  auto sprites = get_citybar_sprites(tileset);
1269  make_helppiclabel(sprites->food, tooltip, layout2);
1270  make_helplabel(QString::number(sh), tooltip, layout2)
1271  ->setProperty("shieldlab", "true");
1272  make_helppiclabel(sprites->shields, tooltip, layout2);
1273  make_helplabel(QString::number(eco), tooltip, layout2)
1274  ->setProperty("ecolab", "true");
1275  make_helppiclabel(sprites->trade, tooltip, layout2);
1276  w2->setLayout(layout2);
1277 
1278  layout->addWidget(w1, Qt::AlignVCenter);
1279  layout->addWidget(w2, Qt::AlignVCenter);
1280  return layout;
1281 }
1282 
1283 // helper
1285 {
1286  QLabel *tb = set_properties(this);
1287  tb->setText(str.trimmed());
1288  connect(tb, &QLabel::linkActivated, this, &help_widget::anchor_clicked);
1289  info_layout->addWidget(tb);
1290 }
1291 
1296  const char *title)
1297 {
1298  char buffer[MAX_HELP_TEXT_SIZE];
1299  struct terrain *pterrain, *max;
1300  QPixmap *canvas;
1301  QVBoxLayout *vbox;
1302  bool show_panel = false;
1303  QScrollArea *area;
1304  QWidget *panel;
1305  QString str;
1306 
1307  pterrain = terrain_by_translated_name(title);
1308  if (pterrain) {
1309  struct universal for_terr;
1310 
1311  for_terr.kind = VUT_TERRAIN;
1312  for_terr.value.terrain = pterrain;
1313 
1314  helptext_terrain(buffer, sizeof(buffer), client.conn.playing,
1315  topic->text, pterrain);
1316  text_browser->setPlainText(buffer);
1317 
1318  // Create information panel
1319  show_info_panel();
1320  max = terrain_max_values();
1321 
1322  // Create terrain icon. Use shadow to help distinguish terrain.
1323  canvas = terrain_canvas(pterrain);
1324  add_info_pixmap(canvas, true);
1325  delete canvas;
1326 
1327  add_info_progress(_("Food:"), pterrain->output[O_FOOD], 0,
1328  max->output[O_FOOD]);
1329  add_info_progress(_("Production:"), pterrain->output[O_SHIELD], 0,
1330  max->output[O_SHIELD]);
1331  add_info_progress(_("Trade:"), pterrain->output[O_TRADE], 0,
1332  max->output[O_TRADE]);
1333 
1335 
1336  add_info_progress(_("Move cost:"), pterrain->movement_cost, 0,
1337  max->movement_cost);
1338  add_info_progress(_("Defense bonus:"), MIN(100, pterrain->defense_bonus),
1339  0, 100,
1340  // TRANS: Display a percentage, eg "50%".
1341  QString(_("%1%")).arg(pterrain->defense_bonus));
1342 
1344 
1345  if (pterrain->irrigation_result != pterrain
1346  && pterrain->irrigation_result != T_NONE
1347  && action_id_univs_not_blocking(ACTION_CULTIVATE, nullptr,
1348  &for_terr)) {
1349  char buffer[1024];
1350 
1351  fc_snprintf(buffer, sizeof(buffer),
1352  PL_("%d turn", "%d turns", pterrain->cultivate_time),
1353  pterrain->cultivate_time);
1354  str = N_("Cultivate Rslt/Time:");
1355  str = str
1357  HELP_TERRAIN)
1358  + QString(buffer).toHtmlEscaped();
1359  make_terrain_lab(str);
1360  }
1361 
1362  if (pterrain->mining_result != pterrain
1363  && pterrain->mining_result != T_NONE
1364  && action_id_univs_not_blocking(ACTION_PLANT, nullptr, &for_terr)) {
1365  char buffer[1024];
1366 
1367  fc_snprintf(buffer, sizeof(buffer),
1368  PL_("%d turn", "%d turns", pterrain->plant_time),
1369  pterrain->plant_time);
1370  str = N_("Plant Rslt/Time:");
1371  str = str
1373  HELP_TERRAIN)
1374  + QString(buffer).toHtmlEscaped();
1375  make_terrain_lab(str);
1376  }
1377 
1378  if (pterrain->transform_result != T_NONE
1379  && action_id_univs_not_blocking(ACTION_TRANSFORM_TERRAIN, nullptr,
1380  &for_terr)) {
1381  char buffer[1024];
1382 
1383  fc_snprintf(buffer, sizeof(buffer),
1384  PL_("%d turn", "%d turns", pterrain->transform_time),
1385  pterrain->transform_time);
1386  str = N_("Transform Rslt/Time:");
1387  str = str
1389  HELP_TERRAIN)
1390  + QString(buffer).toHtmlEscaped();
1391  make_terrain_lab(str);
1392  }
1393 
1394  if (pterrain->irrigation_result == pterrain
1395  && action_id_univs_not_blocking(ACTION_IRRIGATE, nullptr,
1396  &for_terr)) {
1397  // TRANS: this and similar literal strings interpreted as (Qt) HTML
1398  add_extras_of_act_for_terrain(pterrain, ACTIVITY_IRRIGATE,
1399  _("Build as irrigation"));
1400  }
1401  if (pterrain->mining_result == pterrain && pterrain->mining_time != 0
1402  && action_id_univs_not_blocking(ACTION_MINE, nullptr, &for_terr)) {
1403  add_extras_of_act_for_terrain(pterrain, ACTIVITY_MINE,
1404  _("Build as mine"));
1405  }
1406  if (pterrain->road_time != 0) {
1407  add_extras_of_act_for_terrain(pterrain, ACTIVITY_GEN_ROAD,
1408  _("Build as road"));
1409  }
1410  if (pterrain->base_time != 0) {
1411  add_extras_of_act_for_terrain(pterrain, ACTIVITY_BASE,
1412  _("Build as base"));
1413  }
1414 
1415  info_panel_done();
1416 
1417  // Create bottom widget
1418  panel = new QWidget();
1419  vbox = new QVBoxLayout(panel);
1420 
1421  if (*(pterrain->resources)) {
1422  struct extra_type **r;
1423 
1424  for (r = pterrain->resources; *r; r++) {
1425  canvas = terrain_canvas(pterrain, *r);
1426  vbox->addLayout(create_terrain_widget(
1428  pterrain->output[O_FOOD] + (*r)->data.resource->output[O_FOOD],
1429  pterrain->output[O_SHIELD]
1430  + (*r)->data.resource->output[O_SHIELD],
1431  pterrain->output[O_TRADE] + (*r)->data.resource->output[O_TRADE],
1432  // TRANS: Tooltip decorating strings like "1, 2, 3".
1433  _("Output (Food, Shields, Trade) of a tile where the resource "
1434  "is "
1435  "present.")));
1436  delete canvas;
1437  show_panel = true;
1438  }
1439  }
1440 
1441  vbox->addStretch(100);
1442  vbox->setSizeConstraint(QLayout::SetMinimumSize);
1443  if (show_panel) {
1444  area = new QScrollArea();
1445  area->setWidget(panel);
1446  set_bottom_panel(area);
1447  } else {
1448  panel->deleteLater();
1449  }
1450  delete max;
1451  } else {
1452  set_topic_other(topic, title);
1453  }
1454 }
1455 
1459 void help_widget::set_topic_extra(const help_item *topic, const char *title)
1460 {
1461  char buffer[MAX_HELP_TEXT_SIZE];
1462  struct extra_type *pextra = extra_type_by_translated_name(title);
1463  if (pextra) {
1464  helptext_extra(buffer, sizeof(buffer), client.conn.playing, topic->text,
1465  pextra);
1466  text_browser->setPlainText(buffer);
1467  } else {
1468  set_topic_other(topic, title);
1469  }
1470 }
1471 
1476  const char *title)
1477 {
1478  char buffer[MAX_HELP_TEXT_SIZE];
1479  struct specialist *pspec = specialist_by_translated_name(title);
1480  if (pspec) {
1481  helptext_specialist(buffer, sizeof(buffer), client.conn.playing,
1482  topic->text, pspec);
1483  text_browser->setPlainText(buffer);
1484  } else {
1485  set_topic_other(topic, title);
1486  }
1487 }
1488 
1493  const char *title)
1494 {
1495  char buffer[MAX_HELP_TEXT_SIZE];
1496  struct government *pgov = government_by_translated_name(title);
1497  if (pgov) {
1498  helptext_government(buffer, sizeof(buffer), client.conn.playing,
1499  topic->text, pgov);
1500  text_browser->setPlainText(buffer);
1501  } else {
1502  set_topic_other(topic, title);
1503  }
1504 }
1505 
1509 void help_widget::set_topic_nation(const help_item *topic, const char *title)
1510 {
1511  char buffer[MAX_HELP_TEXT_SIZE];
1512  struct nation_type *pnation = nation_by_translated_plural(title);
1513  if (pnation) {
1514  helptext_nation(buffer, sizeof(buffer), pnation, topic->text);
1515  text_browser->setPlainText(buffer);
1516  } else {
1517  set_topic_other(topic, title);
1518  }
1519 }
1520 
1524 void help_widget::set_topic_goods(const help_item *topic, const char *title)
1525 {
1526  char buffer[MAX_HELP_TEXT_SIZE];
1527  struct goods_type *pgood = goods_by_translated_name(title);
1528  if (pgood) {
1529  helptext_goods(buffer, sizeof(buffer), client.conn.playing, topic->text,
1530  pgood);
1531  text_browser->setText(buffer);
1532  } else {
1533  set_topic_other(topic, title);
1534  }
1535 }
1536 
1548 {
1549  Terrain_type_id i, count;
1550  struct terrain *terrain;
1551  struct terrain *max = new struct terrain();
1552  max->base_time = 0;
1553  max->clean_fallout_time = 0;
1554  max->clean_pollution_time = 0;
1555  max->defense_bonus = 0;
1556  max->irrigation_food_incr = 0;
1557  max->irrigation_time = 0;
1558  max->mining_shield_incr = 0;
1559  max->mining_time = 0;
1560  max->movement_cost = 0;
1561  max->output[O_FOOD] = 0;
1562  max->output[O_GOLD] = 0;
1563  max->output[O_LUXURY] = 0;
1564  max->output[O_SCIENCE] = 0;
1565  max->output[O_SHIELD] = 0;
1566  max->output[O_TRADE] = 0;
1567  max->pillage_time = 0;
1568  max->road_output_incr_pct[O_FOOD] = 0;
1569  max->road_output_incr_pct[O_GOLD] = 0;
1570  max->road_output_incr_pct[O_LUXURY] = 0;
1571  max->road_output_incr_pct[O_SCIENCE] = 0;
1572  max->road_output_incr_pct[O_SHIELD] = 0;
1573  max->road_output_incr_pct[O_TRADE] = 0;
1574  max->road_time = 0;
1575  max->transform_time = 0;
1576  count = terrain_count();
1577  for (i = 0; i < count; ++i) {
1579 #define SET_MAX(v) max->v = max->v > terrain->v ? max->v : terrain->v
1580  SET_MAX(base_time);
1589  SET_MAX(output[O_FOOD]);
1590  SET_MAX(output[O_GOLD]);
1602  SET_MAX(road_time);
1604 #undef SET_MAX
1605  }
1606  return max;
1607 }
1608 
1619 {
1620  struct unit_type *max = new struct unit_type();
1621  max->uclass = uclass;
1622  max->attack_strength = 0;
1623  max->bombard_rate = 0;
1624  max->build_cost = 0;
1625  max->convert_time = 0;
1626  max->city_size = 0;
1627  max->defense_strength = 0;
1628  max->firepower = 0;
1629  max->fuel = 0;
1630  max->happy_cost = 0;
1631  max->hp = 0;
1632  max->move_rate = 0;
1633  max->pop_cost = 0;
1634  max->upkeep[O_FOOD] = 0;
1635  max->upkeep[O_GOLD] = 0;
1636  max->upkeep[O_LUXURY] = 0;
1637  max->upkeep[O_SCIENCE] = 0;
1638  max->upkeep[O_SHIELD] = 0;
1639  max->upkeep[O_TRADE] = 0;
1640  max->vision_radius_sq = 0;
1641  unit_type_iterate(utype)
1642  {
1643  if (utype->uclass == uclass) {
1644 #define SET_MAX(v) max->v = max->v > utype->v ? max->v : utype->v
1648  SET_MAX(city_size);
1651  SET_MAX(firepower);
1652  SET_MAX(fuel);
1654  SET_MAX(hp);
1655  SET_MAX(move_rate);
1656  SET_MAX(pop_cost);
1657  SET_MAX(upkeep[O_FOOD]);
1658  SET_MAX(upkeep[O_GOLD]);
1664 #undef SET_MAX
1665  }
1666  }
1667  unit_type_iterate_end return max;
1668 }
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition: actions.h:754
QRect zealous_crop_rect(QImage &p)
Return rectangle containing pure image (crops transparency)
Definition: canvas.cpp:81
QFont getFont(const QString &name, double zoom=1.0) const
Returns desired font.
Definition: fonts.cpp:57
static fcFont * instance()
Returns instance of fc_font.
Definition: fonts.cpp:34
fc_settings qt_settings
Definition: fc_client.h:126
QTreeWidget * tree_wdg
Definition: helpdlg.h:42
void showEvent(QShowEvent *event) override
Show event.
Definition: helpdlg.cpp:172
int history_pos
Definition: helpdlg.h:47
bool update_history
Definition: helpdlg.h:53
QPushButton * prev_butt
Definition: helpdlg.h:40
help_dialog(QWidget *parent=0)
Constructor for help dialog.
Definition: helpdlg.cpp:97
void history_forward()
Goes to next topic in history.
Definition: helpdlg.cpp:328
QPushButton * next_butt
Definition: helpdlg.h:41
void set_topic(const help_item *item)
Changes the displayed topic.
Definition: helpdlg.cpp:310
void closeEvent(QCloseEvent *event) override
Close event.
Definition: helpdlg.cpp:192
help_widget * help_wdg
Definition: helpdlg.h:43
void make_tree()
Create the help tree.
Definition: helpdlg.cpp:202
QHash< QTreeWidgetItem *, const help_item * > topics_map
Definition: helpdlg.h:46
void item_changed(QTreeWidgetItem *item, QTreeWidgetItem *prev)
Called when a tree item is activated.
Definition: helpdlg.cpp:379
void update_fonts()
Update fonts for help_wdg.
Definition: helpdlg.cpp:157
void hideEvent(QHideEvent *event) override
Hide event.
Definition: helpdlg.cpp:162
QSplitter * splitter
Definition: helpdlg.h:44
void update_buttons()
Update buttons (back and next)
Definition: helpdlg.cpp:362
QList< QTreeWidgetItem * > item_history
Definition: helpdlg.h:45
void history_back()
Backs in history to previous topic.
Definition: helpdlg.cpp:345
void add_info_separator()
Adds a separator to the information panel.
Definition: helpdlg.cpp:727
QString link_me(const char *str, help_page_type hpt)
Creates link to given help page.
Definition: helpdlg.cpp:716
void add_info_pixmap(const QPixmap *pm, bool shadow=false)
Adds a pixmap to the information panel.
Definition: helpdlg.cpp:594
void show_info_panel()
Creates the information panel.
Definition: helpdlg.cpp:585
void update_fonts()
Updates fonts for manual.
Definition: helpdlg.cpp:533
void set_topic_specialist(const help_item *item, const char *title)
Creates specialist help pages.
Definition: helpdlg.cpp:1475
void info_panel_done()
Called when everything needed has been added to the information panel.
Definition: helpdlg.cpp:735
void add_info_progress(const QString &label, int progress, int min, int max, const QString &value=QString())
Adds a widget indicating a progress to the information panel.
Definition: helpdlg.cpp:632
QSplitter * splitter
Definition: helpdlg.h:81
void anchor_clicked(const QString &link)
Hyperlink clicked, link has 2 variables, string(name of given help) and int(help_page_type)
Definition: helpdlg.cpp:741
void set_bottom_panel(QWidget *widget)
Sets the bottom panel.
Definition: helpdlg.cpp:826
QWidget * main_widget
Definition: helpdlg.h:77
void setup_ui()
Creates the UI.
Definition: helpdlg.cpp:445
void add_info_label(const QString &text)
Adds a text label to the information panel.
Definition: helpdlg.cpp:615
QVBoxLayout * info_layout
Definition: helpdlg.h:82
void set_topic_tech(const help_item *item, const char *title)
Creates technology help pages.
Definition: helpdlg.cpp:1051
void add_extras_of_act_for_terrain(struct terrain *pterr, enum unit_activity act, const char *label)
Create labels about all extras of one cause buildable to the terrain.
Definition: helpdlg.cpp:680
QFrame * box_wdg
Definition: helpdlg.h:74
void set_topic_other(const help_item *item, const char *title)
Creates help pages with no special widgets.
Definition: helpdlg.cpp:834
QLayout * create_terrain_widget(const QString &title, const QPixmap *image, const int &food, const int &sh, const int &eco, const QString &tooltip=QString())
Creates a terrain widget with title, terrain image, legend.
Definition: helpdlg.cpp:1239
void set_topic_extra(const help_item *item, const char *title)
Creates extra help pages.
Definition: helpdlg.cpp:1459
void set_topic(const help_item *item)
Shows the given help page.
Definition: helpdlg.cpp:768
void set_topic_nation(const help_item *item, const char *title)
Creates nation help pages.
Definition: helpdlg.cpp:1509
void undo_layout()
Deletes the widgets created by do_complex_layout().
Definition: helpdlg.cpp:562
~help_widget() override
Destructor.
Definition: helpdlg.cpp:437
QList< int > splitter_sizes
Definition: helpdlg.h:83
struct unit_type * uclass_max_values(struct unit_class *uclass)
Retrieves the maximum values any unit of uclass will ever have.
Definition: helpdlg.cpp:1618
void make_terrain_lab(QString &str)
Definition: helpdlg.cpp:1284
QTextBrowser * text_browser
Definition: helpdlg.h:78
void do_layout()
Lays things out.
Definition: helpdlg.cpp:495
help_widget(QWidget *parent=0)
Creates a new, empty help widget.
Definition: helpdlg.cpp:414
void set_topic_terrain(const help_item *item, const char *title)
Creates terrain help pages.
Definition: helpdlg.cpp:1295
void set_topic_goods(const help_item *item, const char *title)
Creates goods help page.
Definition: helpdlg.cpp:1524
QWidget * info_panel
Definition: helpdlg.h:80
void set_topic_building(const help_item *item, const char *title)
Creates improvement help pages.
Definition: helpdlg.cpp:959
void set_topic_government(const help_item *item, const char *title)
Creates government help pages.
Definition: helpdlg.cpp:1492
void set_topic_unit(const help_item *item, const char *title)
Creates unit help pages.
Definition: helpdlg.cpp:848
QWidget * bottom_panel
Definition: helpdlg.h:79
QLabel * title_label
Definition: helpdlg.h:75
struct terrain * terrain_max_values()
Retrieves the maximum values any terrain will ever have.
Definition: helpdlg.cpp:1547
struct civclient client
struct nation_set * client_current_nation_set()
Returns the nation set in use.
Definition: climisc.cpp:1190
enum event_type event
Definition: events.cpp:68
const char * extra_name_translation(const struct extra_type *pextra)
Return the (translated) name of the extra type.
Definition: extras.cpp:165
enum extra_cause activity_to_extra_cause(enum unit_activity act)
What extra cause activity is considered to be?
Definition: extras.cpp:973
struct extra_type * extra_type_by_translated_name(const char *name)
Returns extra type matching the translated name, or nullptr if there is no extra type with that name.
Definition: extras.cpp:208
#define extra_type_by_cause_iterate_end
Definition: extras.h:307
#define extra_type_by_cause_iterate(_cause, _extra)
Definition: extras.h:299
class fc_client * king()
Return fc_client instance.
Definition: gui_main.cpp:58
int Terrain_type_id
Definition: fc_types.h:290
@ O_SHIELD
Definition: fc_types.h:86
@ O_FOOD
Definition: fc_types.h:85
@ O_TRADE
Definition: fc_types.h:87
@ O_SCIENCE
Definition: fc_types.h:90
@ O_LUXURY
Definition: fc_types.h:89
@ O_GOLD
Definition: fc_types.h:88
const char * skip_intl_qualifier_prefix(const char *str)
Some strings are ambiguous for translation.
Definition: fcintl.cpp:39
#define PL_(String1, String2, n)
Definition: fcintl.h:54
#define _(String)
Definition: fcintl.h:50
#define N_(String)
Definition: fcintl.h:52
std::vector< government > governments
Definition: government.cpp:28
const char * government_name_translation(const struct government *pgovern)
Return the (translated) name of the given government.
Definition: government.cpp:136
struct government * government_by_translated_name(const char *name)
Returns the government that has the given (translated) name.
Definition: government.cpp:33
void helptext_advance(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, int i, const nation_set *nations_to_show)
Append misc dynamic text for advance/technology.
Definition: helpdata.cpp:2886
void helptext_government(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct government *gov)
Append text for government.
Definition: helpdata.cpp:3942
void helptext_extra(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct extra_type *pextra)
Append misc dynamic text for extras.
Definition: helpdata.cpp:3395
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
const struct help_item * get_help_item_spec(const char *name, enum help_page_type htype, int *pos)
The following few functions are essentially wrappers for the help_nodes help_list.
Definition: helpdata.cpp:1118
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
void helptext_goods(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct goods_type *pgood)
Append misc dynamic text for goods.
Definition: helpdata.cpp:3853
const char * helptext_extra_for_terrain_str(struct extra_type *pextra, struct terrain *pterrain, enum unit_activity act)
Return a brief description specific to the extra and terrain, when extra is built by cause 'act'.
Definition: helpdata.cpp:3361
void helptext_specialist(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct specialist *pspec)
Append misc dynamic text for specialists.
Definition: helpdata.cpp:3905
void helptext_terrain(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct terrain *pterrain)
Append text for terrain.
Definition: helpdata.cpp:3115
void helptext_nation(char *buf, size_t bufsz, struct nation_type *pnation, const char *user_text)
Returns nation legend and characteristics.
Definition: helpdata.cpp:4653
help_page_type
Definition: helpdata.h:20
@ HELP_ANY
Definition: helpdata.h:21
@ HELP_MULTIPLIER
Definition: helpdata.h:35
@ HELP_TERRAIN
Definition: helpdata.h:27
@ HELP_EXTRA
Definition: helpdata.h:28
@ HELP_NATIONS
Definition: helpdata.h:34
@ HELP_LAST
Definition: helpdata.h:37
@ HELP_IMPROVEMENT
Definition: helpdata.h:24
@ HELP_UNIT
Definition: helpdata.h:23
@ HELP_SPECIALIST
Definition: helpdata.h:30
@ HELP_GOVERNMENT
Definition: helpdata.h:31
@ HELP_EFFECT
Definition: helpdata.h:36
@ HELP_GOODS
Definition: helpdata.h:29
@ HELP_WONDER
Definition: helpdata.h:25
@ HELP_TECH
Definition: helpdata.h:26
@ HELP_RULESET
Definition: helpdata.h:32
@ HELP_TEXT
Definition: helpdata.h:22
@ HELP_TILESET
Definition: helpdata.h:33
QPixmap * terrain_canvas(struct terrain *terrain, const struct extra_type *resource=nullptr, enum extra_cause cause=EC_COUNT)
Creates a terrain image on the given canvas.
Definition: helpdlg.cpp:1155
QList< const struct help_item * > * help_nodes
Definition: helpdata.cpp:65
static QLabel * set_properties(help_widget *hw)
Definition: helpdlg.cpp:668
void popdown_help_dialog(void)
Close the help dialog.
Definition: helpdlg.cpp:75
static void make_helppiclabel(QPixmap *spr, const QString &tooltip, QHBoxLayout *layout)
Definition: helpdlg.cpp:1211
#define SET_MAX(v)
static help_dialog * help_dlg
Definition: helpdlg.cpp:43
void update_help_fonts()
Updates fonts.
Definition: helpdlg.cpp:87
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Popup the help dialog to display help on the given string topic from the given section.
Definition: helpdlg.cpp:56
#define REQ_LABEL_NEVER
Definition: helpdlg.cpp:41
#define REQ_LABEL_NONE
Definition: helpdlg.cpp:42
static QLabel * make_helplabel(const QString &title, const QString &tooltip, QHBoxLayout *layout)
Definition: helpdlg.cpp:1197
#define MAX_HELP_TEXT_SIZE
Definition: helpdlg.cpp:40
int impr_base_build_shield_cost(const struct impr_type *pimprove)
Returns the base number of shields it takes to build this improvement.
struct impr_type * improvement_by_translated_name(const char *name)
Does a linear search of improvement_types[].name.translated Returns nullptr when none match.
bool is_great_wonder(const struct impr_type *pimprove)
Is this building a great wonder?
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
#define improvement_iterate_end
Definition: improvement.h:199
#define improvement_iterate(_p)
Definition: improvement.h:193
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
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
const char *const default_font
Definition: fonts.h:18
const char *const notify_label
Definition: fonts.h:19
const char *const help_label
Definition: fonts.h:20
const char *const help_text
Definition: fonts.h:21
struct nation_type * nation_by_translated_plural(const char *name)
Returns the nation that has the given (translated) plural noun.
Definition: nation.cpp:83
void universal_extraction(const struct universal *source, int *kind, int *value)
Extract universal structure into its components for serialization; the opposite of universal_by_numbe...
bool universal_fulfills_requirements(bool check_necessary, const struct requirement_vector *reqs, const struct universal *source)
Will the universal 'source' fulfill the requirements in the list? If 'check_necessary' is FALSE: are ...
const char * universal_name_translation(const struct universal *psource, char *buf, size_t bufsz)
Make user-friendly text for the source.
#define requirement_vector_iterate_end
Definition: requirements.h:80
#define requirement_vector_iterate(req_vec, preq)
Definition: requirements.h:78
#define MIN(x, y)
Definition: shared.h:49
struct specialist * specialist_by_translated_name(const char *name)
Return the specialist type with the given (translated, plural) name.
Definition: specialist.cpp:124
size_t size
Definition: specvec.h:64
Definition: tech.h:113
struct connection conn
Definition: client_main.h:89
struct player * playing
Definition: connection.h:142
struct resource_type * resource
Definition: extras.h:136
QByteArray help_geometry
Definition: fc_client.h:65
QByteArray help_splitter1
Definition: fc_client.h:66
char * topic
Definition: helpdata.h:71
enum help_page_type type
Definition: helpdata.h:72
char * text
Definition: helpdata.h:71
Definition: mapimg.cpp:266
int upkeep
Definition: improvement.h:69
struct requirement_vector obsolete_by
Definition: improvement.h:67
struct requirement_vector reqs
Definition: improvement.h:66
Definition: climisc.h:66
struct extra_type ** resources
Definition: terrain.h:190
int road_time
Definition: terrain.h:194
int plant_time
Definition: terrain.h:198
int irrigation_food_incr
Definition: terrain.h:201
int clean_fallout_time
Definition: terrain.h:213
struct terrain * irrigation_result
Definition: terrain.h:200
int defense_bonus
Definition: terrain.h:186
int cultivate_time
Definition: terrain.h:196
int movement_cost
Definition: terrain.h:185
int pillage_time
Definition: terrain.h:214
int output[O_LAST]
Definition: terrain.h:188
int transform_time
Definition: terrain.h:211
struct terrain * mining_result
Definition: terrain.h:204
int mining_time
Definition: terrain.h:206
int clean_pollution_time
Definition: terrain.h:212
int road_output_incr_pct[O_LAST]
Definition: terrain.h:192
struct terrain * transform_result
Definition: terrain.h:210
int irrigation_time
Definition: terrain.h:202
int base_time
Definition: terrain.h:193
int mining_shield_incr
Definition: terrain.h:205
struct unit_class * uclass
Definition: unittype.h:519
int pop_cost
Definition: unittype.h:477
int defense_strength
Definition: unittype.h:480
int firepower
Definition: unittype.h:490
int build_cost
Definition: unittype.h:476
int convert_time
Definition: unittype.h:496
int city_size
Definition: unittype.h:515
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 bombard_rate
Definition: unittype.h:512
int hp
Definition: unittype.h:489
int fuel
Definition: unittype.h:497
int upkeep[O_LAST]
Definition: unittype.h:503
int attack_strength
Definition: unittype.h:479
int happy_cost
Definition: unittype.h:502
enum universals_n kind
Definition: fc_types.h:740
universals_u value
Definition: fc_types.h:739
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
struct advance * advance_by_translated_name(const char *name)
Does a linear search of advances[].name.translated Returns nullptr when none match.
Definition: tech.cpp:163
bool is_future_tech(Tech_type_id tech)
Is the given tech a future tech.
Definition: tech.cpp:268
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Definition: tech.cpp:94
Tech_type_id advance_number(const struct advance *padvance)
Return the advance index.
Definition: tech.cpp:85
const char * advance_name_translation(const struct advance *padvance)
Return the (translated) name of the given advance/technology.
Definition: tech.cpp:274
#define A_NONE
Definition: tech.h:36
Terrain_type_id terrain_count()
Return the number of terrains.
Definition: terrain.cpp:93
struct terrain * terrain_by_translated_name(const char *name)
Return the terrain type matching the name, or T_UNKNOWN if none matches.
Definition: terrain.cpp:158
struct terrain * terrain_by_number(const Terrain_type_id type)
Return the terrain for the given terrain index.
Definition: terrain.cpp:128
const char * terrain_name_translation(const struct terrain *pterrain)
Return the (translated) name of the terrain.
Definition: terrain.cpp:175
#define T_NONE
Definition: terrain.h:50
std::vector< drawn_sprite > fill_basic_terrain_layer_sprite_array(struct tileset *t, int layer, struct terrain *pterrain)
Fill the sprite array with sprites that together make a representative image of the given terrain typ...
Definition: tilespec.cpp:3642
const QPixmap * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Return the sprite for the nation.
Definition: tilespec.cpp:3367
int tileset_full_tile_height(const struct tileset *t)
Return the full tile height of the current tileset.
Definition: tilespec.cpp:407
const QPixmap * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Return the sprite for the technology/advance.
Definition: tilespec.cpp:3385
const struct citybar_sprites * get_citybar_sprites(const struct tileset *t)
Return all the sprites used for city bar drawing.
Definition: tilespec.cpp:3523
std::vector< drawn_sprite > fill_basic_extra_sprite_array(const struct tileset *t, const struct extra_type *pextra)
Return a representative sprite for the given extra type.
Definition: tilespec.cpp:3679
const QPixmap * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing, const QColor &replace)
Return the sprite for the unit type (the base "unit" sprite).
Definition: tilespec.cpp:3416
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
Definition: tilespec.cpp:383
const QPixmap * get_government_sprite(const struct tileset *t, const struct government *gov)
Return the sprite for the government.
Definition: tilespec.cpp:3404
int tileset_full_tile_width(const struct tileset *t)
Return the full tile width of the current tileset.
Definition: tilespec.cpp:394
const QPixmap * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Return the sprite for the building/improvement.
Definition: tilespec.cpp:3394
struct goods_type * goods_by_translated_name(const char *name)
struct terrain * terrain
Definition: fc_types.h:583
int utype_build_shield_cost_base(const struct unit_type *punittype)
Returns the number of shields this unit type represents.
Definition: unittype.cpp:1168
struct unit_type * unit_type_by_translated_name(const char *name)
Returns the unit type that has the given (translated) name.
Definition: unittype.cpp:1427
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
#define unit_type_iterate(_p)
Definition: unittype.h:785
#define unit_type_iterate_end
Definition: unittype.h:791
QPixmap * canvas
void put_drawn_sprites(QPixmap *pcanvas, const QPoint &canvas_loc, const std::vector< drawn_sprite > &sprites, bool fog, bool city_unit)
Draw an array of drawn sprites onto the canvas.