dots/config/inkscape/extensions/org.inkscape.extension.30306/scientific_inkscape/gallery_viewer.py
2026-06-05 13:11:08 +02:00

132 lines
4.9 KiB
Python

#!/usr/bin/env python
# coding=utf-8
#
# Copyright (c) 2023 David Burghoff <burghoff@utexas.edu>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
DEBUGGING = False
dispprofile = False
import dhelpers as dh
import inkex
import os, sys, copy, subprocess, platform
# Convenience functions
def joinmod(dirc, f):
return os.path.join(os.path.abspath(dirc), f)
# Runs a Python script using a Python binary in a working directory
# It detaches from Inkscape, allowing it to continue running after the extension has finished
def run_python(python_bin, python_script, python_wd, interminal=False):
if platform.system() == "Windows":
DEVNULL = "nul"
else:
DEVNULL = "/dev/null"
# DEVNULL = dh.si_tmp(filename="si_gv_output.txt")
# dh.idebug(DEVNULL)
with open(DEVNULL, "w") as devnull:
subprocess.Popen([python_bin, python_script], stdout=devnull, stderr=devnull)
class GalleryViewer(inkex.EffectExtension):
def add_arguments(self, pars):
pars.add_argument("--tab", help="The selected UI-tab when OK was pressed")
pars.add_argument("--portnum", help="Port number for server")
def effect(self):
if dispprofile:
import cProfile, pstats, io
from pstats import SortKey
pr = cProfile.Profile()
pr.enable()
# Make an options copy we can pass to the external program
optcopy = copy.copy(self.options)
delattr(optcopy, "output")
delattr(optcopy, "input_file")
bfn = inkex.inkscape_system_info.binary_location
bloc, bnm = os.path.split(bfn)
pyloc, pybin = os.path.split(sys.executable)
aepy = os.path.join(dh.si_dir, "gallery_viewer_script.py")
# Pass settings using a config file. Include the current path so Inkex can be called if needed.
import pickle
optcopy.inkscape_bfn = bfn
optcopy.syspath = sys.path
optcopy.inshell = False
optcopy.logfile = dh.shared_temp(filename="si_gv_output.txt")
import tempfile
settings = os.path.join(
os.path.abspath(tempfile.gettempdir()), "si_gv_settings.p"
)
with open(settings, "wb") as f:
pickle.dump(optcopy, f)
import warnings
warnings.simplefilter("ignore", ResourceWarning) # prevent process open warning
run_python(pybin, aepy, pyloc, optcopy.inshell)
# Make a batch file that can run the Gallery Viewer directly on Windows
# Hardcodes the pickled settings
if platform.system() == "Windows":
python_cwd = os.getcwd()
pickled_file_path = settings
with open(pickled_file_path, "rb") as f:
pickled_data = f.read()
import base64
pickled_data_base64 = base64.b64encode(pickled_data).decode('utf-8')
current_script_dir = os.path.dirname(os.path.abspath(__file__))
batch_file_path = os.path.join(current_script_dir, "Gallery Viewer.bat")
batch_content = '''@echo off
cd "{python_cwd}"
SET PYBIN="{pybin}"
SET AEPY="{aepy}"
SET PICKLED_FILE="{pickled_file}"
REM Use PowerShell to decode the base64 string and write the binary pickled data
powershell -Command "[System.IO.File]::WriteAllBytes('%PICKLED_FILE%', [Convert]::FromBase64String('{pickled_data_base64}'))"
REM Start the Python script in a new process without opening a new window
start "" %PYBIN% %AEPY%
'''.format(
python_cwd=python_cwd, # Add the current working directory
pybin=sys.executable,
aepy=aepy,
pickled_file=pickled_file_path.replace('\\', '\\\\'),
pickled_data_base64=pickled_data_base64
)
with open(batch_file_path, "w") as batch_file:
batch_file.write(batch_content)
if dispprofile:
pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
dh.debug(s.getvalue())
if __name__ == "__main__":
dh.Run_SI_Extension(GalleryViewer(), "Gallery Viewer")