1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:57:43 +00:00

FileManager+LibGUI: Fix two folder-related crashes (#569)

Fix a crash when opening a folder, and another one when trying to open
a newly created folder.

It was not safe to modify a GModelSelection while it's being iterated over.

Fixes #536.
This commit is contained in:
Brandon Scott 2019-09-17 02:26:10 -05:00 committed by Andreas Kling
parent caf1b37e75
commit a4d52b122d
4 changed files with 46 additions and 5 deletions

View file

@ -104,6 +104,20 @@ int main(int argc, char** argv)
if (rc < 0) { if (rc < 0) {
GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, GMessageBox::InputType::OK, window); GMessageBox::show(String::format("mkdir(\"%s\") failed: %s", new_dir_path.characters(), strerror(errno)), "Error", GMessageBox::Type::Error, GMessageBox::InputType::OK, window);
} else { } else {
file_system_model->update();
auto current_path = directory_view->path();
// not exactly sure why i have to reselect the root node first, but the index() fails if I dont
auto root_index = file_system_model->index(file_system_model->root_path());
tree_view->selection().set(root_index);
// reselect the existing folder in the tree
auto new_index = file_system_model->index(current_path);
tree_view->selection().set(new_index);
tree_view->scroll_into_view(new_index, Orientation::Vertical);
tree_view->update();
directory_view->refresh(); directory_view->refresh();
} }
} }

View file

@ -31,6 +31,15 @@ struct GFileSystemModel::Node {
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
void cleanup()
{
for (auto& child: children) {
child->cleanup();
delete child;
}
children.clear();
}
void traverse_if_needed(const GFileSystemModel& model) void traverse_if_needed(const GFileSystemModel& model)
{ {
if (type != Node::Directory || has_traversed) if (type != Node::Directory || has_traversed)
@ -146,15 +155,22 @@ GFileSystemModel::~GFileSystemModel()
void GFileSystemModel::update() void GFileSystemModel::update()
{ {
// FIXME: Support refreshing the model! cleanup();
if (m_root)
return;
m_root = new Node; m_root = new Node;
m_root->name = m_root_path; m_root->name = m_root_path;
m_root->reify_if_needed(*this); m_root->reify_if_needed(*this);
} }
void GFileSystemModel::cleanup()
{
if (m_root) {
m_root->cleanup();
delete m_root;
m_root = nullptr;
}
}
int GFileSystemModel::row_count(const GModelIndex& index) const int GFileSystemModel::row_count(const GModelIndex& index) const
{ {
if (!index.is_valid()) if (!index.is_valid())

View file

@ -37,6 +37,7 @@ private:
struct Node; struct Node;
Node* m_root { nullptr }; Node* m_root { nullptr };
void cleanup();
GIcon m_open_folder_icon; GIcon m_open_folder_icon;
GIcon m_closed_folder_icon; GIcon m_closed_folder_icon;

View file

@ -33,17 +33,27 @@ public:
template<typename Callback> template<typename Callback>
void for_each_index(Callback callback) void for_each_index(Callback callback)
{ {
for (auto& index : m_indexes) for (auto& index : indexes())
callback(index); callback(index);
} }
template<typename Callback> template<typename Callback>
void for_each_index(Callback callback) const void for_each_index(Callback callback) const
{ {
for (auto& index : m_indexes) for (auto& index : indexes())
callback(index); callback(index);
} }
Vector<GModelIndex> indexes() const
{
Vector<GModelIndex> selected_indexes;
for (auto& index : m_indexes)
selected_indexes.append(index);
return selected_indexes;
}
// FIXME: This doesn't guarantee that what you get is the lowest or "first" index selected.. // FIXME: This doesn't guarantee that what you get is the lowest or "first" index selected..
GModelIndex first() const GModelIndex first() const
{ {