diff --git a/Settings/FileVersionDetectionPage.cpp b/Settings/FileVersionDetectionPage.cpp index a2ba5a17..06e5c5ff 100644 --- a/Settings/FileVersionDetectionPage.cpp +++ b/Settings/FileVersionDetectionPage.cpp @@ -1,322 +1,333 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "FileVersionDetectionPage.h" #include "SettingsData.h" #include #include #include #include #include #include #include #include Settings::FileVersionDetectionPage::FileVersionDetectionPage(QWidget *parent) : QWidget(parent) { QVBoxLayout *topLayout = new QVBoxLayout(this); QString txt; // General file searching { QGroupBox *generalBox = new QGroupBox(i18n("New File Searches"), this); topLayout->addWidget(generalBox); QVBoxLayout *layout = new QVBoxLayout(generalBox); // Search for images on startup m_searchForImagesOnStart = new QCheckBox(i18n("Search for new images and videos on startup"), generalBox); layout->addWidget(m_searchForImagesOnStart); m_ignoreFileExtension = new QCheckBox(i18n("Ignore file extensions when searching for new images and videos"), generalBox); layout->addWidget(m_ignoreFileExtension); m_skipSymlinks = new QCheckBox(i18n("Skip symbolic links when searching for new images"), generalBox); layout->addWidget(m_skipSymlinks); m_skipRawIfOtherMatches = new QCheckBox(i18n("Do not read RAW files if a matching JPEG/TIFF file exists"), generalBox); layout->addWidget(m_skipRawIfOtherMatches); // Exclude directories from search QLabel *excludeDirectoriesLabel = new QLabel(i18n("Directories to exclude from new file search:"), generalBox); layout->addWidget(excludeDirectoriesLabel); m_excludeDirectories = new QLineEdit(generalBox); layout->addWidget(m_excludeDirectories); excludeDirectoriesLabel->setBuddy(m_excludeDirectories); txt = i18n("

KPhotoAlbum is capable of searching for new images and videos when started, this does, " "however, take some time, so instead you may wish to manually tell KPhotoAlbum to search for new images " "using Maintenance->Rescan for new images

"); m_searchForImagesOnStart->setWhatsThis(txt); txt = i18n("

KPhotoAlbum will normally search new images and videos by their file extension. " "If this option is set, all files neither in the database nor in the block list " "will be checked by their Mime type, regardless of their extension. This will take " "significantly longer than finding files by extension!

"); m_ignoreFileExtension->setWhatsThis(txt); txt = i18n("

KPhotoAlbum attempts to read all image files whether actual files or symbolic links. If you " "wish to ignore symbolic links, check this option. This is useful if for some reason you have e.g. " "both the original files and symbolic links to these files within your image directory.

"); m_skipSymlinks->setWhatsThis(txt); txt = i18n("

KPhotoAlbum is capable of reading certain kinds of RAW images. " "Some cameras store both a RAW image and a matching JPEG or TIFF image. " "This causes duplicate images to be stored in KPhotoAlbum, which may be undesirable. " "If this option is checked, KPhotoAlbum will not read RAW files for which matching image files also exist.

"); m_skipRawIfOtherMatches->setWhatsThis(txt); txt = i18n("

Directories defined here (separated by comma ,) are " "skipped when searching for new photos. Thumbnail directories of different " "tools should be configured here. E.g. xml,ThumbNails,.thumbs,.thumbnails.

"); excludeDirectoriesLabel->setWhatsThis(txt); } // Original/Modified File Support { QGroupBox *modifiedBox = new QGroupBox(i18n("File Version Detection Settings"), this); topLayout->addWidget(modifiedBox); QVBoxLayout *layout = new QVBoxLayout(modifiedBox); m_detectModifiedFiles = new QCheckBox(i18n("Try to detect multiple versions of files"), modifiedBox); layout->addWidget(m_detectModifiedFiles); QLabel *modifiedFileComponentLabel = new QLabel(i18n("File versions search regexp:"), modifiedBox); layout->addWidget(modifiedFileComponentLabel); m_modifiedFileComponent = new QLineEdit(modifiedBox); layout->addWidget(m_modifiedFileComponent); QLabel *originalFileComponentLabel = new QLabel(i18n("Original file replacement text:"), modifiedBox); layout->addWidget(originalFileComponentLabel); m_originalFileComponent = new QLineEdit(modifiedBox); layout->addWidget(m_originalFileComponent); m_moveOriginalContents = new QCheckBox(i18n("Move meta-data (i.e. delete tags from the original)"), modifiedBox); layout->addWidget(m_moveOriginalContents); m_autoStackNewFiles = new QCheckBox(i18n("Automatically stack new versions of images"), modifiedBox); layout->addWidget(m_autoStackNewFiles); txt = i18n("

When KPhotoAlbum searches for new files and finds a file that matches the " "modified file search regexp it is assumed that an original version of " "the image may exist. The regexp pattern will be replaced with the original " "file replacement text and if that file exists, all associated metadata (category " "information, ratings, etc) will be copied or moved from the original file to the new one.

"); m_detectModifiedFiles->setWhatsThis(txt); txt = i18n("

A perl regular expression that should match a modified file. " "

  • A dot matches a single character (\\. matches a dot)
  • " "
  • You can use the quantifiers *,+,?, or you can " " match multiple occurrences of an expression by using curly brackets (e.g. " "e{0,1} matches 0 or 1 occurrences of the character \"e\").
  • " "
  • You can group parts of the expression using parenthesis.
  • " "
Example: -modified\\.(jpg|tiff)

"); modifiedFileComponentLabel->setWhatsThis(txt); m_modifiedFileComponent->setWhatsThis(txt); txt = i18n("

A string that is used to replace the match from the File versions search regexp. " "This can be a semicolon (;) separated list. Each string is used to replace the match " "in the new file's name until an original file is found or we run out of options.

"); originalFileComponentLabel->setWhatsThis(txt); m_originalFileComponent->setWhatsThis(txt); txt = i18n("

The tagging is moved from the original file to the new file. This way " "only the latest version of an image is tagged.

"); m_moveOriginalContents->setWhatsThis(txt); txt = i18n("

If this option is set, new versions of an image are automatically stacked " "and placed to the top of the stack. This way the new image is shown when the " "stack is in collapsed state - the default state in KPhotoAlbum.

"); m_autoStackNewFiles->setWhatsThis(txt); } // Copy File Support { QGroupBox *copyBox = new QGroupBox(i18nc("Configure the feature to make a copy of a file first and then open the copied file with an external application", "Copy File and Open with an External Application"), this); topLayout->addWidget(copyBox); QVBoxLayout *layout = new QVBoxLayout(copyBox); QLabel *copyFileComponentLabel = new QLabel(i18n("Copy file search regexp:"), copyBox); layout->addWidget(copyFileComponentLabel); m_copyFileComponent = new QLineEdit(copyBox); layout->addWidget(m_copyFileComponent); QLabel *copyFileReplacementComponentLabel = new QLabel(i18n("Copy file replacement text:"), copyBox); layout->addWidget(copyFileReplacementComponentLabel); m_copyFileReplacementComponent = new QLineEdit(copyBox); layout->addWidget(m_copyFileReplacementComponent); txt = i18n("

KPhotoAlbum can make a copy of an image before opening it with an external application. This configuration defines how the new file is named.

" "

The regular expression defines the part of the original file name that is replaced with the replacement text. " "E.g. regexp \"\\.(jpg|png)\" and replacement text \"-mod.\\1\" would copy test.jpg to test-mod.jpg and open the new file in selected application.

"); copyFileComponentLabel->setWhatsThis(txt); m_copyFileComponent->setWhatsThis(txt); copyFileReplacementComponentLabel->setWhatsThis(txt); m_copyFileReplacementComponent->setWhatsThis(txt); } // Loader Optimization Setting (prototype) { QGroupBox *loadOptimizationBox = new QGroupBox(i18n("EXPERIMENTAL: Tune new image loading for best performance."), this); topLayout->addWidget(loadOptimizationBox); QGridLayout *layout = new QGridLayout(loadOptimizationBox); int row = 0; // Loader preset QLabel *loadOptimizationPresetLabel = new QLabel(i18n("Type of media on which your images are stored.")); layout->addWidget(loadOptimizationPresetLabel, row, 0); layout->setColumnStretch(0, 1); m_loadOptimizationPreset = new KComboBox; m_loadOptimizationPreset->addItems(QStringList() << i18n("Hard Disk") - << i18n("Network") - << i18n("SATA SSD") - << i18n("Slow PCIe/NVMe") - << i18n("Fast PCIe/NVMe") - << i18n("Manual Settings")); + << i18n("Network") + << i18n("SATA SSD") + << i18n("Slow PCIe/NVMe") + << i18n("Fast PCIe/NVMe") + << i18n("Manual Settings")); // manual is expected to be the last item layout->addWidget(m_loadOptimizationPreset, row, 1); txt = i18n("

Tune image loading for best performance based on the type of storage your image database resides on. If your image database resides on multiple media, choose the slowet media type used.

" "

Use Manual Settings to configure details of how the loading is performed.

"); loadOptimizationPresetLabel->setWhatsThis(txt); m_loadOptimizationPreset->setWhatsThis(txt); + connect(m_loadOptimizationPreset, QOverload::of(&QComboBox::activated), this, &FileVersionDetectionPage::slotUpdateOptimizationUI); // Overlap load with MD5 computation ++row; QLabel *overlapLoadMD5Label = new QLabel(i18n("Calculate MD5 checksum while images are being preloaded")); layout->addWidget(overlapLoadMD5Label, row, 0); m_overlapLoadMD5 = new QCheckBox; layout->addWidget(m_overlapLoadMD5, row, 1); txt = i18n("

Calculate MD5 checksums while images are being preloaded. This works well if the storage is very fast, such as an NVMe drive. If the storage is slow, this degrades performance as the checksum calculation has to wait longer for the images to be preloaded.

"); overlapLoadMD5Label->setWhatsThis(txt); m_overlapLoadMD5->setWhatsThis(txt); // Threads for preload ++row; QLabel *preloadThreadCountLabel = new QLabel(i18n("Number of threads to use for preloading (scouting) images")); layout->addWidget(preloadThreadCountLabel, row, 0); m_preloadThreadCount = new QSpinBox; m_preloadThreadCount->setRange(1, 16); m_preloadThreadCount->setSingleStep(1); layout->addWidget(m_preloadThreadCount, row, 1); txt = i18n("

Number of threads to use for preloading images to have them in memory when their checksums are calculated. This should generally be set higher for faster storage, but not more than the number of cores in your CPU.<. Default is 1, which works well for mechanical hard disks./p>"); preloadThreadCountLabel->setWhatsThis(txt); m_preloadThreadCount->setWhatsThis(txt); // Threads for thumbnailPreload ++row; QLabel *thumbnailPreloadThreadCountLabel = new QLabel(i18n("Number of threads to use for thumbnailPreloading (scouting) images")); layout->addWidget(thumbnailPreloadThreadCountLabel, row, 0); m_thumbnailPreloadThreadCount = new QSpinBox; m_thumbnailPreloadThreadCount->setRange(1, 16); m_thumbnailPreloadThreadCount->setSingleStep(1); layout->addWidget(m_thumbnailPreloadThreadCount, row, 1); txt = i18n("

Number of threads to use for preloading images prior to building thumbnails. Normally this should be set to 1; the exception might be if you have very fast storage.

"); thumbnailPreloadThreadCountLabel->setWhatsThis(txt); m_thumbnailPreloadThreadCount->setWhatsThis(txt); // Threads for thumbnailBuilder ++row; QLabel *thumbnailBuilderThreadCountLabel = new QLabel(i18n("Number of threads to use for building thumbnails")); layout->addWidget(thumbnailBuilderThreadCountLabel, row, 0); m_thumbnailBuilderThreadCount = new QSpinBox(loadOptimizationBox); m_thumbnailBuilderThreadCount->setRange(0, 16); m_thumbnailBuilderThreadCount->setSingleStep(1); layout->addWidget(m_thumbnailBuilderThreadCount, row, 1); txt = i18n("

Number of threads to use for building thumbnails. If set to 0 this will be set automatically one less than the number of cores, at least one and no more than three. If you have fast storage and a CPU with many cores, you may see benefit from setting this to a larger value.

" "

KPhotoAlbum must be restarted for changes to take effect.

"); thumbnailBuilderThreadCountLabel->setWhatsThis(txt); m_thumbnailBuilderThreadCount->setWhatsThis(txt); } } Settings::FileVersionDetectionPage::~FileVersionDetectionPage() { delete m_searchForImagesOnStart; delete m_ignoreFileExtension; delete m_skipSymlinks; delete m_skipRawIfOtherMatches; delete m_excludeDirectories; delete m_detectModifiedFiles; delete m_modifiedFileComponent; delete m_originalFileComponent; delete m_moveOriginalContents; delete m_autoStackNewFiles; delete m_copyFileComponent; delete m_copyFileReplacementComponent; delete m_loadOptimizationPreset; delete m_overlapLoadMD5; delete m_preloadThreadCount; delete m_thumbnailPreloadThreadCount; delete m_thumbnailBuilderThreadCount; } void Settings::FileVersionDetectionPage::loadSettings(Settings::SettingsData *opt) { m_searchForImagesOnStart->setChecked(opt->searchForImagesOnStart()); m_ignoreFileExtension->setChecked(opt->ignoreFileExtension()); m_skipSymlinks->setChecked(opt->skipSymlinks()); m_skipRawIfOtherMatches->setChecked(opt->skipRawIfOtherMatches()); m_excludeDirectories->setText(opt->excludeDirectories()); m_detectModifiedFiles->setChecked(opt->detectModifiedFiles()); m_modifiedFileComponent->setText(opt->modifiedFileComponent()); m_originalFileComponent->setText(opt->originalFileComponent()); m_moveOriginalContents->setChecked(opt->moveOriginalContents()); m_autoStackNewFiles->setChecked(opt->autoStackNewFiles()); m_copyFileComponent->setText(opt->copyFileComponent()); m_copyFileReplacementComponent->setText(opt->copyFileReplacementComponent()); m_loadOptimizationPreset->setCurrentIndex(opt->loadOptimizationPreset()); m_overlapLoadMD5->setChecked(opt->overlapLoadMD5()); m_preloadThreadCount->setValue(opt->preloadThreadCount()); m_thumbnailPreloadThreadCount->setValue(opt->thumbnailPreloadThreadCount()); m_thumbnailBuilderThreadCount->setValue(opt->thumbnailBuilderThreadCount()); + slotUpdateOptimizationUI(); } void Settings::FileVersionDetectionPage::saveSettings(Settings::SettingsData *opt) { opt->setSearchForImagesOnStart(m_searchForImagesOnStart->isChecked()); opt->setIgnoreFileExtension(m_ignoreFileExtension->isChecked()); opt->setSkipSymlinks(m_skipSymlinks->isChecked()); opt->setSkipRawIfOtherMatches(m_skipRawIfOtherMatches->isChecked()); opt->setExcludeDirectories(m_excludeDirectories->text()); opt->setDetectModifiedFiles(m_detectModifiedFiles->isChecked()); opt->setModifiedFileComponent(m_modifiedFileComponent->text()); opt->setOriginalFileComponent(m_originalFileComponent->text()); opt->setAutoStackNewFiles(m_autoStackNewFiles->isChecked()); opt->setCopyFileComponent(m_copyFileComponent->text()); opt->setCopyFileReplacementComponent(m_copyFileReplacementComponent->text()); opt->setLoadOptimizationPreset(m_loadOptimizationPreset->currentIndex()); opt->setOverlapLoadMD5(m_overlapLoadMD5->isChecked()); opt->setPreloadThreadCount(m_preloadThreadCount->value()); opt->setThumbnailPreloadThreadCount(m_thumbnailPreloadThreadCount->value()); opt->setThumbnailBuilderThreadCount(m_thumbnailBuilderThreadCount->value()); } + +void Settings::FileVersionDetectionPage::slotUpdateOptimizationUI() +{ + const bool manualModeIsSelected = (m_loadOptimizationPreset->currentIndex() + 1 == m_loadOptimizationPreset->count()); + m_overlapLoadMD5->setEnabled(manualModeIsSelected); + m_preloadThreadCount->setEnabled(manualModeIsSelected); + m_thumbnailPreloadThreadCount->setEnabled(manualModeIsSelected); + m_thumbnailBuilderThreadCount->setEnabled(manualModeIsSelected); +} // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/Settings/FileVersionDetectionPage.h b/Settings/FileVersionDetectionPage.h index c414c3f0..3480b58d 100644 --- a/Settings/FileVersionDetectionPage.h +++ b/Settings/FileVersionDetectionPage.h @@ -1,63 +1,70 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef FILEVERSIONDETECTIONPAGE_H #define FILEVERSIONDETECTIONPAGE_H #include class KComboBox; class QLineEdit; class QSpinBox; class QComboBox; class QCheckBox; namespace Settings { class SettingsData; class FileVersionDetectionPage : public QWidget { public: explicit FileVersionDetectionPage(QWidget *parent); ~FileVersionDetectionPage() override; void loadSettings(Settings::SettingsData *); void saveSettings(Settings::SettingsData *); +private slots: + /** + * @brief Enable/disable UI elements for manual optimization settings based on + * the active m_loadOptimizationPreset combobox value. + */ + void slotUpdateOptimizationUI(); + private: QCheckBox *m_searchForImagesOnStart; QCheckBox *m_ignoreFileExtension; QCheckBox *m_skipSymlinks; QCheckBox *m_skipRawIfOtherMatches; QLineEdit *m_excludeDirectories; // Directories to exclude QCheckBox *m_detectModifiedFiles; QLineEdit *m_modifiedFileComponent; QLineEdit *m_originalFileComponent; QCheckBox *m_moveOriginalContents; QCheckBox *m_autoStackNewFiles; QLineEdit *m_copyFileComponent; QLineEdit *m_copyFileReplacementComponent; KComboBox *m_loadOptimizationPreset; QCheckBox *m_overlapLoadMD5; - QSpinBox *m_preloadThreadCount; - QSpinBox *m_thumbnailPreloadThreadCount; - QSpinBox *m_thumbnailBuilderThreadCount; + QSpinBox *m_preloadThreadCount; + QSpinBox *m_thumbnailPreloadThreadCount; + QSpinBox *m_thumbnailBuilderThreadCount; }; } #endif /* FILEVERSIONDETECTIONPAGE_H */ // vi:expandtab:tabstop=4 shiftwidth=4: