Kstars

kswizard.cpp
1/*
2 SPDX-FileCopyrightText: 2004 Jason Harris <kstars@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "kswizard.h"
8
9#include "geolocation.h"
10#include "kspaths.h"
11#include "kstars.h"
12#include "kstarsdata.h"
13#include "ksnotification.h"
14#include "ksutils.h"
15#include "Options.h"
16#include "widgets/dmsbox.h"
17
18#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
19#include <KNSWidgets/dialog.h>
20#else
21#include <kns3/downloaddialog.h>
22#endif
23
24#include <QDesktopServices>
25#include <QFile>
26#include <QLineEdit>
27#include <QPixmap>
28#include <QPushButton>
29#include <QStackedWidget>
30#include <QStandardPaths>
31
32namespace
33{
34bool hasPrefix(QString str, QString prefix)
35{
36 if (prefix.isEmpty())
37 return true;
38 return str.startsWith(prefix, Qt::CaseInsensitive);
39}
40}
41
42WizWelcomeUI::WizWelcomeUI(QWidget *parent) : QFrame(parent)
43{
44 setupUi(this);
45}
46
47WizLocationUI::WizLocationUI(QWidget *parent) : QFrame(parent)
48{
49 setupUi(this);
50}
51
52WizDownloadUI::WizDownloadUI(QWidget *parent) : QFrame(parent)
53{
54 setupUi(this);
55}
56
57#ifdef Q_OS_MACOS
58WizDataUI::WizDataUI(QWidget *parent) : QFrame(parent)
59{
60 setupUi(this);
61}
62#endif
63
65{
66 wizardStack = new QStackedWidget(this);
67 adjustSize();
68
69 setWindowTitle(i18nc("@title:window", "Startup Wizard"));
70
71 QVBoxLayout *mainLayout = new QVBoxLayout;
72 mainLayout->addWidget(wizardStack);
73 setLayout(mainLayout);
74
75 buttonBox = new QDialogButtonBox(Qt::Horizontal);
76 nextB = new QPushButton(i18n("&Next >"));
77 nextB->setDefault(true);
78 backB = new QPushButton(i18n("< &Back"));
79 backB->setEnabled(false);
80 completeB = new QPushButton(i18n("Done"));
81
82 buttonBox->addButton(backB, QDialogButtonBox::ActionRole);
83 buttonBox->addButton(nextB, QDialogButtonBox::ActionRole);
84 buttonBox->addButton(completeB, QDialogButtonBox::AcceptRole);
85 completeB->setVisible(false);
86
87 mainLayout->addWidget(buttonBox);
88
89 welcome = new WizWelcomeUI(wizardStack);
90#ifdef Q_OS_MACOS
91 data = new WizDataUI(wizardStack);
92#endif
93 location = new WizLocationUI(wizardStack);
94 WizDownloadUI *download = new WizDownloadUI(wizardStack);
95
96 wizardStack->addWidget(welcome);
97#ifdef Q_OS_MACOS
98 wizardStack->addWidget(data);
99#endif
100 wizardStack->addWidget(location);
101 wizardStack->addWidget(download);
102 wizardStack->setCurrentWidget(welcome);
103
104 //Load images into banner frames.
105 QPixmap im;
106 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzstars.png")))
107 welcome->Banner->setPixmap(im);
108 else if (im.load(QDir(QCoreApplication::applicationDirPath() + "/../Resources/kstars").absolutePath() +
109 "/wzstars.png"))
110 welcome->Banner->setPixmap(im);
111 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzgeo.png")))
112 location->Banner->setPixmap(im);
113 else if (im.load(QDir(QCoreApplication::applicationDirPath() + "/../Resources/kstars").absolutePath() + "/wzgeo.png"))
114 location->Banner->setPixmap(im);
115 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzdownload.png")))
116 download->Banner->setPixmap(im);
117 else if (im.load(QDir(QCoreApplication::applicationDirPath() + "/../Resources/kstars").absolutePath() +
118 "/wzdownload.png"))
119 download->Banner->setPixmap(im);
120
121#ifdef Q_OS_MACOS
122 if (im.load(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "wzdownload.png")))
123 data->Banner->setPixmap(im);
124 else if (im.load(QDir(QCoreApplication::applicationDirPath() + "/../Resources/kstars").absolutePath() +
125 "/wzdownload.png"))
126 data->Banner->setPixmap(im);
127
128 data->dataPath->setText(
130 "kstars");
131 slotUpdateDataButtons();
132
133 connect(data->copyKStarsData, SIGNAL(clicked()), this, SLOT(slotOpenOrCopyKStarsDataDirectory()));
134 connect(data->installGSC, SIGNAL(clicked()), this, SLOT(slotInstallGSC()));
135
136 gscMonitor = new QProgressIndicator(data);
137 data->GSCLayout->addWidget(gscMonitor);
138 data->downloadProgress->setValue(0);
139
140 data->downloadProgress->setEnabled(false);
141 data->downloadProgress->setVisible(false);
142
143 data->gscInstallCancel->setVisible(false);
144 data->gscInstallCancel->setEnabled(false);
145
146#endif
147
148 //connect signals/slots
149 connect(nextB, SIGNAL(clicked()), this, SLOT(slotNextPage()));
150 connect(backB, SIGNAL(clicked()), this, SLOT(slotPrevPage()));
151 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
152 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
153
154 connect(location->CityListBox, SIGNAL(itemSelectionChanged()), this, SLOT(slotChangeCity()));
155 connect(location->CityFilter, SIGNAL(textChanged(QString)), this, SLOT(slotFilterCities()));
156 connect(location->ProvinceFilter, SIGNAL(textChanged(QString)), this, SLOT(slotFilterCities()));
157 connect(location->CountryFilter, SIGNAL(textChanged(QString)), this, SLOT(slotFilterCities()));
158 connect(download->DownloadButton, SIGNAL(clicked()), this, SLOT(slotDownload()));
159
160 //Initialize Geographic Location page
161 if (KStars::Instance())
162 initGeoPage();
163}
164
165void KSWizard::setButtonsEnabled()
166{
167 nextB->setEnabled(wizardStack->currentIndex() < wizardStack->count() - 1);
168 backB->setEnabled(wizardStack->currentIndex() > 0);
169 completeB->setVisible(wizardStack->currentIndex() == wizardStack->count() - 1);
170
171#ifdef Q_OS_MACOS
172 if ((wizardStack->currentWidget() == data) && (!dataDirExists()))
173 {
174 nextB->setEnabled(false);
175 }
176#endif
177}
178
179void KSWizard::slotNextPage()
180{
181 wizardStack->setCurrentIndex(wizardStack->currentIndex() + 1);
182 setButtonsEnabled();
183}
184
185void KSWizard::slotPrevPage()
186{
187 wizardStack->setCurrentIndex(wizardStack->currentIndex() - 1);
188 setButtonsEnabled();
189}
190
191void KSWizard::initGeoPage()
192{
193 KStarsData *data = KStarsData::Instance();
194 location->LongBox->setReadOnly(true);
195 location->LatBox->setReadOnly(true);
196
197 //Populate the CityListBox
198 //flag the ID of the current City
199 foreach (GeoLocation *loc, data->getGeoList())
200 {
201 location->CityListBox->addItem(loc->fullName());
202 filteredCityList.append(loc);
203 if (loc->fullName() == data->geo()->fullName())
204 {
205 Geo = loc;
206 }
207 }
208
209 //Sort alphabetically
210 location->CityListBox->sortItems();
211 //preset to current city
212 QList<QListWidgetItem*> locations = location->CityListBox->findItems(QString(data->geo()->fullName()), Qt::MatchExactly);
213 if (locations.isEmpty() == false)
214 location->CityListBox->setCurrentItem(locations[0]);
215}
216
217void KSWizard::slotChangeCity()
218{
219 if (location->CityListBox->currentItem())
220 {
221 for (auto &city : filteredCityList)
222 {
223 if (city->fullName() == location->CityListBox->currentItem()->text())
224 {
225 Geo = city;
226 break;
227 }
228 }
229 location->LongBox->show(Geo->lng());
230 location->LatBox->show(Geo->lat());
231 }
232}
233
234void KSWizard::slotFilterCities()
235{
236 location->CityListBox->clear();
237 //Do NOT delete members of filteredCityList!
238 filteredCityList.clear();
239
240 foreach (GeoLocation *loc, KStarsData::Instance()->getGeoList())
241 {
242 if (hasPrefix(loc->translatedName(), location->CityFilter->text()) &&
243 hasPrefix(loc->translatedCountry(), location->CountryFilter->text()) &&
244 hasPrefix(loc->translatedProvince(), location->ProvinceFilter->text()))
245 {
246 location->CityListBox->addItem(loc->fullName());
247 filteredCityList.append(loc);
248 }
249 }
250 location->CityListBox->sortItems();
251
252 if (location->CityListBox->count() > 0) // set first item in list as selected
253 location->CityListBox->setCurrentItem(location->CityListBox->item(0));
254}
255
256void KSWizard::slotDownload()
257{
259}
260
261void KSWizard::slotOpenOrCopyKStarsDataDirectory()
262{
263#ifdef Q_OS_MACOS
264 QString dataLocation =
266 if (dataLocation.isEmpty())
267 {
268 QDir dataSourceDir = QDir(QCoreApplication::applicationDirPath() + "/../Resources/kstars").absolutePath();
269 if (! dataSourceDir.exists()) //If there is no default data directory in the app bundle
270 {
271 KSNotification::sorry(i18n("There was no default data directory found in the app bundle."));
272 return;
273 }
274 QDir writableDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
275 writableDir.mkpath(".");
276 dataLocation =
278 if (dataLocation.isEmpty()) //If there *still* is not a kstars data directory
279 {
280 KSNotification::sorry(i18n("There was a problem creating the data directory ~/Library/Application Support/."));
281 return;
282 }
283 KSUtils::copyRecursively(dataSourceDir.absolutePath(), dataLocation);
284 //This will update the next, ok, and copy kstars dir buttons.
285 slotUpdateDataButtons();
286 }
287 else
288 {
292 }
293
294#endif
295}
296
297void KSWizard::slotInstallGSC()
298{
299#ifdef Q_OS_MACOS
300
302
303 QString location =
305 gscZipPath = location + "/gsc.zip";
306
307 data->downloadProgress->setVisible(true);
308 data->downloadProgress->setEnabled(true);
309
310 data->gscInstallCancel->setVisible(true);
311 data->gscInstallCancel->setEnabled(true);
312
313 QString gscURL = "http://www.indilib.org/jdownloads/Mac/gsc.zip";
314
315 QNetworkReply *response = manager->get(QNetworkRequest(QUrl(gscURL)));
316
317 QMetaObject::Connection *cancelConnection = new QMetaObject::Connection();
318 QMetaObject::Connection *replyConnection = new QMetaObject::Connection();
319 QMetaObject::Connection *percentConnection = new QMetaObject::Connection();
320
321 *percentConnection = connect(response, &QNetworkReply::downloadProgress,
322 [ = ](qint64 bytesReceived, qint64 bytesTotal)
323 {
324 data->downloadProgress->setValue(bytesReceived);
325 data->downloadProgress->setMaximum(bytesTotal);
326 });
327
328 *cancelConnection = connect(data->gscInstallCancel, &QPushButton::clicked,
329 [ = ]()
330 {
331 qDebug() << Q_FUNC_INFO << "Download Cancelled.";
332
333 if(cancelConnection)
334 disconnect(*cancelConnection);
335 if(replyConnection)
336 disconnect(*replyConnection);
337
338 if(response)
339 {
340 response->abort();
341 response->deleteLater();
342 }
343
344 data->downloadProgress->setVisible(false);
345 data->downloadProgress->setEnabled(false);
346
347 data->gscInstallCancel->setVisible(false);
348 data->gscInstallCancel->setEnabled(false);
349
350 if(manager)
351 manager->deleteLater();
352
353 });
354
355 *replyConnection = connect(response, &QNetworkReply::finished, this,
356 [ = ]()
357 {
358 if(response)
359 {
360
361 if(cancelConnection)
362 disconnect(*cancelConnection);
363 if(replyConnection)
364 disconnect(*replyConnection);
365
366 data->downloadProgress->setVisible(false);
367 data->downloadProgress->setEnabled(false);
368
369 data->gscInstallCancel->setVisible(false);
370 data->gscInstallCancel->setEnabled(false);
371
372
373 response->deleteLater();
374 if(manager)
375 manager->deleteLater();
376 if (response->error() != QNetworkReply::NoError)
377 return;
378
379 QByteArray responseData = response->readAll();
380
381 QFile file(gscZipPath);
382 if (QFileInfo(QFileInfo(file).path()).isWritable())
383 {
384 if (!file.open(QIODevice::WriteOnly))
385 {
386 KSNotification::error( i18n("File write error."));
387 return;
388 }
389 else
390 {
391 file.write(responseData.data(), responseData.size());
392 file.close();
393 slotExtractGSC();
394 }
395 }
396 else
397 {
398 KSNotification::error( i18n("Data folder permissions error."));
399 }
400 }
401 });
402
403#endif
404}
405
406void KSWizard::slotExtractGSC()
407{
408#ifdef Q_OS_MACOS
411 QProcess *gscExtractor = new QProcess();
412 connect(gscExtractor, SIGNAL(finished(int)), this, SLOT(slotGSCInstallerFinished()));
413 connect(gscExtractor, SIGNAL(finished(int)), this, SLOT(gscExtractor.deleteLater()));
414 gscExtractor->setWorkingDirectory(location);
415 gscExtractor->start("unzip", QStringList() << "-ao"
416 << "gsc.zip");
417 gscMonitor->startAnimation();
418#endif
419}
420
421void KSWizard::slotGSCInstallerFinished()
422{
423#ifdef Q_OS_MACOS
424 if (downloadMonitor)
425 {
426 downloadMonitor->stop();
427 delete downloadMonitor;
428 }
429 data->downloadProgress->setEnabled(false);
430 data->downloadProgress->setValue(0);
431 data->downloadProgress->setVisible(false);
432 gscMonitor->stopAnimation();
433 slotUpdateDataButtons();
434 if (QFile(gscZipPath).exists())
435 QFile(gscZipPath).remove();
436#endif
437}
438
439#ifdef Q_OS_MACOS
440bool KSWizard::dataDirExists()
441{
442 QString dataLocation =
444 return !dataLocation.isEmpty();
445}
446
447bool KSWizard::GSCExists()
448{
449 QString GSCLocation =
451 return !GSCLocation.isEmpty();
452}
453
454#endif
455
456void KSWizard::slotUpdateDataButtons()
457{
458#ifdef Q_OS_MACOS
459 data->dataDirFound->setChecked(dataDirExists());
460 if (dataDirExists())
461 {
462 data->copyKStarsData->setText("Open KStars Data Directory");
463 data->foundFeedback1->setText("The KStars Data Directory called kstars is located at:");
464 data->foundFeedback2->setText("Your data directory was found. If you have any problems with it, you can "
465 "always delete this data directory and KStars will give you a new data "
466 "directory. You can click this button to open the data directory, just be "
467 "careful not to delete any important files.");
468 }
469 else
470 {
471 data->foundFeedback1->setText("The KStars Data Directory called kstars should be located at:");
472 data->foundFeedback2->setText("<html><head/><body><p>Your data directory was not found. You can click the "
473 "button below to copy a default KStars data directory to the correct location, "
474 "or if you have a KStars directory already some place else, you can exit KStars "
475 "and copy it to that location yourself.</p></body></html>");
476 }
477 bool ifGSCExists = GSCExists();
478 data->GSCFound->setChecked(ifGSCExists);
479 data->installGSC->setDisabled(ifGSCExists || !dataDirExists());
480 if (ifGSCExists)
481 data->GSCFeedback->setText("GSC was found on your system. To use it, just take an image in the CCD simulator. "
482 "To uninstall, just delete the gsc folder from your data directory above.");
483 setButtonsEnabled();
484#endif
485}
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
QString fullName() const
const CachingDms * lat() const
Definition geolocation.h:70
const CachingDms * lng() const
Definition geolocation.h:64
QString translatedCountry() const
QString translatedName() const
QString translatedProvince() const
KSWizard(QWidget *parent=nullptr)
Constructor.
Definition kswizard.cpp:64
KStarsData is the backbone of KStars.
Definition kstarsdata.h:74
QList< GeoLocation * > & getGeoList()
Definition kstarsdata.h:238
GeoLocation * geo()
Definition kstarsdata.h:232
void slotDownload()
action slot: open KNewStuff window to download extra data.
static KStars * Instance()
Definition kstars.h:121
The QProgressIndicator class lets an application display a progress indicator to show that a long tas...
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QVariant location(const QVariant &res)
QString path(const QString &relativePath)
void clicked(bool checked)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
char * data()
qsizetype size() const const
QString applicationDirPath()
bool openUrl(const QUrl &url)
virtual void accept()
void accepted()
void finished(int result)
virtual void reject()
void rejected()
QPushButton * addButton(StandardButton button)
QString absolutePath() const const
bool exists() const const
bool remove()
QByteArray readAll()
void append(QList< T > &&value)
bool isEmpty() const const
QNetworkReply * get(const QNetworkRequest &request)
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
NetworkError error() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
bool load(const QString &fileName, const char *format, Qt::ImageConversionFlags flags)
void setWorkingDirectory(const QString &dir)
void start(OpenMode mode)
void setDefault(bool)
int addWidget(QWidget *widget)
QWidget * currentWidget() const const
void setCurrentWidget(QWidget *widget)
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
CaseInsensitive
MatchExactly
Horizontal
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QUrl fromLocalFile(const QString &localFile)
void adjustSize()
void setEnabled(bool)
void setLayout(QLayout *layout)
void show()
virtual void setVisible(bool visible)
void setWindowTitle(const QString &)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:16:40 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.