diff --git a/lib/extensions/print_pdf.py b/lib/extensions/print_pdf.py index 4913a32a0..e736b05bd 100644 --- a/lib/extensions/print_pdf.py +++ b/lib/extensions/print_pdf.py @@ -1,27 +1,27 @@ -import sys -import os -from threading import Thread -import socket -import errno -import time -import logging from copy import deepcopy -import wx -import appdirs +from datetime import date +import errno import json +import logging +import os +import socket +import sys +from threading import Thread +import time + +import appdirs +from flask import Flask, request, Response, send_from_directory, jsonify import inkex from jinja2 import Environment, FileSystemLoader, select_autoescape -from datetime import date -from flask import Flask, request, Response, send_from_directory, jsonify -import webbrowser import requests -from .base import InkstitchExtension +from ..gui import open_url from ..i18n import _, translation as inkstitch_translation +from ..stitch_plan import patches_to_stitch_plan from ..svg import render_stitch_plan from ..svg.tags import INKSCAPE_GROUPMODE -from ..stitch_plan import patches_to_stitch_plan from ..threads import ThreadCatalog +from .base import InkstitchExtension def datetimeformat(value, format='%Y/%m/%d'): @@ -51,42 +51,6 @@ def save_defaults(defaults): json.dump(defaults, defaults_file) -def open_url(url): - # Avoid spurious output from xdg-open. Any output on stdout will crash - # inkscape. - null = open(os.devnull, 'w') - old_stdout = os.dup(sys.stdout.fileno()) - os.dup2(null.fileno(), sys.stdout.fileno()) - - if getattr(sys, 'frozen', False): - - # PyInstaller sets LD_LIBRARY_PATH. We need to temporarily clear it - # to avoid confusing xdg-open, which webbrowser will run. - - # The following code is adapted from PyInstaller's documentation - # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html - - old_environ = dict(os.environ) # make a copy of the environment - lp_key = 'LD_LIBRARY_PATH' # for Linux and *BSD. - lp_orig = os.environ.get(lp_key + '_ORIG') # pyinstaller >= 20160820 has this - if lp_orig is not None: - os.environ[lp_key] = lp_orig # restore the original, unmodified value - else: - os.environ.pop(lp_key, None) # last resort: remove the env var - - webbrowser.open(url) - - # restore the old environ - os.environ.clear() - os.environ.update(old_environ) - else: - webbrowser.open(url) - - # restore file descriptors - os.dup2(old_stdout, sys.stdout.fileno()) - os.close(old_stdout) - - class PrintPreviewServer(Thread): def __init__(self, *args, **kwargs): self.html = kwargs.pop('html') @@ -96,7 +60,6 @@ class PrintPreviewServer(Thread): self.realistic_color_block_svgs = kwargs.pop('realistic_color_block_svgs') Thread.__init__(self, *args, **kwargs) self.daemon = True - self.last_request_time = None self.shutting_down = False self.__setup_app() @@ -111,16 +74,6 @@ class PrintPreviewServer(Thread): self.__set_resources_path() self.app = Flask(__name__) - @self.app.before_request - def request_started(): - self.last_request_time = time.time() - - @self.app.before_first_request - def start_watcher(): - self.watcher_thread = Thread(target=self.watch) - self.watcher_thread.daemon = True - self.watcher_thread.start() - @self.app.route('/') def index(): return self.html @@ -129,17 +82,12 @@ class PrintPreviewServer(Thread): def shutdown(): self.shutting_down = True request.environ.get('werkzeug.server.shutdown')() - return _('Closing...') + '

' + _('It is safe to close this window now.') + return "shutting down" @self.app.route('/resources/', methods=['GET']) def resources(resource): return send_from_directory(self.resources_path, resource, cache_timeout=1) - @self.app.route('/ping') - def ping(): - # Javascript is letting us know it's still there. This resets self.last_request_time. - return "pong" - @self.app.route('/printing/start') def printing_start(): # temporarily turn off the watcher while the print dialog is up, @@ -215,21 +163,6 @@ class PrintPreviewServer(Thread): # the context of a flask request, so we'll just make one requests.post("http://%s:%s/shutdown" % (self.host, self.port)) - def watch(self): - try: - while True: - time.sleep(1) - if self.shutting_down: - break - - if self.last_request_time is not None and \ - (time.time() - self.last_request_time) > 3: - self.stop() - break - except BaseException: - # seems like sometimes this thread blows up during shutdown - pass - def disable_logging(self): logging.getLogger('werkzeug').setLevel(logging.ERROR) @@ -252,42 +185,6 @@ class PrintPreviewServer(Thread): break -class PrintInfoFrame(wx.Frame): - def __init__(self, *args, **kwargs): - self.print_server = kwargs.pop("print_server") - wx.Frame.__init__(self, *args, **kwargs) - - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - - message = _("A print preview has been opened in your web browser. " - "This window will stay open in order to communicate with the JavaScript code running in your browser.\n\n" - "This window will close after you close the print preview in your browser, or you can close it manually if necessary.") - text = wx.StaticText(panel, label=message) - font = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL) - text.SetFont(font) - sizer.Add(text, proportion=1, flag=wx.ALL | wx.EXPAND, border=20) - - stop_button = wx.Button(panel, id=wx.ID_CLOSE) - stop_button.Bind(wx.EVT_BUTTON, self.close_button_clicked) - sizer.Add(stop_button, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=10) - - panel.SetSizer(sizer) - panel.Layout() - - self.timer = wx.PyTimer(self.__watcher) - self.timer.Start(250) - - def close_button_clicked(self, event): - self.print_server.stop() - - def __watcher(self): - if not self.print_server.is_alive(): - self.timer.Stop() - self.timer = None - self.Destroy() - - class Print(InkstitchExtension): def build_environment(self): if getattr(sys, 'frozen', False): @@ -409,11 +306,7 @@ class Print(InkstitchExtension): realistic_color_block_svgs=realistic_color_block_svgs ) print_server.start() - - time.sleep(1) - open_url("http://%s:%s/" % (print_server.host, print_server.port)) - - app = wx.App() - info_frame = PrintInfoFrame(None, title=_("Ink/Stitch Print"), size=(450, 350), print_server=print_server) - info_frame.Show() - app.MainLoop() + browser_window = open_url("http://%s:%s/" % (print_server.host, print_server.port)) + browser_window.wait() + print_server.stop() + print_server.join() diff --git a/lib/gui/__init__.py b/lib/gui/__init__.py index 060c3d938..5e249a55c 100644 --- a/lib/gui/__init__.py +++ b/lib/gui/__init__.py @@ -1,3 +1,4 @@ from dialogs import info_dialog, confirm_dialog +from electron import open_url from presets import PresetsPanel from simulator import EmbroiderySimulator, SimulatorPreview, show_simulator diff --git a/lib/gui/electron.py b/lib/gui/electron.py new file mode 100644 index 000000000..cad86a16b --- /dev/null +++ b/lib/gui/electron.py @@ -0,0 +1,16 @@ +import os +import subprocess + +from ..utils import get_bundled_dir + + +app_process = None + + +def open_url(url): + global app + + electron_path = os.path.join(get_bundled_dir("electron"), "out", "inkstitch-linux-x64", "inkstitch-gui") + app_process = subprocess.Popen([electron_path, url]) + + return app_process diff --git a/print/resources/inkstitch.js b/print/resources/inkstitch.js index 86bc213e7..c58aed8a0 100644 --- a/print/resources/inkstitch.js +++ b/print/resources/inkstitch.js @@ -11,12 +11,6 @@ var realistic_rendering = {}; var realistic_cache = {}; var normal_rendering = {}; -function ping() { - $.get("/ping") - .done(function() { setTimeout(ping, 1000) }) - .fail(function() { $('#errors').attr('class', 'show') }); -} - //function to chunk opd view into pieces // source: https://stackoverflow.com/questions/3366529/wrap-every-3-divs-in-a-div $.fn.chunk = function(size) { @@ -199,7 +193,6 @@ function setSVGTransform(figure, transform) { } $(function() { - setTimeout(ping, 1000); /* SCALING AND MOVING SVG */ /* Mousewheel scaling */ @@ -369,22 +362,7 @@ $(function() { /* Settings Bar */ $('button.close').click(function() { - $.post('/shutdown', {}) - .always(function(data) { - window.close(); - - /* Chrome and Firefox both have a rule: scripts can only close windows - * that they opened. Chrome seems to have an exception for windows that - * were opened by an outside program, so the above works fine. Firefox - * steadfastly refuses to allow us to close the window, so we'll tell - * the user (in their language) that they can close it. - */ - setTimeout(function() { - document.open(); - document.write("" + data + ""); - document.close(); - }, 1000); - }); + window.close(); }); $('button.print').click(function() { diff --git a/print/templates/index.html b/print/templates/index.html index d0ab848f3..375fdc778 100644 --- a/print/templates/index.html +++ b/print/templates/index.html @@ -2,6 +2,8 @@ Ink/Stitch Print Preview + +