Kstars

opships.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Jasem Mutlaq <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 
8 #include "opships.h"
9 
10 #include "kstars.h"
11 #include "hipsmanager.h"
12 #include "Options.h"
13 #include "skymap.h"
14 #include "auxiliary/ksnotification.h"
15 #include "auxiliary/filedownloader.h"
16 #include "auxiliary/kspaths.h"
17 
18 #include <KConfigDialog>
19 
20 #include <QCheckBox>
21 #include <QComboBox>
22 #include <QFileDialog>
23 #include <QPushButton>
24 #include <QStringList>
25 
26 // Qt version calming
27 #include <qtkeepemptyparts.h>
28 
29 static const QStringList hipsKeys = { "ID", "obs_title", "obs_description", "hips_order", "hips_frame", "hips_tile_width", "hips_tile_format", "hips_service_url", "moc_sky_fraction"};
30 
31 OpsHIPSDisplay::OpsHIPSDisplay() : QFrame(KStars::Instance())
32 {
33  setupUi(this);
34 }
35 
36 OpsHIPSCache::OpsHIPSCache() : QFrame(KStars::Instance())
37 {
38  setupUi(this);
39 
40  connect(selectDirectoryB, &QPushButton::clicked, this, [this]()
41  {
42  QString dir = QFileDialog::getExistingDirectory(this, i18nc("@title:window", "HiPS Offline Storage"),
43  kcfg_HIPSOfflinePath->text());
44 
45  if (dir.isEmpty())
46  return;
47 
48  kcfg_HIPSOfflinePath->setText(dir);
49 
50  QDir hipsDirectory(dir);
51  auto orders = hipsDirectory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
52  HIPSManager::Instance()->setOfflineLevels(orders);
53  HIPSManager::Instance()->setCurrentSource("Offline");
54  });
55 }
56 
57 OpsHIPS::OpsHIPS() : QFrame(KStars::Instance())
58 {
59  setupUi(this);
60 
61  //Get a pointer to the KConfigDialog
62  m_ConfigDialog = KConfigDialog::exists("hipssettings");
63 
64  QString path = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(
65  QLatin1String("hips_previews/"));
66  QDir dir;
67  dir.mkpath(path);
68 
69  connect(refreshSourceB, SIGNAL(clicked()), this, SLOT(slotRefresh()));
70 
71  connect(sourcesList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(slotItemUpdated(QListWidgetItem*)));
72  connect(sourcesList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(slotItemClicked(QListWidgetItem*)));
73 
74  if (sourcesList->count() == 0)
75  slotRefresh();
76 }
77 
78 void OpsHIPS::slotRefresh()
79 {
80  downloadJob = new FileDownloader();
81 
82  downloadJob->setProgressDialogEnabled(true, i18n("HiPS Update"), i18n("Downloading HiPS sources..."));
83 
84  QObject::connect(downloadJob, SIGNAL(downloaded()), this, SLOT(downloadReady()));
85  QObject::connect(downloadJob, SIGNAL(error(QString)), this, SLOT(downloadError(QString)));
86 
87  downloadJob->get(
88  QUrl("http://alasky.unistra.fr/MocServer/query?hips_service_url=*&dataproduct_type=!catalog&dataproduct_type=!cube&&moc_sky_fraction=1&get=record"));
89 }
90 
91 void OpsHIPS::downloadReady()
92 {
93  sources.clear();
94 
95  QTextStream stream(downloadJob->downloadedData());
96 
97  QStringList hipsTitles;
98 
99  QMap<QString, QString> oneSource;
100  while (stream.atEnd() == false)
101  {
102  QString line = stream.readLine();
103  if (line.isEmpty())
104  {
105  sources.append(oneSource);
106  oneSource.clear();
107  continue;
108  }
109 
110  QStringList keyvalue = line.split('=', Qt::KeepEmptyParts);
111  QString key = keyvalue[0].simplified();
112  if (hipsKeys.contains(key) == false)
113  continue;
114  QString value = keyvalue[1].simplified();
115  oneSource[key] = value;
116  if (key == "obs_title")
117  hipsTitles << value;
118  }
119 
120  // Get existing database sources
121  QList<QMap<QString, QString>> dbSources;
122  KStarsData::Instance()->userdb()->GetAllHIPSSources(dbSources);
123 
124  // Get existing database titles
125  QStringList dbTitles;
126  for (QMap<QString, QString> oneSource : dbSources)
127  dbTitles << oneSource["obs_title"];
128 
129  // Add all titles to list widget
130  sourcesList->addItems(hipsTitles);
131  QListWidgetItem* item = nullptr;
132 
133  // Make sources checkable and check sources that already exist in the database
134  sourcesList->blockSignals(true);
135  for(int i = 0; i < sourcesList->count(); ++i)
136  {
137  item = sourcesList->item(i);
138  item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
139  item->setCheckState(dbTitles.contains(item->text()) ? Qt::Checked : Qt::Unchecked);
140 
141  if (item->text() == Options::hIPSSource())
142  {
143  item->setSelected(true);
144  sourcesList->scrollToItem(item);
145  slotItemClicked(item);
146  }
147  }
148  sourcesList->blockSignals(false);
149 
150  // Delete job later
151  downloadJob->deleteLater();
152 }
153 
154 void OpsHIPS::downloadError(const QString &errorString)
155 {
156  KSNotification::error(i18n("Error downloading HiPS sources: %1", errorString));
157  downloadJob->deleteLater();
158 }
159 
160 void OpsHIPS::slotItemUpdated(QListWidgetItem *item)
161 {
162  for(QMap<QString, QString> &oneSource : sources)
163  {
164  if (oneSource.value("obs_title") == item->text())
165  {
166  if (item->checkState() == Qt::Checked)
167  KStarsData::Instance()->userdb()->AddHIPSSource(oneSource);
168  else
169  KStarsData::Instance()->userdb()->DeleteHIPSSource(oneSource.value("ID"));
170  break;
171  }
172  }
173 }
174 
175 void OpsHIPS::slotItemClicked(QListWidgetItem *item)
176 {
177  for(QMap<QString, QString> &oneSource : sources)
178  {
179  if (oneSource.value("obs_title") == item->text())
180  {
181  sourceDescription->setText(oneSource.value("obs_description"));
182  // Get stored preview, if not found, it will be downloaded.
183  setPreview(oneSource.value("ID"), oneSource.value("hips_service_url"));
184  break;
185  }
186  }
187 }
188 
189 void OpsHIPS::setPreview(const QString &id, const QString &url)
190 {
191  uint hash = qHash(id);
192  QString previewName = QString("%1.jpg").arg(hash);
193 
194  QString currentPreviewPath = QDir(KSPaths::locate(QStandardPaths::AppLocalDataLocation,
195  QLatin1String("hips_previews"))).filePath(previewName);
196  if (currentPreviewPath.isEmpty() == false)
197  {
198  sourceImage->setPixmap(QPixmap(currentPreviewPath));
199  }
200  else
201  {
202  currentPreviewPath = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(
203  QLatin1String("hips_previews/") + previewName);
204 
205  previewJob = new FileDownloader();
206  connect(previewJob, SIGNAL(downloaded()), this, SLOT(previewReady()));
207 
208  previewJob->setDownloadedFileURL(QUrl::fromLocalFile(currentPreviewPath));
209 
210  previewJob->get(QUrl(url + QLatin1String("/preview.jpg")));
211  }
212 }
213 
214 void OpsHIPS::previewReady()
215 {
216  QString previewFile = previewJob->getDownloadedFileURL().toLocalFile();
217  QFileInfo previewInfo(previewFile);
218  // If less than 1kb then it's junk
219  if (previewInfo.size() < 1024)
220  {
221  sourceImage->setPixmap(QPixmap(":/images/noimage.png"));
222  QFile::remove(previewFile);
223  }
224  else
225  sourceImage->setPixmap(QPixmap(previewFile));
226 }
227 
QString text() const const
bool remove()
Qt::CheckState checkState() const const
void clear()
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
void clicked(bool checked)
void setSelected(bool select)
KSUserDB * userdb()
Definition: kstarsdata.h:214
Qt::ItemFlags flags() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setFlags(Qt::ItemFlags flags)
void setCheckState(Qt::CheckState state)
ItemIsUserCheckable
QString i18n(const char *text, const TYPE &arg...)
KeepEmptyParts
bool isEmpty() const const
QUrl fromLocalFile(const QString &localFile)
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
static KConfigDialog * exists(const QString &name)
This is the main window for KStars. In addition to the GUI elements, the class contains the program c...
Definition: kstars.h:92
void setupUi(QWidget *widget)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
KIOFILEWIDGETS_EXPORT QString dir(const QString &fileClass)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString filePath(const QString &fileName) const const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
QString & append(QChar ch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:56 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.