-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvia_resource_editor.py
241 lines (204 loc) · 10.1 KB
/
via_resource_editor.py
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
from PySide6.QtWidgets import QDialog, QInputDialog, QMessageBox, QFileDialog, QMenuBar, QMenu, QWidget
from PySide6.QtCore import Slot, Qt
from PySide6.QtGui import QUndoStack, QKeySequence, QUndoCommand
class ViaResourceEditor(QDialog):
def __init__(self):
super().__init__()
self.dirty_resource = False
self.active_idx = 0
self.resource_slugs = {}
self.resource_set_slugs = {}
self.resource_titles = {}
self.resource_set_titles = {}
self.sorted_flag = False
# Base class must initialize self.set as ViaResourceSet derived class
@Slot()
def on_saveResourceSet_clicked(self):
name = self.get_resource_set_name(self.set.data['title'])
if name == '':
return
description = self.get_description(self.set.data['description'])
self.set.save_set(name, description)
self.update_resource_sets()
self.selectResourceSet.setCurrentIndex(self.selectResourceSet.findText(self.resource_set_titles[name]))
self.update_resource_ui()
@Slot()
def on_selectResourceSet_activated(self):
if not self.set.is_clean():
if self.prompt_to_discard():
self.set.restore()
else:
self.selectResourceSet.setCurrentIndex(self.selectResourceSet.findText(self.resource_set_slugs[self.set_slug]))
self.update_resource_ui()
return
slug = self.resource_set_titles[self.selectResourceSet.currentText()]
if slug in self.resource_set_slugs:
self.set_slug = slug
self.set.load_set(slug)
self.setDescription.setText(self.set.data['description'])
self.switch_slot(self.active_idx)
@Slot()
def on_saveForRack_clicked(self):
bin_write_dir = QFileDialog.getExistingDirectory(self, "Select save directory")
if bin_write_dir != '':
filename = self.set.pack_binary(bin_write_dir + '/', self.set.data['title'])
self.update_resource_ui()
QMessageBox.information(self, "File saved successfully", "File saved to: " + filename)
else:
QMessageBox.warning(self, "No file saved!", "File not saved, no valid directory selected")
# Load/save resource
def update_set_slug(self, set_slug):
self.set_slug = set_slug
self.update_resource_sets()
self.on_selectResourceSet_activated()
def handle_select_resource(self):
resource_title = self.selectResource.currentText()
if resource_title in self.resource_titles:
self.resource_slug = self.resource_titles[resource_title]
self.set.replace_resource(self.resource_slug, self.active_idx)
self.switch_slot(self.active_idx)
def handle_save_resource(self):
name = self.get_resource_name(self.resource_slugs[self.resource_slug])
if name == '':
return
default_description = ''
if 'description' in self.set.resources[self.active_idx].data:
default_description = self.set.resources[self.active_idx].data['description']
description = self.get_description(default_description)
self.set.save_resource(name, self.active_idx, description)
self.update_resources()
self.update_resource_selection(name)
self.update_resource_ui()
# Save/load helpers
def update_resource_selection(self, name):
self.selectResource.setCurrentIndex(self.selectResource.findText(name))
def update_resource_sets(self):
self.selectResourceSet.clear()
self.resource_set_slugs, self.resource_set_titles = self.set.get_available_resource_sets()
resource_titles = []
for resource in self.resource_set_slugs:
resource_titles.append(self.resource_set_slugs[resource])
resource_titles = sorted(resource_titles, reverse=True)
for resource_title in resource_titles:
self.selectResourceSet.insertItem(-1, resource_title)
self.selectResourceSet.setCurrentIndex(self.selectResourceSet.findText(self.resource_set_slugs[self.set_slug]))
def update_resources(self):
self.selectResource.clear()
self.resource_slugs, self.resource_titles = self.set.get_available_resources()
resource_titles = []
for resource in self.resource_slugs:
resource_titles.append(self.resource_slugs[resource])
resource_titles = sorted(resource_titles, reverse=True)
for resource_title in resource_titles:
self.selectResource.insertItem(-1, resource_title)
def switch_slot(self, slot_num):
if self.dirty_resource:
if self.prompt_to_discard():
self.dirty_resource = False
self.resource_undo_stack.clear()
self.set.restore_resource(self.active_idx)
else:
# Throw him in the dungeon
eval('self.slot%d' % (self.active_idx+1)).setChecked(True)
self.update_resource_ui()
return
self.active_idx = slot_num
self.resource_slug = self.set.data['slug_list'][slot_num]
self.update_resource_selection(self.resource_slugs[self.resource_slug])
# Throw him in the dungeon
eval('self.slot%d' % (self.active_idx+1)).setChecked(True)
self.update_resource_ui()
def prompt_to_discard(self):
if QMessageBox.question(self, "", 'Unsaved changes will be lost, continue?') == QMessageBox.Yes:
return True
else:
return False
# Make sure this does not collide with existing resource in a case insensitive fashion
def get_resource_name(self, default=''):
title = QInputDialog.getText(self, 'Save Resource', 'Enter resource name:', text=default)[0]
remote_titles = []
remote_slugs = []
for slug in self.remote_resources['resources']:
remote_titles.append(self.resource_slugs[slug].lower())
remote_slugs.append(slug.lower())
while title.lower() in remote_titles or title.lower() in remote_slugs:
filename = QInputDialog.getText(self, 'Save Resource', 'Reserved name, enter new name:', text=default)[0]
if title in self.resource_slugs:
if QMessageBox.question(self, 'Overwrite?', 'Name in use, overwrite?') == QMessageBox.No:
return
return title
# Make sure this does not collide with existing resource set in a case insensitive fashion
def get_resource_set_name(self, default=''):
title = QInputDialog.getText(self, 'Save Resource Set', 'Enter resource set name:', text=default)[0]
remote_titles = []
remote_slugs = []
for slug in self.remote_resources['resources']:
remote_titles.append(self.resource_slugs[slug].lower())
remote_slugs.append(slug.lower())
while title.lower() in remote_titles or title.lower() in remote_slugs:
title = QInputDialog.getText(self, 'Save Resource Set', 'Reserved name, enter new name:', text=default)[0]
if title in self.resource_set_slugs:
if QMessageBox.question(self, 'Overwrite?', 'Name in use, overwrite?') == QMessageBox.No:
return
return title
def get_description(self, default=''):
return QInputDialog.getText(self, 'Enter Description', 'Enter a description if you want to :)', text=default)[0]
def keyPressEvent(self, evt):
if evt.key() == Qt.Key_Enter or evt.key() == Qt.Key_Return:
return
super().keyPressEvent(evt)
@Slot()
def handle_clean_changed(self):
if not self.resource_undo_stack.isClean():
self.saveResource.setEnabled(True)
self.dirty_resource = True
else:
self.saveResource.setEnabled(True)
self.dirty_resource = False
def handle_set_clean_changed(self):
if not self.resource_set_undo_stack.isClean():
self.saveResourceSet.setEnabled(True)
self.dirty_resource_set = True
else:
self.saveResourceSet.setEnabled(True)
self.dirty_resource_set = False
def create_undo_stack(self):
self.resource_undo_stack = QUndoStack()
self.undo_action = self.resource_undo_stack.createUndoAction(self, "Undo")
self.undo_action.setShortcuts(QKeySequence.Undo)
self.redo_action = self.resource_undo_stack.createRedoAction(self, "Redo")
self.redo_action.setShortcuts(QKeySequence.Redo)
self.resource_undo_stack.cleanChanged.connect(self.handle_clean_changed)
self.addAction(self.undo_action)
self.addAction(self.redo_action)
self.menu = QMenuBar(self)
self.edit_menu = self.menu.addMenu("Edit")
self.edit_menu.addAction(self.undo_action)
self.edit_menu.addAction(self.redo_action)
# self.undo_action.setVisible(False)
# self.redo_action.setVisible(False)
def undo_stack_init(self):
self.create_undo_stack()
self.saveResource.setEnabled(False)
self.dirty_resource = False
def propogate_undo_actions(self):
for widget in self.findChildren(QWidget):
widget.addAction(self.undo_action)
widget.addAction(self.redo_action)
def clear_menu(self):
return
def reject(self):
if self.dirty_resource or not self.set.is_clean():
if not self.prompt_to_discard():
return
super().reject()
def closeEvent(self, event):
if self.dirty_resource or not self.set.is_clean():
if self.prompt_to_discard():
return
self.done(QDialog.Accepted)
super().closeEvent(event)
def initToolTips(self):
self.selectResourceSet.setToolTip("Select an available resource set to edit.")
self.saveResourceSet.setToolTip("Save the set of resource objects, requires saving any changes to the resource being edited.")
self.saveForRack.setToolTip("Select a directory to save the current set of the editor to a file that can be loaded by VCV Rack. The file will be named according to the currently selected resource set title.")