فهرست منبع

FileManager: Make the tree view follow the directory view navigations.

Andreas Kling 6 سال پیش
والد
کامیت
2c6a597d77

+ 1 - 0
AK/FileSystemPath.cpp

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

+ 3 - 0
AK/FileSystemPath.h

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

+ 4 - 1
Applications/FileManager/main.cpp

@@ -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) {

+ 4 - 0
LibGUI/GAbstractView.cpp

@@ -35,3 +35,7 @@ void GAbstractView::did_update_model()
 {
     model_notification(GModelNotification(GModelNotification::ModelUpdated));
 }
+
+void GAbstractView::did_update_selection()
+{
+}

+ 1 - 2
LibGUI/GAbstractView.h

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

+ 24 - 0
LibGUI/GFileSystemModel.cpp

@@ -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())

+ 1 - 0
LibGUI/GFileSystemModel.h

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

+ 3 - 0
LibGUI/GModel.cpp

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

+ 29 - 0
LibGUI/GTreeView.cpp

@@ -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();
+    }
+}

+ 2 - 0
LibGUI/GTreeView.h

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