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()
zip_buffer.close()
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))),
(("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 typing import Any
from cbz.constants import YesNo, Manga, AgeRating, Format, PageType, FIELDS, PAGE_FIELDS
from cbz.utils import _get, _set
class ComicModel:
@@ -48,35 +48,25 @@ class ComicModel:
_filepath: str = ""
def __init__(self, kwargs: dict):
"""
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)
_set(self, FIELDS, kwargs)
def _get(self) -> dict:
"""
Create dictionary from variables by FIELDS
:return: dictionary with variables value
"""
return {key[1]: self._check_type(value[0], getattr(self, value[0]), value[1]) for key, value in FIELDS}
return _get(self, FIELDS)
class PageModel:
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 json
from io import BytesIO
from typing import Union
from pathlib import Path
from typing import Union
from PIL import Image
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):
with Image.open(BytesIO(content)) as image:
self.suffix = f'.{image.format.lower()}'
super(PageInfo, self).__init__(kwargs)
self.content = content
self.__info = {
# 'Image': 0,
'Type': PageType(kwargs.get('type', PageType.STORY)),
'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)
}
@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._image_width = int(image.width)
self._image_height = int(image.height)
self._image_size = len(value)
self._content = value
def dumps(self) -> dict:
return utils.dumps(self.__info)
return utils.dumps(self._get())
def __repr__(self) -> str:
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}')
with Path(path).open(mode='rb') as f:
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 typing import Any
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'}
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