Freeciv-3.4
Loading...
Searching...
No Matches
citydlg.cpp
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
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 <QApplication>
20#include <QCheckBox>
21#include <QGroupBox>
22#include <QHeaderView>
23#include <QImage>
24#include <QMenu>
25#include <QMessageBox>
26#include <QPainter>
27#include <QRadioButton>
28#include <QRect>
29#include <QScreen>
30#include <QScrollArea>
31#include <QScrollBar>
32#include <QSplitter>
33#include <QToolTip>
34#include <QVBoxLayout>
35#include <QWheelEvent>
36#include <QWidgetAction>
37
38// utility
39#include "support.h"
40
41// common
42#include "citizens.h"
43#include "city.h"
44#include "counters.h"
45#include "game.h"
46
47//agents
48#include "cma_core.h"
49#include "cma_fec.h"
50
51// client
52#include "citydlg_common.h"
53#include "client_main.h"
54#include "climisc.h"
55#include "control.h"
56#include "global_worklist.h"
57#include "helpdata.h"
58#include "mapview_common.h"
59#include "movement.h"
60#include "sprite.h"
61#include "text.h"
62#include "tilespec.h"
63
64// gui-qt
65#include "citydlg.h"
66#include "colors.h"
67#include "fc_client.h"
68#include "gui_main.h"
69#include "hudwidget.h"
70
71static bool city_dlg_created = false;
76extern QString split_text(QString text, bool cut);
77extern QString cut_helptext(QString text);
78
79/************************************************************************/
83{
84 m_timer.start();
85 startTimer(50);
87 sfont = new QFont;
89 pix = nullptr;
90}
91
92/************************************************************************/
96{
97 if (pix != nullptr) {
98 delete pix;
99 }
100 delete sfont;
101}
102
103/************************************************************************/
110
111/************************************************************************/
115{
116 struct sprite *sprite;
118 QImage img;
120 QRect crop;
121
122 if (VUT_UTYPE == target->kind) {
125 } else {
127 }
128 if (pix != nullptr) {
129 delete pix;
130 }
131 if (sprite == nullptr) {
132 pix = nullptr;
133 return;
134 }
135 img = sprite->pm->toImage();
137 cropped_img = img.copy(crop);
138 tpix = QPixmap::fromImage(cropped_img);
139 pix = new QPixmap(tpix.width(), tpix.height());
140 pix->fill(Qt::transparent);
141 pixmap_copy(pix, &tpix, 0 , 0, 0, 0, tpix.width(), tpix.height());
142}
143
144/************************************************************************/
148{
149 struct sprite *sprite;
150
153 } else {
154 sprite = nullptr;
155 }
156 if (pix != nullptr) {
157 delete pix;
158 }
159 if (sprite == nullptr) {
160 pix = nullptr;
161 return;
162 }
163 pix = new QPixmap(sprite->pm->width(),
164 sprite->pm->height());
165 pix->fill(Qt::transparent);
166 pixmap_copy(pix, sprite->pm, 0 , 0, 0, 0,
167 sprite->pm->width(), sprite->pm->height());
168 if (isVisible()) {
169 update();
170 }
171}
172
173/************************************************************************/
177{
178 if ((value() != minimum() && value() < maximum())
179 || (0 == minimum() && 0 == maximum())) {
180 m_animate_step = m_timer.elapsed() / 50;
181 update();
182 }
183}
184
185/************************************************************************/
189{
190 QPainter p;
192 QColor c;
193 QRect r, rx, r2;
194 int max;
195 int f_pixel_size;
196 int pix_width = 0;
197 int pixel_size = sfont->pixelSize();
198 int pbw, pbh;
199
200 if (pix != nullptr) {
201 pix_width = height() - 4;
202 }
203
204 if (pixel_size > 0) {
206 } else {
208
209 f_pixel_size = fm.height();
210 }
211
212 pbw = width();
213 pbh = height();
214
215 rx.setX(0);
216 rx.setY(0);
217 rx.setWidth(pbw);
218 rx.setHeight(pbh);
219 p.begin(this);
220 p.drawLine(rx.topLeft(), rx.topRight());
221 p.drawLine(rx.bottomLeft(), rx.bottomRight());
222
223 max = maximum();
224
225 if (max == 0) {
226 max = 1;
227 }
228
229 r = QRect(0, 0, pbw * value() / max, pbh);
230
231 gx = QLinearGradient(0 , 0, 0, pbh);
232 c = QColor(palette().color(QPalette::Highlight));
233 gx.setColorAt(0, c);
234 gx.setColorAt(0.5, QColor(40, 40, 40));
235 gx.setColorAt(1, c);
236 p.fillRect(r, QBrush(gx));
237 p.setClipRegion(reg.translated(m_animate_step % 32, 0));
238
239 g = QLinearGradient(0 , 0, pbw, pbh);
240 c.setAlphaF(0.1);
241 g.setColorAt(0, c);
242 c.setAlphaF(0.9);
243 g.setColorAt(1, c);
244 p.fillRect(r, QBrush(g));
245
246 p.setClipping(false);
247 r2 = QRect(pbw * value() / max, 0, pbw, pbh);
248 c = palette().color(QPalette::Window);
249 p.fillRect(r2, c);
250
251 // Draw icon
252 if (pix != nullptr) {
253 p.setCompositionMode(QPainter::CompositionMode_SourceOver);
254 p.drawPixmap(2 , 2, pix_width
255 * static_cast<float>(pix->width()) / pix->height(),
256 pix_width, *pix, 0, 0, pix->width(), pix->height());
257 }
258
259 // Draw text
260 c = palette().color(QPalette::Text);
261 p.setPen(c);
262 sfont->setCapitalization(QFont::AllUppercase);
263 sfont->setBold(true);
264
265 if (text().contains('\n')) {
266 QString s1, s2;
267 int i, j;
268 QFont tmp_font = *sfont; // Don't make changes to font to be kept
269
270 i = text().indexOf('\n');
271 s1 = text().left(i);
272 s2 = text().right(text().length() - i);
273
274 if (2 * f_pixel_size >= 3 * pbh / 2) {
275 tmp_font.setPixelSize(pbh / 3);
276 }
277
278 p.setFont(tmp_font);
279
280 j = pbh - 2 * f_pixel_size;
281 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
283
284 if (fm.horizontalAdvance(s1) > rx.width()) {
285 s1 = fm.elidedText(s1, Qt::ElideRight, rx.width());
286 }
287
288 i = rx.width() - fm.horizontalAdvance(s1) + pix_width;
289 i = qMax(0, i);
290 p.drawText(i / 2, j / 3 + f_pixel_size, s1);
291
292 if (fm.horizontalAdvance(s2) > rx.width()) {
293 s2 = fm.elidedText(s2, Qt::ElideRight, rx.width());
294 }
295
296 i = rx.width() - fm.horizontalAdvance(s2) + pix_width;
297 i = qMax(0, i);
298
299 p.drawText(i / 2, pbh - j / 3, s2);
300 } else {
301 QString s;
302 int i, j;
303
304 p.setFont(*sfont);
305
306 s = text();
307 j = pbh - f_pixel_size;
308 p.setCompositionMode(QPainter::CompositionMode_ColorDodge);
310
311 if (fm.horizontalAdvance(s) > rx.width()) {
312 s = fm.elidedText(s, Qt::ElideRight, rx.width());
313 }
314
315 i = rx.width() - fm.horizontalAdvance(s) + pix_width;
316 i = qMax(0, i);
317 p.drawText(i / 2, j / 2 + f_pixel_size, s);
318 }
319
320 p.end();
321}
322
323/************************************************************************/
327{
328 int offset;
329 QRect r(-50, 0, width() + 50, height());
330 int chunk_width = 16;
331 int size = width() + 50;
332 reg = QRegion();
333
334 for (offset = 0; offset < (size * 2); offset += (chunk_width * 2)) {
335 QPolygon a;
336
337 a.setPoints(4, r.x(), r.y() + offset,
338 r.x() + r.width(), (r.y() + offset) - size,
339 r.x() + r.width(),
340 (r.y() + offset + chunk_width) - size,
341 r.x(), r.y() + offset + chunk_width);
342 reg += QRegion(a);
343 }
344
345}
346
347/************************************************************************/
350static void pixmap_put_x(QPixmap *pix)
351{
352 QPen pen(QColor(0, 0, 0));
353 QPainter p;
354
355 pen.setWidth(2);
356 p.begin(pix);
357 p.setRenderHint(QPainter::Antialiasing);
358 p.setPen(pen);
359 p.drawLine(0, 0, pix->width(), pix->height());
360 p.drawLine(pix->width(), 0, 0, pix->height());
361 p.end();
362}
363
364/************************************************************************/
367impr_item::impr_item(QWidget *parent, const impr_type *building,
368 struct city *pcity): QLabel(parent)
369{
371 dlgcity = pcity;
372 impr = building;
373 impr_pixmap = nullptr;
374 struct sprite *sprite;
375 sprite = get_building_sprite(tileset , building);
376
377 if (sprite != nullptr) {
379 sprite->pm->height());
380 impr_pixmap->map_pixmap.fill(Qt::transparent);
381 pixmap_copy(&impr_pixmap->map_pixmap, sprite->pm, 0 , 0, 0, 0,
382 sprite->pm->width(), sprite->pm->height());
383 } else {
385 impr_pixmap->map_pixmap.fill(Qt::red);
386 }
387
391}
392
393/************************************************************************/
397{
398 if (impr_pixmap) {
400 }
401}
402
403/************************************************************************/
407{
409 update();
410}
411
412/************************************************************************/
416{
417 struct sprite *sprite;
418 QPainter p;
419
420 if (impr_pixmap) {
422 }
423
425 if (impr && sprite) {
427 sprite->pm->height());
428 impr_pixmap->map_pixmap.fill(QColor(palette().color(QPalette::Highlight)));
429 pixmap_copy(&impr_pixmap->map_pixmap, sprite->pm, 0 , 0, 0, 0,
430 sprite->pm->width(), sprite->pm->height());
431 } else {
433 impr_pixmap->map_pixmap.fill(QColor(palette().color(QPalette::Highlight)));
434 }
435
436 init_pix();
437}
438
439/************************************************************************/
443{
444 struct sprite *sprite;
445
446 if (impr_pixmap) {
448 }
449
451 if (impr && sprite) {
453 sprite->pm->height());
454 impr_pixmap->map_pixmap.fill(Qt::transparent);
455 pixmap_copy(&impr_pixmap->map_pixmap, sprite->pm, 0 , 0, 0, 0,
456 sprite->pm->width(), sprite->pm->height());
457 } else {
459 impr_pixmap->map_pixmap.fill(Qt::red);
460 }
461
462 init_pix();
463}
464
465/************************************************************************/
469{
471 layout = new QHBoxLayout(this);
472 init_layout();
473}
474
475/************************************************************************/
479{
480 QSizePolicy size_fixed_policy(QSizePolicy::Fixed,
481 QSizePolicy::MinimumExpanding,
482 QSizePolicy::Slider);
483
486}
487
488/************************************************************************/
492{
493
494}
495
496/************************************************************************/
500{
501 impr_list.append(item);
502}
503
504/************************************************************************/
508{
509 int i = impr_list.count();
510 impr_item *ui;
511 int j;
512 setUpdatesEnabled(false);
513 setMouseTracking(false);
514
515 for (j = 0; j < i; j++) {
516 ui = impr_list[j];
517 layout->removeWidget(ui);
518 delete ui;
519 }
520
521 while (!impr_list.empty()) {
522 impr_list.removeFirst();
523 }
524
525 setMouseTracking(true);
526 setUpdatesEnabled(true);
527}
528
529/************************************************************************/
533{
534 QPoint p;
535
536 p = parentWidget()->parentWidget()->pos();
537 p = mapToGlobal(p);
538
539 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
540 event->angleDelta(),
541 event->buttons(),
542 event->modifiers(),
543 event->phase(), false, event->source());
544
545 QApplication::sendEvent(parentWidget(), &new_event);
546}
547
548/************************************************************************/
552{
553 int i = impr_list.count();
554 int j;
555 int h = 0;
556 impr_item *ui;
557
558 setUpdatesEnabled(false);
559 hide();
560
561 for (j = 0; j < i; j++) {
562 ui = impr_list[j];
563 h = ui->height();
564 layout->addWidget(ui, 0, Qt::AlignVCenter);
565 }
566
567 if (impr_list.count() > 0) {
568 parentWidget()->parentWidget()->setFixedHeight(city_dlg->scroll_height
569 + h + 6);
570 } else {
571 parentWidget()->parentWidget()->setFixedHeight(0);
572 }
573
574 show();
575 setUpdatesEnabled(true);
576 layout->update();
578}
579
580/************************************************************************/
584{
585 QPoint p;
586
587 p = parentWidget()->parentWidget()->pos();
588 p = mapToGlobal(p);
589
590 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
591 event->angleDelta(),
592 event->buttons(),
593 event->modifiers(),
594 event->phase(), false, event->source());
595
596 QApplication::sendEvent(parentWidget()->parentWidget(),
597 &new_event);
598}
599
600/************************************************************************/
604{
606 return;
607 }
608
609 if (event->button() == Qt::LeftButton) {
610 char buf[256];
611 int price;
612 const int impr_id = improvement_number(impr);
613 const int city_id = dlgcity->id;
615
617 impr) != TR_SUCCESS) {
618 return;
619 }
620
622
625 PL_("Sell %s for %d gold?",
626 "Sell %s for %d gold?", price),
628
629 ask->set_text_title(buf, (_("Sell improvement?")));
630 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
631 ask->setAttribute(Qt::WA_DeleteOnClose);
632 connect(ask, &hud_message_box::accepted, [=]() {
633 struct city *pcity = game_city_by_number(city_id);
634
635 if (pcity == nullptr) {
636 return;
637 }
639 });
640 ask->show();
641 }
642}
643
644/************************************************************************/
648 bool supp, int hppy_cost) : QLabel()
649{
652 QImage img;
653 QRect crop;
654 qunit = punit;
655 struct canvas *unit_pixmap;
656 struct tileset *tmp;
657 float isosize;
658
660 supported = supp;
661
662 tmp = nullptr;
663 if (unscaled_tileset) {
664 tmp = tileset;
666 }
667 isosize = 0.6;
669 isosize = 0.45;
670 }
671
672 if (punit) {
673 if (supported) {
676 } else {
679 }
680
681 unit_pixmap->map_pixmap.fill(Qt::transparent);
682 put_unit(punit, unit_pixmap, 1.0, 0, 0);
683
684 if (supported) {
688 }
689 } else {
691 unit_pixmap->map_pixmap.fill(Qt::transparent);
692 }
693
694 img = unit_pixmap->map_pixmap.toImage();
696 cropped_img = img.copy(crop);
699 * isosize, Qt::SmoothTransformation);
700 } else {
702 Qt::SmoothTransformation);
703 }
705 if (tmp != nullptr) {
706 tileset = tmp;
707 }
708
710 setFixedWidth(unit_img.width() + 4);
711 setFixedHeight(unit_img.height());
713}
714
715/************************************************************************/
719{
720 setPixmap(QPixmap::fromImage(unit_img));
721 update();
722}
723
724/************************************************************************/
730
731/************************************************************************/
735{
736 QMenu *menu;
737
739 return;
740 }
741
742 if (unit_owner(qunit) != client_player()) {
743 return;
744 }
745
746 menu = new QMenu(gui()->central_wdg);
747 menu->addAction(activate);
748 menu->addAction(activate_and_close);
749
750 if (sentry) {
751 menu->addAction(sentry);
752 }
753
754 if (fortify) {
755 menu->addAction(fortify);
756 }
757
758 if (change_home) {
759 menu->addAction(change_home);
760 }
761
762 if (load) {
763 menu->addAction(load);
764 }
765
766 if (unload) {
767 menu->addAction(unload);
768 }
769
770 if (unload_trans) {
771 menu->addAction(unload_trans);
772 }
773
774 if (disband_action) {
775 menu->addAction(disband_action);
776 }
777
778 if (upgrade) {
779 menu->addAction(upgrade);
780 }
781
782 menu->popup(event->globalPos());
783}
784
785/************************************************************************/
789{
790 struct unit_list *qunits;
791
793 return;
794 }
795
798 activate = new QAction(_("Activate unit"), this);
799 connect(activate, &QAction::triggered, this, &unit_item::activate_unit);
800 activate_and_close = new QAction(_("Activate and close dialog"), this);
801 connect(activate_and_close, &QAction::triggered, this,
803
805 sentry = new QAction(_("Sentry unit"), this);
806 connect(sentry, &QAction::triggered, this, &unit_item::sentry_unit);
807 } else {
808 sentry = nullptr;
809 }
810
812 fortify = new QAction(_("Fortify unit"), this);
813 connect(fortify, &QAction::triggered, this, &unit_item::fortify_unit);
814 } else {
815 fortify = nullptr;
816 }
818 disband_action = new QAction(_("Disband unit"), this);
819 connect(disband_action, &QAction::triggered, this, &unit_item::disband);
820 } else {
821 disband_action = nullptr;
822 }
823
826 this);
827 connect(change_home, &QAction::triggered, this, &unit_item::change_homecity);
828 } else {
829 change_home = nullptr;
830 }
831
832 if (units_can_load(qunits)) {
833 load = new QAction(_("Load"), this);
834 connect(load, &QAction::triggered, this, &unit_item::load_unit);
835 } else {
836 load = nullptr;
837 }
838
839 if (units_can_unload(&(wld.map), qunits)) {
840 unload = new QAction(_("Unload"), this);
841 connect(unload, &QAction::triggered, this, &unit_item::unload_unit);
842 } else {
843 unload = nullptr;
844 }
845
847 unload_trans = new QAction(_("Unload All From Transporter"), this);
848 connect(unload_trans, &QAction::triggered, this, &unit_item::unload_all);
849 } else {
850 unload_trans = nullptr;
851 }
852
853 if (units_can_upgrade(&(wld.map), qunits)) {
854 upgrade = new QAction(_("Upgrade Unit"), this);
855 connect(upgrade, &QAction::triggered, this, &unit_item::upgrade_unit);
856 } else {
857 upgrade = nullptr;
858 }
859
861}
862
863/************************************************************************/
867{
868 struct unit_list *punits;
870
871 if (punit == nullptr) {
872 return;
873 }
874
879}
880
881/************************************************************************/
888
889/************************************************************************/
896
897/************************************************************************/
904
905/************************************************************************/
916
917/************************************************************************/
926
927/************************************************************************/
937
938/************************************************************************/
942{
943 if (qunit) {
945 }
946}
947
948/************************************************************************/
952{
953 if (qunit) {
955 }
956}
957
958/************************************************************************/
962{
963 QImage temp_img(unit_img.size(), QImage::Format_ARGB32_Premultiplied);
964 QPainter p;
965
966 p.begin(&temp_img);
967 p.fillRect(0, 0, unit_img.width(), unit_img.height(),
968 QColor(palette().color(QPalette::Highlight)));
969 p.drawImage(0, 0, unit_img);
970 p.end();
971
972 setPixmap(QPixmap::fromImage(temp_img));
973 update();
974}
975
976/************************************************************************/
980{
981 init_pix();
982}
983
984/************************************************************************/
988{
989 QPoint p;
990
991 p = parentWidget()->parentWidget()->pos();
992 p = mapToGlobal(p);
993
994 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
995 event->angleDelta(),
996 event->buttons(),
997 event->modifiers(),
998 event->phase(), false, event->source());
999
1000 QApplication::sendEvent(parentWidget()->parentWidget(),
1001 &new_event);
1002}
1003
1004/************************************************************************/
1008{
1009 if (event->button() == Qt::LeftButton) {
1010 if (qunit) {
1013 }
1014 }
1015}
1016
1017/************************************************************************/
1021{
1022 if (qunit) {
1024 }
1025}
1026
1027/************************************************************************/
1031{
1032 layout = new QHBoxLayout(this);
1033 init_layout();
1034 supports = supp;
1035}
1036
1037/************************************************************************/
1041{
1043 unit_list.clear();
1044}
1045
1046/************************************************************************/
1050{
1051 unit_list.append(item);
1052}
1053
1054/************************************************************************/
1058{
1059 QSizePolicy size_fixed_policy(QSizePolicy::Fixed,
1060 QSizePolicy::MinimumExpanding,
1061 QSizePolicy::Slider);
1064}
1065
1066/************************************************************************/
1070{
1071 QPoint p;
1072
1073 p = parentWidget()->parentWidget()->pos();
1074 p = mapToGlobal(p);
1075
1076 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
1077 event->angleDelta(),
1078 event->buttons(),
1079 event->modifiers(),
1080 event->phase(), false, event->source());
1081
1082 QApplication::sendEvent(parentWidget(), &new_event);
1083}
1084
1085/************************************************************************/
1089{
1090 int i = unit_list.count();
1091 int j;
1092 int h;
1093 float hexfix;
1094 unit_item *ui;
1095
1096 setUpdatesEnabled(false);
1097 hide();
1098
1099 for (j = 0; j < i; j++) {
1100 ui = unit_list[j];
1101 layout->addWidget(ui, 0, Qt::AlignVCenter);
1102 }
1103
1104 hexfix = 1.0;
1106 hexfix = 0.75;
1107 }
1108
1110 h = tileset_unit_width(get_tileset()) * 0.7 * hexfix + 6;
1111 } else {
1113 }
1114 if (unit_list.count() > 0) {
1115 parentWidget()->parentWidget()->setFixedHeight(city_dlg->scroll_height
1116 + h);
1117 } else {
1118 parentWidget()->parentWidget()->setFixedHeight(0);
1119 }
1120 show();
1121 setUpdatesEnabled(true);
1122 layout->update();
1124}
1125
1126/************************************************************************/
1130{
1131 int i = unit_list.count();
1132 unit_item *ui;
1133 int j;
1134 setUpdatesEnabled(false);
1135 setMouseTracking(false);
1136
1137 for (j = 0; j < i; j++) {
1138 ui = unit_list[j];
1139 layout->removeWidget(ui);
1140 delete ui;
1141 }
1142
1143 while (!unit_list.empty()) {
1144 unit_list.removeFirst();
1145 }
1146
1147 setMouseTracking(true);
1148 setUpdatesEnabled(true);
1149}
1150
1151/************************************************************************/
1155city_label::city_label(int t, QWidget *parent) : QLabel(parent)
1156{
1157 type = t;
1158}
1159
1160/************************************************************************/
1164{
1165 int citnum, i;
1166 int w = tileset_small_sprite_width(tileset) / gui()->map_scale;
1167 int num_citizens = pcity->size;
1168
1169 if (cma_is_city_under_agent(pcity, nullptr)) {
1170 return;
1171 }
1172
1173 i = 1 + (num_citizens * 5 / 200);
1174 w = w / i;
1175 citnum = event->pos().x() / w;
1176
1177 if (!can_client_issue_orders()) {
1178 return;
1179 }
1180
1182}
1183
1184/************************************************************************/
1188{
1189 pcity = pciti;
1190}
1191
1192/************************************************************************/
1196{
1198 radius = 0;
1204 view->map_pixmap.fill(Qt::black);
1206 miniview->map_pixmap.fill(Qt::black);
1207 delta_x = 0;
1208 delta_y = 0;
1209 setContextMenuPolicy(Qt::CustomContextMenu);
1210 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
1211 this, SLOT(context_menu(const QPoint &)));
1212}
1213
1214/************************************************************************/
1222
1223/************************************************************************/
1227{
1229 QString str;
1230
1231 painter.begin(this);
1232 painter.drawPixmap(0, 0, zoomed_pixmap);
1233
1234 if (cma_is_city_under_agent(mcity, nullptr)) {
1235 painter.fillRect(0, 0, zoomed_pixmap.width(), zoomed_pixmap.height(),
1236 QBrush(QColor(60, 60 , 60 , 110)));
1237 painter.setPen(QColor(255, 255, 255));
1238 // TRANS: %1 is a custom string chosen by player.
1239 str = QString(_("Governor %1"))
1241 painter.drawText(5, zoomed_pixmap.height() - 10, str);
1242 }
1243
1244 painter.end();
1245}
1246
1247/************************************************************************/
1250void city_map::set_pixmap(struct city *pcity, float z)
1251{
1252 int r, max_r;
1253 QSize size;
1254
1255 zoom = z;
1257
1258 if (radius != r) {
1260 radius = r;
1262 cutted_width = wdth * (r + 1) / max_r;
1263 cutted_height = height * (r + 1) / max_r;
1266 delta_x = (wdth - cutted_width) / 2;
1267 delta_y = (height - cutted_height) / 2;
1269 miniview->map_pixmap.fill(Qt::black);
1270 }
1271
1275 size = miniview->map_pixmap.size();
1277 Qt::KeepAspectRatio,
1278 Qt::SmoothTransformation);
1280 mcity = pcity;
1281}
1282
1283/************************************************************************/
1287{
1288 return zoomed_pixmap.size();
1289}
1290
1291/************************************************************************/
1295{
1296 return zoomed_pixmap.size();
1297}
1298
1299/************************************************************************/
1303{
1305 QPoint pos;
1306
1307 if (!can_client_issue_orders() || event->button() != Qt::LeftButton) {
1308 return;
1309 }
1310
1311 pos = event->pos();
1312 canvas_x = pos.x() / zoom + delta_x;
1313 canvas_y = pos.y() / zoom + delta_y;
1314
1316 canvas_x, canvas_y)) {
1318 }
1319}
1320
1321/************************************************************************/
1325{
1327 QAction *con_cultivate = nullptr;
1328 QAction *con_irrig = nullptr;
1329 QAction *con_plant = nullptr;
1330 QAction *con_mine = nullptr;
1331 QAction *con_road = nullptr;
1332 QAction *con_trfrm = nullptr;
1333 QAction *con_clean = nullptr;
1334 QAction *con_clear = nullptr;
1335 QMenu *con_menu;
1337 struct terrain *pterr;
1338 struct tile *ptile;
1339 struct universal for_terr;
1340 struct worker_task *ptask;
1341 int city_id = mcity->id;
1342
1343 if (!can_client_issue_orders()) {
1344 return;
1345 }
1346
1347 canvas_x = point.x() / zoom + delta_x;
1348 canvas_y = point.y() / zoom + delta_y;
1349
1351 canvas_x, canvas_y)) {
1352 return;
1353 }
1354
1356 city_x, city_y);
1357 pterr = tile_terrain(ptile);
1358 for_terr.kind = VUT_TERRAIN;
1359 for_terr.value.terrain = pterr;
1361
1362 wid_act = new QWidgetAction(this);
1363 wid_act->setDefaultWidget(new QLabel(_("Autoworker activity:")));
1364
1365 con_menu = new QMenu(this);
1366 con_menu->addAction(wid_act);
1367
1368 if (pterr->plant_result != nullptr
1370 con_plant = con_menu->addAction(_("Plant"));
1371 }
1373 con_mine = con_menu->addAction(Q_("?act:Mine"));
1374 }
1375
1376 if (pterr->cultivate_result != nullptr
1378 con_cultivate = con_menu->addAction(_("Cultivate"));
1379 }
1381 con_irrig = con_menu->addAction(_("Irrigate"));
1382 }
1383
1384 if (pterr->transform_result != pterr && pterr->transform_result != nullptr
1386 nullptr, &for_terr)) {
1387 con_trfrm = con_menu->addAction(_("Transform"));
1388 }
1389
1390 if (next_extra_for_tile(ptile, EC_ROAD, city_owner(mcity), nullptr) != nullptr) {
1391 con_road = con_menu->addAction(_("Road"));
1392 }
1393
1394 if (prev_extra_in_tile(ptile, ERM_CLEAN,
1395 city_owner(mcity), nullptr) != nullptr) {
1396 con_clean = con_menu->addAction(_("Clean"));
1397 }
1398
1399 if (ptask != nullptr) {
1400 con_clear = con_menu->addAction(_("Clear"));
1401 }
1402
1403 con_menu->setAttribute(Qt::WA_DeleteOnClose);
1404 connect(con_menu, &QMenu::triggered,
1406 bool target = false;
1407 struct packet_worker_task task;
1408
1409 if (!act) {
1410 return;
1411 }
1412
1413 task.city_id = city_id;
1414
1415 if (act == con_road) {
1417 target = TRUE;
1418 } else if (act == con_mine) {
1419 task.activity = ACTIVITY_MINE;
1420 target = TRUE;
1421 } else if (act == con_plant) {
1422 task.activity = ACTIVITY_PLANT;
1423 } else if (act == con_irrig) {
1425 target = TRUE;
1426 } else if (act == con_cultivate) {
1428 } else if (act == con_trfrm) {
1430 } else if (act == con_clean) {
1431 task.activity = ACTIVITY_CLEAN;
1432 target = TRUE;
1433 } else if (act == con_clear) {
1434 task.activity = ACTIVITY_LAST;
1435 } else {
1436 // Closed dialog without selecting any activity entry.
1437 return;
1438 }
1439
1440 task.want = 100;
1441
1442 if (target) {
1443 enum extra_cause cause = activity_to_extra_cause(task.activity);
1445 struct extra_type *tgt;
1446
1447 if (cause != EC_NONE) {
1448 tgt = next_extra_for_tile(ptile, cause, city_owner(mcity), nullptr);
1449 } else if (rmcause != ERM_NONE) {
1450 tgt = prev_extra_in_tile(ptile, rmcause, city_owner(mcity), nullptr);
1451 } else {
1452 tgt = nullptr;
1453 }
1454
1455 if (tgt != nullptr) {
1456 task.tgt = extra_index(tgt);
1457 } else {
1458 task.tgt = -1;
1459 }
1460 } else {
1461 task.tgt = -1;
1462 }
1463
1464 task.tile_id = ptile->index;
1466 });
1467
1468 con_menu->popup(mapToGlobal(point));
1469}
1470
1471/************************************************************************/
1475{
1476 QFont f = QApplication::font();
1477 QFont *small_font;
1478 QFontMetrics fm(f);
1484 QHeaderView *header;
1485 QLabel *lab2, *label, *ql, *some_label;
1486 QPushButton *qpush2;
1488 QSizePolicy size_expanding_policy(QSizePolicy::Expanding,
1489 QSizePolicy::Expanding);
1490 QSlider *slider;
1491 QStringList info_list, str_list;
1496 int list_size;
1497 int h = 2 * fm.height() + 2;
1498
1501 zoom = 1.0;
1502
1504 central_splitter->setOpaqueResize(false);
1506 central_left_splitter->setOpaqueResize(false);
1508 prod_unit_splitter->setOpaqueResize(false);
1509
1510 setMouseTracking(true);
1511 selected_row_p = -1;
1512 dlgcity = nullptr;
1513 lcity_name = new QPushButton(this);
1514 lcity_name->setToolTip(_("Click to change city name"));
1515
1517 single_page_layout->setContentsMargins(0, 0 ,0 ,0);
1518 size_expanding_policy.setHorizontalStretch(0);
1519 size_expanding_policy.setVerticalStretch(0);
1521 current_building = 0;
1522
1523 // Map view
1524 map_box = new QGroupBox(this);
1525
1526 // City information widget texts about surpluses and so on
1527 info_wdg = new QWidget(this);
1528
1529 // Fill info_wdg with labels
1531
1532 info_wdg->setFont(*small_font);
1533 info_grid_layout->setSpacing(0);
1534 info_grid_layout->setContentsMargins(0, 0, 0, 0);
1535
1536
1537 for (enum city_info info_field = city_info_begin();
1540
1541 ql = new QLabel(_(city_info_name(info_field)), info_wdg);
1542 ql->setFont(*small_font);
1543 ql->setProperty(fonts::notify_label, "true");
1544 info_grid_layout->addWidget(ql, info_field, 0);
1545 qlt[info_field] = new QLabel(info_wdg);
1546 qlt[info_field]->setFont(*small_font);
1547 qlt[info_field]->setProperty(fonts::notify_label, "true");
1548 info_grid_layout->addWidget(qlt[info_field], info_field, 1);
1549 info_grid_layout->setRowStretch(info_field, 0);
1550 }
1551
1552 info_wdg->setLayout(info_grid_layout);
1553
1554 // Buy button
1555 buy_button = new QPushButton();
1556 buy_button->setIcon(fc_icons::instance()->get_icon("help-donate"));
1557 connect(buy_button, &QAbstractButton::clicked, this, &city_dialog::buy);
1558
1559 connect(lcity_name, &QAbstractButton::clicked, this, &city_dialog::city_rename);
1561 citizen_pixmap = nullptr;
1562 view = new city_map(this);
1563
1564 zoom_vbox = new QVBoxLayout();
1565 zoom_in_button = new QPushButton();
1566 zoom_in_button->setIcon(fc_icons::instance()->get_icon("plus"));
1567 zoom_in_button->setIconSize(QSize(16, 16));
1568 zoom_in_button->setFixedSize(QSize(20, 20));
1569 zoom_in_button->setToolTip(_("Zoom in"));
1570 connect(zoom_in_button, &QAbstractButton::clicked, this, &city_dialog::zoom_in);
1571 zoom_out_button = new QPushButton();
1572 zoom_out_button->setIcon(fc_icons::instance()->get_icon("minus"));
1573 zoom_out_button->setIconSize(QSize(16, 16));
1574 zoom_out_button->setFixedSize(QSize(20, 20));
1575 zoom_out_button->setToolTip(_("Zoom out"));
1576 connect(zoom_out_button, &QAbstractButton::clicked, this, &city_dialog::zoom_out);
1577 zoom_vbox->addWidget(zoom_in_button);
1578 zoom_vbox->addWidget(zoom_out_button);
1579
1580 // City map group box
1583 hbox_layout->addStretch(100);
1584 hbox_layout->addWidget(view);
1585 hbox_layout->addStretch(100);
1586 hbox_layout->addLayout(zoom_vbox);
1587 vbox_layout->addLayout(hbox_layout);
1588 vbox_layout->addWidget(lcity_name);
1589 map_box->setLayout(vbox_layout);
1590 map_box->setTitle(_("City map"));
1591
1592 // Current/supported units/improvements widgets
1593 supp_units = new QLabel();
1594 curr_units = new QLabel();
1595 curr_impr = new QLabel();
1596 curr_units->setAlignment(Qt::AlignLeft);
1597 curr_impr->setAlignment(Qt::AlignLeft);
1598 supp_units->setAlignment(Qt::AlignLeft);
1599 supported_units = new unit_info(true);
1600 scroll = new QScrollArea;
1601 scroll->setWidgetResizable(true);
1602 scroll->setMaximumHeight(tileset_unit_with_upkeep_height(get_tileset()) + 6
1603 + scroll->horizontalScrollBar()->height());
1604 scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1605 scroll->setWidget(supported_units);
1606 current_units = new unit_info(false);
1607 scroll2 = new QScrollArea;
1608 scroll2->setWidgetResizable(true);
1609 scroll2->setMaximumHeight(tileset_unit_height(get_tileset()) + 6
1610 + scroll2->horizontalScrollBar()->height());
1611 scroll2->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1612 scroll2->setWidget(current_units);
1613 scroll_height = scroll2->horizontalScrollBar()->height();
1614 city_buildings = new impr_info(this);
1615 scroll3 = new QScrollArea;
1616 scroll3->setWidgetResizable(true);
1617 scroll3->setMaximumHeight(tileset_unit_height(tileset) + 6
1618 + scroll3->horizontalScrollBar()->height());
1619 scroll3->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1620 scroll3->setWidget(city_buildings);
1621 scroll->setProperty("city_scroll", true);
1622 scroll2->setProperty("city_scroll", true);
1623 scroll3->setProperty("city_scroll", true);
1624
1627 right_layout = new QVBoxLayout();
1629 units_layout = new QVBoxLayout();
1630 left_layout = new QVBoxLayout();
1631
1632 /* Checkboxes to show units/wonders/improvements
1633 * on production list */
1636 show_buildings->setToolTip(_("Show buildings"));
1637 show_buildings->setChecked(true);
1638 label = new QLabel();
1639 label->setPixmap(*fc_icons::instance()->get_pixmap("building"));
1640 label->setToolTip(_("Show buildings"));
1641 prod_option_layout->addWidget(show_buildings, Qt::AlignLeft);
1642 prod_option_layout->addWidget(label, Qt::AlignLeft);
1643 prod_option_layout->addStretch(100);
1644 label = new QLabel();
1645 label->setPixmap(*fc_icons::instance()->get_pixmap("cunits"));
1646 label->setToolTip(_("Show units"));
1647 show_units = new QCheckBox;
1648 show_units->setToolTip(_("Show units"));
1649 show_units->setChecked(true);
1650 prod_option_layout->addWidget(show_units, Qt::AlignHCenter);
1651 prod_option_layout->addWidget(label, Qt::AlignHCenter);
1652 prod_option_layout->addStretch(100);
1653 label = new QLabel();
1654 label->setPixmap(*fc_icons::instance()->get_pixmap("wonder"));
1655 label->setToolTip(_("Show wonders"));
1656 show_wonders = new QCheckBox;
1657 show_wonders->setToolTip(_("Show wonders"));
1658 show_wonders->setChecked(true);
1659 prod_option_layout->addWidget(show_wonders);
1660 prod_option_layout->addWidget(label);
1661 prod_option_layout->addStretch(100);
1662 label = new QLabel();
1663 label->setPixmap(*fc_icons::instance()->get_pixmap("future"));
1664 label->setToolTip(_("Show future targets"));
1666 future_targets->setToolTip(_("Show future targets"));
1667 future_targets->setChecked(false);
1669 prod_option_layout->addWidget(label, Qt::AlignRight);
1670 prod_options = new QGroupBox(this);
1671 prod_options->setLayout(prod_option_layout);
1672 prod_options->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
1673
1674 // Prev/next and close buttons
1675 button = new QPushButton;
1676 button->setIcon(fc_icons::instance()->get_icon("city-close"));
1677 button->setIconSize(QSize(56, 56));
1678 button->setToolTip(_("Close city dialog"));
1679 connect(button, &QAbstractButton::clicked, this, &QWidget::hide);
1680
1681 next_city_but = new QPushButton();
1682 next_city_but->setIcon(fc_icons::instance()->get_icon("city-right"));
1683 next_city_but->setIconSize(QSize(56, 56));
1684 next_city_but->setToolTip(_("Show next city"));
1685 connect(next_city_but, &QAbstractButton::clicked, this, &city_dialog::next_city);
1686
1687 prev_city_but = new QPushButton();
1688 connect(prev_city_but, &QAbstractButton::clicked, this, &city_dialog::prev_city);
1689 prev_city_but->setIcon(fc_icons::instance()->get_icon("city-left"));
1690 prev_city_but->setIconSize(QSize(56, 56));
1691 prev_city_but->setToolTip(_("Show previous city"));
1692
1693 happiness_button = new QPushButton();
1694 happiness_button->setIcon(fc_icons::instance()->get_icon("smiley"));
1695 happiness_button->setIconSize(QSize(56,28));
1696 connect(happiness_button, &QAbstractButton::clicked, this,
1698
1699 settings_button = new QPushButton(_("Settings"));
1700 connect(settings_button, &QAbstractButton::clicked, this,
1702 settings_button->setToolTip(_("Counters, worklist, and options menu"));
1703
1704 button->setFixedSize(64, 64);
1705 prev_city_but->setFixedSize(64, 64);
1706 next_city_but->setFixedSize(64, 64);
1707 happiness_button->setFixedSize(64, 32);
1708 settings_button->setFixedSize(64, 32);
1710 vbox_layout->addWidget(prev_city_but);
1711 vbox_layout->addWidget(next_city_but);
1712 vbox_layout->addWidget(button);
1713 vbox_layout->addWidget(happiness_button, Qt::AlignHCenter);
1714 vbox_layout->addWidget(settings_button, Qt::AlignHCenter);
1715
1716 update_tabs();
1718
1719 hbox_layout->addLayout(vbox_layout, Qt::AlignLeft);
1720 hbox_layout->addWidget(info_wdg, Qt::AlignLeft);
1721 hbox_layout->addWidget(map_box, Qt::AlignCenter);
1722
1723 // Layout with city view and buttons
1724 lefttop_layout->addWidget(citizens_label, Qt::AlignHCenter);
1725 lefttop_layout->addStretch(0);
1726 lefttop_layout->addLayout(hbox_layout);
1727 lefttop_layout->addStretch(50);
1728
1729 // Layout for units/buildings
1730 curr_unit_wdg = new QWidget();
1731 supp_unit_wdg = new QWidget();
1732 curr_impr_wdg = new QWidget();
1733 v_layout = new QVBoxLayout;
1734 v_layout->addWidget(curr_impr);
1735 v_layout->addWidget(scroll3);
1736 v_layout->setContentsMargins(0 , 0 , 0, 0);
1737 v_layout->setSpacing(0);
1738 curr_impr_wdg->setLayout(v_layout);
1739 v_layout = new QVBoxLayout;
1740 v_layout->addWidget(curr_units);
1741 v_layout->addWidget(scroll2);
1742 v_layout->setContentsMargins(0 , 0 , 0, 0);
1743 v_layout->setSpacing(0);
1744 curr_unit_wdg->setLayout(v_layout);
1745 v_layout = new QVBoxLayout;
1746 v_layout->addWidget(supp_units);
1747 v_layout->addWidget(scroll);
1748 v_layout->setContentsMargins(0 , 0 , 0, 0);
1749 v_layout->setSpacing(0);
1750 supp_unit_wdg->setLayout(v_layout);
1751
1752 units_layout->addWidget(curr_unit_wdg);
1753 units_layout->addWidget(supp_unit_wdg);
1754 units_layout->addWidget(curr_impr_wdg);
1755 units_layout->setSpacing(0);
1756 units_layout->setContentsMargins(0 , 0 , 0, 0);
1757
1758 vbox = new QVBoxLayout;
1760 qgbprod = new QGroupBox;
1761 group_box = new QGroupBox(_("Worklist Option"));
1763 work_next_but = new QPushButton(fc_icons::instance()->get_icon(
1764 "go-down"), "");
1765 work_prev_but = new QPushButton(fc_icons::instance()->get_icon(
1766 "go-up"), "");
1767 work_add_but = new QPushButton(fc_icons::instance()->get_icon(
1768 "list-add"), "");
1769 work_rem_but = new QPushButton(style()->standardIcon(
1770 QStyle::SP_DialogDiscardButton), "");
1771 work_but_layout->addWidget(work_add_but);
1772 work_but_layout->addWidget(work_next_but);
1773 work_but_layout->addWidget(work_prev_but);
1774 work_but_layout->addWidget(work_rem_but);
1776 production_combo_p->setToolTip(_("Click to change current production"));
1777 p_table_p = new QTableWidget;
1778
1779 r1 = new QRadioButton(_("Change"));
1780 r2 = new QRadioButton(_("Insert Before"));
1781 r3 = new QRadioButton(_("Insert After"));
1782 r4 = new QRadioButton(_("Add Last"));
1783 r4->setChecked(true);
1784 group_box->setLayout(vbox);
1785
1786
1787 p_table_p->setColumnCount(3);
1788 p_table_p->setProperty("showGrid", "false");
1789 p_table_p->setProperty("selectionBehavior", "SelectRows");
1790 p_table_p->setEditTriggers(QAbstractItemView::NoEditTriggers);
1791 p_table_p->verticalHeader()->setVisible(false);
1792 p_table_p->horizontalHeader()->setVisible(false);
1793 p_table_p->setSelectionMode(QAbstractItemView::SingleSelection);
1794 production_combo_p->setFixedHeight(h);
1795 p_table_p->setMinimumWidth(200);
1796 p_table_p->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
1797 p_table_p->setContextMenuPolicy(Qt::CustomContextMenu);
1798 p_table_p->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
1799 header = p_table_p->horizontalHeader();
1800 header->setStretchLastSection(true);
1801
1802 qgbprod->setTitle(_("Worklist"));
1803 vbox_layout->setSpacing(0);
1804 vbox_layout->addWidget(prod_options);
1805 vbox_layout->addWidget(buy_button);
1806 vbox_layout->addWidget(production_combo_p);
1807 vbox_layout->addLayout(work_but_layout);
1808 vbox_layout->addWidget(p_table_p);
1809 qgbprod->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1810 qgbprod->setLayout(vbox_layout);
1811
1812 worklist_layout->setSpacing(0);
1813 worklist_layout->addWidget(qgbprod);
1814 connect(p_table_p,
1815 &QWidget::customContextMenuRequested, this,
1818 connect(work_add_but, &QAbstractButton::clicked, this, &city_dialog::show_targets_worklist);
1819 connect(work_prev_but, &QAbstractButton::clicked, this, &city_dialog::worklist_up);
1820 connect(work_next_but, &QAbstractButton::clicked, this, &city_dialog::worklist_down);
1821 connect(work_rem_but, &QAbstractButton::clicked, this, &city_dialog::worklist_del);
1822 connect(p_table_p,
1823 &QTableWidget::itemDoubleClicked,
1825 connect(p_table_p->selectionModel(),
1827 const QItemSelection &)),
1829 const QItemSelection &)));
1830 happiness_group = new QGroupBox(_("Happiness"));
1831 gridl = new QGridLayout;
1832
1833 nationality_table = new QTableWidget;
1834 nationality_table->setColumnCount(3);
1835 nationality_table->setProperty("showGrid", "false");
1836 nationality_table->setProperty("selectionBehavior", "SelectRows");
1837 nationality_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
1838 nationality_table->verticalHeader()->setVisible(false);
1839 nationality_table->horizontalHeader()->setStretchLastSection(true);
1840
1841 info_list.clear();
1842 info_list << _("Cities:") << _("Luxuries:") << _("Buildings:")
1843 << _("Nationality:") << _("Units:") << _("Wonders:");
1844
1845 for (int i = 0; i < info_list.count(); i++) {
1846 lab_table[i] = new city_label(1 + i, this);
1847 gridl->addWidget(lab_table[i], i, 1, 1, 1);
1848 lab2 = new QLabel(this);
1849 lab2->setFont(*small_font);
1850 lab2->setProperty(fonts::notify_label, "true");
1851 lab2->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1852 lab2->setText(info_list.at(i));
1853 gridl->addWidget(lab2, i, 0, 1, 1);
1854 }
1855
1856 gridl->setSpacing(0);
1857 happiness_group->setLayout(gridl);
1858
1859
1863 happiness_layout->setStretch(0, 10);
1864 happiness_widget = new QWidget();
1866 qgbox = new QGroupBox(_("Presets:"));
1867 qsliderbox = new QGroupBox(_("Governor settings"));
1868 result_box = new QGroupBox(_("Results:"));
1869 hbox = new QHBoxLayout;
1870 gridl = new QGridLayout;
1872
1873 counters_widget = new QWidget();
1875 counters_widget->setLayout(counters_layout);
1876
1877 qpush2
1878 = new QPushButton(style()->standardIcon(QStyle::SP_DialogSaveButton),
1879 _("Save"));
1880 connect(qpush2, &QAbstractButton::pressed, this, &city_dialog::save_cma);
1881
1882 cma_info_text = new QLabel;
1883 cma_info_text->setFont(*small_font);
1884 cma_info_text->setAlignment(Qt::AlignCenter);
1885 cma_table = new QTableWidget;
1886 cma_table->setColumnCount(1);
1887 cma_table->setProperty("showGrid", "false");
1888 cma_table->setProperty("selectionBehavior", "SelectRows");
1889 cma_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
1890 cma_table->setSelectionMode(QAbstractItemView::SingleSelection);
1891 cma_table->setContextMenuPolicy(Qt::CustomContextMenu);
1892 cma_table->verticalHeader()->setVisible(false);
1893 cma_table->horizontalHeader()->setVisible(false);
1894 cma_table->horizontalHeader()->setSectionResizeMode(
1895 QHeaderView::Stretch);
1896
1897 connect(cma_table->selectionModel(),
1899 const QItemSelection &)),
1901 const QItemSelection &)));
1902 connect(cma_table,
1903 &QWidget::customContextMenuRequested, this,
1905 connect(cma_table, &QTableWidget::cellDoubleClicked, this,
1907 gridl->addWidget(cma_table, 0, 0, 1, 2);
1908 qgbox->setLayout(gridl);
1909 hbox->addWidget(cma_info_text);
1910 result_box->setLayout(hbox);
1911 str_list << _("Food") << _("Shield") << _("Trade") << _("Gold")
1912 << _("Luxury") << _("Science") << _("Celebrate")
1913 << _("Maximize growth");
1914 some_label = new QLabel(_("Minimal Surplus"));
1916 some_label->setAlignment(Qt::AlignRight);
1917 slider_grid->addWidget(some_label, 0, 0, 1, 3);
1918 some_label = new QLabel(_("Priority"));
1920 some_label->setAlignment(Qt::AlignCenter);
1921 slider_grid->addWidget(some_label, 0, 3, 1, 2);
1922
1923 list_size = str_list.count();
1924 for (int i = 0; i < list_size; i++) {
1925 some_label = new QLabel(str_list.at(i));
1926 slider_grid->addWidget(some_label, i + 1, 0, 1, 1);
1927 some_label = new QLabel("0");
1928 some_label->setMinimumWidth(25);
1929
1930 if (i < list_size - 2) {
1931 slider = new QSlider(Qt::Horizontal);
1932 slider->setPageStep(1);
1933 slider->setFocusPolicy(Qt::TabFocus);
1934 slider_tab[2 * i] = slider;
1935 slider->setRange(-20, 20);
1936 slider->setSingleStep(1);
1937 slider_grid->addWidget(some_label, i + 1, 1, 1, 1);
1938 slider_grid->addWidget(slider, i + 1, 2, 1, 1);
1939 slider->setProperty("FC", QVariant::fromValue((void *)some_label));
1940
1941 connect(slider, &QAbstractSlider::valueChanged, this, &city_dialog::cma_slider);
1942 } else if (i == list_size - 2) {
1944 slider_grid->addWidget(cma_celeb_checkbox, i + 1, 2 , 1 , 1);
1945#ifdef FC_QT6X_MODE
1946 // Qt-6.7
1947 connect(cma_celeb_checkbox,
1948 &QCheckBox::checkStateChanged, this, &city_dialog::cma_toggle_changed);
1949#else // FC_QT6X_MODE
1950 connect(cma_celeb_checkbox,
1951 &QCheckBox::stateChanged, this, &city_dialog::cma_toggle_changed_depr);
1952#endif // FC_QT6X_MODE
1953 } else {
1954 fc_assert(i == list_size - 1);
1955
1957 slider_grid->addWidget(cma_max_growth, i + 1, 2 , 1 , 1);
1958#ifdef FC_QT6X_MODE
1959 // Qt-6.7
1960 connect(cma_max_growth,
1961 &QCheckBox::checkStateChanged, this, &city_dialog::cma_toggle_changed);
1962#else // FC_QT6X_MODE
1963 connect(cma_max_growth,
1964 &QCheckBox::stateChanged, this, &city_dialog::cma_toggle_changed_depr);
1965#endif // FC_QT6X_MODE
1966 }
1967
1968 if (i <= list_size - 2) {
1969 some_label = new QLabel("0");
1970 some_label->setMinimumWidth(25);
1971 slider = new QSlider(Qt::Horizontal);
1972 slider->setFocusPolicy(Qt::TabFocus);
1973 slider->setRange(0, 25);
1974 slider_tab[2 * i + 1] = slider;
1975 slider->setProperty("FC", QVariant::fromValue((void *)some_label));
1976 slider_grid->addWidget(some_label, i + 1, 3, 1, 1);
1977 slider_grid->addWidget(slider, i + 1, 4, 1, 1);
1978 connect(slider, &QAbstractSlider::valueChanged, this, &city_dialog::cma_slider);
1979 }
1980 }
1981
1982 cma_enable_but = new QPushButton();
1983 cma_enable_but->setFocusPolicy(Qt::TabFocus);
1984 connect(cma_enable_but, &QAbstractButton::pressed, this, &city_dialog::cma_enable);
1985 slider_grid->addWidget(cma_enable_but, O_LAST + 4, 0, 1, 3);
1986 slider_grid->addWidget(qpush2, O_LAST + 4, 3, 1, 2);
1987
1988 qsliderbox->setLayout(slider_grid);
1989 cma_result = new QLabel;
1990 cma_result_pix = new QLabel;
1991
1992 hbox = new QHBoxLayout;
1993 QScrollArea *govA = new QScrollArea();
1994 hbox->addWidget(cma_result_pix);
1995 hbox->addWidget(cma_result);
1996 hbox->addStretch(10);
1997 govA->setWidget(qsliderbox);
1998 govA->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
1999 right_layout->addWidget(qgbox);
2000 right_layout->addLayout(hbox);
2001 right_layout->addWidget(govA);
2002
2003 split_widget1 = new QWidget;
2004 split_widget1->setLayout(worklist_layout);
2005 split_widget2 = new QWidget;
2006 split_widget2->setLayout(units_layout);
2009 prod_unit_splitter->setStretchFactor(0, 3);
2010 prod_unit_splitter->setStretchFactor(1, 97);
2011 prod_unit_splitter->setOrientation(Qt::Horizontal);
2013 top_widget = new QWidget;
2014 top_widget->setLayout(lefttop_layout);
2015 top_widget->setSizePolicy(QSizePolicy::Minimum,
2016 QSizePolicy::Minimum);
2017 scroll_info = new QScrollArea();
2018 scroll_info->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
2019 scroll_unit = new QScrollArea();
2020 scroll_info->setWidget(top_widget);
2021 scroll_info->setWidgetResizable(true);
2022 prod_happ_widget = new QWidget;
2023 prod_happ_widget->setLayout(leftbot_layout);
2024 prod_happ_widget->setSizePolicy(QSizePolicy::MinimumExpanding,
2025 QSizePolicy::MinimumExpanding);
2026 scroll_unit->setWidget(prod_happ_widget);
2027 scroll_unit->setWidgetResizable(true);
2030 central_left_splitter->setStretchFactor(0, 40);
2031 central_left_splitter->setStretchFactor(1, 60);
2032 central_left_splitter->setOrientation(Qt::Vertical);
2034
2035 split_widget1 = new QWidget(this);
2036 split_widget2 = new QWidget(this);
2037 split_widget1->setLayout(left_layout);
2038 split_widget2->setLayout(right_layout);
2039 central_splitter->addWidget(split_widget1);
2040 central_splitter->addWidget(split_widget2);
2041 central_splitter->setStretchFactor(0, 99);
2042 central_splitter->setStretchFactor(1, 1);
2043 central_splitter->setOrientation(Qt::Horizontal);
2045 setSizeGripEnabled(true);
2047
2048 installEventFilter(this);
2049
2050 ::city_dlg_created = true;
2051
2053}
2054
2055/************************************************************************/
2059{
2060
2061 cid cprod;
2062 int i, pos;
2063 int item, targets_used;
2065 QString str;
2066 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2067 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2068 struct universal univ;
2069
2070 pos = 0;
2073 name_and_sort_items(targets, targets_used, items, false, dlgcity);
2074
2075 for (item = 0; item < targets_used; item++) {
2076 if (can_city_build_now(&(wld.map), dlgcity, &items[item].item,
2077 RPT_CERTAIN)) {
2078 prod_list << cid_encode(items[item].item);
2079 }
2080 }
2081
2082 for (i = 0; i < prod_list.size(); i++) {
2083 if (prod_list.at(i) == cprod) {
2084 if (next) {
2085 pos = i + 1;
2086 } else {
2087 pos = i - 1;
2088 }
2089 }
2090 }
2091 if (pos == prod_list.size()) {
2092 pos = 0;
2093 }
2094 if (pos == - 1) {
2095 pos = prod_list.size() - 1;
2096 }
2097 univ = cid_decode(static_cast<cid>(prod_list.at(pos)));
2099}
2100
2101/************************************************************************/
2105{
2106 if (current_tab == happiness) {
2107 happiness_button->setIcon(fc_icons::instance()->get_icon("city-switch"));
2108 happiness_button->setToolTip(_("Show city production"));
2109 } else {
2110 happiness_button->setIcon(fc_icons::instance()->get_icon("smiley"));
2111 happiness_button->setToolTip(_("Show happiness information"));
2112 }
2113}
2114
2115/************************************************************************/
2119{
2121 setUpdatesEnabled(false);
2122
2123
2124 if (current_tab != happiness) {
2125 leftbot_layout->replaceWidget(active_tab,
2127 Qt::FindDirectChildrenOnly);
2128 active_tab->hide();
2129 happiness_widget->show();
2130 happiness_widget->updateGeometry();
2132 } else {
2133 /* We do not change prod_unit_splitter to current_tab,
2134 * because happiness is active tab and clicked -
2135 * switching to default */
2136 leftbot_layout->replaceWidget(happiness_widget,
2138 Qt::FindDirectChildrenOnly);
2139 prod_unit_splitter->show();
2140 prod_unit_splitter->updateGeometry();
2141 happiness_widget->hide();
2143 }
2144
2145 setUpdatesEnabled(true);
2146 update();
2147 update_tabs();
2148}
2149
2150/************************************************************************/
2154{
2155 setUpdatesEnabled(false);
2156
2157 leftbot_layout->replaceWidget(counters_widget,
2159 Qt::FindDirectChildrenOnly);
2160 prod_unit_splitter->show();
2161 prod_unit_splitter->updateGeometry();
2162 counters_widget->hide();
2164
2165 setUpdatesEnabled(true);
2166 update();
2167 update_tabs();
2168}
2169
2170/************************************************************************/
2174{
2176
2177 if (current_tab != counters) {
2178 setUpdatesEnabled(false);
2179
2180 leftbot_layout->replaceWidget(active_tab,
2182 Qt::FindDirectChildrenOnly);
2183 active_tab->hide();
2184 counters_widget->show();
2185 counters_widget->updateGeometry();
2187
2188 setUpdatesEnabled(true);
2189 update();
2190 update_tabs();
2191 }
2192}
2193
2194/************************************************************************/
2198{
2199 struct player *pplayer = client_player();
2200
2201 if (pplayer == nullptr
2202 || city_owner(dlgcity) != pplayer) {
2203 prev_city_but->setDisabled(true);
2204 next_city_but->setDisabled(true);
2205 buy_button->setDisabled(true);
2206 cma_enable_but->setDisabled(true);
2207 production_combo_p->setDisabled(true);
2208 current_units->setDisabled(true);
2209 supported_units->setDisabled(true);
2210 view->setDisabled(true);
2211 } else {
2212 prev_city_but->setEnabled(true);
2213 next_city_but->setEnabled(true);
2214 buy_button->setEnabled(true);
2215 cma_enable_but->setEnabled(true);
2216 production_combo_p->setEnabled(true);
2217 current_units->setEnabled(true);
2218 supported_units->setEnabled(true);
2219 view->setEnabled(true);
2220 }
2221
2223 cma_enable_but->setEnabled(true);
2224 } else {
2225 cma_enable_but->setDisabled(true);
2226 }
2227
2229}
2230
2231/************************************************************************/
2235{
2236 struct player *pplayer = client_player();
2237
2238 work_next_but->setDisabled(true);
2239 work_prev_but->setDisabled(true);
2240 work_add_but->setDisabled(true);
2241 work_rem_but->setDisabled(true);
2242
2243 if (pplayer != nullptr
2244 && city_owner(dlgcity) == pplayer) {
2245 work_add_but->setEnabled(true);
2246
2247 if (selected_row_p >= 0 && selected_row_p < p_table_p->rowCount()) {
2248 work_rem_but->setEnabled(true);
2249 }
2250
2251 if (selected_row_p >= 0 && selected_row_p < p_table_p->rowCount() - 1) {
2252 work_next_but->setEnabled(true);
2253 }
2254
2255 if (selected_row_p > 0 && selected_row_p < p_table_p->rowCount()) {
2256 work_prev_but->setEnabled(true);
2257 }
2258 }
2259}
2260
2261/************************************************************************/
2265{
2266 if (citizen_pixmap) {
2267 citizen_pixmap->detach();
2268 delete citizen_pixmap;
2269 }
2270
2271 cma_table->clear();
2272 p_table_p->clear();
2273 nationality_table->clear();
2275 supported_units->clear_layout();
2276 removeEventFilter(this);
2277 ::city_dlg_created = false;
2278
2279 // Delete the one widget that currently does NOT have a parent
2280 if (current_tab == common) {
2281 delete happiness_widget;
2282 delete counters_widget;
2283 }
2284 else if (current_tab == counters) {
2285 delete happiness_widget;
2286 delete prod_unit_splitter;
2287 } else {
2288 delete counters_widget;
2289 delete prod_unit_splitter;
2290 }
2291}
2292
2293/************************************************************************/
2297{
2298 gui()->qt_settings.city_geometry = saveGeometry();
2299 gui()->qt_settings.city_splitter1 = prod_unit_splitter->saveState();
2300 gui()->qt_settings.city_splitter2 = central_left_splitter->saveState();
2301 gui()->qt_settings.city_splitter3 = central_splitter->saveState();
2302}
2303
2304/************************************************************************/
2308{
2309 if (!gui()->qt_settings.city_geometry.isNull()) {
2310 restoreGeometry(gui()->qt_settings.city_geometry);
2311 prod_unit_splitter->restoreState(gui()->qt_settings.city_splitter1);
2312 central_left_splitter->restoreState(gui()->qt_settings.city_splitter2);
2313 central_splitter->restoreState(gui()->qt_settings.city_splitter3);
2314 } else {
2315 QRect rect = QApplication::primaryScreen()->availableGeometry();
2316
2317 resize((rect.width() * 4) / 5, (rect.height() * 5) / 6);
2318 }
2319}
2320
2321/************************************************************************/
2325{
2326 gui()->qt_settings.city_geometry = saveGeometry();
2327 gui()->qt_settings.city_splitter1 = prod_unit_splitter->saveState();
2328 gui()->qt_settings.city_splitter2 = central_left_splitter->saveState();
2329 gui()->qt_settings.city_splitter3 = central_splitter->saveState();
2330}
2331
2332/************************************************************************/
2335bool city_dialog::eventFilter(QObject *obj, QEvent *event)
2336{
2337
2338 if (obj == this) {
2339 if (event->type() == QEvent::KeyPress) {
2340 }
2341
2342 if (event->type() == QEvent::ShortcutOverride) {
2343 QKeyEvent *key_event = static_cast<QKeyEvent *>(event);
2344 if (key_event->key() == Qt::Key_Right) {
2345 next_city();
2346 event->setAccepted(true);
2347 return true;
2348 }
2349 if (key_event->key() == Qt::Key_Left) {
2350 prev_city();
2351 event->setAccepted(true);
2352 return true;
2353 }
2354 if (key_event->key() == Qt::Key_Up) {
2355 change_production(true);
2356 event->setAccepted(true);
2357 return true;
2358 }
2359 if (key_event->key() == Qt::Key_Down) {
2360 change_production(false);
2361 event->setAccepted(true);
2362 return true;
2363 }
2364 }
2365 }
2366 return QObject::eventFilter(obj, event);
2367}
2368
2369/************************************************************************/
2373{
2375 const int city_id = dlgcity->id;
2376
2377 if (!can_client_issue_orders()) {
2378 return;
2379 }
2380
2381 ask = new hud_input_box(gui()->central_wdg);
2382 ask->set_text_title_definput(_("What should we rename the city to?"),
2383 _("Rename City"), city_name_get(dlgcity));
2384 ask->setAttribute(Qt::WA_DeleteOnClose);
2385 connect(ask, &hud_message_box::accepted, this, [=]() {
2386 struct city *pcity = game_city_by_number(city_id);
2388
2389 if (!pcity) {
2390 return;
2391 }
2392
2393 ask_bytes = ask->input_edit.text().toUtf8();
2394 ::city_rename(pcity, ask_bytes.data());
2395 });
2396 ask->show();
2397}
2398
2399/************************************************************************/
2403{
2404 zoom = zoom * 1.2;
2405 if (dlgcity) {
2406 view->set_pixmap(dlgcity, zoom);
2407 }
2409 left_layout->update();
2410}
2411
2412/************************************************************************/
2416{
2417 zoom = zoom / 1.2;
2418 if (dlgcity) {
2419 view->set_pixmap(dlgcity, zoom);
2420 }
2422 left_layout->update();
2423}
2424
2425/************************************************************************/
2429{
2430 hud_input_box *ask = new hud_input_box(gui()->central_wdg);
2431
2432 ask->set_text_title_definput(_("What should we name the preset?"),
2433 _("Name new preset"),
2434 _("new preset"));
2435 ask->setAttribute(Qt::WA_DeleteOnClose);
2436 connect(ask, &hud_message_box::accepted, this,
2438 struct cm_parameter param;
2439 QByteArray ask_bytes = ask->input_edit.text().toUtf8();
2440 QString text = ask_bytes.data();
2441 if (!text.isEmpty()) {
2442 param.allow_disorder = false;
2443 param.allow_specialists = true;
2444 param.require_happy = cma_celeb_checkbox->isChecked();
2445 param.max_growth = cma_max_growth->isChecked();
2446 param.happy_factor = slider_tab[2 * O_LAST + 1]->value();
2447
2448 for (int i = O_FOOD; i < O_LAST; i++) {
2449 param.minimal_surplus[i] = slider_tab[2 * i]->value();
2450 param.factor[i] = slider_tab[2 * i + 1]->value();
2451 }
2452
2453 ask_bytes = text.toUtf8();
2454 cmafec_preset_add(ask_bytes.data(), &param);
2456 }
2457 });
2458 ask->show();
2459}
2460
2461/************************************************************************/
2465{
2466 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2468
2469 return;
2470 }
2471
2472 cma_changed();
2474}
2475
2476/************************************************************************/
2480{
2481 struct cm_parameter param;
2482
2483 param.allow_disorder = false;
2484 param.allow_specialists = true;
2485 param.require_happy = cma_celeb_checkbox->isChecked();
2486 param.max_growth = cma_max_growth->isChecked();
2487 param.happy_factor = slider_tab[2 * O_LAST + 1]->value();
2488
2489 for (int i = O_FOOD; i < O_LAST; i++) {
2490 param.minimal_surplus[i] = slider_tab[2 * i]->value();
2491 param.factor[i] = slider_tab[2 * i + 1]->value();
2492 }
2493
2495}
2496
2497/************************************************************************/
2501{
2502 const struct cm_parameter *param;
2503
2504 if (!can_client_issue_orders()) {
2505 return;
2506 }
2508 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2510 }
2511
2514}
2515
2516/************************************************************************/
2520 const QItemSelection &ds)
2521{
2522 const struct cm_parameter *param;
2523 QModelIndex index;
2524 QModelIndexList indexes = sl.indexes();
2525
2526 if (indexes.isEmpty() || cma_table->signalsBlocked()) {
2527 return;
2528 }
2529
2530 index = indexes.at(0);
2531 int ind = index.row();
2532
2533 if (cma_table->currentRow() == -1 || cmafec_preset_num() == 0) {
2534 return;
2535 }
2536
2539
2540 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2543 }
2544}
2545
2546/************************************************************************/
2550{
2551 struct cm_parameter param;
2552 const struct cm_parameter *cparam;
2553 int output;
2554 QVariant qvar;
2555 QLabel *label;
2556
2557 if (!cma_is_city_under_agent(dlgcity, &param)) {
2558 if (cma_table->currentRow() == -1 || cmafec_preset_num() == 0) {
2559 return;
2560 }
2562 cm_copy_parameter(&param, cparam);
2563 }
2564
2565 for (output = O_FOOD; output < 2 * O_LAST; output++) {
2566 slider_tab[output]->blockSignals(true);
2567 }
2568
2569 for (output = O_FOOD; output < O_LAST; output++) {
2570 qvar = slider_tab[2 * output + 1]->property("FC");
2571 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2572 label->setText(QString::number(param.factor[output]));
2573 slider_tab[2 * output + 1]->setValue(param.factor[output]);
2574 qvar = slider_tab[2 * output]->property("FC");
2575 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2576 label->setText(QString::number(param.minimal_surplus[output]));
2577 slider_tab[2 * output]->setValue(param.minimal_surplus[output]);
2578 }
2579
2580 slider_tab[2 * O_LAST + 1]->blockSignals(true);
2581 qvar = slider_tab[2 * O_LAST + 1]->property("FC");
2582 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2583 label->setText(QString::number(param.happy_factor));
2584 slider_tab[2 * O_LAST + 1]->setValue(param.happy_factor);
2585 slider_tab[2 * O_LAST + 1]->blockSignals(false);
2586 cma_celeb_checkbox->blockSignals(true);
2587 cma_celeb_checkbox->setChecked(param.require_happy);
2588 cma_celeb_checkbox->blockSignals(false);
2589 cma_max_growth->blockSignals(true);
2590 cma_max_growth->setChecked(param.max_growth);
2591 cma_max_growth->blockSignals(false);
2592
2593 for (output = O_FOOD; output < 2 * O_LAST; output++) {
2594 slider_tab[output]->blockSignals(false);
2595 }
2596}
2597
2598/************************************************************************/
2602{
2603 QString s;
2605 struct cm_parameter param;
2606 QPixmap pix;
2607 int i;
2608
2609 cma_table->clear();
2610 cma_table->setRowCount(0);
2611
2612 for (i = 0; i < cmafec_preset_num(); i++) {
2613 item = new QTableWidgetItem;
2614 item->setText(cmafec_preset_get_descr(i));
2615 cma_table->insertRow(i);
2616 cma_table->setItem(i, 0, item);
2617 }
2618
2619 if (cmafec_preset_num() == 0) {
2620 cma_table->insertRow(0);
2621 item = new QTableWidgetItem;
2622 item->setText(_("No governor defined"));
2623 cma_table->setItem(0, 0, item);
2624 }
2625
2626 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2627 view->update();
2629 pix = style()->standardPixmap(QStyle::SP_DialogApplyButton);
2630 pix = pix.scaled(2 * pix.width(), 2 * pix.height(),
2631 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
2632 cma_result_pix->setPixmap(pix);
2633 cma_result_pix->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
2634 // TRANS: %1 is custom string chosen by player
2635 cma_result->setText(QString(_("<h3>Governor Enabled<br>(%1)</h3>"))
2636 .arg(s.toHtmlEscaped()));
2637 cma_result->setAlignment(Qt::AlignCenter);
2638 } else {
2639 pix = style()->standardPixmap(QStyle::SP_DialogCancelButton);
2640 pix = pix.scaled(1.6 * pix.width(), 1.6 * pix.height(),
2641 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
2642 cma_result_pix->setPixmap(pix);
2643 cma_result_pix->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
2644 cma_result->setText(QString(_("<h3>Governor Disabled</h3>")));
2645 cma_result->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
2646 }
2647
2648 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2651 cm_parameter *const >(&param));
2652 if (i >= 0 && i < cma_table->rowCount()) {
2653 cma_table->blockSignals(true);
2654 cma_table->setCurrentCell(i, 0);
2655 cma_table->blockSignals(false);
2656 }
2657
2658 cma_enable_but->setText(_("Disable"));
2659 } else {
2660 cma_enable_but->setText(_("Enable"));
2661 }
2663}
2664
2665/************************************************************************/
2669{
2670 int i;
2672
2673 i = cma_table->currentRow();
2674
2675 if (i == -1 || cmafec_preset_num() == 0) {
2676 return;
2677 }
2678
2680 ask->set_text_title(_("Remove this preset?"), cmafec_preset_get_descr(i));
2681 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
2682 ask->setDefaultButton(QMessageBox::Cancel);
2683 ask->setAttribute(Qt::WA_DeleteOnClose);
2684 connect(ask, &hud_message_box::accepted, this,
2688 });
2689 ask->show();
2690}
2691
2692/************************************************************************/
2695void city_dialog::cma_toggle_changed(Qt::CheckState state)
2696{
2697 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2698 cma_changed();
2700 }
2701}
2702
2703/************************************************************************/
2708{
2709 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2710 cma_changed();
2712 }
2713}
2714
2715/************************************************************************/
2719{
2720 QVariant qvar;
2721 QSlider *slider;
2722 QLabel *label;
2723
2725 qvar = slider->property("FC");
2726
2727 if (qvar.isNull() || !qvar.isValid()) {
2728 return;
2729 }
2730
2731 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2732 label->setText(QString::number(value));
2733
2734 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2735 cma_changed();
2737 }
2738}
2739
2740/************************************************************************/
2760
2761/************************************************************************/
2765{
2766 QMenu *cma_menu = new QMenu(this);
2768
2769 cma_menu->setAttribute(Qt::WA_DeleteOnClose);
2770 cma_del_item = cma_menu->addAction(_("Remove Governor"));
2771 connect(cma_menu, &QMenu::triggered, this,
2773 if (act == cma_del_item) {
2774 cma_remove();
2775 }
2776 });
2777
2778 cma_menu->popup(QCursor::pos());
2779}
2780
2781/************************************************************************/
2785{
2786 QAction *action;
2787 QAction *disband;
2793 QMap<QString, cid>::const_iterator map_iter;
2794 QMenu *change_menu;
2795 QMenu *insert_menu;
2796 QMenu *settings_menu;
2797 QMenu *options_menu;
2798 int city_id = dlgcity->id;
2799
2800 if (!can_client_issue_orders()) {
2801 return;
2802 }
2803 settings_menu = new QMenu(this);
2804 counters_action = settings_menu->addAction(_("Counters"));
2805 connect(counters_action, &QAction::triggered, this,
2807 change_menu = settings_menu->addMenu(_("Change worklist"));
2808 insert_menu = settings_menu->addMenu(_("Insert worklist"));
2809 wl_clear = settings_menu->addAction(_("Clear worklist"));
2810 connect(wl_clear, &QAction::triggered, this, &city_dialog::clear_worklist);
2811 list.clear();
2812
2816
2817 if (list.count() == 0) {
2818 wl_empty = change_menu->addAction(_("(no worklists defined)"));
2819 insert_menu->addAction(wl_empty);
2820 }
2821
2822 map_iter = list.constBegin();
2823
2824 while (map_iter != list.constEnd()) {
2825 action = change_menu->addAction(map_iter.key());
2826 action->setData(map_iter.value());
2827
2828 action = insert_menu->addAction(map_iter.key());
2829 action->setData(map_iter.value());
2830
2831 map_iter++;
2832 }
2833
2834 wl_save = settings_menu->addAction(_("Save worklist"));
2835 connect(wl_save, &QAction::triggered, this, &city_dialog::save_worklist);
2836 options_menu = settings_menu->addMenu(_("Options"));
2837 disband = options_menu->addAction(_("Allow disbanding city"));
2838 disband->setCheckable(true);
2839 disband->setChecked(is_city_option_set(dlgcity, CITYO_DISBAND));
2840 connect(disband, &QAction::triggered, this,
2842
2843 connect(change_menu, &QMenu::triggered, this, [=](QAction *act) {
2844 QVariant id = act->data();
2845 struct city *pcity = game_city_by_number(city_id);
2846 const struct worklist *worklist;
2847
2848 if (!pcity) {
2849 return;
2850 }
2851
2852 fc_assert_ret(id.typeId() == QMetaType::Int);
2853
2856 });
2857
2858 connect(insert_menu, &QMenu::triggered, this,
2860 QVariant id = act->data();
2861 struct city *pcity = game_city_by_number(city_id);
2862 const struct worklist *worklist;
2863
2864 if (!pcity) {
2865 return;
2866 }
2867
2868 fc_assert_ret(id.typeId() == QMetaType::Int);
2869
2872 });
2873
2874 settings_menu->popup(QCursor::pos());
2875}
2876
2877/************************************************************************/
2881{
2882 QString str;
2883 int value;
2884 struct player *pplayer = client_player();
2885
2886 buy_button->setDisabled(true);
2887
2888 if (!client_is_observer() && pplayer != nullptr) {
2889 value = dlgcity->client.buy_cost;
2890 str = QString(PL_("Buy (%1 gold)", "Buy (%1 gold)",
2891 value)).arg(QString::number(value));
2892
2893 if (pplayer->economic.gold >= value && value != 0) {
2894 buy_button->setEnabled(true);
2895 }
2896 } else {
2897 str = QString(_("Buy"));
2898 }
2899
2900 buy_button->setText(str);
2901}
2902
2903/************************************************************************/
2907{
2908 enum citizen_category categories[MAX_CITY_SIZE];
2909 int i, j, width, height;
2910 QPainter p;
2911 QPixmap *pix;
2913 int num_supers
2915 ARRAY_SIZE(categories) - num_citizens,
2916 &categories[num_citizens]);
2917
2918 int w = tileset_small_sprite_width(tileset) / gui()->map_scale;
2919 int h = tileset_small_sprite_height(tileset) / gui()->map_scale;
2920
2921 if (num_supers >= 0) {
2922 /* Just draw superspecialists in the common roster */
2924 } else {
2925 /* FIXME: show them in some compact way */
2926 num_citizens = ARRAY_SIZE(categories);
2927 }
2928 i = 1 + (num_citizens * 5 / 200);
2929 w = w / i;
2930 QRect source_rect(0, 0, w, h);
2931 QRect dest_rect(0, 0, w, h);
2932 width = w * num_citizens;
2933 height = h;
2934
2935 if (citizen_pixmap) {
2936 citizen_pixmap->detach();
2937 delete citizen_pixmap;
2938 }
2939
2941
2942 for (j = 0, i = 0; i < num_citizens; i++, j++) {
2943 dest_rect.moveTo(i * w, 0);
2944 pix = get_citizen_sprite(tileset, categories[j], j, dlgcity)->pm;
2945 p.begin(citizen_pixmap);
2946 p.drawPixmap(dest_rect, *pix, source_rect);
2947 p.end();
2948 }
2949
2951 citizens_label->setPixmap(*citizen_pixmap);
2952
2955
2956 for (int k = 0; k < FEELING_LAST - 1; k++) {
2959 static_cast<citizen_feeling>(k),
2960 categories);
2961
2962 for (j = 0, i = 0; i < num_citizens; i++, j++) {
2963 dest_rect.moveTo(i * w, 0);
2964 pix = get_citizen_sprite(tileset, categories[j], j, dlgcity)->pm;
2965 p.begin(citizen_pixmap);
2966 p.drawPixmap(dest_rect, *pix, source_rect);
2967 p.end();
2968 }
2969
2970 lab_table[k]->setPixmap(*citizen_pixmap);
2971
2972 switch (k) {
2973 case FEELING_BASE:
2974 lab_table[k]->setToolTip(text_happiness_cities(dlgcity));
2975 break;
2976
2977 case FEELING_LUXURY:
2978 lab_table[k]->setToolTip(text_happiness_luxuries(dlgcity));
2979 break;
2980
2981 case FEELING_EFFECT :
2983 break;
2984
2987 break;
2988
2989 case FEELING_MARTIAL:
2990 lab_table[k]->setToolTip(text_happiness_units(dlgcity));
2991 break;
2992
2993 default:
2994 break;
2995 }
2996 }
2997}
2998
2999/************************************************************************/
3003{
3004 setUpdatesEnabled(false);
3005 production_combo_p->blockSignals(true);
3006
3007 if (dlgcity) {
3008 view->set_pixmap(dlgcity, zoom);
3009 view->update();
3010 update_title();
3017 update_units();
3021 } else {
3023 }
3024
3025 production_combo_p->blockSignals(false);
3026 setUpdatesEnabled(true);
3028 update();
3029}
3030
3031/************************************************************************/
3035{
3036 QFont *small_font;
3037
3039
3040 qDeleteAll(counters_widget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
3041
3042 QWidget *titlebar_widget = new QWidget();
3044 titlebar_widget->setLayout(titlebar_layout);
3045
3046 titlebar_layout->addWidget(new QLabel(_("<u>Counters</u>"),
3048 0, Qt::AlignCenter);
3049 QPushButton *closeButton =
3050 new QPushButton(fc_icons::instance()->get_icon("close"), "",
3052 connect(closeButton, &QPushButton::clicked, this,
3054 closeButton->setFixedSize(28, 28);
3055
3056 titlebar_layout->setContentsMargins(11, 0, 5, 0);
3057 titlebar_layout->addWidget(closeButton, 0);
3058
3059 counters_layout->setContentsMargins(11, 0, 11, 5);
3060 counters_layout->addWidget(titlebar_widget, 0, Qt::AlignTop);
3061 counters_layout->setStretch(0, 0);
3062
3064 QString helptext;
3065 char buf[1024];
3066 QLabel *name, *value, *activated, *help;
3067
3068 name = new QLabel(name_translation_get(&pcount->name));
3069 fc_snprintf(buf, sizeof(buf), _("Current value is: %d"),
3071 value = new QLabel(buf);
3072 fc_snprintf(buf, sizeof(buf), _("Activated once value equal "
3073 "or higher than: %d"),
3074 pcount->checkpoint);
3075 activated = new QLabel(buf);
3076 if (pcount->helptext != nullptr) {
3077 strvec_iterate(pcount->helptext, text_) {
3078 helptext += text_;
3080 }
3081 help = new QLabel(helptext);
3082
3083 name->setFont(*small_font);
3084 value->setFont(*small_font);
3085 activated->setFont(*small_font);
3086 help->setFont(*small_font);
3087
3088 counters_layout->addWidget(name);
3089 counters_layout->addWidget(value);
3090 counters_layout->addWidget(activated);
3091 counters_layout->addWidget(help);
3093}
3094
3095/************************************************************************/
3099{
3100 QFont f = QApplication::font();
3101 QFontMetrics fm(f);
3102 QPixmap *pix = nullptr;
3104 QString str;
3107 char buf[8];
3109 int h;
3110 int i = 0;
3111 struct sprite *sprite;
3112
3113 h = fm.height() + 6;
3114 nationality_table->clear();
3115 nationality_table->setRowCount(0);
3116 info_list.clear();
3117 info_list << _("#") << _("Flag") << _("Nation");
3118 nationality_table->setHorizontalHeaderLabels(info_list);
3119
3120 citizens_iterate(dlgcity, pslot, nationality) {
3121 nationality_table->insertRow(i);
3122
3123 for (int j = 0; j < nationality_table->columnCount(); j++) {
3124 item = new QTableWidgetItem;
3125
3126 switch (j) {
3127 case 0:
3129
3130 if (nationality_i == 0) {
3131 str = "-";
3132 } else {
3133 fc_snprintf(buf, sizeof(buf), "%d", nationality_i);
3134 str = QString(buf);
3135 }
3136
3137 item->setText(str);
3138 break;
3139
3140 case 1:
3143 (player_slot_get_player(pslot)));
3144
3145 if (sprite != nullptr) {
3146 pix = sprite->pm;
3147 pix_scaled = pix->scaledToHeight(h);
3148 item->setData(Qt::DecorationRole, pix_scaled);
3149 } else {
3150 item->setText("FLAG MISSING");
3151 }
3152 break;
3153
3154 case 2:
3156 (player_slot_get_player(pslot)));
3157 break;
3158
3159 default:
3160 break;
3161 }
3162 nationality_table->setItem(i, j, item);
3163 }
3164 i++;
3166 nationality_table->horizontalHeader()->setStretchLastSection(false);
3167 nationality_table->resizeColumnsToContents();
3168 nationality_table->resizeRowsToContents();
3169 nationality_table->horizontalHeader()->setStretchLastSection(true);
3170}
3171
3172/************************************************************************/
3176{
3177 int illness = 0;
3178 char buffer[512];
3179 char buf_info[NUM_INFO_FIELDS][512];
3180 char buf_tooltip[NUM_INFO_FIELDS][512];
3181 int granaryturns;
3182 int spec, supers;
3183
3184 for (int i = 0; i < NUM_INFO_FIELDS; i++) {
3185 buf_info[i][0] = '\0';
3186 buf_tooltip[i][0] = '\0';
3187 }
3188
3189 // Fill the buffers with the necessary info
3190 spec = city_specialists(dlgcity);
3192
3194 "%3d (%4d)", dlgcity->size, spec);
3195 if (supers) {
3197 _("Population: %d, Specialists: %d + %d"),
3198 dlgcity->size, spec, supers);
3199 } else {
3201 _("Population: %d, Specialists: %d"),
3202 dlgcity->size, spec);
3203 }
3204 fc_snprintf(buf_info[INFO_FOOD], sizeof(buf_info[INFO_FOOD]), "%3d (%+4d)",
3207 "%3d (%+4d)", dlgcity->prod[O_SHIELD] + dlgcity->waste[O_SHIELD],
3209 fc_snprintf(buf_info[INFO_TRADE], sizeof(buf_info[INFO_TRADE]), "%3d (%+4d)",
3212 fc_snprintf(buf_info[INFO_GOLD], sizeof(buf_info[INFO_GOLD]), "%3d (%+4d)",
3219 "%4d/%-4d", dlgcity->food_stock,
3221
3223 sizeof(buf_tooltip[INFO_FOOD]));
3225 sizeof(buf_tooltip[INFO_SHIELD]));
3227 sizeof(buf_tooltip[INFO_TRADE]));
3229 sizeof(buf_tooltip[INFO_GOLD]));
3231 sizeof(buf_tooltip[INFO_SCIENCE]));
3233 sizeof(buf_tooltip[INFO_LUXURY]));
3235 sizeof(buf_tooltip[INFO_CULTURE]));
3237 sizeof(buf_tooltip[INFO_POLLUTION]));
3239 sizeof(buf_tooltip[INFO_ILLNESS]));
3240
3242
3243 if (granaryturns == 0) {
3244 // TRANS: city growth is blocked. Keep short.
3245 fc_snprintf(buf_info[INFO_GROWTH], sizeof(buf_info[INFO_GROWTH]), _("blocked"));
3246 } else if (granaryturns == FC_INFINITY) {
3247 // TRANS: city is not growing. Keep short.
3248 fc_snprintf(buf_info[INFO_GROWTH], sizeof(buf_info[INFO_GROWTH]), _("never"));
3249 } else {
3250 /* A negative value means we'll have famine in that many turns.
3251 But that's handled down below. */
3252 // TRANS: city growth turns. Keep short.
3254 PL_("%d turn", "%d turns", abs(granaryturns)),
3255 abs(granaryturns));
3256 }
3257
3259 "%4d", dlgcity->waste[O_TRADE]);
3266
3267 if (!game.info.illness_on) {
3269 " -.-");
3270 } else {
3271 illness = city_illness_calc(dlgcity, nullptr, nullptr, nullptr, nullptr);
3272 // Illness is in tenth of percent
3274 "%5.1f%%", (float) illness / 10.0);
3275 }
3276 if (dlgcity->steal) {
3278 PL_("%d time", "%d times", dlgcity->steal), dlgcity->steal);
3279 } else {
3281 _("Not stolen"));
3282 }
3283
3285 sizeof(buf_info[INFO_AIRLIFT]));
3287 sizeof(buf_tooltip[INFO_AIRLIFT]));
3288
3289 get_city_dialog_output_text(dlgcity, O_FOOD, buffer, sizeof(buffer));
3290
3291 for (int i = 0; i < NUM_INFO_FIELDS; i++) {
3292 qlt[i]->setText(QString(buf_info[i]));
3293
3294 if (buf_tooltip[i][0]) {
3295 qlt[i]->setToolTip("<pre>" + QString(buf_tooltip[i]).toHtmlEscaped()
3296 + "</pre>");
3297 }
3298 }
3299}
3300
3301/************************************************************************/
3305{
3308
3309 setContentsMargins(0, 0 ,0 ,0);
3311 dlgcity = qcity;
3312 production_combo_p->blockSignals(true);
3313 refresh();
3314 production_combo_p->blockSignals(false);
3315}
3316
3317/************************************************************************/
3321{
3322 struct worklist queue;
3323
3324 city_get_queue(dlgcity, &queue);
3325
3327 return;
3328 }
3329
3331 city_set_queue(dlgcity, &queue);
3332}
3333
3334/************************************************************************/
3338{
3339 unit_item *ui;
3340 struct unit_list *units;
3341 char buf[256];
3342 int n;
3343 int happy_cost;
3345 struct player *pplayer = client_player();
3346 const struct civ_map *nmap = &(wld.map);
3347
3348 supported_units->setUpdatesEnabled(false);
3349 supported_units->clear_layout();
3350
3351 if (pplayer != nullptr
3352 && city_owner(dlgcity) != pplayer) {
3354 } else {
3355 units = dlgcity->units_supported;
3356 }
3357
3358 unit_list_iterate(units, punit) {
3360 ui = new unit_item(this, punit, true, happy_cost);
3361 ui->init_pix();
3362 supported_units->add_item(ui);
3364 n = unit_list_size(units);
3365 fc_snprintf(buf, sizeof(buf), _("Supported units %d"), n);
3366 supp_units->setText(QString(buf));
3367 supported_units->update_units();
3368 supported_units->setUpdatesEnabled(true);
3369 current_units->setUpdatesEnabled(true);
3371
3372 if (pplayer != nullptr
3373 && city_owner(dlgcity) != pplayer) {
3375 } else {
3376 units = dlgcity->tile->units;
3377 }
3378
3379 unit_list_iterate(units, punit) {
3380 ui = new unit_item(this , punit, false);
3381 ui->init_pix();
3384
3385 n = unit_list_size(units);
3386 fc_snprintf(buf, sizeof(buf), _("Present units %d"), n);
3387 curr_units->setText(QString(buf));
3388
3390 current_units->setUpdatesEnabled(true);
3391}
3392
3393/************************************************************************/
3397 const QItemSelection &ds)
3398{
3399 QModelIndex index;
3400 QModelIndexList indexes = sl.indexes();
3401
3402 if (indexes.isEmpty()) {
3403 return;
3404 }
3405
3406 index = indexes.at(0);
3407 selected_row_p = index.row();
3409}
3410
3411/************************************************************************/
3415{
3416 int size, i;
3417 struct city *other_pcity = nullptr;
3418 struct player *pplayer = client_player();
3419
3420 if (pplayer == nullptr) {
3421 return;
3422 }
3423
3424 size = city_list_size(pplayer->cities);
3425
3426 if (size <= 1) {
3427 return;
3428 }
3429
3430 for (i = 0; i < size; i++) {
3431 if (dlgcity == city_list_get(pplayer->cities, i)) {
3432 break;
3433 }
3434 }
3435
3436 if (i >= size - 1) {
3437 // Current city last in the list (size - 1) or disappeared (size)
3438 other_pcity = city_list_get(pplayer->cities, 0);
3439 } else {
3440 other_pcity = city_list_get(pplayer->cities, i + 1);
3441 }
3442
3445}
3446
3447/************************************************************************/
3451{
3452 int size, i;
3453 struct city *other_pcity = nullptr;
3454 struct player *pplayer = client_player();
3455
3456 if (pplayer == nullptr) {
3457 return;
3458 }
3459
3460 size = city_list_size(pplayer->cities);
3461
3462 if (size <= 1) {
3463 return;
3464 }
3465
3466 for (i = 0; i < size; i++) {
3467 if (dlgcity == city_list_get(pplayer->cities, i)) {
3468 break;
3469 }
3470 }
3471
3472 if (i == 0 || i == size) {
3473 // Current city in the beginning of the list or disappeared
3474 other_pcity = city_list_get(pplayer->cities, size - 1);
3475 } else {
3476 other_pcity = city_list_get(pplayer->cities, i - 1);
3477 }
3478
3481}
3482
3483/************************************************************************/
3487{
3488 char buf[32];
3489 QString str;
3491
3493 production_combo_p->setRange(0, cost);
3495 if (dlgcity->shield_stock >= cost) {
3496 production_combo_p->setValue(cost);
3497 } else {
3499 }
3500 production_combo_p->setAlignment(Qt::AlignCenter);
3501 str = QString(buf);
3502 str = str.simplified();
3503
3504 production_combo_p->setFormat(QString("(%p%) %2\n%1")
3506 str));
3507
3508 production_combo_p->updateGeometry();
3509
3510}
3511
3512/************************************************************************/
3516{
3517 char buf[1024], buf2[1024];
3519 int value = dlgcity->client.buy_cost;
3521 int city_id = dlgcity->id;
3522
3523 if (!can_client_issue_orders()) {
3524 return;
3525 }
3526
3528 fc_snprintf(buf2, ARRAY_SIZE(buf2), PL_("Treasury contains %d gold.",
3529 "Treasury contains %d gold.",
3530 client_player()->economic.gold),
3531 client_player()->economic.gold);
3532 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Buy %s for %d gold?",
3533 "Buy %s for %d gold?", value),
3534 name, value);
3535 ask->set_text_title(buf, buf2);
3536 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
3537 ask->setDefaultButton(QMessageBox::Cancel);
3538 ask->setAttribute(Qt::WA_DeleteOnClose);
3539 connect(ask, &hud_message_box::accepted, this, [=]() {
3540 struct city *pcity = game_city_by_number(city_id);
3541
3542 if (!pcity) {
3543 return;
3544 }
3545
3547 });
3548 ask->show();
3549}
3550
3551/************************************************************************/
3555{
3556 QFont f = QApplication::font();
3557 QFontMetrics fm(f);
3558 QPixmap *pix = nullptr;
3562 struct sprite *sprite;
3563 int h, cost, item, targets_used, col, upkeep;
3564 struct item items[MAX_NUM_PRODUCTION_TARGETS];
3565 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
3566 struct worklist queue;
3567 impr_item *ui;
3568
3569 upkeep = 0;
3570 city_buildings->setUpdatesEnabled(false);
3572
3573 h = fm.height() + 6;
3575 name_and_sort_items(targets, targets_used, items, false, dlgcity);
3576
3577 for (item = 0; item < targets_used; item++) {
3578 struct universal target = items[item].item;
3579
3580 ui = new impr_item(this, target.value.building, dlgcity);
3581 ui->init_pix();
3583
3584 fc_assert_action(VUT_IMPROVEMENT == target.kind, continue);
3586 upkeep = upkeep + city_improvement_upkeep(dlgcity, target.value.building);
3587 if (sprite != nullptr) {
3588 pix = sprite->pm;
3589 pix_scaled = pix->scaledToHeight(h);
3590 }
3591 }
3592
3593 city_get_queue(dlgcity, &queue);
3594 p_table_p->setRowCount(worklist_length(&queue));
3595
3596 for (int i = 0; i < worklist_length(&queue); i++) {
3597 struct universal target = queue.entries[i];
3598
3599 tooltip = "";
3600
3601 if (VUT_UTYPE == target.kind) {
3603 cost = utype_build_shield_cost(dlgcity, nullptr, target.value.utype);
3604 tooltip = get_tooltip_unit(target.value.utype, true).trimmed();
3608 } else {
3612 dlgcity, true).trimmed();
3613
3615 cost = -1;
3616 } else {
3618 }
3619 }
3620
3621 for (col = 0; col < 3; col++) {
3622 qitem = new QTableWidgetItem();
3623 qitem->setToolTip(tooltip);
3624
3625 switch (col) {
3626 case 0:
3627 if (sprite) {
3628 pix = sprite->pm;
3629 pix_scaled = pix->scaledToHeight(h);
3630 qitem->setData(Qt::DecorationRole, pix_scaled);
3631 }
3632 break;
3633
3634 case 1:
3635 if (str.contains('[') && str.contains(']')) {
3636 int ii, ij;
3637
3638 ii = str.lastIndexOf('[');
3639 ij = str.lastIndexOf(']');
3640 if (ij > ii) {
3641 str = str.remove(ii, ij - ii + 1);
3642 }
3643 }
3644 qitem->setText(str);
3645 break;
3646
3647 case 2:
3648 qitem->setTextAlignment(Qt::AlignRight);
3649 qitem->setText(QString::number(cost));
3650 break;
3651 }
3652 p_table_p->setItem(i, col, qitem);
3653 }
3654 }
3655
3656 p_table_p->horizontalHeader()->setStretchLastSection(false);
3657 p_table_p->resizeColumnsToContents();
3658 p_table_p->resizeRowsToContents();
3659 p_table_p->horizontalHeader()->setStretchLastSection(true);
3660
3662 city_buildings->setUpdatesEnabled(true);
3663 city_buildings->setUpdatesEnabled(true);
3664
3665 curr_impr->setText(QString(_("Improvements - upkeep %1")).arg(upkeep));
3666}
3667
3668/************************************************************************/
3672{
3673 cid id;
3674 QVariant qvar;
3675
3677 struct universal univ;
3678
3679 id = qvar.toInt();
3680 univ = cid_production(id);
3682 }
3683}
3684
3685/************************************************************************/
3690{
3692 int when = 1;
3693
3694 pw = new production_widget(this, dlgcity, future_targets->isChecked(),
3695 when, selected_row_p, show_units->isChecked(),
3696 false, show_wonders->isChecked(),
3697 show_buildings->isChecked());
3698 pw->show();
3699}
3700
3701/************************************************************************/
3706{
3708 int when = 4;
3709
3710 pw = new production_widget(this, dlgcity, future_targets->isChecked(),
3711 when, selected_row_p, show_units->isChecked(),
3712 false, show_wonders->isChecked(),
3713 show_buildings->isChecked());
3714 pw->show();
3715}
3716
3717/************************************************************************/
3721{
3722 struct worklist empty;
3723
3724 if (!can_client_issue_orders()) {
3725 return;
3726 }
3727
3730}
3731
3732/************************************************************************/
3736{
3737 QModelIndex index;
3738 struct worklist queue;
3739 struct universal *target;
3740
3742 return;
3743 }
3744
3745 target = new universal;
3746 city_get_queue(dlgcity, &queue);
3747 worklist_peek_ith(&queue, target, selected_row_p);
3749 worklist_insert(&queue, target, selected_row_p - 1);
3750 city_set_queue(dlgcity, &queue);
3751 index = p_table_p->model()->index(selected_row_p - 1, 0);
3752 p_table_p->setCurrentIndex(index);
3753 delete target;
3754
3755}
3756
3757/************************************************************************/
3761{
3763
3764 if (selected_row_p < 0
3765 || selected_row_p >= p_table_p->rowCount()) {
3766 return;
3767 }
3768
3772}
3773
3774/************************************************************************/
3778{
3779 QModelIndex index;
3780 struct worklist queue;
3781 struct universal *target;
3782
3784 return;
3785 }
3786
3787 target = new universal;
3788 city_get_queue(dlgcity, &queue);
3789 worklist_peek_ith(&queue, target, selected_row_p);
3791 worklist_insert(&queue, target, selected_row_p + 1);
3792 city_set_queue(dlgcity, &queue);
3793 index = p_table_p->model()->index(selected_row_p + 1, 0);
3794 p_table_p->setCurrentIndex(index);
3795 delete target;
3796}
3797
3798/************************************************************************/
3802{
3803 hud_input_box *ask = new hud_input_box(gui()->central_wdg);
3804 int city_id = dlgcity->id;
3805
3806 ask->set_text_title_definput(_("What should we name new worklist?"),
3807 _("Save current worklist"),
3808 _("New worklist"));
3809 ask->setAttribute(Qt::WA_DeleteOnClose);
3810 connect(ask, &hud_message_box::accepted, [=]() {
3811 struct global_worklist *gw;
3812 struct worklist queue;
3814 QString text;
3815 struct city *pcity = game_city_by_number(city_id);
3816
3817 ask_bytes = ask->input_edit.text().toUtf8();
3818 text = ask_bytes.data();
3819 if (!text.isEmpty()) {
3820 ask_bytes = text.toUtf8();
3822 city_get_queue(pcity, &queue);
3823 global_worklist_set(gw, &queue);
3824 }
3825 });
3826 ask->show();
3827}
3828
3829/************************************************************************/
3833{
3834 QString buf;
3835
3836 // Defeat keyboard shortcut mnemonics
3838 .replace("&", "&&"));
3839
3840 if (city_unhappy(dlgcity)) {
3841 // TRANS: city dialog title
3842 buf = QString(_("%1 - %2 citizens - DISORDER")).arg(city_name_getx(dlgcity),
3844 } else if (city_celebrating(dlgcity)) {
3845 // TRANS: city dialog title
3846 buf = QString(_("%1 - %2 citizens - celebrating")).arg(city_name_getx(dlgcity),
3848 } else if (city_happy(dlgcity)) {
3849 // TRANS: city dialog title
3850 buf = QString(_("%1 - %2 citizens - happy")).arg(city_name_getx(dlgcity),
3852 } else {
3853 // TRANS: city dialog title
3854 buf = QString(_("%1 - %2 citizens")).arg(city_name_getx(dlgcity),
3856 }
3857
3859}
3860
3861/************************************************************************/
3866{
3867 if (!::city_dlg_created) {
3868 ::city_dlg = new city_dialog(gui()->mapview_wdg);
3869 }
3870
3872 city_dlg->show();
3873 city_dlg->activateWindow();
3874 city_dlg->raise();
3875}
3876
3877/************************************************************************/
3881{
3882 if (!::city_dlg_created) {
3883 return;
3884 }
3885
3886 city_dlg->close();
3887 ::city_dlg_created = false;
3888}
3889
3890/************************************************************************/
3894{
3895 if (!::city_dlg_created) {
3896 return;
3897 }
3898
3900}
3901
3902/************************************************************************/
3909
3910/************************************************************************/
3914{
3915 if (!::city_dlg_created) {
3916 return;
3917 }
3918
3920 city_dlg->refresh();
3921 }
3922}
3923
3924/************************************************************************/
3928{
3930 QFont *f;
3931
3932 if (!::city_dlg_created) {
3933 return;
3934 }
3935
3936 l = city_dlg->findChildren<QLabel *>();
3937
3939
3940 for (int i = 0; i < l.size(); ++i) {
3941 if (l.at(i)->property(fonts::notify_label).isValid()) {
3942 l.at(i)->setFont(*f);
3943 }
3944 }
3945}
3946
3947/************************************************************************/
3964
3965/************************************************************************/
3969{
3970 if (!::city_dlg_created) {
3971 return false;
3972 }
3973
3974 if (city_dlg->dlgcity == pcity && city_dlg->isVisible()) {
3975 return true;
3976 }
3977
3978 return false;
3979}
3980
3981/************************************************************************/
3984bool fc_tooltip::eventFilter(QObject *obj, QEvent *ev)
3985{
3988 QRect rect;
3989
3990 if (ev->type() == QEvent::ToolTip) {
3992
3993 if (!view) {
3994 return false;
3995 }
3996
3997 help_event = static_cast<QHelpEvent *>(ev);
3998 QPoint pos = help_event->pos();
3999 QModelIndex index = view->indexAt(pos);
4000 QPoint hpos;
4001
4002 if (!index.isValid()) {
4003 return false;
4004 }
4005
4006 item_tooltip = view->model()->data(index, Qt::ToolTipRole).toString();
4007 rect = view->visualRect(index);
4008
4009 hpos = help_event->globalPos();
4010
4011 rect.setX(rect.x() + hpos.x());
4012 rect.setY(rect.y() + hpos.y());
4013
4014 if (!item_tooltip.isEmpty()) {
4015 QToolTip::showText(help_event->globalPos(), item_tooltip, view, rect);
4016 } else {
4017 QToolTip::hideText();
4018 }
4019
4020 return true;
4021 }
4022
4023 return false;
4024}
4025
4026/************************************************************************/
4030{
4031 return QString("<b>" + text + "</b>");
4032}
4033
4034/************************************************************************/
4039 bool ext)
4040{
4042 QString upkeep;
4043 QString s1, s2, str;
4044 const char *req = skip_intl_qualifier_prefix(_("?tech:None"));
4045 struct player *pplayer = client_player();
4046
4047 if (pcity != nullptr) {
4048 upkeep = QString::number(city_improvement_upkeep(pcity, building));
4049 } else {
4050 upkeep = QString::number(building->upkeep);
4051 }
4053 if (pobs->source.kind == VUT_ADVANCE) {
4054 req = advance_name_translation(pobs->source.value.advance);
4055 break;
4056 }
4058 s2 = QString(req);
4059 str = _("Obsolete by:");
4060 str = str + " " + s2;
4061 def_str = "<p style='white-space:pre'><b>"
4062 + QString(improvement_name_translation(building)).toHtmlEscaped()
4063 + "</b>\n";
4064 if (pcity != nullptr) {
4065 def_str += QString(_("Cost: %1, Upkeep: %2\n"))
4066 .arg(impr_build_shield_cost(pcity, building))
4067 .arg(upkeep).toHtmlEscaped();
4068 } else {
4070 nullptr, building);
4071
4072 def_str += QString(_("Cost Estimate: %1, Upkeep: %2\n"))
4073 .arg(cost_est)
4074 .arg(upkeep).toHtmlEscaped();
4075 }
4076 if (s1.compare(s2) != 0) {
4077 def_str = def_str + str.toHtmlEscaped() + "\n";
4078 }
4079 def_str = def_str + "\n";
4080 if (ext) {
4081 char buffer[8192];
4082
4083 str = helptext_building(buffer, sizeof(buffer), pplayer,
4084 nullptr, building);
4085 str = cut_helptext(str);
4086 str = split_text(str, true);
4087 str = str.trimmed();
4088 def_str = def_str + str.toHtmlEscaped();
4089 }
4090 return def_str;
4091}
4092
4093/************************************************************************/
4097QString get_tooltip_unit(const struct unit_type *utype, bool ext)
4098{
4101 QString str;
4102 const struct unit_type *obsolete;
4103 struct advance *tech;
4104
4105 def_str = "<b>"
4106 + QString(utype_name_translation(utype)).toHtmlEscaped()
4107 + "</b>\n";
4108 obsolete = utype->obsoleted_by;
4109 if (obsolete) {
4110 // FIXME: Don't give the impression that primary tech is (always) the only one.
4112 obsolete_str = QString("</td></tr><tr><td colspan=\"3\">");
4113 if (tech && tech != advance_by_number(A_NONE)) {
4114 /* TRANS: this and nearby literal strings are interpreted
4115 * as (Qt) HTML */
4116 obsolete_str = obsolete_str + QString(_("Obsoleted by %1 (%2)."))
4118 .arg(advance_name_translation(tech)).toHtmlEscaped();
4119 } else {
4120 obsolete_str = obsolete_str + QString(_("Obsoleted by %1."))
4121 .arg(utype_name_translation(obsolete)).toHtmlEscaped();
4122 }
4123 }
4124 def_str += "<table width=\"100\%\"><tr><td>"
4125 + bold(QString(_("Attack:"))) + " "
4126 + QString::number(utype->attack_strength).toHtmlEscaped()
4127 + QString("</td><td>") + bold(QString(_("Defense:"))) + " "
4128 + QString::number(utype->defense_strength).toHtmlEscaped()
4129 + QString("</td><td>") + bold(QString(_("Move:"))) + " "
4130 + QString(move_points_text(utype->move_rate, TRUE)).toHtmlEscaped()
4131 + QString("</td></tr><tr><td>")
4132 + bold(QString(_("Cost:"))) + " "
4133 + QString::number(utype_build_shield_cost_base(utype))
4134 .toHtmlEscaped()
4135 + QString("</td><td colspan=\"2\">")
4136 + bold(QString(_("Basic Upkeep:")))
4137 + " " + QString(helptext_unit_upkeep_str(utype)).toHtmlEscaped()
4138 + QString("</td></tr><tr><td>")
4139 + bold(QString(_("Hitpoints:"))) + " "
4140 + QString::number(utype->hp).toHtmlEscaped()
4141 + QString("</td><td>") + bold(QString(_("Firepower:"))) + " "
4142 + QString::number(utype->firepower).toHtmlEscaped()
4143 + QString("</td><td>") + bold(QString(_("Vision:"))) + " "
4144 + QString::number((int) sqrt((double) utype->vision_radius_sq))
4145 .toHtmlEscaped()
4146 + obsolete_str
4147 + QString("</td></tr></table><p style='white-space:pre'>");
4148 if (ext) {
4149 char buffer[8192];
4150 char buf2[1];
4151
4152 buf2[0] = '\0';
4153 str = helptext_unit(buffer, sizeof(buffer), client_player(),
4154 buf2, utype, TRUE);
4155 str = cut_helptext(str);
4156 str = split_text(str, true);
4157 str = str.trimmed().toHtmlEscaped();
4158 def_str = def_str + str;
4159 }
4160
4161 return def_str;
4162};
4163
4164/************************************************************************/
4168{
4171 char buffer[8192];
4172 char buf2[1];
4173 struct universal *target;
4174 struct player *pplayer = client_player();
4175
4176 buf2[0] = '\0';
4177 target = reinterpret_cast<universal *>(qvar.value<void *>());
4178
4179 if (target == nullptr) {
4180 } else if (VUT_UTYPE == target->kind) {
4182 str = helptext_unit(buffer, sizeof(buffer), pplayer,
4183 buf2, target->value.utype, TRUE);
4184 } else {
4185 if (!is_convert_improvement(target->value.building)) {
4187 }
4188
4189 str = helptext_building(buffer, sizeof(buffer), pplayer,
4190 nullptr, target->value.building);
4191 }
4192
4193 // Remove all lines from help which has '*' in first 3 chars
4195 ret_str = split_text(ret_str, true);
4196 ret_str = ret_str.trimmed();
4197 ret_str = def_str + ret_str.toHtmlEscaped();
4198
4199 return ret_str;
4200}
4201
4202/************************************************************************/
4206 QObject *parent,
4207 struct city *city)
4208 : QItemDelegate(parent)
4209{
4210 pd = sh;
4211 item_height = sh.y();
4212 pcity = city;
4213}
4214
4215/************************************************************************/
4220 const QModelIndex &index) const
4221{
4222 struct universal *target;
4223 QString name;
4224 QVariant qvar;
4225 QPixmap *pix;
4227 QRect rect1;
4228 QRect rect2;
4229 struct sprite *sprite;
4230 bool useless = false;
4231 bool is_convert = false;
4232 bool is_neutral = false;
4233 bool is_sea = false;
4234 bool is_flying = false;
4235 bool is_unit = true;
4236 QPixmap pix_dec(option.rect.width(), option.rect.height());
4238 color col;
4239 QIcon icon = current_app()->style()->standardIcon(QStyle::SP_DialogCancelButton);
4240 bool free_sprite = false;
4241 struct unit_class *pclass;
4242
4243 if (!option.rect.isValid()) {
4244 return;
4245 }
4246
4247 qvar = index.data();
4248
4249 if (!qvar.isValid()) {
4250 return;
4251 }
4252
4253 target = reinterpret_cast<universal *>(qvar.value<void *>());
4254
4255 if (target == nullptr) {
4256 col.qcolor = Qt::white;
4257 sprite = qtg_create_sprite(100, 100, &col);
4258 free_sprite = true;
4259 *sprite->pm = icon.pixmap(100, 100);
4260 name = _("Cancel");
4261 is_unit = false;
4262 } else if (VUT_UTYPE == target->kind) {
4265 pclass = utype_class(target->value.utype);
4269 is_sea = true;
4270 }
4271
4272 if ((utype_fuel(target->value.utype)
4277 /* FIXME: Assumed to be flying since only missiles can do suicide
4278 * attacks in classic-like rulesets. This isn't true for all
4279 * rulesets. Not a high priority to fix since all is_flying and
4280 * is_sea is used for is to set a color. */
4282 target->value.utype)) {
4283 if (is_sea) {
4284 is_sea = false;
4285 }
4286 is_flying = true;
4287 }
4288
4292 } else {
4293 is_unit = false;
4296 useless = is_improvement_redundant(pcity, target->value.building);
4297 is_convert = (target->value.building->genus == IG_CONVERT);
4298 }
4299
4300 if (sprite != nullptr) {
4301 pix = sprite->pm;
4302 pix_scaled = pix->scaledToHeight(item_height - 2, Qt::SmoothTransformation);
4303
4304 if (useless) {
4306 }
4307 }
4308
4309 opt = QItemDelegate::setOptions(index, option);
4310 painter->save();
4311 opt.displayAlignment = Qt::AlignLeft;
4312 opt.textElideMode = Qt::ElideMiddle;
4313 QItemDelegate::drawBackground(painter, opt, index);
4314 rect1 = option.rect;
4315 rect1.setWidth(pix_scaled.width() + 4);
4316 rect2 = option.rect;
4317 rect2.setLeft(option.rect.left() + rect1.width());
4318 rect2.setTop(rect2.top() + (rect2.height()
4319 - painter->fontMetrics().height()) / 2);
4320 QItemDelegate::drawDisplay(painter, opt, rect2, name);
4321
4322 if (is_unit) {
4323 if (is_sea) {
4324 pix_dec.fill(QColor(0, 0, 255, 80));
4325 } else if (is_flying) {
4326 pix_dec.fill(QColor(220, 0, 0, 80));
4327 } else if (is_neutral) {
4328 pix_dec.fill(QColor(0, 120, 0, 40));
4329 } else {
4330 pix_dec.fill(QColor(0, 0, 150, 40));
4331 }
4332
4333 QItemDelegate::drawDecoration(painter, option, option.rect, pix_dec);
4334 }
4335
4336 if (is_convert) {
4337 pix_dec.fill(QColor(255, 255, 0, 70));
4338 QItemDelegate::drawDecoration(painter, option, option.rect, pix_dec);
4339 }
4340
4341 if (!pix_scaled.isNull()) {
4342 QItemDelegate::drawDecoration(painter, opt, rect1, pix_scaled);
4343 }
4344
4345 drawFocus(painter, opt, option.rect);
4346
4347 painter->restore();
4348
4349 if (free_sprite) {
4351 }
4352}
4353
4354/************************************************************************/
4359 const QRect &rect) const
4360{
4361 QPixmap pix(option.rect.width(), option.rect.height());
4362
4363 if ((option.state & QStyle::State_MouseOver) == 0 || !rect.isValid()) {
4364 return;
4365 }
4366
4367 pix.fill(QColor(50, 50, 50, 50));
4368 QItemDelegate::drawDecoration(painter, option, option.rect, pix);
4369}
4370
4371/************************************************************************/
4375 const QModelIndex &index) const
4376{
4377 QSize s;
4378
4379 s.setWidth(pd.x());
4380 s.setHeight(pd.y());
4381 return s;
4382}
4383
4384/************************************************************************/
4388 QObject *parent): QObject()
4389{
4391 target = ptarget;
4392}
4393
4394/************************************************************************/
4398{
4399 // Allocated as renegade in model
4400 if (target != nullptr) {
4401 delete target;
4402 }
4403}
4404
4405/************************************************************************/
4409{
4410 return QVariant::fromValue((void *)target);
4411}
4412
4413/************************************************************************/
4417{
4418 return false;
4419}
4420
4421/************************************************************************/
4425 bool su, bool sw, bool sb,
4426 QObject *parent)
4427 : QAbstractListModel(parent)
4428{
4429 show_units = su;
4430 show_wonders = sw;
4432 mcity = pcity;
4433 future_t = f;
4434 populate();
4435}
4436
4437/************************************************************************/
4445
4446/************************************************************************/
4450{
4451 if (!index.isValid()) {
4452 return QVariant();
4453 }
4454
4455 if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0
4456 && index.column() < columnCount()
4457 && (index.column() + index.row() * 3 < city_target_list.count())) {
4458 int r, c, t, new_index;
4459
4460 r = index.row();
4461 c = index.column();
4462 t = r * 3 + c;
4463 new_index = t / 3 + rowCount() * c;
4464 // Exception, shift whole column
4465 if ((c == 2) && city_target_list.count() % 3 == 1) {
4466 new_index = t / 3 + rowCount() * c - 1;
4467 }
4468 if (role == Qt::ToolTipRole) {
4470 }
4471
4472 return city_target_list[new_index]->data();
4473 }
4474
4475 return QVariant();
4476}
4477
4478/************************************************************************/
4482{
4484 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
4485 struct item items[MAX_NUM_PRODUCTION_TARGETS];
4486 struct universal *renegade;
4487 int item, targets_used;
4488 QString str;
4490 QFontMetrics fm(f);
4491
4492 sh.setY(fm.height() * 2);
4493 sh.setX(0);
4494
4496 city_target_list.clear();
4497
4499 future_t);
4500 name_and_sort_items(targets, targets_used, items, false, mcity);
4501
4502 for (item = 0; item < targets_used; item++) {
4503 if (future_t || can_city_build_now(&(wld.map), mcity, &items[item].item,
4504 RPT_CERTAIN)) {
4505 renegade = new universal(items[item].item);
4506
4507 // Renegade deleted in production_item destructor
4508 if (VUT_UTYPE == renegade->kind) {
4509 str = utype_name_translation(renegade->value.utype);
4510 sh.setX(qMax(sh.x(), fm.horizontalAdvance(str)));
4511
4512 if (show_units) {
4513 pi = new production_item(renegade, this);
4515 } else {
4516 delete renegade;
4517 }
4518 } else {
4519 str = improvement_name_translation(renegade->value.building);
4520 sh.setX(qMax(sh.x(), fm.horizontalAdvance(str)));
4521
4522 if ((is_wonder(renegade->value.building) && show_wonders)
4523 || (is_improvement(renegade->value.building) && show_buildings)
4524 || (is_convert_improvement(renegade->value.building))
4525 || (is_special_improvement(renegade->value.building)
4526 && show_buildings)) {
4527 pi = new production_item(renegade, this);
4529 } else {
4530 delete renegade;
4531 }
4532 }
4533 }
4534 }
4535
4536 pi = new production_item(nullptr, this);
4538 sh.setX(2 * sh.y() + sh.x());
4539 sh.setX(qMin(sh.x(), 250));
4540}
4541
4542/************************************************************************/
4546 const QVariant &value, int role)
4547{
4548 if (!index.isValid() || role != Qt::DisplayRole || role != Qt::ToolTipRole)
4549 return false;
4550
4551 if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0
4552 && index.column() < columnCount()) {
4553 bool change = city_target_list[index.row()]->setData();
4554 return change;
4555 }
4556
4557 return false;
4558}
4559
4560/************************************************************************/
4569 bool future, int when, int curr,
4570 bool show_units, bool buy,
4571 bool show_wonders,
4572 bool show_buildings): QTableView()
4573{
4574 QPoint pos, sh;
4575 QRect rect = QApplication::primaryScreen()->availableGeometry();
4576 int desk_width = rect.width();
4577 int desk_height = rect.height();
4578 fc_tt = new fc_tooltip(this);
4579 setAttribute(Qt::WA_DeleteOnClose);
4580 setWindowFlags(Qt::Popup);
4581 verticalHeader()->setVisible(false);
4582 horizontalHeader()->setVisible(false);
4583 setProperty("showGrid", false);
4585 sh_units = show_units;
4586 pw_city = pcity;
4587 buy_it = buy;
4588 when_change = when;
4589 list_model = new city_production_model(pw_city, future, show_units,
4590 show_wonders, show_buildings, this);
4591 sh = list_model->sh;
4592 c_p_d = new city_production_delegate(sh, this, pw_city);
4595 viewport()->installEventFilter(fc_tt);
4596 installEventFilter(this);
4598 const QItemSelection &)),
4600 const QItemSelection &)));
4603 setFixedWidth(3 * sh.x() + 6);
4604 setFixedHeight(list_model->rowCount()*sh.y() + 6);
4605
4606 if (width() > desk_width) {
4608 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
4609 } else {
4610 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
4611 }
4612
4613 if (height() > desk_height) {
4615 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
4616 } else {
4617 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
4618 }
4619
4620 pos = QCursor::pos();
4621
4622 if (pos.x() + width() > desk_width) {
4623 pos.setX(desk_width - width());
4624 } else if (pos.x() - width() < 0) {
4625 pos.setX(0);
4626 }
4627
4628 if (pos.y() + height() > desk_height) {
4629 pos.setY(desk_height - height());
4630 } else if (pos.y() - height() < 0) {
4631 pos.setY(0);
4632 }
4633
4634 move(pos);
4635 setMouseTracking(true);
4636 setFocus();
4637}
4638
4639/************************************************************************/
4643{
4644 if (event->button() == Qt::RightButton) {
4645 close();
4646 return;
4647 }
4648
4649 QAbstractItemView::mousePressEvent(event);
4650}
4651
4652/************************************************************************/
4656{
4657 QRect pw_rect;
4658 QPoint br;
4659
4660 if (obj != this)
4661 return false;
4662
4663 if (ev->type() == QEvent::MouseButtonPress) {
4664 pw_rect.setTopLeft(pos());
4665 br.setX(pos().x() + width());
4666 br.setY(pos().y() + height());
4667 pw_rect.setBottomRight(br);
4668
4669 if (!pw_rect.contains(QCursor::pos())) {
4670 close();
4671 }
4672 }
4673
4674 return false;
4675}
4676
4677/************************************************************************/
4681 const QItemSelection &ds)
4682{
4683 QModelIndexList indexes = selectionModel()->selectedIndexes();
4684 QModelIndex index;
4685 QVariant qvar;
4686 struct worklist queue;
4687 struct universal *target;
4688
4689 if (indexes.isEmpty() || client_is_observer()) {
4690 return;
4691 }
4692 index = indexes.at(0);
4693 qvar = index.data(Qt::UserRole);
4694 if (!qvar.isValid()) {
4695 return;
4696 }
4697 target = reinterpret_cast<universal *>(qvar.value<void *>());
4698 if (target != nullptr) {
4699 city_get_queue(pw_city, &queue);
4700 switch (when_change) {
4701 case 0: // Change current target
4703 if (city_can_buy(pw_city) && buy_it) {
4705 }
4706 break;
4707
4708 case 1: // Change current (selected on list)
4711 } else {
4713 worklist_insert(&queue, target, curr_selection);
4714 city_set_queue(pw_city, &queue);
4715 }
4716 break;
4717
4718 case 2: // Insert before
4720 curr_selection = 0;
4721 }
4724 worklist_insert(&queue, target, curr_selection);
4725 city_set_queue(pw_city, &queue);
4726 break;
4727
4728 case 3: // Insert after
4730 city_queue_insert(pw_city, -1, target);
4731 break;
4732 }
4734 worklist_insert(&queue, target, curr_selection);
4735 city_set_queue(pw_city, &queue);
4736 break;
4737
4738 case 4: // Add last
4739 city_queue_insert(pw_city, -1, target);
4740 break;
4741
4742 default:
4743 break;
4744 }
4745 }
4746 close();
4747 destroy();
4748}
4749
4750/************************************************************************/
4754{
4755 delete c_p_d;
4756 delete list_model;
4757 viewport()->removeEventFilter(fc_tt);
4758 removeEventFilter(this);
4759}
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1271
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:740
#define str
Definition astring.c:76
#define n
Definition astring.c:77
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_CLR(bv, bit)
Definition bitvector.h:94
QRect zealous_crop_rect(QImage &p)
Definition canvas.cpp:419
void qtg_canvas_free(struct canvas *store)
Definition canvas.cpp:48
struct canvas * qtg_canvas_create(int width, int height)
Definition canvas.cpp:36
void qtg_canvas_copy(struct canvas *dest, struct canvas *src, int src_x, int src_y, int dest_x, int dest_y, int width, int height)
Definition canvas.cpp:79
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
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 canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
citizens citizens_nation_get(const struct city *pcity, const struct player_slot *pslot)
Definition citizens.c:74
#define citizens_iterate_end
Definition citizens.h:54
#define citizens_iterate(_pcity, _pslot, _nationality)
Definition citizens.h:48
const char * city_improvement_name_translation(const struct city *pcity, const struct impr_type *pimprove)
Definition city.c:666
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:740
const char * city_name_getx(const struct city *pcity)
Definition city.c:1166
int city_granary_size(int city_size)
Definition city.c:2203
struct tile * city_map_to_tile(const struct civ_map *nmap, const struct tile *city_center, int city_radius_sq, int city_map_x, int city_map_y)
Definition city.c:305
int city_superspecialists(const struct city *pcity)
Definition city.c:3430
const char * city_name_get(const struct city *pcity)
Definition city.c:1157
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1312
bool is_city_option_set(const struct city *pcity, enum city_options option)
Definition city.c:3500
int city_population(const struct city *pcity)
Definition city.c:1247
int city_unit_unhappiness(const struct civ_map *nmap, struct unit *punit, int *free_unhappy)
Definition city.c:3121
bool city_unhappy(const struct city *pcity)
Definition city.c:1683
bool city_celebrating(const struct city *pcity)
Definition city.c:1702
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2942
bool city_happy(const struct city *pcity)
Definition city.c:1671
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target, const enum req_problem_type prob_type)
Definition city.c:1028
int rs_max_city_radius_sq(void)
Definition city.c:159
citizens city_specialists(const struct city *pcity)
Definition city.c:3415
int city_turns_to_grow(const struct city *pcity)
Definition city.c:2053
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:703
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
citizen_category
Definition city.h:265
#define city_owner(_pcity_)
Definition city.h:564
#define MAX_CITY_SIZE
Definition city.h:104
citizen_feeling
Definition city.h:276
@ FEELING_EFFECT
Definition city.h:279
@ FEELING_LUXURY
Definition city.h:278
@ FEELING_FINAL
Definition city.h:282
@ FEELING_LAST
Definition city.h:283
@ FEELING_BASE
Definition city.h:277
@ FEELING_NATIONALITY
Definition city.h:280
@ FEELING_MARTIAL
Definition city.h:281
void qtg_popdown_city_dialog(struct city *pcity)
Definition citydlg.cpp:3893
void qtg_real_city_dialog_refresh(struct city *pcity)
Definition citydlg.cpp:3913
QString split_text(QString text, bool cut)
Definition optiondlg.cpp:62
void city_font_update()
Definition citydlg.cpp:3927
bool qtg_city_dialog_is_open(struct city *pcity)
Definition citydlg.cpp:3968
QString get_tooltip(QVariant qvar)
Definition citydlg.cpp:4167
void qtg_popdown_all_city_dialogs()
Definition citydlg.cpp:3905
static city_dialog * city_dlg
Definition citydlg.cpp:75
void qtg_refresh_unit_city_dialogs(struct unit *punit)
Definition citydlg.cpp:3952
static QString bold(QString text)
Definition citydlg.cpp:4029
void qtg_real_city_dialog_popup(struct city *pcity)
Definition citydlg.cpp:3865
QString get_tooltip_improvement(const impr_type *building, struct city *pcity, bool ext)
Definition citydlg.cpp:4038
static bool city_dlg_created
Definition citydlg.cpp:71
static void pixmap_put_x(QPixmap *pix)
Definition citydlg.cpp:350
QString cut_helptext(QString text)
QString get_tooltip_unit(const struct unit_type *utype, bool ext)
Definition citydlg.cpp:4097
void destroy_city_dialog()
Definition citydlg.cpp:3880
void get_city_dialog_output_text(const struct city *pcity, Output_type_id otype, char *buf, size_t bufsz)
void get_city_dialog_production(struct city *pcity, char *buffer, size_t buffer_len)
int city_set_worklist(struct city *pcity, const struct worklist *pworklist)
int get_city_citizen_types(struct city *pcity, enum citizen_feeling idx, enum citizen_category *categories)
int city_buy_production(struct city *pcity)
bool city_queue_insert(struct city *pcity, int position, struct universal *item)
bool city_queue_insert_worklist(struct city *pcity, int position, const struct worklist *worklist)
int city_toggle_worker(struct city *pcity, int city_x, int city_y)
void get_city_dialog_airlift_text(const struct city *pcity, char *buf, size_t bufsz)
bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
int city_change_production(struct city *pcity, struct universal *target)
void city_rotate_specialist(struct city *pcity, int citizen_index)
int get_citydlg_canvas_width(void)
bool canvas_to_city_pos(int *city_x, int *city_y, int city_radius_sq, int canvas_x, int canvas_y)
int city_try_fill_superspecialists(struct city *pcity, int cat_len, enum citizen_category *categories)
void get_city_dialog_airlift_value(const struct city *pcity, char *buf, size_t bufsz)
void city_get_queue(struct city *pcity, struct worklist *pqueue)
void city_dialog_redraw_map(struct city *pcity, struct canvas *pcanvas)
int city_sell_improvement(struct city *pcity, Impr_type_id sell_id)
void get_city_dialog_pollution_text(const struct city *pcity, char *buf, size_t bufsz)
void get_city_dialog_culture_text(const struct city *pcity, char *buf, size_t bufsz)
bool city_can_buy(const struct city *pcity)
int get_citydlg_canvas_height(void)
void get_city_dialog_illness_text(const struct city *pcity, char *buf, size_t bufsz)
void set_city(struct city *pcity)
Definition citydlg.cpp:1187
struct city * pcity
Definition citydlg.h:418
city_label(int type, QWidget *parent=nullptr)
Definition citydlg.cpp:1155
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:1163
int wdth
Definition citydlg.h:279
int cutted_height
Definition citydlg.h:282
QSize sizeHint() const
Definition citydlg.cpp:1286
void paintEvent(QPaintEvent *event)
Definition citydlg.cpp:1226
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:1302
int height
Definition citydlg.h:280
void set_pixmap(struct city *pcity, float z)
Definition citydlg.cpp:1250
void context_menu(QPoint point)
Definition citydlg.cpp:1324
canvas * miniview
Definition citydlg.h:266
struct city * mcity
Definition citydlg.h:276
QSize minimumSizeHint() const
Definition citydlg.cpp:1294
float zoom
Definition citydlg.h:278
QPixmap zoomed_pixmap
Definition citydlg.h:267
city_map(QWidget *parent)
Definition citydlg.cpp:1195
int cutted_width
Definition citydlg.h:281
int radius
Definition citydlg.h:277
int delta_y
Definition citydlg.h:284
int delta_x
Definition citydlg.h:283
city_production_delegate(QPoint sh, QObject *parent, struct city *city)
Definition citydlg.cpp:4205
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition citydlg.cpp:4218
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition citydlg.cpp:4374
struct city * pcity
Definition citydlg.h:310
void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const
Definition citydlg.cpp:4357
int rowCount(const QModelIndex &index=QModelIndex()) const
Definition citydlg.h:348
QList< production_item * > city_target_list
Definition citydlg.h:364
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::DisplayRole)
Definition citydlg.cpp:4545
int columnCount(const QModelIndex &parent=QModelIndex()) const
Definition citydlg.h:352
city_production_model(struct city *pcity, bool f, bool su, bool sw, bool sb, QObject *parent=nullptr)
Definition citydlg.cpp:4424
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Definition citydlg.cpp:4449
struct city * mcity
Definition citydlg.h:365
static fc_font * instance()
Definition fonts.cpp:41
QFont * get_font(QString name)
Definition fonts.cpp:63
static fc_icons * instance()
bool eventFilter(QObject *obj, QEvent *event)
Definition citydlg.cpp:3984
void update_buildings()
Definition citydlg.cpp:551
QHBoxLayout * layout
Definition citydlg.h:252
void add_item(impr_item *item)
Definition citydlg.cpp:499
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:532
impr_info(QWidget *parent)
Definition citydlg.cpp:468
void clear_layout()
Definition citydlg.cpp:507
void init_layout()
Definition citydlg.cpp:478
QList< impr_item * > impr_list
Definition citydlg.h:253
void mouseDoubleClickEvent(QMouseEvent *event)
Definition citydlg.cpp:603
impr_item(QWidget *parent, const struct impr_type *building, struct city *pcity)
Definition citydlg.cpp:367
void init_pix()
Definition citydlg.cpp:406
void enterEvent(QEnterEvent *event)
Definition citydlg.cpp:415
struct canvas * impr_pixmap
Definition citydlg.h:229
struct city * dlgcity
Definition citydlg.h:230
const struct impr_type * impr
Definition citydlg.h:228
void leaveEvent(QEvent *event)
Definition citydlg.cpp:442
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:583
struct universal * target
Definition citydlg.h:334
QVariant data() const
Definition citydlg.cpp:4408
production_item(struct universal *ptarget, QObject *parent)
Definition citydlg.cpp:4387
bool eventFilter(QObject *obj, QEvent *ev)
Definition citydlg.cpp:4655
void prod_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:4680
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:4642
city_production_model * list_model
Definition citydlg.h:379
struct city * pw_city
Definition citydlg.h:396
fc_tooltip * fc_tt
Definition citydlg.h:401
city_production_delegate * c_p_d
Definition citydlg.h:380
production_widget(QWidget *parent, struct city *pcity, bool future, int when, int curr, bool show_units, bool buy=false, bool show_wonders=true, bool show_buildings=true)
Definition citydlg.cpp:4568
progress_bar(QWidget *parent)
Definition citydlg.cpp:82
void paintEvent(QPaintEvent *event)
Definition citydlg.cpp:188
int m_animate_step
Definition citydlg.h:133
void resizeEvent(QResizeEvent *event)
Definition citydlg.cpp:106
QRegion reg
Definition citydlg.h:135
void set_pixmap(struct universal *target)
Definition citydlg.cpp:114
void create_region()
Definition citydlg.cpp:326
QElapsedTimer m_timer
Definition citydlg.h:114
void timerEvent(QTimerEvent *event)
Definition citydlg.cpp:176
QPixmap * pix
Definition citydlg.h:134
QFont * sfont
Definition citydlg.h:136
void clicked()
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:1069
void init_layout()
Definition citydlg.cpp:1057
unit_info(bool supp)
Definition citydlg.cpp:1030
void add_item(unit_item *item)
Definition citydlg.cpp:1049
QHBoxLayout * layout
Definition citydlg.h:205
void update_units()
Definition citydlg.cpp:1088
void clear_layout()
Definition citydlg.cpp:1129
QList< unit_item * > unit_list
Definition citydlg.h:206
bool supports
Definition citydlg.h:209
QAction * activate
Definition citydlg.h:147
QAction * disband_action
Definition citydlg.h:145
void enterEvent(QEnterEvent *event)
Definition citydlg.cpp:961
void contextMenuEvent(QContextMenuEvent *ev)
Definition citydlg.cpp:734
QAction * sentry
Definition citydlg.h:149
struct unit * qunit
Definition citydlg.h:164
QAction * activate_and_close
Definition citydlg.h:148
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:1007
int happy_cost
Definition citydlg.h:168
void change_homecity()
Definition citydlg.cpp:920
QAction * unload
Definition citydlg.h:152
QAction * upgrade
Definition citydlg.h:153
bool supported
Definition citydlg.h:169
void fortify_unit()
Definition citydlg.cpp:951
void sentry_unit()
Definition citydlg.cpp:1020
QAction * unload_trans
Definition citydlg.h:154
void load_unit()
Definition citydlg.cpp:884
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:987
QAction * load
Definition citydlg.h:151
void activate_unit()
Definition citydlg.cpp:941
QAction * change_home
Definition citydlg.h:146
QAction * fortify
Definition citydlg.h:150
QImage unit_img
Definition citydlg.h:165
void create_actions()
Definition citydlg.cpp:788
void unload_all()
Definition citydlg.cpp:900
void disband()
Definition citydlg.cpp:866
void upgrade_unit()
Definition citydlg.cpp:908
void init_pix()
Definition citydlg.cpp:718
void leaveEvent(QEvent *event)
Definition citydlg.cpp:979
unit_item(QWidget *parent, struct unit *punit, bool supp=false, int happy_cost=0)
Definition citydlg.cpp:647
void unload_unit()
Definition citydlg.cpp:892
void activate_and_close_dialog()
Definition citydlg.cpp:930
bool client_is_observer(void)
struct civclient client
bool can_client_issue_orders(void)
#define client_player()
int collect_eventually_buildable_targets(struct universal *targets, struct city *pcity, bool advanced_tech)
Definition climisc.c:821
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:650
cid cid_encode(struct universal target)
Definition climisc.c:483
int collect_already_built_targets(struct universal *targets, struct city *pcity)
Definition climisc.c:918
struct universal cid_decode(cid id)
Definition climisc.c:526
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:89
#define cid_production
Definition climisc.h:71
int cid
Definition climisc.h:31
static struct fc_sockaddr_list * list
Definition clinet.c:102
void cm_copy_parameter(struct cm_parameter *dest, const struct cm_parameter *const src)
Definition cm.c:2176
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:552
void cma_put_city_under_agent(struct city *pcity, const struct cm_parameter *const parameter)
Definition cma_core.c:524
void cma_release_city(struct city *pcity)
Definition cma_core.c:542
char * cmafec_preset_get_descr(int idx)
Definition cma_fec.c:169
const char * cmafec_get_short_descr_of_city(const struct city *pcity)
Definition cma_fec.c:221
const struct cm_parameter * cmafec_preset_get_parameter(int idx)
Definition cma_fec.c:182
void cmafec_preset_add(const char *descr_name, struct cm_parameter *pparam)
Definition cma_fec.c:136
int cmafec_preset_get_index_of_parameter(const struct cm_parameter *const parameter)
Definition cma_fec.c:196
void cmafec_preset_remove(int idx)
Definition cma_fec.c:153
int cmafec_preset_num(void)
Definition cma_fec.c:213
void cmafec_get_fe_parameter(struct city *pcity, struct cm_parameter *dest)
Definition cma_fec.c:115
char * incite_cost
Definition comments.c:77
void request_unit_fortify(struct unit *punit)
Definition control.c:2365
struct unit * request_unit_unload_all(struct unit *punit)
Definition control.c:1523
void unit_focus_set(struct unit *punit)
Definition control.c:518
void request_unit_change_homecity(struct unit *punit)
Definition control.c:2106
void request_unit_unload(struct unit *pcargo)
Definition control.c:2206
void request_unit_sentry(struct unit *punit)
Definition control.c:2354
#define can_unit_do_activity_client(_punit_, _act_)
Definition control.h:41
int counter_index(const struct counter *pcount)
Definition counters.c:176
#define city_counters_iterate_end
Definition counters.h:64
#define city_counters_iterate(pcount)
Definition counters.h:57
bool qtg_request_transport(struct unit *pcargo, struct tile *ptile)
Definition dialogs.cpp:4968
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
int int id
Definition editgui_g.h:28
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:842
enum event_type event
Definition events.c:82
struct extra_type * next_extra_for_tile(const struct tile *ptile, enum extra_cause cause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:779
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:804
enum extra_cause activity_to_extra_cause(enum unit_activity act)
Definition extras.c:1090
enum extra_rmcause activity_to_extra_rmcause(enum unit_activity act)
Definition extras.c:1111
#define extra_index(_e_)
Definition extras.h:183
unsigned char citizens
Definition fc_types.h:249
@ RPT_CERTAIN
Definition fc_types.h:516
#define EC_NONE
Definition fc_types.h:808
@ TR_SUCCESS
Definition fc_types.h:941
#define ERM_NONE
Definition fc_types.h:831
@ O_SHIELD
Definition fc_types.h:103
@ O_FOOD
Definition fc_types.h:103
@ O_TRADE
Definition fc_types.h:103
@ O_SCIENCE
Definition fc_types.h:103
@ O_LUXURY
Definition fc_types.h:103
@ O_GOLD
Definition fc_types.h:103
@ O_LAST
Definition fc_types.h:103
const char * skip_intl_qualifier_prefix(const char *str)
Definition fcintl.c:48
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * population_to_text(int thousand_citizen)
Definition game.c:743
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct city * game_city_by_number(int id)
Definition game.c:106
struct global_worklist * global_worklist_by_id(int id)
bool global_worklist_set(struct global_worklist *pgwl, const struct worklist *pwl)
const char * global_worklist_name(const struct global_worklist *pgwl)
int global_worklist_id(const struct global_worklist *pgwl)
const struct worklist * global_worklist_get(const struct global_worklist *pgwl)
struct global_worklist * global_worklist_new(const char *name)
#define global_worklists_iterate(pgwl)
#define global_worklists_iterate_end
void canvas_free(struct canvas *store)
Definition canvas.c:44
@ INFO_LUXURY
Definition citydlg.c:120
@ INFO_STEAL
Definition citydlg.c:122
@ INFO_CORRUPTION
Definition citydlg.c:121
@ NUM_INFO_FIELDS
Definition citydlg.c:123
@ INFO_ILLNESS
Definition citydlg.c:122
@ INFO_WASTE
Definition citydlg.c:121
@ INFO_GROWTH
Definition citydlg.c:120
@ INFO_SHIELD
Definition citydlg.c:119
@ INFO_CULTURE
Definition citydlg.c:121
@ INFO_GOLD
Definition citydlg.c:119
@ INFO_SCIENCE
Definition citydlg.c:120
@ INFO_POLLUTION
Definition citydlg.c:121
@ INFO_TRADE
Definition citydlg.c:119
@ INFO_AIRLIFT
Definition citydlg.c:122
@ INFO_GRANARY
Definition citydlg.c:120
@ INFO_FOOD
Definition citydlg.c:119
void popup_upgrade_dialog(struct unit_list *punits)
Definition dialogs.c:1435
void popup_disband_dialog(struct unit_list *punits)
Definition dialogs.c:1473
static struct tile * pos
Definition finddlg.c:53
const char * tooltip
Definition repodlgs.c:1315
void free_sprite(struct sprite *s)
Definition sprite.c:278
static GMenu * change_menu
Definition cityrep.c:119
static GMenu * options_menu
Definition menu.c:91
QString get_tooltip_improvement(const impr_type *building, struct city *pcity=nullptr, bool ext=false)
Definition citydlg.cpp:4038
QString get_tooltip(QVariant qvar)
Definition citydlg.cpp:4167
void set_theme_style()
Definition themes.cpp:107
#define CAPTURE_DEFAULT_THIS
Definition gui_main.h:23
#define show(id)
Definition widget.h:235
#define hide(id)
Definition widget.h:238
QApplication * current_app()
Definition gui_main.cpp:227
char * helptext_unit(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct unit_type *utype, bool class_help)
Definition helpdata.c:1985
char * helptext_unit_upkeep_str(const struct unit_type *utype)
Definition helpdata.c:5095
char * helptext_building(char *buf, size_t bufsz, struct player *pplayer, const char *user_text, const struct impr_type *pimprove)
Definition helpdata.c:1439
int impr_sell_gold(const struct impr_type *pimprove)
enum test_result test_player_sell_building_now(struct player *pplayer, struct city *pcity, const struct impr_type *pimprove)
bool is_special_improvement(const struct impr_type *pimprove)
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
bool is_improvement(const struct impr_type *pimprove)
Impr_type_id improvement_number(const struct impr_type *pimprove)
int impr_build_shield_cost(const struct city *pcity, const struct impr_type *pimprove)
bool is_wonder(const struct impr_type *pimprove)
bool is_convert_improvement(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
int impr_estimate_build_shield_cost(const struct player *pplayer, const struct tile *ptile, const struct impr_type *pimprove)
const char * name
Definition inputfile.c:127
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_action(condition, action)
Definition log.h:188
int send_packet_worker_task(struct connection *pc, const struct packet_worker_task *packet)
int dsend_packet_city_options_req(struct connection *pc, int city_id, bv_city_options options, enum city_wl_cancel_behavior wl_cb)
void put_unit(const struct unit *punit, struct canvas *pcanvas, float zoom, int canvas_x, int canvas_y)
void put_unit_city_overlays(struct unit *punit, struct canvas *pcanvas, int canvas_x, int canvas_y, int *upkeep_cost, int happy_cost)
void center_tile_mapcanvas(const struct tile *ptile)
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1066
static mpgui * gui
Definition mpgui_qt.cpp:53
static const char * name_translation_get(const struct name_translation *ptrans)
const char *const default_font
Definition fonts.h:27
const char *const notify_label
Definition fonts.h:28
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
const char * text_happiness_cities(const struct city *pcity)
Definition text.c:1979
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1217
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:432
void qtg_free_sprite(struct sprite *s)
Definition sprite.cpp:173
struct sprite * qtg_create_sprite(int width, int height, struct color *pcolor)
Definition sprite.cpp:182
#define requirement_vector_iterate_end
#define requirement_vector_iterate(req_vec, preq)
#define ARRAY_SIZE(x)
Definition shared.h:85
#define FC_INFINITY
Definition shared.h:36
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
#define strvec_iterate(psv, str)
#define strvec_iterate_end
QPixmap map_pixmap
Definition canvas.h:25
void setup_ui(struct city *qcity)
Definition citydlg.cpp:3304
int current_building
Definition citydlg.h:504
void worklist_up()
Definition citydlg.cpp:3735
city_label * citizens_label
Definition citydlg.h:447
QPushButton * lcity_name
Definition citydlg.h:490
void show_happiness()
Definition citydlg.cpp:2118
void closeEvent(QCloseEvent *event)
Definition citydlg.cpp:2324
void show_counters()
Definition citydlg.cpp:2173
void update_nation_table()
Definition citydlg.cpp:3098
void hideEvent(QHideEvent *event)
Definition citydlg.cpp:2296
void cma_toggle_changed_depr(int state)
Definition citydlg.cpp:2707
void close_counters()
Definition citydlg.cpp:2153
QPushButton * work_next_but
Definition citydlg.h:478
void next_city()
Definition citydlg.cpp:3414
progress_bar * production_combo_p
Definition citydlg.h:462
QTableWidget * nationality_table
Definition citydlg.h:464
QRadioButton * r3
Definition citydlg.h:472
QTableWidget * cma_table
Definition citydlg.h:465
void showEvent(QShowEvent *event)
Definition citydlg.cpp:2307
QPushButton * happiness_button
Definition citydlg.h:482
void cma_double_clicked(int row, int column)
Definition citydlg.cpp:2500
void update_disabled()
Definition citydlg.cpp:2197
QLabel * supp_units
Definition citydlg.h:459
QPushButton * next_city_but
Definition citydlg.h:476
QLabel * qlt[NUM_INFO_FIELDS]
Definition citydlg.h:455
QPushButton * work_prev_but
Definition citydlg.h:479
QHBoxLayout * single_page_layout
Definition citydlg.h:436
QVBoxLayout * counters_layout
Definition citydlg.h:438
QWidget * counters_widget
Definition citydlg.h:453
void update_buy_button()
Definition citydlg.cpp:2880
int selected_row_p
Definition citydlg.h:491
QHBoxLayout * leftbot_layout
Definition citydlg.h:442
void update_building()
Definition citydlg.cpp:3486
QPushButton * zoom_in_button
Definition citydlg.h:484
void save_worklist()
Definition citydlg.cpp:3801
void worklist_del()
Definition citydlg.cpp:3760
QGridLayout * info_grid_layout
Definition citydlg.h:449
void clear_worklist()
Definition citydlg.cpp:3720
impr_info * city_buildings
Definition citydlg.h:489
QLabel * curr_impr
Definition citydlg.h:461
city_label * lab_table[6]
Definition citydlg.h:448
int scroll_height
Definition citydlg.h:500
QLabel * curr_units
Definition citydlg.h:460
unit_info * current_units
Definition citydlg.h:487
void zoom_out()
Definition citydlg.cpp:2415
void zoom_in()
Definition citydlg.cpp:2402
struct unit_node_vector supported_units
Definition citydlg.c:163
QPushButton * zoom_out_button
Definition citydlg.h:485
struct city * pcity
Definition citydlg.c:138
struct city_dialog::@148 happiness
void update_info_label()
Definition citydlg.cpp:3175
QPushButton * work_add_but
Definition citydlg.h:480
QSplitter * central_left_splitter
Definition citydlg.h:440
void disband_state_changed(bool allow_disband)
Definition citydlg.cpp:2743
void update_citizens()
Definition citydlg.cpp:2906
QRadioButton * r1
Definition citydlg.h:472
void cma_slider(int val)
Definition citydlg.cpp:2718
QCheckBox * cma_celeb_checkbox
Definition citydlg.h:466
QCheckBox * show_units
Definition citydlg.h:469
enum city_dialog::city_dialog_tab current_tab
void worklist_down()
Definition citydlg.cpp:3777
void update_title()
Definition citydlg.cpp:3832
QLabel * cma_info_text
Definition citydlg.h:456
void dbl_click_p(QTableWidgetItem *item)
Definition citydlg.cpp:3320
QPushButton * cma_enable_but
Definition citydlg.h:475
QLabel * cma_result
Definition citydlg.h:457
void cma_remove()
Definition citydlg.cpp:2668
QSlider * slider_tab[2 *O_LAST+2]
Definition citydlg.h:492
QPushButton * button
Definition citydlg.h:473
bool eventFilter(QObject *obj, QEvent *event)
Definition citydlg.cpp:2335
QSplitter * prod_unit_splitter
Definition citydlg.h:439
QVBoxLayout * left_layout
Definition citydlg.h:445
void prev_city()
Definition citydlg.cpp:3450
void city_rename()
Definition citydlg.cpp:2372
void refresh()
Definition citydlg.cpp:3002
void update_cma_tab()
Definition citydlg.cpp:2601
QPushButton * work_rem_but
Definition citydlg.h:481
float zoom
Definition citydlg.h:501
QSplitter * central_splitter
Definition citydlg.h:441
QWidget * prod_happ_widget
Definition citydlg.h:443
void show_targets()
Definition citydlg.cpp:3689
city_dialog(QWidget *parent=nullptr)
Definition citydlg.cpp:1474
void cma_toggle_changed(Qt::CheckState state)
Definition citydlg.cpp:2695
QWidget * top_widget
Definition citydlg.h:444
void update_tabs()
Definition citydlg.cpp:2104
QPushButton * prev_city_but
Definition citydlg.h:477
void cma_enable()
Definition citydlg.cpp:2464
QLabel * cma_result_pix
Definition citydlg.h:458
struct city * dlgcity
Definition citydlg.h:499
void update_counters_table()
Definition citydlg.cpp:3034
void update_sliders()
Definition citydlg.cpp:2549
void update_improvements()
Definition citydlg.cpp:3554
GtkWidget * worklist
Definition citydlg.c:176
QHBoxLayout * happiness_layout
Definition citydlg.h:437
QPushButton * settings_button
Definition citydlg.h:483
void display_settings_menu()
Definition citydlg.cpp:2784
QCheckBox * future_targets
Definition citydlg.h:468
void change_production(bool next)
Definition citydlg.cpp:2058
void cma_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:2519
QCheckBox * cma_max_growth
Definition citydlg.h:467
void item_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:3396
void show_targets_worklist()
Definition citydlg.cpp:3705
QCheckBox * show_wonders
Definition citydlg.h:471
void cma_context_menu(const QPoint &p)
Definition citydlg.cpp:2764
void cma_changed()
Definition citydlg.cpp:2479
QPushButton * buy_button
Definition citydlg.h:474
QRadioButton * r4
Definition citydlg.h:472
struct city_dialog::@149 counters
void update_units()
Definition citydlg.cpp:3337
QRadioButton * r2
Definition citydlg.h:472
QTableWidget * p_table_p
Definition citydlg.h:463
void save_cma()
Definition citydlg.cpp:2428
QPixmap * citizen_pixmap
Definition citydlg.h:486
void production_changed(int index)
Definition citydlg.cpp:3671
void update_prod_buttons()
Definition citydlg.cpp:2234
QWidget * happiness_widget
Definition citydlg.h:452
QGroupBox * happiness_group
Definition citydlg.h:451
QCheckBox * show_buildings
Definition citydlg.h:470
Definition city.h:318
struct worker_task_list * task_reqs
Definition city.h:410
int surplus[O_LAST]
Definition city.h:353
enum city_wl_cancel_behavior wlcb
Definition city.h:402
int food_stock
Definition city.h:365
int * counter_values
Definition city.h:406
int pollution
Definition city.h:367
int id
Definition city.h:324
int waste[O_LAST]
Definition city.h:354
struct unit_list * info_units_present
Definition city.h:474
struct unit_list * info_units_supported
Definition city.h:473
struct universal production
Definition city.h:394
int steal
Definition city.h:412
citizens size
Definition city.h:330
int culture
Definition city.h:465
int buy_cost
Definition city.h:466
struct city::@18::@21 client
struct tile * tile
Definition city.h:320
int shield_stock
Definition city.h:366
int prod[O_LAST]
Definition city.h:356
struct unit_list * units_supported
Definition city.h:404
struct packet_game_info info
Definition game.h:89
struct connection conn
Definition client_main.h:96
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
Definition colors.h:21
Definition mapimg.c:367
enum impr_genus_id genus
Definition improvement.h:63
struct requirement_vector obsolete_by
Definition improvement.h:59
Definition climisc.h:82
struct universal item
Definition climisc.h:83
enum unit_activity activity
struct city_list * cities
Definition player.h:281
struct player_economic economic
Definition player.h:284
QPixmap * pm
Definition sprite.h:25
Definition tile.h:50
int index
Definition tile.h:51
struct unit_list * units
Definition tile.h:58
int defense_strength
Definition unittype.h:523
int firepower
Definition unittype.h:532
const struct unit_type * obsoleted_by
Definition unittype.h:536
int vision_radius_sq
Definition unittype.h:529
int move_rate
Definition unittype.h:524
int attack_strength
Definition unittype.h:522
Definition unit.h:139
int upkeep[O_LAST]
Definition unit.h:149
int id
Definition unit.h:146
struct tile * tile
Definition unit.h:141
int homecity
Definition unit.h:147
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
struct universal entries[MAX_LEN_WORKLIST]
Definition worklist.h:30
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#define TRUE
Definition support.h:46
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
bool is_future_tech(Tech_type_id tech)
Definition tech.c:286
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:181
#define A_NONE
Definition tech.h:43
const char * text_happiness_nationality(const struct city *pcity)
Definition text.c:1907
const char * text_happiness_wonders(const struct city *pcity)
Definition text.c:1949
const char * text_happiness_units(const struct city *pcity)
Definition text.c:2113
const char * text_happiness_luxuries(const struct city *pcity)
Definition text.c:2152
const char * text_happiness_buildings(const struct city *pcity)
Definition text.c:1879
const char * unit_description(struct unit *punit)
Definition text.c:528
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_terrain(_tile)
Definition tile.h:115
int tileset_hex_width(const struct tileset *t)
Definition tilespec.c:747
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:7033
int tileset_unit_width(const struct tileset *t)
Definition tilespec.c:823
int tileset_unit_height(const struct tileset *t)
Definition tilespec.c:831
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:927
struct tileset * get_tileset(void)
Definition tilespec.c:718
struct tileset * unscaled_tileset
Definition tilespec.c:592
int tileset_unit_layout_offset_y(const struct tileset *t)
Definition tilespec.c:908
bool tileset_is_isometric(const struct tileset *t)
Definition tilespec.c:738
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:963
struct sprite * get_icon_sprite(const struct tileset *t, enum icon_type icon)
Definition tilespec.c:7237
int tileset_unit_with_upkeep_height(const struct tileset *t)
Definition tilespec.c:885
int tileset_hex_height(const struct tileset *t)
Definition tilespec.c:756
struct sprite * get_citizen_sprite(const struct tileset *t, enum citizen_category type, int citizen_index, const struct city *pcity)
Definition tilespec.c:6972
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7055
struct sprite * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:7006
struct sprite * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Definition tilespec.c:7024
@ ICON_CITYDLG
Definition tilespec.h:317
const struct unit_type * utype
Definition fc_types.h:536
const struct impr_type * building
Definition fc_types.h:529
bool can_unit_change_homecity(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:524
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:402
#define unit_tile(_pu)
Definition unit.h:407
#define unit_owner(_pu)
Definition unit.h:406
bool units_are_occupied(const struct unit_list *punits)
Definition unitlist.c:275
bool units_can_unload(const struct civ_map *nmap, const struct unit_list *punits)
Definition unitlist.c:303
bool units_can_upgrade(const struct civ_map *nmap, const struct unit_list *punits)
Definition unitlist.c:337
bool units_can_load(const struct unit_list *punits)
Definition unitlist.c:289
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
int utype_build_shield_cost_base(const struct unit_type *punittype)
Definition unittype.c:1493
bool utype_is_consumed_by_action_result(enum action_result result, const struct unit_type *utype)
Definition unittype.c:1254
struct advance * utype_primary_tech_req(const struct unit_type *ptype)
Definition unittype.c:2747
bool utype_can_do_action_result(const struct unit_type *putype, enum action_result result)
Definition unittype.c:412
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1463
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
const char * utype_values_translation(const struct unit_type *punittype)
Definition unittype.c:1643
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:773
#define utype_class(_t_)
Definition unittype.h:756
#define utype_fuel(ptype)
Definition unittype.h:849
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
bool worklist_peek_ith(const struct worklist *pwl, struct universal *prod, int idx)
Definition worklist.c:86
bool worklist_insert(struct worklist *pwl, const struct universal *prod, int idx)
Definition worklist.c:167
void worklist_remove(struct worklist *pwl, int idx)
Definition worklist.c:122
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57