v0.3: Enhanced Script Mods tab — grouped by mod name, file counts, toggle, context menu
- Script mods now grouped by mod name instead of flat file list - Shows file count per mod and category totals - Toggle button to enable/disable script mods - Right-click context menu for script mods - Info label showing total mods and files - Support for redscript, TweakXL, CET, red4ext, ArchiveXL
This commit is contained in:
+77
-6
@@ -856,11 +856,24 @@ class ModManagerWindow(QMainWindow):
|
|||||||
layout.addWidget(QLabel("📜 Script-based mods (redscript, TweakXL, CET, red4ext, ArchiveXL):"))
|
layout.addWidget(QLabel("📜 Script-based mods (redscript, TweakXL, CET, red4ext, ArchiveXL):"))
|
||||||
|
|
||||||
self.script_tree = QTreeWidget()
|
self.script_tree = QTreeWidget()
|
||||||
self.script_tree.setHeaderLabels(["Type", "Path", "Status"])
|
self.script_tree.setHeaderLabels(["Type", "Mod Name", "Path", "Files", "Status"])
|
||||||
self.script_tree.setAlternatingRowColors(True)
|
self.script_tree.setAlternatingRowColors(True)
|
||||||
|
header = self.script_tree.header()
|
||||||
|
header.setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
|
||||||
|
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
|
||||||
|
header.setSectionResizeMode(2, QHeaderView.ResizeMode.Stretch)
|
||||||
|
header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
|
||||||
|
header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents)
|
||||||
|
self.script_tree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
|
self.script_tree.customContextMenuRequested.connect(self._script_context_menu)
|
||||||
layout.addWidget(self.script_tree, 1)
|
layout.addWidget(self.script_tree, 1)
|
||||||
|
|
||||||
# Add script mod button
|
# Info label
|
||||||
|
self.script_info_label = QLabel("Ready. Click Refresh to scan.")
|
||||||
|
self.script_info_label.setStyleSheet("color: #888; font-size: 11px;")
|
||||||
|
layout.addWidget(self.script_info_label)
|
||||||
|
|
||||||
|
# Buttons
|
||||||
btn_layout = QHBoxLayout()
|
btn_layout = QHBoxLayout()
|
||||||
add_script_btn = QPushButton("➕ Add Script Mod (.yaml, .reds, .zip, .7z)")
|
add_script_btn = QPushButton("➕ Add Script Mod (.yaml, .reds, .zip, .7z)")
|
||||||
add_script_btn.clicked.connect(self.add_script_mod)
|
add_script_btn.clicked.connect(self.add_script_mod)
|
||||||
@@ -870,6 +883,10 @@ class ModManagerWindow(QMainWindow):
|
|||||||
refresh_script_btn.clicked.connect(self.refresh_script_mods)
|
refresh_script_btn.clicked.connect(self.refresh_script_mods)
|
||||||
btn_layout.addWidget(refresh_script_btn)
|
btn_layout.addWidget(refresh_script_btn)
|
||||||
|
|
||||||
|
toggle_script_btn = QPushButton("🔄 Toggle Selected")
|
||||||
|
toggle_script_btn.clicked.connect(self._toggle_script_mod)
|
||||||
|
btn_layout.addWidget(toggle_script_btn)
|
||||||
|
|
||||||
btn_layout.addStretch()
|
btn_layout.addStretch()
|
||||||
layout.addLayout(btn_layout)
|
layout.addLayout(btn_layout)
|
||||||
|
|
||||||
@@ -1113,24 +1130,78 @@ class ModManagerWindow(QMainWindow):
|
|||||||
"archivexl": "🗂️",
|
"archivexl": "🗂️",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
total_mods = 0
|
||||||
|
total_files = 0
|
||||||
|
|
||||||
for category, files in self.script_mods.items():
|
for category, files in self.script_mods.items():
|
||||||
if not files:
|
if not files:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Group by mod name (top-level folder or filename)
|
||||||
|
mod_groups = {}
|
||||||
|
for f in files:
|
||||||
|
# Extract mod name from path
|
||||||
|
path_parts = f.split("/")
|
||||||
|
if category == "cet" and len(path_parts) >= 7:
|
||||||
|
# bin/x64/plugins/cyber_engine_tweaks/mods/<modname>/...
|
||||||
|
mod_name = path_parts[6]
|
||||||
|
elif category == "red4ext" and len(path_parts) >= 3:
|
||||||
|
# red4ext/plugins/<modname>/...
|
||||||
|
mod_name = path_parts[2]
|
||||||
|
elif category == "redscript" and len(path_parts) >= 3:
|
||||||
|
# r6/scripts/<modname>/...
|
||||||
|
mod_name = path_parts[2] if path_parts[2] != "r6" else path_parts[-1]
|
||||||
|
elif category == "tweakxl" and len(path_parts) >= 3:
|
||||||
|
# r6/tweaks/<modname>/...
|
||||||
|
mod_name = path_parts[2] if path_parts[2] != "r6" else path_parts[-1]
|
||||||
|
else:
|
||||||
|
mod_name = path_parts[-1]
|
||||||
|
|
||||||
|
if mod_name not in mod_groups:
|
||||||
|
mod_groups[mod_name] = []
|
||||||
|
mod_groups[mod_name].append(f)
|
||||||
|
|
||||||
parent = QTreeWidgetItem()
|
parent = QTreeWidgetItem()
|
||||||
parent.setText(0, f"{icons.get(category, '📋')} {category.upper()}")
|
parent.setText(0, f"{icons.get(category, '📋')} {category.upper()}")
|
||||||
parent.setText(2, f"{len(files)} items")
|
parent.setText(1, f"{len(mod_groups)} mods")
|
||||||
|
parent.setText(3, f"{len(files)} files")
|
||||||
|
parent.setText(4, "✅ Active")
|
||||||
parent.setForeground(0, QColor("#00ff9f"))
|
parent.setForeground(0, QColor("#00ff9f"))
|
||||||
|
parent.setForeground(4, QColor("#00ff9f"))
|
||||||
|
parent.setExpanded(True)
|
||||||
|
|
||||||
for f in files:
|
for mod_name, mod_files in sorted(mod_groups.items()):
|
||||||
child = QTreeWidgetItem()
|
child = QTreeWidgetItem()
|
||||||
child.setText(1, f)
|
child.setText(1, mod_name)
|
||||||
child.setText(2, "✅ Active")
|
child.setText(3, str(len(mod_files)))
|
||||||
|
|
||||||
|
# Check if disabled (.disabled suffix on folder or file)
|
||||||
|
is_disabled = any(".disabled" in f for f in mod_files)
|
||||||
|
child.setText(4, "❌ Disabled" if is_disabled else "✅ Active")
|
||||||
|
if is_disabled:
|
||||||
|
child.setForeground(4, QColor("#ff0080"))
|
||||||
|
else:
|
||||||
|
child.setForeground(4, QColor("#00ff9f"))
|
||||||
|
|
||||||
|
child.setData(0, Qt.ItemDataRole.UserRole, {
|
||||||
|
"category": category,
|
||||||
|
"mod_name": mod_name,
|
||||||
|
"files": mod_files,
|
||||||
|
"disabled": is_disabled
|
||||||
|
})
|
||||||
|
|
||||||
|
# Show first file as path hint
|
||||||
|
child.setText(2, mod_files[0] if mod_files else "")
|
||||||
|
|
||||||
parent.addChild(child)
|
parent.addChild(child)
|
||||||
|
total_mods += 1
|
||||||
|
total_files += len(mod_files)
|
||||||
|
|
||||||
self.script_tree.addTopLevelItem(parent)
|
self.script_tree.addTopLevelItem(parent)
|
||||||
parent.setExpanded(True)
|
parent.setExpanded(True)
|
||||||
|
|
||||||
|
self.script_info_label.setText(f"Total: {total_mods} mods, {total_files} files")
|
||||||
|
|
||||||
def _on_mod_checkbox_changed(self, item, column):
|
def _on_mod_checkbox_changed(self, item, column):
|
||||||
if column != 0:
|
if column != 0:
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user