Compare commits
6 Commits
0.2.1
...
b8b4b4e790
| Author | SHA1 | Date | |
|---|---|---|---|
| b8b4b4e790 | |||
| 66d6a728cc | |||
| 56189f4094 | |||
| 5f30862a83 | |||
| 017a51a24a | |||
| 442d3173c8 |
@@ -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)
|
||||||
|
|||||||
@@ -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,30 +257,31 @@ class InnerBigText(QWidget):
|
|||||||
manage_highlighting.setShortcut("CTRL+H")
|
manage_highlighting.setShortcut("CTRL+H")
|
||||||
menu.addAction(manage_highlighting)
|
menu.addAction(manage_highlighting)
|
||||||
|
|
||||||
menu.addSeparator()
|
if self.parent.show_range_slider:
|
||||||
|
menu.addSeparator()
|
||||||
|
|
||||||
set_range_start = QAction(
|
set_range_start = QAction(
|
||||||
Icon("icons/myicons/range-start.svg"),
|
Icon("icons/myicons/range-start.svg"),
|
||||||
_("Set Range Start"),
|
_("Set Range Start"),
|
||||||
self,
|
self,
|
||||||
triggered=lambda: self._set_range_start_by_y_pos(position.y())
|
triggered=lambda: self._set_range_start_by_y_pos(position.y())
|
||||||
)
|
)
|
||||||
menu.addAction(set_range_start)
|
menu.addAction(set_range_start)
|
||||||
|
|
||||||
set_range_end = QAction(
|
set_range_end = QAction(
|
||||||
Icon("icons/myicons/range-end.svg"),
|
Icon("icons/myicons/range-end.svg"),
|
||||||
_("Set Range End"),
|
_("Set Range End"),
|
||||||
self,
|
self,
|
||||||
triggered=lambda: self._set_range_end_by_y_pos(position.y())
|
triggered=lambda: self._set_range_end_by_y_pos(position.y())
|
||||||
)
|
)
|
||||||
menu.addAction(set_range_end)
|
menu.addAction(set_range_end)
|
||||||
|
|
||||||
reset_range = QAction(
|
reset_range = QAction(
|
||||||
_("Reset Range"),
|
_("Reset Range"),
|
||||||
self,
|
self,
|
||||||
triggered=lambda: self._reset_range()
|
triggered=lambda: self._reset_range()
|
||||||
)
|
)
|
||||||
menu.addAction(reset_range)
|
menu.addAction(reset_range)
|
||||||
|
|
||||||
menu.exec(self.mapToGlobal(position))
|
menu.exec(self.mapToGlobal(position))
|
||||||
|
|
||||||
@@ -559,7 +555,8 @@ 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)
|
||||||
self.parent.range_limit.set_maximum(byte_count)
|
if self.parent.show_range_slider:
|
||||||
|
self.parent.range_limit.set_maximum(byte_count)
|
||||||
|
|
||||||
for line in self.lines:
|
for line in self.lines:
|
||||||
self.update_longest_line(len(line.line()))
|
self.update_longest_line(len(line.line()))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user