Add recursive sub-folder image browsing
Add toggle button in the top toolbar of the file browser to activate or deactivate recursive browsing. Toggle state is saved in options. Limit recursion depth and explored directory count.
This commit is contained in:
98
rtdata/images/svg/folder-subfolder.svg
Normal file
98
rtdata/images/svg/folder-subfolder.svg
Normal 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:#2a7fff;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:#2a7fff;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:#2a7fff;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:#2a7fff;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 |
@@ -200,6 +200,7 @@ FILEBROWSER_SHOWRANK4HINT;Show images ranked as 4-star.\nShortcut: <b>4</b>
|
|||||||
FILEBROWSER_SHOWRANK5HINT;Show images ranked as 5-star.\nShortcut: <b>5</b>
|
FILEBROWSER_SHOWRANK5HINT;Show images ranked as 5-star.\nShortcut: <b>5</b>
|
||||||
FILEBROWSER_SHOWRECENTLYSAVEDHINT;Show saved images.\nShortcut: <b>Alt-7</b>
|
FILEBROWSER_SHOWRECENTLYSAVEDHINT;Show saved images.\nShortcut: <b>Alt-7</b>
|
||||||
FILEBROWSER_SHOWRECENTLYSAVEDNOTHINT;Show unsaved images.\nShortcut: <b>Alt-6</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_SHOWTRASHHINT;Show contents of trash.\nShortcut: <b>Ctrl-t</b>
|
||||||
FILEBROWSER_SHOWUNCOLORHINT;Show images without a color label.\nShortcut: <b>Alt-0</b>
|
FILEBROWSER_SHOWUNCOLORHINT;Show images without a color label.\nShortcut: <b>Alt-0</b>
|
||||||
FILEBROWSER_SHOWUNRANKHINT;Show unranked images.\nShortcut: <b>0</b>
|
FILEBROWSER_SHOWUNRANKHINT;Show unranked images.\nShortcut: <b>0</b>
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "filecatalog.h"
|
#include "filecatalog.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#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));
|
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);
|
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.png")));
|
||||||
|
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 (*bTrash, Gtk::PACK_SHRINK);
|
||||||
buttonBar->pack_start (*bNotTrash, Gtk::PACK_SHRINK);
|
buttonBar->pack_start (*bNotTrash, Gtk::PACK_SHRINK);
|
||||||
buttonBar->pack_start (*bOriginal, 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);
|
buttonBar->pack_start (*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)), Gtk::PACK_SHRINK);
|
||||||
fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) );
|
fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) );
|
||||||
|
|
||||||
@@ -544,9 +554,7 @@ void FileCatalog::closeDir ()
|
|||||||
exportPanel->set_sensitive (false);
|
exportPanel->set_sensitive (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dirMonitor) {
|
dirMonitors.clear();
|
||||||
dirMonitor->cancel ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore old requests
|
// ignore old requests
|
||||||
++selectedDirectoryId;
|
++selectedDirectoryId;
|
||||||
@@ -570,19 +578,24 @@ void FileCatalog::closeDir ()
|
|||||||
redrawAll ();
|
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;
|
std::vector<Glib::ustring> names;
|
||||||
|
|
||||||
const std::set<std::string>& extensions = options.parsedExtensionsSet;
|
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 {
|
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");
|
auto enumerator = dir->enumerate_children("standard::name,standard::type,standard::is-hidden");
|
||||||
|
|
||||||
|
if (directories_explored) {
|
||||||
|
directories_explored->push_back(dir);
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
const auto file = enumerator->next_file();
|
const auto file = enumerator->next_file();
|
||||||
@@ -590,11 +603,15 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->get_file_type() == Gio::FILE_TYPE_DIRECTORY) {
|
if (!options.fbShowHidden && file->is_hidden()) {
|
||||||
continue;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +626,7 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
names.push_back(Glib::build_filename(selectedDirectory, fname));
|
file_names.emplace_back(Glib::build_filename(dir_path, fname));
|
||||||
} catch (Glib::Exception& exception) {
|
} catch (Glib::Exception& exception) {
|
||||||
if (rtengine::settings->verbose) {
|
if (rtengine::settings->verbose) {
|
||||||
std::cerr << exception.what() << std::endl;
|
std::cerr << exception.what() << std::endl;
|
||||||
@@ -620,10 +637,14 @@ std::vector<Glib::ustring> FileCatalog::getFileList()
|
|||||||
} catch (Glib::Exception& exception) {
|
} catch (Glib::Exception& exception) {
|
||||||
|
|
||||||
if (rtengine::settings->verbose) {
|
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;
|
return names;
|
||||||
}
|
}
|
||||||
@@ -649,9 +670,10 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring
|
|||||||
|
|
||||||
selectedDirectory = dir->get_parse_name();
|
selectedDirectory = dir->get_parse_name();
|
||||||
|
|
||||||
|
std::vector<Glib::RefPtr<Gio::File>> allDirs;
|
||||||
BrowsePath->set_text(selectedDirectory);
|
BrowsePath->set_text(selectedDirectory);
|
||||||
buttonBrowsePath->set_image(*iRefreshWhite);
|
buttonBrowsePath->set_image(*iRefreshWhite);
|
||||||
fileNameList = getFileList();
|
fileNameList = getFileList(&allDirs);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < fileNameList.size(); i++) {
|
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
|
if (openfile.empty() || fileNameList[i] != openfile) { // if we opened a file at the beginning don't add it again
|
||||||
@@ -667,13 +689,45 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring
|
|||||||
filepanel->loadingThumbs(M("PROGRESSBAR_LOADINGTHUMBS"), 0);
|
filepanel->loadingThumbs(M("PROGRESSBAR_LOADINGTHUMBS"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirMonitor = dir->monitor_directory ();
|
refreshDirectoryMonitors(allDirs);
|
||||||
dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false));
|
|
||||||
} catch (Glib::Exception& ex) {
|
} catch (Glib::Exception& ex) {
|
||||||
std::cout << ex.what();
|
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)
|
void FileCatalog::enableTabMode(bool enable)
|
||||||
{
|
{
|
||||||
inTabMode = enable;
|
inTabMode = enable;
|
||||||
@@ -1581,6 +1635,12 @@ void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileCatalog::showRecursiveToggled()
|
||||||
|
{
|
||||||
|
options.browseRecursive = bRecursive->get_active();
|
||||||
|
reparseDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
BrowserFilter FileCatalog::getFilter ()
|
BrowserFilter FileCatalog::getFilter ()
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1717,18 +1777,25 @@ void FileCatalog::reparseDirectory ()
|
|||||||
// check if a thumbnailed file has been deleted
|
// check if a thumbnailed file has been deleted
|
||||||
const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries();
|
const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries();
|
||||||
std::vector<Glib::ustring> fileNamesToDel;
|
std::vector<Glib::ustring> fileNamesToDel;
|
||||||
|
std::vector<Glib::ustring> fileNamesToRemove;
|
||||||
|
|
||||||
for (const auto& entry : t) {
|
for (const auto& entry : t) {
|
||||||
if (!Glib::file_test(entry->filename, Glib::FILE_TEST_EXISTS)) {
|
if (!Glib::file_test(entry->filename, Glib::FILE_TEST_EXISTS)) {
|
||||||
fileNamesToDel.push_back(entry->filename);
|
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) {
|
for (const auto& toRemove : fileNamesToRemove) {
|
||||||
delete fileBrowser->delEntry(toDelete);
|
delete fileBrowser->delEntry(toRemove);
|
||||||
cacheMgr->deleteEntry(toDelete);
|
|
||||||
--previewsLoaded;
|
--previewsLoaded;
|
||||||
}
|
}
|
||||||
|
for (const auto& toDelete : fileNamesToDel) {
|
||||||
|
cacheMgr->deleteEntry(toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
if (!fileNamesToDel.empty()) {
|
if (!fileNamesToDel.empty()) {
|
||||||
_refreshProgressBar();
|
_refreshProgressBar();
|
||||||
@@ -1741,7 +1808,8 @@ void FileCatalog::reparseDirectory ()
|
|||||||
oldNames.insert(oldName.collate_key());
|
oldNames.insert(oldName.collate_key());
|
||||||
}
|
}
|
||||||
|
|
||||||
fileNameList = getFileList();
|
std::vector<Glib::RefPtr<Gio::File>> allDirs;
|
||||||
|
fileNameList = getFileList(&allDirs);
|
||||||
for (const auto& newName : fileNameList) {
|
for (const auto& newName : fileNameList) {
|
||||||
if (oldNames.find(newName.collate_key()) == oldNames.end()) {
|
if (oldNames.find(newName.collate_key()) == oldNames.end()) {
|
||||||
addFile(newName);
|
addFile(newName);
|
||||||
@@ -1749,6 +1817,7 @@ 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)
|
void FileCatalog::on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal)
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ public:
|
|||||||
typedef sigc::slot<void, const Glib::ustring&> DirSelectionSlot;
|
typedef sigc::slot<void, const Glib::ustring&> DirSelectionSlot;
|
||||||
|
|
||||||
private:
|
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;
|
FilePanel* filepanel;
|
||||||
Gtk::Box* hBox;
|
Gtk::Box* hBox;
|
||||||
Glib::ustring selectedDirectory;
|
Glib::ustring selectedDirectory;
|
||||||
@@ -95,6 +102,7 @@ private:
|
|||||||
Gtk::ToggleButton* bTrash;
|
Gtk::ToggleButton* bTrash;
|
||||||
Gtk::ToggleButton* bNotTrash;
|
Gtk::ToggleButton* bNotTrash;
|
||||||
Gtk::ToggleButton* bOriginal;
|
Gtk::ToggleButton* bOriginal;
|
||||||
|
Gtk::ToggleButton* bRecursive;
|
||||||
Gtk::ToggleButton* categoryButtons[20];
|
Gtk::ToggleButton* categoryButtons[20];
|
||||||
Gtk::ToggleButton* exifInfo;
|
Gtk::ToggleButton* exifInfo;
|
||||||
sigc::connection bCateg[20];
|
sigc::connection bCateg[20];
|
||||||
@@ -143,14 +151,15 @@ private:
|
|||||||
std::set<Glib::ustring> editedFiles;
|
std::set<Glib::ustring> editedFiles;
|
||||||
guint modifierKey; // any modifiers held when rank button was pressed
|
guint modifierKey; // any modifiers held when rank button was pressed
|
||||||
|
|
||||||
Glib::RefPtr<Gio::FileMonitor> dirMonitor;
|
std::vector<FileMonitorInfo> dirMonitors;
|
||||||
|
|
||||||
IdleRegister idle_register;
|
IdleRegister idle_register;
|
||||||
|
|
||||||
void addAndOpenFile (const Glib::ustring& fname);
|
void addAndOpenFile (const Glib::ustring& fname);
|
||||||
void addFile (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 ();
|
BrowserFilter getFilter ();
|
||||||
|
void refreshDirectoryMonitors(const std::vector<Glib::RefPtr<Gio::File>> &dirs_to_monitor);
|
||||||
void trashChanged ();
|
void trashChanged ();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -240,6 +249,7 @@ public:
|
|||||||
void setExportPanel (ExportPanel* expanel);
|
void setExportPanel (ExportPanel* expanel);
|
||||||
void exifInfoButtonToggled();
|
void exifInfoButtonToggled();
|
||||||
void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick);
|
void categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick);
|
||||||
|
void showRecursiveToggled();
|
||||||
bool capture_event(GdkEventButton* event);
|
bool capture_event(GdkEventButton* event);
|
||||||
void filterChanged ();
|
void filterChanged ();
|
||||||
void runFilterDialog ();
|
void runFilterDialog ();
|
||||||
|
|||||||
@@ -435,6 +435,9 @@ void Options::setDefaults()
|
|||||||
parseExtensionsEnabled.clear();
|
parseExtensionsEnabled.clear();
|
||||||
parsedExtensions.clear();
|
parsedExtensions.clear();
|
||||||
parsedExtensionsSet.clear();
|
parsedExtensionsSet.clear();
|
||||||
|
browseRecursive = false;
|
||||||
|
browseRecursiveDepth = 10;
|
||||||
|
browseRecursiveMaxDirs = 100;
|
||||||
renameUseTemplates = false;
|
renameUseTemplates = false;
|
||||||
renameTemplates.clear();
|
renameTemplates.clear();
|
||||||
thumbnailZoomRatios.clear();
|
thumbnailZoomRatios.clear();
|
||||||
@@ -1342,6 +1345,18 @@ void Options::readFromFile(Glib::ustring fname)
|
|||||||
if (keyFile.has_key("File Browser", "SortDescending")) {
|
if (keyFile.has_key("File Browser", "SortDescending")) {
|
||||||
sortDescending = keyFile.get_boolean("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_group("Clipping Indication")) {
|
if (keyFile.has_group("Clipping Indication")) {
|
||||||
@@ -2410,6 +2425,9 @@ void Options::saveToFile(Glib::ustring fname)
|
|||||||
}
|
}
|
||||||
keyFile.set_integer("File Browser", "SortMethod", sortMethod);
|
keyFile.set_integer("File Browser", "SortMethod", sortMethod);
|
||||||
keyFile.set_boolean("File Browser", "SortDescending", sortDescending);
|
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_integer("Clipping Indication", "HighlightThreshold", highlightThreshold);
|
keyFile.set_integer("Clipping Indication", "HighlightThreshold", highlightThreshold);
|
||||||
keyFile.set_integer("Clipping Indication", "ShadowThreshold", shadowThreshold);
|
keyFile.set_integer("Clipping Indication", "ShadowThreshold", shadowThreshold);
|
||||||
keyFile.set_boolean("Clipping Indication", "BlinkClipped", blinkClipped);
|
keyFile.set_boolean("Clipping Indication", "BlinkClipped", blinkClipped);
|
||||||
|
|||||||
@@ -315,6 +315,9 @@ public:
|
|||||||
std::vector<int> parseExtensionsEnabled; // List of bool to retain extension or not
|
std::vector<int> parseExtensionsEnabled; // List of bool to retain extension or not
|
||||||
std::vector<Glib::ustring> parsedExtensions; // List containing all retained extensions (lowercase)
|
std::vector<Glib::ustring> parsedExtensions; // List containing all retained extensions (lowercase)
|
||||||
std::set<std::string> parsedExtensionsSet; // Set containing all retained extensions (lowercase)
|
std::set<std::string> parsedExtensionsSet; // Set containing all retained extensions (lowercase)
|
||||||
|
bool browseRecursive;
|
||||||
|
int browseRecursiveDepth;
|
||||||
|
int browseRecursiveMaxDirs;
|
||||||
std::vector<int> tpOpen;
|
std::vector<int> tpOpen;
|
||||||
bool autoSaveTpOpen;
|
bool autoSaveTpOpen;
|
||||||
//std::vector<int> crvOpen;
|
//std::vector<int> crvOpen;
|
||||||
|
|||||||
Reference in New Issue
Block a user