12 #include <QApplication>
13 #include <QGraphicsDropShadowEffect>
15 #include <QProgressBar>
17 #include <QScrollArea>
19 #include <QTreeWidget>
20 #include <QVBoxLayout>
40 #define MAX_HELP_TEXT_SIZE 8192
41 #define REQ_LABEL_NEVER _("(Never)")
42 #define REQ_LABEL_NONE _("?tech:None")
46 enum extra_cause cause = EC_COUNT);
48 extern QList<const struct help_item *> *
help_nodes;
101 QTreeWidgetItem *first;
105 setWindowTitle(
_(
"Freeciv21 Help Browser"));
108 layout =
new QVBoxLayout(
this);
119 connect(
tree_wdg, &QTreeWidget::currentItemChanged,
this,
121 help_wdg->layout()->setContentsMargins(0, 0, 0, 0);
124 buttons =
new QWidget;
125 hbox =
new QHBoxLayout;
127 style()->standardIcon(QStyle::QStyle::SP_ArrowLeft), (
""));
128 connect(
prev_butt, &QAbstractButton::clicked,
this,
132 style()->standardIcon(QStyle::QStyle::SP_ArrowRight), (
""));
133 connect(
next_butt, &QAbstractButton::clicked,
this,
136 hbox->addStretch(20);
137 but =
new QPushButton(style()->standardIcon(QStyle::SP_DialogHelpButton),
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);
176 if (!
king()->qt_settings.help_geometry.isNull()) {
177 restoreGeometry(
king()->qt_settings.help_geometry);
178 splitter->restoreState(
king()->qt_settings.help_splitter1);
180 resize(
size().boundedTo(screen()->availableSize()));
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});
207 QHash<int, QTreeWidgetItem *> hash;
209 QTreeWidgetItem *
item;
210 const QPixmap *spite;
220 for (
const auto *pitem : qAsConst(*
help_nodes)) {
223 title = pitem->topic;
224 for (s = pitem->topic; *s ==
' '; s++) {
228 item =
new QTreeWidgetItem(QStringList(title));
230 dep = s - pitem->topic;
231 hash.insert(dep,
item);
240 switch (pitem->type) {
245 QPixmap pix(*sprs.front().sprite);
248 for (std::size_t i = 1; i < sprs.size(); ++i) {
249 p.drawPixmap(0, 0, *sprs[i].sprite);
296 icon = QIcon(*spite);
298 if (!icon.isNull()) {
299 item->setIcon(0, icon);
302 hash.value(last)->addChild(
item);
314 QHash<QTreeWidgetItem *, const help_item *>::const_iterator i =
317 if (i.value() == topic) {
397 auto item_parents = std::set<QTreeWidgetItem *>();
398 for (
auto i =
item; i !=
nullptr; i = i->parent()) {
399 item_parents.insert(i);
401 for (
auto i = prev; i !=
nullptr; i = i->parent()) {
402 if (item_parents.count(i) == 0) {
415 : QWidget(parent), main_widget(nullptr), text_browser(nullptr),
416 bottom_panel(nullptr), info_panel(nullptr), splitter(nullptr),
426 : QWidget(parent), main_widget(nullptr), text_browser(nullptr),
427 bottom_panel(nullptr), info_panel(nullptr), splitter(nullptr),
448 QHBoxLayout *group_layout;
450 layout =
new QVBoxLayout();
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);
503 splitter =
new QSplitter(Qt::Vertical);
527 qobject_cast<QVBoxLayout *>(layout())->setStretchFactor(
main_widget, 100);
537 l = findChildren<QWidget *>();
540 for (
auto i : qAsConst(l)) {
546 for (
auto i : qAsConst(l)) {
552 for (
auto i : qAsConst(l)) {
596 QLabel *label =
new QLabel();
597 QGraphicsDropShadowEffect *
effect;
599 label->setAlignment(Qt::AlignHCenter);
600 label->setPixmap(*pm);
603 effect =
new QGraphicsDropShadowEffect(label);
606 label->setGraphicsEffect(
effect);
617 QLabel *label =
new QLabel(text);
618 label->setWordWrap(
true);
619 label->setTextFormat(Qt::RichText);
633 int min,
int max,
const QString &value)
641 layout =
new QGridLayout(wdg);
642 layout->setContentsMargins(0, 0, 0, 0);
643 layout->setVerticalSpacing(0);
645 label =
new QLabel(text, wdg);
646 layout->addWidget(label, 0, 0);
648 label =
new QLabel(wdg);
649 if (value.isEmpty()) {
650 label->setNum(progress);
652 label->setText(value);
655 layout->addWidget(label, 0, 1, Qt::AlignRight);
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);
670 QLabel *tb =
new QLabel(hw);
672 tb->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
673 tb->setTextFormat(Qt::RichText);
681 enum unit_activity act,
687 for_terr.
kind = VUT_TERRAIN;
692 if (pextra->buildable
699 str = str + QString(label)
704 tb->setText(str.trimmed());
705 connect(tb, &QLabel::linkActivated,
this,
719 s = QString(str).toHtmlEscaped().replace(QLatin1String(
" "),
720 QLatin1String(
" "));
721 return " <a href=" + QString::number(hpt) +
"," + s +
">" + s +
"</a> ";
748 sl = link.split(QStringLiteral(
","));
749 n = sl.at(0).toInt();
752 st = st.replace(
"\u00A0", QLatin1String(
" "));
755 && strcmp(qUtf8Printable(st),
758 && strcmp(qUtf8Printable(st),
770 char *title = topic->
topic;
771 for (; *title ==
' '; ++title) {
779 switch (topic->
type) {
851 int upkeep, max_upkeep;
911 str =
"<b>" + str +
"</b> "
913 tb->setText(str.trimmed());
914 connect(tb, &QLabel::linkActivated,
this,
928 str =
_(
"Obsoleted by");
929 str =
"<b>" + str +
"</b> "
933 tb->setText(str.trimmed());
934 connect(tb, &QLabel::linkActivated,
this,
940 QString(
_(
"Obsoleted by %1."))
978 str =
_(
"Base Cost:");
979 str =
"<b>" + str +
"</b>" +
" "
985 str =
"<b>" + str +
"</b>" +
" "
986 + QString::number(itype->
upkeep).toHtmlEscaped();
992 if (!preq->present) {
996 if (type == VUT_ADVANCE) {
1000 }
else if (type == VUT_GOVERNMENT) {
1004 }
else if (type == VUT_TERRAIN) {
1013 if (!s1.isEmpty()) {
1014 str =
_(
"Requirement:");
1015 str =
"<b>" + str +
"</b> " + s1;
1017 tb->setText(str.trimmed());
1018 connect(tb, &QLabel::linkActivated,
this,
1025 if (pobs->source.kind == VUT_ADVANCE) {
1033 str =
_(
"Obsolete by:");
1034 str =
"<b>" + str +
"</b> " + s2;
1035 if (!s2.isEmpty()) {
1037 tb->setText(str.trimmed());
1038 connect(tb, &QLabel::linkActivated,
this,
1070 if (VUT_ADVANCE == preq->source.kind
1071 && preq->source.value.advance == padvance) {
1074 str =
"<b>" + str +
"</b> "
1077 tb->setText(str.trimmed());
1078 connect(tb, &QLabel::linkActivated,
this,
1090 if (VUT_ADVANCE == preq->source.kind
1091 && preq->source.value.advance == padvance) {
1093 str =
"<b>" + str +
"</b> "
1098 tb->setText(str.trimmed());
1099 connect(tb, &QLabel::linkActivated,
this,
1108 if (pobs->source.kind == VUT_ADVANCE
1109 && pobs->source.value.advance == padvance) {
1110 str =
_(
"Obsoletes");
1111 str =
"<b>" + str +
"</b> "
1116 tb->setText(str.trimmed());
1117 connect(tb, &QLabel::linkActivated,
this,
1128 if (padvance != punittype->require_advance) {
1132 str =
"<b>" + str +
"</b> "
1135 tb->setText(str.trimmed());
1136 connect(tb, &QLabel::linkActivated,
this,
1157 enum extra_cause cause)
1160 int canvas_y, i, width, height;
1167 canvas =
new QPixmap(width, height);
1168 canvas->fill(Qt::transparent);
1169 for (i = 0; i < 3; ++i) {
1176 if (cause != EC_COUNT) {
1198 QHBoxLayout *layout)
1202 label =
new QLabel(title);
1203 layout->addWidget(label, Qt::AlignVCenter);
1205 label->setToolTip(tooltip);
1206 label->setMaximumHeight(QFontMetrics(f).height() * 1.2);
1212 QHBoxLayout *layout)
1222 img = spr->toImage();
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);
1240 const QPixmap *image,
1241 const int &food,
const int &sh,
1243 const QString &tooltip)
1245 QGraphicsDropShadowEffect *
effect;
1247 QHBoxLayout *layout =
new QHBoxLayout();
1248 QHBoxLayout *layout1 =
new QHBoxLayout();
1249 QHBoxLayout *layout2 =
new QHBoxLayout();
1254 label =
new QLabel();
1255 effect =
new QGraphicsDropShadowEffect(label);
1256 effect->setBlurRadius(3);
1258 label->setGraphicsEffect(
effect);
1259 label->setPixmap(*image);
1260 layout1->addWidget(label, Qt::AlignVCenter);
1261 w1->setLayout(layout1);
1267 ->setProperty(
"foodlab",
"true");
1271 ->setProperty(
"shieldlab",
"true");
1274 ->setProperty(
"ecolab",
"true");
1276 w2->setLayout(layout2);
1278 layout->addWidget(w1, Qt::AlignVCenter);
1279 layout->addWidget(w2, Qt::AlignVCenter);
1287 tb->setText(str.trimmed());
1299 struct terrain *pterrain, *max;
1302 bool show_panel =
false;
1311 for_terr.
kind = VUT_TERRAIN;
1315 topic->
text, pterrain);
1354 str =
N_(
"Cultivate Rslt/Time:");
1358 + QString(buffer).toHtmlEscaped();
1370 str =
N_(
"Plant Rslt/Time:");
1374 + QString(buffer).toHtmlEscaped();
1386 str =
N_(
"Transform Rslt/Time:");
1390 + QString(buffer).toHtmlEscaped();
1399 _(
"Build as irrigation"));
1404 _(
"Build as mine"));
1408 _(
"Build as road"));
1412 _(
"Build as base"));
1418 panel =
new QWidget();
1419 vbox =
new QVBoxLayout(panel);
1424 for (r = pterrain->
resources; *r; r++) {
1430 + (*r)->data.resource->output[
O_SHIELD],
1433 _(
"Output (Food, Shields, Trade) of a tile where the resource "
1441 vbox->addStretch(100);
1442 vbox->setSizeConstraint(QLayout::SetMinimumSize);
1444 area =
new QScrollArea();
1445 area->setWidget(panel);
1448 panel->deleteLater();
1482 topic->
text, pspec);
1577 for (i = 0; i < count; ++i) {
1579 #define SET_MAX(v) max->v = max->v > terrain->v ? max->v : terrain->v
1643 if (utype->uclass ==
uclass) {
1644 #define SET_MAX(v) max->v = max->v > utype->v ? max->v : utype->v
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
QRect zealous_crop_rect(QImage &p)
Return rectangle containing pure image (crops transparency)
QFont getFont(const QString &name, double zoom=1.0) const
Returns desired font.
static fcFont * instance()
Returns instance of fc_font.
void showEvent(QShowEvent *event) override
Show event.
help_dialog(QWidget *parent=0)
Constructor for help dialog.
void history_forward()
Goes to next topic in history.
void set_topic(const help_item *item)
Changes the displayed topic.
void closeEvent(QCloseEvent *event) override
Close event.
void make_tree()
Create the help tree.
QHash< QTreeWidgetItem *, const help_item * > topics_map
void item_changed(QTreeWidgetItem *item, QTreeWidgetItem *prev)
Called when a tree item is activated.
void update_fonts()
Update fonts for help_wdg.
void hideEvent(QHideEvent *event) override
Hide event.
void update_buttons()
Update buttons (back and next)
QList< QTreeWidgetItem * > item_history
void history_back()
Backs in history to previous topic.
struct nation_set * client_current_nation_set()
Returns the nation set in use.
class fc_client * king()
Return fc_client instance.
const char * skip_intl_qualifier_prefix(const char *str)
Some strings are ambiguous for translation.
#define PL_(String1, String2, n)
std::vector< government > governments
const char * government_name_translation(const struct government *pgovern)
Return the (translated) name of the given government.
struct government * government_by_translated_name(const char *name)
Returns the government that has the given (translated) name.
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.
void helptext_government(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct government *gov)
Append text for government.
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.
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.
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.
char * helptext_unit_upkeep_str(const struct unit_type *utype)
Returns pointer to static string with eg: "1 shield, 1 unhappy".
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,...
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.
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'.
void helptext_specialist(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct specialist *pspec)
Append misc dynamic text for specialists.
void helptext_terrain(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, struct terrain *pterrain)
Append text for terrain.
void helptext_nation(char *buf, size_t bufsz, struct nation_type *pnation, const char *user_text)
Returns nation legend and characteristics.
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.
QList< const struct help_item * > * help_nodes
static QLabel * set_properties(help_widget *hw)
void popdown_help_dialog(void)
Close the help dialog.
static void make_helppiclabel(QPixmap *spr, const QString &tooltip, QHBoxLayout *layout)
static help_dialog * help_dlg
void update_help_fonts()
Updates fonts.
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.
static QLabel * make_helplabel(const QString &title, const QString &tooltip, QHBoxLayout *layout)
#define MAX_HELP_TEXT_SIZE
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
#define improvement_iterate(_p)
#define fc_assert_ret_val(condition, val)
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...
const char *const default_font
const char *const notify_label
const char *const help_label
const char *const help_text
struct nation_type * nation_by_translated_plural(const char *name)
Returns the nation that has the given (translated) plural noun.
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
#define requirement_vector_iterate(req_vec, preq)
struct specialist * specialist_by_translated_name(const char *name)
Return the specialist type with the given (translated, plural) name.
QByteArray help_splitter1
struct requirement_vector obsolete_by
struct requirement_vector reqs
struct extra_type ** resources
struct terrain * irrigation_result
struct terrain * mining_result
int road_output_incr_pct[O_LAST]
struct terrain * transform_result
struct unit_class * uclass
const struct unit_type * obsoleted_by
struct advance * require_advance
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
struct advance * advance_by_translated_name(const char *name)
Does a linear search of advances[].name.translated Returns nullptr when none match.
bool is_future_tech(Tech_type_id tech)
Is the given tech a future tech.
struct advance * advance_by_number(const Tech_type_id atype)
Return the advance for the given advance index.
Tech_type_id advance_number(const struct advance *padvance)
Return the advance index.
const char * advance_name_translation(const struct advance *padvance)
Return the (translated) name of the given advance/technology.
Terrain_type_id terrain_count()
Return the number of terrains.
struct terrain * terrain_by_translated_name(const char *name)
Return the terrain type matching the name, or T_UNKNOWN if none matches.
struct terrain * terrain_by_number(const Terrain_type_id type)
Return the terrain for the given terrain index.
const char * terrain_name_translation(const struct terrain *pterrain)
Return the (translated) name of the terrain.
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...
const QPixmap * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Return the sprite for the nation.
int tileset_full_tile_height(const struct tileset *t)
Return the full tile height of the current tileset.
const QPixmap * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Return the sprite for the technology/advance.
const struct citybar_sprites * get_citybar_sprites(const struct tileset *t)
Return all the sprites used for city bar drawing.
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.
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).
int tileset_tile_height(const struct tileset *t)
Return the tile height of the current tileset.
const QPixmap * get_government_sprite(const struct tileset *t, const struct government *gov)
Return the sprite for the government.
int tileset_full_tile_width(const struct tileset *t)
Return the full tile width of the current tileset.
const QPixmap * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Return the sprite for the building/improvement.
struct goods_type * goods_by_translated_name(const char *name)
int utype_build_shield_cost_base(const struct unit_type *punittype)
Returns the number of shields this unit type represents.
struct unit_type * unit_type_by_translated_name(const char *name)
Returns the unit type that has the given (translated) name.
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
#define unit_type_iterate(_p)
#define unit_type_iterate_end
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.