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:
parent
caf1b37e75
commit
a4d52b122d
4 changed files with 46 additions and 5 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue