import sys import os import json import shutil from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListWidget, QPushButton, QListWidgetItem, QMessageBox from PyQt5.QtCore import Qt import configparser import qtvscodestyle class DragDropApp(QWidget): def __init__(self): super().__init__() self.setWindowTitle('Drag and Drop JSON Reorder') # Initialize window size from config.ini self.initWindowSize() self.initUI() def initWindowSize(self): self.mod_dir = os.getcwd() self.config = configparser.ConfigParser() self.config_path = os.path.join(self.mod_dir, 'config.ini') if not os.path.exists(self.config_path): # Create config.ini with default values self.createDefaultConfig() # Read width and height from config.ini self.config.read(self.config_path) width = int(self.config.get('DEFAULT', 'width', fallback='400')) height = int(self.config.get('DEFAULT', 'height', fallback='300')) self.resize(width, height) def createDefaultConfig(self): self.config['DEFAULT'] = { 'sptBaseDir': '', 'addNewItemsTo': 'end', 'reminder': 'True', 'width': '400', 'height': '300' } with open(self.config_path, 'w') as configfile: self.config.write(configfile) def initUI(self): layout = QVBoxLayout(self) self.list_widget = QListWidget() layout.addWidget(self.list_widget) self.save_button = QPushButton('Save Order') layout.addWidget(self.save_button) self.mod_dir = os.getcwd() self.config = configparser.ConfigParser() self.config_path = os.path.join(self.mod_dir, 'config.ini') self.loadConfig() if not self.checkModsDirectory(): return self.initial_order = [] self.loadData(self.mod_dir) self.list_widget.setDragDropMode(QListWidget.InternalMove) self.list_widget.setAlternatingRowColors(True) self.save_button.clicked.connect(lambda: self.saveOrder(self.mod_dir)) # Apply the dark theme stylesheet = qtvscodestyle.load_stylesheet(qtvscodestyle.Theme.DARK_VS) self.setStyleSheet(stylesheet) def loadConfig(self): self.config.read(self.config_path) self.spt_base_dir = self.config.get('DEFAULT', 'sptBaseDir', fallback='') self.add_new_items_to = self.config.get('DEFAULT', 'addNewItemsTo', fallback='end') self.reminder = self.config.getboolean('DEFAULT', 'reminder', fallback=True) self.width = int(self.config.get('DEFAULT', 'width', fallback='400')) self.height = int(self.config.get('DEFAULT', 'height', fallback='300')) def checkModsDirectory(self): mods_dir = os.path.join(self.mod_dir, 'user', 'mods') if not os.path.exists(mods_dir): error_message = f"Could not find user/mods. This exe belongs in the base directory of SPT-AKI!\nCurrent Directory: {self.mod_dir}\nconfig.ini has been created in the current directory, where you can set the path if you prefer." QMessageBox.critical(self, "Error", error_message) return False return True def loadData(self, mod_dir): print("Loading mod data...") mod_info = [] order_file_path = os.path.join(mod_dir, 'user', 'mods', 'order.json') if os.path.exists(order_file_path): with open(order_file_path, 'r') as order_file: order_data = json.load(order_file) ordered_mods = order_data.get("order", []) for entry in os.scandir(os.path.join(mod_dir, "user", "mods")): if entry.is_dir(): package_file = os.path.join(entry.path, "package.json") if os.path.exists(package_file): print(f"Found package.json in {entry.path}") with open(package_file, 'r') as file: data = json.load(file) folder_name = os.path.basename(entry.path) mod_info.append({ "name": data["name"], "folder_name": folder_name, "version": data["version"], "author": data["author"], "akiVersion": data.get("akiVersion", "") }) print(f"akiVersion for {folder_name}: {data.get('akiVersion', '')}") if os.path.exists(order_file_path): ordered_mod_info = [] for mod_name in ordered_mods: for mod in mod_info: if mod["folder_name"] == mod_name: ordered_mod_info.append(mod) mod_info.remove(mod) break ordered_mod_info.extend(mod_info) mod_info = ordered_mod_info if self.add_new_items_to == 'start': self.list_widget.clear() for mod in mod_info: self.addListItem(mod, 0) elif self.add_new_items_to == 'end': for mod in mod_info: self.addListItem(mod) self.initial_order = [item.text() for item in [self.list_widget.item(i) for i in range(self.list_widget.count())]] def addListItem(self, mod, position=None): list_item = QListWidgetItem(mod["folder_name"]) tooltip_text = "\n".join([f"{key}: {value}" for key, value in mod.items()]) list_item.setToolTip(tooltip_text) if position is None: self.list_widget.addItem(list_item) else: self.list_widget.insertItem(position, list_item) def saveOrder(self, mod_dir): print("Saving order...") print(f"Mod directory: {mod_dir}") new_order = [self.list_widget.item(i).text() for i in range(self.list_widget.count())] print(f"New order: {new_order}") order_file_path = os.path.join(mod_dir, 'user', 'mods', 'order.json') backup_file_path = os.path.join(mod_dir, 'user', 'mods', 'order.bkp') try: shutil.copy(order_file_path, backup_file_path) print('Backup created successfully!') except Exception as e: print(f'Error creating backup: {e}') with open(order_file_path, 'w') as file: json.dump({"order": new_order}, file, indent=4) print('Order saved successfully!') self.initial_order = new_order self.config.set('DEFAULT', 'width', str(self.width)) self.config.set('DEFAULT', 'height', str(self.height)) with open(self.config_path, 'w') as configfile: self.config.write(configfile) def resizeEvent(self, event): self.width = self.size().width() self.height = self.size().height() event.accept() def closeEvent(self, event): if self.reminder and self.list_widget.count() > 0: current_order = [self.list_widget.item(i).text() for i in range(self.list_widget.count())] if current_order != self.initial_order: reply = QMessageBox.question(self, 'Reminder', 'You have unsaved changes.\nSave before closing?', QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.Yes: self.saveOrder(self.mod_dir) print(f"Current width: {self.width}, Current height: {self.height}") self.config.set('DEFAULT', 'width', str(self.width)) self.config.set('DEFAULT', 'height', str(self.height)) print(f"Updated width: {self.width}, Updated height: {self.height}") with open(self.config_path, 'w') as configfile: self.config.write(configfile) event.accept() if __name__ == '__main__': app = QApplication(sys.argv) window = DragDropApp() window.show() sys.exit(app.exec_())