more tests for scrolling

This commit is contained in:
2021-10-25 16:20:30 +02:00
parent 3662b47651
commit 603b748180
5 changed files with 173 additions and 18 deletions

View File

@@ -93,7 +93,7 @@ class InnerBigText(QWidget):
self.scroll_by_lines(-3) self.scroll_by_lines(-3)
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
#print("wheel event fired :) %s" % (direction)) #print("wheel event fired :) %s" % (direction))
self.scroll_by_lines(direction * 3) self.scroll_by_lines(direction * 3)
@@ -164,9 +164,9 @@ class InnerBigText(QWidget):
self.lines = self.model.data(self._byte_offset, self.scroll_lines, lines_to_show) self.lines = self.model.data(self._byte_offset, self.scroll_lines, lines_to_show)
#print("lines_to_show: %d returned: %d" % (lines_to_show, len(self.lines))) #print("lines_to_show: %d returned: %d" % (lines_to_show, len(self.lines)))
self.scroll_lines=0 self.scroll_lines=0
self._byte_offset = self.lines[0].byte_offset() self._byte_offset = self.lines[0].byte_offset() if len(self.lines) > 0 else 0
# document length == maximum + pageStep + aFewBytesSoThatTheLastLineIsShown # document length == maximum + pageStep + aFewBytesSoThatTheLastLineIsShown
self.parent.v_scroll_bar.setMaximum(self.model.byte_count() - 1 - 10) self.parent.v_scroll_bar.setMaximum(self.model.byte_count() - 1)
for l in self.lines: for l in self.lines:

View File

@@ -31,4 +31,7 @@ class Line:
return self._line[offset:offset+length] return self._line[offset:offset+length]
def suffix(self, index: int) -> str: def suffix(self, index: int) -> str:
return self._line[index:] return self._line[index:]
def __str__(self):
return "%s (%d->%d)" % (self._line, self._byte_offset, self._byte_end)

View File

@@ -1,8 +1,8 @@
import math
import threading import threading
from typing import List from typing import List
import os
from line import Line from line import Line
import os
from settings import Settings from settings import Settings
@@ -13,11 +13,12 @@ class LogFileModel:
self._file = file self._file = file
def data(self, byte_offset, scroll_lines, lines) -> List[Line]: def data(self, byte_offset, scroll_lines, lines) -> List[Line]:
#print("data(%s, %s, %s)" % (byte_offset, scroll_lines, lines)) print("data(%s, %s, %s)" % (byte_offset, scroll_lines, lines))
lines_before_offset: List[Line] = [] lines_before_offset: List[Line] = []
lines_after_offset: List[Line] = [] lines_after_offset: List[Line] = []
result: List[Line] = [] result: List[Line] = []
lines_to_find = lines + abs(scroll_lines) lines_to_find = lines + abs(scroll_lines)
lines_to_return = math.ceil(lines)
with self._lock: with self._lock:
# TODO handle lines longer than 4096 bytes # TODO handle lines longer than 4096 bytes
@@ -42,18 +43,12 @@ class LogFileModel:
eof_reached = False eof_reached = False
break break
if scroll_lines > 0: all_lines = lines_before_offset + lines_after_offset
result = result + lines_before_offset[-scroll_lines:] start = max(0, len(lines_before_offset) + scroll_lines)
result = result + lines_after_offset if start + lines_to_return-1 < len(all_lines):
elif eof_reached: result = all_lines[start:start+lines_to_return]
# we always return the number of requested lines even if we reach the end of the file
lines_to_return_from_before_offset = int(lines_to_find - len(lines_after_offset));
#print(lines_to_return_from_before_offset)
if lines_to_return_from_before_offset > 0:
result = result + lines_before_offset[-lines_to_return_from_before_offset:]
result = result + lines_after_offset
else: else:
result = result + lines_after_offset[-scroll_lines:] result = all_lines[-lines_to_return+1:]
#print("returning %s lines" % (len(result))) #print("returning %s lines" % (len(result)))
return result return result

15
scribble.py Normal file
View File

@@ -0,0 +1,15 @@
import math
before = []#[0,1,2,3]
after = ["a","b","c","d"]
both = before + after
scroll = -3
lines = 1
start = len(before) + scroll
if start+lines < len(both):
result = both[start:start+lines]
else:
result = both[-lines:]
print("%s" % result)

142
testlogfilemodel.py Normal file
View File

@@ -0,0 +1,142 @@
import unittest
import tempfile
from os.path import join
from logFileModel import LogFileModel
from line import Line
class TestLogFileModel(unittest.TestCase):
def setUp(self):
self.test_dir = tempfile.TemporaryDirectory()
self.tmpfile = join(self.test_dir.name, "my.log")
self.model = LogFileModel(self.tmpfile)
def tearDown(self):
self.test_dir.cleanup()
def write_str(self, string: str):
with open(self.tmpfile, "w+b") as f:
f.write(string.encode("utf8"))
def test_load_from_beginning(self):
self.write_str("1\n2\n3\n4\n5\n6\n7\n")
expected_lines = ["1", "2", "3", "4", "5"]
lines = self.model.data(0, 0, 5)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_load_from_middle_of_first_line(self):
self.write_str("abc\ndef\nghi\njkl")
expected_lines = ["def", "ghi", "jkl"]
lines = self.model.data(1, 0, 3)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_read_from_newline_character(self):
self.write_str("abc\ndef\nghi\njkl")
expected_lines = ["def", "ghi"]
lines = self.model.data(3, 0, 2)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_negative_byte_offset(self):
self.write_str("abc\ndef\nghi\njkl")
expected_lines = ["abc","def"]
lines = self.model.data(-1, 0, 2)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_empty_last_line_is_ignored(self):
self.write_str("1\n")
expected_lines = ["1"]
lines = self.model.data(0, 0, 5)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_load_more_lines_than_are_available(self):
"""
Wants to read 4 lines in a file with only 3 lines.
Returns all three lines.
"""
self.write_str("abc\ndef\nghi")
expected_lines = ["abc", "def", "ghi"]
lines = self.model.data(0, 0, 4)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_read_behind_eof(self):
"""
Wants to read 4 lines from the middle of the second line.
File has only 3 lines.
Returns all 3 lines.
"""
text = "abc\ndef\nghi"
self.write_str(text)
expected_lines = ["abc", "def", "ghi"]
lines = self.model.data(text.index("e"), 0, 4)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_read_after_scrolling_2_lines(self):
"""
"""
text = "0___\n1___\n2___\n3___\n4___\n5___"
self.write_str(text)
expected_lines = ["3___", "4___"]
lines = self.model.data(text.index("1___"), 2, 2)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_scroll_with_float(self):
"""
If lines to lines to return is a float, then the value is rounded up.
Floats mean that the text area is such that a line is partially visible.
"""
text = "0___\n1___\n2___\n3___\n4___\n5___"
self.write_str(text)
expected_lines = ["3___","4___", "5___"]
lines = self.model.data(text.index("1___"), 2, 2.1)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
def test_scroll_up_at_beginning_of_file(self):
"""
Scrolling up at beginning of file.
Return
"""
text = "0___\n1___\n2___\n3___\n4___\n5___"
self.write_str(text)
expected_lines = ["0___", "1___"]
lines = self.model.data(5, -2, 2)
line_str = [l.line() for l in lines]
self.assertEqual(expected_lines, line_str)
if __name__ == '__main__':
unittest.main()