Freeciv-3.3
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/************************************************************************/
415#ifndef FC_QT5_MODE
417#else // FC_QT5_MODE
418void impr_item::enterEvent(QEvent *event)
419#endif // FC_QT5_MODE
420{
421 struct sprite *sprite;
422 QPainter p;
423
424 if (impr_pixmap) {
425 canvas_free(impr_pixmap);
426 }
427
429 if (impr && sprite) {
430 impr_pixmap = qtg_canvas_create(sprite->pm->width(),
431 sprite->pm->height());
432 impr_pixmap->map_pixmap.fill(QColor(palette().color(QPalette::Highlight)));
433 pixmap_copy(&impr_pixmap->map_pixmap, sprite->pm, 0 , 0, 0, 0,
434 sprite->pm->width(), sprite->pm->height());
435 } else {
436 impr_pixmap = qtg_canvas_create(10, 10);
437 impr_pixmap->map_pixmap.fill(QColor(palette().color(QPalette::Highlight)));
438 }
439
440 init_pix();
441}
442
443/************************************************************************/
447{
448 struct sprite *sprite;
449
450 if (impr_pixmap) {
452 }
453
455 if (impr && sprite) {
457 sprite->pm->height());
458 impr_pixmap->map_pixmap.fill(Qt::transparent);
459 pixmap_copy(&impr_pixmap->map_pixmap, sprite->pm, 0 , 0, 0, 0,
460 sprite->pm->width(), sprite->pm->height());
461 } else {
463 impr_pixmap->map_pixmap.fill(Qt::red);
464 }
465
466 init_pix();
467}
468
469/************************************************************************/
473{
475 layout = new QHBoxLayout(this);
476 init_layout();
477}
478
479/************************************************************************/
483{
484 QSizePolicy size_fixed_policy(QSizePolicy::Fixed,
485 QSizePolicy::MinimumExpanding,
486 QSizePolicy::Slider);
487
490}
491
492/************************************************************************/
496{
497
498}
499
500/************************************************************************/
504{
505 impr_list.append(item);
506}
507
508/************************************************************************/
512{
513 int i = impr_list.count();
514 impr_item *ui;
515 int j;
516 setUpdatesEnabled(false);
517 setMouseTracking(false);
518
519 for (j = 0; j < i; j++) {
520 ui = impr_list[j];
521 layout->removeWidget(ui);
522 delete ui;
523 }
524
525 while (!impr_list.empty()) {
526 impr_list.removeFirst();
527 }
528
529 setMouseTracking(true);
530 setUpdatesEnabled(true);
531}
532
533/************************************************************************/
537{
538 QPoint p;
539
540 p = parentWidget()->parentWidget()->pos();
541 p = mapToGlobal(p);
542
543 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
544 event->angleDelta(),
545 event->buttons(),
546 event->modifiers(),
547 event->phase(), false, event->source());
548
549 QApplication::sendEvent(parentWidget(), &new_event);
550}
551
552/************************************************************************/
556{
557 int i = impr_list.count();
558 int j;
559 int h = 0;
560 impr_item *ui;
561
562 setUpdatesEnabled(false);
563 hide();
564
565 for (j = 0; j < i; j++) {
566 ui = impr_list[j];
567 h = ui->height();
568 layout->addWidget(ui, 0, Qt::AlignVCenter);
569 }
570
571 if (impr_list.count() > 0) {
572 parentWidget()->parentWidget()->setFixedHeight(city_dlg->scroll_height
573 + h + 6);
574 } else {
575 parentWidget()->parentWidget()->setFixedHeight(0);
576 }
577
578 show();
579 setUpdatesEnabled(true);
580 layout->update();
582}
583
584/************************************************************************/
588{
589 QPoint p;
590
591 p = parentWidget()->parentWidget()->pos();
592 p = mapToGlobal(p);
593
594 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
595 event->angleDelta(),
596 event->buttons(),
597 event->modifiers(),
598 event->phase(), false, event->source());
599
600 QApplication::sendEvent(parentWidget()->parentWidget(),
601 &new_event);
602}
603
604/************************************************************************/
608{
610 return;
611 }
612
613 if (event->button() == Qt::LeftButton) {
614 char buf[256];
615 int price;
616 const int impr_id = improvement_number(impr);
617 const int city_id = dlgcity->id;
619
621 impr) != TR_SUCCESS) {
622 return;
623 }
624
626
629 PL_("Sell %s for %d gold?",
630 "Sell %s for %d gold?", price),
632
633 ask->set_text_title(buf, (_("Sell improvement?")));
634 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
635 ask->setAttribute(Qt::WA_DeleteOnClose);
636 connect(ask, &hud_message_box::accepted, [=]() {
637 struct city *pcity = game_city_by_number(city_id);
638
639 if (pcity == nullptr) {
640 return;
641 }
643 });
644 ask->show();
645 }
646}
647
648/************************************************************************/
652 bool supp, int hppy_cost) : QLabel()
653{
656 QImage img;
657 QRect crop;
658 qunit = punit;
659 struct canvas *unit_pixmap;
660 struct tileset *tmp;
661 float isosize;
662
664 supported = supp;
665
666 tmp = nullptr;
667 if (unscaled_tileset) {
668 tmp = tileset;
670 }
671 isosize = 0.6;
673 isosize = 0.45;
674 }
675
676 if (punit) {
677 if (supported) {
680 } else {
683 }
684
685 unit_pixmap->map_pixmap.fill(Qt::transparent);
686 put_unit(punit, unit_pixmap, 1.0, 0, 0);
687
688 if (supported) {
692 }
693 } else {
695 unit_pixmap->map_pixmap.fill(Qt::transparent);
696 }
697
698 img = unit_pixmap->map_pixmap.toImage();
700 cropped_img = img.copy(crop);
703 * isosize, Qt::SmoothTransformation);
704 } else {
706 Qt::SmoothTransformation);
707 }
709 if (tmp != nullptr) {
710 tileset = tmp;
711 }
712
714 setFixedWidth(unit_img.width() + 4);
715 setFixedHeight(unit_img.height());
717}
718
719/************************************************************************/
723{
724 setPixmap(QPixmap::fromImage(unit_img));
725 update();
726}
727
728/************************************************************************/
734
735/************************************************************************/
739{
740 QMenu *menu;
741
743 return;
744 }
745
746 if (unit_owner(qunit) != client_player()) {
747 return;
748 }
749
750 menu = new QMenu(gui()->central_wdg);
751 menu->addAction(activate);
752 menu->addAction(activate_and_close);
753
754 if (sentry) {
755 menu->addAction(sentry);
756 }
757
758 if (fortify) {
759 menu->addAction(fortify);
760 }
761
762 if (change_home) {
763 menu->addAction(change_home);
764 }
765
766 if (load) {
767 menu->addAction(load);
768 }
769
770 if (unload) {
771 menu->addAction(unload);
772 }
773
774 if (unload_trans) {
775 menu->addAction(unload_trans);
776 }
777
778 if (disband_action) {
779 menu->addAction(disband_action);
780 }
781
782 if (upgrade) {
783 menu->addAction(upgrade);
784 }
785
786 menu->popup(event->globalPos());
787}
788
789/************************************************************************/
793{
794 struct unit_list *qunits;
795
797 return;
798 }
799
802 activate = new QAction(_("Activate unit"), this);
803 connect(activate, &QAction::triggered, this, &unit_item::activate_unit);
804 activate_and_close = new QAction(_("Activate and close dialog"), this);
805 connect(activate_and_close, &QAction::triggered, this,
807
809 sentry = new QAction(_("Sentry unit"), this);
810 connect(sentry, &QAction::triggered, this, &unit_item::sentry_unit);
811 } else {
812 sentry = nullptr;
813 }
814
816 fortify = new QAction(_("Fortify unit"), this);
817 connect(fortify, &QAction::triggered, this, &unit_item::fortify_unit);
818 } else {
819 fortify = nullptr;
820 }
822 disband_action = new QAction(_("Disband unit"), this);
823 connect(disband_action, &QAction::triggered, this, &unit_item::disband);
824 } else {
825 disband_action = nullptr;
826 }
827
830 this);
831 connect(change_home, &QAction::triggered, this, &unit_item::change_homecity);
832 } else {
833 change_home = nullptr;
834 }
835
836 if (units_can_load(qunits)) {
837 load = new QAction(_("Load"), this);
838 connect(load, &QAction::triggered, this, &unit_item::load_unit);
839 } else {
840 load = nullptr;
841 }
842
843 if (units_can_unload(&(wld.map), qunits)) {
844 unload = new QAction(_("Unload"), this);
845 connect(unload, &QAction::triggered, this, &unit_item::unload_unit);
846 } else {
847 unload = nullptr;
848 }
849
851 unload_trans = new QAction(_("Unload All From Transporter"), this);
852 connect(unload_trans, &QAction::triggered, this, &unit_item::unload_all);
853 } else {
854 unload_trans = nullptr;
855 }
856
857 if (units_can_upgrade(&(wld.map), qunits)) {
858 upgrade = new QAction(_("Upgrade Unit"), this);
859 connect(upgrade, &QAction::triggered, this, &unit_item::upgrade_unit);
860 } else {
861 upgrade = nullptr;
862 }
863
865}
866
867/************************************************************************/
871{
872 struct unit_list *punits;
874
875 if (punit == nullptr) {
876 return;
877 }
878
883}
884
885/************************************************************************/
892
893/************************************************************************/
900
901/************************************************************************/
908
909/************************************************************************/
920
921/************************************************************************/
930
931/************************************************************************/
941
942/************************************************************************/
946{
947 if (qunit) {
949 }
950}
951
952/************************************************************************/
956{
957 if (qunit) {
959 }
960}
961
962/************************************************************************/
965#ifndef FC_QT5_MODE
967#else // FC_QT5_MODE
968void unit_item::enterEvent(QEvent *event)
969#endif // FC_QT5_MODE
970{
971 QImage temp_img(unit_img.size(), QImage::Format_ARGB32_Premultiplied);
972 QPainter p;
973
974 p.begin(&temp_img);
975 p.fillRect(0, 0, unit_img.width(), unit_img.height(),
976 QColor(palette().color(QPalette::Highlight)));
977 p.drawImage(0, 0, unit_img);
978 p.end();
979
980 setPixmap(QPixmap::fromImage(temp_img));
981 update();
982}
983
984/************************************************************************/
988{
989 init_pix();
990}
991
992/************************************************************************/
996{
997 QPoint p;
998
999 p = parentWidget()->parentWidget()->pos();
1000 p = mapToGlobal(p);
1001
1002 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
1003 event->angleDelta(),
1004 event->buttons(),
1005 event->modifiers(),
1006 event->phase(), false, event->source());
1007
1008 QApplication::sendEvent(parentWidget()->parentWidget(),
1009 &new_event);
1010}
1011
1012/************************************************************************/
1016{
1017 if (event->button() == Qt::LeftButton) {
1018 if (qunit) {
1021 }
1022 }
1023}
1024
1025/************************************************************************/
1029{
1030 if (qunit) {
1032 }
1033}
1034
1035/************************************************************************/
1039{
1040 layout = new QHBoxLayout(this);
1041 init_layout();
1042 supports = supp;
1043}
1044
1045/************************************************************************/
1049{
1051 unit_list.clear();
1052}
1053
1054/************************************************************************/
1058{
1059 unit_list.append(item);
1060}
1061
1062/************************************************************************/
1066{
1067 QSizePolicy size_fixed_policy(QSizePolicy::Fixed,
1068 QSizePolicy::MinimumExpanding,
1069 QSizePolicy::Slider);
1072}
1073
1074/************************************************************************/
1078{
1079 QPoint p;
1080
1081 p = parentWidget()->parentWidget()->pos();
1082 p = mapToGlobal(p);
1083
1084 QWheelEvent new_event(QPoint(5, 5), p + QPoint(5,5), event->pixelDelta(),
1085 event->angleDelta(),
1086 event->buttons(),
1087 event->modifiers(),
1088 event->phase(), false, event->source());
1089
1090 QApplication::sendEvent(parentWidget(), &new_event);
1091}
1092
1093/************************************************************************/
1097{
1098 int i = unit_list.count();
1099 int j;
1100 int h;
1101 float hexfix;
1102 unit_item *ui;
1103
1104 setUpdatesEnabled(false);
1105 hide();
1106
1107 for (j = 0; j < i; j++) {
1108 ui = unit_list[j];
1109 layout->addWidget(ui, 0, Qt::AlignVCenter);
1110 }
1111
1112 hexfix = 1.0;
1114 hexfix = 0.75;
1115 }
1116
1118 h = tileset_unit_width(get_tileset()) * 0.7 * hexfix + 6;
1119 } else {
1121 }
1122 if (unit_list.count() > 0) {
1123 parentWidget()->parentWidget()->setFixedHeight(city_dlg->scroll_height
1124 + h);
1125 } else {
1126 parentWidget()->parentWidget()->setFixedHeight(0);
1127 }
1128 show();
1129 setUpdatesEnabled(true);
1130 layout->update();
1132}
1133
1134/************************************************************************/
1138{
1139 int i = unit_list.count();
1140 unit_item *ui;
1141 int j;
1142 setUpdatesEnabled(false);
1143 setMouseTracking(false);
1144
1145 for (j = 0; j < i; j++) {
1146 ui = unit_list[j];
1147 layout->removeWidget(ui);
1148 delete ui;
1149 }
1150
1151 while (!unit_list.empty()) {
1152 unit_list.removeFirst();
1153 }
1154
1155 setMouseTracking(true);
1156 setUpdatesEnabled(true);
1157}
1158
1159/************************************************************************/
1163city_label::city_label(int t, QWidget *parent) : QLabel(parent)
1164{
1165 type = t;
1166}
1167
1168/************************************************************************/
1172{
1173 int citnum, i;
1174 int w = tileset_small_sprite_width(tileset) / gui()->map_scale;
1175 int num_citizens = pcity->size;
1176
1177 if (cma_is_city_under_agent(pcity, nullptr)) {
1178 return;
1179 }
1180
1181 i = 1 + (num_citizens * 5 / 200);
1182 w = w / i;
1183 citnum = event->pos().x() / w;
1184
1185 if (!can_client_issue_orders()) {
1186 return;
1187 }
1188
1190}
1191
1192/************************************************************************/
1196{
1197 pcity = pciti;
1198}
1199
1200/************************************************************************/
1204{
1206 radius = 0;
1212 view->map_pixmap.fill(Qt::black);
1214 miniview->map_pixmap.fill(Qt::black);
1215 delta_x = 0;
1216 delta_y = 0;
1217 setContextMenuPolicy(Qt::CustomContextMenu);
1218 connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
1219 this, SLOT(context_menu(const QPoint &)));
1220}
1221
1222/************************************************************************/
1230
1231/************************************************************************/
1235{
1237 QString str;
1238
1239 painter.begin(this);
1240 painter.drawPixmap(0, 0, zoomed_pixmap);
1241
1242 if (cma_is_city_under_agent(mcity, nullptr)) {
1243 painter.fillRect(0, 0, zoomed_pixmap.width(), zoomed_pixmap.height(),
1244 QBrush(QColor(60, 60 , 60 , 110)));
1245 painter.setPen(QColor(255, 255, 255));
1246 // TRANS: %1 is a custom string chosen by player.
1247 str = QString(_("Governor %1"))
1249 painter.drawText(5, zoomed_pixmap.height() - 10, str);
1250 }
1251
1252 painter.end();
1253}
1254
1255/************************************************************************/
1258void city_map::set_pixmap(struct city *pcity, float z)
1259{
1260 int r, max_r;
1261 QSize size;
1262
1263 zoom = z;
1265
1266 if (radius != r) {
1268 radius = r;
1270 cutted_width = wdth * (r + 1) / max_r;
1271 cutted_height = height * (r + 1) / max_r;
1274 delta_x = (wdth - cutted_width) / 2;
1275 delta_y = (height - cutted_height) / 2;
1277 miniview->map_pixmap.fill(Qt::black);
1278 }
1279
1283 size = miniview->map_pixmap.size();
1285 Qt::KeepAspectRatio,
1286 Qt::SmoothTransformation);
1288 mcity = pcity;
1289}
1290
1291/************************************************************************/
1295{
1296 return zoomed_pixmap.size();
1297}
1298
1299/************************************************************************/
1303{
1304 return zoomed_pixmap.size();
1305}
1306
1307/************************************************************************/
1311{
1313 QPoint pos;
1314
1315 if (!can_client_issue_orders() || event->button() != Qt::LeftButton) {
1316 return;
1317 }
1318
1319 pos = event->pos();
1320 canvas_x = pos.x() / zoom + delta_x;
1321 canvas_y = pos.y() / zoom + delta_y;
1322
1324 canvas_x, canvas_y)) {
1326 }
1327}
1328
1329/************************************************************************/
1333{
1335 QAction *con_cultivate = nullptr;
1336 QAction *con_irrig = nullptr;
1337 QAction *con_plant = nullptr;
1338 QAction *con_mine = nullptr;
1339 QAction *con_road = nullptr;
1340 QAction *con_trfrm = nullptr;
1341 QAction *con_clean = nullptr;
1342 QAction *con_clear = nullptr;
1343 QMenu *con_menu;
1345 struct terrain *pterr;
1346 struct tile *ptile;
1347 struct universal for_terr;
1348 struct worker_task *ptask;
1349 int city_id = mcity->id;
1350
1351 if (!can_client_issue_orders()) {
1352 return;
1353 }
1354
1355 canvas_x = point.x() / zoom + delta_x;
1356 canvas_y = point.y() / zoom + delta_y;
1357
1359 canvas_x, canvas_y)) {
1360 return;
1361 }
1362
1364 city_x, city_y);
1365 pterr = tile_terrain(ptile);
1366 for_terr.kind = VUT_TERRAIN;
1367 for_terr.value.terrain = pterr;
1369
1370 wid_act = new QWidgetAction(this);
1371 wid_act->setDefaultWidget(new QLabel(_("Autoworker activity:")));
1372
1373 con_menu = new QMenu(this);
1374 con_menu->addAction(wid_act);
1375
1376 if (pterr->plant_result != nullptr
1378 con_plant = con_menu->addAction(_("Plant"));
1379 }
1381 con_mine = con_menu->addAction(Q_("?act:Mine"));
1382 }
1383
1384 if (pterr->cultivate_result != nullptr
1386 con_cultivate = con_menu->addAction(_("Cultivate"));
1387 }
1389 con_irrig = con_menu->addAction(_("Irrigate"));
1390 }
1391
1392 if (pterr->transform_result != pterr && pterr->transform_result != nullptr
1394 nullptr, &for_terr)) {
1395 con_trfrm = con_menu->addAction(_("Transform"));
1396 }
1397
1398 if (next_extra_for_tile(ptile, EC_ROAD, city_owner(mcity), nullptr) != nullptr) {
1399 con_road = con_menu->addAction(_("Road"));
1400 }
1401
1402 if (prev_extra_in_tile(ptile, ERM_CLEAN,
1403 city_owner(mcity), nullptr) != nullptr) {
1404 con_clean = con_menu->addAction(_("Clean"));
1405 }
1406
1407 if (ptask != nullptr) {
1408 con_clear = con_menu->addAction(_("Clear"));
1409 }
1410
1411 con_menu->setAttribute(Qt::WA_DeleteOnClose);
1412 connect(con_menu, &QMenu::triggered,
1414 bool target = false;
1415 struct packet_worker_task task;
1416
1417 if (!act) {
1418 return;
1419 }
1420
1421 task.city_id = city_id;
1422
1423 if (act == con_road) {
1425 target = TRUE;
1426 } else if (act == con_mine) {
1427 task.activity = ACTIVITY_MINE;
1428 target = TRUE;
1429 } else if (act == con_plant) {
1430 task.activity = ACTIVITY_PLANT;
1431 } else if (act == con_irrig) {
1433 target = TRUE;
1434 } else if (act == con_cultivate) {
1436 } else if (act == con_trfrm) {
1438 } else if (act == con_clean) {
1439 task.activity = ACTIVITY_CLEAN;
1440 target = TRUE;
1441 } else if (act == con_clear) {
1442 task.activity = ACTIVITY_LAST;
1443 } else {
1444 // Closed dialog without selecting any activity entry.
1445 return;
1446 }
1447
1448 task.want = 100;
1449
1450 if (target) {
1451 enum extra_cause cause = activity_to_extra_cause(task.activity);
1453 struct extra_type *tgt;
1454
1455 if (cause != EC_NONE) {
1456 tgt = next_extra_for_tile(ptile, cause, city_owner(mcity), nullptr);
1457 } else if (rmcause != ERM_NONE) {
1458 tgt = prev_extra_in_tile(ptile, rmcause, city_owner(mcity), nullptr);
1459 } else {
1460 tgt = nullptr;
1461 }
1462
1463 if (tgt != nullptr) {
1464 task.tgt = extra_index(tgt);
1465 } else {
1466 task.tgt = -1;
1467 }
1468 } else {
1469 task.tgt = -1;
1470 }
1471
1472 task.tile_id = ptile->index;
1474 });
1475
1476 con_menu->popup(mapToGlobal(point));
1477}
1478
1479/************************************************************************/
1483{
1484 QFont f = QApplication::font();
1485 QFont *small_font;
1486 QFontMetrics fm(f);
1492 QHeaderView *header;
1493 QLabel *lab2, *label, *ql, *some_label;
1494 QPushButton *qpush2;
1496 QSizePolicy size_expanding_policy(QSizePolicy::Expanding,
1497 QSizePolicy::Expanding);
1498 QSlider *slider;
1499 QStringList info_list, str_list;
1504 int list_size;
1505 int h = 2 * fm.height() + 2;
1506
1509 zoom = 1.0;
1510
1512 central_splitter->setOpaqueResize(false);
1514 central_left_splitter->setOpaqueResize(false);
1516 prod_unit_splitter->setOpaqueResize(false);
1517
1518 setMouseTracking(true);
1519 selected_row_p = -1;
1520 dlgcity = nullptr;
1521 lcity_name = new QPushButton(this);
1522 lcity_name->setToolTip(_("Click to change city name"));
1523
1525 single_page_layout->setContentsMargins(0, 0 ,0 ,0);
1526 size_expanding_policy.setHorizontalStretch(0);
1527 size_expanding_policy.setVerticalStretch(0);
1529 current_building = 0;
1530
1531 // Map view
1532 map_box = new QGroupBox(this);
1533
1534 // City information widget texts about surpluses and so on
1535 info_wdg = new QWidget(this);
1536
1537 // Fill info_wdg with labels
1539
1540 info_wdg->setFont(*small_font);
1541 info_grid_layout->setSpacing(0);
1542 info_grid_layout->setContentsMargins(0, 0, 0, 0);
1543
1544
1545 for (enum city_info info_field = city_info_begin();
1548
1549 ql = new QLabel(_(city_info_name(info_field)), info_wdg);
1550 ql->setFont(*small_font);
1551 ql->setProperty(fonts::notify_label, "true");
1552 info_grid_layout->addWidget(ql, info_field, 0);
1553 qlt[info_field] = new QLabel(info_wdg);
1554 qlt[info_field]->setFont(*small_font);
1555 qlt[info_field]->setProperty(fonts::notify_label, "true");
1556 info_grid_layout->addWidget(qlt[info_field], info_field, 1);
1557 info_grid_layout->setRowStretch(info_field, 0);
1558 }
1559
1560 info_wdg->setLayout(info_grid_layout);
1561
1562 // Buy button
1563 buy_button = new QPushButton();
1564 buy_button->setIcon(fc_icons::instance()->get_icon("help-donate"));
1565 connect(buy_button, &QAbstractButton::clicked, this, &city_dialog::buy);
1566
1567 connect(lcity_name, &QAbstractButton::clicked, this, &city_dialog::city_rename);
1569 citizen_pixmap = nullptr;
1570 view = new city_map(this);
1571
1572 zoom_vbox = new QVBoxLayout();
1573 zoom_in_button = new QPushButton();
1574 zoom_in_button->setIcon(fc_icons::instance()->get_icon("plus"));
1575 zoom_in_button->setIconSize(QSize(16, 16));
1576 zoom_in_button->setFixedSize(QSize(20, 20));
1577 zoom_in_button->setToolTip(_("Zoom in"));
1578 connect(zoom_in_button, &QAbstractButton::clicked, this, &city_dialog::zoom_in);
1579 zoom_out_button = new QPushButton();
1580 zoom_out_button->setIcon(fc_icons::instance()->get_icon("minus"));
1581 zoom_out_button->setIconSize(QSize(16, 16));
1582 zoom_out_button->setFixedSize(QSize(20, 20));
1583 zoom_out_button->setToolTip(_("Zoom out"));
1584 connect(zoom_out_button, &QAbstractButton::clicked, this, &city_dialog::zoom_out);
1585 zoom_vbox->addWidget(zoom_in_button);
1586 zoom_vbox->addWidget(zoom_out_button);
1587
1588 // City map group box
1591 hbox_layout->addStretch(100);
1592 hbox_layout->addWidget(view);
1593 hbox_layout->addStretch(100);
1594 hbox_layout->addLayout(zoom_vbox);
1595 vbox_layout->addLayout(hbox_layout);
1596 vbox_layout->addWidget(lcity_name);
1597 map_box->setLayout(vbox_layout);
1598 map_box->setTitle(_("City map"));
1599
1600 // Current/supported units/improvements widgets
1601 supp_units = new QLabel();
1602 curr_units = new QLabel();
1603 curr_impr = new QLabel();
1604 curr_units->setAlignment(Qt::AlignLeft);
1605 curr_impr->setAlignment(Qt::AlignLeft);
1606 supp_units->setAlignment(Qt::AlignLeft);
1607 supported_units = new unit_info(true);
1608 scroll = new QScrollArea;
1609 scroll->setWidgetResizable(true);
1610 scroll->setMaximumHeight(tileset_unit_with_upkeep_height(get_tileset()) + 6
1611 + scroll->horizontalScrollBar()->height());
1612 scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1613 scroll->setWidget(supported_units);
1614 current_units = new unit_info(false);
1615 scroll2 = new QScrollArea;
1616 scroll2->setWidgetResizable(true);
1617 scroll2->setMaximumHeight(tileset_unit_height(get_tileset()) + 6
1618 + scroll2->horizontalScrollBar()->height());
1619 scroll2->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1620 scroll2->setWidget(current_units);
1621 scroll_height = scroll2->horizontalScrollBar()->height();
1622 city_buildings = new impr_info(this);
1623 scroll3 = new QScrollArea;
1624 scroll3->setWidgetResizable(true);
1625 scroll3->setMaximumHeight(tileset_unit_height(tileset) + 6
1626 + scroll3->horizontalScrollBar()->height());
1627 scroll3->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1628 scroll3->setWidget(city_buildings);
1629 scroll->setProperty("city_scroll", true);
1630 scroll2->setProperty("city_scroll", true);
1631 scroll3->setProperty("city_scroll", true);
1632
1635 right_layout = new QVBoxLayout();
1637 units_layout = new QVBoxLayout();
1638 left_layout = new QVBoxLayout();
1639
1640 /* Checkboxes to show units/wonders/improvements
1641 * on production list */
1644 show_buildings->setToolTip(_("Show buildings"));
1645 show_buildings->setChecked(true);
1646 label = new QLabel();
1647 label->setPixmap(*fc_icons::instance()->get_pixmap("building"));
1648 label->setToolTip(_("Show buildings"));
1649 prod_option_layout->addWidget(show_buildings, Qt::AlignLeft);
1650 prod_option_layout->addWidget(label, Qt::AlignLeft);
1651 prod_option_layout->addStretch(100);
1652 label = new QLabel();
1653 label->setPixmap(*fc_icons::instance()->get_pixmap("cunits"));
1654 label->setToolTip(_("Show units"));
1655 show_units = new QCheckBox;
1656 show_units->setToolTip(_("Show units"));
1657 show_units->setChecked(true);
1658 prod_option_layout->addWidget(show_units, Qt::AlignHCenter);
1659 prod_option_layout->addWidget(label, Qt::AlignHCenter);
1660 prod_option_layout->addStretch(100);
1661 label = new QLabel();
1662 label->setPixmap(*fc_icons::instance()->get_pixmap("wonder"));
1663 label->setToolTip(_("Show wonders"));
1664 show_wonders = new QCheckBox;
1665 show_wonders->setToolTip(_("Show wonders"));
1666 show_wonders->setChecked(true);
1667 prod_option_layout->addWidget(show_wonders);
1668 prod_option_layout->addWidget(label);
1669 prod_option_layout->addStretch(100);
1670 label = new QLabel();
1671 label->setPixmap(*fc_icons::instance()->get_pixmap("future"));
1672 label->setToolTip(_("Show future targets"));
1674 future_targets->setToolTip(_("Show future targets"));
1675 future_targets->setChecked(false);
1677 prod_option_layout->addWidget(label, Qt::AlignRight);
1678 prod_options = new QGroupBox(this);
1679 prod_options->setLayout(prod_option_layout);
1680 prod_options->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
1681
1682 // Prev/next and close buttons
1683 button = new QPushButton;
1684 button->setIcon(fc_icons::instance()->get_icon("city-close"));
1685 button->setIconSize(QSize(56, 56));
1686 button->setToolTip(_("Close city dialog"));
1687 connect(button, &QAbstractButton::clicked, this, &QWidget::hide);
1688
1689 next_city_but = new QPushButton();
1690 next_city_but->setIcon(fc_icons::instance()->get_icon("city-right"));
1691 next_city_but->setIconSize(QSize(56, 56));
1692 next_city_but->setToolTip(_("Show next city"));
1693 connect(next_city_but, &QAbstractButton::clicked, this, &city_dialog::next_city);
1694
1695 prev_city_but = new QPushButton();
1696 connect(prev_city_but, &QAbstractButton::clicked, this, &city_dialog::prev_city);
1697 prev_city_but->setIcon(fc_icons::instance()->get_icon("city-left"));
1698 prev_city_but->setIconSize(QSize(56, 56));
1699 prev_city_but->setToolTip(_("Show previous city"));
1700
1701 happiness_button = new QPushButton();
1702 happiness_button->setIcon(fc_icons::instance()->get_icon("smiley"));
1703 happiness_button->setIconSize(QSize(56,28));
1704 connect(happiness_button, &QAbstractButton::clicked, this,
1706
1707 settings_button = new QPushButton(_("Settings"));
1708 connect(settings_button, &QAbstractButton::clicked, this,
1710 settings_button->setToolTip(_("Counters, worklist, and options menu"));
1711
1712 button->setFixedSize(64, 64);
1713 prev_city_but->setFixedSize(64, 64);
1714 next_city_but->setFixedSize(64, 64);
1715 happiness_button->setFixedSize(64, 32);
1716 settings_button->setFixedSize(64, 32);
1718 vbox_layout->addWidget(prev_city_but);
1719 vbox_layout->addWidget(next_city_but);
1720 vbox_layout->addWidget(button);
1721 vbox_layout->addWidget(happiness_button, Qt::AlignHCenter);
1722 vbox_layout->addWidget(settings_button, Qt::AlignHCenter);
1723
1724 update_tabs();
1726
1727 hbox_layout->addLayout(vbox_layout, Qt::AlignLeft);
1728 hbox_layout->addWidget(info_wdg, Qt::AlignLeft);
1729 hbox_layout->addWidget(map_box, Qt::AlignCenter);
1730
1731 // Layout with city view and buttons
1732 lefttop_layout->addWidget(citizens_label, Qt::AlignHCenter);
1733 lefttop_layout->addStretch(0);
1734 lefttop_layout->addLayout(hbox_layout);
1735 lefttop_layout->addStretch(50);
1736
1737 // Layout for units/buildings
1738 curr_unit_wdg = new QWidget();
1739 supp_unit_wdg = new QWidget();
1740 curr_impr_wdg = new QWidget();
1741 v_layout = new QVBoxLayout;
1742 v_layout->addWidget(curr_impr);
1743 v_layout->addWidget(scroll3);
1744 v_layout->setContentsMargins(0 , 0 , 0, 0);
1745 v_layout->setSpacing(0);
1746 curr_impr_wdg->setLayout(v_layout);
1747 v_layout = new QVBoxLayout;
1748 v_layout->addWidget(curr_units);
1749 v_layout->addWidget(scroll2);
1750 v_layout->setContentsMargins(0 , 0 , 0, 0);
1751 v_layout->setSpacing(0);
1752 curr_unit_wdg->setLayout(v_layout);
1753 v_layout = new QVBoxLayout;
1754 v_layout->addWidget(supp_units);
1755 v_layout->addWidget(scroll);
1756 v_layout->setContentsMargins(0 , 0 , 0, 0);
1757 v_layout->setSpacing(0);
1758 supp_unit_wdg->setLayout(v_layout);
1759
1760 units_layout->addWidget(curr_unit_wdg);
1761 units_layout->addWidget(supp_unit_wdg);
1762 units_layout->addWidget(curr_impr_wdg);
1763 units_layout->setSpacing(0);
1764 units_layout->setContentsMargins(0 , 0 , 0, 0);
1765
1766 vbox = new QVBoxLayout;
1768 qgbprod = new QGroupBox;
1769 group_box = new QGroupBox(_("Worklist Option"));
1771 work_next_but = new QPushButton(fc_icons::instance()->get_icon(
1772 "go-down"), "");
1773 work_prev_but = new QPushButton(fc_icons::instance()->get_icon(
1774 "go-up"), "");
1775 work_add_but = new QPushButton(fc_icons::instance()->get_icon(
1776 "list-add"), "");
1777 work_rem_but = new QPushButton(style()->standardIcon(
1778 QStyle::SP_DialogDiscardButton), "");
1779 work_but_layout->addWidget(work_add_but);
1780 work_but_layout->addWidget(work_next_but);
1781 work_but_layout->addWidget(work_prev_but);
1782 work_but_layout->addWidget(work_rem_but);
1784 production_combo_p->setToolTip(_("Click to change current production"));
1785 p_table_p = new QTableWidget;
1786
1787 r1 = new QRadioButton(_("Change"));
1788 r2 = new QRadioButton(_("Insert Before"));
1789 r3 = new QRadioButton(_("Insert After"));
1790 r4 = new QRadioButton(_("Add Last"));
1791 r4->setChecked(true);
1792 group_box->setLayout(vbox);
1793
1794
1795 p_table_p->setColumnCount(3);
1796 p_table_p->setProperty("showGrid", "false");
1797 p_table_p->setProperty("selectionBehavior", "SelectRows");
1798 p_table_p->setEditTriggers(QAbstractItemView::NoEditTriggers);
1799 p_table_p->verticalHeader()->setVisible(false);
1800 p_table_p->horizontalHeader()->setVisible(false);
1801 p_table_p->setSelectionMode(QAbstractItemView::SingleSelection);
1802 production_combo_p->setFixedHeight(h);
1803 p_table_p->setMinimumWidth(200);
1804 p_table_p->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
1805 p_table_p->setContextMenuPolicy(Qt::CustomContextMenu);
1806 p_table_p->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
1807 header = p_table_p->horizontalHeader();
1808 header->setStretchLastSection(true);
1809
1810 qgbprod->setTitle(_("Worklist"));
1811 vbox_layout->setSpacing(0);
1812 vbox_layout->addWidget(prod_options);
1813 vbox_layout->addWidget(buy_button);
1814 vbox_layout->addWidget(production_combo_p);
1815 vbox_layout->addLayout(work_but_layout);
1816 vbox_layout->addWidget(p_table_p);
1817 qgbprod->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1818 qgbprod->setLayout(vbox_layout);
1819
1820 worklist_layout->setSpacing(0);
1821 worklist_layout->addWidget(qgbprod);
1822 connect(p_table_p,
1823 &QWidget::customContextMenuRequested, this,
1826 connect(work_add_but, &QAbstractButton::clicked, this, &city_dialog::show_targets_worklist);
1827 connect(work_prev_but, &QAbstractButton::clicked, this, &city_dialog::worklist_up);
1828 connect(work_next_but, &QAbstractButton::clicked, this, &city_dialog::worklist_down);
1829 connect(work_rem_but, &QAbstractButton::clicked, this, &city_dialog::worklist_del);
1830 connect(p_table_p,
1831 &QTableWidget::itemDoubleClicked,
1833 connect(p_table_p->selectionModel(),
1835 const QItemSelection &)),
1837 const QItemSelection &)));
1838 happiness_group = new QGroupBox(_("Happiness"));
1839 gridl = new QGridLayout;
1840
1841 nationality_table = new QTableWidget;
1842 nationality_table->setColumnCount(3);
1843 nationality_table->setProperty("showGrid", "false");
1844 nationality_table->setProperty("selectionBehavior", "SelectRows");
1845 nationality_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
1846 nationality_table->verticalHeader()->setVisible(false);
1847 nationality_table->horizontalHeader()->setStretchLastSection(true);
1848
1849 info_list.clear();
1850 info_list << _("Cities:") << _("Luxuries:") << _("Buildings:")
1851 << _("Nationality:") << _("Units:") << _("Wonders:");
1852
1853 for (int i = 0; i < info_list.count(); i++) {
1854 lab_table[i] = new city_label(1 + i, this);
1855 gridl->addWidget(lab_table[i], i, 1, 1, 1);
1856 lab2 = new QLabel(this);
1857 lab2->setFont(*small_font);
1858 lab2->setProperty(fonts::notify_label, "true");
1859 lab2->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
1860 lab2->setText(info_list.at(i));
1861 gridl->addWidget(lab2, i, 0, 1, 1);
1862 }
1863
1864 gridl->setSpacing(0);
1865 happiness_group->setLayout(gridl);
1866
1867
1871 happiness_layout->setStretch(0, 10);
1872 happiness_widget = new QWidget();
1874 qgbox = new QGroupBox(_("Presets:"));
1875 qsliderbox = new QGroupBox(_("Governor settings"));
1876 result_box = new QGroupBox(_("Results:"));
1877 hbox = new QHBoxLayout;
1878 gridl = new QGridLayout;
1880
1881 counters_widget = new QWidget();
1883 counters_widget->setLayout(counters_layout);
1884
1885 qpush2
1886 = new QPushButton(style()->standardIcon(QStyle::SP_DialogSaveButton),
1887 _("Save"));
1888 connect(qpush2, &QAbstractButton::pressed, this, &city_dialog::save_cma);
1889
1890 cma_info_text = new QLabel;
1891 cma_info_text->setFont(*small_font);
1892 cma_info_text->setAlignment(Qt::AlignCenter);
1893 cma_table = new QTableWidget;
1894 cma_table->setColumnCount(1);
1895 cma_table->setProperty("showGrid", "false");
1896 cma_table->setProperty("selectionBehavior", "SelectRows");
1897 cma_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
1898 cma_table->setSelectionMode(QAbstractItemView::SingleSelection);
1899 cma_table->setContextMenuPolicy(Qt::CustomContextMenu);
1900 cma_table->verticalHeader()->setVisible(false);
1901 cma_table->horizontalHeader()->setVisible(false);
1902 cma_table->horizontalHeader()->setSectionResizeMode(
1903 QHeaderView::Stretch);
1904
1905 connect(cma_table->selectionModel(),
1907 const QItemSelection &)),
1909 const QItemSelection &)));
1910 connect(cma_table,
1911 &QWidget::customContextMenuRequested, this,
1913 connect(cma_table, &QTableWidget::cellDoubleClicked, this,
1915 gridl->addWidget(cma_table, 0, 0, 1, 2);
1916 qgbox->setLayout(gridl);
1917 hbox->addWidget(cma_info_text);
1918 result_box->setLayout(hbox);
1919 str_list << _("Food") << _("Shield") << _("Trade") << _("Gold")
1920 << _("Luxury") << _("Science") << _("Celebrate")
1921 << _("Maximize growth");
1922 some_label = new QLabel(_("Minimal Surplus"));
1924 some_label->setAlignment(Qt::AlignRight);
1925 slider_grid->addWidget(some_label, 0, 0, 1, 3);
1926 some_label = new QLabel(_("Priority"));
1928 some_label->setAlignment(Qt::AlignCenter);
1929 slider_grid->addWidget(some_label, 0, 3, 1, 2);
1930
1931 list_size = str_list.count();
1932 for (int i = 0; i < list_size; i++) {
1933 some_label = new QLabel(str_list.at(i));
1934 slider_grid->addWidget(some_label, i + 1, 0, 1, 1);
1935 some_label = new QLabel("0");
1936 some_label->setMinimumWidth(25);
1937
1938 if (i < list_size - 2) {
1939 slider = new QSlider(Qt::Horizontal);
1940 slider->setPageStep(1);
1941 slider->setFocusPolicy(Qt::TabFocus);
1942 slider_tab[2 * i] = slider;
1943 slider->setRange(-20, 20);
1944 slider->setSingleStep(1);
1945 slider_grid->addWidget(some_label, i + 1, 1, 1, 1);
1946 slider_grid->addWidget(slider, i + 1, 2, 1, 1);
1947 slider->setProperty("FC", QVariant::fromValue((void *)some_label));
1948
1949 connect(slider, &QAbstractSlider::valueChanged, this, &city_dialog::cma_slider);
1950 } else if (i == list_size - 2) {
1952 slider_grid->addWidget(cma_celeb_checkbox, i + 1, 2 , 1 , 1);
1953#ifdef FC_QT6X_MODE
1954 // Qt-6.7
1955 connect(cma_celeb_checkbox,
1956 &QCheckBox::checkStateChanged, this, &city_dialog::cma_toggle_changed);
1957#else // FC_QT6X_MODE
1958 connect(cma_celeb_checkbox,
1959 &QCheckBox::stateChanged, this, &city_dialog::cma_toggle_changed_depr);
1960#endif // FC_QT6X_MODE
1961 } else {
1962 fc_assert(i == list_size - 1);
1963
1965 slider_grid->addWidget(cma_max_growth, i + 1, 2 , 1 , 1);
1966#ifdef FC_QT6X_MODE
1967 // Qt-6.7
1968 connect(cma_max_growth,
1969 &QCheckBox::checkStateChanged, this, &city_dialog::cma_toggle_changed);
1970#else // FC_QT6X_MODE
1971 connect(cma_max_growth,
1972 &QCheckBox::stateChanged, this, &city_dialog::cma_toggle_changed_depr);
1973#endif // FC_QT6X_MODE
1974 }
1975
1976 if (i <= list_size - 2) {
1977 some_label = new QLabel("0");
1978 some_label->setMinimumWidth(25);
1979 slider = new QSlider(Qt::Horizontal);
1980 slider->setFocusPolicy(Qt::TabFocus);
1981 slider->setRange(0, 25);
1982 slider_tab[2 * i + 1] = slider;
1983 slider->setProperty("FC", QVariant::fromValue((void *)some_label));
1984 slider_grid->addWidget(some_label, i + 1, 3, 1, 1);
1985 slider_grid->addWidget(slider, i + 1, 4, 1, 1);
1986 connect(slider, &QAbstractSlider::valueChanged, this, &city_dialog::cma_slider);
1987 }
1988 }
1989
1990 cma_enable_but = new QPushButton();
1991 cma_enable_but->setFocusPolicy(Qt::TabFocus);
1992 connect(cma_enable_but, &QAbstractButton::pressed, this, &city_dialog::cma_enable);
1993 slider_grid->addWidget(cma_enable_but, O_LAST + 4, 0, 1, 3);
1994 slider_grid->addWidget(qpush2, O_LAST + 4, 3, 1, 2);
1995
1996 qsliderbox->setLayout(slider_grid);
1997 cma_result = new QLabel;
1998 cma_result_pix = new QLabel;
1999
2000 hbox = new QHBoxLayout;
2001 QScrollArea *govA = new QScrollArea();
2002 hbox->addWidget(cma_result_pix);
2003 hbox->addWidget(cma_result);
2004 hbox->addStretch(10);
2005 govA->setWidget(qsliderbox);
2006 govA->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
2007 right_layout->addWidget(qgbox);
2008 right_layout->addLayout(hbox);
2009 right_layout->addWidget(govA);
2010
2011 split_widget1 = new QWidget;
2012 split_widget1->setLayout(worklist_layout);
2013 split_widget2 = new QWidget;
2014 split_widget2->setLayout(units_layout);
2017 prod_unit_splitter->setStretchFactor(0, 3);
2018 prod_unit_splitter->setStretchFactor(1, 97);
2019 prod_unit_splitter->setOrientation(Qt::Horizontal);
2021 top_widget = new QWidget;
2022 top_widget->setLayout(lefttop_layout);
2023 top_widget->setSizePolicy(QSizePolicy::Minimum,
2024 QSizePolicy::Minimum);
2025 scroll_info = new QScrollArea();
2026 scroll_info->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
2027 scroll_unit = new QScrollArea();
2028 scroll_info->setWidget(top_widget);
2029 scroll_info->setWidgetResizable(true);
2030 prod_happ_widget = new QWidget;
2031 prod_happ_widget->setLayout(leftbot_layout);
2032 prod_happ_widget->setSizePolicy(QSizePolicy::MinimumExpanding,
2033 QSizePolicy::MinimumExpanding);
2034 scroll_unit->setWidget(prod_happ_widget);
2035 scroll_unit->setWidgetResizable(true);
2038 central_left_splitter->setStretchFactor(0, 40);
2039 central_left_splitter->setStretchFactor(1, 60);
2040 central_left_splitter->setOrientation(Qt::Vertical);
2042
2043 split_widget1 = new QWidget(this);
2044 split_widget2 = new QWidget(this);
2045 split_widget1->setLayout(left_layout);
2046 split_widget2->setLayout(right_layout);
2047 central_splitter->addWidget(split_widget1);
2048 central_splitter->addWidget(split_widget2);
2049 central_splitter->setStretchFactor(0, 99);
2050 central_splitter->setStretchFactor(1, 1);
2051 central_splitter->setOrientation(Qt::Horizontal);
2053 setSizeGripEnabled(true);
2055
2056 installEventFilter(this);
2057
2058 ::city_dlg_created = true;
2059
2061}
2062
2063/************************************************************************/
2067{
2068
2069 cid cprod;
2070 int i, pos;
2071 int item, targets_used;
2073 QString str;
2074 struct item items[MAX_NUM_PRODUCTION_TARGETS];
2075 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
2076 struct universal univ;
2077
2078 pos = 0;
2081 name_and_sort_items(targets, targets_used, items, false, dlgcity);
2082
2083 for (item = 0; item < targets_used; item++) {
2084 if (can_city_build_now(&(wld.map), dlgcity, &items[item].item)) {
2085 prod_list << cid_encode(items[item].item);
2086 }
2087 }
2088
2089 for (i = 0; i < prod_list.size(); i++) {
2090 if (prod_list.at(i) == cprod) {
2091 if (next) {
2092 pos = i + 1;
2093 } else {
2094 pos = i - 1;
2095 }
2096 }
2097 }
2098 if (pos == prod_list.size()) {
2099 pos = 0;
2100 }
2101 if (pos == - 1) {
2102 pos = prod_list.size() - 1;
2103 }
2104 univ = cid_decode(static_cast<cid>(prod_list.at(pos)));
2106}
2107
2108/************************************************************************/
2112{
2113 if (current_tab == happiness) {
2114 happiness_button->setIcon(fc_icons::instance()->get_icon("city-switch"));
2115 happiness_button->setToolTip(_("Show city production"));
2116 } else {
2117 happiness_button->setIcon(fc_icons::instance()->get_icon("smiley"));
2118 happiness_button->setToolTip(_("Show happiness information"));
2119 }
2120}
2121
2122/************************************************************************/
2126{
2128 setUpdatesEnabled(false);
2129
2130
2131 if (current_tab != happiness) {
2132 leftbot_layout->replaceWidget(active_tab,
2134 Qt::FindDirectChildrenOnly);
2135 active_tab->hide();
2136 happiness_widget->show();
2137 happiness_widget->updateGeometry();
2139 } else {
2140 /* We do not change prod_unit_splitter to current_tab,
2141 * because happiness is active tab and clicked -
2142 * switching to default */
2143 leftbot_layout->replaceWidget(happiness_widget,
2145 Qt::FindDirectChildrenOnly);
2146 prod_unit_splitter->show();
2147 prod_unit_splitter->updateGeometry();
2148 happiness_widget->hide();
2150 }
2151
2152 setUpdatesEnabled(true);
2153 update();
2154 update_tabs();
2155}
2156
2157/************************************************************************/
2161{
2162 setUpdatesEnabled(false);
2163
2164 leftbot_layout->replaceWidget(counters_widget,
2166 Qt::FindDirectChildrenOnly);
2167 prod_unit_splitter->show();
2168 prod_unit_splitter->updateGeometry();
2169 counters_widget->hide();
2171
2172 setUpdatesEnabled(true);
2173 update();
2174 update_tabs();
2175}
2176
2177/************************************************************************/
2181{
2183
2184 if (current_tab != counters) {
2185 setUpdatesEnabled(false);
2186
2187 leftbot_layout->replaceWidget(active_tab,
2189 Qt::FindDirectChildrenOnly);
2190 active_tab->hide();
2191 counters_widget->show();
2192 counters_widget->updateGeometry();
2194
2195 setUpdatesEnabled(true);
2196 update();
2197 update_tabs();
2198 }
2199}
2200
2201/************************************************************************/
2205{
2206 struct player *pplayer = client_player();
2207
2208 if (pplayer == nullptr
2209 || city_owner(dlgcity) != pplayer) {
2210 prev_city_but->setDisabled(true);
2211 next_city_but->setDisabled(true);
2212 buy_button->setDisabled(true);
2213 cma_enable_but->setDisabled(true);
2214 production_combo_p->setDisabled(true);
2215 current_units->setDisabled(true);
2216 supported_units->setDisabled(true);
2217 view->setDisabled(true);
2218 } else {
2219 prev_city_but->setEnabled(true);
2220 next_city_but->setEnabled(true);
2221 buy_button->setEnabled(true);
2222 cma_enable_but->setEnabled(true);
2223 production_combo_p->setEnabled(true);
2224 current_units->setEnabled(true);
2225 supported_units->setEnabled(true);
2226 view->setEnabled(true);
2227 }
2228
2230 cma_enable_but->setEnabled(true);
2231 } else {
2232 cma_enable_but->setDisabled(true);
2233 }
2234
2236}
2237
2238/************************************************************************/
2242{
2243 struct player *pplayer = client_player();
2244
2245 work_next_but->setDisabled(true);
2246 work_prev_but->setDisabled(true);
2247 work_add_but->setDisabled(true);
2248 work_rem_but->setDisabled(true);
2249
2250 if (pplayer != nullptr
2251 && city_owner(dlgcity) == pplayer) {
2252 work_add_but->setEnabled(true);
2253
2254 if (selected_row_p >= 0 && selected_row_p < p_table_p->rowCount()) {
2255 work_rem_but->setEnabled(true);
2256 }
2257
2258 if (selected_row_p >= 0 && selected_row_p < p_table_p->rowCount() - 1) {
2259 work_next_but->setEnabled(true);
2260 }
2261
2262 if (selected_row_p > 0 && selected_row_p < p_table_p->rowCount()) {
2263 work_prev_but->setEnabled(true);
2264 }
2265 }
2266}
2267
2268/************************************************************************/
2272{
2273 if (citizen_pixmap) {
2274 citizen_pixmap->detach();
2275 delete citizen_pixmap;
2276 }
2277
2278 cma_table->clear();
2279 p_table_p->clear();
2280 nationality_table->clear();
2282 supported_units->clear_layout();
2283 removeEventFilter(this);
2284 ::city_dlg_created = false;
2285
2286 // Delete the one widget that currently does NOT have a parent
2287 if (current_tab == common) {
2288 delete happiness_widget;
2289 delete counters_widget;
2290 }
2291 else if (current_tab == counters) {
2292 delete happiness_widget;
2293 delete prod_unit_splitter;
2294 } else {
2295 delete counters_widget;
2296 delete prod_unit_splitter;
2297 }
2298}
2299
2300/************************************************************************/
2304{
2305 gui()->qt_settings.city_geometry = saveGeometry();
2306 gui()->qt_settings.city_splitter1 = prod_unit_splitter->saveState();
2307 gui()->qt_settings.city_splitter2 = central_left_splitter->saveState();
2308 gui()->qt_settings.city_splitter3 = central_splitter->saveState();
2309}
2310
2311/************************************************************************/
2315{
2316 if (!gui()->qt_settings.city_geometry.isNull()) {
2317 restoreGeometry(gui()->qt_settings.city_geometry);
2318 prod_unit_splitter->restoreState(gui()->qt_settings.city_splitter1);
2319 central_left_splitter->restoreState(gui()->qt_settings.city_splitter2);
2320 central_splitter->restoreState(gui()->qt_settings.city_splitter3);
2321 } else {
2322 QRect rect = QApplication::primaryScreen()->availableGeometry();
2323
2324 resize((rect.width() * 4) / 5, (rect.height() * 5) / 6);
2325 }
2326}
2327
2328/************************************************************************/
2332{
2333 gui()->qt_settings.city_geometry = saveGeometry();
2334 gui()->qt_settings.city_splitter1 = prod_unit_splitter->saveState();
2335 gui()->qt_settings.city_splitter2 = central_left_splitter->saveState();
2336 gui()->qt_settings.city_splitter3 = central_splitter->saveState();
2337}
2338
2339/************************************************************************/
2342bool city_dialog::eventFilter(QObject *obj, QEvent *event)
2343{
2344
2345 if (obj == this) {
2346 if (event->type() == QEvent::KeyPress) {
2347 }
2348
2349 if (event->type() == QEvent::ShortcutOverride) {
2350 QKeyEvent *key_event = static_cast<QKeyEvent *>(event);
2351 if (key_event->key() == Qt::Key_Right) {
2352 next_city();
2353 event->setAccepted(true);
2354 return true;
2355 }
2356 if (key_event->key() == Qt::Key_Left) {
2357 prev_city();
2358 event->setAccepted(true);
2359 return true;
2360 }
2361 if (key_event->key() == Qt::Key_Up) {
2362 change_production(true);
2363 event->setAccepted(true);
2364 return true;
2365 }
2366 if (key_event->key() == Qt::Key_Down) {
2367 change_production(false);
2368 event->setAccepted(true);
2369 return true;
2370 }
2371 }
2372 }
2373 return QObject::eventFilter(obj, event);
2374}
2375
2376/************************************************************************/
2380{
2382 const int city_id = dlgcity->id;
2383
2384 if (!can_client_issue_orders()) {
2385 return;
2386 }
2387
2388 ask = new hud_input_box(gui()->central_wdg);
2389 ask->set_text_title_definput(_("What should we rename the city to?"),
2390 _("Rename City"), city_name_get(dlgcity));
2391 ask->setAttribute(Qt::WA_DeleteOnClose);
2392 connect(ask, &hud_message_box::accepted, this, [=]() {
2393 struct city *pcity = game_city_by_number(city_id);
2395
2396 if (!pcity) {
2397 return;
2398 }
2399
2400 ask_bytes = ask->input_edit.text().toUtf8();
2401 ::city_rename(pcity, ask_bytes.data());
2402 });
2403 ask->show();
2404}
2405
2406/************************************************************************/
2410{
2411 zoom = zoom * 1.2;
2412 if (dlgcity) {
2413 view->set_pixmap(dlgcity, zoom);
2414 }
2416 left_layout->update();
2417}
2418
2419/************************************************************************/
2423{
2424 zoom = zoom / 1.2;
2425 if (dlgcity) {
2426 view->set_pixmap(dlgcity, zoom);
2427 }
2429 left_layout->update();
2430}
2431
2432/************************************************************************/
2436{
2437 hud_input_box *ask = new hud_input_box(gui()->central_wdg);
2438
2439 ask->set_text_title_definput(_("What should we name the preset?"),
2440 _("Name new preset"),
2441 _("new preset"));
2442 ask->setAttribute(Qt::WA_DeleteOnClose);
2443 connect(ask, &hud_message_box::accepted, this,
2445 struct cm_parameter param;
2446 QByteArray ask_bytes = ask->input_edit.text().toUtf8();
2447 QString text = ask_bytes.data();
2448 if (!text.isEmpty()) {
2449 param.allow_disorder = false;
2450 param.allow_specialists = true;
2451 param.require_happy = cma_celeb_checkbox->isChecked();
2452 param.max_growth = cma_max_growth->isChecked();
2453 param.happy_factor = slider_tab[2 * O_LAST + 1]->value();
2454
2455 for (int i = O_FOOD; i < O_LAST; i++) {
2456 param.minimal_surplus[i] = slider_tab[2 * i]->value();
2457 param.factor[i] = slider_tab[2 * i + 1]->value();
2458 }
2459
2460 ask_bytes = text.toUtf8();
2461 cmafec_preset_add(ask_bytes.data(), &param);
2463 }
2464 });
2465 ask->show();
2466}
2467
2468/************************************************************************/
2472{
2473 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2475
2476 return;
2477 }
2478
2479 cma_changed();
2481}
2482
2483/************************************************************************/
2487{
2488 struct cm_parameter param;
2489
2490 param.allow_disorder = false;
2491 param.allow_specialists = true;
2492 param.require_happy = cma_celeb_checkbox->isChecked();
2493 param.max_growth = cma_max_growth->isChecked();
2494 param.happy_factor = slider_tab[2 * O_LAST + 1]->value();
2495
2496 for (int i = O_FOOD; i < O_LAST; i++) {
2497 param.minimal_surplus[i] = slider_tab[2 * i]->value();
2498 param.factor[i] = slider_tab[2 * i + 1]->value();
2499 }
2500
2502}
2503
2504/************************************************************************/
2508{
2509 const struct cm_parameter *param;
2510
2511 if (!can_client_issue_orders()) {
2512 return;
2513 }
2515 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2517 }
2518
2521}
2522
2523/************************************************************************/
2527 const QItemSelection &ds)
2528{
2529 const struct cm_parameter *param;
2530 QModelIndex index;
2531 QModelIndexList indexes = sl.indexes();
2532
2533 if (indexes.isEmpty() || cma_table->signalsBlocked()) {
2534 return;
2535 }
2536
2537 index = indexes.at(0);
2538 int ind = index.row();
2539
2540 if (cma_table->currentRow() == -1 || cmafec_preset_num() == 0) {
2541 return;
2542 }
2543
2546
2547 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2550 }
2551}
2552
2553/************************************************************************/
2557{
2558 struct cm_parameter param;
2559 const struct cm_parameter *cparam;
2560 int output;
2561 QVariant qvar;
2562 QLabel *label;
2563
2564 if (!cma_is_city_under_agent(dlgcity, &param)) {
2565 if (cma_table->currentRow() == -1 || cmafec_preset_num() == 0) {
2566 return;
2567 }
2569 cm_copy_parameter(&param, cparam);
2570 }
2571
2572 for (output = O_FOOD; output < 2 * O_LAST; output++) {
2573 slider_tab[output]->blockSignals(true);
2574 }
2575
2576 for (output = O_FOOD; output < O_LAST; output++) {
2577 qvar = slider_tab[2 * output + 1]->property("FC");
2578 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2579 label->setText(QString::number(param.factor[output]));
2580 slider_tab[2 * output + 1]->setValue(param.factor[output]);
2581 qvar = slider_tab[2 * output]->property("FC");
2582 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2583 label->setText(QString::number(param.minimal_surplus[output]));
2584 slider_tab[2 * output]->setValue(param.minimal_surplus[output]);
2585 }
2586
2587 slider_tab[2 * O_LAST + 1]->blockSignals(true);
2588 qvar = slider_tab[2 * O_LAST + 1]->property("FC");
2589 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2590 label->setText(QString::number(param.happy_factor));
2591 slider_tab[2 * O_LAST + 1]->setValue(param.happy_factor);
2592 slider_tab[2 * O_LAST + 1]->blockSignals(false);
2593 cma_celeb_checkbox->blockSignals(true);
2594 cma_celeb_checkbox->setChecked(param.require_happy);
2595 cma_celeb_checkbox->blockSignals(false);
2596 cma_max_growth->blockSignals(true);
2597 cma_max_growth->setChecked(param.max_growth);
2598 cma_max_growth->blockSignals(false);
2599
2600 for (output = O_FOOD; output < 2 * O_LAST; output++) {
2601 slider_tab[output]->blockSignals(false);
2602 }
2603}
2604
2605/************************************************************************/
2609{
2610 QString s;
2612 struct cm_parameter param;
2613 QPixmap pix;
2614 int i;
2615
2616 cma_table->clear();
2617 cma_table->setRowCount(0);
2618
2619 for (i = 0; i < cmafec_preset_num(); i++) {
2620 item = new QTableWidgetItem;
2621 item->setText(cmafec_preset_get_descr(i));
2622 cma_table->insertRow(i);
2623 cma_table->setItem(i, 0, item);
2624 }
2625
2626 if (cmafec_preset_num() == 0) {
2627 cma_table->insertRow(0);
2628 item = new QTableWidgetItem;
2629 item->setText(_("No governor defined"));
2630 cma_table->setItem(0, 0, item);
2631 }
2632
2633 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2634 view->update();
2636 pix = style()->standardPixmap(QStyle::SP_DialogApplyButton);
2637 pix = pix.scaled(2 * pix.width(), 2 * pix.height(),
2638 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
2639 cma_result_pix->setPixmap(pix);
2640 cma_result_pix->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
2641 // TRANS: %1 is custom string chosen by player
2642 cma_result->setText(QString(_("<h3>Governor Enabled<br>(%1)</h3>"))
2643 .arg(s.toHtmlEscaped()));
2644 cma_result->setAlignment(Qt::AlignCenter);
2645 } else {
2646 pix = style()->standardPixmap(QStyle::SP_DialogCancelButton);
2647 pix = pix.scaled(1.6 * pix.width(), 1.6 * pix.height(),
2648 Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
2649 cma_result_pix->setPixmap(pix);
2650 cma_result_pix->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
2651 cma_result->setText(QString(_("<h3>Governor Disabled</h3>")));
2652 cma_result->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
2653 }
2654
2655 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2658 cm_parameter *const >(&param));
2659 if (i >= 0 && i < cma_table->rowCount()) {
2660 cma_table->blockSignals(true);
2661 cma_table->setCurrentCell(i, 0);
2662 cma_table->blockSignals(false);
2663 }
2664
2665 cma_enable_but->setText(_("Disable"));
2666 } else {
2667 cma_enable_but->setText(_("Enable"));
2668 }
2670}
2671
2672/************************************************************************/
2676{
2677 int i;
2679
2680 i = cma_table->currentRow();
2681
2682 if (i == -1 || cmafec_preset_num() == 0) {
2683 return;
2684 }
2685
2687 ask->set_text_title(_("Remove this preset?"), cmafec_preset_get_descr(i));
2688 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
2689 ask->setDefaultButton(QMessageBox::Cancel);
2690 ask->setAttribute(Qt::WA_DeleteOnClose);
2691 connect(ask, &hud_message_box::accepted, this,
2695 });
2696 ask->show();
2697}
2698
2699/************************************************************************/
2702void city_dialog::cma_toggle_changed(Qt::CheckState state)
2703{
2704 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2705 cma_changed();
2707 }
2708}
2709
2710/************************************************************************/
2715{
2716 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2717 cma_changed();
2719 }
2720}
2721
2722/************************************************************************/
2726{
2727 QVariant qvar;
2728 QSlider *slider;
2729 QLabel *label;
2730
2732 qvar = slider->property("FC");
2733
2734 if (qvar.isNull() || !qvar.isValid()) {
2735 return;
2736 }
2737
2738 label = reinterpret_cast<QLabel *>(qvar.value<void *>());
2739 label->setText(QString::number(value));
2740
2741 if (cma_is_city_under_agent(dlgcity, nullptr)) {
2742 cma_changed();
2744 }
2745}
2746
2747/************************************************************************/
2767
2768/************************************************************************/
2772{
2773 QMenu *cma_menu = new QMenu(this);
2775
2776 cma_menu->setAttribute(Qt::WA_DeleteOnClose);
2777 cma_del_item = cma_menu->addAction(_("Remove Governor"));
2778 connect(cma_menu, &QMenu::triggered, this,
2780 if (act == cma_del_item) {
2781 cma_remove();
2782 }
2783 });
2784
2785 cma_menu->popup(QCursor::pos());
2786}
2787
2788/************************************************************************/
2792{
2793 QAction *action;
2794 QAction *disband;
2800 QMap<QString, cid>::const_iterator map_iter;
2801 QMenu *change_menu;
2802 QMenu *insert_menu;
2803 QMenu *settings_menu;
2804 QMenu *options_menu;
2805 int city_id = dlgcity->id;
2806
2807 if (!can_client_issue_orders()) {
2808 return;
2809 }
2810 settings_menu = new QMenu(this);
2811 counters_action = settings_menu->addAction(_("Counters"));
2812 connect(counters_action, &QAction::triggered, this,
2814 change_menu = settings_menu->addMenu(_("Change worklist"));
2815 insert_menu = settings_menu->addMenu(_("Insert worklist"));
2816 wl_clear = settings_menu->addAction(_("Clear worklist"));
2817 connect(wl_clear, &QAction::triggered, this, &city_dialog::clear_worklist);
2818 list.clear();
2819
2823
2824 if (list.count() == 0) {
2825 wl_empty = change_menu->addAction(_("(no worklists defined)"));
2826 insert_menu->addAction(wl_empty);
2827 }
2828
2829 map_iter = list.constBegin();
2830
2831 while (map_iter != list.constEnd()) {
2832 action = change_menu->addAction(map_iter.key());
2833 action->setData(map_iter.value());
2834
2835 action = insert_menu->addAction(map_iter.key());
2836 action->setData(map_iter.value());
2837
2838 map_iter++;
2839 }
2840
2841 wl_save = settings_menu->addAction(_("Save worklist"));
2842 connect(wl_save, &QAction::triggered, this, &city_dialog::save_worklist);
2843 options_menu = settings_menu->addMenu(_("Options"));
2844 disband = options_menu->addAction(_("Allow disbanding city"));
2845 disband->setCheckable(true);
2846 disband->setChecked(is_city_option_set(dlgcity, CITYO_DISBAND));
2847 connect(disband, &QAction::triggered, this,
2849
2850 connect(change_menu, &QMenu::triggered, this, [=](QAction *act) {
2851 QVariant id = act->data();
2852 struct city *pcity = game_city_by_number(city_id);
2853 const struct worklist *worklist;
2854
2855 if (!pcity) {
2856 return;
2857 }
2858
2859#ifndef FC_QT5_MODE
2860 fc_assert_ret(id.typeId() == QMetaType::Int);
2861#else // FC_QT5_MODE
2862 fc_assert_ret(id.type() == QVariant::Int);
2863#endif // FC_QT5_MODE
2864
2867 });
2868
2869 connect(insert_menu, &QMenu::triggered, this,
2871 QVariant id = act->data();
2872 struct city *pcity = game_city_by_number(city_id);
2873 const struct worklist *worklist;
2874
2875 if (!pcity) {
2876 return;
2877 }
2878
2879#ifndef FC_QT5_MODE
2880 fc_assert_ret(id.typeId() == QMetaType::Int);
2881#else // FC_QT5_MODE
2882 fc_assert_ret(id.type() == QVariant::Int);
2883#endif // FC_QT5_MODE
2884
2887 });
2888
2889 settings_menu->popup(QCursor::pos());
2890}
2891
2892/************************************************************************/
2896{
2897 QString str;
2898 int value;
2899 struct player *pplayer = client_player();
2900
2901 buy_button->setDisabled(true);
2902
2903 if (!client_is_observer() && pplayer != nullptr) {
2904 value = dlgcity->client.buy_cost;
2905 str = QString(PL_("Buy (%1 gold)", "Buy (%1 gold)",
2906 value)).arg(QString::number(value));
2907
2908 if (pplayer->economic.gold >= value && value != 0) {
2909 buy_button->setEnabled(true);
2910 }
2911 } else {
2912 str = QString(_("Buy"));
2913 }
2914
2915 buy_button->setText(str);
2916}
2917
2918/************************************************************************/
2922{
2923 enum citizen_category categories[MAX_CITY_SIZE];
2924 int i, j, width, height;
2925 QPainter p;
2926 QPixmap *pix;
2928 int w = tileset_small_sprite_width(tileset) / gui()->map_scale;
2929 int h = tileset_small_sprite_height(tileset) / gui()->map_scale;
2930
2931 i = 1 + (num_citizens * 5 / 200);
2932 w = w / i;
2933 QRect source_rect(0, 0, w, h);
2934 QRect dest_rect(0, 0, w, h);
2935 width = w * num_citizens;
2936 height = h;
2937
2938 if (citizen_pixmap) {
2939 citizen_pixmap->detach();
2940 delete citizen_pixmap;
2941 }
2942
2944
2945 for (j = 0, i = 0; i < num_citizens; i++, j++) {
2946 dest_rect.moveTo(i * w, 0);
2947 pix = get_citizen_sprite(tileset, categories[j], j, dlgcity)->pm;
2948 p.begin(citizen_pixmap);
2949 p.drawPixmap(dest_rect, *pix, source_rect);
2950 p.end();
2951 }
2952
2954 citizens_label->setPixmap(*citizen_pixmap);
2955
2958
2959 for (int k = 0; k < FEELING_LAST - 1; k++) {
2962 static_cast<citizen_feeling>(k),
2963 categories);
2964
2965 for (j = 0, i = 0; i < num_citizens; i++, j++) {
2966 dest_rect.moveTo(i * w, 0);
2967 pix = get_citizen_sprite(tileset, categories[j], j, dlgcity)->pm;
2968 p.begin(citizen_pixmap);
2969 p.drawPixmap(dest_rect, *pix, source_rect);
2970 p.end();
2971 }
2972
2973 lab_table[k]->setPixmap(*citizen_pixmap);
2974
2975 switch (k) {
2976 case FEELING_BASE:
2977 lab_table[k]->setToolTip(text_happiness_cities(dlgcity));
2978 break;
2979
2980 case FEELING_LUXURY:
2981 lab_table[k]->setToolTip(text_happiness_luxuries(dlgcity));
2982 break;
2983
2984 case FEELING_EFFECT :
2986 break;
2987
2990 break;
2991
2992 case FEELING_MARTIAL:
2993 lab_table[k]->setToolTip(text_happiness_units(dlgcity));
2994 break;
2995
2996 default:
2997 break;
2998 }
2999 }
3000}
3001
3002/************************************************************************/
3006{
3007 setUpdatesEnabled(false);
3008 production_combo_p->blockSignals(true);
3009
3010 if (dlgcity) {
3011 view->set_pixmap(dlgcity, zoom);
3012 view->update();
3013 update_title();
3020 update_units();
3024 } else {
3026 }
3027
3028 production_combo_p->blockSignals(false);
3029 setUpdatesEnabled(true);
3031 update();
3032}
3033
3034/************************************************************************/
3038{
3039 QFont *small_font;
3040 char buf[1024];
3041 QWidget *titlebar_widget;
3043 QPushButton *closeButton;
3044
3046
3047 qDeleteAll(counters_widget->findChildren<QWidget*>("", Qt::FindDirectChildrenOnly));
3048
3049 titlebar_widget = new QWidget();
3051 titlebar_widget->setLayout(titlebar_layout);
3052
3053 fc_snprintf(buf, sizeof(buf), _("<u>%s</u>"), _("Counters"));
3054 titlebar_layout->addWidget(new QLabel(buf, titlebar_widget),
3055 0, Qt::AlignCenter);
3057 = new QPushButton(fc_icons::instance()->get_icon("close"), "",
3059 connect(closeButton, &QPushButton::clicked, this,
3061 closeButton->setFixedSize(28, 28);
3062
3063 titlebar_layout->setContentsMargins(11, 0, 5, 0);
3064 titlebar_layout->addWidget(closeButton, 0);
3065
3066 counters_layout->setContentsMargins(11, 0, 11, 5);
3067 counters_layout->addWidget(titlebar_widget, 0, Qt::AlignTop);
3068 counters_layout->setStretch(0, 0);
3069
3071 QString helptext;
3072 QLabel *name, *value, *activated, *help;
3073
3074 name = new QLabel(name_translation_get(&pcount->name));
3075 fc_snprintf(buf, sizeof(buf), _("Current value is: %d"),
3077 value = new QLabel(buf);
3078 fc_snprintf(buf, sizeof(buf), _("Activated once value equal "
3079 "or higher than: %d"),
3080 pcount->checkpoint);
3081 activated = new QLabel(buf);
3082 if (pcount->helptext != nullptr) {
3083 strvec_iterate(pcount->helptext, text_) {
3084 helptext += text_;
3086 }
3087 help = new QLabel(helptext);
3088
3089 name->setFont(*small_font);
3090 value->setFont(*small_font);
3091 activated->setFont(*small_font);
3092 help->setFont(*small_font);
3093
3094 counters_layout->addWidget(name);
3095 counters_layout->addWidget(value);
3096 counters_layout->addWidget(activated);
3097 counters_layout->addWidget(help);
3099}
3100
3101/************************************************************************/
3105{
3106 QFont f = QApplication::font();
3107 QFontMetrics fm(f);
3108 QPixmap *pix = nullptr;
3110 QString str;
3113 char buf[8];
3115 int h;
3116 int i = 0;
3117 struct sprite *sprite;
3118
3119 h = fm.height() + 6;
3120 nationality_table->clear();
3121 nationality_table->setRowCount(0);
3122 info_list.clear();
3123 info_list << _("#") << _("Flag") << _("Nation");
3124 nationality_table->setHorizontalHeaderLabels(info_list);
3125
3126 citizens_iterate(dlgcity, pslot, nationality) {
3127 nationality_table->insertRow(i);
3128
3129 for (int j = 0; j < nationality_table->columnCount(); j++) {
3130 item = new QTableWidgetItem;
3131
3132 switch (j) {
3133 case 0:
3135
3136 if (nationality_i == 0) {
3137 str = "-";
3138 } else {
3139 fc_snprintf(buf, sizeof(buf), "%d", nationality_i);
3140 str = QString(buf);
3141 }
3142
3143 item->setText(str);
3144 break;
3145
3146 case 1:
3149 (player_slot_get_player(pslot)));
3150
3151 if (sprite != nullptr) {
3152 pix = sprite->pm;
3153 pix_scaled = pix->scaledToHeight(h);
3154 item->setData(Qt::DecorationRole, pix_scaled);
3155 } else {
3156 item->setText("FLAG MISSING");
3157 }
3158 break;
3159
3160 case 2:
3162 (player_slot_get_player(pslot)));
3163 break;
3164
3165 default:
3166 break;
3167 }
3168 nationality_table->setItem(i, j, item);
3169 }
3170 i++;
3172 nationality_table->horizontalHeader()->setStretchLastSection(false);
3173 nationality_table->resizeColumnsToContents();
3174 nationality_table->resizeRowsToContents();
3175 nationality_table->horizontalHeader()->setStretchLastSection(true);
3176}
3177
3178/************************************************************************/
3182{
3183 int illness = 0;
3184 char buffer[512];
3185 char buf_info[NUM_INFO_FIELDS][512];
3186 char buf_tooltip[NUM_INFO_FIELDS][512];
3187 int granaryturns;
3188 int spec;
3189
3190 for (int i = 0; i < NUM_INFO_FIELDS; i++) {
3191 buf_info[i][0] = '\0';
3192 buf_tooltip[i][0] = '\0';
3193 }
3194
3195 // Fill the buffers with the necessary info
3196 spec = city_specialists(dlgcity);
3198 "%3d (%4d)", dlgcity->size, spec);
3200 _("Population: %d, Specialists: %d"),
3201 dlgcity->size, spec);
3202 fc_snprintf(buf_info[INFO_FOOD], sizeof(buf_info[INFO_FOOD]), "%3d (%+4d)",
3205 "%3d (%+4d)", dlgcity->prod[O_SHIELD] + dlgcity->waste[O_SHIELD],
3207 fc_snprintf(buf_info[INFO_TRADE], sizeof(buf_info[INFO_TRADE]), "%3d (%+4d)",
3210 fc_snprintf(buf_info[INFO_GOLD], sizeof(buf_info[INFO_GOLD]), "%3d (%+4d)",
3217 "%4d/%-4d", dlgcity->food_stock,
3219
3221 sizeof(buf_tooltip[INFO_FOOD]));
3223 sizeof(buf_tooltip[INFO_SHIELD]));
3225 sizeof(buf_tooltip[INFO_TRADE]));
3227 sizeof(buf_tooltip[INFO_GOLD]));
3229 sizeof(buf_tooltip[INFO_SCIENCE]));
3231 sizeof(buf_tooltip[INFO_LUXURY]));
3233 sizeof(buf_tooltip[INFO_CULTURE]));
3235 sizeof(buf_tooltip[INFO_POLLUTION]));
3237 sizeof(buf_tooltip[INFO_ILLNESS]));
3238
3240
3241 if (granaryturns == 0) {
3242 // TRANS: city growth is blocked. Keep short.
3243 fc_snprintf(buf_info[INFO_GROWTH], sizeof(buf_info[INFO_GROWTH]), _("blocked"));
3244 } else if (granaryturns == FC_INFINITY) {
3245 // TRANS: city is not growing. Keep short.
3246 fc_snprintf(buf_info[INFO_GROWTH], sizeof(buf_info[INFO_GROWTH]), _("never"));
3247 } else {
3248 /* A negative value means we'll have famine in that many turns.
3249 But that's handled down below. */
3250 // TRANS: city growth turns. Keep short.
3252 PL_("%d turn", "%d turns", abs(granaryturns)),
3253 abs(granaryturns));
3254 }
3255
3257 "%4d", dlgcity->waste[O_TRADE]);
3264
3265 if (!game.info.illness_on) {
3267 " -.-");
3268 } else {
3269 illness = city_illness_calc(dlgcity, nullptr, nullptr, nullptr, nullptr);
3270 // Illness is in tenth of percent
3272 "%5.1f%%", (float) illness / 10.0);
3273 }
3274 if (dlgcity->steal) {
3276 PL_("%d time", "%d times", dlgcity->steal), dlgcity->steal);
3277 } else {
3279 _("Not stolen"));
3280 }
3281
3283 sizeof(buf_info[INFO_AIRLIFT]));
3285 sizeof(buf_tooltip[INFO_AIRLIFT]));
3286
3287 get_city_dialog_output_text(dlgcity, O_FOOD, buffer, sizeof(buffer));
3288
3289 for (int i = 0; i < NUM_INFO_FIELDS; i++) {
3290 qlt[i]->setText(QString(buf_info[i]));
3291
3292 if (buf_tooltip[i][0]) {
3293 qlt[i]->setToolTip("<pre>" + QString(buf_tooltip[i]).toHtmlEscaped()
3294 + "</pre>");
3295 }
3296 }
3297}
3298
3299/************************************************************************/
3303{
3306
3307 setContentsMargins(0, 0 ,0 ,0);
3309 dlgcity = qcity;
3310 production_combo_p->blockSignals(true);
3311 refresh();
3312 production_combo_p->blockSignals(false);
3313}
3314
3315/************************************************************************/
3319{
3320 struct worklist queue;
3321
3322 city_get_queue(dlgcity, &queue);
3323
3325 return;
3326 }
3327
3329 city_set_queue(dlgcity, &queue);
3330}
3331
3332/************************************************************************/
3336{
3337 unit_item *ui;
3338 struct unit_list *units;
3339 char buf[256];
3340 int n;
3341 int happy_cost;
3343 struct player *pplayer = client_player();
3344 const struct civ_map *nmap = &(wld.map);
3345
3346 supported_units->setUpdatesEnabled(false);
3347 supported_units->clear_layout();
3348
3349 if (pplayer != nullptr
3350 && city_owner(dlgcity) != pplayer) {
3352 } else {
3353 units = dlgcity->units_supported;
3354 }
3355
3356 unit_list_iterate(units, punit) {
3358 ui = new unit_item(this, punit, true, happy_cost);
3359 ui->init_pix();
3360 supported_units->add_item(ui);
3362 n = unit_list_size(units);
3363 fc_snprintf(buf, sizeof(buf), _("Supported units %d"), n);
3364 supp_units->setText(QString(buf));
3365 supported_units->update_units();
3366 supported_units->setUpdatesEnabled(true);
3367 current_units->setUpdatesEnabled(true);
3369
3370 if (pplayer != nullptr
3371 && city_owner(dlgcity) != pplayer) {
3373 } else {
3374 units = dlgcity->tile->units;
3375 }
3376
3377 unit_list_iterate(units, punit) {
3378 ui = new unit_item(this , punit, false);
3379 ui->init_pix();
3382
3383 n = unit_list_size(units);
3384 fc_snprintf(buf, sizeof(buf), _("Present units %d"), n);
3385 curr_units->setText(QString(buf));
3386
3388 current_units->setUpdatesEnabled(true);
3389}
3390
3391/************************************************************************/
3395 const QItemSelection &ds)
3396{
3397 QModelIndex index;
3398 QModelIndexList indexes = sl.indexes();
3399
3400 if (indexes.isEmpty()) {
3401 return;
3402 }
3403
3404 index = indexes.at(0);
3405 selected_row_p = index.row();
3407}
3408
3409/************************************************************************/
3413{
3414 int size, i;
3415 struct city *other_pcity = nullptr;
3416 struct player *pplayer = client_player();
3417
3418 if (pplayer == nullptr) {
3419 return;
3420 }
3421
3422 size = city_list_size(pplayer->cities);
3423
3424 if (size <= 1) {
3425 return;
3426 }
3427
3428 for (i = 0; i < size; i++) {
3429 if (dlgcity == city_list_get(pplayer->cities, i)) {
3430 break;
3431 }
3432 }
3433
3434 if (i >= size - 1) {
3435 // Current city last in the list (size - 1) or disappeared (size)
3436 other_pcity = city_list_get(pplayer->cities, 0);
3437 } else {
3438 other_pcity = city_list_get(pplayer->cities, i + 1);
3439 }
3440
3443}
3444
3445/************************************************************************/
3449{
3450 int size, i;
3451 struct city *other_pcity = nullptr;
3452 struct player *pplayer = client_player();
3453
3454 if (pplayer == nullptr) {
3455 return;
3456 }
3457
3458 size = city_list_size(pplayer->cities);
3459
3460 if (size <= 1) {
3461 return;
3462 }
3463
3464 for (i = 0; i < size; i++) {
3465 if (dlgcity == city_list_get(pplayer->cities, i)) {
3466 break;
3467 }
3468 }
3469
3470 if (i == 0 || i == size) {
3471 // Current city in the beginning of the list or disappeared
3472 other_pcity = city_list_get(pplayer->cities, size - 1);
3473 } else {
3474 other_pcity = city_list_get(pplayer->cities, i - 1);
3475 }
3476
3479}
3480
3481/************************************************************************/
3485{
3486 char buf[32];
3487 QString str;
3489
3491 production_combo_p->setRange(0, cost);
3493 if (dlgcity->shield_stock >= cost) {
3494 production_combo_p->setValue(cost);
3495 } else {
3497 }
3498 production_combo_p->setAlignment(Qt::AlignCenter);
3499 str = QString(buf);
3500 str = str.simplified();
3501
3502 production_combo_p->setFormat(QString("(%p%) %2\n%1")
3504 str));
3505
3506 production_combo_p->updateGeometry();
3507
3508}
3509
3510/************************************************************************/
3514{
3515 char buf[1024], buf2[1024];
3517 int value = dlgcity->client.buy_cost;
3519 int city_id = dlgcity->id;
3520
3521 if (!can_client_issue_orders()) {
3522 return;
3523 }
3524
3526 fc_snprintf(buf2, ARRAY_SIZE(buf2), PL_("Treasury contains %d gold.",
3527 "Treasury contains %d gold.",
3528 client_player()->economic.gold),
3529 client_player()->economic.gold);
3530 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Buy %s for %d gold?",
3531 "Buy %s for %d gold?", value),
3532 name, value);
3533 ask->set_text_title(buf, buf2);
3534 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
3535 ask->setDefaultButton(QMessageBox::Cancel);
3536 ask->setAttribute(Qt::WA_DeleteOnClose);
3537 connect(ask, &hud_message_box::accepted, this, [=]() {
3538 struct city *pcity = game_city_by_number(city_id);
3539
3540 if (!pcity) {
3541 return;
3542 }
3543
3545 });
3546 ask->show();
3547}
3548
3549/************************************************************************/
3553{
3554 QFont f = QApplication::font();
3555 QFontMetrics fm(f);
3556 QPixmap *pix = nullptr;
3560 struct sprite *sprite;
3561 int h, cost, item, targets_used, col, upkeep;
3562 struct item items[MAX_NUM_PRODUCTION_TARGETS];
3563 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
3564 struct worklist queue;
3565 impr_item *ui;
3566
3567 upkeep = 0;
3568 city_buildings->setUpdatesEnabled(false);
3570
3571 h = fm.height() + 6;
3573 name_and_sort_items(targets, targets_used, items, false, dlgcity);
3574
3575 for (item = 0; item < targets_used; item++) {
3576 struct universal target = items[item].item;
3577
3578 ui = new impr_item(this, target.value.building, dlgcity);
3579 ui->init_pix();
3581
3582 fc_assert_action(VUT_IMPROVEMENT == target.kind, continue);
3584 upkeep = upkeep + city_improvement_upkeep(dlgcity, target.value.building);
3585 if (sprite != nullptr) {
3586 pix = sprite->pm;
3587 pix_scaled = pix->scaledToHeight(h);
3588 }
3589 }
3590
3591 city_get_queue(dlgcity, &queue);
3592 p_table_p->setRowCount(worklist_length(&queue));
3593
3594 for (int i = 0; i < worklist_length(&queue); i++) {
3595 struct universal target = queue.entries[i];
3596
3597 tooltip = "";
3598
3599 if (VUT_UTYPE == target.kind) {
3601 cost = utype_build_shield_cost(dlgcity, nullptr, target.value.utype);
3602 tooltip = get_tooltip_unit(target.value.utype, true).trimmed();
3606 } else {
3610 dlgcity, true).trimmed();
3611
3613 cost = -1;
3614 } else {
3616 }
3617 }
3618
3619 for (col = 0; col < 3; col++) {
3620 qitem = new QTableWidgetItem();
3621 qitem->setToolTip(tooltip);
3622
3623 switch (col) {
3624 case 0:
3625 if (sprite) {
3626 pix = sprite->pm;
3627 pix_scaled = pix->scaledToHeight(h);
3628 qitem->setData(Qt::DecorationRole, pix_scaled);
3629 }
3630 break;
3631
3632 case 1:
3633 if (str.contains('[') && str.contains(']')) {
3634 int ii, ij;
3635
3636 ii = str.lastIndexOf('[');
3637 ij = str.lastIndexOf(']');
3638 if (ij > ii) {
3639 str = str.remove(ii, ij - ii + 1);
3640 }
3641 }
3642 qitem->setText(str);
3643 break;
3644
3645 case 2:
3646 qitem->setTextAlignment(Qt::AlignRight);
3647 qitem->setText(QString::number(cost));
3648 break;
3649 }
3650 p_table_p->setItem(i, col, qitem);
3651 }
3652 }
3653
3654 p_table_p->horizontalHeader()->setStretchLastSection(false);
3655 p_table_p->resizeColumnsToContents();
3656 p_table_p->resizeRowsToContents();
3657 p_table_p->horizontalHeader()->setStretchLastSection(true);
3658
3660 city_buildings->setUpdatesEnabled(true);
3661 city_buildings->setUpdatesEnabled(true);
3662
3663 curr_impr->setText(QString(_("Improvements - upkeep %1")).arg(upkeep));
3664}
3665
3666/************************************************************************/
3670{
3671 cid id;
3672 QVariant qvar;
3673
3675 struct universal univ;
3676
3677 id = qvar.toInt();
3678 univ = cid_production(id);
3680 }
3681}
3682
3683/************************************************************************/
3688{
3690 int when = 1;
3691
3692 pw = new production_widget(this, dlgcity, future_targets->isChecked(),
3693 when, selected_row_p, show_units->isChecked(),
3694 false, show_wonders->isChecked(),
3695 show_buildings->isChecked());
3696 pw->show();
3697}
3698
3699/************************************************************************/
3704{
3706 int when = 4;
3707
3708 pw = new production_widget(this, dlgcity, future_targets->isChecked(),
3709 when, selected_row_p, show_units->isChecked(),
3710 false, show_wonders->isChecked(),
3711 show_buildings->isChecked());
3712 pw->show();
3713}
3714
3715/************************************************************************/
3719{
3720 struct worklist empty;
3721
3722 if (!can_client_issue_orders()) {
3723 return;
3724 }
3725
3728}
3729
3730/************************************************************************/
3734{
3735 QModelIndex index;
3736 struct worklist queue;
3737 struct universal *target;
3738
3740 return;
3741 }
3742
3743 target = new universal;
3744 city_get_queue(dlgcity, &queue);
3745 worklist_peek_ith(&queue, target, selected_row_p);
3747 worklist_insert(&queue, target, selected_row_p - 1);
3748 city_set_queue(dlgcity, &queue);
3749 index = p_table_p->model()->index(selected_row_p - 1, 0);
3750 p_table_p->setCurrentIndex(index);
3751 delete target;
3752
3753}
3754
3755/************************************************************************/
3759{
3761
3762 if (selected_row_p < 0
3763 || selected_row_p >= p_table_p->rowCount()) {
3764 return;
3765 }
3766
3770}
3771
3772/************************************************************************/
3776{
3777 QModelIndex index;
3778 struct worklist queue;
3779 struct universal *target;
3780
3782 return;
3783 }
3784
3785 target = new universal;
3786 city_get_queue(dlgcity, &queue);
3787 worklist_peek_ith(&queue, target, selected_row_p);
3789 worklist_insert(&queue, target, selected_row_p + 1);
3790 city_set_queue(dlgcity, &queue);
3791 index = p_table_p->model()->index(selected_row_p + 1, 0);
3792 p_table_p->setCurrentIndex(index);
3793 delete target;
3794}
3795
3796/************************************************************************/
3800{
3801 hud_input_box *ask = new hud_input_box(gui()->central_wdg);
3802 int city_id = dlgcity->id;
3803
3804 ask->set_text_title_definput(_("What should we name new worklist?"),
3805 _("Save current worklist"),
3806 _("New worklist"));
3807 ask->setAttribute(Qt::WA_DeleteOnClose);
3808 connect(ask, &hud_message_box::accepted, [=]() {
3809 struct global_worklist *gw;
3810 struct worklist queue;
3812 QString text;
3813 struct city *pcity = game_city_by_number(city_id);
3814
3815 ask_bytes = ask->input_edit.text().toUtf8();
3816 text = ask_bytes.data();
3817 if (!text.isEmpty()) {
3818 ask_bytes = text.toUtf8();
3820 city_get_queue(pcity, &queue);
3821 global_worklist_set(gw, &queue);
3822 }
3823 });
3824 ask->show();
3825}
3826
3827/************************************************************************/
3831{
3832 QString buf;
3833
3834 // Defeat keyboard shortcut mnemonics
3836 .replace("&", "&&"));
3837
3838 if (city_unhappy(dlgcity)) {
3839 // TRANS: city dialog title
3840 buf = QString(_("%1 - %2 citizens - DISORDER")).arg(city_name_get(dlgcity),
3842 } else if (city_celebrating(dlgcity)) {
3843 // TRANS: city dialog title
3844 buf = QString(_("%1 - %2 citizens - celebrating")).arg(city_name_get(dlgcity),
3846 } else if (city_happy(dlgcity)) {
3847 // TRANS: city dialog title
3848 buf = QString(_("%1 - %2 citizens - happy")).arg(city_name_get(dlgcity),
3850 } else {
3851 // TRANS: city dialog title
3852 buf = QString(_("%1 - %2 citizens")).arg(city_name_get(dlgcity),
3854 }
3855
3857}
3858
3859/************************************************************************/
3864{
3865 if (!::city_dlg_created) {
3866 ::city_dlg = new city_dialog(gui()->mapview_wdg);
3867 }
3868
3870 city_dlg->show();
3871 city_dlg->activateWindow();
3872 city_dlg->raise();
3873}
3874
3875/************************************************************************/
3879{
3880 if (!::city_dlg_created) {
3881 return;
3882 }
3883
3884 city_dlg->close();
3885 ::city_dlg_created = false;
3886}
3887
3888/************************************************************************/
3892{
3893 if (!::city_dlg_created) {
3894 return;
3895 }
3896
3898}
3899
3900/************************************************************************/
3907
3908/************************************************************************/
3912{
3913 if (!::city_dlg_created) {
3914 return;
3915 }
3916
3918 city_dlg->refresh();
3919 }
3920}
3921
3922/************************************************************************/
3926{
3928 QFont *f;
3929
3930 if (!::city_dlg_created) {
3931 return;
3932 }
3933
3934 l = city_dlg->findChildren<QLabel *>();
3935
3937
3938 for (int i = 0; i < l.size(); ++i) {
3939 if (l.at(i)->property(fonts::notify_label).isValid()) {
3940 l.at(i)->setFont(*f);
3941 }
3942 }
3943}
3944
3945/************************************************************************/
3962
3963/************************************************************************/
3967{
3968 if (!::city_dlg_created) {
3969 return false;
3970 }
3971
3972 if (city_dlg->dlgcity == pcity && city_dlg->isVisible()) {
3973 return true;
3974 }
3975
3976 return false;
3977}
3978
3979/************************************************************************/
3982bool fc_tooltip::eventFilter(QObject *obj, QEvent *ev)
3983{
3986 QRect rect;
3987
3988 if (ev->type() == QEvent::ToolTip) {
3990
3991 if (!view) {
3992 return false;
3993 }
3994
3995 help_event = static_cast<QHelpEvent *>(ev);
3996 QPoint pos = help_event->pos();
3997 QModelIndex index = view->indexAt(pos);
3998 QPoint hpos;
3999
4000 if (!index.isValid()) {
4001 return false;
4002 }
4003
4004 item_tooltip = view->model()->data(index, Qt::ToolTipRole).toString();
4005 rect = view->visualRect(index);
4006
4007 hpos = help_event->globalPos();
4008
4009 rect.setX(rect.x() + hpos.x());
4010 rect.setY(rect.y() + hpos.y());
4011
4012 if (!item_tooltip.isEmpty()) {
4013 QToolTip::showText(help_event->globalPos(), item_tooltip, view, rect);
4014 } else {
4015 QToolTip::hideText();
4016 }
4017
4018 return true;
4019 }
4020
4021 return false;
4022}
4023
4024/************************************************************************/
4028{
4029 return QString("<b>" + text + "</b>");
4030}
4031
4032/************************************************************************/
4037 bool ext)
4038{
4040 QString upkeep;
4041 QString s1, s2, str;
4042 const char *req = skip_intl_qualifier_prefix(_("?tech:None"));
4043 struct player *pplayer = client_player();
4044
4045 if (pcity != nullptr) {
4046 upkeep = QString::number(city_improvement_upkeep(pcity, building));
4047 } else {
4048 upkeep = QString::number(building->upkeep);
4049 }
4051 if (pobs->source.kind == VUT_ADVANCE) {
4052 req = advance_name_translation(pobs->source.value.advance);
4053 break;
4054 }
4056 s2 = QString(req);
4057 str = _("Obsolete by:");
4058 str = str + " " + s2;
4059 def_str = "<p style='white-space:pre'><b>"
4060 + QString(improvement_name_translation(building)).toHtmlEscaped()
4061 + "</b>\n";
4062 if (pcity != nullptr) {
4063 def_str += QString(_("Cost: %1, Upkeep: %2\n"))
4064 .arg(impr_build_shield_cost(pcity, building))
4065 .arg(upkeep).toHtmlEscaped();
4066 } else {
4068 nullptr, building);
4069
4070 def_str += QString(_("Cost Estimate: %1, Upkeep: %2\n"))
4071 .arg(cost_est)
4072 .arg(upkeep).toHtmlEscaped();
4073 }
4074 if (s1.compare(s2) != 0) {
4075 def_str = def_str + str.toHtmlEscaped() + "\n";
4076 }
4077 def_str = def_str + "\n";
4078 if (ext) {
4079 char buffer[8192];
4080
4081 str = helptext_building(buffer, sizeof(buffer), pplayer,
4082 nullptr, building);
4083 str = cut_helptext(str);
4084 str = split_text(str, true);
4085 str = str.trimmed();
4086 def_str = def_str + str.toHtmlEscaped();
4087 }
4088 return def_str;
4089}
4090
4091/************************************************************************/
4095QString get_tooltip_unit(const struct unit_type *utype, bool ext)
4096{
4099 QString str;
4100 const struct unit_type *obsolete;
4101 struct advance *tech;
4102
4103 def_str = "<b>"
4104 + QString(utype_name_translation(utype)).toHtmlEscaped()
4105 + "</b>\n";
4106 obsolete = utype->obsoleted_by;
4107 if (obsolete) {
4108 // FIXME: Don't give the impression that primary tech is (always) the only one.
4110 obsolete_str = QString("</td></tr><tr><td colspan=\"3\">");
4111 if (tech && tech != advance_by_number(A_NONE)) {
4112 /* TRANS: this and nearby literal strings are interpreted
4113 * as (Qt) HTML */
4114 obsolete_str = obsolete_str + QString(_("Obsoleted by %1 (%2)."))
4116 .arg(advance_name_translation(tech)).toHtmlEscaped();
4117 } else {
4118 obsolete_str = obsolete_str + QString(_("Obsoleted by %1."))
4119 .arg(utype_name_translation(obsolete)).toHtmlEscaped();
4120 }
4121 }
4122 def_str += "<table width=\"100\%\"><tr><td>"
4123 + bold(QString(_("Attack:"))) + " "
4124 + QString::number(utype->attack_strength).toHtmlEscaped()
4125 + QString("</td><td>") + bold(QString(_("Defense:"))) + " "
4126 + QString::number(utype->defense_strength).toHtmlEscaped()
4127 + QString("</td><td>") + bold(QString(_("Move:"))) + " "
4128 + QString(move_points_text(utype->move_rate, TRUE)).toHtmlEscaped()
4129 + QString("</td></tr><tr><td>")
4130 + bold(QString(_("Cost:"))) + " "
4131 + QString::number(utype_build_shield_cost_base(utype))
4132 .toHtmlEscaped()
4133 + QString("</td><td colspan=\"2\">")
4134 + bold(QString(_("Basic Upkeep:")))
4135 + " " + QString(helptext_unit_upkeep_str(utype)).toHtmlEscaped()
4136 + QString("</td></tr><tr><td>")
4137 + bold(QString(_("Hitpoints:"))) + " "
4138 + QString::number(utype->hp).toHtmlEscaped()
4139 + QString("</td><td>") + bold(QString(_("Firepower:"))) + " "
4140 + QString::number(utype->firepower).toHtmlEscaped()
4141 + QString("</td><td>") + bold(QString(_("Vision:"))) + " "
4142 + QString::number((int) sqrt((double) utype->vision_radius_sq))
4143 .toHtmlEscaped()
4144 + obsolete_str
4145 + QString("</td></tr></table><p style='white-space:pre'>");
4146 if (ext) {
4147 char buffer[8192];
4148 char buf2[1];
4149
4150 buf2[0] = '\0';
4151 str = helptext_unit(buffer, sizeof(buffer), client_player(),
4152 buf2, utype, TRUE);
4153 str = cut_helptext(str);
4154 str = split_text(str, true);
4155 str = str.trimmed().toHtmlEscaped();
4156 def_str = def_str + str;
4157 }
4158
4159 return def_str;
4160};
4161
4162/************************************************************************/
4166{
4169 char buffer[8192];
4170 char buf2[1];
4171 struct universal *target;
4172 struct player *pplayer = client_player();
4173
4174 buf2[0] = '\0';
4175 target = reinterpret_cast<universal *>(qvar.value<void *>());
4176
4177 if (target == nullptr) {
4178 } else if (VUT_UTYPE == target->kind) {
4180 str = helptext_unit(buffer, sizeof(buffer), pplayer,
4181 buf2, target->value.utype, TRUE);
4182 } else {
4183 if (!is_convert_improvement(target->value.building)) {
4185 }
4186
4187 str = helptext_building(buffer, sizeof(buffer), pplayer,
4188 nullptr, target->value.building);
4189 }
4190
4191 // Remove all lines from help which has '*' in first 3 chars
4193 ret_str = split_text(ret_str, true);
4194 ret_str = ret_str.trimmed();
4195 ret_str = def_str + ret_str.toHtmlEscaped();
4196
4197 return ret_str;
4198}
4199
4200/************************************************************************/
4204 QObject *parent,
4205 struct city *city)
4206 : QItemDelegate(parent)
4207{
4208 pd = sh;
4209 item_height = sh.y();
4210 pcity = city;
4211}
4212
4213/************************************************************************/
4218 const QModelIndex &index) const
4219{
4220 struct universal *target;
4221 QString name;
4222 QVariant qvar;
4223 QPixmap *pix;
4225 QRect rect1;
4226 QRect rect2;
4227 struct sprite *sprite;
4228 bool useless = false;
4229 bool is_convert = false;
4230 bool is_neutral = false;
4231 bool is_sea = false;
4232 bool is_flying = false;
4233 bool is_unit = true;
4234 QPixmap pix_dec(option.rect.width(), option.rect.height());
4236 color col;
4237 QIcon icon = current_app()->style()->standardIcon(QStyle::SP_DialogCancelButton);
4238 bool free_sprite = false;
4239 struct unit_class *pclass;
4240
4241 if (!option.rect.isValid()) {
4242 return;
4243 }
4244
4245 qvar = index.data();
4246
4247 if (!qvar.isValid()) {
4248 return;
4249 }
4250
4251 target = reinterpret_cast<universal *>(qvar.value<void *>());
4252
4253 if (target == nullptr) {
4254 col.qcolor = Qt::white;
4255 sprite = qtg_create_sprite(100, 100, &col);
4256 free_sprite = true;
4257 *sprite->pm = icon.pixmap(100, 100);
4258 name = _("Cancel");
4259 is_unit = false;
4260 } else if (VUT_UTYPE == target->kind) {
4263 pclass = utype_class(target->value.utype);
4267 is_sea = true;
4268 }
4269
4270 if ((utype_fuel(target->value.utype)
4275 /* FIXME: Assumed to be flying since only missiles can do suicide
4276 * attacks in classic-like rulesets. This isn't true for all
4277 * rulesets. Not a high priority to fix since all is_flying and
4278 * is_sea is used for is to set a color. */
4280 target->value.utype)) {
4281 if (is_sea) {
4282 is_sea = false;
4283 }
4284 is_flying = true;
4285 }
4286
4290 } else {
4291 is_unit = false;
4295 is_convert = (target->value.building->genus == IG_CONVERT);
4296 }
4297
4298 if (sprite != nullptr) {
4299 pix = sprite->pm;
4300 pix_scaled = pix->scaledToHeight(item_height - 2, Qt::SmoothTransformation);
4301
4302 if (useless) {
4304 }
4305 }
4306
4307 opt = QItemDelegate::setOptions(index, option);
4308 painter->save();
4309 opt.displayAlignment = Qt::AlignLeft;
4310 opt.textElideMode = Qt::ElideMiddle;
4311 QItemDelegate::drawBackground(painter, opt, index);
4312 rect1 = option.rect;
4313 rect1.setWidth(pix_scaled.width() + 4);
4314 rect2 = option.rect;
4315 rect2.setLeft(option.rect.left() + rect1.width());
4316 rect2.setTop(rect2.top() + (rect2.height()
4317 - painter->fontMetrics().height()) / 2);
4318 QItemDelegate::drawDisplay(painter, opt, rect2, name);
4319
4320 if (is_unit) {
4321 if (is_sea) {
4322 pix_dec.fill(QColor(0, 0, 255, 80));
4323 } else if (is_flying) {
4324 pix_dec.fill(QColor(220, 0, 0, 80));
4325 } else if (is_neutral) {
4326 pix_dec.fill(QColor(0, 120, 0, 40));
4327 } else {
4328 pix_dec.fill(QColor(0, 0, 150, 40));
4329 }
4330
4331 QItemDelegate::drawDecoration(painter, option, option.rect, pix_dec);
4332 }
4333
4334 if (is_convert) {
4335 pix_dec.fill(QColor(255, 255, 0, 70));
4336 QItemDelegate::drawDecoration(painter, option, option.rect, pix_dec);
4337 }
4338
4339 if (!pix_scaled.isNull()) {
4340 QItemDelegate::drawDecoration(painter, opt, rect1, pix_scaled);
4341 }
4342
4343 drawFocus(painter, opt, option.rect);
4344
4345 painter->restore();
4346
4347 if (free_sprite) {
4349 }
4350}
4351
4352/************************************************************************/
4357 const QRect &rect) const
4358{
4359 QPixmap pix(option.rect.width(), option.rect.height());
4360
4361 if ((option.state & QStyle::State_MouseOver) == 0 || !rect.isValid()) {
4362 return;
4363 }
4364
4365 pix.fill(QColor(50, 50, 50, 50));
4366 QItemDelegate::drawDecoration(painter, option, option.rect, pix);
4367}
4368
4369/************************************************************************/
4373 const QModelIndex &index) const
4374{
4375 QSize s;
4376
4377 s.setWidth(pd.x());
4378 s.setHeight(pd.y());
4379 return s;
4380}
4381
4382/************************************************************************/
4386 QObject *parent): QObject()
4387{
4389 target = ptarget;
4390}
4391
4392/************************************************************************/
4396{
4397 // Allocated as renegade in model
4398 if (target != nullptr) {
4399 delete target;
4400 }
4401}
4402
4403/************************************************************************/
4407{
4408 return QVariant::fromValue((void *)target);
4409}
4410
4411/************************************************************************/
4415{
4416 return false;
4417}
4418
4419/************************************************************************/
4423 bool su, bool sw, bool sb,
4424 QObject *parent)
4425 : QAbstractListModel(parent)
4426{
4427 show_units = su;
4428 show_wonders = sw;
4430 mcity = pcity;
4431 future_t = f;
4432 populate();
4433}
4434
4435/************************************************************************/
4443
4444/************************************************************************/
4448{
4449 if (!index.isValid()) {
4450 return QVariant();
4451 }
4452
4453 if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0
4454 && index.column() < columnCount()
4455 && (index.column() + index.row() * 3 < city_target_list.count())) {
4456 int r, c, t, new_index;
4457
4458 r = index.row();
4459 c = index.column();
4460 t = r * 3 + c;
4461 new_index = t / 3 + rowCount() * c;
4462 // Exception, shift whole column
4463 if ((c == 2) && city_target_list.count() % 3 == 1) {
4464 new_index = t / 3 + rowCount() * c - 1;
4465 }
4466 if (role == Qt::ToolTipRole) {
4468 }
4469
4470 return city_target_list[new_index]->data();
4471 }
4472
4473 return QVariant();
4474}
4475
4476/************************************************************************/
4480{
4482 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
4483 struct item items[MAX_NUM_PRODUCTION_TARGETS];
4484 struct universal *renegade;
4485 int item, targets_used;
4486 QString str;
4488 QFontMetrics fm(f);
4489
4490 sh.setY(fm.height() * 2);
4491 sh.setX(0);
4492
4494 city_target_list.clear();
4495
4497 future_t);
4498 name_and_sort_items(targets, targets_used, items, false, mcity);
4499
4500 for (item = 0; item < targets_used; item++) {
4501 if (future_t || can_city_build_now(&(wld.map), mcity, &items[item].item)) {
4502 renegade = new universal(items[item].item);
4503
4504 // Renegade deleted in production_item destructor
4505 if (VUT_UTYPE == renegade->kind) {
4506 str = utype_name_translation(renegade->value.utype);
4507 sh.setX(qMax(sh.x(), fm.horizontalAdvance(str)));
4508
4509 if (show_units) {
4510 pi = new production_item(renegade, this);
4512 } else {
4513 delete renegade;
4514 }
4515 } else {
4516 str = improvement_name_translation(renegade->value.building);
4517 sh.setX(qMax(sh.x(), fm.horizontalAdvance(str)));
4518
4519 if ((is_wonder(renegade->value.building) && show_wonders)
4520 || (is_improvement(renegade->value.building) && show_buildings)
4521 || (is_convert_improvement(renegade->value.building))
4522 || (is_special_improvement(renegade->value.building)
4523 && show_buildings)) {
4524 pi = new production_item(renegade, this);
4526 } else {
4527 delete renegade;
4528 }
4529 }
4530 }
4531 }
4532
4533 pi = new production_item(nullptr, this);
4535 sh.setX(2 * sh.y() + sh.x());
4536 sh.setX(qMin(sh.x(), 250));
4537}
4538
4539/************************************************************************/
4543 const QVariant &value, int role)
4544{
4545 if (!index.isValid() || role != Qt::DisplayRole || role != Qt::ToolTipRole)
4546 return false;
4547
4548 if (index.row() >= 0 && index.row() < rowCount() && index.column() >= 0
4549 && index.column() < columnCount()) {
4550 bool change = city_target_list[index.row()]->setData();
4551 return change;
4552 }
4553
4554 return false;
4555}
4556
4557/************************************************************************/
4566 bool future, int when, int curr,
4567 bool show_units, bool buy,
4568 bool show_wonders,
4569 bool show_buildings): QTableView()
4570{
4571 QPoint pos, sh;
4572 QRect rect = QApplication::primaryScreen()->availableGeometry();
4573 int desk_width = rect.width();
4574 int desk_height = rect.height();
4575 fc_tt = new fc_tooltip(this);
4576 setAttribute(Qt::WA_DeleteOnClose);
4577 setWindowFlags(Qt::Popup);
4578 verticalHeader()->setVisible(false);
4579 horizontalHeader()->setVisible(false);
4580 setProperty("showGrid", false);
4582 sh_units = show_units;
4583 pw_city = pcity;
4584 buy_it = buy;
4585 when_change = when;
4586 list_model = new city_production_model(pw_city, future, show_units,
4587 show_wonders, show_buildings, this);
4588 sh = list_model->sh;
4589 c_p_d = new city_production_delegate(sh, this, pw_city);
4592 viewport()->installEventFilter(fc_tt);
4593 installEventFilter(this);
4595 const QItemSelection &)),
4597 const QItemSelection &)));
4600 setFixedWidth(3 * sh.x() + 6);
4601 setFixedHeight(list_model->rowCount()*sh.y() + 6);
4602
4603 if (width() > desk_width) {
4605 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
4606 } else {
4607 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
4608 }
4609
4610 if (height() > desk_height) {
4612 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
4613 } else {
4614 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
4615 }
4616
4617 pos = QCursor::pos();
4618
4619 if (pos.x() + width() > desk_width) {
4620 pos.setX(desk_width - width());
4621 } else if (pos.x() - width() < 0) {
4622 pos.setX(0);
4623 }
4624
4625 if (pos.y() + height() > desk_height) {
4626 pos.setY(desk_height - height());
4627 } else if (pos.y() - height() < 0) {
4628 pos.setY(0);
4629 }
4630
4631 move(pos);
4632 setMouseTracking(true);
4633 setFocus();
4634}
4635
4636/************************************************************************/
4640{
4641 if (event->button() == Qt::RightButton) {
4642 close();
4643 return;
4644 }
4645
4646 QAbstractItemView::mousePressEvent(event);
4647}
4648
4649/************************************************************************/
4653{
4654 QRect pw_rect;
4655 QPoint br;
4656
4657 if (obj != this)
4658 return false;
4659
4660 if (ev->type() == QEvent::MouseButtonPress) {
4661 pw_rect.setTopLeft(pos());
4662 br.setX(pos().x() + width());
4663 br.setY(pos().y() + height());
4664 pw_rect.setBottomRight(br);
4665
4666 if (!pw_rect.contains(QCursor::pos())) {
4667 close();
4668 }
4669 }
4670
4671 return false;
4672}
4673
4674/************************************************************************/
4678 const QItemSelection &ds)
4679{
4680 QModelIndexList indexes = selectionModel()->selectedIndexes();
4681 QModelIndex index;
4682 QVariant qvar;
4683 struct worklist queue;
4684 struct universal *target;
4685
4686 if (indexes.isEmpty() || client_is_observer()) {
4687 return;
4688 }
4689 index = indexes.at(0);
4690 qvar = index.data(Qt::UserRole);
4691 if (!qvar.isValid()) {
4692 return;
4693 }
4694 target = reinterpret_cast<universal *>(qvar.value<void *>());
4695 if (target != nullptr) {
4696 city_get_queue(pw_city, &queue);
4697 switch (when_change) {
4698 case 0: // Change current target
4700 if (city_can_buy(pw_city) && buy_it) {
4702 }
4703 break;
4704
4705 case 1: // Change current (selected on list)
4708 } else {
4710 worklist_insert(&queue, target, curr_selection);
4711 city_set_queue(pw_city, &queue);
4712 }
4713 break;
4714
4715 case 2: // Insert before
4717 curr_selection = 0;
4718 }
4721 worklist_insert(&queue, target, curr_selection);
4722 city_set_queue(pw_city, &queue);
4723 break;
4724
4725 case 3: // Insert after
4727 city_queue_insert(pw_city, -1, target);
4728 break;
4729 }
4731 worklist_insert(&queue, target, curr_selection);
4732 city_set_queue(pw_city, &queue);
4733 break;
4734
4735 case 4: // Add last
4736 city_queue_insert(pw_city, -1, target);
4737 break;
4738
4739 default:
4740 break;
4741 }
4742 }
4743 close();
4744 destroy();
4745}
4746
4747/************************************************************************/
4751{
4752 delete c_p_d;
4753 delete list_model;
4754 viewport()->removeEventFilter(fc_tt);
4755 removeEventFilter(this);
4756}
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
#define action_id_univs_not_blocking(act_id, act_uni, tgt_uni)
Definition actions.h:714
#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:663
int city_production_build_shield_cost(const struct city *pcity)
Definition city.c:737
int city_granary_size(int city_size)
Definition city.c:2146
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
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
int city_improvement_upkeep(const struct city *pcity, const struct impr_type *b)
Definition city.c:1255
bool is_city_option_set(const struct city *pcity, enum city_options option)
Definition city.c:3427
int city_population(const struct city *pcity)
Definition city.c:1191
int city_unit_unhappiness(const struct civ_map *nmap, struct unit *punit, int *free_unhappy)
Definition city.c:3063
bool city_unhappy(const struct city *pcity)
Definition city.c:1626
bool city_celebrating(const struct city *pcity)
Definition city.c:1645
int city_illness_calc(const struct city *pcity, int *ill_base, int *ill_size, int *ill_trade, int *ill_pollution)
Definition city.c:2884
bool city_happy(const struct city *pcity)
Definition city.c:1614
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:137
int rs_max_city_radius_sq(void)
Definition city.c:159
citizens city_specialists(const struct city *pcity)
Definition city.c:3356
bool can_city_build_now(const struct civ_map *nmap, const struct city *pcity, const struct universal *target)
Definition city.c:1013
int city_turns_to_grow(const struct city *pcity)
Definition city.c:1996
const char * city_production_name_translation(const struct city *pcity)
Definition city.c:700
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
citizen_category
Definition city.h:264
#define city_owner(_pcity_)
Definition city.h:560
#define MAX_CITY_SIZE
Definition city.h:103
citizen_feeling
Definition city.h:275
@ FEELING_EFFECT
Definition city.h:278
@ FEELING_LUXURY
Definition city.h:277
@ FEELING_FINAL
Definition city.h:281
@ FEELING_LAST
Definition city.h:282
@ FEELING_BASE
Definition city.h:276
@ FEELING_NATIONALITY
Definition city.h:279
@ FEELING_MARTIAL
Definition city.h:280
void qtg_popdown_city_dialog(struct city *pcity)
Definition citydlg.cpp:3891
void qtg_real_city_dialog_refresh(struct city *pcity)
Definition citydlg.cpp:3911
QString split_text(QString text, bool cut)
Definition optiondlg.cpp:62
void city_font_update()
Definition citydlg.cpp:3925
bool qtg_city_dialog_is_open(struct city *pcity)
Definition citydlg.cpp:3966
QString get_tooltip(QVariant qvar)
Definition citydlg.cpp:4165
void qtg_popdown_all_city_dialogs()
Definition citydlg.cpp:3903
static city_dialog * city_dlg
Definition citydlg.cpp:75
void qtg_refresh_unit_city_dialogs(struct unit *punit)
Definition citydlg.cpp:3950
static QString bold(QString text)
Definition citydlg.cpp:4027
void qtg_real_city_dialog_popup(struct city *pcity)
Definition citydlg.cpp:3863
QString get_tooltip_improvement(const impr_type *building, struct city *pcity, bool ext)
Definition citydlg.cpp:4036
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:4095
void destroy_city_dialog()
Definition citydlg.cpp:3878
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)
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:1195
struct city * pcity
Definition citydlg.h:427
city_label(int type, QWidget *parent=nullptr)
Definition citydlg.cpp:1163
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:1171
int wdth
Definition citydlg.h:288
int cutted_height
Definition citydlg.h:291
QSize sizeHint() const
Definition citydlg.cpp:1294
void paintEvent(QPaintEvent *event)
Definition citydlg.cpp:1234
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:1310
int height
Definition citydlg.h:289
void set_pixmap(struct city *pcity, float z)
Definition citydlg.cpp:1258
void context_menu(QPoint point)
Definition citydlg.cpp:1332
canvas * miniview
Definition citydlg.h:275
struct city * mcity
Definition citydlg.h:285
QSize minimumSizeHint() const
Definition citydlg.cpp:1302
float zoom
Definition citydlg.h:287
QPixmap zoomed_pixmap
Definition citydlg.h:276
city_map(QWidget *parent)
Definition citydlg.cpp:1203
int cutted_width
Definition citydlg.h:290
int radius
Definition citydlg.h:286
int delta_y
Definition citydlg.h:293
int delta_x
Definition citydlg.h:292
city_production_delegate(QPoint sh, QObject *parent, struct city *city)
Definition citydlg.cpp:4203
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition citydlg.cpp:4216
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition citydlg.cpp:4372
struct city * pcity
Definition citydlg.h:319
void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect) const
Definition citydlg.cpp:4355
int rowCount(const QModelIndex &index=QModelIndex()) const
Definition citydlg.h:357
QList< production_item * > city_target_list
Definition citydlg.h:373
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::DisplayRole)
Definition citydlg.cpp:4542
int columnCount(const QModelIndex &parent=QModelIndex()) const
Definition citydlg.h:361
city_production_model(struct city *pcity, bool f, bool su, bool sw, bool sb, QObject *parent=nullptr)
Definition citydlg.cpp:4422
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const
Definition citydlg.cpp:4447
struct city * mcity
Definition citydlg.h:374
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:3982
void update_buildings()
Definition citydlg.cpp:555
QHBoxLayout * layout
Definition citydlg.h:261
void add_item(impr_item *item)
Definition citydlg.cpp:503
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:536
impr_info(QWidget *parent)
Definition citydlg.cpp:472
void clear_layout()
Definition citydlg.cpp:511
void init_layout()
Definition citydlg.cpp:482
QList< impr_item * > impr_list
Definition citydlg.h:262
void mouseDoubleClickEvent(QMouseEvent *event)
Definition citydlg.cpp:607
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:416
struct canvas * impr_pixmap
Definition citydlg.h:233
struct city * dlgcity
Definition citydlg.h:234
const struct impr_type * impr
Definition citydlg.h:232
void leaveEvent(QEvent *event)
Definition citydlg.cpp:446
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:587
struct universal * target
Definition citydlg.h:343
QVariant data() const
Definition citydlg.cpp:4406
production_item(struct universal *ptarget, QObject *parent)
Definition citydlg.cpp:4385
bool eventFilter(QObject *obj, QEvent *ev)
Definition citydlg.cpp:4652
void prod_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:4677
void mousePressEvent(QMouseEvent *event)
Definition citydlg.cpp:4639
city_production_model * list_model
Definition citydlg.h:388
struct city * pw_city
Definition citydlg.h:405
fc_tooltip * fc_tt
Definition citydlg.h:410
city_production_delegate * c_p_d
Definition citydlg.h:389
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:4565
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:1077
void init_layout()
Definition citydlg.cpp:1065
unit_info(bool supp)
Definition citydlg.cpp:1038
void add_item(unit_item *item)
Definition citydlg.cpp:1057
QHBoxLayout * layout
Definition citydlg.h:209
void update_units()
Definition citydlg.cpp:1096
void clear_layout()
Definition citydlg.cpp:1137
QList< unit_item * > unit_list
Definition citydlg.h:210
bool supports
Definition citydlg.h:213
QAction * activate
Definition citydlg.h:147
QAction * disband_action
Definition citydlg.h:145
void enterEvent(QEnterEvent *event)
Definition citydlg.cpp:966
void contextMenuEvent(QContextMenuEvent *ev)
Definition citydlg.cpp:738
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:1015
int happy_cost
Definition citydlg.h:168
void change_homecity()
Definition citydlg.cpp:924
QAction * unload
Definition citydlg.h:152
QAction * upgrade
Definition citydlg.h:153
bool supported
Definition citydlg.h:169
void fortify_unit()
Definition citydlg.cpp:955
void sentry_unit()
Definition citydlg.cpp:1028
QAction * unload_trans
Definition citydlg.h:154
void load_unit()
Definition citydlg.cpp:888
void wheelEvent(QWheelEvent *event)
Definition citydlg.cpp:995
QAction * load
Definition citydlg.h:151
void activate_unit()
Definition citydlg.cpp:945
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:792
void unload_all()
Definition citydlg.cpp:904
void disband()
Definition citydlg.cpp:870
void upgrade_unit()
Definition citydlg.cpp:912
void init_pix()
Definition citydlg.cpp:722
void leaveEvent(QEvent *event)
Definition citydlg.cpp:987
unit_item(QWidget *parent, struct unit *punit, bool supp=false, int happy_cost=0)
Definition citydlg.cpp:651
void unload_unit()
Definition citydlg.cpp:896
void activate_and_close_dialog()
Definition citydlg.cpp:934
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:819
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:913
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:2174
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:76
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:174
#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:5365
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:81
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:248
#define EC_NONE
Definition fc_types.h:820
@ TR_SUCCESS
Definition fc_types.h:953
#define ERM_NONE
Definition fc_types.h:843
@ O_SHIELD
Definition fc_types.h:102
@ O_FOOD
Definition fc_types.h:102
@ O_TRADE
Definition fc_types.h:102
@ O_SCIENCE
Definition fc_types.h:102
@ O_LUXURY
Definition fc_types.h:102
@ O_GOLD
Definition fc_types.h:102
@ O_LAST
Definition fc_types.h:102
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:739
struct civ_game game
Definition game.c:61
struct world wld
Definition game.c:62
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
GType type
Definition repodlgs.c:1313
void free_sprite(struct sprite *s)
Definition sprite.c:278
static GMenu * change_menu
Definition cityrep.c:116
static GMenu * options_menu
Definition menu.c:90
QString get_tooltip_improvement(const impr_type *building, struct city *pcity=nullptr, bool ext=false)
Definition citydlg.cpp:4036
QString get_tooltip(QVariant qvar)
Definition citydlg.cpp:4165
void set_theme_style()
Definition themes.cpp:107
#define CAPTURE_DEFAULT_THIS
Definition gui_main.h:31
#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:5047
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
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:52
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:444
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)
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:1229
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
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:3302
int current_building
Definition citydlg.h:513
void worklist_up()
Definition citydlg.cpp:3733
city_label * citizens_label
Definition citydlg.h:456
QPushButton * lcity_name
Definition citydlg.h:499
void show_happiness()
Definition citydlg.cpp:2125
void closeEvent(QCloseEvent *event)
Definition citydlg.cpp:2331
void show_counters()
Definition citydlg.cpp:2180
void update_nation_table()
Definition citydlg.cpp:3104
void hideEvent(QHideEvent *event)
Definition citydlg.cpp:2303
void cma_toggle_changed_depr(int state)
Definition citydlg.cpp:2714
void close_counters()
Definition citydlg.cpp:2160
QPushButton * work_next_but
Definition citydlg.h:487
void next_city()
Definition citydlg.cpp:3412
progress_bar * production_combo_p
Definition citydlg.h:471
QTableWidget * nationality_table
Definition citydlg.h:473
QRadioButton * r3
Definition citydlg.h:481
QTableWidget * cma_table
Definition citydlg.h:474
void showEvent(QShowEvent *event)
Definition citydlg.cpp:2314
QPushButton * happiness_button
Definition citydlg.h:491
void cma_double_clicked(int row, int column)
Definition citydlg.cpp:2507
void update_disabled()
Definition citydlg.cpp:2204
QLabel * supp_units
Definition citydlg.h:468
QPushButton * next_city_but
Definition citydlg.h:485
QLabel * qlt[NUM_INFO_FIELDS]
Definition citydlg.h:464
QPushButton * work_prev_but
Definition citydlg.h:488
QHBoxLayout * single_page_layout
Definition citydlg.h:445
QVBoxLayout * counters_layout
Definition citydlg.h:447
QWidget * counters_widget
Definition citydlg.h:462
void update_buy_button()
Definition citydlg.cpp:2895
int selected_row_p
Definition citydlg.h:500
QHBoxLayout * leftbot_layout
Definition citydlg.h:451
void update_building()
Definition citydlg.cpp:3484
QPushButton * zoom_in_button
Definition citydlg.h:493
void save_worklist()
Definition citydlg.cpp:3799
void worklist_del()
Definition citydlg.cpp:3758
QGridLayout * info_grid_layout
Definition citydlg.h:458
void clear_worklist()
Definition citydlg.cpp:3718
impr_info * city_buildings
Definition citydlg.h:498
QLabel * curr_impr
Definition citydlg.h:470
city_label * lab_table[6]
Definition citydlg.h:457
int scroll_height
Definition citydlg.h:509
QLabel * curr_units
Definition citydlg.h:469
unit_info * current_units
Definition citydlg.h:496
void zoom_out()
Definition citydlg.cpp:2422
void zoom_in()
Definition citydlg.cpp:2409
struct unit_node_vector supported_units
Definition citydlg.c:163
QPushButton * zoom_out_button
Definition citydlg.h:494
struct city * pcity
Definition citydlg.c:138
struct city_dialog::@148 happiness
void update_info_label()
Definition citydlg.cpp:3181
QPushButton * work_add_but
Definition citydlg.h:489
QSplitter * central_left_splitter
Definition citydlg.h:449
void disband_state_changed(bool allow_disband)
Definition citydlg.cpp:2750
void update_citizens()
Definition citydlg.cpp:2921
QRadioButton * r1
Definition citydlg.h:481
void cma_slider(int val)
Definition citydlg.cpp:2725
QCheckBox * cma_celeb_checkbox
Definition citydlg.h:475
QCheckBox * show_units
Definition citydlg.h:478
enum city_dialog::city_dialog_tab current_tab
void worklist_down()
Definition citydlg.cpp:3775
void update_title()
Definition citydlg.cpp:3830
QLabel * cma_info_text
Definition citydlg.h:465
void dbl_click_p(QTableWidgetItem *item)
Definition citydlg.cpp:3318
QPushButton * cma_enable_but
Definition citydlg.h:484
QLabel * cma_result
Definition citydlg.h:466
void cma_remove()
Definition citydlg.cpp:2675
QSlider * slider_tab[2 *O_LAST+2]
Definition citydlg.h:501
QPushButton * button
Definition citydlg.h:482
bool eventFilter(QObject *obj, QEvent *event)
Definition citydlg.cpp:2342
QSplitter * prod_unit_splitter
Definition citydlg.h:448
QVBoxLayout * left_layout
Definition citydlg.h:454
void prev_city()
Definition citydlg.cpp:3448
void city_rename()
Definition citydlg.cpp:2379
void refresh()
Definition citydlg.cpp:3005
void update_cma_tab()
Definition citydlg.cpp:2608
QPushButton * work_rem_but
Definition citydlg.h:490
float zoom
Definition citydlg.h:510
QSplitter * central_splitter
Definition citydlg.h:450
QWidget * prod_happ_widget
Definition citydlg.h:452
void show_targets()
Definition citydlg.cpp:3687
city_dialog(QWidget *parent=nullptr)
Definition citydlg.cpp:1482
void cma_toggle_changed(Qt::CheckState state)
Definition citydlg.cpp:2702
QWidget * top_widget
Definition citydlg.h:453
void update_tabs()
Definition citydlg.cpp:2111
QPushButton * prev_city_but
Definition citydlg.h:486
void cma_enable()
Definition citydlg.cpp:2471
QLabel * cma_result_pix
Definition citydlg.h:467
struct city * dlgcity
Definition citydlg.h:508
void update_counters_table()
Definition citydlg.cpp:3037
void update_sliders()
Definition citydlg.cpp:2556
void update_improvements()
Definition citydlg.cpp:3552
GtkWidget * worklist
Definition citydlg.c:176
QHBoxLayout * happiness_layout
Definition citydlg.h:446
QPushButton * settings_button
Definition citydlg.h:492
void display_settings_menu()
Definition citydlg.cpp:2791
QCheckBox * future_targets
Definition citydlg.h:477
void change_production(bool next)
Definition citydlg.cpp:2066
void cma_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:2526
QCheckBox * cma_max_growth
Definition citydlg.h:476
void item_selected(const QItemSelection &sl, const QItemSelection &ds)
Definition citydlg.cpp:3394
void show_targets_worklist()
Definition citydlg.cpp:3703
QCheckBox * show_wonders
Definition citydlg.h:480
void cma_context_menu(const QPoint &p)
Definition citydlg.cpp:2771
void cma_changed()
Definition citydlg.cpp:2486
QPushButton * buy_button
Definition citydlg.h:483
QRadioButton * r4
Definition citydlg.h:481
struct city_dialog::@149 counters
void update_units()
Definition citydlg.cpp:3335
QRadioButton * r2
Definition citydlg.h:481
QTableWidget * p_table_p
Definition citydlg.h:472
void save_cma()
Definition citydlg.cpp:2435
QPixmap * citizen_pixmap
Definition citydlg.h:495
void production_changed(int index)
Definition citydlg.cpp:3669
void update_prod_buttons()
Definition citydlg.cpp:2241
QWidget * happiness_widget
Definition citydlg.h:461
QGroupBox * happiness_group
Definition citydlg.h:460
QCheckBox * show_buildings
Definition citydlg.h:479
Definition city.h:317
struct worker_task_list * task_reqs
Definition city.h:409
int surplus[O_LAST]
Definition city.h:352
enum city_wl_cancel_behavior wlcb
Definition city.h:401
int food_stock
Definition city.h:364
int * counter_values
Definition city.h:405
int pollution
Definition city.h:366
int id
Definition city.h:323
int waste[O_LAST]
Definition city.h:353
struct unit_list * info_units_present
Definition city.h:471
struct unit_list * info_units_supported
Definition city.h:470
struct universal production
Definition city.h:393
int steal
Definition city.h:411
citizens size
Definition city.h:329
int culture
Definition city.h:462
int buy_cost
Definition city.h:463
struct city::@18::@21 client
struct tile * tile
Definition city.h:319
int shield_stock
Definition city.h:365
int prod[O_LAST]
Definition city.h:355
struct unit_list * units_supported
Definition city.h:403
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:521
int firepower
Definition unittype.h:530
const struct unit_type * obsoleted_by
Definition unittype.h:534
int vision_radius_sq
Definition unittype.h:527
int move_rate
Definition unittype.h:522
int attack_strength
Definition unittype.h:520
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:609
universals_u value
Definition fc_types.h:608
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:107
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:300
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
#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:7030
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:7234
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:6969
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7052
struct sprite * get_nation_flag_sprite(const struct tileset *t, const struct nation_type *pnation)
Definition tilespec.c:7003
struct sprite * get_tech_sprite(const struct tileset *t, Tech_type_id tech)
Definition tilespec.c:7021
@ ICON_CITYDLG
Definition tilespec.h:315
const struct unit_type * utype
Definition fc_types.h:554
const struct impr_type * building
Definition fc_types.h:547
bool can_unit_change_homecity(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:523
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:401
#define unit_tile(_pu)
Definition unit.h:406
#define unit_owner(_pu)
Definition unit.h:405
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:1472
bool utype_is_consumed_by_action_result(enum action_result result, const struct unit_type *utype)
Definition unittype.c:1233
struct advance * utype_primary_tech_req(const struct unit_type *ptype)
Definition unittype.c:2714
bool utype_can_do_action_result(const struct unit_type *putype, enum action_result result)
Definition unittype.c:391
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1442
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1564
const char * utype_values_translation(const struct unit_type *punittype)
Definition unittype.c:1621
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:771
#define utype_class(_t_)
Definition unittype.h:754
#define utype_fuel(ptype)
Definition unittype.h:844
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
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