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>
24 #include <QHBoxLayout>
25 #include <QHeaderView>
28 #include <QPaintEvent>
29 #include <QRadioButton>
30 #include <QSpacerItem>
31 #include <QVBoxLayout>
44 #include "hudwidget.h"
46 #include "qtg_cxxside.h"
50 const char *calendar_text(void);
52 static QString
popup_terrain_info(struct tile
*ptile
);
54 /***************************************************************************
55 Returns true if player has any unit of unit_type
56 ***************************************************************************/
57 bool has_player_unit_type(Unit_type_id utype
)
59 unit_list_iterate(client
.conn
.playing
->units
, punit
) {
60 if (utype_number(punit
->utype
) == utype
) {
63 } unit_list_iterate_end
;
68 /****************************************************************************
69 Custom message box constructor
70 ****************************************************************************/
71 hud_message_box::hud_message_box(QWidget
*parent
): QMessageBox(parent
)
74 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
75 | Qt::FramelessWindowHint
);
76 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
77 f_title
= *fc_font::instance()->get_font(fonts::default_font
);
79 size
= f_text
.pointSize();
81 f_text
.setPointSize(size
* 4 / 3);
82 f_title
.setPointSize(size
* 3 / 2);
84 size
= f_text
.pixelSize();
85 f_text
.setPixelSize(size
* 4 / 3);
86 f_title
.setPointSize(size
* 3 / 2);
88 f_title
.setBold(true);
89 f_title
.setCapitalization(QFont::SmallCaps
);
90 fm_text
= new QFontMetrics(f_text
);
91 fm_title
= new QFontMetrics(f_title
);
98 /****************************************************************************
99 Custom message box destructor
100 ****************************************************************************/
101 hud_message_box::~hud_message_box()
106 /****************************************************************************
107 Key press event for hud message box
108 ****************************************************************************/
109 void hud_message_box::keyPressEvent(QKeyEvent
*event
)
111 if (event
->key() == Qt::Key_Escape
) {
116 QWidget::keyPressEvent(event
);
119 /****************************************************************************
120 Sets text and title and shows message box
121 ****************************************************************************/
122 void hud_message_box::set_text_title(QString s1
, QString s2
)
129 if (s1
.contains('\n')) {
131 i
= s1
.indexOf('\n');
133 cs2
= s1
.right(s1
.count() - i
);
135 w2
= qMax(fm_text
->width(cs1
), fm_text
->width(cs2
));
136 w
= qMax(w2
, fm_title
->width(s2
));
138 w
= qMax(fm_text
->width(s1
), fm_title
->width(s2
));
141 h
= mult
* (fm_text
->height() * 3 / 2) + 2 * fm_title
->height();
142 top
= 2 * fm_title
->height();
143 spacer
= new QSpacerItem(w
, 0, QSizePolicy::Minimum
,
144 QSizePolicy::Expanding
);
145 layout
= (QGridLayout
*)this->layout();
146 layout
->addItem(spacer
, layout
->rowCount(), 0, 1, layout
->columnCount());
147 spacer
= new QSpacerItem(0, h
, QSizePolicy::Expanding
,
148 QSizePolicy::Minimum
);
149 layout
->addItem(spacer
, 0, 0, 1, layout
->columnCount());
154 p
= QPoint((parentWidget()->width() - w
) / 2,
155 (parentWidget()->height() - h
) / 2);
156 p
= parentWidget()->mapToGlobal(p
);
163 /****************************************************************************
164 Timer event used to animate message box
165 ****************************************************************************/
166 void hud_message_box::timerEvent(QTimerEvent
*event
)
168 m_animate_step
= m_timer
.elapsed() / 40;
172 /****************************************************************************
173 Paint event for custom message box
174 ****************************************************************************/
175 void hud_message_box::paintEvent(QPaintEvent
*event
)
184 step
= m_animate_step
% 300;
191 rfull
= QRect(2 , 2, width() - 4 , height() - 4);
192 rx
= QRect(2 , 2, width() - 4 , top
);
193 ry
= QRect(2 , top
, width() - 4, height() - top
- 4);
195 c1
= QColor(palette().color(QPalette::Highlight
));
196 c2
= QColor(palette().color(QPalette::AlternateBase
));
197 step
= qMax(0, step
);
198 step
= qMin(255, step
);
202 g
= QLinearGradient(0 , 0, width(), height());
207 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
208 p
.fillRect(ry
, QColor(palette().color(QPalette::AlternateBase
)));
209 p
.fillRect(rfull
, g
);
211 p
.drawText((width() - fm_title
->width(title
)) / 2,
212 fm_title
->height() * 4 / 3, title
);
215 p
.drawText((width() - fm_text
->width(text
)) / 2,
216 2 * fm_title
->height() + fm_text
->height() * 4 / 3, text
);
218 p
.drawText((width() - fm_text
->width(cs1
)) / 2,
219 2 * fm_title
->height() + fm_text
->height() * 4 / 3, cs1
);
220 p
.drawText((width() - fm_text
->width(cs2
)) / 2,
221 2 * fm_title
->height() + fm_text
->height() * 8 / 3, cs2
);
227 /****************************************************************************
228 Hud text constructor takes text to display and time
229 ****************************************************************************/
230 hud_text::hud_text(QString s
, int time_secs
,
231 QWidget
*parent
) : QWidget(parent
)
238 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
239 | Qt::FramelessWindowHint
);
240 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
241 f_text
.setBold(true);
242 f_text
.setCapitalization(QFont::SmallCaps
);
243 size
= f_text
.pointSize();
245 f_text
.setPointSize(size
* 2);
247 size
= f_text
.pixelSize();
248 f_text
.setPixelSize(size
* 2);
250 fm_text
= new QFontMetrics(f_text
);
254 setAttribute(Qt::WA_TranslucentBackground
);
255 setAttribute(Qt::WA_ShowWithoutActivating
);
256 setFocusPolicy(Qt::NoFocus
);
259 /****************************************************************************
261 ****************************************************************************/
262 void hud_text::show_me()
268 /****************************************************************************
269 Moves to top center parent widget and sets size new size
270 ****************************************************************************/
271 void hud_text::center_me()
276 if (bound_rect
.isEmpty() == false) {
277 setFixedSize(bound_rect
.width(), bound_rect
.height());
279 p
= QPoint((parentWidget()->width() - w
) / 2,
280 parentWidget()->height() / 10);
281 p
= parentWidget()->mapToGlobal(p
);
285 /****************************************************************************
286 Destructor for hud text
287 ****************************************************************************/
288 hud_text::~hud_text()
293 /****************************************************************************
294 Timer event, closes widget after timeout
295 ****************************************************************************/
296 void hud_text::timerEvent(QTimerEvent
*event
)
298 m_animate_step
= m_timer
.elapsed() / 40;
299 if (m_timer
.elapsed() > timeout
* 1000) {
306 /****************************************************************************
307 Paint event for custom hud_text
308 ****************************************************************************/
309 void hud_text::paintEvent(QPaintEvent
*event
)
318 if (m_timer
.elapsed() < timeout
* 500) {
319 opacity
= static_cast<float>(m_timer
.elapsed())/(timeout
* 300);
321 opacity
= static_cast<float>(5000 - m_timer
.elapsed())/(timeout
* 200);
323 opacity
= qMin(1.0f
, opacity
);
324 opacity
= qMax(0.0f
, opacity
);
325 rfull
= QRect(0 , 0, width(), height());
326 c1
= QColor(Qt::white
);
327 c1
.setAlphaF(c1
.alphaF() * opacity
);
331 p
.drawText(rfull
, Qt::AlignCenter
, text
, &bound_rect
);
336 /****************************************************************************
337 Custom input box constructor
338 ****************************************************************************/
339 hud_input_box::hud_input_box(QWidget
*parent
): QDialog(parent
)
343 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
344 | Qt::FramelessWindowHint
);
346 f_text
= *fc_font::instance()->get_font(fonts::default_font
);
347 f_title
= *fc_font::instance()->get_font(fonts::default_font
);
349 size
= f_text
.pointSize();
351 f_text
.setPointSize(size
* 4 / 3);
352 f_title
.setPointSize(size
* 3 / 2);
354 size
= f_text
.pixelSize();
355 f_text
.setPixelSize(size
* 4 / 3);
356 f_title
.setPointSize(size
* 3 / 2);
358 f_title
.setBold(true);
359 f_title
.setCapitalization(QFont::SmallCaps
);
360 fm_text
= new QFontMetrics(f_text
);
361 fm_title
= new QFontMetrics(f_title
);
368 /****************************************************************************
369 Custom input box destructor
370 ****************************************************************************/
371 hud_input_box::~hud_input_box()
376 /****************************************************************************
377 Sets text, title and default text and shows input box
378 ****************************************************************************/
379 void hud_input_box::set_text_title_definput(QString s1
, QString s2
,
385 QDialogButtonBox
*button_box
;
388 button_box
= new QDialogButtonBox(QDialogButtonBox::Ok
389 | QDialogButtonBox::Cancel
,
390 Qt::Horizontal
, this);
391 layout
= new QVBoxLayout
;
392 if (s1
.contains('\n')) {
394 i
= s1
.indexOf('\n');
396 cs2
= s1
.right(s1
.count() - i
);
398 w2
= qMax(fm_text
->width(cs1
), fm_text
->width(cs2
));
399 w
= qMax(w2
, fm_title
->width(s2
));
401 w
= qMax(fm_text
->width(s1
), fm_title
->width(s2
));
404 h
= mult
* (fm_text
->height() * 3 / 2) + 2 * fm_title
->height();
405 top
= 2 * fm_title
->height();
407 spacer
= new QSpacerItem(w
, h
, QSizePolicy::Expanding
,
408 QSizePolicy::Minimum
);
409 layout
->addItem(spacer
);
410 layout
->addWidget(&input_edit
);
411 layout
->addWidget(button_box
);
412 input_edit
.setFont(f_text
);
413 input_edit
.setText(def_input
);
415 QObject::connect(button_box
, SIGNAL(accepted()), this, SLOT(accept()));
416 QObject::connect(button_box
, SIGNAL(rejected()), this, SLOT(reject()));
420 p
= QPoint((parentWidget()->width() - w
) / 2,
421 (parentWidget()->height() - h
) / 2);
422 p
= parentWidget()->mapToGlobal(p
);
424 input_edit
.activateWindow();
425 input_edit
.setFocus();
432 /****************************************************************************
433 Timer event used to animate input box
434 ****************************************************************************/
435 void hud_input_box::timerEvent(QTimerEvent
*event
)
437 m_animate_step
= m_timer
.elapsed() / 40;
442 /****************************************************************************
443 Paint event for custom input box
444 ****************************************************************************/
445 void hud_input_box::paintEvent(QPaintEvent
*event
)
457 step
= m_animate_step
% 300;
463 rx
= QRect(2 , 2, width() - 4 , top
);
464 ry
= QRect(2 , top
, width() - 4, height() - top
- 4);
466 c1
= QColor(palette().color(QPalette::Highlight
));
467 c2
= QColor(Qt::transparent
);
468 c3
= QColor(palette().color(QPalette::Highlight
)).lighter(145);
469 step
= qMax(0, step
);
470 step
= qMin(255, step
);
475 fstep
= static_cast<float>(step
) / 400;
476 g
= QLinearGradient(0 , 0, width(), height());
478 g
.setColorAt(fstep
, c3
);
482 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
483 p
.fillRect(ry
, QColor(palette().color(QPalette::AlternateBase
)));
486 p
.drawText((width() - fm_title
->width(title
)) / 2,
487 fm_title
->height() * 4 / 3, title
);
490 p
.drawText((width() - fm_text
->width(text
)) / 2,
491 2 * fm_title
->height() + fm_text
->height() * 4 / 3, text
);
493 p
.drawText((width() - fm_text
->width(cs1
)) / 2,
494 2 * fm_title
->height() + fm_text
->height() * 4 / 3, cs1
);
495 p
.drawText((width() - fm_text
->width(cs2
)) / 2,
496 2 * fm_title
->height() + fm_text
->height() * 8 / 3, cs2
);
502 /****************************************************************************
503 Constructor for hud_units (holds layout for whole uunits info)
504 ****************************************************************************/
505 hud_units::hud_units(QWidget
*parent
) : QFrame(parent
)
508 QVBoxLayout
*unit_lab
;
512 main_layout
= new QHBoxLayout
;
513 sp
= new QSpacerItem(50, 2);
514 vbox
= new QVBoxLayout
;
515 unit_lab
= new QVBoxLayout
;
516 unit_lab
->setContentsMargins(6, 9, 0, 3);
518 unit_lab
->addWidget(&unit_label
);
519 main_layout
->addLayout(unit_lab
);
520 main_layout
->addWidget(&tile_label
);
521 unit_icons
= new unit_actions(this, nullptr);
522 vbox
->addSpacerItem(sp
);
523 vbox
->addWidget(&text_label
);
524 vbox
->addWidget(unit_icons
);
525 main_layout
->addLayout(vbox
);
526 main_layout
->setSpacing(0);
527 main_layout
->setSpacing(3);
528 main_layout
->setContentsMargins(0, 0, 0, 0);
530 vbox
->setContentsMargins(0, 0, 0, 0);
531 setLayout(main_layout
);
532 mw
= new move_widget(this);
533 setFocusPolicy(Qt::ClickFocus
);
537 /****************************************************************************
539 ****************************************************************************/
540 hud_units::~hud_units()
545 /****************************************************************************
546 Move Event for hud_units, used to save position
547 ****************************************************************************/
548 void hud_units::moveEvent(QMoveEvent
*event
)
550 if (event
->pos().x() != 0) {
551 gui()->qt_settings
.unit_info_pos_x
= 1 + (event
->pos().x() * 1000)
552 / gui()->mapview_wdg
->width();
554 gui()->qt_settings
.unit_info_pos_x
= 0;
556 if (event
->pos().y() != 0) {
557 gui()->qt_settings
.unit_info_pos_y
= 1 + (event
->pos().y() * 1000)
558 / gui()->mapview_wdg
->height();
560 gui()->qt_settings
.unit_info_pos_y
= 0;
565 /****************************************************************************
566 Update possible action for given units
567 ****************************************************************************/
568 void hud_units::update_actions(unit_list
*punits
)
572 QFont font
= *fc_font::instance()->get_font(fonts::notify_label
);
581 struct canvas
*tile_pixmap
;
582 struct canvas
*unit_pixmap
;
584 struct player
*owner
;
587 punit
= head_of_units_in_focus();
588 if (punit
== nullptr) {
593 font
.setCapitalization(QFont::AllUppercase
);
595 setFixedHeight(parentWidget()->height() / 12);
596 text_label
.setFixedHeight((height() * 2) / 10);
597 move((gui()->mapview_wdg
->width()
598 * gui()->qt_settings
.unit_info_pos_x
) / 1000,
599 (gui()->mapview_wdg
->height()
600 * gui()->qt_settings
.unit_info_pos_y
) / 1000);
601 unit_icons
->setFixedHeight((height() * 8) / 10);
603 setUpdatesEnabled(false);
605 text_str
= QString(unit_name_translation(punit
));
606 owner
= punit
->owner
;
607 pcity
= player_city_by_number(owner
, punit
->homecity
);
609 text_str
= QString(("%1(%2)"))
610 .arg(unit_name_translation(punit
), city_name_get(pcity
));
612 text_str
= text_str
+ " ";
613 mp
= QString(move_points_text(punit
->moves_left
, false));
614 if (utype_fuel(unit_type_get(punit
))) {
615 mp
= mp
+ QString("(") + QString(move_points_text((
616 unit_type_get(punit
)->move_rate
617 * ((punit
->fuel
) - 1)
618 + punit
->moves_left
), false))
621 /* TRANS: MP = Movement points */
622 mp
= QString(_("MP: ")) + mp
;
623 text_str
= text_str
+ mp
+ " ";
624 text_str
+= QString(_("HP:%1/%2")).arg(
625 QString::number(punit
->hp
),
626 QString::number(unit_type_get(punit
)->hp
));
627 num
= unit_list_size(punit
->tile
->units
);
628 snum
= QString::number(unit_list_size(punit
->tile
->units
) - 1);
629 if (unit_list_size(get_units_in_focus()) > 1) {
630 text_str
= text_str
+ QString(_(" (Selected %1 units)"))
631 .arg(unit_list_size(get_units_in_focus()));
632 } else if (num
> 2) {
633 text_str
= text_str
+ QString(_(" +%1 units"))
634 .arg(snum
.toLocal8Bit().data());
635 } else if (num
== 2) {
636 text_str
= text_str
+ QString(_(" +1 unit"));
638 text_label
.setText(text_str
);
639 font
.setPixelSize((text_label
.height() * 9) / 10);
640 text_label
.setFont(font
);
641 fm
= new QFontMetrics(font
);
642 text_label
.setFixedWidth(fm
->width(text_str
) + 20);
645 unit_pixmap
= qtg_canvas_create(tileset_unit_width(tileset
),
646 tileset_unit_height(tileset
));
647 unit_pixmap
->map_pixmap
.fill(Qt::transparent
);
648 put_unit(punit
, unit_pixmap
, 1, 0, 0);
649 img
= unit_pixmap
->map_pixmap
.toImage();
650 crop
= zealous_crop_rect(img
);
651 cropped_img
= img
.copy(crop
);
652 img
= cropped_img
.scaledToHeight(height(), Qt::SmoothTransformation
);
653 pix
= QPixmap::fromImage(img
);
654 wwidth
= 2 * 3 + pix
.width();
655 unit_label
.setPixmap(pix
);
656 if (tileset_is_isometric(tileset
)) {
657 tile_pixmap
= qtg_canvas_create(tileset_full_tile_width(tileset
),
658 tileset_tile_height(tileset
) * 2);
660 tile_pixmap
= qtg_canvas_create(tileset_full_tile_width(tileset
),
661 tileset_tile_height(tileset
));
663 tile_pixmap
->map_pixmap
.fill(QColor(0 , 0 , 0 , 0));
664 put_terrain(punit
->tile
, tile_pixmap
, 1.0, 0, 0);
665 img
= tile_pixmap
->map_pixmap
.toImage();
666 crop
= zealous_crop_rect(img
);
667 cropped_img
= img
.copy(crop
);
668 img
= cropped_img
.scaledToWidth(wwidth
- 10,
669 Qt::SmoothTransformation
);
670 pix
= QPixmap::fromImage(img
);
671 tile_label
.setPixmap(pix
);
672 unit_label
.setToolTip(popup_info_text(punit
->tile
));
673 tile_label
.setToolTip(popup_terrain_info(punit
->tile
));
674 wwidth
= wwidth
+ pix
.width();
675 qtg_canvas_free(tile_pixmap
);
676 qtg_canvas_free(unit_pixmap
);
678 setFixedWidth(wwidth
+ qMax(unit_icons
->update_actions() * (height() * 8)
679 / 10, text_label
.width()));
681 setUpdatesEnabled(true);
688 /****************************************************************************
689 Custom label with extra mouse events
690 ****************************************************************************/
691 click_label::click_label() : QLabel()
693 connect(this, SIGNAL(left_clicked()), SLOT(on_clicked()));
696 /****************************************************************************
697 Mouse event for click_label
698 ****************************************************************************/
699 void click_label::mousePressEvent(QMouseEvent
*e
)
701 if (e
->button() == Qt::LeftButton
) {
706 /****************************************************************************
707 Centers on current unit
708 ****************************************************************************/
709 void click_label::on_clicked()
711 gui()->game_tab_widget
->setCurrentIndex(0);
712 request_center_focus_unit();
715 /****************************************************************************
716 Hud action constructor, used to show one action
717 ****************************************************************************/
718 hud_action::hud_action(QWidget
*parent
) : QWidget(parent
)
720 connect(this, SIGNAL(left_clicked()), SLOT(on_clicked()));
721 setFocusPolicy(Qt::ClickFocus
);
723 action_pixmap
= nullptr;
726 /****************************************************************************
727 Sets given pixmap for hud_action
728 ****************************************************************************/
729 void hud_action::set_pixmap(QPixmap
*p
)
734 /****************************************************************************
735 Custom painting for hud_action
736 ****************************************************************************/
737 void hud_action::paintEvent(QPaintEvent
*event
)
742 rx
= QRect(0, 0, width(), height());
743 ry
= QRect(0, 0, action_pixmap
->width(), action_pixmap
->height());
744 rz
= QRect(0, 0, width() - 1, height() - 3);
746 p
.setCompositionMode(QPainter::CompositionMode_Source
);
747 p
.setRenderHint(QPainter::SmoothPixmapTransform
);
748 p
.drawPixmap(rx
, *action_pixmap
, ry
);
749 p
.setPen(QColor(palette().color(QPalette::Text
)));
752 p
.setCompositionMode(QPainter::CompositionMode_DestinationOver
);
753 p
.fillRect(rx
, QColor(palette().color(QPalette::Highlight
)));
759 /****************************************************************************
760 Hud action destructor
761 ****************************************************************************/
762 hud_action::~hud_action()
765 delete action_pixmap
;
769 /****************************************************************************
770 Mouse press event for hud_action
771 ****************************************************************************/
772 void hud_action::mousePressEvent(QMouseEvent
*e
)
774 if (e
->button() == Qt::RightButton
) {
775 emit
right_clicked();
776 } else if (e
->button() == Qt::LeftButton
) {
781 /****************************************************************************
782 Leave event for hud_action, used to get status of pixmap higlight
783 ****************************************************************************/
784 void hud_action::leaveEvent(QEvent
*event
)
788 QWidget::leaveEvent(event
);
791 /****************************************************************************
792 Enter event for hud_action, used to get status of pixmap higlight
793 ****************************************************************************/
794 void hud_action::enterEvent(QEvent
*event
)
798 QWidget::enterEvent(event
);
801 /****************************************************************************
802 Right click event for hud_action
803 ****************************************************************************/
804 void hud_action::on_right_clicked()
808 /****************************************************************************
809 Left click event for hud_action
810 ****************************************************************************/
811 void hud_action::on_clicked()
813 gui()->menu_bar
->execute_shortcut(action_shortcut
);
816 /****************************************************************************
817 Units action contructor, holds possible hud_actions
818 ****************************************************************************/
819 unit_actions::unit_actions(QWidget
*parent
, unit
*punit
) : QWidget(parent
)
821 layout
= new QHBoxLayout(this);
822 layout
->setSpacing(3);
823 layout
->setContentsMargins(0, 0, 0, 0);
824 current_unit
= punit
;
826 setFocusPolicy(Qt::ClickFocus
);
831 /****************************************************************************
832 Destructor for unit_actions
833 ****************************************************************************/
834 unit_actions::~unit_actions()
841 /****************************************************************************
842 Initiazlizes layout ( layout needs to be changed after adding units )
843 ****************************************************************************/
844 void unit_actions::init_layout()
846 QSizePolicy
size_fixed_policy(QSizePolicy::MinimumExpanding
,
849 setSizePolicy(size_fixed_policy
);
850 layout
->setSpacing(0);
855 /****************************************************************************
856 Updates avaialable actions, returns actions count
857 ****************************************************************************/
858 int unit_actions::update_actions()
862 current_unit
= head_of_units_in_focus();
864 if (current_unit
== nullptr) {
871 setUpdatesEnabled(false);
874 foreach (a
, actions
) {
880 /* Create possible actions */
882 if (unit_can_build_city(current_unit
)) {
883 a
= new hud_action(this);
884 a
->action_shortcut
= SC_BUILDCITY
;
885 a
->set_pixmap(fc_icons::instance()->get_pixmap("home"));
890 if (can_unit_do_activity(current_unit
, ACTIVITY_MINE
)) {
891 struct terrain
*pterrain
= tile_terrain(unit_tile(current_unit
));
892 a
= new hud_action(this);
893 a
->action_shortcut
= SC_BUILDMINE
;
895 if (pterrain
->mining_result
!= T_NONE
896 && pterrain
->mining_result
!= pterrain
) {
897 if (!strcmp(terrain_rule_name(pterrain
), "Jungle")
898 || !strcmp(terrain_rule_name(pterrain
), "Plains")
899 || !strcmp(terrain_rule_name(pterrain
), "Grassland")
900 || !strcmp(terrain_rule_name(pterrain
), "Swamp")) {
901 a
->set_pixmap(fc_icons::instance()->get_pixmap("plantforest"));
903 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
906 a
->set_pixmap(fc_icons::instance()->get_pixmap("mine"));
910 if (can_unit_do_activity(current_unit
, ACTIVITY_IRRIGATE
)) {
911 struct terrain
*pterrain
= tile_terrain(unit_tile(current_unit
));
912 a
= new hud_action(this);
913 a
->action_shortcut
= SC_BUILDIRRIGATION
;
914 if (pterrain
->irrigation_result
!= T_NONE
915 && pterrain
->irrigation_result
!= pterrain
) {
916 if ((!strcmp(terrain_rule_name(pterrain
), "Forest") ||
917 !strcmp(terrain_rule_name(pterrain
), "Jungle"))) {
918 a
->set_pixmap(fc_icons::instance()->get_pixmap("chopchop"));
920 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
923 a
->set_pixmap(fc_icons::instance()->get_pixmap("irrigation"));
928 if (can_unit_do_activity(current_unit
, ACTIVITY_TRANSFORM
)) {
929 a
= new hud_action(this);
930 a
->action_shortcut
= SC_TRANSFORM
;
931 a
->set_pixmap(fc_icons::instance()->get_pixmap("transform"));
938 extra_type_by_cause_iterate(EC_ROAD
, pextra
) {
939 struct road_type
*proad
= extra_road_get(pextra
);
940 if (can_build_road(proad
, current_unit
, unit_tile(current_unit
))) {
944 extra_type_by_cause_iterate_end
;
946 a
= new hud_action(this);
947 a
->action_shortcut
= SC_BUILDROAD
;
948 a
->set_pixmap(fc_icons::instance()->get_pixmap("buildroad"));
953 a
= new hud_action(this);
954 a
->action_shortcut
= SC_GOTO
;
955 a
->set_pixmap(fc_icons::instance()->get_pixmap("goto"));
959 if (can_unit_do_activity(current_unit
, ACTIVITY_FORTIFYING
)) {
960 a
= new hud_action(this);
961 a
->action_shortcut
= SC_FORTIFY
;
962 a
->set_pixmap(fc_icons::instance()->get_pixmap("fortify"));
967 if (can_unit_do_activity(current_unit
, ACTIVITY_SENTRY
)) {
968 a
= new hud_action(this);
969 a
->action_shortcut
= SC_SENTRY
;
970 a
->set_pixmap(fc_icons::instance()->get_pixmap("sentry"));
974 if (unit_can_load(current_unit
)) {
975 a
= new hud_action(this);
976 a
->action_shortcut
= SC_LOAD
;
977 a
->set_pixmap(fc_icons::instance()->get_pixmap("load"));
981 if (tile_city(unit_tile(current_unit
))) {
982 if (can_unit_change_homecity_to(current_unit
,
983 tile_city(unit_tile(current_unit
)))) {
984 a
= new hud_action(this);
985 a
->action_shortcut
= SC_SETHOME
;
986 a
->set_pixmap(fc_icons::instance()->get_pixmap("set_homecity"));
991 if (UU_OK
== unit_upgrade_test(current_unit
, FALSE
)) {
992 a
= new hud_action(this);
993 a
->action_shortcut
= SC_UPGRADE_UNIT
;
994 a
->set_pixmap(fc_icons::instance()->get_pixmap("upgrade"));
998 if (can_unit_do_autosettlers(current_unit
)) {
999 a
= new hud_action(this);
1000 a
->action_shortcut
= SC_AUTOMATE
;
1001 a
->set_pixmap(fc_icons::instance()->get_pixmap("automate"));
1005 if (unit_has_type_flag(current_unit
, UTYF_PARATROOPERS
)) {
1006 a
= new hud_action(this);
1007 a
->action_shortcut
= SC_PARADROP
;
1008 a
->set_pixmap(fc_icons::instance()->get_pixmap("paradrop"));
1011 /* Clean pollution */
1012 if (can_unit_do_activity(current_unit
, ACTIVITY_POLLUTION
)) {
1013 a
= new hud_action(this);
1014 a
->action_shortcut
= SC_PARADROP
;
1015 a
->set_pixmap(fc_icons::instance()->get_pixmap("pollution"));
1019 if (unit_transported(current_unit
)
1020 && can_unit_unload(current_unit
, unit_transport_get(current_unit
))
1021 && can_unit_exist_at_tile(current_unit
, unit_tile(current_unit
))) {
1022 a
= new hud_action(this);
1023 a
->action_shortcut
= SC_UNLOAD
;
1024 a
->set_pixmap(fc_icons::instance()->get_pixmap("unload"));
1028 if (unit_has_type_flag(current_unit
, UTYF_NUCLEAR
)) {
1029 a
= new hud_action(this);
1030 a
->action_shortcut
= SC_NUKE
;
1031 a
->set_pixmap(fc_icons::instance()->get_pixmap("nuke"));
1036 a
= new hud_action(this);
1037 a
->action_shortcut
= SC_WAIT
;
1038 a
->set_pixmap(fc_icons::instance()->get_pixmap("wait"));
1042 a
= new hud_action(this);
1043 a
->action_shortcut
= SC_DONE_MOVING
;
1044 a
->set_pixmap(fc_icons::instance()->get_pixmap("done"));
1048 foreach (a
, actions
) {
1049 a
->setToolTip(gui()->menu_bar
->shortcut_2_menustring(a
->action_shortcut
));
1050 a
->setFixedHeight(height());
1051 a
->setFixedWidth(height());
1052 layout
->addWidget(a
);
1055 setFixedWidth(actions
.count() * height());
1056 setUpdatesEnabled(true);
1060 return actions
.count();
1063 /****************************************************************************
1064 Cleans layout - run it before layout initialization
1065 ****************************************************************************/
1066 void unit_actions::clear_layout()
1068 int i
= actions
.count();
1072 setUpdatesEnabled(false);
1073 for (j
= 0; j
< i
; j
++) {
1075 layout
->removeWidget(ui
);
1078 while (!actions
.empty()) {
1079 actions
.removeFirst();
1081 setUpdatesEnabled(true);
1084 /****************************************************************************
1085 Constructor for widget allowing loading units on transports
1086 ****************************************************************************/
1087 hud_unit_loader::hud_unit_loader(struct unit
*pcargo
, struct tile
*ptile
)
1089 setProperty("showGrid", "false");
1090 setProperty("selectionBehavior", "SelectRows");
1091 setEditTriggers(QAbstractItemView::NoEditTriggers
);
1092 setSelectionMode(QAbstractItemView::SingleSelection
);
1093 verticalHeader()->setVisible(false);
1094 horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents
);
1095 horizontalHeader()->setVisible(false);
1096 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1097 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
1098 connect(selectionModel(),
1099 SIGNAL(selectionChanged(const QItemSelection
&,
1100 const QItemSelection
&)), this,
1101 SLOT(selection_changed(const QItemSelection
&,
1102 const QItemSelection
&)));
1108 /****************************************************************************
1109 Destructor for units loader
1110 ****************************************************************************/
1111 hud_unit_loader::~hud_unit_loader()
1116 /****************************************************************************
1117 Shows unit loader, adds possible tranportsand units to table
1118 Calculates table size
1119 ****************************************************************************/
1120 void hud_unit_loader::show_me()
1122 QTableWidgetItem
*new_item
;
1128 unit_list_iterate(qtile
->units
, ptransport
) {
1129 if (can_unit_transport(ptransport
, cargo
)
1130 && get_transporter_occupancy(ptransport
)
1131 < get_transporter_capacity(ptransport
)) {
1132 transports
.append(ptransport
);
1133 max_size
= qMax(max_size
, get_transporter_occupancy(ptransport
));
1135 } unit_list_iterate_end
;
1137 setRowCount(transports
.count());
1138 setColumnCount(max_size
+ 1);
1139 for (i
= 0 ; i
< transports
.count(); i
++) {
1141 spite
= get_unittype_sprite(tileset
, transports
.at(i
)->utype
,
1142 direction8_invalid(), true);
1143 str
= utype_rule_name(transports
.at(i
)->utype
);
1144 /* TRANS: MP - just movement points */
1146 + QString(move_points_text(transports
.at(i
)->moves_left
, false))
1148 new_item
= new QTableWidgetItem(QIcon(*spite
->pm
), str
);
1149 setItem(i
, 0, new_item
);
1151 unit_list_iterate(transports
.at(i
)->transporting
, tunit
) {
1152 spite
= get_unittype_sprite(tileset
, tunit
->utype
,
1153 direction8_invalid(), true);
1154 new_item
= new QTableWidgetItem(QIcon(*spite
->pm
), "");
1155 setItem(i
, j
, new_item
);
1157 } unit_list_iterate_end
;
1160 w
= verticalHeader()->width() + 4;
1161 for (i
= 0; i
< columnCount(); i
++) {
1162 w
+= columnWidth(i
);
1164 h
= horizontalHeader()->height() + 4;
1165 for (i
= 0; i
< rowCount(); i
++) {
1170 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
1171 | Qt::FramelessWindowHint
);
1175 /****************************************************************************
1176 Selects given tranport and closes widget
1177 ****************************************************************************/
1178 void hud_unit_loader::selection_changed(const QItemSelection
& s1
,
1179 const QItemSelection
& s2
)
1183 curr_row
= s1
.indexes().at(0).row();
1184 request_unit_load(cargo
, transports
.at(curr_row
), qtile
);
1188 /****************************************************************************
1189 Constructor for unit_hud_selector
1190 ****************************************************************************/
1191 unit_hud_selector::unit_hud_selector(QWidget
*parent
) : QFrame(parent
)
1193 QHBoxLayout
*hbox
, *hibox
;
1194 Unit_type_id utype_id
;
1196 QVBoxLayout
*groupbox_layout
;
1199 struct unit
*punit
= head_of_units_in_focus();
1201 setWindowFlags(Qt::WindowStaysOnTopHint
| Qt::Dialog
1202 | Qt::FramelessWindowHint
);
1203 main_layout
= new QVBoxLayout(this);
1205 unit_sel_type
= new QComboBox();
1207 unit_type_iterate(utype
) {
1208 utype_id
= utype_index(utype
);
1209 if (has_player_unit_type(utype_id
)) {
1210 unit_sel_type
->addItem(utype_name_translation(utype
), utype_id
);
1213 unit_type_iterate_end
;
1217 i
= unit_sel_type
->findText(utype_name_translation(punit
->utype
));
1218 unit_sel_type
->setCurrentIndex(i
);
1220 no_name
= new QGroupBox();
1221 no_name
->setTitle(_("Unit type"));
1222 this_type
= new QRadioButton(_("Selected type"), no_name
);
1223 this_type
->setChecked(true);
1224 any_type
= new QRadioButton(_("All types"), no_name
);
1225 connect(unit_sel_type
, SIGNAL(currentIndexChanged(int)), this,
1226 SLOT(select_units(int)));
1227 connect(this_type
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1228 connect(any_type
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1229 groupbox_layout
= new QVBoxLayout
;
1230 groupbox_layout
->addWidget(unit_sel_type
);
1231 groupbox_layout
->addWidget(this_type
);
1232 groupbox_layout
->addWidget(any_type
);
1233 no_name
->setLayout(groupbox_layout
);
1234 hibox
= new QHBoxLayout
;
1235 hibox
->addWidget(no_name
);
1237 no_name
= new QGroupBox();
1238 no_name
->setTitle(_("Unit activity"));
1239 any_activity
= new QRadioButton(_("Any activity"), no_name
);
1240 any_activity
->setChecked(true);
1241 fortified
= new QRadioButton(_("Fortified"), no_name
);
1242 idle
= new QRadioButton(_("Idle"), no_name
);
1243 sentried
= new QRadioButton(_("Sentried"), no_name
);
1244 connect(any_activity
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1245 connect(idle
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1246 connect(fortified
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1247 connect(sentried
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1248 groupbox_layout
= new QVBoxLayout
;
1249 groupbox_layout
->addWidget(any_activity
);
1250 groupbox_layout
->addWidget(idle
);
1251 groupbox_layout
->addWidget(fortified
);
1252 groupbox_layout
->addWidget(sentried
);
1253 no_name
->setLayout(groupbox_layout
);
1254 hibox
->addWidget(no_name
);
1255 main_layout
->addLayout(hibox
);
1257 no_name
= new QGroupBox();
1258 no_name
->setTitle(_("Unit HP and MP"));
1259 any
= new QRadioButton(_("Any unit"), no_name
);
1260 full_hp
= new QRadioButton(_("Full HP"), no_name
);
1261 full_mp
= new QRadioButton(_("Full MP"), no_name
);
1262 full_hp_mp
= new QRadioButton(_("Full HP and MP"), no_name
);
1263 full_hp_mp
->setChecked(true);
1264 connect(any
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1265 connect(full_hp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1266 connect(full_mp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1267 connect(full_hp_mp
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1268 groupbox_layout
= new QVBoxLayout
;
1269 groupbox_layout
->addWidget(any
);
1270 groupbox_layout
->addWidget(full_hp
);
1271 groupbox_layout
->addWidget(full_mp
);
1272 groupbox_layout
->addWidget(full_hp_mp
);
1273 no_name
->setLayout(groupbox_layout
);
1274 hibox
= new QHBoxLayout
;
1275 hibox
->addWidget(no_name
);
1277 no_name
= new QGroupBox();
1278 no_name
->setTitle(_("Location"));
1279 everywhere
= new QRadioButton(_("Everywhere"), no_name
);
1280 this_tile
= new QRadioButton(_("Current tile"), no_name
);
1281 this_continent
= new QRadioButton(_("Current continent"), no_name
);
1282 main_continent
= new QRadioButton(_("Main continent"), no_name
);
1283 groupbox_layout
= new QVBoxLayout
;
1286 this_tile
->setChecked(true);
1288 this_tile
->setDisabled(true);
1289 this_continent
->setDisabled(true);
1290 main_continent
->setChecked(true);
1293 groupbox_layout
->addWidget(this_tile
);
1294 groupbox_layout
->addWidget(this_continent
);
1295 groupbox_layout
->addWidget(main_continent
);
1296 groupbox_layout
->addWidget(everywhere
);
1298 no_name
->setLayout(groupbox_layout
);
1299 hibox
->addWidget(no_name
);
1300 main_layout
->addLayout(hibox
);
1302 select
= new QPushButton(_("Select"));
1303 cancel
= new QPushButton(_("Cancel"));
1304 connect(everywhere
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1305 connect(this_tile
, SIGNAL(toggled(bool)), this, SLOT(select_units(bool)));
1306 connect(this_continent
, SIGNAL(toggled(bool)), this,
1307 SLOT(select_units(bool)));
1308 connect(main_continent
, SIGNAL(toggled(bool)), this,
1309 SLOT(select_units(bool)));
1310 connect(select
, SIGNAL(clicked()), this, SLOT(uhs_select()));
1311 connect(cancel
, SIGNAL(clicked()), this, SLOT(uhs_cancel()));
1312 hbox
= new QHBoxLayout
;
1313 hbox
->addWidget(cancel
);
1314 hbox
->addWidget(select
);
1316 result_label
.setAlignment(Qt::AlignCenter
);
1317 main_layout
->addWidget(&result_label
, Qt::AlignHCenter
);
1318 main_layout
->addLayout(hbox
);
1319 setLayout(main_layout
);
1323 /****************************************************************************
1324 Shows and moves to center unit_hud_selector
1325 ****************************************************************************/
1326 void unit_hud_selector::show_me()
1330 p
= QPoint((parentWidget()->width() - sizeHint().width()) / 2,
1331 (parentWidget()->height() - sizeHint().height()) / 2);
1332 p
= parentWidget()->mapToGlobal(p
);
1339 /****************************************************************************
1340 Unit_hud_selector destructor
1341 ****************************************************************************/
1342 unit_hud_selector::~unit_hud_selector()
1347 /****************************************************************************
1348 Selects and closes widget
1349 ****************************************************************************/
1350 void unit_hud_selector::uhs_select()
1352 const struct player
*pplayer
;
1354 pplayer
= client_player();
1356 unit_list_iterate(pplayer
->units
, punit
) {
1357 if (activity_filter(punit
) && hp_filter(punit
)
1358 && island_filter(punit
) && type_filter(punit
)) {
1359 unit_focus_add(punit
);
1361 } unit_list_iterate_end
;
1365 /****************************************************************************
1366 Closes current widget
1367 ****************************************************************************/
1368 void unit_hud_selector::uhs_cancel()
1373 /****************************************************************************
1374 Shows number of selected units on label
1375 ****************************************************************************/
1376 void unit_hud_selector::select_units(int x
)
1379 const struct player
*pplayer
;
1381 pplayer
= client_player();
1383 unit_list_iterate(pplayer
->units
, punit
) {
1384 if (activity_filter(punit
) && hp_filter(punit
)
1385 && island_filter(punit
) && type_filter(punit
)) {
1388 } unit_list_iterate_end
;
1389 result_label
.setText(QString(PL_("%1 unit", "%1 units", num
)).arg(num
));
1392 /****************************************************************************
1393 Convinient slot for ez connect
1394 ****************************************************************************/
1395 void unit_hud_selector::select_units(bool x
)
1400 /****************************************************************************
1401 Key press event for unit_hud_selector
1402 ****************************************************************************/
1403 void unit_hud_selector::keyPressEvent(QKeyEvent
*event
)
1405 if ((event
->key() == Qt::Key_Return
)
1406 || (event
->key() == Qt::Key_Enter
)) {
1409 if (event
->key() == Qt::Key_Escape
) {
1413 QWidget::keyPressEvent(event
);
1416 /****************************************************************************
1418 ****************************************************************************/
1419 bool unit_hud_selector::activity_filter(struct unit
*punit
)
1421 if ((punit
->activity
== ACTIVITY_FORTIFIED
&& fortified
->isChecked())
1422 || (punit
->activity
== ACTIVITY_SENTRY
&& sentried
->isChecked())
1423 || (punit
->activity
== ACTIVITY_IDLE
&& idle
->isChecked())
1424 || any_activity
->isChecked()) {
1430 /****************************************************************************
1432 ****************************************************************************/
1433 bool unit_hud_selector::hp_filter(struct unit
*punit
)
1435 if ((any
->isChecked()
1436 || (full_mp
->isChecked()
1437 && punit
->moves_left
>= punit
->utype
->move_rate
)
1438 || (full_hp
->isChecked() && punit
->hp
>= punit
->utype
->hp
)
1439 || (full_hp_mp
->isChecked() && punit
->hp
>= punit
->utype
->hp
1440 && punit
->moves_left
>= punit
->utype
->move_rate
))) {
1446 /****************************************************************************
1448 ****************************************************************************/
1449 bool unit_hud_selector::island_filter(struct unit
*punit
)
1452 struct unit
*cunit
= head_of_units_in_focus();
1454 if (this_tile
->isChecked() && cunit
) {
1455 if (punit
->tile
== cunit
->tile
) {
1460 if (main_continent
->isChecked() && player_capital(client_player())) {
1461 island
= player_capital(client_player())->tile
->continent
;
1462 } else if (this_continent
->isChecked() && cunit
) {
1463 island
= cunit
->tile
->continent
;
1467 if (punit
->tile
->continent
== island
) {
1472 if (everywhere
->isChecked()) {
1478 /****************************************************************************
1480 ****************************************************************************/
1481 bool unit_hud_selector::type_filter(struct unit
*punit
)
1484 Unit_type_id utype_id
;
1486 if (this_type
->isChecked()) {
1487 qvar
= unit_sel_type
->currentData();
1488 utype_id
= qvar
.toInt();
1489 if (utype_id
== utype_index(punit
->utype
)) {
1495 if (any_type
->isChecked()) {
1501 /****************************************************************************
1502 Tooltip text for terrain information
1503 ****************************************************************************/
1504 QString
popup_terrain_info(struct tile
*ptile
)
1507 struct terrain
*terr
;
1509 terr
= ptile
->terrain
;
1510 ret
= QString(_("Terrain: %1\n")).arg(tile_get_info_text(ptile
, TRUE
, 0));
1511 ret
= ret
+ QString(_("Food/Prod/Trade: %1\n"))
1512 .arg(get_tile_output_text(ptile
));
1513 t
= get_infrastructure_text(ptile
->extras
);
1515 ret
= ret
+ QString(_("Infrastructure: %1\n")).arg(t
);
1517 ret
= ret
+ QString(_("Defence bonus: %1%")).arg(terr
->defense_bonus
);
1521 /****************************************************************************
1522 Shows new turn information with big font
1523 ****************************************************************************/
1524 void show_new_turn_info()
1528 QList
<hud_text
*> close_list
;
1529 struct research
*research
;
1532 if (client_has_player() == false
1533 || gui()->qt_settings
.show_new_turn_text
== false) {
1536 close_list
= gui()->mapview_wdg
->findChildren
<hud_text
*>();
1537 for (i
= 0; i
< close_list
.size(); ++i
) {
1538 close_list
.at(i
)->close();
1539 close_list
.at(i
)->deleteLater();
1541 research
= research_get(client_player());
1542 s
= QString(_("Year: %1 (Turn: %2)"))
1543 .arg(calendar_text()).arg(game
.info
.turn
) + "\n";
1544 s
= s
+ QString(nation_plural_for_player(client_player()));
1545 s
= s
+ " - " + QString(_("Population: %1"))
1546 .arg(population_to_text(civ_population(client
.conn
.playing
)));
1547 if (research
->researching
!= A_UNKNOWN
1548 && research
->researching
!= A_UNSET
1549 && research
->researching
!= A_NONE
) {
1550 s
= s
+ "\n" + QString(research_advance_name_translation(research
,
1551 research
->researching
)) +
1552 " (" + QString::number(research
->bulbs_researched
) + "/"
1553 + QString::number(research
->client
.researching_cost
) + ")";
1555 s
= s
+ "\n" + science_dialog_text() + "\n";
1556 s
= s
+ QString(_("Gold: %1 (+%2)"))
1557 .arg(client
.conn
.playing
->economic
.gold
)
1558 .arg(player_get_expected_income(client
.conn
.playing
));
1559 ht
= new hud_text(s
, 5, gui()->mapview_wdg
);