2022-11-30 15:57:58 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# Copyright (C) 2017 Florian Festi
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import os.path
|
2024-03-31 18:51:28 +02:00
|
|
|
import sys
|
2022-11-30 15:57:58 +01:00
|
|
|
from xml.sax.saxutils import quoteattr
|
|
|
|
|
|
|
|
try:
|
|
|
|
import boxes.generators
|
|
|
|
except ImportError:
|
|
|
|
sys.path.append(os.path.dirname(__file__) + "/..")
|
|
|
|
import boxes.generators
|
|
|
|
|
2024-03-31 18:51:28 +02:00
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
class Boxes2INX:
|
2024-03-31 18:51:28 +02:00
|
|
|
def __init__(self) -> None:
|
|
|
|
self.boxes = {b.__name__: b() for b in boxes.generators.getAllBoxGenerators().values() if b.webinterface}
|
2022-11-30 15:57:58 +01:00
|
|
|
self.groups = boxes.generators.ui_groups
|
|
|
|
self.groups_by_name = boxes.generators.ui_groups_by_name
|
|
|
|
|
|
|
|
for name, box in self.boxes.items():
|
2024-03-31 18:51:28 +02:00
|
|
|
self.groups_by_name.get(box.ui_group, self.groups_by_name["Misc"]).add(box)
|
2022-11-30 15:57:58 +01:00
|
|
|
|
|
|
|
def arg2inx(self, a, prefix):
|
|
|
|
name = a.option_strings[0].replace("-", "")
|
2024-03-31 18:51:28 +02:00
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
if isinstance(a, argparse._HelpAction):
|
|
|
|
return ""
|
2024-03-31 18:51:28 +02:00
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
viewname = name
|
|
|
|
if prefix and name.startswith(prefix + '_'):
|
2024-03-31 18:51:28 +02:00
|
|
|
viewname = name[len(prefix) + 1:]
|
2022-11-30 15:57:58 +01:00
|
|
|
|
|
|
|
if (isinstance(a, argparse._StoreAction) and hasattr(a.type, "inx")):
|
2024-03-31 18:51:28 +02:00
|
|
|
return a.type.inx(name, viewname, a) # see boxes.__init__.py
|
2022-11-30 15:57:58 +01:00
|
|
|
elif a.dest == "layout":
|
|
|
|
return ""
|
2024-03-31 18:51:28 +02:00
|
|
|
# val = a.default.split("\n")
|
|
|
|
# input = f"""<textarea name="{name}" cols="{max(len(l) for l in val) + 10}" rows="{len(val) + 1}">{a.default}</textarea>"""
|
2022-11-30 15:57:58 +01:00
|
|
|
elif a.choices:
|
|
|
|
uniqueChoices = []
|
|
|
|
for e in a.choices:
|
|
|
|
if e not in uniqueChoices:
|
|
|
|
uniqueChoices.append(e)
|
2024-03-31 18:51:28 +02:00
|
|
|
return (f'''<param name="{name}" type="optiongroup" appearance="combo" gui-text="{viewname}" gui-description={quoteattr(a.help or viewname)}>\n''' +
|
|
|
|
"".join(f'<option value="{e}">{e}</option>\n' for e in uniqueChoices) + ' </param>\n')
|
2022-11-30 15:57:58 +01:00
|
|
|
else:
|
|
|
|
default = a.default
|
|
|
|
if isinstance(a.type, boxes.BoolArg):
|
|
|
|
t = '"bool"'
|
|
|
|
default = str(a.default).lower()
|
2024-03-31 18:51:28 +02:00
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
elif a.type is boxes.argparseSections:
|
|
|
|
t = '"string"'
|
2024-03-31 18:51:28 +02:00
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
else:
|
2024-03-31 18:51:28 +02:00
|
|
|
t = {int: '"int"',
|
|
|
|
float: '"float" precision="2"',
|
|
|
|
str: '"string"',
|
|
|
|
}.get(a.type, '"string"')
|
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
if t == '"int"' or t == '"float" precision="2"':
|
2024-03-31 18:51:28 +02:00
|
|
|
return f'''<param name="{name}" type={t} max="9999" gui-text="{viewname}" gui-description={quoteattr(a.help or viewname)}>{default}</param>\n'''
|
2022-11-30 15:57:58 +01:00
|
|
|
|
|
|
|
else:
|
2024-03-31 18:51:28 +02:00
|
|
|
return f'''<param name="{name}" type={t} gui-text="{viewname}" gui-description={quoteattr(a.help or viewname)}>{default}</param>\n'''
|
2022-11-30 15:57:58 +01:00
|
|
|
|
|
|
|
def generator2inx(self, name, box):
|
2024-03-31 18:51:28 +02:00
|
|
|
result = [f"""<?xml version="1.0" encoding="UTF-8"?>
|
2022-11-30 15:57:58 +01:00
|
|
|
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
2024-03-31 18:51:28 +02:00
|
|
|
<name>{name}</name>
|
|
|
|
<id>info.festi.boxes.py.{name}</id>
|
|
|
|
<param name="generator" type="string" gui-hidden="true">{name.lower()}</param>
|
|
|
|
<param name="tab" type="notebook">"""]
|
2022-11-30 15:57:58 +01:00
|
|
|
groupid = 0
|
|
|
|
for group in box.argparser._action_groups:
|
|
|
|
if not group._group_actions:
|
|
|
|
continue
|
|
|
|
prefix = getattr(group, "prefix", None)
|
|
|
|
title = group.title
|
|
|
|
if title.startswith("Settings for "):
|
|
|
|
title = title[len("Settings for "):]
|
|
|
|
if title.endswith(" Settings"):
|
2024-03-31 18:51:28 +02:00
|
|
|
title = title[:-len(" Settings")]
|
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
pageParams = []
|
|
|
|
for a in group._group_actions:
|
|
|
|
if a.dest in ("input", "output", "format"):
|
2024-03-31 18:51:28 +02:00
|
|
|
continue
|
2022-11-30 15:57:58 +01:00
|
|
|
if self.arg2inx(a, prefix) != "":
|
|
|
|
pageParams.append(self.arg2inx(a, prefix))
|
|
|
|
if len(pageParams) > 0:
|
2024-03-31 18:51:28 +02:00
|
|
|
result.append(f"""<page name="tab_{groupid}" gui-text="{title}">""")
|
2022-11-30 15:57:58 +01:00
|
|
|
result.extend(pageParams)
|
2024-03-31 18:51:28 +02:00
|
|
|
result.append("</page>\n")
|
|
|
|
|
2022-11-30 15:57:58 +01:00
|
|
|
groupid += 1
|
2024-03-31 18:51:28 +02:00
|
|
|
result.append(f"""<page name="tab_{groupid}" gui-text="Example">\n""")
|
|
|
|
result.append(f"""<image>./{name}-thumb.jpg</image>\n""")
|
|
|
|
result.append("</page>\n")
|
|
|
|
result.append(f"""</param>
|
|
|
|
<label appearance="url">https://www.festi.info/boxes.py/{name}</label>
|
2022-11-30 15:57:58 +01:00
|
|
|
<effect>
|
|
|
|
<object-type>all</object-type>
|
|
|
|
<effects-menu>
|
|
|
|
<submenu name="Boxes.py">
|
2024-03-31 18:51:28 +02:00
|
|
|
<submenu name="{self.groups_by_name[box.ui_group].title}"/>
|
2022-11-30 15:57:58 +01:00
|
|
|
</submenu>
|
|
|
|
</effects-menu>
|
|
|
|
</effect>
|
|
|
|
<script>
|
|
|
|
<command location="inx" interpreter="python">boxes_proxy.py</command>
|
|
|
|
</script>
|
2024-03-31 18:51:28 +02:00
|
|
|
</inkscape-extension>""")
|
2022-11-30 15:57:58 +01:00
|
|
|
return b''.join(s.encode("utf-8") for s in result)
|
|
|
|
|
|
|
|
def writeINX(self, name, box, path):
|
|
|
|
with open(os.path.join(path, "boxes.py." + name + '.inx'), "wb") as f:
|
|
|
|
f.write(self.generator2inx(name, box))
|
|
|
|
|
|
|
|
def writeAllINX(self, path):
|
|
|
|
for name, box in self.boxes.items():
|
|
|
|
if name.startswith("TrayLayout"):
|
|
|
|
# The two stage thing does not work (yet?)
|
|
|
|
continue
|
|
|
|
self.writeINX(name, box, path)
|
|
|
|
|
2024-03-31 18:51:28 +02:00
|
|
|
|
|
|
|
def main() -> None:
|
2022-11-30 15:57:58 +01:00
|
|
|
if len(sys.argv) != 2:
|
2024-03-31 18:51:28 +02:00
|
|
|
print("Usage: boxes2inkscape TARGETPATH")
|
|
|
|
return
|
2022-11-30 15:57:58 +01:00
|
|
|
b = Boxes2INX()
|
|
|
|
b.writeAllINX(sys.argv[1])
|
2024-03-31 18:51:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|