Compare commits

...

8 Commits

Author SHA1 Message Date
7f4f6ab004 use folder of the original file in "copy to file" action 2024-03-26 18:17:52 +01:00
270b3a8683 remove some debug logging 2024-03-26 18:15:30 +01:00
b8b4b4e790 make the original file name known to the filter view 2024-03-26 18:12:42 +01:00
66d6a728cc make it possible to activate highlighter only for specific file types
In stage 1 we use a glob pattern matching the file name.
Stage 2 (which I will maybe implement some day) might use some additional magic byte sequence for file type detection.
2024-03-25 19:23:24 +01:00
56189f4094 use transparent line background by default 2024-03-25 18:40:03 +01:00
5f30862a83 keep position on handle 2024-03-24 20:06:00 +01:00
017a51a24a remove code for drawing ticks 2024-03-24 19:59:38 +01:00
442d3173c8 don't show context menu entries for ranges when range slider is disabled 2024-03-24 16:46:15 +01:00
8 changed files with 84 additions and 61 deletions

View File

@@ -55,9 +55,9 @@ def _new_recursive(current_action_id: str, items: [MenuContribution]) -> [MenuCo
for item in items: for item in items:
mc: MenuContribution = item mc: MenuContribution = item
print("%s checking %s" % (current_action_id, mc.action_id)) # print("%s checking %s" % (current_action_id, mc.action_id))
if mc.after == current_action_id: if mc.after == current_action_id:
print("%s adding %s" % (current_action_id, mc.action_id)) #print("%s adding %s" % (current_action_id, mc.action_id))
result.append(mc) result.append(mc)
result = result + _new_recursive(mc.action_id, items) result = result + _new_recursive(mc.action_id, items)
@@ -65,7 +65,7 @@ def _new_recursive(current_action_id: str, items: [MenuContribution]) -> [MenuCo
def _recursive_half_order_adder(result: [MenuContribution], items: [MenuContribution]): def _recursive_half_order_adder(result: [MenuContribution], items: [MenuContribution]):
print("%s -- %s" % ([mc.action_id for mc in result], [mc.action_id for mc in items])) #print("%s -- %s" % ([mc.action_id for mc in result], [mc.action_id for mc in items]))
for item in items: for item in items:
mc: MenuContribution = item mc: MenuContribution = item
if mc.after: if mc.after:

View File

@@ -225,7 +225,7 @@ class FilterWidget(QWidget):
(handle, self.tmp_filename) = tempfile.mkstemp() (handle, self.tmp_filename) = tempfile.mkstemp()
os.close(handle) os.close(handle)
self.filter_model = LogFileModel(self.tmp_filename, self.source_model.settings) self.filter_model = LogFileModel(self.tmp_filename, self.source_model.settings, source_model.get_file())
self.hits_view = BigText(self.filter_model, show_range_slider=False) self.hits_view = BigText(self.filter_model, show_range_slider=False)
self.layout.addWidget(filter_bar) self.layout.addWidget(filter_bar)

View File

@@ -77,6 +77,7 @@ class BigText(QWidget):
def __init__(self, model: LogFileModel, show_range_slider=True): def __init__(self, model: LogFileModel, show_range_slider=True):
super(BigText, self).__init__() super(BigText, self).__init__()
self.show_range_slider = show_range_slider
self.model = model self.model = model
self.grid = QGridLayout() self.grid = QGridLayout()
@@ -87,10 +88,7 @@ class BigText(QWidget):
self.v_scroll_bar = ScaledScrollBar() self.v_scroll_bar = ScaledScrollBar()
self.range_limit = RangeSlider() self.big_text = InnerBigText(self, model, self.v_scroll_bar)
self.range_limit.value_changed.connect(self._range_limit_event)
self.big_text = InnerBigText(self, model, self.v_scroll_bar, self.range_limit)
self.big_text.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)) self.big_text.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding))
self.h_scroll_bar = QScrollBar(Qt.Orientation.Horizontal) self.h_scroll_bar = QScrollBar(Qt.Orientation.Horizontal)
@@ -102,9 +100,9 @@ class BigText(QWidget):
self.v_scroll_bar.scaledValueChanged.connect(self.big_text.v_scroll_event) self.v_scroll_bar.scaledValueChanged.connect(self.big_text.v_scroll_event)
self.v_scroll_bar.scrolled_to_end.connect(self.big_text.v_scroll_update_follow_tail) self.v_scroll_bar.scrolled_to_end.connect(self.big_text.v_scroll_update_follow_tail)
if show_range_slider: if show_range_slider:
self.range_limit = RangeSlider()
self.range_limit.value_changed.connect(self._range_limit_event)
self.grid.addWidget(self.range_limit, 0, 0) self.grid.addWidget(self.range_limit, 0, 0)
self.grid.addWidget(self.big_text, 0, 1) self.grid.addWidget(self.big_text, 0, 1)
self.grid.addWidget(self.h_scroll_bar, 1, 1) self.grid.addWidget(self.h_scroll_bar, 1, 1)
@@ -149,14 +147,12 @@ class InnerBigText(QWidget):
_range_start = 0 _range_start = 0
_range_end = -1 _range_end = -1
def __init__(self, parent: BigText, model: LogFileModel, v_scaled_scrollbar: ScaledScrollBar, def __init__(self, parent: BigText, model: LogFileModel, v_scaled_scrollbar: ScaledScrollBar):
range_limit: RangeSlider):
super(InnerBigText, self).__init__() super(InnerBigText, self).__init__()
self.char_height = None self.char_height = None
self.char_width = None self.char_width = None
self.model = model self.model = model
self._v_scaled_scrollbar = v_scaled_scrollbar self._v_scaled_scrollbar = v_scaled_scrollbar
self._range_limit = range_limit
self.parent = parent self.parent = parent
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
self.setFocusPolicy(Qt.FocusPolicy.WheelFocus) self.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
@@ -219,7 +215,6 @@ class InnerBigText(QWidget):
elif e.modifiers() == Qt.KeyboardModifier.ControlModifier and e.key() == 65: # ctrl + a elif e.modifiers() == Qt.KeyboardModifier.ControlModifier and e.key() == 65: # ctrl + a
self._select_all() self._select_all()
def wheelEvent(self, event: QWheelEvent): def wheelEvent(self, event: QWheelEvent):
direction = 1 if event.angleDelta().y() < 0 else -1 direction = 1 if event.angleDelta().y() < 0 else -1
if event.modifiers() == Qt.KeyboardModifier.ControlModifier: if event.modifiers() == Qt.KeyboardModifier.ControlModifier:
@@ -262,6 +257,7 @@ class InnerBigText(QWidget):
manage_highlighting.setShortcut("CTRL+H") manage_highlighting.setShortcut("CTRL+H")
menu.addAction(manage_highlighting) menu.addAction(manage_highlighting)
if self.parent.show_range_slider:
menu.addSeparator() menu.addSeparator()
set_range_start = QAction( set_range_start = QAction(
@@ -491,7 +487,7 @@ class InnerBigText(QWidget):
(selected_file, _filter) = dialog.getSaveFileName( (selected_file, _filter) = dialog.getSaveFileName(
parent=self, parent=self,
caption=_("Save File"), caption=_("Save File"),
dir=os.path.dirname(self.model.get_file()) dir=os.path.dirname(self.model.get_original_file())
) )
if selected_file: if selected_file:
self.model.write_range(start, end, selected_file) self.model.write_range(start, end, selected_file)
@@ -559,6 +555,7 @@ class InnerBigText(QWidget):
byte_count = self.model.byte_count() byte_count = self.model.byte_count()
vmax = byte_count - 1 if self._range_end < 0 else min(self._range_end, self.model.byte_count() - 1) vmax = byte_count - 1 if self._range_end < 0 else min(self._range_end, self.model.byte_count() - 1)
self.parent.v_scroll_bar.setMaximum(vmax) self.parent.v_scroll_bar.setMaximum(vmax)
if self.parent.show_range_slider:
self.parent.range_limit.set_maximum(byte_count) self.parent.range_limit.set_maximum(byte_count)
for line in self.lines: for line in self.lines:

View File

@@ -1,3 +1,5 @@
import fnmatch
import glob
from typing import Optional from typing import Optional
from src.ui.bigtext.highlight import Highlight from src.ui.bigtext.highlight import Highlight
@@ -12,7 +14,7 @@ import re
class HighlightRegex(Highlight): class HighlightRegex(Highlight):
def __init__(self, query: str, ignore_case: bool, is_regex: bool, hit_background_color: str = "None", def __init__(self, query: str, ignore_case: bool, is_regex: bool, hit_background_color: str = "None",
line_background_color: str = "None", active: bool = True): line_background_color: str = "None", active: bool = True, activated_for_file_type: str = "*"):
self.active = active self.active = active
self.query = query self.query = query
self.ignore_case = ignore_case self.ignore_case = ignore_case
@@ -20,6 +22,7 @@ class HighlightRegex(Highlight):
self.regex = self._get_regex() self.regex = self._get_regex()
self.hit_background_color = hit_background_color self.hit_background_color = hit_background_color
self.line_background_color = line_background_color self.line_background_color = line_background_color
self.activated_for_file_type = activated_for_file_type
self._brush_hit = self.brush(self.hit_background_color) self._brush_hit = self.brush(self.hit_background_color)
self._brush_line = self.brush(self.line_background_color) self._brush_line = self.brush(self.line_background_color)
@@ -99,3 +102,15 @@ class HighlightRegex(Highlight):
alpha = int(color[6:8], 16) alpha = int(color[6:8], 16)
return QBrush(QColor(red, green, blue, alpha)) return QBrush(QColor(red, green, blue, alpha))
return QBrush() return QBrush()
def set_activated_for_file_type(self, activated_for_file_type: str):
self.activated_for_file_type = activated_for_file_type
def file_type_matches(self, file_name: str) -> bool:
if self.activated_for_file_type is None or len(self.activated_for_file_type) == 0:
return True
glob_patterns: [str] = self.activated_for_file_type.split(",") # support multiple globs like: "*.txt, *.csv"
for glob_pattern in glob_patterns:
if fnmatch.fnmatch(file_name, glob_pattern.strip()):
return True
return False

View File

@@ -25,6 +25,7 @@ class Highlighting:
is_regex = session.getboolean(section, "is-regex", fallback=False) is_regex = session.getboolean(section, "is-regex", fallback=False)
line_background_color = session.get(section, "line.background.color", fallback="None") line_background_color = session.get(section, "line.background.color", fallback="None")
hit_background_color = session.get(section, "hit.background.color", fallback="None") hit_background_color = session.get(section, "hit.background.color", fallback="None")
activated_for_file_type = session.get(section, "activated-for-file-type", fallback="*")
try: try:
highlight = HighlightRegex( highlight = HighlightRegex(
@@ -33,7 +34,8 @@ class Highlighting:
is_regex=is_regex, is_regex=is_regex,
hit_background_color=hit_background_color, hit_background_color=hit_background_color,
line_background_color=line_background_color, line_background_color=line_background_color,
active=active active=active,
activated_for_file_type=activated_for_file_type
) )
result.append(highlight) result.append(highlight)
except: except:
@@ -57,6 +59,7 @@ class Highlighting:
settings.session.set(section, "is-regex", str(highlighter.is_regex)) settings.session.set(section, "is-regex", str(highlighter.is_regex))
settings.session.set(section, "line.background.color", highlighter.line_background_color) settings.session.set(section, "line.background.color", highlighter.line_background_color)
settings.session.set(section, "hit.background.color", highlighter.hit_background_color) settings.session.set(section, "hit.background.color", highlighter.hit_background_color)
settings.session.set(section, "activated-for-file-type", highlighter.activated_for_file_type)
@staticmethod @staticmethod
def remove_highlighting_sections(settings: Settings): def remove_highlighting_sections(settings: Settings):

View File

@@ -21,21 +21,31 @@ class LogFileModel:
range_start = 0 range_start = 0
range_end = -1 range_end = -1
def __init__(self, file: str, settings: Settings): def __init__(self, file: str, settings: Settings, original_file: str = False):
"""
:param file:
:param settings:
:param original_file: used in the filter widget to denote the original file, the one being filtered, because 'file' points to the tmp file
"""
self.settings = settings self.settings = settings
self._file = os.path.realpath(file) self._file = os.path.realpath(file)
self._original_file = os.path.realpath(original_file) if original_file else self._file
self._file_name = os.path.basename(self._original_file)
def highlighters(self): def highlighters(self):
all_highlighters = Highlighting.read_config(self.settings) all_highlighters = Highlighting.read_config(self.settings)
active_highlighters = [] active_highlighters = []
for h in all_highlighters: for h in all_highlighters:
if h.is_active(): if h.is_active() and h.file_type_matches(self._file_name):
active_highlighters.append(h) active_highlighters.append(h)
return active_highlighters return active_highlighters
def get_file(self): def get_file(self):
return self._file return self._file
def get_original_file(self):
return self._original_file
def __str__(self): def __str__(self):
return self._file return self._file

View File

@@ -118,7 +118,7 @@ class NewHighlightingDialog(QDialog):
def _new_highlighter(self): def _new_highlighter(self):
highlight_regex = HighlightRegex("", ignore_case=True, is_regex=True, hit_background_color="ccb400", highlight_regex = HighlightRegex("", ignore_case=True, is_regex=True, hit_background_color="ccb400",
line_background_color="fff080") line_background_color="None")
self._add_highlight_regex_to_list(highlight_regex, select=True) self._add_highlight_regex_to_list(highlight_regex, select=True)
@@ -139,7 +139,7 @@ class HighlightListItemWidget(QWidget):
self.active = QCheckBox("") self.active = QCheckBox("")
self.active.setChecked(highlight_regex.is_active()) self.active.setChecked(highlight_regex.is_active())
self.active.stateChanged.connect(self._change_active_state) self.active.stateChanged.connect(self._change_active_state)
self.layout.addWidget(self.active, row, 0, 3, 1, alignment=QtCore.Qt.AlignmentFlag.AlignVCenter) self.layout.addWidget(self.active, row, 0, 4, 1, alignment=QtCore.Qt.AlignmentFlag.AlignVCenter)
query = QLineEdit(self) query = QLineEdit(self)
query.setText(highlight_regex.query) query.setText(highlight_regex.query)
@@ -181,6 +181,18 @@ class HighlightListItemWidget(QWidget):
is_regex.setEnabled(highlight_regex.is_active()) is_regex.setEnabled(highlight_regex.is_active())
self.layout.addWidget(is_regex, row, 3) self.layout.addWidget(is_regex, row, 3)
row = row + 1
activated_for_file_type_label = QLabel(_("File Type:"), self)
activated_for_file_type_label.setEnabled(highlight_regex.is_active())
self.layout.addWidget(activated_for_file_type_label, row, 1)
activated_for_file_type = QLineEdit(self)
activated_for_file_type.setEnabled(highlight_regex.is_active())
activated_for_file_type.setText(highlight_regex.activated_for_file_type)
activated_for_file_type.textChanged[str].connect(
lambda: highlight_regex.set_activated_for_file_type(activated_for_file_type.text()))
self.layout.addWidget(activated_for_file_type, row, 2)
def _change_active_state(self): def _change_active_state(self):
active = self.active.isChecked() active = self.active.isChecked()
self.highlight_regex.set_active(active) self.highlight_regex.set_active(active)

View File

@@ -44,8 +44,6 @@ class RangeSlider(QWidget):
super(RangeSlider, self).__init__() super(RangeSlider, self).__init__()
self.setFixedWidth(self._width) self.setFixedWidth(self._width)
self.draw_ticks = False
self.min_value = 0 self.min_value = 0
self.max_value = 100 self.max_value = 100
@@ -54,6 +52,7 @@ class RangeSlider(QWidget):
self.selected_handle = None self.selected_handle = None
self.selection_drag_range = (self.min_value, self.max_value) self.selection_drag_range = (self.min_value, self.max_value)
self.drag_y_offset_in_handle = 0
def set_maximum(self, max: int): def set_maximum(self, max: int):
if self.max_value == max: if self.max_value == max:
@@ -69,8 +68,6 @@ class RangeSlider(QWidget):
def paintEvent(self, event: PySide6.QtGui.QPaintEvent) -> None: def paintEvent(self, event: PySide6.QtGui.QPaintEvent) -> None:
painter = QPainter(self) painter = QPainter(self)
self._draw_background(painter) self._draw_background(painter)
if self.draw_ticks:
self._draw_ticks(painter)
self._draw_handle(painter, self.lower_value) self._draw_handle(painter, self.lower_value)
self._draw_handle(painter, self.upper_value, direction=-1) self._draw_handle(painter, self.upper_value, direction=-1)
@@ -90,19 +87,6 @@ class RangeSlider(QWidget):
self._value_to_pixel(self.upper_value.value - self.lower_value.value) - 2 * self._handle_width) self._value_to_pixel(self.upper_value.value - self.lower_value.value) - 2 * self._handle_width)
painter.drawRoundedRect(rect, 3.0, 3.0) painter.drawRoundedRect(rect, 3.0, 3.0)
def _draw_ticks(self, painter: QPainter) -> None:
painter.setPen(to_qcolor("333333"))
min_tick_distance = 25
full_height = self.height() - 2 * self._handle_width
ticks = math.floor(full_height / min_tick_distance)
actual_tick_distance = full_height / ticks
print(f"ticks {ticks}")
y = actual_tick_distance + self._handle_width
while y < full_height:
painter.drawLine(8, y, 12, y)
y = y + actual_tick_distance
def _draw_handle(self, painter: QPainter, handle: RangeSliderHandle, direction=1) -> None: def _draw_handle(self, painter: QPainter, handle: RangeSliderHandle, direction=1) -> None:
y_pixel = self._value_to_pixel(handle.value) y_pixel = self._value_to_pixel(handle.value)
@@ -144,9 +128,11 @@ class RangeSlider(QWidget):
if self._is_on_handle(self.lower_value, pos.y(), direction=1): if self._is_on_handle(self.lower_value, pos.y(), direction=1):
self.selected_handle = self.lower_value self.selected_handle = self.lower_value
self.selection_drag_range = (self.min_value, self.upper_value.value) self.selection_drag_range = (self.min_value, self.upper_value.value)
self.drag_y_offset_in_handle = self.selected_handle.value - self._pixel_to_value(pos.y())
if self._is_on_handle(self.upper_value, pos.y(), direction=-1): if self._is_on_handle(self.upper_value, pos.y(), direction=-1):
self.selected_handle = self.upper_value self.selected_handle = self.upper_value
self.selection_drag_range = (self.lower_value.value, self.max_value) self.selection_drag_range = (self.lower_value.value, self.max_value)
self.drag_y_offset_in_handle = self.selected_handle.value - self._pixel_to_value(pos.y())
def mouseReleaseEvent(self, event: PySide6.QtGui.QMouseEvent) -> None: def mouseReleaseEvent(self, event: PySide6.QtGui.QMouseEvent) -> None:
self.selected_handle = None self.selected_handle = None
@@ -154,7 +140,7 @@ class RangeSlider(QWidget):
def mouseMoveEvent(self, e: PySide6.QtGui.QMouseEvent) -> None: def mouseMoveEvent(self, e: PySide6.QtGui.QMouseEvent) -> None:
if self.selected_handle != None: if self.selected_handle != None:
pos: QPoint = e.pos() pos: QPoint = e.pos()
value = self._pixel_to_value(pos.y()) value = self._pixel_to_value(pos.y()) + self.drag_y_offset_in_handle
if self.selection_drag_range[0] <= value <= self.selection_drag_range[1]: if self.selection_drag_range[0] <= value <= self.selection_drag_range[1]:
self.selected_handle.value = value self.selected_handle.value = value
# print("%s, %s" %(self.lower_value.value, self.upper_value.value)) # print("%s, %s" %(self.lower_value.value, self.upper_value.value))