Skip to content

Commit c5f5953

Browse files
committed
feat: add CustomSlideMaster and CustomTitleSlide for enhanced slide customization
1 parent 30921ba commit c5f5953

File tree

6 files changed

+103
-11
lines changed

6 files changed

+103
-11
lines changed

examples/custom_slide_master.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from pathlib import Path
2+
3+
import tppt
4+
from tppt._tppt.slide_layout import DefaultMasterSlide, DefaultTitleSlide
5+
6+
7+
def main():
8+
class CustomMasterSlide(DefaultMasterSlide):
9+
pass
10+
11+
class CustomTitleSlide(DefaultTitleSlide):
12+
pass
13+
14+
class CustomSlideMaster(tppt.TpptSlideMaster):
15+
Master = CustomMasterSlide
16+
Title = CustomTitleSlide
17+
18+
presentation = (
19+
tppt.Presentation.builder(CustomSlideMaster)
20+
.slide(
21+
lambda layout: layout.Master(
22+
title="Custom Master Title",
23+
text="Custom Master Text",
24+
)
25+
.builder()
26+
.text(
27+
"a",
28+
left=(100, "pt"),
29+
top=(100, "pt"),
30+
width=(100, "pt"),
31+
height=(100, "pt"),
32+
)
33+
)
34+
.slide(lambda layout: layout.Title(title="Custom Title"))
35+
.build()
36+
)
37+
38+
presentation.save(Path(__file__).with_suffix(".pptx"))
39+
40+
41+
if __name__ == "__main__":
42+
main()

examples/presentation_tree.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ def main() -> None:
1010
presentation = (
1111
tppt.Presentation.builder()
1212
.slide(
13-
tppt.SlideBuilder().text(
13+
lambda layout: layout.Master(
14+
title="Hello, world!",
15+
text="Hello, world!",
16+
)
17+
.builder()
18+
.text(
1419
"Hello, world!",
1520
left=(100, "pt"),
1621
top=(100, "pt"),

src/tppt/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
from tppt._pptx.slide import SlideBuilder as SlideBuilder
88
from tppt._pptx.slide_layout import SlideLayout as SlideLayout
99
from tppt._pptx.slide_master import SlideMaster as SlideMaster
10+
from tppt._tppt.slide_layout import TpptSlideLayout as TpptSlideLayout
1011
from tppt._tppt.slide_master import TpptSlideMaster as TpptSlideMaster

src/tppt/_pptx/presentation.py

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
"""Presentation wrapper implementation."""
22

33
import os
4-
from typing import IO, Any, Generic, Self
4+
from typing import IO, Any, Callable, Generic, Self, overload
55

66
from pptx.presentation import Presentation as PptxPresentation
77

88
from tppt._pptx.tree import ppt2dict
9-
from tppt._tppt.slide_master import GenericTpptSlideMaster
9+
from tppt._tppt.slide_layout import TpptSlideLayout
10+
from tppt._tppt.slide_master import (
11+
DefaultSlideMaster,
12+
GenericTpptSlideMaster,
13+
)
1014
from tppt.types import FilePath
1115

1216
from .converter import PptxConvertible
@@ -38,11 +42,28 @@ def tree(self) -> dict[str, Any]:
3842
"""Get the node tree of the presentation."""
3943
return ppt2dict(self._pptx)
4044

45+
@overload
4146
@classmethod
4247
def builder(
43-
cls, slide_master: "GenericTpptSlideMaster | None" = None
44-
) -> "PresentationBuilder[GenericTpptSlideMaster]":
48+
cls,
49+
) -> "PresentationBuilder[DefaultSlideMaster]": ...
50+
51+
@overload
52+
@classmethod
53+
def builder(
54+
cls,
55+
slide_master: "type[GenericTpptSlideMaster]",
56+
) -> "PresentationBuilder[GenericTpptSlideMaster]": ...
57+
58+
@classmethod
59+
def builder(
60+
cls,
61+
slide_master=None,
62+
):
4563
"""Get a builder for the presentation."""
64+
65+
if slide_master is None:
66+
slide_master = DefaultSlideMaster
4667
return PresentationBuilder(slide_master)
4768

4869
def save(self, file: FilePath | IO[bytes]) -> None:
@@ -64,17 +85,33 @@ def from_pptx(cls, pptx_obj: PptxPresentation) -> Self:
6485
class PresentationBuilder(Generic[GenericTpptSlideMaster]):
6586
"""Builder for presentations."""
6687

67-
def __init__(self, slide_master: "GenericTpptSlideMaster | None" = None) -> None:
88+
def __init__(
89+
self,
90+
slide_master: "type[GenericTpptSlideMaster]",
91+
) -> None:
6892
"""Initialize the builder."""
6993
import pptx
7094

7195
self._pptx = pptx.Presentation()
7296
self._slide_master = slide_master
7397

74-
def slide(self, slide: SlideBuilder, /) -> Self:
98+
def slide(
99+
self,
100+
slide: SlideBuilder
101+
| Callable[[type[GenericTpptSlideMaster]], SlideBuilder | TpptSlideLayout],
102+
/,
103+
) -> Self:
75104
"""Add a slide to the presentation."""
76-
77-
slide._build(self)
105+
if isinstance(slide, SlideBuilder):
106+
slide._build(self)
107+
else:
108+
slide_layout = slide(self._slide_master)
109+
slide_builder = (
110+
slide_layout.builder()
111+
if isinstance(slide_layout, TpptSlideLayout)
112+
else slide_layout
113+
)
114+
slide_builder._build(self)
78115

79116
return self
80117

src/tppt/_tppt/slide_layout.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import datetime
2-
from typing import Any, Self, overload
2+
from typing import TYPE_CHECKING, Any, Self, overload
3+
4+
if TYPE_CHECKING:
5+
from tppt._pptx.slide import SlideBuilder
36

47

58
class TpptSlideLayout:
@@ -18,6 +21,11 @@ def __get__(self, instance: object | None, objtype: type[Any]) -> type[Self] | S
1821
else:
1922
return self
2023

24+
def builder(self) -> "SlideBuilder":
25+
from tppt._pptx.slide import SlideBuilder
26+
27+
return SlideBuilder()
28+
2129

2230
class DefaultMasterSlide(TpptSlideLayout):
2331
"""Default master slide layout."""

src/tppt/_tppt/slide_master.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,4 @@ class DefaultSlideMaster(TpptSlideMaster):
6060
GenericTpptSlideMaster = TypeVar(
6161
"GenericTpptSlideMaster",
6262
bound=TpptSlideMaster,
63-
default=DefaultSlideMaster,
6463
)

0 commit comments

Comments
 (0)