1 /*
2 * Copyright (C) 2014-2019 Christopho, Solarus - http://www.solarus-games.org
3 *
4 * Solarus Quest Editor is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Solarus Quest Editor is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 #include "widgets/package_dialog.h"
18 #include "editor_settings.h"
19 #include "quest.h"
20 #include "ui_package_dialog.h"
21
22 #include <QFileDialog>
23
24 /* In terms of implementation, this class wraps four states and handles the
25 * transitions
26 *
27 * 0. selection: Choose the package location and name.
28 * You can cancel the operation (close) or go ahead to 1.
29 * 1. ongoing: Tells you the operation is in progress.
30 * You can cancel the operation, it goes to 2 on success
31 * 2. complete: Just a little message and a close button.
32 * Optionally there is an auto-close feature.
33 * 3. failed: The packaging failed, error message should be displayed.
34 * After looking at the message close the dialog.
35 *
36 * For simplicity we use the widget pointers instead of the index to refer to
37 * them. (Except that we start at index 0: selection.)
38 */
39
40 namespace SolarusEditor {
41
42 namespace {
43
get_default_save_path(const Quest & quest)44 QString get_default_save_path(const Quest &quest) {
45 return quest.get_root_path() + "/" + quest.get_name() + ".solarus";
46 }
47
48 } // Anonymous namespace.
49
PackageDialog(Quest const & quest,QWidget * parent)50 PackageDialog::PackageDialog(Quest const& quest, QWidget *parent) :
51 QDialog(parent),
52 ui(new Ui::PackageDialog),
53 process(),
54 quest(quest),
55 save_path() {
56
57 ui->setupUi(this);
58 ui->stacked_widget->setCurrentWidget(ui->selection);
59 ui->button_box->button(QDialogButtonBox::Apply)->setText(tr("Build"));
60
61 process.setReadChannel(QProcess::StandardOutput);
62
63 connect(ui->button_box->button(QDialogButtonBox::Apply), &QPushButton::clicked,
64 this, &PackageDialog::process_start);
65 connect(ui->selection_browse, &QPushButton::clicked,
66 this, &PackageDialog::start_file_selection);
67 connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
68 this, &PackageDialog::process_finished);
69 connect(&process, &QProcess::readyReadStandardOutput,
70 this, &PackageDialog::handle_process_standard_output);
71
72 const QString &saved_path = EditorSettings()
73 .get_value_string(EditorSettings::package_save_path);
74 set_save_path(saved_path.isEmpty() ? get_default_save_path(quest) : saved_path);
75 }
76
77 PackageDialog::~PackageDialog() = default;
78
set_save_path(const QString & new_save_path)79 void PackageDialog::set_save_path(const QString &new_save_path) {
80 save_path = new_save_path;
81 ui->selection_file->setText(save_path);
82 EditorSettings().set_value(
83 EditorSettings::package_save_path, QVariant(save_path));
84 }
85
process_start()86 void PackageDialog::process_start() {
87 ui->button_box->button(QDialogButtonBox::Apply)->setEnabled(false);
88 ui->button_box->button(QDialogButtonBox::Close)->setEnabled(false);
89 ui->stacked_widget->setCurrentWidget(ui->ongoing);
90 ui->ongoing_output->setPlainText(tr("Starting...\n"));
91
92 process.setWorkingDirectory(quest.get_data_path());
93 process.start("zip", QStringList() << "-r" << save_path << ".");
94 }
95
process_finished(int code,QProcess::ExitStatus status)96 void PackageDialog::process_finished(int code, QProcess::ExitStatus status) {
97
98 if (status == QProcess::CrashExit || code != 0) {
99 ui->failed_output->setPlainText(
100 QString(process.readAllStandardError()));
101 ui->failed_code->setText(
102 status == QProcess::CrashExit ?
103 tr("Crashed") : QString::number(code));
104 ui->stacked_widget->setCurrentWidget(ui->failed);
105 } else {
106 ui->stacked_widget->setCurrentWidget(ui->completed);
107 }
108 ui->button_box->button(QDialogButtonBox::Close)->setEnabled(true);
109 }
110
start_file_selection()111 void PackageDialog::start_file_selection() {
112
113 const QString& path = QFileDialog::getSaveFileName(
114 this, tr("Quest package location:"), save_path,
115 tr("Solarus Packages (*.solarus)"));
116 if (!path.isEmpty()) {
117 set_save_path(path);
118 }
119 }
120
handle_process_standard_output()121 void PackageDialog::handle_process_standard_output() {
122 while (process.canReadLine()) {
123 const QByteArray &line = process.readLine();
124 ui->ongoing_output->moveCursor(QTextCursor::End);
125 ui->ongoing_output->insertPlainText(QString(line));
126 }
127 }
128
129 }
130