Freeciv-3.3: /fast/freeciv/nightly/main/tools/ruledit/tab_tech.cpp Source File

Freeciv-3.3

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/**********************************************************************/
46tab_tech::tab_tech(ruledit_gui *ui_in) : QWidget()
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);
94 req1 = prepare_req_button(req1_button, AR_ONE);
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();
102 req2 = prepare_req_button(req2_button, AR_TWO);
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);
111 root_req = prepare_req_button(root_req_button, AR_ROOT);
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
124 delete_button = new QPushButton(QString::fromUtf8(R__("Remove this tech")), this);
125 connect(delete_button, SIGNAL(pressed()), this, SLOT(delete_now()));
126 tech_layout->addWidget(delete_button, row++, 2);
127
128 refresh();
129 update_tech_info(nullptr);
130
131 main_layout->addLayout(tech_layout);
132
133 setLayout(main_layout);
134}
135
136/**********************************************************************/
139 void tab_tech::refresh()
140{
141 tech_list->clear();
142
143 advance_re_active_iterate(padv) {
144 QListWidgetItem *item = new QListWidgetItem(advance_rule_name(padv));
145
146 tech_list->insertItem(advance_index(padv), item);
147 } advance_re_active_iterate_end;
148
149 techs_to_menu(req1);
150 techs_to_menu(req2);
151 techs_to_menu(root_req);
152}
153
154/**********************************************************************/
157QMenu *tab_tech::prepare_req_button(QToolButton *button, enum tech_req rn)
158{
159 QMenu *menu = new QMenu();
160
161 button->setToolButtonStyle(Qt::ToolButtonTextOnly);
162 button->setPopupMode(QToolButton::MenuButtonPopup);
163
164 switch (rn) {
165 case AR_ONE:
166 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(req1_menu(QAction *)));
167 break;
168 case AR_TWO:
169 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(req2_menu(QAction *)));
170 break;
171 case AR_ROOT:
172 connect(menu, SIGNAL(triggered(QAction *)), this, SLOT(root_req_menu(QAction *)));
173 break;
174 case AR_SIZE:
175 fc_assert(rn != AR_SIZE);
176 break;
177 }
178
179 button->setMenu(menu);
180
181 return menu;
182}
183
184/**********************************************************************/
187 void tab_tech::techs_to_menu(QMenu *fill_menu)
188{
189 fill_menu->clear();
190
191 advance_iterate_all(padv) {
192 fill_menu->addAction(tech_name(padv));
193 } advance_iterate_all_end;
194}
195
196/**********************************************************************/
199 QString tab_tech::tech_name(struct advance *padv)
200{
201 if (padv == A_NEVER) {
202 return QString::fromUtf8(R__("Never"));
203 }
204
205 return QString::fromUtf8(advance_rule_name(padv));
206}
207
208/**********************************************************************/
211 void tab_tech::update_tech_info(struct advance *adv)
212{
213 selected = adv;
214
215 if (selected != nullptr) {
216 QString dispn = QString::fromUtf8(untranslated_name(&(adv->name)));
217 QString rulen = QString::fromUtf8(rule_name_get(&(adv->name)));
218
219 name->setText(dispn);
220 rname->setText(rulen);
221
222 if (dispn == rulen) {
223 name->setEnabled(false);
224 same_name->setChecked(true);
225 } else {
226 same_name->setChecked(false);
227 name->setEnabled(true);
228 }
229
230 req1_button->setText(tech_name(adv->require[AR_ONE]));
231 req2_button->setText(tech_name(adv->require[AR_TWO]));
232 root_req_button->setText(tech_name(adv->require[AR_ROOT]));
233 } else {
234 name->setText(R__("None"));
235 rname->setText(R__("None"));
236 // FIXME: Could these be translated, or do we depend on
237 // them matching English rule_name of tech "None"?
238 req1_button->setText("None");
239 req2_button->setText("None");
240 root_req_button->setText("None");
241 same_name->setChecked(true);
242 name->setEnabled(false);
243 }
244}
245
246/**********************************************************************/
249 void tab_tech::select_tech()
250{
251 QList<QListWidgetItem *> select_list = tech_list->selectedItems();
252
253 if (!select_list.isEmpty()) {
254 QByteArray tn_bytes;
255
256 tn_bytes = select_list.at(0)->text().toUtf8();
257 update_tech_info(advance_by_rule_name(tn_bytes.data()));
258 }
259}
260
261/**********************************************************************/
264 void tab_tech::req1_jump()
265{
266 if (selected != 0 && advance_number(selected->require[AR_ONE]) != A_NONE) {
267 update_tech_info(selected->require[AR_ONE]);
268 }
269}
270
271/**********************************************************************/
274 void tab_tech::req2_jump()
275{
276 if (selected != 0 && advance_number(selected->require[AR_TWO]) != A_NONE) {
277 update_tech_info(selected->require[AR_TWO]);
278 }
279}
280
281/**********************************************************************/
284 void tab_tech::root_req_jump()
285{
286 if (selected != 0 && advance_number(selected->require[AR_ROOT]) != A_NONE) {
287 update_tech_info(selected->require[AR_ROOT]);
288 }
289}
290
291/**********************************************************************/
294 void tab_tech::req1_menu(QAction *action)
295{
296 struct advance *padv;
297 QByteArray an_bytes;
298
299 an_bytes = action->text().toUtf8();
300 padv = advance_by_rule_name(an_bytes.data());
301
302 if (padv != 0 && selected != 0) {
303 selected->require[AR_ONE] = padv;
304
305 update_tech_info(selected);
306 }
307}
308
309/**********************************************************************/
312 void tab_tech::req2_menu(QAction *action)
313{
314 struct advance *padv;
315 QByteArray an_bytes;
316
317 an_bytes = action->text().toUtf8();
318 padv = advance_by_rule_name(an_bytes.data());
319
320 if (padv != 0 && selected != 0) {
321 selected->require[AR_TWO] = padv;
322
323 update_tech_info(selected);
324 }
325}
326
327/**********************************************************************/
330 void tab_tech::root_req_menu(QAction *action)
331{
332 struct advance *padv;
333 QByteArray an_bytes;
334
335 an_bytes = action->text().toUtf8();
336 padv = advance_by_rule_name(an_bytes.data());
337
338 if (padv != 0 && selected != 0) {
339 selected->require[AR_ROOT] = padv;
340
341 update_tech_info(selected);
342 }
343}
344
345/**********************************************************************/
348 void tab_tech::name_given()
349{
350 if (selected != nullptr) {
351 QByteArray name_bytes;
352 QByteArray rname_bytes;
353
354 advance_iterate(padv) {
355 if (padv != selected
356 && padv->require[AR_ONE] != A_NEVER) {
357 rname_bytes = rname->text().toUtf8();
358 if (!strcmp(advance_rule_name(padv), rname_bytes.data())) {
359 ui->display_msg(R__("A tech with that rule name already exists!"));
360 return;
361 }
362 }
363 } advance_iterate_end;
364
365 if (same_name->isChecked()) {
366 name->setText(rname->text());
367 }
368
369 name_bytes = name->text().toUtf8();
370 rname_bytes = rname->text().toUtf8();
371 names_set(&(selected->name), 0,
372 name_bytes.data(),
373 rname_bytes.data());
374 refresh();
375 }
376}
377
378/**********************************************************************/
381 void tab_tech::delete_now()
382{
383 if (selected != 0) {
384 requirers_dlg *requirers;
385
386 requirers = ui->create_requirers(advance_rule_name(selected));
387 if (is_tech_needed(selected, &ruledit_qt_display_requirers, requirers)) {
388 return;
389 }
390
391 selected->require[AR_ONE] = A_NEVER;
392
393 if (selected->ruledit_dlg != nullptr) {
394 ((edit_tech *)selected->ruledit_dlg)->done(0);
395 }
396
397 refresh();
398 update_tech_info(nullptr);
399 }
400}
401
402/**********************************************************************/
405 bool tab_tech::initialize_new_tech(struct advance *padv)
406{
407 struct advance *none = advance_by_number(A_NONE);
408
409 if (advance_by_rule_name("New Tech") != nullptr) {
410 return false;
411 }
412
413 padv->require[AR_ONE] = none;
414 padv->require[AR_TWO] = none;
415 padv->require[AR_ROOT] = none;
416 name_set(&(padv->name), 0, "New Tech");
417 BV_CLR_ALL(padv->flags);
418
419 return true;
420}
421
422/**********************************************************************/
425 void tab_tech::add_now()
426{
427 struct advance *new_adv;
428
429 // Try to reuse freed tech slot
430 advance_iterate(padv) {
431 if (padv->require[AR_ONE] == A_NEVER) {
432 if (initialize_new_tech(padv)) {
433 update_tech_info(padv);
434 refresh();
435 }
436 return;
437 }
438 } advance_iterate_end;
439
440 // Try to add completely new tech
441 if (game.control.num_tech_types >= A_LAST) {
442 return;
443 }
444
445 // num_tech_types must be big enough to hold new tech or
446 // advance_by_number() fails.
447 game.control.num_tech_types++;
448 new_adv = advance_by_number(game.control.num_tech_types - 1);
449 if (initialize_new_tech(new_adv)) {
450 update_tech_info(new_adv);
451 refresh();
452 } else {
453 game.control.num_tech_types--; // Restore
454 }
455}
456
457/**********************************************************************/
460 void tab_tech::same_name_toggle(bool checked)
461{
462 name->setEnabled(!checked);
463 if (checked) {
464 name->setText(rname->text());
465 }
466}
467
468/**********************************************************************/
471 void tab_tech::edit_effects()
472{
473 if (selected != nullptr) {
474 struct universal uni;
475
476 uni.value.advance = selected;
477 uni.kind = VUT_ADVANCE;
478
479 ui->open_effect_edit(QString::fromUtf8(advance_rule_name(selected)),
480 &uni, EFMC_NORMAL);
481 }
482}
483
484/**********************************************************************/
487 void tab_tech::edit_now()
488{
489 if (selected != nullptr) {
490 if (selected->ruledit_dlg == nullptr) {
491 edit_tech *edit = new edit_tech(ui, selected);
492
493 edit->show();
494 selected->ruledit_dlg = edit;
495 } else {
496 ((edit_tech *)selected->ruledit_dlg)->raise();
497 }
498 }
499}
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
edit_tech
Definition edit_tech.h:35
requirers_dlg
Definition requirers_dlg.h:28
ruledit_gui
Definition ruledit_qt.h:97
ruledit_gui::display_msg
void display_msg(const char *msg)
Definition ruledit_qt.cpp:293
ruledit_gui::create_requirers
requirers_dlg * create_requirers(const char *title)
Definition ruledit_qt.cpp:301
ruledit_gui::open_effect_edit
void open_effect_edit(QString target, struct universal *uni, enum effect_filter_main_class efmc)
Definition ruledit_qt.cpp:404
tab_tech::same_name
QCheckBox * same_name
Definition tab_tech.h:62
tab_tech::root_req_button
QToolButton * root_req_button
Definition tab_tech.h:57
tab_tech::ui
ruledit_gui * ui
Definition tab_tech.h:48
tab_tech::edit_now
void edit_now()
Definition tab_tech.cpp:487
tab_tech::same_name_toggle
void same_name_toggle(bool checked)
Definition tab_tech.cpp:460
tab_tech::initialize_new_tech
bool initialize_new_tech(struct advance *padv)
Definition tab_tech.cpp:405
tab_tech::select_tech
void select_tech()
Definition tab_tech.cpp:249
tab_tech::req1_button
QToolButton * req1_button
Definition tab_tech.h:55
tab_tech::rname
QLineEdit * rname
Definition tab_tech.h:54
tab_tech::req1_menu
void req1_menu(QAction *action)
Definition tab_tech.cpp:294
tab_tech::edit_effects
void edit_effects()
Definition tab_tech.cpp:471
tab_tech::refresh
void refresh()
Definition tab_tech.cpp:139
tab_tech::selected
struct advance * selected
Definition tab_tech.h:64
tab_tech::delete_now
void delete_now()
Definition tab_tech.cpp:381
tab_tech::req1
QMenu * req1
Definition tab_tech.h:58
tab_tech::techs_to_menu
static void techs_to_menu(QMenu *fill_menu)
Definition tab_tech.cpp:187
tab_tech::name
QLineEdit * name
Definition tab_tech.h:53
tab_tech::add_now
void add_now()
Definition tab_tech.cpp:425
tab_tech::prepare_req_button
QMenu * prepare_req_button(QToolButton *button, enum tech_req rn)
Definition tab_tech.cpp:157
tab_tech::req2_jump
void req2_jump()
Definition tab_tech.cpp:274
tab_tech::req2_menu
void req2_menu(QAction *action)
Definition tab_tech.cpp:312
tab_tech::root_req_menu
void root_req_menu(QAction *action)
Definition tab_tech.cpp:330
tab_tech::req1_jump
void req1_jump()
Definition tab_tech.cpp:264
tab_tech::root_req_jump
void root_req_jump()
Definition tab_tech.cpp:284
tab_tech::name_given
void name_given()
Definition tab_tech.cpp:348
tab_tech::req2_button
QToolButton * req2_button
Definition tab_tech.h:56
tab_tech::root_req
QMenu * root_req
Definition tab_tech.h:60
tab_tech::tab_tech
tab_tech(ruledit_gui *ui_in)
Definition tab_tech.cpp:46
tab_tech::tech_name
static QString tech_name(struct advance *padv)
Definition tab_tech.cpp:199
tab_tech::tech_list
QListWidget * tech_list
Definition tab_tech.h:61
tab_tech::req2
QMenu * req2
Definition tab_tech.h:59
tab_tech::update_tech_info
void update_tech_info(struct advance *adv)
Definition tab_tech.cpp:211
incite_cost
char * incite_cost
Definition comments.c:74
edit_tech.h
EFMC_NORMAL
@ EFMC_NORMAL
Definition effect_edit.h:34
fcintl.h
R__
#define R__(String)
Definition fcintl.h:75
game
struct civ_game game
Definition game.c:61
game.h
edit
#define edit(pedit)
Definition widget_edit.h:34
log.h
fc_assert
#define fc_assert(condition)
Definition log.h:176
name_set
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
Definition name_translation.h:88
rule_name_get
static const char * rule_name_get(const struct name_translation *ptrans)
Definition name_translation.h:112
untranslated_name
static const char * untranslated_name(const struct name_translation *ptrans)
Definition name_translation.h:104
names_set
static void names_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name, const char *rule_name)
Definition name_translation.h:60
ruledit.h
ruledit_qt_display_requirers
void ruledit_qt_display_requirers(const char *msg, void *data)
Definition ruledit_qt.cpp:97
ruledit_qt.h
action
Definition actions.h:106
advance
Definition tech.h:124
advance::ruledit_dlg
void * ruledit_dlg
Definition tech.h:127
advance::require
struct advance * require[AR_SIZE]
Definition tech.h:132
advance::name
struct name_translation name
Definition tech.h:126
civ_game::control
struct packet_ruleset_control control
Definition game.h:83
item
Definition climisc.h:80
packet_ruleset_control::num_tech_types
int num_tech_types
Definition packets_gen.h:1441
universal
Definition fc_types.h:878
universal::kind
enum universals_n kind
Definition fc_types.h:880
universal::value
universals_u value
Definition fc_types.h:879
tab_tech.h
advance_by_number
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
advance_rule_name
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:309
advance_index
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
advance_by_rule_name
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
advance_number
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
tech.h
advance_re_active_iterate
#define advance_re_active_iterate(_p)
Definition tech.h:282
A_NEVER
#define A_NEVER
Definition tech.h:51
advance_iterate_all_end
#define advance_iterate_all_end
Definition tech.h:280
tech_req
tech_req
Definition tech.h:110
AR_TWO
@ AR_TWO
Definition tech.h:112
AR_ROOT
@ AR_ROOT
Definition tech.h:113
AR_ONE
@ AR_ONE
Definition tech.h:111
AR_SIZE
@ AR_SIZE
Definition tech.h:114
advance_re_active_iterate_end
#define advance_re_active_iterate_end
Definition tech.h:286
advance_iterate_all
#define advance_iterate_all(_p)
Definition tech.h:279
A_NONE
#define A_NONE
Definition tech.h:43
advance_iterate
#define advance_iterate(_p)
Definition tech.h:276
advance_iterate_end
#define advance_iterate_end
Definition tech.h:277
A_LAST
#define A_LAST
Definition tech.h:45
universals_u::advance
struct advance * advance
Definition fc_types.h:688
is_tech_needed
bool is_tech_needed(struct advance *padv, requirers_cb cb, void *data)
Definition validity.c:199
validity.h