diff --git a/kstars/fitsviewer/fitstab.cpp b/kstars/fitsviewer/fitstab.cpp index 0d79a0815..f1a6d23c3 100644 --- a/kstars/fitsviewer/fitstab.cpp +++ b/kstars/fitsviewer/fitstab.cpp @@ -1,372 +1,375 @@ /*************************************************************************** FITS Tab ------------------- copyright : (C) 2012 by Jasem Mutlaq email : mutlaqja@ikarustech.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "fitstab.h" #include "fitsdata.h" #include "fitshistogram.h" #include "fitsview.h" #include "fitsviewer.h" #include "kstars.h" #include "Options.h" #include "ui_fitsheaderdialog.h" #include "ui_statform.h" #include #include FITSTab::FITSTab(FITSViewer *parent) : QWidget(parent) { viewer = parent; undoStack = new QUndoStack(this); undoStack->setUndoLimit(10); undoStack->clear(); connect(undoStack, SIGNAL(cleanChanged(bool)), this, SLOT(modifyFITSState(bool))); statWidget = new QDialog(this); fitsHeaderDialog = new QDialog(this); histogram = new FITSHistogram(this); } FITSTab::~FITSTab() { // Make sure it's done histogramFuture.waitForFinished(); //disconnect(); } void FITSTab::saveUnsaved() { if (undoStack->isClean() || view->getMode() != FITS_NORMAL) return; QString caption = i18n("Save Changes to FITS?"); QString message = i18n("The current FITS file has unsaved changes. Would you like to save before closing it?"); int ans = KMessageBox::warningYesNoCancel(nullptr, message, caption, KStandardGuiItem::save(), KStandardGuiItem::discard()); if (ans == KMessageBox::Yes) saveFile(); if (ans == KMessageBox::No) { undoStack->clear(); modifyFITSState(); } } void FITSTab::closeEvent(QCloseEvent *ev) { saveUnsaved(); if (undoStack->isClean()) ev->accept(); else ev->ignore(); } QString FITSTab::getPreviewText() const { return previewText; } void FITSTab::setPreviewText(const QString &value) { previewText = value; } void FITSTab::loadFITS(const QUrl &imageURL, FITSMode mode, FITSScale filter, bool silent) { if (view.get() == nullptr) { view.reset(new FITSView(this, mode, filter)); view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QVBoxLayout *vlayout = new QVBoxLayout(); fitsSplitter = new QSplitter(Qt::Horizontal,this); fitsTools = new QToolBox(); stat.setupUi(statWidget); fitsTools->addItem(statWidget,i18n("Statistics")); fitsTools->addItem(histogram,i18n("Histogram")); header.setupUi(fitsHeaderDialog); fitsTools->addItem(fitsHeaderDialog,i18n("FITS Header")); QScrollArea *scrollFitsPanel = new QScrollArea(fitsSplitter); scrollFitsPanel->setWidgetResizable(true); scrollFitsPanel->setWidget(fitsTools); fitsSplitter->addWidget(scrollFitsPanel); fitsSplitter->addWidget(view.get()); //This code allows the fitsTools to start in a closed state fitsSplitter->setSizes(QList() << 0 << view->width() ); vlayout->addWidget(fitsSplitter); connect(fitsSplitter, &QSplitter::splitterMoved, histogram, &FITSHistogram::resizePlot); setLayout(vlayout); connect(view.get(), &FITSView::newStatus, this, &FITSTab::newStatus); connect(view.get(), &FITSView::debayerToggled, this, &FITSTab::debayerToggled); // On Failure to load connect(view.get(), &FITSView::failed, this, &FITSTab::failed); // On Success loading image connect(view.get(), &FITSView::loaded, [&,filter]() { // If it was already running make sure it's done histogramFuture.waitForFinished(); FITSData *image_data = view->getImageData(); if (histogram == nullptr) { histogram = new FITSHistogram(this); image_data->setHistogram(histogram); } histogramFuture = QtConcurrent::run([&]() {histogram->constructHistogram();}); + if(histogram->isVisible()) + histogramFuture.waitForFinished(); + // if (filter != FITS_NONE) // { // image_data->applyFilter(filter); // view->rescale(ZOOM_KEEP_LEVEL); // } if (viewer->isStarsMarked()) view->toggleStars(true); evaluateStats(); loadFITSHeader(); view->updateFrame(); emit loaded(); }); } currentURL = imageURL; view->setFilter(filter); view->loadFITS(imageURL.toLocalFile(), silent); } void FITSTab::modifyFITSState(bool clean) { if (clean) { if (undoStack->isClean() == false) undoStack->setClean(); mDirty = false; } else mDirty = true; emit changeStatus(clean); } int FITSTab::saveFITS(const QString &filename) { return view->saveFITS(filename); } void FITSTab::copyFITS() { QApplication::clipboard()->setImage(view->getDisplayImage()); } void FITSTab::histoFITS() { fitsTools->setCurrentIndex(1); if(view->width()>200) fitsSplitter->setSizes(QList() << 200 << view->width() - 200); else fitsSplitter->setSizes(QList() << 50 << 50); } void FITSTab::evaluateStats() { FITSData *image_data = view->getImageData(); stat.widthOUT->setText(QString::number(image_data->width())); stat.heightOUT->setText(QString::number(image_data->height())); stat.bitpixOUT->setText(QString::number(image_data->bpp())); stat.maxOUT->setText(QString::number(image_data->getMax(), 'f', 3)); stat.minOUT->setText(QString::number(image_data->getMin(), 'f', 3)); stat.meanOUT->setText(QString::number(image_data->getMean(), 'f', 3)); stat.stddevOUT->setText(QString::number(image_data->getStdDev(), 'f', 3)); stat.HFROUT->setText(QString::number(image_data->getHFR(), 'f', 3)); stat.medianOUT->setText(QString::number(image_data->getMedian(), 'f', 3)); stat.SNROUT->setText(QString::number(image_data->getSNR(), 'f', 3)); } void FITSTab::statFITS() { fitsTools->setCurrentIndex(0); if(view->width()>200) fitsSplitter->setSizes(QList() << 200 << view->width() - 200); else fitsSplitter->setSizes(QList() << 50 << 50); } void FITSTab::loadFITSHeader() { FITSData *image_data = view->getImageData(); int nkeys = image_data->getRecords().size(); int counter=0; header.tableWidget->setRowCount(nkeys); for (FITSData::Record *oneRecord : image_data->getRecords()) { QTableWidgetItem *tempItem = new QTableWidgetItem(oneRecord->key); tempItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); header.tableWidget->setItem(counter, 0, tempItem); tempItem = new QTableWidgetItem(oneRecord->value.toString()); tempItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); header.tableWidget->setItem(counter, 1, tempItem); tempItem = new QTableWidgetItem(oneRecord->comment); tempItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); header.tableWidget->setItem(counter, 2, tempItem); counter++; } header.tableWidget->setColumnWidth(0,100); header.tableWidget->setColumnWidth(1,100); header.tableWidget->setColumnWidth(2,250); } void FITSTab::headerFITS() { fitsTools->setCurrentIndex(2); if(view->width()>200) fitsSplitter->setSizes(QList() << 200 << view->width() - 200); else fitsSplitter->setSizes(QList() << 50 << 50); } bool FITSTab::saveFile() { QUrl backupCurrent = currentURL; QUrl currentDir(Options::fitsDir()); currentDir.setScheme("file"); if (currentURL.toLocalFile().startsWith(QLatin1String("/tmp/")) || currentURL.toLocalFile().contains("/Temp")) currentURL.clear(); // If no changes made, return. if (mDirty == false && !currentURL.isEmpty()) return false; if (currentURL.isEmpty()) { currentURL = QFileDialog::getSaveFileUrl(KStars::Instance(), i18n("Save FITS"), currentDir, "FITS (*.fits *.fits.gz *.fit)"); // if user presses cancel if (currentURL.isEmpty()) { currentURL = backupCurrent; return false; } if (currentURL.toLocalFile().contains('.') == 0) currentURL.setPath(currentURL.toLocalFile() + ".fits"); // Already display by dialog /*if (QFile::exists(currentURL.toLocalFile())) { int r = KMessageBox::warningContinueCancel(0, i18n( "A file named \"%1\" already exists. " "Overwrite it?", currentURL.fileName() ), i18n( "Overwrite File?" ), KGuiItem(i18n( "&Overwrite" )) ); if(r==KMessageBox::Cancel) return false; }*/ } if (currentURL.isValid()) { int err_status = 0; char err_text[FLEN_STATUS]; if ((err_status = saveFITS('!' + currentURL.toLocalFile())) != 0) { // -1000 = user canceled if (err_status == -1000) return false; fits_get_errstatus(err_status, err_text); // Use KMessageBox or something here KMessageBox::error(nullptr, i18n("FITS file save error: %1", QString::fromUtf8(err_text)), i18n("FITS Save")); return false; } //statusBar()->changeItem(i18n("File saved."), 3); emit newStatus(i18n("File saved to %1", currentURL.url()), FITS_MESSAGE); modifyFITSState(); return true; } else { QString message = i18n("Invalid URL: %1", currentURL.url()); KMessageBox::sorry(nullptr, message, i18n("Invalid URL")); return false; } } bool FITSTab::saveFileAs() { currentURL.clear(); return saveFile(); } void FITSTab::ZoomIn() { QPoint oldCenter = view->getImagePoint(view->viewport()->rect().center()); view->ZoomIn(); view->cleanUpZoom(oldCenter); } void FITSTab::ZoomOut() { QPoint oldCenter = view->getImagePoint(view->viewport()->rect().center()); view->ZoomOut(); view->cleanUpZoom(oldCenter); } void FITSTab::ZoomDefault() { QPoint oldCenter = view->getImagePoint(view->viewport()->rect().center()); view->ZoomDefault(); view->cleanUpZoom(oldCenter); } void FITSTab::tabPositionUpdated() { undoStack->setActive(true); emit newStatus(QString("%1%").arg(view->getCurrentZoom()), FITS_ZOOM); emit newStatus(QString("%1x%2").arg(view->getImageData()->width()).arg(view->getImageData()->height()), FITS_RESOLUTION); }