Merge pull request #3094 from adamreichold/fix-cluts-dir-listing
Fix slow parsing of CLUT directory
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
#include "filmsimulation.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "options.h"
|
||||
#include "../rtengine/clutstore.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
@@ -6,6 +9,30 @@
|
||||
using namespace rtengine;
|
||||
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;
|
||||
|
||||
FilmSimulation::FilmSimulation()
|
||||
@@ -143,83 +170,119 @@ ClutComboBox::ClutColumns::ClutColumns()
|
||||
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() ) {
|
||||
m_model.clear();
|
||||
m_model = Gtk::TreeStore::create( m_columns );
|
||||
set_model( m_model );
|
||||
result = parseDir( path, 0 );
|
||||
pack_start( m_columns.label, false );
|
||||
const auto result = parseDir (path);
|
||||
|
||||
if (result > 0) {
|
||||
pack_start (m_columns.label, false);
|
||||
}
|
||||
|
||||
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 ( parent ) {
|
||||
result = model->append( parent->children() );
|
||||
|
||||
} else {
|
||||
result = model->append();
|
||||
if (path.empty () || !Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
const auto startedAt = std::chrono::system_clock::now ();
|
||||
|
||||
int ClutComboBox::parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow )
|
||||
{
|
||||
int result = 0;
|
||||
// Build menu of limited directory structure using breadth-first search
|
||||
using Dirs = std::vector<std::pair<Glib::ustring, Gtk::TreeModel::Row>>;
|
||||
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 ) {
|
||||
Glib::ustring current = *it;
|
||||
for (auto& dir : currDirs) {
|
||||
|
||||
if ( current != "." && current != ".." ) {
|
||||
names.push_back( current );
|
||||
}
|
||||
}
|
||||
const auto& path = dir.first;
|
||||
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 ) {
|
||||
Glib::ustring current = *it;
|
||||
Glib::ustring fullname = Glib::build_filename( path, current );
|
||||
const auto entryPath = Glib::build_filename (path, entry);
|
||||
|
||||
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 );
|
||||
newFolderMenu[ m_columns.label ] = current;
|
||||
result += parseDir( fullname, &newFolderMenu );
|
||||
} else {
|
||||
Glib::ustring name, extension, profileName;
|
||||
splitClutFilename( current, name, extension, profileName );
|
||||
auto newRow = row ? *m_model->append (row.children ()) : *m_model->append ();
|
||||
newRow[m_columns.label] = entry;
|
||||
|
||||
if ( extension == "tif" ||
|
||||
extension == "TIF" ||
|
||||
extension == "png" ||
|
||||
extension == "PNG" ) {
|
||||
Gtk::TreeModel::Row newClut = *appendToModel( m_model, parentRow );
|
||||
newClut[ m_columns.label ] = name;
|
||||
newClut[ m_columns.clutFilename ] = fullname;
|
||||
++result;
|
||||
nextDirs.emplace_back (entryPath, newRow);
|
||||
}
|
||||
} catch (Glib::Exception&) {}
|
||||
|
||||
dirs.push_back (std::move (dir));
|
||||
|
||||
notifySlowParseDir (startedAt);
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -11,7 +11,7 @@
|
||||
class ClutComboBox : public MyComboBox
|
||||
{
|
||||
public:
|
||||
int fillFromDir( Glib::ustring path );
|
||||
int fillFromDir (const Glib::ustring& path);
|
||||
Glib::ustring getSelectedClut();
|
||||
void setSelectedClut( Glib::ustring filename );
|
||||
void addUnchangedEntry();
|
||||
@@ -25,7 +25,7 @@ private:
|
||||
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 );
|
||||
|
||||
Glib::RefPtr<Gtk::TreeStore> m_model;
|
||||
|
Reference in New Issue
Block a user