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

KDE's Doxygen guidelines are available online.