Merge pull request #3094 from adamreichold/fix-cluts-dir-listing

Fix slow parsing of CLUT directory
This commit is contained in:
adamreichold
2016-01-19 15:23:45 +01:00
4 changed files with 119 additions and 55 deletions

View File

@@ -1466,6 +1466,7 @@ TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
TP_FILMSIMULATION_LABEL;Film Simulation TP_FILMSIMULATION_LABEL;Film Simulation
TP_FILMSIMULATION_STRENGTH;Strength TP_FILMSIMULATION_STRENGTH;Strength
TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences TP_FILMSIMULATION_ZEROCLUTSFOUND;Set HaldCLUT directory in Preferences
TP_FILMSIMULATION_SLOWPARSEDIR;The Film Simulation HaldCLUT folder you pointed RawTherapee to is taking too long to load. Reduce the number of files in that folder or point RawTherapee to an empty one instead.\n\nSee Preferences > Image Processing > Film Simulation
TP_FLATFIELD_AUTOSELECT;Auto-selection TP_FLATFIELD_AUTOSELECT;Auto-selection
TP_FLATFIELD_BLURRADIUS;Blur radius TP_FLATFIELD_BLURRADIUS;Blur radius
TP_FLATFIELD_BLURTYPE;Blur type TP_FLATFIELD_BLURTYPE;Blur type

View File

@@ -54,7 +54,7 @@ void loadProfiles (const Glib::ustring& dirName,
const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold (); const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold ();
if (extension.compare(".icc") == 0 && extension.compare(".icm") == 0) if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0)
continue; continue;
const Glib::ustring filePath = Glib::build_filename (dirName, fileName); const Glib::ustring filePath = Glib::build_filename (dirName, fileName);

View File

@@ -1,4 +1,7 @@
#include "filmsimulation.h" #include "filmsimulation.h"
#include <chrono>
#include "options.h" #include "options.h"
#include "../rtengine/clutstore.h" #include "../rtengine/clutstore.h"
#include "../rtengine/safegtk.h" #include "../rtengine/safegtk.h"
@@ -6,6 +9,30 @@
using namespace rtengine; using namespace rtengine;
using namespace rtengine::procparams; using namespace rtengine::procparams;
namespace
{
void notifySlowParseDir (const std::chrono::system_clock::time_point& startedAt)
{
static bool alreadyNotified = false;
if (alreadyNotified) {
return;
}
const auto now = std::chrono::system_clock::now ();
if (now - startedAt < std::chrono::seconds (10)) {
return;
}
Gtk::MessageDialog dialog (M ("TP_FILMSIMULATION_SLOWPARSEDIR"), false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
dialog.run ();
alreadyNotified = true;
}
}
typedef std::vector<Glib::ustring> Strings; typedef std::vector<Glib::ustring> Strings;
FilmSimulation::FilmSimulation() FilmSimulation::FilmSimulation()
@@ -143,83 +170,119 @@ ClutComboBox::ClutColumns::ClutColumns()
add( clutFilename ); add( clutFilename );
} }
int ClutComboBox::fillFromDir( Glib::ustring path ) int ClutComboBox::fillFromDir (const Glib::ustring& path)
{ {
int result = 0; m_model = Gtk::TreeStore::create (m_columns);
set_model (m_model);
if ( !path.empty() ) { const auto result = parseDir (path);
m_model.clear();
m_model = Gtk::TreeStore::create( m_columns ); if (result > 0) {
set_model( m_model ); pack_start (m_columns.label, false);
result = parseDir( path, 0 );
pack_start( m_columns.label, false );
} }
return result; return result;
} }
Gtk::TreeIter appendToModel( Glib::RefPtr<Gtk::TreeStore> model, Gtk::TreeModel::Row *parent ) int ClutComboBox::parseDir (const Glib::ustring& path)
{ {
Gtk::TreeIter result; if (path.empty () || !Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
return 0;
if ( parent ) {
result = model->append( parent->children() );
} else {
result = model->append();
} }
return result; const auto startedAt = std::chrono::system_clock::now ();
}
int ClutComboBox::parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow ) // Build menu of limited directory structure using breadth-first search
{ using Dirs = std::vector<std::pair<Glib::ustring, Gtk::TreeModel::Row>>;
int result = 0; Dirs dirs;
if ( path.empty() || !safe_file_test( path, Glib::FILE_TEST_EXISTS ) || !safe_file_test ( path, Glib::FILE_TEST_IS_DIR ) ) { {
return result; Dirs currDirs;
} Dirs nextDirs;
Glib::Dir* dir = new Glib::Dir( path ); currDirs.emplace_back (path, Gtk::TreeModel::Row ());
Strings names; while (!currDirs.empty ()) {
for( Glib::DirIterator it = dir->begin(); it != dir->end(); ++it ) { for (auto& dir : currDirs) {
Glib::ustring current = *it;
if ( current != "." && current != ".." ) { const auto& path = dir.first;
names.push_back( current ); const auto& row = dir.second;
}
}
std::sort( names.begin(), names.end() ); try {
for (const auto& entry : Glib::Dir (path)) {
for ( Strings::iterator it = names.begin(); it != names.end(); ++it ) { const auto entryPath = Glib::build_filename (path, entry);
Glib::ustring current = *it;
Glib::ustring fullname = Glib::build_filename( path, current );
if ( safe_file_test( fullname, Glib::FILE_TEST_IS_DIR ) ) { if (!Glib::file_test (entryPath, Glib::FILE_TEST_IS_DIR)) {
continue;
}
Gtk::TreeModel::Row newFolderMenu = *appendToModel( m_model, parentRow ); auto newRow = row ? *m_model->append (row.children ()) : *m_model->append ();
newFolderMenu[ m_columns.label ] = current; newRow[m_columns.label] = entry;
result += parseDir( fullname, &newFolderMenu );
} else {
Glib::ustring name, extension, profileName;
splitClutFilename( current, name, extension, profileName );
if ( extension == "tif" || nextDirs.emplace_back (entryPath, newRow);
extension == "TIF" || }
extension == "png" || } catch (Glib::Exception&) {}
extension == "PNG" ) {
Gtk::TreeModel::Row newClut = *appendToModel( m_model, parentRow ); dirs.push_back (std::move (dir));
newClut[ m_columns.label ] = name;
newClut[ m_columns.clutFilename ] = fullname; notifySlowParseDir (startedAt);
++result;
} }
currDirs.clear ();
currDirs.swap (nextDirs);
} }
} }
return result; // Fill menu structure with CLUT files
Strings entries;
auto fileCount = 0;
for (const auto& dir : dirs) {
const auto& path = dir.first;
const auto& row = dir.second;
entries.clear ();
try {
for (const auto& entry : Glib::Dir (path)) {
const auto entryPath = Glib::build_filename (path, entry);
if (!Glib::file_test (entryPath, Glib::FILE_TEST_IS_REGULAR)) {
continue;
}
entries.push_back (entryPath);
}
} catch (Glib::Exception&) {}
std::sort (entries.begin (), entries.end ());
for (const auto& entry : entries) {
Glib::ustring name, extension, profileName;
splitClutFilename (entry, name, extension, profileName);
extension = extension.casefold ();
if (extension.compare ("tif") != 0 && extension.compare ("png") != 0) {
continue;
}
auto newRow = row ? *m_model->append (row.children ()) : *m_model->append ();
newRow[m_columns.label] = name;
newRow[m_columns.clutFilename] = entry;
++fileCount;
notifySlowParseDir (startedAt);
}
}
return fileCount;
} }
Glib::ustring ClutComboBox::getSelectedClut() Glib::ustring ClutComboBox::getSelectedClut()

View File

@@ -11,7 +11,7 @@
class ClutComboBox : public MyComboBox class ClutComboBox : public MyComboBox
{ {
public: public:
int fillFromDir( Glib::ustring path ); int fillFromDir (const Glib::ustring& path);
Glib::ustring getSelectedClut(); Glib::ustring getSelectedClut();
void setSelectedClut( Glib::ustring filename ); void setSelectedClut( Glib::ustring filename );
void addUnchangedEntry(); void addUnchangedEntry();
@@ -25,7 +25,7 @@ private:
ClutColumns(); ClutColumns();
}; };
int parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow ); int parseDir (const Glib::ustring& path);
Gtk::TreeIter findRowByClutFilename( Gtk::TreeModel::Children childs, Glib::ustring filename ); Gtk::TreeIter findRowByClutFilename( Gtk::TreeModel::Children childs, Glib::ustring filename );
Glib::RefPtr<Gtk::TreeStore> m_model; Glib::RefPtr<Gtk::TreeStore> m_model;