Some miscellaneous updates to main help, for new features and otherwise.
[freeciv.git] / client / gui-qt / mapview.cpp
blob0e136c669be2f1b404408a59b5d3c6bee7fe2ea8
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 // Qt
19 #include <QToolTip>
21 // utility
22 #include "support.h"
24 // common
25 #include "game.h"
27 // client
28 #include "climisc.h"
29 #include "mapctrl_common.h"
30 #include "overview_common.h"
31 #include "sprite.h"
32 #include "text.h"
34 // qui-qt
35 #include "qtg_cxxside.h"
36 #include "mapview.h"
38 const char*get_timeout_label_text();
39 static int mapview_frozen_level = 0;
40 extern void destroy_city_dialog();
41 extern struct canvas *canvas;
42 extern QApplication *qapp;
44 #define MAX_DIRTY_RECTS 20
45 static int num_dirty_rects = 0;
46 static QRect dirty_rects[MAX_DIRTY_RECTS];
48 /**************************************************************************
49 Check if point x, y is in area (px -> pxe, py - pye)
50 **************************************************************************/
51 bool is_point_in_area(int x, int y, int px, int py, int pxe, int pye)
53 if (x >= px && y >= py && x <= pxe && y <= pye) {
54 return true;
56 return false;
60 /**************************************************************************
61 Constructor for idle callbacks
62 **************************************************************************/
63 mr_idle::mr_idle()
65 connect(&timer, SIGNAL(timeout()), this, SLOT(idling()));
66 /*if there would be messages in
67 *that queue is big we may want to decrease it*/
68 timer.start(50);
71 /**************************************************************************
72 slot used to execute 1 callback from callabcks stored in idle list
73 **************************************************************************/
74 void mr_idle::idling()
76 call_me_back* cb = new call_me_back;
78 while (!callback_list.isEmpty()) {
79 cb = callback_list.dequeue();
80 (cb->callback) (cb->data);
81 delete cb;
85 /**************************************************************************
86 Adds one callback to execute later
87 **************************************************************************/
88 void mr_idle::add_callback(call_me_back* cb)
90 callback_list.enqueue(cb);
93 /**************************************************************************
94 Constructor for map
95 **************************************************************************/
96 map_view::map_view() : QWidget()
98 setMouseTracking(true);
101 /**************************************************************************
102 slot inherited from QPixamp
103 **************************************************************************/
104 void map_view::paintEvent(QPaintEvent *event)
106 QPainter painter;
108 painter.begin(this);
109 paint(&painter, event);
110 painter.end();
113 /**************************************************************************
114 Redraws visible map
115 **************************************************************************/
116 void map_view::paint(QPainter *painter, QPaintEvent *event)
118 int width = mapview.store->map_pixmap.width();
119 int height = mapview.store->map_pixmap.height();
121 painter->drawPixmap(0, 0, width, height, mapview.store->map_pixmap);
124 /**************************************************************************
125 Sets new point for new search
126 **************************************************************************/
127 void map_view::resume_searching(int pos_x ,int pos_y ,int &w, int &h,
128 int wdth, int hght, int recursive_nr)
130 int new_pos_x, new_pos_y;
132 recursive_nr++;
133 new_pos_x = pos_x;
134 new_pos_y = pos_y;
136 if (pos_y + hght + 4 < height() && pos_x > width() / 2) {
137 new_pos_y = pos_y + 5;
138 } else if (pos_x > 0 && pos_y > 10) {
139 new_pos_x = pos_x - 5;
140 } else if (pos_y > 0) {
141 new_pos_y = pos_y - 5;
142 } else if (pos_x + wdth + 4 < this->width()) {
143 new_pos_x = pos_x + 5;
145 find_place(new_pos_x, new_pos_y, w, h, wdth, hght, recursive_nr);
148 /**************************************************************************
149 Searches place for widget with size w and height h
150 Starts looking from position pos_x, pos_y, going clockwork
151 Returns position as (w,h)
152 Along with resume_searching its recursive function.
153 **************************************************************************/
154 void map_view::find_place(int pos_x, int pos_y, int &w, int &h, int wdth,
155 int hght, int recursive_nr)
157 int i;
158 int x, y, xe, ye;
159 QList <fcwidget *>widgets = this->findChildren <fcwidget *>();
160 bool cont_searching = false;
162 if (recursive_nr >= 1000) {
164 * give up searching position
166 return;
169 * try position pos_x, pos_y,
170 * check middle and borders if aren't above other widget
172 for (i = 0; i < widgets.count(); i++) {
173 if (widgets[i]->was_destroyed == true) {
174 continue;
176 x = widgets[i]->pos().x();
177 y = widgets[i]->pos().y();
178 if (x == 0 && y ==0) {
179 continue;
181 xe = widgets[i]->pos().x() + widgets[i]->width();
182 ye = widgets[i]->pos().y() + widgets[i]->height();
184 if (is_point_in_area(pos_x, pos_y, x, y, xe, ye)) {
185 cont_searching = true;
187 if (is_point_in_area(pos_x + wdth, pos_y, x, y, xe, ye)) {
188 cont_searching = true;
190 if (is_point_in_area(pos_x + wdth, pos_y + hght, x, y, xe, ye)) {
191 cont_searching = true;
193 if (is_point_in_area(pos_x, pos_y + hght, x, y, xe, ye)) {
194 cont_searching = true;
196 if (is_point_in_area(pos_x + wdth / 2, pos_y + hght / 2, x, y, xe, ye)) {
197 cont_searching = true;
200 w = pos_x;
201 h = pos_y;
202 if (cont_searching) {
203 resume_searching(pos_x, pos_y, w, h, wdth, hght, recursive_nr);
208 /****************************************************************************
209 Called when map view has been resized
210 ****************************************************************************/
211 void map_view::resizeEvent(QResizeEvent* event)
213 QSize size;
215 size = event->size();
217 if (C_S_RUNNING == client_state()) {
218 map_canvas_resized(size.width(), size.height());
219 gui()->unitinfo_wdg->move(0,size.height()-gui()->unitinfo_wdg->height());
220 gui()->game_info_label->move(size.width()
221 -gui()->game_info_label->width(),
222 size.height()
223 -gui()->game_info_label->height());
227 /****************************************************************************
228 Constructor for resize widget
229 ****************************************************************************/
230 resize_widget::resize_widget(QWidget *parent) : QLabel()
232 setParent(parent);
233 setCursor(Qt::SizeFDiagCursor);
234 setPixmap(QPixmap(resize_button));
237 /****************************************************************************
238 Puts resize widget to right bottom corner
239 ****************************************************************************/
240 void resize_widget::put_to_corner()
242 move(parentWidget()->width() - width(),
243 parentWidget()->height() - height());
246 /****************************************************************************
247 Mouse handler for resize widget (resizes parent widget)
248 ****************************************************************************/
249 void resize_widget::mouseMoveEvent(QMouseEvent * event)
251 QPoint qp, np;
253 qp = event->globalPos();
254 np.setX(qp.x() - point.x());
255 np.setY(qp.y() - point.y());
256 np.setX(qMax(np.x(), 32));
257 np.setY(qMax(np.y(), 32));
258 parentWidget()->resize(np.x(), np.y());
261 /****************************************************************************
262 Sets moving point for resize widget;
263 ****************************************************************************/
264 void resize_widget::mousePressEvent(QMouseEvent* event)
266 QPoint qp;
268 qp = event->globalPos();
269 point.setX(qp.x() - parentWidget()->width());
270 point.setY(qp.y() - parentWidget()->height());
271 update();
274 /****************************************************************************
275 Constructor for close widget
276 ****************************************************************************/
277 close_widget::close_widget(QWidget *parent) : QLabel()
279 setParent(parent);
280 setCursor(Qt::ArrowCursor);
281 setPixmap(QPixmap(close_button));
284 /****************************************************************************
285 Puts close widget to right top corner
286 ****************************************************************************/
287 void close_widget::put_to_corner()
289 move(parentWidget()->width()-width(), 0);
292 /****************************************************************************
293 Mouse handler for close widget, hides parent widget
294 ****************************************************************************/
295 void close_widget::mousePressEvent(QMouseEvent* event)
297 if (event->button() == Qt::LeftButton) {
298 parentWidget()->hide();
299 notify_parent();
302 /****************************************************************************
303 Notifies parent to do custom action, parent is already hidden.
304 ****************************************************************************/
305 void close_widget::notify_parent()
307 fcwidget *fcw;
309 fcw = reinterpret_cast<fcwidget *>(parentWidget());
310 fcw->update_menu();
314 /**************************************************************************
315 Constructor for minimap
316 **************************************************************************/
317 minimap_view::minimap_view(QWidget *parent) : fcwidget()
319 setParent(parent);
320 setScaledContents(true);
321 w_ratio = 1.0;
322 h_ratio = 1.0;
323 move(4, 4);
324 background = QBrush(QColor (0, 0, 0));
325 setCursor(Qt::CrossCursor);
326 rw = new resize_widget(this);
327 rw->put_to_corner();
328 cw = new close_widget(this);
329 cw->put_to_corner();
330 pix = new QPixmap;
331 scale_factor = 1.0;
334 /**************************************************************************
335 Paint event for minimap
336 **************************************************************************/
337 void minimap_view::paintEvent(QPaintEvent *event)
339 QPainter painter;
341 painter.begin(this);
342 paint(&painter, event);
343 painter.end();
346 /**************************************************************************
347 Sets scaling factor for minimap
348 **************************************************************************/
349 void minimap_view::scale(double factor)
351 scale_factor *= factor;
352 if (scale_factor < 1) {
353 scale_factor = 1.0;
355 update_image();
358 /**************************************************************************
359 Converts gui to overview position.
360 **************************************************************************/
361 static void gui_to_overview(int *map_x, int *map_y, int gui_x, int gui_y)
363 const int W = tileset_tile_width(tileset);
364 const int H = tileset_tile_height(tileset);
365 const int HH = tileset_hex_height(tileset);
366 const int HW = tileset_hex_width(tileset);
367 int a, b;
369 if (HH > 0 || HW > 0) {
370 int x, y, dx, dy;
371 int xmult, ymult, mod, compar;
372 x = DIVIDE(gui_x, W);
373 y = DIVIDE(gui_y, H);
374 dx = gui_x - x * W;
375 dy = gui_y - y * H;
376 xmult = (dx >= W / 2) ? -1 : 1;
377 ymult = (dy >= H / 2) ? -1 : 1;
378 dx = (dx >= W / 2) ? (W - 1 - dx) : dx;
379 dy = (dy >= H / 2) ? (H - 1 - dy) : dy;
380 if (HW > 0) {
381 compar = (dx - HW / 2) * (H / 2) - (H / 2 - 1 - dy) * (W / 2 - HW);
382 } else {
383 compar = (dy - HH / 2) * (W / 2) - (W / 2 - 1 - dx) * (H / 2 - HH);
385 mod = (compar < 0) ? -1 : 0;
386 *map_x = (x + y) + mod * (xmult + ymult) / 2;
387 *map_y = (y - x) + mod * (ymult - xmult) / 2;
388 } else if (tileset_is_isometric(tileset)) {
389 gui_x -= W / 2;
390 *map_x = DIVIDE(gui_x * H + gui_y * W, W * H);
391 *map_y = DIVIDE(gui_y * W - gui_x * H, W * H);
392 } else {
393 *map_x = DIVIDE(gui_x, W);
394 *map_y = DIVIDE(gui_y, H);
396 a = *map_x;
397 b = *map_y;
398 map_to_overview_pos(map_x, map_y, a, b);
399 *map_x = *map_x + 1;
400 *map_y = *map_y + 1;
403 /**************************************************************************
404 Called by close widget, cause widget has been hidden. Updates menu.
405 **************************************************************************/
406 void minimap_view::update_menu()
408 ::gui()->menu_bar->minimap_status->setChecked(false);
411 /**************************************************************************
412 Minimap is being moved, position is being remebered
413 **************************************************************************/
414 void minimap_view::moveEvent(QMoveEvent* event)
416 position = event->pos();
419 /**************************************************************************
420 Minimap is just unhidden, old position is restored
421 **************************************************************************/
422 void minimap_view::showEvent(QShowEvent* event)
424 move(position);
425 event->setAccepted(true);
428 /**************************************************************************
429 Draws viewport on minimap
430 **************************************************************************/
431 void minimap_view::draw_viewport(QPainter *painter)
433 int i, x[4], y[4];
434 int src_x, src_y, dst_x, dst_y;
436 if (!overview.map) {
437 return;
439 gui_to_overview(&x[0], &y[0], mapview.gui_x0, mapview.gui_y0);
440 gui_to_overview(&x[1], &y[1], mapview.gui_x0 + mapview.width,
441 mapview.gui_y0);
442 gui_to_overview(&x[2], &y[2], mapview.gui_x0 + mapview.width,
443 mapview.gui_y0 + mapview.height);
444 gui_to_overview(&x[3], &y[3], mapview.gui_x0,
445 mapview.gui_y0 + mapview.height);
446 painter->setPen(QColor(Qt::white));
448 if (scale_factor > 1) {
449 for (i = 0; i < 4; i++) {
450 scale_point(x[i], y[i]);
454 for (i = 0; i < 4; i++) {
455 src_x = x[i] * w_ratio;
456 src_y = y[i] * h_ratio;
457 dst_x = x[(i + 1) % 4] * w_ratio;
458 dst_y = y[(i + 1) % 4] * h_ratio;
459 painter->drawLine(src_x, src_y, dst_x, dst_y);
463 /**************************************************************************
464 Scales point from real overview coords to scaled overview coords.
465 **************************************************************************/
466 void minimap_view::scale_point(int &x, int &y)
468 int ax, bx;
469 int dx, dy;
471 gui_to_overview(&ax, &bx, mapview.gui_x0 + mapview.width / 2,
472 mapview.gui_y0 + mapview.height / 2);
473 x = qRound(x * scale_factor);
474 y = qRound(y * scale_factor);
475 dx = qRound(ax * scale_factor - overview.width / 2);
476 dy = qRound(bx * scale_factor - overview.height / 2);
477 x = x - dx;
478 y = y - dy;
482 /**************************************************************************
483 Scales point from scaled overview coords to real overview coords.
484 **************************************************************************/
485 void minimap_view::unscale_point(int &x, int &y)
487 int ax, bx;
488 int dx, dy;
490 gui_to_overview(&ax, &bx, mapview.gui_x0 + mapview.width / 2,
491 mapview.gui_y0 + mapview.height / 2);
492 dx = qRound(ax * scale_factor - overview.width / 2);
493 dy = qRound(bx * scale_factor - overview.height / 2);
494 x = x + dx;
495 y = y + dy;
496 x = qRound(x / scale_factor);
497 y = qRound(y / scale_factor);
502 /**************************************************************************
503 Updates minimap's pixmap
504 **************************************************************************/
505 void minimap_view::update_image()
507 QPixmap *tpix;
508 QPixmap gpix;
509 QPixmap bigger_pix(overview.width * 2, overview.height * 2);
510 int delta_x, delta_y;
511 int x, y, ix, iy;
512 float wf, hf;
513 QPixmap *src, *dst;
515 if (isHidden() == true ){
516 return;
518 if (overview.map != NULL) {
519 if (scale_factor > 1) {
520 /* move minimap now,
521 scale later and draw without looking for origin */
522 src = &overview.map->map_pixmap;
523 dst = &overview.window->map_pixmap;
524 x = overview.map_x0;
525 y = overview.map_y0;
526 ix = overview.width - x;
527 iy = overview.height - y;
528 pixmap_copy(dst, src, 0, 0, ix, iy, x, y);
529 pixmap_copy(dst, src, 0, y, ix, 0, x, iy);
530 pixmap_copy(dst, src, x, 0, 0, iy, ix, y);
531 pixmap_copy(dst, src, x, y, 0, 0, ix, iy);
532 tpix = &overview.window->map_pixmap;
533 wf = static_cast <float>(overview.width) / scale_factor;
534 hf = static_cast <float>(overview.height) / scale_factor;
535 x = 0;
536 y = 0;
537 unscale_point(x, y);
538 /* qt 4.8 is going to copy pixmap badly if coords x+size, y+size
539 will go over image so we create extra black bigger image */
540 bigger_pix.fill(Qt::black);
541 delta_x = overview.width / 2;
542 delta_y = overview.height / 2;
543 pixmap_copy(&bigger_pix, tpix, 0, 0, delta_x, delta_y, overview.width,
544 overview.height);
545 gpix = bigger_pix.copy(delta_x + x, delta_y + y, wf, hf);
546 *pix = gpix.scaled(width(), height(),
547 Qt::IgnoreAspectRatio, Qt::FastTransformation);
548 } else {
549 tpix = &overview.map->map_pixmap;
550 *pix = tpix->scaled(width(), height(),
551 Qt::IgnoreAspectRatio, Qt::FastTransformation);
554 update();
557 /**************************************************************************
558 Redraws visible map using stored pixmap
559 **************************************************************************/
560 void minimap_view::paint(QPainter * painter, QPaintEvent * event)
562 int x, y, ix, iy;
564 x = overview.map_x0 * w_ratio;
565 y = overview.map_y0 * h_ratio;
566 ix = pix->width() - x;
567 iy = pix->height() - y;
569 if (scale_factor > 1) {
570 painter->drawPixmap(0, 0, *pix, 0, 0, pix->width(), pix->height());
571 } else {
572 painter->drawPixmap(ix, iy, *pix, 0, 0, x, y);
573 painter->drawPixmap(ix, 0, *pix, 0, y, x, iy);
574 painter->drawPixmap(0, iy, *pix, x, 0, ix, y);
575 painter->drawPixmap(0, 0, *pix, x, y, ix, iy);
577 painter->setPen(QColor(Qt::yellow));
578 painter->setRenderHint(QPainter::Antialiasing);
579 painter->drawRect(0, 0, width() - 1, height() - 1);
580 draw_viewport(painter);
581 rw->put_to_corner();
582 cw->put_to_corner();
585 /****************************************************************************
586 Called when minimap has been resized
587 ****************************************************************************/
588 void minimap_view::resizeEvent(QResizeEvent* event)
590 QSize size;
591 size = event->size();
593 if (C_S_RUNNING == client_state()) {
594 w_ratio = static_cast<float>(width()) / overview.width;
595 h_ratio = static_cast<float>(height()) / overview.height;
597 update_image();
600 /****************************************************************************
601 Wheel event for minimap - zooms it in or out
602 ****************************************************************************/
603 void minimap_view::wheelEvent(QWheelEvent * event)
605 if (event->delta() > 0) {
606 zoom_in();
607 } else {
608 zoom_out();
610 event->accept();
613 /****************************************************************************
614 Sets scale factor to scale minimap 20% up
615 ****************************************************************************/
616 void minimap_view::zoom_in()
618 if (scale_factor < overview.width / 8) {
619 scale(1.2);
623 /****************************************************************************
624 Sets scale factor to scale minimap 20% down
625 ****************************************************************************/
626 void minimap_view::zoom_out()
628 scale(0.833);
631 /**************************************************************************
632 Mouse Handler for minimap_view
633 Left button - moves minimap
634 Right button - recenters on some point
635 For wheel look mouseWheelEvent
636 **************************************************************************/
637 void minimap_view::mousePressEvent(QMouseEvent * event)
639 int fx, fy;
640 int x, y;
642 if (event->button() == Qt::LeftButton) {
643 cursor = event->globalPos() - geometry().topLeft();
645 if (event->button() == Qt::RightButton) {
646 cursor = event->pos();
647 fx = event->pos().x();
648 fy = event->pos().y();
649 fx = qRound(fx / w_ratio);
650 fy = qRound(fy / h_ratio);
651 if (scale_factor > 1) {
652 unscale_point(fx, fy);
654 fx = qMax(fx, 1);
655 fy = qMax(fy, 1);
656 fx = qMin(fx, overview.width - 1);
657 fy = qMin(fy, overview.height - 1);
658 overview_to_map_pos(&x, &y, fx, fy);
659 center_tile_mapcanvas(map_pos_to_tile(x, y));
660 update_image();
662 event->setAccepted(true);
665 /**************************************************************************
666 Called when mouse button was pressed. Used to moving minimap.
667 **************************************************************************/
668 void minimap_view::mouseMoveEvent(QMouseEvent* event)
670 if (event->buttons() & Qt::LeftButton) {
671 move(event->globalPos() - cursor);
672 setCursor(Qt::SizeAllCursor);
676 /**************************************************************************
677 Called when mouse button unpressed. Restores cursor.
678 **************************************************************************/
679 void minimap_view::mouseReleaseEvent(QMouseEvent* event)
681 setCursor(Qt::CrossCursor);
685 /**************************************************************************
686 Constructor for information label
687 **************************************************************************/
688 info_label::info_label(QWidget *parent) : fcwidget()
690 setParent(parent);
691 indicator_icons = NULL;
692 rates_label = NULL;
693 setMouseTracking(true);
694 ufont = new QFont;
695 create_end_turn_pixmap();
696 highlight_end_button = true;
697 end_button_area.setWidth(0);
698 rates_area.setWidth(0);
699 indicator_area.setWidth(0);
702 /**************************************************************************
703 Sets information about current turn
704 **************************************************************************/
705 void info_label::set_turn_info(QString str)
707 turn_info = str;
710 /**************************************************************************
711 Sets information about current time
712 **************************************************************************/
713 void info_label::set_time_info(QString str)
715 time_label = str;
716 update();
719 /**************************************************************************
720 Sets information about current economy
721 **************************************************************************/
722 void info_label::set_eco_info(QString str)
724 eco_info = str;
727 /**************************************************************************
728 Updates menu
729 **************************************************************************/
730 void info_label::update_menu()
732 /** Function inherited from abstract parent
733 * PORTME , if needed */
736 /**************************************************************************
737 Creates end turn pixmap, to use at painting.
738 It searches for optimal pixel size for font to get optimal size.
739 Pixmap size is 80% width of rates pixmap
740 **************************************************************************/
741 void info_label::create_end_turn_pixmap()
743 int w, s, r;
744 QString str(_("End Turn"));
745 QFontMetrics fm(*ufont);
746 QPainter p;
747 QPen pen;
748 struct sprite *sprite = get_tax_sprite(tileset, O_LUXURY);
750 w = 8 * sprite->pm->width();
751 r = 8;
752 for (s = 8; s < 30; s++) {
753 ufont->setPixelSize(s);
754 if (fm.width(str) < w) {
755 r = s;
758 ufont->setPixelSize(r);
759 pen.setColor(QColor(30, 175, 30));
760 end_turn_pix = new QPixmap(w, fm.height() + 4);
761 end_turn_pix->fill(Qt::transparent);
762 p.begin(end_turn_pix);
763 p.setPen(pen);
764 p.setFont(*ufont);
765 p.drawText(0, fm.height() + 3, str);
766 p.end();
769 /**************************************************************************
770 Sets pixmap about current rates
771 **************************************************************************/
772 void info_label::set_rates_pixmap()
774 QString eco_info;
775 int d;
776 QPainter p;
777 struct sprite *sprite = get_tax_sprite(tileset, O_LUXURY);
778 int w = sprite->pm->width();
779 int h = sprite->pm->height();
780 QRect source_rect;
781 QRect dest_rect;
783 if (rates_label == NULL) {
784 rates_label = new QPixmap(10 * w, h);
787 source_rect = QRect(0, 0, w, h);
788 dest_rect = QRect(0, 0, w, h);
789 rates_label->fill(Qt::transparent);
790 d = 0;
792 if (client_is_global_observer()){
793 return;
796 for (; d < client.conn.playing->economic.luxury / 10; d++) {
797 dest_rect.moveTo(d * w, 0);
798 p.begin(rates_label);
799 p.drawPixmap(dest_rect, *sprite->pm, source_rect);
800 p.end();
802 sprite = get_tax_sprite(tileset, O_SCIENCE);
804 for (; d < (client.conn.playing->economic.science
805 + client.conn.playing->economic.luxury) / 10; d++) {
806 dest_rect.moveTo(d * w, 0);
807 p.begin(rates_label);
808 p.drawPixmap(dest_rect, *sprite->pm, source_rect);
809 p.end();
811 sprite = get_tax_sprite(tileset, O_GOLD);
813 for (; d < 10; d++) {
814 dest_rect.moveTo(d * w, 0);
815 p.begin(rates_label);
816 p.drawPixmap(dest_rect, *sprite->pm, source_rect);
818 p.end();
822 /**************************************************************************
823 Highligts end turn button and shows tooltips
824 **************************************************************************/
825 void info_label::mouseMoveEvent(QMouseEvent *event)
827 QPoint p(event->x(), event->y());
828 p = this->mapToGlobal(p);
829 bool redraw = false;
830 struct sprite *sprite;
831 int w;
833 if (client_is_global_observer()){
834 return;
837 if (end_button_area.contains(event->x(), event->y())) {
838 if (highlight_end_button == false) {
839 redraw = true;
841 highlight_end_button = true;
842 } else {
843 if (highlight_end_button == true) {
844 redraw = true;
846 highlight_end_button = false;
849 if (indicator_area.contains(event->x(), event->y())) {
850 sprite = get_tax_sprite(tileset, O_LUXURY);
851 w = sprite->pm->width();
852 switch (event->x() / w) {
853 case 3:
854 QToolTip::showText(p, QString(get_bulb_tooltip()));
855 break;
856 case 4:
857 QToolTip::showText(p, QString(get_global_warming_tooltip()));
858 break;
859 case 5:
860 QToolTip::showText(p, QString(get_nuclear_winter_tooltip()));
861 break;
862 case 6:
863 QToolTip::showText(p, QString(get_government_tooltip()));
864 break;
865 default:
866 QToolTip::hideText();
867 break;
871 if (rates_area.contains(event->x(), event->y())) {
872 QToolTip::showText(p,
873 QString(_("Shows your current luxury/science/tax "
874 "rates. Use mouse wheel to change them")));
875 } else if (!indicator_area.contains(event->x(), event->y())) {
876 QToolTip::hideText();
879 if (redraw) {
880 update();
884 /**************************************************************************
885 Mouse wheel event, used for changing tax rates
886 **************************************************************************/
887 void info_label::wheelEvent(QWheelEvent *event)
889 int a, b, c;
890 QPoint p(event->x(), event->y());
891 int delta = event->delta();
892 int pos;
893 int p2;
895 p = this->mapToGlobal(p);
896 pos = rates_label->width() / 10;
897 p2 = event->x() - rates_area.left();
898 if (client_is_global_observer()){
899 return;
901 a = client.conn.playing->economic.luxury / 10;
902 b = client.conn.playing->economic.science / 10;
903 c = 10 - a - b;
904 if (rates_area.contains(event->x(), event->y())) {
905 if (a * pos > p2) {
906 /* luxury icon */
907 if (delta > 0) {
908 a++;
909 a = qMin(a, 10);
910 b--;
911 b = qMax(b, 0);
912 c = 10 - a - b;
913 } else {
914 a--;
915 a = qMax(a, 0);
916 b++;
917 b = qMin(b, 10);
918 c = 10 - a - b;
920 } else if ((a + b) * pos > p2) {
921 /* science icon */
922 if (delta > 0) {
923 b++;
924 b = qMin(b, 10);
925 a--;
926 a = qMax(a, 0);
927 c = 10 - a - b;
928 } else {
929 b--;
930 b = qMax(b, 0);
931 c++;
932 c = qMin(c, 10);
933 a = 10 - c - b;
935 } else {
936 /* tax icon */
937 if (delta > 0) {
938 c++;
939 c = qMin(c, 10);
940 b--;
941 b = qMax(b, 0);
942 a = 10 - b - c;
943 } else {
944 c--;
945 c = qMax(c, 0);
946 b++;
947 b = qMin(b, 10);
948 a = 10 - b - c;
952 if (a + b + c == 10) {
953 dsend_packet_player_rates(&client.conn, qMax(c, 0) * 10,
954 qMax(a, 0) * 10, qMax(b, 0) * 10);
959 /**************************************************************************
960 Mouse press event for information label.
961 Checks if end turn has been clicked or rates dialog
962 (in rates dialog raises luxury only, rest can be easily changed by wheel)
963 **************************************************************************/
964 void info_label::mousePressEvent(QMouseEvent *event)
967 QPoint p(event->x(), event->y());
968 int pos = rates_label->width() / 10;
969 int p2 = event->x() - rates_area.left();
970 int a;
971 int b;
972 int c;
974 p = this->mapToGlobal(p);
975 if (client_is_global_observer()){
976 return;
979 b = client.conn.playing->economic.science / 10;
980 if (event->button() == Qt::LeftButton) {
981 if (end_button_area.contains(event->x(), event->y())) {
982 key_end_turn();
983 end_turn_button = true;
985 if (rates_area.contains(event->x(), event->y())) {
986 a = p2 / pos + 1;
987 c = 10 - a - b;
988 if (c < 0) {
989 c = 0;
990 b = 10 - a;
992 dsend_packet_player_rates(&client.conn, (10 - a - b) * 10,
993 a * 10, b * 10);
998 /**************************************************************************
999 Paint event for information label
1000 **************************************************************************/
1001 void info_label::paint(QPainter *painter, QPaintEvent *event)
1003 int h = 0;
1004 int w;
1005 QFontMetrics *fm;
1006 ufont->setPixelSize(14);
1008 fm = new QFontMetrics(*ufont);
1009 QPainter::CompositionMode comp_mode = painter->compositionMode();
1010 QPen pen;
1012 pen.setWidth(1);
1013 pen.setColor(QColor(232, 255, 0));
1014 painter->setBrush(QColor(0, 0, 0, 135));
1015 painter->drawRect(0, 0, width(), height());
1016 painter->setPen(pen);
1017 painter->setFont(*ufont);
1018 h = h + fm->height() + 5;
1019 w = fm->width(turn_info);
1020 w = (width() - w) / 2;
1021 painter->drawText(w, h, turn_info);
1022 h = h + fm->height() + 5;
1023 w = fm->width(time_label);
1024 w = (width() - w) / 2;
1025 painter->drawText(w, h, time_label);
1026 w = fm->width(eco_info);
1027 w = (width() - w) / 2;
1028 h = h + fm->height() + 5;
1029 painter->drawText(w, h, eco_info);
1030 h = h + indicator_icons->height();
1031 w = rates_label->width();
1032 w = (width() - w) / 2;
1033 indicator_area.setRect(w, h, indicator_icons->width(),
1034 indicator_icons->height());
1035 painter->drawPixmap(w, h, *indicator_icons);
1036 h = h + rates_label->height() + 6;
1037 rates_area.setRect(w, h, rates_label->width(), rates_label->height());
1038 painter->drawPixmap(w, h, *rates_label);
1039 h = h + end_turn_pix->height() + 6;
1040 w = end_turn_pix->width();
1041 w = (width() - w) / 2;
1042 end_button_area.setRect(w, h, end_turn_pix->width(),
1043 end_turn_pix->height() - 10);
1044 if (highlight_end_button == true) {
1045 painter->setCompositionMode(QPainter::CompositionMode_HardLight);
1047 if (end_turn_button == false) {
1048 painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
1050 painter->drawPixmap(w, h, *end_turn_pix);
1051 painter->setCompositionMode(comp_mode);
1052 delete fm;
1055 /**************************************************************************
1056 Paint event for information label, redirects event to paint(...)
1057 **************************************************************************/
1058 void info_label::paintEvent(QPaintEvent *event)
1060 QPainter painter;
1062 painter.begin(this);
1063 paint(&painter, event);
1064 painter.end();
1067 /**************************************************************************
1068 Updates size and size of objects
1069 **************************************************************************/
1070 void info_label::info_update()
1072 int w = 0, h = 0;
1073 QFontMetrics *fm;
1075 ufont->setPixelSize(14);
1076 fm = new QFontMetrics(*ufont);
1077 w = qMax(w, fm->width(eco_info));
1078 w = qMax(w, fm->width(turn_info));
1079 w = qMax(w, fm->width(time_label));
1080 if (rates_label != NULL && indicator_icons != NULL) {
1081 h = 3 * (fm->height() + 5) + rates_label->height() +
1082 indicator_icons->height();
1083 w = qMax(w, rates_label->width());
1084 w = qMax(w, indicator_icons->width());
1086 ufont->setPixelSize(20);
1087 h = h + fm->height() + 20;
1088 setFixedWidth(h + 20);
1089 setFixedHeight(w + 20);
1090 update();
1091 delete fm;
1094 /****************************************************************************
1095 Typically an info box is provided to tell the player about the state
1096 of their civilization. This function is called when the label is
1097 changed.
1098 ****************************************************************************/
1099 void update_info_label(void)
1101 QString eco_info;
1102 QString s = QString::fromLatin1(textyear(game.info.year)) + " ("
1103 + _("Turn") + ":" + QString::number(game.info.turn) + ")";
1104 gui()->game_info_label->set_turn_info(s);
1105 set_indicator_icons(client_research_sprite(),
1106 client_warming_sprite(),
1107 client_cooling_sprite(), client_government_sprite());
1108 if (client.conn.playing != NULL) {
1109 eco_info = QString(_("Gold")) + ": "
1110 + QString::number(client.conn.playing->economic.gold);
1111 gui()->game_info_label->set_eco_info(eco_info);
1113 gui()->game_info_label->set_rates_pixmap();
1114 gui()->game_info_label->info_update();
1117 /****************************************************************************
1118 Update the information label which gives info on the current unit
1119 and the tile under the current unit, for specified unit. Note that
1120 in practice punit is always the focus unit.
1122 Clears label if punit is NULL.
1124 Typically also updates the cursor for the map_canvas (this is
1125 related because the info label may includes "select destination"
1126 prompt etc). And it may call update_unit_pix_label() to update the
1127 icons for units on this tile.
1128 ****************************************************************************/
1129 void update_unit_info_label(struct unit_list *punitlist)
1131 gui()->unitinfo_wdg->uupdate(punitlist);
1134 /****************************************************************************
1135 Update the mouse cursor. Cursor type depends on what user is doing and
1136 pointing.
1137 ****************************************************************************/
1138 void update_mouse_cursor(enum cursor_type new_cursor_type)
1140 /* PORTME */
1143 /****************************************************************************
1144 Update the timeout display. The timeout is the time until the turn
1145 ends, in seconds.
1146 ****************************************************************************/
1147 void qtg_update_timeout_label(void)
1149 gui()->game_info_label->set_time_info (
1150 QString::fromLatin1(get_timeout_label_text()));
1153 /****************************************************************************
1154 If do_restore is false it should change the turn button style (to
1155 draw the user's attention to it). If called regularly from a timer
1156 this will give a blinking turn done button. If do_restore is true
1157 this should reset the turn done button to the default style.
1158 ****************************************************************************/
1159 void update_turn_done_button(bool do_restore)
1161 if (!get_turn_done_button_state()) {
1162 return;
1165 if (do_restore) {
1166 gui()->game_info_label->end_turn_button = true;
1171 /**************************************************************************
1172 Sets indicator icons in information label
1173 It assumes all icons have the same size
1174 **************************************************************************/
1175 void info_label::set_indicator_icons(QPixmap* bulb, QPixmap* sol,
1176 QPixmap* flake, QPixmap* gov)
1178 QPainter p;
1179 QRect source_rect(0, 0, bulb->width(), bulb->height());
1180 QRect dest_rect(0, 0, bulb->width(), bulb->height());
1182 if (indicator_icons == NULL) {
1183 indicator_icons = new QPixmap(7 * bulb->width(), bulb->height());
1185 indicator_icons->fill(Qt::transparent);
1187 p.begin(indicator_icons);
1188 dest_rect.setLeft(3 * bulb->width());
1189 p.drawPixmap(dest_rect, *bulb, source_rect);
1190 dest_rect.setLeft(4 * bulb->width());
1191 p.drawPixmap(dest_rect, *sol, source_rect);
1192 dest_rect.setLeft(5 * bulb->width());
1193 p.drawPixmap(dest_rect, *flake, source_rect);
1194 dest_rect.setLeft(6 * bulb->width());
1195 p.drawPixmap(dest_rect, *gov, source_rect);
1196 p.end();
1199 /****************************************************************************
1200 Set information for the indicator icons typically shown in the main
1201 client window. The parameters tell which sprite to use for the
1202 indicator.
1203 ****************************************************************************/
1204 void set_indicator_icons(struct sprite *bulb, struct sprite *sol,
1205 struct sprite *flake, struct sprite *gov)
1207 gui()->game_info_label->set_indicator_icons(bulb->pm, sol->pm, flake->pm,
1208 gov->pm);
1211 /****************************************************************************
1212 Return a canvas that is the overview window.
1213 ****************************************************************************/
1214 struct canvas *get_overview_window(void)
1216 return NULL;
1219 /****************************************************************************
1220 Flush the given part of the canvas buffer (if there is one) to the
1221 screen.
1222 ****************************************************************************/
1223 void flush_mapcanvas(int canvas_x, int canvas_y,
1224 int pixel_width, int pixel_height)
1226 gui()->mapview_wdg->repaint(canvas_x, canvas_y, pixel_width, pixel_height);
1229 /****************************************************************************
1230 Mark the rectangular region as "dirty" so that we know to flush it
1231 later.
1232 ****************************************************************************/
1233 void dirty_rect(int canvas_x, int canvas_y,
1234 int pixel_width, int pixel_height)
1236 if (mapview_is_frozen()) {
1237 return;
1239 if (num_dirty_rects < MAX_DIRTY_RECTS) {
1240 dirty_rects[num_dirty_rects].setX(canvas_x);
1241 dirty_rects[num_dirty_rects].setY(canvas_y);
1242 dirty_rects[num_dirty_rects].setWidth(pixel_width);
1243 dirty_rects[num_dirty_rects].setHeight(pixel_height);
1244 num_dirty_rects++;
1248 /****************************************************************************
1249 Mark the entire screen area as "dirty" so that we can flush it later.
1250 ****************************************************************************/
1251 void dirty_all(void)
1253 if (mapview_is_frozen()) {
1254 return;
1256 num_dirty_rects = MAX_DIRTY_RECTS;
1259 /****************************************************************************
1260 Flush all regions that have been previously marked as dirty. See
1261 dirty_rect and dirty_all. This function is generally called after we've
1262 processed a batch of drawing operations.
1263 ****************************************************************************/
1264 void flush_dirty(void)
1266 if (mapview_is_frozen()) {
1267 return;
1269 if (num_dirty_rects == MAX_DIRTY_RECTS) {
1270 flush_mapcanvas(0, 0, gui()->mapview_wdg->width(),
1271 gui()->mapview_wdg->height());
1272 } else {
1273 int i;
1274 for (i = 0; i < num_dirty_rects; i++) {
1275 flush_mapcanvas(dirty_rects[i].x(), dirty_rects[i].y(),
1276 dirty_rects[i].width(), dirty_rects[i].height());
1279 num_dirty_rects = 0;
1282 /****************************************************************************
1283 Do any necessary synchronization to make sure the screen is up-to-date.
1284 The canvas should have already been flushed to screen via flush_dirty -
1285 all this function does is make sure the hardware has caught up.
1286 ****************************************************************************/
1287 void gui_flush(void)
1289 gui()->mapview_wdg->update();
1292 /****************************************************************************
1293 Update (refresh) the locations of the mapview scrollbars (if it uses
1294 them).
1295 ****************************************************************************/
1296 void update_map_canvas_scrollbars(void)
1298 gui()->mapview_wdg->update();
1301 /****************************************************************************
1302 Update the size of the sliders on the scrollbars.
1303 ****************************************************************************/
1304 void update_map_canvas_scrollbars_size(void)
1306 /* PORTME */
1309 /****************************************************************************
1310 Update (refresh) all city descriptions on the mapview.
1311 ****************************************************************************/
1312 void update_city_descriptions(void)
1314 update_map_canvas_visible();
1317 /**************************************************************************
1318 Put overlay tile to pixmap
1319 **************************************************************************/
1320 void pixmap_put_overlay_tile(int canvas_x, int canvas_y,
1321 struct sprite *ssprite)
1323 if (!ssprite) {
1324 return;
1327 /* PORTME */
1330 /****************************************************************************
1331 Draw a cross-hair overlay on a tile.
1332 ****************************************************************************/
1333 void put_cross_overlay_tile(struct tile *ptile)
1335 int canvas_x, canvas_y;
1337 if (tile_to_canvas_pos(&canvas_x, &canvas_y, ptile)) {
1338 pixmap_put_overlay_tile(canvas_x, canvas_y,
1339 get_attention_crosshair_sprite(tileset));
1344 /****************************************************************************
1345 Area Selection
1346 ****************************************************************************/
1347 void draw_selection_rectangle(int canvas_x, int canvas_y, int w, int h)
1349 /* PORTME */
1352 /****************************************************************************
1353 This function is called when the tileset is changed.
1354 ****************************************************************************/
1355 void tileset_changed(void)
1357 gui()->unitinfo_wdg->update_arrow_pix();
1358 destroy_city_dialog();
1361 /****************************************************************************
1362 Return the dimensions of the area (container widget; maximum size) for
1363 the overview.
1364 ****************************************************************************/
1365 void get_overview_area_dimensions(int *width, int *height)
1367 *width = ::gui()->minimapview_wdg->width();
1368 *height = ::gui()->minimapview_wdg->height();
1371 /****************************************************************************
1372 Called when the map size changes. This may be used to change the
1373 size of the GUI element holding the overview canvas. The
1374 overview.width and overview.height are updated if this function is
1375 called.
1376 It's used for first creation of overview only, later overview stays the
1377 same size, scaled by qt-specific function.
1378 ****************************************************************************/
1379 void overview_size_changed(void)
1381 int map_width, map_height, over_width, over_height, ow, oh;
1382 float ratio;
1383 map_width = gui()->mapview_wdg->width();
1384 map_height = gui()->mapview_wdg->height();
1385 over_width = overview.width;
1386 over_height = overview.height;
1388 /* lower overview width size to max 20% of map width, keep aspect ratio*/
1389 if (map_width/over_width < 5){
1390 ratio = static_cast<float>(map_width)/over_width;
1391 ow = static_cast<float>(map_width)/5.0;
1392 ratio = static_cast<float>(over_width)/ow;
1393 over_height=static_cast<float>(over_height)/ratio;
1394 over_width=ow;
1396 /* if height still too high lower again */
1397 if (map_height/over_height < 5){
1398 ratio = static_cast<float>(map_height)/over_height;
1399 oh = static_cast<float>(map_height)/5.0;
1400 ratio = static_cast<float>(over_height)/oh;
1401 over_width=static_cast<float>(over_width)/ratio;
1402 over_height = oh;
1404 /* make minimap not less than 48x48 */
1405 if (over_width < 48) {
1406 over_width =48;
1408 if (over_height < 48) {
1409 over_height = 48;
1411 gui()->minimapview_wdg->resize(over_width, over_height);
1414 /**************************************************************************
1415 Constructor for unit_label (shows information about unit) and
1416 might call for unit_selection_dialog
1417 It uses default font for display text with modified size to fit on screen
1418 **************************************************************************/
1419 unit_label::unit_label(QWidget *parent)
1421 setParent(parent);
1422 pix = NULL;
1423 arrow_pix = NULL;
1424 ufont = new QFont;
1425 w_width = 0;
1426 selection_area.setWidth(0);
1427 highlight_pix = false;
1428 setMouseTracking(true);
1429 setFixedWidth(0);
1430 setFixedHeight(0);
1433 /**************************************************************************
1434 Updates units label (pixmap and text) and calls update() to redraw
1435 Font size is fixed to match widget size.
1436 **************************************************************************/
1437 void unit_label::uupdate(unit_list *punits)
1439 struct city *pcity;
1440 struct unit *punit = unit_list_get(punits, 0);
1441 struct player *owner;
1442 struct canvas *unit_pixmap;
1444 one_unit = true;
1445 setFixedHeight(50);
1446 if (unit_list_size(punits) == 0) {
1447 unit_label1 = "";
1448 unit_label2 = "";
1449 if (pix != NULL) {
1450 delete pix;
1452 pix = NULL;
1453 update();
1454 return;
1455 } else if (unit_list_size(punits) == 1) {
1456 if (unit_list_size(unit_tile(punit)->units) > 1) {
1457 one_unit = false;
1461 ufont->setPixelSize(height() / 3);
1462 ul_units = punits;
1463 unit_label1 = get_unit_info_label_text1(punits);
1464 owner = unit_owner(punit);
1465 pcity = player_city_by_number(owner, punit->homecity);
1466 if (pcity != NULL && unit_list_size(punits) == 1) {
1467 unit_label1 = unit_label1 + " " + _("from") + " ";
1468 unit_label1 += QString(city_name(pcity));
1470 unit_label2 = QString(unit_activity_text(unit_list_get(punits, 0)))
1471 + QString(" ") + QString(_("HP")) + QString(": ")
1472 + QString::number(punit->hp) + QString("/")
1473 + QString::number(unit_type(punit)->hp);
1475 if (pix != NULL) {
1476 delete pix;
1477 pix = NULL;
1479 punit = head_of_units_in_focus();
1480 if (punit) {
1481 unit_pixmap = qtg_canvas_create(tileset_full_tile_width(tileset),
1482 tileset_tile_height(tileset) * 3 / 2);
1483 unit_pixmap->map_pixmap.fill(Qt::transparent);
1484 put_unit(punit, unit_pixmap, 0, 0);
1485 pix = &unit_pixmap->map_pixmap;
1486 *pix = pix->scaledToHeight(height());
1487 w_width = pix->width() + 1;
1489 QFontMetrics fm(*ufont);
1490 if (arrow_pix == NULL) {
1491 arrow_pix = get_arrow_sprite(tileset, ARROW_PLUS)->pm;
1492 *arrow_pix = arrow_pix->scaledToHeight(height());
1494 w_width += qMax(fm.width(unit_label1), fm.width(unit_label2));
1495 if (one_unit == false) {
1496 w_width += arrow_pix->width() + 1;
1498 w_width += 5;
1499 setFixedWidth(w_width);
1500 move(0, parentWidget()->height() - height());
1501 update();
1504 /**************************************************************************
1505 Mouse press event for unit label, it calls unit selector
1506 **************************************************************************/
1507 void unit_label::mousePressEvent(QMouseEvent *event)
1509 struct unit *punit = unit_list_get(ul_units, 0);
1511 if (event->button() == Qt::LeftButton) {
1512 if (selection_area.contains(event->x(), event->y())) {
1513 if (punit != NULL && selection_area.width() > 0) {
1514 unit_select_dialog_popup(unit_tile(punit));
1520 /**************************************************************************
1521 Mouse move event for unit label, used for highlighting pixmap of
1522 unit selector
1523 **************************************************************************/
1524 void unit_label::mouseMoveEvent(QMouseEvent *event)
1526 bool redraw = false;
1528 if (selection_area.contains(event->x(), event->y())) {
1529 if (highlight_pix == false) {
1530 redraw = true;
1532 highlight_pix = true;
1533 } else {
1534 if (highlight_pix == true) {
1535 redraw = true;
1537 highlight_pix = false;
1539 if (redraw) {
1540 update();
1544 /**************************************************************************
1545 Paint event for unit label
1546 **************************************************************************/
1547 void unit_label::paint(QPainter *painter, QPaintEvent *event)
1549 int w;
1550 QPainter::CompositionMode comp_mode = painter->compositionMode();
1551 QPen pen;
1553 selection_area.setWidth(0);
1554 pen.setWidth(1);
1555 pen.setColor(QColor(232, 255, 0));
1556 painter->setBrush(QColor(0, 0, 0, 135));
1557 painter->drawRect(0, 0, w_width, height());
1558 painter->setFont(*ufont);
1559 painter->setPen(pen);
1560 if (pix != NULL) {
1561 painter->drawPixmap(0, (height() - pix->height()) / 2, *pix);
1562 w = pix->width() + 1;
1563 if (one_unit == false) {
1564 if (highlight_pix) {
1565 painter->setCompositionMode(QPainter::CompositionMode_HardLight);
1567 painter->drawPixmap(w, 0, *arrow_pix);
1568 selection_area.setRect(w, 5, arrow_pix->width(),
1569 arrow_pix->height() - 10);
1570 w = w + arrow_pix->width() + 1;
1572 painter->setCompositionMode(comp_mode);
1573 painter->drawText(w, height() / 2.5, unit_label1);
1574 painter->drawText(w, height() - 8, unit_label2);
1575 } else {
1576 painter->drawText(5, height() / 3 + 5, _("No units selected."));
1580 /**************************************************************************
1581 Updates unit selector pixmap, necessary when changing tileset
1582 **************************************************************************/
1583 void unit_label::update_arrow_pix()
1585 arrow_pix = get_arrow_sprite(tileset, ARROW_PLUS)->pm;
1586 *arrow_pix = arrow_pix->scaledToHeight(height());
1589 /**************************************************************************
1590 Paint event for unit label, it calls paint(...)
1591 **************************************************************************/
1592 void unit_label::paintEvent(QPaintEvent *event)
1594 QPainter painter;
1596 painter.begin(this);
1597 paint(&painter, event);
1598 painter.end();
1601 /**************************************************************************
1602 Updates menu for unit label
1603 **************************************************************************/
1604 void unit_label::update_menu()
1606 /* PORTME, if needed */
1608 /**************************************************************************
1609 Sets the position of the overview scroll window based on mapview position.
1610 **************************************************************************/
1611 void update_overview_scroll_window_pos(int x, int y)
1613 /* TODO: PORTME. */
1617 /****************************************************************************
1618 Return whether the map should be drawn or not.
1619 ****************************************************************************/
1620 bool mapview_is_frozen(void)
1622 return (0 < mapview_frozen_level);
1626 /****************************************************************************
1627 Freeze the drawing of the map.
1628 ****************************************************************************/
1629 void mapview_freeze(void)
1631 mapview_frozen_level++;
1634 /****************************************************************************
1635 Thaw the drawing of the map.
1636 ****************************************************************************/
1637 void mapview_thaw(void)
1639 if (1 < mapview_frozen_level) {
1640 mapview_frozen_level--;
1641 } else {
1642 fc_assert(0 < mapview_frozen_level);
1643 mapview_frozen_level = 0;
1644 dirty_all();
1648 /**************************************************************************
1649 Constructor for info_tile
1650 **************************************************************************/
1651 info_tile::info_tile(struct tile *ptile, QWidget *parent): QLabel(parent)
1653 setParent(parent);
1654 info_font = gui()->fc_fonts.get_font("gui_qt_font_comment_label");
1655 itile = ptile;
1656 calc_size();
1659 /**************************************************************************
1660 Calculates size of info_tile and moves it to be fully visible
1661 **************************************************************************/
1662 void info_tile::calc_size()
1664 QFontMetrics fm(*info_font);
1665 QString str;
1666 int hh = tileset_tile_height(tileset);
1667 int fin_x;
1668 int fin_y;
1669 int x, y;
1670 int w = 0;
1672 str = popup_info_text(itile);
1673 str_list = str.split("\n");
1675 foreach(str, str_list) {
1676 w = qMax(w, fm.width(str));
1678 setFixedHeight(str_list.count() * (fm.height() + 5));
1679 setFixedWidth(w + 10);
1680 if (tile_to_canvas_pos(&x, &y, itile)) {
1681 fin_x = x;
1682 fin_y = y;
1683 if (y - height() > 0) {
1684 fin_y = y - height();
1685 } else {
1686 fin_y = y + hh;
1688 if (x + width() > parentWidget()->width()) {
1689 fin_x = parentWidget()->width() - width();
1691 move(fin_x, fin_y);
1695 /**************************************************************************
1696 Redirected paint event for info_tile
1697 **************************************************************************/
1698 void info_tile::paint(QPainter *painter, QPaintEvent *event)
1700 QPen pen;
1701 QFontMetrics fm(*info_font);
1702 int pos, h;
1704 h = fm.height();
1705 pos = h;
1706 pen.setWidth(1);
1707 pen.setColor(QColor(232, 255, 0));
1708 painter->setBrush(QColor(0, 0, 0, 205));
1709 painter->drawRect(0, 0, width(), height());
1710 painter->setPen(pen);
1711 painter->setFont(*info_font);
1712 for (int i = 0; i < str_list.count(); i++) {
1713 painter->drawText(5, pos, str_list.at(i));
1714 pos = pos + 5 + h;
1718 /**************************************************************************
1719 Paint event for info_tile
1720 **************************************************************************/
1721 void info_tile::paintEvent(QPaintEvent *event)
1723 QPainter painter;
1725 painter.begin(this);
1726 paint(&painter, event);
1727 painter.end();