diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2020-01-10 18:58:00 +0300 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2020-01-10 17:45:59 +0100 |
commit | fdeb91e000f57407334c7cfdd11ccd7c97dd51c6 (patch) | |
tree | 1e68a3045aebeb9e3bd04ea2eac5298651540b6d /Applications/FileManager | |
parent | 0f18a16e2c855a99e5c261793a8d36565b410a72 (diff) | |
download | serenity-fdeb91e000f57407334c7cfdd11ccd7c97dd51c6.zip |
LibGUI+FileManager: Merge GDirectoryModel into GFileSystemModel
We used to have two different models for displaying file system contents:
the FileManager-grade table-like directory model, which exposed rich data
(such as file icons with integrated image previews) about contents of a
single directory, and the tree-like GFileSystemModel, which only exposed
a tree of file names with very basic info about them.
This commit unifies the two. The new GFileSystemModel can be used both as a
tree-like and as a table-like model, or in fact in both ways simultaneously.
It exposes rich data about a file system subtree rooted at the given root.
The users of the two previous models are all ported to use this new model.
Diffstat (limited to 'Applications/FileManager')
-rw-r--r-- | Applications/FileManager/DirectoryView.cpp | 43 | ||||
-rw-r--r-- | Applications/FileManager/DirectoryView.h | 10 | ||||
-rw-r--r-- | Applications/FileManager/PropertiesDialog.cpp | 9 | ||||
-rw-r--r-- | Applications/FileManager/PropertiesDialog.h | 6 | ||||
-rw-r--r-- | Applications/FileManager/main.cpp | 44 |
5 files changed, 60 insertions, 52 deletions
diff --git a/Applications/FileManager/DirectoryView.cpp b/Applications/FileManager/DirectoryView.cpp index 9de5fa4b92..928a0a1e90 100644 --- a/Applications/FileManager/DirectoryView.cpp +++ b/Applications/FileManager/DirectoryView.cpp @@ -27,13 +27,13 @@ void DirectoryView::handle_activation(const GModelIndex& index) if (!index.is_valid()) return; dbgprintf("on activation: %d,%d, this=%p, m_model=%p\n", index.row(), index.column(), this, m_model.ptr()); - auto& entry = model().entry(index.row()); - auto path = canonicalized_path(String::format("%s/%s", model().path().characters(), entry.name.characters())); - if (entry.is_directory()) { + auto& node = model().node(index); + auto path = node.full_path(model()); + if (node.is_directory()) { open(path); return; } - if (entry.is_executable()) { + if (node.is_executable()) { if (fork() == 0) { int rc = execl(path.characters(), path.characters(), nullptr); if (rc < 0) @@ -83,7 +83,7 @@ void DirectoryView::handle_activation(const GModelIndex& index) DirectoryView::DirectoryView(GWidget* parent) : GStackWidget(parent) - , m_model(GDirectoryModel::create()) + , m_model(GFileSystemModel::create()) { set_active_widget(nullptr); m_item_view = GItemView::construct(this); @@ -92,22 +92,25 @@ DirectoryView::DirectoryView(GWidget* parent) m_table_view = GTableView::construct(this); m_table_view->set_model(GSortingProxyModel::create(m_model)); - m_table_view->model()->set_key_column_and_sort_order(GDirectoryModel::Column::Name, GSortOrder::Ascending); + m_table_view->model()->set_key_column_and_sort_order(GFileSystemModel::Column::Name, GSortOrder::Ascending); - m_item_view->set_model_column(GDirectoryModel::Column::Name); + m_item_view->set_model_column(GFileSystemModel::Column::Name); - m_model->on_path_change = [this] { + m_model->on_root_path_change = [this] { m_table_view->selection().clear(); m_item_view->selection().clear(); if (on_path_change) - on_path_change(model().path()); + on_path_change(model().root_path()); }; // NOTE: We're using the on_update hook on the GSortingProxyModel here instead of - // the GDirectoryModel's hook. This is because GSortingProxyModel has already - // installed an on_update hook on the GDirectoryModel internally. + // the GFileSystemModel's hook. This is because GSortingProxyModel has already + // installed an on_update hook on the GFileSystemModel internally. // FIXME: This is an unfortunate design. We should come up with something better. m_table_view->model()->on_update = [this] { + for_each_view_implementation([](auto& view) { + view.selection().clear(); + }); update_statusbar(); }; @@ -180,7 +183,7 @@ void DirectoryView::add_path_to_history(const StringView& path) void DirectoryView::open(const StringView& path) { add_path_to_history(path); - model().open(path); + model().set_root_path(path); } void DirectoryView::set_status_message(const StringView& message) @@ -191,9 +194,9 @@ void DirectoryView::set_status_message(const StringView& message) void DirectoryView::open_parent_directory() { - auto path = String::format("%s/..", model().path().characters()); + auto path = String::format("%s/..", model().root_path().characters()); add_path_to_history(path); - model().open(path); + model().set_root_path(path); } void DirectoryView::refresh() @@ -205,24 +208,25 @@ void DirectoryView::open_previous_directory() { if (m_path_history_position > 0) { m_path_history_position--; - model().open(m_path_history[m_path_history_position]); + model().set_root_path(m_path_history[m_path_history_position]); } } void DirectoryView::open_next_directory() { if (m_path_history_position < m_path_history.size() - 1) { m_path_history_position++; - model().open(m_path_history[m_path_history_position]); + model().set_root_path(m_path_history[m_path_history_position]); } } void DirectoryView::update_statusbar() { + size_t total_size = model().node({}).total_size; if (current_view().selection().is_empty()) { set_status_message(String::format("%d item%s (%s)", model().row_count(), model().row_count() != 1 ? "s" : "", - human_readable_size(model().bytes_in_files()).characters())); + human_readable_size(total_size).characters())); return; } @@ -230,8 +234,9 @@ void DirectoryView::update_statusbar() size_t selected_byte_count = 0; current_view().selection().for_each_index([&](auto& index) { - auto size_index = current_view().model()->index(index.row(), GDirectoryModel::Column::Size); - auto file_size = current_view().model()->data(size_index).to_int(); + auto& model = *current_view().model(); + auto size_index = model.sibling(index.row(), GFileSystemModel::Column::Size, model.parent_index(index)); + auto file_size = model.data(size_index).to_int(); selected_byte_count += file_size; }); diff --git a/Applications/FileManager/DirectoryView.h b/Applications/FileManager/DirectoryView.h index e9feeca8ba..2e314f8e60 100644 --- a/Applications/FileManager/DirectoryView.h +++ b/Applications/FileManager/DirectoryView.h @@ -1,7 +1,7 @@ #pragma once #include <AK/Vector.h> -#include <LibGUI/GDirectoryModel.h> +#include <LibGUI/GFileSystemModel.h> #include <LibGUI/GItemView.h> #include <LibGUI/GStackWidget.h> #include <LibGUI/GTableView.h> @@ -13,7 +13,7 @@ public: virtual ~DirectoryView() override; void open(const StringView& path); - String path() const { return model().path(); } + String path() const { return model().root_path(); } void open_parent_directory(); void open_previous_directory(); void open_next_directory(); @@ -55,11 +55,11 @@ public: callback(*m_item_view); } - GDirectoryModel& model() { return *m_model; } + GFileSystemModel& model() { return *m_model; } private: explicit DirectoryView(GWidget* parent); - const GDirectoryModel& model() const { return *m_model; } + const GFileSystemModel& model() const { return *m_model; } void handle_activation(const GModelIndex&); @@ -68,7 +68,7 @@ private: ViewMode m_view_mode { Invalid }; - NonnullRefPtr<GDirectoryModel> m_model; + NonnullRefPtr<GFileSystemModel> m_model; int m_path_history_position { 0 }; Vector<String> m_path_history; void add_path_to_history(const StringView& path); diff --git a/Applications/FileManager/PropertiesDialog.cpp b/Applications/FileManager/PropertiesDialog.cpp index bde03b9e53..9b7a67029b 100644 --- a/Applications/FileManager/PropertiesDialog.cpp +++ b/Applications/FileManager/PropertiesDialog.cpp @@ -9,7 +9,7 @@ #include <stdio.h> #include <unistd.h> -PropertiesDialog::PropertiesDialog(GDirectoryModel& model, String path, bool disable_rename, CObject* parent) +PropertiesDialog::PropertiesDialog(GFileSystemModel& model, String path, bool disable_rename, CObject* parent) : GDialog(parent) , m_model(model) { @@ -92,8 +92,8 @@ PropertiesDialog::PropertiesDialog(GDirectoryModel& model, String path, bool dis properties.append({ "Size:", String::format("%zu bytes", st.st_size) }); properties.append({ "Owner:", String::format("%s (%lu)", user_pw->pw_name, static_cast<u32>(user_pw->pw_uid)) }); properties.append({ "Group:", String::format("%s (%lu)", group_pw->pw_name, static_cast<u32>(group_pw->pw_uid)) }); - properties.append({ "Created at:", GDirectoryModel::timestamp_string(st.st_ctime) }); - properties.append({ "Last modified:", GDirectoryModel::timestamp_string(st.st_mtime) }); + properties.append({ "Created at:", GFileSystemModel::timestamp_string(st.st_ctime) }); + properties.append({ "Last modified:", GFileSystemModel::timestamp_string(st.st_mtime) }); make_property_value_pairs(properties, general_tab); @@ -127,7 +127,6 @@ PropertiesDialog::~PropertiesDialog() {} void PropertiesDialog::update() { - m_model.update(); m_icon->set_icon(const_cast<GraphicsBitmap*>(m_model.icon_for_file(m_mode, m_name).bitmap_for_size(32))); set_title(String::format("Properties of \"%s\"", m_name.characters())); } @@ -146,7 +145,7 @@ void PropertiesDialog::permission_changed(mode_t mask, bool set) String PropertiesDialog::make_full_path(String name) { - return String::format("%s/%s", m_model.path().characters(), name.characters()); + return String::format("%s/%s", m_model.root_path().characters(), name.characters()); } bool PropertiesDialog::apply_changes() diff --git a/Applications/FileManager/PropertiesDialog.h b/Applications/FileManager/PropertiesDialog.h index d4f3e6d709..7561eee805 100644 --- a/Applications/FileManager/PropertiesDialog.h +++ b/Applications/FileManager/PropertiesDialog.h @@ -4,7 +4,7 @@ #include <LibCore/CFile.h> #include <LibGUI/GButton.h> #include <LibGUI/GDialog.h> -#include <LibGUI/GDirectoryModel.h> +#include <LibGUI/GFileSystemModel.h> #include <LibGUI/GLabel.h> #include <LibGUI/GTextBox.h> @@ -14,7 +14,7 @@ public: virtual ~PropertiesDialog() override; private: - explicit PropertiesDialog(GDirectoryModel&, String, bool disable_rename, CObject* parent = nullptr); + PropertiesDialog(GFileSystemModel&, String, bool disable_rename, CObject* parent = nullptr); struct PropertyValuePair { String property; @@ -58,7 +58,7 @@ private: void update(); String make_full_path(String name); - GDirectoryModel& m_model; + GFileSystemModel& m_model; RefPtr<GButton> m_apply_button; RefPtr<GTextBox> m_name_box; RefPtr<GLabel> m_icon; diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index 118d6ae6ef..d3f64ba9f8 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -70,10 +70,17 @@ int main(int argc, char** argv) auto splitter = GSplitter::construct(Orientation::Horizontal, widget); auto tree_view = GTreeView::construct(splitter); - auto file_system_model = GFileSystemModel::create("/", GFileSystemModel::Mode::DirectoriesOnly); - tree_view->set_model(file_system_model); + auto directories_model = GFileSystemModel::create("/", GFileSystemModel::Mode::DirectoriesOnly); + tree_view->set_model(directories_model); + tree_view->set_column_hidden(GFileSystemModel::Column::Icon, true); + tree_view->set_column_hidden(GFileSystemModel::Column::Size, true); + tree_view->set_column_hidden(GFileSystemModel::Column::Owner, true); + tree_view->set_column_hidden(GFileSystemModel::Column::Group, true); + tree_view->set_column_hidden(GFileSystemModel::Column::Permissions, true); + tree_view->set_column_hidden(GFileSystemModel::Column::ModificationTime, true); + tree_view->set_column_hidden(GFileSystemModel::Column::Inode, true); tree_view->set_size_policy(SizePolicy::Fixed, SizePolicy::Fill); - tree_view->set_preferred_size(200, 0); + tree_view->set_preferred_size(150, 0); auto directory_view = DirectoryView::construct(splitter); auto statusbar = GStatusBar::construct(widget); @@ -91,7 +98,7 @@ int main(int argc, char** argv) }; auto refresh_tree_view = [&] { - file_system_model->update(); + directories_model->update(); auto current_path = directory_view->path(); @@ -100,17 +107,13 @@ int main(int argc, char** argv) while (lstat(current_path.characters(), &st) != 0) { directory_view->open_parent_directory(); current_path = directory_view->path(); - if (current_path == file_system_model->root_path()) { + if (current_path == directories_model->root_path()) { break; } } - // 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); + // Reselect the existing folder in the tree. + auto new_index = directories_model->index(current_path, GFileSystemModel::Column::Name); tree_view->selection().set(new_index); tree_view->scroll_into_view(new_index, Orientation::Vertical); tree_view->update(); @@ -175,7 +178,8 @@ int main(int argc, char** argv) auto& view = directory_view->current_view(); auto& model = *view.model(); view.selection().for_each_index([&](const GModelIndex& index) { - auto name_index = model.index(index.row(), GDirectoryModel::Column::Name); + auto parent_index = model.parent_index(index); + auto name_index = model.index(index.row(), GFileSystemModel::Column::Name, parent_index); auto path = model.data(name_index, GModel::Role::Custom).to_string(); paths.append(path); }); @@ -186,7 +190,7 @@ int main(int argc, char** argv) Vector<String> paths; auto& view = tree_view; view->selection().for_each_index([&](const GModelIndex& index) { - paths.append(file_system_model->path(index)); + paths.append(directories_model->full_path(index)); }); return paths; }; @@ -254,9 +258,10 @@ int main(int argc, char** argv) path = directory_view->path(); selected = selected_file_paths(); } else { - path = file_system_model->path(tree_view->selection().first()); + path = directories_model->full_path(tree_view->selection().first()); selected = tree_view_selected_file_paths(); } + RefPtr<PropertiesDialog> properties; if (selected.is_empty()) { properties = PropertiesDialog::construct(model, path, true, window); @@ -413,7 +418,7 @@ int main(int argc, char** argv) directory_view->on_path_change = [&](const String& new_path) { window->set_title(String::format("File Manager: %s", new_path.characters())); location_textbox->set_text(new_path); - auto new_index = file_system_model->index(new_path); + auto new_index = directories_model->index(new_path, GFileSystemModel::Column::Name); if (new_index.is_valid()) { tree_view->selection().set(new_index); tree_view->scroll_into_view(new_index, Orientation::Vertical); @@ -482,20 +487,19 @@ int main(int argc, char** argv) directory_view->on_context_menu_request = [&](const GAbstractView&, const GModelIndex& index, const GContextMenuEvent& event) { if (index.is_valid()) { - auto& entry = directory_view->model().entry(index.row()); + auto& node = directory_view->model().node(index); - if (entry.is_directory()) { + if (node.is_directory()) directory_context_menu->popup(event.screen_position()); - } else { + else file_context_menu->popup(event.screen_position()); - } } else { directory_view_context_menu->popup(event.screen_position()); } }; tree_view->on_selection_change = [&] { - auto path = file_system_model->path(tree_view->selection().first()); + auto path = directories_model->full_path(tree_view->selection().first()); if (directory_view->path() == path) return; directory_view->open(path); |