Freeciv21
Develop your civilization from humble roots to a global empire
req_vec_fix.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  __ __ part of Freeciv21. Freeciv21 is free software: you can
4 / \\..// \ redistribute it and/or modify it under the terms of the GNU
5  ( oo ) General Public License as published by the Free Software
6  \__/ Foundation, either version 3 of the License, or (at your
7  option) any later version. You should have received
8  a copy of the GNU General Public License along with Freeciv21. If not,
9  see https://www.gnu.org/licenses/.
10  */
11 
12 // Qt
13 #include <QButtonGroup>
14 #include <QHBoxLayout>
15 #include <QLabel>
16 #include <QListWidgetItem>
17 #include <QMessageBox>
18 #include <QPushButton>
19 #include <QRadioButton>
20 #include <QStackedLayout>
21 
22 // ruledit
23 #include "ruledit_qt.h"
24 
25 #include "req_vec_fix.h"
26 
32 void mark_item(QListWidgetItem *item,
33  enum req_vec_problem_seriousness problem_level)
34 {
35  QWidget *in = item->listWidget();
36  switch (problem_level) {
37  case RVPS_NO_PROBLEM:
38  item->setIcon(QIcon());
39  break;
40  case RVPS_IMPROVE:
41  item->setIcon(in->style()->standardIcon(QStyle::SP_MessageBoxWarning));
42  break;
43  case RVPS_REPAIR:
44  item->setIcon(in->style()->standardIcon(QStyle::SP_MessageBoxCritical));
45  break;
46  }
47 }
48 
55  const struct req_vec_problem *problem, req_vec_fix_item *item_info)
56  : QWidget(), solutions(nullptr)
57 {
58  int i;
59  QLabel *description;
60  QPushButton *accept;
61 
62  QVBoxLayout *layout_main = new QVBoxLayout();
63 
64  // Sanity check.
65  fc_assert_ret(item_info);
66 
67  description = new QLabel();
68  layout_main->addWidget(description);
69 
70  if (problem == nullptr) {
71  // Everything is OK.
72 
73  /* TRANS: Trying to fix a requirement vector problem but can't find
74  * any. */
75  description->setText(R__("No problem found"));
76  this->setLayout(layout_main);
77  return;
78  }
79 
80  if (problem->num_suggested_solutions == 0) {
81  // Didn't get any suggestions about how to solve this.
82 
83  char buf[MAX_LEN_NAME * 3];
84 
85  fc_snprintf(buf, sizeof(buf),
86  /* TRANS: Trying to fix a requirement vector problem but
87  * don't know how to solve it. */
88  R__("Don't know how to fix %s: %s"), item_info->name(),
89  problem->description);
90 
91  description->setText(buf);
92  this->setLayout(layout_main);
93  return;
94  }
95 
96  // A problem with at least one solution exists.
97  fc_assert_ret(problem && problem->num_suggested_solutions > 0);
98 
99  // Display the problem text
100  description->setText(QString::fromUtf8(problem->description_translated));
101 
102  // Display each solution
103  solutions = new QButtonGroup(this);
104  for (i = 0; i < problem->num_suggested_solutions; i++) {
105  QRadioButton *solution = new QRadioButton(req_vec_change_translation(
106  &problem->suggested_solutions[i], item_info->vector_namer()));
107 
108  solutions->addButton(solution, i);
109  solution->setChecked(i == 0);
110 
111  layout_main->addWidget(solution);
112  }
113 
114  // TRANS: Apply the selected requirement vector problem fix.
115  accept = new QPushButton(R__("Accept selected solution"));
116  connect(accept, &QAbstractButton::pressed, this,
118  layout_main->addWidget(accept);
119 
120  this->setLayout(layout_main);
121 }
122 
128 {
129  emit solution_accepted(solutions->checkedId());
130 }
131 
140  : QWidget()
141 {
142  QVBoxLayout *layout_main = new QVBoxLayout();
143  QHBoxLayout *layout_buttons = new QHBoxLayout();
144 
145  this->ui = ui_in;
148 
149  this->item_info = item_info;
150 
151  this->current_problem = nullptr;
152  this->did_apply_a_solution = false;
153 
154  this->setWindowTitle(R__("Requirement problem"));
155  this->setAttribute(Qt::WA_DeleteOnClose);
156 
157  // Set up the area for viewing problems
158  this->current_problem_viewer = nullptr;
159  this->current_problem_area = new QStackedLayout();
160  layout_main->addLayout(current_problem_area);
161 
162  /* TRANS: Button text in the requirement vector fixer dialog. Cancels all
163  * changes done since the last time all accepted changes were done. */
164  abort = new QPushButton(R__("Undo all"));
165  /* TRANS: Tool tip text in the requirement vector fixer dialog. Cancels
166  * all changes done since the last time all accepted changes were done. */
167  abort->setToolTip(R__("Undo all accepted solutions since you started or"
168  " since last time you ordered all accepted changes"
169  " done."));
170  connect(abort, &QAbstractButton::pressed, this,
172  layout_buttons->addWidget(abort);
173 
174  /* TRANS: Perform all the changes to the ruleset item the user has
175  * accepted. Button text in the requirement vector fixer dialog. */
176  apply_changes = new QPushButton(R__("Do accepted changes"));
177  /* TRANS: Perform all the changes to the ruleset item the user has
178  * accepted. Tool tip text in the requirement vector fixer dialog. */
179  apply_changes->setToolTip(R__("Perform all the changes you have accepted"
180  " to the ruleset item. You can then fix the"
181  " current issue by hand and come back here"
182  " to find the next issue."));
183  connect(apply_changes, &QAbstractButton::pressed, this,
185  layout_buttons->addWidget(apply_changes);
186 
187  close = new QPushButton(R__("Close"));
188  connect(close, &QAbstractButton::pressed, this, &QWidget::close);
189  layout_buttons->addWidget(close);
190 
191  layout_main->addLayout(layout_buttons);
192 
193  this->setLayout(layout_main);
194 }
195 
200 {
201  if (current_problem != nullptr) {
203  }
204 
205  this->item_info->close();
206 
207  this->ui->unregister_req_vec_fix(this);
208 }
209 
214 const void *req_vec_fix::item() { return this->item_info->item(); }
215 
221 {
222  if (current_problem != nullptr) {
223  /* The old problem is hopefully solved. If it isn't it will probably be
224  * returned again. */
226  }
227 
228  // Update the current problem.
230 
231  // Display the new problem
232  if (current_problem_viewer != nullptr) {
233  current_problem_viewer->hide();
234  current_problem_viewer->deleteLater();
235  }
241  current_problem_area->setCurrentWidget(current_problem_viewer);
242 
243  // Only shown when there is something to do
244  apply_changes->setVisible(did_apply_a_solution);
245  abort->setVisible(did_apply_a_solution);
246 
247  // Only shown when no work will be lost
248  close->setVisible(!did_apply_a_solution);
249 
250  return current_problem != nullptr;
251 }
252 
257 void req_vec_fix::apply_solution(int selected_solution)
258 {
259  const struct req_vec_change *solution;
260 
262  fc_assert_ret(selected_solution >= 0);
263  fc_assert_ret(selected_solution
265 
266  solution = &current_problem->suggested_solutions[selected_solution];
267 
268  if (!req_vec_change_apply(solution, item_info->vector_getter(),
270  QMessageBox *box = new QMessageBox();
271 
272  box->setWindowTitle(R__("Unable to apply solution"));
273 
274  box->setText(
275  // TRANS: requirement vector fix failed to apply
276  QString(R__("Failed to apply solution %1 for %2 to %3."))
277  .arg(req_vec_change_translation(solution,
280  box->setStandardButtons(QMessageBox::Ok);
281  box->exec();
282  } else {
283  // A solution has been applied
284  this->did_apply_a_solution = true;
285  }
286 
287  this->refresh();
288 }
289 
294 {
295  int i;
296 
298 
299  // All is accepted
300  this->did_apply_a_solution = false;
301 
302  // New check point.
303  this->refresh();
304 
305  for (i = 0; i < item_info->num_vectors(); i++) {
308  }
309 }
310 
315 {
317 
318  // All is gone
319  this->did_apply_a_solution = false;
320 
321  // Back to the start again.
322  this->refresh();
323 }
324 
329 void req_vec_fix::incoming_rec_vec_change(const requirement_vector *vec)
330 {
331  if (this->item_info->vector_in_item(vec)) {
332  // Can't trust the changes done against a previous version.
334  }
335 }
Ruleset entity specific methods for the ruleset item having its requirements fixed.
Definition: req_vec_fix.h:44
virtual requirement_vector_by_number vector_getter()=0
Returns a function pointer to a function that returns a writable pointer to the specified requirement...
virtual requirement_vector_namer vector_namer()=0
Returns a function pointer to a function that names this item kind's requirement vector number number...
virtual void close()=0
Tell the helper that it has outlived its usefulness.
virtual void * item_working_copy()=0
Returns a pointer to the working copy of the ruleset item.
virtual void undo_accepted_changes()=0
Undo all the changes the user has accepted to the ruleset item.
virtual const void * item()=0
Returns a pointer to the ruleset item.
virtual void apply_accepted_changes()=0
Do all the changes the user has accepted to the ruleset item.
virtual bool vector_in_item(const struct requirement_vector *vec)=0
Check if the specified vector belongs to this item.
virtual int num_vectors()=0
Returns the number of requirement vectors in this item.
virtual const char * name()=0
Returns a name to describe the item, hopefully good enough to distinguish it from other items.
virtual struct req_vec_problem * find_next_problem()=0
Returns the next detected requirement vector problem for the ruleset item or nullptr if no fix is fou...
Widget for choosing among the suggested solutions to a problem.
Definition: req_vec_fix.h:126
req_vec_fix_problem(const struct req_vec_problem *problem, req_vec_fix_item *item_info)
Set up the display and solution choice of the specified problem.
Definition: req_vec_fix.cpp:54
void solution_accepted(int selected_solution)
QButtonGroup * solutions
Definition: req_vec_fix.h:134
void accept_solution()
The user selected one of the suggested solutions to the requirement vector problem.
struct req_vec_problem * current_problem
Definition: req_vec_fix.h:165
QPushButton * close
Definition: req_vec_fix.h:173
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.
const void * item()
Returns the item this dialog is trying to fix.
void accept_applied_solutions()
Do all the accepted solutions for real.
req_vec_fix_problem * current_problem_viewer
Definition: req_vec_fix.h:171
void incoming_rec_vec_change(const requirement_vector *vec)
A requirement vector may have been changed.
QPushButton * abort
Definition: req_vec_fix.h:173
QStackedLayout * current_problem_area
Definition: req_vec_fix.h:172
void reject_applied_solutions()
Undo all accepted solutions.
ruledit_gui * ui
Definition: req_vec_fix.h:169
~req_vec_fix() override
Destructor for req_vec_fix.
void apply_solution(int selected_solution)
Apply the selected solution to the current requirement vector problem.
req_vec_fix(ruledit_gui *ui_in, req_vec_fix_item *item_info)
Set up a widget for displaying and fixing requirement vector problems for a specific ruleset entity i...
req_vec_fix_item * item_info
Definition: req_vec_fix.h:166
bool did_apply_a_solution
Definition: req_vec_fix.h:167
QPushButton * apply_changes
Definition: req_vec_fix.h:173
void rec_vec_may_have_changed(const requirement_vector *vec)
A requirement vector may have been changed.
void unregister_req_vec_fix(req_vec_fix *fixer)
Unregister closed req_vec_fix dialog.
Definition: ruledit_qt.cpp:342
#define MAX_LEN_NAME
Definition: fc_types.h:61
#define R__(String)
Definition: fcintl.h:58
#define fc_assert_ret(condition)
Definition: log.h:112
void mark_item(QListWidgetItem *item, enum req_vec_problem_seriousness problem_level)
Mark a ruleset item in a list as having a problem.
Definition: req_vec_fix.cpp:32
req_vec_problem_seriousness
Definition: req_vec_fix.h:31
@ RVPS_NO_PROBLEM
Definition: req_vec_fix.h:32
@ RVPS_REPAIR
Definition: req_vec_fix.h:34
@ RVPS_IMPROVE
Definition: req_vec_fix.h:33
bool req_vec_change_apply(const struct req_vec_change *modification, requirement_vector_by_number getter, const void *parent_item)
Returns TRUE iff the specified requirement vector modification was successfully applied to the specif...
void req_vec_problem_free(struct req_vec_problem *issue)
De-allocates resources associated with the given requirement vector problem.
const char * req_vec_change_translation(const struct req_vec_change *change, const requirement_vector_namer namer)
Returns the specified requirement vector change as a translated string ready for use in the user inte...
Definition: climisc.h:66
int num_suggested_solutions
Definition: requirements.h:203
char description[500]
Definition: requirements.h:200
char description_translated[500]
Definition: requirements.h:201
struct req_vec_change * suggested_solutions
Definition: requirements.h:204
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537