Freeciv-3.3
Loading...
Searching...
No Matches
fc_client.cpp
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development 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 <QApplication>
20#include <QComboBox>
21#include <QFormLayout>
22#include <QLineEdit>
23#include <QMainWindow>
24#include <QPainter>
25#include <QResizeEvent>
26#include <QScrollBar>
27#include <QSettings>
28#include <QShortcut>
29#include <QSocketNotifier>
30#include <QSpinBox>
31#include <QStackedLayout>
32#include <QStandardPaths>
33#include <QStatusBar>
34#include <QStyleFactory>
35#include <QTabBar>
36#include <QTextBlock>
37
38#ifdef FC_QT5_MODE
39#include <QTextCodec>
40#endif // FC_QT5_MODE
41
42#include <QTextEdit>
43
44// common
45#include "game.h"
46
47// client
48#include "connectdlg_common.h"
49
50// gui-qt
51#include "fc_client.h"
52#include "fonts.h"
53#include "gui_main.h"
54#include "optiondlg.h"
55#include "sidebar.h"
56#include "sprite.h"
57
60extern "C" {
62}
63extern void write_shortcuts();
64
66
67/************************************************************************/
70fc_client::fc_client() : QMainWindow()
71{
73
74#ifdef FC_QT5_MODE
75 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
76#endif // FC_QT5_MODE
77
85 main_wdg = nullptr;
86 connect_lan = nullptr;
87 connect_metaserver = nullptr;
88 central_layout = nullptr;
89 output_window = nullptr;
90 scenarios_view = nullptr;
91 connect_host_edit = nullptr;
92 connect_port_edit = nullptr;
93 connect_login_edit = nullptr;
94 connect_password_edit = nullptr;
96 button = nullptr;
97 button_box = nullptr;
98 server_notifier = nullptr;
99 chat_line = nullptr;
100 lan_widget = nullptr;
101 wan_widget = nullptr;
102 info_widget = nullptr;
103 saves_load = nullptr;
104 scenarios_load = nullptr;
105 meta_scan_timer = nullptr;
106 lan_scan_timer = nullptr;
107 status_bar = nullptr;
108 status_bar_label = nullptr;
109 menu_bar = nullptr;
110 mapview_wdg = nullptr;
111 sidebar_wdg = nullptr;
112 msgwdg = nullptr;
113 infotab = nullptr;
114 central_wdg = nullptr;
115 game_tab_widget = nullptr;
116 start_players_tree = nullptr;
117 unit_sel = nullptr;
118 info_tile_wdg = nullptr;
119 opened_dialog = nullptr;
120 current_file = "";
121 status_bar_queue.clear();
122 quitting = false;
123 pre_vote = nullptr;
124 x_vote = nullptr;
125 gtd = nullptr;
126 update_info_timer = nullptr;
127 unitinfo_wdg = nullptr;
128 battlelog_wdg = nullptr;
129 interface_locked = false;
130 map_scale = 1.0f;
131 map_font_scale = true;
132 for (int i = 0; i <= PAGE_GAME; i++) {
133 pages_layout[i] = nullptr;
134 pages[i] = nullptr;
135 }
136
137 wtitle = _("Freeciv (%1)");
138 wtitle = wtitle.arg(
140 "Qt6x"
142 "Qt5"
143#else // FC_QT6X_MODE
144 "Qt6"
145#endif // FC_QT6X_MODE
146 );
147
149
150 init();
151}
152
153/************************************************************************/
157{
160 QApplication::setFont(*fc_font::instance()->get_font(fonts::default_font));
161 QString path;
162 central_wdg = new QWidget;
164
165 // General part not related to any single page
166 menu_bar = new mr_menu();
168 corner_wid = new fc_corner(this);
169 menu_bar->setCornerWidget(corner_wid);
170 }
173 status_bar_label = new QLabel;
174 status_bar_label->setAlignment(Qt::AlignCenter);
175 status_bar->addWidget(status_bar_label, 1);
176 set_status_bar(_("Welcome to Freeciv"));
178
179 // PAGE_MAIN
180 pages[PAGE_MAIN] = new QWidget(central_wdg);
181 page = PAGE_MAIN;
183
184 // PAGE_START
185 pages[PAGE_START] = new QWidget(central_wdg);
187
188 // PAGE_SCENARIO
189 pages[PAGE_SCENARIO] = new QWidget(central_wdg);
191
192 // PAGE_LOAD
193 pages[PAGE_LOAD] = new QWidget(central_wdg);
195
196 // PAGE_NETWORK
197 pages[PAGE_NETWORK] = new QWidget(central_wdg);
199 pages[PAGE_NETWORK]->setVisible(false);
200
201 // PAGE_GAME
203 path = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
204 if (!path.isEmpty()) {
205 QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, path);
206 }
207 pages[PAGE_GAME] = new QWidget(central_wdg);
210
211 pages[PAGE_GAME + 1] = new QWidget(central_wdg);
213
214 pages_layout[PAGE_GAME]->setContentsMargins(0, 0, 0, 0);
215
222 pages[PAGE_GAME + 1]->setLayout(pages_layout[PAGE_GAME + 1]);
223
224 central_layout->addWidget(pages[PAGE_MAIN]);
225 central_layout->addWidget(pages[PAGE_NETWORK]);
226 central_layout->addWidget(pages[PAGE_LOAD]);
228 central_layout->addWidget(pages[PAGE_START]);
229 central_layout->addWidget(pages[PAGE_GAME]);
230 central_layout->addWidget(pages[PAGE_GAME + 1]);
231
232 central_wdg->setLayout(central_layout);
234
235 resize(pages[PAGE_MAIN]->minimumSizeHint());
236 setVisible(true);
237
240
241 QPixmapCache::setCacheLimit(80000);
242}
243
244/************************************************************************/
248{
249 status_bar_queue.clear();
250 if (fc_shortcuts::sc()) {
251 delete fc_shortcuts::sc();
252 }
254}
255
256
257/************************************************************************/
264{
265 QShortcut *quit_shortcut = new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q), this);
266
267 qRegisterMetaType<QTextCursor>("QTextCursor");
268 qRegisterMetaType<QTextBlock>("QTextBlock");
270 real_output_window_append(_("This is Qt-client for Freeciv."), nullptr, -1);
273
275
277 connect(quit_shortcut, &QShortcut::activated, this, &fc_client::quit);
278 connect(qapp, &QCoreApplication::aboutToQuit, this, &fc_client::closing);
279 qapp->exec();
280
283}
284
285/************************************************************************/
289{
290 return quitting;
291}
292
293/************************************************************************/
297{
298 quitting = true;
299}
300
301/************************************************************************/
308
309/************************************************************************/
313 const struct text_tag_list *tags)
314{
315 QTextCursor cursor;
316 QColor col = output_window->palette().color(QPalette::Text);
317 QString str = apply_tags(message, tags, col);
318
319 if (output_window != nullptr) {
320 output_window->append(str);
321 output_window->verticalScrollBar()->setSliderPosition(
322 output_window->verticalScrollBar()->maximum());
323 }
324}
325
326/************************************************************************/
330{
331 if (check == PAGE_START || check == PAGE_GAME) {
332 return true;
333 }
334
335 return false;
336}
337
338/************************************************************************/
345{
346 char buf[256];
348 int i_page;
349
350 new_page = static_cast<client_pages>(new_pg);
351
353 && !is_server_running()) {
354 current_file = "";
356 return;
357 }
358
359 if (page == PAGE_NETWORK) {
361 }
362 menuBar()->setVisible(false);
363 if (status_bar != nullptr) {
364 status_bar->setVisible(true);
365 }
366 QApplication::alert(gui()->central_wdg);
367 central_layout->setCurrentWidget(pages[new_pg]);
368 page = new_page;
370 switch (i_page) {
371 case PAGE_MAIN:
372 break;
373 case PAGE_START:
374 pre_vote->hide();
376 break;
377 case PAGE_LOAD:
379 break;
380 case PAGE_GAME:
382 setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
383 }
385 // For MS Windows, it might ignore first
388 status_bar->setVisible(false);
389
392 }
393
394 menuBar()->setVisible(true);
395 mapview_wdg->setFocus();
404 break;
405 case PAGE_SCENARIO:
407 break;
408 case PAGE_NETWORK:
412 fc_snprintf(buf, sizeof(buf), "%d", server_port);
413 connect_port_edit->setText(buf);
415 connect_password_edit->setDisabled(true);
416 connect_confirm_password_edit->setDisabled(true);
417 break;
418 case (PAGE_GAME + 1):
419 break;
420 default:
421 if (client.conn.used) {
423 }
425 break;
426 }
427}
428
429/************************************************************************/
433{
435 gui()->showFullScreen();
436 gui()->game_tab_widget->showFullScreen();
437 } else {
438 // FIXME: Doesn't return properly, probably something with sidebar
439 gui()->showNormal();
440 gui()->game_tab_widget->showNormal();
441 }
442}
443
444/************************************************************************/
448{
449 return page;
450}
451
452/************************************************************************/
456{
457 server_notifier = new QSocketNotifier(sock, QSocketNotifier::Read);
458
459 connect(server_notifier, &QSocketNotifier::activated, this,
461}
462
463/************************************************************************/
470
471/************************************************************************/
475{
476 if (event->type() == QEvent::User) {
478 dynamic_cast<version_message_event&>(*event);
479 set_status_bar(vmevt.get_message());
480 return true;
481 } else {
482 return QMainWindow::event(event);
483 }
484}
485
486/************************************************************************/
490{
491 if (!is_client_quitting()) {
493 event->ignore();
494 }
495}
496
497/************************************************************************/
501{
502 server_notifier->deleteLater();
503}
504
505/************************************************************************/
509{
510 server_notifier->setEnabled(false);
511 input_from_server(sock);
512 server_notifier->setEnabled(true);
513}
514
515/************************************************************************/
519{
520 // Prevent current timer from repeating with possibly wrong interval
521 killTimer(event->timerId());
522
523 // Call timer callback in client common code and
524 // start new timer with correct interval
526}
527
528/************************************************************************/
532{
534
535 if (qapp != nullptr) {
536 qapp->quit();
537 }
538}
539
540/************************************************************************/
551
552/************************************************************************/
556{
558 if (game.info.is_new_game) {
559 send_chat("/take -");
560 } else {
561 send_chat("/detach");
562 }
563 obs_button->setText(_("Don't Observe"));
564 } else {
565 send_chat("/observe");
566 obs_button->setText(_("Observe"));
567 }
568}
569
570/************************************************************************/
583
584/****************************************************************************
585 Deletes cursors
586****************************************************************************/
588{
589 int frame;
590 int cursor;
591
592 for (cursor = 0; cursor < CURSOR_LAST; cursor++) {
593 for (frame = 0; frame < NUM_CURSOR_FRAMES; frame++) {
594 delete fc_cursors[cursor][frame];
595 }
596 }
597}
598
599
600/************************************************************************/
604{
605 QString x;
606
608
609 if (x.isEmpty()) {
610 opened_repo_dlgs.insert(str, widget);
611 return;
612 }
613 log_error("Failed to find place for new tab widget");
614 return;
615}
616
617/************************************************************************/
623{
624 QWidget *w;
625
626 w = opened_repo_dlgs.value(str);
627
628 if (w == nullptr) {
629 return false;
630 }
631
632 return true;
633}
634
635/************************************************************************/
639{
640 int i;
641 QWidget *w;
642
643 if (str == "MAP") {
644 return 0;
645 }
646
647 w = opened_repo_dlgs.value(str);
648 i = game_tab_widget->indexOf(w);
649 return i;
650}
651
652/************************************************************************/
656{
657 // This can't be shared between freeciv versions as the content
658 // might be incompatible.
659 QString sname = "freeciv-qt-client-set-"
660 + QString::number(MAJOR_NEW_OPTION_FILE_NAME) + "."
661 + QString::number(MINOR_NEW_OPTION_FILE_NAME);
662 QSettings s(QSettings::IniFormat, QSettings::UserScope,
663 sname);
664
665 if (s.contains("Chat-fx-size")) {
666 qt_settings.chat_fwidth = s.value("Chat-fx-size").toFloat();
667 } else {
669 }
670 if (s.contains("Chat-fy-size")) {
671 qt_settings.chat_fheight = s.value("Chat-fy-size").toFloat();
672 } else {
674 }
675 if (s.contains("Chat-fx-pos")) {
676 qt_settings.chat_fx_pos = s.value("Chat-fx-pos").toFloat();
677 } else {
679 }
680 if (s.contains("Chat-fy-pos")) {
681 qt_settings.chat_fy_pos = s.value("Chat-fy-pos").toFloat();
682 } else {
684 }
685 if (s.contains("unit_fx")) {
686 qt_settings.unit_info_pos_fx = s.value("unit_fx").toFloat();
687 } else {
689 }
690 if (s.contains("unit_fy")) {
691 qt_settings.unit_info_pos_fy = s.value("unit_fy").toFloat();
692 } else {
694 }
695 if (s.contains("minimap_x")) {
696 qt_settings.minimap_x = s.value("minimap_x").toFloat();
697 } else {
698 qt_settings.minimap_x = 0.84;
699 }
700 if (s.contains("minimap_y")) {
701 qt_settings.minimap_y = s.value("minimap_y").toFloat();
702 } else {
703 qt_settings.minimap_y = 0.79;
704 }
705 if (s.contains("minimap_width")) {
706 qt_settings.minimap_width = s.value("minimap_width").toFloat();
707 } else {
709 }
710 if (s.contains("minimap_height")) {
711 qt_settings.minimap_height = s.value("minimap_height").toFloat();
712 } else {
714 }
715 if (s.contains("battlelog_scale")) {
716 qt_settings.battlelog_scale = s.value("battlelog_scale").toFloat();
717 } else {
719 }
720
721 if (s.contains("City-dialog")) {
722 qt_settings.city_geometry = s.value("City-dialog").toByteArray();
723 }
724 if (s.contains("splitter1")) {
725 qt_settings.city_splitter1 = s.value("splitter1").toByteArray();
726 }
727 if (s.contains("splitter2")) {
728 qt_settings.city_splitter2 = s.value("splitter2").toByteArray();
729 }
730 if (s.contains("splitter3")) {
731 qt_settings.city_splitter3 = s.value("splitter3").toByteArray();
732 }
733 if (s.contains("help-dialog")) {
734 qt_settings.help_geometry = s.value("help-dialog").toByteArray();
735 }
736 if (s.contains("help_splitter1")) {
737 qt_settings.help_splitter1 = s.value("help_splitter1").toByteArray();
738 }
739 if (s.contains("opt-client-dialog")) {
740 qt_settings.options_client_geometry = s.value("opt-client-dialog").toByteArray();
741 }
742 if (s.contains("opt-server-dialog")) {
743 qt_settings.options_server_geometry = s.value("opt-server-dialog").toByteArray();
744 }
745 if (s.contains("new_turn_text")) {
746 qt_settings.show_new_turn_text = s.value("new_turn_text").toBool();
747 } else {
749 }
750 if (s.contains("show_battle_log")) {
751 qt_settings.show_battle_log = s.value("show_battle_log").toBool();
752 } else {
754 }
755 if (s.contains("battlelog_x")) {
756 qt_settings.battlelog_x = s.value("battlelog_x").toFloat();
757 } else {
759 }
760 if (s.contains("minimap_y")) {
761 qt_settings.battlelog_y = s.value("battlelog_y").toFloat();
762 } else {
764 }
766
767 if (s.contains("city_repo_columns")) {
768 qt_settings.city_repo_columns = s.value("city_repo_columns").toByteArray();
769 } else {
771 }
772
775 }
778 }
779 if (qt_settings.chat_fwidth < 0.05 || qt_settings.chat_fwidth > 0.9) {
781 }
782 if (qt_settings.chat_fheight < 0.05 || qt_settings.chat_fheight > 0.9) {
784 }
785 if (qt_settings.battlelog_x < 0.0) {
787 }
788 if (qt_settings.battlelog_y < 0.0) {
790 }
791 if (qt_settings.battlelog_scale > 5.0) {
793 }
796 }
799 }
800}
801
802/************************************************************************/
806{
807 QString sname = "freeciv-qt-client-set-"
808 + QString::number(MAJOR_NEW_OPTION_FILE_NAME) + "."
809 + QString::number(MINOR_NEW_OPTION_FILE_NAME);
810 QSettings s(QSettings::IniFormat, QSettings::UserScope,
811 sname);
812
813 s.setValue("Chat-fx-size", qt_settings.chat_fwidth);
814 s.setValue("Chat-fy-size", qt_settings.chat_fheight);
815 s.setValue("Chat-fx-pos", qt_settings.chat_fx_pos);
816 s.setValue("Chat-fy-pos", qt_settings.chat_fy_pos);
817 s.setValue("City-dialog", qt_settings.city_geometry);
818 s.setValue("splitter1", qt_settings.city_splitter1);
819 s.setValue("splitter2", qt_settings.city_splitter2);
820 s.setValue("splitter3", qt_settings.city_splitter3);
821 s.setValue("help-dialog", qt_settings.help_geometry);
822 s.setValue("help_splitter1", qt_settings.help_splitter1);
823 s.setValue("opt-client-dialog", qt_settings.options_client_geometry);
824 s.setValue("opt-server-dialog", qt_settings.options_server_geometry);
825 s.setValue("unit_fx", qt_settings.unit_info_pos_fx);
826 s.setValue("unit_fy", qt_settings.unit_info_pos_fy);
827 s.setValue("minimap_x", qt_settings.minimap_x);
828 s.setValue("minimap_y", qt_settings.minimap_y);
829 s.setValue("minimap_width", qt_settings.minimap_width);
830 s.setValue("minimap_height", qt_settings.minimap_height);
831 s.setValue("battlelog_scale", qt_settings.battlelog_scale);
832 s.setValue("battlelog_x", qt_settings.battlelog_x);
833 s.setValue("battlelog_y", qt_settings.battlelog_y);
834 s.setValue("new_turn_text", qt_settings.show_new_turn_text);
835 s.setValue("show_battle_log", qt_settings.show_battle_log);
836 s.setValue("city_repo_columns", qt_settings.city_repo_columns);
838}
839
840/************************************************************************/
844{
845 if (unit_sel != nullptr) {
846 unit_sel->close();
847 delete unit_sel;
848 unit_sel = new units_select(ptile, gui()->mapview_wdg);
849 unit_sel->show();
850 } else {
851 unit_sel = new units_select(ptile, gui()->mapview_wdg);
852 unit_sel->show();
853 }
854}
855
856/************************************************************************/
860{
861 if (unit_sel != nullptr) {
864 unit_sel->update();
865 }
866}
867
868/************************************************************************/
872{
873 if (unit_sel != nullptr) {
874 unit_sel->close();
875 delete unit_sel;
876 unit_sel = nullptr;
877 }
878}
879
880/************************************************************************/
884{
885 // If app is closing, opened_repo_dlg is already deleted */
886 if (!is_closing()) {
887 opened_repo_dlgs.remove(str);
888 }
889}
890
891/************************************************************************/
895{
896 option_dialog_popup(_("Set local options"), client_optset, true);
897}
898
899/************************************************************************/
903{
904 enum cursor_type curs;
905 int cursor;
906 QPixmap *pix;
907 int hot_x, hot_y;
908 struct sprite *sprite;
909 int frame;
910 QCursor *c;
911 for (cursor = 0; cursor < CURSOR_LAST; cursor++) {
912 for (frame = 0; frame < NUM_CURSOR_FRAMES; frame++) {
913 curs = static_cast<cursor_type>(cursor);
914 sprite = get_cursor_sprite(tileset, curs, &hot_x, &hot_y, frame);
915 pix = sprite->pm;
916 c = new QCursor(*pix, hot_x, hot_y);
917 fc_cursors[cursor][frame] = c;
918 }
919 }
920}
921
922/************************************************************************/
925fc_corner::fc_corner(QMainWindow *qmw): QWidget()
926{
928 QPushButton *qpb;
929 int h;
931
932 if (f->pointSize() > 0) {
933 h = f->pointSize();
934 } else {
935 h = f->pixelSize();
936 }
937 mw = qmw;
938 hb = new QHBoxLayout();
939 qpb = new QPushButton(fc_icons::instance()->get_icon("cmin"), "");
940 qpb->setFixedSize(h, h);
941 connect(qpb, &QAbstractButton::clicked, this, &fc_corner::minimize);
942 hb->addWidget(qpb);
943 qpb = new QPushButton(fc_icons::instance()->get_icon("cmax"), "");
944 qpb->setFixedSize(h, h);
945 connect(qpb, &QAbstractButton::clicked, this, &fc_corner::maximize);
946 hb->addWidget(qpb);
947 qpb = new QPushButton(fc_icons::instance()->get_icon("cclose"), "");
948 qpb->setFixedSize(h, h);
949 connect(qpb, &QAbstractButton::clicked, this, &fc_corner::close_fc);
950 hb->addWidget(qpb);
951 setLayout(hb);
952}
953
954/************************************************************************/
958{
959 mw->close();
960}
961
962/************************************************************************/
966{
967 if (!mw->isMaximized()) {
968 mw->showMaximized();
969 } else {
970 mw->showNormal();
971 }
972}
973
974/************************************************************************/
978{
979 mw->showMinimized();
980}
981
982/************************************************************************/
986{
987}
988
989/************************************************************************/
993{
994 connect(this, &QStackedWidget::currentChanged, this, &fc_game_tab_widget::current_changed);
995}
996
997/************************************************************************/
1003
1004/************************************************************************/
1008{
1009 if (!m_instance) {
1010 m_instance = new fc_icons;
1011 }
1012 return m_instance;
1013}
1014
1015/************************************************************************/
1019{
1020 if (m_instance) {
1021 delete m_instance;
1022 m_instance = 0;
1023 }
1024}
1025
1026/************************************************************************/
1030{
1031 QIcon icon;
1032 QString str;
1035
1036 str = QString("themes") + DIR_SEPARATOR + "gui-qt" + DIR_SEPARATOR;
1037 // Try custom icon from theme
1038 pn_bytes = str.toUtf8();
1040 + id + ".png").toUtf8();
1041 icon.addFile(fileinfoname(get_data_dirs(),
1042 png_bytes.data()));
1043 str = str + "icons" + DIR_SEPARATOR;
1044 // Try icon from icons dir
1045 if (icon.isNull()) {
1046 pn_bytes = str.toUtf8();
1047 png_bytes = QString(pn_bytes.data() + id + ".png").toUtf8();
1048 icon.addFile(fileinfoname(get_data_dirs(),
1049 png_bytes.data()));
1050 }
1051
1052 return QIcon(icon);
1053}
1054
1055/************************************************************************/
1059{
1060 QPixmap *pm;
1061 bool status;
1062 QString str;
1064
1065 pm = new QPixmap;
1066 if (QPixmapCache::find(id, pm)) {
1067 return pm;
1068 }
1069 str = QString("themes") + DIR_SEPARATOR + "gui-qt" + DIR_SEPARATOR;
1071 + id + ".png").toUtf8();
1072 status = pm->load(fileinfoname(get_data_dirs(),
1073 png_bytes.data()));
1074
1075 if (!status) {
1076 str = str + "icons" + DIR_SEPARATOR;
1077 png_bytes = QString(str + id + ".png").toUtf8();
1078 pm->load(fileinfoname(get_data_dirs(), png_bytes.data()));
1079 }
1080 QPixmapCache::insert(id, *pm);
1081
1082 return pm;
1083}
1084
1085/************************************************************************/
1089{
1090 QString str;
1092
1093 str = QString("themes") + DIR_SEPARATOR + "gui-qt"
1094 + DIR_SEPARATOR + "icons" + DIR_SEPARATOR;
1095 png_bytes = QString(str + id + ".png").toUtf8();
1096
1097 return fileinfoname(get_data_dirs(),
1098 png_bytes.data());
1099}
1100
1101/************************************************************************/
1105{
1106 QSize size;
1107
1108 size = event->size();
1109 if (C_S_RUNNING <= client_state()) {
1110 gui()->sidebar_wdg->resize_me(size.height());
1111 map_canvas_resized(size.width(), size.height());
1112 gui()->infotab->resize(qRound((size.width()
1113 * gui()->qt_settings.chat_fwidth)),
1114 qRound((size.height()
1115 * gui()->qt_settings.chat_fheight)));
1116 gui()->infotab->move(qRound((size.width()
1117 * gui()->qt_settings.chat_fx_pos)),
1118 qRound((size.height()
1119 * gui()->qt_settings.chat_fy_pos)));
1120 gui()->infotab->restore_chat();
1121 gui()->minimapview_wdg->move(qRound(gui()->qt_settings.minimap_x
1122 * mapview.width),
1123 qRound(gui()->qt_settings.minimap_y
1124 * mapview.height));
1125 gui()->minimapview_wdg->resize(qRound(gui()->qt_settings.minimap_width
1126 * mapview.width),
1127 qRound(gui()->qt_settings.minimap_height
1128 * mapview.height));
1129 gui()->battlelog_wdg->set_scale(gui()->qt_settings.battlelog_scale);
1130 gui()->battlelog_wdg->move(qRound(gui()->qt_settings.battlelog_x
1131 * mapview.width),
1132 qRound(gui()->qt_settings.battlelog_y
1133 * mapview.height));
1134 gui()->x_vote->move(width() / 2 - gui()->x_vote->width() / 2, 0);
1137 gui()->mapview_wdg->resize(event->size().width(),size.height());
1138 gui()->unitinfo_wdg->update_actions(nullptr);
1139 }
1140 event->setAccepted(true);
1141}
1142
1143/************************************************************************/
1147{
1149 fc_sidewidget *sw;
1150
1151 if (gui()->is_closing()) {
1152 return;
1153 }
1155
1156 foreach(sw, objs) {
1157 sw->update_final_pixmap();
1158 }
1159 currentWidget()->hide();
1160 widget(index)->show();
1161
1162 // Set focus to map instead sidebar
1163 if (gui()->mapview_wdg && gui()->current_page() == PAGE_GAME
1164 && index == 0) {
1165 gui()->mapview_wdg->setFocus();
1166 }
1167
1168}
1169
1170/************************************************************************/
1174{
1175}
1176
1177/************************************************************************/
1181{
1183 QPushButton *qclient_options;
1184 QHBoxLayout *hbox = nullptr;
1185 QPushButton *but;
1186 int level;
1187
1188 layout = new QFormLayout(this);
1189 nation = new QPushButton(this);
1190 qclient_options = new QPushButton(_("Client Options"));
1191 max_players = new QSpinBox(this);
1192 ailevel = new QComboBox(this);
1193 cruleset = new QComboBox(this);
1194 max_players->setRange(1, MAX_NUM_PLAYERS);
1195
1196 // Text and icon set by update_buttons()
1197 connect(nation, &QPushButton::clicked,
1199 connect(qclient_options, SIGNAL(clicked()), parentWidget(),
1200 SLOT(popup_client_options()));
1201 for (level = 0; level < AI_LEVEL_COUNT; level++) {
1202 if (is_settable_ai_level(static_cast<ai_level>(level))) {
1204 static_cast<ai_level>(level));
1205 ailevel->addItem(level_name, level);
1206 }
1207 }
1208 ailevel->setCurrentIndex(-1);
1209
1210 connect(max_players, SIGNAL(valueChanged(int)),
1211 SLOT(max_players_change(int)));
1212 connect(ailevel, SIGNAL(currentIndexChanged(int)),
1213 SLOT(ailevel_change(int)));
1214 connect(cruleset, SIGNAL(currentIndexChanged(int)),
1215 SLOT(ruleset_change(int)));
1216
1217 but = new QPushButton;
1218 but->setText(_("More Game Options"));
1219 but->setIcon(fc_icons::instance()->get_icon("preferences-other"));
1220 QObject::connect(but, &QAbstractButton::clicked, this,
1222
1223 layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
1224 layout->addRow(_("Nation:"), nation);
1225 layout->addRow(_("Rules:"), cruleset);
1226
1227 hbox = new QHBoxLayout();
1228 hbox->addWidget(max_players);
1229 hbox->addWidget(ailevel);
1230 layout->addRow(_("Players:"), hbox);
1231 layout->addWidget(but);
1232 layout->addWidget(qclient_options);
1234
1236}
1237
1238/************************************************************************/
1242{
1243 int i;
1244 int def_idx = -1;
1245
1246 cruleset->clear();
1247 cruleset->blockSignals(true);
1248 for (i = 0; i < num_rulesets; i++) {
1249 cruleset->addItem(rulesets[i], i);
1250 if (!strcmp("default", rulesets[i])) {
1251 def_idx = i;
1252 }
1253 }
1254
1255 // HACK: server should tell us the current ruleset.
1256 cruleset->setCurrentIndex(def_idx);
1257 cruleset->blockSignals(false);
1258}
1259
1260/************************************************************************/
1265{
1266 max_players->blockSignals(true);
1267 max_players->setValue(aifill);
1268 max_players->blockSignals(false);
1269}
1270
1271/************************************************************************/
1275{
1276 struct sprite *psprite = nullptr;
1277 QPixmap *pixmap = nullptr;
1278 const struct player *pplayer = client_player();
1279
1280 // Update the "Select Nation" button
1281 if (pplayer != nullptr) {
1282 if (pplayer->nation != nullptr) {
1283 // Defeat keyboard shortcut mnemonics
1284 nation->setText(QString(nation_adjective_for_player(pplayer))
1285 .replace("&", "&&"));
1287 pixmap = psprite->pm;
1288 nation->setIconSize(pixmap->size());
1289 nation->setIcon(QIcon(*pixmap));
1290 } else {
1291 nation->setText(_("Random"));
1292 nation->setIcon(fc_icons::instance()->get_icon("flush-random"));
1293 }
1294 }
1295}
1296
1297/************************************************************************/
1301{
1302 enum ai_level level = server_ai_level();
1303
1304 if (ai_level_is_valid(level)) {
1305 int i = ailevel->findData(level);
1306
1307 ailevel->setCurrentIndex(i);
1308 } else {
1309 ailevel->setCurrentIndex(-1);
1310 }
1311}
1312
1313/************************************************************************/
1320
1321/************************************************************************/
1325{
1326 QVariant v = ailevel->currentData();
1327
1328 if (v.isValid()) {
1329 enum ai_level k = static_cast<ai_level>(v.toInt());
1330
1331 // Suppress changes provoked by server rather than local user
1332 if (server_ai_level() != k) {
1333 const char *name = ai_level_cmd(k);
1334
1335 send_chat_printf("/%s", name);
1336 }
1337 }
1338}
1339
1340/************************************************************************/
1344{
1345 if (!cruleset->currentText().isEmpty()) {
1347
1348 rn_bytes = cruleset->currentText().toUtf8();
1349 set_ruleset(rn_bytes.data());
1350 }
1351}
1352
1353/************************************************************************/
1360
1361/************************************************************************/
1365{
1366 option_dialog_popup(_("Set server options"), server_optset, false);
1367}
#define str
Definition astring.c:76
static QFont * get_font(enum client_font font)
Definition canvas.cpp:379
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
QString apply_tags(QString str, const struct text_tag_list *tags, QColor bg_color)
Definition chatline.cpp:573
int send_chat_printf(const char *format,...)
int send_chat(const char *message)
void fc_allocate_ow_mutex(void)
void fc_release_ow_mutex(void)
void chat_welcome_message(bool gui_has_copying_mitem)
void send_chat_message(const QString &message)
Definition chatline.cpp:109
void update_widgets()
Definition chatline.cpp:504
fc_game_tab_widget * game_tab_widget
Definition fc_client.h:258
void chat_message_received(const QString &message, const struct text_tag_list *tags)
void apply_fullscreen()
info_tile * info_tile_wdg
Definition fc_client.h:217
QStringList status_bar_queue
Definition fc_client.h:351
QSocketNotifier * server_notifier
Definition fc_client.h:200
QLineEdit * connect_host_edit
Definition fc_client.h:187
void popdown_unit_sel()
QTextEdit * output_window
Definition fc_client.h:180
bool interface_locked
Definition fc_client.h:272
void init()
void update_sidebar_tooltips()
Definition pages.cpp:2162
fc_settings qt_settings
Definition fc_client.h:267
goto_dialog * gtd
Definition fc_client.h:264
mr_menu * menu_bar
Definition fc_client.h:256
bool quitting
Definition fc_client.h:354
QTimer * meta_scan_timer
Definition fc_client.h:211
hud_battle_log * battlelog_wdg
Definition fc_client.h:271
void closing()
QWidget * connect_lan
Definition fc_client.h:173
QTableWidget * lan_widget
Definition fc_client.h:204
QWidget * connect_metaserver
Definition fc_client.h:174
QLineEdit * connect_confirm_password_edit
Definition fc_client.h:191
chat_input * chat_line
Definition fc_client.h:202
hud_units * unitinfo_wdg
Definition fc_client.h:270
bool map_font_scale
Definition fc_client.h:279
choice_dialog * opened_dialog
Definition fc_client.h:218
pregamevote * pre_vote
Definition fc_client.h:261
QTableWidget * saves_load
Definition fc_client.h:207
void read_settings()
messagewdg * msgwdg
Definition fc_client.h:259
void set_status_bar(QString str, int timeout=2000)
Definition pages.cpp:456
QPushButton * button
Definition fc_client.h:193
bool is_repo_dlg_open(QString str)
void server_input(int sock)
enum client_pages page
Definition fc_client.h:349
enum client_pages current_page()
units_select * unit_sel
Definition fc_client.h:262
QLineEdit * connect_password_edit
Definition fc_client.h:190
void quit()
minimap_view * minimapview_wdg
Definition fc_client.h:231
QStatusBar * status_bar
Definition fc_client.h:215
QTableWidget * wan_widget
Definition fc_client.h:205
void gimme_place(QWidget *widget, QString str)
QCursor * fc_cursors[CURSOR_LAST][NUM_CURSOR_FRAMES]
Definition fc_client.h:265
map_view * mapview_wdg
Definition fc_client.h:229
void delete_cursors(void)
QStackedLayout * central_layout
Definition fc_client.h:178
void write_settings()
info_tab * infotab
Definition fc_client.h:260
void create_start_page()
Definition pages.cpp:652
void slot_disconnect()
QWidget * pages[(int) PAGE_GAME+2]
Definition fc_client.h:172
void slot_pregame_observe()
QTableWidget * info_widget
Definition fc_client.h:206
void set_connection_state(enum connection_state state)
Definition pages.cpp:271
QPushButton * obs_button
Definition fc_client.h:194
void update_info_label()
Definition mapview.cpp:999
QLabel * status_bar_label
Definition fc_client.h:216
QGridLayout * pages_layout[PAGE_GAME+2]
Definition fc_client.h:177
QWidget * main_wdg
Definition fc_client.h:171
QLineEdit * connect_login_edit
Definition fc_client.h:189
void add_server_source(int)
QTextEdit * scenarios_view
Definition fc_client.h:181
QDialogButtonBox * button_box
Definition fc_client.h:198
void destroy_server_scans(void)
Definition pages.cpp:1026
void create_cursors(void)
void switch_page(int i)
void create_network_page()
Definition pages.cpp:308
QTreeWidget * start_players_tree
Definition fc_client.h:209
bool chat_active_on_page(enum client_pages)
void create_load_page()
Definition pages.cpp:500
QTimer * lan_scan_timer
Definition fc_client.h:212
QLineEdit * connect_port_edit
Definition fc_client.h:188
fc_sidebar * sidebar_wdg
Definition fc_client.h:230
void create_main_page()
Definition pages.cpp:138
bool event(QEvent *event)
float map_scale
Definition fc_client.h:278
void create_loading_page()
Definition pages.cpp:488
void update_fonts()
void update_network_lists()
Definition pages.cpp:1056
QWidget * central_wdg
Definition fc_client.h:255
void fc_main(QApplication *qapp)
QMap< QString, QWidget * > opened_repo_dlgs
Definition fc_client.h:350
QString current_file
Definition fc_client.h:352
void closeEvent(QCloseEvent *event)
xvote * x_vote
Definition fc_client.h:263
void remove_repo_dlg(QString str)
void slot_pregame_start()
QTimer * update_info_timer
Definition fc_client.h:213
void toggle_unit_sel_widget(struct tile *ptile)
void popup_client_options()
void update_unit_sel()
void update_load_page(void)
Definition pages.cpp:1442
QTableWidget * scenarios_load
Definition fc_client.h:208
int gimme_index_of(QString str)
fc_corner * corner_wid
Definition fc_client.h:257
void send_fake_chat_message(const QString &message)
void timerEvent(QTimerEvent *)
bool is_closing()
void create_scenario_page()
Definition pages.cpp:585
void remove_server_source()
void update_scenarios_page(void)
Definition pages.cpp:1473
void create_game_page()
Definition pages.cpp:736
void minimize()
QMainWindow * mw
Definition fc_client.h:157
void maximize()
void close_fc()
fc_corner(QMainWindow *qmw)
static fc_font * m_instance
Definition fonts.h:43
void init_fonts()
Definition fonts.cpp:77
static fc_font * instance()
Definition fonts.cpp:41
QFont * get_font(QString name)
Definition fonts.cpp:63
void resizeEvent(QResizeEvent *event)
void current_changed(int index)
QIcon get_icon(const QString &id)
static void drop()
static fc_icons * m_instance
Definition fc_client.h:93
QPixmap * get_pixmap(const QString &id)
static fc_icons * instance()
QString get_path(const QString &id)
static fc_shortcuts * sc()
void resize_me(int height, bool force=false)
Definition sidebar.cpp:570
QList< fc_sidewidget * > objects
Definition sidebar.h:121
void update_fonts()
Definition sidebar.cpp:612
void update_final_pixmap()
Definition sidebar.cpp:393
void set_scale(float s)
void update_actions(unit_list *punits)
void restore_chat()
chatwdg * chtwdg
Definition messagewin.h:79
void reset()
Definition mapview.cpp:731
void popup_server_options()
QPushButton * nation
Definition fc_client.h:374
QComboBox * ailevel
Definition fc_client.h:372
void ailevel_change(int i)
void set_rulesets(int num_rulesets, char **rulesets)
void set_aifill(int aifill)
void max_players_change(int i)
QComboBox * cruleset
Definition fc_client.h:373
pregame_options(QWidget *parent)
void ruleset_change(int i)
QSpinBox * max_players
Definition fc_client.h:375
void update_units()
Definition dialogs.cpp:4854
void create_pixmap()
Definition dialogs.cpp:4553
bool is_client_quitting(void)
bool can_client_control(void)
bool client_is_global_observer(void)
bool client_is_observer(void)
char user_name[512]
double real_timer_callback(void)
char server_host[512]
struct civclient client
enum client_states client_state(void)
int server_port
void set_client_state(enum client_states newstate)
#define client_player()
#define TIMER_INTERVAL
Definition client_main.h:30
@ C_S_DISCONNECTED
Definition client_main.h:45
@ C_S_RUNNING
Definition client_main.h:47
enum ai_level server_ai_level(void)
Definition climisc.c:1519
void center_on_something(void)
Definition climisc.c:430
void disconnect_from_server(bool leaving_sound)
Definition clinet.c:306
void input_from_server(int fd)
Definition clinet.c:411
char * incite_cost
Definition comments.c:76
void set_ruleset(const char *ruleset)
bool is_server_running(void)
enum event_type event
Definition events.c:81
bool get_turn_done_button_state()
QString current_theme
Definition fc_client.cpp:65
void write_shortcuts()
@ LOGIN_TYPE
Definition fc_client.h:56
class fc_client * gui()
Definition gui_main.cpp:82
#define MAX_NUM_PLAYERS
Definition fc_types.h:36
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:61
static PangoLayout * layout
Definition canvas.c:325
void real_output_window_append(const char *astring, const struct text_tag_list *tags, int conn_id)
Definition chatline.c:875
void popup_races_dialog(struct player *pplayer)
Definition dialogs.c:1215
void popup_quit_dialog(void)
Definition gui_main.c:2347
void overview_size_changed(void)
Definition mapview.c:326
void option_dialog_popup(const char *name, const struct option_set *poptset)
Definition optiondlg.c:984
static enum client_pages current_page
Definition pages.c:78
void voteinfo_gui_update(void)
static QApplication * qapp
Definition gui_main.cpp:69
QApplication * current_app()
Definition gui_main.cpp:227
void show_new_turn_info()
const char * name
Definition inputfile.c:127
#define log_error(message,...)
Definition log.h:104
void side_disable_endturn(bool do_restore)
Definition sidebar.cpp:676
void init_mapcanvas_and_overview(void)
struct view mapview
void free_mapcanvas_and_overview(void)
bool map_canvas_resized(int width, int height)
const char *const default_font
Definition fonts.h:27
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const struct option_set * server_optset
Definition options.c:4077
const struct option_set * client_optset
Definition options.c:1291
struct client_options gui_options
Definition options.c:71
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:442
bool option_int_set(struct option *poption, int val)
Definition options.c:889
#define MAJOR_NEW_OPTION_FILE_NAME
Definition options.h:38
#define MINOR_NEW_OPTION_FILE_NAME
Definition options.h:42
int dsend_packet_player_ready(struct connection *pc, int player_no, bool is_ready)
bool is_settable_ai_level(enum ai_level level)
Definition player.c:1925
int player_number(const struct player *pplayer)
Definition player.c:837
#define ai_level_cmd(_level_)
Definition player.h:572
void qtg_real_science_report_dialog_update(void *unused)
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
const char * fileinfoname(const struct strvec *dirs, const char *filename)
Definition shared.c:1094
const struct strvec * get_data_dirs(void)
Definition shared.c:886
#define DIR_SEPARATOR
Definition shared.h:127
size_t size
Definition specvec.h:72
struct sprite int x
Definition sprite_g.h:31
const char * aifill(int amount)
Definition srv_main.c:2548
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
bool gui_qt_fullscreen
Definition options.h:413
bool gui_qt_allied_chat_only
Definition options.h:415
bool gui_qt_show_titlebar
Definition options.h:426
QByteArray city_splitter2
Definition fc_client.h:134
QByteArray city_geometry
Definition fc_client.h:132
QByteArray help_geometry
Definition fc_client.h:136
float unit_info_pos_fx
Definition fc_client.h:140
QByteArray options_client_geometry
Definition fc_client.h:138
float unit_info_pos_fy
Definition fc_client.h:141
float chat_fwidth
Definition fc_client.h:123
float chat_fheight
Definition fc_client.h:124
QByteArray help_splitter1
Definition fc_client.h:137
float chat_fx_pos
Definition fc_client.h:125
float battlelog_scale
Definition fc_client.h:146
float battlelog_x
Definition fc_client.h:147
QByteArray city_splitter3
Definition fc_client.h:135
float minimap_x
Definition fc_client.h:142
float minimap_height
Definition fc_client.h:145
bool show_battle_log
Definition fc_client.h:129
float minimap_width
Definition fc_client.h:144
float battlelog_y
Definition fc_client.h:148
QByteArray options_server_geometry
Definition fc_client.h:139
QByteArray city_repo_columns
Definition fc_client.h:131
float chat_fy_pos
Definition fc_client.h:126
QByteArray city_splitter1
Definition fc_client.h:133
bool show_new_turn_text
Definition fc_client.h:128
float minimap_y
Definition fc_client.h:143
int player_repo_sort_col
Definition fc_client.h:127
struct nation_type * nation
Definition player.h:260
QPixmap * pm
Definition sprite.h:25
Definition tile.h:50
int height
int width
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#define TRUE
Definition support.h:46
void tileset_free_tiles(struct tileset *t)
Definition tilespec.c:6842
struct sprite * get_nation_shield_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:7012
struct sprite * get_cursor_sprite(const struct tileset *t, enum cursor_type cursor, int *hot_x, int *hot_y, int frame)
Definition tilespec.c:7215
#define NUM_CURSOR_FRAMES
Definition tilespec.h:304
cursor_type
Definition tilespec.h:288
@ CURSOR_LAST
Definition tilespec.h:300
void client_start_server_and_set_page(enum client_pages page)
void set_client_page(enum client_pages page)