11#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
12#include <QtGui/QUndoGroup>
15#include "QtWidgets/qmenu.h"
16#include "QtWidgets/qstatusbar.h"
17#include "config-kstars.h"
20#include "fitsdebayer.h"
27#include "indi/indilistener.h"
30#include <KActionCollection>
34#include <knotification.h>
36#include <fits_debug.h>
41bool FITSViewer::m_BlinkBusy =
false;
45 ki18n(
"Flip Vertical")
51 if (Options::independentWindowFITS())
69 fitsTabWidget->setTabsClosable(
true);
89 fitsPosition.setMinimumWidth(100);
91 fitsValue.setMinimumWidth(40);
93 fitsWCS.setVisible(
false);
134 action->setText(
i18n(
"Open/Blink Directory"));
141 saveFileAsAction->setIcon(
188 roiActionMenu->setText(
i18n(
"&Selection Statistics"));
190 roiActionMenu->addSeparator();
196 roiActionMenu->addAction(ksa);
200 roiActionMenu->addAction(ksa);
204 roiActionMenu->addAction(ksa);
208 roiActionMenu->addAction(ksa);
210 action->setMenu(roiActionMenu->menu());
212 action->setCheckable(
true);
223 action->setCheckable(
true);
230 action->setCheckable(
true);
235 action->setText(
i18n(
"Show Pixel Gridlines"));
236 action->setCheckable(
true);
241 action->setText(
i18n(
"Show Equatorial Gridlines"));
242 action->setCheckable(
true);
243 action->setDisabled(
true);
248 action->setText(
i18n(
"Show Objects in Image"));
249 action->setCheckable(
true);
250 action->setDisabled(
true);
256 action->setCheckable(
true);
257 action->setDisabled(
true);
261 action->setIcon(
QIcon(
":/icons/center_telescope.svg"));
262 action->setText(
i18n(
"Center Telescope\n*No Telescopes Detected*"));
263 action->setDisabled(
true);
264 action->setCheckable(
true);
294 action->setText(
i18n(
"Previous Blink Image"));
311 action->setCheckable(
true);
314#ifdef HAVE_DATAVISUALIZATION
318 action->setCheckable(
true);
323 int filterCounter = 1;
325 for (
auto &filter : FITSViewer::filterTypes)
328 action->setText(
i18n(filter.toString().toUtf8().constData()));
341 resize(INITIAL_W, INITIAL_H);
356FITSViewer::~FITSViewer()
369 if (a && viewers.
count() == 1)
390 if (viewers.
count() <= 1)
411 const double hfrValue = data->getHFR();
412 if (hfrValue <= 0.0)
return QString(
"");
413 if (data->getSkyBackground().starsDetected > 0)
415 i18np(
"HFR:%2 Ecc:%3 %1 star.",
"HFR:%2 Ecc:%3 %1 stars.",
416 data->getSkyBackground().starsDetected,
421 i18np(
"HFR:%2, %1 star.",
"HFR:%2, %1 stars.",
422 data->getDetectedStars(),
426QString HFRClipString(FITSView* view)
428 if (view->isClippingShown())
430 const int numClipped = view->getNumClipped();
434 return QString(
"Clip:%1").
arg(view->getNumClipped());
441 FITSMode mode,
const QString &previewText)
443 int tabIndex = fitsTabWidget->
indexOf(tab.
get());
451 tab->setPreviewText(previewText);
454 tab->disconnect(
this);
455 connect(tab.
get(), &FITSTab::newStatus,
this, &FITSViewer::updateStatusBar);
456 connect(tab.
get(), &FITSTab::changeStatus,
this, &FITSViewer::updateTabStatus);
457 connect(tab.
get(), &FITSTab::debayerToggled,
this, &FITSViewer::setDebayerAction);
459 connect(tab->getView().get(), &FITSView::actionUpdated,
this, &FITSViewer::updateAction);
461 connect(tab->getView().get(), &FITSView::starProfileWindowClosed,
this, &FITSViewer::starProfileButtonOff);
467 fitsTabWidget->addTab(tab.
get(), previewText.
isEmpty() ? imageName.
fileName() : previewText);
471 fitsTabWidget->addTab(tab.
get(),
i18n(
"Focus"));
475 fitsTabWidget->addTab(tab.
get(),
i18n(
"Guide"));
479 fitsTabWidget->addTab(tab.
get(),
i18n(
"Align"));
486 saveFileAction->setEnabled(
true);
487 saveFileAsAction->setEnabled(
true);
489 undoGroup->addStack(tab->getUndoStack());
491 fitsMap[fitsID] = tab;
493 fitsTabWidget->setCurrentWidget(tab.
get());
497 tab->tabPositionUpdated();
503 if (tab->shouldComputeHFR())
504 updateStatusBar(HFRStatusString(tab->getView()->imageData()), FITS_HFR);
506 updateStatusBar(
"", FITS_HFR);
507 updateStatusBar(
i18n(
"Ready."), FITS_MESSAGE);
509 updateStatusBar(HFRClipString(tab->getView().get()), FITS_CLIP);
511 tab->getView()->setCursorMode(FITSView::dragCursor);
521void FITSViewer::loadFiles()
523 if (m_urls.size() == 0)
526 const QUrl imageName = m_urls[0];
531 for (
auto tab : m_Tabs)
533 const QString cpath = tab->getCurrentURL()->path();
536 fitsTabWidget->setCurrentWidget(tab.
get());
537 if (m_urls.size() > 0)
546 QSharedPointer<FITSTab> tab(
new FITSTab(
this));
548 m_Tabs.push_back(tab);
550 connect(tab.
get(), &FITSTab::failed,
this, [
this ](
const QString & errorMessage)
552 QApplication::restoreOverrideCursor();
553 led.setColor(Qt::red);
555 emit failed(errorMessage);
556 if (m_Tabs.size() == 0)
562 if (m_urls.size() > 0)
566 connect(tab.
get(), &FITSTab::loaded,
this, [ = ]()
568 if (addFITSCommon(m_Tabs.last(), imageName, FITS_NORMAL,
""))
569 emit loaded(fitsID++);
573 if (m_urls.size() > 0)
577 tab->loadFile(imageName, FITS_NORMAL, FITS_NONE);
580int FITSViewer::loadFile(
const QUrl &imageName, FITSMode mode, FITSScale filter,
const QString &previewText)
585 QSharedPointer<FITSTab> tab(
new FITSTab(
this));
587 m_Tabs.push_back(tab);
588 const int id = fitsID;
590 connect(tab.
get(), &FITSTab::failed,
this, [
this ](
const QString & errorMessage)
592 QApplication::restoreOverrideCursor();
593 led.setColor(Qt::red);
595 emit failed(errorMessage);
596 if (m_Tabs.size() == 0)
603 connect(tab.
get(), &FITSTab::loaded,
this, [ = ]()
605 if (addFITSCommon(m_Tabs.last(), imageName, mode, previewText))
606 emit loaded(fitsID++);
611 tab->loadFile(imageName, mode, filter);
616 FITSScale filter,
const QString &previewText)
621 QSharedPointer<FITSTab> tab(
new FITSTab(
this));
623 m_Tabs.push_back(tab);
625 if (!tab->loadData(data, mode, filter))
627 auto errorMessage = tab->getView()->imageData()->getLastError();
631 emit failed(errorMessage);
632 if (m_Tabs.size() == 0)
640 if (!addFITSCommon(tab, imageName, mode, previewText))
650bool FITSViewer::removeFITS(
int fitsUID)
652 auto tab = fitsMap.value(fitsUID);
656 qCWarning(KSTARS_FITS) <<
"Cannot find tab with UID " << fitsUID <<
" in the FITS Viewer";
660 int index = m_Tabs.indexOf(tab);
671void FITSViewer::updateFile(
const QUrl &imageName,
int fitsUID, FITSScale filter)
673 static bool updateBusy =
false;
678 auto tab = fitsMap.value(fitsUID);
682 QString message =
i18n(
"Cannot find tab with UID %1 in the FITS Viewer", fitsUID);
683 emit failed(message);
688 if (tab->isVisible())
692 auto conn = std::make_shared<QMetaObject::Connection>();
693 *conn =
connect(tab.
get(), &FITSTab::loaded,
this, [ = ]()
695 if (updateFITSCommon(tab, imageName))
697 QObject::disconnect(*conn);
698 emit loaded(tab->getUID());
703 auto conn2 = std::make_shared<QMetaObject::Connection>();
704 *conn2 =
connect(tab.
get(), &FITSTab::failed,
this, [ = ](
const QString & errorMessage)
706 Q_UNUSED(errorMessage);
707 QObject::disconnect(*conn2);
711 tab->loadFile(imageName, tab->getView()->getMode(), filter);
717 int tabIndex = fitsTabWidget->indexOf(tab.
get());
722 fitsTabWidget->setTabText(tabIndex, tabTitle);
723 else if (tab->getView()->getMode() == FITS_NORMAL)
725 if ((imageName.
fileName() ==
"Preview" ||
728 Options::singlePreviewFITS())
729 fitsTabWidget->setTabText(tabIndex,
730 tab->getPreviewText().isEmpty() ?
i18n(
"Preview") : tab->getPreviewText());
731 else if (tab->getPreviewText() !=
i18n(
"Preview") || imageName.
fileName().
size() > 0)
732 fitsTabWidget->setTabText(tabIndex, imageName.
fileName());
735 fitsTabWidget->setTabText(tabIndex, imageName.
fileName());
737 tab->getUndoStack()->clear();
739 if (tab->isVisible())
742 if (tab->shouldComputeHFR())
743 updateStatusBar(HFRStatusString(tab->getView()->imageData()), FITS_HFR);
745 updateStatusBar(
"", FITS_HFR);
747 updateStatusBar(HFRClipString(tab->getView().get()), FITS_CLIP);
756 FITSMode mode, FITSScale filter,
const QString &tabTitle)
758 auto tab = fitsMap.value(fitsUID);
763 if (mode != FITS_UNKNOWN)
764 tab->getView()->updateMode(mode);
766 if (tab->isVisible())
769 if (!tab->loadData(data, tab->getView()->getMode(), filter))
772 if (!updateFITSCommon(tab, imageName, tabTitle))
775 *tab_uid = tab->getUID();
779void FITSViewer::tabFocusUpdated(
int currentIndex)
781 if (currentIndex < 0 || m_Tabs.empty())
784 m_Tabs[currentIndex]->tabPositionUpdated();
786 auto view = m_Tabs[currentIndex]->getView();
788 view->toggleStars(markStars);
793 if (m_Tabs[currentIndex]->shouldComputeHFR())
794 updateStatusBar(HFRStatusString(view->imageData()), FITS_HFR);
796 updateStatusBar(
"", FITS_HFR);
798 updateStatusBar(HFRClipString(m_Tabs[currentIndex]->getView().
get()), FITS_CLIP);
800 if (view->imageData()->hasDebayer())
807 view->imageData()->getBayerParams(¶m);
808 debayerDialog->setBayerParams(¶m);
814 updateStatusBar(
"", FITS_WCS);
815 connect(view.get(), &FITSView::starProfileWindowClosed,
this, &FITSViewer::starProfileButtonOff);
816 QSharedPointer<FITSView> currentView;
817 if (getCurrentView(currentView))
819 updateButtonStatus(
"toggle_3D_graph",
i18n(
"currentView 3D Graph"), currentView->isStarProfileShown());
820 updateButtonStatus(
"view_crosshair",
i18n(
"Cross Hairs"), currentView->isCrosshairShown());
821 updateButtonStatus(
"view_clipping",
i18n(
"Clipping"), currentView->isClippingShown());
822 updateButtonStatus(
"view_eq_grid",
i18n(
"Equatorial Gridlines"), currentView->isEQGridShown());
823 updateButtonStatus(
"view_objects",
i18n(
"Objects in Image"), currentView->areObjectsShown());
824 updateButtonStatus(
"view_pixel_grid",
i18n(
"Pixel Gridlines"), currentView->isPixelGridShown());
825 updateButtonStatus(
"view_hips_overlay",
i18n(
"HiPS Overlay"), currentView->isHiPSOverlayShown());
835void FITSViewer::starProfileButtonOff()
837 updateButtonStatus(
"toggle_3D_graph",
i18n(
"View 3D Graph"),
false);
850 QRegularExpression re(
".*(fits|fits.fz|fit|fts|xisf|jpg|jpeg|png|gif|bmp|cr2|cr3|crw|nef|raf|dng|arw|orf)$");
851 while (!dirs.
empty())
855 auto list =
dir.entryInfoList( nameFilter, filter );
864 if (
match.hasMatch())
872void FITSViewer::blink()
879 dialog.setDirectoryUrl(lastURL);
886 QStringList selected = dialog.selectedFiles();
887 if (selected.
size() < 1)
892 QString topDir = selected[0];
894 auto allImages = findAllImagesBelowDir(QDir(topDir));
895 if (allImages.size() == 0)
906 QSharedPointer<FITSTab> tab(
new FITSTab(
this));
908 int tabIndex = m_Tabs.size();
909 if (allImages.size() > 1)
911 m_Tabs.push_back(tab);
912 tab->initBlink(allImages);
913 tab->setBlinkUpto(1);
915 QString tabName = QString(
"%1/%2 %3")
916 .arg(1).arg(allImages.size()).arg(QFileInfo(allImages[0]).fileName());
917 connect(tab.
get(), &FITSTab::failed,
this, [
this ](
const QString & errorMessage)
919 Q_UNUSED(errorMessage);
920 QObject::sender()->disconnect(this);
921 QApplication::restoreOverrideCursor();
922 led.setColor(Qt::red);
926 connect(tab.
get(), &FITSTab::loaded,
this, [ = ]()
928 QObject::sender()->disconnect(this);
929 addFITSCommon(m_Tabs.last(), imageName, FITS_NORMAL,
"");
931 fitsTabWidget->setTabText(tabIndex, tabName);
938 tab->loadFile(imageName, FITS_NORMAL, FITS_NONE);
942void FITSViewer::changeBlink(
bool increment)
944 if (m_Tabs.empty() || m_BlinkBusy)
948 const int tabIndex = fitsTabWidget->currentIndex();
949 if (tabIndex >= m_Tabs.count() || tabIndex < 0)
954 auto tab = m_Tabs[tabIndex];
955 const QList<QString> &filenames = tab->blinkFilenames();
956 if (filenames.
size() <= 1)
962 int blinkIndex = tab->blinkUpto() + (increment ? 1 : -1);
963 if (blinkIndex >= filenames.
size())
965 else if (blinkIndex < 0)
966 blinkIndex = filenames.
size() - 1;
968 QString nextFilename = filenames[blinkIndex];
969 QString tabName = QString(
"%1/%2 %3")
970 .
arg(blinkIndex + 1).
arg(filenames.
size()).
arg(QFileInfo(nextFilename).fileName());
971 tab->disconnect(
this);
972 connect(tab.
get(), &FITSTab::failed,
this, [
this, nextFilename ](
const QString & errorMessage)
974 Q_UNUSED(errorMessage);
975 QObject::sender()->disconnect(this);
976 QApplication::restoreOverrideCursor();
977 led.setColor(Qt::red);
981 connect(tab.
get(), &FITSTab::loaded,
this, [ = ]()
983 QObject::sender()->disconnect(this);
984 updateFITSCommon(tab, QUrl::fromLocalFile(nextFilename));
985 fitsTabWidget->setTabText(tabIndex, tabName);
989 tab->setBlinkUpto(blinkIndex);
993void FITSViewer::nextBlink()
998void FITSViewer::previousBlink()
1003void FITSViewer::openFile()
1007 dialog.setDirectoryUrl(lastURL);
1008 dialog.setNameFilter(
"Images (*.fits *.fits.fz *.fit *.fts *.xisf "
1009 "*.jpg *.jpeg *.png *.gif *.bmp "
1010 "*.cr2 *.cr3 *.crw *.nef *.raf *.dng *.arw *.orf)");
1013 m_urls = dialog.selectedUrls();
1014 if (m_urls.size() < 1)
1017 constexpr int MAX_NUM_OPENS = 40;
1018 if (m_urls.size() > MAX_NUM_OPENS)
1025void FITSViewer::saveFile()
1027 m_Tabs[fitsTabWidget->currentIndex()]->saveFile();
1030void FITSViewer::saveFileAs()
1035 if (m_Tabs[fitsTabWidget->currentIndex()]->saveFileAs() &&
1036 m_Tabs[fitsTabWidget->currentIndex()]->getView()->getMode() == FITS_NORMAL)
1037 fitsTabWidget->setTabText(fitsTabWidget->currentIndex(),
1038 m_Tabs[fitsTabWidget->currentIndex()]->getCurrentURL()->fileName());
1041void FITSViewer::copyFITS()
1046 m_Tabs[fitsTabWidget->currentIndex()]->copyFITS();
1049void FITSViewer::histoFITS()
1054 m_Tabs[fitsTabWidget->currentIndex()]->histoFITS();
1057void FITSViewer::statFITS()
1062 m_Tabs[fitsTabWidget->currentIndex()]->statFITS();
1065void FITSViewer::rotateCW()
1067 applyFilter(FITS_ROTATE_CW);
1070void FITSViewer::rotateCCW()
1072 applyFilter(FITS_ROTATE_CCW);
1075void FITSViewer::flipHorizontal()
1077 applyFilter(FITS_MOUNT_FLIP_H);
1080void FITSViewer::flipVertical()
1082 applyFilter(FITS_MOUNT_FLIP_V);
1085void FITSViewer::headerFITS()
1090 m_Tabs[fitsTabWidget->currentIndex()]->headerFITS();
1093void FITSViewer::debayerFITS()
1095 if (debayerDialog ==
nullptr)
1097 debayerDialog =
new FITSDebayer(
this);
1100 QSharedPointer<FITSView> view;
1101 if (getCurrentView(view))
1104 view->imageData()->getBayerParams(¶m);
1105 debayerDialog->setBayerParams(¶m);
1106 debayerDialog->show();
1110void FITSViewer::updateStatusBar(
const QString &msg, FITSBar
id)
1115 fitsPosition.setText(msg);
1117 case FITS_RESOLUTION:
1118 fitsResolution.setText(msg);
1121 fitsZoom.setText(msg);
1124 fitsWCS.setVisible(
true);
1125 fitsWCS.setText(msg);
1128 fitsValue.setText(msg);
1131 fitsHFR.setText(msg);
1134 fitsClip.setText(msg);
1145void FITSViewer::ZoomAllIn()
1151 for (
int i = 0; i < fitsTabWidget->count(); ++i)
1152 if (i != fitsTabWidget->currentIndex())
1153 m_Tabs[i]->ZoomIn();
1155 m_Tabs[fitsTabWidget->currentIndex()]->ZoomIn();
1158void FITSViewer::ZoomAllOut()
1164 for (
int i = 0; i < fitsTabWidget->count(); ++i)
1165 if (i != fitsTabWidget->currentIndex())
1166 m_Tabs[i]->ZoomOut();
1168 m_Tabs[fitsTabWidget->currentIndex()]->ZoomOut();
1171void FITSViewer::ZoomIn()
1176 m_Tabs[fitsTabWidget->currentIndex()]->ZoomIn();
1179void FITSViewer::ZoomOut()
1184 m_Tabs[fitsTabWidget->currentIndex()]->ZoomOut();
1187void FITSViewer::ZoomDefault()
1192 m_Tabs[fitsTabWidget->currentIndex()]->ZoomDefault();
1195void FITSViewer::ZoomToFit()
1200 QSharedPointer<FITSView> currentView;
1201 if (getCurrentView(currentView))
1202 currentView->ZoomToFit();
1209void FITSViewer::FitToZoom()
1214 QSharedPointer<FITSView> currentView;
1215 if (!getCurrentView(currentView))
1218 const double zoom = currentView->getCurrentZoom() * .01;
1219 const int w =
zoom * currentView->imageData()->width();
1220 const int h =
zoom * currentView->imageData()->height();
1221 const int extraW =
width() - currentView->width();
1222 const int extraH =
height() - currentView->height();
1225 const int wNeeded = w + extraW + 4;
1226 const int hNeeded = h + extraH + 4;
1227 resize(wNeeded, hNeeded);
1230void FITSViewer::updateAction(
const QString &name,
bool enable)
1234 if (toolAction !=
nullptr)
1238void FITSViewer::updateTabStatus(
bool clean,
const QUrl &imageURL)
1240 if (m_Tabs.empty() || (fitsTabWidget->currentIndex() >= m_Tabs.size()))
1243 if (m_Tabs[fitsTabWidget->currentIndex()]->getView()->getMode() != FITS_NORMAL)
1248 QString tabText = imageURL.
isEmpty() ? fitsTabWidget->tabText(fitsTabWidget->currentIndex()) : imageURL.
fileName();
1250 fitsTabWidget->setTabText(fitsTabWidget->currentIndex(), clean ? tabText.
remove(
'*') : tabText +
'*');
1253void FITSViewer::closeTab(
int index)
1258 auto tab = m_Tabs[index];
1260 int UID = tab->getUID();
1262 fitsMap.remove(UID);
1263 m_Tabs.removeOne(tab);
1267 saveFileAction->setEnabled(
false);
1268 saveFileAsAction->setEnabled(
false);
1280void FITSViewer::updateButtonStatus(
const QString &action,
const QString &item,
bool showing)
1305 if (!getCurrentView(currentView))
1308 if (currentView->imageHasWCS())
1314 if (currentView->isTelescopeActive())
1338void FITSViewer::updateScopeButton()
1341 if (!getCurrentView(currentView))
1344 if (currentView->getCursorMode() == FITSView::scopeCursor)
1354void FITSViewer::ROIFixedSize(
int s)
1359 QSharedPointer<FITSView> currentView;
1360 if (getCurrentView(currentView))
1362 if(!currentView->isSelectionRectShown())
1364 toggleSelectionMode();
1365 updateButtonStatus(
"image_roi_stats",
i18n(
"Selection Rectangle"), currentView->isSelectionRectShown());
1367 currentView->processRectangleFixed(s);
1371void FITSViewer::customROIInputWindow()
1376 QSharedPointer<FITSView> currentView;
1377 if (getCurrentView(currentView))
1379 if(!currentView->isSelectionRectShown())
1382 int mh = currentView->imageData()->height();
1383 int mw = currentView->imageData()->width();
1390 QDialog customRoiDialog;
1391 QFormLayout form(&customRoiDialog);
1394 form.addRow(
new QLabel(
i18n(
"Size")));
1396 QLineEdit wle(&customRoiDialog);
1397 QLineEdit hle(&customRoiDialog);
1399 wle.setValidator(
new QIntValidator(1, mw, &wle));
1400 hle.setValidator(
new QIntValidator(1, mh, &hle));
1402 form.addRow(
i18n(
"Width"), &wle);
1403 form.addRow(
i18n(
"Height"), &hle);
1404 form.addRow(&buttonBox);
1411 QPoint resetCenter = currentView->getSelectionRegion().center();
1412 int newheight = hle.text().toInt();
1413 int newwidth = wle.text().toInt();
1415 newheight = qMin(newheight, mh) ;
1416 newheight = qMax(newheight, 1) ;
1417 newwidth = qMin(newwidth, mw);
1418 newwidth = qMax(newwidth, 1);
1420 QPoint topLeft = resetCenter;
1421 QPoint botRight = resetCenter;
1423 topLeft.
setX((topLeft.
x() - newwidth / 2));
1424 topLeft.
setY((topLeft.
y() - newheight / 2));
1425 botRight.
setX((botRight.
x() + newwidth / 2));
1426 botRight.
setY((botRight.
y() + newheight / 2));
1428 emit currentView->setRubberBand(QRect(topLeft, botRight));
1429 currentView->processRectangle(topLeft, botRight,
true);
1441 if (!getCurrentView(currentView))
1445 if (currentView->getCursorMode() == FITSView::scopeCursor)
1447 currentView->setCursorMode(currentView->lastMouseMode);
1451 currentView->lastMouseMode = currentView->getCursorMode();
1452 currentView->setCursorMode(FITSView::scopeCursor);
1454 updateScopeButton();
1457void FITSViewer::toggleCrossHair()
1463 if (!getCurrentView(currentView))
1466 currentView->toggleCrosshair();
1467 updateButtonStatus(
"view_crosshair",
i18n(
"Cross Hairs"), currentView->isCrosshairShown());
1470void FITSViewer::toggleClipping()
1475 QSharedPointer<FITSView> currentView;
1476 if (!getCurrentView(currentView))
1478 currentView->toggleClipping();
1479 if (!currentView->isClippingShown())
1481 updateButtonStatus(
"view_clipping",
i18n(
"Clipping"), currentView->isClippingShown());
1484void FITSViewer::toggleEQGrid()
1489 QSharedPointer<FITSView> currentView;
1490 if (!getCurrentView(currentView))
1493 currentView->toggleEQGrid();
1494 updateButtonStatus(
"view_eq_grid",
i18n(
"Equatorial Gridlines"), currentView->isEQGridShown());
1497void FITSViewer::toggleHiPSOverlay()
1502 QSharedPointer<FITSView> currentView;
1503 if (!getCurrentView(currentView))
1506 currentView->toggleHiPSOverlay();
1507 updateButtonStatus(
"view_hips_overlay",
i18n(
"HiPS Overlay"), currentView->isHiPSOverlayShown());
1510void FITSViewer::toggleSelectionMode()
1515 QSharedPointer<FITSView> currentView;
1516 if (!getCurrentView(currentView))
1519 currentView->toggleSelectionMode();
1520 updateButtonStatus(
"image_roi_stats",
i18n(
"Selection Rectangle"), currentView->isSelectionRectShown());
1523void FITSViewer::toggleObjects()
1528 QSharedPointer<FITSView> currentView;
1529 if (!getCurrentView(currentView))
1532 currentView->toggleObjects();
1533 updateButtonStatus(
"view_objects",
i18n(
"Objects in Image"), currentView->areObjectsShown());
1536void FITSViewer::togglePixelGrid()
1541 QSharedPointer<FITSView> currentView;
1542 if (!getCurrentView(currentView))
1545 currentView->togglePixelGrid();
1546 updateButtonStatus(
"view_pixel_grid",
i18n(
"Pixel Gridlines"), currentView->isPixelGridShown());
1549void FITSViewer::toggle3DGraph()
1554 QSharedPointer<FITSView> currentView;
1555 if (!getCurrentView(currentView))
1558 currentView->toggleStarProfile();
1559 updateButtonStatus(
"toggle_3D_graph",
i18n(
"View 3D Graph"), currentView->isStarProfileShown());
1562void FITSViewer::nextTab()
1567 int index = fitsTabWidget->currentIndex() + 1;
1568 if (index >= m_Tabs.count() || index < 0)
1570 fitsTabWidget->setCurrentIndex(index);
1576void FITSViewer::previousTab()
1581 int index = fitsTabWidget->currentIndex() - 1;
1582 if (index >= m_Tabs.count() || index < 0)
1583 index = m_Tabs.count() - 1;
1584 fitsTabWidget->setCurrentIndex(index);
1591void FITSViewer::toggleStars()
1604 for (
auto tab : m_Tabs)
1606 tab->getView()->toggleStars(markStars);
1607 tab->getView()->updateFrame();
1611void FITSViewer::applyFilter(
int ftype)
1617 updateStatusBar(
i18n(
"Processing %1...", filterTypes[ftype - 1]), FITS_MESSAGE);
1618 qApp->processEvents();
1619 m_Tabs[fitsTabWidget->currentIndex()]->getHistogram()->applyFilter(
static_cast<FITSScale
>(ftype));
1620 qApp->processEvents();
1621 m_Tabs[fitsTabWidget->currentIndex()]->getView()->updateFrame();
1623 updateStatusBar(
i18n(
"Ready."), FITS_MESSAGE);
1628 auto tab = fitsMap.value(fitsUID);
1631 view = tab->getView();
1640 if (m_Tabs.empty() || fitsTabWidget->currentIndex() >= m_Tabs.count())
1643 view = m_Tabs[fitsTabWidget->currentIndex()]->getView();
1647void FITSViewer::setDebayerAction(
bool enable)
1652bool FITSViewer::tabExists(
int fitsUID)
1654 auto tab = fitsMap.value(fitsUID);
1655 return (!tab.
isNull() && tab.
data() !=
nullptr);
FITSViewer(QWidget *parent)
Constructor.
void centerTelescope()
This method either enables or disables the scope mouse mode so you can slew your scope to coordinates...
void updateWCSFunctions()
This is a method that either enables or disables the WCS based features in the Current View.
Q_INVOKABLE QAction * action(const QString &name) const
ActionType * add(const QString &name, const QObject *receiver=nullptr, const char *member=nullptr)
QAction * addAction(const QString &name, const QObject *receiver=nullptr, const char *member=nullptr)
static void setDefaultShortcut(QAction *action, const QKeySequence &shortcut)
static KStars * Instance()
virtual KActionCollection * actionCollection() const
virtual QAction * action(const QDomElement &element) const
void createGUI(const QString &xmlfile=QString())
KXmlGuiWindow(QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags())
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT QString dir(const QString &fileClass)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QAction * zoomIn(const QObject *recvr, const char *slot, QObject *parent)
QAction * close(const QObject *recvr, const char *slot, QObject *parent)
QAction * undo(const QObject *recvr, const char *slot, QObject *parent)
QAction * copy(const QObject *recvr, const char *slot, QObject *parent)
QAction * zoomOut(const QObject *recvr, const char *slot, QObject *parent)
QAction * redo(const QObject *recvr, const char *slot, QObject *parent)
QAction * save(const QObject *recvr, const char *slot, QObject *parent)
QAction * open(const QObject *recvr, const char *slot, QObject *parent)
QAction * actualSize(const QObject *recvr, const char *slot, QObject *parent)
QAction * zoom(const QObject *recvr, const char *slot, QObject *parent)
QAction * saveAs(const QObject *recvr, const char *slot, QObject *parent)
void setIcon(const QIcon &icon)
void setText(const QString &text)
void triggered(bool checked)
QCoreApplication * instance()
QString absoluteFilePath() const const
QString completeSuffix() const const
QString filePath() const const
void restoreOverrideCursor()
void setOverrideCursor(const QCursor &cursor)
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
qsizetype count() const const
void push_back(parameter_type value)
qsizetype size() const const
void setCentralWidget(QWidget *widget)
QStatusBar * statusBar() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QList< T > findChildren(Qt::FindChildOptions options) const const
QObject * parent() const const
bool isNull() const const
void showMessage(const QString &message, int timeout)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QString & remove(QChar ch, Qt::CaseSensitivity cs)
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void canRedoChanged(bool canRedo)
void canUndoChanged(bool canUndo)
QString fileName(ComponentFormattingOptions options) const const
QUrl fromLocalFile(const QString &localFile)
bool isEmpty() const const
bool isValid() const const
QString path(ComponentFormattingOptions options) const const
QString toLocalFile() const const
QString url(FormattingOptions options) const const