9#include "QtNetwork/qnetworkreply.h"
11#include "fitshistogramcommand.h"
13#include "fitsviewer.h"
14#include "ksnotification.h"
17#include "platesolve.h"
18#include "ui_fitsheaderdialog.h"
19#include "ui_statform.h"
20#include "fitsstretchui.h"
27#include <fits_debug.h>
28#include "fitscommon.h"
29#include <QDesktopServices>
39 undoStack->setUndoLimit(10);
41 connect(undoStack, SIGNAL(cleanChanged(
bool)),
this, SLOT(modifyFITSState(
bool)));
43 m_PlateSolve.reset(
new PlateSolve(
this));
44 m_CatalogObjectWidget =
new QDialog(
this);
46 fitsHeaderDialog =
new QDialog(
this);
47 m_HistogramEditor =
new FITSHistogramEditor(
this);
48 connect(m_HistogramEditor, &FITSHistogramEditor::newHistogramCommand,
this, [
this](FITSHistogramCommand * command)
50 undoStack->push(command);
58void FITSTab::saveUnsaved()
60 if (undoStack->isClean() || m_View->getMode() != FITS_NORMAL)
63 QString caption =
i18n(
"Save Changes to FITS?");
64 QString message =
i18n(
"The current FITS file has unsaved changes. Would you like to save before closing it?");
81 if (undoStack->isClean())
86QString FITSTab::getPreviewText()
const
91void FITSTab::setPreviewText(
const QString &value)
96void FITSTab::selectRecentFITS(
int i)
101void FITSTab::clearRecentFITS()
104 recentImages->clear();
108bool FITSTab::setupView(FITSMode mode, FITSScale filter)
112 m_View.reset(
new FITSView(
this, mode, filter));
114 QVBoxLayout *vlayout =
new QVBoxLayout();
116 connect(m_View.get(), &FITSView::rectangleUpdated,
this, [
this](QRect roi)
118 displayStats(roi.isValid());
121 fitsTools =
new QToolBox();
123 stat.setupUi(statWidget);
125 for (
int i = 0; i <= STAT_STDDEV; i++)
127 for (
int j = 0; j < 3; j++)
129 stat.statsTable->setItem(i, j,
new QTableWidgetItem());
135 stat.statsTable->setSpan(i, 0, 1, 3);
138 connect(m_PlateSolve.get(), &PlateSolve::clicked,
this, &FITSTab::extractImage);
140 fitsTools->addItem(statWidget,
i18n(
"Statistics"));
141 fitsTools->addItem(m_PlateSolve.get(),
i18n(
"Plate Solving"));
144 m_CatalogObjectUI.setupUi(m_CatalogObjectWidget);
145 m_CatalogObjectItem = fitsTools->addItem(m_CatalogObjectWidget,
i18n(
"Catalog Objects"));
148 fitsTools->addItem(m_HistogramEditor,
i18n(
"Histogram"));
150 header.setupUi(fitsHeaderDialog);
151 fitsTools->addItem(fitsHeaderDialog,
i18n(
"FITS Header"));
152 connect(m_View.get(), &FITSView::headerChanged,
this, &FITSTab::loadFITSHeader);
154 QVBoxLayout *recentPanelLayout =
new QVBoxLayout();
156 recentPanel->
setLayout(recentPanelLayout);
157 fitsTools->addItem(recentPanel,
i18n(
"Recent Images"));
158 recentImages =
new QListWidget(recentPanel);
159 recentPanelLayout->
addWidget(recentImages);
160 QPushButton *clearRecent =
new QPushButton(
i18n(
"Clear"));
161 recentPanelLayout->
addWidget(clearRecent);
165 QScrollArea *scrollFitsPanel =
new QScrollArea(fitsSplitter);
169 fitsSplitter->addWidget(scrollFitsPanel);
170 fitsSplitter->addWidget(m_View.get());
173 fitsSplitter->setSizes(QList<int>() << 0 << m_View->width() );
177 stretchUI.reset(
new FITSStretchUI(m_View,
nullptr));
183 connect(m_View.get(), &FITSView::newStatus,
this, &FITSTab::newStatus);
184 connect(m_View.get(), &FITSView::debayerToggled,
this, &FITSTab::debayerToggled);
185 connect(m_View.get(), &FITSView::updated,
this, &FITSTab::updated);
188 connect(m_View.get(), &FITSView::failed,
this, &FITSTab::failed);
197void FITSTab::loadFile(
const QUrl &imageURL, FITSMode mode, FITSScale filter)
206 if (setupView(mode, filter))
210 connect(m_View.get(), &FITSView::loaded,
this, [&]()
216 connect(m_View.get(), &FITSView::updated,
this, &FITSTab::updated);
220 modifyFITSState(
true, imageURL);
222 currentURL = imageURL;
224 m_View->setFilter(filter);
229bool FITSTab::shouldComputeHFR()
const
231 if (viewer->isStarsMarked())
233 if (!Options::autoHFR())
235 return ((!m_View.isNull()) && (m_View->getMode() == FITS_NORMAL));
238void FITSTab::processData()
240 const QSharedPointer<FITSData> &imageData = m_View->imageData();
242 m_HistogramEditor->setImageData(imageData);
252 if (shouldComputeHFR())
254 m_View->searchStars();
255 qCDebug(KSTARS_FITS) <<
"FITS HFR:" << imageData->getHFR();
263 if (recentImages->findItems(currentURL.toLocalFile(),
Qt::MatchExactly).count() == 0)
269 &FITSTab::selectRecentFITS);
270 recentImages->addItem(imageData->filename());
271 recentImages->setCurrentRow(recentImages->count() - 1);
273 &FITSTab::selectRecentFITS);
281 if (viewer->isStarsMarked())
283 m_View->toggleStars(
true);
284 m_View->updateFrame();
290 stretchUI->generateHistogram();
295 setupView(mode, filter);
300 if (viewer->isStarsMarked())
302 m_View->toggleStars(
true);
306 m_View->setFilter(filter);
308 if (!m_View->loadData(data))
319void FITSTab::modifyFITSState(
bool clean,
const QUrl &imageURL)
323 if (undoStack->isClean() ==
false)
324 undoStack->setClean();
331 emit changeStatus(clean, imageURL);
334bool FITSTab::saveImage(
const QString &filename)
336 return m_View->saveImage(filename);
339void FITSTab::copyFITS()
344void FITSTab::histoFITS()
346 fitsTools->setCurrentIndex(1);
347 if(m_View->width() > 200)
348 fitsSplitter->setSizes(QList<int>() << 200 << m_View->width() - 200);
350 fitsSplitter->setSizes(QList<int>() << 50 << 50);
353void FITSTab::displayStats(
bool roi)
355 const QSharedPointer<FITSData> &imageData = m_View->imageData();
357 stat.statsTable->item(STAT_WIDTH, 0)->setText(
QString::number(imageData->width(roi)));
358 stat.statsTable->item(STAT_HEIGHT, 0)->setText(
QString::number(imageData->height(roi)));
359 stat.statsTable->item(STAT_BITPIX, 0)->setText(
QString::number(imageData->bpp()));
362 stat.statsTable->item(STAT_HFR, 0)->setText(
QString::number(imageData->getHFR(),
'f', 3));
364 stat.statsTable->item(STAT_HFR, 0)->setText(
"---");
366 if (imageData->channels() == 1)
368 for (
int i = STAT_MIN; i <= STAT_STDDEV; i++)
370 if (stat.statsTable->columnSpan(i, 0) != 3)
371 stat.statsTable->setSpan(i, 0, 1, 3);
374 stat.statsTable->horizontalHeaderItem(0)->setText(
i18n(
"Value"));
375 stat.statsTable->hideColumn(1);
376 stat.statsTable->hideColumn(2);
380 for (
int i = STAT_MIN; i <= STAT_STDDEV; i++)
382 if (stat.statsTable->columnSpan(i, 0) != 1)
383 stat.statsTable->setSpan(i, 0, 1, 1);
386 stat.statsTable->horizontalHeaderItem(0)->setText(
i18nc(
"Red",
"R"));
387 stat.statsTable->showColumn(1);
388 stat.statsTable->showColumn(2);
391 if (!Options::nonLinearHistogram() && !imageData->isHistogramConstructed())
392 imageData->constructHistogram();
394 for (
int i = 0; i < imageData->channels(); i++)
396 stat.statsTable->item(STAT_MIN, i)->setText(
QString::number(imageData->getMin(i, roi),
'f', 3));
397 stat.statsTable->item(STAT_MAX, i)->setText(
QString::number(imageData->getMax(i, roi),
'f', 3));
398 stat.statsTable->item(STAT_MEAN, i)->setText(
QString::number(imageData->getMean(i, roi),
'f', 3));
399 stat.statsTable->item(STAT_MEDIAN, i)->setText(
QString::number(imageData->getMedian(i, roi),
'f', 3));
400 stat.statsTable->item(STAT_STDDEV, i)->setText(
QString::number(imageData->getStdDev(i, roi),
'f', 3));
404void FITSTab::statFITS()
406 fitsTools->setCurrentIndex(0);
407 if(m_View->width() > 200)
408 fitsSplitter->setSizes(QList<int>() << 200 << m_View->width() - 200);
410 fitsSplitter->setSizes(QList<int>() << 50 << 50);
414void FITSTab::loadFITSHeader()
416 const QSharedPointer<FITSData> &imageData = m_View->imageData();
420 int nkeys = imageData->getRecords().size();
422 header.tableWidget->setRowCount(nkeys);
423 for (
const auto &oneRecord : imageData->getRecords())
425 QTableWidgetItem *tempItem =
new QTableWidgetItem(oneRecord.key);
427 header.tableWidget->setItem(counter, 0, tempItem);
428 tempItem =
new QTableWidgetItem(oneRecord.value.toString());
430 header.tableWidget->setItem(counter, 1, tempItem);
431 tempItem =
new QTableWidgetItem(oneRecord.comment);
433 header.tableWidget->setItem(counter, 2, tempItem);
437 header.tableWidget->setColumnWidth(0, 100);
438 header.tableWidget->setColumnWidth(1, 100);
439 header.tableWidget->setColumnWidth(2, 250);
442void FITSTab::loadCatalogObjects()
447 const QSharedPointer<FITSData> &imageData = m_View->imageData();
450 QList<CatObject> catObjects = imageData->getCatObjects();
453 m_CatalogObjectUI.tableView->setSortingEnabled(
false);
455 m_CatObjModel.removeRows(0, m_CatObjModel.rowCount());
457 int counter = 0, total = 0, highlightRow = -1;
461 for (
const CatObject &catObject : catObjects)
466 m_CatObjModel.setRowCount(counter + 1);
469 QStandardItem* tempItem =
new QStandardItem(
QString::number(catObject.num));
470 tempItem->
setData(catObject.num, CAT_OBJ_SORT_ROLE);
472 m_CatObjModel.setItem(counter, CAT_NUM, tempItem);
475 tempItem =
new QStandardItem();
477 m_CatObjModel.setItem(counter, CAT_CDSPORTAL, tempItem);
480 tempItem =
new QStandardItem();
482 m_CatObjModel.setItem(counter, CAT_SIMBAD, tempItem);
485 tempItem =
new QStandardItem();
487 m_CatObjModel.setItem(counter, CAT_NED, tempItem);
490 tempItem =
new QStandardItem(catObject.name);
491 tempItem->
setData(catObject.name, CAT_OBJ_SORT_ROLE);
492 m_CatObjModel.setItem(counter, CAT_OBJECT, tempItem);
495 tempItem =
new QStandardItem(catObject.typeCode);
496 tempItem->
setData(catObject.typeCode, CAT_OBJ_SORT_ROLE);
497 m_CatObjModel.setItem(counter, CAT_TYPECODE, tempItem);
500 tempItem =
new QStandardItem(catObject.typeLabel);
501 tempItem->
setData(catObject.typeLabel, CAT_OBJ_SORT_ROLE);
502 m_CatObjModel.setItem(counter, CAT_TYPELABEL, tempItem);
505 QString coordStr = QString(
"%1 %2").arg(catObject.r.toHMSString(
false,
true))
506 .arg(catObject.d.toDMSString(
true,
false,
true));
507 tempItem =
new QStandardItem(coordStr);
508 tempItem->
setData(coordStr, CAT_OBJ_SORT_ROLE);
509 m_CatObjModel.setItem(counter, CAT_COORDS, tempItem);
513 tempItem->
setData(catObject.dist, CAT_OBJ_SORT_ROLE);
515 m_CatObjModel.setItem(counter, CAT_DISTANCE, tempItem);
518 QString magStr = (catObject.magnitude <= 0.0) ?
"" : QString(
"%1").arg(catObject.magnitude, 0,
'f', 1);
519 tempItem =
new QStandardItem(magStr);
520 tempItem->
setData(catObject.magnitude, CAT_OBJ_SORT_ROLE);
522 m_CatObjModel.setItem(counter, CAT_MAGNITUDE, tempItem);
525 QString sizeStr = (catObject.size <= 0.0) ?
"" : QString(
"%1").arg(catObject.
size, 0,
'f', 0);
526 tempItem =
new QStandardItem(sizeStr);
527 tempItem->
setData(catObject.size, CAT_OBJ_SORT_ROLE);
529 m_CatObjModel.setItem(counter, CAT_SIZE, tempItem);
531 if (catObject.highlight)
532 highlightRow = counter;
540 if (highlightRow >= 0)
541 catHighlightRow(highlightRow);
544 m_CatObjModel.setSortRole(CAT_OBJ_SORT_ROLE);
545 m_CatalogObjectUI.tableView->setSortingEnabled(
true);
548 if (!imageData->getCatQueryInProgress())
549 m_CatalogObjectUI.status->setText(
i18n(
"%1 / %2 Simbad objects loaded", counter, total));
552void FITSTab::queriedCatalogObjects()
555 if (fitsTools->currentIndex() != m_CatalogObjectItem)
557 fitsTools->setCurrentIndex(m_CatalogObjectItem);
558 if(m_View->width() > 200)
559 fitsSplitter->setSizes(QList<int>() << 200 << m_View->width() - 200);
561 fitsSplitter->setSizes(QList<int>() << 50 << 50);
564 m_CatalogObjectUI.status->setText(
i18n(
"Simbad query in progress..."));
567void FITSTab::catQueryFailed(
const QString text)
569 m_CatalogObjectUI.status->setText(text);
572void FITSTab::catReset()
574 m_CatalogObjectUI.status->setText(
"");
576 m_CatObjModel.removeRows(0, m_CatObjModel.rowCount());
579void FITSTab::catHighlightRow(
const int row)
581 m_CatalogObjectUI.tableView->selectRow(row);
582 QModelIndex index = m_CatalogObjectUI.tableView->indexAt(QPoint(row, CAT_NUM));
587void FITSTab::catHighlightChanged(
const int highlight)
591 const QSharedPointer<FITSData> &imageData = m_View->imageData();
594 QList<CatObject> catObjects = imageData->getCatObjects();
596 if (highlight < 0 || highlight >= catObjects.
size())
599 int num = catObjects[highlight].num;
600 for (
int i = 0; i < m_CatObjModel.rowCount(); i++)
603 QStandardItem *itm = m_CatObjModel.item(i, CAT_NUM);
606 int itmRow = itm->
row();
607 QModelIndex currentIndex = m_CatalogObjectUI.tableView->currentIndex();
610 int currentRow = m_CatObjModel.itemFromIndex(currentIndex)->row();
611 if (currentRow == itmRow)
616 catHighlightRow(itmRow);
625 const QSharedPointer<FITSData> &imageData = m_View->imageData();
630 int selNum = -1, deselNum = -1;
632 QStandardItem * selItem = m_CatObjModel.itemFromIndex(current);
634 selNum = m_CatObjModel.item(selItem->
row(), CAT_NUM)->text().toInt(&ok);
637 QStandardItem * deselItem = m_CatObjModel.itemFromIndex(previous);
639 deselNum = m_CatObjModel.item(deselItem->
row(), CAT_NUM)->text().toInt(&ok);
643 imageData->highlightCatObject(selNum - 1, deselNum - 1);
644 m_View->updateFrame();
648void FITSTab::catCellDoubleClicked(
const QModelIndex &index)
650 QStandardItem * item = m_CatObjModel.itemFromIndex(index);
651 int row = item->
row();
654 QString catObjectName = m_CatObjModel.item(row, CAT_OBJECT)->text();
656 if (col == CAT_CDSPORTAL)
657 launchCDS(catObjectName);
658 else if (col == CAT_SIMBAD)
659 launchSimbad(catObjectName);
660 else if (col == CAT_NED)
661 launchNED(catObjectName);
662 else if (col == CAT_TYPECODE || col == CAT_TYPELABEL)
663 launchCatTypeFilterDialog();
666void FITSTab::launchCatTypeFilterDialog()
668 m_CatObjTypeFilterDialog->show();
669 m_CatObjTypeFilterDialog->raise();
672void FITSTab::showCatObjNames(
bool enabled)
676 const QSharedPointer<FITSData> &imageData = m_View->imageData();
680 Options::setFitsCatObjShowNames(
enabled);
681 m_View->updateFrame();
684void FITSTab::launchSimbad(
QString name)
686 QUrl url = QUrl(
"https://simbad.u-strasbg.fr/simbad/sim-id");
687 QString ident = QString(
"Ident=%1").arg(name);
689 ident.
remove(QRegularExpression(
"[\\[\\]]+"));
693 qCDebug(KSTARS_FITS) <<
"Unable to open Simbad url:" << url;
696void FITSTab::launchCDS(
QString name)
698 QUrl url = QUrl(
"https://cdsportal.u-strasbg.fr/");
699 QString ident = QString(
"target=%1").
arg(name);
701 ident.
remove(QRegularExpression(
"[\\[\\]]+"));
705 qCDebug(KSTARS_FITS) <<
"Unable to open CDS Portal url:" << url;
708void FITSTab::launchNED(
QString name)
710 QUrl url = QUrl(
"https://ned.ipac.caltech.edu/cgi-bin/objsearch");
711 QString
query = QString(
"objname=%1").arg(name);
717 qCDebug(KSTARS_FITS) <<
"Unable to open NED url" << url;
720void FITSTab::initCatalogObject()
723 m_CatalogObjectUI.tableView->setModel(&m_CatObjModel);
726 QStringList Headers {
i18n(
"Num"),
737 m_CatObjModel.setColumnCount(CAT_MAX_COLS);
738 m_CatObjModel.setHorizontalHeaderLabels(Headers);
742 m_CatObjModel.setHeaderData(CAT_CDSPORTAL,
Qt::Horizontal,
i18n(
"Double click to launch CDS Portal browser"),
748 i18n(
"Object Type Code. Double click to launch Object Type Filter.\n\nSee https://simbad.cds.unistra.fr/guide/otypes.htx for more details"),
751 i18n(
"Object Type Label. Double click to launch Object Type Filter.\n\nSee https://simbad.cds.unistra.fr/guide/otypes.htx for more details"),
754 m_CatObjModel.setHeaderData(CAT_DISTANCE,
Qt::Horizontal,
i18n(
"Object distance in arcmins from the search center"),
760 QStyledItemDelegate *delegate =
new QStyledItemDelegate(m_CatalogObjectUI.tableView);
761 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_NUM, delegate);
762 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_CDSPORTAL, delegate);
763 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_SIMBAD, delegate);
764 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_NED, delegate);
765 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_OBJECT, delegate);
766 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_TYPECODE, delegate);
767 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_TYPELABEL, delegate);
768 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_COORDS, delegate);
769 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_DISTANCE, delegate);
770 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_MAGNITUDE, delegate);
771 m_CatalogObjectUI.tableView->setItemDelegateForColumn(CAT_SIZE, delegate);
773 m_CatalogObjectUI.tableView->setAutoScroll(
true);
775 connect(m_View.get(), &FITSView::catLoaded,
this, &FITSTab::loadCatalogObjects);
776 connect(m_View.get(), &FITSView::catQueried,
this, &FITSTab::queriedCatalogObjects);
777 connect(m_View.get(), &FITSView::catQueryFailed,
this, &FITSTab::catQueryFailed);
778 connect(m_View.get(), &FITSView::catReset,
this, &FITSTab::catReset);
779 connect(m_View.get(), &FITSView::catHighlightChanged,
this, &FITSTab::catHighlightChanged);
781 &FITSTab::catRowChanged);
786 setupCatObjTypeFilter();
789 m_CatalogObjectUI.kcfg_FitsCatObjShowNames->setChecked(Options::fitsCatObjShowNames());
793void FITSTab::setupCatObjTypeFilter()
796 m_CatObjTypeFilterDialog =
new QDialog(
this);
797 m_CatObjTypeFilterUI.setupUi(m_CatObjTypeFilterDialog);
811 QTreeWidgetItem * treeItem[CAT_OBJ_MAX_DEPTH];
812 for (
int i = 0; i < MAX_CAT_OBJ_TYPES; i++)
814 const int depth = catObjTypes[i].depth;
820 treeItem[
depth] =
new QTreeWidgetItem(m_CatObjTypeFilterUI.tree);
823 treeItem[
depth] =
new QTreeWidgetItem(treeItem[
depth - 1]);
826 treeItem[
depth]->
setText(CATTYPE_CODE, catObjTypes[i].code);
827 treeItem[
depth]->
setText(CATTYPE_CANDCODE, catObjTypes[i].candidateCode);
828 treeItem[
depth]->
setText(CATTYPE_LABEL, catObjTypes[i].label);
829 treeItem[
depth]->
setText(CATTYPE_DESCRIPTION, catObjTypes[i].description);
830 treeItem[
depth]->
setText(CATTYPE_COMMENTS, catObjTypes[i].comments);
832 m_CatObjTypeFilterUI.tree->expandAll();
833 for (
int i = 0; i < CAT_OBJ_MAX_DEPTH; i++)
835 m_CatObjTypeFilterUI.tree->resizeColumnToContents(i);
841void FITSTab::applyTypeFilter()
845 const QSharedPointer<FITSData> &imageData = m_View->imageData();
850 QList<QTreeWidgetItem *> items = m_CatObjTypeFilterUI.tree->findItems(
"*",
852 for (
auto item : items)
864 m_View->imageData()->setCatObjectsFilters(filters);
866 m_View->imageData()->filterCatObjects();
867 m_View->updateFrame();
869 loadCatalogObjects();
872void FITSTab::checkAllTypeFilter()
874 QList<QTreeWidgetItem *> items = m_CatObjTypeFilterUI.tree->findItems(
"*",
876 for (
auto item : items)
882void FITSTab::uncheckAllTypeFilter()
884 QList<QTreeWidgetItem *> items = m_CatObjTypeFilterUI.tree->findItems(
"*",
886 for (
auto item : items)
900 QTreeWidgetItem *child = item->
child(i);
905void FITSTab::headerFITS()
907 fitsTools->setCurrentIndex(2);
908 if(m_View->width() > 200)
909 fitsSplitter->setSizes(QList<int>() << 200 << m_View->width() - 200);
911 fitsSplitter->setSizes(QList<int>() << 50 << 50);
914bool FITSTab::saveFile()
916 QUrl backupCurrent = currentURL;
917 QUrl currentDir(Options::fitsDir());
918 currentDir.setScheme(
"file");
920 if (currentURL.toLocalFile().startsWith(QLatin1String(
"/tmp/")) || currentURL.toLocalFile().contains(
"/Temp"))
924 if (mDirty ==
false && !currentURL.isEmpty())
927 if (currentURL.isEmpty())
929 QString selectedFilter;
933 "Images (*.fits *.fits.gz *.fit *.xisf *.jpg *.jpeg *.png)");
937 "FITS (*.fits *.fits.gz *.fit);;XISF (*.xisf);;JPEG (*.jpg *.jpeg);;PNG (*.png)", &selectedFilter);
940 if (currentURL.isEmpty())
942 currentURL = backupCurrent;
947 if (currentURL.toLocalFile().contains(
'.') == 0)
949 if (selectedFilter.
contains(
"XISF"))
950 currentURL.setPath(currentURL.toLocalFile() +
".xisf");
951 else if (selectedFilter.
contains(
"JPEG"))
952 currentURL.setPath(currentURL.toLocalFile() +
".jpg");
953 else if (selectedFilter.
contains(
"PNG"))
954 currentURL.setPath(currentURL.toLocalFile() +
".png");
956 currentURL.setPath(currentURL.toLocalFile() +
".fits");
960 if (currentURL.isValid())
962 QString localFile = currentURL.toLocalFile();
966 if (!saveImage(localFile))
968 KSNotification::error(
i18n(
"Image save error: %1", m_View->imageData()->getLastError()),
i18n(
"Image Save"));
972 emit newStatus(
i18n(
"File saved to %1", currentURL.url()), FITS_MESSAGE);
978 QString message =
i18n(
"Invalid URL: %1", currentURL.url());
979 KSNotification::sorry(message,
i18n(
"Invalid URL"));
984bool FITSTab::saveFileAs()
990void FITSTab::ZoomIn()
992 QPoint oldCenter = m_View->getImagePoint(m_View->viewport()->rect().center());
994 m_View->cleanUpZoom(oldCenter);
997void FITSTab::ZoomOut()
999 QPoint oldCenter = m_View->getImagePoint(m_View->viewport()->rect().center());
1001 m_View->cleanUpZoom(oldCenter);
1004void FITSTab::ZoomDefault()
1006 QPoint oldCenter = m_View->getImagePoint(m_View->viewport()->rect().center());
1007 m_View->ZoomDefault();
1008 m_View->cleanUpZoom(oldCenter);
1011void FITSTab::tabPositionUpdated()
1013 undoStack->setActive(
true);
1015 emit newStatus(QString(
"%1x%2").arg(m_View->imageData()->width()).arg(m_View->imageData()->height()),
1019void FITSTab::setStretchValues(
double shadows,
double midtones,
double highlights)
1022 stretchUI->setStretchValues(shadows, midtones, highlights);
1025void FITSTab::setAutoStretch()
1027 if (!m_View->getAutoStretch())
1028 m_View->setAutoStretchParams();
1031void FITSTab::extractImage()
1033 connect(m_PlateSolve.get(), &PlateSolve::extractorSuccess,
this, [
this]()
1035 m_View->updateFrame();
1036 m_PlateSolve->solveImage(m_View->imageData());
1038 connect(m_PlateSolve.get(), &PlateSolve::extractorFailed,
this, [
this]()
1040 disconnect(m_PlateSolve.get());
1042 connect(m_PlateSolve.get(), &PlateSolve::solverFailed,
this, [
this]()
1044 disconnect(m_PlateSolve.get());
1046 connect(m_PlateSolve.get(), &PlateSolve::solverSuccess,
this, [
this]()
1048 m_View->syncWCSState();
1049 if (m_View->areObjectsShown())
1051 m_View->imageData()->searchObjects();
1052 disconnect(m_PlateSolve.get());
1054 m_PlateSolve->extractImage(m_View->imageData());
Primary window to view monochrome and color FITS images.
static KStars * Instance()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
void doubleClicked(const QModelIndex &index)
void setImage(const QImage &image, Mode mode)
bool openUrl(const QUrl &url)
QUrl getSaveFileUrl(QWidget *parent, const QString &caption, const QUrl &dir, const QString &filter, QString *selectedFilter, Options options, const QStringList &supportedSchemes)
bool exists() const const
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
void push_back(parameter_type value)
void remove(qsizetype i, qsizetype n)
void replace(qsizetype i, parameter_type value)
qsizetype size() const const
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
void splitterMoved(int pos, int index)
Qt::CheckState checkState() const const
void setCheckState(Qt::CheckState state)
virtual void setData(const QVariant &value, int role)
void setTextAlignment(Qt::Alignment alignment)
QString text() const const
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
int toInt(bool *ok, int base) const const
QByteArray toLatin1() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setText(int column, const QString &text)
QUrl fromLocalFile(const QString &localFile)
bool isEmpty() const const
bool isValid() const const
void setQuery(const QString &query, ParsingMode mode)
QString toLocalFile() const const
QString toString(FormattingOptions options) const const