Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
UncertainProd
GitHub Repository: UncertainProd/FnF-Spritesheet-and-XML-Maker
Path: blob/master/src/xmltablewindow.py
254 views
1
from PyQt5.QtWidgets import QTableWidgetItem, QWidget, QMenu, QAction, QMessageBox, QLineEdit, QInputDialog
2
from PyQt5.QtCore import Qt
3
from PyQt5.QtGui import QCursor
4
from utils import temp_path_shortener, imghashes
5
import engine.spritesheetutils as spritesheetutils
6
from xmltablewindowUI import Ui_TableWidgetThing
7
from utils import display_msg_box
8
9
class XMLTableView(QWidget):
10
def __init__(self, table_headings):
11
super().__init__()
12
self.ui = Ui_TableWidgetThing()
13
self.ui.setupUi(self)
14
15
self.table_headings = table_headings
16
self.ui.xmltable.setColumnCount(len(table_headings))
17
self.ui.xmltable.setHorizontalHeaderLabels(table_headings)
18
self.ui.xmltable.contextMenuEvent = self.handle_context_menu_event
19
20
# self.ui.xmltable.cellClicked.connect(self.handle_cell_click)
21
# self.ui.xmltable.cellActivated.connect(self.handle_cell_click)
22
# self.ui.xmltable.cellPressed.connect(self.handle_cell_click)
23
self.ui.xmltable.currentCellChanged.connect(self.handle_curr_cell_change)
24
self.ui.frame_preview_label.setStyleSheet("QFrame{ border: 1px solid black; }")
25
# self.ui.xmltable.selectionModel().selectionChanged.connect(self.handle_cell_selection)
26
27
# list[SpriteFrame]
28
self.tabledata = []
29
self.canchange = True
30
self.frame_info = [None, None, None, None]
31
self.frame_spinboxes = [self.ui.framex_spinbox, self.ui.framey_spinbox, self.ui.framewidth_spinbox, self.ui.frameheight_spinbox]
32
33
self.ui.framex_spinbox.valueChanged.connect(self.handle_framex_change)
34
self.ui.framey_spinbox.valueChanged.connect(self.handle_framey_change)
35
self.ui.framewidth_spinbox.valueChanged.connect(self.handle_framew_change)
36
self.ui.frameheight_spinbox.valueChanged.connect(self.handle_frameh_change)
37
38
self.selected_row = None
39
self.selected_row_index = None
40
41
self.was_opened = False
42
43
self.selected_cells = []
44
45
def handle_curr_cell_change(self, current_row, current_col, prev_row, prev_col):
46
self.selected_row_index = current_row
47
self.handle_display_stuff(self.selected_row_index)
48
49
def handle_context_menu_event(self, event):
50
self.menu = QMenu(self)
51
renameAction = QAction('Set Value', self)
52
renameAction.triggered.connect(lambda: self.set_value_handle())
53
self.menu.addAction(renameAction)
54
# add other required actions
55
self.menu.popup(QCursor.pos())
56
57
def set_value_handle(self):
58
_cells = self.ui.xmltable.selectedItems()
59
idx = -1
60
for _cell in _cells:
61
if not (_cell.flags() & Qt.ItemIsEditable):
62
display_msg_box(self, "Bad cell selection", "There are un-editable cells in your selection!\nSelect cells from the same column, valid columns being\nFrameX, FrameY, FrameWidth or FrameHeight", QMessageBox.Critical)
63
return
64
else:
65
if idx != -1 and _cell.column() != idx:
66
display_msg_box(self, "Multiple Columns Selected", "Your selection spans multiple columns. Make sure to select cells that belong to the same column, valid columns being\nFrameX, FrameY, FrameWidth or FrameHeight", QMessageBox.Critical)
67
return
68
else:
69
idx = _cell.column()
70
71
rows = [ x.row() for x in _cells ]
72
text, okPressed = QInputDialog.getText(self, f"Change Value of {self.table_headings[idx - 4]}", "New value:"+(" "*50), QLineEdit.Normal)
73
is_real_number = lambda s: s.isnumeric() or (s[0] == '-' and s[1:].isnumeric())
74
if okPressed and text != '' and is_real_number(text):
75
val = int(text)
76
old_selected_row_index = self.selected_row_index
77
old_selected_row = self.selected_row
78
for row_num in rows:
79
self.ui.xmltable.setItem(row_num, idx, QTableWidgetItem(str(val)))
80
self.selected_row_index = row_num
81
self.selected_row = self.tabledata[row_num]
82
self.handle_cell_change(row_num, idx)
83
84
# restoring things back to normal
85
self.selected_row_index = old_selected_row_index
86
self.selected_row = old_selected_row
87
self.set_true_frame()
88
else:
89
print("Text invalid / cancel was pressed")
90
91
92
def handle_framex_change(self, newval):
93
if self.canchange:
94
if self.selected_row:
95
self.selected_row.data.framex = newval
96
self.ui.xmltable.setItem(self.selected_row_index, 4, QTableWidgetItem(str(newval)))
97
self.set_true_frame()
98
99
def handle_framey_change(self, newval):
100
if self.canchange:
101
if self.selected_row:
102
self.selected_row.data.framey = newval
103
self.ui.xmltable.setItem(self.selected_row_index, 5, QTableWidgetItem(str(newval)))
104
self.set_true_frame()
105
106
def handle_framew_change(self, newval):
107
if self.canchange:
108
if self.selected_row:
109
self.selected_row.data.framew = newval
110
self.ui.xmltable.setItem(self.selected_row_index, 6, QTableWidgetItem(str(newval)))
111
self.set_true_frame()
112
113
def handle_frameh_change(self, newval):
114
if self.canchange:
115
if self.selected_row:
116
self.selected_row.data.frameh = newval
117
self.ui.xmltable.setItem(self.selected_row_index, 7, QTableWidgetItem(str(newval)))
118
self.set_true_frame()
119
120
def set_true_frame(self):
121
# set the frame pixmap
122
curimg = imghashes.get(self.selected_row.data.img_hash)
123
truframe = spritesheetutils.get_true_frame(
124
curimg,
125
self.selected_row.data.framex if self.selected_row.data.framex is not None else 0,
126
self.selected_row.data.framey if self.selected_row.data.framey is not None else 0,
127
self.selected_row.data.framew if self.selected_row.data.framew is not None else curimg.width,
128
self.selected_row.data.frameh if self.selected_row.data.frameh is not None else curimg.height,
129
).toqpixmap()
130
self.ui.frame_preview_label.setPixmap(truframe)
131
self.ui.frame_preview_label.setFixedSize(truframe.width(), truframe.height())
132
133
def fill_data(self, data):
134
# data: list[Spriteframe]
135
table = self.ui.xmltable
136
if self.was_opened:
137
table.cellChanged.disconnect(self.handle_cell_change)
138
self.tabledata = data
139
table.setRowCount(len(data))
140
for rownum, label in enumerate(data):
141
tabledat = [label.data.imgpath, label.data.pose_name, label.data.img_width, label.data.img_height, label.data.framex, label.data.framey, label.data.framew, label.data.frameh]
142
for colnum, col in enumerate(tabledat):
143
table_cell = QTableWidgetItem(str(col))
144
if colnum < 4:
145
table_cell.setFlags(table_cell.flags() ^ Qt.ItemIsEditable)
146
table.setItem(rownum, colnum, table_cell)
147
148
table.cellChanged.connect(self.handle_cell_change)
149
self.was_opened = True
150
151
def handle_cell_change(self, row, col):
152
idx = col - 4
153
154
if idx >= 0:
155
self.canchange = False
156
newval = self.ui.xmltable.item(row, col).text()
157
if newval.lower() == 'default':
158
# default framex = framey = 0, framew = img.width, frameh = img.height
159
if idx <= 1:
160
newval = 0
161
elif idx == 2:
162
newval = self.selected_row.data.img_width
163
elif idx == 3:
164
newval = self.selected_row.data.img_height
165
else:
166
print("Something's wrong")
167
self.ui.xmltable.setItem(row, col, QTableWidgetItem(str(newval)))
168
else:
169
try:
170
newval = int(newval)
171
assert (idx >= 2 and newval > 0) or (idx < 2)
172
except Exception as e:
173
print("Exception:\n", e)
174
if idx == 0:
175
newval = self.selected_row.data.framex
176
elif idx == 1:
177
newval = self.selected_row.data.framey
178
elif idx == 2:
179
newval = self.selected_row.data.framew
180
elif idx == 3:
181
newval = self.selected_row.data.frameh
182
else:
183
print("Something's wrong")
184
self.ui.xmltable.setItem(row, col, QTableWidgetItem(str(newval)))
185
186
self.frame_spinboxes[idx].setValue(newval if newval else 0)
187
self.canchange = True
188
189
# idx: 0 = framex, 1 = framey, 2 = framew, 3 = frameh
190
if idx == 0:
191
self.selected_row.data.framex = newval
192
elif idx == 1:
193
self.selected_row.data.framey = newval
194
elif idx == 2:
195
self.selected_row.data.framew = newval
196
elif idx == 3:
197
self.selected_row.data.frameh = newval
198
else:
199
print("[ERROR] Some error occured!")
200
201
self.set_true_frame()
202
203
# def handle_cell_selection(self, selected, deselected):
204
# if selected.indexes():
205
# self.selected_cells.extend(selected.indexes())
206
# self.selected_row_index = selected.indexes()[-1].row()
207
# self.handle_display_stuff(self.selected_row_index)
208
# elif deselected.indexes():
209
# for _cell in deselected.indexes():
210
# print(f"Removing: {_cell.row()}, {_cell.column()}")
211
# self.selected_cells.remove(_cell)
212
# self.selected_row_index = deselected.indexes()[-1].row()
213
# self.handle_display_stuff(self.selected_row_index)
214
# print(f'{[ (c.row(), c.column()) for c in self.selected_cells ]}')
215
# else:
216
# print("Something's weird here")
217
218
def handle_display_stuff(self, row):
219
self.selected_row = self.tabledata[row]
220
short_path = temp_path_shortener(self.selected_row.data.imgpath)
221
222
self.ui.frame_preview_label.clear()
223
self.set_true_frame()
224
225
if self.selected_row.data.from_single_png:
226
self.ui.frame_info_label.setText(f"Image path: {short_path}\tFrom existing spritesheet: No")
227
else:
228
self.ui.frame_info_label.setText(f"Image path: {short_path}\tFrom existing spritesheet: Yes\tCo-ords in source spritesheet: x={self.selected_row.data.tx} y={self.selected_row.data.ty} w={self.selected_row.data.tw} h={self.selected_row.data.th}")
229
230
self.frame_info = [self.selected_row.data.framex, self.selected_row.data.framey, self.selected_row.data.framew, self.selected_row.data.frameh]
231
for spinbox, info in zip(self.frame_spinboxes, self.frame_info):
232
self.canchange = False
233
spinbox.setValue(int(info) if info is not None and str(info).lower() != "default" else 0)
234
self.canchange = True
235