diff --git a/locales/de_DE/LC_MESSAGES/messages.mo b/locales/de_DE/LC_MESSAGES/messages.mo index 273881b..f7514af 100644 Binary files a/locales/de_DE/LC_MESSAGES/messages.mo and b/locales/de_DE/LC_MESSAGES/messages.mo differ diff --git a/locales/de_DE/LC_MESSAGES/messages.po b/locales/de_DE/LC_MESSAGES/messages.po index ce677f1..99b49d1 100644 --- a/locales/de_DE/LC_MESSAGES/messages.po +++ b/locales/de_DE/LC_MESSAGES/messages.po @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: RavenLog\n" -"POT-Creation-Date: 2024-03-21 19:39+0100\n" -"PO-Revision-Date: 2024-03-21 19:40+0100\n" +"POT-Creation-Date: 2024-03-24 12:00+0100\n" +"PO-Revision-Date: 2024-03-24 12:02+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" @@ -226,27 +226,39 @@ msgstr "In &Datei Kopieren" msgid "Select &All" msgstr "&Alles Selektieren" -#: src/ui/bigtext/bigtext.py:414 +#: src/ui/bigtext/bigtext.py:268 +msgid "Set Range Start" +msgstr "Setze Start des Anzeigebereichs" + +#: src/ui/bigtext/bigtext.py:276 +msgid "Set Range End" +msgstr "Setze Ende des Anzeigebereichs" + +#: src/ui/bigtext/bigtext.py:283 +msgid "Reset Range" +msgstr "Anzeigebereich Zurücksetzen" + +#: src/ui/bigtext/bigtext.py:458 msgid "warning" msgstr "Achtung" -#: src/ui/bigtext/bigtext.py:415 +#: src/ui/bigtext/bigtext.py:459 msgid "You have selected {0} of data." msgstr "Du hast {0} selektiert." -#: src/ui/bigtext/bigtext.py:420 +#: src/ui/bigtext/bigtext.py:464 msgid "Copy {0} to Clipboard" msgstr "Kopiere {0} in die Zwischenablage" -#: src/ui/bigtext/bigtext.py:424 +#: src/ui/bigtext/bigtext.py:468 msgid "Write to File" msgstr "Schreibe in Datei" -#: src/ui/bigtext/bigtext.py:448 +#: src/ui/bigtext/bigtext.py:492 msgid "Save File" msgstr "Speichere Datei" -#: src/ui/bigtext/bigtext.py:485 +#: src/ui/bigtext/bigtext.py:529 msgid "selected {0} - {1:,.0f}:{2:,.0f}" msgstr "selektiert {0} - {1:,.0f}:{2:,.0f}" @@ -304,7 +316,7 @@ msgstr "Pale Crimson" #: src/ui/colorbutton.py:23 msgid "Broken Buttercup" -msgstr "Broken Buttercup" +msgstr "Kaputtes Butterfass" #: src/ui/colorbutton.py:24 msgid "Passion Fruit Sugar" @@ -358,6 +370,10 @@ msgstr "Grau" msgid "transparent" msgstr "Transparent" +#: src/ui/rangeslider.py:180 +msgid "showing bytes {0} to {1} ({2})" +msgstr "Anzeigebereich: Bytes {0} bis {1} ({2})" + #~ msgid "data selection" #~ msgstr "selektion" diff --git a/locales/messages.pot b/locales/messages.pot index e384aa3..3309562 100644 --- a/locales/messages.pot +++ b/locales/messages.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2024-03-21 19:39+0100\n" +"POT-Creation-Date: 2024-03-24 12:00+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -220,27 +220,39 @@ msgstr "" msgid "Select &All" msgstr "" -#: src/ui/bigtext/bigtext.py:414 +#: src/ui/bigtext/bigtext.py:268 +msgid "Set Range Start" +msgstr "" + +#: src/ui/bigtext/bigtext.py:276 +msgid "Set Range End" +msgstr "" + +#: src/ui/bigtext/bigtext.py:283 +msgid "Reset Range" +msgstr "" + +#: src/ui/bigtext/bigtext.py:458 msgid "warning" msgstr "" -#: src/ui/bigtext/bigtext.py:415 +#: src/ui/bigtext/bigtext.py:459 msgid "You have selected {0} of data." msgstr "" -#: src/ui/bigtext/bigtext.py:420 +#: src/ui/bigtext/bigtext.py:464 msgid "Copy {0} to Clipboard" msgstr "" -#: src/ui/bigtext/bigtext.py:424 +#: src/ui/bigtext/bigtext.py:468 msgid "Write to File" msgstr "" -#: src/ui/bigtext/bigtext.py:448 +#: src/ui/bigtext/bigtext.py:492 msgid "Save File" msgstr "" -#: src/ui/bigtext/bigtext.py:485 +#: src/ui/bigtext/bigtext.py:529 msgid "selected {0} - {1:,.0f}:{2:,.0f}" msgstr "" @@ -352,3 +364,7 @@ msgstr "" msgid "transparent" msgstr "" +#: src/ui/rangeslider.py:180 +msgid "showing bytes {0} to {1} ({2})" +msgstr "" + diff --git a/src/ui/bigtext/bigtext.py b/src/ui/bigtext/bigtext.py index 37aaaa8..a6e6eb7 100644 --- a/src/ui/bigtext/bigtext.py +++ b/src/ui/bigtext/bigtext.py @@ -87,7 +87,10 @@ class BigText(QWidget): self.v_scroll_bar = ScaledScrollBar() - self.big_text = InnerBigText(self, model, self.v_scroll_bar) + self.range_limit = RangeSlider() + 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.h_scroll_bar = QScrollBar(Qt.Orientation.Horizontal) @@ -99,8 +102,7 @@ class BigText(QWidget): 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.range_limit = RangeSlider() - self.range_limit.value_changed.connect(self._range_limit_event) + if show_range_slider: self.grid.addWidget(self.range_limit, 0, 0) @@ -112,12 +114,9 @@ class BigText(QWidget): QThreadPool.globalInstance().start(self.watchdog) self.trigger_update.connect(self.big_text._file_changed) - def _range_limit_event(self, lower_value: float, upper_value: float): - byte_count = self.model.byte_count() - range_start = int(byte_count * (lower_value / 100.0)) - range_end = int(byte_count * (upper_value / 100.0)) - print(f"-> {lower_value}, {upper_value}, {range_start}, {range_end} -- range limit event") - self.big_text.set_range(range_start, range_end) + def _range_limit_event(self, range_start: str, range_end: str): + # print("-> %s, %s -- range limit event" %(range_start, range_end)) + self.big_text.set_range(int(range_start), int(range_end)) def get_file(self): return self.model.get_file() @@ -150,12 +149,14 @@ class InnerBigText(QWidget): _range_start = 0 _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__() self.char_height = None self.char_width = None self.model = model self._v_scaled_scrollbar = v_scaled_scrollbar + self._range_limit = range_limit self.parent = parent self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) self.setFocusPolicy(Qt.FocusPolicy.WheelFocus) @@ -232,7 +233,7 @@ class InnerBigText(QWidget): # print("wheel event fired :) %s" % (direction)) self.scroll_by_lines(direction * 3) - def _open_menu(self, position): + def _open_menu(self, position: QPoint): menu = QMenu(self) copy_clipboard = QAction(Icon.fromTheme("edit-copy", "icons/myicons/edit-copy.svg"), _("&Copy to Clipboard"), @@ -261,8 +262,52 @@ class InnerBigText(QWidget): manage_highlighting.setShortcut("CTRL+H") menu.addAction(manage_highlighting) + menu.addSeparator() + + set_range_start = QAction( + Icon("icons/myicons/range-start.svg"), + _("Set Range Start"), + self, + triggered=lambda: self._set_range_start_by_y_pos(position.y()) + ) + menu.addAction(set_range_start) + + set_range_end = QAction( + Icon("icons/myicons/range-end.svg"), + _("Set Range End"), + self, + triggered=lambda: self._set_range_end_by_y_pos(position.y()) + ) + menu.addAction(set_range_end) + + reset_range = QAction( + _("Reset Range"), + self, + triggered=lambda: self._reset_range() + ) + menu.addAction(reset_range) + menu.exec(self.mapToGlobal(position)) + def _set_range_start_by_y_pos(self, y_pos: int) -> None: + line_number = self.y_pos_to_line(y_pos) + self.lines = self.model.data(self._byte_offset, 0, line_number + 1, self._range_start, + self._range_end) + range_start = self.lines[line_number].byte_offset() + self.parent.range_limit.set_range_start(range_start) + + def _set_range_end_by_y_pos(self, y_pos: int) -> None: + line_number = self.y_pos_to_line(y_pos) + self.lines = self.model.data(self._byte_offset, 0, line_number + 1, self._range_start, + self._range_end) + range_end = self.lines[line_number].byte_end() + 1 + + self.parent.range_limit.set_range_end(range_end) + + def _reset_range(self): + self.parent.range_limit.set_range_start(0) + self.parent.range_limit.set_range_end(self.model.byte_count()) + def scroll_by_lines(self, scroll_lines: int): self.scroll_lines = scroll_lines self.update() @@ -511,8 +556,10 @@ class InnerBigText(QWidget): self._byte_offset = self.lines[0].byte_offset() if len(self.lines) > 0 else 0 # print("new byte offset: ", self._byte_offset) # document length == maximum + pageStep + aFewBytesSoThatTheLastLineIsShown - vmax = self.model.byte_count() - 1 if self._range_end < 0 else min(self._range_end, self.model.byte_count() - 1) + 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) self.parent.v_scroll_bar.setMaximum(vmax) + self.parent.range_limit.set_maximum(byte_count) for line in self.lines: self.update_longest_line(len(line.line())) diff --git a/src/ui/rangeslider.py b/src/ui/rangeslider.py index 408ce75..c73756a 100644 --- a/src/ui/rangeslider.py +++ b/src/ui/rangeslider.py @@ -7,8 +7,10 @@ from PySide6.QtCore import QRect, QPoint, Signal from PySide6.QtGui import QPainter, Qt from PySide6.QtWidgets import QWidget +from src.pluginregistry import PluginRegistry +from src.util import conversion from src.util.color import to_qcolor - +from src.i18n import _ class RangeSliderHandle(): def __init__(self, value: int): @@ -27,7 +29,13 @@ class UpdateStyle(Enum): class RangeSlider(QWidget): - value_changed = Signal(float, float) + value_changed = Signal(str, str) + """Signal emitted when the range slider value changes. + **Note**: The value is a string and must be parsed into an int. + QT's signal api only supports 32bit integers. Ints larger + than 2**32-1 will overflow. Probably because there is some C/C++ + code involved. We work around this by converting the python int + into a string.""" _width = 20 _handle_width = 12 @@ -42,11 +50,22 @@ class RangeSlider(QWidget): self.max_value = 100 self.lower_value = RangeSliderHandle(0) - self.upper_value = RangeSliderHandle(100) + self.upper_value = RangeSliderHandle(self.max_value) self.selected_handle = None self.selection_drag_range = (self.min_value, self.max_value) + def set_maximum(self, max: int): + if self.max_value == max: + return + was_at_max = self.upper_value.value == self.max_value + + self.max_value = max + + if was_at_max: + self.upper_value.value = max + self._emit_value_changed() + def paintEvent(self, event: PySide6.QtGui.QPaintEvent) -> None: painter = QPainter(self) self._draw_background(painter) @@ -104,13 +123,13 @@ class RangeSlider(QWidget): painter.drawEllipse(QPoint(self._width / 2, y_pixel), self._handle_width / 2 - 1, self._handle_width / 2 - 1) def _value_to_pixel(self, value: int) -> int: - value_percent = value / (self.max_value - self.min_value) + value_percent = value / self.max_value pixel = (self.height() - 2 * self._handle_width) * value_percent + self._handle_width return pixel def _pixel_to_value(self, pixel: int) -> int: pixel_percent = (pixel - self._handle_width) / (self.height() - 2 * self._handle_width) - return (self.max_value - self.min_value) * pixel_percent + return int(math.floor(self.max_value * pixel_percent)) def _is_on_handle(self, handle: RangeSliderHandle, y_pixel: int, direction=1) -> bool: handle_y_pixel = self._value_to_pixel(handle.value) @@ -139,5 +158,28 @@ class RangeSlider(QWidget): if self.selection_drag_range[0] <= value <= self.selection_drag_range[1]: self.selected_handle.value = value # print("%s, %s" %(self.lower_value.value, self.upper_value.value)) - self.value_changed.emit(self.lower_value.value, self.upper_value.value) + self._emit_value_changed() self.update() + self._update_tooltip() + + def set_range_start(self, value: int): + self.lower_value.value = value + self._emit_value_changed() + self.update() + + def set_range_end(self, value: int): + self.upper_value.value = value + self._emit_value_changed() + self.update() + + def _emit_value_changed(self): + # print(f"emit {str(self.lower_value.value)}, {str(self.upper_value.value)}") + self.value_changed.emit(str(self.lower_value.value), str(self.upper_value.value)) + + def _update_tooltip(self): + text = _("showing bytes {0} to {1} ({2})").format( + self.lower_value.value, + self.upper_value.value, + conversion.humanbytes(self.upper_value.value - self.lower_value.value)) + PluginRegistry.execute("update_status_bar", text) + self.setToolTip(text)