Files
tenmon/settingsdialog.cpp
T
2025-04-28 17:06:24 +02:00

241 lines
9.5 KiB
C++

#include "settingsdialog.h"
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QLabel>
#include <QSettings>
#include <QApplication>
#include <QProcess>
#include <QCoreApplication>
#include <QFileInfo>
#include <QMessageBox>
#include <QDir>
#include <QPushButton>
#include <QLineEdit>
#include <QColorDialog>
#include "rawimage.h"
extern int DEFAULT_WIDTH;
extern double SATURATION;
extern int FILTERING;
extern bool BESTFIT;
extern QMap<QString, QColor> headerHighlight;
class EvenNumber : public QSpinBox
{
public:
explicit EvenNumber(QWidget *parent) : QSpinBox(parent){}
protected:
QValidator::State validate(QString &text, int &) const
{
bool ok;
int val = text.toInt(&ok);
if(ok && (val & 1) == 0)return QValidator::Acceptable;
if(ok)return QValidator::Intermediate;
return QValidator::Invalid;
}
void fixup(QString &input) const
{
bool ok;
int val = input.toInt(&ok);
val -= val & 1;
input = QString::number(val);
}
};
SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent)
{
QFormLayout *layout = new QFormLayout(this);
setWindowTitle(tr("Settings"));
QSettings settings;
m_preloadImages = new QSpinBox(this);
m_preloadImages->setRange(0, 32);
m_preloadImages->setValue(settings.value("settings/preloadimagecount", DEFAULT_WIDTH).toInt());
m_preloadImages->setToolTip(tr("How many images are preloaded before and after current image."));
m_thumSize = new EvenNumber(this);
m_thumSize->setRange(64, 512);
m_thumSize->setSingleStep(2);
m_thumSize->setValue(settings.value("settings/thumnailsize", THUMB_SIZE).toInt());
m_thumSize->setToolTip(tr("Thumbnail size in pixels"));
m_saturation = new QDoubleSpinBox(this);
m_saturation->setMinimum(0);
m_saturation->setMaximum(100);
m_saturation->setSuffix(" %");
m_saturation->setValue(settings.value("settings/saturation", SATURATION * 100.0).toDouble());
m_saturation->setToolTip(tr("Set threshold value that is considered saturated when showing statistics.\nFor RAW files you may set 22%"));
m_slideShowTime = new QDoubleSpinBox(this);
m_slideShowTime->setMinimum(0.01);
m_slideShowTime->setMaximum(10);
m_slideShowTime->setSuffix(" s");
m_slideShowTime->setValue(settings.value("settings/slideshowtime", 1.0).toDouble());
m_slideShowTime->setSingleStep(0.1);
m_useNativeDialog = new QCheckBox(tr("Don't use native file dialog"), this);
m_useNativeDialog->setChecked(QApplication::testAttribute(Qt::AA_DontUseNativeDialogs));
m_filtering = new QComboBox(this);
m_filtering->addItems({tr("Nearest"), tr("Linear"), tr("Cubic")});
m_filtering->setCurrentIndex(FILTERING);
m_qualityThumbnail = new QCheckBox(tr("Smooth thumbnails"), this);
m_qualityThumbnail->setChecked(QUALITY_RESIZE);
m_qualityThumbnail->setToolTip(tr("Use box filter when downsampling thumbnails instead of nearest. Slightly slower."));
m_bestFit = new QCheckBox(tr("Best Fit on image load"));
m_bestFit->setToolTip(tr("Set Best Fit zoom level when opening new image."));
m_bestFit->setChecked(BESTFIT);
m_headerHighlight = new QListWidget(this);
m_headerHighlight->setToolTip(tr("List of FITS keywords that will be highlighted in Image info"));
for(auto i = headerHighlight.begin(); i != headerHighlight.end(); i++)
{
QListWidgetItem *item = new QListWidgetItem(m_headerHighlight);
item->setText(i.key());
item->setBackground(i.value());
}
m_keyword = new QLineEdit(this);
m_keyword->setPlaceholderText(tr("FITS keyword"));
QPushButton *color = new QPushButton(this);
QPixmap pix(16, 16);
pix.fill(m_color);
color->setIcon(pix);
connect(color, &QPushButton::clicked, [this, color](){
QColor rgb = QColorDialog::getColor(m_color, this);
if(rgb.isValid())
{
QPixmap pix(16, 16);
pix.fill(rgb);
color->setIcon(pix);
m_color = rgb;
}
});
QPushButton *add = new QPushButton(tr("Add keyword highlight"), this);
connect(add, &QPushButton::clicked, [this](){
auto list = m_headerHighlight->findItems(m_keyword->text(), Qt::MatchFixedString | Qt::MatchCaseSensitive);
if(list.size())return;
QListWidgetItem *item = new QListWidgetItem(m_headerHighlight);
item->setText(m_keyword->text());
item->setBackground(m_color);
});
QPushButton *remove = new QPushButton(tr("Remove keyword highlight"), this);
connect(remove, &QPushButton::clicked, [this](){
auto list = m_headerHighlight->selectedItems();
for(auto item : list)
delete item;
});
layout->addRow(tr("Image preload count"), m_preloadImages);
layout->addRow(tr("Thumbnails size"), m_thumSize);
layout->addRow(tr("Saturation"), m_saturation);
layout->addRow(tr("Slideshow interval"), m_slideShowTime);
layout->addRow(tr("Image interpolation"), m_filtering);
layout->addRow(m_qualityThumbnail);
layout->addRow(m_useNativeDialog);
layout->addRow(m_bestFit);
layout->addRow(new QLabel(tr("FITS header highlight"), this));
layout->addRow(m_headerHighlight);
layout->addRow(m_keyword, color);
layout->addRow(add, remove);
#ifdef Q_OS_WIN64
QPushButton *installThumbnailer = new QPushButton(tr("Install"), this);
installThumbnailer->setToolTip(tr("This will install thumnail generation for FITS and XISF files in File Explorer"));
connect(installThumbnailer, &QPushButton::clicked, this, &SettingsDialog::installThumbnailer);
layout->addRow(tr("Install thumbnailer"), installThumbnailer);
#endif
//layout->addRow(new QLabel(tr("Changes in settings will take effect after program restart.")));
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(this, &QDialog::accepted, this, &SettingsDialog::saveSettings);
layout->addRow(buttonBox);
}
void SettingsDialog::loadSettings()
{
QSettings settings;
THUMB_SIZE = settings.value("settings/thumbnailsize", THUMB_SIZE).toInt();
THUMB_SIZE_BORDER = THUMB_SIZE + 10;
THUMB_SIZE_BORDER_Y = THUMB_SIZE + 30;
DEFAULT_WIDTH = settings.value("settings/preloadimagecount", DEFAULT_WIDTH).toInt();
SATURATION = settings.value("settings/saturation", 95.0).toDouble() / 100.0;
FILTERING = settings.value("settings/filtering", FILTERING).toInt();
QUALITY_RESIZE = settings.value("settings/qualitythumbnail", QUALITY_RESIZE).toBool();
BESTFIT = settings.value("settings/bestfit", BESTFIT).toBool();
QStringList keywords = settings.value("settings/headerhighlightkeywords").toStringList();
QStringList colors = settings.value("settings/headerhighlightcolors").toStringList();
for(int i = 0; i < std::min(keywords.size(), colors.size()); i++)
headerHighlight.insert(keywords[i], QColor::fromString(colors[i]));
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, settings.value("settings/dontusenativedialogs", false).toBool());
}
bool SettingsDialog::loadThumbsizes()
{
QSettings settings;
int OLD_THUMB_SIZE = THUMB_SIZE;
THUMB_SIZE = settings.value("settings/thumbnailsize", THUMB_SIZE).toInt();
THUMB_SIZE_BORDER = THUMB_SIZE + 10;
THUMB_SIZE_BORDER_Y = THUMB_SIZE + 30;
return OLD_THUMB_SIZE != THUMB_SIZE;
}
void SettingsDialog::installThumbnailer()
{
#ifdef Q_OS_WIN64
QString path = QCoreApplication::instance()->applicationDirPath() + "/tenmonthumbnailer.dll";
if(!QFileInfo::exists(path))
{
QMessageBox::critical(this, tr("Missing dll"), tr("Can't find ") + path);
return;
}
QProcess regsvr;
int ret = regsvr.execute("regsvr32.exe", {"/s", path});
if(ret == 0)
QMessageBox::information(this, tr("Thumbnail support"), tr("Thumbnail generation support sucessufully installed."));
else
QMessageBox::critical(this, tr("Error"), tr("Failed to register thumbnailer. %1").arg(ret));
#endif
}
void SettingsDialog::saveSettings()
{
QSettings settings;
settings.setValue("settings/thumbnailsize", m_thumSize->value());
settings.setValue("settings/preloadimagecount", m_preloadImages->value());
settings.setValue("settings/dontusenativedialogs", m_useNativeDialog->isChecked());
settings.setValue("settings/saturation", m_saturation->value());
settings.setValue("settings/slideshowtime", m_slideShowTime->value());
settings.setValue("settings/qualitythumbnail", m_qualityThumbnail->isChecked());
QUALITY_RESIZE = m_qualityThumbnail->isChecked();
FILTERING = m_filtering->currentIndex();
BESTFIT = m_bestFit->isChecked();
settings.setValue("settings/filtering", FILTERING);
settings.setValue("settings/bestfit", BESTFIT);
SATURATION = m_saturation->value() / 100.0;
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, m_useNativeDialog->isChecked());
if(DEFAULT_WIDTH != m_preloadImages->value())
emit preloadChanged(m_preloadImages->value());
headerHighlight.clear();
QStringList colors;
for(int i = 0; i < m_headerHighlight->count(); i++)
{
auto item = m_headerHighlight->item(i);
colors.push_back(item->background().color().name());
headerHighlight[item->text()] = item->background().color();
}
settings.setValue("settings/headerhighlightkeywords", headerHighlight.keys());
settings.setValue("settings/headerhighlightcolors", colors);
}