Merge pull request #6769 from Lawrence37/browse-subfolder

Recursive image browsing
This commit is contained in:
Lawrence37
2024-03-24 12:02:21 -07:00
committed by GitHub
8 changed files with 305 additions and 50 deletions

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="24px"
height="24px"
viewBox="0 0 24 24"
version="1.1"
id="SVGRoot"
inkscape:export-filename="/tmp/template.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="folder-subfolder.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<sodipodi:namedview
id="base"
pagecolor="#E0E1E2"
bordercolor="#666768"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="27.559042"
inkscape:cx="11.067148"
inkscape:cy="11.212291"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1920"
inkscape:window-height="1041"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true"
inkscape:pagecheckerboard="false"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-others="false"
inkscape:object-nodes="true"
inkscape:snap-grids="false"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-intersection-paths="true"
inkscape:object-paths="true"
inkscape:showpageshadow="2"
inkscape:deskcolor="#E0E1E2">
<inkscape:grid
type="xygrid"
id="grid1374"
originx="1"
originy="1"
empspacing="11"
dotted="false"
spacingx="1"
spacingy="1"
visible="true" />
</sodipodi:namedview>
<defs
id="defs815" />
<metadata
id="metadata818">
<rdf:RDF />
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.5;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 8.3845376,8 C 8.094003,8 7.7740668,8.0155229 7.4612704,8.2668157 7.148474,8.5181086 7.055613,8.9356452 7.0631644,9.2267877 V 19.533781 c -8.84e-5,0.199356 0.082156,0.389899 0.2272874,0.526573 0.2698504,0.283712 0.5071187,0.520303 0.7905739,0.765991 -0.086082,-0.07558 -0.2899772,-0.262658 -0.2400017,-0.577429 l 1.5331317,-7.333295 c 0.061673,-0.345222 0.3622328,-0.596383 0.7129203,-0.595747 h 10.693806 v -2.030059 l -0.0014,0.0056 c 0.0021,-0.28168 -0.08163,-0.6906547 -0.395249,-0.9458534 C 20.070572,9.094409 19.749426,9.0799684 19.458096,9.0799684 H 12.80182 L 12.450301,8.4785743 C 12.405002,8.4009886 12.345637,8.332527 12.275248,8.2766978 12.119431,8.1534118 11.88987,8 11.527034,8 Z"
id="path1026"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscccccccccccscccss" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.9;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.85216;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 10.087076,12.319875 C 9.7363885,12.319329 9.4358285,12.53473 9.3741557,12.830801 L 7.841024,20.248916 c -0.07805,0.379479 0.2622,0.727446 0.7115087,0.727646 H 20.824645 c 0.350155,-4.1e-5 0.649929,-0.215306 0.711508,-0.510926 l 1.534544,-7.418115 c 0.07815,-0.379963 -0.263039,-0.728199 -0.71292,-0.727646 z"
id="rect1030"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<g
id="g1729"
style="opacity:0.5">
<path
style="fill:none;stroke:#cccccc;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="M 2,3 V 19 H 5"
id="path1712" />
<path
style="fill:none;stroke:#cccccc;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 2,3 v 8 h 3"
id="path1714" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -203,6 +203,7 @@ FILEBROWSER_SHOWRANK4HINT;Show images ranked as 4-star.\nShortcut: <b>Shift-4</b
FILEBROWSER_SHOWRANK5HINT;Show images ranked as 5-star.\nShortcut: <b>Shift-5</b>
FILEBROWSER_SHOWRECENTLYSAVEDHINT;Show saved images.\nShortcut: <b>Alt-7</b>
FILEBROWSER_SHOWRECENTLYSAVEDNOTHINT;Show unsaved images.\nShortcut: <b>Alt-6</b>
FILEBROWSER_SHOWRECURSIVE;Show images in sub-folders recursively.
FILEBROWSER_SHOWTRASHHINT;Show contents of trash.\nShortcut: <b>Ctrl-t</b>
FILEBROWSER_SHOWUNCOLORHINT;Show images without a color label.\nShortcut: <b>Alt-0</b>
FILEBROWSER_SHOWUNRANKHINT;Show unranked images.\nShortcut: <b>Shift-0</b>
@@ -1844,6 +1845,9 @@ PREFERENCES_BEHADDALLHINT;Set all parameters to the <b>Add</b> mode.\nAdjustment
PREFERENCES_BEHAVIOR;Behavior
PREFERENCES_BEHSETALL;All to 'Set'
PREFERENCES_BEHSETALLHINT;Set all parameters to the <b>Set</b> mode.\nAdjustments of parameters in the batch tool panel will be <b>absolute</b>, the actual values will be displayed.
PREFERENCES_BROWSERECURSIVEDEPTH;Browse sub-folders depth
PREFERENCES_BROWSERECURSIVEFOLLOWLINKS;Follow symbolic links when browsing sub-folders
PREFERENCES_BROWSERECURSIVEMAXDIRS;Maximum sub-folders
PREFERENCES_CACHECLEAR;Clear
PREFERENCES_CACHECLEAR_ALL;Clear all cached files:
PREFERENCES_CACHECLEAR_ALLBUTPROFILES;Clear all cached files except for cached processing profiles:

View File

@@ -19,6 +19,8 @@
*/
#include "filecatalog.h"
#include <algorithm>
#include <iterator>
#include <iostream>
#include <iomanip>
@@ -347,9 +349,17 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) :
bCateg[19] = bOriginal->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bOriginal, true));
bOriginal->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event), false);
bRecursive = Gtk::manage(new Gtk::ToggleButton());
bRecursive->set_image(*Gtk::manage(new RTImage("folder-subfolder", Gtk::ICON_SIZE_LARGE_TOOLBAR)));
bRecursive->set_tooltip_text(M("FILEBROWSER_SHOWRECURSIVE"));
bRecursive->set_relief(Gtk::RELIEF_NONE);
bRecursive->set_active(options.browseRecursive);
bRecursive->signal_toggled().connect(sigc::mem_fun(*this, &FileCatalog::showRecursiveToggled));
buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK);
buttonBar->pack_start (*bNotTrash, Gtk::PACK_SHRINK);
buttonBar->pack_start (*bOriginal, Gtk::PACK_SHRINK);
buttonBar->pack_start(*bRecursive, Gtk::PACK_SHRINK);
buttonBar->pack_start (*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)), Gtk::PACK_SHRINK);
fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) );
@@ -541,9 +551,7 @@ void FileCatalog::closeDir ()
exportPanel->set_sensitive (false);
}
if (dirMonitor) {
dirMonitor->cancel ();
}
dirMonitors.clear();
// ignore old requests
++selectedDirectoryId;
@@ -567,18 +575,32 @@ void FileCatalog::closeDir ()
redrawAll ();
}
std::vector<Glib::ustring> FileCatalog::getFileList()
std::vector<Glib::ustring> FileCatalog::getFileList(std::vector<Glib::RefPtr<Gio::File>> *dirs_explored)
{
std::vector<Glib::ustring> names;
const std::set<std::string>& extensions = options.parsedExtensionsSet;
static void (*getFilesRecursively)(const Glib::ustring &, int, int &, std::vector<Glib::ustring> &, std::vector<Glib::RefPtr<Gio::File>> *) = [](const Glib::ustring &dir_path, int max_depth, int &dir_quota, std::vector<Glib::ustring> &file_names, std::vector<Glib::RefPtr<Gio::File>> * directories_explored) {
try {
const auto dir = Gio::File::create_for_path(selectedDirectory);
const auto dir = Gio::File::create_for_path(dir_path);
auto enumerator = dir->enumerate_children("standard::name,standard::type,standard::is-hidden");
static const auto enumerate_attrs =
std::string(G_FILE_ATTRIBUTE_STANDARD_NAME) + "," +
G_FILE_ATTRIBUTE_STANDARD_TYPE + "," +
G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN + "," +
G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET;
auto enumerator = dir->enumerate_children(
enumerate_attrs,
options.browseRecursiveFollowLinks
? Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NONE
: Gio::FileQueryInfoFlags::FILE_QUERY_INFO_NOFOLLOW_SYMLINKS);
if (directories_explored) {
directories_explored->push_back(dir);
}
while (true) {
try {
@@ -587,11 +609,15 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
break;
}
if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
if (!options.fbShowHidden && file->is_hidden()) {
continue;
}
if (!options.fbShowHidden && file->is_hidden()) {
if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
if (max_depth > 0 && dir_quota > 0) {
const Glib::ustring child_dir_path = Glib::build_filename(dir_path, file->get_name());
getFilesRecursively(child_dir_path, max_depth - 1, --dir_quota, file_names, directories_explored);
}
continue;
}
@@ -606,7 +632,7 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
continue;
}
names.push_back(Glib::build_filename(selectedDirectory, fname));
file_names.emplace_back(Glib::build_filename(dir_path, fname));
} catch (Glib::Exception& exception) {
if (rtengine::settings->verbose) {
std::cerr << exception.what() << std::endl;
@@ -617,10 +643,14 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
} catch (Glib::Exception& exception) {
if (rtengine::settings->verbose) {
std::cerr << "Failed to list directory \"" << selectedDirectory << "\": " << exception.what() << std::endl;
std::cerr << "Failed to list directory \"" << dir_path << "\": " << exception.what() << std::endl;
}
}
};
int dirs_left = options.browseRecursive ? options.browseRecursiveMaxDirs : 0;
getFilesRecursively(selectedDirectory, options.browseRecursiveDepth, dirs_left, names, dirs_explored);
return names;
}
@@ -646,9 +676,10 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring
selectedDirectory = dir->get_parse_name();
std::vector<Glib::RefPtr<Gio::File>> allDirs;
BrowsePath->set_text(selectedDirectory);
buttonBrowsePath->set_image(*iRefreshWhite);
fileNameList = getFileList();
fileNameList = getFileList(&allDirs);
for (unsigned int i = 0; i < fileNameList.size(); i++) {
if (openfile.empty() || fileNameList[i] != openfile) { // if we opened a file at the beginning don't add it again
@@ -664,13 +695,45 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring
filepanel->loadingThumbs(M("PROGRESSBAR_LOADINGTHUMBS"), 0);
}
dirMonitor = dir->monitor_directory ();
dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false));
refreshDirectoryMonitors(allDirs);
} catch (Glib::Exception& ex) {
std::cout << ex.what();
}
}
void FileCatalog::refreshDirectoryMonitors(const std::vector<Glib::RefPtr<Gio::File>> &dirs_to_monitor)
{
std::vector<Glib::ustring> updated_dir_names;
std::transform(
dirs_to_monitor.cbegin(), dirs_to_monitor.cend(),
std::back_inserter(updated_dir_names),
[](const Glib::RefPtr<Gio::File> &updated_dir) { return updated_dir->get_path(); });
// Remove monitors on directories that are no longer shown.
dirMonitors.erase(
std::remove_if(dirMonitors.begin(), dirMonitors.end(),
[&updated_dir_names](const FileMonitorInfo &fileMonitorInfo) {
return std::find(updated_dir_names.cbegin(), updated_dir_names.cend(), fileMonitorInfo.filePath) == updated_dir_names.cend();
}),
dirMonitors.end());
// Add monitors that do not exist yet.
std::vector<Glib::ustring> monitored_dir_names;
std::transform(
dirMonitors.cbegin(), dirMonitors.cend(),
std::back_inserter(monitored_dir_names),
[](const FileMonitorInfo &dir_monitor) { return dir_monitor.filePath; });
for (const auto &dir_to_monitor : dirs_to_monitor) {
const auto dir_path = dir_to_monitor->get_path();
if (std::find(monitored_dir_names.cbegin(), monitored_dir_names.cend(), dir_path) != monitored_dir_names.cend()) {
continue; // A monitor exists already.
}
auto dir_monitor = dir_to_monitor->monitor_directory();
dir_monitor->signal_changed().connect(sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false));
dirMonitors.emplace_back(dir_monitor, dir_path);
}
}
void FileCatalog::enableTabMode(bool enable)
{
inTabMode = enable;
@@ -1579,6 +1642,12 @@ void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick
}
}
void FileCatalog::showRecursiveToggled()
{
options.browseRecursive = bRecursive->get_active();
reparseDirectory();
}
BrowserFilter FileCatalog::getFilter ()
{
@@ -1712,21 +1781,28 @@ void FileCatalog::reparseDirectory ()
return;
}
// check if a thumbnailed file has been deleted
// check if a thumbnailed file has been deleted or is not in a directory of interest
const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries();
std::vector<Glib::ustring> fileNamesToDel;
std::vector<Glib::ustring> fileNamesToRemove;
for (const auto& entry : t) {
if (!Glib::file_test(entry->filename, Glib::FILE_TEST_EXISTS)) {
fileNamesToDel.push_back(entry->filename);
fileNamesToRemove.push_back(entry->filename);
}
else if (!options.browseRecursive && Glib::path_get_dirname(entry->filename) != selectedDirectory) {
fileNamesToRemove.push_back(entry->filename);
}
}
for (const auto& toDelete : fileNamesToDel) {
delete fileBrowser->delEntry(toDelete);
cacheMgr->deleteEntry(toDelete);
for (const auto& toRemove : fileNamesToRemove) {
delete fileBrowser->delEntry(toRemove);
--previewsLoaded;
}
for (const auto& toDelete : fileNamesToDel) {
cacheMgr->deleteEntry(toDelete);
}
if (!fileNamesToDel.empty()) {
_refreshProgressBar();
@@ -1739,7 +1815,8 @@ void FileCatalog::reparseDirectory ()
oldNames.insert(oldName.collate_key());
}
fileNameList = getFileList();
std::vector<Glib::RefPtr<Gio::File>> allDirs;
fileNameList = getFileList(&allDirs);
for (const auto& newName : fileNameList) {
if (oldNames.find(newName.collate_key()) == oldNames.end()) {
addFile(newName);
@@ -1747,13 +1824,16 @@ void FileCatalog::reparseDirectory ()
}
}
refreshDirectoryMonitors(allDirs);
}
void FileCatalog::on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal)
{
if (options.has_retained_extention(file->get_parse_name())
&& (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)) {
if ((options.has_retained_extention(file->get_parse_name())
&& (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED))
|| (event_type == Gio::FILE_MONITOR_EVENT_CREATED && Glib::file_test(file->get_path(), Glib::FileTest::FILE_TEST_IS_DIR))
|| (event_type == Gio::FILE_MONITOR_EVENT_DELETED && std::find_if(dirMonitors.cbegin(), dirMonitors.cend(), [&file](const FileMonitorInfo &monitor) { return monitor.filePath == file->get_path(); }) != dirMonitors.cend())) {
if (!internal) {
GThreadLock lock;
reparseDirectory ();

View File

@@ -54,6 +54,13 @@ public:
typedef sigc::slot<void, const Glib::ustring&> DirSelectionSlot;
private:
struct FileMonitorInfo {
FileMonitorInfo(const Glib::RefPtr<Gio::FileMonitor> &file_monitor, const Glib::ustring &file_path) :
fileMonitor(file_monitor), filePath(file_path) {}
Glib::RefPtr<Gio::FileMonitor> fileMonitor;
Glib::ustring filePath;
};
FilePanel* filepanel;
Gtk::Box* hBox;
Glib::ustring selectedDirectory;
@@ -95,6 +102,7 @@ private:
Gtk::ToggleButton* bTrash;
Gtk::ToggleButton* bNotTrash;
Gtk::ToggleButton* bOriginal;
Gtk::ToggleButton* bRecursive;
Gtk::ToggleButton* categoryButtons[20];
Gtk::ToggleButton* exifInfo;
sigc::connection bCateg[20];
@@ -143,14 +151,15 @@ private:
std::set<Glib::ustring> editedFiles;
guint modifierKey; // any modifiers held when rank button was pressed
Glib::RefPtr<Gio::FileMonitor> dirMonitor;
std::vector<FileMonitorInfo> dirMonitors;
IdleRegister idle_register;
void addAndOpenFile (const Glib::ustring& fname);
void addFile (const Glib::ustring& fName);
std::vector<Glib::ustring> getFileList ();
std::vector<Glib::ustring> getFileList(std::vector<Glib::RefPtr<Gio::File>> *dirs_explored = nullptr);
BrowserFilter getFilter ();
void refreshDirectoryMonitors(const std::vector<Glib::RefPtr<Gio::File>> &dirs_to_monitor);
void trashChanged ();
public:
@@ -240,6 +249,7 @@ public:
void setExportPanel (ExportPanel* expanel);
void exifInfoButtonToggled();
void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick);
void showRecursiveToggled();
bool capture_event(GdkEventButton* event);
void filterChanged ();
void runFilterDialog ();

View File

@@ -435,6 +435,10 @@ void Options::setDefaults()
parseExtensionsEnabled.clear();
parsedExtensions.clear();
parsedExtensionsSet.clear();
browseRecursive = false;
browseRecursiveDepth = 10;
browseRecursiveMaxDirs = 100;
browseRecursiveFollowLinks = true;
renameUseTemplates = false;
renameTemplates.clear();
thumbnailZoomRatios.clear();
@@ -1346,6 +1350,22 @@ void Options::readFromFile(Glib::ustring fname)
if (keyFile.has_key("File Browser", "SortDescending")) {
sortDescending = keyFile.get_boolean("File Browser", "SortDescending");
}
if (keyFile.has_key("File Browser", "BrowseRecursive")) {
browseRecursive = keyFile.get_boolean("File Browser", "BrowseRecursive");
}
if (keyFile.has_key("File Browser", "BrowseRecursiveDepth")) {
browseRecursiveDepth = keyFile.get_integer("File Browser", "BrowseRecursiveDepth");
}
if (keyFile.has_key("File Browser", "BrowseRecursiveMaxDirs")) {
browseRecursiveMaxDirs = keyFile.get_integer("File Browser", "BrowseRecursiveMaxDirs");
}
if (keyFile.has_key("File Browser", "BrowseRecursiveFollowLinks")) {
browseRecursiveFollowLinks = keyFile.get_integer("File Browser", "BrowseRecursiveFollowLinks");
}
}
if (keyFile.has_group("Clipping Indication")) {
@@ -2444,6 +2464,10 @@ void Options::saveToFile(Glib::ustring fname)
}
keyFile.set_integer("File Browser", "SortMethod", sortMethod);
keyFile.set_boolean("File Browser", "SortDescending", sortDescending);
keyFile.set_boolean("File Browser", "BrowseRecursive", browseRecursive);
keyFile.set_integer("File Browser", "BrowseRecursiveDepth", browseRecursiveDepth);
keyFile.set_integer("File Browser", "BrowseRecursiveMaxDirs", browseRecursiveMaxDirs);
keyFile.set_boolean("File Browser", "BrowseRecursiveFollowLinks", browseRecursiveFollowLinks);
keyFile.set_integer("Clipping Indication", "HighlightThreshold", highlightThreshold);
keyFile.set_integer("Clipping Indication", "ShadowThreshold", shadowThreshold);
keyFile.set_boolean("Clipping Indication", "BlinkClipped", blinkClipped);

View File

@@ -314,6 +314,10 @@ public:
std::vector<int> parseExtensionsEnabled; // List of bool to retain extension or not
std::vector<Glib::ustring> parsedExtensions; // List containing all retained extensions (lowercase)
std::set<std::string> parsedExtensionsSet; // Set containing all retained extensions (lowercase)
bool browseRecursive;
int browseRecursiveDepth;
int browseRecursiveMaxDirs;
bool browseRecursiveFollowLinks;
std::vector<int> tpOpen;
bool autoSaveTpOpen;
//std::vector<int> crvOpen;

View File

@@ -1480,6 +1480,28 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
maxRecentFolders->set_range(1, 25);
vbro->pack_start(*hbrecent, Gtk::PACK_SHRINK, 4);
// Recursive browsing options.
Gtk::Box *hbBrowseRecursive = Gtk::manage(new Gtk::Box());
Gtk::Label *labBrowseRecursiveDepth = Gtk::manage(new Gtk::Label(M("PREFERENCES_BROWSERECURSIVEDEPTH") + ":"));
browseRecursiveDepth = Gtk::manage(new Gtk::SpinButton());
browseRecursiveDepth->set_digits(0);
browseRecursiveDepth->set_increments(1, 5);
browseRecursiveDepth->set_range(1, 999);
Gtk::Label *labBrowseRecursiveMaxDirs = Gtk::manage(new Gtk::Label(M("PREFERENCES_BROWSERECURSIVEMAXDIRS") + ":"));
browseRecursiveMaxDirs = Gtk::manage(new Gtk::SpinButton());
browseRecursiveMaxDirs->set_digits(0);
browseRecursiveMaxDirs->set_increments(1, 5);
browseRecursiveMaxDirs->set_range(1, 999);
hbBrowseRecursive->pack_start(*labBrowseRecursiveDepth, Gtk::PACK_SHRINK, 4);
hbBrowseRecursive->pack_start(*browseRecursiveDepth, Gtk::PACK_SHRINK, 4);
hbBrowseRecursive->pack_start(*labBrowseRecursiveMaxDirs, Gtk::PACK_SHRINK, 4);
hbBrowseRecursive->pack_start(*browseRecursiveMaxDirs, Gtk::PACK_SHRINK, 4);
vbro->pack_start(*hbBrowseRecursive, Gtk::PACK_SHRINK, 0);
#ifndef _WIN32
browseRecursiveFollowLinks = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_BROWSERECURSIVEFOLLOWLINKS")));
vbro->pack_start(*browseRecursiveFollowLinks, Gtk::PACK_SHRINK, 0);
#endif
fro->add(*vbro);
@@ -1936,6 +1958,11 @@ void Preferences::storePreferences()
moptions.filmStripOverlayedFileNames = filmStripOverlayedFileNames->get_active();
moptions.sameThumbSize = sameThumbSize->get_active();
moptions.internalThumbIfUntouched = ckbInternalThumbIfUntouched->get_active();
moptions.browseRecursiveDepth = static_cast<int>(browseRecursiveDepth->get_value());
moptions.browseRecursiveMaxDirs = static_cast<int>(browseRecursiveMaxDirs->get_value());
if (browseRecursiveFollowLinks) {
moptions.browseRecursiveFollowLinks = browseRecursiveFollowLinks->get_active();
}
auto save_where = saveParamsPreference->get_active_row_number();
moptions.saveParamsFile = save_where == 0 || save_where == 2;
@@ -2165,6 +2192,11 @@ void Preferences::fillPreferences()
filmStripOverlayedFileNames->set_active(moptions.filmStripOverlayedFileNames);
sameThumbSize->set_active(moptions.sameThumbSize);
ckbInternalThumbIfUntouched->set_active(moptions.internalThumbIfUntouched);
browseRecursiveDepth->set_value(moptions.browseRecursiveDepth);
browseRecursiveMaxDirs->set_value(moptions.browseRecursiveMaxDirs);
if (browseRecursiveFollowLinks) {
browseRecursiveFollowLinks->set_active(moptions.browseRecursiveFollowLinks);
}
saveParamsPreference->set_active(moptions.saveParamsFile ? (moptions.saveParamsCache ? 2 : 0) : 1);

View File

@@ -186,6 +186,9 @@ class Preferences final :
Gtk::CheckButton* overlayedFileNames;
Gtk::CheckButton* filmStripOverlayedFileNames;
Gtk::CheckButton* sameThumbSize;
Gtk::SpinButton* browseRecursiveDepth;
Gtk::SpinButton* browseRecursiveMaxDirs;
Gtk::CheckButton* browseRecursiveFollowLinks{nullptr};
Gtk::SpinButton* threadsSpinBtn;
Gtk::SpinButton* clutCacheSizeSB;