Implementation of page controller

This commit is contained in:
Oleskii Pyskun
2024-07-02 10:08:55 +03:00
parent 5515fd3660
commit 2a508f0265
5 changed files with 163 additions and 49 deletions
+57
View File
@@ -118,3 +118,60 @@ class ComicInfo(ComicModel):
result = zip_buffer.getvalue() result = zip_buffer.getvalue()
zip_buffer.close() zip_buffer.close()
return result return result
def get_page(self, index: int) -> PageInfo:
"""
Get page by index
:param index:
:return:
"""
return self.__pages[index]
def show_page(self, index: int) -> None:
"""
Display page by index
:param index:
:return:
"""
self.__pages[index].show()
def delete_page(self, index: int) -> PageInfo:
"""
Delete page by index
:param index:
:return: deleted page
"""
return self.__pages.pop(index)
def add_page(self, page: PageInfo) -> list[PageInfo]:
"""
Add new page to the book
:param page:
:return: new list of pages
"""
self.__pages.append(page)
return self.__pages
def insert_page(self, index: int, page: PageInfo) -> list[PageInfo]:
"""
Add new page to position
:param page:
:param index:
:return:
"""
self.__pages.insert(index, page)
return self.__pages
def get_pages_count(self) -> int:
"""
Get count of pages
:return:
"""
return len(self.__pages)
def get_all_pages(self) -> list[PageInfo]:
"""
Get all pages of book
:return:
"""
return self.__pages
+12
View File
@@ -162,3 +162,15 @@ FIELDS = (
(("language_iso", "LanguageISO"), ("language_iso", (ValidLanguage, str))), (("language_iso", "LanguageISO"), ("language_iso", (ValidLanguage, str))),
(("community_rating", "CommunityRating"), ("community_rating", (ValidRating, float, int, str))), (("community_rating", "CommunityRating"), ("community_rating", (ValidRating, float, int, str))),
) )
PAGE_FIELDS = (
# model: (key, xml key): (variable name, (expected type, second expected type,...))
# in case of multiple expected formats, value cast to first type in tuple
(("type", "Type"), ("type", (PageType, str))),
(("double", "DoublePage"), ("double", (bool,))),
(("key", "Key"), ("key", (str,))),
(("bookmark", "Bookmark"), ("bookmark", (str,))),
(("image_size", "ImageSize"), ("_image_size", (int,))),
(("image_width", "ImageWidth"), ("_image_width", (int,))),
(("image_height", "ImageHeight"), ("_image_height", (int,))),
)
+22 -32
View File
@@ -1,5 +1,5 @@
from cbz.constants import YesNo, Manga, AgeRating, Format, FIELDS from cbz.constants import YesNo, Manga, AgeRating, Format, PageType, FIELDS, PAGE_FIELDS
from typing import Any from cbz.utils import _get, _set
class ComicModel: class ComicModel:
@@ -48,35 +48,25 @@ class ComicModel:
_filepath: str = "" _filepath: str = ""
def __init__(self, kwargs: dict): def __init__(self, kwargs: dict):
""" _set(self, FIELDS, kwargs)
Set class variables from input dictionary, check types of input and cast values to correct type
:param kwargs: dictionary of input data
"""
for kwarg_key, kwarg_value in kwargs.items():
for keys, values in FIELDS:
if kwarg_key in keys:
variable, types = values
if hasattr(self, variable):
setattr(self, variable, self._check_type(kwarg_key, kwarg_value, types))
break
@staticmethod
def _check_type(key: str, value: Any, types: tuple) -> Any:
"""
Check type of value, and cast this value to first type of the types
:param key: name of key of variable (using only for best error information)
:param value: value for a check
:param types: list of the allowed types
:return: value with new type
"""
if not isinstance(value, types):
raise ValueError(
f"Unexpected type of {key}, got: {type(value).__name__}, expected: {[i.__name__ for i in types]}")
return types[0](value)
def _get(self) -> dict: def _get(self) -> dict:
""" return _get(self, FIELDS)
Create dictionary from variables by FIELDS
:return: dictionary with variables value
""" class PageModel:
return {key[1]: self._check_type(value[0], getattr(self, value[0]), value[1]) for key, value in FIELDS} suffix: str
_content: bytes
type: PageType = PageType.STORY
double: bool = False
_image_size: int = 0
key: str = ""
bookmark: str = ""
_image_width: int = 0
_image_height: int = 0
def __init__(self, kwargs: dict):
_set(self, PAGE_FIELDS, kwargs)
def _get(self) -> dict:
return _get(self, PAGE_FIELDS)
+35 -17
View File
@@ -3,35 +3,45 @@ from __future__ import annotations
import base64 import base64
import json import json
from io import BytesIO from io import BytesIO
from typing import Union
from pathlib import Path from pathlib import Path
from typing import Union
from PIL import Image from PIL import Image
from cbz import utils from cbz import utils
from cbz.constants import PageType from cbz.models import PageModel
class PageInfo: class PageInfo(PageModel):
def __init__(self, content: bytes, **kwargs): def __init__(self, content: bytes, **kwargs):
with Image.open(BytesIO(content)) as image: super(PageInfo, self).__init__(kwargs)
self.content = content
@property
def content(self) -> bytes:
"""
content getter
:return:
"""
return self._content
@content.setter
def content(self, value) -> None:
"""
Set image info by current content
:param value:
:return:
"""
with Image.open(BytesIO(value)) as image:
self.suffix = f'.{image.format.lower()}' self.suffix = f'.{image.format.lower()}'
self.content = content self._image_width = int(image.width)
self.__info = { self._image_height = int(image.height)
# 'Image': 0, self._image_size = len(value)
'Type': PageType(kwargs.get('type', PageType.STORY)), self._content = value
'DoublePage': bool(kwargs.get('double', False)),
'ImageSize': len(content),
'Key': str(kwargs.get('key', '')),
'Bookmark': str(kwargs.get('bookmark', '')),
'ImageWidth': int(image.width),
'ImageHeight': int(image.height)
}
def dumps(self) -> dict: def dumps(self) -> dict:
return utils.dumps(self.__info) return utils.dumps(self._get())
def __repr__(self) -> str: def __repr__(self) -> str:
return json.dumps(self.dumps(), indent=2) return json.dumps(self.dumps(), indent=2)
@@ -50,3 +60,11 @@ class PageInfo:
raise ValueError(f'Expecting Path object or path string, got {path!r}') raise ValueError(f'Expecting Path object or path string, got {path!r}')
with Path(path).open(mode='rb') as f: with Path(path).open(mode='rb') as f:
return cls(f.read(), **kwargs) return cls(f.read(), **kwargs)
def show(self) -> None:
"""
display this page
:return:
"""
with Image.open(BytesIO(self.content)) as image:
image.show()
+37
View File
@@ -1,5 +1,42 @@
from enum import Enum from enum import Enum
from typing import Any
def dumps(data: dict) -> dict: def dumps(data: dict) -> dict:
return {k: v.value if isinstance(v, Enum) else v for k, v in data.items() if v and v != -1 and v != 'Unknown'} return {k: v.value if isinstance(v, Enum) else v for k, v in data.items() if v and v != -1 and v != 'Unknown'}
def _check_type(key: str, value: Any, types: tuple) -> Any:
"""
Check type of value, and cast this value to first type of the types
:param key: name of key of variable (using only for best error information)
:param value: value for a check
:param types: list of the allowed types
:return: value with new type
"""
if not isinstance(value, types):
raise ValueError(
f"Unexpected type of {key}, got: {type(value).__name__}, expected: {[i.__name__ for i in types]}")
return types[0](value)
def _get(obj: Any, fields: tuple) -> dict:
"""
Create dictionary from variables by PAGE_FIELDS
:return: dictionary with variables value
"""
return {key[1]: _check_type(value[0], getattr(obj, value[0]), value[1]) for key, value in fields}
def _set(obj: Any, fields: tuple, data_dict: dict) -> None:
"""
Set class variables from input dictionary, check types of input and cast values to correct type
:param kwargs: dictionary of input data
"""
for kwarg_key, kwarg_value in data_dict.items():
for keys, values in fields:
if kwarg_key in keys:
variable, types = values
if hasattr(obj, variable):
setattr(obj, variable, _check_type(kwarg_key, kwarg_value, types))
break