From eab422a6ce89b1b6fd78df3ac95c1205b1d0c558 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Sun, 24 Oct 2021 18:49:47 +0200 Subject: [PATCH] improve highlighting --- bigtext.py | 44 ++++++++++++++++++++++++++++++------------ highlight.py | 12 ++++++++++++ highlight_selection.py | 42 ++++++++++++++++++++++++++++++++++++++++ highlighted_range.py | 23 ++++++++++++++++++++++ logFileModel.py | 6 ++++-- main.py | 2 ++ settings.py | 6 ++++++ 7 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 highlight.py create mode 100644 highlight_selection.py create mode 100644 highlighted_range.py create mode 100644 settings.py diff --git a/bigtext.py b/bigtext.py index 7c79339..3f8b084 100644 --- a/bigtext.py +++ b/bigtext.py @@ -1,9 +1,13 @@ import math - +from typing import Optional +import PyQt6.QtGui from PyQt6.QtCore import * from PyQt6.QtGui import * from PyQt6.QtWidgets import * +from highlight import Highlight +from highlight_selection import HightlightSelection +from highlighted_range import HighlightedRange from line import Line from logFileModel import LogFileModel @@ -11,9 +15,8 @@ from logFileModel import LogFileModel class BigText(QWidget): _byte_offset = 0 _left_offset = 0 - _selection_start_byte = 0 - _selection_end_byte = 0 + highlights : [Highlight] = [] def __init__(self, model: LogFileModel): super(BigText, self).__init__() @@ -21,21 +24,24 @@ class BigText(QWidget): self.font = QFont("monospace", 20) self.update_font_metrics(QPainter(self)) self.lines = [] + self.selection_highlight= HightlightSelection(0,0) + self.highlights = [self.selection_highlight] def paintEvent(self, event: QPaintEvent) -> None: self.draw() def mousePressEvent(self, e: QMouseEvent) -> None: if e.buttons() == Qt.MouseButton.LeftButton: - self._selection_start_byte = self.to_byte_offset(e) - self._selection_end_byte = self._selection_start_byte + offset = self.to_byte_offset(e) + self.selection_highlight.set_start(offset) + self.selection_highlight.set_end_byte(offset) self.update() def mouseMoveEvent(self, e: QMouseEvent): current_byte = self.to_byte_offset(e) - if self._selection_end_byte != current_byte: - self._selection_end_byte = current_byte + if self.selection_highlight.end_byte != current_byte: + self.selection_highlight.set_end_byte(current_byte) self.update() #print("-> %s,%s" %(self._selection_start_byte, self._selection_end_byte)) @@ -69,8 +75,12 @@ class BigText(QWidget): # draws over a character y_line_offset = self.char_height; for l in self.lines: - if l.intersects(self._selection_start_byte, self._selection_end_byte): - self.draw_selection(painter, l, y_line_offset) + #if l.intersects(self._selection_start_byte, self._selection_end_byte): + # self.draw_selection(painter, l, y_line_offset) + for h in self.highlights: + optional_highlight_range = h.compute_highlight(l) + if optional_highlight_range: + self.draw_highlight(optional_highlight_range, painter, y_line_offset) y_line_offset = y_line_offset + self.char_height y_line_offset = self.char_height; @@ -100,11 +110,21 @@ class BigText(QWidget): #print(rect) self.hightlight(painter,rect , hightlight_color) - def hightlight(self, painter: QPainter,rect: QRect, color: QColor): + def draw_highlight(self, highlight: HighlightedRange, painter: QPainter, y_line_offset:int): + x1 = highlight.get_start()*self.char_width + width = highlight.get_width()*self.char_width + + y1 = y_line_offset- self.char_height + self.char_height / 7 + height = self.char_height + rect = QRect(x1,y1,width,height) + #print(rect) + self.hightlight(painter,rect , highlight.get_brush(), highlight.get_pen()) + + def hightlight(self, painter: QPainter,rect: QRect, brush: QBrush, pen:QPen): old_brush = painter.brush() old_pen = painter.pen() - painter.setBrush(color) - painter.setPen(Qt.PenStyle.NoPen) + painter.setBrush(brush) + painter.setPen(pen) painter.drawRoundedRect(rect, 3.0, 3.0) painter.setBrush(old_brush) painter.setPen(old_pen) diff --git a/highlight.py b/highlight.py new file mode 100644 index 0000000..49ff93a --- /dev/null +++ b/highlight.py @@ -0,0 +1,12 @@ +from typing import Optional + +from line import Line +from highlighted_range import HighlightedRange + + +class Highlight: + def __init__(self): + pass + + def compute_highlight(self, line: Line) -> Optional[HighlightedRange]: + return None diff --git a/highlight_selection.py b/highlight_selection.py new file mode 100644 index 0000000..afd6d1f --- /dev/null +++ b/highlight_selection.py @@ -0,0 +1,42 @@ +from typing import Optional + +from highlight import Highlight +from highlighted_range import HighlightedRange +from line import Line +from PyQt6.QtCore import * +from PyQt6.QtGui import * +from PyQt6.QtWidgets import * + +from settings import Settings + + +class HightlightSelection(Highlight): + + def __init__(self, start_byte: int, end_byte: int): + self.start_byte = start_byte + self.end_byte = end_byte + + def set_start(self, start_byte): + self.start_byte = start_byte + + def set_end_byte(self, end_byte): + self.end_byte = end_byte + + def compute_highlight(self, line: Line) -> Optional[HighlightedRange]: + begin = min(self.start_byte, self.end_byte) + end = max(self.start_byte, self.end_byte) + + if line.intersects(begin, end): + if line.includes_byte(begin): + start = begin - line.byte_offset() + else: + start = 0 + + if line.includes_byte(end): + length = end - line.byte_offset() - start + else: + length = Settings.max_line_length() -start + + return HighlightedRange(start, length, QBrush(QColor(255, 255, 0)), Qt.PenStyle.NoPen) + else: + return None diff --git a/highlighted_range.py b/highlighted_range.py new file mode 100644 index 0000000..1d45ffb --- /dev/null +++ b/highlighted_range.py @@ -0,0 +1,23 @@ +from PyQt6.QtCore import * +from PyQt6.QtGui import * +from PyQt6.QtWidgets import * + + +class HighlightedRange: + def __init__(self, start: int, width: int, brush: QBrush = QBrush(), pen: QPen = Qt.PenStyle.NoPen): + self.start = start + self.width = width + self.brush = brush + self.pen = pen + + def get_start(self): + return self.start + + def get_width(self): + return self.width + + def get_brush(self): + return self.brush + + def get_pen(self): + return self.pen diff --git a/logFileModel.py b/logFileModel.py index ea1a517..2594cd4 100644 --- a/logFileModel.py +++ b/logFileModel.py @@ -2,6 +2,8 @@ from typing import List import os from line import Line +from settings import Settings + class LogFileModel: def __init__(self, file): @@ -12,8 +14,8 @@ class LogFileModel: # TODO handle lines longer than 4096 bytes with open(self._file, 'r') as f: - offset = max(0, byte_offset - 4096) - offset = offset - offset % 4096 # align to blocks of 4kb + offset = max(0, byte_offset - Settings.max_line_length()) + offset = offset - offset % Settings.max_line_length() # align to blocks of 4kb f.seek(offset) while l := f.readline(): new_offset = f.tell() diff --git a/main.py b/main.py index 1b748aa..dc278e7 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,8 @@ import sys from bigtext import BigText from logFileModel import LogFileModel +MAX_LINE_LENGTH = 4096 + class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): diff --git a/settings.py b/settings.py new file mode 100644 index 0000000..8be1035 --- /dev/null +++ b/settings.py @@ -0,0 +1,6 @@ + + +class Settings(): + @staticmethod + def max_line_length(): + return 4096 \ No newline at end of file