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