Freeciv-3.4
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/***********************************************************************/
228{
229 if (!hover) {
230 hover = true;
232 QWidget::enterEvent(event);
233 update();
234 }
235}
236
237/***********************************************************************/
241{
242 if (hover) {
243 hover = false;
245 QWidget::leaveEvent(event);
246 update();
247
248 }
249}
250
251/***********************************************************************/
255{
256 if (hover) {
257 hover = false;
259 QWidget::contextMenuEvent(event);
260 update();
261 }
262}
263
264/***********************************************************************/
271
272/***********************************************************************/
279
280/***********************************************************************/
287
288/***********************************************************************/
295
296/***********************************************************************/
300{
301 if (event->button() == Qt::LeftButton && left_click != nullptr) {
302 left_click(true);
303 }
304 if (event->button() == Qt::RightButton && right_click != nullptr) {
305 right_click();
306 }
307 if (event->button() == Qt::RightButton && right_click == nullptr) {
308 gui()->game_tab_widget->setCurrentIndex(0);
309 }
310}
311
312/***********************************************************************/
316{
317 int delta = event->angleDelta().y();
318
319 if (delta < -90 && wheel_down) {
320 wheel_down();
321 } else if (delta > 90 && wheel_up) {
322 wheel_up();
323 }
324
325 event->accept();
326}
327
328/***********************************************************************/
332{
333 if (keep_blinking) {
334 if (!timer->isActive()) {
335 timer->start();
336 }
337 blink = !blink;
338 } else {
339 blink = false;
340 if (timer->isActive()) {
341 timer->stop();
342 }
343 }
345}
346
347/***********************************************************************/
353{
355 struct player *obs_player;
356 QAction *act;
357
359 qvar = act->data();
360
361 if (!qvar.isValid()) {
362 return;
363 }
364
365 if (act->property("scimenu").toBool()) {
367 return;
368 }
369
370 if (qvar.toInt() == -1) {
371 send_chat("/observe");
372 return;
373 }
374
375 obs_player = reinterpret_cast<struct player *>(qvar.value<void *>());
376 if (obs_player != nullptr) {
377 QString s;
379
380 s = QString("/observe \"%1\"").arg(obs_player->name);
381 cn_bytes = s.toUtf8();
382 send_chat(cn_bytes.data());
383 }
384}
385
386/***********************************************************************/
390{
391 const struct sprite *sprite;
392 int w, h, pos, i;
393 QPainter p;
394 QPen pen;
395 bool current = false;
396
397 if (final_pixmap) {
398 delete final_pixmap;
399 }
400
401 i = gui()->gimme_index_of(page);
402 if (i == gui()->game_tab_widget->currentIndex()) {
403 current = true;
404 }
405 final_pixmap = new QPixmap(scaled_pixmap->width(), scaled_pixmap->height());
406 final_pixmap->fill(Qt::transparent);
407
408 if (scaled_pixmap->width() == 0 || scaled_pixmap->height() == 0) {
409 return;
410 }
411
412 p.begin(final_pixmap);
413 p.setFont(*sfont);
414 pen.setColor(QColor(232, 255, 0));
415 p.setPen(pen);
416
418 int d, modulo;
419
420 pos = 0;
422 if (sprite == nullptr) {
423 return;
424 }
425 w = width() / 10;
426 modulo = width() % 10;
427 h = sprite->pm->height();
429 if (client.conn.playing == nullptr) {
430 return;
431 }
432 for (d = 0; d < client.conn.playing->economic.tax / 10; ++d) {
433 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
434 pos = pos + w;
436 }
437
439
440 for (; d < (client.conn.playing->economic.tax
441 + client.conn.playing->economic.science) / 10; ++d) {
442 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
443 pos = pos + w;
445 }
446
448
449 for (; d < 10 ; ++d) {
450 p.drawPixmap(pos, 5, sprite->pm->scaled(w, h), 0, 0, w, h);
451 pos = pos + w;
453 }
454 } else if (standard == SW_INDICATORS) {
456 w = sprite->pm->width();
457 pos = scaled_pixmap->width() / 2 - 2 * w;
458 p.drawPixmap(pos, 5, *sprite->pm);
459 pos = pos + w;
461 p.drawPixmap(pos, 5, *sprite->pm);
462 pos = pos + w;
464 p.drawPixmap(pos, 5, *sprite->pm);
465 pos = pos + w;
467 p.drawPixmap(pos, 5, *sprite->pm);
468
469 } else {
470 p.drawPixmap(0, 0 , *scaled_pixmap);
471 p.drawText(0, height() - 6 , desc);
472 }
473
474 p.setPen(palette().color(QPalette::Text));
475 if (!custom_label.isEmpty()) {
476 p.setFont(*info_font);
477 p.drawText(0, 0, width(), height(), Qt::AlignLeft | Qt::TextWordWrap,
479 }
480
481 if (current) {
482 p.setPen(palette().color(QPalette::Highlight));
483 p.drawRect(0 , 0, width() - 1 , height() - 1);
484 }
485
486 if (hover && !disabled) {
487 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
488 p.setPen(palette().color(QPalette::Highlight));
489 p.setBrush(palette().color(QPalette::AlternateBase));
490 p.drawRect(0 , 0, width() - 1 , height() - 1);
491 }
492
493 if (disabled) {
494 p.setCompositionMode(QPainter::CompositionMode_Darken);
495 p.setPen(QColor(0, 0, 0));
496 p.setBrush(QColor(0, 0, 50, 95));
497 p.drawRect(0 , 0, width(), height());
498 }
499
500 if (blink) {
501 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
502 p.setPen(QColor(0, 0, 0));
503 p.setBrush(palette().color(QPalette::HighlightedText));
504 p.drawRect(0 , 0, width(), height());
505 }
506
507 p.end();
508 update();
509}
510
511/***********************************************************************/
515{
516 setAttribute(Qt::WA_OpaquePaintEvent, true);
517 layout = new QVBoxLayout;
518 layout->setContentsMargins(0, 0, 0, 0);
520 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Ignored);
521}
522
523/***********************************************************************/
529
530/***********************************************************************/
534{
535 objects.append(fsw);
536 layout->addWidget(fsw);
537 return;
538}
539
540/***********************************************************************/
544{
546
547 painter.begin(this);
549 painter.end();
550}
551
552/***********************************************************************/
556{
557 painter->setBrush(QBrush(QColor(40, 40, 40)));
558 painter->drawRect(event->rect());
559}
560
561/**************************************************************************
562 Resize sidebar to take at least 80 pixels width and 100 pixels for FullHD
563 desktop and scaled accordingly for bigger resolutions eg 200 pixels for 4k
564 desktop.
565**************************************************************************/
567{
569
570 h = hght;
571 screen_hres = QApplication::primaryScreen()->availableGeometry().width();
572 w = (100 * screen_hres) / 1920;
573 w = qMax(w, 80);
574
575 if (!force && w == width() && h == height()) {
576 return;
577 }
578
579 non_std = 0;
580 non_std_count = 0;
581
582 // Resize all non standard sidewidgets first
583 foreach (fc_sidewidget *sw, objects) {
584 if (sw->standard != SW_STD) {
585 sw->resize_pixmap(w, 0);
586 sw->setFixedSize(w, sw->get_pixmap()->height());
588 non_std = non_std + sw->get_pixmap()->height();
590 }
591 }
592
593 h = h - non_std;
594 h = h / (objects.count() - non_std_count) - 2;
595 // Resize all standard sidewidgets
596 foreach (fc_sidewidget *sw, objects) {
597 if (sw->standard == SW_STD) {
598 sw->resize_pixmap(w, h);
599 sw->setFixedSize(w, h);
601 }
602 }
603}
604
605/***********************************************************************/
609{
610 foreach (fc_sidewidget *sw, objects) {
611 sw->update_fonts();
613 }
614}
615
616/***********************************************************************/
620{
621 gui()->game_tab_widget->setCurrentIndex(0);
622}
623
624/***********************************************************************/
628{
629 key_end_turn();
630}
631
632/***********************************************************************/
636{
637 if (!client_is_observer()) {
639 }
640}
641
642/***********************************************************************/
646{
647 gui()->game_tab_widget->setCurrentIndex(0);
649}
650
651/**********************************************************************/
655{
656 struct option *opt = optset_option_by_name(server_optset, "fixedlength");
657
658 if (opt != nullptr && option_bool_get(opt)) {
659 gui()->sw_endturn->setToolTip(_("Fixed length turns"));
660 } else {
661 char buf[256];
662
663 fc_snprintf(buf, sizeof(buf), "%s:\n%s",
664 _("Turn Done"), _("Shift+Return"));
665 gui()->sw_endturn->setToolTip(buf);
666 }
667}
668
669/***********************************************************************/
673{
674 if (gui()->current_page() != PAGE_GAME) {
675 return;
676 }
677
678 gui()->sw_endturn->disabled = !do_restore;
679 gui()->sw_endturn->update_final_pixmap();
680}
681
682/***********************************************************************/
686{
687 if (gui()->current_page() != PAGE_GAME) {
688 return;
689 }
690 gui()->sw_endturn->blink = !do_restore;
691 gui()->sw_endturn->update_final_pixmap();
692}
693
694/***********************************************************************/
698{
699 gov_menu *menu = new gov_menu(gui()->sidebar_wdg);
700
701 menu->create();
702 menu->update();
703 menu->popup(QCursor::pos());
704}
705
706/***********************************************************************/
712{
713 if (client_is_observer()) {
714 QMenu *menu = new QMenu(gui()->central_wdg);
717
718 players_iterate(pplayer) {
719 if (pplayer == client.conn.playing) {
720 continue;
721 }
722 erwischt = QString(_("Observe %1")).arg(pplayer->name);
723 erwischt = erwischt + " ("
724 + nation_plural_translation(pplayer->nation) + ")";
725 eiskalt = new QAction(erwischt, gui()->mapview_wdg);
726 eiskalt->setData(QVariant::fromValue((void *)pplayer));
727 QObject::connect(eiskalt, &QAction::triggered, gui()->sw_diplo,
729 menu->addAction(eiskalt);
731
733 eiskalt = new QAction(_("Observe globally"), gui()->mapview_wdg);
734 eiskalt->setData(-1);
735 menu->addAction(eiskalt);
736 QObject::connect(eiskalt, &QAction::triggered, gui()->sw_diplo,
738 }
739
740 menu->setAttribute(Qt::WA_DeleteOnClose);
741 menu->popup(QCursor::pos());
742 } else {
743 int i;
744
745 i = gui()->gimme_index_of("DDI");
746 if (i < 0) {
747 return;
748 }
749 gui()->game_tab_widget->setCurrentIndex(i);
750 }
751}
752
753/***********************************************************************/
757{
758 QMenu *menu;
759 QAction *act;
761 QList<qlist_item> curr_list;
763
764 if (!client_is_observer()) {
766
769 && research->researching != i) {
770 item.tech_str =
771 QString::fromUtf8(advance_name_translation(advance_by_number(i)));
772 item.id = i;
773 curr_list.append(item);
774 }
776 if (curr_list.isEmpty()) {
777 return;
778 }
779 std::sort(curr_list.begin(), curr_list.end(), comp_less_than);
780 menu = new QMenu(gui()->central_wdg);
781 for (int i = 0; i < curr_list.count(); i++) {
782 QIcon ic;
783 struct sprite *sp;
784
785 qvar = curr_list.at(i).id;
786 sp = get_tech_sprite(tileset, curr_list.at(i).id);
787 if (sp) {
788 ic = QIcon(*sp->pm);
789 }
790 act = new QAction(ic, curr_list.at(i).tech_str, gui()->mapview_wdg);
791 act->setData(qvar);
792 act->setProperty("scimenu", true);
793 menu->addAction(act);
794 QObject::connect(act, &QAction::triggered, gui()->sw_science,
796 }
797 menu->setAttribute(Qt::WA_DeleteOnClose);
798 menu->popup(QCursor::pos());
799 }
800}
801
802/***********************************************************************/
806{
808 int i;
809 QWidget *w;
810
812 return;
813 }
814 if (!gui()->is_repo_dlg_open("SCI")) {
816 sci_rep->init();
817 } else {
818 i = gui()->gimme_index_of("SCI");
819 w = gui()->game_tab_widget->widget(i);
820 if (w->isVisible()) {
821 gui()->game_tab_widget->setCurrentIndex(0);
822 return;
823 }
824 sci_rep = reinterpret_cast<science_report*>(w);
825 gui()->game_tab_widget->setCurrentWidget(sci_rep);
826 }
827}
#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:121
void resize_me(int height, bool force=false)
Definition sidebar.cpp:566
void add_widget(fc_sidewidget *fsw)
Definition sidebar.cpp:533
QList< fc_sidewidget * > objects
Definition sidebar.h:117
void update_fonts()
Definition sidebar.cpp:608
void paintEvent(QPaintEvent *event)
Definition sidebar.cpp:543
void paint(QPainter *painter, QPaintEvent *event)
Definition sidebar.cpp:555
void update_fonts()
Definition sidebar.cpp:132
void set_wheel_down(pfcn func)
Definition sidebar.cpp:283
QPixmap * final_pixmap
Definition sidebar.h:96
QFont * info_font
Definition sidebar.h:94
pfcn wheel_down
Definition sidebar.h:90
QString custom_label
Definition sidebar.h:98
QFont * sfont
Definition sidebar.h:93
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:315
QString desc
Definition sidebar.h:99
void set_wheel_up(pfcn func)
Definition sidebar.cpp:291
void some_slot()
Definition sidebar.cpp:352
void contextMenuEvent(QContextMenuEvent *event)
Definition sidebar.cpp:254
pfcn wheel_up
Definition sidebar.h:91
QPixmap * def_pixmap
Definition sidebar.h:95
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:299
void set_left_click(pfcn_bool func)
Definition sidebar.cpp:267
void set_label(QString str)
Definition sidebar.cpp:176
void sblink()
Definition sidebar.cpp:331
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:100
void set_right_click(pfcn func)
Definition sidebar.cpp:275
bool disabled
Definition sidebar.h:73
void set_tooltip(QString tooltip)
Definition sidebar.cpp:160
void leaveEvent(QEvent *event)
Definition sidebar.cpp:240
pfcn_bool left_click
Definition sidebar.h:92
void enterEvent(QEnterEvent *event)
Definition sidebar.cpp:227
void update_final_pixmap()
Definition sidebar.cpp:389
QPixmap * scaled_pixmap
Definition sidebar.h:97
QPixmap * get_pixmap()
Definition sidebar.cpp:168
pfcn right_click
Definition sidebar.h:89
void create()
Definition menu.cpp:590
void update()
Definition menu.cpp:631
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:102
@ O_LUXURY
Definition fc_types.h:102
@ O_GOLD
Definition fc_types.h:102
#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
int dsend_packet_player_research(struct connection *pc, int tech)
static mpgui * gui
Definition mpgui_qt.cpp:53
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:4369
bool option_bool_get(const struct option *poption)
Definition options.c:848
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:482
#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:541
struct research * research_get(const struct player *pplayer)
Definition research.c:130
static void reduce_mod(int &val, int &mod)
Definition sidebar.cpp:49
void side_center_unit()
Definition sidebar.cpp:645
void side_show_map(bool nothing)
Definition sidebar.cpp:619
void update_turn_done_tooltip()
Definition sidebar.cpp:654
void side_indicators_menu()
Definition sidebar.cpp:697
void side_left_click_science(bool nothing)
Definition sidebar.cpp:805
void side_rates_wdg(bool nothing)
Definition sidebar.cpp:635
void side_finish_turn(bool nothing)
Definition sidebar.cpp:627
void side_right_click_science(void)
Definition sidebar.cpp:756
void side_blink_endturn(bool do_restore)
Definition sidebar.cpp:685
void side_disable_endturn(bool do_restore)
Definition sidebar.cpp:672
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:711
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:246
#define A_FIRST
Definition tech.h:44
#define advance_index_iterate(_start, _index)
Definition tech.h:242
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:7127
struct sprite * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Definition tilespec.c:7014