From 9e5e2c6718ed2abae7d54e6eac189914968c671d Mon Sep 17 00:00:00 2001 From: miruka Date: Wed, 17 Apr 2019 17:07:20 -0400 Subject: [PATCH] Use a Deque for roomEvents's ListModel - Take a custom container callable for ListModel __init__ (defaults to list, must be a MutableSequence) - Use a Deque for roomEvents, which is much faster for inserting new items at the beginning. --- harmonyqml/backend/model/list_model.py | 44 ++++++++++--------- harmonyqml/backend/model/list_model_map.py | 8 ++-- harmonyqml/backend/model/qml_models.py | 4 +- .../components/chat/MessageDelegate.qml | 3 -- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/harmonyqml/backend/model/list_model.py b/harmonyqml/backend/model/list_model.py index 2a587978..f8457251 100644 --- a/harmonyqml/backend/model/list_model.py +++ b/harmonyqml/backend/model/list_model.py @@ -1,6 +1,7 @@ import logging from typing import ( - Any, Dict, Iterable, List, Mapping, Optional, Sequence, Tuple, Union + Any, Callable, Dict, Iterable, List, Mapping, MutableSequence, Optional, + Sequence, Tuple, Union ) from namedlist import namedlist @@ -17,23 +18,24 @@ class ListModel(QAbstractListModel): changed = pyqtSignal() def __init__(self, - initial_data: Optional[List[NewValue]] = None, - parent: Optional[QObject] = None) -> None: + initial_data: Optional[List[NewValue]] = None, + container: Callable[..., MutableSequence] = list, + parent: Optional[QObject] = None) -> None: super().__init__(parent) - self._ref_namedlist = None - self._roles: Tuple[str, ...] = () - self._list: list = [] + self._ref_namedlist = None + self._roles: Tuple[str, ...] = () + self._data: MutableSequence = container() if initial_data: self.extend(initial_data) def __repr__(self) -> str: - return "%s[%s]" % (type(self).__name__, - ", ".join((repr(i) for i in self))) + return "%s(%r)" % (type(self).__name__, self._data) + def __getitem__(self, index): - return self._list[index] + return self._data[index] def __setitem__(self, index, value) -> None: @@ -57,11 +59,11 @@ class ListModel(QAbstractListModel): if role <= Qt.UserRole: return None - return self._list[index.row()][role - Qt.UserRole - 1] + return self._data[index.row()][role - Qt.UserRole - 1] def rowCount(self, _: QModelIndex = QModelIndex()) -> int: - return len(self._list) + return len(self._data) def _convert_new_value(self, value: NewValue) -> Any: @@ -98,12 +100,12 @@ class ListModel(QAbstractListModel): @pyqtSlot(int, result="QVariantMap") def get(self, index: int) -> ReturnItem: - return self._list[index]._asdict() + return self._data[index]._asdict() @pyqtSlot(str, "QVariant", result=int) def indexWhere(self, prop: str, is_value: Any) -> int: - for i, item in enumerate(self._list): + for i, item in enumerate(self._data): if getattr(item, prop) == is_value: return i @@ -120,7 +122,7 @@ class ListModel(QAbstractListModel): def insert(self, index: int, value: NewValue) -> None: value = self._convert_new_value(value) self.beginInsertRows(QModelIndex(), index, index) - self._list.insert(index, value) + self._data.insert(index, value) self.endInsertRows() self.changed.emit() @@ -140,14 +142,14 @@ class ListModel(QAbstractListModel): def set(self, index: int, value: NewValue) -> None: qidx = QAbstractListModel.index(self, index, 0) value = self._convert_new_value(value) - self._list[index] = value + self._data[index] = value self.dataChanged.emit(qidx, qidx, self.roleNames()) self.changed.emit() @pyqtSlot(int, str, "QVariant") def setProperty(self, index: int, prop: str, value: Any) -> None: - self._list[index][self._roles.index(prop)] = value + self._data[index][self._roles.index(prop)] = value qidx = QAbstractListModel.index(self, index, 0) self.dataChanged.emit(qidx, qidx, self.roleNames()) self.changed.emit() @@ -175,9 +177,9 @@ class ListModel(QAbstractListModel): return last = from_ + n - cut = self._list[from_:last] - del self._list[from_:last] - self._list[to:to] = cut + cut = self._data[from_:last] + del self._data[from_:last] + self._data[to:to] = cut self.endMoveRows() self.changed.emit() @@ -186,7 +188,7 @@ class ListModel(QAbstractListModel): @pyqtSlot(int) def remove(self, index: int) -> None: # pylint: disable=arguments-differ self.beginRemoveRows(QModelIndex(), index, index) - del self._list[index] + del self._data[index] self.endRemoveRows() self.changed.emit() @@ -195,6 +197,6 @@ class ListModel(QAbstractListModel): def clear(self) -> None: # Reimplemented for performance reasons (begin/endRemoveRows) self.beginRemoveRows(QModelIndex(), 0, self.rowCount()) - self._list.clear() + self._data.clear() self.endRemoveRows() self.changed.emit() diff --git a/harmonyqml/backend/model/list_model_map.py b/harmonyqml/backend/model/list_model_map.py index 51322bc9..23c3a31e 100644 --- a/harmonyqml/backend/model/list_model_map.py +++ b/harmonyqml/backend/model/list_model_map.py @@ -1,4 +1,4 @@ -from typing import Any, DefaultDict +from typing import Any, Callable, DefaultDict, MutableSequence from PyQt5.QtCore import QObject, pyqtSlot @@ -6,12 +6,14 @@ from .list_model import ListModel class ListModelMap(QObject): - def __init__(self) -> None: + def __init__(self, models_container: Callable[..., MutableSequence] = list + ) -> None: super().__init__() # Set the parent to prevent item garbage-collection on the C++ side self.dict: DefaultDict[Any, ListModel] = \ - DefaultDict(lambda: ListModel(parent=self)) + DefaultDict(lambda: ListModel(parent = self, + container = models_container)) @pyqtSlot(str, result="QVariant") diff --git a/harmonyqml/backend/model/qml_models.py b/harmonyqml/backend/model/qml_models.py index d3fd4585..b70d5743 100644 --- a/harmonyqml/backend/model/qml_models.py +++ b/harmonyqml/backend/model/qml_models.py @@ -1,6 +1,8 @@ # Copyright 2019 miruka # This file is part of harmonyqml, licensed under GPLv3. +from typing import Deque + from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal from .list_model import ListModel @@ -15,7 +17,7 @@ class QMLModels(QObject): super().__init__() self._accounts: ListModel = ListModel() self._rooms: ListModelMap = ListModelMap() - self._room_events: ListModelMap = ListModelMap() + self._room_events: ListModelMap = ListModelMap(models_container=Deque) @pyqtProperty(ListModel, constant=True) diff --git a/harmonyqml/components/chat/MessageDelegate.qml b/harmonyqml/components/chat/MessageDelegate.qml index 61ea8536..dc897c5b 100644 --- a/harmonyqml/components/chat/MessageDelegate.qml +++ b/harmonyqml/components/chat/MessageDelegate.qml @@ -7,7 +7,6 @@ Column { id: "rootCol" function mins_between(date1, date2) { - console.log(Math.round((((date2 - date1) % 86400000) % 3600000) / 60000)) return Math.round((((date2 - date1) % 86400000) % 3600000) / 60000) } @@ -59,8 +58,6 @@ Column { combine ? standardSpacing / 4 : standardSpacing - //Text { text: rootCol.topPadding } - Daybreak { visible: dayBreak } MessageContent { visible: isMessage }