Refix Event.source, JSONify dicts for ListModel

This commit is contained in:
miruka 2020-02-12 13:04:46 -04:00
parent ae780345e8
commit ce0a868579
9 changed files with 37 additions and 28 deletions

View File

@ -42,9 +42,6 @@
- Don't put all the binds in one central file - Don't put all the binds in one central file
- Missing room keybinds (invite, etc) and close failed upload - Missing room keybinds (invite, etc) and close failed upload
- Use QML states? - Use QML states?
- Try gel for the models and stop being lazy in python
- Room Sidepane save/load size & keybinds
## Issues ## Issues
@ -76,6 +73,7 @@
## Interface ## Interface
- Room Sidepane keybinds
- Remember ctrl+tab page target - Remember ctrl+tab page target
- https://doc.qt.io/qt-5/qml-qtquick-smoothedanimation.html for progress bars - https://doc.qt.io/qt-5/qml-qtquick-smoothedanimation.html for progress bars
- Make all "Cancel" buttons able to cancel running Backend coroutines set - Make all "Cancel" buttons able to cancel running Backend coroutines set

View File

@ -3,6 +3,7 @@
"""`ModelItem` subclasses definitions.""" """`ModelItem` subclasses definitions."""
import asyncio import asyncio
import json
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime, timedelta from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
@ -217,7 +218,8 @@ class Event(ModelItem):
def serialize_field(self, field: str) -> Any: def serialize_field(self, field: str) -> Any:
if field == "source": if field == "source":
return self.source.__dict__ if self.source else {} source_dict = nio.attr.asdict(self.source) if self.source else {}
return json.dumps(source_dict)
return super().serialize_field(field) return super().serialize_field(field)

View File

@ -56,7 +56,10 @@ class ModelItem:
def serialize_field(self, field: str) -> Any: def serialize_field(self, field: str) -> Any:
return serialize_value_for_qml(getattr(self, field), json_lists=True) return serialize_value_for_qml(
getattr(self, field),
json_list_dicts=True,
)
@property @property

View File

@ -17,13 +17,11 @@ if TYPE_CHECKING:
class PyOtherSideEvent: class PyOtherSideEvent:
"""Event that will be sent on instanciation to QML by PyOtherSide.""" """Event that will be sent on instanciation to QML by PyOtherSide."""
json_lists = False
def __post_init__(self) -> None: def __post_init__(self) -> None:
# CPython 3.6 or any Python implemention >= 3.7 is required for correct # CPython 3.6 or any Python implemention >= 3.7 is required for correct
# __dataclass_fields__ dict order. # __dataclass_fields__ dict order.
args = [ args = [
serialize_value_for_qml(getattr(self, field), self.json_lists) serialize_value_for_qml(getattr(self, field))
for field in self.__dataclass_fields__ # type: ignore for field in self.__dataclass_fields__ # type: ignore
] ]
pyotherside.send(type(self).__name__, *args) pyotherside.send(type(self).__name__, *args)
@ -65,19 +63,14 @@ class LoopException(PyOtherSideEvent):
@dataclass @dataclass
class ModelEvent(ABC, PyOtherSideEvent): class ModelItemInserted(PyOtherSideEvent):
json_lists = True
@dataclass
class ModelItemInserted(ModelEvent):
sync_id: SyncId = field() sync_id: SyncId = field()
index: int = field() index: int = field()
item: "ModelItem" = field() item: "ModelItem" = field()
@dataclass @dataclass
class ModelItemFieldChanged(ModelEvent): class ModelItemFieldChanged(PyOtherSideEvent):
sync_id: SyncId = field() sync_id: SyncId = field()
item_index_then: int = field() item_index_then: int = field()
item_index_now: int = field() item_index_now: int = field()
@ -86,11 +79,11 @@ class ModelItemFieldChanged(ModelEvent):
@dataclass @dataclass
class ModelItemDeleted(ModelEvent): class ModelItemDeleted(PyOtherSideEvent):
sync_id: SyncId = field() sync_id: SyncId = field()
index: int = field() index: int = field()
@dataclass @dataclass
class ModelCleared(ModelEvent): class ModelCleared(PyOtherSideEvent):
sync_id: SyncId = field() sync_id: SyncId = field()

View File

@ -8,12 +8,12 @@ import inspect
import io import io
import json import json
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
from datetime import timedelta from datetime import datetime, timedelta
from enum import Enum from enum import Enum
from enum import auto as autostr from enum import auto as autostr
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import Any, Dict, Tuple, Type from typing import Any, Dict, Mapping, Sequence, Tuple, Type
from uuid import UUID from uuid import UUID
import filetype import filetype
@ -125,7 +125,7 @@ def plain2html(text: str) -> str:
.replace("\t", " " * 4) .replace("\t", " " * 4)
def serialize_value_for_qml(value: Any, json_lists: bool = False) -> Any: def serialize_value_for_qml(value: Any, json_list_dicts: bool = False) -> Any:
"""Convert a value to make it easier to use from QML. """Convert a value to make it easier to use from QML.
Returns: Returns:
@ -138,7 +138,10 @@ def serialize_value_for_qml(value: Any, json_lists: bool = False) -> Any:
- `ModelItem.serialized` for `ModelItem`s - `ModelItem.serialized` for `ModelItem`s
""" """
if json_lists and isinstance(value, list): if isinstance(value, (int, float, bool, str, datetime)):
return value
if json_list_dicts and isinstance(value, (Sequence, Mapping)):
return json.dumps(value) return json.dumps(value)
if hasattr(value, "serialized"): if hasattr(value, "serialized"):

View File

@ -64,8 +64,11 @@ HColumnLayout {
function json() { function json() {
const events = ModelStore.get(chat.userId, chat.roomId, "events") let event = ModelStore.get(chat.userId, chat.roomId, "events")
return JSON.stringify(events.get(model.id), null, 4) .get(model.id)
event = JSON.parse(JSON.stringify(event))
event.source = JSON.parse(event.source)
return JSON.stringify(event, null, 4)
} }
function openContextMenu() { function openContextMenu() {

View File

@ -40,6 +40,8 @@ HTile {
property EventMediaLoader loader property EventMediaLoader loader
readonly property bool cryptDict: loader.singleMediaInfo.media_crypt_dict readonly property bool cryptDict:
JSON.parse(loader.singleMediaInfo.media_crypt_dict)
readonly property bool isEncrypted: ! utils.isEmptyObject(cryptDict) readonly property bool isEncrypted: ! utils.isEmptyObject(cryptDict)
} }

View File

@ -15,9 +15,11 @@ HMxcImage {
mxc: thumbnail ? mxc: thumbnail ?
(loader.thumbnailMxc || loader.mediaUrl) : (loader.thumbnailMxc || loader.mediaUrl) :
(loader.mediaUrl || loader.thumbnailMxc) (loader.mediaUrl || loader.thumbnailMxc)
cryptDict: thumbnail && loader.thumbnailMxc ? cryptDict: JSON.parse(
thumbnail && loader.thumbnailMxc ?
loader.singleMediaInfo.thumbnail_crypt_dict : loader.singleMediaInfo.thumbnail_crypt_dict :
loader.singleMediaInfo.media_crypt_dict loader.singleMediaInfo.media_crypt_dict
)
property EventMediaLoader loader property EventMediaLoader loader

View File

@ -80,7 +80,10 @@ HLoader {
if (! downloadedPath) print("Downloading " + loader.mediaUrl + " ...") if (! downloadedPath) print("Downloading " + loader.mediaUrl + " ...")
const args = [loader.mediaUrl, loader.singleMediaInfo.media_crypt_dict] const args = [
loader.mediaUrl,
JSON.parse(loader.singleMediaInfo.media_crypt_dict)
]
py.callCoro("media_cache.get_media", args, path => { py.callCoro("media_cache.get_media", args, path => {
if (! downloadedPath) print("Done: " + path) if (! downloadedPath) print("Done: " + path)