From 20f78a983b026fb08554bb6c782d909afac99c7d Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 29 May 2023 19:50:48 +0200 Subject: [PATCH] add view that only shows matches --- src/plugins/logfile/filterwidget.py | 50 ++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/plugins/logfile/filterwidget.py b/src/plugins/logfile/filterwidget.py index a600046..0f92536 100644 --- a/src/plugins/logfile/filterwidget.py +++ b/src/plugins/logfile/filterwidget.py @@ -7,7 +7,7 @@ from typing import Optional, Callable from PySide6.QtCore import QRunnable, QThreadPool, Signal from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QPushButton, QComboBox, \ - QSizePolicy, QProgressBar + QSizePolicy, QProgressBar, QLineEdit from src.plugins.domain.raction import RAction from src.plugins.logfile.preprocesslineshook import PreProcessLinesHook @@ -36,7 +36,9 @@ class FilterTask(QRunnable): progress_handler: Callable[[float], None], update_hits_handler: Callable[[int], None], on_before: Callable[[], None], - on_finish: Callable[[], None] + on_finish: Callable[[], None], + show_only_matches: bool, + matches_separator: str ): super(FilterTask, self).__init__() self.source_model = source_model @@ -49,6 +51,26 @@ class FilterTask(QRunnable): self.on_finish = on_finish self.lock = lock self.filter_match_found_listeners = filter_match_found_listeners + self.show_only_matches = show_only_matches + self.matches_separator = matches_separator + + def only_matches(self, line: str, regex: re.Pattern): + result = "" + first = True + match_iter = re.finditer(regex, line) + for match in match_iter: + # print("%s" % match) + + # if the regex has groups then skip the first, it represents the whole match, + # but we only want to highlight the groups + first_group = 1 if len(match.groups()) > 0 else 0 + for i in range(first_group, len(match.groups()) + 1): + if not first: + result = result + self.matches_separator + first = False + result = result + match.group(i) + + return result + "\n" # todo preserve original line ending def run(self): # print("writing to tmp file", self.filter_model.get_file()) @@ -93,7 +115,10 @@ class FilterTask(QRunnable): h: PreProcessLinesHook = hook line = h.pre_process_line(line, target) - target.write(line.encode("utf8")) + if self.show_only_matches: + target.write(self.only_matches(line, self.regex).encode("utf8")) + else: + target.write(line.encode("utf8")) hits_count = hits_count + 1 # sometime buffering can hide results for a while @@ -172,6 +197,18 @@ class FilterWidget(QWidget): self.is_regex.setChecked(True) self.is_regex.stateChanged.connect(self.filter_changed) + self.matches_separator = QLineEdit(",") + self.matches_separator.setMaximumWidth(15) + self.matches_separator.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.matches_separator.setVisible(False) + self.matches_separator.textChanged.connect(self.filter_changed) + + self.show_only_matches = QCheckBox(_("only matches")) + self.show_only_matches.setChecked(False) + self.show_only_matches.stateChanged.connect(self.filter_changed) + self.show_only_matches.stateChanged.connect( + lambda: self.matches_separator.setVisible(self.show_only_matches.isChecked())) + filter_bar = QWidget() filter_bar.layout = QHBoxLayout(filter_bar) filter_bar.layout.setContentsMargins(0, 0, 0, 0) @@ -183,6 +220,8 @@ class FilterWidget(QWidget): filter_bar.layout.addWidget(self.menu) filter_bar.layout.addWidget(self.ignore_case) filter_bar.layout.addWidget(self.is_regex) + filter_bar.layout.addWidget(self.show_only_matches) + filter_bar.layout.addWidget(self.matches_separator) (handle, self.tmp_filename) = tempfile.mkstemp() os.close(handle) @@ -270,6 +309,7 @@ class FilterWidget(QWidget): query = self.query_field.currentText() ignore_case = self.ignore_case.isChecked() is_regex = self.is_regex.isChecked() + show_only_matches = self.show_only_matches.isChecked() # cancel previous search self._cancel_search() @@ -308,6 +348,8 @@ class FilterWidget(QWidget): self.progress_handler, self.update_hits_handler, lambda: self.search_is_running.emit(True), - lambda: self.search_is_running.emit(False) + lambda: self.search_is_running.emit(False), + show_only_matches, + self.matches_separator.text() ) QThreadPool.globalInstance().start(self.filter_task)