Limit the recusrion depth, direction and file count of the search for CLUT files.

This commit is contained in:
Adam Reichold
2016-01-11 20:58:36 +01:00
parent b8aa69c8d5
commit cc585058ab
2 changed files with 91 additions and 46 deletions

View File

@@ -148,7 +148,7 @@ int ClutComboBox::fillFromDir (const Glib::ustring& path)
m_model = Gtk::TreeStore::create (m_columns); m_model = Gtk::TreeStore::create (m_columns);
set_model (m_model); set_model (m_model);
const auto result = parseDir (path, nullptr); const auto result = parseDir (path);
if (result > 0) { if (result > 0) {
pack_start (m_columns.label, false); pack_start (m_columns.label, false);
@@ -157,68 +157,113 @@ int ClutComboBox::fillFromDir (const Glib::ustring& path)
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; // Build menu of limited directory structure using breadth-first search
} using Dirs = std::vector<std::pair<Glib::ustring, Gtk::TreeModel::Row>>;
Dirs dirs;
int ClutComboBox::parseDir( Glib::ustring path, Gtk::TreeModel::Row *parentRow )
{ {
int result = 0; Dirs currDirs;
Dirs nextDirs;
if ( path.empty() || !safe_file_test( path, Glib::FILE_TEST_EXISTS ) || !safe_file_test ( path, Glib::FILE_TEST_IS_DIR ) ) { constexpr auto maxDirCount = 128, maxDirDepth = 4;
return result; auto dirCount = 0, dirDepth = 0;
currDirs.emplace_back (path, Gtk::TreeModel::Row ());
while (!currDirs.empty ()) {
for (auto& dir : currDirs) {
const auto& path = dir.first;
const auto& row = dir.second;
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_DIR)) {
continue;
} }
Glib::Dir* dir = new Glib::Dir( path ); auto newRow = row ? *m_model->append (row.children ()) : *m_model->append ();
newRow[m_columns.label] = entry;
Strings names; nextDirs.emplace_back (entryPath, newRow);
}
} catch (Glib::Exception&) {}
for( Glib::DirIterator it = dir->begin(); it != dir->end(); ++it ) { dirs.push_back (std::move (dir));
Glib::ustring current = *it; if (++dirCount > maxDirCount) {
m_model->clear ();
if ( current != "." && current != ".." ) { return 0;
names.push_back( current );
} }
} }
std::sort( names.begin(), names.end() ); currDirs.clear ();
currDirs.swap (nextDirs);
if (++dirDepth > maxDirDepth) {
m_model->clear ();
return 0;
}
}
}
for ( Strings::iterator it = names.begin(); it != names.end(); ++it ) { // Fill menu structure with CLUT files
Glib::ustring current = *it; Strings entries;
Glib::ustring fullname = Glib::build_filename( path, current );
if ( safe_file_test( fullname, Glib::FILE_TEST_IS_DIR ) ) { constexpr auto maxFileCount = 4096;
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)) {
entries.push_back (entry);
}
} catch (Glib::Exception&) {}
std::sort (entries.begin (), entries.end ());
for (const auto& entry : entries) {
const auto entryPath = Glib::build_filename (path, entry);
if (!Glib::file_test (entryPath, Glib::FILE_TEST_IS_REGULAR)) {
continue;
}
Gtk::TreeModel::Row newFolderMenu = *appendToModel( m_model, parentRow );
newFolderMenu[ m_columns.label ] = current;
result += parseDir( fullname, &newFolderMenu );
} else {
Glib::ustring name, extension, profileName; Glib::ustring name, extension, profileName;
splitClutFilename( current, name, extension, profileName ); splitClutFilename (entry, name, extension, profileName);
if ( extension == "tif" || extension = extension.casefold ();
extension == "TIF" || if (extension.compare ("tif") == 0 && extension.compare ("png") == 0) {
extension == "png" || continue;
extension == "PNG" ) { }
Gtk::TreeModel::Row newClut = *appendToModel( m_model, parentRow );
newClut[ m_columns.label ] = name; auto newRow = row ? *m_model->append (row.children ()) : *m_model->append ();
newClut[ m_columns.clutFilename ] = fullname; newRow[m_columns.label] = name;
++result; newRow[m_columns.clutFilename] = entryPath;
if (++fileCount > maxFileCount) {
m_model->clear ();
return 0;
} }
} }
} }
return result; return fileCount;
} }
Glib::ustring ClutComboBox::getSelectedClut() Glib::ustring ClutComboBox::getSelectedClut()

View File

@@ -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;