python-pptx2 2.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pptx2/__init__.py +152 -0
- pptx2/_color.py +75 -0
- pptx2/_slide_importer.py +597 -0
- pptx2/_svg.py +155 -0
- pptx2/_template_applier.py +292 -0
- pptx2/_textstyle.py +187 -0
- pptx2/accessibility.py +365 -0
- pptx2/action.py +270 -0
- pptx2/animation.py +2237 -0
- pptx2/api.py +49 -0
- pptx2/audit.py +258 -0
- pptx2/chart/__init__.py +0 -0
- pptx2/chart/analytics.py +381 -0
- pptx2/chart/axis.py +543 -0
- pptx2/chart/category.py +200 -0
- pptx2/chart/chart.py +670 -0
- pptx2/chart/data.py +864 -0
- pptx2/chart/datalabel.py +406 -0
- pptx2/chart/legend.py +86 -0
- pptx2/chart/marker.py +70 -0
- pptx2/chart/palettes.py +129 -0
- pptx2/chart/plot.py +462 -0
- pptx2/chart/point.py +101 -0
- pptx2/chart/quick_layouts.py +325 -0
- pptx2/chart/series.py +334 -0
- pptx2/chart/xlsx.py +272 -0
- pptx2/chart/xmlwriter.py +1845 -0
- pptx2/compose/__init__.py +28 -0
- pptx2/compose/from_spec.py +1094 -0
- pptx2/design/__init__.py +8 -0
- pptx2/design/components.py +607 -0
- pptx2/design/figures.py +389 -0
- pptx2/design/layout.py +370 -0
- pptx2/design/recipes.py +1967 -0
- pptx2/design/style.py +209 -0
- pptx2/design/tokens.py +915 -0
- pptx2/diagrams.py +754 -0
- pptx2/dml/__init__.py +0 -0
- pptx2/dml/chtfmt.py +40 -0
- pptx2/dml/color.py +496 -0
- pptx2/dml/effect.py +909 -0
- pptx2/dml/fill.py +691 -0
- pptx2/dml/line.py +287 -0
- pptx2/dml/picture.py +212 -0
- pptx2/dml/three_d.py +381 -0
- pptx2/enum/__init__.py +0 -0
- pptx2/enum/action.py +71 -0
- pptx2/enum/animation.py +31 -0
- pptx2/enum/base.py +218 -0
- pptx2/enum/chart.py +574 -0
- pptx2/enum/dml.py +740 -0
- pptx2/enum/lang.py +685 -0
- pptx2/enum/presentation.py +133 -0
- pptx2/enum/shapes.py +1029 -0
- pptx2/enum/text.py +230 -0
- pptx2/exc.py +42 -0
- pptx2/formats.py +139 -0
- pptx2/geometry.py +420 -0
- pptx2/inherit.py +109 -0
- pptx2/lint.py +2256 -0
- pptx2/math.py +177 -0
- pptx2/media.py +197 -0
- pptx2/opc/__init__.py +0 -0
- pptx2/opc/constants.py +332 -0
- pptx2/opc/oxml.py +188 -0
- pptx2/opc/package.py +762 -0
- pptx2/opc/packuri.py +109 -0
- pptx2/opc/serialized.py +296 -0
- pptx2/opc/shared.py +20 -0
- pptx2/opc/spec.py +45 -0
- pptx2/oxml/__init__.py +555 -0
- pptx2/oxml/action.py +53 -0
- pptx2/oxml/chart/__init__.py +0 -0
- pptx2/oxml/chart/axis.py +337 -0
- pptx2/oxml/chart/chart.py +481 -0
- pptx2/oxml/chart/datalabel.py +253 -0
- pptx2/oxml/chart/legend.py +72 -0
- pptx2/oxml/chart/marker.py +61 -0
- pptx2/oxml/chart/plot.py +365 -0
- pptx2/oxml/chart/series.py +425 -0
- pptx2/oxml/chart/shared.py +220 -0
- pptx2/oxml/coreprops.py +288 -0
- pptx2/oxml/dml/__init__.py +0 -0
- pptx2/oxml/dml/color.py +135 -0
- pptx2/oxml/dml/effect.py +213 -0
- pptx2/oxml/dml/fill.py +316 -0
- pptx2/oxml/dml/line.py +12 -0
- pptx2/oxml/dml/three_d.py +110 -0
- pptx2/oxml/ns.py +135 -0
- pptx2/oxml/presentation.py +313 -0
- pptx2/oxml/shapes/__init__.py +19 -0
- pptx2/oxml/shapes/autoshape.py +467 -0
- pptx2/oxml/shapes/connector.py +107 -0
- pptx2/oxml/shapes/graphfrm.py +347 -0
- pptx2/oxml/shapes/groupshape.py +329 -0
- pptx2/oxml/shapes/picture.py +270 -0
- pptx2/oxml/shapes/shared.py +577 -0
- pptx2/oxml/simpletypes.py +1027 -0
- pptx2/oxml/slide.py +563 -0
- pptx2/oxml/table.py +650 -0
- pptx2/oxml/text.py +815 -0
- pptx2/oxml/theme.py +36 -0
- pptx2/oxml/xmlchemy.py +717 -0
- pptx2/package.py +222 -0
- pptx2/parts/__init__.py +0 -0
- pptx2/parts/chart.py +95 -0
- pptx2/parts/coreprops.py +167 -0
- pptx2/parts/diagram.py +37 -0
- pptx2/parts/embeddedpackage.py +93 -0
- pptx2/parts/image.py +275 -0
- pptx2/parts/media.py +37 -0
- pptx2/parts/presentation.py +136 -0
- pptx2/parts/slide.py +371 -0
- pptx2/presentation.py +408 -0
- pptx2/py.typed +0 -0
- pptx2/render.py +586 -0
- pptx2/section.py +272 -0
- pptx2/shapes/__init__.py +26 -0
- pptx2/shapes/autoshape.py +442 -0
- pptx2/shapes/base.py +1078 -0
- pptx2/shapes/connector.py +297 -0
- pptx2/shapes/freeform.py +337 -0
- pptx2/shapes/graphfrm.py +316 -0
- pptx2/shapes/group.py +264 -0
- pptx2/shapes/picture.py +422 -0
- pptx2/shapes/placeholder.py +468 -0
- pptx2/shapes/shapetree.py +2027 -0
- pptx2/shared.py +82 -0
- pptx2/skill/SKILL.md +450 -0
- pptx2/skill/__init__.py +78 -0
- pptx2/skill/__main__.py +64 -0
- pptx2/skill/references/animations.md +189 -0
- pptx2/skill/references/basics.md +421 -0
- pptx2/skill/references/charts.md +254 -0
- pptx2/skill/references/compose.md +234 -0
- pptx2/skill/references/design.md +366 -0
- pptx2/skill/references/effects.md +249 -0
- pptx2/skill/references/end-to-end-deck.md +231 -0
- pptx2/skill/references/geometry-and-arrows.md +334 -0
- pptx2/skill/references/lint.md +275 -0
- pptx2/skill/references/math.md +86 -0
- pptx2/skill/references/picture-effects.md +129 -0
- pptx2/skill/references/render.md +151 -0
- pptx2/skill/references/smart-art.md +75 -0
- pptx2/skill/references/space-aware-authoring.md +249 -0
- pptx2/skill/references/tables.md +244 -0
- pptx2/skill/references/theme.md +127 -0
- pptx2/skill/references/three-d.md +109 -0
- pptx2/skill/references/transitions.md +100 -0
- pptx2/slide.py +1244 -0
- pptx2/smart_art.py +220 -0
- pptx2/spec.py +633 -0
- pptx2/table.py +1181 -0
- pptx2/table_styles.py +184 -0
- pptx2/templates/default.pptx +0 -0
- pptx2/templates/docx-icon.emf +0 -0
- pptx2/templates/generic-icon.emf +0 -0
- pptx2/templates/notes.xml +23 -0
- pptx2/templates/notesMaster.xml +352 -0
- pptx2/templates/pptx-icon.emf +0 -0
- pptx2/templates/theme.xml +321 -0
- pptx2/templates/xlsx-icon.emf +0 -0
- pptx2/text/__init__.py +0 -0
- pptx2/text/fonts.py +482 -0
- pptx2/text/layout.py +374 -0
- pptx2/text/text.py +1272 -0
- pptx2/theme.py +721 -0
- pptx2/types.py +36 -0
- pptx2/util.py +263 -0
- python_pptx2-2.13.0.dist-info/METADATA +351 -0
- python_pptx2-2.13.0.dist-info/RECORD +175 -0
- python_pptx2-2.13.0.dist-info/WHEEL +5 -0
- python_pptx2-2.13.0.dist-info/entry_points.txt +3 -0
- python_pptx2-2.13.0.dist-info/licenses/LICENSE +22 -0
- python_pptx2-2.13.0.dist-info/top_level.txt +1 -0
pptx2/parts/slide.py
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"""Slide and related objects."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import IO, TYPE_CHECKING, cast
|
|
6
|
+
|
|
7
|
+
from pptx2.enum.shapes import PROG_ID
|
|
8
|
+
from pptx2.opc.constants import CONTENT_TYPE as CT
|
|
9
|
+
from pptx2.opc.constants import RELATIONSHIP_TYPE as RT
|
|
10
|
+
from pptx2.opc.package import XmlPart
|
|
11
|
+
from pptx2.opc.oxml import serialize_part_xml
|
|
12
|
+
from pptx2.opc.packuri import PackURI
|
|
13
|
+
from pptx2.oxml import parse_xml
|
|
14
|
+
from pptx2.oxml.slide import (
|
|
15
|
+
CT_NotesMaster,
|
|
16
|
+
CT_NotesSlide,
|
|
17
|
+
CT_Slide,
|
|
18
|
+
slide_has_p14_transition,
|
|
19
|
+
unwrap_p14_transitions,
|
|
20
|
+
wrap_p14_transitions,
|
|
21
|
+
)
|
|
22
|
+
from pptx2.oxml.theme import CT_OfficeStyleSheet
|
|
23
|
+
from pptx2.parts.chart import ChartPart
|
|
24
|
+
from pptx2.parts.embeddedpackage import EmbeddedPackagePart
|
|
25
|
+
from pptx2.slide import NotesMaster, NotesSlide, Slide, SlideLayout, SlideMaster
|
|
26
|
+
from pptx2.util import lazyproperty
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from pptx2.chart.data import ChartData
|
|
30
|
+
from pptx2.enum.chart import XL_CHART_TYPE
|
|
31
|
+
from pptx2.media import Video
|
|
32
|
+
from pptx2.parts.image import Image, ImagePart
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class BaseSlidePart(XmlPart):
|
|
36
|
+
"""Base class for slide parts.
|
|
37
|
+
|
|
38
|
+
This includes slide, slide-layout, and slide-master parts, but also notes-slide,
|
|
39
|
+
notes-master, and handout-master parts.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
_element: CT_Slide
|
|
43
|
+
|
|
44
|
+
@classmethod
|
|
45
|
+
def load(cls, partname, content_type, package, blob):
|
|
46
|
+
"""Parse *blob* and normalise any PowerPoint-2010 transition wrapper.
|
|
47
|
+
|
|
48
|
+
A morph/p14 transition is stored on disk inside ``<mc:AlternateContent>``;
|
|
49
|
+
we unwrap it to a plain ``<p:transition>`` so the high-level
|
|
50
|
+
``slide.transition`` accessors see a normal element. ``blob`` re-wraps it
|
|
51
|
+
on save.
|
|
52
|
+
"""
|
|
53
|
+
element = cast("CT_Slide", parse_xml(blob))
|
|
54
|
+
unwrap_p14_transitions(element)
|
|
55
|
+
return cls(partname, content_type, package, element)
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def blob(self) -> bytes:
|
|
59
|
+
"""XML serialization, re-wrapping p14 transitions in mc:AlternateContent.
|
|
60
|
+
|
|
61
|
+
The wrap is done on a copy so the live element tree keeps its plain
|
|
62
|
+
``<p:transition>`` (and the accessors that read it) intact after a save.
|
|
63
|
+
"""
|
|
64
|
+
element = self._element
|
|
65
|
+
if not slide_has_p14_transition(element):
|
|
66
|
+
return serialize_part_xml(element)
|
|
67
|
+
from copy import deepcopy
|
|
68
|
+
|
|
69
|
+
copy = deepcopy(element)
|
|
70
|
+
wrap_p14_transitions(copy)
|
|
71
|
+
return serialize_part_xml(copy)
|
|
72
|
+
|
|
73
|
+
def get_image(self, rId: str) -> Image:
|
|
74
|
+
"""Return an |Image| object containing the image related to this slide by *rId*.
|
|
75
|
+
|
|
76
|
+
Raises |KeyError| if no image is related by that id, which would generally indicate a
|
|
77
|
+
corrupted .pptx file.
|
|
78
|
+
"""
|
|
79
|
+
return cast("ImagePart", self.related_part(rId)).image
|
|
80
|
+
|
|
81
|
+
def get_or_add_image_part(self, image_file: str | IO[bytes]):
|
|
82
|
+
"""Return `(image_part, rId)` pair corresponding to `image_file`.
|
|
83
|
+
|
|
84
|
+
The returned |ImagePart| object contains the image in `image_file` and is
|
|
85
|
+
related to this slide with the key `rId`. If either the image part or
|
|
86
|
+
relationship already exists, they are reused, otherwise they are newly created.
|
|
87
|
+
"""
|
|
88
|
+
image_part = self._package.get_or_add_image_part(image_file)
|
|
89
|
+
rId = self.relate_to(image_part, RT.IMAGE)
|
|
90
|
+
return image_part, rId
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def name(self) -> str:
|
|
94
|
+
"""Internal name of this slide."""
|
|
95
|
+
return self._element.cSld.name
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class NotesMasterPart(BaseSlidePart):
|
|
99
|
+
"""Notes master part.
|
|
100
|
+
|
|
101
|
+
Corresponds to package file `ppt/notesMasters/notesMaster1.xml`.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def create_default(cls, package):
|
|
106
|
+
"""
|
|
107
|
+
Create and return a default notes master part, including creating the
|
|
108
|
+
new theme it requires.
|
|
109
|
+
"""
|
|
110
|
+
notes_master_part = cls._new(package)
|
|
111
|
+
theme_part = cls._new_theme_part(package)
|
|
112
|
+
notes_master_part.relate_to(theme_part, RT.THEME)
|
|
113
|
+
return notes_master_part
|
|
114
|
+
|
|
115
|
+
@lazyproperty
|
|
116
|
+
def notes_master(self):
|
|
117
|
+
"""
|
|
118
|
+
Return the |NotesMaster| object that proxies this notes master part.
|
|
119
|
+
"""
|
|
120
|
+
return NotesMaster(self._element, self)
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def _new(cls, package):
|
|
124
|
+
"""
|
|
125
|
+
Create and return a standalone, default notes master part based on
|
|
126
|
+
the built-in template (without any related parts, such as theme).
|
|
127
|
+
"""
|
|
128
|
+
return NotesMasterPart(
|
|
129
|
+
PackURI("/ppt/notesMasters/notesMaster1.xml"),
|
|
130
|
+
CT.PML_NOTES_MASTER,
|
|
131
|
+
package,
|
|
132
|
+
CT_NotesMaster.new_default(),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def _new_theme_part(cls, package):
|
|
137
|
+
"""Return new default theme-part suitable for use with a notes master."""
|
|
138
|
+
return ThemePart(
|
|
139
|
+
package.next_partname("/ppt/theme/theme%d.xml"),
|
|
140
|
+
CT.OFC_THEME,
|
|
141
|
+
package,
|
|
142
|
+
CT_OfficeStyleSheet.new_default(),
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ThemePart(XmlPart):
|
|
147
|
+
"""Package part for an Office theme (``ppt/theme/themeN.xml``).
|
|
148
|
+
|
|
149
|
+
Themes were previously loaded as generic |Part| blobs which made
|
|
150
|
+
high-level write operations on |Theme| transient (every read parsed
|
|
151
|
+
a fresh element). Promoting them to |XmlPart| keeps a single live
|
|
152
|
+
``<a:theme>`` element on the part so that mutations from
|
|
153
|
+
:class:`pptx2.theme.Theme` round-trip on save.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
_element: CT_OfficeStyleSheet
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class NotesSlidePart(BaseSlidePart):
|
|
160
|
+
"""Notes slide part.
|
|
161
|
+
|
|
162
|
+
Contains the slide notes content and the layout for the slide handout page.
|
|
163
|
+
Corresponds to package file `ppt/notesSlides/notesSlide[1-9][0-9]*.xml`.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def new(cls, package, slide_part):
|
|
168
|
+
"""Return new |NotesSlidePart| for the slide in `slide_part`.
|
|
169
|
+
|
|
170
|
+
The new notes-slide part is based on the (singleton) notes master and related to
|
|
171
|
+
both the notes-master part and `slide_part`. If no notes-master is present,
|
|
172
|
+
one is created based on the default template.
|
|
173
|
+
"""
|
|
174
|
+
notes_master_part = package.presentation_part.notes_master_part
|
|
175
|
+
notes_slide_part = cls._add_notes_slide_part(package, slide_part, notes_master_part)
|
|
176
|
+
notes_slide = notes_slide_part.notes_slide
|
|
177
|
+
notes_slide.clone_master_placeholders(notes_master_part.notes_master)
|
|
178
|
+
return notes_slide_part
|
|
179
|
+
|
|
180
|
+
@lazyproperty
|
|
181
|
+
def notes_master(self):
|
|
182
|
+
"""Return the |NotesMaster| object this notes slide inherits from."""
|
|
183
|
+
notes_master_part = self.part_related_by(RT.NOTES_MASTER)
|
|
184
|
+
return notes_master_part.notes_master
|
|
185
|
+
|
|
186
|
+
@lazyproperty
|
|
187
|
+
def notes_slide(self):
|
|
188
|
+
"""Return the |NotesSlide| object that proxies this notes slide part."""
|
|
189
|
+
return NotesSlide(self._element, self)
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def _add_notes_slide_part(cls, package, slide_part, notes_master_part):
|
|
193
|
+
"""Create and return a new notes-slide part.
|
|
194
|
+
|
|
195
|
+
The return part is fully related, but has no shape content (i.e. placeholders
|
|
196
|
+
not cloned).
|
|
197
|
+
"""
|
|
198
|
+
notes_slide_part = NotesSlidePart(
|
|
199
|
+
package.next_partname("/ppt/notesSlides/notesSlide%d.xml"),
|
|
200
|
+
CT.PML_NOTES_SLIDE,
|
|
201
|
+
package,
|
|
202
|
+
CT_NotesSlide.new(),
|
|
203
|
+
)
|
|
204
|
+
notes_slide_part.relate_to(notes_master_part, RT.NOTES_MASTER)
|
|
205
|
+
notes_slide_part.relate_to(slide_part, RT.SLIDE)
|
|
206
|
+
return notes_slide_part
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
class SlidePart(BaseSlidePart):
|
|
210
|
+
"""Slide part. Corresponds to package files ppt/slides/slide[1-9][0-9]*.xml."""
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def new(cls, partname, package, slide_layout_part):
|
|
214
|
+
"""Return newly-created blank slide part.
|
|
215
|
+
|
|
216
|
+
The new slide-part has `partname` and a relationship to `slide_layout_part`.
|
|
217
|
+
"""
|
|
218
|
+
slide_part = cls(partname, CT.PML_SLIDE, package, CT_Slide.new())
|
|
219
|
+
slide_part.relate_to(slide_layout_part, RT.SLIDE_LAYOUT)
|
|
220
|
+
return slide_part
|
|
221
|
+
|
|
222
|
+
def add_chart_part(self, chart_type: XL_CHART_TYPE, chart_data: ChartData):
|
|
223
|
+
"""Return str rId of new |ChartPart| object containing chart of `chart_type`.
|
|
224
|
+
|
|
225
|
+
The chart depicts `chart_data` and is related to the slide contained in this
|
|
226
|
+
part by `rId`.
|
|
227
|
+
"""
|
|
228
|
+
return self.relate_to(ChartPart.new(chart_type, chart_data, self._package), RT.CHART)
|
|
229
|
+
|
|
230
|
+
def add_embedded_ole_object_part(
|
|
231
|
+
self, prog_id: PROG_ID | str, ole_object_file: str | IO[bytes]
|
|
232
|
+
):
|
|
233
|
+
"""Return rId of newly-added OLE-object part formed from `ole_object_file`."""
|
|
234
|
+
relationship_type = RT.PACKAGE if isinstance(prog_id, PROG_ID) else RT.OLE_OBJECT
|
|
235
|
+
return self.relate_to(
|
|
236
|
+
EmbeddedPackagePart.factory(
|
|
237
|
+
prog_id, self._blob_from_file(ole_object_file), self._package
|
|
238
|
+
),
|
|
239
|
+
relationship_type,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
def get_or_add_video_media_part(self, video: Video) -> tuple[str, str]:
|
|
243
|
+
"""Return rIds for media and video relationships to media part.
|
|
244
|
+
|
|
245
|
+
A new |MediaPart| object is created if it does not already exist
|
|
246
|
+
(such as would occur if the same video appeared more than once in
|
|
247
|
+
a presentation). Two relationships to the media part are created,
|
|
248
|
+
one each with MEDIA and VIDEO relationship types. The need for two
|
|
249
|
+
appears to be for legacy support for an earlier (pre-Office 2010)
|
|
250
|
+
PowerPoint media embedding strategy.
|
|
251
|
+
"""
|
|
252
|
+
media_part = self._package.get_or_add_media_part(video)
|
|
253
|
+
media_rId = self.relate_to(media_part, RT.MEDIA)
|
|
254
|
+
video_rId = self.relate_to(media_part, RT.VIDEO)
|
|
255
|
+
return media_rId, video_rId
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def has_notes_slide(self):
|
|
259
|
+
"""
|
|
260
|
+
Return True if this slide has a notes slide, False otherwise. A notes
|
|
261
|
+
slide is created by the :attr:`notes_slide` property when one doesn't
|
|
262
|
+
exist; use this property to test for a notes slide without the
|
|
263
|
+
possible side-effect of creating one.
|
|
264
|
+
"""
|
|
265
|
+
try:
|
|
266
|
+
self.part_related_by(RT.NOTES_SLIDE)
|
|
267
|
+
except KeyError:
|
|
268
|
+
return False
|
|
269
|
+
return True
|
|
270
|
+
|
|
271
|
+
@lazyproperty
|
|
272
|
+
def notes_slide(self) -> NotesSlide:
|
|
273
|
+
"""The |NotesSlide| instance associated with this slide.
|
|
274
|
+
|
|
275
|
+
If the slide does not have a notes slide, a new one is created. The same single instance
|
|
276
|
+
is returned on each call.
|
|
277
|
+
"""
|
|
278
|
+
try:
|
|
279
|
+
notes_slide_part = self.part_related_by(RT.NOTES_SLIDE)
|
|
280
|
+
except KeyError:
|
|
281
|
+
notes_slide_part = self._add_notes_slide_part()
|
|
282
|
+
return notes_slide_part.notes_slide
|
|
283
|
+
|
|
284
|
+
@lazyproperty
|
|
285
|
+
def slide(self):
|
|
286
|
+
"""
|
|
287
|
+
The |Slide| object representing this slide part.
|
|
288
|
+
"""
|
|
289
|
+
return Slide(self._element, self)
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def slide_id(self) -> int:
|
|
293
|
+
"""Return the slide identifier stored in the presentation part for this slide part."""
|
|
294
|
+
presentation_part = self.package.presentation_part
|
|
295
|
+
return presentation_part.slide_id(self)
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def slide_layout(self) -> SlideLayout:
|
|
299
|
+
"""|SlideLayout| object the slide in this part inherits appearance from."""
|
|
300
|
+
slide_layout_part = self.part_related_by(RT.SLIDE_LAYOUT)
|
|
301
|
+
return slide_layout_part.slide_layout
|
|
302
|
+
|
|
303
|
+
def _add_notes_slide_part(self):
|
|
304
|
+
"""
|
|
305
|
+
Return a newly created |NotesSlidePart| object related to this slide
|
|
306
|
+
part. Caller is responsible for ensuring this slide doesn't already
|
|
307
|
+
have a notes slide part.
|
|
308
|
+
"""
|
|
309
|
+
notes_slide_part = NotesSlidePart.new(self.package, self)
|
|
310
|
+
self.relate_to(notes_slide_part, RT.NOTES_SLIDE)
|
|
311
|
+
return notes_slide_part
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class SlideLayoutPart(BaseSlidePart):
|
|
315
|
+
"""Slide layout part.
|
|
316
|
+
|
|
317
|
+
Corresponds to package files ``ppt/slideLayouts/slideLayout[1-9][0-9]*.xml``.
|
|
318
|
+
"""
|
|
319
|
+
|
|
320
|
+
@lazyproperty
|
|
321
|
+
def slide_layout(self):
|
|
322
|
+
"""
|
|
323
|
+
The |SlideLayout| object representing this part.
|
|
324
|
+
"""
|
|
325
|
+
return SlideLayout(self._element, self)
|
|
326
|
+
|
|
327
|
+
@property
|
|
328
|
+
def slide_master(self) -> SlideMaster:
|
|
329
|
+
"""Slide master from which this slide layout inherits properties."""
|
|
330
|
+
return self.part_related_by(RT.SLIDE_MASTER).slide_master
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class SlideMasterPart(BaseSlidePart):
|
|
334
|
+
"""Slide master part.
|
|
335
|
+
|
|
336
|
+
Corresponds to package files ppt/slideMasters/slideMaster[1-9][0-9]*.xml.
|
|
337
|
+
"""
|
|
338
|
+
|
|
339
|
+
def related_slide_layout(self, rId: str) -> SlideLayout:
|
|
340
|
+
"""Return |SlideLayout| related to this slide-master by key `rId`."""
|
|
341
|
+
return self.related_part(rId).slide_layout
|
|
342
|
+
|
|
343
|
+
@lazyproperty
|
|
344
|
+
def slide_master(self):
|
|
345
|
+
"""
|
|
346
|
+
The |SlideMaster| object representing this part.
|
|
347
|
+
"""
|
|
348
|
+
return SlideMaster(self._element, self)
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def theme(self):
|
|
352
|
+
"""Return a |Theme| object for the theme related to this slide master.
|
|
353
|
+
|
|
354
|
+
Returns ``None`` when no theme relationship is present.
|
|
355
|
+
"""
|
|
356
|
+
from pptx2.oxml import parse_xml
|
|
357
|
+
from pptx2.theme import Theme
|
|
358
|
+
|
|
359
|
+
try:
|
|
360
|
+
theme_part = self.part_related_by(RT.THEME)
|
|
361
|
+
except KeyError:
|
|
362
|
+
return None
|
|
363
|
+
# Theme parts are typed as ThemePart (an XmlPart subclass) and
|
|
364
|
+
# always carry a live `_element`. Older packages or generic
|
|
365
|
+
# Parts fall through to a fresh parse so the read still works
|
|
366
|
+
# (writes won't persist on a generic Part — but they do on
|
|
367
|
+
# any presentation loaded through the registered factory).
|
|
368
|
+
elm = getattr(theme_part, "_element", None)
|
|
369
|
+
if elm is None:
|
|
370
|
+
elm = parse_xml(theme_part.blob)
|
|
371
|
+
return Theme(elm)
|