305 lines
9.3 KiB
Python
305 lines
9.3 KiB
Python
import threading
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
|
|
from PySide6.QtCore import QSize, Qt, QObject, Signal, Slot
|
|
from PySide6.QtWidgets import QWidget, QVBoxLayout, QComboBox, QListWidget, QPushButton, QLabel, QHBoxLayout, \
|
|
QSizePolicy
|
|
|
|
from core_lib.game.version_info import get_all_versions, get_available_version_types
|
|
from manager.game import ManifestManager, GameManager
|
|
from manager.widgets import SignalTransferItem, WidgetManager
|
|
|
|
LOADER_LIST = {
|
|
"fabric": {
|
|
"type": "modded",
|
|
"loadVersionMethod": None,
|
|
},
|
|
"Don't Install": {
|
|
"type": "vanilla",
|
|
"loadVersionMethod": "official",
|
|
}
|
|
}
|
|
|
|
class CreateProfilePage(QWidget):
|
|
def __init__(self, app, parent=None):
|
|
super(CreateProfilePage, self).__init__(parent)
|
|
self.app = app
|
|
|
|
# Manager
|
|
self.widget_mgr: WidgetManager = app.widget_manager
|
|
self.game_mgr: GameManager = app.game_manager
|
|
self.manifest_mgr: ManifestManager = self.game_mgr.manifest
|
|
|
|
# Layout
|
|
self.layout = QVBoxLayout()
|
|
self.content_layout = QHBoxLayout()
|
|
|
|
self.main_layout = QVBoxLayout()
|
|
self.right_layout = QVBoxLayout()
|
|
self.operate_layout = QHBoxLayout()
|
|
|
|
# Some items
|
|
self.version_type_label = QLabel("Version Type")
|
|
self.version_type_dropdown = QComboBox()
|
|
self.version_type_dropdown.setObjectName("Dropdown")
|
|
|
|
# Mod loader
|
|
self.mod_loader_icon_label = QLabel()
|
|
icon = self.app.get_icon(Path(self.app.icon_dir, "mod_loader_temp.png"))
|
|
pixmap = icon.pixmap(QSize(100, 100))
|
|
self.mod_loader_icon_label.setPixmap(pixmap)
|
|
self.mod_loader_label = QLabel("Mod Loader")
|
|
self.mod_loader_dropdown = QComboBox()
|
|
self.mod_loader_dropdown.setObjectName("Dropdown")
|
|
|
|
# Mod loader layout
|
|
self.mod_config_layout = QHBoxLayout()
|
|
self.mod_config_fields_layout = QVBoxLayout()
|
|
|
|
self.mod_loader_version_label = QLabel(
|
|
"Mod Loader Version"
|
|
)
|
|
|
|
self.mod_loader_version_list = QListWidget()
|
|
self.mod_loader_version_list.setObjectName(
|
|
"ListWidget"
|
|
)
|
|
|
|
# Version list
|
|
self.version_list_type_label = QLabel("Version: Vanilla")
|
|
self.version_list_label = QLabel("Select a version to continue:")
|
|
self.version_list = QListWidget()
|
|
self.version_list.setObjectName("ListWidget")
|
|
|
|
# Button
|
|
self.create_profile = QPushButton("Create Profile")
|
|
self.create_profile.setObjectName("Button")
|
|
|
|
self.refresh_button = QPushButton("Refresh")
|
|
self.refresh_button.setObjectName("Button")
|
|
|
|
# Bind widget
|
|
self.main_layout.addWidget(self.version_list_label)
|
|
self.main_layout.addWidget(self.version_list)
|
|
self.operate_layout.addWidget(self.version_list_type_label)
|
|
self.operate_layout.addStretch()
|
|
self.operate_layout.addWidget(self.refresh_button)
|
|
self.operate_layout.addWidget(self.create_profile)
|
|
|
|
self.mod_config_fields_layout.addWidget(
|
|
self.mod_loader_label
|
|
)
|
|
self.mod_config_fields_layout.addWidget(
|
|
self.mod_loader_dropdown
|
|
)
|
|
self.mod_config_fields_layout.addWidget(
|
|
self.version_type_label
|
|
)
|
|
self.mod_config_fields_layout.addWidget(
|
|
self.version_type_dropdown
|
|
)
|
|
self.mod_config_fields_layout.addStretch()
|
|
self.mod_config_layout.addWidget(
|
|
self.mod_loader_icon_label,
|
|
alignment=Qt.AlignmentFlag.AlignTop,
|
|
)
|
|
self.mod_config_layout.addLayout(
|
|
self.mod_config_fields_layout
|
|
)
|
|
self.right_layout.addLayout(
|
|
self.mod_config_layout
|
|
)
|
|
|
|
self.right_layout.addWidget(self.mod_loader_version_label)
|
|
self.right_layout.addWidget(
|
|
self.mod_loader_version_list,
|
|
1,
|
|
)
|
|
self.mod_loader_version_list.setSizePolicy(
|
|
QSizePolicy.Policy.Expanding,
|
|
QSizePolicy.Policy.Expanding,
|
|
)
|
|
self.right_layout.setContentsMargins(0, 20, 0, 0)
|
|
|
|
self.setLayout(self.layout)
|
|
self.content_layout.addLayout(
|
|
self.main_layout,
|
|
stretch=2,
|
|
)
|
|
self.content_layout.addLayout(
|
|
self.right_layout,
|
|
stretch=1,
|
|
)
|
|
|
|
self.layout.addLayout(
|
|
self.content_layout,
|
|
stretch=1,
|
|
)
|
|
self.layout.addLayout(
|
|
self.operate_layout,
|
|
)
|
|
|
|
# Signals
|
|
self.signals = self.PageSignal()
|
|
|
|
self.signals.get_selected_type.connect(self.get_selected_type)
|
|
self.signals.get_selected_version.connect(self.get_selected_version)
|
|
self.signals.update_type_dropdown.connect(self.update_type_dropdown)
|
|
self.signals.update_version_dropdown.connect(self.update_version_dropdown)
|
|
|
|
# events
|
|
self.type_list_loading = threading.Event()
|
|
self.version_list_loading = threading.Event()
|
|
|
|
self.init_all()
|
|
|
|
class PageSignal(QObject):
|
|
mod_loader_dropdown_changed = Signal(str)
|
|
load_version_list = Signal()
|
|
|
|
# widget
|
|
clean_list = Signal(object)
|
|
update_version_dropdown = Signal(list)
|
|
update_type_dropdown = Signal(list)
|
|
update_mod_loader_icon_label = Signal(object)
|
|
update_mod_loader_dropdown = Signal(list)
|
|
update_mod_loader_version_list = Signal(list)
|
|
|
|
get_selected_version = Signal(object)
|
|
get_selected_type = Signal(object)
|
|
|
|
#
|
|
# Signal Handler
|
|
#
|
|
@staticmethod
|
|
def clean_list(target_list: QListWidget | QComboBox):
|
|
if not isinstance(target_list, QListWidget | QComboBox):
|
|
raise TypeError("Target list is not a QListWidget")
|
|
|
|
target_list.clear()
|
|
|
|
@Slot(dict)
|
|
def get_selected_type(self, item: SignalTransferItem):
|
|
if not isinstance(item, SignalTransferItem):
|
|
raise TypeError("Item is not a SignalTransferItem")
|
|
|
|
selected_type = self.version_type_dropdown.currentText()
|
|
|
|
if not selected_type:
|
|
item.result_queue.put(None)
|
|
else:
|
|
item.result_queue.put(selected_type)
|
|
|
|
item.wait_event.set()
|
|
|
|
@Slot(object)
|
|
def get_selected_version(self, item: SignalTransferItem):
|
|
if not isinstance(item, SignalTransferItem):
|
|
raise TypeError("Item is not a SignalTransferItem")
|
|
|
|
selected_item = self.version_list.currentItem()
|
|
|
|
if selected_item is None:
|
|
item.result_queue.put(None)
|
|
else:
|
|
item.result_queue.put(selected_item.text())
|
|
|
|
item.wait_event.set()
|
|
|
|
def update_type_dropdown(self, types: list):
|
|
# Move release to top
|
|
if "release" in types:
|
|
types.pop(types.index("release"))
|
|
types.insert(0, "release")
|
|
|
|
self.version_type_dropdown.addItems(types)
|
|
|
|
if len(self.version_type_dropdown.currentText()) == 0:
|
|
self.version_type_dropdown.setCurrentIndex(0)
|
|
|
|
def update_version_dropdown(self, versions: list):
|
|
ids = []
|
|
|
|
for version in versions:
|
|
ver_id = version.get("id", None)
|
|
if ver_id is not None:
|
|
ids.append(ver_id)
|
|
|
|
self.version_list.addItems(ids)
|
|
|
|
selected_item = self.version_list.currentItem()
|
|
|
|
if selected_item is None and len(ids) > 0:
|
|
self.version_list.setCurrentRow(0)
|
|
|
|
#
|
|
# Thread Starter
|
|
#
|
|
def init_all(self):
|
|
self.start_load_type_list(callback=self.start_load_version_list)
|
|
|
|
def start_load_type_list(self, callback=None):
|
|
thread = threading.Thread(target=self.load_type_list, args=(callback,))
|
|
thread.start()
|
|
|
|
def start_load_version_list(self):
|
|
thread = threading.Thread(target=self.load_version_list)
|
|
thread.start()
|
|
|
|
def start_load_mod_loader_list_and_version(self):
|
|
pass
|
|
|
|
#
|
|
# Background Thread
|
|
#
|
|
def load_type_list(self, callback: Callable[None]=None):
|
|
# Cleanup
|
|
self.signals.clean_list.emit(self.version_type_dropdown)
|
|
|
|
manifest = self.manifest_mgr.get_cached_version_manifest()
|
|
if not manifest:
|
|
return
|
|
|
|
ver_types = get_available_version_types(manifest)
|
|
|
|
self.signals.update_type_dropdown.emit(ver_types)
|
|
|
|
if callable(callback):
|
|
callback()
|
|
|
|
def load_version_list(self, callback: Callable[Callable[None] | None]=None):
|
|
# Cleanup
|
|
self.version_list.clear()
|
|
|
|
# Get selected version type
|
|
request = SignalTransferItem()
|
|
self.signals.get_selected_type.emit(request)
|
|
|
|
if not request.wait(10):
|
|
self.widget_mgr.signal.show_error_message.emit(
|
|
"Timeout while waiting for selected type.",
|
|
)
|
|
return
|
|
|
|
selected_type = request.result()
|
|
|
|
if not selected_type:
|
|
self.widget_mgr.signal.show_warning_message.emit(
|
|
"No type selected.",
|
|
)
|
|
return
|
|
|
|
# Fetch (or read) manifest
|
|
manifest = self.manifest_mgr.get_cached_version_manifest()
|
|
versions = get_all_versions(
|
|
manifest,
|
|
specified_type=selected_type
|
|
)
|
|
|
|
# Update list
|
|
self.update_version_dropdown(versions)
|
|
|
|
if callable(callback):
|
|
callback(None)
|