File indexing completed on 2024-04-28 15:39:08
0001 // SPDX-FileCopyrightText: 2020-2024 Tobias Leupold <tl at stonemx dot de> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 // Local includes 0006 #include "SettingsDialog.h" 0007 #include "Settings.h" 0008 0009 // KDE includes 0010 #include <KLocalizedString> 0011 0012 // Qt includes 0013 #include <QVBoxLayout> 0014 #include <QDialogButtonBox> 0015 #include <QDebug> 0016 #include <QGroupBox> 0017 #include <QGridLayout> 0018 #include <QLabel> 0019 #include <QComboBox> 0020 #include <QSpinBox> 0021 #include <QPushButton> 0022 #include <QColorDialog> 0023 #include <QCheckBox> 0024 #include <QScrollArea> 0025 #include <QScrollBar> 0026 #include <QMessageBox> 0027 #include <QHBoxLayout> 0028 0029 SettingsDialog::SettingsDialog(Settings *settings, QWidget *parent) 0030 : QDialog(parent), 0031 m_settings(settings) 0032 { 0033 setAttribute(Qt::WA_DeleteOnClose, true); 0034 setWindowTitle(i18n("KGeoTag: Settings")); 0035 0036 auto *mainLayout = new QVBoxLayout(this); 0037 0038 // Header 0039 0040 auto *header = new QLabel(i18n("KGeoTag settings")); 0041 header->setStyleSheet(QStringLiteral("QLabel { font-weight: bold; font-size: %1pt; }").arg( 0042 (int) double(header->font().pointSize()) * 1.2)); 0043 header->setAlignment(Qt::AlignCenter); 0044 mainLayout->addWidget(header); 0045 0046 // Settings 0047 0048 setStyleSheet(QStringLiteral("QGroupBox { font-weight: bold; }")); 0049 0050 auto *settingsWidget = new QWidget; 0051 0052 int row; 0053 0054 auto *layout = new QVBoxLayout(settingsWidget); 0055 0056 // Image lists 0057 0058 auto *listsBox = new QGroupBox(i18n("Image lists")); 0059 layout->addWidget(listsBox); 0060 0061 auto *listsBoxLayout = new QVBoxLayout(listsBox); 0062 0063 auto *listsModeLabel = new QLabel(i18n( 0064 "<p>Loaded images can either be listed in two different lists (one for all images without " 0065 "and one for images with coordinates), or using a combined consecutive list for all images." 0066 "</p>" 0067 "<p>Use the following images list(s) mode:</p>")); 0068 listsModeLabel->setWordWrap(true); 0069 listsBoxLayout->addWidget(listsModeLabel); 0070 0071 m_imageListsMode = new QComboBox; 0072 m_imageListsMode->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); 0073 0074 m_imageListsMode->addItem(i18n("Separate \"Assigned\" and \"Unassigned\" list")); 0075 m_imageListsMode->addItem(i18n("One combined list for all images")); 0076 0077 m_imageListsMode->setCurrentIndex(m_settings->splitImagesList() ? 0 : 1); 0078 0079 listsBoxLayout->addWidget(m_imageListsMode); 0080 0081 // Automatic matching 0082 0083 auto *searchMatchesBox = new QGroupBox(i18n("Image Assignment")); 0084 layout->addWidget(searchMatchesBox); 0085 0086 auto *searchMatchesBoxLayout = new QVBoxLayout(searchMatchesBox); 0087 0088 auto *matchModeLabel = new QLabel(i18n("Search type for the main menu \"Assign images to GPS " 0089 "data\" entry")); 0090 matchModeLabel->setWordWrap(true); 0091 searchMatchesBoxLayout->addWidget(matchModeLabel); 0092 0093 m_automaticMatchingMode = new QComboBox; 0094 m_automaticMatchingMode->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); 0095 0096 m_automaticMatchingMode->addItem(i18n("Combined match search"), KGeoTag::CombinedMatchSearch); 0097 m_automaticMatchingMode->addItem(i18n("Search exact matches only"), KGeoTag::ExactMatchSearch); 0098 m_automaticMatchingMode->addItem(i18n("Search interpolated matches only"), 0099 KGeoTag::InterpolatedMatchSearch); 0100 0101 m_automaticMatchingMode->setCurrentIndex( 0102 m_automaticMatchingMode->findData(m_settings->defaultMatchingMode())); 0103 0104 searchMatchesBoxLayout->addWidget(m_automaticMatchingMode); 0105 0106 auto *matchModeNoteLabel = new QLabel(i18n( 0107 "This triggers an automatic (re-)assignment of all images, respecting the \"Exclude " 0108 "manually tagged images\" setting from the \"Automatic assignment\" dock.")); 0109 matchModeNoteLabel->setWordWrap(true); 0110 searchMatchesBoxLayout->addWidget(matchModeNoteLabel); 0111 0112 // Images 0113 0114 auto *imagesBox = new QGroupBox(i18n("Thumbnails and previews")); 0115 auto *imagesBoxLayout = new QVBoxLayout(imagesBox); 0116 layout->addWidget(imagesBox); 0117 0118 auto *sizesLayoutWrapper = new QHBoxLayout; 0119 imagesBoxLayout->addLayout(sizesLayoutWrapper); 0120 auto *sizesLayout = new QGridLayout; 0121 sizesLayoutWrapper->addLayout(sizesLayout); 0122 row = -1; 0123 0124 sizesLayout->addWidget(new QLabel(i18n("Thumbnail size:")), ++row, 0); 0125 m_thumbnailSize = new QSpinBox; 0126 m_thumbnailSize->setMinimum(16); 0127 m_thumbnailSize->setMaximum(512); 0128 m_originalThumbnailSizeValue = m_settings->thumbnailSize(); 0129 m_thumbnailSize->setValue(m_originalThumbnailSizeValue); 0130 sizesLayout->addWidget(m_thumbnailSize, row, 1); 0131 sizesLayout->addWidget(new QLabel(i18n("px")), row, 2); 0132 0133 sizesLayout->addWidget(new QLabel(i18n("Preview size:")), ++row, 0); 0134 m_previewSize = new QSpinBox; 0135 m_previewSize->setMinimum(100); 0136 m_previewSize->setMaximum(1920); 0137 m_originalPreviewSizeValue = m_settings->previewSize(); 0138 m_previewSize->setValue(m_originalPreviewSizeValue); 0139 sizesLayout->addWidget(m_previewSize, row, 1); 0140 sizesLayout->addWidget(new QLabel(i18n("px")), row, 2); 0141 0142 sizesLayoutWrapper->addStretch(); 0143 0144 auto *imagesChangesLabel = new QLabel(i18n("Please restart the program after changes to these " 0145 "values so that they are applied and become " 0146 "visible.")); 0147 imagesChangesLabel->setWordWrap(true); 0148 imagesBoxLayout->addWidget(imagesChangesLabel); 0149 0150 // GPX track rendering 0151 0152 auto *trackBox = new QGroupBox(i18n("GPX track rendering")); 0153 auto *trackBoxLayout = new QHBoxLayout(trackBox); 0154 layout->addWidget(trackBox); 0155 0156 auto *renderingLayout = new QGridLayout; 0157 trackBoxLayout->addLayout(renderingLayout); 0158 row = -1; 0159 0160 renderingLayout->addWidget(new QLabel(i18n("Color:")), ++row, 0); 0161 m_trackColor = new QPushButton; 0162 m_trackColor->setFlat(true); 0163 m_currentTrackColor = m_settings->trackColor(); 0164 connect(m_trackColor, &QPushButton::clicked, this, &SettingsDialog::setTrackColor); 0165 renderingLayout->addWidget(m_trackColor, row, 1); 0166 0167 m_trackOpacity = new QLabel; 0168 renderingLayout->addWidget(m_trackOpacity, row, 2); 0169 0170 updateTrackColor(); 0171 0172 renderingLayout->addWidget(new QLabel(i18n("Line width:")), ++row, 0); 0173 m_trackWidth = new QSpinBox; 0174 m_trackWidth->setMinimum(1); 0175 m_trackWidth->setMaximum(50); 0176 m_trackWidth->setValue(m_settings->trackWidth()); 0177 renderingLayout->addWidget(m_trackWidth, row, 1); 0178 0179 renderingLayout->addWidget(new QLabel(i18n("Line style:")), ++row, 0); 0180 m_trackStyle = new QComboBox; 0181 m_trackStyle->addItem(i18n("Solid"), static_cast<int>(Qt::SolidLine)); 0182 m_trackStyle->addItem(i18n("Dashes"), static_cast<int>(Qt::DashLine)); 0183 m_trackStyle->addItem(i18n("Dots"), static_cast<int>(Qt::DotLine)); 0184 m_trackStyle->addItem(i18n("Dash-Dot"), static_cast<int>(Qt::DashDotLine)); 0185 m_trackStyle->addItem(i18n("Dash-Dot-Dot"), static_cast<int>(Qt::DashDotDotLine)); 0186 m_trackStyle->setCurrentIndex( 0187 m_trackStyle->findData(static_cast<int>(m_settings->trackStyle()))); 0188 renderingLayout->addWidget(m_trackStyle, row, 1); 0189 0190 trackBoxLayout->addStretch(); 0191 0192 // Elevation lookup 0193 0194 auto *elevationBox = new QGroupBox(i18n("Elevation lookup")); 0195 auto *elevationBoxLayout = new QVBoxLayout(elevationBox); 0196 layout->addWidget(elevationBox); 0197 0198 auto *lookupLabel = new QLabel(i18n("Elevations can be looked up using opentopodata.org's web " 0199 "API.")); 0200 lookupLabel->setWordWrap(true); 0201 elevationBoxLayout->addWidget(lookupLabel); 0202 0203 auto *datasetLayout = new QHBoxLayout; 0204 elevationBoxLayout->addLayout(datasetLayout); 0205 0206 datasetLayout->addWidget(new QLabel(i18n("Elevation dataset:"))); 0207 0208 m_elevationDataset = new QComboBox; 0209 0210 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "ASTER"), 0211 QStringLiteral("aster30m")); 0212 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "ETOPO1"), 0213 QStringLiteral("etopo1")); 0214 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "EU-DEM"), 0215 QStringLiteral("eudem25m")); 0216 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "Mapzen"), 0217 QStringLiteral("mapzen")); 0218 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "NED"), 0219 QStringLiteral("ned10m")); 0220 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "NZ DEM"), 0221 QStringLiteral("nzdem8m")); 0222 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "SRTM (30 m)"), 0223 QStringLiteral("srtm30m")); 0224 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", "SRTM (90 m)"), 0225 QStringLiteral("srtm90m")); 0226 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", 0227 "EMODnet 2018 Bathymetry"), 0228 QStringLiteral("emod2018")); 0229 m_elevationDataset->addItem(i18nc("opentopodata.org elevation dataset", 0230 "GEBCO 2020 Bathymetry"), 0231 QStringLiteral("gebco2020")); 0232 0233 m_elevationDataset->setCurrentIndex( 0234 m_elevationDataset->findData(m_settings->elevationDataset())); 0235 0236 datasetLayout->addWidget(m_elevationDataset); 0237 0238 datasetLayout->addStretch(); 0239 0240 auto *datasetInfoLabel = new QLabel(i18n("Cf. <a href=\"https://www.opentopodata.org/\">" 0241 "https://www.opentopodata.org/</a> for further " 0242 "information about the available datasets, like the " 0243 "respective coverage!")); 0244 datasetInfoLabel->setWordWrap(true); 0245 datasetInfoLabel->setOpenExternalLinks(true); 0246 elevationBoxLayout->addWidget(datasetInfoLabel); 0247 0248 m_lookupElevationAutomatically = new QCheckBox(i18n("Request and set altitudes automatically")); 0249 m_lookupElevationAutomatically->setChecked(m_settings->lookupElevationAutomatically()); 0250 elevationBoxLayout->addWidget(m_lookupElevationAutomatically); 0251 0252 // Data saving 0253 0254 auto *saveBox = new QGroupBox(i18n("Saving")); 0255 auto *saveBoxLayout = new QVBoxLayout(saveBox); 0256 layout->addWidget(saveBox); 0257 0258 auto *saveTargetLayout = new QHBoxLayout; 0259 saveBoxLayout->addLayout(saveTargetLayout); 0260 0261 saveTargetLayout->addWidget(new QLabel(i18n("Write changes to:"))); 0262 0263 m_writeMode = new QComboBox; 0264 0265 m_writeMode->addItem(i18n("Exif header"), 0266 QStringLiteral("WRITETOIMAGEONLY")); 0267 m_writeMode->addItem(i18n("XMP sidecar file"), 0268 QStringLiteral("WRITETOSIDECARONLY")); 0269 m_writeMode->addItem(i18n("Exif header and XMP sidecar file"), 0270 QStringLiteral("WRITETOSIDECARANDIMAGE")); 0271 0272 m_writeMode->setCurrentIndex(m_writeMode->findData(m_settings->writeMode())); 0273 0274 saveTargetLayout->addWidget(m_writeMode); 0275 0276 saveTargetLayout->addStretch(); 0277 0278 m_allowWriteRawFiles = new QCheckBox(i18n("Allow altering Exif headers of RAW images")); 0279 m_allowWriteRawFiles->setChecked(m_settings->allowWriteRawFiles()); 0280 saveBoxLayout->addWidget(m_allowWriteRawFiles); 0281 0282 auto *label = new QLabel(i18n( 0283 "<b>Caution!</b> This is experimental. By default, regardless of the setting for \"Write " 0284 "changes to\", all changes to RAW images are written to XMP sidecar files. Have backups " 0285 "and check your Exif data to be still complete and correct when using this!" 0286 )); 0287 label->setWordWrap(true); 0288 label->setIndent(30); 0289 saveBoxLayout->addWidget(label); 0290 0291 m_createBackups = new QCheckBox(i18n("Create a backup before altering a file")); 0292 m_createBackups->setChecked(m_settings->createBackups()); 0293 saveBoxLayout->addWidget(m_createBackups); 0294 0295 // Scroll area 0296 0297 auto *scrollArea = new QScrollArea; 0298 scrollArea->setWidgetResizable(true); 0299 const int styleAddition = scrollArea->width() - scrollArea->viewport()->width(); 0300 scrollArea->setWidget(settingsWidget); 0301 mainLayout->addWidget(scrollArea); 0302 0303 show(); 0304 const int widgetWidth = settingsWidget->width() + scrollArea->verticalScrollBar()->width() 0305 + styleAddition; 0306 scrollArea->setMinimumWidth(widgetWidth); 0307 0308 // Button box 0309 0310 auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Close); 0311 connect(buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::accept); 0312 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0313 mainLayout->addWidget(buttonBox); 0314 } 0315 0316 void SettingsDialog::updateTrackColor() 0317 { 0318 m_trackColor->setStyleSheet(QStringLiteral("border: none; background-color: %1;").arg( 0319 m_currentTrackColor.name())); 0320 m_trackOpacity->setText(i18n("Opacity: %1%", int(m_currentTrackColor.alphaF() * 100.0))); 0321 } 0322 0323 void SettingsDialog::setTrackColor() 0324 { 0325 QColorDialog dialog(m_currentTrackColor); 0326 dialog.setOption(QColorDialog::ShowAlphaChannel, true); 0327 0328 if (! dialog.exec()) { 0329 return; 0330 } 0331 0332 m_currentTrackColor = dialog.currentColor(); 0333 updateTrackColor(); 0334 } 0335 0336 void SettingsDialog::accept() 0337 { 0338 const auto splitImagesList = m_imageListsMode->currentIndex() == 0; 0339 m_settings->saveSplitImagesList(splitImagesList); 0340 0341 m_settings->saveDefaultMatchingMode(static_cast<KGeoTag::SearchType>( 0342 m_automaticMatchingMode->currentData().toInt())); 0343 0344 const auto thumbnailSize = m_thumbnailSize->value(); 0345 m_settings->saveThumbnailSize(thumbnailSize); 0346 const auto previewSize = m_previewSize->value(); 0347 m_settings->savePreviewSize(previewSize); 0348 0349 m_settings->saveTrackColor(m_currentTrackColor); 0350 m_settings->saveTrackWidth(m_trackWidth->value()); 0351 m_settings->saveTrackStyle(static_cast<Qt::PenStyle>(m_trackStyle->currentData().toInt())); 0352 0353 m_settings->saveLookupElevationAutomatically(m_lookupElevationAutomatically->isChecked()); 0354 m_settings->saveElevationDataset(m_elevationDataset->currentData().toString()); 0355 0356 m_settings->saveWriteMode(m_writeMode->currentData().toString()); 0357 m_settings->saveAllowWriteRawFiles(m_allowWriteRawFiles->isChecked()); 0358 m_settings->saveCreateBackups(m_createBackups->isChecked()); 0359 0360 if ( thumbnailSize != m_originalThumbnailSizeValue 0361 || previewSize != m_originalPreviewSizeValue) { 0362 0363 QMessageBox::information(this, i18n("Settings changed"), 0364 i18n("Please restart KGeoTag to apply the changed settings and make them visible!")); 0365 } 0366 0367 if (splitImagesList != m_originalSplitImagesListValue) { 0368 Q_EMIT imagesListsModeChanged(); 0369 } 0370 0371 QDialog::accept(); 0372 }