mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
FileManager: Make the tree view follow the directory view navigations.
This commit is contained in:
parent
f10e0d0546
commit
2c6a597d77
Notes:
sideshowbarker
2024-07-19 14:53:45 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/2c6a597d776
10 changed files with 72 additions and 3 deletions
|
@ -40,6 +40,7 @@ bool FileSystemPath::canonicalize(bool resolve_symbolic_links)
|
|||
builder.append('/');
|
||||
builder.append(cpart);
|
||||
}
|
||||
m_parts = move(canonical_parts);
|
||||
m_string = builder.to_string();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@ public:
|
|||
|
||||
String basename() const { return m_basename; }
|
||||
|
||||
const Vector<String>& parts() const { return m_parts; }
|
||||
|
||||
private:
|
||||
bool canonicalize(bool resolve_symbolic_links = false);
|
||||
|
||||
Vector<String> m_parts;
|
||||
String m_string;
|
||||
String m_basename;
|
||||
bool m_is_valid { false };
|
||||
|
|
|
@ -166,9 +166,12 @@ int main(int argc, char** argv)
|
|||
main_toolbar->add_action(view_as_icons_action.copy_ref());
|
||||
main_toolbar->add_action(view_as_table_action.copy_ref());
|
||||
|
||||
directory_view->on_path_change = [window, location_textbox] (const String& new_path) {
|
||||
directory_view->on_path_change = [window, location_textbox, &file_system_model, tree_view] (const String& new_path) {
|
||||
window->set_title(String::format("FileManager: %s", new_path.characters()));
|
||||
location_textbox->set_text(new_path);
|
||||
file_system_model->set_selected_index(file_system_model->index(new_path));
|
||||
tree_view->scroll_into_view(file_system_model->selected_index(), Orientation::Vertical);
|
||||
tree_view->update();
|
||||
};
|
||||
|
||||
directory_view->on_status_message = [statusbar] (String message) {
|
||||
|
|
|
@ -35,3 +35,7 @@ void GAbstractView::did_update_model()
|
|||
{
|
||||
model_notification(GModelNotification(GModelNotification::ModelUpdated));
|
||||
}
|
||||
|
||||
void GAbstractView::did_update_selection()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -14,10 +14,9 @@ public:
|
|||
GModel* model() { return m_model.ptr(); }
|
||||
const GModel* model() const { return m_model.ptr(); }
|
||||
|
||||
void scroll_into_view(const GModelIndex&, Orientation);
|
||||
|
||||
virtual bool accepts_focus() const override { return true; }
|
||||
virtual void did_update_model();
|
||||
virtual void did_update_selection();
|
||||
|
||||
Function<void(const GModelNotification&)> on_model_notification;
|
||||
|
||||
|
|
|
@ -92,6 +92,30 @@ struct GFileSystemModel::Node {
|
|||
}
|
||||
};
|
||||
|
||||
GModelIndex GFileSystemModel::index(const String& path) const
|
||||
{
|
||||
FileSystemPath canonical_path(path);
|
||||
const Node* node = m_root;
|
||||
if (canonical_path.string() == "/")
|
||||
return m_root->index(*this);
|
||||
for (int i = 0; i < canonical_path.parts().size(); ++i) {
|
||||
auto& part = canonical_path.parts()[i];
|
||||
bool found = false;
|
||||
for (auto& child : node->children) {
|
||||
if (child->name == part) {
|
||||
node = child;
|
||||
found = true;
|
||||
if (i == canonical_path.parts().size() - 1)
|
||||
return node->index(*this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return { };
|
||||
}
|
||||
return { };
|
||||
}
|
||||
|
||||
String GFileSystemModel::path(const GModelIndex& index) const
|
||||
{
|
||||
if (!index.is_valid())
|
||||
|
|
|
@ -15,6 +15,7 @@ public:
|
|||
|
||||
String root_path() const { return m_root_path; }
|
||||
String path(const GModelIndex&) const;
|
||||
GModelIndex index(const String& path) const;
|
||||
|
||||
virtual int row_count(const GModelIndex& = GModelIndex()) const override;
|
||||
virtual int column_count(const GModelIndex& = GModelIndex()) const override;
|
||||
|
|
|
@ -41,6 +41,9 @@ void GModel::set_selected_index(const GModelIndex& index)
|
|||
m_selected_index = index;
|
||||
if (on_selection_changed)
|
||||
on_selection_changed(index);
|
||||
for_each_view([] (auto& view) {
|
||||
view.did_update_selection();
|
||||
});
|
||||
if (m_activates_on_selection && is_valid(index))
|
||||
activate(index);
|
||||
}
|
||||
|
|
|
@ -270,3 +270,32 @@ void GTreeView::paint_event(GPaintEvent& event)
|
|||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
void GTreeView::scroll_into_view(const GModelIndex& a_index, Orientation orientation)
|
||||
{
|
||||
if (!a_index.is_valid())
|
||||
return;
|
||||
Rect found_rect;
|
||||
traverse_in_paint_order([&] (const GModelIndex& index, const Rect& rect, int) {
|
||||
if (index == a_index) {
|
||||
found_rect = rect;
|
||||
return IterationDecision::Abort;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
GScrollableWidget::scroll_into_view(found_rect, orientation);
|
||||
}
|
||||
|
||||
void GTreeView::did_update_selection()
|
||||
{
|
||||
ASSERT(model());
|
||||
auto& model = *this->model();
|
||||
auto index = model.selected_index();
|
||||
if (!index.is_valid())
|
||||
return;
|
||||
auto parent = index.parent();
|
||||
while (parent.is_valid()) {
|
||||
ensure_metadata_for_index(parent).open = true;
|
||||
parent = parent.parent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ public:
|
|||
explicit GTreeView(GWidget*);
|
||||
virtual ~GTreeView() override;
|
||||
|
||||
virtual void scroll_into_view(const GModelIndex&, Orientation);
|
||||
virtual const char* class_name() const override { return "GTreeView"; }
|
||||
|
||||
GModelIndex index_at_content_position(const Point&) const;
|
||||
|
@ -14,6 +15,7 @@ public:
|
|||
protected:
|
||||
virtual void paint_event(GPaintEvent&) override;
|
||||
virtual void mousedown_event(GMouseEvent&) override;
|
||||
virtual void did_update_selection() override;
|
||||
|
||||
private:
|
||||
int item_height() const { return 16; }
|
||||
|
|
Loading…
Reference in a new issue