Remove hard limitation that AI wonder cities never build settlers
[freeciv.git] / tools / mpgui_qt.cpp
blobb0b30f9223c08c1d38ddb793ae21bd2baff13adc
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 // Qt
19 #include <QApplication>
20 #include <QCloseEvent>
21 #include <QHBoxLayout>
22 #include <QHeaderView>
23 #include <QLabel>
24 #include <QLineEdit>
25 #include <QMainWindow>
26 #include <QMessageBox>
27 #include <QProgressBar>
28 #include <QPushButton>
29 #include <QTableWidget>
30 #include <QVBoxLayout>
32 // utility
33 #include "fc_cmdline.h"
34 #include "fciconv.h"
35 #include "fcintl.h"
36 #include "log.h"
38 // common
39 #include "version.h"
41 // modinst
42 #include "download.h"
43 #include "mpcmdline.h"
44 #include "mpdb.h"
45 #include "mpgui_qt_worker.h"
46 #include "modinst.h"
48 #include "mpgui_qt.h"
50 struct fcmp_params fcmp = { MODPACK_LIST_URL, NULL, NULL };
52 static mpgui *gui;
54 static mpqt_worker *worker = nullptr;
56 static int mpcount = 0;
58 #define ML_COL_NAME 0
59 #define ML_COL_VER 1
60 #define ML_COL_INST 2
61 #define ML_COL_TYPE 3
62 #define ML_COL_SUBTYPE 4
63 #define ML_COL_LIC 5
64 #define ML_COL_URL 6
66 #define ML_TYPE 7
68 #define ML_COL_COUNT 8
70 static void setup_modpack_list(const char *name, const char *URL,
71 const char *version, const char *license,
72 enum modpack_type type, const char *subtype,
73 const char *notes);
74 static void msg_callback(const char *msg);
75 static void msg_callback_thr(const char *msg);
76 static void progress_callback_thr(int downloaded, int max);
78 static void gui_download_modpack(QString URL);
80 /**************************************************************************
81 Entry point for whole freeciv-mp-qt program.
82 **************************************************************************/
83 int main(int argc, char **argv)
85 int ui_options;
87 fcmp_init();
89 /* This modifies argv! */
90 ui_options = fcmp_parse_cmdline(argc, argv);
92 if (ui_options != -1) {
93 int i;
95 for (i = 1; i <= ui_options; i++) {
96 if (is_option("--help", argv[i])) {
97 fc_fprintf(stderr,
98 _("This modpack installer accepts the standard Qt command-line options\n"
99 "after '--'. See the Qt documentation.\n\n"));
101 /* TRANS: No full stop after the URL, could cause confusion. */
102 fc_fprintf(stderr, _("Report bugs at %s\n"), BUG_URL);
104 ui_options = -1;
109 if (ui_options != -1) {
110 QApplication *qapp;
111 mpgui_main *main_window;
112 QWidget *central;
113 const char *errmsg;
115 load_install_info_lists(&fcmp);
117 qapp = new QApplication(ui_options, argv);
118 central = new QWidget;
119 main_window = new mpgui_main(qapp, central);
121 main_window->setGeometry(0, 30, 640, 60);
122 main_window->setWindowTitle(QString::fromUtf8(_("Freeciv modpack installer (Qt)")));
124 gui = new mpgui;
126 gui->setup(central, &fcmp);
128 main_window->setCentralWidget(central);
129 main_window->setVisible(true);
131 errmsg = download_modpack_list(&fcmp, setup_modpack_list, msg_callback);
132 if (errmsg != nullptr) {
133 gui->display_msg(errmsg);
136 qapp->exec();
138 if (worker != nullptr) {
139 if (worker->isRunning()) {
140 worker->wait();
142 delete worker;
145 delete gui;
146 delete qapp;
148 save_install_info_lists(&fcmp);
151 fcmp_deinit();
152 cmdline_option_values_free();
154 return EXIT_SUCCESS;
157 /**************************************************************************
158 Progress indications from downloader
159 **************************************************************************/
160 static void msg_callback(const char *msg)
162 gui->display_msg(msg);
165 /**************************************************************************
166 Progress indications from downloader thread
167 **************************************************************************/
168 static void msg_callback_thr(const char *msg)
170 gui->display_msg_thr(msg);
173 /**************************************************************************
174 Progress indications from downloader
175 **************************************************************************/
176 static void progress_callback_thr(int downloaded, int max)
178 gui->progress_thr(downloaded, max);
181 /**************************************************************************
182 Setup GUI object
183 **************************************************************************/
184 void mpgui::setup(QWidget *central, struct fcmp_params *params)
186 #define URL_LABEL_TEXT N_("Modpack URL")
187 QVBoxLayout *main_layout = new QVBoxLayout();
188 QHBoxLayout *hl = new QHBoxLayout();
189 QPushButton *install_button = new QPushButton(QString::fromUtf8(_("Install modpack")));
190 QStringList headers;
191 QLabel *URL_label;
192 QLabel *version_label;
193 char verbuf[2048];
194 const char *rev_ver = fc_svn_revision();
196 if (rev_ver == nullptr) {
197 rev_ver = fc_git_revision();
199 if (rev_ver == nullptr) {
200 fc_snprintf(verbuf, sizeof(verbuf), "%s%s", word_version(), VERSION_STRING);
201 } else {
202 fc_snprintf(verbuf, sizeof(verbuf), _("%s%s\ncommit: %s"),
203 word_version(), VERSION_STRING, rev_ver);
205 } else {
206 fc_snprintf(verbuf, sizeof(verbuf), "%s%s (%s)", word_version(), VERSION_STRING,
207 rev_ver);
210 version_label = new QLabel(QString::fromUtf8(verbuf));
211 version_label->setAlignment(Qt::AlignHCenter);
212 version_label->setParent(central);
213 version_label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
214 main_layout->addWidget(version_label);
216 mplist_table = new QTableWidget();
217 mplist_table->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
218 mplist_table->setColumnCount(ML_COL_COUNT);
219 headers << QString::fromUtf8(_("Name")) << QString::fromUtf8(_("Version"));
220 headers << QString::fromUtf8(_("Installed")) << QString::fromUtf8(Q_("?modpack:Type"));
221 headers << QString::fromUtf8(_("Subtype")) << QString::fromUtf8(_("License"));
222 headers << QString::fromUtf8(_("URL")) << "typeint";
223 mplist_table->setHorizontalHeaderLabels(headers);
224 mplist_table->verticalHeader()->setVisible(false);
225 mplist_table->setEditTriggers(QAbstractItemView::NoEditTriggers);
226 mplist_table->setSelectionBehavior(QAbstractItemView::SelectRows);
227 mplist_table->setSelectionMode(QAbstractItemView::SingleSelection);
228 mplist_table->hideColumn(ML_TYPE);
230 connect(mplist_table, SIGNAL(cellClicked(int, int)), this, SLOT(row_selected(int, int)));
231 connect(mplist_table, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(row_download(QModelIndex)));
232 connect(this, SIGNAL(display_msg_thr_signal(const char *)), this, SLOT(display_msg(const char *)));
233 connect(this, SIGNAL(progress_thr_signal(int, int)), this, SLOT(progress(int, int)));
234 connect(this, SIGNAL(refresh_list_versions_thr_signal()), this, SLOT(refresh_list_versions()));
236 main_layout->addWidget(mplist_table);
238 URL_label = new QLabel(QString::fromUtf8(_(URL_LABEL_TEXT)));
239 URL_label->setParent(central);
240 hl->addWidget(URL_label);
242 URLedit = new QLineEdit(central);
243 if (params->autoinstall == nullptr) {
244 URLedit->setText(DEFAULT_URL_START);
245 } else {
246 URLedit->setText(QString::fromUtf8(params->autoinstall));
248 URLedit->setFocus();
250 connect(URLedit, SIGNAL(returnPressed()), this, SLOT(URL_given()));
252 hl->addWidget(URLedit);
253 main_layout->addLayout(hl);
255 connect(install_button, SIGNAL(pressed()), this, SLOT(URL_given()));
256 main_layout->addWidget(install_button);
258 bar = new QProgressBar(central);
259 main_layout->addWidget(bar);
261 msg_dspl = new QLabel(QString::fromUtf8(_("Select modpack to install")));
262 msg_dspl->setParent(central);
263 main_layout->addWidget(msg_dspl);
265 msg_dspl->setAlignment(Qt::AlignHCenter);
267 central->setLayout(main_layout);
270 /**************************************************************************
271 Display status message
272 **************************************************************************/
273 void mpgui::display_msg(const char *msg)
275 log_verbose("%s", msg);
276 msg_dspl->setText(QString::fromUtf8(msg));
279 /**************************************************************************
280 Display status message from another thread
281 **************************************************************************/
282 void mpgui::display_msg_thr(const char *msg)
284 emit display_msg_thr_signal(msg);
287 /**************************************************************************
288 Update progress bar
289 **************************************************************************/
290 void mpgui::progress(int downloaded, int max)
292 bar->setMaximum(max);
293 bar->setValue(downloaded);
296 /**************************************************************************
297 Update progress bar from another thread
298 **************************************************************************/
299 void mpgui::progress_thr(int downloaded, int max)
301 emit progress_thr_signal(downloaded, max);
304 /**************************************************************************
305 Download modpack from given URL
306 **************************************************************************/
307 static void gui_download_modpack(QString URL)
309 if (worker != nullptr) {
310 if (worker->isRunning()) {
311 gui->display_msg(_("Another download already active"));
312 return;
314 } else {
315 worker = new mpqt_worker;
318 worker->download(URL, gui, &fcmp, msg_callback_thr, progress_callback_thr);
321 /**************************************************************************
322 User entered URL
323 **************************************************************************/
324 void mpgui::URL_given()
326 gui_download_modpack(URLedit->text());
329 /**************************************************************************
330 Refresh display of modpack list modpack versions
331 **************************************************************************/
332 void mpgui::refresh_list_versions()
334 for (int i = 0; i < mpcount; i++) {
335 QString name_str;
336 int type_int;
337 const char *new_inst;
338 enum modpack_type type;
340 name_str = mplist_table->item(i, ML_COL_NAME)->text();
341 type_int = mplist_table->item(i, ML_TYPE)->text().toInt();
342 type = (enum modpack_type) type_int;
343 new_inst = get_installed_version(name_str.toUtf8().data(), type);
345 if (new_inst == nullptr) {
346 new_inst = _("Not installed");
349 mplist_table->item(i, ML_COL_INST)->setText(QString::fromUtf8(new_inst));
352 mplist_table->resizeColumnsToContents();
355 /**************************************************************************
356 Refresh display of modpack list modpack versions from another thread
357 **************************************************************************/
358 void mpgui::refresh_list_versions_thr()
360 emit refresh_list_versions_thr_signal();
363 /**************************************************************************
364 Build main modpack list view
365 **************************************************************************/
366 void mpgui::setup_list(const char *name, const char *URL,
367 const char *version, const char *license,
368 enum modpack_type type, const char *subtype,
369 const char *notes)
371 const char *type_str;
372 const char *lic_str;
373 const char *inst_str;
374 QString type_nbr;
375 QTableWidgetItem *item;
377 if (modpack_type_is_valid(type)) {
378 type_str = _(modpack_type_name(type));
379 } else {
380 /* TRANS: Unknown modpack type */
381 type_str = _("?");
384 if (license != nullptr) {
385 lic_str = license;
386 } else {
387 /* TRANS: License of modpack is not known */
388 lic_str = Q_("?license:Unknown");
391 inst_str = get_installed_version(name, type);
392 if (inst_str == nullptr) {
393 inst_str = _("Not installed");
396 mplist_table->setRowCount(mpcount+1);
398 item = new QTableWidgetItem(QString::fromUtf8(name));
399 item->setToolTip(QString::fromUtf8(notes));
400 mplist_table->setItem(mpcount, ML_COL_NAME, item);
401 item = new QTableWidgetItem(QString::fromUtf8(version));
402 item->setToolTip(QString::fromUtf8(notes));
403 mplist_table->setItem(mpcount, ML_COL_VER, item);
404 item = new QTableWidgetItem(QString::fromUtf8(inst_str));
405 item->setToolTip(QString::fromUtf8(notes));
406 mplist_table->setItem(mpcount, ML_COL_INST, item);
407 item = new QTableWidgetItem(QString::fromUtf8(type_str));
408 item->setToolTip(QString::fromUtf8(notes));
409 mplist_table->setItem(mpcount, ML_COL_TYPE, item);
410 item = new QTableWidgetItem(QString::fromUtf8(subtype));
411 item->setToolTip(QString::fromUtf8(notes));
412 mplist_table->setItem(mpcount, ML_COL_SUBTYPE, item);
413 item = new QTableWidgetItem(QString::fromUtf8(lic_str));
414 item->setToolTip(QString::fromUtf8(notes));
415 mplist_table->setItem(mpcount, ML_COL_LIC, item);
416 item = new QTableWidgetItem(QString::fromUtf8(URL));
417 item->setToolTip(QString::fromUtf8(notes));
418 mplist_table->setItem(mpcount, ML_COL_URL, item);
420 type_nbr.setNum(type);
421 item = new QTableWidgetItem(type_nbr);
422 item->setToolTip(notes);
423 mplist_table->setItem(mpcount, ML_TYPE, item);
425 mplist_table->resizeColumnsToContents();
426 mpcount++;
429 /**************************************************************************
430 Build main modpack list view
431 **************************************************************************/
432 static void setup_modpack_list(const char *name, const char *URL,
433 const char *version, const char *license,
434 enum modpack_type type, const char *subtype,
435 const char *notes)
437 // Just call setup_list for gui singleton
438 gui->setup_list(name, URL, version, license, type, subtype, notes);
441 /**************************************************************************
442 User activated another table row
443 **************************************************************************/
444 void mpgui::row_selected(int row, int column)
446 QString URL = mplist_table->item(row, ML_COL_URL)->text();
448 URLedit->setText(URL);
451 /**************************************************************************
452 User activated another table row
453 **************************************************************************/
454 void mpgui::row_download(const QModelIndex &index)
456 QString URL = mplist_table->item(index.row(), ML_COL_URL)->text();
458 URLedit->setText(URL);
460 URL_given();
463 /**************************************************************************
464 Main window constructor
465 **************************************************************************/
466 mpgui_main::mpgui_main(QApplication *qapp_in, QWidget *central_in) : QMainWindow()
468 qapp = qapp_in;
469 central = central_in;
472 /**************************************************************************
473 Open dialog to confirm that user wants to quit modpack installer.
474 **************************************************************************/
475 void mpgui_main::popup_quit_dialog()
477 QMessageBox ask(central);
478 int ret;
480 ask.setText(_("Modpack installation in progress.\nAre you sure you want to quit?"));
481 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
482 ask.setDefaultButton(QMessageBox::Cancel);
483 ask.setIcon(QMessageBox::Warning);
484 ask.setWindowTitle(_("Quit?"));
485 ret = ask.exec();
487 switch (ret) {
488 case QMessageBox::Cancel:
489 return;
490 break;
491 case QMessageBox::Ok:
492 qapp->quit();
493 break;
497 /**************************************************************************
498 User clicked windows close button.
499 **************************************************************************/
500 void mpgui_main::closeEvent(QCloseEvent *event)
502 if (worker != nullptr && worker->isRunning()) {
503 // Download in progress. Confirm quit from user.
504 popup_quit_dialog();
505 event->ignore();