1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
import json
import os
import re
import wx
from ..i18n import _
from ..utils import cache
from .dialogs import info_dialog
class PresetsPanel(wx.Panel):
"""A wx.Panel for loading, saving, and applying presets.
A preset is a named collection of settings. From the perspective of this
class, a preset is an opaque JSON-serializable object.
The PresetsPanel will handle interaction with the user and inform the
instantiator of events such as a preset being loaded. Presets starting
and ending with "__" will not be shown to the user. This allows for the
instantiator to manage hidden presets such as "__LAST__".
"""
HIDDEN_PRESET_RE = re.compile('^__.*__$')
def __init__(self, parent, *args, **kwargs):
"""Construct a PresetsPanel.
The parent is the parent window for this wx.Panel. The parent is
expected to implement the following methods:
def get_preset_data(self)
returns a JSON object representing the current state as a preset
def apply_preset_data(self, preset_data):
apply the preset data to the GUI, updating GUI elements as necessary
def get_preset_suite_name(self):
Return a string used in the presets filename, e.g. "lettering" -> "lettering_presets.json".
If not defined, "presets.json" will be used.
"""
kwargs.setdefault('style', wx.BORDER_NONE)
wx.Panel.__init__(self, parent, wx.ID_ANY, *args, **kwargs)
self.parent = parent
self.presets_box = wx.StaticBox(self, wx.ID_ANY, label=_("Presets"))
self.preset_chooser = wx.ComboBox(self, wx.ID_ANY)
self.update_preset_list()
self.preset_chooser.SetSelection(-1)
self.load_preset_button = wx.Button(self, wx.ID_ANY, _("Load"))
self.load_preset_button.Bind(wx.EVT_BUTTON, self.load_selected_preset)
self.add_preset_button = wx.Button(self, wx.ID_ANY, _("Add"))
self.add_preset_button.Bind(wx.EVT_BUTTON, self.add_preset)
self.overwrite_preset_button = wx.Button(self, wx.ID_ANY, _("Overwrite"))
self.overwrite_preset_button.Bind(wx.EVT_BUTTON, self.overwrite_preset)
self.delete_preset_button = wx.Button(self, wx.ID_ANY, _("Delete"))
self.delete_preset_button.Bind(wx.EVT_BUTTON, self.delete_preset)
presets_sizer = wx.StaticBoxSizer(self.presets_box, wx.HORIZONTAL)
presets_sizer.Add(self.preset_chooser, 1, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
presets_sizer.Add(self.load_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
presets_sizer.Add(self.add_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
presets_sizer.Add(self.overwrite_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
presets_sizer.Add(self.delete_preset_button, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
self.SetSizerAndFit(presets_sizer)
self.Layout()
@property
@cache
def suite_name(self):
try:
return self.parent.get_preset_suite_name() + "_presets"
except AttributeError:
return "presets"
@cache
def presets_path(self):
try:
import appdirs
config_path = appdirs.user_config_dir('inkstitch')
except ImportError:
config_path = os.path.expanduser('~/.inkstitch')
if not os.path.exists(config_path):
os.makedirs(config_path)
return os.path.join(config_path, '%s.json' % self.suite_name)
def _load_presets(self):
try:
with open(self.presets_path(), 'r') as presets:
presets = json.load(presets)
return presets
except IOError:
return {}
def _save_presets(self, presets):
with open(self.presets_path(), 'w') as presets_file:
json.dump(presets, presets_file)
def update_preset_list(self):
preset_names = self._load_presets().keys()
preset_names = [preset for preset in preset_names if not self.is_hidden(preset)]
self.preset_chooser.SetItems(sorted(preset_names))
def is_hidden(self, preset_name):
return self.HIDDEN_PRESET_RE.match(preset_name)
def get_preset_name(self):
preset_name = self.preset_chooser.GetValue().strip()
if preset_name:
return preset_name
else:
info_dialog(self, _("Please enter or select a preset name first."), caption=_('Preset'))
return
def check_and_load_preset(self, preset_name):
preset = self._load_presets().get(preset_name)
if not preset:
info_dialog(self, _('Preset "%s" not found.') % preset_name, caption=_('Preset'))
return preset
def store_preset(self, preset_name, data):
presets = self._load_presets()
presets[preset_name] = data
self._save_presets(presets)
self.update_preset_list()
def add_preset(self, event, overwrite=False):
preset_name = self.get_preset_name()
if not preset_name:
return
if not overwrite and preset_name in self._load_presets():
info_dialog(self, _('Preset "%s" already exists. Please use another name or press "Overwrite"') % preset_name, caption=_('Preset'))
self.store_preset(preset_name, self.parent.get_preset_data())
event.Skip()
def overwrite_preset(self, event):
self.add_preset(event, overwrite=True)
def load_preset(self, preset_name):
preset = self.check_and_load_preset(preset_name)
if not preset:
return
self.parent.apply_preset_data(preset)
def load_selected_preset(self, event):
preset_name = self.get_preset_name()
if not preset_name:
return
self.load_preset(preset_name)
event.Skip()
def delete_preset(self, event):
preset_name = self.get_preset_name()
if not preset_name:
return
preset = self.check_and_load_preset(preset_name)
if not preset:
return
presets = self._load_presets()
presets.pop(preset_name, None)
self._save_presets(presets)
self.update_preset_list()
self.preset_chooser.SetValue("")
event.Skip()
|