""".. versionadded:: 0.0.2
Control the macOS Keynote application using JXA-like syntax.
"""
from enum import Enum
from typing import Any, Union
import AppKit
from PyXA import XABase
from PyXA import XAEvents
from PyXA.XABase import OSType
from . import iWorkApplicationBase
[docs]
class XAKeynoteApplication(iWorkApplicationBase.XAiWorkApplication):
"""A class for managing and interacting with Keynote.app.
.. seealso:: :class:`XAKeynoteWindow`, :class:`XAKeynoteDocument`
.. versionadded:: 0.0.2
"""
[docs]
class ObjectType(Enum):
"""Object types available for creation in Keynote.
"""
DOCUMENT = "document"
SHAPE = "shape"
TABLE = "table"
AUDIO_CLIP = "audio_clip"
CHART = "chart"
IMAGE = "image"
SLIDE = "slide"
LINE = "line"
MOVIE = "movie"
TEXT_ITEM = "text_item"
GROUP = "group"
iWORK_ITEM = "iwork_item"
TRANSITION_SETTINGS = "transition_settings"
[docs]
class Codec(Enum):
"""Options for which video codec to use.
"""
H264 = OSType('Kmc1') # H.264
APPLE_PRO_RES_422 = OSType('Kmc2') # Apple ProRes 422
APPLE_PRO_RES_4444 = OSType('Kmc3') # Apple ProRes 4444
APPLE_PRO_RES_422LT = OSType('Kmc4') # Apple ProRes 422LT
APPLE_PRO_RES_422HQ = OSType('Kmc5') # Apple ProRes 422HQ
APPLE_PRO_RES_422Proxy = OSType('Kmc6') # Apple ProRes 422Proxy
HEVC = OSType('Kmc7') # HEVC
[docs]
class Framerate(Enum):
"""Options for which framerate to use when exporting a Keynote project as a video.
"""
FPS_12 = OSType('Kfr1') # 12 FPS
FPS_2398 = OSType('Kfr2') # 23.98 FPS
FPS_24 = OSType('Kfr3') # 24 FPS
FPS_25 = OSType('Kfr4') # 25 FPS
FPS_2997 = OSType('Kfr5') # 29.97 FPS
FPS_30 = OSType('Kfr6') # 30 FPS
FPS_50 = OSType('Kfr7') # 50 FPS
FPS_5994 = OSType('Kfr8') # 59.94 FPS
FPS_60 = OSType('Kfr9') # 60 FPS
[docs]
class PrintSetting(Enum):
"""Options to use when printing slides.
"""
STANDARD_ERROR_HANDLING = OSType('lwst') # Standard PostScript error handling
DETAILED_ERROR_HANDLING = OSType('lwdt') # print a detailed report of PostScript errors
INDIVIDUAL_SLIDES = OSType('Kpwi') # individual slides
SLIDE_WITH_NOTES = OSType('Kpwn') # slides with notes
HANDOUTS = OSType('Kpwh') # handouts
[docs]
class Transition(Enum):
"""The available options for transitions to assign to slides.
"""
NONE = OSType('tnil')
MAGIC_MOVE = OSType('tmjv')
SHIMMER = OSType('tshm')
SPARKLE = OSType('tspk')
SWING = OSType('tswg')
OBJECT_CUBE = OSType('tocb')
OBJECT_FLIP = OSType('tofp')
OBJECT_POP = OSType('topp')
OBJECT_PUSH = OSType('toph')
OBJECT_REVOLVE = OSType('torv')
OBJECT_ZOOM = OSType('tozm')
PERSPECTIVE = OSType('tprs')
CLOTHESLINE = OSType('tclo')
CONFETTI = OSType('tcft')
DISSOLVE = OSType('tdis')
DROP = OSType('tdrp')
DROPLET = OSType('tdpl')
FADE_THROUGH_COLOR = OSType('tftc')
GRID = OSType('tgrd')
IRIS = OSType('tirs')
MOVE_IN = OSType('tmvi')
PUSH = OSType('tpsh')
REVEAL = OSType('trvl')
SWITCH = OSType('tswi')
WIPE = OSType('twpe')
BLINDS = OSType('tbld')
COLOR_PANES = OSType('tcpl')
CUBE = OSType('tcub')
DOORWAY = OSType('tdwy')
FALL = OSType('tfal')
FLIP = OSType('tfip')
FLOP = OSType('tfop')
MOSAIC = OSType('tmsc')
PAGE_FLIP = OSType('tpfl')
PIVOT = OSType('tpvt')
REFLECTION = OSType('trfl')
REVOLVING_DOOR = OSType('trev')
SCALE = OSType('tscl')
SWAP = OSType('tswp')
SWOOSH = OSType('tsws')
TWIRL = OSType('ttwl')
TWIST = OSType('ttwi')
FADE_AND_MOVE = OSType('tfad')
def __init__(self, properties):
super().__init__(properties)
self.xa_wcls = XAKeynoteWindow
@property
def properties(self) -> dict:
"""All properties of the Keynote application.
"""
raw_dict = self.xa_scel.properties()
return {
"slide_switcher_visible": raw_dict["slideSwitcherVisible"] == 1,
"frontmost": self.frontmost,
"playing": self.playing,
"version": self.version,
"name": self.name,
}
@property
def playing(self) -> bool:
"""Whether a slideshow is currently playing.
"""
return self.xa_scel.playing()
@property
def slide_switcher_visible(self) -> bool:
"""Whether the slide switcher is visible.
"""
return self.xa_scel.slideSwitcherVisible()
[docs]
def show_next(self) -> 'XAKeynoteApplication':
"""Advance one slide or animation build.
"""
self.xa_scel.showNext()
return self
[docs]
def show_previous(self) -> 'XAKeynoteApplication':
"""Go back one slide or animation build.
"""
self.xa_scel.showPrevious()
return self
[docs]
def documents(self, filter: Union[dict, None] = None) -> 'XAKeynoteDocumentList':
"""Returns a list of documents, as PyXA objects, matching the given filter.
:param filter: A dictionary specifying property-value pairs that all returned documents will have, or None
:type filter: Union[dict, None]
:return: The list of documents
:rtype: XAKeynoteDocumentList
:Example 1: List the name of every open Keynote document
>>> import PyXA
>>> app = PyXA.Application("Keynote")
>>> docs = app.documents()
>>> for doc in docs:
>>> print(doc.name)
Example1.key
Example2.key
.. versionadded:: 0.0.2
"""
return self._new_element(self.xa_scel.documents(), XAKeynoteDocumentList, filter)
[docs]
def new_document(self, file_path: Union[str, XABase.XAPath] = "./Untitled.key", theme: 'XAKeynoteTheme' = None) -> 'XAKeynoteDocument':
"""Creates a new document at the specified path and with the specified theme.
:param file_path: The path to create the document at, defaults to "./Untitled.key"
:type file_path: str, optional
:param template: The theme to initialize the document with, defaults to None
:type template: XAKeynoteTheme, optional
:return: The newly created document object
:rtype: XAKeynoteDocument
.. versionadded:: 0.0.8
"""
if isinstance(file_path, str):
file_path = XABase.XAPath(file_path)
properties = {
"file": file_path.xa_elem,
}
if theme is not None:
properties["documentTheme"] = theme.xa_elem
new_document = self.make("document", properties)
self.documents().push(new_document)
return self.documents()[0]
[docs]
def themes(self, filter: Union[dict, None] = None) -> 'XAKeynoteThemeList':
"""Returns a list of themes, as PyXA objects, matching the given filter.
:param filter: A dictionary specifying property-value pairs that all returned themes will have, or None
:type filter: Union[dict, None]
:return: The list of themes
:rtype: XAKeynoteThemeList
:Example 1: List the name of each theme
>>> import PyXA
>>> app = PyXA.Application("Keynote")
>>> themes = app.themes()
>>> print(themes.name())
['Basic White', 'Basic Black', 'Classic White', 'White', 'Black', 'Basic Color', 'Color Gradient Light', 'Color Gradient', 'Gradient', 'Showroom', 'Modern Portfolio', 'Slate', 'Photo Essay', 'Bold Color', 'Showcase', 'Briefing', 'Academy', 'Modern Type', 'Exhibition', 'Feature Story', 'Look Book', 'Classic', 'Editorial', 'Cream Paper', 'Industrial', 'Blueprint', 'Graph Paper', 'Chalkboard', 'Photo Portfolio', 'Leather Book', 'Artisan', 'Improv', 'Drafting', 'Kyoto', 'Brushed Canvas', 'Craft', 'Parchment', 'Renaissance', 'Moroccan', 'Hard Cover', 'Linen Book', 'Vintage', 'Typeset', 'Harmony', 'Formal']
.. versionadded:: 0.0.2
"""
return self._new_element(self.xa_scel.themes(), XAKeynoteThemeList, filter)
[docs]
def make(self, specifier: Union[str, 'XAKeynoteApplication.ObjectType'], properties: dict = None, data: Any = None):
"""Creates a new element of the given specifier class without adding it to any list.
Use :func:`XABase.XAList.push` to push the element onto a list.
:param specifier: The classname of the object to create
:type specifier: Union[str, XAKeynoteApplication.ObjectType]
:param properties: The properties to give the object
:type properties: dict
:param data: The data to initialize the object with
:type data: Any
:return: A PyXA wrapped form of the object
:rtype: XABase.XAObject
.. versionadded:: 0.0.5
"""
if isinstance(specifier, XAKeynoteApplication.ObjectType):
specifier = specifier.value
if data is None:
camelized_properties = {}
if properties is None:
properties = {}
for key, value in properties.items():
if key == "url":
key = "URL"
camelized_properties[XABase.camelize(key)] = value
obj = (
self.xa_scel.classForScriptingClass_(specifier)
.alloc()
.initWithProperties_(camelized_properties)
)
else:
obj = (
self.xa_scel.classForScriptingClass_(specifier)
.alloc()
.initWithData_(data)
)
if specifier == "document":
return self._new_element(obj, XAKeynoteDocument)
elif specifier == "shape":
return self._new_element(obj, iWorkApplicationBase.XAiWorkShape)
elif specifier == "table":
return self._new_element(obj, iWorkApplicationBase.XAiWorkTable)
elif specifier == "audio_clip":
return self._new_element(obj, iWorkApplicationBase.XAiWorkAudioClip)
elif specifier == "chart":
return self._new_element(obj, iWorkApplicationBase.XAiWorkChart)
elif specifier == "image":
return self._new_element(obj, iWorkApplicationBase.XAiWorkImage)
elif specifier == "slide":
return self._new_element(obj, XAKeynoteSlide)
elif specifier == "line":
return self._new_element(obj, iWorkApplicationBase.XAiWorkLine)
elif specifier == "movie":
return self._new_element(obj, iWorkApplicationBase.XAiWorkMovie)
elif specifier == "text_item":
return self._new_element(obj, iWorkApplicationBase.XAiWorkTextItem)
elif specifier == "group":
return self._new_element(obj, iWorkApplicationBase.XAiWorkGroup)
elif specifier == "iwork_item":
return self._new_element(obj, iWorkApplicationBase.XAiWorkiWorkItem)
elif specifier == "transition_settings":
return self._new_element(obj, XAKeynoteTransitionSettings)
[docs]
class XAKeynoteWindow(iWorkApplicationBase.XAiWorkWindow):
"""A class for managing and interacting with windows in Keynote.app.
.. versionadded:: 0.0.1
"""
def __init__(self, properties):
super().__init__(properties)
@property
def document(self) -> 'XAKeynoteDocument':
"""The document currently displayed in the window.
"""
return self._new_element(self.xa_elem.document(), XAKeynoteDocument)
[docs]
class XAKeynoteDocumentList(iWorkApplicationBase.XAiWorkDocumentList):
"""A wrapper around lists of themes that employs fast enumeration techniques.
All properties of themes can be called as methods on the wrapped list, returning a list containing each theme's value for the property.
.. versionadded:: 0.0.5
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None):
super().__init__(properties, filter, XAKeynoteDocument)
[docs]
def properties(self) -> list[dict]:
pyxa_dicts = [None] * len(self.xa_elem)
for index, document in enumerate(self.xa_elem):
pyxa_dicts[index] = {
"name": document.name(),
"modified": document.modified(),
"file": XABase.XAPath(document.file()),
"id": document.id(),
"slide_numbers_showing": document.slideNumbersShowing(),
"document_theme": self._new_element(document.documentTheme(), XAKeynoteTheme),
"auto_loop": document.autoLoop(),
"auto_play": document.autoPlay(),
"auto_restart": document.autoRestart(),
"maximum_idle_duration": document.maximumIdleDuration(),
"current_slide": self._new_element(document.currentSlide(), XAKeynoteSlide),
"height": document.height(),
"width": document.width(),
"selection": [self._new_element(x, iWorkApplicationBase.XAiWorkiWorkItem) for x in document.selection()],
"password_protected": document.passwordProtected(),
}
return pyxa_dicts
[docs]
def slide_numbers_showing(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("slideNumbersShowing") or [])
[docs]
def document_theme(self) -> 'XAKeynoteThemeList':
ls = self.xa_elem.arrayByApplyingSelector_("documentTheme") or []
return self._new_element(ls, XAKeynoteThemeList)
[docs]
def auto_loop(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("autoLoop") or [])
[docs]
def auto_play(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("autoPlay") or [])
[docs]
def auto_restart(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("autoRestart") or [])
[docs]
def maximum_idle_duration(self) -> list[int]:
return list(self.xa_elem.arrayByApplyingSelector_("maximumIdleDuration") or [])
[docs]
def current_slide(self) -> 'XAKeynoteSlideList':
ls = self.xa_elem.arrayByApplyingSelector_("currentSlide") or []
return self._new_element(ls, XAKeynoteSlideList)
[docs]
def height(self) -> list[int]:
return list(self.xa_elem.arrayByApplyingSelector_("height") or [])
[docs]
def width(self) -> list[int]:
return list(self.xa_elem.arrayByApplyingSelector_("width") or [])
[docs]
def by_properties(self, properties: dict) -> Union['XAKeynoteDocument', None]:
raw_dict = {}
if "name" in properties:
raw_dict["name"] = properties["name"]
if "file" in properties:
if isinstance(properties["file"], str):
raw_dict["file"] = properties["file"]
else:
raw_dict["file"] = properties["file"].xa_elem
if "slide_numbers_showing" in properties:
raw_dict["slideNumbersShowing"] = properties["slide_numbers_showing"]
if "document_theme" in properties:
raw_dict["documentTheme"] = properties["document_theme"].xa_elem
if "auto_loop" in properties:
raw_dict["autoLoop"] = properties["auto_loop"]
if "auto_play" in properties:
raw_dict["autoPlay"] = properties["auto_play"]
if "auto_restart" in properties:
raw_dict["autoRestart"] = properties["auto_restart"]
if "maximum_idle_duration" in properties:
raw_dict["maximumIdleDuration"] = properties["maximum_idle_duration"]
if "height" in properties:
raw_dict["height"] = properties["height"]
if "width" in properties:
raw_dict["width"] = properties["width"]
for document in self.xa_elem:
if all(raw_dict[x] == document.properties()[x] for x in raw_dict):
return self._new_element(document, XAKeynoteDocument)
[docs]
def by_slide_numbers_showing(self, slide_numbers_showing: bool) -> Union['XAKeynoteDocument', None]:
return self.by_property("slideNumbersShowing", slide_numbers_showing)
[docs]
def by_document_theme(self, document_theme: 'XAKeynoteTheme') -> Union['XAKeynoteDocument', None]:
return self.by_property("documentTheme", document_theme.xa_elem)
[docs]
def by_auto_loop(self, auto_loop: bool) -> Union['XAKeynoteDocument', None]:
return self.by_property("autoLoop", auto_loop)
[docs]
def by_auto_play(self, auto_play: bool) -> Union['XAKeynoteDocument', None]:
return self.by_property("autoPlay", auto_play)
[docs]
def by_auto_restart(self, auto_restart: bool) -> Union['XAKeynoteDocument', None]:
return self.by_property("autoRestart", auto_restart)
[docs]
def by_maximum_idle_duration(self, maximum_idle_duration: int) -> Union['XAKeynoteDocument', None]:
return self.by_property("maxmimumIdleDuration", maximum_idle_duration)
[docs]
def by_current_slide(self, current_slide: 'XAKeynoteSlide') -> Union['XAKeynoteDocument', None]:
return self.by_property("currentSlide", current_slide.xa_elem)
[docs]
def by_height(self, height: int) -> Union['XAKeynoteDocument', None]:
return self.by_property("height", height)
[docs]
def by_width(self, width: int) -> Union['XAKeynoteDocument', None]:
return self.by_property("width", width)
[docs]
def by_selection(self, selection: 'iWorkApplicationBase.XAiWorkiWorkItemList') -> Union['XAKeynoteDocument', None]:
return self.by_property("selection", selection.xa_elem)
[docs]
def by_password_protected(self, password_protected: bool) -> Union['XAKeynoteDocument', None]:
return self.by_property("passwordProtected", password_protected)
def __repr__(self):
return f"<{str(type(self))}{self.name()}>"
[docs]
class XAKeynoteDocument(iWorkApplicationBase.XAiWorkDocument):
"""A class for managing and interacting with TextEdit documents.
.. seealso:: :class:`XAKeynoteApplication`
.. versionadded:: 0.0.2
"""
def __init__(self, properties):
super().__init__(properties)
@property
def properties(self) -> dict:
"""All properties of the document.
"""
pyxa_dict = {
"name": self.xa_elem.name(),
"modified": self.xa_elem.modified(),
"file": XABase.XAPath(self.xa_elem.file()),
"id": self.xa_elem.id(),
"slide_numbers_showing": self.xa_elem.slideNumbersShowing(),
"document_theme": self._new_element(self.xa_elem.documentTheme(), XAKeynoteTheme),
"auto_loop": self.xa_elem.autoLoop(),
"auto_play": self.xa_elem.autoPlay(),
"auto_restart": self.xa_elem.autoRestart(),
"maximum_idle_duration": self.xa_elem.maximumIdleDuration(),
"current_slide": self._new_element(self.xa_elem.currentSlide(), XAKeynoteSlide),
"height": self.xa_elem.height(),
"width": self.xa_elem.width(),
"selection": self._new_element(self.xa_elem.selection(), iWorkApplicationBase.XAiWorkiWorkItemList),
"password_protected": self.xa_elem.passwordProtected(),
}
return pyxa_dict
@property
def name(self) -> str:
"""The name of the document.
"""
return self.xa_elem.name()
@property
def modified(self) -> bool:
"""Whether the document has been modified since its last save.
"""
return self.xa_elem.modified()
@property
def file(self) -> str:
"""The location of the document on the disk, if one exists.
"""
return self.xa_elem.file()
@property
def id(self) -> str:
"""The unique identifier for the document.
"""
return self.xa_elem.id()
@property
def slide_numbers_showing(self) -> bool:
"""Whether slide numbers are displayed.
"""
return self.xa_elem.slideNumbersShowing()
@slide_numbers_showing.setter
def slide_numbers_showing(self, slide_numbers_showing: bool):
self.set_property('slideNumbersShowing', slide_numbers_showing)
@property
def document_theme(self) -> 'XAKeynoteTheme':
"""The theme assigned to the document.
"""
return self._new_element(self.xa_elem.documentTheme(), XAKeynoteTheme)
@document_theme.setter
def document_theme(self, document_theme: 'XAKeynoteTheme'):
self.set_property('documentTheme', document_theme.xa_elem)
@property
def auto_loop(self) -> bool:
"""Whether the slideshow should play repeatedly.
"""
return self.xa_elem.autoLoop()
@auto_loop.setter
def auto_loop(self, auto_loop: bool):
self.set_property('autoLoop', auto_loop)
@property
def auto_play(self) -> bool:
"""Whether the slideshow should automatically play when opening the file.
"""
return self.xa_elem.autoPlay()
@auto_play.setter
def auto_play(self, auto_play: bool):
self.set_property('autoPlay', auto_play)
@property
def auto_restart(self) -> bool:
"""Whether the slideshow should restart if its inactive for the maximum idle duration.
"""
return self.xa_elem.autoRestart()
@auto_restart.setter
def auto_restart(self, auto_restart: bool):
self.set_property('autoRestart', auto_restart)
@property
def maximum_idle_duration(self) -> int:
"""The duration before which the slideshow restarts due to inactivity.
"""
return self.xa_elem.maximumIdleDuration()
@maximum_idle_duration.setter
def maximum_idle_duration(self, maximum_idle_duration: int):
self.set_property('maximumIdleDuration', maximum_idle_duration)
@property
def current_slide(self) -> 'XAKeynoteSlide':
"""The currently selected slide, or the slide that would display is the presentation was started.
"""
return self._new_element(self.xa_elem.currentSlide(), XAKeynoteSlide)
@current_slide.setter
def current_slide(self, current_slide: 'XAKeynoteSlide'):
self.set_property('currentSlide', current_slide.xa_elem)
@property
def height(self) -> int:
"""The height of the document in points; standard is 768; wide slide height is 1080.
"""
return self.xa_elem.height()
@height.setter
def height(self, height: int):
self.set_property('height', height)
@property
def width(self) -> int:
"""The width of the document in points; standard is 1080; wide slide width is 1920.
"""
return self.xa_elem.width()
@width.setter
def width(self, width: int):
self.set_property('width', width)
@property
def selection(self) -> 'iWorkApplicationBase.XAiWorkiWorkItemList':
"""A list of the currently selected items.
"""
return self._new_element(self.xa_elem.selection(), iWorkApplicationBase.XAiWorkiWorkItemList)
@selection.setter
def selection(self, selection: Union['iWorkApplicationBase.XAiWorkiWorkItemList', list['iWorkApplicationBase.XAiWorkiWorkItem']]):
if isinstance(selection, list):
selection = [x.xa_elem for x in selection]
self.set_property('selection', selection)
else:
self.set_property('selection', selection.xa_elem)
@property
def password_protected(self) -> bool:
"""Whether the document is password protected.
"""
return self.xa_elem.passwordProtected()
[docs]
def start_from(self, slide: 'XAKeynoteSlide') -> 'XAKeynoteSlide':
"""Starts the slideshow from the specified slide.
.. versionadded:: 0.0.3
"""
self.xa_elem.startFrom_(slide.xa_elem)
return self
[docs]
def stop(self):
"""Stops the currently playing slideshow.
.. versionadded:: 0.0.3
"""
self.xa_elem.stop()
[docs]
def show_slide_switcher(self):
"""Shows the slide switch within the active slideshow interface.
.. versionadded:: 0.0.3
"""
self.xa_elem.showSlideSwitcher()
[docs]
def hide_slide_switcher(self):
"""Hides the slide switcher.
.. versionadded:: 0.0.3
"""
self.xa_elem.hideSlideSwitcher()
[docs]
def move_slide_switcher_forward(self):
"""Advances the slide switcher one slide forward.
.. versionadded:: 0.0.3
"""
self.xa_elem.moveSlideSwitcherForward()
[docs]
def move_slide_switcher_backward(self):
"""Goes back one slide in the slide switcher.
.. versionadded:: 0.0.3
"""
self.xa_elem.moveSlideSwitcherBackward()
[docs]
def cancel_slide_switcher(self):
"""Dismisses the slide switcher.
.. versionadded:: 0.0.3
"""
self.xa_elem.cancelSlideSwitcher()
[docs]
def accept_slide_switcher(self):
"""Advances the slideshow to the selected slide of the slide switcher.
.. versionadded:: 0.0.3
"""
self.xa_elem.acceptSlideSwitcher()
[docs]
def save(self):
"""Saves the Keynote file.
.. versionadded:: 0.0.3
"""
export_format = XAKeynoteApplication.ExportFormat.KEYNOTE.value
self.xa_elem.saveIn_as_(self.file, export_format)
[docs]
def export(self, file_path: Union[str, XABase.XAPath] = None, format: XAKeynoteApplication.ExportFormat = XAKeynoteApplication.ExportFormat.PDF):
"""Exports the slideshow in the specified format.
:param file_path: The path to save the exported file at, defaults to None
:type file_path: Union[str, XABase.XAPath], optional
:param format: The format to export the file in, defaults to XAKeynoteApplication.ExportFormat.PDF
:type format: XAKeynoteApplication.ExportFormat, optional
.. versionadded:: 0.0.3
"""
if file_path is None:
file_path = self.file.path()[:-4] + ".pdf"
if isinstance(file_path, str):
file_path = XABase.XAPath(file_path)
self.xa_elem.exportTo_as_withProperties_(file_path.xa_elem, format.value, None)
[docs]
def make_image_slides(self, files: list[Union[str, XABase.XAPath]], set_titles: bool = False, slide_layout: 'XAKeynoteSlideLayout' = None) -> 'XAKeynoteDocument':
"""Creates slides out of image files.
Creates a new slide for each image file path in the files list, if the image can be found.
:param files: A list of paths to image files
:type files: list[Union[str, XABase.XAPath]]
:param set_titles: Whether to set the slide titles to the image file name, defaults to False
:type set_titles: bool, optional
:param slide_layout: The base slide layout to use for the new slides, defaults to None
:type slide_layout: XAKeynoteSlideLayout, optional
:return: A reference back to this PyXA object.
:rtype: XAKeynoteDocument
.. versionadded:: 0.0.3
"""
urls = []
for file in files:
if isinstance(file, str):
file = XABase.XAPath(file)
urls.append(file.xa_elem)
self.xa_elem.makeImageSlidesFiles_setTitles_slideLayout_(urls, set_titles, slide_layout)
return self
[docs]
def slides(self, filter: Union[dict, None] = None) -> 'XAKeynoteSlideList':
"""Returns a list of slides, as PyXA objects, matching the given filter.
:param filter: A dictionary specifying property-value pairs that all returned slides will have, or None
:type filter: Union[dict, None]
:return: The list of slides
:rtype: XAKeynoteSlideList
:Example 1: List all slides
>>> import PyXA
>>> app = PyXA.Application("Keynotes")
>>> print(app.slides())
:Example 2: List slides after applying a filter
>>> import PyXA
>>> app = PyXA.Application("Keynotes")
>>> print(app.slides().greater_than("slideNumber", 5))
.. versionadded:: 0.0.2
"""
return self._new_element(self.xa_elem.slides(), XAKeynoteSlideList, filter)
[docs]
def new_slide(self, properties: dict) -> 'XAKeynoteSlide':
"""Creates a new slide at the end of the presentation.
:param properties: The properties to give the new slide
:type properties: dict
:return: A reference to the newly created slide
:rtype: XAKeynoteSlide
.. versionadded:: 0.0.2
"""
return self.xa_prnt.xa_prnt.new_slide(self, properties)
[docs]
def slide_layouts(self, filter: Union[dict, None] = None) -> 'XAKeynoteSlideLayoutList':
"""Returns a list of slide layouts, as PyXA objects, matching the given filter.
:param filter: A dictionary specifying property-value pairs that all returned slide layouts will have, or None
:type filter: Union[dict, None]
:return: The list of slide layouts
:rtype: XAKeynoteSlideLayoutList
:Example: List all slide layouts
>>> import PyXA
>>> app = PyXA.Application("Keynotes")
>>> print(app.slide_layouts())
.. versionadded:: 0.0.2
"""
return self._new_element(self.xa_elem.slideLayouts(), XAKeynoteSlideLayoutList, filter)
def __repr__(self):
return f"<{str(type(self))}{self.name}>"
[docs]
class XAKeynoteThemeList(XABase.XAList):
"""A wrapper around lists of themes that employs fast enumeration techniques.
All properties of themes can be called as methods on the wrapped list, returning a list containing each theme's value for the property.
.. versionadded:: 0.0.5
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None):
super().__init__(properties, XAKeynoteTheme, filter)
[docs]
def properties(self) -> list[str]:
# TODO
pyxa_dicts = [None] * len(self.xa_elem)
for index, theme in enumerate(self.xa_elem):
pyxa_dicts[index] = {
"id": theme.id(),
"name": theme.name()
}
return pyxa_dicts
[docs]
def id(self) -> list[str]:
return list(self.xa_elem.arrayByApplyingSelector_("id") or [])
[docs]
def name(self) -> list[str]:
return list(self.xa_elem.arrayByApplyingSelector_("name") or [])
[docs]
def by_properties(self, properties: dict) -> Union['XAKeynoteTheme', None]:
for theme in self.xa_elem:
if all(properties[x] == theme.properties()[x] for x in properties):
return self._new_element(theme, XAKeynoteTheme)
[docs]
def by_id(self, id: str) -> Union['XAKeynoteTheme', None]:
return self.by_property("id", id)
[docs]
def by_name(self, name: str) -> Union['XAKeynoteTheme', None]:
return self.by_property("name", name)
def __repr__(self):
return f"<{str(type(self))}{self.name()}>"
[docs]
class XAKeynoteTheme(XABase.XAObject):
"""A class for managing and interacting with Keynote themes.
.. seealso:: :class:`XAKeynoteApplication`
.. versionadded:: 0.0.2
"""
def __init__(self, properties):
super().__init__(properties)
@property
def properties(self) -> dict:
"""All properties of the theme.
"""
return {
"id": self.xa_elem.id(),
"name": self.xa_elem.name()
}
@property
def id(self) -> str:
"""The unique identifier for the theme.
"""
return self.xa_elem.id()
@property
def name(self) -> str:
"""The name of the theme.
"""
return self.xa_elem.name()
def __repr__(self):
return f"<{str(type(self))}{self.name}, id={str(self.id)}>"
[docs]
class XAKeynoteContainerList(iWorkApplicationBase.XAiWorkContainerList):
"""A wrapper around lists of containers that employs fast enumeration techniques.
.. versionadded:: 0.0.5
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None, obj_class = None):
if obj_class is None:
obj_class = XAKeynoteContainer
self._xa_ccls = XAKeynoteSlideList
super().__init__(properties, filter, obj_class)
[docs]
class XAKeynoteContainer(iWorkApplicationBase.XAiWorkContainer):
"""A class for managing and interacting with containers in Keynote.
.. versionadded:: 0.0.2
"""
def __init__(self, properties):
self._xa_ccls = XAKeynoteSlideList
super().__init__(properties)
[docs]
class XAKeynoteSlideList(XAKeynoteContainerList):
"""A wrapper around lists of themes that employs fast enumeration techniques.
All properties of themes can be called as methods on the wrapped list, returning a list containing each theme's value for the property.
.. versionadded:: 0.0.5
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None, obj_class = None):
if obj_class is None:
obj_class = XAKeynoteSlide
super().__init__(properties, filter, obj_class)
[docs]
def properties(self) -> list[dict]:
raw_dicts = self.xa_elem.arrayByApplyingSelector_("properties") or []
pyxa_dicts = [None] * len(self.xa_elem)
for index, raw_dict in enumerate(raw_dicts):
pyxa_dicts[index] = {
"default_title_item": self._new_element(raw_dict["defaultTitleItem"], iWorkApplicationBase.XAiWorkShape),
"slide_number": raw_dict["slideNumber"],
"default_body_item": self._new_element(raw_dict["defaultBodyItem"], iWorkApplicationBase.XAiWorkShape),
"skipped": raw_dict["skipped"] == 1,
"body_showing": raw_dict["bodyShowing"] == 1,
"presenter_notes": self._new_element(raw_dict["presenterNotes"], XABase.XAText),
"title_showing": raw_dict["titleShowing"] == 1,
"transition_properties": XAKeynoteTransitionSettings({
"automatic_transition": raw_dict["transitionProperties"]["automaticTransition"] == 1,
"transition_delay": raw_dict["transitionProperties"]["transitionDelay"],
"transtion_duration": raw_dict["transitionProperties"]["transitionDuration"],
"transition_effect": XAKeynoteApplication.Transition(XABase.OSType(raw_dict["transitionProperties"]["transitionEffect"].stringValue()))
}, self._new_element(self.xa_elem[index], XAKeynoteSlide)),
"base_layout": self._new_element(raw_dict["baseLayout"], XAKeynoteSlideLayout)
}
return pyxa_dicts
[docs]
def body_showing(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("bodyShowing") or [])
[docs]
def skipped(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("skipped") or [])
[docs]
def slide_number(self) -> list[int]:
return list(self.xa_elem.arrayByApplyingSelector_("slideNumber") or [])
[docs]
def title_showing(self) -> list[bool]:
return list(self.xa_elem.arrayByApplyingSelector_("titleShowing") or [])
[docs]
def transition_properties(self) -> list[dict]:
raw_dicts = self.xa_elem.arrayByApplyingSelector_("transitionProperties") or []
pyxa_dicts = [None] * len(self.xa_elem)
for index, raw_dict in enumerate(raw_dicts):
pyxa_dicts[index] = XAKeynoteTransitionSettings({
"automatic_transition": raw_dict["automaticTransition"] == 1,
"transition_delay": raw_dict["transitionDelay"],
"transtion_duration": raw_dict["transitionDuration"],
"transition_effect": XAKeynoteApplication.Transition(XABase.OSType(raw_dict["transitionEffect"].stringValue()))
}, self._new_element(self.xa_elem[index], XAKeynoteSlide))
return pyxa_dicts
[docs]
def base_layout(self) -> 'XAKeynoteSlideLayoutList':
ls = self.xa_elem.arrayByApplyingSelector_("baseLayout") or []
return self._new_element(ls, XAKeynoteSlideLayoutList)
[docs]
def default_body_item(self) -> 'iWorkApplicationBase.XAiWorkShapeList':
ls = self.xa_elem.arrayByApplyingSelector_("defaultBodyItem") or []
return self._new_element(ls, iWorkApplicationBase.XAiWorkShapeList)
[docs]
def default_title_item(self) -> 'iWorkApplicationBase.XAiWorkShapeList':
ls = self.xa_elem.arrayByApplyingSelector_("defaultTitleItem") or []
return self._new_element(ls, iWorkApplicationBase.XAiWorkShapeList)
[docs]
def presenter_notes(self) -> XABase.XATextList:
ls = self.xa_elem.arrayByApplyingSelector_("presenterNotes") or []
return self._new_element(ls, XABase.XATextList)
[docs]
def by_properties(self, properties: dict) -> 'XAKeynoteSlide':
raw_dict = {}
if "default_title_item" in properties:
raw_dict["defaultTitleItem"] = properties["default_title_item"].xa_elem
if "slide_number" in properties:
raw_dict["slideNumber"] = properties["slide_number"]
if "default_body_item" in properties:
raw_dict["defaultBodyItem"] = properties["default_body_item"].xa_elem
if "skipped" in properties:
raw_dict["skipped"] = properties["skipped"]
if "body_showing" in properties:
raw_dict["bodyShowing"] = properties["body_showing"]
if "presenter_notes" in properties:
if isinstance(properties["presenter_notes"], str):
raw_dict["presenterNotes"] = properties["presenter_notes"]
else:
raw_dict["presenterNotes"] = properties["presenter_notes"].xa_elem
if "title_showing" in properties:
raw_dict["titleShowing"] = properties["title_showing"]
if "transition_properties" in properties:
raw_dict["transitionProperties"] = {}
if isinstance(properties["transition_properties"], XAKeynoteTransitionSettings):
properties["transition_properties"] = properties["transition_properties"]._pyxa_dict
if "automatic_transition" in properties["transition_properties"]:
raw_dict["transitionProperties"]["automaticTransition"] = properties["transition_properties"]["automatic_transition"]
if "transition_delay" in properties["transition_properties"]:
raw_dict["transitionProperties"]["transitionDelay"] = properties["transition_properties"]["transition_delay"]
if "transtion_duration" in properties["transition_properties"]:
raw_dict["transitionProperties"]["transitionDuration"] = properties["transition_properties"]["transtion_duration"]
if "transition_effect" in properties["transition_properties"]:
raw_dict["transitionProperties"]["transitionEffect"] = XAEvents.event_from_type_code(properties["transition_properties"]["transition_effect"].value)
if "base_layout" in properties:
raw_dict["baseLayout"] = properties["base_layout"].xa_elem
for slide in self.xa_elem:
if all(raw_dict[x] == slide.properties()[x] for x in raw_dict):
return self._new_element(slide, XAKeynoteSlide)
[docs]
def by_body_showing(self, body_showing: bool) -> 'XAKeynoteSlide':
return self.by_property("bodyShowing", body_showing)
[docs]
def by_skipped(self, skipped: bool) -> 'XAKeynoteSlide':
return self.by_property("skipped", skipped)
[docs]
def by_slide_number(self, slide_number: int) -> 'XAKeynoteSlide':
return self.by_property("slideNumber", slide_number)
[docs]
def by_title_showing(self, title_showing: bool) -> 'XAKeynoteSlide':
return self.by_property("titleShowing", title_showing)
[docs]
def by_transition_properties(self, transition_properties: Union['XAKeynoteTransitionSettings', dict]) -> 'XAKeynoteSlide':
properties = {}
if isinstance(transition_properties, XAKeynoteTransitionSettings):
transition_properties = transition_properties._pyxa_dict
if "automatic_transition" in transition_properties:
properties["automaticTransition"] = transition_properties["automatic_transition"]
if "transition_delay" in transition_properties:
properties["transitionDelay"] = transition_properties["transition_delay"]
if "transtion_duration" in transition_properties:
properties["transitionDuration"] = transition_properties["transtion_duration"]
if "transition_effect" in transition_properties:
properties["transitionEffect"] = XAEvents.event_from_type_code(transition_properties["transition_effect"].value)
return self.by_property("transitionProperties", properties)
[docs]
def by_base_layout(self, base_layout: 'XAKeynoteSlideLayout') -> 'XAKeynoteSlide':
return self.by_property("baseLayout", base_layout.xa_elem)
[docs]
def by_default_body_item(self, default_body_item: 'iWorkApplicationBase.XAiWorkShape') -> 'XAKeynoteSlide':
return self.by_property("defaultBodyItem", default_body_item.xa_elem)
[docs]
def by_default_text_item(self, default_text_item: 'iWorkApplicationBase.XAiWorkShape') -> 'XAKeynoteSlide':
return self.by_property("defaultTextItem", default_text_item.xa_elem)
[docs]
def by_presenter_notes(self, presenter_notes: Union[str, XABase.XAText]) -> 'XAKeynoteSlide':
if isinstance(presenter_notes, str):
self.by_property('presenterNotes', presenter_notes)
else:
self.by_property('presenterNotes', presenter_notes.xa_elem)
def __repr__(self):
return "<" + str(type(self)) + "length: " + str(len(self.xa_elem)) + ">"
[docs]
class XAKeynoteSlide(XAKeynoteContainer):
"""A class for managing and interacting with Keynote slides.
.. seealso:: :class:`XAKeynoteApplication`, :class:`iWorkApplicationBase.XAiWorkiWorkItem`
.. versionadded:: 0.0.2
"""
def __init__(self, properties):
super().__init__(properties)
@property
def properties(self) -> dict:
"""All properties of the slide.
"""
raw_dict = self.xa_elem.properties()
pyxa_dict = {
"default_title_item": self._new_element(raw_dict["defaultTitleItem"], iWorkApplicationBase.XAiWorkShape),
"slide_number": raw_dict["slideNumber"],
"default_body_item": self._new_element(raw_dict["defaultBodyItem"], iWorkApplicationBase.XAiWorkShape),
"skipped": raw_dict["skipped"] == 1,
"body_showing": raw_dict["bodyShowing"] == 1,
"presenter_notes": self._new_element(raw_dict["presenterNotes"], XABase.XAText),
"title_showing": raw_dict["titleShowing"] == 1,
"transition_properties": XAKeynoteTransitionSettings({
"automatic_transition": raw_dict["transitionProperties"]["automaticTransition"] == 1,
"transition_delay": raw_dict["transitionProperties"]["transitionDelay"],
"transition_duration": raw_dict["transitionProperties"]["transitionDuration"],
"transition_effect": XAKeynoteApplication.Transition(XABase.OSType(raw_dict["transitionProperties"]["transitionEffect"].stringValue()))
}, self),
"base_layout": self._new_element(raw_dict["baseLayout"], XAKeynoteSlideLayout)
}
return pyxa_dict
@property
def body_showing(self) -> bool:
"""Whether the default body text is displayed.
"""
return self.xa_elem.bodyShowing()
@body_showing.setter
def body_showing(self, body_showing: bool):
self.set_property('bodyShowing', body_showing)
@property
def skipped(self) -> bool:
"""Whether the slide is skipped.
"""
return self.xa_elem.skipped()
@skipped.setter
def skipped(self, skipped: bool):
self.set_property('skipped', skipped)
@property
def slide_number(self) -> int:
"""The index of the slide in the document.
"""
return self.xa_elem.slideNumber()
@property
def title_showing(self) -> bool:
"""Whether the default slide title is displayed.
"""
return self.xa_elem.titleShowing()
@title_showing.setter
def title_showing(self, title_showing: bool):
self.set_property('titleShowing', title_showing)
@property
def transition_properties(self) -> dict:
"""The transition settings applied to the slide.
"""
raw_dict = self.xa_elem.transitionProperties()
pyxa_dict = {
"automatic_transition": raw_dict["automaticTransition"] == 1,
"transition_delay": raw_dict["transitionDelay"],
"transition_duration": raw_dict["transitionDuration"],
"transition_effect": XAKeynoteApplication.Transition(XABase.OSType(raw_dict["transitionEffect"].stringValue()))
}
return XAKeynoteTransitionSettings(pyxa_dict, self)
@transition_properties.setter
def transition_properties(self, transition_properties: Union['XAKeynoteTransitionSettings', dict]):
properties = {}
if isinstance(transition_properties, XAKeynoteTransitionSettings):
transition_properties = transition_properties._pyxa_dict
if "automatic_transition" in transition_properties:
properties["automaticTransition"] = transition_properties["automatic_transition"]
if "transition_delay" in transition_properties:
properties["transitionDelay"] = transition_properties["transition_delay"]
if "transtion_duration" in transition_properties:
properties["transitionDuration"] = transition_properties["transtion_duration"]
if "transition_effect" in transition_properties:
properties["transitionEffect"] = XAEvents.event_from_type_code(transition_properties["transition_effect"].value)
self.set_property('transitionProperties', properties)
@property
def base_layout(self) -> 'XAKeynoteSlideLayout':
"""The slide layout this slide is based on.
"""
return self._new_element(self.xa_elem.baseLayout(), XAKeynoteSlideLayout)
@base_layout.setter
def base_layout(self, base_layout: 'XAKeynoteSlideLayout'):
self.set_property('baseLayout', base_layout.xa_elem)
@property
def default_body_item(self) -> 'iWorkApplicationBase.XAiWorkShape':
"""The default body container of the slide.
"""
return self._new_element(self.xa_elem.defaultBodyItem(), iWorkApplicationBase.XAiWorkShape)
@property
def default_title_item(self) -> 'iWorkApplicationBase.XAiWorkShape':
"""The default title container of the slide.
"""
return self._new_element(self.xa_elem.defaultTitleItem(), iWorkApplicationBase.XAiWorkShape)
@property
def presenter_notes(self) -> XABase.XAText:
"""The presenter notes for the slide.
"""
return self._new_element(self.xa_elem.presenterNotes(), XABase.XAText)
@presenter_notes.setter
def presenter_notes(self, presenter_notes: Union[XABase.XAText, str]):
if isinstance(presenter_notes, str):
self.set_property('presenterNotes', presenter_notes)
else:
self.set_property('presenterNotes', presenter_notes.xa_elem)
[docs]
def move(self, location: Union[XAKeynoteDocument, XAKeynoteSlideList], position: int = -1) -> 'XAKeynoteSlide':
"""Moves the slide to the specified location, at the specified position.
:param location: The document or list of slides to move this slide to
:type location: Union[XAKeynoteDocument, XAKeynoteSlideList]
:param position: The index to insert the slide within a list, defaults to -1
:type position: int, optional
:return: A reference to the slide object
:rtype: XAKeynoteSlide
:Example:
>>> import PyXA
>>> app = PyXA.Keynote()
>>> doc = app.documents()[0]
>>> doc2 = app.documents()[1]
>>> doc.slides()[0].move(doc2)
<<class 'PyXA.apps.Keynote.XAKeynoteSlide'>slide number: 5>
.. versionadded:: 0.2.2
"""
if isinstance(location, XAKeynoteSlideList):
if position == -1:
self.xa_elem.moveTo_(location.xa_elem.lastObject().positionAfter())
return location[-1]
else:
self.xa_elem.moveTo_(location.xa_elem[position].positionBefore())
return location[position]
elif isinstance(location, XAKeynoteDocument):
if position == -1:
self.xa_elem.moveTo_(location.slides().xa_elem.lastObject().positionAfter())
return location.slides()[-1]
else:
self.xa_elem.moveTo_(location.slides().xa_elem[position].positionBefore())
return location.slides()[position]
[docs]
def duplicate(self, location: Union[XAKeynoteDocument, XAKeynoteSlideList, None] = None, position: int = -1) -> 'XAKeynoteSlide':
"""Duplicates the slide, mimicking the action of copying and pasting the slide manually.
:param location: The document or list of slides to duplicate this slide to, or None to duplicate into the current document, defaults to None
:type location: Union[XAKeynoteDocument, XAKeynoteSlideList, None], optional
:param position: The index to insert the slide within a list, defaults to -1
:type position: int, optional
:return: A reference to newly created (duplicate) slide object.
:rtype: XAKeynoteSlide
:Example: Duplicate Slide From One Document To Another
>>> import PyXA
>>> app = PyXA.Keynote()
>>> doc1 = app.documents()[0]
>>> doc2 = app.documents()[1]
>>> doc1.slides()[0].duplicate(doc2)
<<class 'PyXA.apps.Keynote.XAKeynoteSlide'>slide number: 5>
.. versionadded:: 0.2.2
"""
if location is None:
location = self.xa_prnt
source = self.xa_prnt
if isinstance(source, XAKeynoteSlideList):
self.xa_elem.duplicateTo_withProperties_(source.xa_elem.lastObject().positionAfter(), None)
return source[-1].move(location, position)
elif isinstance(source, XAKeynoteDocument):
self.xa_elem.duplicateTo_withProperties_(source.slides().xa_elem.lastObject().positionAfter(), None)
return source.slides()[-1].move(location, position)
[docs]
def delete(self):
"""Deletes the slide.
.. versionadded:: 0.0.2
"""
self.xa_elem.delete()
[docs]
def add_image(self, file_path: Union[str, XABase.XAPath, XABase.XAURL]) -> 'iWorkApplicationBase.XAiWorkImage':
"""Adds the image at the specified path to the slide.
:param file_path: The path to the image file.
:type file_path: Union[str, XABase.XAPath, XABase.XAURL]
:return: The newly created image object.
:rtype: iWorkApplicationBase.XAiWorkImage
.. versionadded:: 0.0.2
"""
url = file_path
if isinstance(url, str):
if "://" in url:
url = XABase.XAURL(url)
else:
url = XABase.XAPath(url)
image = None
parent = self.xa_prnt.xa_prnt
max_backtracks = 6 # this -> slidelist -> document -> document list -> window -> window list -> application
num_backtracks = 0
while not hasattr(parent, "make") and num_backtracks < max_backtracks:
parent = parent.xa_prnt
num_backtracks += 1
image = parent.make("image", { "file": url.xa_elem })
return self.images().push(image)
[docs]
def add_chart(self, row_names: list[str], column_names: list[str], data: list[list[Any]], type: int = XAKeynoteApplication.ChartType.LINE_2D.value, group_by: int = XAKeynoteApplication.ChartGrouping.ROW.value) -> 'iWorkApplicationBase.XAiWorkChart':
"""_summary_
_extended_summary_
:param row_names: A list of row names.
:type row_names: list[str]
:param column_names: A list of column names.
:type column_names: list[str]
:param data: A 2d array
:type data: list[list[Any]]
:param type: The chart type, defaults to _KeynoteLegacyChartType.KeynoteLegacyChartTypeLine_2d.value
:type type: int, optional
:param group_by: The grouping schema, defaults to _KeynoteLegacyChartGrouping.KeynoteLegacyChartGroupingChartRow.value
:type group_by: int, optional
:return: A reference to the newly created chart object.
:rtype: iWorkApplicationBase.XAiWorkChart
.. versionadded:: 0.0.2
"""
parent = self.xa_prnt
max_backtracks = 2 # this -> slidelist -> document
num_backtracks = 0
while not isinstance(parent, XAKeynoteDocument) and num_backtracks < max_backtracks:
parent = parent.xa_prnt
num_backtracks += 1
self.xa_prnt.set_property("currentSlide", self.xa_elem)
self.xa_elem.addChartRowNames_columnNames_data_type_groupBy_(row_names, column_names, data, type, group_by)
chart = self.xa_elem.charts()[-1].get()
return self._new_element(chart, iWorkApplicationBase.XAiWorkChart)
def __repr__(self):
return "<" + str(type(self)) + "slide number: " + str(self.slide_number) + ">"
[docs]
class XAKeynoteSlideLayoutList(XAKeynoteSlideList):
"""A wrapper around lists of themes that employs fast enumeration techniques.
All properties of themes can be called as methods on the wrapped list, returning a list containing each theme's value for the property.
.. versionadded:: 0.0.5
"""
def __init__(self, properties: dict, filter: Union[dict, None] = None):
super().__init__(properties, XAKeynoteSlideLayout, filter)
[docs]
def name(self) -> list[str]:
return list(self.xa_elem.arrayByApplyingSelector_("name") or [])
[docs]
def by_name(self, name: str) -> 'XAKeynoteSlideLayout':
return self.by_property("name", name)
def __repr__(self):
return "<" + str(type(self)) + str(self.name()) + ">"
[docs]
class XAKeynoteSlideLayout(XAKeynoteSlide):
"""A class for managing and interacting with Keynote slide layouts.
.. seealso:: :class:`XAKeynoteSlide`
.. versionadded:: 0.0.2
"""
def __init__(self, properties):
super().__init__(properties)
@property
def name(self) -> str:
"""The name of the slide layout.
"""
return self.xa_elem.name()
def __repr__(self):
return "<" + str(type(self)) + str(self.name) + ">"
[docs]
class XAKeynoteTransitionSettings(XABase.XAObject):
"""Properties common to all transtions.
.. versionadded:: 0.1.0
"""
def __init__(self, properties: dict, parent: XABase.XAObject = None):
self.__automatic_transition: bool = properties["automatic_transition"]
self.__transition_delay: float = properties["transition_delay"]
self.__transition_duration: float = properties["transition_duration"]
self.__transition_effect: XAKeynoteApplication.Transition = properties["transition_effect"]
self.__parent = parent
@property
def _pyxa_dict(self):
return {
"automatic_transition": self.__automatic_transition,
"transition_telay": self.__transition_delay,
"transition_duration": self.__transition_duration,
"transition_effect": self.__transition_effect
}
@property
def automatic_transition(self) -> bool:
return self.__automatic_transition
@automatic_transition.setter
def automatic_transition(self, automatic_transition: bool):
self.__automatic_transition = automatic_transition
if self.__parent is not None:
self.__parent.transition_properties = self._pyxa_dict
@property
def transition_delay(self) -> float:
return self.__transition_delay
@transition_delay.setter
def automatic_transition(self, transition_delay: float):
self.__transition_delay = transition_delay
if self.__parent is not None:
self.__parent.transition_properties = self._pyxa_dict
@property
def transition_duration(self) -> float:
return self.__transition_duration
@transition_duration.setter
def automatic_transition(self, transition_duration: float):
self.__transition_duration = transition_duration
if self.__parent is not None:
self.__parent.transition_properties = self._pyxa_dict
@property
def transition_effect(self) -> XAKeynoteApplication.Transition:
return self.__transition_effect
@transition_effect.setter
def transition_effect(self, transition_effect: XAKeynoteApplication.Transition):
self.__transition_effect = transition_effect
if self.__parent is not None:
self.__parent.transition_properties = self._pyxa_dict
def __repr__(self):
return "<" + str(type(self)) + str(self._pyxa_dict) + ">"