]> git.mxchange.org Git - flightgear.git/blob - src/GUI/SetupRootDialog.cxx
Code cleanups, code updates and fix at least on (possible) devide-by-zero
[flightgear.git] / src / GUI / SetupRootDialog.cxx
1 // SetupRootDialog.cxx - part of GUI launcher using Qt5
2 //
3 // Written by James Turner, started December 2014.
4 //
5 // Copyright (C) 2014 James Turner <zakalawe@mac.com>
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "SetupRootDialog.hxx"
26
27 #include <QFileDialog>
28 #include <QDesktopServices>
29 #include <QDir>
30 #include <QFileInfo>
31 #include <QMessageBox>
32 #include <QSettings>
33 #include <QDebug>
34 #include <QSettings>
35 #include <QUrl>
36
37 #include "ui_SetupRootDialog.h"
38
39 #include <Main/globals.hxx>
40 #include <Main/fg_init.hxx>
41 #include <Main/options.hxx>
42 #include <Include/version.h>
43 #include <Viewer/WindowBuilder.hxx>
44
45 SetupRootDialog::SetupRootDialog(PromptState prompt) :
46     QDialog(),
47     m_promptState(prompt)
48 {
49     m_ui.reset(new Ui::SetupRootDialog);
50     m_ui->setupUi(this);
51
52     connect(m_ui->browseButton, &QPushButton::clicked,
53              this, &SetupRootDialog::onBrowse);
54     connect(m_ui->downloadButton, &QPushButton::clicked,
55             this, &SetupRootDialog::onDownload);
56     connect(m_ui->buttonBox, &QDialogButtonBox::rejected,
57             this, &QDialog::reject);
58     connect(m_ui->useDefaultsButton, &QPushButton::clicked,
59             this, &SetupRootDialog::onUseDefaults);
60
61     // decide if the 'use defaults' button should be enabled or not
62     bool ok = defaultRootAcceptable();
63     m_ui->useDefaultsButton->setEnabled(ok);
64     m_ui->useDefaultLabel->setEnabled(ok);
65
66     m_ui->versionLabel->setText(tr("FlightGear version %1").arg(FLIGHTGEAR_VERSION));
67     m_ui->bigIcon->setPixmap(QPixmap(":/app-icon-large"));
68     updatePromptText();
69 }
70
71 bool SetupRootDialog::runDialog(bool usingDefaultRoot)
72 {
73     SetupRootDialog::PromptState prompt =
74         usingDefaultRoot ? DefaultPathCheckFailed : ExplicitPathCheckFailed;
75     return runDialog(prompt);
76 }
77
78 bool SetupRootDialog::runDialog(PromptState prompt)
79 {
80     // avoid double Apple menu and other weirdness if both Qt and OSG
81     // try to initialise various Cocoa structures.
82     flightgear::WindowBuilder::setPoseAsStandaloneApp(false);
83
84     SetupRootDialog dlg(prompt);
85     dlg.exec();
86     if (dlg.result() != QDialog::Accepted) {
87         exit(-1);
88     }
89
90     return true;
91 }
92
93 std::string SetupRootDialog::restoreUserSelectedRoot()
94 {
95     QSettings settings;
96     QString path = settings.value("fg-root").toString();
97     if (path == "!ask") {
98         bool ok = runDialog(ManualChoiceRequested);
99         Q_ASSERT(ok);
100         // run dialog either exit()s or sets fg_root, so this
101         // behaviour is safe and correct.
102         return globals->get_fg_root();
103     }
104
105     if (path.isEmpty()) {
106         return std::string(); // use the default path
107     }
108
109     if (validatePath(path) && validateVersion(path)) {
110         return path.toStdString();
111     } else {
112         // we have an existing path but it's invalid. Let's ask the
113         // user what they want
114         bool ok = runDialog(VersionCheckFailed);
115         Q_ASSERT(ok);
116         // run dialog either exit()s or sets fg_root, so this
117         // behaviour is safe and correct.
118         return globals->get_fg_root();
119     }
120 }
121
122 bool SetupRootDialog::validatePath(QString path)
123 {
124     // check assorted files exist in the root location, to avoid any chance of
125     // selecting an incomplete base package. This is probably overkill but does
126     // no harm
127     QStringList files = QStringList()
128         << "version"
129         << "preferences.xml"
130         << "Materials/base/materials-base.xml"
131         << "gui/menubar.xml"
132         << "Timezone/zone.tab";
133
134     QDir d(path);
135     if (!d.exists()) {
136         return false;
137     }
138
139     Q_FOREACH(QString s, files) {
140         if (!d.exists(s)) {
141             return false;
142         }
143     }
144
145     return true;
146 }
147
148 bool SetupRootDialog::validateVersion(QString path)
149 {
150     std::string ver = fgBasePackageVersion(SGPath(path.toStdString()));
151     return (ver == FLIGHTGEAR_VERSION);
152 }
153
154 bool SetupRootDialog::defaultRootAcceptable()
155 {
156     std::string r = flightgear::Options::sharedInstance()->platformDefaultRoot();
157     QString defaultRoot = QString::fromStdString(r);
158     return validatePath(defaultRoot) && validateVersion(defaultRoot);
159 }
160
161 SetupRootDialog::~SetupRootDialog()
162 {
163
164 }
165
166 void SetupRootDialog::onBrowse()
167 {
168     m_browsedPath = QFileDialog::getExistingDirectory(this,
169                                                      tr("Choose FlightGear data folder"));
170     if (m_browsedPath.isEmpty()) {
171         return;
172     }
173
174     if (!validatePath(m_browsedPath)) {
175         m_promptState = ChoseInvalidLocation;
176         updatePromptText();
177         return;
178     }
179
180     if (!validateVersion(m_browsedPath)) {
181         m_promptState = ChoseInvalidVersion;
182         updatePromptText();
183         return;
184     }
185
186     globals->set_fg_root(m_browsedPath.toStdString());
187
188     QSettings settings;
189     settings.setValue("fg-root", m_browsedPath);
190
191     accept(); // we're done
192 }
193
194 void SetupRootDialog::onDownload()
195 {
196     QUrl downloadUrl("http://download.flightgear.org/flightgear/Shared/");
197     QDesktopServices::openUrl(downloadUrl);
198 }
199
200 void SetupRootDialog::onUseDefaults()
201 {
202     std::string r = flightgear::Options::sharedInstance()->platformDefaultRoot();
203     m_browsedPath = QString::fromStdString(r);
204     globals->set_fg_root(r);
205     QSettings settings;
206     settings.remove("fg-root"); // remove any setting
207     accept();
208 }
209
210 void SetupRootDialog::updatePromptText()
211 {
212     QString t;
213     QString curRoot = QString::fromStdString(globals->get_fg_root());
214     switch (m_promptState) {
215     case DefaultPathCheckFailed:
216         t = tr("This copy of FlightGear does not include the base data files. " \
217                "Please select a suitable folder containing a previously download set of files.");
218         break;
219
220     case ExplicitPathCheckFailed:
221         t = tr("The requested location '%1' does not appear to be a valid set of data files for FlightGear").arg(curRoot);
222         break;
223
224     case VersionCheckFailed:
225     {
226         QString curVer = QString::fromStdString(fgBasePackageVersion(globals->get_fg_root()));
227         t = tr("Detected incompatible version of the data files: version %1 found, but this is FlightGear %2. " \
228                "(At location: '%3') " \
229                "Please install or select a matching set of data files.").arg(curVer).arg(QString::fromLatin1(FLIGHTGEAR_VERSION)).arg(curRoot);
230         break;
231     }
232
233     case ManualChoiceRequested:
234         t = tr("Please select or download a copy of the FlightGear data files.");
235         break;
236
237     case ChoseInvalidLocation:
238         t = tr("The choosen location (%1) does not appear to contain FlightGear data files. Please try another location.").arg(m_browsedPath);
239         break;
240
241     case ChoseInvalidVersion:
242     {
243         QString curVer = QString::fromStdString(fgBasePackageVersion(m_browsedPath.toStdString()));
244         t = tr("The choosen location (%1) contains files for version %2, but this is FlightGear %3. " \
245                "Please update or try another location").arg(m_browsedPath).arg(curVer).arg(QString::fromLatin1(FLIGHTGEAR_VERSION));
246         break;
247     }
248     }
249
250     m_ui->promptText->setText(t);
251 }
252