1#!/usr/local/bin/python3.8
2#
3# Copyright 2008, 2009 Hannes Hochreiner
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see http://www.gnu.org/licenses/.
17#
18"""Effect to print out jessyInk summary"""
19
20from collections import defaultdict
21import inkex
22
23from jessyink_install import JessyInkMixin, _
24
25class Summary(JessyInkMixin, inkex.EffectExtension):
26    """Print of jessyInk summary"""
27    def add_arguments(self, pars):
28        pars.add_argument('--tab')
29
30    def effect(self):
31        self.is_installed()
32
33        # Find the script node, if present
34        for node in self.svg.xpath("//svg:script[@id='JessyInk']"):
35            version = node.get("jessyink:version")
36            if version:
37                self.msg(_(f"JessyInk script version {version} installed."))
38            else:
39                self.msg(_("JessyInk script installed."))
40
41        slides = []
42        master_slide = None
43
44        for node in self.svg.descendants().get(inkex.Layer):
45            if node.get("jessyink:master_slide"):
46                master_slide = node
47            else:
48                slides.append(node)
49
50        if master_slide is not None:
51            self.msg(_("\nMaster slide:"))
52            self.describe_node(master_slide, "\t",\
53                ["<the number of the slide>", len(slides), "<the title of the slide>"])
54
55        for i, slide in enumerate(slides):
56            self.msg(_("\nSlide {0!s}:").format(i+1))
57            self.describe_node(slide, "\t", [i + 1, len(slides), slide.label])
58
59    def describe_node(self, node, prefix, dat):
60        """Standard print out formatter"""
61
62        self.msg(_(f"{prefix}Layer name: {node.label}"))
63        self.describe_transition(node, prefix, "In")
64        self.describe_transition(node, prefix, "Out")
65        self.describe_autotext(node, prefix, dat)
66        self.describe_effects(node, prefix)
67
68    def describe_transition(self, node, prefix, transition):
69        """Display information about transitions."""
70        trans = inkex.Style(node.get(f"jessyink:transition{transition}"))
71        if trans:
72            name = trans["name"]
73            if name != "appear" and "length" in trans:
74                length = int(trans["length"] / 1000.0)
75                self.msg(_(f"{prefix}Transition {transition}: {name} ({length!s} s)"))
76            else:
77                self.msg(_(f"{prefix}Transition {transition}: {name}"))
78
79    def describe_autotext(self, node, prefix, dat):
80        """Display information about auto-texts."""
81        auto_texts = {"slide_num" : dat[0], "num" : dat[1], "title" : dat[2]}
82        for x, child in enumerate(node.xpath(".//*[@jessyink:autoText]")):
83            if not x:
84                self.msg(_(f"\n{prefix}Auto-texts:"))
85
86            pid = child.getparent().get("id")
87            val = auto_texts[child.get('jessyink:autoText')]
88            self.msg(_(
89                f'{prefix}\t"{child.text}" (object id "{pid}") will be replaced by "{val}".'))
90
91    def describe_effects(self, node, prefix):
92        """Display information about effects."""
93        effects = sorted(self.collect_effects(node), key=lambda val: val[0])
94        for x, (enum, effect) in enumerate(effects):
95            ret = ""
96
97            order = effect[0]["order"]
98            if not x:
99                ret += _(f"\n{prefix}Initial effect (order number {order}):")
100            else:
101                ret += _(f"\n{prefix}Effect {enum!s} (order number {order}):")
102
103            for item in effect:
104                eid = item["id"]
105                if item["type"] == "view":
106                    ret += _(f"{prefix}\tView will be set according to object \"{eid}\"")
107                else:
108                    ret += _(f"{prefix}\tObject \"{eid}\"")
109
110                    if item["direction"] == "in":
111                        ret += _(" will appear")
112                    elif item["direction"] == "out":
113                        ret += _(" will disappear")
114
115                if item["name"] != "appear":
116                    ret += _(" using effect \"{0}\"").format(item["name"])
117
118                if "length" in item:
119                    ret += _(" in {0!s} s").format(int(item["length"]) / 1000.0)
120
121            self.msg(ret + ".\n")
122
123    @staticmethod
124    def collect_effects(node):
125        """Collect information about effects."""
126        effects = defaultdict(list)
127        for child in node.xpath(".//*[@jessyink:effectIn]"):
128            effect_data = inkex.Style(child.get('jessyink:effectIn'))
129            effect_data["direction"] = "in"
130            effect_data["id"] = child.get("id")
131            effect_data["type"] = "effect"
132            effects[effect_data["order"]].append(effect_data)
133
134        for child in node.xpath(".//*[@jessyink:effectOut]"):
135            effect_data = inkex.Style(child.get('jessyink:effectOut'))
136            effect_data["direction"] = "out"
137            effect_data["id"] = child.get("id")
138            effect_data["type"] = "effect"
139            effects[effect_data["order"]].append(effect_data)
140
141        for child in node.xpath(".//*[@jessyink:view]"):
142            effect_data = inkex.Style(child.get('jessyink:view'))
143            effect_data["id"] = child.get("id")
144            effect_data["type"] = "view"
145            effects[effect_data["order"]].append(effect_data)
146        return effects
147
148if __name__ == '__main__':
149    Summary().run()
150