diff --git a/DeepSkyStacker/DeepSkyStacker.cpp b/DeepSkyStacker/DeepSkyStacker.cpp index 0866981e8..3c475155e 100644 --- a/DeepSkyStacker/DeepSkyStacker.cpp +++ b/DeepSkyStacker/DeepSkyStacker.cpp @@ -63,7 +63,6 @@ namespace bip = boost::interprocess; #include "QEventLogger.h" -CString OUTPUTFILE_FILTERS; CString STARMASKFILE_FILTERS; bool g_bShowRefStars = false; @@ -732,8 +731,6 @@ BOOL DeepSkyStackerApp::InitInstance() AfxInitRichEdit2(); - - OUTPUTFILE_FILTERS.LoadString(IDS_FILTER_OUTPUT); STARMASKFILE_FILTERS.LoadString(IDS_FILTER_MASK); return TRUE; diff --git a/DeepSkyStacker/DeepSkyStacker.vcxproj b/DeepSkyStacker/DeepSkyStacker.vcxproj index 73e96a7fa..f0a9829dd 100644 --- a/DeepSkyStacker/DeepSkyStacker.vcxproj +++ b/DeepSkyStacker/DeepSkyStacker.vcxproj @@ -429,7 +429,7 @@ $(QtToolsPath)\windeployqt --pdb $(TargetPath) - + diff --git a/DeepSkyStacker/DeepSkyStacker.vcxproj.filters b/DeepSkyStacker/DeepSkyStacker.vcxproj.filters index b456023ea..6c3d29ed4 100644 --- a/DeepSkyStacker/DeepSkyStacker.vcxproj.filters +++ b/DeepSkyStacker/DeepSkyStacker.vcxproj.filters @@ -271,9 +271,6 @@ Header Files - - Dialogs\Processing - Dialogs\Processing @@ -885,6 +882,9 @@ Dialogs\Processing + + Dialogs\Processing + diff --git a/DeepSkyStacker/ProcessingDlg.cpp b/DeepSkyStacker/ProcessingDlg.cpp index c0ead43f5..b599a231e 100644 --- a/DeepSkyStacker/ProcessingDlg.cpp +++ b/DeepSkyStacker/ProcessingDlg.cpp @@ -5,6 +5,7 @@ #include "selectrect.h" #include "FrameInfoSupport.h" #include "ProcessingSettingsDlg.h" +#include "SavePicture.h" #include #define dssApp DeepSkyStacker::instance() @@ -238,28 +239,7 @@ namespace DSS bool ProcessingDlg::saveOnClose() { - ZFUNCTRACE_RUNTIME(); - // - // The existing image is being closed and has been changed, ask the user if they want to save it - // - if (dirty_) - { - QString message{ tr("Do you want to save the modifications?", "IDS_MSG_SAVEMODIFICATIONS")}; - auto result = QMessageBox::question(this, "DeepSkyStacker", - message, (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel), QMessageBox::No); - switch (result) - { - case QMessageBox::Cancel: - return false; - break; - case QMessageBox::No: - return true; - break; - default: - return saveImage(); - } - } - else return true; + return askToSave(); } /* ------------------------------------------------------------------- */ @@ -282,10 +262,10 @@ namespace DSS /* ------------------------------------------------------------------- */ - void ProcessingDlg::loadFile(const fs::path& file) + void ProcessingDlg::loadStackedImage(const fs::path& file) { ZFUNCTRACE_RUNTIME(); - qDebug() << "Load File"; + qDebug() << "Load stacked image"; // // Load the output file created at the end of the stacking process. @@ -336,88 +316,90 @@ namespace DSS ZFUNCTRACE_RUNTIME(); qDebug() << "Load image"; - QFileDialog fileDialog(this); - QSettings settings; - QString directory; - QString extension; - QString strTitle; - fs::path file; + if (askToSave()) + { - DSS::ProgressDlg dlg{ DeepSkyStacker::instance() }; + QFileDialog fileDialog(this); + QSettings settings; + QString directory; + QString extension; + QString strTitle; + fs::path file; - timer.stop(); + DSS::ProgressDlg dlg{ DeepSkyStacker::instance() }; - directory = settings.value("Folders/SaveDSIFolder").toString(); - extension = settings.value("Folders/SavePictureExtension").toString(); - if (extension.isEmpty()) extension = "tif"; - fileDialog.setDefaultSuffix(extension); - fileDialog.setFileMode(QFileDialog::ExistingFile); // There can be only one + timer.stop(); - fileDialog.setNameFilter(tr("TIFF and FITS Files (*.tif *.tiff *.fits *.fit *.fts)", "IDS_FILTER_DSIIMAGETIFF")); - fileDialog.selectFile(QString()); // No file(s) selected - if (!directory.isEmpty()) - fileDialog.setDirectory(directory); + directory = settings.value("Folders/SaveDSIFolder").toString(); + extension = settings.value("Folders/SavePictureExtension").toString(); + if (extension.isEmpty()) extension = "tif"; + fileDialog.setDefaultSuffix(extension); + fileDialog.setFileMode(QFileDialog::ExistingFile); // There can be only one - if (QDialog::Accepted == fileDialog.exec()) - { - QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - QStringList files = fileDialog.selectedFiles(); + fileDialog.setNameFilter(tr("TIFF and FITS Files (*.tif *.tiff *.fits *.fit *.fts)", "IDS_FILTER_DSIIMAGETIFF")); + fileDialog.selectFile(QString()); // No file(s) selected + if (!directory.isEmpty()) + fileDialog.setDirectory(directory); - // - // Now get the file as a standard fs::path object - // - if (!files.empty()) // Never, ever attempt to add zero rows!!! + if (QDialog::Accepted == fileDialog.exec()) { - file = files.at(0).toStdU16String(); - - if (file.has_parent_path()) - directory = QString::fromStdU16String(file.parent_path().generic_u16string()); - else - directory = QString::fromStdU16String(file.root_path().generic_u16string()); + QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + QStringList files = fileDialog.selectedFiles(); - extension = QString::fromStdU16String(file.extension().generic_u16string()); - } - - settings.setValue("Folders/SaveDSIFolder", directory); - settings.setValue("Folders/SavePictureExtension", extension); + // + // Now get the file as a standard fs::path object + // + if (!files.empty()) // Never, ever attempt to add zero rows!!! + { + file = files.at(0).toStdU16String(); - // - // Finally load the file of interest - // - currentFile = file; // Remember the current file - dssApp->deepStack().reset(); - dssApp->deepStack().SetProgress(&dlg); - bool OK = dssApp->deepStack().LoadStackedInfo(file); - ZASSERT(OK); + if (file.has_parent_path()) + directory = QString::fromStdU16String(file.parent_path().generic_u16string()); + else + directory = QString::fromStdU16String(file.root_path().generic_u16string()); - dssApp->deepStack().SetProgress(nullptr); + extension = QString::fromStdU16String(file.extension().generic_u16string()); + } - modifyRGBKGradientControls(); - updateInformation(); + settings.setValue("Folders/SaveDSIFolder", directory); + settings.setValue("Folders/SavePictureExtension", extension); - dssApp->deepStack().GetStackedBitmap().GetBezierAdjust(processingSettings.bezierAdjust_); - dssApp->deepStack().GetStackedBitmap().GetHistogramAdjust(processingSettings.histoAdjust_); + // + // Finally load the file of interest + // + currentFile = file; // Remember the current file + dssApp->deepStack().reset(); + dssApp->deepStack().SetProgress(&dlg); + bool OK = dssApp->deepStack().LoadStackedInfo(file); + ZASSERT(OK); - updateControlsFromSettings(); + dssApp->deepStack().SetProgress(nullptr); - showHistogram(false); - resetSliders(); - int height = dssApp->deepStack().GetHeight(); - rectToProcess.Init(dssApp->deepStack().GetWidth(), height, height / 3); + modifyRGBKGradientControls(); + updateInformation(); - processingSettingsList.clear(); - picture->clear(); - processAndShow(true); + dssApp->deepStack().GetStackedBitmap().GetBezierAdjust(processingSettings.bezierAdjust_); + dssApp->deepStack().GetStackedBitmap().GetHistogramAdjust(processingSettings.histoAdjust_); - setDirty(false); + updateControlsFromSettings(); - timer.start(); + showHistogram(false); + resetSliders(); + int height = dssApp->deepStack().GetHeight(); + rectToProcess.Init(dssApp->deepStack().GetWidth(), height, height / 3); - QGuiApplication::restoreOverrideCursor(); + processingSettingsList.clear(); + picture->clear(); + processAndShow(true); - }; + setDirty(false); + timer.start(); + QGuiApplication::restoreOverrideCursor(); + + } + } } /* ------------------------------------------------------------------- */ @@ -427,6 +409,46 @@ namespace DSS ZFUNCTRACE_RUNTIME(); qDebug() << "Save image to file"; bool bResult = false; + + + if (dssApp->deepStack().IsLoaded()) + { + QSettings settings; + + auto baseDirectory{ settings.value("Folders/SavePictureFolder").toString() }; + auto extension{ settings.value("Folders/SavePictureExtension").toString().toLower() }; + auto applied{ settings.value("Folders/SaveApplySetting", false).toBool() }; + auto compression{ settings.value("Folders/SaveCompression", (uint)TC_NONE).toUInt() }; + auto filterIndex{ settings.value("Folders/SavePictureIndex", 0).toUInt() }; + + + QStringList fileFilters{ + tr("TIFF Image 16 bit/ch (*.tif)", "IDS_FILTER_OUTPUT"), + tr("TIFF Image 32 bit/ch - integer (*.tif)", "IDS_FILTER_OUTPUT"), + tr("TIFF Image 32 bit/ch - rational (*.tif)", "IDS_FILTER_OUTPUT"), + tr("FITS Image 16 bit/ch (*.fts)", "IDS_FILTER_OUTPUT"), + tr("FITS Image 32 bit/ch - integer (*.fts)", "IDS_FILTER_OUTPUT"), + tr("FITS Image 32 bit/ch - rational (*.fts)", "IDS_FILTER_OUTPUT") + }; + + if (extension.isEmpty()) extension = ".tif"; + + // + // SavePicture is a sub-class of QFileDialog, we'll set the QFileDialog vars first + // + SavePicture dlg{ this, tr("Save Image"), baseDirectory }; + dlg.setDefaultSuffix(extension); + dlg.setNameFilters(fileFilters); + dlg.selectNameFilter(fileFilters.at(filterIndex)); + dlg.setFilter(QDir::Files | QDir::Writable); + + // + // Now set our sub-class variables + // + dlg.setCompression(TIFFCOMPRESSION(compression)); + dlg.setApply(applied); + dlg.exec(); + } /* QSettings settings; CString strBaseDirectory; @@ -1126,6 +1148,33 @@ namespace DSS rectToProcess.Reset(); }; + /* ------------------------------------------------------------------- */ + + bool ProcessingDlg::askToSave() + { + ZFUNCTRACE_RUNTIME(); + // + // The existing image is being closed and has been changed, ask the user if they want to save it + // + if (dirty_) + { + QString message{ tr("Do you want to save the modifications?", "IDS_MSG_SAVEMODIFICATIONS") }; + auto result = QMessageBox::question(this, "DeepSkyStacker", + message, (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel), QMessageBox::No); + switch (result) + { + case QMessageBox::Cancel: + return false; + break; + case QMessageBox::No: + return true; + break; + default: + return saveImage(); + } + } + else return true; + }; // @@ -1189,40 +1238,51 @@ namespace DSS timer.start(); }; - + void ProcessingDlg::updateBezierCurve() + { + setDirty(); + showHistogram(); + }; void ProcessingDlg::darkAngleChanged() { updateDarkText(); + emit updateBezierCurve(); } void ProcessingDlg::darkPowerChanged() { updateDarkText(); + emit updateBezierCurve(); } void ProcessingDlg::midAngleChanged() { updateMidText(); + emit updateBezierCurve(); } void ProcessingDlg::midToneChanged() { updateMidText(); + emit updateBezierCurve(); } void ProcessingDlg::highAngleChanged() { updateHighText(); + emit updateBezierCurve(); } void ProcessingDlg::highPowerChanged() { updateHighText(); + emit updateBezierCurve(); } void ProcessingDlg::saturationChanged() { + setDirty(); updateSaturationText(); } @@ -1556,122 +1616,6 @@ void CProcessingDlg::OnShowWindow(BOOL bShow, UINT nStatus) /* ------------------------------------------------------------------- */ -void CProcessingDlg::LoadFile(LPCTSTR szFileName) -{ - -}; - -/* ------------------------------------------------------------------- */ - -void CProcessingDlg::OnLoaddsi() -{ - if (AskToSave()) - { - bool bOk = false; - CString strFilter; - QSettings settings; - - CString strBaseDirectory = (LPCTSTR)settings.value("Folders/SaveDSIFolder", QString("")).toString().utf16(); - - strFilter.LoadString(IDS_FILTER_DSIIMAGETIFF); - CFileDialog dlgOpen(true, - _T(".DSImage"), - nullptr, - OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_PATHMUSTEXIST, - strFilter, - this); - TCHAR szBigBuffer[20000] = _T(""); - DSS::ProgressDlg dlg{ DeepSkyStacker::instance() }; - - if (strBaseDirectory.GetLength()) - dlgOpen.m_ofn.lpstrInitialDir = strBaseDirectory.GetBuffer(_MAX_PATH); - - timer.stop(); - - dlgOpen.m_ofn.lpstrFile = szBigBuffer; - dlgOpen.m_ofn.nMaxFile = sizeof(szBigBuffer) / sizeof(szBigBuffer[0]); - - if (dlgOpen.DoModal() == IDOK) - { - CString strFile; - POSITION pos; - - pos = dlgOpen.GetStartPosition(); - while (pos && !bOk) - { - BeginWaitCursor(); - strFile = dlgOpen.GetNextPathName(pos); - dssApp->deepStack().Clear(); - dssApp->deepStack().SetProgress(&dlg); - bOk = dssApp->deepStack().LoadStackedInfo(strFile); - dssApp->deepStack().SetProgress(nullptr); - EndWaitCursor(); - }; - - if (bOk) - { - m_strCurrentFile = strFile; - - TCHAR szDir[1 + _MAX_DIR]; - TCHAR szDrive[1 + _MAX_DRIVE]; - - _tsplitpath(strFile, szDrive, szDir, nullptr, nullptr); - strBaseDirectory = szDrive; - strBaseDirectory += szDir; - - settings.setValue("Folders/SaveDSIFolder", QString::fromWCharArray(strBaseDirectory.GetString())); - - UpdateMonochromeControls(); - UpdateInfos(); - BeginWaitCursor(); - dssApp->deepStack().GetStackedBitmap().GetBezierAdjust(processingSettings.bezierAdjust_); - dssApp->deepStack().GetStackedBitmap().GetHistogramAdjust(processingSettings.histoAdjust_); - - updateControlsFromSettings(); - - showHistogram(false); - // resetSliders(); - int height = dssApp->deepStack().GetHeight(); - rectToProcess.Init(dssApp->deepStack().GetWidth(), height, height / 3); - - processingSettingsList.clear(); - m_Picture.SetImg((HBITMAP)nullptr); - processAndShow(true); - EndWaitCursor(); - m_bDirty = false; - }; - }; - - timer.start(); - }; -} - -/* ------------------------------------------------------------------- */ - -bool CProcessingDlg::AskToSave() -{ - bool bResult = false; - - if (m_bDirty) - { - int nResult; - - nResult = AfxMessageBox(IDS_MSG_SAVEMODIFICATIONS, MB_YESNOCANCEL | MB_ICONQUESTION); - if (nResult == IDCANCEL) - bResult = false; - else if (nResult == IDNO) - bResult = true; - else - bResult = SavePictureToFile(); - } - else - bResult = true; - - return bResult; -}; - -/* ------------------------------------------------------------------- */ - void CProcessingDlg::CopyPictureToClipboard() { HBITMAP hBitmap; @@ -1727,194 +1671,4 @@ void CProcessingDlg::CreateStarMask() } -bool CProcessingDlg::SavePictureToFile() -{ - bool bResult = false; - QSettings settings; - CString strBaseDirectory; - CString strBaseExtension; - bool applied = false; - uint dwCompression; - CRect rcSelect; - - if (dssApp->deepStack().IsLoaded()) - { - strBaseDirectory = (LPCTSTR)settings.value("Folders/SavePictureFolder").toString().utf16(); - strBaseExtension = (LPCTSTR)settings.value("Folders/SavePictureExtension").toString().utf16(); - auto dwFilterIndex = settings.value("Folders/SavePictureIndex", 0).toUInt(); - applied = settings.value("Folders/SaveApplySetting", false).toBool(); - dwCompression = settings.value("Folders/SaveCompression", (uint)TC_NONE).toUInt(); - - if (!strBaseExtension.GetLength()) - strBaseExtension = _T(".tif"); - - CSavePicture dlgOpen(false, - _T(".TIF"), - nullptr, - OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ENABLESIZING, - OUTPUTFILE_FILTERS, - this); - - if (m_SelectRectSink.GetSelectRect(rcSelect)) - dlgOpen.SetUseRect(true, true); - if (applied) - dlgOpen.SetApplied(true); - - dlgOpen.SetCompression((TIFFCOMPRESSION)dwCompression); - - if (strBaseDirectory.GetLength()) - dlgOpen.m_ofn.lpstrInitialDir = strBaseDirectory.GetBuffer(_MAX_PATH); - dlgOpen.m_ofn.nFilterIndex = dwFilterIndex; - - TCHAR szBigBuffer[20000] = _T(""); - DSS::ProgressDlg dlg{ DeepSkyStacker::instance() }; - - dlgOpen.m_ofn.lpstrFile = szBigBuffer; - dlgOpen.m_ofn.nMaxFile = sizeof(szBigBuffer) / sizeof(szBigBuffer[0]); - - if (dlgOpen.DoModal() == IDOK) - { - POSITION pos; - - pos = dlgOpen.GetStartPosition(); - if (pos) - { - CString strFile; - LPRECT lpRect = nullptr; - bool bApply; - bool bUseRect; - TIFFCOMPRESSION Compression; - - bApply = dlgOpen.GetApplied(); - bUseRect = dlgOpen.GetUseRect(); - Compression = dlgOpen.GetCompression(); - - if (bUseRect && m_SelectRectSink.GetSelectRect(rcSelect)) - lpRect = &rcSelect; - - BeginWaitCursor(); - strFile = dlgOpen.GetNextPathName(pos); - if (dlgOpen.m_ofn.nFilterIndex == 1) - dssApp->deepStack().GetStackedBitmap().SaveTIFF16Bitmap(strFile, lpRect, &dlg, bApply, Compression); - else if (dlgOpen.m_ofn.nFilterIndex == 2) - dssApp->deepStack().GetStackedBitmap().SaveTIFF32Bitmap(strFile, lpRect, &dlg, bApply, false, Compression); - else if (dlgOpen.m_ofn.nFilterIndex == 3) - dssApp->deepStack().GetStackedBitmap().SaveTIFF32Bitmap(strFile, lpRect, &dlg, bApply, true, Compression); - else if (dlgOpen.m_ofn.nFilterIndex == 4) - dssApp->deepStack().GetStackedBitmap().SaveFITS16Bitmap(strFile, lpRect, &dlg, bApply); - else if (dlgOpen.m_ofn.nFilterIndex == 5) - dssApp->deepStack().GetStackedBitmap().SaveFITS32Bitmap(strFile, lpRect, &dlg, bApply, false); - else if (dlgOpen.m_ofn.nFilterIndex == 6) - dssApp->deepStack().GetStackedBitmap().SaveFITS32Bitmap(strFile, lpRect, &dlg, bApply, true); - - TCHAR szDir[1 + _MAX_DIR]; - TCHAR szDrive[1 + _MAX_DRIVE]; - TCHAR szExt[1 + _MAX_EXT]; - - _tsplitpath(strFile, szDrive, szDir, nullptr, szExt); - strBaseDirectory = szDrive; - strBaseDirectory += szDir; - strBaseExtension = szExt; - - dwFilterIndex = dlgOpen.m_ofn.nFilterIndex; - settings.setValue("Folders/SavePictureFolder", QString::fromWCharArray(strBaseDirectory.GetString())); - settings.setValue("Folders/SavePictureExtension", QString::fromWCharArray(strBaseExtension.GetString())); - settings.setValue("Folders/SavePictureIndex", (uint)dwFilterIndex); - settings.setValue("Folders/SaveApplySetting", bApply); - settings.setValue("Folders/SaveCompression", (uint)Compression); - - EndWaitCursor(); - - m_strCurrentFile = strFile; - UpdateInfos(); - m_bDirty = false; - bResult = true; - }; - }; - } - else - { - AfxMessageBox(IDS_MSG_NOPICTURETOSAVE, MB_OK | MB_ICONSTOP); - }; - - return bResult; -}; - -/* ------------------------------------------------------------------- */ - -void CProcessingDlg::OnProcess() -{ - processAndShow(true); -} - - -/* ------------------------------------------------------------------- */ - - -/* ------------------------------------------------------------------- */ - -void CProcessingDlg::OnNotifyRedChangeSelPeg(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyRedPegMove(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyRedPegMoved(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyGreenChangeSelPeg(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyGreenPegMove(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyGreenPegMoved(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyBlueChangeSelPeg(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyBluePegMove(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -void CProcessingDlg::OnNotifyBluePegMoved(NMHDR*, LRESULT*) -{ - m_bDirty = true; - showHistogram(); -}; - -/* ------------------------------------------------------------------- */ - -void CProcessingDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) -{ - m_bDirty = true; - showHistogram(); - CDialog::OnHScroll(nSBCode, nPos, pScrollBar); -} - -/* ------------------------------------------------------------------- */ #endif \ No newline at end of file diff --git a/DeepSkyStacker/ProcessingDlg.h b/DeepSkyStacker/ProcessingDlg.h index 17e9ec39f..dd28ffc8f 100644 --- a/DeepSkyStacker/ProcessingDlg.h +++ b/DeepSkyStacker/ProcessingDlg.h @@ -307,7 +307,7 @@ namespace DSS void copyToClipboard(); void createStarMask(); - void loadFile(const fs::path& file); + void loadStackedImage(const fs::path& file); void loadImage(); bool saveImage(); @@ -361,7 +361,6 @@ namespace DSS void processAndShow(bool bSaveUndo = true); // Driven by Apply button - inline void updateDarkText() { // @@ -428,6 +427,8 @@ namespace DSS void UpdateHistogramAdjust(); + bool askToSave(); + public slots: void setSelectionRect(const QRectF& rect); @@ -468,6 +469,8 @@ namespace DSS void highAngleChanged(); void highPowerChanged(); + void updateBezierCurve(); + void saturationChanged(); @@ -483,9 +486,6 @@ namespace DSS bool SavePictureToFile(); void CreateStarMask(); - void LoadFile(LPCTSTR szFileName); - - #endif }; diff --git a/DeepSkyStacker/ProcessingSettingsDlg.cpp b/DeepSkyStacker/ProcessingSettingsDlg.cpp index f0c3b1b62..842e96761 100644 --- a/DeepSkyStacker/ProcessingSettingsDlg.cpp +++ b/DeepSkyStacker/ProcessingSettingsDlg.cpp @@ -140,7 +140,7 @@ namespace DSS { void ProcessingSettingsDlg::nameEdited(const QString& text) { - if (text.contains(QRegularExpression("[/\\]"))) + if (text.contains(QRegularExpression("[/\\\\]"))) { QApplication::beep(); QMessageBox::critical(const_cast(this), "DeepSkyStacker", diff --git a/DeepSkyStacker/ProcessingSettingsDlg.h b/DeepSkyStacker/ProcessingSettingsDlg.h index e8970223f..f22f7ab93 100644 --- a/DeepSkyStacker/ProcessingSettingsDlg.h +++ b/DeepSkyStacker/ProcessingSettingsDlg.h @@ -33,7 +33,8 @@ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** -****************************************************************************/#include +****************************************************************************/ +#include #include "BaseDialog.h" #include "ProcessingSettings.h" #include "ui_ProcessingSettingsDlg.h" diff --git a/DeepSkyStacker/SavePicture.cpp b/DeepSkyStacker/SavePicture.cpp index 85684328f..7ce2fd59b 100644 --- a/DeepSkyStacker/SavePicture.cpp +++ b/DeepSkyStacker/SavePicture.cpp @@ -1,9 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2024 David C. Partridge +** +** BSD License Usage +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of DeepSkyStacker nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** +****************************************************************************/ // SavePicture.cpp : implementation file // - #include "stdafx.h" + +#include +#include +#include +#include +#include +#include + #include "SavePicture.h" -#include "resourceCZ.h" + +namespace DSS +{ + SavePicture::SavePicture(QWidget* parent, const QString& caption, const QString& directory, const QString& filter) : + QFileDialog(parent, caption, directory, filter), + compressionGroup(new QGroupBox(this)), + compressionLayout(new QHBoxLayout(compressionGroup)), + compressionNone(new QRadioButton(compressionGroup)), + compressionZIP(new QRadioButton(compressionGroup)), + compressionLZW(new QRadioButton(compressionGroup)), + optionsGroup(new QGroupBox(this)), + optionsLayout(new QVBoxLayout(optionsGroup)), + applyAdjustments(new QRadioButton(optionsGroup)), + embedAdjustments(new QRadioButton(optionsGroup)), + useRectangle(new QCheckBox(optionsGroup)) + { + compressionGroup->setObjectName("compressionGroup"); + compressionLayout->setObjectName("compressionLayout"); + compressionNone->setObjectName("compressionNone"); + compressionZIP->setObjectName("compressionZIP"); + compressionLZW->setObjectName("compressionLZW"); + + optionsGroup->setObjectName("optionsGroup"); + optionsLayout->setObjectName("optionsLayout"); + applyAdjustments->setObjectName("applyAdjustments"); + embedAdjustments->setObjectName("embedAdjustments"); + useRectangle->setObjectName("useRectangle"); + + compressionGroup->setLayout(compressionLayout); + compressionLayout->addWidget(compressionNone); + compressionLayout->addWidget(compressionZIP); + compressionLayout->addWidget(compressionLZW); + + optionsGroup->setLayout(optionsLayout); + optionsLayout->addWidget(applyAdjustments); + optionsLayout->addWidget(embedAdjustments); + optionsLayout->addWidget(useRectangle); + + retranslateUi(this); + + // + // Setting DontUseNativeDialog forces Qt to use a Widget based dialogue. + // + // This uses a QGridLayout to position the controls, and we can add + // additional controls using QGridLayout::addWidget() + // + setOption(QFileDialog::DontUseNativeDialog); + + QGridLayout* layout{ dynamic_cast(this->layout()) }; + layout->addWidget(compressionGroup, layout->rowCount(), 0, 1, 2); + layout->addWidget(optionsGroup, layout->rowCount(), 0, 1, 2); + + connectSignalsToSlots(); + } + + void SavePicture::retranslateUi([[maybe_unused]]QWidget* wdgt) + { + compressionGroup->setTitle(tr("Compression", "IDD_SAVEPICTURE")); + compressionNone->setText(tr("None", "IDC_COMPRESSION_NONE")); + compressionZIP->setText(tr("ZIP (Deflate)", "IDC_COMPRESSION_ZIP")); + compressionLZW->setText(tr("LZW (Deprecated)", "IDC_COMPRESSION_LZW")); + optionsGroup->setTitle(tr("Options", "IDD_SAVEPICTURE")); + applyAdjustments->setText(tr("Apply adjustments to the saved image", "IDC_APPLIED")); + embedAdjustments->setText(tr("Embed adjustments in the saved image but do not apply them", "IDC_EMBEDDED")); + embedText = embedAdjustments->text(); + noAdjustments = tr("Do not apply adjustments to the saved image", "IDS_SAVENOADJUSTMENT"); + useRectangle->setText(tr("Create an image from the selected rectangle", "IDC_USERECT")); + } + + void SavePicture::connectSignalsToSlots() + { + connect(compressionNone, &QRadioButton::clicked, this, &SavePicture::onCompressionNone); + connect(compressionZIP, &QRadioButton::clicked, this, &SavePicture::onCompressionZIP); + connect(compressionLZW, &QRadioButton::clicked, this, &SavePicture::onCompressionLZW); + connect(applyAdjustments, &QRadioButton::clicked, this, &SavePicture::onApply); + connect(embedAdjustments, &QRadioButton::clicked, this, &SavePicture::onEmbed); + connect(this, &QFileDialog::filterSelected, this, &SavePicture::onFilter); + } + + // + // Slots + // + void SavePicture::onCompressionNone(bool checked) + { + if (checked) compression_ = TC_NONE; + } + + void SavePicture::onCompressionZIP(bool checked) + { + if (checked) compression_ = TC_DEFLATE; + } + + void SavePicture::onCompressionLZW(bool checked) + { + if (checked) compression_ = TC_LZW; + } + + void SavePicture::onApply(bool checked) + { + if (checked) apply_ = true; + } + + void SavePicture::onEmbed(bool checked) + { + if (checked) apply_ = false; + } + + + void SavePicture::onFilter(const QString& filter) + { + auto index{ nameFilters().indexOf(filter) }; + if (index > 2) // FITS files + { + compression_ = TC_NONE; + compressionNone->setChecked(true); + compressionZIP->setEnabled(false); + compressionLZW->setEnabled(false); + embedAdjustments->setText(noAdjustments); + } + else // TIF files + { + compressionZIP->setEnabled(true); + compressionLZW->setEnabled(true); + embedAdjustments->setText(embedText); + } + } + +} + +#if (0) /* ------------------------------------------------------------------- */ // CSavePicture @@ -204,3 +375,4 @@ void CSavePicture::OnTypeChange() /* ------------------------------------------------------------------- */ +#endif \ No newline at end of file diff --git a/DeepSkyStacker/SavePicture.h b/DeepSkyStacker/SavePicture.h index 9d9fa6133..3e2aed661 100644 --- a/DeepSkyStacker/SavePicture.h +++ b/DeepSkyStacker/SavePicture.h @@ -1,6 +1,131 @@ #pragma once +/**************************************************************************** +** +** Copyright (C) 2024 David C. Partridge +** +** BSD License Usage +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of DeepSkyStacker nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** +****************************************************************************/ +#include #include "DSSCommon.h" -#include "ToolTipButton.h" + +class QCheckBox; +class QGroupBox; +class QHBoxLayout; +class QRadioButton; +class QVBoxLayout; + +namespace DSS +{ + class SavePicture final : public QFileDialog + { + Q_OBJECT + + public: + SavePicture(QWidget* parent = nullptr, const QString& caption = QString(), const QString& directory = QString(), const QString& filter = QString()); + + ~SavePicture() = default; + + SavePicture(const SavePicture&) = delete; + SavePicture(SavePicture&&) = delete; + SavePicture& operator=(const SavePicture& rhs) = delete; + + void retranslateUi(QWidget*); + + void connectSignalsToSlots(); + + inline void setCompression(const TIFFCOMPRESSION comp) + { + compression_ = comp; + switch (comp) + { + case TC_NONE: + compressionNone->setChecked(true); + break; + case TC_DEFLATE: + compressionZIP->setChecked(true); + break; + case TC_LZW: + compressionLZW->setChecked(true); + break; + } + } + + inline void setApply(const bool apply) + { + apply_ = apply; + switch (apply) + { + case false: + embedAdjustments->setChecked(true); + break; + case true: + applyAdjustments->setChecked(true); + break; + } + } + + private: + QGroupBox* compressionGroup; + QHBoxLayout* compressionLayout; + QRadioButton* compressionNone; + QRadioButton* compressionZIP; + QRadioButton* compressionLZW; + + QGroupBox* optionsGroup; + QVBoxLayout* optionsLayout; + QRadioButton* applyAdjustments; + QRadioButton* embedAdjustments; + QCheckBox* useRectangle; + + QString embedText; + QString noAdjustments; + + TIFFCOMPRESSION compression_; + bool apply_; + bool useRect_; + + + private slots: + void onCompressionNone(bool checked); + void onCompressionZIP(bool checked); + void onCompressionLZW(bool checked); + void onApply(bool checked); + void onEmbed(bool checked); + void onFilter(const QString& filter); + + }; +} + +#if (0) // CSavePicture class CSavePicture : public CFileDialog @@ -80,5 +205,4 @@ private : public: virtual BOOL OnInitDialog(); }; - - +#endif \ No newline at end of file diff --git a/DeepSkyStacker/StackingDlg.cpp b/DeepSkyStacker/StackingDlg.cpp index 04447a41d..eddf2e371 100644 --- a/DeepSkyStacker/StackingDlg.cpp +++ b/DeepSkyStacker/StackingDlg.cpp @@ -474,8 +474,7 @@ namespace DSS copy{ nullptr }, erase{ nullptr }, networkManager{ nullptr }, - m_tipShowCount{ 0 }, - dockTitle{ new QLabel(this) } + m_tipShowCount{ 0 } { ui->setupUi(this); isos << "100" << "125" << "160" << "200" << "250" << "320" << "400" << @@ -680,8 +679,6 @@ namespace DSS updateListInfo(); // Update information bar and tooltip - dockTitle->setToolTip(tr("Double click here to dock/undock the image list")); - // // Now iterate over the groups and retranslate the group names and all strings in the table model // for the image list. @@ -1126,19 +1123,6 @@ namespace DSS ui->gamma->setPegsOnLeftOrBottom(true). setOrientation(QLinearGradientCtrl::Orientation::ForceHorizontal); - // - // Set an informative title bar on the dockable image list with a nice gradient - // as the background (like the old "listInfo" static control). - // - QSize size{ 625, 25 }; - dockTitle->setObjectName("dockTitle"); - dockTitle->setMinimumSize(size); - dockTitle->resize(size); - dockTitle->setStyleSheet(QString::fromUtf8("QLabel {" - "background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, " - "stop:0 rgba(138, 185, 242, 0), stop:1 rgba(138, 185, 242, 255))}")); - pictureList->setTitleBarWidget(dockTitle); - // // Set up the tab bar (used to be a tab widget) // @@ -1771,7 +1755,7 @@ namespace DSS .arg(frameList.checkedImageCount(PICTURETYPE_OFFSETFRAME)) }; - dockTitle->setText(text); + pictureList->dockTitle->setText(text); for (int i = 0; i < pictureList->tabBar->count(); i++) { @@ -2505,7 +2489,7 @@ namespace DSS dlg.SetJointProgress(false); dlg.Close(); - dssApp->getProcessingDlg().loadFile(strFileName); + dssApp->getProcessingDlg().loadStackedImage(strFileName); // Change tab to processing dssApp->setPanel(ActivePanel::ProcessingPanel); diff --git a/DeepSkyStacker/StackingDlg.h b/DeepSkyStacker/StackingDlg.h index 1d8fa40a4..0ffbe58fa 100644 --- a/DeepSkyStacker/StackingDlg.h +++ b/DeepSkyStacker/StackingDlg.h @@ -297,8 +297,6 @@ namespace DSS QAction* copy; QAction* erase; - QLabel* dockTitle; - void checkAskRegister(); void onInitDialog(); diff --git a/DeepSkyStacker/picturelist.cpp b/DeepSkyStacker/picturelist.cpp index 78fe8db23..3c4ac4d6a 100644 --- a/DeepSkyStacker/picturelist.cpp +++ b/DeepSkyStacker/picturelist.cpp @@ -2,12 +2,28 @@ #include "picturelist.h" namespace DSS { - PictureList::PictureList(QWidget* parent) - : QDockWidget(parent) + PictureList::PictureList(QWidget* parent) : + QDockWidget(parent), + dockTitle{ new QLabel(this) } { setupUi(this); tableView->horizontalHeader()->setSortIndicator(1, Qt::AscendingOrder); tableView->horizontalHeader()->setSortIndicatorShown(true); + + dockTitle->setToolTip(tr("Double click here to dock/undock the image list")); + + // + // Set an informative title bar on the dockable image list with a nice gradient + // as the background (like the old "listInfo" static control). + // + QSize size{ 625, 25 }; + dockTitle->setObjectName("dockTitle"); + dockTitle->setMinimumSize(size); + dockTitle->resize(size); + dockTitle->setStyleSheet(QString::fromUtf8("QLabel {" + "background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(138, 185, 242, 0), stop:1 rgba(138, 185, 242, 255))}")); + setTitleBarWidget(dockTitle); } PictureList::~PictureList() diff --git a/DeepSkyStacker/picturelist.h b/DeepSkyStacker/picturelist.h index 04ddd26ac..e92e4ceb3 100644 --- a/DeepSkyStacker/picturelist.h +++ b/DeepSkyStacker/picturelist.h @@ -16,6 +16,10 @@ namespace DSS public: PictureList(QWidget* parent = nullptr); ~PictureList(); + + private: + QLabel* dockTitle; + #if QT_VERSION < 0x060601 // Shouldn't need this in QT 6.6.1 inline void setDSSClosing() { dssClosing = true; }