Freeciv21
Develop your civilization from humble roots to a global empire
ruledit_qt.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2022 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <fc_config.h>
15 
16 // Qt
17 #include <QApplication>
18 #include <QCloseEvent>
19 #include <QLabel>
20 #include <QLineEdit>
21 #include <QMainWindow>
22 #include <QMessageBox>
23 #include <QPushButton>
24 #include <QStackedLayout>
25 #include <QVBoxLayout>
26 
27 // utility
28 #include "fcintl.h"
29 #include "log.h"
30 #include "registry.h"
31 #include "version.h"
32 
33 // common
34 #include "game.h"
35 #include "version.h"
36 
37 // server
38 #include "ruleset.h"
39 
40 // ruledit
41 #include "conversion_log.h"
42 #include "effect_edit.h"
43 #include "req_edit.h"
44 #include "req_vec_fix.h"
45 #include "requirers_dlg.h"
46 #include "ruledit.h"
47 #include "tab_building.h"
48 #include "tab_enablers.h"
49 #include "tab_extras.h"
50 #include "tab_good.h"
51 #include "tab_gov.h"
52 #include "tab_misc.h"
53 #include "tab_multiplier.h"
54 #include "tab_nation.h"
55 #include "tab_tech.h"
56 #include "tab_terrains.h"
57 #include "tab_unit.h"
58 
59 #include "ruledit_qt.h"
60 
61 static ruledit_gui *gui;
63 
67 void ruledit_qt_display_requirers(const char *msg, void *data)
68 {
69  requirers_dlg *requirers = (requirers_dlg *) data;
70 
71  gui->show_required(requirers, msg);
72 }
73 
78 {
79  QVBoxLayout *full_layout = new QVBoxLayout();
80  QVBoxLayout *preload_layout = new QVBoxLayout();
81  QWidget *preload_widget = new QWidget();
82  QVBoxLayout *edit_layout = new QVBoxLayout();
83  QWidget *edit_widget = new QWidget();
84  QPushButton *ruleset_accept;
85  QLabel *rs_label;
86 
87  data.nationlist = nullptr;
88  data.nationlist_saved = nullptr;
89 
90  auto *central = new QWidget;
91  main->setCentralWidget(central);
92 
93  main_layout = new QStackedLayout();
94 
95  preload_layout->setSizeConstraint(QLayout::SetMaximumSize);
96 
97  auto version_label =
98  new QLabel(QString(_("Version %1")).arg(freeciv21_version()));
99  version_label->setAlignment(Qt::AlignHCenter);
100  version_label->setParent(central);
101  preload_layout->addWidget(version_label);
102  rs_label = new QLabel(
103  QString::fromUtf8(R__("Give ruleset to use as starting point.")));
104  rs_label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
105  preload_layout->addWidget(rs_label);
106  ruleset_select = new QLineEdit(central);
107  if (reargs.ruleset.isEmpty()) {
108  ruleset_select->setText(reargs.ruleset);
109  } else {
111  }
112  connect(ruleset_select, &QLineEdit::returnPressed, this,
114  preload_layout->addWidget(ruleset_select);
115  ruleset_accept = new QPushButton(QString::fromUtf8(R__("Start editing")));
116  connect(ruleset_accept, &QAbstractButton::pressed, this,
118  preload_layout->addWidget(ruleset_accept);
119 
120  preload_widget->setLayout(preload_layout);
121  main_layout->addWidget(preload_widget);
122 
123  stack = new QTabWidget(central);
124 
125  misc = new tab_misc(this);
126  stack->addTab(misc, QString::fromUtf8(R__("Misc")));
127  tech = new tab_tech(this);
128  stack->addTab(tech, QString::fromUtf8(R__("Tech")));
129  bldg = new tab_building(this);
130  stack->addTab(bldg, QString::fromUtf8(R__("Buildings")));
131  unit = new tab_unit(this);
132  stack->addTab(unit, QString::fromUtf8(R__("Units")));
133  good = new tab_good(this);
134  stack->addTab(good, QString::fromUtf8(R__("Goods")));
135  gov = new tab_gov(this);
136  stack->addTab(gov, QString::fromUtf8(R__("Governments")));
137  enablers = new tab_enabler(this);
138  stack->addTab(enablers, QString::fromUtf8(R__("Enablers")));
139  extras = new tab_extras(this);
140  stack->addTab(extras, QString::fromUtf8(R__("Extras")));
141  terrains = new tab_terrains(this);
142  stack->addTab(terrains, QString::fromUtf8(R__("Terrains")));
143  multipliers = new tab_multiplier(this);
144  stack->addTab(multipliers, QString::fromUtf8(R__("Multipliers")));
145  nation = new tab_nation(this);
146  stack->addTab(nation, QString::fromUtf8(R__("Nations")));
147 
148  edit_layout->addWidget(stack);
149 
150  edit_widget->setLayout(edit_layout);
151  main_layout->addWidget(edit_widget);
152 
153  full_layout->addLayout(main_layout);
154 
155  msg_dspl =
156  new QLabel(QString::fromUtf8(R__("Welcome to freeciv21-ruledit")));
157  msg_dspl->setParent(central);
158 
159  msg_dspl->setAlignment(Qt::AlignHCenter);
160 
161  full_layout->addWidget(msg_dspl);
162 
163  central->setLayout(full_layout);
164 
165  req_edits = req_edit_list_new();
166  this->req_vec_fixers = req_vec_fix_list_new();
167  effect_edits = effect_edit_list_new();
168 
169  // FIXME Should get rid of the static variable.
170  gui = this;
171 }
172 
177 {
178  req_edit_list_destroy(req_edits);
179  req_vec_fix_list_destroy(req_vec_fixers);
180  effect_edit_list_destroy(effect_edits);
181 }
182 
186 static void conversion_log_cb(const char *msg) { convlog->add(msg); }
187 
192 {
193  QByteArray rn_bytes;
194 
195  convlog = new conversion_log();
196 
197  rn_bytes = ruleset_select->text().toUtf8();
198  sz_strlcpy(game.server.rulesetdir, rn_bytes.data());
199 
200  if (load_rulesets(nullptr, nullptr, true, conversion_log_cb, false, true,
201  true)) {
202  display_msg(R__("Ruleset loaded"));
203 
204  // Make freeable copy
205  if (game.server.ruledit.nationlist != nullptr) {
206  data.nationlist = fc_strdup(game.server.ruledit.nationlist);
207  } else {
208  data.nationlist = nullptr;
209  }
210 
211  bldg->refresh();
212  misc->refresh();
213  nation->refresh();
214  tech->refresh();
215  unit->refresh();
216  good->refresh();
217  gov->refresh();
218  enablers->refresh();
219  extras->refresh();
220  multipliers->refresh();
221  terrains->refresh();
222  main_layout->setCurrentIndex(1);
223  } else {
224  display_msg(R__("Ruleset loading failed!"));
225  }
226 }
227 
232 void ruledit_gui::incoming_rec_vec_change(const requirement_vector *vec)
233 {
234  emit rec_vec_may_have_changed(vec);
235 }
236 
240 void ruledit_gui::display_msg(const char *msg)
241 {
242  msg_dspl->setText(QString::fromUtf8(msg));
243 }
244 
249 {
250  requirers_dlg *requirers;
251 
252  requirers = new requirers_dlg(this);
253 
254  requirers->clear(title);
255 
256  return requirers;
257 }
258 
262 void ruledit_gui::show_required(requirers_dlg *requirers, const char *msg)
263 {
264  requirers->add(msg);
265 
266  // Show dialog if not already visible
267  requirers->show();
268 }
269 
274 
278 void ruledit_gui::open_req_edit(const QString &target,
279  struct requirement_vector *preqs)
280 {
281  req_edit *redit;
282 
284  {
285  if (old_edit->req_vector == preqs) {
286  // Already open
287  return;
288  }
289  }
291 
292  redit = new req_edit(this, target, preqs);
293 
294  redit->show();
295 
296  connect(redit, &req_edit::rec_vec_may_have_changed, this,
298 
299  req_edit_list_append(req_edits, redit);
300 }
301 
306 {
307  req_edit_list_remove(req_edits, redit);
308 }
309 
314 {
315  req_vec_fix *fixer;
316 
318  {
319  if (old_fixer->item() == item_info->item()) {
320  item_info->close();
321 
322  // Already open
323  return;
324  }
325  }
327 
328  fixer = new req_vec_fix(this, item_info);
329 
330  fixer->refresh();
331  fixer->show();
332 
333  connect(fixer, &req_vec_fix::rec_vec_may_have_changed, this,
335 
336  req_vec_fix_list_append(req_vec_fixers, fixer);
337 }
338 
343 {
344  req_vec_fix_list_remove(req_vec_fixers, fixer);
345 }
346 
350 void ruledit_gui::open_effect_edit(const QString &target,
351  struct universal *uni,
352  enum effect_filter_main_class efmc)
353 {
354  effect_edit *e_edit;
355 
357  {
358  struct universal *old = old_edit->filter_get();
359 
360  if (uni != nullptr) {
361  if (are_universals_equal(old, uni)) {
362  // Already open
363  return;
364  }
365  } else if (old->kind == VUT_NONE && old_edit->efmc == efmc) {
366  // Already open
367  return;
368  }
369  }
371 
372  e_edit = new effect_edit(this, target, uni, efmc);
373 
374  e_edit->show();
375 
376  effect_edit_list_append(effect_edits, e_edit);
377 }
378 
383 {
384  effect_edit_list_remove(effect_edits, e_edit);
385 }
386 
391 {
392  effect_edit_list_iterate(effect_edits, e_edit) { e_edit->refresh(); }
394 }
395 
399 ruledit_main::ruledit_main() : QMainWindow()
400 {
401  const QString title = QString::fromUtf8(R__("Freeciv21 Ruleset Editor"));
402 
403  setWindowTitle(title);
404 }
405 
409 void ruledit_main::closeEvent(QCloseEvent *cevent)
410 {
411  // Ask for confirmation
412  QMessageBox ask(centralWidget());
413  int ret;
414 
415  ask.setText(R__("Are you sure you want to quit?"));
416  ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
417  ask.setDefaultButton(QMessageBox::Cancel);
418  ask.setIcon(QMessageBox::Warning);
419  ask.setWindowTitle(R__("Quit?"));
420  ret = ask.exec();
421 
422  switch (ret) {
423  case QMessageBox::Cancel:
424  // Cancelled by user
425  cevent->ignore();
426  break;
427  case QMessageBox::Ok:
428  close();
429  break;
430  }
431 }
void add(const char *msg)
Add entry.
void rec_vec_may_have_changed(const requirement_vector *vec)
A requirement vector may have been changed.
Ruleset entity specific methods for the ruleset item having its requirements fixed.
Definition: req_vec_fix.h:44
virtual void close()=0
Tell the helper that it has outlived its usefulness.
virtual const void * item()=0
Returns a pointer to the ruleset item.
Widget for solving requirement vector problems for a ruleset item.
Definition: req_vec_fix.h:146
void rec_vec_may_have_changed(const requirement_vector *vec)
A requirement vector may have been changed.
bool refresh()
Find the next requirement vector problem and its suggested solutions.
void clear(const char *title)
Clear text area.
void add(const char *msg)
Add requirer entry.
tab_nation * nation
Definition: ruledit_qt.h:132
void open_req_vec_fix(req_vec_fix_item *item_info)
Open req_vec_fix dialog.
Definition: ruledit_qt.cpp:313
tab_good * good
Definition: ruledit_qt.h:126
tab_enabler * enablers
Definition: ruledit_qt.h:128
void unregister_effect_edit(class effect_edit *e_edit)
Unregisted closed effect_edit dialog.
Definition: ruledit_qt.cpp:382
void flush_widgets()
Flush information from widgets to stores where it can be saved from.
Definition: ruledit_qt.cpp:273
void rec_vec_may_have_changed(const requirement_vector *vec)
A requirement vector may have been changed.
tab_multiplier * multipliers
Definition: ruledit_qt.h:130
QStackedLayout * main_layout
Definition: ruledit_qt.h:120
struct rule_data data
Definition: ruledit_qt.h:107
tab_misc * misc
Definition: ruledit_qt.h:123
struct effect_edit_list * effect_edits
Definition: ruledit_qt.h:136
tab_extras * extras
Definition: ruledit_qt.h:129
tab_terrains * terrains
Definition: ruledit_qt.h:131
void display_msg(const char *msg)
Display status message.
Definition: ruledit_qt.cpp:240
void refresh_effect_edits()
Refresh all effect edit dialogs.
Definition: ruledit_qt.cpp:390
tab_gov * gov
Definition: ruledit_qt.h:127
ruledit_gui(ruledit_main *main)
Setup GUI object.
Definition: ruledit_qt.cpp:77
void incoming_rec_vec_change(const requirement_vector *vec)
A requirement vector may have been changed.
Definition: ruledit_qt.cpp:232
void unregister_req_vec_fix(req_vec_fix *fixer)
Unregister closed req_vec_fix dialog.
Definition: ruledit_qt.cpp:342
void open_req_edit(const QString &target, struct requirement_vector *preqs)
Open req_edit dialog.
Definition: ruledit_qt.cpp:278
tab_building * bldg
Definition: ruledit_qt.h:122
requirers_dlg * create_requirers(const char *title)
Create requirers dlg.
Definition: ruledit_qt.cpp:248
tab_tech * tech
Definition: ruledit_qt.h:124
void launch_now()
User entered savedir.
Definition: ruledit_qt.cpp:191
struct req_edit_list * req_edits
Definition: ruledit_qt.h:134
QTabWidget * stack
Definition: ruledit_qt.h:118
struct req_vec_fix_list * req_vec_fixers
Definition: ruledit_qt.h:135
void show_required(requirers_dlg *requirers, const char *msg)
Add entry to requirers dlg.
Definition: ruledit_qt.cpp:262
QLabel * msg_dspl
Definition: ruledit_qt.h:117
QLineEdit * ruleset_select
Definition: ruledit_qt.h:119
~ruledit_gui() override
Destructor.
Definition: ruledit_qt.cpp:176
void open_effect_edit(const QString &target, struct universal *uni, enum effect_filter_main_class efmc)
Open effect_edit dialog.
Definition: ruledit_qt.cpp:350
void unregister_req_edit(class req_edit *redit)
Unregisted closed req_edit dialog.
Definition: ruledit_qt.cpp:305
ruledit_main()
Main window constructor.
Definition: ruledit_qt.cpp:399
void closeEvent(QCloseEvent *cevent) override
User clicked windows close button.
Definition: ruledit_qt.cpp:409
void refresh()
Refresh the information.
void refresh()
Refresh the information.
void refresh()
Refresh the information.
Definition: tab_extras.cpp:113
void refresh()
Refresh the information.
Definition: tab_good.cpp:114
void refresh()
Refresh the information.
Definition: tab_gov.cpp:113
void refresh()
Refresh the information.
Definition: tab_misc.cpp:198
void refresh()
Refresh the information.
void flush_widgets()
Flush information from widgets to stores where it can be saved from.
Definition: tab_nation.cpp:79
void refresh()
Refresh the information.
Definition: tab_nation.cpp:64
void refresh()
Refresh the information.
Definition: tab_tech.cpp:139
void refresh()
Refresh the information.
effect_filter_main_class
Definition: effect_edit.h:31
#define _(String)
Definition: fcintl.h:50
#define R__(String)
Definition: fcintl.h:58
struct civ_game game
Definition: game.cpp:47
#define GAME_DEFAULT_RULESETDIR
Definition: game.h:630
bool are_universals_equal(const struct universal *psource1, const struct universal *psource2)
Return TRUE iff the two sources are equivalent.
struct ruledit_arguments reargs
Definition: ruledit.cpp:52
void ruledit_qt_display_requirers(const char *msg, void *data)
Display requirer list.
Definition: ruledit_qt.cpp:67
static void conversion_log_cb(const char *msg)
Ruleset conversion log callback.
Definition: ruledit_qt.cpp:186
static ruledit_gui * gui
Definition: ruledit_qt.cpp:61
static conversion_log * convlog
Definition: ruledit_qt.cpp:62
#define effect_edit_list_iterate_end
Definition: ruledit_qt.h:72
#define req_edit_list_iterate(reqeditlist, preqedit)
Definition: ruledit_qt.h:61
#define req_vec_fix_list_iterate(reqvecfixlist, preqvecfix)
Definition: ruledit_qt.h:79
#define effect_edit_list_iterate(effecteditlist, peffectedit)
Definition: ruledit_qt.h:70
#define req_edit_list_iterate_end
Definition: ruledit_qt.h:63
#define req_vec_fix_list_iterate_end
Definition: ruledit_qt.h:81
bool load_rulesets(const char *restore, const char *alt, bool compat_mode, rs_conversion_logger logger, bool act, bool buffer_script, bool load_luadata)
Loads the rulesets.
Definition: ruleset.cpp:8582
struct civ_game::@28::@32 server
char * nationlist
Definition: rulesave.h:15
char * nationlist_saved
Definition: rulesave.h:16
QString ruleset
Definition: ruledit.h:20
Definition: unit.h:134
enum universals_n kind
Definition: fc_types.h:740
#define sz_strlcpy(dest, src)
Definition: support.h:140
#define fc_strdup(str)
Definition: support.h:111
const char * freeciv21_version()
Returns the raw version string.
Definition: version.cpp:29