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