mirror of
https://github.com/jketterl/openwebrx.git
synced 2026-01-01 22:30:12 +01:00
implement additional movement options
This commit is contained in:
parent
dcc0f404b7
commit
1fb3ed4066
|
|
@ -39,6 +39,12 @@ class ActiveListIndexDeleted(ActiveListChange):
|
|||
self.oldValue = oldValue
|
||||
|
||||
|
||||
class ActiveListIndexMoved(ActiveListChange):
|
||||
def __init__(self, old_index: int, new_index: int):
|
||||
self.old_index = old_index
|
||||
self.new_index = new_index
|
||||
|
||||
|
||||
class ActiveListListener(ABC):
|
||||
@abstractmethod
|
||||
def onListChange(self, source: "ActiveList", changes: list[ActiveListChange]):
|
||||
|
|
@ -105,6 +111,8 @@ class ActiveListTransformationListener(ActiveListListener):
|
|||
elif isinstance(change, ActiveListIndexDeleted):
|
||||
del self.target[change.index]
|
||||
self.transformation.unmonitor(change.oldValue)
|
||||
elif isinstance(change, ActiveListIndexMoved):
|
||||
self.target.move(change.old_index, change.new_index)
|
||||
|
||||
def _onMonitor(self, value):
|
||||
idx = self.source.index(value)
|
||||
|
|
@ -152,6 +160,9 @@ class ActiveListFilterListener(ActiveListListener):
|
|||
del self.keyMap[idx]
|
||||
for i in range(idx, len(self.keyMap)):
|
||||
self.keyMap[i] -= 1
|
||||
elif isinstance(change, ActiveListIndexMoved):
|
||||
idx = self.keyMap.index(change.old_index)
|
||||
#TODO update keymap, fire change event
|
||||
|
||||
def _onMonitor(self, value):
|
||||
idx = self.source.index(value)
|
||||
|
|
@ -199,6 +210,12 @@ class ActiveListFlattenListener(ActiveListListener):
|
|||
change.oldValue.removeListener(self)
|
||||
idx = self.getOffsetForIndex(change.index)
|
||||
del self.target[idx, idx + len(change.oldValue)]
|
||||
elif isinstance(change, ActiveListIndexMoved):
|
||||
old_index = self.getOffsetForIndex(change.old_index)
|
||||
new_index = self.getOffsetForIndex(change.new_index)
|
||||
moved_list = self.source[change.new_index]
|
||||
for (idx, element) in enumerate(moved_list):
|
||||
self.target.move(old_index + idx, new_index + idx)
|
||||
else:
|
||||
if isinstance(change, ActiveListIndexAdded):
|
||||
self.target.insert(self.getOffsetFor(source) + change.index, change.newValue)
|
||||
|
|
@ -206,6 +223,9 @@ class ActiveListFlattenListener(ActiveListListener):
|
|||
self.target[self.getOffsetFor(source) + change.index] = change.newValue
|
||||
elif isinstance(change, ActiveListIndexDeleted):
|
||||
del self.target[self.getOffsetFor(source) + change.index]
|
||||
elif isinstance(change, ActiveListIndexMoved):
|
||||
offset = self.getOffsetFor(source)
|
||||
self.target.move(offset + change.old_index, offset + change.new_index)
|
||||
|
||||
|
||||
class ActiveList:
|
||||
|
|
@ -241,6 +261,10 @@ class ActiveList:
|
|||
self.delegate.insert(index, value)
|
||||
self.__fireChanges([ActiveListIndexInserted(index, value)])
|
||||
|
||||
def move(self, old_index, new_index):
|
||||
self.delegate.insert(new_index, self.delegate.pop(old_index))
|
||||
self.__fireChanges([ActiveListIndexMoved(old_index, new_index)])
|
||||
|
||||
def index(self, value):
|
||||
return self.delegate.index(value)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from owrx.active.list import ActiveList, ActiveListIndexUpdated, ActiveListIndexAppended, ActiveListIndexDeleted, ActiveListIndexInserted
|
||||
from owrx.active.list import ActiveList, ActiveListIndexUpdated, ActiveListIndexAppended, ActiveListIndexDeleted, ActiveListIndexInserted, ActiveListIndexMoved
|
||||
from unittest import TestCase
|
||||
from unittest.mock import Mock
|
||||
|
||||
|
|
@ -333,3 +333,106 @@ class ActiveListTest(TestCase):
|
|||
self.assertEqual(len(filteredList), 2)
|
||||
# update should propagate
|
||||
self.assertEqual(filteredList[0], 42)
|
||||
|
||||
def testListMove(self):
|
||||
list = ActiveList([1, 2, 3, 4, 5])
|
||||
list.move(1, 4)
|
||||
self.assertEqual(len(list), 5)
|
||||
self.assertEqual(list[1], 3)
|
||||
self.assertEqual(list[4], 2)
|
||||
|
||||
list = ActiveList([1, 2, 3, 4, 5])
|
||||
list.move(4, 1)
|
||||
self.assertEqual(len(list), 5)
|
||||
self.assertEqual(list[4], 4)
|
||||
self.assertEqual(list[1], 5)
|
||||
|
||||
def testListMoveNotification(self):
|
||||
list = ActiveList([1, 2, 3, 4, 5])
|
||||
listenerMock = Mock()
|
||||
list.addListener(listenerMock)
|
||||
list.move(1, 4)
|
||||
listenerMock.onListChange.assert_called_once()
|
||||
source, changes = listenerMock.onListChange.call_args.args
|
||||
self.assertIs(source, list)
|
||||
self.assertEqual(len(changes), 1)
|
||||
self.assertIsInstance(changes[0], ActiveListIndexMoved)
|
||||
self.assertEqual(changes[0].old_index, 1)
|
||||
self.assertEqual(changes[0].new_index, 4)
|
||||
|
||||
def testActiveTransformationMove(self):
|
||||
list = ActiveList([1, 2, 3, 4, 5])
|
||||
transformedList = list.map(lambda x: x + 10)
|
||||
list.move(1, 4)
|
||||
self.assertEqual(len(transformedList), 5)
|
||||
self.assertEqual(transformedList[1], 13)
|
||||
self.assertEqual(transformedList[4], 12)
|
||||
|
||||
def testActiveTransformationMoveNotification(self):
|
||||
list = ActiveList([1, 2, 3, 4, 5])
|
||||
transformedList = list.map(lambda x: x + 10)
|
||||
listenerMock = Mock()
|
||||
transformedList.addListener(listenerMock)
|
||||
list.move(1, 4)
|
||||
listenerMock.onListChange.assert_called_once()
|
||||
source, changes = listenerMock.onListChange.call_args.args
|
||||
self.assertIs(source, transformedList)
|
||||
self.assertEqual(len(changes), 1)
|
||||
self.assertIsInstance(changes[0], ActiveListIndexMoved)
|
||||
self.assertEqual(changes[0].old_index, 1)
|
||||
self.assertEqual(changes[0].new_index, 4)
|
||||
|
||||
#def testActiveFilterMove(self):
|
||||
# list = ActiveList([1, 2, 3, 4, 5])
|
||||
# filteredList = list.filter(lambda x: x != 3)
|
||||
# list.move(1, 4)
|
||||
# self.assertEqual(len(filteredList), 4)
|
||||
# self.assertEqual(filteredList[1], 4)
|
||||
# self.assertEqual(filteredList[3], 2)
|
||||
|
||||
def testActiveListFlattenMove(self):
|
||||
firstMember = ActiveList([1, 2, 3, 4, 5])
|
||||
list = ActiveList([firstMember, ActiveList([6, 7, 8, 9, 10])])
|
||||
flattenedList = list.flatten()
|
||||
firstMember.move(1, 4)
|
||||
self.assertEqual(len(flattenedList), 10)
|
||||
self.assertEqual(flattenedList[1], 3)
|
||||
self.assertEqual(flattenedList[4], 2)
|
||||
|
||||
def testActiveListFlattenMoveNotification(self):
|
||||
firstMember = ActiveList([1, 2, 3, 4, 5])
|
||||
secondMember = ActiveList([6, 7, 8, 9, 10])
|
||||
list = ActiveList([firstMember, secondMember])
|
||||
flattenedList = list.flatten()
|
||||
listenerMock = Mock()
|
||||
flattenedList.addListener(listenerMock)
|
||||
secondMember.move(1, 4)
|
||||
listenerMock.onListChange.assert_called_once()
|
||||
source, changes = listenerMock.onListChange.call_args.args
|
||||
self.assertIs(source, flattenedList)
|
||||
self.assertEqual(len(changes), 1)
|
||||
self.assertIsInstance(changes[0], ActiveListIndexMoved)
|
||||
self.assertEqual(changes[0].old_index, 6)
|
||||
self.assertEqual(changes[0].new_index, 9)
|
||||
|
||||
def testActiveListFlattenListMove(self):
|
||||
list = ActiveList([ActiveList([1]), ActiveList([2]), ActiveList([3]), ActiveList([4]), ActiveList([5])])
|
||||
flattenedList = list.flatten()
|
||||
list.move(1, 4)
|
||||
self.assertEqual(len(flattenedList), 5)
|
||||
self.assertEqual(flattenedList[1], 3)
|
||||
self.assertEqual(flattenedList[4], 2)
|
||||
|
||||
def testActiveListFlattenListMoveNotification(self):
|
||||
list = ActiveList([ActiveList([1, 2, 3, 4, 5]), ActiveList([6, 7, 8, 9, 10])])
|
||||
flattenedList = list.flatten()
|
||||
listenerMock = Mock()
|
||||
flattenedList.addListener(listenerMock)
|
||||
list.move(0, 1)
|
||||
self.assertEqual(listenerMock.onListChange.call_count, 5)
|
||||
for i in range(0, 5):
|
||||
source, changes = listenerMock.onListChange.call_args_list[i].args
|
||||
self.assertIs(source, flattenedList)
|
||||
self.assertEqual(len(changes), 1)
|
||||
self.assertEqual(changes[0].old_index, i)
|
||||
self.assertEqual(changes[0].new_index, i + 5)
|
||||
|
|
|
|||
Loading…
Reference in a new issue