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)
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 ***********************************************************************/
15 #include <fc_config.h>
20 #include <QApplication>
22 #include <QDialogButtonBox>
23 #include <QGridLayout>
25 #include <QHBoxLayout>
26 #include <QHeaderView>
29 #include <QPaintEvent>
30 #include <QRadioButton>
31 #include <QSpacerItem>
32 #include <QVBoxLayout>
42 #include "client_main.h"
46 #include "fc_client.h"
48 #include "hudwidget.h"
52 const char *calendar_text(void);
54 static QString
popup_terrain_info(struct tile
*ptile
);
56 /***************************************************************************
57 Returns true if player has any unit of unit_type
58 ***************************************************************************/
59 bool has_player_unit_type(Unit_type_id utype
)
61 unit_list_iterate(client
.conn
.playing
->units
, punit
) {
62 if (utype_number(punit
->utype
) == utype
) {
65 } unit_list_iterate_end
;
70 /****************************************************************************
71 Custom message box constructor
72 ****************************************************************************/
73 hud_message_box::hud_message_box(QWidget
*parent
): QMessageBox(parent
)
76 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
77 | Qt::FramelessWindowHint
);
78 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
79 f_title
= *fc_font::instance()->get_font(fonts::default_font
);
81 size
= f_text
.pointSize();
83 f_text
.setPointSize(size
* 4 / 3);
84 f_title
.setPointSize(size
* 3 / 2);
86 size
= f_text
.pixelSize();
87 f_text
.setPixelSize(size
* 4 / 3);
88 f_title
.setPointSize(size
* 3 / 2);
90 f_title
.setBold(true);
91 f_title
.setCapitalization(QFont::SmallCaps
);
92 fm_text
= new QFontMetrics(f_text
);
93 fm_title
= new QFontMetrics(f_title
);
100 /****************************************************************************
101 Custom message box destructor
102 ****************************************************************************/
103 hud_message_box::~hud_message_box()
108 /****************************************************************************
109 Key press event for hud message box
110 ****************************************************************************/
111 void hud_message_box::keyPressEvent(QKeyEvent
*event
)
113 if (event
->key() == Qt::Key_Escape
) {
118 QWidget::keyPressEvent(event
);
121 /****************************************************************************
122 Sets text and title and shows message box
123 ****************************************************************************/
124 void hud_message_box::set_text_title(QString s1
, QString s2
)
131 if (s1
.contains('\n')) {
133 i
= s1
.indexOf('\n');
135 cs2
= s1
.right(s1
.count() - i
);
137 w2
= qMax(fm_text
->width(cs1
), fm_text
->width(cs2
));
138 w
= qMax(w2
, fm_title
->width(s2
));
140 w
= qMax(fm_text
->width(s1
), fm_title
->width(s2
));
143 h
= mult
* (fm_text
->height() * 3 / 2) + 2 * fm_title
->height();
144 top
= 2 * fm_title
->height();
145 spacer
= new QSpacerItem(w
, 0, QSizePolicy::Minimum
,
146 QSizePolicy::Expanding
);
147 layout
= (QGridLayout
*)this->layout();
148 layout
->addItem(spacer
, layout
->rowCount(), 0, 1, layout
->columnCount());
149 spacer
= new QSpacerItem(0, h
, QSizePolicy::Expanding
,
150 QSizePolicy::Minimum
);
151 layout
->addItem(spacer
, 0, 0, 1, layout
->columnCount());
156 p
= QPoint((parentWidget()->width() - w
) / 2,
157 (parentWidget()->height() - h
) / 2);
158 p
= parentWidget()->mapToGlobal(p
);
165 /****************************************************************************
166 Timer event used to animate message box
167 ****************************************************************************/
168 void hud_message_box::timerEvent(QTimerEvent
*event
)
170 m_animate_step
= m_timer
.elapsed() / 40;
174 /****************************************************************************
175 Paint event for custom message box
176 ****************************************************************************/
177 void hud_message_box::paintEvent(QPaintEvent
*event
)
186 step
= m_animate_step
% 300;
193 rfull
= QRect(2 , 2, width() - 4 , height() - 4);
194 rx
= QRect(2 , 2, width() - 4 , top
);
195 ry
= QRect(2 , top
, width() - 4, height() - top
- 4);
197 c1
= QColor(palette().color(QPalette::Highlight
));
198 c2
= QColor(palette().color(QPalette::AlternateBase
));
199 step
= qMax(0, step
);
200 step
= qMin(255, step
);
204 g
= QLinearGradient(0 , 0, width(), height());
209 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
210 p
.fillRect(ry
, QColor(palette().color(QPalette::AlternateBase
)));
211 p
.fillRect(rfull
, g
);
213 p
.drawText((width() - fm_title
->width(title
)) / 2,
214 fm_title
->height() * 4 / 3, title
);
217 p
.drawText((width() - fm_text
->width(text
)) / 2,
218 2 * fm_title
->height() + fm_text
->height() * 4 / 3, text
);
220 p
.drawText((width() - fm_text
->width(cs1
)) / 2,
221 2 * fm_title
->height() + fm_text
->height() * 4 / 3, cs1
);
222 p
.drawText((width() - fm_text
->width(cs2
)) / 2,
223 2 * fm_title
->height() + fm_text
->height() * 8 / 3, cs2
);
229 /****************************************************************************
230 Hud text constructor takes text to display and time
231 ****************************************************************************/
232 hud_text::hud_text(QString s
, int time_secs
,
233 QWidget
*parent
) : QWidget(parent
)
240 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::FramelessWindowHint
);
241 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
242 f_text
.setBold(true);
243 f_text
.setCapitalization(QFont::SmallCaps
);
244 size
= f_text
.pointSize();
246 f_text
.setPointSize(size
* 2);
248 size
= f_text
.pixelSize();
249 f_text
.setPixelSize(size
* 2);
251 fm_text
= new QFontMetrics(f_text
);
255 setAttribute(Qt::WA_TranslucentBackground
);
256 setAttribute(Qt::WA_ShowWithoutActivating
);
257 setAttribute(Qt::WA_TransparentForMouseEvents
);
258 setFocusPolicy(Qt::NoFocus
);
261 /****************************************************************************
263 ****************************************************************************/
264 void hud_text::show_me()
270 /****************************************************************************
271 Moves to top center parent widget and sets size new size
272 ****************************************************************************/
273 void hud_text::center_me()
278 if (bound_rect
.isEmpty() == false) {
279 setFixedSize(bound_rect
.width(), bound_rect
.height());
281 p
= QPoint((parentWidget()->width() - w
) / 2,
282 parentWidget()->height() / 20);
286 /****************************************************************************
287 Destructor for hud text
288 ****************************************************************************/
289 hud_text::~hud_text()
294 /****************************************************************************
295 Timer event, closes widget after timeout
296 ****************************************************************************/
297 void hud_text::timerEvent(QTimerEvent
*event
)
299 m_animate_step
= m_timer
.elapsed() / 40;
300 if (m_timer
.elapsed() > timeout
* 1000) {
307 /****************************************************************************
308 Paint event for custom hud_text
309 ****************************************************************************/
310 void hud_text::paintEvent(QPaintEvent
*event
)
319 if (m_timer
.elapsed() < timeout
* 500) {
320 opacity
= static_cast<float>(m_timer
.elapsed())/(timeout
* 300);
322 opacity
= static_cast<float>(5000 - m_timer
.elapsed())/(timeout
* 200);
324 opacity
= qMin(1.0f
, opacity
);
325 opacity
= qMax(0.0f
, opacity
);
326 rfull
= QRect(0 , 0, width(), height());
327 c1
= QColor(Qt::white
);
328 c2
= QColor(35, 35, 35, 175);
329 c1
.setAlphaF(c1
.alphaF() * opacity
);
330 c2
.setAlphaF(c2
.alphaF() * opacity
);
333 p
.setPen(QColor(0, 0, 0, 0));
334 p
.drawRoundedRect(rfull
, height() / 6 , height() / 6);
337 p
.drawText(rfull
, Qt::AlignCenter
, text
, &bound_rect
);
342 /****************************************************************************
343 Custom input box constructor
344 ****************************************************************************/
345 hud_input_box::hud_input_box(QWidget
*parent
): QDialog(parent
)
349 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
350 | Qt::FramelessWindowHint
);
352 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
353 f_title
= *fc_font::instance()->get_font(fonts::default_font
);
355 size
= f_text
.pointSize();
357 f_text
.setPointSize(size
* 4 / 3);
358 f_title
.setPointSize(size
* 3 / 2);
360 size
= f_text
.pixelSize();
361 f_text
.setPixelSize(size
* 4 / 3);
362 f_title
.setPointSize(size
* 3 / 2);
364 f_title
.setBold(true);
365 f_title
.setCapitalization(QFont::SmallCaps
);
366 fm_text
= new QFontMetrics(f_text
);
367 fm_title
= new QFontMetrics(f_title
);
374 /****************************************************************************
375 Custom input box destructor
376 ****************************************************************************/
377 hud_input_box::~hud_input_box()
382 /****************************************************************************
383 Sets text, title and default text and shows input box
384 ****************************************************************************/
385 void hud_input_box::set_text_title_definput(QString s1
, QString s2
,
391 QDialogButtonBox
*button_box
;
394 button_box
= new QDialogButtonBox(QDialogButtonBox::Ok
395 | QDialogButtonBox::Cancel
,
396 Qt::Horizontal
, this);
397 layout
= new QVBoxLayout
;
398 if (s1
.contains('\n')) {
400 i
= s1
.indexOf('\n');
402 cs2
= s1
.right(s1
.count() - i
);
404 w2
= qMax(fm_text
->width(cs1
), fm_text
->width(cs2
));
405 w
= qMax(w2
, fm_title
->width(s2
));
407 w
= qMax(fm_text
->width(s1
), fm_title
->width(s2
));
410 h
= mult
* (fm_text
->height() * 3 / 2) + 2 * fm_title
->height();
411 top
= 2 * fm_title
->height();
413 spacer
= new QSpacerItem(w
, h
, QSizePolicy::Expanding
,
414 QSizePolicy::Minimum
);
415 layout
->addItem(spacer
);
416 layout
->addWidget(&input_edit
);
417 layout
->addWidget(button_box
);
418 input_edit
.setFont(f_text
);
419 input_edit
.setText(def_input
);
421 QObject::connect(button_box
, SIGNAL(accepted()), this, SLOT(accept()));
422 QObject::connect(button_box
, SIGNAL(rejected()), this, SLOT(reject()));
426 p
= QPoint((parentWidget()->width() - w
) / 2,
427 (parentWidget()->height() - h
) / 2);
428 p
= parentWidget()->mapToGlobal(p
);
430 input_edit
.activateWindow();
431 input_edit
.setFocus();
438 /****************************************************************************
439 Timer event used to animate input box
440 ****************************************************************************/
441 void hud_input_box::timerEvent(QTimerEvent
*event
)
443 m_animate_step
= m_timer
.elapsed() / 40;
448 /****************************************************************************
449 Paint event for custom input box
450 ****************************************************************************/
451 void hud_input_box::paintEvent(QPaintEvent
*event
)
463 step
= m_animate_step
% 300;
469 rx
= QRect(2 , 2, width() - 4 , top
);
470 ry
= QRect(2 , top
, width() - 4, height() - top
- 4);
472 c1
= QColor(palette().color(QPalette::Highlight
));
473 c2
= QColor(Qt::transparent
);
474 c3
= QColor(palette().color(QPalette::Highlight
)).lighter(145);
475 step
= qMax(0, step
);
476 step
= qMin(255, step
);
481 fstep
= static_cast<float>(step
) / 400;
482 g
= QLinearGradient(0 , 0, width(), height());
484 g
.setColorAt(fstep
, c3
);
488 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
489 p
.fillRect(ry
, QColor(palette().color(QPalette::AlternateBase
)));
492 p
.drawText((width() - fm_title
->width(title
)) / 2,
493 fm_title
->height() * 4 / 3, title
);
496 p
.drawText((width() - fm_text
->width(text
)) / 2,
497 2 * fm_title
->height() + fm_text
->height() * 4 / 3, text
);
499 p
.drawText((width() - fm_text
->width(cs1
)) / 2,
500 2 * fm_title
->height() + fm_text
->height() * 4 / 3, cs1
);
501 p
.drawText((width() - fm_text
->width(cs2
)) / 2,
502 2 * fm_title
->height() + fm_text
->height() * 8 / 3, cs2
);
508 /****************************************************************************
509 Constructor for hud_units (holds layout for whole uunits info)
510 ****************************************************************************/
511 hud_units::hud_units(QWidget
*parent
) : QFrame(parent
)
514 QVBoxLayout
*unit_lab
;
518 main_layout
= new QHBoxLayout
;
519 sp
= new QSpacerItem(50, 2);
520 vbox
= new QVBoxLayout
;
521 unit_lab
= new QVBoxLayout
;
522 unit_lab
->setContentsMargins(6, 9, 0, 3);
524 unit_lab
->addWidget(&unit_label
);
525 main_layout
->addLayout(unit_lab
);
526 main_layout
->addWidget(&tile_label
);
527 unit_icons
= new unit_actions(this, nullptr);
528 vbox
->addSpacerItem(sp
);
529 vbox
->addWidget(&text_label
);
530 vbox
->addWidget(unit_icons
);
531 main_layout
->addLayout(vbox
);
532 main_layout
->setSpacing(0);
533 main_layout
->setSpacing(3);
534 main_layout
->setContentsMargins(0, 0, 0, 0);
536 vbox
->setContentsMargins(0, 0, 0, 0);
537 setLayout(main_layout
);
538 mw
= new move_widget(this);
539 setFocusPolicy(Qt::ClickFocus
);
543 /****************************************************************************
545 ****************************************************************************/
546 hud_units::~hud_units()
551 /****************************************************************************
552 Move Event for hud_units, used to save position
553 ****************************************************************************/
554 void hud_units::moveEvent(QMoveEvent
*event
)
556 gui()->qt_settings
.unit_info_pos_fx
= static_cast<float>(event
->pos().x())
557 / gui()->mapview_wdg
->width();
558 gui()->qt_settings
.unit_info_pos_fy
= static_cast<float>(event
->pos().y())
559 / gui()->mapview_wdg
->height();
563 /****************************************************************************
564 Update possible action for given units
565 ****************************************************************************/
566 void hud_units::update_actions(unit_list
*punits
)
571 QFont font
= *fc_font::instance()->get_font(fonts::notify_label
);
577 QRect crop
, bounding_rect
;
580 QString fraction1
, fraction2
;
581 QString text_str
, move_pt_text
;
582 struct canvas
*tile_pixmap
;
583 struct canvas
*unit_pixmap
;
585 struct player
*owner
;
588 punit
= head_of_units_in_focus();
589 if (punit
== nullptr) {
594 font
.setCapitalization(QFont::AllUppercase
);
596 setFixedHeight(parentWidget()->height() / 12);
597 text_label
.setFixedHeight((height() * 2) / 10);
599 move(qRound(gui()->mapview_wdg
->width()
600 * gui()->qt_settings
.unit_info_pos_fx
),
601 qRound((gui()->mapview_wdg
->height()
602 * gui()->qt_settings
.unit_info_pos_fy
)));
603 unit_icons
->setFixedHeight((height() * 8) / 10);
605 setUpdatesEnabled(false);
607 text_str
= QString(unit_name_translation(punit
));
608 owner
= punit
->owner
;
609 pcity
= player_city_by_number(owner
, punit
->homecity
);
611 text_str
= QString(("%1(%2)"))
612 .arg(unit_name_translation(punit
), city_name_get(pcity
));
614 text_str
= text_str
+ " ";
615 mp
= QString(move_points_text(punit
->moves_left
, false));
616 if (utype_fuel(unit_type_get(punit
))) {
617 mp
= mp
+ QString("(") + QString(move_points_text((
618 unit_type_get(punit
)->move_rate
619 * ((punit
->fuel
) - 1)
620 + punit
->moves_left
), false))
623 /* TRANS: MP = Movement points */
624 mp
= QString(_("MP: ")) + mp
;
625 text_str
= text_str
+ mp
+ " ";
626 text_str
+= QString(_("HP:%1/%2")).arg(
627 QString::number(punit
->hp
),
628 QString::number(unit_type_get(punit
)->hp
));
629 num
= unit_list_size(punit
->tile
->units
);
630 snum
= QString::number(unit_list_size(punit
->tile
->units
) - 1);
631 if (unit_list_size(get_units_in_focus()) > 1) {
632 text_str
= text_str
+ QString(_(" (Selected %1 units)"))
633 .arg(unit_list_size(get_units_in_focus()));
634 } else if (num
> 2) {
635 text_str
= text_str
+ QString(_(" +%1 units"))
636 .arg(snum
.toLocal8Bit().data());
637 } else if (num
== 2) {
638 text_str
= text_str
+ QString(_(" +1 unit"));
640 text_label
.setText(text_str
);
641 font
.setPixelSize((text_label
.height() * 9) / 10);
642 text_label
.setFont(font
);
643 fm
= new QFontMetrics(font
);
644 text_label
.setFixedWidth(fm
->width(text_str
) + 20);
647 unit_pixmap
= qtg_canvas_create(tileset_unit_width(tileset
),
648 tileset_unit_height(tileset
));
649 unit_pixmap
->map_pixmap
.fill(Qt::transparent
);
650 put_unit(punit
, unit_pixmap
, 1, 0, 0);
651 img
= unit_pixmap
->map_pixmap
.toImage();
652 crop
= zealous_crop_rect(img
);
653 cropped_img
= img
.copy(crop
);
654 img
= cropped_img
.scaledToHeight(height(), Qt::SmoothTransformation
);
655 pix
= QPixmap::fromImage(img
);
656 /* add transparent borders if image is too slim */
657 if (pix
.width() < tileset_unit_width(tileset
)) {
658 int px
= tileset_full_tile_width(tileset
);
659 pix2
= QPixmap(px
, pix
.height());
660 pix2
.fill(Qt::transparent
);
662 p
.drawPixmap(px
/ 2 - pix
.width() / 2, 0, pix
);
666 /* Draw movement points */
667 move_pt_text
= move_points_text(punit
->moves_left
, false);
668 if (move_pt_text
.contains('/')) {
669 fraction2
= move_pt_text
.right(1);
670 move_pt_text
.remove(move_pt_text
.count() - 2, 2);
671 fraction1
= move_pt_text
.right(1);
672 move_pt_text
.remove(move_pt_text
.count() - 1, 1);
674 crop
= QRect(5, 5, pix
.width() - 5, pix
.height() - 5);
675 font
.setCapitalization(QFont::Capitalize
);
676 font
.setPointSize((pix
.height() * 2) / 5);
680 p
.drawText(crop
, Qt::AlignLeft
| Qt::AlignBottom
, move_pt_text
);
681 if (move_pt_text
.isEmpty()) {
684 bounding_rect
= p
.boundingRect(crop
, Qt::AlignLeft
| Qt::AlignBottom
,
686 font
.setPointSize(pix
.height() / 5);
687 fm
= new QFontMetrics(font
);
688 font_width
= (fm
->width(move_pt_text
) * 3) / 5;
691 if (fraction1
.isNull() == false) {
692 int t
= 2 * font
.pointSize();
693 crop
= QRect(bounding_rect
.right() - font_width
,
694 bounding_rect
.top(), t
, (t
/ 5) * 4);
695 p
.drawText(crop
, Qt::AlignLeft
| Qt::AlignBottom
, fraction1
);
696 crop
= QRect(bounding_rect
.right() - font_width
,
697 (bounding_rect
.bottom() + bounding_rect
.top()) / 2,
699 p
.drawText(crop
, Qt::AlignLeft
| Qt::AlignTop
, fraction2
);
700 crop
= QRect(bounding_rect
.right() - font_width
,
701 (bounding_rect
.bottom() + bounding_rect
.top()) / 2 - t
/ 16,
703 p
.fillRect(crop
, Qt::white
);
706 wwidth
= 2 * 3 + pix
.width();
707 unit_label
.setPixmap(pix
);
708 if (tileset_is_isometric(tileset
)) {
709 tile_pixmap
= qtg_canvas_create(tileset_full_tile_width(tileset
),
710 tileset_tile_height(tileset
) * 2);
712 tile_pixmap
= qtg_canvas_create(tileset_full_tile_width(tileset
),
713 tileset_tile_height(tileset
));
715 tile_pixmap
->map_pixmap
.fill(QColor(0 , 0 , 0 , 0));
716 put_terrain(punit
->tile
, tile_pixmap
, 1.0, 0, 0);
717 img
= tile_pixmap
->map_pixmap
.toImage();
718 crop
= zealous_crop_rect(img
);
719 cropped_img
= img
.copy(crop
);
720 if (cropped_img
.height() > height() - 5 ||
721 cropped_img
.height() < height() / 3) {
722 img
= cropped_img
.scaledToHeight(height() - 5,
723 Qt::SmoothTransformation
);
727 pix
= QPixmap::fromImage(img
);
728 tile_label
.setPixmap(pix
);
729 unit_label
.setToolTip(popup_info_text(punit
->tile
));
730 tile_label
.setToolTip(popup_terrain_info(punit
->tile
));
731 wwidth
= wwidth
+ pix
.width();
732 qtg_canvas_free(tile_pixmap
);
733 qtg_canvas_free(unit_pixmap
);
735 setFixedWidth(wwidth
+ qMax(unit_icons
->update_actions() * (height() * 8)
736 / 10, text_label
.width()));
738 setUpdatesEnabled(true);
745 /****************************************************************************
746 Custom label with extra mouse events
747 ****************************************************************************/
748 click_label::click_label() : QLabel()
750 connect(this, SIGNAL(left_clicked()), SLOT(on_clicked()));
753 /****************************************************************************
754 Mouse event for click_label
755 ****************************************************************************/
756 void click_label::mousePressEvent(QMouseEvent
*e
)
758 if (e
->button() == Qt::LeftButton
) {
763 /****************************************************************************
764 Centers on current unit
765 ****************************************************************************/
766 void click_label::on_clicked()
768 gui()->game_tab_widget
->setCurrentIndex(0);
769 request_center_focus_unit();
772 /****************************************************************************
773 Hud action constructor, used to show one action
774 ****************************************************************************/
775 hud_action::hud_action(QWidget
*parent
) : QWidget(parent
)
777 connect(this, SIGNAL(left_clicked()), SLOT(on_clicked()));
778 setFocusPolicy(Qt::StrongFocus
);
779 setMouseTracking(true);
781 action_pixmap
= nullptr;
784 /****************************************************************************
785 Sets given pixmap for hud_action
786 ****************************************************************************/
787 void hud_action::set_pixmap(QPixmap
*p
)
792 /****************************************************************************
793 Custom painting for hud_action
794 ****************************************************************************/
795 void hud_action::paintEvent(QPaintEvent
*event
)
800 rx
= QRect(0, 0, width(), height());
801 ry
= QRect(0, 0, action_pixmap
->width(), action_pixmap
->height());
802 rz
= QRect(0, 0, width() - 1, height() - 3);
804 p
.setCompositionMode(QPainter::CompositionMode_Source
);
805 p
.setRenderHint(QPainter::SmoothPixmapTransform
);
806 p
.drawPixmap(rx
, *action_pixmap
, ry
);
807 p
.setPen(QColor(palette().color(QPalette::Text
)));
810 p
.setCompositionMode(QPainter::CompositionMode_DestinationOver
);
811 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
817 /****************************************************************************
818 Hud action destructor
819 ****************************************************************************/
820 hud_action::~hud_action()
823 delete action_pixmap
;
827 /****************************************************************************
828 Mouse press event for hud_action
829 ****************************************************************************/
830 void hud_action::mousePressEvent(QMouseEvent
*e
)
832 if (e
->button() == Qt::RightButton
) {
833 emit
right_clicked();
834 } else if (e
->button() == Qt::LeftButton
) {
839 /****************************************************************************
840 Mouse move event for hud_action, draw focus
841 ****************************************************************************/
842 void hud_action::mouseMoveEvent(QMouseEvent
*event
)
847 /****************************************************************************
848 Leave event for hud_action, used to get status of pixmap higlight
849 ****************************************************************************/
850 void hud_action::leaveEvent(QEvent
*event
)
854 QWidget::leaveEvent(event
);
857 /****************************************************************************
858 Enter event for hud_action, used to get status of pixmap higlight
859 ****************************************************************************/
860 void hud_action::enterEvent(QEvent
*event
)
864 QWidget::enterEvent(event
);
867 /****************************************************************************
868 Right click event for hud_action
869 ****************************************************************************/
870 void hud_action::on_right_clicked()
874 /****************************************************************************
875 Left click event for hud_action
876 ****************************************************************************/
877 void hud_action::on_clicked()
879 gui()->menu_bar
->execute_shortcut(action_shortcut
);
882 /****************************************************************************
883 Units action contructor, holds possible hud_actions
884 ****************************************************************************/
885 unit_actions::unit_actions(QWidget
*parent
, unit
*punit
) : QWidget(parent
)
887 layout
= new QHBoxLayout(this);
888 layout
->setSpacing(3);
889 layout
->setContentsMargins(0, 0, 0, 0);
890 current_unit
= punit
;
892 setFocusPolicy(Qt::ClickFocus
);
897 /****************************************************************************
898 Destructor for unit_actions
899 ****************************************************************************/
900 unit_actions::~unit_actions()
907 /****************************************************************************
908 Initiazlizes layout ( layout needs to be changed after adding units )
909 ****************************************************************************/
910 void unit_actions::init_layout()
912 QSizePolicy
size_fixed_policy(QSizePolicy::MinimumExpanding
,
915 setSizePolicy(size_fixed_policy
);
916 layout
->setSpacing(0);
921 /****************************************************************************
922 Updates avaialable actions, returns actions count
923 ****************************************************************************/
924 int unit_actions::update_actions()
928 current_unit
= head_of_units_in_focus();
930 if (current_unit
== nullptr) {
937 setUpdatesEnabled(false);
940 foreach (a
, actions
) {
946 /* Create possible actions */
948 if (unit_can_add_or_build_city(current_unit
)) {
949 a
= new hud_action(this);
950 a
->action_shortcut
= SC_BUILDCITY
;
951 a
->set_pixmap(fc_icons::instance()->get_pixmap("home"));
956 if (can_unit_do_activity(current_unit
, ACTIVITY_MINE
)) {
957 struct terrain
*pterrain
= tile_terrain(unit_tile(current_unit
));
958 a
= new hud_action(this);
959 a
->action_shortcut
= SC_BUILDMINE
;
961 if (pterrain
->mining_result
!= T_NONE
962 && pterrain
->mining_result
!= pterrain
) {
963 if (!strcmp(terrain_rule_name(pterrain
), "Jungle")
964 || !strcmp(terrain_rule_name(pterrain
), "Plains")
965 || !strcmp(terrain_rule_name(pterrain
), "Grassland")
966 || !strcmp(terrain_rule_name(pterrain
), "Swamp")) {
967 a
->set_pixmap(fc_icons::instance()->get_pixmap("plantforest"));
969 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
972 a
->set_pixmap(fc_icons::instance()->get_pixmap("mine"));
976 if (can_unit_do_activity(current_unit
, ACTIVITY_IRRIGATE
)) {
977 struct terrain
*pterrain
= tile_terrain(unit_tile(current_unit
));
978 a
= new hud_action(this);
979 a
->action_shortcut
= SC_BUILDIRRIGATION
;
980 if (pterrain
->irrigation_result
!= T_NONE
981 && pterrain
->irrigation_result
!= pterrain
) {
982 if ((!strcmp(terrain_rule_name(pterrain
), "Forest") ||
983 !strcmp(terrain_rule_name(pterrain
), "Jungle"))) {
984 a
->set_pixmap(fc_icons::instance()->get_pixmap("chopchop"));
986 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
989 a
->set_pixmap(fc_icons::instance()->get_pixmap("irrigation"));
994 if (can_unit_do_activity(current_unit
, ACTIVITY_TRANSFORM
)) {
995 a
= new hud_action(this);
996 a
->action_shortcut
= SC_TRANSFORM
;
997 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
1004 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
1005 struct road_type
*proad
= extra_road_get(pextra
);
1006 if (can_build_road(proad
, current_unit
, unit_tile(current_unit
))) {
1010 extra_type_by_cause_iterate_end
;
1012 a
= new hud_action(this);
1013 a
->action_shortcut
= SC_BUILDROAD
;
1014 a
->set_pixmap(fc_icons::instance()->get_pixmap("buildroad"));
1019 a
= new hud_action(this);
1020 a
->action_shortcut
= SC_GOTO
;
1021 a
->set_pixmap(fc_icons::instance()->get_pixmap("goto"));
1025 if (can_unit_do_activity(current_unit
, ACTIVITY_FORTIFYING
)) {
1026 a
= new hud_action(this);
1027 a
->action_shortcut
= SC_FORTIFY
;
1028 a
->set_pixmap(fc_icons::instance()->get_pixmap("fortify"));
1033 if (can_unit_do_activity(current_unit
, ACTIVITY_SENTRY
)) {
1034 a
= new hud_action(this);
1035 a
->action_shortcut
= SC_SENTRY
;
1036 a
->set_pixmap(fc_icons::instance()->get_pixmap("sentry"));
1041 if (unit_can_load(current_unit
)) {
1042 a
= new hud_action(this);
1043 a
->action_shortcut
= SC_LOAD
;
1044 a
->set_pixmap(fc_icons::instance()->get_pixmap("load"));
1049 if (tile_city(unit_tile(current_unit
))) {
1050 if (can_unit_change_homecity_to(current_unit
,
1051 tile_city(unit_tile(current_unit
)))) {
1052 a
= new hud_action(this);
1053 a
->action_shortcut
= SC_SETHOME
;
1054 a
->set_pixmap(fc_icons::instance()->get_pixmap("set_homecity"));
1060 if (UU_OK
== unit_upgrade_test(current_unit
, FALSE
)) {
1061 a
= new hud_action(this);
1062 a
->action_shortcut
= SC_UPGRADE_UNIT
;
1063 a
->set_pixmap(fc_icons::instance()->get_pixmap("upgrade"));
1068 if (can_unit_do_autosettlers(current_unit
)) {
1069 a
= new hud_action(this);
1070 a
->action_shortcut
= SC_AUTOMATE
;
1071 a
->set_pixmap(fc_icons::instance()->get_pixmap("automate"));
1076 if (can_unit_paradrop(current_unit
)) {
1077 a
= new hud_action(this);
1078 a
->action_shortcut
= SC_PARADROP
;
1079 a
->set_pixmap(fc_icons::instance()->get_pixmap("paradrop"));
1083 /* Clean pollution */
1084 if (can_unit_do_activity(current_unit
, ACTIVITY_POLLUTION
)) {
1085 a
= new hud_action(this);
1086 a
->action_shortcut
= SC_PARADROP
;
1087 a
->set_pixmap(fc_icons::instance()->get_pixmap("pollution"));
1092 if (unit_transported(current_unit
)
1093 && can_unit_unload(current_unit
, unit_transport_get(current_unit
))
1094 && can_unit_exist_at_tile(&(wld
.map
), current_unit
,
1095 unit_tile(current_unit
))) {
1096 a
= new hud_action(this);
1097 a
->action_shortcut
= SC_UNLOAD
;
1098 a
->set_pixmap(fc_icons::instance()->get_pixmap("unload"));
1103 if (unit_can_do_action(current_unit
, ACTION_NUKE
)) {
1104 a
= new hud_action(this);
1105 a
->action_shortcut
= SC_NUKE
;
1106 a
->set_pixmap(fc_icons::instance()->get_pixmap("nuke"));
1111 a
= new hud_action(this);
1112 a
->action_shortcut
= SC_WAIT
;
1113 a
->set_pixmap(fc_icons::instance()->get_pixmap("wait"));
1117 a
= new hud_action(this);
1118 a
->action_shortcut
= SC_DONE_MOVING
;
1119 a
->set_pixmap(fc_icons::instance()->get_pixmap("done"));
1123 foreach (a
, actions
) {
1124 a
->setToolTip(gui()->menu_bar
->shortcut_2_menustring(a
->action_shortcut
));
1125 a
->setFixedHeight(height());
1126 a
->setFixedWidth(height());
1127 layout
->addWidget(a
);
1130 setFixedWidth(actions
.count() * height());
1131 setUpdatesEnabled(true);
1135 return actions
.count();
1138 /****************************************************************************
1139 Cleans layout - run it before layout initialization
1140 ****************************************************************************/
1141 void unit_actions::clear_layout()
1143 int i
= actions
.count();
1147 setUpdatesEnabled(false);
1148 for (j
= 0; j
< i
; j
++) {
1150 layout
->removeWidget(ui
);
1153 while (!actions
.empty()) {
1154 actions
.removeFirst();
1156 setUpdatesEnabled(true);
1159 /****************************************************************************
1160 Constructor for widget allowing loading units on transports
1161 ****************************************************************************/
1162 hud_unit_loader::hud_unit_loader(struct unit
*pcargo
, struct tile
*ptile
)
1164 setProperty("showGrid", "false");
1165 setProperty("selectionBehavior", "SelectRows");
1166 setEditTriggers(QAbstractItemView::NoEditTriggers
);
1167 setSelectionMode(QAbstractItemView::SingleSelection
);
1168 verticalHeader()->setVisible(false);
1169 horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents
);
1170 horizontalHeader()->setVisible(false);
1171 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1172 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1173 connect(selectionModel(),
1174 SIGNAL(selectionChanged(const QItemSelection
&,
1175 const QItemSelection
&)), this,
1176 SLOT(selection_changed(const QItemSelection
&,
1177 const QItemSelection
&)));
1183 /****************************************************************************
1184 Destructor for units loader
1185 ****************************************************************************/
1186 hud_unit_loader::~hud_unit_loader()
1191 /****************************************************************************
1192 Shows unit loader, adds possible tranportsand units to table
1193 Calculates table size
1194 ****************************************************************************/
1195 void hud_unit_loader::show_me()
1197 QTableWidgetItem
*new_item
;
1203 unit_list_iterate(qtile
->units
, ptransport
) {
1204 if (can_unit_transport(ptransport
, cargo
)
1205 && get_transporter_occupancy(ptransport
)
1206 < get_transporter_capacity(ptransport
)) {
1207 transports
.append(ptransport
);
1208 max_size
= qMax(max_size
, get_transporter_occupancy(ptransport
));
1210 } unit_list_iterate_end
;
1212 setRowCount(transports
.count());
1213 setColumnCount(max_size
+ 1);
1214 for (i
= 0 ; i
< transports
.count(); i
++) {
1216 spite
= get_unittype_sprite(tileset
, transports
.at(i
)->utype
,
1217 direction8_invalid());
1218 str
= utype_rule_name(transports
.at(i
)->utype
);
1219 /* TRANS: MP - just movement points */
1221 + QString(move_points_text(transports
.at(i
)->moves_left
, false))
1223 new_item
= new QTableWidgetItem(QIcon(*spite
->pm
), str
);
1224 setItem(i
, 0, new_item
);
1226 unit_list_iterate(transports
.at(i
)->transporting
, tunit
) {
1227 spite
= get_unittype_sprite(tileset
, tunit
->utype
,
1228 direction8_invalid());
1229 new_item
= new QTableWidgetItem(QIcon(*spite
->pm
), "");
1230 setItem(i
, j
, new_item
);
1232 } unit_list_iterate_end
;
1235 w
= verticalHeader()->width() + 4;
1236 for (i
= 0; i
< columnCount(); i
++) {
1237 w
+= columnWidth(i
);
1239 h
= horizontalHeader()->height() + 4;
1240 for (i
= 0; i
< rowCount(); i
++) {
1245 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
1246 | Qt::FramelessWindowHint
);
1250 /****************************************************************************
1251 Selects given tranport and closes widget
1252 ****************************************************************************/
1253 void hud_unit_loader::selection_changed(const QItemSelection
& s1
,
1254 const QItemSelection
& s2
)
1258 curr_row
= s1
.indexes().at(0).row();
1259 request_unit_load(cargo
, transports
.at(curr_row
), qtile
);
1263 /****************************************************************************
1264 Constructor for unit_hud_selector
1265 ****************************************************************************/
1266 unit_hud_selector::unit_hud_selector(QWidget
*parent
) : QFrame(parent
)
1268 QHBoxLayout
*hbox
, *hibox
;
1269 Unit_type_id utype_id
;
1271 QVBoxLayout
*groupbox_layout
;
1274 struct unit
*punit
= head_of_units_in_focus();
1276 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
1277 | Qt::FramelessWindowHint
);
1278 main_layout
= new QVBoxLayout(this);
1280 unit_sel_type
= new QComboBox();
1282 unit_type_iterate(utype
) {
1283 utype_id
= utype_index(utype
);
1284 if (has_player_unit_type(utype_id
)) {
1285 unit_sel_type
->addItem(utype_name_translation(utype
), utype_id
);
1288 unit_type_iterate_end
;
1292 i
= unit_sel_type
->findText(utype_name_translation(punit
->utype
));
1293 unit_sel_type
->setCurrentIndex(i
);
1295 no_name
= new QGroupBox();
1296 no_name
->setTitle(_("Unit type"));
1297 this_type
= new QRadioButton(_("Selected type"), no_name
);
1298 this_type
->setChecked(true);
1299 any_type
= new QRadioButton(_("All types"), no_name
);
1300 connect(unit_sel_type
, SIGNAL(currentIndexChanged(int)), this,
1301 SLOT(select_units(int)));
1302 connect(this_type
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1303 connect(any_type
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1304 groupbox_layout
= new QVBoxLayout
;
1305 groupbox_layout
->addWidget(unit_sel_type
);
1306 groupbox_layout
->addWidget(this_type
);
1307 groupbox_layout
->addWidget(any_type
);
1308 no_name
->setLayout(groupbox_layout
);
1309 hibox
= new QHBoxLayout
;
1310 hibox
->addWidget(no_name
);
1312 no_name
= new QGroupBox();
1313 no_name
->setTitle(_("Unit activity"));
1314 any_activity
= new QRadioButton(_("Any activity"), no_name
);
1315 any_activity
->setChecked(true);
1316 fortified
= new QRadioButton(_("Fortified"), no_name
);
1317 idle
= new QRadioButton(_("Idle"), no_name
);
1318 sentried
= new QRadioButton(_("Sentried"), no_name
);
1319 connect(any_activity
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1320 connect(idle
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1321 connect(fortified
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1322 connect(sentried
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1323 groupbox_layout
= new QVBoxLayout
;
1324 groupbox_layout
->addWidget(any_activity
);
1325 groupbox_layout
->addWidget(idle
);
1326 groupbox_layout
->addWidget(fortified
);
1327 groupbox_layout
->addWidget(sentried
);
1328 no_name
->setLayout(groupbox_layout
);
1329 hibox
->addWidget(no_name
);
1330 main_layout
->addLayout(hibox
);
1332 no_name
= new QGroupBox();
1333 no_name
->setTitle(_("Unit HP and MP"));
1334 any
= new QRadioButton(_("Any unit"), no_name
);
1335 full_hp
= new QRadioButton(_("Full HP"), no_name
);
1336 full_mp
= new QRadioButton(_("Full MP"), no_name
);
1337 full_hp_mp
= new QRadioButton(_("Full HP and MP"), no_name
);
1338 full_hp_mp
->setChecked(true);
1339 connect(any
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1340 connect(full_hp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1341 connect(full_mp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1342 connect(full_hp_mp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1343 groupbox_layout
= new QVBoxLayout
;
1344 groupbox_layout
->addWidget(any
);
1345 groupbox_layout
->addWidget(full_hp
);
1346 groupbox_layout
->addWidget(full_mp
);
1347 groupbox_layout
->addWidget(full_hp_mp
);
1348 no_name
->setLayout(groupbox_layout
);
1349 hibox
= new QHBoxLayout
;
1350 hibox
->addWidget(no_name
);
1352 no_name
= new QGroupBox();
1353 no_name
->setTitle(_("Location"));
1354 everywhere
= new QRadioButton(_("Everywhere"), no_name
);
1355 this_tile
= new QRadioButton(_("Current tile"), no_name
);
1356 this_continent
= new QRadioButton(_("Current continent"), no_name
);
1357 main_continent
= new QRadioButton(_("Main continent"), no_name
);
1358 groupbox_layout
= new QVBoxLayout
;
1361 this_tile
->setChecked(true);
1363 this_tile
->setDisabled(true);
1364 this_continent
->setDisabled(true);
1365 main_continent
->setChecked(true);
1368 groupbox_layout
->addWidget(this_tile
);
1369 groupbox_layout
->addWidget(this_continent
);
1370 groupbox_layout
->addWidget(main_continent
);
1371 groupbox_layout
->addWidget(everywhere
);
1373 no_name
->setLayout(groupbox_layout
);
1374 hibox
->addWidget(no_name
);
1375 main_layout
->addLayout(hibox
);
1377 select
= new QPushButton(_("Select"));
1378 cancel
= new QPushButton(_("Cancel"));
1379 connect(everywhere
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1380 connect(this_tile
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1381 connect(this_continent
, SIGNAL(toggled(bool)), this,
1382 SLOT(select_units(bool)));
1383 connect(main_continent
, SIGNAL(toggled(bool)), this,
1384 SLOT(select_units(bool)));
1385 connect(select
, SIGNAL(clicked()), this, SLOT(uhs_select()));
1386 connect(cancel
, SIGNAL(clicked()), this, SLOT(uhs_cancel()));
1387 hbox
= new QHBoxLayout
;
1388 hbox
->addWidget(cancel
);
1389 hbox
->addWidget(select
);
1391 result_label
.setAlignment(Qt::AlignCenter
);
1392 main_layout
->addWidget(&result_label
, Qt::AlignHCenter
);
1393 main_layout
->addLayout(hbox
);
1394 setLayout(main_layout
);
1398 /****************************************************************************
1399 Shows and moves to center unit_hud_selector
1400 ****************************************************************************/
1401 void unit_hud_selector::show_me()
1405 p
= QPoint((parentWidget()->width() - sizeHint().width()) / 2,
1406 (parentWidget()->height() - sizeHint().height()) / 2);
1407 p
= parentWidget()->mapToGlobal(p
);
1414 /****************************************************************************
1415 Unit_hud_selector destructor
1416 ****************************************************************************/
1417 unit_hud_selector::~unit_hud_selector()
1422 /****************************************************************************
1423 Selects and closes widget
1424 ****************************************************************************/
1425 void unit_hud_selector::uhs_select()
1427 const struct player
*pplayer
;
1429 pplayer
= client_player();
1431 unit_list_iterate(pplayer
->units
, punit
) {
1432 if (activity_filter(punit
) && hp_filter(punit
)
1433 && island_filter(punit
) && type_filter(punit
)) {
1434 unit_focus_add(punit
);
1436 } unit_list_iterate_end
;
1440 /****************************************************************************
1441 Closes current widget
1442 ****************************************************************************/
1443 void unit_hud_selector::uhs_cancel()
1448 /****************************************************************************
1449 Shows number of selected units on label
1450 ****************************************************************************/
1451 void unit_hud_selector::select_units(int x
)
1454 const struct player
*pplayer
;
1456 pplayer
= client_player();
1458 unit_list_iterate(pplayer
->units
, punit
) {
1459 if (activity_filter(punit
) && hp_filter(punit
)
1460 && island_filter(punit
) && type_filter(punit
)) {
1463 } unit_list_iterate_end
;
1464 result_label
.setText(QString(PL_("%1 unit", "%1 units", num
)).arg(num
));
1467 /****************************************************************************
1468 Convinient slot for ez connect
1469 ****************************************************************************/
1470 void unit_hud_selector::select_units(bool x
)
1475 /****************************************************************************
1476 Key press event for unit_hud_selector
1477 ****************************************************************************/
1478 void unit_hud_selector::keyPressEvent(QKeyEvent
*event
)
1480 if ((event
->key() == Qt::Key_Return
)
1481 || (event
->key() == Qt::Key_Enter
)) {
1484 if (event
->key() == Qt::Key_Escape
) {
1488 QWidget::keyPressEvent(event
);
1491 /****************************************************************************
1493 ****************************************************************************/
1494 bool unit_hud_selector::activity_filter(struct unit
*punit
)
1496 if ((punit
->activity
== ACTIVITY_FORTIFIED
&& fortified
->isChecked())
1497 || (punit
->activity
== ACTIVITY_SENTRY
&& sentried
->isChecked())
1498 || (punit
->activity
== ACTIVITY_IDLE
&& idle
->isChecked())
1499 || any_activity
->isChecked()) {
1505 /****************************************************************************
1507 ****************************************************************************/
1508 bool unit_hud_selector::hp_filter(struct unit
*punit
)
1510 if ((any
->isChecked()
1511 || (full_mp
->isChecked()
1512 && punit
->moves_left
>= punit
->utype
->move_rate
)
1513 || (full_hp
->isChecked() && punit
->hp
>= punit
->utype
->hp
)
1514 || (full_hp_mp
->isChecked() && punit
->hp
>= punit
->utype
->hp
1515 && punit
->moves_left
>= punit
->utype
->move_rate
))) {
1521 /****************************************************************************
1523 ****************************************************************************/
1524 bool unit_hud_selector::island_filter(struct unit
*punit
)
1527 struct unit
*cunit
= head_of_units_in_focus();
1529 if (this_tile
->isChecked() && cunit
) {
1530 if (punit
->tile
== cunit
->tile
) {
1535 if (main_continent
->isChecked() && player_capital(client_player())) {
1536 island
= player_capital(client_player())->tile
->continent
;
1537 } else if (this_continent
->isChecked() && cunit
) {
1538 island
= cunit
->tile
->continent
;
1542 if (punit
->tile
->continent
== island
) {
1547 if (everywhere
->isChecked()) {
1553 /****************************************************************************
1555 ****************************************************************************/
1556 bool unit_hud_selector::type_filter(struct unit
*punit
)
1559 Unit_type_id utype_id
;
1561 if (this_type
->isChecked()) {
1562 qvar
= unit_sel_type
->currentData();
1563 utype_id
= qvar
.toInt();
1564 if (utype_id
== utype_index(punit
->utype
)) {
1570 if (any_type
->isChecked()) {
1576 /****************************************************************************
1577 Tooltip text for terrain information
1578 ****************************************************************************/
1579 QString
popup_terrain_info(struct tile
*ptile
)
1582 struct terrain
*terr
;
1583 QString ret
, t
, move_text
;
1584 bool has_road
= false;
1586 terr
= ptile
->terrain
;
1587 ret
= QString(_("Terrain: %1\n")).arg(tile_get_info_text(ptile
, TRUE
, 0));
1588 ret
= ret
+ QString(_("Food/Prod/Trade: %1\n"))
1589 .arg(get_tile_output_text(ptile
));
1590 t
= get_infrastructure_text(ptile
->extras
);
1592 ret
= ret
+ QString(_("Infrastructure: %1\n")).arg(t
);
1594 ret
= ret
+ QString(_("Defense bonus: %1%\n")).arg(terr
->defense_bonus
);
1595 movement_cost
= terr
->movement_cost
;
1597 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
1598 struct road_type
*proad
= extra_road_get(pextra
);
1600 if (tile_has_road(ptile
, proad
)) {
1601 if (proad
->move_cost
<= movement_cost
) {
1603 move_text
= move_points_text(proad
->move_cost
, TRUE
);
1604 movement_cost
= proad
->move_cost
;
1607 } extra_type_by_cause_iterate_end
;
1609 if (has_road
== true) {
1610 ret
= ret
+ QString(_("Movement cost: %1")).arg(move_text
);
1612 ret
= ret
+ QString(_("Movement cost: %1")).arg(movement_cost
);
1618 /****************************************************************************
1619 Shows new turn information with big font
1620 ****************************************************************************/
1621 void show_new_turn_info()
1625 QList
<hud_text
*> close_list
;
1626 struct research
*research
;
1629 if (client_has_player() == false
1630 || gui()->qt_settings
.show_new_turn_text
== false) {
1633 close_list
= gui()->mapview_wdg
->findChildren
<hud_text
*>();
1634 for (i
= 0; i
< close_list
.size(); ++i
) {
1635 close_list
.at(i
)->close();
1636 close_list
.at(i
)->deleteLater();
1638 research
= research_get(client_player());
1639 s
= QString(_("Year: %1 (Turn: %2)"))
1640 .arg(calendar_text()).arg(game
.info
.turn
) + "\n";
1641 s
= s
+ QString(nation_plural_for_player(client_player()));
1642 s
= s
+ " - " + QString(_("Population: %1"))
1643 .arg(population_to_text(civ_population(client
.conn
.playing
)));
1644 if (research
->researching
!= A_UNKNOWN
1645 && research
->researching
!= A_UNSET
1646 && research
->researching
!= A_NONE
) {
1647 s
= s
+ "\n" + QString(research_advance_name_translation(research
,
1648 research
->researching
)) +
1649 " (" + QString::number(research
->bulbs_researched
) + "/"
1650 + QString::number(research
->client
.researching_cost
) + ")";
1652 s
= s
+ "\n" + science_dialog_text() + "\n";
1653 s
= s
+ QString(_("Gold: %1 (+%2)"))
1654 .arg(client
.conn
.playing
->economic
.gold
)
1655 .arg(player_get_expected_income(client
.conn
.playing
));
1656 ht
= new hud_text(s
, 5, gui()->mapview_wdg
);
1660 /****************************************************************************
1661 Hud unit combat contructor, prepares images to show as result
1662 ****************************************************************************/
1663 hud_unit_combat::hud_unit_combat(int attacker_unit_id
, int defender_unit_id
,
1664 int attacker_hp
, int defender_hp
,
1665 bool make_winner_veteran
,
1666 QWidget
*parent
) : QWidget(parent
)
1668 QImage crdimg
, acrimg
, at
, dt
;
1671 struct canvas
*defender_pixmap
;
1672 struct canvas
*attacker_pixmap
;
1675 w
= 3 * tileset_unit_height(tileset
) / 2;
1676 att_hp
= attacker_hp
;
1677 def_hp
= defender_hp
;
1679 winner_veteran
= make_winner_veteran
;
1680 attacker
= game_unit_by_number(attacker_unit_id
);
1681 defender
= game_unit_by_number(defender_unit_id
);
1682 att_hp_loss
= attacker
->hp
- att_hp
;
1683 def_hp_loss
= defender
->hp
- def_hp
;
1684 if (defender_hp
== 0) {
1686 winner_tile
= attacker
->tile
;
1689 winner_tile
= defender
->tile
;
1691 setSizePolicy(QSizePolicy::Ignored
, QSizePolicy::Ignored
);
1692 setFixedSize(2 * w
, w
);
1695 defender_pixmap
= qtg_canvas_create(tileset_unit_width(tileset
),
1696 tileset_unit_height(tileset
));
1697 defender_pixmap
->map_pixmap
.fill(Qt::transparent
);
1698 if (defender
!= nullptr) {
1699 put_unit(defender
, defender_pixmap
, 1.0, 0, 0);
1700 dimg
= defender_pixmap
->map_pixmap
.toImage();
1701 dr
= zealous_crop_rect(dimg
);
1702 crdimg
= dimg
.copy(dr
);
1703 dimg
= crdimg
.scaledToHeight(w
, Qt::SmoothTransformation
);
1705 if (dimg
.width() < w
) {
1706 dt
= QImage(w
, dimg
.height(), QImage::Format_ARGB32_Premultiplied
);
1707 dt
.fill(Qt::transparent
);
1709 p
.drawImage(w
/ 2 - dimg
.width() / 2, 0, dimg
);
1713 dimg
= dimg
.scaled(w
, w
, Qt::IgnoreAspectRatio
,
1714 Qt::SmoothTransformation
);
1715 attacker_pixmap
= qtg_canvas_create(tileset_unit_width(tileset
),
1716 tileset_unit_height(tileset
));
1717 attacker_pixmap
->map_pixmap
.fill(Qt::transparent
);
1718 if (attacker
!= nullptr) {
1719 put_unit(attacker
, attacker_pixmap
, 1, 0, 0);
1720 aimg
= attacker_pixmap
->map_pixmap
.toImage();
1721 ar
= zealous_crop_rect(aimg
);
1722 acrimg
= aimg
.copy(ar
);
1723 aimg
= acrimg
.scaledToHeight(w
, Qt::SmoothTransformation
);
1725 if (aimg
.width() < w
) {
1726 at
= QImage(w
, dimg
.height(), QImage::Format_ARGB32_Premultiplied
);
1727 at
.fill(Qt::transparent
);
1729 p
.drawImage(w
/ 2 - aimg
.width() / 2, 0, aimg
);
1733 aimg
= aimg
.scaled(w
, w
, Qt::IgnoreAspectRatio
,
1734 Qt::SmoothTransformation
);
1737 /****************************************************************************
1738 Hud unit combat destructor
1739 ****************************************************************************/
1740 hud_unit_combat::~hud_unit_combat()
1744 /****************************************************************************
1746 ****************************************************************************/
1747 void hud_unit_combat::set_fading(float fade
)
1753 /****************************************************************************
1754 Returns true if widget has focus (used to prevent hiding parent)
1755 ****************************************************************************/
1756 bool hud_unit_combat::get_focus()
1761 /****************************************************************************
1762 Paint event for hud_unit combat
1763 ****************************************************************************/
1764 void hud_unit_combat::paintEvent(QPaintEvent
*event
)
1770 QFont f
= *fc_font::instance()->get_font(fonts::default_font
);
1771 QString ahploss
, dhploss
;
1772 if (att_hp_loss
> 0) {
1773 ahploss
= "-" + QString::number(att_hp_loss
);
1777 if (def_hp_loss
> 0) {
1778 dhploss
= "-" + QString::number(def_hp_loss
);
1785 c1
= QColor(25, 125, 25, 175);
1786 c2
= QColor(125, 25, 25, 175);
1788 c1
= QColor(125, 25, 25, 175);
1789 c2
= QColor(25, 125, 25, 175);
1791 int w
= 3 * tileset_unit_height(tileset
) / 2;
1793 left
= QRect(0 , 0, w
, w
);
1794 right
= QRect(w
, 0, w
, w
);
1795 pen
= QPen(QColor(palette().color(QPalette::AlternateBase
)), 2.0);
1798 p
.setOpacity(fading
);
1800 if (focus
== true) {
1801 p
.fillRect(left
, QColor(palette().color(QPalette::Highlight
)));
1802 p
.fillRect(right
, QColor(palette().color(QPalette::Highlight
)));
1806 p
.fillRect(left
, c1
);
1807 p
.fillRect(right
, c2
);
1809 p
.drawRect(1, 1, width() - 2 , height() - 2);
1810 p
.drawImage(left
, aimg
);
1812 p
.setPen(QColor(Qt::white
));
1813 if (winner
== defender
&& winner_veteran
) {
1814 p
.drawText(right
, Qt::AlignHCenter
| Qt::AlignJustify
1815 | Qt::AlignAbsolute
, "*");
1817 if (winner
== attacker
&& winner_veteran
) {
1818 p
.drawText(left
, Qt::AlignHCenter
| Qt::AlignJustify
1819 | Qt::AlignAbsolute
, "*");
1821 p
.drawText(left
, Qt::AlignHorizontal_Mask
, ahploss
);
1822 p
.drawImage(right
, dimg
);
1823 p
.drawText(right
, Qt::AlignHorizontal_Mask
, dhploss
);
1827 /****************************************************************************
1828 Mouse press event, centers on highlighted combat
1829 ****************************************************************************/
1830 void hud_unit_combat::mousePressEvent(QMouseEvent
*e
)
1832 center_tile_mapcanvas(winner_tile
);
1835 /****************************************************************************
1836 Leave event for hud unit combat. Stops showing highlight.
1837 ****************************************************************************/
1838 void hud_unit_combat::leaveEvent(QEvent
*event
)
1844 /****************************************************************************
1845 Leave event for hud unit combat. Shows highlight.
1846 ****************************************************************************/
1847 void hud_unit_combat::enterEvent(QEvent
*event
)
1853 /****************************************************************************
1854 Hud battle log contructor
1855 ****************************************************************************/
1856 hud_battle_log::hud_battle_log(QWidget
*parent
) : QWidget(parent
)
1858 setSizePolicy(QSizePolicy::Ignored
, QSizePolicy::Ignored
);
1859 main_layout
= new QVBoxLayout
;
1860 mw
= new move_widget(this);
1861 setContentsMargins(0, 0, 0, 0);
1862 main_layout
->setContentsMargins(0, 0, 0, 0);
1865 /****************************************************************************
1866 Hud battle log destructor
1867 ****************************************************************************/
1868 hud_battle_log::~hud_battle_log()
1872 /****************************************************************************
1873 Adds comabt information to battle log
1874 ****************************************************************************/
1875 void hud_battle_log::add_combat_info(hud_unit_combat
*huc
)
1877 hud_unit_combat
*hudc
;
1878 int w
= 3 * tileset_unit_height(tileset
) / 2;
1881 main_layout
= new QVBoxLayout
;
1883 while (lhuc
.count() > 5) {
1884 hudc
= lhuc
.takeLast();
1887 foreach (hudc
, lhuc
) {
1888 main_layout
->addWidget(hudc
);
1889 hudc
->set_fading(1.0);
1891 setFixedSize(2 * w
+ 10, lhuc
.count() * w
+ 10);
1892 setLayout(main_layout
);
1900 /****************************************************************************
1901 Paint event for hud battle log
1902 ****************************************************************************/
1903 void hud_battle_log::paintEvent(QPaintEvent
*event
)
1905 mw
->put_to_corner();
1908 /****************************************************************************
1909 Move event, saves current position
1910 ****************************************************************************/
1911 void hud_battle_log::moveEvent(QMoveEvent
*event
)
1915 gui()->qt_settings
.battlelog_x
= static_cast<float>(p
.x()) / mapview
.width
;
1916 gui()->qt_settings
.battlelog_y
= static_cast<float>(p
.y())
1920 /****************************************************************************
1921 Timer event. Starts/stops fading
1922 ****************************************************************************/
1923 void hud_battle_log::timerEvent(QTimerEvent
*event
)
1925 hud_unit_combat
*hudc
;
1926 hud_unit_combat
*hupdate
;
1927 if (m_timer
.elapsed() > 4000 && m_timer
.elapsed() < 5000) {
1928 foreach (hudc
, lhuc
) {
1929 if (hudc
->get_focus() == true) {
1931 foreach (hupdate
, lhuc
) {
1932 hupdate
->set_fading(1.0);
1936 hudc
->set_fading((5000.0 - m_timer
.elapsed()) / 1000);
1939 if (m_timer
.elapsed() >= 5000) {
1944 /****************************************************************************
1945 Show event, restart fading timer
1946 ****************************************************************************/
1947 void hud_battle_log::showEvent(QShowEvent
*event
)
1949 hud_unit_combat
*hupdate
;
1950 foreach (hupdate
, lhuc
) {
1951 hupdate
->set_fading(1.0);