add preferences UI including cache settings

pull/1732/head
Lex Neva 2022-07-29 18:17:50 -04:00
rodzic a0834e2e7c
commit 98bc2e2ff9
12 zmienionych plików z 378 dodań i 31 usunięć

Wyświetl plik

@ -0,0 +1,216 @@
<template>
<v-card raised rounded="lg" class="preferences-card">
<v-card-title class="text-center justify-center py-6">
<h1 class="font-weight-bold text-h2 basil--text">
Ink/Stitch Settings
</h1>
</v-card-title>
<v-card-text>
<v-tabs v-model="tab" background-color="transparent" grow>
<v-tab key="this_svg_settings">
This SVG
</v-tab>
<v-tab key="global_settings">
Global
</v-tab>
</v-tabs>
<v-tabs-items v-model="tab">
<v-tab-item key="this_svg_settings">
<v-card flat>
<v-card-text>
<table>
<tr>
<td class="label">
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="collapse_len_mm" v-on="on" v-bind="attrs"><translate>Minimum jump stitch length</translate></label>
</template>
<label for="collapse_len_mm"><translate>Jump stitches smaller than this will be treated as normal stitches.</translate></label>
</v-tooltip>
</td>
<td class="preference">
<v-text-field hide-details id="collapse_len_mm" @change="updateSettings" v-model.number="this_svg_settings.collapse_len_mm" type="number"></v-text-field>
</td>
<td class="unit">
mm
</td>
<td class="button">
<v-btn small @click="set_default('collapse_len_mm')"><translate>set as default</translate></v-btn>
</td>
</tr>
<tr>
<td class="label">
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Minimum stitch length</translate></label>
</template>
<label for="min_stitch_len_mm"><translate>Drop stitches smaller than this value.</translate></label>
</v-tooltip>
</td>
<td class="preference">
<v-text-field hide-details id="min_stitch_len_mm" @change="updateSettings" v-model.number="this_svg_settings.min_stitch_len_mm" type="number"></v-text-field>
</td>
<td class="unit">
mm
</td>
<td class="button">
<v-btn small @click="set_default('min_stitch_len_mm')"><translate>set as default</translate></v-btn>
</td>
</tr>
</table>
</v-card-text>
</v-card>
</v-tab-item>
<v-tab-item key="global_settings">
<v-card flat>
<v-card-text>
<table>
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="default_collapse_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum jump stitch length</translate></label>
</template>
<label for="default_collapse_len_mm"><translate>Used for new SVGs.</translate></label>
</v-tooltip>
</td>
<td class="preference">
<v-text-field hide-details id="default_min_stitch_len_mm" @change="updateSettings" v-model.number="global_settings.default_collapse_len_mm" type="number"></v-text-field>
</td>
<td class="unit">
mm
</td>
</tr>
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="default_min_stitch_len_mm" v-on="on" v-bind="attrs"><translate>Default minimum stitch length</translate></label>
</template>
<label for="default_min_stitch_len_mm"><translate>Used for new SVGs.</translate></label>
</v-tooltip>
</td>
<td class="preference">
<v-text-field hide-details id="default_min_stitch_len_mm" @change="updateSettings" v-model.number="global_settings.default_min_stitch_len_mm" type="number"></v-text-field>
</td>
<td class="unit">
mm
</td>
</tr>
<tr>
<td>
<v-tooltip bottom>
<template v-slot:activator="{on, attrs}">
<label for="cache_size" v-on="on" v-bind="attrs"><translate>Stitch plan cache size</translate></label>
</template>
<label for="default_min_stitch_len_mm"><translate>The greater the number, the more stitch plans can be cached, speeding up stitch plan calculation. Default: 100</translate></label>
</v-tooltip>
</td>
<td class="preference">
<v-text-field hide-details id="cache_size" @change="updateSettings" v-model.number="global_settings.cache_size" type="number"></v-text-field>
</td>
<td class="unit">
MB
</td>
<td class="button">
<v-btn small @click="clearCache"><translate>clear stitch plan cache</translate></v-btn>
</td>
</tr>
</table>
</v-card-text>
</v-card>
</v-tab-item>
</v-tabs-items>
</v-card-text>
<v-card-actions>
<v-btn text color="primary" @click="close"><translate>done</translate></v-btn>
</v-card-actions>
</v-card>
</template>
<script>
const inkStitch = require("../../lib/api")
export default {
name: "Preferences",
data: function () {
return {
tab: "this_svg_settings",
this_svg_settings: {
collapse_len_mm: null,
min_stitch_len_mm: null,
},
global_settings: {
default_min_stitch_len_mm: null,
default_collapse_len_mm: null,
cache_size: null
}
}
},
created: function () {
inkStitch.get("preferences/").then(response => {
Object.assign(this.this_svg_settings, response.data.this_svg_settings)
Object.assign(this.global_settings, response.data.global_settings)
})
},
methods: {
setDefault(preference_name) {
console.log(`set default: ${preference_name}`)
this.global_settings[`default_${preference_name}`] = this.this_svg_settings[preference_name]
this.updateSettings()
},
updateSettings() {
console.log(this.this_svg_settings)
console.log(this.global_settings)
inkStitch.post("preferences/", {
this_svg_settings: this.this_svg_settings,
global_settings: this.global_settings
}).then(response => {
console.log(response)
})
},
clearCache() {
inkStitch.post("preferences/clear_cache").then(response => {
console.log(response)
})
},
close() {
window.close()
}
}
}
</script>
<style scoped>
.preferences-card {
margin-left: 20%;
margin-right: 20%;
margin-top: 5%;
}
td.label {
vertical-align: bottom;
}
td.preference {
padding-right: 4px;
padding-left: 16px;
max-width: 100px;
}
td.preference::v-deep input {
text-align: right;
}
td.unit {
vertical-align: bottom;
}
td.button {
vertical-align: bottom;
padding-left: 12px;
}
</style>

Wyświetl plik

@ -23,6 +23,11 @@ export default new Router({
name: 'install',
component: require('@/components/InstallPalettes').default
},
{
path: '/preferences',
name: 'preferences',
component: require('@/components/Preferences').default
},
{
path: '*',
redirect: '/'

Wyświetl plik

@ -0,0 +1,41 @@
# Authors: see git history
#
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from flask import Blueprint, g, jsonify, request
from ..utils.cache import get_stitch_plan_cache
from ..utils.settings import global_settings
preferences = Blueprint('preferences', __name__)
@preferences.route('/', methods=["POST"])
def update_preferences():
metadata = g.extension.get_inkstitch_metadata()
metadata.update(request.json['this_svg_settings'])
global_settings.update(request.json['global_settings'])
# cache size may have changed
stitch_plan_cache = get_stitch_plan_cache()
stitch_plan_cache.size_limit = global_settings['cache_size'] * 1024 * 1024
stitch_plan_cache.cull()
return jsonify({"status": "success"})
@preferences.route('/', methods=["GET"])
def get_preferences():
metadata = g.extension.get_inkstitch_metadata()
return jsonify({"status": "success",
"this_svg_settings": metadata,
"global_settings": global_settings
})
@preferences.route('/clear_cache', methods=["POST"])
def clear_cache():
stitch_plan_cache = get_stitch_plan_cache()
stitch_plan_cache.clear(retry=True)
return jsonify({"status": "success"})

Wyświetl plik

@ -18,6 +18,7 @@ from ..utils.json import InkStitchJSONEncoder
from .install import install
from .simulator import simulator
from .stitch_plan import stitch_plan
from .preferences import preferences
class APIServer(Thread):
@ -45,6 +46,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.register_blueprint(preferences, url_prefix="/preferences")
@self.app.before_request
def store_extension():

Wyświetl plik

@ -17,7 +17,7 @@ from .cut_satin import CutSatin
from .cutwork_segmentation import CutworkSegmentation
from .density_map import DensityMap
from .duplicate_params import DuplicateParams
from .embroider_settings import EmbroiderSettings
from .preferences import Preferences
from .fill_to_stroke import FillToStroke
from .flip import Flip
from .generate_palette import GeneratePalette
@ -96,5 +96,5 @@ __all__ = extensions = [StitchPlanPreview,
Simulator,
Reorder,
DuplicateParams,
EmbroiderSettings,
Preferences,
CutworkSegmentation]

Wyświetl plik

@ -23,6 +23,7 @@ from ..svg import generate_unique_id
from ..svg.tags import (CONNECTOR_TYPE, EMBROIDERABLE_TAGS, INKSCAPE_GROUPMODE,
NOT_EMBROIDERABLE_TAGS, SVG_CLIPPATH_TAG, SVG_DEFS_TAG,
SVG_GROUP_TAG, SVG_MASK_TAG)
from ..utils.settings import DEFAULT_METADATA, global_settings
SVG_METADATA_TAG = inkex.addNS("metadata", "svg")
@ -52,9 +53,14 @@ class InkStitchMetadata(MutableMapping):
"""
def __init__(self, document):
super().__init__()
self.document = document
self.metadata = document.metadata
for setting in DEFAULT_METADATA:
if self[setting] is None:
self[setting] = global_settings[f'default_{setting}']
# Because this class inherints from MutableMapping, all we have to do is
# implement these five methods and we get a full dict-like interface.
@ -96,6 +102,9 @@ class InkStitchMetadata(MutableMapping):
return i + 1
def __json__(self):
return dict(self)
class InkstitchExtension(inkex.Effect):
"""Base class for Inkstitch extensions. Not intended for direct use."""

Wyświetl plik

@ -4,12 +4,15 @@
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from .base import InkstitchExtension
from ..api import APIServer
from ..gui import open_url
class EmbroiderSettings(InkstitchExtension):
class Preferences(InkstitchExtension):
'''
This saves embroider settings into the metadata of the file
'''
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self, *args, **kwargs)
self.arg_parser.add_argument("-c", "--collapse_len_mm",
@ -22,6 +25,13 @@ class EmbroiderSettings(InkstitchExtension):
help="minimum stitch length (mm)")
def effect(self):
self.metadata = self.get_inkstitch_metadata()
self.metadata['collapse_len_mm'] = self.options.collapse_length_mm
self.metadata['min_stitch_len_mm'] = self.options.min_stitch_len_mm
api_server = APIServer(self)
port = api_server.start_server()
electron = open_url("/preferences?port=%d" % port)
electron.wait()
api_server.stop()
api_server.join()
# self.metadata = self.get_inkstitch_metadata()
# self.metadata['collapse_len_mm'] = self.options.collapse_length_mm
# self.metadata['min_stitch_len_mm'] = self.options.min_stitch_len_mm

Wyświetl plik

@ -10,6 +10,8 @@ import pickle
import appdirs
import diskcache
from lib.utils.settings import global_settings
try:
from functools import lru_cache
except ImportError:
@ -29,7 +31,9 @@ def get_stitch_plan_cache():
if __stitch_plan_cache is None:
cache_dir = os.path.join(appdirs.user_config_dir('inkstitch'), 'cache', 'stitch_plan')
__stitch_plan_cache = diskcache.Cache(cache_dir, size=1024 * 1024 * 100)
size_limit = global_settings['cache_size'] * 1024 * 1024
__stitch_plan_cache = diskcache.Cache(cache_dir, size=size_limit)
__stitch_plan_cache.size_limit = size_limit
atexit.register(__stitch_plan_cache.close)
return __stitch_plan_cache

Wyświetl plik

@ -7,6 +7,8 @@ import sys
import os
from os.path import dirname, realpath
import appdirs
def get_bundled_dir(name):
if getattr(sys, 'frozen', None) is not None:
@ -26,3 +28,12 @@ def get_resource_dir(name):
return realpath(os.path.join(sys._MEIPASS, name))
else:
return realpath(os.path.join(dirname(realpath(__file__)), '..', '..', name))
def get_user_dir(name=None):
path = appdirs.user_config_dir("inkstitch")
if name is not None:
path = os.path.join(path, name)
return path

Wyświetl plik

@ -0,0 +1,58 @@
from collections.abc import MutableMapping
import json
import os
from .paths import get_user_dir
# These settings are the defaults for SVG metadata settings of the same name in
# lib.extensions.base.InkstitchMetadata
DEFAULT_METADATA = {
"min_stitch_len_mm": 0,
"collapse_len_mm": 3,
}
DEFAULT_SETTINGS = {
"cache_size": 100
}
class GlobalSettings(MutableMapping):
def __init__(self):
super().__init__()
self.__settings_file = os.path.join(get_user_dir(), "settings.json")
self.__settings = {}
for name, value in DEFAULT_METADATA.items():
self.__settings[f"default_{name}"] = value
self.__settings.update(DEFAULT_SETTINGS)
try:
with open(self.__settings_file, 'r') as settings_file:
self.__settings.update(json.load(settings_file))
except (OSError, json.JSONDecodeError, ValueError):
pass
def __setitem__(self, item, value):
self.__settings[item] = value
with open(self.__settings_file, 'w') as settings_file:
json.dump(self.__settings, settings_file)
def __getitem__(self, item):
return self.__settings[item]
def __delitem__(self, item):
del self.__settings[item]
def __iter__(self):
return iter(self.__settings)
def __len__(self):
return len(self.__settings)
def __json__(self):
return self.__settings
global_settings = GlobalSettings()

Wyświetl plik

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Preferences</name>
<id>org.inkstitch.embroider_settings</id>
<param name="extension" type="string" gui-hidden="true">embroider_settings</param>
<effect needs-live-preview="false">
<object-type>all</object-type>
<effects-menu>
<submenu name="Ink/Stitch" translatable="no" />
</effects-menu>
</effect>
<param name="output_settings" type="description" appearance="header">
Output Settings
</param>
<param name="collapse_len_mm" type="float" precision="1" min="0" max="10"
gui-text="Collapse length (mm)"
gui-description="Jump stitches smaller than this will be treated as normal stitches.">3</param>
<param name="min_stitch_len_mm" type="float" precision="1" min="0" max="10"
gui-text="Minimal stitch length (mm)"
gui-description="Drop stitches smaller than this value.">0.1</param>
<script>
{{ command_tag | safe }}
</script>
</inkscape-extension>

Wyświetl plik

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension translationdomain="inkstitch" xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Preferences</name>
<id>org.inkstitch.preferences</id>
<param name="extension" type="string" gui-hidden="true">preferences</param>
<effect implements-custom-gui="true">
<object-type>all</object-type>
<effects-menu>
<submenu name="Ink/Stitch" translatable="no"/>
</effects-menu>
</effect>
<script>
{{ command_tag | safe }}
</script>
</inkscape-extension>