Kstars

stellarsolverprofileeditor.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Jasem Mutlaq <[email protected]>
3  SPDX-FileCopyrightText: 2017 Robert Lancaster <[email protected]>
4 
5  SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #include "stellarsolverprofileeditor.h"
9 
10 #include "kstars.h"
11 #include "Options.h"
12 #include "kspaths.h"
13 #include "ksmessagebox.h"
14 #include "stellarsolverprofile.h"
15 
16 #include <KConfigDialog>
17 #include <QInputDialog>
18 #include <QFileDialog>
19 #include <QSettings>
20 #include <stellarsolver.h>
21 
22 namespace Ekos
23 {
24 StellarSolverProfileEditor::StellarSolverProfileEditor(QWidget *parent, ProfileGroup group,
25  KConfigDialog *dialog) : QWidget(KStars::Instance())
26 {
27  Q_UNUSED(parent);
28  setupUi(this);
29 
30  //Get a pointer to the KConfigDialog
31  m_ConfigDialog = dialog;
32 
33  setProfileGroup(group);
34  optionsProfileGroup->setEnabled(false);
35 
36  /* // we may want to do this eventually
37  connect(optionsProfileGroup, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index){
38  setProfileGroup((ProfileGroup)index);
39  });
40  */
41 
42  openProfile->setIcon(
43  QIcon::fromTheme("document-open"));
44  openProfile->setAttribute(Qt::WA_LayoutUsesWidgetRect);
45  connect(openProfile, &QPushButton::clicked, this, &StellarSolverProfileEditor::openSingleProfile);
46 
47  saveProfile->setIcon(
48  QIcon::fromTheme("document-save"));
49  saveProfile->setAttribute(Qt::WA_LayoutUsesWidgetRect);
50  connect(saveProfile, &QPushButton::clicked, this, &StellarSolverProfileEditor::saveSingleProfile);
51 
52  /* This is not implemented yet.
53  copyProfile->setIcon(
54  QIcon::fromTheme("edit-copy"));
55  copyProfile->setAttribute(Qt::WA_LayoutUsesWidgetRect);
56  */
57  copyProfile->setVisible(false); //until we enable it.
58 
59  saveBackups->setIcon(
60  QIcon::fromTheme("document-save"));
61  saveBackups->setAttribute(Qt::WA_LayoutUsesWidgetRect);
62  connect(saveBackups, &QPushButton::clicked, this, &StellarSolverProfileEditor::saveBackupProfiles);
63 
64  loadBackups->setIcon(
65  QIcon::fromTheme("document-open"));
66  loadBackups->setAttribute(Qt::WA_LayoutUsesWidgetRect);
67  connect(loadBackups, &QPushButton::clicked, this, &StellarSolverProfileEditor::openBackupProfiles);
68 
69  reloadProfiles->setIcon(
70  QIcon::fromTheme("system-reboot"));
71  reloadProfiles->setAttribute(Qt::WA_LayoutUsesWidgetRect);
72  connect(reloadProfiles, &QPushButton::clicked, this, &StellarSolverProfileEditor::loadProfiles);
73 
74  loadDefaults->setIcon(
75  QIcon::fromTheme("go-down"));
76  loadDefaults->setAttribute(Qt::WA_LayoutUsesWidgetRect);
77  connect(loadDefaults, &QPushButton::clicked, this, &StellarSolverProfileEditor::loadDefaultProfiles);
78 
79  connect(addOptionProfile, &QAbstractButton::clicked, this, [this]()
80  {
81  bool ok;
82  QString name = QInputDialog::getText(this, tr("New Options Profile"),
83  tr("What would you like your profile to be called?"), QLineEdit::Normal,
84  "", &ok);
85  if (ok && !name.isEmpty())
86  {
87  disconnectOptionsProfileComboBox();
88  SSolver::Parameters params = getSettingsFromUI();
89  params.listName = name;
90  optionsList.append(params);
91  optionsProfile->addItem(name);
92  optionsProfile->setCurrentText(name);
93  openOptionsProfileNum = optionsProfile->count() - 1;
94  settingJustChanged();
95  connectOptionsProfileComboBox();
96  }
97  });
98 
99  connect(removeOptionProfile, &QAbstractButton::clicked, this, [this]()
100  {
101  if(optionsList.count() == 0)
102  return;
103  int item = optionsProfile->currentIndex();
104  disconnectOptionsProfileComboBox();
105  optionsProfile->removeItem(item);
106  optionsList.removeAt(item);
107  if(optionsProfile->count() > 0)
108  {
109  if(item > optionsList.count() - 1) //So that it doesn't try to set the new list to a nonexistant one
110  item--;
111  openOptionsProfileNum = item;
112  loadOptionsProfileIgnoreOldSettings(item); //Because the old one no longer exists
113  }
114  settingJustChanged();
115  connectOptionsProfileComboBox();
116  });
117 
118  connect(description, &QTextEdit::textChanged, this, &StellarSolverProfileEditor::settingJustChanged);
119 
120  QList<QLineEdit *> lines = this->findChildren<QLineEdit *>();
121  for(QLineEdit *line : lines)
122  connect(line, &QLineEdit::textEdited, this, &StellarSolverProfileEditor::settingJustChanged);
123 
124  QList<QCheckBox *> checks = this->findChildren<QCheckBox *>();
125  for(QCheckBox *check : checks)
126  connect(check, &QCheckBox::stateChanged, this, &StellarSolverProfileEditor::settingJustChanged);
127 
128  QList<QComboBox *> combos = this->findChildren<QComboBox *>();
129  for(QComboBox *combo : combos)
130  {
131  if(combo != optionsProfile)
132  connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &StellarSolverProfileEditor::settingJustChanged);
133  }
134 
135  QList<QSpinBox *> spins = this->findChildren<QSpinBox *>();
136  for(QSpinBox *spin : spins)
137  connect(spin, QOverload<int>::of(&QSpinBox::valueChanged), this, &StellarSolverProfileEditor::settingJustChanged);
138 
139  if(selectedProfileGroup != AlignProfiles)
140  astrometryOptions->setVisible(false);
141  connect(m_ConfigDialog->button(QDialogButtonBox::Apply), SIGNAL(clicked()), SLOT(slotApply()));
142  connect(m_ConfigDialog->button(QDialogButtonBox::Ok), SIGNAL(clicked()), SLOT(slotApply()));
143 }
144 
145 void StellarSolverProfileEditor::setProfileGroup(ProfileGroup group)
146 {
147  selectedProfileGroup = group;
148  optionsProfileGroup->setCurrentIndex(static_cast<int>(group));
149  QString profileGroupFileName;
150  switch(selectedProfileGroup)
151  {
152  case AlignProfiles:
153  profileGroupFileName = "SavedAlignProfiles.ini";
154  break;
155  case FocusProfiles:
156  profileGroupFileName = "SavedFocusProfiles.ini";
157  break;
158  case GuideProfiles:
159  profileGroupFileName = "SavedGuideProfiles.ini";
160  break;
161  case HFRProfiles:
162  profileGroupFileName = "SavedHFRProfiles.ini";
163  break;
164  }
165 
166  savedOptionsProfiles = QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(profileGroupFileName);
167  loadProfiles();
168 }
169 
170 void StellarSolverProfileEditor::connectOptionsProfileComboBox()
171 {
172  connect(optionsProfile, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
173  &StellarSolverProfileEditor::loadOptionsProfile);
174 }
175 
176 void StellarSolverProfileEditor::disconnectOptionsProfileComboBox()
177 {
178  disconnect(optionsProfile, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
179  &StellarSolverProfileEditor::loadOptionsProfile);
180 }
181 
182 void StellarSolverProfileEditor::settingJustChanged()
183 {
184  optionsAreSaved = false;
185  m_ConfigDialog->button(QDialogButtonBox::Apply)->setEnabled(true);
186 }
187 
188 void StellarSolverProfileEditor::loadProfile(int profile)
189 {
190  optionsProfile->setCurrentIndex(profile);
191 }
192 
193 void StellarSolverProfileEditor::loadOptionsProfile()
194 {
195  if(optionsProfile->count() == 0)
196  return;
197  if(openOptionsProfileNum < optionsList.count() && openOptionsProfileNum > 0)
198  {
199  SSolver::Parameters editorOptions = getSettingsFromUI();
200  SSolver::Parameters currentProfile = optionsList.at(openOptionsProfileNum);
201  if(!(editorOptions == currentProfile) || editorOptions.description != currentProfile.description)
202  {
203  editorOptions.listName = currentProfile.listName;
204  optionsList.replace(openOptionsProfileNum, editorOptions);
205  }
206  }
207  SSolver::Parameters newProfile = optionsList.at(optionsProfile->currentIndex());
208  QList<QWidget *> controls = this->findChildren<QWidget *>();
209  for(QWidget *control : controls)
210  control->blockSignals(true);
211  sendSettingsToUI(newProfile);
212  for(QWidget *control : controls)
213  control->blockSignals(false);
214  openOptionsProfileNum = optionsProfile->currentIndex();
215 }
216 
217 void StellarSolverProfileEditor::loadOptionsProfileIgnoreOldSettings(int index)
218 {
219  if(index >= optionsProfile->count())
220  return;
221  SSolver::Parameters newProfile = optionsList.at(index);
222  QList<QWidget *> controls = this->findChildren<QWidget *>();
223  for(QWidget *control : controls)
224  control->blockSignals(true);
225  sendSettingsToUI(newProfile);
226  optionsProfile->setCurrentIndex(index);
227  openOptionsProfileNum = optionsProfile->currentIndex();
228  for(QWidget *control : controls)
229  control->blockSignals(false);
230 }
231 
232 //This sets all the settings for either the internal or external sextractor
233 //based on the requested settings in the mainwindow interface.
234 //If you are implementing the StellarSolver Library in your progra, you may choose to change some or all of these settings or use the defaults.
235 SSolver::Parameters StellarSolverProfileEditor::getSettingsFromUI()
236 {
237  SSolver::Parameters params;
238  params.description = description->toPlainText();
239  //These are to pass the parameters to the internal sextractor
240  params.apertureShape = (SSolver::Shape) apertureShape->currentIndex();
241  params.kron_fact = kron_fact->text().toDouble();
242  params.subpix = subpix->text().toInt() ;
243  params.r_min = r_min->text().toFloat();
244  params.magzero = magzero->text().toFloat();
245  params.threshold_bg_multiple = threshMultiple->text().toFloat();
246  params.threshold_offset = threshOffset->text().toFloat();
247  params.minarea = minarea->text().toFloat();
248  params.deblend_thresh = deblend_thresh->text().toInt();
249  params.deblend_contrast = deblend_contrast->text().toFloat();
250  params.clean = (cleanCheckBox->isChecked()) ? 1 : 0;
251  params.clean_param = clean_param->text().toDouble();
252  params.convFilterType = (SSolver::ConvFilterType) convFilter->currentIndex();
253  params.fwhm = fwhm->value();
254 
255  //Star Filter Settings
256  params.resort = resort->isChecked();
257  params.maxSize = maxSize->text().toDouble();
258  params.minSize = minSize->text().toDouble();
259  params.maxEllipse = maxEllipse->text().toDouble();
260  params.initialKeep = initialKeep->text().toInt();
261  params.keepNum = keepNum->text().toInt();
262  params.removeBrightest = brightestPercent->text().toDouble();
263  params.removeDimmest = dimmestPercent->text().toDouble();
264  params.saturationLimit = saturationLimit->text().toDouble();
265 
266  //Settings that usually get set by the config file
267 
268  params.maxwidth = maxWidth->text().toDouble();
269  params.minwidth = minWidth->text().toDouble();
270  params.inParallel = inParallel->isChecked();
271  params.multiAlgorithm = (SSolver::MultiAlgo)multiAlgo->currentIndex();
272  params.solverTimeLimit = solverTimeLimit->text().toInt();
273 
274  params.resort = resort->isChecked();
275  params.autoDownsample = autoDownsample->isChecked();
276  params.downsample = downsample->value();
277  params.search_radius = radius->text().toDouble();
278 
279  return params;
280 }
281 
282 void StellarSolverProfileEditor::sendSettingsToUI(SSolver::Parameters a)
283 {
284 
285  description->setText(a.description);
286  //Sextractor Settings
287 
288  apertureShape->setCurrentIndex(a.apertureShape);
289  kron_fact->setText(QString::number(a.kron_fact));
290  subpix->setText(QString::number(a.subpix));
291  r_min->setText(QString::number(a.r_min));
292 
293  magzero->setText(QString::number(a.magzero));
294  threshMultiple->setText(QString::number(a.threshold_bg_multiple));
295  threshOffset->setText(QString::number(a.threshold_offset));
296  minarea->setText(QString::number(a.minarea));
297  deblend_thresh->setText(QString::number(a.deblend_thresh));
298  deblend_contrast->setText(QString::number(a.deblend_contrast));
299  cleanCheckBox->setChecked(a.clean == 1);
300  clean_param->setText(QString::number(a.clean_param));
301  convFilter->setCurrentIndex(a.convFilterType);
302  fwhm->setValue(a.fwhm);
303 
304  //Star Filter Settings
305 
306  maxSize->setText(QString::number(a.maxSize));
307  minSize->setText(QString::number(a.minSize));
308  maxEllipse->setText(QString::number(a.maxEllipse));
309  initialKeep->setText(QString::number(a.initialKeep));
310  keepNum->setText(QString::number(a.keepNum));
311  brightestPercent->setText(QString::number(a.removeBrightest));
312  dimmestPercent->setText(QString::number(a.removeDimmest));
313  saturationLimit->setText(QString::number(a.saturationLimit));
314 
315  //Astrometry Settings
316 
317  autoDownsample->setChecked(a.autoDownsample);
318  downsample->setValue(a.downsample);
319  inParallel->setChecked(a.inParallel);
320  multiAlgo->setCurrentIndex(a.multiAlgorithm);
321  solverTimeLimit->setText(QString::number(a.solverTimeLimit));
322  minWidth->setText(QString::number(a.minwidth));
323  maxWidth->setText(QString::number(a.maxwidth));
324  radius->setText(QString::number(a.search_radius));
325  resort->setChecked(a.resort);
326 }
327 
328 void StellarSolverProfileEditor::copySingleProfile()
329 {
330 
331 }
332 
333 void StellarSolverProfileEditor::openSingleProfile()
334 {
335  QString fileURL = QFileDialog::getOpenFileName(nullptr, "Load Options Profiles File", dirPath,
336  "INI files(*.ini)");
337  if (fileURL.isEmpty())
338  return;
339  if(!QFileInfo(fileURL).exists())
340  {
341  KSMessageBox::warning(this, "Message", "The file doesn't exist");
342  return;
343  }
344  QSettings settings(fileURL, QSettings::IniFormat);
345  QStringList groups = settings.childGroups();
346  for(QString group : groups)
347  {
348  settings.beginGroup(group);
349  QStringList keys = settings.childKeys();
351  for(QString key : keys)
352  map.insert(key, settings.value(key));
353  SSolver::Parameters newParams = SSolver::Parameters::convertFromMap(map);
354  optionsList.append(newParams);
355  optionsProfile->addItem(group);
356  }
357  if(optionsProfile->count() > 0)
358  loadProfile(optionsProfile->count() - 1);
359  m_ConfigDialog->button(QDialogButtonBox::Apply)->setEnabled(true);
360 }
361 
362 void StellarSolverProfileEditor::loadProfiles()
363 {
364  if( !optionsAreSaved )
365  {
366  if(QMessageBox::question(this, "Abort?",
367  "You made unsaved changes in the settings, do you really wish to overwrite them?") == QMessageBox::No)
368  {
369  return;
370  }
371  optionsAreSaved = true; //They just got overwritten
372  }
373  disconnectOptionsProfileComboBox();
374  optionsProfile->clear();
375  if(QFile(savedOptionsProfiles).exists())
376  optionsList = StellarSolver::loadSavedOptionsProfiles(savedOptionsProfiles);
377  else
378  optionsList = getDefaultProfiles();
379  for(SSolver::Parameters params : optionsList)
380  optionsProfile->addItem(params.listName);
381  if(optionsList.count() > 0)
382  {
383  sendSettingsToUI(optionsList.at(0));
384  openOptionsProfileNum = 0;
385  }
386  connectOptionsProfileComboBox();
387  m_ConfigDialog->button(QDialogButtonBox::Apply)->setEnabled(false);
388 }
389 
390 void StellarSolverProfileEditor::saveSingleProfile()
391 {
392  QString fileURL = QFileDialog::getSaveFileName(nullptr, "Save Options Profiles", dirPath,
393  "INI files(*.ini)");
394  if (fileURL.isEmpty())
395  return;
396  QSettings settings(fileURL, QSettings::IniFormat);
397  SSolver::Parameters params = optionsList.at(optionsProfile->currentIndex());
398  settings.beginGroup(params.listName);
399  QMap<QString, QVariant> map = SSolver::Parameters::convertToMap(params);
401  while(it.hasNext())
402  {
403  it.next();
404  settings.setValue(it.key(), it.value());
405  }
406  settings.endGroup();
407 }
408 
409 void StellarSolverProfileEditor::saveProfiles()
410 {
411  QSettings settings(savedOptionsProfiles, QSettings::IniFormat);
412  for(int i = 0 ; i < optionsList.count(); i++)
413  {
414  SSolver::Parameters params = optionsList.at(i);
415  settings.beginGroup(params.listName);
416  QMap<QString, QVariant> map = SSolver::Parameters::convertToMap(params);
418  while(it.hasNext())
419  {
420  it.next();
421  settings.setValue(it.key(), it.value());
422  }
423  settings.endGroup();
424  }
425  QStringList groups = settings.childGroups();
426  for(QString group : groups)
427  {
428  bool groupInList = false;
429  for(SSolver::Parameters params : optionsList)
430  {
431  if(params.listName == group)
432  groupInList = true;
433  }
434  if( ! groupInList)
435  settings.remove(group);
436  }
437 }
438 
439 QList<SSolver::Parameters> StellarSolverProfileEditor::getDefaultProfiles()
440 {
441  switch(selectedProfileGroup)
442  {
443  case FocusProfiles:
444  return getDefaultFocusOptionsProfiles();
445  case HFRProfiles:
446  return getDefaultHFROptionsProfiles();
447  case GuideProfiles:
448  return getDefaultGuideOptionsProfiles();
449  default:
450  case AlignProfiles:
451  return getDefaultAlignOptionsProfiles();
452  }
453 }
454 
455 void StellarSolverProfileEditor::loadDefaultProfiles()
456 {
457  if( !optionsAreSaved )
458  {
459  if(QMessageBox::question(this, "Abort?",
460  "You made unsaved changes in the settings, do you really wish to overwrite them?") == QMessageBox::No)
461  {
462  return;
463  }
464  optionsAreSaved = true; //They just got overwritten
465  }
466  disconnectOptionsProfileComboBox();
467  optionsList = getDefaultProfiles();
468  optionsProfile->clear();
469  for(SSolver::Parameters param : optionsList)
470  optionsProfile->addItem(param.listName);
471  connectOptionsProfileComboBox();
472  if(optionsProfile->count() > 0)
473  loadOptionsProfileIgnoreOldSettings(0);
474  m_ConfigDialog->button(QDialogButtonBox::Apply)->setEnabled(true);
475 }
476 
477 void StellarSolverProfileEditor::saveBackupProfiles()
478 {
479  QString fileURL = QFileDialog::getSaveFileName(nullptr, "Save Options Profiles", dirPath,
480  "INI files(*.ini)");
481  if (fileURL.isEmpty())
482  return;
483  QSettings settings(fileURL, QSettings::IniFormat);
484  for(int i = 0 ; i < optionsList.count(); i++)
485  {
486  SSolver::Parameters params = optionsList.at(i);
487  settings.beginGroup(params.listName);
488  QMap<QString, QVariant> map = SSolver::Parameters::convertToMap(params);
490  while(it.hasNext())
491  {
492  it.next();
493  settings.setValue(it.key(), it.value());
494  }
495  settings.endGroup();
496  }
497 }
498 
499 void StellarSolverProfileEditor::openBackupProfiles()
500 {
501  QString fileURL = QFileDialog::getOpenFileName(nullptr, "Load Options Profiles File", dirPath,
502  "INI files(*.ini)");
503  if (fileURL.isEmpty())
504  return;
505  if(!QFileInfo(fileURL).exists())
506  {
507  QMessageBox::warning(this, "Message", "The file doesn't exist");
508  return;
509  }
510  disconnectOptionsProfileComboBox();
511  optionsList.clear();
512  QSettings settings(fileURL, QSettings::IniFormat);
513  QStringList groups = settings.childGroups();
514  for(QString group : groups)
515  {
516  settings.beginGroup(group);
517  QStringList keys = settings.childKeys();
519  for(QString key : keys)
520  map.insert(key, settings.value(key));
521  SSolver::Parameters newParams = SSolver::Parameters::convertFromMap(map);
522  optionsList.append(newParams);
523  optionsProfile->addItem(group);
524  }
525  if(optionsProfile->count() > 0)
526  loadOptionsProfileIgnoreOldSettings(0);
527  connectOptionsProfileComboBox();
528  m_ConfigDialog->button(QDialogButtonBox::Apply)->setEnabled(true);
529 }
530 
531 void StellarSolverProfileEditor::slotApply()
532 {
533  int index = optionsProfile->currentIndex();
534  SSolver::Parameters currentParams = getSettingsFromUI();
535  SSolver::Parameters savedParams = optionsList.at(index);
536  if(!(currentParams == savedParams) || currentParams.description != savedParams.description)
537  {
538  currentParams.listName = savedParams.listName;
539  optionsList.replace(index, currentParams);
540  }
541  optionsAreSaved = true;
542 
543  saveProfiles();
544  emit optionsProfilesUpdated();
545 }
546 
547 }
QString number(int n, int base)
QString name(void) const override
If star is unnamed return "star" otherwise return the name.
Definition: starobject.h:130
Ekos is an advanced Astrophotography tool for Linux. It is based on a modular extensible framework to...
Definition: align.cpp:70
void clicked(bool checked)
QIcon fromTheme(const QString &name)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
void stateChanged(int state)
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
bool isEmpty() const const
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
This is the main window for KStars. In addition to the GUI elements, the class contains the program c...
Definition: kstars.h:92
void textEdited(const QString &text)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
int count() const const
QString filePath(const QString &fileName) const const
void currentIndexChanged(int index)
void textChanged()
void valueChanged(int i)
QFuture< void > map(Sequence &sequence, MapFunctor function)
WA_LayoutUsesWidgetRect
QString & append(QChar ch)
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sun Aug 14 2022 04:14:02 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.