diff --git a/electron/src/renderer/components/InstallPalettes.vue b/electron/src/renderer/components/InstallPalettes.vue new file mode 100644 index 000000000..73fd28653 --- /dev/null +++ b/electron/src/renderer/components/InstallPalettes.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/electron/src/renderer/main.js b/electron/src/renderer/main.js index 3502ed6a7..c5f399486 100644 --- a/electron/src/renderer/main.js +++ b/electron/src/renderer/main.js @@ -20,6 +20,7 @@ import { faHorse, faInfo, faMinus, + faPalette, faPause, faPlay, faPlus, @@ -52,6 +53,7 @@ library.add( faHorse, faInfo, faMinus, + faPalette, faPause, faPlay, faPlus, diff --git a/electron/src/renderer/router/index.js b/electron/src/renderer/router/index.js index 3a27c4bc1..63e2f4150 100644 --- a/electron/src/renderer/router/index.js +++ b/electron/src/renderer/router/index.js @@ -5,14 +5,19 @@ Vue.use(Router) export default new Router({ routes: [ - { - path: '/simulator', - name: 'simulator', - component: require('@/components/Simulator').default - }, - { - path: '*', - redirect: '/' - } + { + path: '/simulator', + name: 'simulator', + component: require('@/components/Simulator').default + }, + { + path: '/install', + name: 'install', + component: require('@/components/InstallPalettes').default + }, + { + path: '*', + redirect: '/' + } ] }) diff --git a/lib/api/install.py b/lib/api/install.py new file mode 100644 index 000000000..f379f1421 --- /dev/null +++ b/lib/api/install.py @@ -0,0 +1,42 @@ +import os +import sys +from glob import glob + +from flask import Blueprint, request + +from ..utils import get_bundled_dir, guess_inkscape_config_path + +install = Blueprint('install', __name__) + + +@install.route('/palettes') +def palettes(): + base_path = request.json.get('path') or guess_inkscape_config_path() + path = os.path.join(base_path, 'palettes') + src_dir = get_bundled_dir('palettes') + copy_files(glob(os.path.join(src_dir, "*")), path) + + +if sys.platform == "win32": + # If we try to just use shutil.copy it says the operation requires elevation. + def copy_files(files, dest): + import winutils + + if not os.path.exists(dest): + os.makedirs(dest) + + winutils.copy(files, dest) +else: + def copy_files(files, dest): + import shutil + + if not os.path.exists(dest): + os.makedirs(dest) + + for palette_file in files: + shutil.copy(palette_file, dest) + + +@install.route('/default-path') +def default_path(): + return guess_inkscape_config_path() diff --git a/lib/api/server.py b/lib/api/server.py index c57a1785e..bdfa45731 100644 --- a/lib/api/server.py +++ b/lib/api/server.py @@ -1,15 +1,16 @@ import errno import logging import socket -from threading import Thread import time +from threading import Thread -from flask import Flask, request, g import requests +from flask import Flask, g, request -from ..utils.json import InkStitchJSONEncoder +from .install import install from .simulator import simulator from .stitch_plan import stitch_plan +from ..utils.json import InkStitchJSONEncoder class APIServer(Thread): @@ -31,6 +32,7 @@ class APIServer(Thread): self.app.register_blueprint(simulator, url_prefix="/simulator") self.app.register_blueprint(stitch_plan, url_prefix="/stitch_plan") + self.app.register_blueprint(install, url_prefix="/install") @self.app.before_request def store_extension(): diff --git a/lib/extensions/install.py b/lib/extensions/install.py index f9ffe9585..9756fb835 100644 --- a/lib/extensions/install.py +++ b/lib/extensions/install.py @@ -1,116 +1,16 @@ -# -*- coding: UTF-8 -*- - -import sys -import traceback -import os -from glob import glob -import wx -import inkex - -from ..utils import guess_inkscape_config_path, get_bundled_dir -from ..i18n import _ +from .base import InkstitchExtension +from ..api import APIServer +from ..gui import open_url -class InstallerFrame(wx.Frame): - def __init__(self, *args, **kwargs): - wx.Frame.__init__(self, *args, **kwargs) - - self.path = guess_inkscape_config_path() - - panel = wx.Panel(self) - sizer = wx.BoxSizer(wx.VERTICAL) - - text_sizer = wx.BoxSizer(wx.HORIZONTAL) - - text = (_('Ink/Stitch can install files ("add-ons") that make it easier to use Inkscape to create machine embroidery designs. ' - 'These add-ons will be installed:') + - u"\n\n • " + _("thread manufacturer color palettes") + - u"\n • " + _("Ink/Stitch visual commands (Object -> Symbols...)")) - - static_text = wx.StaticText(panel, label=text) - font = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) - static_text.SetFont(font) - text_sizer.Add(static_text, proportion=0, flag=wx.ALL | wx.EXPAND, border=10) - sizer.Add(text_sizer, proportion=3, flag=wx.ALL | wx.EXPAND, border=0) - - buttons_sizer = wx.BoxSizer(wx.HORIZONTAL) - install_button = wx.Button(panel, wx.ID_ANY, _("Install")) - install_button.SetBitmap(wx.ArtProvider.GetBitmap(wx.ART_TICK_MARK)) - buttons_sizer.Add(install_button, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5) - cancel_button = wx.Button(panel, wx.ID_CANCEL, _("Cancel")) - buttons_sizer.Add(cancel_button, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5) - sizer.Add(buttons_sizer, proportion=1, flag=wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM) - - panel.SetSizer(sizer) - panel.Layout() - - cancel_button.Bind(wx.EVT_BUTTON, self.cancel_button_clicked) - install_button.Bind(wx.EVT_BUTTON, self.install_button_clicked) - - def cancel_button_clicked(self, event): - self.Destroy() - - def chooser_button_clicked(self, event): - dialog = wx.DirDialog(self, _("Choose Inkscape directory")) - if dialog.ShowModal() != wx.ID_CANCEL: - self.path_input.SetValue(dialog.GetPath()) - - def install_button_clicked(self, event): - if sys.platform == "win32": - # On windows, the default icon shows as a broken image. No idea - # why. Workaround: don't show an icon. - style = wx.ICON_NONE - else: - style = 0 - - try: - self.install_addons('palettes') - self.install_addons('symbols') - except Exception: - wx.MessageDialog(self, - _('Inkscape add-on installation failed') + ': \n' + traceback.format_exc(), - _('Installation Failed'), - wx.OK | style).ShowModal() - else: - wx.MessageDialog(self, - _('Inkscape add-on files have been installed. Please restart Inkscape to load the new add-ons.'), - _('Installation Completed'), - wx.OK | style).ShowModal() - - self.Destroy() - - def install_addons(self, type): - path = os.path.join(self.path, type) - src_dir = get_bundled_dir(type) - self.copy_files(glob(os.path.join(src_dir, "*")), path) - - if (sys.platform == "win32"): - # If we try to just use shutil.copy it says the operation requires elevation. - def copy_files(self, files, dest): - import winutils - - if not os.path.exists(dest): - os.makedirs(dest) - - winutils.copy(files, dest) - else: - def copy_files(self, files, dest): - import shutil - - if not os.path.exists(dest): - os.makedirs(dest) - - for palette_file in files: - shutil.copy(palette_file, dest) - - -class Install(inkex.Effect): - @classmethod - def name(cls): - return "install" +class Install(InkstitchExtension): + def __init__(self): + InkstitchExtension.__init__(self) def effect(self): - app = wx.App() - installer_frame = InstallerFrame(None, title=_("Ink/Stitch Add-ons Installer"), size=(550, 250)) - installer_frame.Show() - app.MainLoop() + api_server = APIServer(self) + port = api_server.start_server() + electron = open_url("/install?port=%d" % port) + electron.wait() + api_server.stop() + api_server.join()