Freeciv-3.1
Loading...
Searching...
No Matches
pages.cpp
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2004 - The Freeciv Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18// Qt
19#include <QAction>
20#include <QApplication>
21#include <QCheckBox>
22#include <QDateTime>
23#include <QFileDialog>
24#include <QGridLayout>
25#include <QHeaderView>
26#include <QLineEdit>
27#include <QPainter>
28#include <QSplitter>
29#include <QStackedWidget>
30#include <QTableWidget>
31#include <QTextEdit>
32#include <QTreeWidget>
33
34// common
35#include "game.h"
36#include "version.h"
37
38// client
39#include "client_main.h"
40#include "connectdlg_common.h"
41
42// gui-qt
43#include "colors.h"
44#include "dialogs.h"
45#include "fc_client.h"
46#include "pages.h"
47#include "plrdlg.h"
48#include "qtg_cxxside.h"
49#include "sidebar.h"
50#include "sprite.h"
51#include "voteinfo_bar.h"
52
53extern "C" {
54#include "repodlgs_g.h"
55#include "cityrep_g.h"
56const char *science_dialog_text(void);
57const char *get_bulb_tooltip(void);
58const char *get_global_warming_tooltip(void);
59const char *get_nuclear_winter_tooltip(void);
60const char *get_government_tooltip(void);
61const char *get_info_label_text_popup(void);
62const char *get_info_label_text(bool);
63const char *text_happiness_cities(const struct city *pcity);
64}
65
69extern void toggle_units_report(bool);
70extern void popup_shortcuts_dialog();
71static void center_next_enemy_city();
72static void center_next_player_city();
73static void center_next_player_capital();
75static bool holding_srv_list_mutex = false;
77static struct terrain *char2terrain(char ch);
78static void cycle_enemy_units();
80
81/**********************************************************************/
85static struct terrain *char2terrain(char ch)
86{
88 return T_UNKNOWN;
89 }
90 terrain_type_iterate(pterrain) {
91 if (pterrain->identifier_load == ch) {
92 return pterrain;
93 }
95 return nullptr;
96}
97
98
99/**********************************************************************/
102void qtg_real_set_client_page(enum client_pages page)
103{
104 gui()->switch_page(page);
105}
106
107/**********************************************************************/
112void qtg_set_rulesets(int num_rulesets, char **rulesets)
113{
114 gui()->pr_options->set_rulesets(num_rulesets, rulesets);
115}
116
117/**********************************************************************/
121{
122 return gui()->current_page();
123}
124
125/**********************************************************************/
129{
130 gui()->update_start_page();
131}
132
133/**********************************************************************/
137{
138 QPixmap main_graphics(tileset_main_intro_filename(tileset));
139 QLabel* free_main_pic = new QLabel;
140 QPainter painter(&main_graphics);
141 QStringList buttons_names;
142 int buttons_nr;
143 char msgbuf[128];
144 const char *rev_ver;
145 QFont f = QApplication::font();
146 QFontMetrics fm(f);
147 int row = 0;
148#if IS_BETA_VERSION || IS_DEVEL_VERSION
149 QPalette warn_color;
150 QLabel *unstable_label = new QLabel(unstable_message());
151#endif // IS_BETA_VERSION || IS_DEVEL_VERSION
152
153 pages_layout[PAGE_MAIN] = new QGridLayout;
154
155 painter.setPen(Qt::white);
156
157 rev_ver = fc_git_revision();
158
159 if (rev_ver == NULL) {
160 /* TRANS: "version 3.1.0, Qt5 client" */
161#ifdef FC_QT5_MODE
162 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, Qt5 client"),
163 word_version(), VERSION_STRING);
164#else // FC_QT5_MODE
165 fc_snprintf(msgbuf, sizeof(msgbuf), _("%s%s, Qt6 client"),
166 word_version(), VERSION_STRING);
167#endif // FC_QT5_MODE
168 } else {
169 fc_snprintf(msgbuf, sizeof(msgbuf), "%s%s",
170 word_version(), VERSION_STRING);
171 painter.drawText(10,
172 main_graphics.height() - fm.descent() - fm.height() * 2,
173 msgbuf);
174
175 /* TRANS: "commit: [modified] <git commit id>" */
176 fc_snprintf(msgbuf, sizeof(msgbuf), _("commit: %s"), rev_ver);
177 painter.drawText(10,
178 main_graphics.height() - fm.descent() - fm.height(),
179 msgbuf);
180
181#ifdef FC_QT5_MODE
182 strncpy(msgbuf, _("Qt5 client"), sizeof(msgbuf) - 1);
183#else // FC_QT5_MODE
184 strncpy(msgbuf, _("Qt6 client"), sizeof(msgbuf) - 1);
185#endif // FC_QT5_MODE
186 }
187
188 painter.drawText(main_graphics.width() - fm.horizontalAdvance (msgbuf)
189 -10, main_graphics.height() - fm.descent(), msgbuf);
190 free_main_pic->setPixmap(main_graphics);
191 pages_layout[PAGE_MAIN]->addWidget(free_main_pic,
192 row++, 0, 1, 2, Qt::AlignCenter);
193
194#if IS_BETA_VERSION || IS_DEVEL_VERSION
195 warn_color.setColor(QPalette::WindowText, Qt::red);
196 unstable_label->setPalette(warn_color);
197 unstable_label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Maximum);
198 unstable_label->setAlignment(Qt::AlignCenter);
199 pages_layout[PAGE_MAIN]->addWidget(unstable_label,
200 row++, 0, 1, 2, Qt::AlignHCenter);
201#endif // IS_BETA_VERSION || IS_DEVEL_VERSION
202
203 buttons_names << _("Start new game") << _("Start scenario game")
204 << _("Load saved game") << _("Connect to network game")
205 << _("Options") << _("Quit");
206
207 buttons_nr = buttons_names.count();
208
209 for (int iter = 0; iter < buttons_nr; iter++) {
210 button = new QPushButton(buttons_names[iter]);
211
212 switch (iter) {
213 case 0:
214 pages_layout[PAGE_MAIN]->addWidget(button, row + 1, 0);
215 connect(button, &QAbstractButton::clicked, this, &fc_client::start_new_game);
216 break;
217 case 1:
218 pages_layout[PAGE_MAIN]->addWidget(button, row + 2, 0);
219 QObject::connect(button, &QPushButton::clicked, [this]() {
220 switch_page(PAGE_SCENARIO);
221 });
222 break;
223 case 2:
224 pages_layout[PAGE_MAIN]->addWidget(button, row + 3, 0);
225 QObject::connect(button, &QPushButton::clicked, [this]() {
226 switch_page(PAGE_LOAD);
227 });
228 break;
229 case 3:
230 pages_layout[PAGE_MAIN]->addWidget(button, row + 1, 1);
231 QObject::connect(button, &QPushButton::clicked, [this]() {
232 switch_page(PAGE_NETWORK);
233 });
234 break;
235 case 4:
236 pages_layout[PAGE_MAIN]->addWidget(button, row + 2, 1);
237 connect(button, &QAbstractButton::clicked, this, &fc_client::popup_client_options);
238 break;
239 case 5:
240 pages_layout[PAGE_MAIN]->addWidget(button, row + 3, 1);
241 QObject::connect(button, &QAbstractButton::clicked, this, &fc_client::quit);
242 break;
243 default:
244 break;
245 }
246 }
247}
248
249/**********************************************************************/
253{
254 switch (state) {
255 case LOGIN_TYPE:
256 set_status_bar("");
257 connect_password_edit->setText("");
258 connect_password_edit->setDisabled(true);
260 connect_confirm_password_edit->setDisabled(true);
261 break;
263 connect_password_edit->setText("");
265 connect_password_edit->setDisabled(false);
266 connect_confirm_password_edit->setDisabled(false);
267 connect_password_edit->setFocus(Qt::OtherFocusReason);
268 break;
270 connect_password_edit->setText("");
272 connect_password_edit->setDisabled(false);
273 connect_confirm_password_edit->setDisabled(true);
274 connect_password_edit->setFocus(Qt::OtherFocusReason);
275
276
277 break;
278 case WAITING_TYPE:
279 set_status_bar("");
280 break;
281 }
282
283 connection_status = state;
284}
285
286/**********************************************************************/
290{
291 QHeaderView *header;
292 QLabel *connect_msg;
293 QLabel *lan_label;
294 QPushButton *network_button;
295
296 pages_layout[PAGE_NETWORK] = new QGridLayout;
297 QVBoxLayout *page_network_layout = new QVBoxLayout;
298 QGridLayout *page_network_grid_layout = new QGridLayout;
299 QHBoxLayout *page_network_lan_layout = new QHBoxLayout;
300 QHBoxLayout *page_network_wan_layout = new QHBoxLayout;
301
302 connect_host_edit = new QLineEdit;
303 connect_port_edit = new QLineEdit;
304 connect_login_edit = new QLineEdit;
305 connect_password_edit = new QLineEdit;
306 connect_confirm_password_edit = new QLineEdit;
307
308 connect_password_edit->setEchoMode(QLineEdit::Password);
309 connect_confirm_password_edit->setEchoMode(QLineEdit::Password);
310
311 connect_password_edit->setDisabled(true);
312 connect_confirm_password_edit->setDisabled(true);
313 connect_lan = new QWidget;
314 connect_metaserver = new QWidget;
315 lan_widget = new QTableWidget;
316 wan_widget = new QTableWidget;
317 info_widget = new QTableWidget;
318
319 QStringList servers_list;
320 servers_list << _("Server Name") << _("Port") << _("Version")
321 << _("Status") << Q_("?count:Players") << _("Comment");
322 QStringList server_info;
323 server_info << _("Name") << _("Type") << _("Host") << _("Nation");
324
325 lan_widget->setRowCount(0);
326 lan_widget->setColumnCount(servers_list.count());
327 lan_widget->verticalHeader()->setVisible(false);
328 lan_widget->setAutoScroll(false);
329
330 wan_widget->setRowCount(0);
331 wan_widget->setColumnCount(servers_list.count());
332 wan_widget->verticalHeader()->setVisible(false);
333 wan_widget->setAutoScroll(false);
334
335 info_widget->setRowCount(0);
336 info_widget->setColumnCount(server_info.count());
337 info_widget->verticalHeader()->setVisible(false);
338
339 lan_widget->setHorizontalHeaderLabels(servers_list);
340 lan_widget->setProperty("showGrid", "false");
341 lan_widget->setProperty("selectionBehavior", "SelectRows");
342 lan_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
343 lan_widget->setSelectionMode(QAbstractItemView::SingleSelection);
344
345 wan_widget->setHorizontalHeaderLabels(servers_list);
346 wan_widget->setProperty("showGrid", "false");
347 wan_widget->setProperty("selectionBehavior", "SelectRows");
348 wan_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
349 wan_widget->setSelectionMode(QAbstractItemView::SingleSelection);
350
351 connect(wan_widget->selectionModel(),
352 &QItemSelectionModel::selectionChanged, this,
354
355 connect(lan_widget->selectionModel(),
356 &QItemSelectionModel::selectionChanged, this,
358 connect(wan_widget, &QTableWidget::itemDoubleClicked, this,
360 connect(lan_widget, &QTableWidget::itemDoubleClicked, this,
362
363 info_widget->setHorizontalHeaderLabels(server_info);
364 info_widget->setProperty("selectionBehavior", "SelectRows");
365 info_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
366 info_widget->setSelectionMode(QAbstractItemView::SingleSelection);
367 info_widget->setProperty("showGrid", "false");
368 info_widget->setAlternatingRowColors(true);
369
370 header = lan_widget->horizontalHeader();
371 header->setSectionResizeMode(0, QHeaderView::Stretch);
372 header->setStretchLastSection(true);
373 header = wan_widget->horizontalHeader();
374 header->setSectionResizeMode(0, QHeaderView::Stretch);
375 header->setStretchLastSection(true);
376 header = info_widget->horizontalHeader();
377 header->setSectionResizeMode(0, QHeaderView::Stretch);
378 header->setStretchLastSection(true);
379
380 QStringList label_names;
381 label_names << _("Connect") << _("Port") << _("Login")
382 << _("Password") << _("Confirm Password");
383
384 for (int i = 0; i < label_names.count(); i++) {
385 connect_msg = new QLabel;
386 connect_msg->setText(label_names[i]);
387 page_network_grid_layout->addWidget(connect_msg, i, 0, Qt::AlignHCenter);
388 }
389
390 page_network_grid_layout->addWidget(connect_host_edit, 0, 1);
391 page_network_grid_layout->addWidget(connect_port_edit, 1, 1);
392 page_network_grid_layout->addWidget(connect_login_edit, 2, 1);
393 page_network_grid_layout->addWidget(connect_password_edit, 3, 1);
394 page_network_grid_layout->addWidget(connect_confirm_password_edit, 4, 1);
395 page_network_grid_layout->addWidget(info_widget, 0, 2, 5, 4);
396
397 network_button = new QPushButton(_("Refresh"));
398 QObject::connect(network_button, &QAbstractButton::clicked, this,
400 page_network_grid_layout->addWidget(network_button, 5, 0);
401
402 network_button = new QPushButton(_("Cancel"));
403 QObject::connect(network_button, &QPushButton::clicked, [this]() {
404 switch_page(PAGE_MAIN);
405 });
406 page_network_grid_layout->addWidget(network_button, 5, 2, 1, 1);
407
408 network_button = new QPushButton(_("Connect"));
409 page_network_grid_layout->addWidget(network_button, 5, 5, 1, 1);
410 connect(network_button, &QAbstractButton::clicked, this, &fc_client::slot_connect);
411 connect(connect_login_edit, &QLineEdit::returnPressed,
413 connect(connect_password_edit, &QLineEdit::returnPressed,
415 connect(connect_confirm_password_edit, &QLineEdit::returnPressed,
417
418 connect_lan->setLayout(page_network_lan_layout);
419 connect_metaserver->setLayout(page_network_wan_layout);
420 page_network_lan_layout->addWidget(lan_widget, 0);
421 page_network_wan_layout->addWidget(wan_widget, 1);
422 lan_label = new QLabel(_("Internet servers:"));
423 page_network_layout->addWidget(lan_label, 1);
424 page_network_layout->addWidget(wan_widget, 10);
425 lan_label = new QLabel(_("Local servers:"));
426 page_network_layout->addWidget(lan_label, 1);
427 page_network_layout->addWidget(lan_widget, 1);
428 page_network_grid_layout->setColumnStretch(3, 4);
429 pages_layout[PAGE_NETWORK]->addLayout(page_network_layout, 1, 1);
430 pages_layout[PAGE_NETWORK]->addLayout(page_network_grid_layout, 2, 1);
431
432}
433
434/**********************************************************************/
437void fc_client::set_status_bar(QString message, int timeout)
438{
439 if (status_bar_label->text().isEmpty()) {
440 status_bar_label->setText(message);
441 QTimer::singleShot(timeout, this, SLOT(clear_status_bar()));
442 } else {
444 while (status_bar_queue.count() > 3) {
445 status_bar_queue.removeFirst();
446 }
447 }
448}
449
450/**********************************************************************/
454{
455 QString str;
456
457 if (!status_bar_queue.isEmpty()) {
458 str = status_bar_queue.takeFirst();
459 status_bar_label->setText(str);
460 QTimer::singleShot(2000, this, SLOT(clear_status_bar()));
461 } else {
462 status_bar_label->setText("");
463 }
464}
465
466/**********************************************************************/
470{
471 QLabel *label = new QLabel(_("Loading..."));
472
473 pages_layout[PAGE_GAME + 1] = new QGridLayout;
474 pages_layout[PAGE_GAME + 1]->addWidget(label, 0, 0, 1, 1,
475 Qt::AlignHCenter);
476}
477
478/**********************************************************************/
482{
483 pages_layout[PAGE_LOAD] = new QGridLayout;
484 QPushButton *but;
485 QHeaderView *header;
486 QLabel *lbl_show_preview;
487 QWidget *wdg;
488 QHBoxLayout *hbox;
489
490 saves_load = new QTableWidget;
491 wdg = new QWidget;
492 hbox = new QHBoxLayout;
493 QStringList sav;
494 lbl_show_preview = new QLabel(_("Show preview"));
495 sav << _("Choose Saved Game to Load") << _("Date");
496 load_pix = new QLabel;
497 load_pix->setProperty("themed_border", true);
498 load_pix->setFixedSize(0 ,0);
499 load_save_text = new QLabel;
500 load_save_text->setTextFormat(Qt::RichText);
501 load_save_text->setWordWrap(true);
502 show_preview = new QCheckBox;
504 saves_load->setAlternatingRowColors(true);
505 saves_load->setRowCount(0);
506 saves_load->setColumnCount(sav.count());
507 saves_load->setHorizontalHeaderLabels(sav);
508 hbox->addWidget(show_preview);
509 hbox->addWidget(lbl_show_preview, Qt::AlignLeft);
510 wdg->setLayout(hbox);
511
512 saves_load->setProperty("showGrid", "false");
513 saves_load->setProperty("selectionBehavior", "SelectRows");
514 saves_load->setEditTriggers(QAbstractItemView::NoEditTriggers);
515 saves_load->setSelectionMode(QAbstractItemView::SingleSelection);
516 saves_load->verticalHeader()->setVisible(false);
517
518 header = saves_load->horizontalHeader();
519 header->setSectionResizeMode(0, QHeaderView::Stretch);
520 header->setStretchLastSection(true);
521
522 pages_layout[PAGE_LOAD]->addWidget(saves_load, 0, 0, 1, 4);
523 connect(saves_load->selectionModel(),
524 &QItemSelectionModel::selectionChanged, this,
526 connect(show_preview, &QCheckBox::stateChanged, this,
528 pages_layout[PAGE_LOAD]->addWidget(wdg, 1, 0);
529 pages_layout[PAGE_LOAD]->addWidget(load_save_text, 2, 0, 1, 2);
530 pages_layout[PAGE_LOAD]->addWidget(load_pix, 2, 2, 1, 2);
531
532 but = new QPushButton;
533 but->setText(_("Browse..."));
534 but->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirIcon));
535 connect(but, &QAbstractButton::clicked, this, &fc_client::browse_saves);
536 pages_layout[PAGE_LOAD]->addWidget(but, 3, 0);
537
538 but = new QPushButton;
539 but->setText(_("Cancel"));
540 but->setIcon(QApplication::style()->standardIcon(
541 QStyle::SP_DialogCancelButton));
542 connect(but, &QAbstractButton::clicked, this, &fc_client::slot_disconnect);
543 pages_layout[PAGE_LOAD]->addWidget(but, 3, 2);
544
545 but = new QPushButton;
546 but->setText(_("Load"));
547 but->setIcon(QApplication::style()->standardIcon(
548 QStyle::SP_DialogOkButton));
549 connect(but, &QAbstractButton::clicked, this, &fc_client::start_from_save);
550 pages_layout[PAGE_LOAD]->addWidget(but, 3, 3);
551 pages_layout[PAGE_LOAD]->setColumnStretch(3, 10);
552 pages_layout[PAGE_LOAD]->setColumnStretch(2, 10);
553 pages_layout[PAGE_LOAD]->setColumnStretch(0, 10);
554
555}
556
557/**********************************************************************/
561{
562 QPushButton *but;
563 QHeaderView *header;
564 QStringList sav;
565
566 pages_layout[PAGE_SCENARIO] = new QGridLayout;
567 scenarios_load = new QTableWidget;
568 scenarios_view = new QTextEdit;
569 scenarios_text = new QLabel;
570
571 scenarios_view->setObjectName("scenarios_view");
572 scenarios_text->setTextFormat(Qt::RichText);
573 scenarios_text->setWordWrap(true);
574 sav << _("Choose a Scenario");
575 scenarios_load->setRowCount(0);
576 scenarios_load->setColumnCount(sav.count());
577 scenarios_load->setHorizontalHeaderLabels(sav);
578 scenarios_load->setProperty("showGrid", "false");
579 scenarios_load->setProperty("selectionBehavior", "SelectRows");
580 scenarios_load->setEditTriggers(QAbstractItemView::NoEditTriggers);
581 scenarios_load->setSelectionMode(QAbstractItemView::SingleSelection);
582 scenarios_load->verticalHeader()->setVisible(false);
583 pages_layout[PAGE_SCENARIO]->addWidget(scenarios_load, 0, 0, 3, 3,
584 Qt::AlignLeft);
585 pages_layout[PAGE_SCENARIO]->addWidget(scenarios_view, 1, 3, 2, 3);
586 pages_layout[PAGE_SCENARIO]->addWidget(scenarios_text, 0, 3, 1, 2,
587 Qt::AlignTop);
588 scenarios_view->setReadOnly(true);
589 scenarios_view->setWordWrapMode(QTextOption::WordWrap);
590 scenarios_text->setAlignment(Qt::AlignCenter);
591
592 header = scenarios_load->horizontalHeader();
593 header->setSectionResizeMode(0, QHeaderView::Stretch);
594 header->setStretchLastSection(true);
595 connect(scenarios_load->selectionModel(),
596 &QItemSelectionModel::selectionChanged, this,
598
599 but = new QPushButton;
600 but->setText(_("Browse..."));
601 but->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirIcon));
602 connect(but, &QAbstractButton::clicked, this, &fc_client::browse_scenarios);
603 pages_layout[PAGE_SCENARIO]->addWidget(but, 4, 0);
604
605 but = new QPushButton;
606 but->setText(_("Cancel"));
607 but->setIcon(QApplication::style()->standardIcon(
608 QStyle::SP_DialogCancelButton));
609 connect(but, &QAbstractButton::clicked, this, &fc_client::slot_disconnect);
610 pages_layout[PAGE_SCENARIO]->addWidget(but, 4, 3);
611
612 pages_layout[PAGE_SCENARIO]->setColumnStretch(2, 10);
613 pages_layout[PAGE_SCENARIO]->setColumnStretch(4, 20);
614 pages_layout[PAGE_SCENARIO]->setColumnStretch(3, 20);
615 pages_layout[PAGE_SCENARIO]->setRowStretch(1, 5);
616 but = new QPushButton;
617 but->setText(_("Load Scenario"));
618 but->setIcon(QApplication::style()->standardIcon(
619 QStyle::SP_DialogOkButton));
620 connect(but, &QAbstractButton::clicked, this, &fc_client::start_scenario);
621 pages_layout[PAGE_SCENARIO]->addWidget(but, 4, 4);
622}
623
624/**********************************************************************/
628{
629 QPushButton *but;
630 QSplitter *splitter;
631 QGridLayout *up_layout;
632 QGridLayout *down_layout;
633 QWidget *up_widget;
634 QWidget *down_widget;
635 QFont f;
636
637 QStringList player_widget_list;
638 pages_layout[PAGE_START] = new QGridLayout;
639 up_layout = new QGridLayout;
640 down_layout = new QGridLayout;
641 start_players_tree = new QTreeWidget;
642 pr_options = new pregame_options(this);
643 chat_line = new chat_input;
644 chat_line->setProperty("doomchat", true);
645 output_window = new QTextEdit;
646 output_window->setReadOnly(false);
647 f.setBold(true);
648 output_window->setFont(f);
649
650 pr_options->init();
651 player_widget_list << _("Name") << _("Ready") << Q_("?player:Leader")
652 << _("Flag") << _("Border") << _("Nation") << _("Team")
653 << _("Host");
654
655 start_players_tree->setColumnCount(player_widget_list.count());
656 start_players_tree->setHeaderLabels(player_widget_list);
657 start_players_tree->setContextMenuPolicy(Qt::CustomContextMenu);
658 start_players_tree->setProperty("selectionBehavior", "SelectRows");
659 start_players_tree->setEditTriggers(QAbstractItemView::NoEditTriggers);
660 start_players_tree->setRootIsDecorated(false);
661
662 connect(start_players_tree,
663 SIGNAL(customContextMenuRequested(const QPoint&)),
664 SLOT(start_page_menu(QPoint)));
665
666 up_layout->addWidget(start_players_tree, 0, 0, 3, 6);
667 up_layout->addWidget(pr_options, 0, 6, 3, 2);
668 but = new QPushButton;
669 but->setText(_("Disconnect"));
670 but->setIcon(style()->standardPixmap(QStyle::SP_DialogCancelButton));
671 QObject::connect(but, &QAbstractButton::clicked, this, &fc_client::slot_disconnect);
672 down_layout->addWidget(but, 5, 4);
673 nation_button = new QPushButton;
674 nation_button->setText(_("Pick Nation"));
675 nation_button->setIcon(fc_icons::instance()->get_icon("flag"));
676 down_layout->addWidget(nation_button, 5, 5);
677 QObject::connect(nation_button, &QAbstractButton::clicked, this,
679
680 obs_button = new QPushButton;
681 obs_button->setText(_("Observe"));
682 obs_button->setIcon(fc_icons::instance()->get_icon("meeting-observer"));
683 down_layout->addWidget(obs_button, 5, 6);
684 QObject::connect(obs_button, &QAbstractButton::clicked, this,
686 start_button = new QPushButton;
687 start_button->setText(_("Start"));
688 start_button->setIcon(style()->standardPixmap(QStyle::SP_DialogOkButton));
689 down_layout->addWidget(start_button, 5, 7);
690 QObject::connect(start_button, &QAbstractButton::clicked, this,
692 pre_vote = new pregamevote;
693
694 down_layout->addWidget(pre_vote, 4, 0, 1, 4);
695 down_layout->addWidget(chat_line, 5, 0, 1, 4);
696 down_layout->addWidget(output_window, 3, 0, 1, 8);
697 splitter = new QSplitter;
698 up_widget = new QWidget();
699 down_widget = new QWidget();
700 up_widget->setLayout(up_layout);
701 down_widget->setLayout(down_layout);
702 splitter->addWidget(up_widget);
703 splitter->addWidget(down_widget);
704 splitter->setOrientation(Qt::Vertical);
705 pages_layout[PAGE_START]->addWidget(splitter);
706}
707
708/**********************************************************************/
712{
713 QGridLayout *game_layout;
714
715 pages_layout[PAGE_GAME] = new QGridLayout;
716 game_main_widget = new QWidget;
717 game_layout = new QGridLayout;
718 game_layout->setContentsMargins(0, 0, 0, 0);
719 game_layout->setSpacing(0);
720 mapview_wdg = new map_view();
721 mapview_wdg->setFocusPolicy(Qt::WheelFocus);
722 sidebar_wdg = new fc_sidebar();
723
724 sw_map = new fc_sidewidget(fc_icons::instance()->get_pixmap("view"),
725 Q_("?noun:View"), "MAP", side_show_map);
726 sw_tax = new fc_sidewidget(nullptr, nullptr, "", side_rates_wdg, SW_TAX);
727 sw_indicators = new fc_sidewidget(nullptr, nullptr, "", side_show_map,
730 sw_cunit = new fc_sidewidget(fc_icons::instance()->get_pixmap("units"),
731 _("Units"), "",
733 sw_cities = new fc_sidewidget(fc_icons::instance()->get_pixmap("cities"),
734 _("Cities"), "CTS",
738 sw_diplo = new fc_sidewidget(fc_icons::instance()->get_pixmap("nations"),
739 _("Nations"), "PLR", popup_players_dialog);
742 sw_science = new fc_sidewidget(fc_icons::instance()->get_pixmap("research"),
743 _("Research"), "SCI",
745 sw_economy = new fc_sidewidget(fc_icons::instance()->get_pixmap("economy"),
746 _("Economy"), "ECO",
748 sw_endturn = new fc_sidewidget(fc_icons::instance()->get_pixmap("endturn"),
749 _("Turn Done"), "", side_finish_turn);
755
765
767 minimapview_wdg->show();
770 battlelog_wdg->hide();
772 infotab->show();
773 x_vote = new xvote(mapview_wdg);
774 x_vote->hide();
776 gtd->hide();
777
778 game_layout->addWidget(mapview_wdg, 1, 0);
779 game_main_widget->setLayout(game_layout);
781 game_tab_widget->setMinimumSize(600,400);
782 game_tab_widget->setContentsMargins(0, 0, 0, 0);
785 pages_layout[PAGE_GAME]->addWidget(sidebar_wdg, 1, 0);
786 } else {
787 pages_layout[PAGE_GAME]->addWidget(sidebar_wdg, 1, 2);
788 }
789 pages_layout[PAGE_GAME]->addWidget(game_tab_widget, 1, 1);
790 pages_layout[PAGE_GAME]->setContentsMargins(0, 0, 0, 0);
791 pages_layout[PAGE_GAME]->setSpacing(0);
792}
793
794/**********************************************************************/
798{
799 int i;
800
801 i = game_tab_widget->addWidget(widget);
802 game_tab_widget->setCurrentWidget(widget);
803 return i;
804}
805
806/**********************************************************************/
810{
811 game_tab_widget->removeWidget(game_tab_widget->widget(index));
812}
813
814/**********************************************************************/
818{
819 QString str;
820 str = QString(_("Save Files"))
821 + QString(" (*.sav *.sav.bz2 *.sav.gz *.sav.xz *.sav.zst)");
822 current_file = QFileDialog::getOpenFileName(gui()->central_wdg,
823 _("Open Save File"),
824 QDir::homePath(), str);
825 if (!current_file.isEmpty()) {
827 }
828}
829
830/**********************************************************************/
833void fc_client::state_preview(int new_state)
834{
835 QItemSelection slctn;
836
837 if (show_preview->checkState() == Qt::Unchecked) {
839 } else {
841 }
842 slctn = saves_load->selectionModel()->selection();
843 saves_load->selectionModel()->clearSelection();
844 saves_load->selectionModel()->select(slctn, QItemSelectionModel::Rows
845 | QItemSelectionModel::SelectCurrent);
846}
847
848/**********************************************************************/
852{
853 QString str;
854
855 str = QString(_("Scenarios Files"))
856 + QString(" (*.sav *.sav.bz2 *.sav.gz *.sav.xz *.sav.zst)");
857 current_file = QFileDialog::getOpenFileName(gui()->central_wdg,
858 _("Open Scenario File"),
859 QDir::homePath(), str);
860 if (!current_file.isEmpty()) {
862 }
863}
864
865/**********************************************************************/
869 const struct server_list *list)
870{
871 QTableWidget* sel = NULL;
872 QString host, portstr;
873 int port;
874 int row;
875 int old_row_count;
876
877 switch (sstype) {
879 sel = lan_widget;
880 break;
882 sel = wan_widget;
883 break;
884 default:
885 break;
886 }
887
888 if (!sel) {
889 return;
890 }
891
892 if (!list) {
893 return;
894 }
895
896 host = connect_host_edit->text();
897 portstr = connect_port_edit->text();
898 port = portstr.toInt();
899 old_row_count = sel->rowCount();
900 sel->clearContents();
901 row = 0;
902 server_list_iterate(list, pserver) {
903 char buf[35];
904 int tmp;
905 QString tstring;
906
907 if (old_row_count <= row) {
908 sel->insertRow(row);
909 }
910
911 if (pserver->humans >= 0) {
912 fc_snprintf(buf, sizeof(buf), "%d", pserver->humans);
913 } else {
914 strncpy(buf, _("Unknown"), sizeof(buf) - 1);
915 buf[sizeof(buf) - 1] = '\0';
916 }
917
918 tmp = pserver->port;
919 tstring = QString::number(tmp);
920
921 for (int col = 0; col < 6; col++) {
922 QTableWidgetItem *item;
923
924 item = new QTableWidgetItem();
925
926 switch (col) {
927 case 0:
928 item->setText(pserver->host);
929 break;
930 case 1:
931 item->setText(tstring);
932 break;
933 case 2:
934 item->setText(pserver->version);
935 break;
936 case 3:
937 item->setText(_(pserver->state));
938 break;
939 case 4:
940 item->setText(buf);
941 break;
942 case 5:
943 item->setText(pserver->message);
944 break;
945 default:
946 break;
947 }
948 sel->setItem(row, col, item);
949 }
950
951 if (host == pserver->host && port == pserver->port) {
952 sel->selectRow(row);
953 }
954
955 row++;
957
958 /* Remove unneeded rows, if there are any */
959 while (old_row_count - row > 0) {
960 sel->removeRow(old_row_count - 1);
961 old_row_count--;
962 }
963
964}
965
966/**********************************************************************/
969void server_scan_error(struct server_scan *scan, const char *message)
970{
972 log_error("%s", message);
973
974 /* Main thread will finalize the scan later (or even concurrently) -
975 * do not do anything here to cause double free or raze condition. */
976}
977
978
979/**********************************************************************/
983{
984 if (meta_scan) {
986 meta_scan = NULL;
987 }
988
989 if (meta_scan_timer != NULL) {
990 meta_scan_timer->stop();
991 meta_scan_timer->disconnect();
992 delete meta_scan_timer;
993 meta_scan_timer = NULL;
994 }
995
996 if (lan_scan) {
998 lan_scan = NULL;
999 }
1000
1001 if (lan_scan_timer != NULL) {
1002 lan_scan_timer->stop();
1003 lan_scan_timer->disconnect();
1004 delete lan_scan_timer;
1005 lan_scan_timer = NULL;
1006 }
1007}
1008
1009/**********************************************************************/
1013{
1015
1016 lan_scan_timer = new QTimer(this);
1018 connect(lan_scan_timer, &QTimer::timeout, this, &fc_client::slot_lan_scan);
1019 lan_scan_timer->start(500);
1020
1021 meta_scan_timer = new QTimer(this);
1023 connect(meta_scan_timer, &QTimer::timeout, this, &fc_client::slot_meta_scan);
1024 meta_scan_timer->start(800);
1025
1026}
1027
1028/**********************************************************************/
1032{
1033 struct server_scan *scan = scan_data;
1034 enum server_scan_status stat;
1035
1036 if (!scan) {
1037 return false;
1038 }
1039
1040 stat = server_scan_poll(scan);
1041
1042 if (stat >= SCAN_STATUS_PARTIAL) {
1044 struct srv_list *srvrs;
1045
1046 type = server_scan_get_type(scan);
1047 srvrs = server_scan_get_list(scan);
1048 fc_allocate_mutex(&srvrs->mutex);
1051 holding_srv_list_mutex = false;
1052 fc_release_mutex(&srvrs->mutex);
1053 }
1054
1055 if (stat == SCAN_STATUS_ERROR || stat == SCAN_STATUS_DONE) {
1056 return false;
1057 }
1058
1059 return true;
1060}
1061
1062/**********************************************************************/
1066{
1067 if (lan_scan_timer == NULL) {
1068 return;
1069 }
1071}
1072
1073/**********************************************************************/
1077{
1078 if (meta_scan_timer == NULL) {
1079 return;
1080 }
1082}
1083
1084/**********************************************************************/
1088{
1089 if (!is_server_running()) {
1091
1092 /* Saved settings are sent in client/options.c
1093 * resend_desired_settable_options() */
1094 }
1095}
1096
1097/**********************************************************************/
1101{
1102 if (!is_server_running()) {
1104 send_chat("/detach");
1105 }
1106 if (is_server_running() && !current_file.isEmpty()) {
1107 QByteArray c_bytes;
1108
1109 c_bytes = current_file.toUtf8();
1110 send_chat_printf("/load %s", c_bytes.data());
1111 switch_page(PAGE_GAME + 1);
1112 }
1113}
1114
1115/**********************************************************************/
1119{
1120 if (!is_server_running()) {
1122 send_chat("/detach");
1123 }
1124 if (is_server_running() && !current_file.isEmpty()) {
1125 QByteArray c_bytes;
1126
1127 c_bytes = current_file.toUtf8();
1128 send_chat_printf("/load %s", c_bytes.data());
1129 switch_page(PAGE_GAME + 1);
1130 }
1131}
1132
1133/**********************************************************************/
1136void fc_client::slot_selection_changed(const QItemSelection &selected,
1137 const QItemSelection &deselected)
1138{
1139 QModelIndexList indexes = selected.indexes();
1140 QStringList sl;
1141 QModelIndex index;
1142 QTableWidgetItem *item;
1143 QItemSelectionModel *tw;
1144 QVariant qvar;
1145 QString str_pixmap;
1146
1147 client_pages cpage = current_page();
1148 const char *terr_name;
1149 const struct server *pserver = NULL;
1150 int ii = 0;
1151 int k, col, n, nat_y, nat_x;
1152 struct section_file *sf;
1153 struct srv_list *srvrs;
1154 QByteArray fn_bytes;
1155
1156 if (indexes.isEmpty()) {
1157 return;
1158 }
1159
1160 switch (cpage) {
1161 case PAGE_NETWORK:
1162 index = indexes.at(0);
1163 connect_host_edit->setText(index.data().toString());
1164 index = indexes.at(1);
1165 connect_port_edit->setText(index.data().toString());
1166
1167 tw = qobject_cast<QItemSelectionModel *>(sender());
1168
1169 if (tw == lan_widget->selectionModel()) {
1170 wan_widget->clearSelection();
1171 } else {
1172 lan_widget->clearSelection();
1173 }
1174
1177 fc_allocate_mutex(&srvrs->mutex);
1178 }
1179 if (srvrs->servers) {
1180 pserver = server_list_get(srvrs->servers, index.row());
1181 }
1183 fc_release_mutex(&srvrs->mutex);
1184 }
1185 if (!pserver || !pserver->players) {
1186 return;
1187 }
1188 n = pserver->nplayers;
1189 info_widget->clearContents();
1190 info_widget->setRowCount(0);
1191 for (k = 0; k < n; k++) {
1192 info_widget->insertRow(k);
1193 for (col = 0; col < 4; col++) {
1194 item = new QTableWidgetItem();
1195 switch (col) {
1196 case 0:
1197 item->setText(pserver->players[k].name);
1198 break;
1199 case 1:
1200 item->setText(pserver->players[k].type);
1201 break;
1202 case 2:
1203 item->setText(pserver->players[k].host);
1204 break;
1205 case 3:
1206 item->setText(pserver->players[k].nation);
1207 break;
1208 default:
1209 break;
1210 }
1211 info_widget->setItem(k, col, item);
1212 }
1213 }
1214 break;
1215 case PAGE_SCENARIO:
1216 index = indexes.at(0);
1217 qvar = index.data(Qt::UserRole);
1218 sl = qvar.toStringList();
1219 scenarios_text->setText(sl.at(0));
1220 if (sl.count() > 1) {
1221 scenarios_view->setText(sl.at(2));
1222 current_file = sl.at(1);
1223 }
1224 break;
1225 case PAGE_LOAD:
1226 index = indexes.at(0);
1227 qvar = index.data(Qt::UserRole);
1228 current_file = qvar.toString();
1229 if (show_preview->checkState() == Qt::Unchecked) {
1230 load_pix->setPixmap(*(new QPixmap));
1231 load_save_text->setText("");
1232 break;
1233 }
1234 fn_bytes = current_file.toUtf8();
1235 if ((sf = secfile_load_section(fn_bytes.data(),
1236 "game", TRUE))) {
1237 const char *sname;
1238 int integer;
1239 QString final_str;
1240 QString pl_str = nullptr;
1241 int num_players = 0;
1242 int curr_player = 0;
1243 QByteArray pl_bytes;
1244
1245 integer = secfile_lookup_int_default(sf, -1, "game.turn");
1246 if (integer >= 0) {
1247 final_str = QString("<b>") + _("Turn") + ":</b> "
1248 + QString::number(integer).toHtmlEscaped() + "<br>";
1249 }
1250 if ((sf = secfile_load_section(fn_bytes.data(),
1251 "players", TRUE))) {
1252 integer = secfile_lookup_int_default(sf, -1, "players.nplayers");
1253 if (integer >= 0) {
1254 final_str = final_str + "<b>" + _("Players") + ":</b>" + " "
1255 + QString::number(integer).toHtmlEscaped() + "<br>";
1256 }
1257 num_players = integer;
1258 }
1259 for (int i = 0; i < num_players; i++) {
1260 pl_str = QString("player") + QString::number(i);
1261 pl_bytes = pl_str.toUtf8();
1262 if ((sf = secfile_load_section(fn_bytes.data(),
1263 pl_bytes.data(), true))) {
1264 if (!secfile_lookup_bool_default(sf, true,
1265 "player%d.unassigned_user",
1266 i)) {
1267 curr_player = i;
1268 break;
1269 }
1270 }
1271 }
1272 /* Break case (and return) if no human player found */
1273 if (pl_str == nullptr) {
1274 load_save_text->setText(final_str);
1275 break;
1276 }
1277
1278 /* Information about human player */
1279 pl_bytes = pl_str.toUtf8();
1280 if ((sf = secfile_load_section(fn_bytes.data(),
1281 pl_bytes.data(), true))) {
1282 sname = secfile_lookup_str_default(sf, nullptr, "player%d.nation",
1283 curr_player);
1284 if (sname) {
1285 final_str = final_str + "<b>" + _("Nation") + ":</b> "
1286 + QString(sname).toHtmlEscaped() + "<br>";
1287 }
1288 integer = secfile_lookup_int_default(sf, -1, "player%d.ncities",
1289 curr_player);
1290 if (integer >= 0) {
1291 final_str = final_str + "<b>" + _("Cities") + ":</b> "
1292 + QString::number(integer).toHtmlEscaped() + "<br>";
1293 }
1294 integer = secfile_lookup_int_default(sf, -1, "player%d.nunits",
1295 curr_player);
1296 if (integer >= 0) {
1297 final_str = final_str + "<b>" + _("Units") + ":</b> "
1298 + QString::number(integer).toHtmlEscaped() + "<br>";
1299 }
1300 integer = secfile_lookup_int_default(sf, -1, "player%d.gold",
1301 curr_player);
1302 if (integer >= 0) {
1303 final_str = final_str + "<b>" + _("Gold") + ":</b> "
1304 + QString::number(integer).toHtmlEscaped() + "<br>";
1305 }
1306 nat_x = 0;
1307 nat_y = 0;
1308 while (true) { // Until breaks out
1309 const char *line = secfile_lookup_str_default(sf, nullptr,
1310 "player%d.map_t%04d",
1311 curr_player, nat_y++);
1312 if (line == nullptr) {
1313 break;
1314 }
1315 nat_x = strlen(line);
1316 str_pixmap = str_pixmap + line;
1317 }
1318
1319 /* Reset terrain information */
1320 terrain_type_iterate(pterr) {
1321 pterr->identifier_load = '\0';
1323
1324 /* Load possible terrains and their identifiers (chars) */
1325 if ((sf = secfile_load_section(fn_bytes.data(),
1326 "savefile", true)))
1327 while ((terr_name = secfile_lookup_str_default(sf, NULL,
1328 "savefile.terrident%d.name", ii)) != NULL) {
1329 struct terrain *pterr = terrain_by_rule_name(terr_name);
1330 if (pterr != NULL) {
1331 const char *iptr = secfile_lookup_str_default(sf, NULL,
1332 "savefile.terrident%d.identifier", ii);
1333 pterr->identifier_load = *iptr;
1334 }
1335 ii++;
1336 }
1337
1338 /* Create image */
1339 QImage img(nat_x, nat_y, QImage::Format_ARGB32_Premultiplied);
1340
1341 img.fill(Qt::black);
1342 for (int a = 0 ; a < nat_x; a++) {
1343 for (int b = 0; b < nat_y; b++) {
1344 struct terrain *tr;
1345 struct rgbcolor *rgb;
1346
1347 tr = char2terrain(str_pixmap.at(b * nat_x + a).toLatin1());
1348 if (tr != nullptr) {
1349 rgb = tr->rgb;
1350 QColor color;
1351
1352 color.setRgb(rgb->r, rgb->g, rgb->b);
1353 img.setPixel(a, b, color.rgb());
1354 }
1355 }
1356 }
1357 if (img.width() > 1) {
1358 load_pix->setPixmap(QPixmap::fromImage(img).scaledToHeight(200));
1359 } else {
1360 load_pix->setPixmap(*(new QPixmap));
1361 }
1362
1363#ifndef FC_QT5_MODE
1364 // This is Qt6 implementation
1365 // Qt-5.15 could use load_pix->pixmap(Qt::ReturnByValue)
1366 QPixmap pm = load_pix->pixmap();
1367
1368 load_pix->setFixedSize(pm.width(),
1369 pm.height());
1370#else /* FC_QT5_MODE */
1371 load_pix->setFixedSize(load_pix->pixmap()->width(),
1372 load_pix->pixmap()->height());
1373#endif /* FC_QT5_MODE */
1374
1375 if ((sf = secfile_load_section(fn_bytes.data(),
1376 "research", TRUE))) {
1377 sname = secfile_lookup_str_default(sf, nullptr,
1378 "research.r%d.now_name",
1379 curr_player);
1380 if (sname) {
1381 final_str = final_str + "<b>" + _("Researching") + ":</b> "
1382 + QString(sname).toHtmlEscaped();
1383 }
1384 }
1385 }
1386 load_save_text->setText(final_str);
1387 }
1388 break;
1389 default:
1390 break;
1391 }
1392
1393}
1394
1395/**********************************************************************/
1399{
1400 struct fileinfo_list *files;
1401 int row;
1402
1403 row = 0;
1404 files = fileinfolist_infix(get_save_dirs(), ".sav", FALSE);
1405 saves_load->clearContents();
1406 saves_load->setRowCount(0);
1408 fileinfo_list_iterate(files, pfile) {
1409 QTableWidgetItem *item;
1410 QDateTime dt;
1411
1412 item = new QTableWidgetItem();
1413 item->setData(Qt::UserRole, QString(pfile->fullname));
1414 saves_load->insertRow(row);
1415 item->setText(pfile->name);
1416 saves_load->setItem(row, 0, item);
1417 item = new QTableWidgetItem();
1418 dt = QDateTime::fromSecsSinceEpoch(pfile->mtime);
1419 item->setText(dt.toString(Qt::TextDate));
1420 saves_load->setItem(row, 1, item);
1421 row++;
1423 fileinfo_list_destroy(files);
1424}
1425
1426/**********************************************************************/
1430{
1431 struct fileinfo_list *files;
1432 int row = 0;
1433
1434 scenarios_load->clearContents();
1435 scenarios_load->setRowCount(0);
1436 scenarios_text->setText("");
1437 scenarios_view->setText("");
1438
1439 files = fileinfolist_infix(get_scenario_dirs(), ".sav", false);
1440 fileinfo_list_iterate(files, pfile) {
1441 struct section_file *sf;
1442
1443 if ((sf = secfile_load_section(pfile->fullname, "scenario", TRUE))
1444 && secfile_lookup_bool_default(sf, TRUE, "scenario.is_scenario")) {
1445
1446 const char *sname, *sdescription, *sauthors;
1447 QTableWidgetItem *item;
1448 QString format;
1449 QString st;
1450 int fcver;
1451 int fcdev;
1452 int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
1453 int current_dev = current_ver;
1454
1455 if (PATCH_VERSION >= 90) {
1456 // Patch level matters on development versions
1457 current_dev += PATCH_VERSION * 100;
1458 }
1459
1460 fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
1461 if (fcver < 30000) {
1462 /* Pre-3.0 versions stored version number without emergency version
1463 * part in the end. To get comparable version number stored,
1464 * multiply by 100. */
1465 fcver *= 100;
1466 }
1467 if (fcver % 10000 >= 9000) {
1468 fcdev = fcver - (fcver % 100); // Emergency version does not count.
1469 } else {
1470 fcdev = fcver - (fcver % 10000); // Patch version does not count.
1471 }
1472 sname = secfile_lookup_str_default(sf, NULL, "scenario.name");
1473 sdescription = secfile_lookup_str_default(sf, NULL,
1474 "scenario.description");
1475 sauthors = secfile_lookup_str_default(sf, NULL,
1476 "scenario.authors");
1477 // Ignore scenarios for newer freeciv versions than we are.
1478 if (fcdev <= current_dev) {
1479 QString version;
1480 bool add_item = true;
1481 bool found = false;
1482 QStringList sl;
1483 int rows;
1484 int found_ver;
1485 int i;
1486
1487 if (fcver > 0) {
1488 int maj;
1489 int min;
1490
1491 maj = fcver / 1000000;
1492 fcver %= 1000000;
1493 min = fcver / 10000;
1494 fcver %= 10000;
1495 if (fcver >= 9000) {
1496 // Development version, have '+'
1497 version = QString("%1.%2+").arg(maj).arg(min);
1498 } else {
1499 version = QString("%1.%2").arg(maj).arg(min);
1500 }
1501 } else {
1502 /* TRANS: Unknown scenario format */
1503 version = QString(_("pre-2.6"));
1504 }
1505
1506 rows = scenarios_load->rowCount();
1507 for (i = 0; i < rows; ++i) {
1508 if (scenarios_load->item(i, 0)
1509 && scenarios_load->item(i, 0)->text() == pfile->name) {
1510 found = true;
1511 item = scenarios_load->takeItem(i, 0);
1512 break;
1513 }
1514 }
1515
1516 if (found) {
1517 sl = item->data(Qt::UserRole).toStringList();
1518 found_ver = sl.at(3).toInt();
1519 if (found_ver < fcver) {
1520 continue;
1521 }
1522 add_item = false;
1523 }
1524 if (add_item) {
1525 item = new QTableWidgetItem();
1526 scenarios_load->insertRow(row);
1527 }
1528 item->setText(QString(pfile->name));
1529 format = QString("<br>") + QString(_("Format:")) + " "
1530 + version.toHtmlEscaped();
1531 if (sauthors) {
1532 st = QString("\n") + QString("<b>") + _("Authors: ")
1533 + QString("</b>") + QString(sauthors).toHtmlEscaped();
1534 } else {
1535 st = "";
1536 }
1537 sl << "<b>"
1538 + QString(sname && strlen(sname) ? Q_(sname) : pfile->name)
1539 .toHtmlEscaped()
1540 + "</b>"
1541 << QString(pfile->fullname).toHtmlEscaped()
1542 << QString(NULL != sdescription && '\0' != sdescription[0]
1543 ? Q_(sdescription) : "").toHtmlEscaped() + st + format
1544 << QString::number(fcver).toHtmlEscaped();
1545 sl.replaceInStrings("\n", "<br>");
1546 item->setData(Qt::UserRole, sl);
1547 if (add_item) {
1548 scenarios_load->setItem(row, 0, item);
1549 row++;
1550 } else {
1551 scenarios_load->setItem(i, 0, item);
1552 }
1553 }
1554 secfile_destroy(sf);
1555 }
1557 fileinfo_list_destroy(files);
1558 scenarios_load->sortItems(0);
1559 scenarios_load->update();
1560}
1561
1562
1563/**********************************************************************/
1568 const char *message)
1569{
1570 set_status_bar(QString::fromUtf8(message));
1572
1573 switch (type) {
1574 case AUTH_NEWUSER_FIRST:
1575 case AUTH_NEWUSER_RETRY:
1577 return;
1578 case AUTH_LOGIN_FIRST:
1579 /* if we magically have a password already present in 'fc_password'
1580 * then, use that and skip the password entry dialog */
1581 if (fc_password[0] != '\0') {
1582 struct packet_authentication_reply reply;
1583
1586 return;
1587 } else {
1589 }
1590
1591 return;
1592 case AUTH_LOGIN_RETRY:
1594 return;
1595 }
1596
1597 log_error("Unsupported authentication type %d: %s.", type, message);
1598}
1599
1600/**********************************************************************/
1606{
1607 char errbuf [512];
1608 struct packet_authentication_reply reply;
1609 QByteArray ba_bytes;
1610
1611 switch (connection_status) {
1612 case LOGIN_TYPE:
1613 ba_bytes = connect_login_edit->text().toUtf8();
1614 sz_strlcpy(user_name, ba_bytes.data());
1615 ba_bytes = connect_host_edit->text().toUtf8();
1616 sz_strlcpy(server_host, ba_bytes.data());
1617 server_port = connect_port_edit->text().toInt();
1618
1620 errbuf, sizeof(errbuf)) != -1) {
1621 } else {
1622 set_status_bar(QString::fromUtf8(errbuf));
1624 }
1625
1626 return;
1627 case NEW_PASSWORD_TYPE:
1628 ba_bytes = connect_password_edit->text().toLatin1();
1629 sz_strlcpy(fc_password, ba_bytes.data());
1630 ba_bytes = connect_confirm_password_edit->text().toLatin1();
1631 sz_strlcpy(reply.password,
1632 ba_bytes.data());
1633
1634 if (strncmp(reply.password, fc_password, MAX_LEN_NAME) == 0) {
1635 fc_password[0] = '\0';
1638 } else {
1639 set_status_bar(_("Passwords don't match, enter password."));
1641 }
1642
1643 return;
1645 ba_bytes = connect_password_edit->text().toLatin1();
1646 sz_strlcpy(reply.password,
1647 ba_bytes.data());
1650 return;
1651 case WAITING_TYPE:
1652 return;
1653 }
1654
1655 log_error("Unsupported connection status: %d", connection_status);
1656}
1657
1658/**********************************************************************/
1663{
1664 int conn_num, i;
1665 QVariant qvar, qvar2;
1666 bool is_ready;
1667 QString host, nation, leader, team, str;
1668 QPixmap *pixmap;
1669 QPainter p;
1670 struct sprite *psprite;
1671 QTreeWidgetItem *item;
1672 QTreeWidgetItem *item_r;
1673 QList <QTreeWidgetItem*> items;
1674 QList <QTreeWidgetItem*> recursed_items;
1675 QTreeWidgetItem *player_item;
1676 QTreeWidgetItem *global_item;
1677 QTreeWidgetItem *detach_item;
1678 int conn_id;
1679 conn_num = conn_list_size(game.est_connections);
1680
1681 if (conn_num == 0) {
1682 return;
1683 }
1684
1685 start_players_tree->clear();
1686 qvar2 = 0;
1687
1688 player_item = new QTreeWidgetItem();
1689 player_item->setText(0, Q_("?header:Players"));
1690 player_item->setData(0, Qt::UserRole, qvar2);
1691
1692 i = 0;
1693 players_iterate(pplayer) {
1694 i++;
1696 gui()->pr_options->set_aifill(i);
1701 players_iterate(pplayer) {
1702 host = "";
1703 if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
1704 conn_id = -1;
1705 conn_list_iterate(pplayer->connections, pconn) {
1706 if (pconn->playing == pplayer && !pconn->observer) {
1707 conn_id = pconn->id;
1708 host = pconn->addr;
1709 break;
1710 }
1712 if (is_barbarian(pplayer)) {
1713 continue;
1714 }
1715 if (is_ai(pplayer)) {
1716 is_ready = true;
1717 } else {
1718 is_ready = pplayer->is_ready;
1719 }
1720
1721 if (pplayer->nation == NO_NATION_SELECTED) {
1722 nation = _("Random");
1723
1724 if (pplayer->was_created) {
1725 leader = player_name(pplayer);
1726 } else {
1727 leader = "";
1728 }
1729 } else {
1730 nation = nation_adjective_for_player(pplayer);
1731 leader = player_name(pplayer);
1732 }
1733
1734 if (pplayer->team) {
1735 team = team_name_translation(pplayer->team);
1736 } else {
1737 team = "";
1738 }
1739
1740 item = new QTreeWidgetItem();
1741 for (int col = 0; col < 8; col++) {
1742 switch (col) {
1743 case 0:
1744 str = pplayer->username;
1745
1746 if (is_ai(pplayer)) {
1747 str = str + " <" + (ai_level_translated_name(pplayer->ai_common.skill_level))
1748 + ">";
1749 item->setIcon(col, fc_icons::instance()->get_icon("ai"));
1750 } else {
1751 item->setIcon(col, fc_icons::instance()->get_icon("human"));
1752 }
1753
1754 item->setText(col, str);
1755 qvar = QVariant::fromValue((void *) pplayer);
1756 qvar2 = 1;
1757 item->setData(0, Qt::UserRole, qvar2);
1758 item->setData(1, Qt::UserRole, qvar);
1759 break;
1760 case 1:
1761 if (is_ready) {
1762 item->setText(col, _("Yes"));
1763 } else {
1764 item->setText(col, _("No"));
1765 }
1766 break;
1767 case 2:
1768 item->setText(col, leader);
1769 break;
1770 case 3:
1771 if (!pplayer->nation) {
1772 break;
1773 }
1774 psprite = get_nation_flag_sprite(tileset, pplayer->nation);
1775 pixmap = psprite->pm;
1776 item->setData(col, Qt::DecorationRole, *pixmap);
1777 break;
1778 case 4:
1779 if (!player_has_color(pplayer)) {
1780 break;
1781 }
1782 pixmap = new QPixmap(
1783 start_players_tree->header()->sectionSizeHint(col), 16);
1784 pixmap->fill(Qt::transparent);
1785 p.begin(pixmap);
1786 p.fillRect(pixmap->width() / 2 - 8, 0, 16, 16, Qt::black);
1787 p.fillRect(pixmap->width() / 2 - 7, 1, 14, 14,
1788 get_player_color(tileset, pplayer)->qcolor);
1789 p.end();
1790 item->setData(col, Qt::DecorationRole, *pixmap);
1791 delete pixmap;
1792 break;
1793 case 5:
1794 item->setText(col, nation);
1795 break;
1796 case 6:
1797 item->setText(col, team);
1798 break;
1799 case 7:
1800 item->setText(col, host);
1801 break;
1802 default:
1803 break;
1804 }
1805 }
1806
1810 recursed_items.clear();
1811 conn_list_iterate(pplayer->connections, pconn) {
1812 if (pconn->id == conn_id) {
1813 continue;
1814 }
1815 item_r = new QTreeWidgetItem();
1816 item_r->setText(0, pconn->username);
1817 item_r->setText(5, _("Observer"));
1818 item_r->setText(7, pconn->addr);
1819 recursed_items.append(item_r);
1820 item->addChildren(recursed_items);
1822 items.append(item);
1823 }
1825
1826 player_item->addChildren(items);
1827 start_players_tree->insertTopLevelItem(0, player_item);
1828
1832 items.clear();
1833 global_item = new QTreeWidgetItem();
1834 global_item->setText(0, _("Global observers"));
1835 qvar2 = 0;
1836 global_item->setData(0, Qt::UserRole, qvar2);
1837
1839 if (NULL != pconn->playing || !pconn->observer) {
1840 continue;
1841 }
1842 item = new QTreeWidgetItem();
1843 for (int col = 0; col < 8; col++) {
1844 switch (col) {
1845 case 0:
1846 item->setText(col, pconn->username);
1847 break;
1848 case 5:
1849 item->setText(col, _("Observer"));
1850 break;
1851 case 7:
1852 item->setText(col, pconn->addr);
1853 break;
1854 default:
1855 break;
1856 }
1857 items.append(item);
1858 }
1860
1861 global_item->addChildren(items);
1862 start_players_tree->insertTopLevelItem(1, global_item);
1863 items.clear();
1864
1868 detach_item = new QTreeWidgetItem();
1869 detach_item->setText(0, _("Detached"));
1870 qvar2 = 0;
1871 detach_item->setData(0, Qt::UserRole, qvar2);
1872
1874 if (NULL != pconn->playing || pconn->observer) {
1875 continue;
1876 }
1877 item = new QTreeWidgetItem();
1878 item->setText(0, pconn->username);
1879 item->setText(7, pconn->addr);
1880 items.append(item);
1882
1883 detach_item->addChildren(items);
1884 start_players_tree->insertTopLevelItem(2, detach_item);
1885 start_players_tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
1886 start_players_tree->expandAll();
1888}
1889
1890/**********************************************************************/
1894{
1895 bool sensitive;
1896 QString text;
1897
1898 /* Observe button */
1900 obs_button->setText(_("Don't Observe"));
1901 } else {
1902 obs_button->setText(_("Observe"));
1903 }
1904
1905 /* Ready button */
1906 if (can_client_control()) {
1907 sensitive = client_player()->is_alive;
1908 if (client_player()->is_ready) {
1909 text = _("Not ready");
1910 } else {
1911 int num_unready = 0;
1912
1913 players_iterate_alive(pplayer) {
1914 if (is_human(pplayer) && !pplayer->is_ready) {
1915 num_unready++;
1916 }
1918
1919 if (num_unready > 1) {
1920 text = _("Ready");
1921 } else {
1922 /* We are the last unready player so clicking here will
1923 * immediately start the game. */
1924 text = _("Start");
1925 }
1926 }
1927 } else {
1928 text = _("Start");
1930 sensitive = true;
1932 if (is_human(plr)) {
1933 /* There's human controlled player(s) in game, so it's their
1934 * job to start the game. */
1935 sensitive = false;
1936 break;
1937 }
1939 } else {
1940 sensitive = false;
1941 }
1942 }
1943 start_button->setEnabled(sensitive);
1944 start_button->setText(text);
1945
1946 /* Nation button */
1947 sensitive = game.info.is_new_game && can_client_control();
1948 nation_button->setEnabled(sensitive);
1949
1950 sensitive = game.info.is_new_game;
1951 pr_options->setEnabled(sensitive);
1952
1955}
1956
1957/**********************************************************************/
1961{
1962 QAction *action;
1963 QPoint global_pos = start_players_tree->mapToGlobal(pos);
1964 QString me, splayer, str, sp;
1965 bool need_empty_team;
1966 const char *level_cmd, *level_name;
1967 int level, count;
1968 QVariant qvar, qvar2;
1969
1970 me = client.conn.username;
1971 QTreeWidgetItem *item = start_players_tree->itemAt(pos);
1972
1973 if (item == nullptr) {
1974 return;
1975 }
1976
1977 qvar = item->data(0, Qt::UserRole);
1978 qvar2 = item->data(1, Qt::UserRole);
1979
1985 if (qvar == 1) {
1986 player *pplayer = (player *) qvar2.value < void *>();
1987
1988 if (pplayer != nullptr) {
1989 QMenu *page_menu = new QMenu(this);
1990
1991 page_submenu_AI = new QMenu(this);
1992 page_submenu_team = new QMenu(this);
1993
1994 splayer = QString(pplayer->name);
1995 sp = "\"" + splayer + "\"";
1996 if (me != splayer) {
1997 str = QString(_("Observe"));
1998 action = new QAction(str, start_players_tree);
1999 str = "/observe " + sp;
2000 QObject::connect(action, &QAction::triggered, [this,str]() {
2002 });
2003 page_menu->addAction(action);
2004
2005 if (ALLOW_CTRL <= client.conn.access_level) {
2006 str = QString(_("Remove player"));
2007 action = new QAction(str, start_players_tree);
2008 str = "/remove " + sp;
2009 QObject::connect(action, &QAction::triggered, [this,str]() {
2011 });
2012 page_menu->addAction(action);
2013 }
2014 str = QString(_("Take this player"));
2015 action = new QAction(str, start_players_tree);
2016 str = "/take " + sp;
2017 QObject::connect(action, &QAction::triggered, [this,str]() {
2019 });
2020 page_menu->addAction(action);
2021 }
2022
2023 if (can_conn_edit_players_nation(&client.conn, pplayer)) {
2024 str = QString(_("Pick nation"));
2025 action = new QAction(str, start_players_tree);
2026 str = "PICK:" + QString(player_name(pplayer)); /* PICK is a key */
2027 QObject::connect(action, &QAction::triggered, [this,str]() {
2029 });
2030 page_menu->addAction(action);
2031 }
2032
2033 if (is_ai(pplayer)) {
2037 if (ALLOW_CTRL <= client.conn.access_level) {
2038 page_submenu_AI->setTitle(_("Set difficulty"));
2039 page_menu->addMenu(page_submenu_AI);
2040
2041 for (level = 0; level < AI_LEVEL_COUNT; level++) {
2042 if (is_settable_ai_level(static_cast < ai_level > (level))) {
2043 level_name = ai_level_translated_name(static_cast < ai_level > (level));
2044 level_cmd = ai_level_cmd(static_cast < ai_level > (level));
2045 action = new QAction(QString(level_name), start_players_tree);
2046 str = "/" + QString(level_cmd) + " " + sp;
2047 QObject::connect(action, &QAction::triggered, [this,str]() {
2049 });
2050 page_submenu_AI->addAction(action);
2051 }
2052 }
2053 }
2054 }
2055
2059 if (game.info.is_new_game) {
2060 page_menu->addMenu(page_submenu_team);
2061 page_submenu_team->setTitle(_("Put on team"));
2062 page_menu->addMenu(page_submenu_team);
2063 count = pplayer->team ?
2064 player_list_size(team_members(pplayer->team)) : 0;
2065 need_empty_team = (count != 1);
2066 team_slots_iterate(tslot) {
2067 if (!team_slot_is_used(tslot)) {
2068 if (!need_empty_team) {
2069 continue;
2070 }
2071 need_empty_team = false;
2072 }
2074 action = new QAction(str, start_players_tree);
2075 str = "/team" + sp + " \"" + QString(team_slot_rule_name(tslot))
2076 + "\"";
2077 QObject::connect(action, &QAction::triggered, [this,str]() {
2079 });
2080 page_submenu_team->addAction(action);
2082 }
2083
2084 if (ALLOW_CTRL <= client.conn.access_level) {
2085 str = QString(_("Aitoggle player"));
2086 action = new QAction(str, start_players_tree);
2087 str = "/aitoggle " + sp;
2088 QObject::connect(action, &QAction::triggered, [this,str]() {
2090 });
2091 page_menu->addAction(action);
2092 }
2093
2094 page_menu->popup(global_pos);
2095 }
2096 }
2097}
2098
2099/**********************************************************************/
2106
2107/**********************************************************************/
2111{
2112 sw_map->set_pixmap(fc_icons::instance()->get_pixmap("view"));
2113 sw_cunit->set_pixmap(fc_icons::instance()->get_pixmap("units"));
2114 sw_cities->set_pixmap(fc_icons::instance()->get_pixmap("cities"));
2115 sw_diplo->set_pixmap(fc_icons::instance()->get_pixmap("nations"));
2116 sw_science->set_pixmap(fc_icons::instance()->get_pixmap("research"));
2117 sw_economy->set_pixmap(fc_icons::instance()->get_pixmap("economy"));
2118 sw_endturn->set_pixmap(fc_icons::instance()->get_pixmap("endturn"));
2119 sidebar_wdg->resize_me(game_tab_widget->height(), true);
2120}
2121
2122/**********************************************************************/
2126{
2127 QString str;
2128 int max;
2129 int entries_used, building_total, unit_total, tax;
2130 char buf[256];
2131
2132 struct improvement_entry building_entries[B_LAST];
2133 struct unit_entry unit_entries[U_LAST];
2134
2135 if (current_page() != PAGE_GAME) {
2136 return;
2137 }
2138
2139 if (NULL != client.conn.playing) {
2140 max = get_player_bonus(client.conn.playing, EFT_MAX_RATES);
2141 } else {
2142 max = 100;
2143 }
2144
2148 str = str + '\n' + get_info_label_text(false);
2150 str = QString(_("Tax: %1% Science: %2% Luxury: %3%\n"))
2154
2155 str += QString(_("%1 - max rate: %2%")).
2157 QString::number(max));
2158
2159 get_economy_report_units_data(unit_entries, &entries_used, &unit_total);
2160 get_economy_report_data(building_entries, &entries_used,
2161 &building_total, &tax);
2162 fc_snprintf(buf, sizeof(buf), _("Income: %d Total Costs: %d"),
2163 tax, building_total + unit_total);
2164 sw_economy->set_tooltip(buf);
2168 }
2169 } else {
2170 sw_tax->set_tooltip("");
2172 sw_map->set_tooltip("");
2174 }
2176}
2177
2178/**********************************************************************/
2182{
2183 bool center_next = false;
2184 bool first_tile = false;
2185 int first_id;
2186 struct tile *ptile = nullptr;
2187
2188 players_iterate(pplayer) {
2189 if (pplayer != client_player()) {
2190 city_list_iterate(pplayer->cities, pcity) {
2191 if (!first_tile) {
2192 first_tile = true;
2193 ptile = pcity->tile;
2194 first_id = pcity->id;
2195 }
2196 if ((last_center_enemy_city == 0) || center_next) {
2197 last_center_enemy_city = pcity->id;
2198 center_tile_mapcanvas(pcity->tile);
2199 return;
2200 }
2201 if (pcity->id == last_center_enemy_city) {
2202 center_next = true;
2203 }
2205 }
2207
2208 if (ptile != nullptr) {
2209 center_tile_mapcanvas(ptile);
2210 last_center_enemy_city = first_id;
2211 }
2212}
2213
2214/**********************************************************************/
2218{
2219 bool center_next = false;
2220 bool first_tile = false;
2221 int first_id;
2222 struct tile *ptile = nullptr;
2223
2224 players_iterate(pplayer) {
2225 if (pplayer == client_player()) {
2226 city_list_iterate(pplayer->cities, pcity) {
2227 if (!first_tile) {
2228 first_tile = true;
2229 ptile = pcity->tile;
2230 first_id = pcity->id;
2231 }
2232 if ((last_center_player_city == 0) || center_next) {
2233 last_center_player_city = pcity->id;
2234 center_tile_mapcanvas(pcity->tile);
2235 return;
2236 }
2237 if (pcity->id == last_center_player_city) {
2238 center_next = true;
2239 }
2241 }
2243
2244 if (ptile != nullptr) {
2245 center_tile_mapcanvas(ptile);
2246 last_center_player_city = first_id;
2247 }
2248}
2249
2250/**********************************************************************/
2254{
2255 struct city *capital;
2256 bool center_next = false;
2257 bool first_tile = false;
2258 int first_id;
2259 struct tile *ptile = nullptr;
2260
2261 players_iterate(pplayer) {
2262 if (pplayer != client_player()) {
2263 capital = player_primary_capital(pplayer);
2264 if (capital == nullptr) {
2265 continue;
2266 }
2267 if (!first_tile) {
2268 first_tile = true;
2269 ptile = capital->tile;
2270 first_id = capital->id;
2271 }
2272 if ((last_center_player_city == 0) || center_next) {
2273 last_center_player_city = capital->id;
2274 center_tile_mapcanvas(capital->tile);
2275 put_cross_overlay_tile(capital->tile);
2276 return;
2277 }
2278 if (capital->id == last_center_player_city) {
2279 center_next = true;
2280 }
2281 }
2283
2284 if (ptile != nullptr) {
2285 center_tile_mapcanvas(ptile);
2287 last_center_player_city = first_id;
2288 }
2289
2290}
2291
2292/**********************************************************************/
2296{
2297 pages_layout[PAGE_GAME]->removeWidget(gui()->sidebar_wdg);
2299 pages_layout[PAGE_GAME]->addWidget(sidebar_wdg, 1, 0);
2300 } else {
2301 pages_layout[PAGE_GAME]->addWidget(sidebar_wdg, 1, 2);
2302 }
2303}
2304
2305/**********************************************************************/
2309{
2310 bool center_next = false;
2311 bool first_tile = false;
2312 int first_id;
2313 struct tile *ptile = nullptr;
2314
2315 players_iterate(pplayer) {
2316 if (pplayer != client_player()) {
2317 unit_list_iterate(pplayer->units, punit) {
2318 if (!first_tile) {
2319 first_tile = true;
2320 ptile = punit->tile;
2321 first_id = punit->id;
2322 }
2323 if ((last_center_enemy == 0) || center_next) {
2326 return;
2327 }
2328 if (punit->id == last_center_enemy) {
2329 center_next = true;
2330 }
2332 }
2334
2335 if (ptile != nullptr) {
2336 center_tile_mapcanvas(ptile);
2337 last_center_enemy = first_id;
2338 }
2339}
int entries_used
Definition agents.c:74
#define str
Definition astring.c:76
#define n
Definition astring.c:77
struct canvas int int struct sprite * psprite
Definition canvas_g.h:50
void qtg_version_message(const char *vertext)
Definition chatline.cpp:808
int send_chat_printf(const char *format,...)
int send_chat(const char *message)
void output_window_append(const struct ft_color color, const char *featured_text)
#define city_list_iterate(citylist, pcity)
Definition city.h:488
#define city_list_iterate_end
Definition city.h:490
fc_game_tab_widget * game_tab_widget
Definition fc_client.h:259
QStringList status_bar_queue
Definition fc_client.h:351
void handle_authentication_req(enum authentication_type type, const char *message)
Definition pages.cpp:1567
QLineEdit * connect_host_edit
Definition fc_client.h:188
fc_sidewidget * sw_tax
Definition fc_client.h:222
void update_buttons()
Definition pages.cpp:1893
QTextEdit * output_window
Definition fc_client.h:181
void update_sidebar_tooltips()
Definition pages.cpp:2125
goto_dialog * gtd
Definition fc_client.h:265
fc_sidewidget * sw_economy
Definition fc_client.h:223
QTimer * meta_scan_timer
Definition fc_client.h:212
hud_battle_log * battlelog_wdg
Definition fc_client.h:272
QPushButton * start_button
Definition fc_client.h:196
void start_from_save()
Definition pages.cpp:1118
QWidget * connect_lan
Definition fc_client.h:174
int add_game_tab(QWidget *widget)
Definition pages.cpp:797
fc_sidewidget * sw_science
Definition fc_client.h:275
QTableWidget * lan_widget
Definition fc_client.h:205
void browse_saves()
Definition pages.cpp:817
QWidget * connect_metaserver
Definition fc_client.h:175
QWidget * game_main_widget
Definition fc_client.h:176
QLineEdit * connect_confirm_password_edit
Definition fc_client.h:192
chat_input * chat_line
Definition fc_client.h:203
hud_units * unitinfo_wdg
Definition fc_client.h:271
pregamevote * pre_vote
Definition fc_client.h:262
QPushButton * nation_button
Definition fc_client.h:197
QTableWidget * saves_load
Definition fc_client.h:208
void set_status_bar(QString str, int timeout=2000)
Definition pages.cpp:437
QPushButton * button
Definition fc_client.h:194
QCheckBox * show_preview
Definition fc_client.h:186
fc_sidewidget * sw_cunit
Definition fc_client.h:274
enum client_pages current_page()
bool check_server_scan(server_scan *scan_data)
Definition pages.cpp:1031
QLineEdit * connect_password_edit
Definition fc_client.h:191
void quit()
minimap_view * minimapview_wdg
Definition fc_client.h:232
void reload_sidebar_icons()
Definition pages.cpp:2110
QTableWidget * wan_widget
Definition fc_client.h:206
void slot_pick_nation()
Definition pages.cpp:2102
map_view * mapview_wdg
Definition fc_client.h:230
void slot_selection_changed(const QItemSelection &, const QItemSelection &)
Definition pages.cpp:1136
fc_sidewidget * sw_indicators
Definition fc_client.h:277
QMenu * page_submenu_AI
Definition fc_client.h:281
info_tab * infotab
Definition fc_client.h:261
QLabel * scenarios_text
Definition fc_client.h:183
QLabel * load_save_text
Definition fc_client.h:184
void create_start_page()
Definition pages.cpp:627
void slot_disconnect()
void clear_status_bar()
Definition pages.cpp:453
fc_sidewidget * sw_endturn
Definition fc_client.h:276
void slot_pregame_observe()
void state_preview(int)
Definition pages.cpp:833
QTableWidget * info_widget
Definition fc_client.h:207
void set_connection_state(enum connection_state state)
Definition pages.cpp:252
QPushButton * obs_button
Definition fc_client.h:195
QLabel * load_pix
Definition fc_client.h:185
QLabel * status_bar_label
Definition fc_client.h:217
QGridLayout * pages_layout[PAGE_GAME+2]
Definition fc_client.h:178
QLineEdit * connect_login_edit
Definition fc_client.h:190
QTextEdit * scenarios_view
Definition fc_client.h:182
void destroy_server_scans(void)
Definition pages.cpp:982
void update_sidebar_position()
Definition pages.cpp:2295
QMenu * page_submenu_team
Definition fc_client.h:282
void switch_page(int i)
void create_network_page()
Definition pages.cpp:289
QTreeWidget * start_players_tree
Definition fc_client.h:210
void create_load_page()
Definition pages.cpp:481
QTimer * lan_scan_timer
Definition fc_client.h:213
void update_start_page()
Definition pages.cpp:1662
QLineEdit * connect_port_edit
Definition fc_client.h:189
fc_sidebar * sidebar_wdg
Definition fc_client.h:231
void create_main_page()
Definition pages.cpp:136
void create_loading_page()
Definition pages.cpp:469
void start_page_menu(QPoint)
Definition pages.cpp:1960
void update_server_list(enum server_scan_type sstype, const struct server_list *list)
Definition pages.cpp:868
void update_network_lists()
Definition pages.cpp:1012
QWidget * central_wdg
Definition fc_client.h:256
void slot_meta_scan()
Definition pages.cpp:1076
QString current_file
Definition fc_client.h:352
void slot_lan_scan()
Definition pages.cpp:1065
xvote * x_vote
Definition fc_client.h:264
void browse_scenarios()
Definition pages.cpp:851
void slot_pregame_start()
fc_sidewidget * sw_cities
Definition fc_client.h:221
void popup_client_options()
void slot_connect()
Definition pages.cpp:1605
fc_sidewidget * sw_map
Definition fc_client.h:220
void update_load_page(void)
Definition pages.cpp:1398
void start_scenario()
Definition pages.cpp:1100
pregame_options * pr_options
Definition fc_client.h:267
QTableWidget * scenarios_load
Definition fc_client.h:209
void rm_game_tab(int index)
Definition pages.cpp:809
void send_fake_chat_message(const QString &message)
fc_sidewidget * sw_diplo
Definition fc_client.h:278
void create_scenario_page()
Definition pages.cpp:560
void start_new_game()
Definition pages.cpp:1087
void update_scenarios_page(void)
Definition pages.cpp:1429
void create_game_page()
Definition pages.cpp:711
QIcon get_icon(const QString &id)
static fc_icons * instance()
void resize_me(int height, bool force=false)
Definition sidebar.cpp:570
void add_widget(fc_sidewidget *fsw)
Definition sidebar.cpp:537
void set_wheel_down(pfcn func)
Definition sidebar.cpp:287
void set_wheel_up(pfcn func)
Definition sidebar.cpp:295
void set_pixmap(QPixmap *pm)
Definition sidebar.cpp:120
void set_right_click(pfcn func)
Definition sidebar.cpp:279
void set_tooltip(QString tooltip)
Definition sidebar.cpp:160
void set_aifill(int aifill)
bool can_client_control(void)
bool client_is_global_observer(void)
bool client_is_observer(void)
char user_name[512]
char server_host[512]
struct civclient client
char fc_password[MAX_LEN_PASSWORD]
int server_port
#define client_player()
static struct fc_sockaddr_list * list
Definition clinet.c:102
int connect_to_server(const char *username, const char *hostname, int port, char *errbuf, int errbufsize)
Definition clinet.c:248
struct color * get_player_color(const struct tileset *t, const struct player *pplayer)
bool player_has_color(const struct player *pplayer)
bool is_server_running(void)
bool client_start_server(void)
bool can_client_access_hack(void)
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define conn_list_iterate_end
Definition connection.h:115
void key_unit_wait(void)
Definition control.c:3348
void key_center_capital(void)
Definition control.c:3109
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
connection_state
Definition fc_client.h:55
@ LOGIN_TYPE
Definition fc_client.h:56
@ NEW_PASSWORD_TYPE
Definition fc_client.h:57
@ WAITING_TYPE
Definition fc_client.h:59
@ ENTER_PASSWORD_TYPE
Definition fc_client.h:58
class fc_client * gui()
Definition gui_main.cpp:83
#define MAX_LEN_NAME
Definition fc_types.h:66
#define Q_(String)
Definition fcintl.h:70
#define _(String)
Definition fcintl.h:67
void fc_allocate_mutex(fc_mutex *mutex)
void fc_release_mutex(fc_mutex *mutex)
const struct ft_color ftc_client
struct civ_game game
Definition game.c:57
const char * government_name_for_player(const struct player *pplayer)
Definition government.c:153
void city_report_dialog_popup(bool raise)
Definition cityrep.c:292
void popup_races_dialog(struct player *pplayer)
Definition dialogs.c:1223
static struct tile * pos
Definition finddlg.c:53
void put_cross_overlay_tile(struct tile *ptile)
Definition mapview.c:622
static struct server_scan_timer_data meta_scan
Definition pages.c:86
static enum connection_state connection_status
Definition pages.c:856
static struct server_scan_timer_data lan_scan
Definition pages.c:87
connection_state
Definition pages.c:849
static void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.c:822
static bool holding_srv_list_mutex
Definition pages.c:95
void popup_players_dialog(bool raise)
Definition plrdlg.c:91
void economy_report_dialog_popup(bool raise)
Definition repodlgs.c:1242
GType type
Definition repodlgs.c:1312
static struct server_list * server_list
Definition connectdlg.c:61
#define B_LAST
Definition improvement.h:42
#define log_error(message,...)
Definition log.h:103
#define nat_x
#define nat_y
void center_tile_mapcanvas(const struct tile *ptile)
static mpgui * gui
Definition mpgui_qt.cpp:52
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
bool can_conn_edit_players_nation(const struct connection *pconn, const struct player *pplayer)
Definition nation.c:1186
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:177
#define NO_NATION_SELECTED
Definition nation.h:29
struct client_options gui_options
Definition options.c:71
authentication_type
Definition packets.h:88
@ AUTH_NEWUSER_RETRY
Definition packets.h:92
@ AUTH_NEWUSER_FIRST
Definition packets.h:90
@ AUTH_LOGIN_RETRY
Definition packets.h:91
@ AUTH_LOGIN_FIRST
Definition packets.h:89
int send_packet_authentication_reply(struct connection *pc, const struct packet_authentication_reply *packet)
const char * get_government_tooltip(void)
Definition text.c:1511
const char * text_happiness_cities(const struct city *pcity)
Definition text.c:1931
void qtg_real_set_client_page(enum client_pages page)
Definition pages.cpp:102
int last_center_capital
Definition pages.cpp:66
int last_center_enemy
Definition pages.cpp:79
static void center_next_enemy_city()
Definition pages.cpp:2181
enum client_pages qtg_get_current_client_page()
Definition pages.cpp:120
static void center_next_player_city()
Definition pages.cpp:2217
void popup_shortcuts_dialog()
static enum connection_state connection_status
Definition pages.cpp:76
static struct server_scan * meta_scan
Definition pages.cpp:74
void qtg_set_rulesets(int num_rulesets, char **rulesets)
Definition pages.cpp:112
int last_center_player_city
Definition pages.cpp:67
const char * get_info_label_text_popup(void)
Definition text.c:1002
void toggle_units_report(bool)
static bool holding_srv_list_mutex
Definition pages.cpp:75
const char * science_dialog_text(void)
Definition text.c:774
static void cycle_enemy_units()
Definition pages.cpp:2308
static struct terrain * char2terrain(char ch)
Definition pages.cpp:85
int last_center_enemy_city
Definition pages.cpp:68
const char * get_nuclear_winter_tooltip(void)
Definition text.c:1484
void server_scan_error(struct server_scan *scan, const char *message)
Definition pages.cpp:969
const char * get_bulb_tooltip(void)
Definition text.c:1400
const char * get_info_label_text(bool)
Definition text.c:950
const char * get_global_warming_tooltip(void)
Definition text.c:1457
void update_start_page(void)
Definition pages.cpp:128
static struct server_scan * lan_scan
Definition pages.cpp:74
static void center_next_player_capital()
Definition pages.cpp:2253
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1883
const char * player_name(const struct player *pplayer)
Definition player.c:886
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1954
struct city * player_primary_capital(const struct player *pplayer)
Definition player.c:1313
#define ai_level_cmd(_level_)
Definition player.h:565
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
#define is_ai(plr)
Definition player.h:234
#define players_iterate_alive_end
Definition player.h:545
#define is_human(plr)
Definition player.h:233
#define players_iterate_alive(_pplayer)
Definition player.h:540
void secfile_destroy(struct section_file *secfile)
struct section_file * secfile_load_section(const char *filename, const char *section, bool allow_duplicates)
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
void get_economy_report_units_data(struct unit_entry *entries, int *num_entries_used, int *total_cost)
void get_economy_report_data(struct improvement_entry *entries, int *num_entries_used, int *total_cost, int *total_income)
static struct terrain * char2terrain(char ch)
Definition savegame2.c:1058
struct srv_list * server_scan_get_list(struct server_scan *scan)
Definition servers.c:855
void server_scan_finish(struct server_scan *scan)
Definition servers.c:868
struct server_scan * server_scan_begin(enum server_scan_type type, ServerScanErrorFunc error_func)
Definition servers.c:744
enum server_scan_type server_scan_get_type(const struct server_scan *scan)
Definition servers.c:798
enum server_scan_status server_scan_poll(struct server_scan *scan)
Definition servers.c:821
#define server_list_iterate_end
Definition servers.h:57
server_scan_status
Definition servers.h:79
@ SCAN_STATUS_PARTIAL
Definition servers.h:82
@ SCAN_STATUS_ERROR
Definition servers.h:80
@ SCAN_STATUS_DONE
Definition servers.h:83
#define server_list_iterate(serverlist, pserver)
Definition servers.h:55
server_scan_type
Definition servers.h:67
@ SERVER_SCAN_LOCAL
Definition servers.h:68
@ SERVER_SCAN_GLOBAL
Definition servers.h:69
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
const struct strvec * get_scenario_dirs(void)
Definition shared.c:971
const struct strvec * get_save_dirs(void)
Definition shared.c:934
struct fileinfo_list * fileinfolist_infix(const struct strvec *dirs, const char *infix, bool nodups)
Definition shared.c:1204
#define fileinfo_list_iterate(list, pnode)
Definition shared.h:176
#define fileinfo_list_iterate_end
Definition shared.h:178
void side_center_unit()
Definition sidebar.cpp:650
void side_show_map(bool nothing)
Definition sidebar.cpp:624
void side_indicators_menu()
Definition sidebar.cpp:702
void side_left_click_science(bool nothing)
Definition sidebar.cpp:809
void side_rates_wdg(bool nothing)
Definition sidebar.cpp:640
void side_finish_turn(bool nothing)
Definition sidebar.cpp:632
void side_right_click_science(void)
Definition sidebar.cpp:760
void side_right_click_diplomacy(void)
Definition sidebar.cpp:716
@ SW_TAX
Definition sidebar.h:26
@ SW_INDICATORS
Definition sidebar.h:26
Definition city.h:309
int id
Definition city.h:315
enum capital_type capital
Definition city.h:317
struct tile * tile
Definition city.h:311
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
struct conn_list * all_connections
Definition game.h:96
struct connection conn
Definition client_main.h:96
bool gui_qt_show_preview
Definition options.h:387
bool gui_qt_sidebar_left
Definition options.h:389
Definition colors.h:20
struct player * playing
Definition connection.h:156
enum cmdlevel access_level
Definition connection.h:182
bool observer
Definition connection.h:152
char username[MAX_LEN_NAME]
Definition connection.h:169
Definition mapimg.c:367
Definition climisc.h:80
char password[MAX_LEN_PASSWORD]
Definition packets_gen.h:68
struct team * team
Definition player.h:261
struct player_economic economic
Definition player.h:284
char name[MAX_LEN_NAME]
Definition player.h:251
int g
Definition rgbcolor.h:34
int b
Definition rgbcolor.h:34
int r
Definition rgbcolor.h:34
char * host
Definition servers.h:43
char * name
Definition servers.h:41
char * nation
Definition servers.h:44
char * type
Definition servers.h:42
struct server::players * players
int nplayers
Definition servers.h:47
fc_mutex mutex
Definition servers.h:64
struct server_list * servers
Definition servers.h:63
Definition team.c:40
char identifier_load
Definition terrain.h:185
struct rgbcolor * rgb
Definition terrain.h:247
Definition tile.h:49
int id
Definition unit.h:145
struct tile * tile
Definition unit.h:140
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
#define sz_strlcpy(dest, src)
Definition support.h:161
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char * team_name_translation(const struct team *pteam)
Definition team.c:420
const char * team_slot_name_translation(const struct team_slot *tslot)
Definition team.c:253
const struct player_list * team_members(const struct team *pteam)
Definition team.c:456
bool team_slot_is_used(const struct team_slot *tslot)
Definition team.c:162
const char * team_slot_rule_name(const struct team_slot *tslot)
Definition team.c:233
#define team_slots_iterate_end
Definition team.h:75
#define team_slots_iterate(_tslot)
Definition team.h:70
struct terrain * terrain_by_rule_name(const char *name)
Definition terrain.c:174
#define terrain_type_iterate(_p)
Definition terrain.h:358
#define T_UNKNOWN
Definition terrain.h:57
#define TERRAIN_UNKNOWN_IDENTIFIER
Definition terrain.h:188
#define terrain_type_iterate_end
Definition terrain.h:364
const char * tileset_main_intro_filename(const struct tileset *t)
Definition tilespec.c:910
struct sprite * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:6471
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
#define U_LAST
Definition unittype.h:40
const char * fc_git_revision(void)
Definition version.c:75
const char * unstable_message(void)
Definition version.c:160
const char * word_version(void)
Definition version.c:62