From 7b3ef315a3b10aa28816ead1c37d9925502ed4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Lach?= Date: Mon, 16 May 2022 15:32:56 +0200 Subject: [PATCH] =?UTF-8?q?!OSDN:=20#TICKET:=2045892:=20S=C5=82awomir=20La?= =?UTF-8?q?ch=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementing ruledit tab for counters diff --git a/meson.build b/meson.build index e3d59b38e5..c93b701051 100644 --- a/meson.build +++ b/meson.build @@ -3494,6 +3494,7 @@ mocced_ruledit = qt_mod.preprocess( 'tools/ruledit/req_vec_fix.h', 'tools/ruledit/requirers_dlg.h', 'tools/ruledit/ruledit_qt.h', + 'tools/ruledit/tab_counters.h', 'tools/ruledit/tab_enablers.h', 'tools/ruledit/tab_extras.h', 'tools/ruledit/tab_misc.h', @@ -3518,6 +3519,7 @@ executable('freeciv-ruledit', 'tools/ruledit/ruledit.cpp', 'tools/ruledit/ruledit_qt.cpp', 'tools/ruledit/tab_building.cpp', + 'tools/ruledit/tab_counters.cpp', 'tools/ruledit/tab_enablers.cpp', 'tools/ruledit/tab_extras.cpp', 'tools/ruledit/tab_good.cpp', diff --git a/tools/ruledit/Makefile.am b/tools/ruledit/Makefile.am index 44d0288c1e..5ac03ae97e 100644 --- a/tools/ruledit/Makefile.am +++ b/tools/ruledit/Makefile.am @@ -33,6 +33,7 @@ MOC_FILES = \ meta_requirers_dlg.cpp \ meta_ruledit_qt.cpp \ meta_tab_building.cpp \ + meta_tab_counters.cpp \ meta_tab_enablers.cpp \ meta_tab_extras.cpp \ meta_tab_good.cpp \ @@ -55,6 +56,8 @@ freeciv_ruledit_SOURCES = \ effect_edit.h \ tab_building.cpp \ tab_building.h \ + tab_counters.cpp \ + tab_counters.h \ tab_enablers.cpp \ tab_enablers.h \ tab_extras.cpp \ diff --git a/tools/ruledit/ruledit_qt.cpp b/tools/ruledit/ruledit_qt.cpp index 967966dfb7..5b0559dadf 100644 --- a/tools/ruledit/ruledit_qt.cpp +++ b/tools/ruledit/ruledit_qt.cpp @@ -46,6 +46,7 @@ #include "req_vec_fix.h" #include "ruledit.h" #include "tab_building.h" +#include "tab_counters.h" #include "tab_enablers.h" #include "tab_extras.h" #include "tab_good.h" @@ -185,6 +186,8 @@ void ruledit_gui::setup(QWidget *central_in) stack->addTab(terrains, QString::fromUtf8(R__("Terrains"))); multipliers = new tab_multiplier(this); stack->addTab(multipliers, QString::fromUtf8(R__("Multipliers"))); + counter = new tab_counter(this); + stack->addTab(counter, QString::fromUtf8(R__("Counters"))); nation = new tab_nation(this); stack->addTab(nation, QString::fromUtf8(R__("Nations"))); @@ -250,6 +253,7 @@ void ruledit_gui::launch_now() extras->refresh(); multipliers->refresh(); terrains->refresh(); + counter->refresh(); main_layout->setCurrentIndex(1); } else { display_msg(R__("Ruleset loading failed!")); diff --git a/tools/ruledit/ruledit_qt.h b/tools/ruledit/ruledit_qt.h index 464d443083..e65192b316 100644 --- a/tools/ruledit/ruledit_qt.h +++ b/tools/ruledit/ruledit_qt.h @@ -30,6 +30,7 @@ class QStackedLayout; class requirers_dlg; class tab_building; +class tab_counter; class tab_good; class tab_gov; class tab_misc; @@ -130,6 +131,7 @@ signals: QStackedLayout *main_layout; tab_building *bldg; + tab_counter *counter; tab_misc *misc; tab_tech *tech; tab_unit *unit; diff --git a/tools/ruledit/tab_counters.cpp b/tools/ruledit/tab_counters.cpp new file mode 100644 index 0000000000..3d53bb21ae --- /dev/null +++ b/tools/ruledit/tab_counters.cpp @@ -0,0 +1,385 @@ +/*********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +// Qt +#include +#include +#include +#include +#include +#include + +// utility +#include "fcintl.h" +#include "log.h" + +// common +#include "counters.h" +#include "fc_types.h" +#include "game.h" + +// ruledit +#include "ruledit.h" +#include "ruledit_qt.h" +#include "validity.h" + +#include "tab_counters.h" + +/**********************************************************************//** + Setup tab_counter object +**************************************************************************/ +tab_counter::tab_counter(ruledit_gui *ui_in) : QWidget() +{ +#define empty_widget (nullptr) +#define add_widget(widget) { column = 0; if (widget) counter_layout->addWidget(widget, row, column); row++; } +#define add_widget_next(widget) { column++; if (widget) counter_layout->addWidget(widget, row - 1, column); } + + QVBoxLayout *main_layout = new QVBoxLayout(this); + QGridLayout *counter_layout = new QGridLayout(); + QLabel *label; + QPushButton *add_button; + QPushButton *delete_button; + int row = 0; + int column = 0; + + ui = ui_in; + selected = nullptr; + + counter_list = new QListWidget(this); + + connect(counter_list, SIGNAL(itemSelectionChanged()), this, SLOT(select_counter())); + main_layout->addWidget(counter_list); + + counter_layout->setSizeConstraint(QLayout::SetMaximumSize); + + label = new QLabel(QString::fromUtf8(R__("Rule Name"))); + label->setParent(this); + rname = new QLineEdit(this); + rname->setText(R__("None")); + connect(rname, SIGNAL(returnPressed()), this, SLOT(name_given())); + add_widget(label); + add_widget_next(empty_widget); + add_widget_next(rname); + + label = new QLabel(QString::fromUtf8(R__("Name"))); + label->setParent(this); + + name = new QLineEdit(this); + name->setText(R__("None")); + connect(name, SIGNAL(returnPressed()), this, SLOT(name_given())); + same_name = new QCheckBox(this); + connect(same_name, SIGNAL(toggled(bool)), this, SLOT(same_name_toggle(bool))); + same_name->setChecked(true); + add_widget(label); + add_widget_next(same_name); + add_widget_next(name); + + label = new QLabel(QString::fromUtf8(R__("Default Value")), this); + label->setParent(this); + add_widget(label); + add_widget_next(empty_widget); + + def = new QSpinBox(this); + def->setMaximum(INT_MAX); + def->setMinimum(INT_MIN); + connect(def, SIGNAL(valueChanged(int)), this, SLOT(default_given(int))); + add_widget_next(def); + + label = new QLabel(QString::fromUtf8(R__("Checkpoint")), this); + label->setParent(this); + add_widget(label); + add_widget_next(empty_widget); + + checkpoint = new QSpinBox(this); + checkpoint->setMaximum(INT_MAX); + checkpoint->setMinimum(INT_MIN); + connect(checkpoint, SIGNAL(valueChanged(int)), this, SLOT(checkpoint_given(int))); + add_widget_next(checkpoint); + + { + QVariant CITY_OWNED_COUNTER(CB_CITY_OWNED_TURNS); + QVariant CB_CITY_CELEBRATION_COUNTER(CB_CITY_CELEBRATION_TURNS); + type = new QComboBox(this); + + label = new QLabel(QString::fromUtf8(R__("Behavior"))); + label->setParent(this); + add_widget(label); + add_widget_next(empty_widget); + show_experimental(label); + + type->addItem(counter_behaviour_name(CB_CITY_OWNED_TURNS), CITY_OWNED_COUNTER); + type->addItem(counter_behaviour_name(CB_CITY_CELEBRATION_TURNS), CB_CITY_CELEBRATION_COUNTER); + + connect(type, SIGNAL(activated(int)), this, SLOT(counter_behaviour_selected(int))); + + add_widget_next(type); + show_experimental(type); + } + + effects_button = new QPushButton(QString::fromUtf8(R__("Effects")), this); + connect(effects_button, SIGNAL(pressed()), this, SLOT(edit_effects())); + add_widget(empty_widget); + add_widget_next(empty_widget); + add_widget_next(effects_button); + + add_button = new QPushButton(QString::fromUtf8(R__("Add Counter")), this); + connect(add_button, SIGNAL(pressed()), this, SLOT(add_now())); + add_widget(empty_widget); + add_widget_next(empty_widget); + add_widget_next(add_button); + show_experimental(add_button); + + delete_button = new QPushButton(QString::fromUtf8(R__("Remove this Counter")), this); + connect(delete_button, SIGNAL(pressed()), this, SLOT(delete_now())); + add_widget_next(delete_button); + show_experimental(delete_button); + + refresh(); + update_counter_info(nullptr); + + main_layout->addLayout(counter_layout); + + setLayout(main_layout); +#undef empty_widget +#undef add_widget +#undef add_widget_next +} + +/**********************************************************************//** + Called when counter behaviour is set by user +**************************************************************************/ +void tab_counter::counter_behaviour_selected(int item) +{ + (void) item; + + QVariant item_data; + if (nullptr == selected) { + + return; + } + item_data = type->currentData(); + selected->type = (enum counter_behaviour) item_data.toInt(); + + update_counter_info(selected); + refresh(); +} + +/**********************************************************************//** + Refresh the information. +**************************************************************************/ +void tab_counter::refresh() +{ + counter_list->clear(); + + counters_re_iterate(pcount) { + QListWidgetItem *item = new QListWidgetItem(counter_rule_name(pcount)); + + counter_list->insertItem(counter_index(pcount), item); + } counters_re_iterate_end; +} + +/**********************************************************************//** + Update info of the counter +**************************************************************************/ +void tab_counter::update_counter_info(struct counter *counter) +{ + selected = counter; + + if (selected != nullptr) { + QString dispn = QString::fromUtf8(untranslated_name(&(counter->name))); + QString rulen = QString::fromUtf8(rule_name_get(&(counter->name))); + + name->setText(dispn); + rname->setText(rulen); + + if (dispn == rulen) { + name->setEnabled(false); + } else { + name->setEnabled(true); + } + + checkpoint->setValue(selected->checkpoint); + def->setValue(selected->def); + } else { + name->setText(R__("None")); + rname->setText(R__("None")); + name->setEnabled(false); + } +} + +/**********************************************************************//** + User selected counter from the list. +**************************************************************************/ +void tab_counter::select_counter() +{ + char *cname; + + QList select_list = counter_list->selectedItems(); + + if (!select_list.isEmpty()) { + QByteArray tn_bytes; + + tn_bytes = select_list.at(0)->text().toUtf8(); + + cname = tn_bytes.data(); + update_counter_info(counter_by_rule_name(cname)); + } +} + + +/**********************************************************************//** + User entered checkpoint value +**************************************************************************/ +void tab_counter::checkpoint_given(int val) +{ + selected->checkpoint = val; +} + +/**********************************************************************//** + User entered default value +**************************************************************************/ +void tab_counter::default_given(int val) +{ + selected->def = val; +} + +/**********************************************************************//** + User entered name for counter +**************************************************************************/ +void tab_counter::name_given() +{ + if (selected != nullptr) { + QByteArray name_bytes; + QByteArray rname_bytes; + + city_counters_iterate(pcounter) { + if (pcounter != selected) { + rname_bytes = rname->text().toUtf8(); + if (!strcmp(counter_rule_name(pcounter), rname_bytes.data())) { + ui->display_msg(R__("A counter with that rule name already exists!")); + return; + } + } + } city_counters_iterate_end; + + name_bytes = name->text().toUtf8(); + rname_bytes = rname->text().toUtf8(); + names_set(&(selected->name), 0, + name_bytes.data(), + rname_bytes.data()); + refresh(); + } +} + +/**********************************************************************//** + User requested counter deletion +**************************************************************************/ +void tab_counter::delete_now() +{ + if (selected != 0) { + requirers_dlg *requirers; + + requirers = ui->create_requirers(counter_rule_name(selected)); + if (is_counter_needed(selected, &ruledit_qt_display_requirers, requirers)) { + return; + } + + selected->ruledit_disabled = true; + + refresh(); + update_counter_info(nullptr); + } +} + +/**********************************************************************//** + Initialize new counter for use. +**************************************************************************/ +bool tab_counter::initialize_new_counter(struct counter *counter) +{ + counter->checkpoint = 0; + counter->def = 0; + counter->target = CTGT_CITY; + counter->type = CB_CITY_OWNED_TURNS; + counter->index = counters_get_city_counters_count() - 1; + counter->ruledit_disabled = FALSE; + + name_set(&counter->name, 0, "New counter"); + + return true; +} + +/**********************************************************************//** + User requested new counter +**************************************************************************/ +void tab_counter::add_now() +{ + struct counter *new_counter; + + // Try to reuse freed counter slot + city_counters_iterate(pcount) { + if (pcount->type == COUNTER_BEHAVIOUR_LAST + || pcount->ruledit_disabled) { + if (initialize_new_counter(pcount)) { + update_counter_info(pcount); + refresh(); + } + return; + } + } city_counters_iterate_end; + + // Try to add completely new counter + if (counters_get_city_counters_count() >= MAX_COUNTERS) { + return; + } + + // num_counter_types must be big enough to hold new counter or + // counter_by_number() fails. + game.control.num_counters++; + new_counter = counter_by_id(counters_get_city_counters_count()); + if (initialize_new_counter(new_counter)) { + update_counter_info(new_counter); + attach_city_counter(new_counter); + refresh(); + } +} + +/**********************************************************************//** + Toggled whether rule_name and name should be kept identical +**************************************************************************/ +void tab_counter::same_name_toggle(bool checked) +{ + name->setEnabled(!checked); + if (checked) { + name->setText(rname->text()); + } +} + +/**********************************************************************//** + User wants to edit effects +**************************************************************************/ +void tab_counter::edit_effects() +{ + if (selected != nullptr) { + struct universal uni; + + uni.value.counter = selected; + uni.kind = VUT_COUNTER; + + ui->open_effect_edit(QString::fromUtf8(counter_rule_name(selected)), + &uni, EFMC_NORMAL); + } +} diff --git a/tools/ruledit/tab_counters.h b/tools/ruledit/tab_counters.h new file mode 100644 index 0000000000..f6acc3ce3c --- /dev/null +++ b/tools/ruledit/tab_counters.h @@ -0,0 +1,76 @@ +/*********************************************************************** + Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +***********************************************************************/ + +#ifndef FC__TAB_COUNTER_H +#define FC__TAB_COUNTER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +// Qt +#include +#include +#include +#include +#include +#include +#include + +// common +#include "counters.h" + +class ruledit_gui; + +class tab_counter : public QWidget +{ + Q_OBJECT + + public: + explicit tab_counter(ruledit_gui *ui_in); + void refresh(); + static void techs_to_menu(QMenu *fill_menu); + static QString counter_name(struct counter *padv); + + private: + ruledit_gui *ui; + + QLineEdit *name; + QLineEdit *rname; + QSpinBox *checkpoint; + QSpinBox *def; + QComboBox *type; + QCheckBox *same_name; + QPushButton *effects_button; + + QListWidget *counter_list; + + struct counter *selected; + + private slots: + void update_counter_info(struct counter *counter); + void checkpoint_given(int val); + void default_given(int val); + void name_given(); + void select_counter(); + void add_now(); + void delete_now(); + void same_name_toggle(bool checked); + void edit_effects(); + bool initialize_new_counter(struct counter *padv); + void counter_behaviour_selected(int item); + //QMenu *prepare_counter_button(QToolButton *button, enum tech_req rn); +}; + + +#endif // FC__TAB_COUNTER_H diff --git a/tools/ruleutil/rulesave.c b/tools/ruleutil/rulesave.c index 836d41b462..ee6cb9f81c 100644 --- a/tools/ruleutil/rulesave.c +++ b/tools/ruleutil/rulesave.c @@ -1787,7 +1787,7 @@ static bool save_game_ruleset(const char *filename, const char *name) comment_counters(sfile); sect_idx = 0; - city_counters_iterate(pcounter) { + counters_re_iterate(pcounter) { char path[512]; fc_snprintf(path, sizeof(path), "counter_%d", sect_idx++); @@ -1799,7 +1799,7 @@ static bool save_game_ruleset(const char *filename, const char *name) secfile_insert_str(sfile, counter_behaviour_name(pcounter->type), "%s.type", path); - } city_counters_iterate_end; + } counters_re_iterate_end; locks = FALSE; settings_iterate(SSET_ALL, pset) { diff --git a/translations/ruledit/POTFILES.in b/translations/ruledit/POTFILES.in index 7678c8d1e0..5050794268 100644 --- a/translations/ruledit/POTFILES.in +++ b/translations/ruledit/POTFILES.in @@ -9,6 +9,7 @@ tools/ruledit/requirers_dlg.cpp tools/ruledit/ruledit.cpp tools/ruledit/ruledit_qt.cpp tools/ruledit/tab_building.cpp +tools/ruledit/tab_counters.cpp tools/ruledit/tab_enablers.cpp tools/ruledit/tab_extras.cpp tools/ruledit/tab_good.cpp -- 2.39.0