Skip to content

Commit

Permalink
Tail log, sync selection, icons.
Browse files Browse the repository at this point in the history
  • Loading branch information
jarruda committed Jun 16, 2024
1 parent badb766 commit 6897992
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 65 deletions.
Binary file removed assets/icons8-add-48-black.png
Binary file not shown.
Binary file removed assets/icons8-add-48-white.png
Binary file not shown.
Binary file removed assets/icons8-copy-48-white.png
Binary file not shown.
Binary file added assets/icons8-duplicate-32-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons8-link-24-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons8-minus-24-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/icons8-minus-48-black.png
Binary file not shown.
Binary file removed assets/icons8-minus-48-white.png
Binary file not shown.
Binary file added assets/icons8-plus-24-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons8-repeat-24-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons8-search-24-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons8-update-50-white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 47 additions & 13 deletions src/app/filtered_log_entries_tab.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use std::time::SystemTime;
use std::{
fs::File,
io,
path::{Path, PathBuf},
};

use egui::Ui;
use grep::searcher::{Searcher, sinks::Lossy};
use egui::{include_image, Button, CursorIcon, Ui};
use grep::searcher::{sinks::Lossy, Searcher};
use grep_regex::RegexMatcherBuilder;
use log::error;

use super::{
log_entries_table::LogEntriesTable,
log_file_reader::{LineNumber, LogFileReader},
log_view::{LogViewerState, LogViewTabTrait},
log_view::{LogViewTabTrait, LogViewerState},
};

#[derive(Debug)]
Expand Down Expand Up @@ -57,7 +58,9 @@ pub struct FilteredLogEntriesTab {
search_term: String,
search_results: Vec<LineNumber>,
search_options: SearchOptions,
selected_line: Option<LineNumber>
log_entries_table: LogEntriesTable,
repeat_search: bool,
last_search_time: Option<SystemTime>,
}

impl FilteredLogEntriesTab {
Expand All @@ -68,7 +71,9 @@ impl FilteredLogEntriesTab {
search_results: vec![],
search_options: Default::default(),
editable_search_term: Default::default(),
selected_line: None
log_entries_table: LogEntriesTable::new(),
repeat_search: true,
last_search_time: None,
})
}

Expand Down Expand Up @@ -112,6 +117,12 @@ impl FilteredLogEntriesTab {

fn execute_search(&mut self) {
self.search_term = self.editable_search_term.clone();
self.last_search_time = Some(SystemTime::now());

if self.search_term.is_empty() {
self.search_results.clear();
return;
}

match Self::search(&self.search_options, &self.log_file_path, &self.search_term) {
Ok(results) => {
Expand Down Expand Up @@ -183,17 +194,40 @@ impl LogViewTabTrait for FilteredLogEntriesTab {
log_reader: &mut LogFileReader,
viewer_state: &mut LogViewerState,
) {
self.ui_search(ui);
let mut repeat_search = self.repeat_search;

let mut log_entries_table = LogEntriesTable::new()
.filtered_lines(&self.search_results)
.select_line(viewer_state.selected_line_num);
self.ui_search(ui);

if self.selected_line != viewer_state.selected_line_num {
self.selected_line = viewer_state.selected_line_num;
log_entries_table = log_entries_table.scroll_to_selected();
if repeat_search && log_reader.load_time_point().is_some() {
let search_needed = match self.last_search_time {
None => true,
Some(last_search_time) => last_search_time < log_reader.load_time_point().unwrap(),
};
if search_needed {
self.execute_search();
}
}

log_entries_table.ui(ui, log_reader, viewer_state);
self.log_entries_table.ui(
ui,
log_reader,
viewer_state,
Some(&self.search_results),
|ui| {
if ui
.add(
Button::image(include_image!("../../assets/icons8-repeat-24-white.png"))
.selected(repeat_search),
)
.on_hover_cursor(CursorIcon::PointingHand)
.on_hover_text("Repeat Search on Change")
.clicked()
{
repeat_search = !repeat_search;
};
},
);

self.repeat_search = repeat_search;
}
}
25 changes: 9 additions & 16 deletions src/app/log_entries_tab.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use crate::app::log_file_reader::LineNumber;
use super::{
log_entries_table::LogEntriesTable,
log_file_reader::{LogFileReader},
log_view::{LogViewerState, LogViewTabTrait},
log_file_reader::LogFileReader,
log_view::{LogViewTabTrait, LogViewerState},
};

pub struct LogEntriesTab {
selected_line: Option<LineNumber>
log_entries_table: LogEntriesTable,
}

impl LogEntriesTab {
pub fn new() -> Box<Self> {
Box::new(Self { selected_line: None })
Box::new(Self {
log_entries_table: LogEntriesTable::new(),
})
}
}

Expand All @@ -24,17 +25,9 @@ impl LogViewTabTrait for LogEntriesTab {
&mut self,
ui: &mut egui::Ui,
log_reader: &mut LogFileReader,
viewer_state: &mut LogViewerState,
viewer_state: &mut LogViewerState,
) {

let mut log_entries_table =
LogEntriesTable::new().select_line(viewer_state.selected_line_num);

if self.selected_line != viewer_state.selected_line_num {
self.selected_line = viewer_state.selected_line_num;
log_entries_table = log_entries_table.scroll_to_selected();
}

log_entries_table.ui(ui, log_reader, viewer_state);
self.log_entries_table
.ui(ui, log_reader, viewer_state, None, |_| {});
}
}
112 changes: 79 additions & 33 deletions src/app/log_entries_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,56 @@ use crate::app::log_view::{ColumnTextColor, LogViewerState};

use super::log_file_reader::{LineNumber, LogFileReader};

pub struct LogEntriesTable<'a> {
filtered_lines: Option<&'a [LineNumber]>,
pub struct LogEntriesTable {
selected_line: Option<usize>,
scroll_to_selected: bool,
sync_line_selection: bool,
tail_log: bool,
}

impl<'a> LogEntriesTable<'a> {
impl LogEntriesTable {
fn add_tool_button(
ui: &mut egui::Ui,
ui: &mut Ui,
image_source: ImageSource<'_>,
hover_text: &str,
) -> Response {
ui.add_sized(Vec2::new(18.0, 18.0), Button::image(image_source))
ui.add_sized(Vec2::new(16.0, 16.0), Button::image(image_source))
.on_hover_cursor(CursorIcon::PointingHand)
.on_hover_text(hover_text)
}

pub fn new() -> Self {
Self {
filtered_lines: None,
selected_line: None,
scroll_to_selected: false,
sync_line_selection: true,
tail_log: false,
}
}

pub fn scroll_to_selected(mut self) -> Self {
self.scroll_to_selected = true;
self
}

pub fn select_line(mut self, row: Option<usize>) -> Self {
self.selected_line = row;
self
}

pub fn filtered_lines(mut self, lines: &'a [LineNumber]) -> Self {
self.filtered_lines = Some(lines);
self
}

pub fn ui(
&mut self,
ui: &mut Ui,
log_file_reader: &mut LogFileReader,
viewer_state: &mut LogViewerState,
filtered_entries: Option<&[LineNumber]>,
add_toolbar_contents: impl FnOnce(&mut Ui)
) {
let total_rows = match self.filtered_lines {
self.toolbar_ui(ui, log_file_reader, viewer_state, add_toolbar_contents);

let total_rows = match filtered_entries {
Some(lines) => lines.len(),
None => log_file_reader.line_count() as usize,
None => log_file_reader.line_count(),
};

let mut table_builder = TableBuilder::new(ui)
.max_scroll_height(f32::INFINITY)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.cell_layout(egui::Layout::left_to_right(Align::Center))
.striped(true)
.auto_shrink(false)
.min_scrolled_height(0.0)
.sense(egui::Sense::click());

let mut col_iter = viewer_state.displayed_columns.iter().peekable();
while let Some(col_key) = col_iter.next() {
let is_last_col = col_iter.peek().is_none();
Expand All @@ -85,10 +76,15 @@ impl<'a> LogEntriesTable<'a> {
table_builder = table_builder.column(col_desc);
}

if self.scroll_to_selected {
if let Some(selected_line) = self.selected_line {
if let Some(selected_row) = self.find_row_for_line(selected_line) {
if self.tail_log {
if let Some(row) = self.last_row_index(log_file_reader, filtered_entries) {
table_builder = table_builder.scroll_to_row(row, Some(Align::BOTTOM));
}
} else if self.sync_line_selection && self.selected_line != viewer_state.selected_line_num {
if let Some(selected_line) = viewer_state.selected_line_num {
if let Some(selected_row) = self.find_row_for_line(selected_line, filtered_entries) {
table_builder = table_builder.scroll_to_row(selected_row, Some(Align::Center));
self.selected_line = viewer_state.selected_line_num;
}
}
self.scroll_to_selected = false;
Expand All @@ -102,7 +98,7 @@ impl<'a> LogEntriesTable<'a> {
row.col(|ui| {
ui.label(RichText::new(displayed_column).strong());
if columns_displayed_count > 1 {
let rm_icon = include_image!("../../assets/icons8-minus-48-white.png");
let rm_icon = include_image!("../../assets/icons8-minus-24-white.png");
if Self::add_tool_button(ui, rm_icon, "Remove Column").clicked() {
columns_to_remove.push(displayed_column.clone());
}
Expand All @@ -121,7 +117,7 @@ impl<'a> LogEntriesTable<'a> {
.body(|body| {
body.rows(16.0, total_rows, |mut row| {
let row_idx = row.index();
let line_number = match self.filtered_lines {
let line_number = match filtered_entries {
Some(lines) => lines[row_idx],
None => row_idx,
};
Expand All @@ -132,7 +128,9 @@ impl<'a> LogEntriesTable<'a> {

if row.response().clicked() {
self.selected_line = Some(line_number);
viewer_state.selected_line_num = self.selected_line;
if self.sync_line_selection {
viewer_state.selected_line_num = self.selected_line;
}
}
});
});
Expand All @@ -141,13 +139,26 @@ impl<'a> LogEntriesTable<'a> {
/// Maps a line number to a table row.
/// If there is a set of filtered lines set, a binary search is performed to
/// find the correct row. Otherwise, the line number is returned as the row.
fn find_row_for_line(&self, line_number: LineNumber) -> Option<usize> {
match self.filtered_lines {
fn find_row_for_line(&self, line_number: LineNumber, filtered_entries: Option<&[LineNumber]>) -> Option<usize> {
match filtered_entries {
Some(lines) => Some(lines.binary_search(&line_number).ok()?),
None => Some(line_number),
}
}

fn last_row_index(&self, log_file_reader: &LogFileReader, filtered_entries: Option<&[LineNumber]>) -> Option<usize> {
match filtered_entries {
Some(lines) => {
if lines.is_empty() {
None
} else {
Some(lines.len() - 1)
}
}
None => Some(log_file_reader.line_count() - 1),
}
}

fn ui_logline(
log_file_reader: &mut LogFileReader,
viewer_state: &mut LogViewerState,
Expand Down Expand Up @@ -217,6 +228,41 @@ impl<'a> LogEntriesTable<'a> {

Some(())
}
fn toolbar_ui(
&mut self,
ui: &mut Ui,
_log_file_reader: &mut LogFileReader,
_log_viewer_state: &mut LogViewerState,
add_toolbar_contents: impl FnOnce(&mut Ui) + Sized,
) {
ui.horizontal(|ui| {
if ui
.add(
Button::image(include_image!("../../assets/icons8-update-50-white.png"))
.selected(self.tail_log),
)
.on_hover_cursor(CursorIcon::PointingHand)
.on_hover_text("Tail Log")
.clicked()
{
self.tail_log = !self.tail_log;
};
if ui
.add(
Button::image(include_image!("../../assets/icons8-link-24-white.png"))
.selected(self.sync_line_selection),
)
.on_hover_cursor(CursorIcon::PointingHand)
.on_hover_text("Sync Selection")
.clicked()
{
self.sync_line_selection = !self.sync_line_selection;
};

add_toolbar_contents(ui);
});
ui.separator();
}
}

fn color_from_loglevel(level: &str) -> Color32 {
Expand Down
6 changes: 3 additions & 3 deletions src/app/log_entry_context_tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl LogEntryContextTab {
image_source: ImageSource<'_>,
hover_text: &str,
) -> Response {
ui.add_sized(Vec2::new(18.0, 18.0), Button::image(image_source))
ui.add_sized(Vec2::new(16.0, 16.0), Button::image(image_source))
.on_hover_text(hover_text)
.on_hover_cursor(CursorIcon::PointingHand)
}
Expand Down Expand Up @@ -78,7 +78,7 @@ impl LogViewTabTrait for LogEntryContextTab {
viewer_state.displayed_columns.iter().any(|s| s == key_str);
if !column_is_shown {
let add_icon =
include_image!("../../assets/icons8-add-48-white.png");
include_image!("../../assets/icons8-plus-24-white.png");
if Self::add_tool_button(ui, add_icon, "Add Column").clicked() {
viewer_state.displayed_columns.push(key_str.to_string());

Expand All @@ -95,7 +95,7 @@ impl LogViewTabTrait for LogEntryContextTab {
});
row.col(|ui| {
let copy_icon =
include_image!("../../assets/icons8-copy-48-white.png");
include_image!("../../assets/icons8-duplicate-32-white.png");
if Self::add_tool_button(ui, copy_icon, "Copy Value").clicked() {
ui.output_mut(|o| {
o.copied_text = value_str.clone();
Expand Down
Loading

0 comments on commit 6897992

Please sign in to comment.