Freeciv-3.3
Loading...
Searching...
No Matches
sidebar.cpp
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18// Qt
19#include <QAction>
20#include <QApplication>
21#include <QHBoxLayout>
22#include <QMenu>
23#include <QPainter>
24#include <QPaintEvent>
25#include <QPixmap>
26#include <QScreen>
27#include <QTimer>
28
29// common
30#include "research.h"
31
32// client
33#include "client_main.h"
34
35// gui-qt
36#include "fc_client.h"
37#include "repodlgs.h"
38#include "sidebar.h"
39#include "sprite.h"
40
41extern void pixmap_copy(QPixmap *dest, QPixmap *src, int src_x, int src_y,
42 int dest_x, int dest_y, int width, int height);
43
44static void reduce_mod(int &val, int &mod);
45
46/***********************************************************************/
49void reduce_mod(int &mod, int &val)
50{
51 if (mod > 0) {
52 val++;
53 mod--;
54 }
55
56 return;
57}
58
59/***********************************************************************/
63 pfcn_bool func, int type): QWidget()
64{
65 if (pix == nullptr) {
66 pix = new QPixmap(12,12);
67 pix->fill(Qt::black);
68 }
69
70 blink = false;
71 disabled = false;
72 def_pixmap = pix;
75
76 sfont = nullptr;
77 info_font = nullptr;
79
81 desc = label;
82 standard = type;
83 hover = false;
84 right_click = nullptr;
85 wheel_down = nullptr;
86 wheel_up = nullptr;
87 page = pg;
88 setContextMenuPolicy(Qt::CustomContextMenu);
89 timer = new QTimer;
90 timer->setSingleShot(false);
91 timer->setInterval(700);
92
93 connect(timer, &QTimer::timeout, this, &fc_sidewidget::sblink);
94}
95
96/***********************************************************************/
100{
101 if (scaled_pixmap) {
102 delete scaled_pixmap;
103 }
104
105 if (def_pixmap) {
106 delete def_pixmap;
107 }
108
109 if (final_pixmap) {
110 delete final_pixmap;
111 }
112 delete timer;
113 delete sfont;
114 delete info_font;
115}
116
117/***********************************************************************/
121{
122 if (def_pixmap) {
123 delete def_pixmap;
124 }
125
126 def_pixmap = pm;
127}
128
129/***********************************************************************/
133{
134 if (sfont != nullptr) {
135 delete sfont;
136 }
138 sfont->setCapitalization(QFont::SmallCaps);
139 sfont->setItalic(true);
140
141 if (info_font != nullptr) {
142 delete info_font;
143 }
144 info_font = new QFont(*sfont);
145 info_font->setBold(true);
146 info_font->setItalic(false);
147}
148
149/***********************************************************************/
156
157/***********************************************************************/
164
165/***********************************************************************/
172
173/***********************************************************************/
180
181/***********************************************************************/
186{
187 if (standard == SW_TAX) {
188 height = get_tax_sprite(tileset, O_LUXURY)->pm->height() + 8;
189 }
190
191 if (standard == SW_INDICATORS) {
192 height = client_government_sprite()->pm->height() + 8;
193 }
194
195 if (def_pixmap) {
196 *scaled_pixmap = def_pixmap->scaled(width, height, Qt::IgnoreAspectRatio,
197 Qt::SmoothTransformation);
198 }
199}
200
201/***********************************************************************/
205{
207
208 painter.begin(this);
210 painter.end();
211}
212
213/***********************************************************************/
217{
218 if (final_pixmap) {
219 painter->drawPixmap(event->rect(), *final_pixmap,
220 event->rect());
221 }
222}
223
224/***********************************************************************/
227#ifndef FC_QT5_MODE
229#else // FC_QT5_MODE
231#endif // FC_QT5_MODE
232{
233 if (!hover) {
234 hover = true;
235 update_final_pixmap();
236 QWidget::enterEvent(event);
237 update();
238 }
239}
240
241/***********************************************************************/
245{
246 if (hover) {
247 hover = false;
249 QWidget::leaveEvent(event);
250 update();
251
252 }
253}
254
255/***********************************************************************/
259{
260 if (hover) {
261 hover = false;
263 QWidget::contextMenuEvent(event);
264 update();
265 }
266}
267
268/***********************************************************************/
275
276/***********************************************************************/
283
284/***********************************************************************/
291
292/***********************************************************************/
299
300/***********************************************************************/
304{
305 if (event->button() == Qt::LeftButton && left_click != nullptr) {
306 left_click(true);
307 }
308 if (event->button() == Qt::RightButton && right_click != nullptr) {
309 right_click();
310 }
311 if (event->button() == Qt::RightButton && right_click == nullptr) {
312 gui()->game_tab_widget->setCurrentIndex(0);
313 }
314}
315
316/***********************************************************************/
320{
321 int delta = event->angleDelta().y();
322
323 if (delta < -90 && wheel_down) {
324 wheel_down();
325 } else if (delta > 90 && wheel_up) {
326 wheel_up();
327 }
328
329 event->accept();
330}
331
332/***********************************************************************/
336{
337 if (keep_blinking) {
338 if (!timer->isActive()) {
339 timer->start();
340 }
341 blink = !blink;
342 } else {
343 blink = false;
344 if (timer->isActive()) {
345 timer->stop();
346 }
347 }
349}
350
351/***********************************************************************/
357{
359 struct player *obs_player;
360 QAction *act;
361
363 qvar = act->data();
364
365 if (!qvar.isValid()) {
366 return;
367 }
368
369 if (act->property("scimenu").toBool()) {
371 return;
372 }
373
374 if (qvar.toInt() == -1) {
375 send_chat("/observe");
376 return;
377 }
378
379 obs_player = reinterpret_cast<struct player *>(qvar.value<void *>());
380 if (obs_player != nullptr) {
381 QString s;
383
384 s = QString("/observe \"%1\"").arg(obs_player->name);
385 cn_bytes = s.toUtf8();
386 send_chat(cn_bytes.data());
387 }
388}
389
390/***********************************************************************/
394{
395 const struct sprite *sprite;
396 int w, h, pos, i;
397 QPainter p;
398 QPen pen;
399 bool current = false;
400
401 if (final_pixmap) {
402 delete final_pixmap;
403 }
404
405 i = gui()->gimme_index_of(page);
406 if (i == gui()->game_tab_widget->currentIndex()) {
407 current = true;
408 }
409 final_pixmap = new QPixmap(scaled_pixmap->width(), scaled_pixmap->height());
410 final_pixmap->fill(Qt::transparent);
411
412 if (scaled_pixmap->width() == 0 || scaled_pixmap->height() == 0) {
413 return;
414 }
415
416 p.begin(final_pixmap);
417 p.setFont(*sfont);
418 pen.setColor(QColor(232, 255, 0));
419 p.setPen(pen);
420
422 int d, modulo;
423
424 pos = 0;
426 if (sprite == nullptr) {
427 return;
428 }
429 w = width() / 10;
430 modulo = width() % 10;
431 h = sprite->pm->height();
433 if (client.conn.playing == nullptr) {
434 return;
435 }
436 for (d = 0; d < client.conn.playing->economic.tax / 10; ++d) {
437 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
438 pos = pos + w;
440 }
441
443
444 for (; d < (client.conn.playing->economic.tax
445 + client.conn.playing->economic.science) / 10; ++d) {
446 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
447 pos = pos + w;
449 }
450
452
453 for (; d < 10 ; ++d) {
454 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
455 pos = pos + w;
457 }
458 } else if (standard == SW_INDICATORS) {
460 w = sprite->pm->width();
461 pos = scaled_pixmap->width() / 2 - 2 * w;
462 p.drawPixmap(pos, 5, *sprite->pm);
463 pos = pos + w;
465 p.drawPixmap(pos, 5, *sprite->pm);
466 pos = pos + w;
468 p.drawPixmap(pos, 5, *sprite->pm);
469 pos = pos + w;
471 p.drawPixmap(pos, 5, *sprite->pm);
472
473 } else {
474 p.drawPixmap(0, 0 , *scaled_pixmap);
475 p.drawText(0, height() - 6 , desc);
476 }
477
478 p.setPen(palette().color(QPalette::Text));
479 if (!custom_label.isEmpty()) {
480 p.setFont(*info_font);
481 p.drawText(0, 0, width(), height(), Qt::AlignLeft | Qt::TextWordWrap,
483 }
484
485 if (current) {
486 p.setPen(palette().color(QPalette::Highlight));
487 p.drawRect(0 , 0, width() - 1 , height() - 1);
488 }
489
490 if (hover && !disabled) {
491 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
492 p.setPen(palette().color(QPalette::Highlight));
493 p.setBrush(palette().color(QPalette::AlternateBase));
494 p.drawRect(0 , 0, width() - 1 , height() - 1);
495 }
496
497 if (disabled) {
498 p.setCompositionMode(QPainter::CompositionMode_Darken);
499 p.setPen(QColor(0, 0, 0));
500 p.setBrush(QColor(0, 0, 50, 95));
501 p.drawRect(0 , 0, width(), height());
502 }
503
504 if (blink) {
505 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
506 p.setPen(QColor(0, 0, 0));
507 p.setBrush(palette().color(QPalette::HighlightedText));
508 p.drawRect(0 , 0, width(), height());
509 }
510
511 p.end();
512 update();
513}
514
515/***********************************************************************/
519{
520 setAttribute(Qt::WA_OpaquePaintEvent, true);
521 layout = new QVBoxLayout;
522 layout->setContentsMargins(0, 0, 0, 0);
524 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Ignored);
525}
526
527/***********************************************************************/
533
534/***********************************************************************/
538{
539 objects.append(fsw);
540 layout->addWidget(fsw);
541 return;
542}
543
544/***********************************************************************/
548{
550
551 painter.begin(this);
553 painter.end();
554}
555
556/***********************************************************************/
560{
561 painter->setBrush(QBrush(QColor(40, 40, 40)));
562 painter->drawRect(event->rect());
563}
564
565/**************************************************************************
566 Resize sidebar to take at least 80 pixels width and 100 pixels for FullHD
567 desktop and scaled accordingly for bigger resolutions eg 200 pixels for 4k
568 desktop.
569**************************************************************************/
571{
573
574 h = hght;
575 screen_hres = QApplication::primaryScreen()->availableGeometry().width();
576 w = (100 * screen_hres) / 1920;
577 w = qMax(w, 80);
578
579 if (!force && w == width() && h == height()) {
580 return;
581 }
582
583 non_std = 0;
584 non_std_count = 0;
585
586 // Resize all non standard sidewidgets first
587 foreach (fc_sidewidget *sw, objects) {
588 if (sw->standard != SW_STD) {
589 sw->resize_pixmap(w, 0);
590 sw->setFixedSize(w, sw->get_pixmap()->height());
592 non_std = non_std + sw->get_pixmap()->height();
594 }
595 }
596
597 h = h - non_std;
598 h = h / (objects.count() - non_std_count) - 2;
599 // Resize all standard sidewidgets
600 foreach (fc_sidewidget *sw, objects) {
601 if (sw->standard == SW_STD) {
602 sw->resize_pixmap(w, h);
603 sw->setFixedSize(w, h);
605 }
606 }
607}
608
609/***********************************************************************/
613{
614 foreach (fc_sidewidget *sw, objects) {
615 sw->update_fonts();
617 }
618}
619
620/***********************************************************************/
624{
625 gui()->game_tab_widget->setCurrentIndex(0);
626}
627
628/***********************************************************************/
632{
633 key_end_turn();
634}
635
636/***********************************************************************/
640{
641 if (!client_is_observer()) {
643 }
644}
645
646/***********************************************************************/
650{
651 gui()->game_tab_widget->setCurrentIndex(0);
653}
654
655/**********************************************************************/
659{
660 struct option *opt = optset_option_by_name(server_optset, "fixedlength");
661
662 if (opt != nullptr && option_bool_get(opt)) {
663 gui()->sw_endturn->setToolTip(_("Fixed length turns"));
664 } else {
665 char buf[256];
666
667 fc_snprintf(buf, sizeof(buf), "%s:\n%s",
668 _("Turn Done"), _("Shift+Return"));
669 gui()->sw_endturn->setToolTip(buf);
670 }
671}
672
673/***********************************************************************/
677{
678 if (gui()->current_page() != PAGE_GAME) {
679 return;
680 }
681
682 gui()->sw_endturn->disabled = !do_restore;
683 gui()->sw_endturn->update_final_pixmap();
684}
685
686/***********************************************************************/
690{
691 if (gui()->current_page() != PAGE_GAME) {
692 return;
693 }
694 gui()->sw_endturn->blink = !do_restore;
695 gui()->sw_endturn->update_final_pixmap();
696}
697
698/***********************************************************************/
702{
703 gov_menu *menu = new gov_menu(gui()->sidebar_wdg);
704
705 menu->create();
706 menu->update();
707 menu->popup(QCursor::pos());
708}
709
710/***********************************************************************/
716{
717 if (client_is_observer()) {
718 QMenu *menu = new QMenu(gui()->central_wdg);
721
722 players_iterate(pplayer) {
723 if (pplayer == client.conn.playing) {
724 continue;
725 }
726 erwischt = QString(_("Observe %1")).arg(pplayer->name);
727 erwischt = erwischt + " ("
728 + nation_plural_translation(pplayer->nation) + ")";
729 eiskalt = new QAction(erwischt, gui()->mapview_wdg);
730 eiskalt->setData(QVariant::fromValue((void *)pplayer));
731 QObject::connect(eiskalt, &QAction::triggered, gui()->sw_diplo,
733 menu->addAction(eiskalt);
735
737 eiskalt = new QAction(_("Observe globally"), gui()->mapview_wdg);
738 eiskalt->setData(-1);
739 menu->addAction(eiskalt);
740 QObject::connect(eiskalt, &QAction::triggered, gui()->sw_diplo,
742 }
743
744 menu->setAttribute(Qt::WA_DeleteOnClose);
745 menu->popup(QCursor::pos());
746 } else {
747 int i;
748
749 i = gui()->gimme_index_of("DDI");
750 if (i < 0) {
751 return;
752 }
753 gui()->game_tab_widget->setCurrentIndex(i);
754 }
755}
756
757/***********************************************************************/
761{
762 QMenu *menu;
763 QAction *act;
765 QList<qlist_item> curr_list;
767
768 if (!client_is_observer()) {
770
773 && research->researching != i) {
774 item.tech_str =
775 QString::fromUtf8(advance_name_translation(advance_by_number(i)));
776 item.id = i;
777 curr_list.append(item);
778 }
780 if (curr_list.isEmpty()) {
781 return;
782 }
783 std::sort(curr_list.begin(), curr_list.end(), comp_less_than);
784 menu = new QMenu(gui()->central_wdg);
785 for (int i = 0; i < curr_list.count(); i++) {
786 QIcon ic;
787 struct sprite *sp;
788
789 qvar = curr_list.at(i).id;
790 sp = get_tech_sprite(tileset, curr_list.at(i).id);
791 if (sp) {
792 ic = QIcon(*sp->pm);
793 }
794 act = new QAction(ic, curr_list.at(i).tech_str, gui()->mapview_wdg);
795 act->setData(qvar);
796 act->setProperty("scimenu", true);
797 menu->addAction(act);
798 QObject::connect(act, &QAction::triggered, gui()->sw_science,
800 }
801 menu->setAttribute(Qt::WA_DeleteOnClose);
802 menu->popup(QCursor::pos());
803 }
804}
805
806/***********************************************************************/
810{
812 int i;
813 QWidget *w;
814
816 return;
817 }
818 if (!gui()->is_repo_dlg_open("SCI")) {
820 sci_rep->init();
821 } else {
822 i = gui()->gimme_index_of("SCI");
823 w = gui()->game_tab_widget->widget(i);
824 if (w->isVisible()) {
825 gui()->game_tab_widget->setCurrentIndex(0);
826 return;
827 }
828 sci_rep = reinterpret_cast<science_report*>(w);
829 gui()->game_tab_widget->setCurrentWidget(sci_rep);
830 }
831}
#define str
Definition astring.c:76
static QFont * get_font(enum client_font font)
Definition canvas.cpp:379
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
int send_chat(const char *message)
static fc_font * instance()
Definition fonts.cpp:41
QVBoxLayout * layout
Definition sidebar.h:125
void resize_me(int height, bool force=false)
Definition sidebar.cpp:570
void add_widget(fc_sidewidget *fsw)
Definition sidebar.cpp:537
QList< fc_sidewidget * > objects
Definition sidebar.h:121
void update_fonts()
Definition sidebar.cpp:612
void paintEvent(QPaintEvent *event)
Definition sidebar.cpp:547
void paint(QPainter *painter, QPaintEvent *event)
Definition sidebar.cpp:559
void update_fonts()
Definition sidebar.cpp:132
void set_wheel_down(pfcn func)
Definition sidebar.cpp:287
QPixmap * final_pixmap
Definition sidebar.h:100
QFont * info_font
Definition sidebar.h:98
pfcn wheel_down
Definition sidebar.h:94
QString custom_label
Definition sidebar.h:102
QFont * sfont
Definition sidebar.h:97
bool keep_blinking
Definition sidebar.h:72
fc_sidewidget(QPixmap *pix, QString label, QString pg, pfcn_bool func, int type=SW_STD)
Definition sidebar.cpp:62
void wheelEvent(QWheelEvent *event)
Definition sidebar.cpp:319
QString desc
Definition sidebar.h:103
void set_wheel_up(pfcn func)
Definition sidebar.cpp:295
void some_slot()
Definition sidebar.cpp:356
void contextMenuEvent(QContextMenuEvent *event)
Definition sidebar.cpp:258
pfcn wheel_up
Definition sidebar.h:95
QPixmap * def_pixmap
Definition sidebar.h:99
void paintEvent(QPaintEvent *event)
Definition sidebar.cpp:204
QString page
Definition sidebar.h:75
void set_custom_labels(QString l)
Definition sidebar.cpp:152
void mousePressEvent(QMouseEvent *event)
Definition sidebar.cpp:303
void set_left_click(pfcn_bool func)
Definition sidebar.cpp:271
void set_label(QString str)
Definition sidebar.cpp:176
void sblink()
Definition sidebar.cpp:335
void set_pixmap(QPixmap *pm)
Definition sidebar.cpp:120
void resize_pixmap(int width, int height)
Definition sidebar.cpp:185
QTimer * timer
Definition sidebar.h:104
void set_right_click(pfcn func)
Definition sidebar.cpp:279
bool disabled
Definition sidebar.h:73
void set_tooltip(QString tooltip)
Definition sidebar.cpp:160
void leaveEvent(QEvent *event)
Definition sidebar.cpp:244
pfcn_bool left_click
Definition sidebar.h:96
void enterEvent(QEnterEvent *event)
Definition sidebar.cpp:228
void update_final_pixmap()
Definition sidebar.cpp:393
QPixmap * scaled_pixmap
Definition sidebar.h:101
QPixmap * get_pixmap()
Definition sidebar.cpp:168
pfcn right_click
Definition sidebar.h:93
void create()
Definition menu.cpp:589
void update()
Definition menu.cpp:630
bool client_is_global_observer(void)
bool client_is_observer(void)
struct civclient client
#define client_player()
struct sprite * client_warming_sprite(void)
Definition climisc.c:377
struct sprite * client_cooling_sprite(void)
Definition climisc.c:394
struct sprite * client_research_sprite(void)
Definition climisc.c:354
struct sprite * client_government_sprite(void)
Definition climisc.c:412
char * incite_cost
Definition comments.c:76
void key_end_turn(void)
Definition control.c:3312
void request_center_focus_unit(void)
Definition control.c:2750
enum event_type event
Definition events.c:81
@ O_SCIENCE
Definition fc_types.h:101
@ O_LUXURY
Definition fc_types.h:101
@ O_GOLD
Definition fc_types.h:101
#define _(String)
Definition fcintl.h:67
static struct tile * pos
Definition finddlg.c:53
void popup_rates_dialog(void)
Definition gamedlgs.c:533
static enum client_pages current_page
Definition pages.c:78
const char * tooltip
Definition repodlgs.c:1315
GType type
Definition repodlgs.c:1313
get_token_fn_t func
Definition inputfile.c:128
static mpgui * gui
Definition mpgui_qt.cpp:52
const char *const notify_label
Definition fonts.h:28
const char * nation_plural_translation(const struct nation_type *pnation)
Definition nation.c:159
const struct option_set * server_optset
Definition options.c:4278
bool option_bool_get(const struct option *poption)
Definition options.c:833
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:467
int dsend_packet_player_research(struct connection *pc, int tech)
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
bool comp_less_than(const qlist_item &q1, const qlist_item &q2)
Definition repodlgs.cpp:545
struct research * research_get(const struct player *pplayer)
Definition research.c:128
static void reduce_mod(int &val, int &mod)
Definition sidebar.cpp:49
void side_center_unit()
Definition sidebar.cpp:649
void side_show_map(bool nothing)
Definition sidebar.cpp:623
void update_turn_done_tooltip()
Definition sidebar.cpp:658
void side_indicators_menu()
Definition sidebar.cpp:701
void side_left_click_science(bool nothing)
Definition sidebar.cpp:809
void side_rates_wdg(bool nothing)
Definition sidebar.cpp:639
void side_finish_turn(bool nothing)
Definition sidebar.cpp:631
void side_right_click_science(void)
Definition sidebar.cpp:760
void side_blink_endturn(bool do_restore)
Definition sidebar.cpp:689
void side_disable_endturn(bool do_restore)
Definition sidebar.cpp:676
void pixmap_copy(QPixmap *dest, QPixmap *src, int src_x, int src_y, int dest_x, int dest_y, int width, int height)
Definition canvas.cpp:101
void side_right_click_diplomacy(void)
Definition sidebar.cpp:715
void(* pfcn_bool)(bool)
Definition sidebar.h:31
void(* pfcn)(void)
Definition sidebar.h:32
@ SW_TAX
Definition sidebar.h:26
@ SW_INDICATORS
Definition sidebar.h:26
@ SW_STD
Definition sidebar.h:26
struct connection conn
Definition client_main.h:96
Definition colors.h:21
struct player * playing
Definition connection.h:151
Definition climisc.h:82
struct player_economic economic
Definition player.h:284
enum tech_state state
Definition research.h:71
Tech_type_id researching
Definition research.h:52
struct research::research_invention inventions[A_ARRAY_SIZE]
QPixmap * pm
Definition sprite.h:25
Definition timing.c:81
union timer::@11 start
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
#define advance_index_iterate_end
Definition tech.h:244
#define A_FIRST
Definition tech.h:44
#define advance_index_iterate(_start, _index)
Definition tech.h:240
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:7103
struct sprite * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Definition tilespec.c:6998