1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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 <QMouseEvent>
20 #include <QPainter>
21 #include <QPixmap>
22 #include <QToolTip>
23 #include <QWheelEvent>
24
25 // utility
26 #include "log.h"
27 #include "support.h"
28
29 // common
30 #include "calendar.h"
31 #include "game.h"
32 #include "map.h"
33 #include "research.h"
34
35 // client
36 #include "climisc.h"
37 #include "mapctrl_common.h"
38 #include "menu.h" // gov_menu
39 #include "movement.h"
40 #include "overview_common.h"
41 #include "sprite.h"
42 #include "repodlgs.h"
43 #include "text.h"
44
45 // gui-qt
46 #include "colors.h"
47 #include "fc_client.h"
48 #include "qtg_cxxside.h"
49 #include "mapview.h"
50 #include "sidebar.h"
51
52 const char *get_timeout_label_text();
53 static int mapview_frozen_level = 0;
54 extern void destroy_city_dialog();
55 extern struct canvas *canvas;
56 extern QApplication *qapp;
57
58 #define MAX_DIRTY_RECTS 20
59 static int num_dirty_rects = 0;
60 static QRect dirty_rects[MAX_DIRTY_RECTS];
61
62 extern int last_center_enemy;
63 extern int last_center_capital;
64 extern int last_center_player_city;
65 extern int last_center_enemy_city;
66
67 /**************************************************************************
68 Check if point x, y is in area (px -> pxe, py - pye)
69 **************************************************************************/
is_point_in_area(int x,int y,int px,int py,int pxe,int pye)70 bool is_point_in_area(int x, int y, int px, int py, int pxe, int pye)
71 {
72 if (x >= px && y >= py && x <= pxe && y <= pye) {
73 return true;
74 }
75 return false;
76 }
77
78 /**************************************************************************
79 Draws calculated trade routes
80 **************************************************************************/
draw_calculated_trade_routes(QPainter * painter)81 void draw_calculated_trade_routes(QPainter *painter)
82 {
83 int dx, dy;
84 float w, h;
85 float x1, y1, x2, y2;
86 qtiles qgilles;
87 struct city *pcity;
88 struct color *pcolor;
89 QPen pen;
90
91 if (!can_client_control()
92 || gui()->trade_gen.cities.empty()) {
93 return;
94 }
95 pcolor = get_color(tileset, COLOR_MAPVIEW_TRADE_ROUTES_NO_BUILT);
96 /* Draw calculated trade routes */
97 if (gui_options.draw_city_trade_routes) {
98
99 foreach (qgilles, gui()->trade_gen.lines) {
100 base_map_distance_vector(&dx, &dy, TILE_XY(qgilles.t1),
101 TILE_XY(qgilles.t2));
102 map_to_gui_vector(tileset, 1.0, &w, &h, dx, dy);
103
104 tile_to_canvas_pos(&x1, &y1, qgilles.t1);
105 tile_to_canvas_pos(&x2, &y2, qgilles.t2);
106
107 /* Dont draw if route was already established */
108 if (tile_city(qgilles.t1) && tile_city(qgilles.t2)
109 && have_cities_trade_route(tile_city(qgilles.t1),
110 tile_city(qgilles.t2))) {
111 continue;
112 }
113
114 if (qgilles.autocaravan != nullptr) {
115 pcolor = get_color(tileset, COLOR_MAPVIEW_TRADE_ROUTES_SOME_BUILT);
116 }
117
118 pen.setColor(pcolor->qcolor);
119 pen.setStyle(Qt::DashLine);
120 pen.setDashOffset(4);
121 pen.setWidth(1);
122 painter->setPen(pen);
123 if (x2 - x1 == w && y2 - y1 == h) {
124 painter->drawLine(x1 + tileset_tile_width(tileset) / 2,
125 y1 + tileset_tile_height(tileset) / 2,
126 x1 + tileset_tile_width(tileset) / 2 + w,
127 y1 + tileset_tile_height(tileset) / 2 + h);
128 continue;
129 }
130 painter->drawLine(x2 + tileset_tile_width(tileset) / 2,
131 y2 + tileset_tile_height(tileset) / 2,
132 x2 + tileset_tile_width(tileset) / 2 - w,
133 y2 + tileset_tile_height(tileset) / 2 - h);
134 }
135 }
136 /* Draw virtual cities */
137 foreach (pcity, gui()->trade_gen.virtual_cities) {
138 float canvas_x, canvas_y;
139 if (pcity->tile != nullptr
140 && tile_to_canvas_pos(&canvas_x, &canvas_y, pcity->tile)) {
141 painter->drawPixmap(static_cast<int>(canvas_x),
142 static_cast<int>(canvas_y),
143 *get_attention_crosshair_sprite(tileset)->pm);
144 }
145 }
146 }
147
148 /**************************************************************************
149 Constructor for idle callbacks
150 **************************************************************************/
mr_idle()151 mr_idle::mr_idle()
152 {
153 connect(&timer, &QTimer::timeout, this, &mr_idle::idling);
154 timer.start(5);
155 }
156
157 /**************************************************************************
158 Destructor for idle callbacks
159 **************************************************************************/
~mr_idle()160 mr_idle::~mr_idle()
161 {
162 call_me_back *cb;
163
164 while (!callback_list.isEmpty()) {
165 cb = callback_list.dequeue();
166 delete cb;
167 }
168 }
169
170 /**************************************************************************
171 Slot used to execute 1 callback from callbacks stored in idle list
172 **************************************************************************/
idling()173 void mr_idle::idling()
174 {
175 call_me_back *cb;
176
177 while (!callback_list.isEmpty()) {
178 cb = callback_list.dequeue();
179 (cb->callback) (cb->data);
180 delete cb;
181 }
182 }
183
184 /**************************************************************************
185 Adds one callback to execute later
186 **************************************************************************/
add_callback(call_me_back * cb)187 void mr_idle::add_callback(call_me_back *cb)
188 {
189 callback_list.enqueue(cb);
190 }
191
192 /**************************************************************************
193 Constructor for map
194 **************************************************************************/
map_view()195 map_view::map_view() : QWidget()
196 {
197 menu_click = false;
198 cursor = -1;
199 QTimer *timer = new QTimer(this);
200 setAttribute(Qt::WA_OpaquePaintEvent, true);
201 connect(timer, &QTimer::timeout, this, &map_view::timer_event);
202 timer->start(200);
203 setMouseTracking(true);
204 stored_autocenter = gui_options.auto_center_on_unit;
205 setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
206 }
207
208 /**************************************************************************
209 Updates cursor
210 **************************************************************************/
update_cursor(enum cursor_type ct)211 void map_view::update_cursor(enum cursor_type ct)
212 {
213 int i;
214
215 if (ct == CURSOR_DEFAULT) {
216 setCursor(Qt::ArrowCursor);
217 cursor = -1;
218 return;
219 }
220 cursor_frame = 0;
221 i = static_cast<int>(ct);
222 cursor = i;
223 setCursor(*(gui()->fc_cursors[i][0]));
224 }
225
226 /**************************************************************************
227 Timer for cursor
228 **************************************************************************/
timer_event()229 void map_view::timer_event()
230 {
231 if (gui()->infotab->underMouse()
232 || gui()->minimapview_wdg->underMouse()
233 || gui()->sidebar_wdg->underMouse()) {
234 update_cursor(CURSOR_DEFAULT);
235 return;
236 }
237 if (cursor == -1) {
238 return;
239 }
240 cursor_frame++;
241 if (cursor_frame == NUM_CURSOR_FRAMES) {
242 cursor_frame = 0;
243 }
244 setCursor(*(gui()->fc_cursors[cursor][cursor_frame]));
245 }
246
247 /**************************************************************************
248 Updates fonts
249 **************************************************************************/
update_font(const QString & name,const QFont & font)250 void map_view::update_font(const QString &name, const QFont &font)
251 {
252 if (name == fonts::city_names ||
253 name == fonts::city_productions) {
254 update_map_canvas_visible();
255 }
256 }
257
258 /**************************************************************************
259 Focus lost event
260 **************************************************************************/
focusOutEvent(QFocusEvent * event)261 void map_view::focusOutEvent(QFocusEvent *event)
262 {
263 update_cursor(CURSOR_DEFAULT);
264 }
265
266 /**************************************************************************
267 Leave event
268 **************************************************************************/
leaveEvent(QEvent * event)269 void map_view::leaveEvent(QEvent *event)
270 {
271 update_cursor(CURSOR_DEFAULT);
272 }
273
274
275 /**************************************************************************
276 slot inherited from QPixamp
277 **************************************************************************/
paintEvent(QPaintEvent * event)278 void map_view::paintEvent(QPaintEvent *event)
279 {
280 QPainter painter;
281
282 painter.begin(this);
283 paint(&painter, event);
284 painter.end();
285 }
286
287 /**************************************************************************
288 Redraws given rectangle on map
289 **************************************************************************/
paint(QPainter * painter,QPaintEvent * event)290 void map_view::paint(QPainter *painter, QPaintEvent *event)
291 {
292 painter->drawPixmap(event->rect(), mapview.store->map_pixmap,
293 event->rect());
294 draw_calculated_trade_routes(painter);
295 }
296
297 /**************************************************************************
298 Sets new point for new search
299 **************************************************************************/
resume_searching(int pos_x,int pos_y,int & w,int & h,int wdth,int hght,int recursive_nr)300 void map_view::resume_searching(int pos_x ,int pos_y ,int &w, int &h,
301 int wdth, int hght, int recursive_nr)
302 {
303 int new_pos_x, new_pos_y;
304
305 recursive_nr++;
306 new_pos_x = pos_x;
307 new_pos_y = pos_y;
308
309 if (pos_y + hght + 4 < height() && pos_x > width() / 2) {
310 new_pos_y = pos_y + 5;
311 } else if (pos_x > 0 && pos_y > 10) {
312 new_pos_x = pos_x - 5;
313 } else if (pos_y > 0) {
314 new_pos_y = pos_y - 5;
315 } else if (pos_x + wdth + 4 < this->width()) {
316 new_pos_x = pos_x + 5;
317 }
318 find_place(new_pos_x, new_pos_y, w, h, wdth, hght, recursive_nr);
319 }
320
321 /**************************************************************************
322 Searches place for widget with size w and height h
323 Starts looking from position pos_x, pos_y, going clockwork
324 Returns position as (w,h)
325 Along with resume_searching its recursive function.
326 **************************************************************************/
find_place(int pos_x,int pos_y,int & w,int & h,int wdth,int hght,int recursive_nr)327 void map_view::find_place(int pos_x, int pos_y, int &w, int &h, int wdth,
328 int hght, int recursive_nr)
329 {
330 int i;
331 int x, y, xe, ye;
332 QList <fcwidget *>widgets = this->findChildren <fcwidget *>();
333 bool cont_searching = false;
334
335 if (recursive_nr >= 1000) {
336 /**
337 * give up searching position
338 */
339 return;
340 }
341 /**
342 * try position pos_x, pos_y,
343 * check middle and borders if aren't above other widget
344 */
345
346 for (i = 0; i < widgets.count(); i++) {
347 if (!widgets[i]->isVisible()) {
348 continue;
349 }
350 x = widgets[i]->pos().x();
351 y = widgets[i]->pos().y();
352
353 if (x == 0 && y ==0) {
354 continue;
355 }
356 xe = widgets[i]->pos().x() + widgets[i]->width();
357 ye = widgets[i]->pos().y() + widgets[i]->height();
358
359 if (is_point_in_area(pos_x, pos_y, x, y, xe, ye)) {
360 cont_searching = true;
361 }
362 if (is_point_in_area(pos_x + wdth, pos_y, x, y, xe, ye)) {
363 cont_searching = true;
364 }
365 if (is_point_in_area(pos_x + wdth, pos_y + hght, x, y, xe, ye)) {
366 cont_searching = true;
367 }
368 if (is_point_in_area(pos_x, pos_y + hght, x, y, xe, ye)) {
369 cont_searching = true;
370 }
371 if (is_point_in_area(pos_x + wdth / 2, pos_y + hght / 2, x, y, xe, ye)) {
372 cont_searching = true;
373 }
374 }
375 w = pos_x;
376 h = pos_y;
377 if (cont_searching) {
378 resume_searching(pos_x, pos_y, w, h, wdth, hght, recursive_nr);
379 }
380 }
381
382
383 /****************************************************************************
384 Constructor for move widget
385 ****************************************************************************/
move_widget(QWidget * parent)386 move_widget::move_widget(QWidget *parent) : QLabel()
387 {
388 QPixmap *pix;
389
390 setParent(parent);
391 setCursor(Qt::SizeAllCursor);
392 pix = fc_icons::instance()->get_pixmap("move");
393 setPixmap(*pix);
394 delete pix;
395 setFixedSize(16, 16);
396 }
397
398
399 /****************************************************************************
400 Puts move widget to left top corner
401 ****************************************************************************/
put_to_corner()402 void move_widget::put_to_corner()
403 {
404 move(0, 0);
405 }
406
407 /****************************************************************************
408 Mouse handler for move widget (moves parent widget)
409 ****************************************************************************/
mouseMoveEvent(QMouseEvent * event)410 void move_widget::mouseMoveEvent(QMouseEvent *event)
411 {
412 if (!gui()->interface_locked) {
413 parentWidget()->move(event->globalPos() - point);
414 }
415 }
416
417 /****************************************************************************
418 Sets moving point for move widget;
419 ****************************************************************************/
mousePressEvent(QMouseEvent * event)420 void move_widget::mousePressEvent(QMouseEvent* event)
421 {
422 if (!gui()->interface_locked) {
423 point = event->globalPos() - parentWidget()->geometry().topLeft();
424 }
425 update();
426 }
427
428 /****************************************************************************
429 Constructor for resize widget
430 ****************************************************************************/
resize_widget(QWidget * parent)431 resize_widget::resize_widget(QWidget *parent) : QLabel()
432 {
433 QPixmap *pix;
434
435 setParent(parent);
436 setCursor(Qt::SizeFDiagCursor);
437 pix = fc_icons::instance()->get_pixmap("resize");
438 setPixmap(*pix);
439 delete pix;
440 }
441
442 /****************************************************************************
443 Puts resize widget to left top corner
444 ****************************************************************************/
put_to_corner()445 void resize_widget::put_to_corner()
446 {
447 move(parentWidget()->width() - width(),
448 parentWidget()->height() - height());
449 }
450
451 /****************************************************************************
452 Mouse handler for resize widget (resizes parent widget)
453 ****************************************************************************/
mouseMoveEvent(QMouseEvent * event)454 void resize_widget::mouseMoveEvent(QMouseEvent * event)
455 {
456 QPoint qp, np;
457
458 if (gui()->interface_locked) {
459 return;
460 }
461 qp = event->globalPos();
462 np.setX(qp.x() - point.x());
463 np.setY(qp.y() - point.y());
464 np.setX(qMax(np.x(), 32));
465 np.setY(qMax(np.y(), 32));
466 parentWidget()->resize(np.x(), np.y());
467 }
468
469 /****************************************************************************
470 Sets moving point for resize widget;
471 ****************************************************************************/
mousePressEvent(QMouseEvent * event)472 void resize_widget::mousePressEvent(QMouseEvent* event)
473 {
474 QPoint qp;
475
476 if (gui()->interface_locked) {
477 return;
478 }
479 qp = event->globalPos();
480 point.setX(qp.x() - parentWidget()->width());
481 point.setY(qp.y() - parentWidget()->height());
482 update();
483 }
484
485 /****************************************************************************
486 Constructor for close widget
487 ****************************************************************************/
close_widget(QWidget * parent)488 close_widget::close_widget(QWidget *parent) : QLabel()
489 {
490 QPixmap *pix;
491
492 setParent(parent);
493 setCursor(Qt::ArrowCursor);
494 pix = fc_icons::instance()->get_pixmap("close");
495 setPixmap(*pix);
496 delete pix;
497 }
498
499 /****************************************************************************
500 Puts close widget to right top corner
501 ****************************************************************************/
put_to_corner()502 void close_widget::put_to_corner()
503 {
504 move(parentWidget()->width()-width(), 0);
505 }
506
507 /****************************************************************************
508 Mouse handler for close widget, hides parent widget
509 ****************************************************************************/
mousePressEvent(QMouseEvent * event)510 void close_widget::mousePressEvent(QMouseEvent* event)
511 {
512 if (gui()->interface_locked) {
513 return;
514 }
515 if (event->button() == Qt::LeftButton) {
516 parentWidget()->hide();
517 notify_parent();
518 }
519 }
520 /****************************************************************************
521 Notifies parent to do custom action, parent is already hidden.
522 ****************************************************************************/
notify_parent()523 void close_widget::notify_parent()
524 {
525 fcwidget *fcw;
526
527 fcw = reinterpret_cast<fcwidget *>(parentWidget());
528 fcw->update_menu();
529 }
530
531
532 /**************************************************************************
533 Constructor for minimap
534 **************************************************************************/
minimap_view(QWidget * parent)535 minimap_view::minimap_view(QWidget *parent) : fcwidget()
536 {
537 setParent(parent);
538 setAttribute(Qt::WA_OpaquePaintEvent, true);
539 w_ratio = 0.0;
540 h_ratio = 0.0;
541 // Dark magic: This call is required for the widget to work.
542 resize(0, 0);
543 background = QBrush(QColor (0, 0, 0));
544 setCursor(Qt::CrossCursor);
545 rw = new resize_widget(this);
546 rw->put_to_corner();
547 pix = new QPixmap;
548 scale_factor = 1.0;
549 connect(&thread, &minimap_thread::rendered_image,
550 this, &minimap_view::update_pixmap);
551 }
552
553 /**************************************************************************
554 Minimap_view destructor
555 **************************************************************************/
~minimap_view()556 minimap_view::~minimap_view()
557 {
558 if (pix) {
559 delete pix;
560 }
561 }
562
563 /**************************************************************************
564 Paint event for minimap
565 **************************************************************************/
paintEvent(QPaintEvent * event)566 void minimap_view::paintEvent(QPaintEvent *event)
567 {
568 QPainter painter;
569
570 painter.begin(this);
571 paint(&painter, event);
572 painter.end();
573 }
574
575 /**************************************************************************
576 Sets scaling factor for minimap
577 **************************************************************************/
scale(double factor)578 void minimap_view::scale(double factor)
579 {
580 scale_factor *= factor;
581 if (scale_factor < 1) {
582 scale_factor = 1.0;
583 };
584 update_image();
585 }
586
587 /**************************************************************************
588 Converts gui to overview position.
589 **************************************************************************/
gui_to_overview(int * ovr_x,int * ovr_y,int gui_x,int gui_y)590 static void gui_to_overview(int *ovr_x, int *ovr_y, int gui_x, int gui_y)
591 {
592 double ntl_x, ntl_y;
593 const double gui_xd = gui_x, gui_yd = gui_y;
594 const double W = tileset_tile_width(tileset);
595 const double H = tileset_tile_height(tileset);
596 double map_x, map_y;
597
598 if (tileset_is_isometric(tileset)) {
599 map_x = (gui_xd * H + gui_yd * W) / (W * H);
600 map_y = (gui_yd * W - gui_xd * H) / (W * H);
601 } else {
602 map_x = gui_xd / W;
603 map_y = gui_yd / H;
604 }
605
606 if (MAP_IS_ISOMETRIC) {
607 ntl_y = map_x + map_y - game.map.xsize;
608 ntl_x = 2 * map_x - ntl_y;
609 } else {
610 ntl_x = map_x;
611 ntl_y = map_y;
612 }
613
614 *ovr_x = floor((ntl_x - (double)gui_options.overview.map_x0)
615 * OVERVIEW_TILE_SIZE);
616 *ovr_y = floor((ntl_y - (double)gui_options.overview.map_y0)
617 * OVERVIEW_TILE_SIZE);
618
619 if (current_topo_has_flag(TF_WRAPX)) {
620 *ovr_x = FC_WRAP(*ovr_x, NATURAL_WIDTH * OVERVIEW_TILE_SIZE);
621 } else {
622 if (MAP_IS_ISOMETRIC) {
623 *ovr_x -= OVERVIEW_TILE_SIZE;
624 }
625 }
626 if (current_topo_has_flag(TF_WRAPY)) {
627 *ovr_y = FC_WRAP(*ovr_y, NATURAL_HEIGHT * OVERVIEW_TILE_SIZE);
628 }
629 }
630
631 /**************************************************************************
632 Called by close widget, cause widget has been hidden. Updates menu.
633 **************************************************************************/
update_menu()634 void minimap_view::update_menu()
635 {
636 ::gui()->menu_bar->minimap_status->setChecked(false);
637 }
638
639 /**************************************************************************
640 Minimap is being moved, position is being remebered
641 **************************************************************************/
moveEvent(QMoveEvent * event)642 void minimap_view::moveEvent(QMoveEvent* event)
643 {
644 position = event->pos();
645 }
646
647 /**************************************************************************
648 Minimap is just unhidden, old position is restored
649 **************************************************************************/
showEvent(QShowEvent * event)650 void minimap_view::showEvent(QShowEvent* event)
651 {
652 move(position);
653 event->setAccepted(true);
654 }
655
656 /**************************************************************************
657 Draws viewport on minimap
658 **************************************************************************/
draw_viewport(QPainter * painter)659 void minimap_view::draw_viewport(QPainter *painter)
660 {
661 int i, x[4], y[4];
662 int src_x, src_y, dst_x, dst_y;
663
664 if (!gui_options.overview.map) {
665 return;
666 }
667
668 gui_to_overview(&x[0], &y[0], mapview.gui_x0, mapview.gui_y0);
669 gui_to_overview(&x[1], &y[1], mapview.gui_x0 + mapview.width,
670 mapview.gui_y0);
671 gui_to_overview(&x[2], &y[2], mapview.gui_x0 + mapview.width,
672 mapview.gui_y0 + mapview.height);
673 gui_to_overview(&x[3], &y[3], mapview.gui_x0,
674 mapview.gui_y0 + mapview.height);
675 painter->setPen(QColor(Qt::white));
676
677 if (scale_factor > 1) {
678 for (i = 0; i < 4; i++) {
679 scale_point(x[i], y[i]);
680 }
681 }
682
683 for (i = 0; i < 4; i++) {
684 src_x = x[i] * w_ratio;
685 src_y = y[i] * h_ratio;
686 dst_x = x[(i + 1) % 4] * w_ratio;
687 dst_y = y[(i + 1) % 4] * h_ratio;
688 painter->drawLine(src_x, src_y, dst_x, dst_y);
689 }
690 }
691
692 /**************************************************************************
693 Scales point from real overview coords to scaled overview coords.
694 **************************************************************************/
scale_point(int & x,int & y)695 void minimap_view::scale_point(int &x, int &y)
696 {
697 int ax, bx;
698 int dx, dy;
699
700 gui_to_overview(&ax, &bx, mapview.gui_x0 + mapview.width / 2,
701 mapview.gui_y0 + mapview.height / 2);
702 x = qRound(x * scale_factor);
703 y = qRound(y * scale_factor);
704 dx = qRound(ax * scale_factor - gui_options.overview.width / 2);
705 dy = qRound(bx * scale_factor - gui_options.overview.height / 2);
706 x = x - dx;
707 y = y - dy;
708
709 }
710
711 /**************************************************************************
712 Scales point from scaled overview coords to real overview coords.
713 **************************************************************************/
unscale_point(double scale_factor,int & x,int & y)714 void unscale_point(double scale_factor, int &x, int &y)
715 {
716 int ax, bx;
717 int dx, dy;
718
719 gui_to_overview(&ax, &bx, mapview.gui_x0 + mapview.width / 2,
720 mapview.gui_y0 + mapview.height / 2);
721 dx = qRound(ax * scale_factor - gui_options.overview.width / 2);
722 dy = qRound(bx * scale_factor - gui_options.overview.height / 2);
723 x = x + dx;
724 y = y + dy;
725 x = qRound(x / scale_factor);
726 y = qRound(y / scale_factor);
727
728 }
729
730 /**************************************************************************
731 Sets minimap scale to default
732 **************************************************************************/
reset()733 void minimap_view::reset()
734 {
735 scale_factor = 1;
736 }
737
738 /**************************************************************************
739 Slot for updating pixmap from thread's image
740 **************************************************************************/
update_pixmap(const QImage & image)741 void minimap_view::update_pixmap(const QImage &image)
742 {
743 *pix = QPixmap::fromImage(image);
744 update();
745 }
746
747 /**************************************************************************
748 Minimap thread's contructor
749 **************************************************************************/
minimap_thread(QObject * parent)750 minimap_thread::minimap_thread(QObject *parent) : QThread(parent)
751 {
752 }
753
754 /**************************************************************************
755 Minimap thread's desctructor
756 **************************************************************************/
~minimap_thread()757 minimap_thread::~minimap_thread()
758 {
759 wait();
760 }
761
762 /**************************************************************************
763 Starts thread
764 **************************************************************************/
render(double scale_factor,int width,int height)765 void minimap_thread::render(double scale_factor, int width, int height)
766 {
767 QMutexLocker locker(&mutex);
768 mini_width = width;
769 mini_height = height;
770 scale = scale_factor;
771 start(LowPriority);
772 }
773
774 /**************************************************************************
775 Updates minimap's iamge in thread
776 **************************************************************************/
run()777 void minimap_thread::run()
778 {
779 QImage tpix;
780 QImage gpix;
781 QImage image(QSize(mini_width, mini_height), QImage::Format_RGB32);
782 QImage bigger_pix(gui_options.overview.width * 2,
783 gui_options.overview.height * 2, QImage::Format_RGB32);
784 int delta_x, delta_y;
785 int x, y, ix, iy;
786 float wf, hf;
787 QPixmap *src, *dst;
788
789 mutex.lock();
790 if (gui_options.overview.map != nullptr) {
791 if (scale > 1) {
792 /* move minimap now,
793 scale later and draw without looking for origin */
794 src = &gui_options.overview.map->map_pixmap;
795 dst = &gui_options.overview.window->map_pixmap;
796 x = gui_options.overview.map_x0;
797 y = gui_options.overview.map_y0;
798 ix = gui_options.overview.width - x;
799 iy = gui_options.overview.height - y;
800 pixmap_copy(dst, src, 0, 0, ix, iy, x, y);
801 pixmap_copy(dst, src, 0, y, ix, 0, x, iy);
802 pixmap_copy(dst, src, x, 0, 0, iy, ix, y);
803 pixmap_copy(dst, src, x, y, 0, 0, ix, iy);
804 tpix = gui_options.overview.window->map_pixmap.toImage();
805 wf = static_cast <float>(gui_options.overview.width) / scale;
806 hf = static_cast <float>(gui_options.overview.height) / scale;
807 x = 0;
808 y = 0;
809 unscale_point(scale, x, y);
810 bigger_pix.fill(Qt::black);
811 delta_x = gui_options.overview.width / 2;
812 delta_y = gui_options.overview.height / 2;
813 image_copy(&bigger_pix, &tpix, 0, 0, delta_x, delta_y,
814 gui_options.overview.width, gui_options.overview.height);
815 gpix = bigger_pix.copy(delta_x + x, delta_y + y, wf, hf);
816 image = gpix.scaled(mini_width, mini_height,
817 Qt::IgnoreAspectRatio, Qt::FastTransformation);
818 } else {
819 tpix = gui_options.overview.map->map_pixmap.toImage();
820 image = tpix.scaled(mini_width, mini_height,
821 Qt::IgnoreAspectRatio, Qt::FastTransformation);
822 }
823 }
824 emit rendered_image(image);
825 mutex.unlock();
826 }
827
828 /**************************************************************************
829 Updates minimap's pixmap
830 **************************************************************************/
update_image()831 void minimap_view::update_image()
832 {
833 if (isHidden()) {
834 return;
835 }
836 thread.render(scale_factor, width(), height());
837 }
838
839 /**************************************************************************
840 Redraws visible map using stored pixmap
841 **************************************************************************/
paint(QPainter * painter,QPaintEvent * event)842 void minimap_view::paint(QPainter * painter, QPaintEvent * event)
843 {
844 int x, y, ix, iy;
845
846 x = gui_options.overview.map_x0 * w_ratio;
847 y = gui_options.overview.map_y0 * h_ratio;
848 ix = pix->width() - x;
849 iy = pix->height() - y;
850
851 if (scale_factor > 1) {
852 painter->drawPixmap(0, 0, *pix, 0, 0, pix->width(), pix->height());
853 } else {
854 painter->drawPixmap(ix, iy, *pix, 0, 0, x, y);
855 painter->drawPixmap(ix, 0, *pix, 0, y, x, iy);
856 painter->drawPixmap(0, iy, *pix, x, 0, ix, y);
857 painter->drawPixmap(0, 0, *pix, x, y, ix, iy);
858 }
859 painter->setPen(QColor(palette().color(QPalette::Highlight)));
860 painter->drawRect(0, 0, width() - 1, height() - 1);
861 draw_viewport(painter);
862 rw->put_to_corner();
863 }
864
865 /****************************************************************************
866 Called when minimap has been resized
867 ****************************************************************************/
resizeEvent(QResizeEvent * event)868 void minimap_view::resizeEvent(QResizeEvent* event)
869 {
870 QSize size;
871 size = event->size();
872
873 if (C_S_RUNNING <= client_state() && size.width() > 0
874 && size.height() > 0) {
875 w_ratio = static_cast<float>(width()) / gui_options.overview.width;
876 h_ratio = static_cast<float>(height()) / gui_options.overview.height;
877 gui()->qt_settings.minimap_width = static_cast<float>(size.width())
878 / mapview.width;
879 gui()->qt_settings.minimap_height = static_cast<float>(size.height())
880 / mapview.height;
881 }
882 update_image();
883 }
884
885 /****************************************************************************
886 Wheel event for minimap - zooms it in or out
887 ****************************************************************************/
wheelEvent(QWheelEvent * event)888 void minimap_view::wheelEvent(QWheelEvent * event)
889 {
890 if (event->delta() > 0) {
891 zoom_in();
892 } else {
893 zoom_out();
894 }
895 event->accept();
896 }
897
898 /****************************************************************************
899 Sets scale factor to scale minimap 20% up
900 ****************************************************************************/
zoom_in()901 void minimap_view::zoom_in()
902 {
903 if (scale_factor < gui_options.overview.width / 8) {
904 scale(1.2);
905 }
906 }
907
908 /****************************************************************************
909 Sets scale factor to scale minimap 20% down
910 ****************************************************************************/
zoom_out()911 void minimap_view::zoom_out()
912 {
913 scale(0.833);
914 }
915
916 /**************************************************************************
917 Mouse Handler for minimap_view
918 Left button - moves minimap
919 Right button - recenters on some point
920 For wheel look mouseWheelEvent
921 **************************************************************************/
mousePressEvent(QMouseEvent * event)922 void minimap_view::mousePressEvent(QMouseEvent * event)
923 {
924 int fx, fy;
925 int x, y;
926
927 if (event->button() == Qt::LeftButton) {
928 if (gui()->interface_locked) {
929 return;
930 }
931 cursor = event->globalPos() - geometry().topLeft();
932 }
933 if (event->button() == Qt::RightButton) {
934 cursor = event->pos();
935 fx = event->pos().x();
936 fy = event->pos().y();
937 fx = qRound(fx / w_ratio);
938 fy = qRound(fy / h_ratio);
939 if (scale_factor > 1) {
940 unscale_point(scale_factor, fx, fy);
941 }
942 fx = qMax(fx, 1);
943 fy = qMax(fy, 1);
944 fx = qMin(fx, gui_options.overview.width - 1);
945 fy = qMin(fy, gui_options.overview.height - 1);
946 overview_to_map_pos(&x, &y, fx, fy);
947 center_tile_mapcanvas(map_pos_to_tile(x, y));
948 update_image();
949 }
950 event->setAccepted(true);
951 }
952
953 /**************************************************************************
954 Called when mouse button was pressed. Used to moving minimap.
955 **************************************************************************/
mouseMoveEvent(QMouseEvent * event)956 void minimap_view::mouseMoveEvent(QMouseEvent* event)
957 {
958 if (gui()->interface_locked) {
959 return;
960 }
961 if (event->buttons() & Qt::LeftButton) {
962 QPoint p, r;
963 p = event->pos();
964 r = mapTo(gui()->mapview_wdg, p);
965 p = r - p;
966 move(event->globalPos() - cursor);
967 setCursor(Qt::SizeAllCursor);
968 gui()->qt_settings.minimap_x = static_cast<float>(p.x()) / mapview.width;
969 gui()->qt_settings.minimap_y = static_cast<float>(p.y())
970 / mapview.height;
971 }
972 }
973
974 /**************************************************************************
975 Called when mouse button unpressed. Restores cursor.
976 **************************************************************************/
mouseReleaseEvent(QMouseEvent * event)977 void minimap_view::mouseReleaseEvent(QMouseEvent* event)
978 {
979 setCursor(Qt::CrossCursor);
980 }
981
982
983 /****************************************************************************
984 Typically an info box is provided to tell the player about the state
985 of their civilization. This function is called when the label is
986 changed.
987 ****************************************************************************/
update_info_label(void)988 void update_info_label(void)
989 {
990 gui()->update_info_label();
991 }
992
993
994 /****************************************************************************
995 Real update, updates only once per 300 ms.
996 ****************************************************************************/
update_info_label(void)997 void fc_client::update_info_label(void)
998 {
999 QString s, eco_info;
1000
1001 if (current_page() != PAGE_GAME) {
1002 return;
1003 }
1004 if (update_info_timer == nullptr) {
1005 update_info_timer = new QTimer();
1006 update_info_timer->setSingleShot(true);
1007 connect(update_info_timer, &QTimer::timeout,
1008 this, &fc_client::update_info_label);
1009 update_info_timer->start(300);
1010 return;
1011 }
1012
1013 if (update_info_timer->remainingTime() > 0) {
1014 return;
1015 }
1016 update_sidebar_tooltips();
1017 if (head_of_units_in_focus() != nullptr) {
1018 real_menus_update();
1019 }
1020 /* TRANS: T is shortcut from Turn */
1021 s = QString(_("%1 \nT:%2")).arg(calendar_text(),
1022 QString::number(game.info.turn));
1023
1024 sw_map->set_custom_labels(s);
1025 sw_map->update_final_pixmap();
1026
1027 set_indicator_icons(client_research_sprite(),
1028 client_warming_sprite(),
1029 client_cooling_sprite(), client_government_sprite());
1030
1031 if (client.conn.playing != NULL) {
1032 if (player_get_expected_income(client.conn.playing) > 0) {
1033 eco_info = QString(_("%1 (+%2)"))
1034 .arg(QString::number(client.conn.playing->economic.gold),
1035 QString::number(player_get_expected_income(client.conn.playing)));
1036 } else {
1037 eco_info = QString(_("%1 (%2)"))
1038 .arg(QString::number(client.conn.playing->economic.gold),
1039 QString::number(player_get_expected_income(client.conn.playing)));
1040 }
1041 sw_economy->set_custom_labels(eco_info);
1042 } else {
1043 sw_economy->set_custom_labels("");
1044 }
1045 sw_tax->update_final_pixmap();
1046 sw_economy->update_final_pixmap();
1047 delete update_info_timer;
1048 update_info_timer = nullptr;
1049 }
1050
1051
1052 /****************************************************************************
1053 Update the information label which gives info on the current unit
1054 and the tile under the current unit, for specified unit. Note that
1055 in practice punit is always the focus unit.
1056
1057 Clears label if punit is NULL.
1058
1059 Typically also updates the cursor for the map_canvas (this is
1060 related because the info label may includes "select destination"
1061 prompt etc). And it may call update_unit_pix_label() to update the
1062 icons for units on this tile.
1063 ****************************************************************************/
update_unit_info_label(struct unit_list * punitlist)1064 void update_unit_info_label(struct unit_list *punitlist)
1065 {
1066 if (gui()->unitinfo_wdg->isVisible()) {
1067 gui()->unitinfo_wdg->update_actions(nullptr);
1068 }
1069 }
1070
1071
1072 /****************************************************************************
1073 Update the mouse cursor. Cursor type depends on what user is doing and
1074 pointing.
1075 ****************************************************************************/
update_mouse_cursor(enum cursor_type new_cursor_type)1076 void update_mouse_cursor(enum cursor_type new_cursor_type)
1077 {
1078 gui()->mapview_wdg->update_cursor(new_cursor_type);
1079 }
1080
1081 /****************************************************************************
1082 Update the timeout display. The timeout is the time until the turn
1083 ends, in seconds.
1084 ****************************************************************************/
qtg_update_timeout_label(void)1085 void qtg_update_timeout_label(void)
1086 {
1087 gui()->sw_endturn->set_custom_labels(QString(get_timeout_label_text()));
1088 gui()->sw_endturn->update_final_pixmap();
1089 }
1090
1091 /****************************************************************************
1092 If do_restore is false it should change the turn button style (to
1093 draw the user's attention to it). If called regularly from a timer
1094 this will give a blinking turn done button. If do_restore is true
1095 this should reset the turn done button to the default style.
1096 ****************************************************************************/
update_turn_done_button(bool do_restore)1097 void update_turn_done_button(bool do_restore)
1098 {
1099 if (!get_turn_done_button_state()) {
1100 return;
1101 }
1102 side_blink_endturn(do_restore);
1103
1104 }
1105
1106
1107 /****************************************************************************
1108 Set information for the indicator icons typically shown in the main
1109 client window. The parameters tell which sprite to use for the
1110 indicator.
1111 ****************************************************************************/
set_indicator_icons(struct sprite * bulb,struct sprite * sol,struct sprite * flake,struct sprite * gov)1112 void set_indicator_icons(struct sprite *bulb, struct sprite *sol,
1113 struct sprite *flake, struct sprite *gov)
1114 {
1115 gui()->sw_indicators->update_final_pixmap();
1116 }
1117
1118 /****************************************************************************
1119 Return a canvas that is the overview window.
1120 ****************************************************************************/
get_overview_window(void)1121 struct canvas *get_overview_window(void)
1122 {
1123 gui()->minimapview_wdg->update_image();
1124 return NULL;
1125 }
1126
1127 /****************************************************************************
1128 Flush the given part of the canvas buffer (if there is one) to the
1129 screen.
1130 ****************************************************************************/
flush_mapcanvas(int canvas_x,int canvas_y,int pixel_width,int pixel_height)1131 void flush_mapcanvas(int canvas_x, int canvas_y,
1132 int pixel_width, int pixel_height)
1133 {
1134 gui()->mapview_wdg->repaint(canvas_x, canvas_y, pixel_width, pixel_height);
1135 }
1136
1137 /****************************************************************************
1138 Mark the rectangular region as "dirty" so that we know to flush it
1139 later.
1140 ****************************************************************************/
dirty_rect(int canvas_x,int canvas_y,int pixel_width,int pixel_height)1141 void dirty_rect(int canvas_x, int canvas_y,
1142 int pixel_width, int pixel_height)
1143 {
1144 if (mapview_is_frozen()) {
1145 return;
1146 }
1147 if (num_dirty_rects < MAX_DIRTY_RECTS) {
1148 dirty_rects[num_dirty_rects].setX(canvas_x);
1149 dirty_rects[num_dirty_rects].setY(canvas_y);
1150 dirty_rects[num_dirty_rects].setWidth(pixel_width);
1151 dirty_rects[num_dirty_rects].setHeight(pixel_height);
1152 num_dirty_rects++;
1153 }
1154 }
1155
1156 /****************************************************************************
1157 Mark the entire screen area as "dirty" so that we can flush it later.
1158 ****************************************************************************/
dirty_all(void)1159 void dirty_all(void)
1160 {
1161 if (mapview_is_frozen()) {
1162 return;
1163 }
1164 num_dirty_rects = MAX_DIRTY_RECTS;
1165 }
1166
1167 /****************************************************************************
1168 Flush all regions that have been previously marked as dirty. See
1169 dirty_rect and dirty_all. This function is generally called after we've
1170 processed a batch of drawing operations.
1171 ****************************************************************************/
flush_dirty(void)1172 void flush_dirty(void)
1173 {
1174 if (mapview_is_frozen()) {
1175 return;
1176 }
1177 if (num_dirty_rects == MAX_DIRTY_RECTS) {
1178 flush_mapcanvas(0, 0, gui()->mapview_wdg->width(),
1179 gui()->mapview_wdg->height());
1180 } else {
1181 int i;
1182 for (i = 0; i < num_dirty_rects; i++) {
1183 flush_mapcanvas(dirty_rects[i].x(), dirty_rects[i].y(),
1184 dirty_rects[i].width(), dirty_rects[i].height());
1185 }
1186 }
1187 num_dirty_rects = 0;
1188 }
1189
1190 /****************************************************************************
1191 Do any necessary synchronization to make sure the screen is up-to-date.
1192 The canvas should have already been flushed to screen via flush_dirty -
1193 all this function does is make sure the hardware has caught up.
1194 ****************************************************************************/
gui_flush(void)1195 void gui_flush(void)
1196 {
1197 gui()->mapview_wdg->update();
1198 }
1199
1200 /****************************************************************************
1201 Update (refresh) the locations of the mapview scrollbars (if it uses
1202 them).
1203 ****************************************************************************/
update_map_canvas_scrollbars(void)1204 void update_map_canvas_scrollbars(void)
1205 {
1206 gui()->mapview_wdg->update();
1207 }
1208
1209 /****************************************************************************
1210 Update the size of the sliders on the scrollbars.
1211 ****************************************************************************/
update_map_canvas_scrollbars_size(void)1212 void update_map_canvas_scrollbars_size(void)
1213 {
1214 /* PORTME */
1215 }
1216
1217 /****************************************************************************
1218 Update (refresh) all city descriptions on the mapview.
1219 ****************************************************************************/
update_city_descriptions(void)1220 void update_city_descriptions(void)
1221 {
1222 update_map_canvas_visible();
1223 }
1224
1225 /**************************************************************************
1226 Put overlay tile to pixmap
1227 **************************************************************************/
pixmap_put_overlay_tile(int canvas_x,int canvas_y,struct sprite * ssprite)1228 void pixmap_put_overlay_tile(int canvas_x, int canvas_y,
1229 struct sprite *ssprite)
1230 {
1231 if (!ssprite) {
1232 return;
1233 }
1234
1235 /* PORTME */
1236 }
1237
1238 /****************************************************************************
1239 Draw a cross-hair overlay on a tile.
1240 ****************************************************************************/
put_cross_overlay_tile(struct tile * ptile)1241 void put_cross_overlay_tile(struct tile *ptile)
1242 {
1243 float canvas_x, canvas_y;
1244
1245 if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
1246 pixmap_put_overlay_tile(canvas_x, canvas_y,
1247 get_attention_crosshair_sprite(tileset));
1248 }
1249
1250 }
1251
1252 /****************************************************************************
1253 Area Selection
1254 ****************************************************************************/
draw_selection_rectangle(int canvas_x,int canvas_y,int w,int h)1255 void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
1256 {
1257 /* PORTME */
1258 }
1259
1260 /****************************************************************************
1261 This function is called when the tileset is changed.
1262 ****************************************************************************/
tileset_changed(void)1263 void tileset_changed(void)
1264 {
1265 int i;
1266 science_report *sci_rep;
1267 QWidget *w;
1268
1269 update_unit_info_label(get_units_in_focus());
1270 destroy_city_dialog();
1271 /* Update science report if open */
1272 if (gui()->is_repo_dlg_open("SCI")) {
1273 i = gui()->gimme_index_of("SCI");
1274 fc_assert(i != -1);
1275 w = gui()->game_tab_widget->widget(i);
1276 sci_rep = reinterpret_cast<science_report*>(w);
1277 sci_rep->reset_tree();
1278 sci_rep->update_report();
1279 sci_rep->repaint();
1280 }
1281 }
1282
1283 /****************************************************************************
1284 Return the dimensions of the area (container widget; maximum size) for
1285 the overview.
1286 ****************************************************************************/
get_overview_area_dimensions(int * width,int * height)1287 void get_overview_area_dimensions(int *width, int *height)
1288 {
1289 *width = 0;
1290 *height = 0;
1291 }
1292
1293 /****************************************************************************
1294 Called when the map size changes. This may be used to change the
1295 size of the GUI element holding the overview canvas. The
1296 overview.width and overview.height are updated if this function is
1297 called.
1298 It's used for first creation of overview only, later overview stays the
1299 same size, scaled by qt-specific function.
1300 ****************************************************************************/
overview_size_changed(void)1301 void overview_size_changed(void)
1302 {
1303 gui()->minimapview_wdg->resize(0, 0);
1304 gui()->minimapview_wdg->move(gui()->qt_settings.minimap_x
1305 * mapview.width,
1306 gui()->qt_settings.minimap_y
1307 * mapview.height);
1308 gui()->minimapview_wdg->resize(gui()->qt_settings.minimap_width
1309 * mapview.width,
1310 gui()->qt_settings.minimap_height
1311 * mapview.height);
1312 }
1313
1314 /**************************************************************************
1315 Sets the position of the overview scroll window based on mapview position.
1316 **************************************************************************/
update_overview_scroll_window_pos(int x,int y)1317 void update_overview_scroll_window_pos(int x, int y)
1318 {
1319 /* TODO: PORTME. */
1320 }
1321
1322
1323 /****************************************************************************
1324 Return whether the map should be drawn or not.
1325 ****************************************************************************/
mapview_is_frozen(void)1326 bool mapview_is_frozen(void)
1327 {
1328 return (0 < mapview_frozen_level);
1329 }
1330
1331
1332 /****************************************************************************
1333 Freeze the drawing of the map.
1334 ****************************************************************************/
mapview_freeze(void)1335 void mapview_freeze(void)
1336 {
1337 mapview_frozen_level++;
1338 }
1339
1340 /****************************************************************************
1341 Thaw the drawing of the map.
1342 ****************************************************************************/
mapview_thaw(void)1343 void mapview_thaw(void)
1344 {
1345 if (1 < mapview_frozen_level) {
1346 mapview_frozen_level--;
1347 } else {
1348 fc_assert(0 < mapview_frozen_level);
1349 mapview_frozen_level = 0;
1350 dirty_all();
1351 }
1352 }
1353
1354 /**************************************************************************
1355 Constructor for info_tile
1356 **************************************************************************/
info_tile(struct tile * ptile,QWidget * parent)1357 info_tile::info_tile(struct tile *ptile, QWidget *parent): QLabel(parent)
1358 {
1359 setParent(parent);
1360 info_font = *fc_font::instance()->get_font(fonts::comment_label);
1361 itile = ptile;
1362 calc_size();
1363 }
1364
1365 /**************************************************************************
1366 Calculates size of info_tile and moves it to be fully visible
1367 **************************************************************************/
calc_size()1368 void info_tile::calc_size()
1369 {
1370 QFontMetrics fm(info_font);
1371 QString str;
1372 int hh = tileset_tile_height(tileset);
1373 int fin_x;
1374 int fin_y;
1375 float x, y;
1376 int w = 0;
1377
1378 str = popup_info_text(itile);
1379 str_list = str.split("\n");
1380
1381 foreach(str, str_list) {
1382 w = qMax(w, fm.horizontalAdvance(str));
1383 }
1384 setFixedHeight(str_list.count() * (fm.height() + 5));
1385 setFixedWidth(w + 10);
1386 if (tile_to_canvas_pos(&x, &y, itile)) {
1387 fin_x = x;
1388 fin_y = y;
1389 if (y - height() > 0) {
1390 fin_y = y - height();
1391 } else {
1392 fin_y = y + hh;
1393 }
1394 if (x + width() > parentWidget()->width()) {
1395 fin_x = parentWidget()->width() - width();
1396 }
1397 move(fin_x, fin_y);
1398 }
1399 }
1400
1401 /**************************************************************************
1402 Redirected paint event for info_tile
1403 **************************************************************************/
paint(QPainter * painter,QPaintEvent * event)1404 void info_tile::paint(QPainter *painter, QPaintEvent *event)
1405 {
1406 QFontMetrics fm(info_font);
1407 int pos, h;
1408
1409 h = fm.height();
1410 pos = h;
1411 painter->setFont(info_font);
1412 for (int i = 0; i < str_list.count(); i++) {
1413 painter->drawText(5, pos, str_list.at(i));
1414 pos = pos + 5 + h;
1415 }
1416 }
1417
1418 /**************************************************************************
1419 Paint event for info_tile
1420 **************************************************************************/
paintEvent(QPaintEvent * event)1421 void info_tile::paintEvent(QPaintEvent *event)
1422 {
1423 QPainter painter;
1424
1425 painter.begin(this);
1426 paint(&painter, event);
1427 painter.end();
1428 }
1429
1430 /**************************************************************************
1431 Updates fonts
1432 **************************************************************************/
update_font(const QString & name,const QFont & font)1433 void info_tile::update_font(const QString &name, const QFont &font)
1434 {
1435 if (name == fonts::comment_label) {
1436 info_font = font;
1437 calc_size();
1438 update();
1439 }
1440 }
1441
1442 /**************************************************************************
1443 New turn callback
1444 **************************************************************************/
qtg_start_turn()1445 void qtg_start_turn()
1446 {
1447 gui()->rallies.run();
1448 show_new_turn_info();
1449 last_center_enemy = 0;
1450 last_center_capital = 0;
1451 last_center_player_city = 0;
1452 last_center_enemy_city = 0;
1453 }
1454