Skip to content

Commit

Permalink
improved search in tables and codeboxes to list and select all the in…
Browse files Browse the repository at this point in the history
…stances (#2155, #2444)
  • Loading branch information
giuspen committed Mar 14, 2024
1 parent 510f29f commit 5de848d
Show file tree
Hide file tree
Showing 12 changed files with 561 additions and 148 deletions.
30 changes: 17 additions & 13 deletions src/ct/ct_actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,23 +226,27 @@ class CtActions
Gtk::TextIter start_iter,
bool forward,
bool all_matches);
const size_t _line_content_limit{100u};
Glib::ustring _get_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer,
const int match_end_offset);
Glib::ustring _get_first_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer);
Glib::ustring _check_pattern_in_object(Glib::RefPtr<Glib::Regex> pattern,
CtAnchoredWidget* obj);
std::pair<int, int> _check_pattern_in_object_between(CtTreeIter tree_iter,
Glib::RefPtr<Gtk::TextBuffer> text_buffer,
Glib::RefPtr<Glib::Regex> pattern,
int start_offset,
int end_offset,
bool forward,
Glib::ustring& obj_content);
bool _check_pattern_in_object(Glib::RefPtr<Glib::Regex> re_pattern,
CtAnchoredWidget* pAnchWidg,
CtAnchMatchList& anchMatchList);
bool _check_pattern_in_object_between(CtTreeIter tree_iter,
Glib::RefPtr<Glib::Regex> pattern,
int start_offset,
int end_offset,
const bool forward,
const bool all_matches,
CtAnchMatchList& anchMatchList);
int _get_num_objs_before_offset(Glib::RefPtr<Gtk::TextBuffer> text_buffer, int max_offset);
void _update_all_matches_progress();
public:
void find_matches_store_reset();
static void find_match_in_obj_focus(const int obj_offset,
Glib::RefPtr<Gtk::TextBuffer> pTextBuffer,
const CtTreeIter& tree_iter,
const CtAnchWidgType anch_type,
const size_t anch_cell_idx,
const int anch_offs_start,
const int anch_offs_end);

public:
// find actions
Expand Down
447 changes: 331 additions & 116 deletions src/ct/ct_actions_find.cc

Large diffs are not rendered by default.

26 changes: 21 additions & 5 deletions src/ct/ct_dialogs.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ struct CtMatchRowData {
int end_offset;
int line_num;
Glib::ustring line_content;
CtAnchWidgType anch_type;
int anch_cell_idx;
int anch_offs_start;
int anch_offs_end;
};
class CtMatchDialogStore : public Gtk::ListStore
{
Expand All @@ -105,6 +109,10 @@ class CtMatchDialogStore : public Gtk::ListStore
Gtk::TreeModelColumn<int> end_offset;
Gtk::TreeModelColumn<int> line_num;
Gtk::TreeModelColumn<Glib::ustring> line_content;
Gtk::TreeModelColumn<CtAnchWidgType> anch_type;
Gtk::TreeModelColumn<int> anch_cell_idx;
Gtk::TreeModelColumn<int> anch_offs_start;
Gtk::TreeModelColumn<int> anch_offs_end;
CtMatchModelColumns() {
add(node_id);
add(node_name);
Expand All @@ -113,6 +121,10 @@ class CtMatchDialogStore : public Gtk::ListStore
add(end_offset);
add(line_num);
add(line_content);
add(anch_type);
add(anch_cell_idx);
add(anch_offs_start);
add(anch_offs_end);
}
} columns;
std::array<int, 2> dlg_size{0,0};
Expand All @@ -122,13 +134,17 @@ class CtMatchDialogStore : public Gtk::ListStore
static Glib::RefPtr<CtMatchDialogStore> create(const size_t maxMatchesInPage);

void deep_clear();
CtMatchRowData* add_row(gint64 node_id,
CtMatchRowData* add_row(const gint64 node_id,
const Glib::ustring& node_name,
const Glib::ustring& node_hier_name,
int start_offset,
int end_offset,
int line_num,
const Glib::ustring& line_content);
const int start_offset,
const int end_offset,
const int line_num,
const Glib::ustring& line_content,
const CtAnchWidgType anch_type,
const int anch_cell_idx,
const int anch_offs_start,
const int anch_offs_end);
void load_current_page();
void load_next_page();
void load_prev_page();
Expand Down
51 changes: 41 additions & 10 deletions src/ct/ct_dialogs_find.cc
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,17 @@ void CtMatchDialogStore::deep_clear()
_all_matches.clear();
}

CtMatchRowData* CtMatchDialogStore::add_row(gint64 node_id,
CtMatchRowData* CtMatchDialogStore::add_row(const gint64 node_id,
const Glib::ustring& node_name,
const Glib::ustring& node_hier_name,
int start_offset,
int end_offset,
int line_num,
const Glib::ustring& line_content)
const int start_offset,
const int end_offset,
const int line_num,
const Glib::ustring& line_content,
const CtAnchWidgType anch_type,
const int anch_cell_idx,
const int anch_offs_start,
const int anch_offs_end)
{
_all_matches.push_back(CtMatchRowData{
.node_id = node_id,
Expand All @@ -396,7 +400,11 @@ CtMatchRowData* CtMatchDialogStore::add_row(gint64 node_id,
.start_offset = start_offset,
.end_offset = end_offset,
.line_num = line_num,
.line_content = line_content
.line_content = line_content,
.anch_type = anch_type,
.anch_cell_idx = anch_cell_idx,
.anch_offs_start = anch_offs_start,
.anch_offs_end = anch_offs_end
});
return &_all_matches.back();
}
Expand Down Expand Up @@ -484,6 +492,10 @@ Gtk::TreeIter CtMatchDialogStore::_add_row(const CtMatchRowData& row_data) {
row[columns.end_offset] = row_data.end_offset;
row[columns.line_num] = row_data.line_num;
row[columns.line_content] = row_data.line_content;
row[columns.anch_type] = row_data.anch_type;
row[columns.anch_cell_idx] = row_data.anch_cell_idx;
row[columns.anch_offs_start] = row_data.anch_offs_start;
row[columns.anch_offs_end] = row_data.anch_offs_end;
return retIter;
}

Expand Down Expand Up @@ -542,10 +554,12 @@ void CtDialogs::match_dialog(const std::string& str_find,

auto select_found_line = [pTreeview, &s_state, pCtMainWin](){
if (s_state.in_loading) {
//spdlog::debug("in_loading");
return;
}
Gtk::TreeIter list_iter = pTreeview->get_selection()->get_selected();
if (not list_iter) {
//spdlog::debug("!get_selected");
return;
}
gint64 node_id = list_iter->get_value(s_state.match_store->columns.node_id);
Expand All @@ -558,14 +572,31 @@ void CtDialogs::match_dialog(const std::string& str_find,
}
// remove previous selection because it can cause freezing in specific cases, see more in issue
auto fake_iter = pCtMainWin->get_text_view().get_buffer()->get_iter_at_offset(-1);
pCtMainWin->get_text_view().get_buffer()->place_cursor(fake_iter);
auto rCurrBuffer = pCtMainWin->get_text_view().get_buffer();
rCurrBuffer->place_cursor(fake_iter);

pCtMainWin->get_tree_view().set_cursor_safe(tree_iter);
auto rCurrBuffer = pCtMainWin->get_text_view().get_buffer();
rCurrBuffer->select_range(rCurrBuffer->get_iter_at_offset(list_iter->get_value(s_state.match_store->columns.start_offset)),
rCurrBuffer->get_iter_at_offset(list_iter->get_value(s_state.match_store->columns.end_offset)));
const int start_offset = list_iter->get_value(s_state.match_store->columns.start_offset);
const int end_offset = list_iter->get_value(s_state.match_store->columns.end_offset);
rCurrBuffer->select_range(rCurrBuffer->get_iter_at_offset(start_offset),
rCurrBuffer->get_iter_at_offset(end_offset));
pCtMainWin->get_text_view().scroll_to(rCurrBuffer->get_insert(), CtTextView::TEXT_SCROLL_MARGIN);

const CtAnchWidgType anch_type = list_iter->get_value(s_state.match_store->columns.anch_type);
//spdlog::debug("anch_type={}", static_cast<int>(anch_type));
if (CtAnchWidgType::None != anch_type) {
const size_t anch_cell_idx = list_iter->get_value(s_state.match_store->columns.anch_cell_idx);
const int anch_offs_start = list_iter->get_value(s_state.match_store->columns.anch_offs_start);
const int anch_offs_end = list_iter->get_value(s_state.match_store->columns.anch_offs_end);
CtActions::find_match_in_obj_focus(start_offset,
rCurrBuffer,
tree_iter,
anch_type,
anch_cell_idx,
anch_offs_start,
anch_offs_end);
}

// pump events so UI's not going to freeze (#835)
while (gdk_events_pending())
gtk_main_iteration();
Expand Down
51 changes: 51 additions & 0 deletions src/ct/ct_misc_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,57 @@ int CtTextIterUtil::get_words_count(const Glib::RefPtr<Gtk::TextBuffer>& text_bu
return words;
}

// Returns the Line Content Given the Text Iter
Glib::ustring CtTextIterUtil::get_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer, const int match_end_offset)
{
Gtk::TextIter line_start = text_buffer->get_iter_at_offset(match_end_offset);
Gtk::TextIter line_end = line_start;
if (not line_start.backward_char()) return "";
while (line_start.get_char() != '\n')
if (not line_start.backward_char())
break;
if (line_start.get_char() == '\n')
line_start.forward_char();
while (line_end.get_char() != '\n')
if (not line_end.forward_char())
break;
Glib::ustring line_content = text_buffer->get_text(line_start, line_end);
return line_content.size() <= LINE_CONTENT_LIMIT ?
line_content : line_content.substr(0u, LINE_CONTENT_LIMIT) + "...";
}

Glib::ustring CtTextIterUtil::get_line_content(const Glib::ustring& text_multiline, const int match_end_offset)
{
std::vector<Glib::ustring> splitted = str::split(text_multiline, "\n");
int sum_rows_chars{0};
for (const Glib::ustring& line_content : splitted) {
sum_rows_chars += line_content.size();
++sum_rows_chars; // newline
if (sum_rows_chars >= match_end_offset) {
return line_content.size() <= LINE_CONTENT_LIMIT ?
line_content : line_content.substr(0u, LINE_CONTENT_LIMIT) + "...";
}
}
spdlog::warn("!! {} offs {}", __FUNCTION__, match_end_offset);
return "!?";
}

// Returns the First Not Empty Line Content Given the Text Buffer
Glib::ustring CtTextIterUtil::get_first_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer)
{
Gtk::TextIter start_iter = text_buffer->get_iter_at_offset(0);
while (start_iter.get_char() == '\n')
if (not start_iter.forward_char())
return "";
Gtk::TextIter end_iter = start_iter;
while (end_iter.get_char() != '\n')
if (not end_iter.forward_char())
break;
Glib::ustring line_content = text_buffer->get_text(start_iter, end_iter);
return line_content.size() <= LINE_CONTENT_LIMIT ?
line_content : line_content.substr(0u, LINE_CONTENT_LIMIT) + "...";
}

// copied from https://gitlab.gnome.org/GNOME/gtk.git origin/gtk-3-24 gtkpango.c _gtk_pango_unichar_direction
PangoDirection CtStrUtil::gtk_pango_unichar_direction(gunichar ch)
{
Expand Down
5 changes: 5 additions & 0 deletions src/ct/ct_misc_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ PangoDirection get_pango_direction(const Gtk::TextIter& textIter);

int get_words_count(const Glib::RefPtr<Gtk::TextBuffer>& text_buffer);

const inline static size_t LINE_CONTENT_LIMIT{100u};
Glib::ustring get_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer, const int match_end_offset);
Glib::ustring get_line_content(const Glib::ustring& text_multiline, const int match_end_offset);
Glib::ustring get_first_line_content(Glib::RefPtr<Gtk::TextBuffer> text_buffer);

} // namespace CtTextIterUtil

namespace CtStrUtil {
Expand Down
40 changes: 39 additions & 1 deletion src/ct/ct_table.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* ct_table.cc
*
* Copyright 2009-2023
* Copyright 2009-2024
* Giuseppe Penone <giuspen@gmail.com>
* Evgenii Gurianov <https://github.com/txe>
*
Expand Down Expand Up @@ -65,6 +65,22 @@ void CtTableCommon::row_move_down(const size_t rowIdx)
grab_focus();
}

void CtTableCommon::set_current_row_column(const size_t rowIdx, const size_t colIdx)
{
if (rowIdx < get_num_rows()) {
_currentRow = rowIdx;
}
else {
spdlog::warn("?? {} row {} >= {}", __FUNCTION__, rowIdx, get_num_rows());
}
if (colIdx < get_num_columns()) {
_currentColumn = colIdx;
}
else {
spdlog::warn("?? {} col {} >= {}", __FUNCTION__, colIdx, get_num_columns());
}
}

bool CtTableCommon::on_table_button_press_event(GdkEventButton* event)
{
_pCtMainWin->get_ct_actions()->curr_table_anchor = this;
Expand Down Expand Up @@ -593,11 +609,33 @@ void CtTableHeavy::grab_focus() const
static_cast<CtTextCell*>(_tableMatrix.at(current_row()).at(current_column()))->get_text_view().grab_focus();
}

void CtTableHeavy::set_selection_at_offset_n_delta(const int offset, const int delta) const
{
curr_cell_text_view().set_selection_at_offset_n_delta(offset, delta);
}

CtTextView& CtTableHeavy::curr_cell_text_view() const
{
return static_cast<CtTextCell*>(_tableMatrix.at(current_row()).at(current_column()))->get_text_view();
}

Glib::RefPtr<Gsv::Buffer> CtTableHeavy::get_buffer(const size_t rowIdx, const size_t colIdx) const
{
if (rowIdx < get_num_rows() and colIdx < get_num_columns()) {
return static_cast<CtTextCell*>(_tableMatrix.at(rowIdx).at(colIdx))->get_buffer();
}
return Glib::RefPtr<Gsv::Buffer>{};
}

Glib::ustring CtTableHeavy::get_line_content(size_t rowIdx, size_t colIdx, int match_end_offset) const
{
Glib::RefPtr<Gsv::Buffer> pBuffer = get_buffer(rowIdx, colIdx);
if (pBuffer) {
return CtTextIterUtil::get_line_content(pBuffer, match_end_offset);
}
return "!?";
}

void CtTableHeavy::_on_grid_set_focus_child(Gtk::Widget* pWidget)
{
for (size_t rowIdx = 0; rowIdx < get_num_rows(); ++rowIdx) {
Expand Down
Loading

0 comments on commit 5de848d

Please sign in to comment.