forked from mirrors/cbz
Implementation of page controller
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
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.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)
|
||||
}
|
||||
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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user