Freeciv21
Develop your civilization from humble roots to a global empire
page_scenario.cpp
Go to the documentation of this file.
1 /*
2  /\ ___ /\ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3  ( o o ) 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
6  / \ ^ General Public License as published by the Free
7 | | // Software Foundation, either version 3 of the License,
8  \ / // or (at your option) any later version.
10  GNU General Public License along with Freeciv21.
11  If not, see https://www.gnu.org/licenses/.
12  */
13 
14 #include "page_scenario.h"
15 
16 // utility
17 #include "fcintl.h"
18 #include "section_file.h"
19 
20 // generated
21 #include "fc_version.h"
22 
23 // client
24 #include "fc_client.h"
25 
26 // Qt
27 #include <QFileDialog>
28 
30  : QWidget(parent)
31 {
32  QHeaderView *header;
33  QStringList sav;
34 
35  ui.setupUi(this);
36  king = gui;
37  ui.scenarios_view->setObjectName(QStringLiteral("scenarios_view"));
38  ui.scenarios_text->setTextFormat(Qt::RichText);
39  ui.scenarios_text->setWordWrap(true);
40  sav << _("Choose a Scenario");
41  ui.scenarios_load->setRowCount(0);
42  ui.scenarios_load->setColumnCount(sav.count());
43  ui.scenarios_load->setHorizontalHeaderLabels(sav);
44  ui.scenarios_load->setProperty("showGrid", "false");
45  ui.scenarios_load->setProperty("selectionBehavior", "SelectRows");
46  ui.scenarios_load->setEditTriggers(QAbstractItemView::NoEditTriggers);
47  ui.scenarios_load->setSelectionMode(QAbstractItemView::SingleSelection);
48  ui.scenarios_load->verticalHeader()->setVisible(false);
49  ui.scenarios_view->setReadOnly(true);
50  ui.scenarios_view->setWordWrapMode(QTextOption::WordWrap);
51  ui.scenarios_text->setAlignment(Qt::AlignCenter);
52 
53  header = ui.scenarios_load->horizontalHeader();
54  header->setSectionResizeMode(0, QHeaderView::Stretch);
55  header->setStretchLastSection(true);
56  connect(ui.scenarios_load->selectionModel(),
57  &QItemSelectionModel::selectionChanged, this,
59 
60  ui.bbrowse->setText(_("Browse..."));
61  ui.bbrowse->setIcon(
62  QApplication::style()->standardIcon(QStyle::SP_DirIcon));
63  connect(ui.bbrowse, &QAbstractButton::clicked, this,
65 
66  ui.bcancel->setText(_("Cancel"));
67  ui.bcancel->setIcon(
68  QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton));
69  connect(ui.bcancel, &QAbstractButton::clicked, gui,
71  ui.bload->setText(_("Load Scenario"));
72  ui.bload->setIcon(
73  QApplication::style()->standardIcon(QStyle::SP_DialogOkButton));
74  connect(ui.bload, &QAbstractButton::clicked, this,
76  setLayout(ui.gridLayout);
77 }
78 
80 
85 {
86  QString str;
87 
88  str = QString(_("Scenarios Files"))
89  + QStringLiteral(" (*.sav *.sav.bz2 *.sav.gz *.sav.xz *.sav.zst)");
90  current_file = QFileDialog::getOpenFileName(this, _("Open Scenario File"),
91  QDir::homePath(), str);
92  if (!current_file.isEmpty()) {
94  }
95 }
96 
101 
106 {
107  int row = 0;
108 
109  ui.scenarios_load->clearContents();
110  ui.scenarios_load->setRowCount(0);
111  ui.scenarios_text->setText(QLatin1String(""));
112  ui.scenarios_view->setText(QLatin1String(""));
113 
114  const auto files = find_files_in_path(get_scenario_dirs(),
115  QStringLiteral("*.sav*"), false);
116  for (const auto &info : files) {
117  struct section_file *sf = secfile_load_section(
118  info.absoluteFilePath(), QStringLiteral("scenario"), true);
119 
120  if (sf
121  && secfile_lookup_bool_default(sf, true, "scenario.is_scenario")) {
122  const char *sname, *sdescription, *sauthors;
123  QTableWidgetItem *item;
124  QString format;
125  QString st;
126  QStringList sl;
127  int fcver;
128  int current_ver = MAJOR_VERSION * 1000000 + MINOR_VERSION * 10000;
129 
130  fcver = secfile_lookup_int_default(sf, 0, "scenario.game_version");
131  if (fcver < 30000) {
132  /* Pre-3.0 versions stored version number without emergency version
133  * part in the end. To get comparable version number stored,
134  * multiply by 100. */
135  fcver *= 100;
136  }
137  fcver -= (fcver % 10000); // Patch level does not affect compatibility
138  sname = secfile_lookup_str_default(sf, nullptr, "scenario.name");
139  sdescription =
140  secfile_lookup_str_default(sf, nullptr, "scenario.description");
141  sauthors = secfile_lookup_str_default(sf, nullptr, "scenario.authors");
142  if (fcver <= current_ver) {
143  QString version;
144  bool add_item = true;
145  bool found = false;
146  QStringList sl;
147  int rows;
148  int found_ver;
149  int i;
150 
151  if (fcver > 0) {
152  int maj;
153  int min;
154 
155  maj = fcver / 1000000;
156  fcver %= 1000000;
157  min = fcver / 10000;
158  version = QStringLiteral("%1.%2").arg(maj).arg(min);
159  } else {
160  // TRANS: Unknown scenario format
161  version = QString(_("pre-2.6"));
162  }
163 
164  rows = ui.scenarios_load->rowCount();
165  for (i = 0; i < rows; ++i) {
166  if (ui.scenarios_load->item(i, 0)
167  && ui.scenarios_load->item(i, 0)->text() == info.baseName()) {
168  found = true;
169  item = ui.scenarios_load->takeItem(i, 0);
170  break;
171  }
172  }
173 
174  if (found) {
175  sl = item->data(Qt::UserRole).toStringList();
176  found_ver = sl.at(3).toInt();
177  if (found_ver < fcver) {
178  secfile_destroy(sf);
179  continue;
180  }
181  add_item = false;
182  }
183  if (add_item) {
184  item = new QTableWidgetItem();
185  ui.scenarios_load->insertRow(row);
186  }
187  item->setText(info.baseName());
188  format = QStringLiteral("<br>") + QString(_("Format:")) + " "
189  + version.toHtmlEscaped();
190  if (sauthors) {
191  st = QStringLiteral("\n") + QStringLiteral("<b>") + _("Authors: ")
192  + QStringLiteral("</b>") + QString(sauthors).toHtmlEscaped();
193  } else {
194  st = QLatin1String("");
195  }
196  sl << "<b>"
197  + QString(sname && qstrlen(sname) ? Q_(sname)
198  : info.baseName())
199  .toHtmlEscaped()
200  + "</b>"
201  << info.absoluteFilePath()
202  << QString(nullptr != sdescription && '\0' != sdescription[0]
203  ? Q_(sdescription)
204  : "")
205  .toHtmlEscaped()
206  + st + format
207  << QString::number(fcver).toHtmlEscaped();
208  sl.replaceInStrings(QStringLiteral("\n"), QStringLiteral("<br>"));
209  item->setData(Qt::UserRole, sl);
210  if (add_item) {
211  ui.scenarios_load->setItem(row, 0, item);
212  row++;
213  } else {
214  ui.scenarios_load->setItem(i, 0, item);
215  }
216  }
217  }
218  secfile_destroy(sf);
219  }
220  ui.scenarios_load->sortItems(0);
221  ui.scenarios_load->update();
222 }
223 
224 void page_scenario::slot_selection_changed(const QItemSelection &selected,
225  const QItemSelection &deselected)
226 {
227  Q_UNUSED(deselected)
228 
229  if (selected.isEmpty()) {
230  return;
231  }
232 
233  auto sl = selected.indexes().front().data(Qt::UserRole).toStringList();
234  ui.scenarios_text->setText(sl.at(0));
235  if (sl.count() > 1) {
236  ui.scenarios_view->setText(sl.at(2));
237  current_file = sl.at(1);
238  }
239 }
void slot_disconnect()
Disconnect from server and return to MAIN PAGE.
Definition: fc_client.cpp:323
void start_from_file(const QString &file)
start from save file
Definition: fc_client.cpp:669
~page_scenario() override
void update_scenarios_page()
Gets scenarios list and updates it in TableWidget = scenarios_load.
fc_client * king
Definition: page_scenario.h:30
Ui::FormPageScenario ui
Definition: page_scenario.h:31
void start_scenario()
Starts game from chosen scenario - chosen_file (save or scenario)
page_scenario(QWidget *, fc_client *)
void browse_scenarios()
Browse scenarios directory.
QString current_file
Definition: page_scenario.h:32
void slot_selection_changed(const QItemSelection &, const QItemSelection &)
#define Q_(String)
Definition: fcintl.h:53
#define _(String)
Definition: fcintl.h:50
static mpgui * gui
Definition: mpgui_qt.cpp:47
void secfile_destroy(struct section_file *secfile)
Free a section file.
struct section_file * secfile_load_section(const QString &filename, const QString &section, bool allow_duplicates)
Create a section file from a file, read only one particular section.
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
Lookup a boolean value in the secfile.
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Lookup a string value in the secfile.
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Lookup a integer value in the secfile.
QFileInfoList find_files_in_path(const QStringList &path, const QString &pattern, bool nodups)
Search for file names matching the pattern in the provided list of directories.
Definition: shared.cpp:681
const QStringList & get_scenario_dirs()
Returns a list of scenario directory paths, in the order in which they should be searched.
Definition: shared.cpp:594
Definition: climisc.h:66