Skip to content

Commit

Permalink
v1.0.0
Browse files Browse the repository at this point in the history
v1.0.0
  • Loading branch information
cgkings committed Jun 30, 2024
1 parent c8be1d0 commit 4c84cca
Showing 1 changed file with 206 additions and 93 deletions.
299 changes: 206 additions & 93 deletions NFO.Editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class NFOEditorApp:
def __init__(self, root):
self.root = root
self.root.title("大锤 v2.0.0 NFO Editor 20240629")
self.root.title("大锤 NFO Editor 20240630")

self.current_file_path = None
self.fields_entries = {}
Expand Down Expand Up @@ -37,14 +37,6 @@ def __init__(self, root):
image_toggle = tk.Checkbutton(top_frame, text="显示图片", variable=self.show_images_var, command=self.toggle_image_display)
image_toggle.pack(side=tk.RIGHT, padx=5)

# 图片显示区域框架
image_frame = tk.Frame(self.root, width=400, height=300, bg="gray")
image_frame.pack(side=tk.RIGHT, padx=10, pady=10)
image_frame.pack_propagate(0)

self.image_label = tk.Label(image_frame, text="图片显示已关闭", bg="gray")
self.image_label.pack(expand=True)

# 创建排序选项
sorting_frame = tk.Frame(self.root)
sorting_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
Expand All @@ -61,19 +53,50 @@ def __init__(self, root):
for text, value in sorting_options:
tk.Radiobutton(sorting_frame, text=text, variable=self.sorting_var, value=value, command=self.sort_files).pack(side=tk.LEFT, padx=5)

# 创建文件列表框
self.file_listbox = tk.Listbox(self.root, width=50, selectmode=tk.EXTENDED)
# 创建文件列表框和滚动条
listbox_frame = tk.Frame(self.root)
listbox_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

self.file_listbox = tk.Listbox(listbox_frame, width=50, selectmode=tk.EXTENDED)
self.file_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
scrollbar.pack(side=tk.LEFT, fill=tk.Y)

scrollbar = tk.Scrollbar(listbox_frame, orient=tk.VERTICAL)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

self.file_listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=self.file_listbox.yview)

self.file_listbox.bind('<<ListboxSelect>>', self.on_file_select)

# 创建字段编辑框架
self.fields_frame = tk.Frame(self.root, padx=10, pady=10)
self.fields_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

# 图片显示区域框架
image_frame = tk.Frame(self.fields_frame)
image_frame.pack(anchor=tk.W, pady=10)

image_label = tk.Label(image_frame, text="图片:", font=("Arial", 12, "bold"))
image_label.pack(side=tk.LEFT, padx=5, pady=5)

poster_frame = tk.Frame(image_frame, width=165, height=225, bg="", highlightthickness=1, highlightbackground="black")
poster_frame.pack(side=tk.LEFT, padx=5)
poster_frame.pack_propagate(0)

# 增加间距的空Frame
empty_frame = tk.Frame(image_frame, width=40, bg="")
empty_frame.pack(side=tk.LEFT)

thumb_frame = tk.Frame(image_frame, width=333, height=225, bg="", highlightthickness=1, highlightbackground="black")
thumb_frame.pack(side=tk.LEFT, padx=5)
thumb_frame.pack_propagate(0)

self.poster_label = tk.Label(poster_frame, text="封面图 (poster)", fg="black") # 设置文本颜色为黑色
self.poster_label.pack(expand=True)

self.thumb_label = tk.Label(thumb_frame, text="缩略图 (thumb)", fg="black") # 设置文本颜色为黑色
self.thumb_label.pack(expand=True)

# 创建字段标签和输入框
self.create_field_labels()

Expand All @@ -88,58 +111,79 @@ def __init__(self, root):

def toggle_image_display(self):
if self.show_images_var.get():
self.image_label.config(text="")
self.poster_label.config(text="封面图 (poster)", fg="black")
self.thumb_label.config(text="缩略图 (thumb)", fg="black")
self.display_image()
else:
self.image_label.config(image="", text="图片显示已关闭")
self.poster_label.config(image="", text="封面图 (poster)", fg="black")
self.thumb_label.config(image="", text="缩略图 (thumb)", fg="black")

def display_image(self):
if self.current_file_path:
folder = os.path.dirname(self.current_file_path)
image_files = [f for f in os.listdir(folder) if f.lower().endswith('.jpg') and 'thumb' in f.lower()]
if image_files:
image_path = os.path.join(folder, image_files[0])
try:
img = Image.open(image_path)
img.thumbnail((400, 300), Image.LANCZOS) # 调整图片大小,保持比例
img = ImageTk.PhotoImage(img)
self.image_label.config(image=img)
self.image_label.image = img # 保持引用防止图片被垃圾回收
except Exception as e:
self.image_label.config(text="加载图片失败: " + str(e))
poster_files = [f for f in os.listdir(folder) if f.lower().endswith('.jpg') and 'poster' in f.lower()]
thumb_files = [f for f in os.listdir(folder) if f.lower().endswith('.jpg') and 'thumb' in f.lower()]

if poster_files:
self.load_image(poster_files[0], self.poster_label, (165, 225))
else:
self.poster_label.config(text="文件夹内无poster图片", fg="black")

if thumb_files:
self.load_image(thumb_files[0], self.thumb_label, (333, 225))
else:
self.image_label.config(text="文件夹内无thumb图片")
self.thumb_label.config(text="文件夹内无thumb图片", fg="black")

def load_image(self, image_file, label, size):
folder = os.path.dirname(self.current_file_path)
image_path = os.path.join(folder, image_file)
try:
img = Image.open(image_path)
img.thumbnail(size, Image.LANCZOS)
img = ImageTk.PhotoImage(img)
label.config(image=img)
label.image = img # 保持引用防止图片被垃圾回收
except Exception as e:
label.config(text="加载图片失败: " + str(e))

def create_field_labels(self):
# 定义各字段的标签文本和高度
fields = {
'title': ('标题 (Title)', 2),
'plot': ('简介 (Plot)', 6),
'actors': ('演员 (Actors)', 2),
'series': ('系列 (Series)', 2),
'tags': ('标签 (Tags)', 3),
'genres': ('类别 (Genre)', 3),
'rating': ('评分 (Rating)', 1)
'title': ('标题', 2),
'plot': ('简介', 5),
'tags': ('标签', 3),
'genres': ('类别', 3),
'actors': ('演员', 1),
'series': ('系列', 1),
'rating': ('评分', 1)
}

# 创建标签和输入框,并存储到 fields_entries 中
for row, (field, (label_text, height)) in enumerate(fields.items()):
label = tk.Label(self.fields_frame, text=label_text + ":", font=("Arial", 12, "bold"))
label.grid(row=row, column=0, sticky=tk.W, pady=5)
entry = tk.Text(self.fields_frame, width=60, height=height)
entry.grid(row=row, column=1, sticky=tk.W, pady=5)
for field, (label_text, height) in fields.items():
frame = tk.Frame(self.fields_frame)
frame.pack(fill=tk.X) # 确保每个输入框在水平方向上填充父容器

label = tk.Label(frame, text=label_text + ":", font=("Arial", 12, "bold"))
label.pack(side=tk.LEFT, padx=5, pady=5, anchor=tk.W) # 左对齐标签

entry = tk.Text(frame, width=60, height=height)
entry.pack(side=tk.LEFT, padx=5, pady=5, fill=tk.X, expand=True)

self.fields_entries[field] = entry

def create_operations_panel(self):
# 创建操作面板,包括保存更改按钮、批量替换按钮和保存时间标签
operations_frame = tk.Frame(self.fields_frame, padx=10, pady=10)
operations_frame.grid(row=len(self.fields_entries), column=0, columnspan=2, pady=10)
operations_frame.pack(fill=tk.X)

save_button = tk.Button(operations_frame, text="保存更改 (Save Changes)", command=self.save_changes)
save_button = tk.Button(operations_frame, text="保存更改 (Save Changes)", command=self.save_changes, width=25)
save_button.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)

batch_replace_button = tk.Button(operations_frame, text="批量替换 (Batch Replace)", command=self.batch_replace)
batch_replace_button.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)
batch_filling_button = tk.Button(operations_frame, text="批量填充 (Batch Filling)", command=self.batch_filling, width=25)
batch_filling_button.grid(row=0, column=1, padx=5, pady=5, sticky=tk.W)

batch_add_button = tk.Button(operations_frame, text="批量新增 (Batch Add)", command=self.batch_add, width=25)
batch_add_button.grid(row=0, column=2, padx=5, pady=5, sticky=tk.W)

self.save_time_label = tk.Label(operations_frame, text="")
self.save_time_label.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky=tk.W)
Expand Down Expand Up @@ -319,19 +363,26 @@ def get_sort_key(nfo_file):
try:
tree = ET.parse(nfo_file)
root = tree.getroot()

if sort_by == "actors":
actors = set()
for actor_elem in root.findall('actor'):
name_elem = actor_elem.find('name')
if name_elem is not None:
actors.add(name_elem.text)
return ', '.join(actors)
actors = {actor_elem.find('name').text.strip() for actor_elem in root.findall('actor') if actor_elem.find('name') is not None}
return ', '.join(sorted(actors)) if actors else ""

elif sort_by == "series":
series_elem = root.find('series')
return series_elem.text.strip() if series_elem is not None and series_elem.text is not None else ""

elif sort_by == "rating":
rating_elem = root.find('rating')
return rating_elem.text.strip() if rating_elem is not None and rating_elem.text is not None else ""

else:
for child in root:
if child.tag == sort_by:
return child.text
if child.tag == sort_by and child.text is not None:
return child.text.strip()
except ET.ParseError:
return ""
pass

return ""

self.nfo_files.sort(key=get_sort_key)
Expand All @@ -341,66 +392,128 @@ def get_sort_key(nfo_file):
for nfo_file in self.nfo_files:
self.file_listbox.insert(tk.END, os.path.relpath(nfo_file, self.folder_path))

def batch_replace(self):
# 批量替换对话框逻辑
def apply_replacement():
def batch_filling(self):
# 批量填充对话框逻辑
def apply_fill():
field = field_var.get()
original_text = original_entry.get()
new_text = new_entry.get()
fill_value = fill_entry.get()
operation_log = ""
if field and original_text and new_text:

if field and fill_value:
for nfo_file in self.nfo_files:
try:
tree = ET.parse(nfo_file)
root = tree.getroot()
modified = False

if field in ['series', 'rating']:
for child in root:
if child.tag == field and child.text == original_text:
child.text = new_text
modified = True
elif field == 'actors':
for actor_elem in root.findall('actor'):
name_elem = actor_elem.find('name')
if name_elem is not None and name_elem.text == original_text:
name_elem.text = new_text
modified = True
if modified:
xml_str = ET.tostring(root, encoding='utf-8')
parsed_str = minidom.parseString(xml_str)
pretty_str = parsed_str.toprettyxml(indent=" ", encoding='utf-8')
with open(nfo_file, 'wb') as file:
file.write(pretty_str)
operation_log += f"{nfo_file}: 修改成功\n"
else:
operation_log += f"{nfo_file}: 未找到匹配内容\n"

# 如果字段不存在,则创建新的元素
field_elem = root.find(field)
if field_elem is None:
field_elem = ET.Element(field)
root.append(field_elem)

# 填充字段值
field_elem.text = fill_value.strip()

# 保存修改后的 XML 文件
xml_str = ET.tostring(root, encoding='utf-8')
parsed_str = minidom.parseString(xml_str)
pretty_str = parsed_str.toprettyxml(indent=" ", encoding='utf-8')

# 去除多余的空行
pretty_lines = pretty_str.decode('utf-8').splitlines()
formatted_lines = []
for line in pretty_lines:
if line.strip():
formatted_lines.append(line)
formatted_str = "\n".join(formatted_lines)

with open(nfo_file, 'w', encoding='utf-8') as file:
file.write(formatted_str)

operation_log += f"{nfo_file}: {field}字段填充成功\n"
except Exception as e:
operation_log += f"{nfo_file}: 修改失败 - {str(e)}\n"
operation_log += f"{nfo_file}: {field}字段填充失败 - {str(e)}\n"

log_text.delete(1.0, tk.END)
log_text.insert(1.0, operation_log)

# 创建批量填充对话框
dialog = Toplevel(self.root)
dialog.title("批量替换 (Batch Replace)")
dialog.title("批量填充 (Batch Fill)")
dialog.geometry("400x300")

tk.Label(dialog, text="选择字段 (Field):").pack(pady=5)
field_var = tk.StringVar(value="title")
tk.Radiobutton(dialog, text="演员 (Actors)", variable=field_var, value="actors").pack(anchor=tk.W)
tk.Label(dialog, text="选择填充替换字段 (Select Field):").pack(pady=5)
field_var = tk.StringVar(value="series")
tk.Radiobutton(dialog, text="系列 (Series)", variable=field_var, value="series").pack(anchor=tk.W)
tk.Radiobutton(dialog, text="评分 (Rating)", variable=field_var, value="rating").pack(anchor=tk.W)

tk.Label(dialog, text="原内容 (Original Content):").pack(pady=5)
original_entry = tk.Entry(dialog, width=40)
original_entry.pack(pady=5)
tk.Label(dialog, text="填充替换值 (Fill Field Value):").pack(pady=5)
fill_entry = tk.Entry(dialog, width=40)
fill_entry.pack(pady=5)

tk.Button(dialog, text="应用填充替换 (Apply Fill)", command=apply_fill).pack(pady=10)

tk.Label(dialog, text="操作日志 (Operation Log):").pack(pady=5)
log_text = tk.Text(dialog, width=50, height=10)
log_text.pack(pady=5)

# 添加批量新增功能的方法 batch_add
def batch_add(self):
# 批量新增对话框逻辑
def apply_add():
field = field_var.get()
add_value = add_entry.get()
operation_log = ""

if field and add_value:
for nfo_file in self.nfo_files:
try:
tree = ET.parse(nfo_file)
root = tree.getroot()

# 创建新的元素并添加新增值
new_elem = ET.Element(field)
new_elem.text = add_value.strip()
root.append(new_elem)

# 保存修改后的 XML 文件
xml_str = ET.tostring(root, encoding='utf-8')
parsed_str = minidom.parseString(xml_str)
pretty_str = parsed_str.toprettyxml(indent=" ", encoding='utf-8')

# 去除多余的空行
pretty_lines = pretty_str.decode('utf-8').splitlines()
formatted_lines = []
for line in pretty_lines:
if line.strip():
formatted_lines.append(line)
formatted_str = "\n".join(formatted_lines)

with open(nfo_file, 'w', encoding='utf-8') as file:
file.write(formatted_str)

operation_log += f"{nfo_file}: {field}字段批量新增成功\n"
except Exception as e:
operation_log += f"{nfo_file}: {field}字段批量新增失败 - {str(e)}\n"

log_text.delete(1.0, tk.END)
log_text.insert(1.0, operation_log)

# 创建批量新增对话框
dialog = Toplevel(self.root)
dialog.title("批量新增 (Batch Add)")
dialog.geometry("400x300")

tk.Label(dialog, text="选择字段新增一个值 (Select Field):").pack(pady=5)
field_var = tk.StringVar(value="tag")
tk.Radiobutton(dialog, text="标签 (Tag)", variable=field_var, value="tag").pack(anchor=tk.W)
tk.Radiobutton(dialog, text="类型 (Genre)", variable=field_var, value="genre").pack(anchor=tk.W)

tk.Label(dialog, text="新内容 (New Content):").pack(pady=5)
new_entry = tk.Entry(dialog, width=40)
new_entry.pack(pady=5)
tk.Label(dialog, text="输入新增值 (Enter Value to Add):").pack(pady=5)
add_entry = tk.Entry(dialog, width=40)
add_entry.pack(pady=5)

tk.Button(dialog, text="应用 (Apply)", command=apply_replacement).pack(pady=10)
tk.Button(dialog, text="应用新增 (Apply Add)", command=apply_add).pack(pady=10)

tk.Label(dialog, text="操作日志 (Operation Log):").pack(pady=5)
log_text = tk.Text(dialog, width=50, height=10)
Expand Down

0 comments on commit 4c84cca

Please sign in to comment.