Freeciv-3.1
Loading...
Searching...
No Matches
tab_tech.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 <QCheckBox>
20#include <QGridLayout>
21#include <QLineEdit>
22#include <QListWidget>
23#include <QMenu>
24#include <QPushButton>
25#include <QToolButton>
26
27// utility
28#include "fcintl.h"
29#include "log.h"
30
31// common
32#include "game.h"
33#include "tech.h"
34
35// ruledit
36#include "edit_tech.h"
37#include "ruledit.h"
38#include "ruledit_qt.h"
39#include "validity.h"
40
41#include "tab_tech.h"
42
43/**********************************************************************/
47{
48 QVBoxLayout *main_layout = new QVBoxLayout(this);
49 QGridLayout *tech_layout = new QGridLayout();
50 QLabel *label;
51 QPushButton *effects_button;
52 QPushButton *add_button;
53 QPushButton *delete_button;
54 QPushButton *edit_button;
55 int row = 0;
56
57 ui = ui_in;
58 selected = 0;
59
60 tech_list = new QListWidget(this);
61
62 connect(tech_list, SIGNAL(itemSelectionChanged()), this, SLOT(select_tech()));
63 main_layout->addWidget(tech_list);
64
65 tech_layout->setSizeConstraint(QLayout::SetMaximumSize);
66
67 label = new QLabel(QString::fromUtf8(R__("Rule Name")));
68 label->setParent(this);
69 rname = new QLineEdit(this);
70 rname->setText(R__("None"));
71 connect(rname, SIGNAL(returnPressed()), this, SLOT(name_given()));
72 tech_layout->addWidget(label, row, 0);
73 tech_layout->addWidget(rname, row++, 2);
74
75 label = new QLabel(QString::fromUtf8(R__("Name")));
76 label->setParent(this);
77 same_name = new QCheckBox();
78 connect(same_name, SIGNAL(toggled(bool)), this, SLOT(same_name_toggle(bool)));
79 name = new QLineEdit(this);
80 name->setText(R__("None"));
81 connect(name, SIGNAL(returnPressed()), this, SLOT(name_given()));
82 tech_layout->addWidget(label, row, 0);
83 tech_layout->addWidget(same_name, row, 1);
84 tech_layout->addWidget(name, row++, 2);
85
86 edit_button = new QPushButton(QString::fromUtf8(R__("Edit Values")), this);
87 connect(edit_button, SIGNAL(pressed()), this, SLOT(edit_now()));
88 tech_layout->addWidget(edit_button, row++, 2);
89
90 label = new QLabel(QString::fromUtf8(R__("Req1")));
91 label->setParent(this);
92 req1_button = new QToolButton();
93 req1_button->setParent(this);
95 connect(req1_button, SIGNAL(pressed()), this, SLOT(req1_jump()));
96 tech_layout->addWidget(label, row, 0);
97 tech_layout->addWidget(req1_button, row++, 2);
98
99 label = new QLabel(QString::fromUtf8(R__("Req2")));
100 label->setParent(this);
101 req2_button = new QToolButton();
103 connect(req2_button, SIGNAL(pressed()), this, SLOT(req2_jump()));
104 tech_layout->addWidget(label, row, 0);
105 tech_layout->addWidget(req2_button, row++, 2);
106
107 label = new QLabel(QString::fromUtf8(R__("Root Req")));
108 label->setParent(this);
109 root_req_button = new QToolButton();
110 root_req_button->setParent(this);
112 connect(root_req_button, SIGNAL(pressed()), this, SLOT(root_req_jump()));
113 tech_layout->addWidget(label, row, 0);
114 tech_layout->addWidget(root_req_button, row++, 2);
115
116 effects_button = new QPushButton(QString::fromUtf8(R__("Effects")), this);
117 connect(effects_button, SIGNAL(pressed()), this, SLOT(edit_effects()));
118 tech_layout->addWidget(effects_button, row++, 2);
119
120 add_button = new QPushButton(QString::fromUtf8(R__("Add tech")), this);
121 connect(add_button, SIGNAL(pressed()), this, SLOT(add_now()));
122 tech_layout->addWidget(add_button, row, 0);
123 show_experimental(add_button);
124
125 delete_button = new QPushButton(QString::fromUtf8(R__("Remove this tech")), this);
126 connect(delete_button, SIGNAL(pressed()), this, SLOT(delete_now()));
127 tech_layout->addWidget(delete_button, row++, 2);
128 show_experimental(delete_button);
129
130 refresh();
131 update_tech_info(nullptr);
132
133 main_layout->addLayout(tech_layout);
134
135 setLayout(main_layout);
136}
137
138/**********************************************************************/
142{
143 tech_list->clear();
144
146 QListWidgetItem *item = new QListWidgetItem(advance_rule_name(padv));
147
148 tech_list->insertItem(advance_index(padv), item);
150
154}
155
156/**********************************************************************/
159QMenu *tab_tech::prepare_req_button(QToolButton *button, enum tech_req rn)
160{
161 QMenu *menu = new QMenu();
162
163 button->setToolButtonStyle(Qt::ToolButtonTextOnly);
164 button->setPopupMode(QToolButton::MenuButtonPopup);
165
166 switch (rn) {
167 case AR_ONE:
168 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(req1_menu(QAction *)));
169 break;
170 case AR_TWO:
171 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(req2_menu(QAction *)));
172 break;
173 case AR_ROOT:
174 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(root_req_menu(QAction *)));
175 break;
176 case AR_SIZE:
177 fc_assert(rn != AR_SIZE);
178 break;
179 }
180
181 button->setMenu(menu);
182
183 return menu;
184}
185
186/**********************************************************************/
189void tab_tech::techs_to_menu(QMenu *fill_menu)
190{
191 fill_menu->clear();
192
193 advance_iterate(A_NONE, padv) {
194 fill_menu->addAction(tech_name(padv));
196}
197
198/**********************************************************************/
201QString tab_tech::tech_name(struct advance *padv)
202{
203 if (padv == A_NEVER) {
204 return QString::fromUtf8(R__("Never"));
205 }
206
207 return QString::fromUtf8(advance_rule_name(padv));
208}
209
210/**********************************************************************/
214{
215 selected = adv;
216
217 if (selected != nullptr) {
218 QString dispn = QString::fromUtf8(untranslated_name(&(adv->name)));
219 QString rulen = QString::fromUtf8(rule_name_get(&(adv->name)));
220
221 name->setText(dispn);
222 rname->setText(rulen);
223
224 if (dispn == rulen) {
225 name->setEnabled(false);
226 same_name->setChecked(true);
227 } else {
228 same_name->setChecked(false);
229 name->setEnabled(true);
230 }
231
232 req1_button->setText(tech_name(adv->require[AR_ONE]));
233 req2_button->setText(tech_name(adv->require[AR_TWO]));
234 root_req_button->setText(tech_name(adv->require[AR_ROOT]));
235 } else {
236 name->setText(R__("None"));
237 rname->setText(R__("None"));
238 // FIXME: Could these be translated, or do we depend on
239 // them matching English rule_name of tech "None"?
240 req1_button->setText("None");
241 req2_button->setText("None");
242 root_req_button->setText("None");
243 same_name->setChecked(true);
244 name->setEnabled(false);
245 }
246}
247
248/**********************************************************************/
252{
253 QList<QListWidgetItem *> select_list = tech_list->selectedItems();
254
255 if (!select_list.isEmpty()) {
256 QByteArray tn_bytes;
257
258 tn_bytes = select_list.at(0)->text().toUtf8();
259 update_tech_info(advance_by_rule_name(tn_bytes.data()));
260 }
261}
262
263/**********************************************************************/
272
273/**********************************************************************/
282
283/**********************************************************************/
292
293/**********************************************************************/
297{
298 struct advance *padv;
299 QByteArray an_bytes;
300
301 an_bytes = action->text().toUtf8();
302 padv = advance_by_rule_name(an_bytes.data());
303
304 if (padv != 0 && selected != 0) {
305 selected->require[AR_ONE] = padv;
306
308 }
309}
310
311/**********************************************************************/
315{
316 struct advance *padv;
317 QByteArray an_bytes;
318
319 an_bytes = action->text().toUtf8();
320 padv = advance_by_rule_name(an_bytes.data());
321
322 if (padv != 0 && selected != 0) {
323 selected->require[AR_TWO] = padv;
324
326 }
327}
328
329/**********************************************************************/
333{
334 struct advance *padv;
335 QByteArray an_bytes;
336
337 an_bytes = action->text().toUtf8();
338 padv = advance_by_rule_name(an_bytes.data());
339
340 if (padv != 0 && selected != 0) {
341 selected->require[AR_ROOT] = padv;
342
344 }
345}
346
347/**********************************************************************/
351{
352 if (selected != nullptr) {
353 QByteArray name_bytes;
354 QByteArray rname_bytes;
355
356 advance_iterate(A_FIRST, padv) {
357 if (padv != selected
358 && padv->require[AR_ONE] != A_NEVER) {
359 rname_bytes = rname->text().toUtf8();
360 if (!strcmp(advance_rule_name(padv), rname_bytes.data())) {
361 ui->display_msg(R__("A tech with that rule name already exists!"));
362 return;
363 }
364 }
366
367 if (same_name->isChecked()) {
368 name->setText(rname->text());
369 }
370
371 name_bytes = name->text().toUtf8();
372 rname_bytes = rname->text().toUtf8();
373 names_set(&(selected->name), 0,
374 name_bytes.data(),
375 rname_bytes.data());
376 refresh();
377 }
378}
379
380/**********************************************************************/
384{
385 if (selected != 0) {
386 requirers_dlg *requirers;
387
390 return;
391 }
392
394
395 if (selected->ruledit_dlg != nullptr) {
396 ((edit_tech *)selected->ruledit_dlg)->done(0);
397 }
398
399 refresh();
400 update_tech_info(nullptr);
401 }
402}
403
404/**********************************************************************/
408{
409 struct advance *none = advance_by_number(A_NONE);
410
411 if (advance_by_rule_name("New Tech") != nullptr) {
412 return false;
413 }
414
415 padv->require[AR_ONE] = none;
416 padv->require[AR_TWO] = none;
417 padv->require[AR_ROOT] = none;
418 name_set(&(padv->name), 0, "New Tech");
419 BV_CLR_ALL(padv->flags);
420 if (padv->helptext != nullptr) {
421 strvec_clear(padv->helptext);
422 }
423
424 return true;
425}
426
427/**********************************************************************/
431{
432 struct advance *new_adv;
433
434 // Try to reuse freed tech slot
435 advance_iterate(A_FIRST, padv) {
436 if (padv->require[AR_ONE] == A_NEVER) {
437 if (initialize_new_tech(padv)) {
438 update_tech_info(padv);
439 refresh();
440 }
441 return;
442 }
444
445 // Try to add completely new tech
447 return;
448 }
449
450 // num_tech_types must be big enough to hold new tech or
451 // advance_by_number() fails.
454 if (initialize_new_tech(new_adv)) {
455 update_tech_info(new_adv);
456 refresh();
457 } else {
458 game.control.num_tech_types--; // Restore
459 }
460}
461
462/**********************************************************************/
466{
467 name->setEnabled(!checked);
468 if (checked) {
469 name->setText(rname->text());
470 }
471}
472
473/**********************************************************************/
477{
478 if (selected != nullptr) {
479 struct universal uni;
480
481 uni.value.advance = selected;
482 uni.kind = VUT_ADVANCE;
483
484 ui->open_effect_edit(QString::fromUtf8(advance_rule_name(selected)),
485 &uni, EFMC_NORMAL);
486 }
487}
488
489/**********************************************************************/
493{
494 if (selected != nullptr) {
495 if (selected->ruledit_dlg == nullptr) {
497
498 edit->show();
500 } else {
501 ((edit_tech *)selected->ruledit_dlg)->raise();
502 }
503 }
504}
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
void display_msg(const char *msg)
requirers_dlg * create_requirers(const char *title)
void open_effect_edit(QString target, struct universal *uni, enum effect_filter_main_class efmc)
QCheckBox * same_name
Definition tab_tech.h:62
QToolButton * root_req_button
Definition tab_tech.h:57
ruledit_gui * ui
Definition tab_tech.h:48
void edit_now()
Definition tab_tech.cpp:492
void same_name_toggle(bool checked)
Definition tab_tech.cpp:465
bool initialize_new_tech(struct advance *padv)
Definition tab_tech.cpp:407
void select_tech()
Definition tab_tech.cpp:251
QToolButton * req1_button
Definition tab_tech.h:55
QLineEdit * rname
Definition tab_tech.h:54
void req1_menu(QAction *action)
Definition tab_tech.cpp:296
void edit_effects()
Definition tab_tech.cpp:476
void refresh()
Definition tab_tech.cpp:141
struct advance * selected
Definition tab_tech.h:64
void delete_now()
Definition tab_tech.cpp:383
QMenu * req1
Definition tab_tech.h:58
static void techs_to_menu(QMenu *fill_menu)
Definition tab_tech.cpp:189
QLineEdit * name
Definition tab_tech.h:53
void add_now()
Definition tab_tech.cpp:430
QMenu * prepare_req_button(QToolButton *button, enum tech_req rn)
Definition tab_tech.cpp:159
void req2_jump()
Definition tab_tech.cpp:276
void req2_menu(QAction *action)
Definition tab_tech.cpp:314
void root_req_menu(QAction *action)
Definition tab_tech.cpp:332
void req1_jump()
Definition tab_tech.cpp:266
void root_req_jump()
Definition tab_tech.cpp:286
void name_given()
Definition tab_tech.cpp:350
QToolButton * req2_button
Definition tab_tech.h:56
QMenu * root_req
Definition tab_tech.h:60
tab_tech(ruledit_gui *ui_in)
Definition tab_tech.cpp:46
static QString tech_name(struct advance *padv)
Definition tab_tech.cpp:201
QListWidget * tech_list
Definition tab_tech.h:61
QMenu * req2
Definition tab_tech.h:59
void update_tech_info(struct advance *adv)
Definition tab_tech.cpp:213
@ EFMC_NORMAL
Definition effect_edit.h:33
#define R__(String)
Definition fcintl.h:75
struct civ_game game
Definition game.c:57
#define fc_assert(condition)
Definition log.h:176
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * untranslated_name(const struct name_translation *ptrans)
static void names_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name, const char *rule_name)
void show_experimental(QWidget *wdg)
Definition ruledit.cpp:216
void ruledit_qt_display_requirers(const char *msg, void *data)
void strvec_clear(struct strvec *psv)
void * ruledit_dlg
Definition tech.h:127
struct advance * require[AR_SIZE]
Definition tech.h:132
struct name_translation name
Definition tech.h:126
struct strvec * helptext
Definition tech.h:140
bv_tech_flags flags
Definition tech.h:139
struct packet_ruleset_control control
Definition game.h:83
Definition climisc.h:82
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
#define advance_re_active_iterate(_p)
Definition tech.h:275
#define A_NEVER
Definition tech.h:51
tech_req
Definition tech.h:110
@ AR_TWO
Definition tech.h:112
@ AR_ROOT
Definition tech.h:113
@ AR_ONE
Definition tech.h:111
@ AR_SIZE
Definition tech.h:114
#define advance_re_active_iterate_end
Definition tech.h:279
#define advance_iterate(_start, _p)
Definition tech.h:264
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate_end
Definition tech.h:270
#define A_LAST
Definition tech.h:45
struct advance * advance
Definition fc_types.h:596
bool is_tech_needed(struct advance *padv, requirers_cb cb, void *data)
Definition validity.c:189
#define edit(pedit)
Definition widget_edit.h:34