mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-08 04:50:08 +03:00
HackStudio: Keep the DeclarationsModel around, and use a filtering proxy
Rather than construct a new DeclarationsModel each time the user types something in the Locator, keep a single one around permanently in the ProjectDeclarations, and then use a FilteringProxyModel over it for the suggestions.
This commit is contained in:
parent
e72b14ef1d
commit
85101c6626
Notes:
sideshowbarker
2024-07-17 14:33:07 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/85101c6626 Pull-request: https://github.com/SerenityOS/serenity/pull/22938
@ -57,4 +57,35 @@ GUI::Variant DeclarationsModel::data(GUI::ModelIndex const& index, GUI::ModelRol
|
||||
return {};
|
||||
}
|
||||
|
||||
GUI::Model::MatchResult DeclarationsModel::data_matches(GUI::ModelIndex const& index, GUI::Variant const& term) const
|
||||
{
|
||||
if (index.row() < 0 || (size_t)index.row() >= m_declarations.size())
|
||||
return { TriState::False };
|
||||
|
||||
auto needle = term.as_string();
|
||||
if (needle.is_empty())
|
||||
return { TriState::True };
|
||||
|
||||
auto& declaration = m_declarations[index.row()];
|
||||
if (declaration.is_filename()) {
|
||||
if (declaration.as_filename->contains(needle, CaseSensitivity::CaseInsensitive))
|
||||
return { TriState::True };
|
||||
return { TriState::False };
|
||||
}
|
||||
if (declaration.is_symbol_declaration()) {
|
||||
if (declaration.as_symbol_declaration->name.contains(needle, CaseSensitivity::CaseInsensitive)
|
||||
|| declaration.as_symbol_declaration->scope.contains(needle, CaseSensitivity::CaseInsensitive))
|
||||
return { TriState::True };
|
||||
return { TriState::False };
|
||||
}
|
||||
|
||||
return { TriState::False };
|
||||
}
|
||||
|
||||
void DeclarationsModel::set_declarations(Vector<HackStudio::Declaration>&& declarations)
|
||||
{
|
||||
m_declarations = move(declarations);
|
||||
did_update();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,8 +48,10 @@ public:
|
||||
|
||||
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Column_Count; }
|
||||
virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override;
|
||||
virtual MatchResult data_matches(GUI::ModelIndex const&, GUI::Variant const&) const override;
|
||||
|
||||
Vector<Declaration> const& declarations() const { return m_declarations; }
|
||||
void set_declarations(Vector<Declaration>&&);
|
||||
|
||||
private:
|
||||
Vector<Declaration> m_declarations;
|
||||
|
@ -77,12 +77,15 @@ Locator::Locator(Core::EventReceiver* parent)
|
||||
m_suggestion_view->on_activation = [this](auto& index) {
|
||||
open_suggestion(index);
|
||||
};
|
||||
|
||||
m_model = GUI::FilteringProxyModel::create(ProjectDeclarations::the().declarations_model()).release_value_but_fixme_should_propagate_errors();
|
||||
m_suggestion_view->set_model(m_model);
|
||||
}
|
||||
|
||||
void Locator::open_suggestion(const GUI::ModelIndex& index)
|
||||
{
|
||||
auto& model = reinterpret_cast<DeclarationsModel&>(*m_suggestion_view->model());
|
||||
auto suggestion = model.declarations()[index.row()];
|
||||
auto original_index = m_model->map(index);
|
||||
auto suggestion = ProjectDeclarations::the().declarations_model().declarations()[original_index.row()];
|
||||
if (suggestion.is_filename()) {
|
||||
auto filename = suggestion.as_filename.value();
|
||||
open_file(filename);
|
||||
@ -111,23 +114,9 @@ void Locator::close()
|
||||
|
||||
void Locator::update_suggestions()
|
||||
{
|
||||
auto typed_text = m_textbox->text();
|
||||
Vector<Declaration> suggestions;
|
||||
project().for_each_text_file([&](auto& file) {
|
||||
if (file.name().contains(typed_text, CaseSensitivity::CaseInsensitive))
|
||||
suggestions.append(Declaration::create_filename(file.name()));
|
||||
});
|
||||
m_model->set_filter_term(m_textbox->text());
|
||||
|
||||
ProjectDeclarations::the().for_each_declared_symbol([&suggestions, &typed_text](auto& decl) {
|
||||
if (decl.name.contains(typed_text, CaseSensitivity::CaseInsensitive) || decl.scope.contains(typed_text, CaseSensitivity::CaseInsensitive))
|
||||
suggestions.append((Declaration::create_symbol_declaration(decl)));
|
||||
});
|
||||
|
||||
bool has_suggestions = !suggestions.is_empty();
|
||||
|
||||
m_suggestion_view->set_model(adopt_ref(*new DeclarationsModel(move(suggestions))));
|
||||
|
||||
if (!has_suggestions)
|
||||
if (m_model->row_count() == 0)
|
||||
m_suggestion_view->selection().clear();
|
||||
else
|
||||
m_suggestion_view->selection().set(m_suggestion_view->model()->index(0));
|
||||
|
@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibGUI/FilteringProxyModel.h>
|
||||
#include <LibGUI/Widget.h>
|
||||
|
||||
namespace HackStudio {
|
||||
@ -29,6 +30,7 @@ private:
|
||||
RefPtr<GUI::TextBox> m_textbox;
|
||||
RefPtr<GUI::Window> m_popup_window;
|
||||
RefPtr<GUI::TableView> m_suggestion_view;
|
||||
RefPtr<GUI::FilteringProxyModel> m_model;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,24 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "ProjectDeclarations.h"
|
||||
#include "HackStudio.h"
|
||||
|
||||
HackStudio::ProjectDeclarations& HackStudio::ProjectDeclarations::the()
|
||||
namespace HackStudio {
|
||||
|
||||
ProjectDeclarations::ProjectDeclarations()
|
||||
: m_declarations_model(adopt_ref(*new DeclarationsModel({})))
|
||||
{
|
||||
}
|
||||
|
||||
ProjectDeclarations& ProjectDeclarations::the()
|
||||
{
|
||||
static ProjectDeclarations s_instance;
|
||||
return s_instance;
|
||||
}
|
||||
void HackStudio::ProjectDeclarations::set_declared_symbols(ByteString const& filename, Vector<CodeComprehension::Declaration> const& declarations)
|
||||
void ProjectDeclarations::set_declared_symbols(ByteString const& filename, Vector<CodeComprehension::Declaration> const& declarations)
|
||||
{
|
||||
m_document_to_declarations.set(filename, declarations);
|
||||
// FIXME: Partially invalidate the model instead of fully rebuilding it.
|
||||
update_declarations_model();
|
||||
if (on_update)
|
||||
on_update();
|
||||
}
|
||||
|
||||
Optional<GUI::Icon> HackStudio::ProjectDeclarations::get_icon_for(CodeComprehension::DeclarationType type)
|
||||
Optional<GUI::Icon> ProjectDeclarations::get_icon_for(CodeComprehension::DeclarationType type)
|
||||
{
|
||||
static GUI::Icon struct_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Struct.png"sv).release_value_but_fixme_should_propagate_errors());
|
||||
static GUI::Icon class_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Class.png"sv).release_value_but_fixme_should_propagate_errors());
|
||||
@ -46,3 +57,17 @@ Optional<GUI::Icon> HackStudio::ProjectDeclarations::get_icon_for(CodeComprehens
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectDeclarations::update_declarations_model()
|
||||
{
|
||||
Vector<Declaration> declarations;
|
||||
project().for_each_text_file([&](auto& file) {
|
||||
declarations.append(Declaration::create_filename(file.name()));
|
||||
});
|
||||
for_each_declared_symbol([&declarations](auto& decl) {
|
||||
declarations.append((Declaration::create_symbol_declaration(decl)));
|
||||
});
|
||||
m_declarations_model->set_declarations(move(declarations));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DeclarationsModel.h"
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/HashMap.h>
|
||||
@ -25,13 +27,18 @@ public:
|
||||
|
||||
void set_declared_symbols(ByteString const& filename, Vector<CodeComprehension::Declaration> const&);
|
||||
|
||||
DeclarationsModel& declarations_model() { return m_declarations_model; }
|
||||
void update_declarations_model();
|
||||
|
||||
static Optional<GUI::Icon> get_icon_for(CodeComprehension::DeclarationType);
|
||||
|
||||
Function<void()> on_update = nullptr;
|
||||
|
||||
private:
|
||||
ProjectDeclarations() = default;
|
||||
ProjectDeclarations();
|
||||
|
||||
HashMap<ByteString, Vector<CodeComprehension::Declaration>> m_document_to_declarations;
|
||||
NonnullRefPtr<DeclarationsModel> m_declarations_model;
|
||||
};
|
||||
|
||||
template<typename Func>
|
||||
|
Loading…
Reference in New Issue
Block a user