Spaces:
Running
Running
| 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() | |