Spaces:
Sleeping
Sleeping
from typing import Dict, Optional, Type | |
from asyncer import asyncify | |
from lagent.actions.base_action import AsyncActionMixin, BaseAction, tool_api | |
from lagent.actions.parser import BaseParser, JsonParser | |
THEME_MAPPING = { | |
'Default': { | |
'template': None, | |
'title': 'Title Slide', | |
'single': 'Title and Content', | |
'two': 'Two Content', | |
} | |
} | |
class PPT(BaseAction): | |
"""Plugin to create ppt slides with text, paragraph, images in good looking styles.""" | |
def __init__( | |
self, | |
theme_mapping: Optional[Dict[str, dict]] = None, | |
description: Optional[dict] = None, | |
parser: Type[BaseParser] = JsonParser, | |
): | |
super().__init__(description, parser) | |
self.theme_mapping = theme_mapping or THEME_MAPPING | |
self.pointer = None | |
self.location = None | |
def create_file(self, theme: str, abs_location: str) -> dict: | |
"""Create a pptx file with specific themes. | |
Args: | |
theme (:class:`str`): the theme used. The value should be one of ['Default']. | |
abs_location (:class:`str`): the ppt file's absolute location | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
from pptx import Presentation | |
self.location = abs_location | |
try: | |
self.pointer = Presentation(self.theme_mapping[theme]['template']) | |
self.pointer.slide_master.name = theme | |
# print('created') | |
except Exception as e: | |
print(e) | |
return dict(status='created a ppt file.') | |
def add_first_page(self, title: str, subtitle: str) -> dict: | |
"""Add the first page of ppt. | |
Args: | |
title (:class:`str`): the title of ppt | |
subtitle (:class:`str`): the subtitle of ppt | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
layout_name = self.theme_mapping[self.pointer.slide_master.name]['title'] | |
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name) | |
slide = self.pointer.slides.add_slide(layout) | |
ph_title, ph_subtitle = slide.placeholders | |
ph_title.text = title | |
if subtitle: | |
ph_subtitle.text = subtitle | |
return dict(status='added page') | |
def add_text_page(self, title: str, bullet_items: str) -> dict: | |
"""Add text page of ppt. | |
Args: | |
title (:class:`str`): the title of the page | |
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them. | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" # noqa: E501 | |
layout_name = self.theme_mapping[self.pointer.slide_master.name]['single'] | |
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name) | |
slide = self.pointer.slides.add_slide(layout) | |
ph_title, ph_body = slide.placeholders | |
ph_title.text = title | |
ph = ph_body | |
tf = ph.text_frame | |
for i, item in enumerate(bullet_items.split('[SPAN]')): | |
if i == 0: | |
p = tf.paragraphs[0] | |
else: | |
p = tf.add_paragraph() | |
p.text = item.strip() | |
p.level = 0 | |
return dict(status='added page') | |
def add_text_image_page(self, title: str, bullet_items: str, image: str) -> dict: | |
"""Add a text page with one image. Image should be a path. | |
Args: | |
title (:class:`str`): the title of the page | |
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them. | |
image (:class:`str`): the path of the image | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" # noqa: E501 | |
from PIL import Image | |
layout_name = self.theme_mapping[self.pointer.slide_master.name]['two'] | |
layout = next(i for i in self.pointer.slide_master.slide_layouts if i.name == layout_name) | |
slide = self.pointer.slides.add_slide(layout) | |
ph_title, ph_body1, ph_body2 = slide.placeholders | |
ph_title.text = title | |
ph = ph_body2 | |
image = Image.open(image) | |
image_pil = image.to_pil() | |
left = ph.left | |
width = ph.width | |
height = int(width / image_pil.width * image_pil.height) | |
top = (ph.top + (ph.top + ph.height)) // 2 - height // 2 | |
slide.shapes.add_picture(image.to_path(), left, top, width, height) | |
ph = ph_body1 | |
tf = ph.text_frame | |
for i, item in enumerate(bullet_items.split('[SPAN]')): | |
if i == 0: | |
p = tf.paragraphs[0] | |
else: | |
p = tf.add_paragraph() | |
p.text = item.strip() | |
p.level = 0 | |
return dict(status='added page') | |
def submit_file(self) -> dict: | |
"""When all steps done, YOU MUST use submit_file() to submit your work. | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
# file_path = os.path.join(self.CACHE_DIR, f'{self._return_timestamp()}.pptx') | |
# self.pointer.save(file_path) | |
# retreival_url = upload_file(file_path) | |
self.pointer.save(self.location) | |
return dict(status=f'submitted. view ppt at {self.location}') | |
class AsyncPPT(AsyncActionMixin, PPT): | |
"""Plugin to create ppt slides with text, paragraph, images in good looking styles.""" | |
def create_file(self, theme: str, abs_location: str) -> dict: | |
"""Create a pptx file with specific themes. | |
Args: | |
theme (:class:`str`): the theme used. The value should be one of ['Default']. | |
abs_location (:class:`str`): the ppt file's absolute location | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
return super().create_file(theme, abs_location) | |
def add_first_page(self, title: str, subtitle: str) -> dict: | |
"""Add the first page of ppt. | |
Args: | |
title (:class:`str`): the title of ppt | |
subtitle (:class:`str`): the subtitle of ppt | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
return super().add_first_page(title, subtitle) | |
def add_text_page(self, title: str, bullet_items: str) -> dict: | |
"""Add text page of ppt. | |
Args: | |
title (:class:`str`): the title of the page | |
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them. | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" # noqa: E501 | |
return super().add_text_page(title, bullet_items) | |
def add_text_image_page(self, title: str, bullet_items: str, image: str) -> dict: | |
"""Add a text page with one image. Image should be a path. | |
Args: | |
title (:class:`str`): the title of the page | |
bullet_items (:class:`str`): bullet_items should be string, for multiple bullet items, please use [SPAN] to separate them. | |
image (:class:`str`): the path of the image | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" # noqa: E501 | |
return super().add_text_image_page(title, bullet_items, image) | |
def submit_file(self) -> dict: | |
"""When all steps done, YOU MUST use submit_file() to submit your work. | |
Returns: | |
:class:`dict`: operation status | |
* status: the result of the execution | |
""" | |
return super().submit_file() | |