Skip to content

Commit 4427f97

Browse files
committed
✨ 更新至0.3.0,重构数据模型,实现移除文件后选中下一个文件的功能
1 parent 9488c6e commit 4427f97

File tree

7 files changed

+229
-202
lines changed

7 files changed

+229
-202
lines changed

main.spec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33

44
a = Analysis(
5-
['main.py'],
6-
pathex=['.venv/Lib/site-packages'],
5+
['src/main.py'],
6+
pathex=['src', '.venv/Lib/site-packages'],
77
binaries=[],
88
datas=[],
9-
hiddenimports=['wx'],
9+
hiddenimports=['wx', 'src'],
1010
hookspath=[],
1111
hooksconfig={},
1212
runtime_hooks=[],

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "simplecutpy"
3-
version = "0.1.0"
4-
description = "Add your description here"
3+
version = "0.3.0"
4+
description = "A simple video cut tool based on wxpython, ffmpeg"
55
readme = "README.md"
66
requires-python = "==3.12.*"
77
dependencies = [

src/SimpleCutMainFrame.py

Lines changed: 83 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
from pymediainfo import MediaInfo
1616

17-
VERSION = "0.2.0"
17+
from src.model import VideoSequenceModel, VideoModel
18+
19+
VERSION = "0.3.0"
1820

1921

2022
class FileDropTarget(wx.FileDropTarget):
@@ -41,7 +43,8 @@ def __init__(self, parent=None):
4143
self.list_ctrl.SetDropTarget(FileDropTarget(self))
4244

4345
self.first_selected_index = 0
44-
self.item_list: list[dict] = [] # 列表是控件上的映射,列表的物品顺序就是控件上物品的顺序
46+
# self.item_list: list[dict] = [] # 列表是控件上的映射,列表的物品顺序就是控件上物品的顺序
47+
self.video_sequence: VideoSequenceModel = VideoSequenceModel()
4548

4649
# list_ctrl 控件添加列
4750
self.list_ctrl.InsertColumn(0, "序号", width=40)
@@ -50,6 +53,9 @@ def __init__(self, parent=None):
5053
self.list_ctrl.InsertColumn(3, "结束时间", width=65)
5154
self.list_ctrl.InsertColumn(4, "文件路径", width=238)
5255

56+
# 标记版本
57+
self.VersionText.SetLabelText(f"Simple Cut Py 版本号\n{VERSION}")
58+
5359
# Handlers for MainFrame events.
5460

5561
# TODO: 参数初始化
@@ -64,25 +70,6 @@ def format_time(time_string: str) -> str:
6470
time_string = str.replace(time_string, ":", ":")
6571
return time_string
6672

67-
def ApplyTimeButtonOnClick(self, event):
68-
apply_time_item_index = self.first_selected_index
69-
70-
# 从控件上读取时间
71-
start_time = self.StartTimeCtrl.GetValue()
72-
end_time = self.EndTimeCtrl.GetValue()
73-
74-
start_time = self.format_time(start_time)
75-
end_time = self.format_time(end_time)
76-
77-
# 设置物品列表的参数,如果为空就不更改
78-
if not start_time == '':
79-
self.item_list[apply_time_item_index]["start_time"] = start_time
80-
if not end_time == '':
81-
self.item_list[apply_time_item_index]["end_time"] = end_time
82-
83-
# 更新界面
84-
self.list_load_item(self.item_list[apply_time_item_index], apply_time_item_index)
85-
8673
def AddFileBtnOnClick(self, event):
8774
# 文件选择对话框
8875
file_dlg = wx.FileDialog(self, u"选择导入的文件", "", "", "*.mp4", wx.FD_OPEN)
@@ -115,53 +102,71 @@ def list_ctrl_on_drop_files(self, event):
115102

116103
def RemoveBtnOnClick(self, event):
117104
# 删除列表中的项
118-
delete_index = self.first_selected_index
119-
self.item_list.pop(delete_index)
105+
index = self.first_selected_index
106+
107+
if index <= -1:
108+
return # 如果没有选中
109+
110+
if index >= len(self.video_sequence):
111+
return # 如果超出范围
112+
113+
self.video_sequence.pop_video(index)
120114

121115
# 删除界面中的项
122116

123-
self.list_ctrl.DeleteItem(delete_index)
117+
self.list_ctrl.DeleteItem(index)
124118

125119
# 删除以后进行序号重排
126-
for i in range(len(self.item_list)):
127-
if i < delete_index:
120+
for i in range(len(self.video_sequence)):
121+
if i < index:
128122
continue
129123

130-
# 从删除项以后的每一个项的序号都要 -1
131-
self.item_list[i]["no"] -= 1
132-
133124
# 从删除项开始后面的每一个物品都重新加载
134-
self.list_load_item(self.item_list[i], i)
125+
self.update_video_model_item(i)
126+
127+
# 选中 index
128+
self.list_ctrl.Select(index)
135129

136130
def MovUpBtnOnClick(self, event):
137-
if self.first_selected_index == -1:
131+
value = self.first_selected_index
132+
133+
if value == -1:
138134
return # 如果没有选中
139135

140-
if self.first_selected_index == 0:
136+
if value == 0:
141137
wx.MessageBox("选中素材已置顶。", "错误", style=wx.YES_DEFAULT | wx.ICON_QUESTION)
142138
return # 如果是第一个物品
143139

144-
self.item_swap(self.first_selected_index, self.first_selected_index - 1)
140+
self.video_sequence.swap_item(value, value - 1)
141+
142+
self.update_video_model_item(value)
143+
self.update_video_model_item(value - 1)
145144

146145
self.list_ctrl.Select(self.first_selected_index, on=0) # 取消原来的选中
147146
self.list_ctrl.Select(self.first_selected_index - 1)
148147

149148
def MovDownBtnOnClick(self, event):
150-
if self.first_selected_index == -1:
149+
value = self.first_selected_index
150+
151+
if value == -1:
151152
return # 如果没有选中
152153

153-
if self.first_selected_index == self.list_ctrl.GetItemCount() - 1:
154+
if value == self.list_ctrl.GetItemCount() - 1:
154155
wx.MessageBox("选中素材在最末端。", "错误", style=wx.YES_DEFAULT | wx.ICON_QUESTION)
155156
return # 如果是最后一个
156157

157-
self.item_swap(self.first_selected_index, self.first_selected_index + 1)
158+
self.video_sequence.swap_item(self.first_selected_index, self.first_selected_index + 1)
159+
160+
self.update_video_model_item(value)
161+
self.update_video_model_item(value + 1)
158162

159163
# 选中转移
160164
self.list_ctrl.Select(self.first_selected_index, on=0) # 取消原来的选中
161165
self.list_ctrl.Select(self.first_selected_index + 1)
162166

163167
def ExportBtnOnClick(self, event):
164168
# TODO: 加了码率设置的功能,别忘了测试
169+
# TODO: item list 重写
165170

166171
# 从界面读取导出文件名、路径、码率
167172
export_name = self.ExportNameCtrl.GetValue()
@@ -183,7 +188,7 @@ def ExportBtnOnClick(self, event):
183188
export_name = export_path + '/' + export_name
184189
else:
185190
# 默认使用第一个文件的目录
186-
path = os.path.dirname(self.item_list[0]["path"])
191+
path = os.path.dirname(self.video_sequence[0].path)
187192
export_name = path + '/' + export_name
188193

189194
threading.Thread(target=self.export_video_file, args=(export_amix, export_mbps, export_name)).start()
@@ -192,28 +197,23 @@ def ExportBtnOnClick(self, event):
192197
return
193198

194199
def export_video_file(self, export_amix, export_mbps, export_name):
200+
# TODO: item list 重写
195201
# 导出命令
196202
console_command = 'ffmpeg '
197203
filter_complex_string = '-filter_complex '
198204
filter_complex_filters: list[str] = []
199205
concat_inputs: list[str] = []
200-
for item in self.item_list:
201-
no = item["no"]
202-
start_time = item["start_time"]
203-
end_time = item["end_time"]
204-
item_path = item["path"]
205-
206-
# 防止一些奇怪的东西
207-
if start_time == '':
208-
start_time = "开头"
209-
if end_time == '':
210-
end_time = "结尾"
206+
for index, item in enumerate(self.video_sequence):
207+
no = index
208+
start_time = item.start_time
209+
end_time = item.end_time
210+
item_path = item.path
211211

212212
# 开始、结束时间以及路径的命令行参数生成
213213
time_param = []
214-
if start_time != "开头":
214+
if start_time != "":
215215
time_param.append(f'-ss {start_time}')
216-
if end_time != "结尾":
216+
if end_time != "":
217217
time_param.append(f'-to {end_time}')
218218
time_param.append(f'-i "{item_path}"')
219219
time_string = " ".join(time_param)
@@ -268,106 +268,78 @@ def add_files(self, item_no, filename, path):
268268
:return: 空
269269
"""
270270
# 构建物品字典
271-
item_dict = {"no": item_no,
272-
"filename": filename,
273-
"start_time": "开头",
274-
"end_time": "结尾",
275-
"path": path
276-
}
271+
item = VideoModel(path, filename)
277272

278273
# 加到物品表
279-
self.item_list.append(item_dict)
274+
self.video_sequence.append_video(item)
280275

281276
# 显示数据在界面
282-
index = self.list_ctrl.InsertItem(item_dict["no"], item_dict["no"])
283-
self.list_load_item(item_dict, index)
284-
285-
pass
277+
index = self.list_ctrl.InsertItem(item_no, item_no)
278+
self.update_video_model_item(index)
286279

287280
def append_files(self, filename, path):
288281
item_no = self.list_ctrl.GetItemCount()
289282
self.add_files(item_no, filename, path)
290283

291284
def OnStartTimeCtrlText(self, event):
292285
"""修改开始时间输入框的时候修改itemlist的start_time"""
293-
first_selected_index = self.first_selected_index
286+
index = self.first_selected_index
294287
value = self.StartTimeCtrl.GetValue()
295288

296-
if value == '':
297-
value = "开头"
298-
self.item_list[first_selected_index]["start_time"] = value
299-
else:
300-
self.item_list[first_selected_index]["start_time"] = self.format_time(value)
289+
self.video_sequence[index].start_time = value
301290

302-
self.list_load_item(self.item_list[first_selected_index], first_selected_index)
291+
self.update_video_model_item(index)
303292

304293
def OnEndTimeCtrlText(self, event):
305294
"""修改结束时间输入框的时候修改itemlist的end_time"""
306-
first_selected_index = self.first_selected_index
295+
index = self.first_selected_index
307296
value = self.EndTimeCtrl.GetValue()
308297

309-
if value == '':
310-
value = "结尾"
311-
self.item_list[first_selected_index]["end_time"] = value
312-
else:
313-
self.item_list[first_selected_index]["end_time"] = self.format_time(value)
298+
self.video_sequence[index].end_time = value
314299

315-
self.list_load_item(self.item_list[first_selected_index], first_selected_index)
300+
self.update_video_model_item(index)
316301

317302
def list_ctrl_on_selected(self, event):
318-
first_selected_index = self.list_ctrl.GetFirstSelected()
319-
self.first_selected_index = first_selected_index
303+
index = self.list_ctrl.GetFirstSelected()
304+
self.first_selected_index = index
320305

321306
# 获取选中的物品时间,同步到输入框
322-
self.StartTimeCtrl.SetValue(self.item_list[first_selected_index]["start_time"])
323-
self.EndTimeCtrl.SetValue(self.item_list[first_selected_index]["end_time"])
307+
self.StartTimeCtrl.SetValue(self.video_sequence[index].start_time)
308+
self.EndTimeCtrl.SetValue(self.video_sequence[index].end_time)
324309

325310
logging.debug(
326-
f"Selected Item Index: {self.first_selected_index}, \
327-
Selected Item no: {self.item_list[self.first_selected_index]}")
311+
f"Selected Item Index: {index}, \
312+
Selected Item no: {self.video_sequence[index]}")
328313

329-
def item_swap(self, item1_index, item2_index):
330-
"""
331-
交换物品函数。会交换物品在列表的序号,位置,并更新控件上的位置
332-
:param item1_index: 交换的物品 1
333-
:param item2_index: 交换的物品 2
334-
:return:
335-
"""
314+
def update_video_model_item(self, no):
315+
self.load_video_model_item(self.video_sequence[no], no)
336316

337-
# 更新物品列表的序号
338-
temp = self.item_list[item1_index]["no"]
339-
self.item_list[item1_index]["no"] = self.item_list[item2_index]["no"]
340-
self.item_list[item2_index]["no"] = temp
317+
def update_sequence_model(self):
318+
self.load_sequence_model(self.video_sequence)
341319

342-
# 更新物品列表的位置
343-
temp = self.item_list[item1_index]
344-
self.item_list[item1_index] = self.item_list[item2_index]
345-
self.item_list[item2_index] = temp
346-
347-
# 交换用户界面上的显示
348-
self.list_load_item(self.item_list[item1_index], self.item_list[item1_index]["no"])
349-
self.list_load_item(self.item_list[item2_index], self.item_list[item2_index]["no"])
350-
351-
def list_load_item(self, load_item, list_ctrl_index):
320+
def load_video_model_item(self, load_item: VideoModel, list_ctrl_index: int):
352321
"""
353-
把物品列表上的物品载入到用户界面的控件上
322+
将 VideoModel 载入到 列表item上
354323
:param load_item: 载入的物品
355324
:param list_ctrl_index: 载入在控件的行数
356325
:return: 无
357326
"""
358-
self.list_ctrl.SetItem(list_ctrl_index, 0, str(load_item["no"]))
359-
self.list_ctrl.SetItem(list_ctrl_index, 1, load_item["filename"])
360-
self.list_ctrl.SetItem(list_ctrl_index, 2, load_item["start_time"])
361-
self.list_ctrl.SetItem(list_ctrl_index, 3, load_item["end_time"])
362-
self.list_ctrl.SetItem(list_ctrl_index, 4, load_item["path"])
327+
self.list_ctrl.SetItem(list_ctrl_index, 0, str(list_ctrl_index))
328+
self.list_ctrl.SetItem(list_ctrl_index, 1, load_item.filename)
329+
330+
start_time = "开头" if load_item.start_time == "" else load_item.start_time
331+
end_time = "结尾" if load_item.end_time == "" else load_item.end_time
332+
self.list_ctrl.SetItem(list_ctrl_index, 2, start_time)
333+
self.list_ctrl.SetItem(list_ctrl_index, 3, end_time)
334+
self.list_ctrl.SetItem(list_ctrl_index, 4, load_item.path)
363335

364-
def list_load_all_item(self):
336+
def load_sequence_model(self, sequence: VideoSequenceModel):
365337
"""
366338
把物品列表上的所有物品载入到用户界面的控件上
367339
:return:
368340
"""
369-
for item in self.item_list:
370-
self.list_load_item(item, item["no"])
341+
for index, item in enumerate(sequence):
342+
self.load_video_model_item(item, index)
371343

372344
def on_export_done(self, msg: ExportMessage):
373345
logging.debug(f"Export Done: {msg}")

0 commit comments

Comments
 (0)