Now game dir is the correct path.
Add experimental manage profile page.
This commit is contained in:
@@ -46,7 +46,7 @@ class Launcher(QApplication, LauncherObject):
|
||||
self.game_manager = GameManager(self)
|
||||
|
||||
# Window config
|
||||
self.setApplicationName("TestLauncher")
|
||||
self.setApplicationName("TapLauncher")
|
||||
self.main_window = LauncherMainWindow(
|
||||
app=self
|
||||
)
|
||||
@@ -139,7 +139,8 @@ class Launcher(QApplication, LauncherObject):
|
||||
|
||||
@property
|
||||
def default_game_dir(self) -> Path:
|
||||
return self.work_dir / "minecraft" if sys.platform.lower() == "darwin" else self.work_dir / ".minecraft"
|
||||
# Completely with official Minecraft launcher
|
||||
return self.work_dir
|
||||
|
||||
@property
|
||||
def resources_dir(self):
|
||||
|
||||
+2
-2
@@ -667,13 +667,13 @@ class ProfileManager(QObject):
|
||||
if not isinstance(request.icon, str):
|
||||
errors["icon"] = "Icon must be a string."
|
||||
|
||||
if request.game_dir is not _UNSET:
|
||||
if request.game_dir is not _UNSET and request.game_dir is not None:
|
||||
try:
|
||||
Path(request.game_dir)
|
||||
except (TypeError, ValueError):
|
||||
errors["game_dir"] = "Game directory is invalid."
|
||||
|
||||
if request.game_dir is not _UNSET:
|
||||
if request.resolution is not _UNSET and request.resolution is not None:
|
||||
if not isinstance(request.resolution, tuple) or len(request.resolution) != 2:
|
||||
errors["resolution"] = (
|
||||
"Resolution must contain width and height."
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"""Launcher settings schemas persisted by SettingsManager."""
|
||||
|
||||
from typing import Literal
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, ConfigDict
|
||||
|
||||
from constant import CLIENT_ID
|
||||
|
||||
|
||||
class GeneralSettings(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
language: Literal["en", "zh-TW"] = "zh-TW"
|
||||
|
||||
|
||||
class AppearanceSettings(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
theme: Literal["system", "light", "dark"] = "system"
|
||||
|
||||
|
||||
class AccountSettings(BaseModel):
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
client_id: UUID = UUID(CLIENT_ID)
|
||||
@@ -0,0 +1,312 @@
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import Qt, QUrl, Signal
|
||||
from PySide6.QtGui import QDesktopServices, QIcon
|
||||
from PySide6.QtWidgets import (
|
||||
QFileDialog, QFormLayout, QFrame, QHBoxLayout, QLabel, QLineEdit,
|
||||
QMessageBox, QPushButton, QScrollArea, QSizePolicy, QSpinBox,
|
||||
QVBoxLayout, QWidget,
|
||||
)
|
||||
|
||||
from manager.profile import ProfileDetail, ProfileManager, ProfileSummary, UpdateProfileRequest
|
||||
|
||||
|
||||
class ManageProfileItem(QPushButton):
|
||||
selected = Signal(object)
|
||||
|
||||
def __init__(self, app, profile: ProfileSummary, parent=None):
|
||||
super().__init__(parent)
|
||||
self.profile = profile
|
||||
self.setObjectName("manageProfileItem")
|
||||
self.setCheckable(True)
|
||||
self.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.setMinimumHeight(64)
|
||||
|
||||
layout = QHBoxLayout(self)
|
||||
layout.setContentsMargins(12, 8, 12, 8)
|
||||
layout.setSpacing(12)
|
||||
|
||||
icon_path = Path(profile.icon)
|
||||
if not icon_path.is_file():
|
||||
icon_path = Path(app.icon_dir, "profile_default.png")
|
||||
icon = QLabel()
|
||||
icon.setFixedSize(40, 40)
|
||||
icon.setPixmap(QIcon(icon_path.as_posix()).pixmap(36, 36))
|
||||
icon.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
|
||||
texts = QVBoxLayout()
|
||||
texts.setSpacing(1)
|
||||
name = QLabel(profile.display_name)
|
||||
name.setObjectName("itemName")
|
||||
version = QLabel(profile.version_id)
|
||||
version.setObjectName("itemVersion")
|
||||
texts.addWidget(name)
|
||||
texts.addWidget(version)
|
||||
|
||||
layout.addWidget(icon)
|
||||
layout.addLayout(texts, 1)
|
||||
self.clicked.connect(lambda: self.selected.emit(self.profile))
|
||||
|
||||
|
||||
class ManageProfilePage(QWidget):
|
||||
"""Select a profile on the left and edit its launcher settings on the right."""
|
||||
|
||||
def __init__(self, app, parent=None):
|
||||
super().__init__(parent)
|
||||
self.app = app
|
||||
self.profile_manager: ProfileManager = app.profile_manager
|
||||
self.selected_profile_id: str | None = None
|
||||
self.profile_items: dict[str, ManageProfileItem] = {}
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
title = QLabel("Manage Profiles (Experimental)")
|
||||
title.setObjectName("manageTitle")
|
||||
root.addWidget(title)
|
||||
|
||||
columns = QHBoxLayout()
|
||||
columns.setSpacing(12)
|
||||
root.addLayout(columns, 1)
|
||||
|
||||
self.list_scroll = self._scroll_area("manageProfileListScroll")
|
||||
self.list_content = QWidget()
|
||||
self.list_layout = QVBoxLayout(self.list_content)
|
||||
self.list_layout.setContentsMargins(6, 6, 6, 6)
|
||||
self.list_layout.setSpacing(4)
|
||||
self.list_layout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
self.list_scroll.setWidget(self.list_content)
|
||||
self.list_scroll.setMinimumWidth(260)
|
||||
self.list_scroll.setMaximumWidth(380)
|
||||
columns.addWidget(self.list_scroll, 2)
|
||||
|
||||
self.options_scroll = self._scroll_area("manageProfileOptionsScroll")
|
||||
self.options_content = QWidget()
|
||||
self.options_layout = QVBoxLayout(self.options_content)
|
||||
self.options_layout.setContentsMargins(20, 16, 20, 20)
|
||||
self.options_layout.setSpacing(14)
|
||||
self.options_scroll.setWidget(self.options_content)
|
||||
columns.addWidget(self.options_scroll, 3)
|
||||
|
||||
self.empty_label = QLabel("Select a profile from the list to edit its settings.")
|
||||
self.empty_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.empty_label.setWordWrap(True)
|
||||
self.options_layout.addWidget(self.empty_label, 1)
|
||||
|
||||
self.editor = QFrame()
|
||||
self.editor.setObjectName("profileEditor")
|
||||
editor_layout = QVBoxLayout(self.editor)
|
||||
editor_layout.setSpacing(14)
|
||||
form = QFormLayout()
|
||||
form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.ExpandingFieldsGrow)
|
||||
form.setVerticalSpacing(12)
|
||||
|
||||
self.name_edit = QLineEdit()
|
||||
self.version_edit = QLineEdit()
|
||||
self.type_edit = QLineEdit()
|
||||
self.game_dir_edit = QLineEdit()
|
||||
self.java_args_edit = QLineEdit()
|
||||
self.icon_edit = QLineEdit()
|
||||
self.width_spin = self._dimension_spin()
|
||||
self.height_spin = self._dimension_spin()
|
||||
|
||||
form.addRow("Profile name", self.name_edit)
|
||||
form.addRow("Version ID", self.version_edit)
|
||||
form.addRow("Profile type", self.type_edit)
|
||||
form.addRow("Game directory", self.game_dir_edit)
|
||||
form.addRow("Java arguments", self.java_args_edit)
|
||||
form.addRow("Icon", self.icon_edit)
|
||||
|
||||
resolution = QHBoxLayout()
|
||||
resolution.addWidget(self.width_spin)
|
||||
resolution.addWidget(QLabel("×"))
|
||||
resolution.addWidget(self.height_spin)
|
||||
form.addRow("Resolution", resolution)
|
||||
editor_layout.addLayout(form)
|
||||
|
||||
file_actions = QHBoxLayout()
|
||||
open_button = QPushButton("Open Profile Folder")
|
||||
open_button.clicked.connect(self.open_profile_folder)
|
||||
import_button = QPushButton("Import Mods…")
|
||||
import_button.clicked.connect(self.import_mods)
|
||||
file_actions.addWidget(open_button)
|
||||
file_actions.addWidget(import_button)
|
||||
file_actions.addStretch()
|
||||
editor_layout.addLayout(file_actions)
|
||||
|
||||
actions = QHBoxLayout()
|
||||
duplicate_button = QPushButton("Duplicate")
|
||||
duplicate_button.clicked.connect(self.duplicate_profile)
|
||||
delete_button = QPushButton("Delete")
|
||||
delete_button.setObjectName("dangerButton")
|
||||
delete_button.clicked.connect(self.delete_profile)
|
||||
save_button = QPushButton("Save Changes")
|
||||
save_button.setObjectName("saveProfileButton")
|
||||
save_button.clicked.connect(self.save_profile)
|
||||
actions.addWidget(duplicate_button)
|
||||
actions.addWidget(delete_button)
|
||||
actions.addStretch()
|
||||
actions.addWidget(save_button)
|
||||
editor_layout.addLayout(actions)
|
||||
|
||||
self.options_layout.addWidget(self.editor)
|
||||
self.options_layout.addStretch()
|
||||
self.editor.hide()
|
||||
|
||||
self.profile_manager.profiles_changed.connect(self.load_profiles)
|
||||
self.app.apply_qss(Path("manage_profile.qss"), self.setStyleSheet)
|
||||
self.load_profiles()
|
||||
|
||||
@staticmethod
|
||||
def _scroll_area(name: str) -> QScrollArea:
|
||||
area = QScrollArea()
|
||||
area.setObjectName(name)
|
||||
area.setWidgetResizable(True)
|
||||
area.setFrameShape(QFrame.Shape.NoFrame)
|
||||
area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
return area
|
||||
|
||||
@staticmethod
|
||||
def _dimension_spin() -> QSpinBox:
|
||||
spin = QSpinBox()
|
||||
spin.setRange(0, 16384)
|
||||
spin.setSpecialValueText("Default")
|
||||
spin.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
return spin
|
||||
|
||||
def load_profiles(self) -> None:
|
||||
while self.list_layout.count():
|
||||
item = self.list_layout.takeAt(0)
|
||||
if item.widget():
|
||||
item.widget().deleteLater()
|
||||
self.profile_items.clear()
|
||||
|
||||
profiles = self.profile_manager.list_profiles()
|
||||
for profile in profiles:
|
||||
item = ManageProfileItem(self.app, profile, self.list_content)
|
||||
item.selected.connect(self.select_profile)
|
||||
self.profile_items[profile.id] = item
|
||||
self.list_layout.addWidget(item)
|
||||
|
||||
available_ids = {profile.id for profile in profiles}
|
||||
if self.selected_profile_id not in available_ids:
|
||||
self.selected_profile_id = None
|
||||
if self.selected_profile_id is None and profiles:
|
||||
current = self.profile_manager.get_current_profile_id()
|
||||
selected = next((p for p in profiles if p.id == current), profiles[0])
|
||||
self.select_profile(selected)
|
||||
elif self.selected_profile_id:
|
||||
profile = next(p for p in profiles if p.id == self.selected_profile_id)
|
||||
self.select_profile(profile)
|
||||
else:
|
||||
self.editor.hide()
|
||||
self.empty_label.show()
|
||||
|
||||
def select_profile(self, profile: ProfileSummary) -> None:
|
||||
detail = self.profile_manager.get_profile(profile.id)
|
||||
if detail is None:
|
||||
return
|
||||
self.selected_profile_id = profile.id
|
||||
for profile_id, item in self.profile_items.items():
|
||||
item.setChecked(profile_id == profile.id)
|
||||
self._set_detail(detail)
|
||||
self.empty_label.hide()
|
||||
self.editor.show()
|
||||
|
||||
def _set_detail(self, profile: ProfileDetail) -> None:
|
||||
self.name_edit.setText(profile.name)
|
||||
self.version_edit.setText(profile.version_id)
|
||||
self.type_edit.setText(profile.version_type)
|
||||
self.game_dir_edit.setText(str(profile.game_dir or ""))
|
||||
self.java_args_edit.setText(profile.java_args)
|
||||
self.icon_edit.setText(profile.icon)
|
||||
width, height = profile.resolution or (0, 0)
|
||||
self.width_spin.setValue(width)
|
||||
self.height_spin.setValue(height)
|
||||
|
||||
def _profile_dir(self) -> Path | None:
|
||||
if self.selected_profile_id is None:
|
||||
return None
|
||||
detail = self.profile_manager.get_profile(self.selected_profile_id)
|
||||
if detail is None:
|
||||
return None
|
||||
return detail.game_dir or Path(self.app.default_game_dir)
|
||||
|
||||
def save_profile(self) -> None:
|
||||
if self.selected_profile_id is None:
|
||||
return
|
||||
width, height = self.width_spin.value(), self.height_spin.value()
|
||||
if (width == 0) != (height == 0):
|
||||
self.app.widget_manager.signal.show_warning_message.emit(
|
||||
"Set both resolution values, or set both to Default."
|
||||
)
|
||||
return
|
||||
game_dir_text = self.game_dir_edit.text().strip()
|
||||
request = UpdateProfileRequest(
|
||||
name=self.name_edit.text().strip(),
|
||||
version_id=self.version_edit.text().strip(),
|
||||
version_type=self.type_edit.text().strip(),
|
||||
game_dir=Path(game_dir_text) if game_dir_text else None,
|
||||
java_args=self.java_args_edit.text(),
|
||||
icon=self.icon_edit.text().strip(),
|
||||
resolution=(width, height) if width and height else None,
|
||||
)
|
||||
if self.profile_manager.validate_update(request).is_valid and self.profile_manager.update_profile(
|
||||
self.selected_profile_id, request
|
||||
):
|
||||
self.profile_manager.save()
|
||||
self.app.widget_manager.signal.show_info_message.emit("Profile settings saved.")
|
||||
else:
|
||||
errors = self.profile_manager.validate_update(request).errors
|
||||
if errors:
|
||||
self.app.widget_manager.signal.show_warning_message.emit("\n".join(errors.values()))
|
||||
|
||||
def open_profile_folder(self) -> None:
|
||||
profile_dir = self._profile_dir()
|
||||
if profile_dir is None:
|
||||
return
|
||||
profile_dir.mkdir(parents=True, exist_ok=True)
|
||||
QDesktopServices.openUrl(QUrl.fromLocalFile(str(profile_dir.resolve())))
|
||||
|
||||
def import_mods(self) -> None:
|
||||
profile_dir = self._profile_dir()
|
||||
if profile_dir is None:
|
||||
return
|
||||
files, _ = QFileDialog.getOpenFileNames(
|
||||
self, "Import Mods", "", "Minecraft mods (*.jar *.zip);;All files (*)"
|
||||
)
|
||||
if not files:
|
||||
return
|
||||
mods_dir = profile_dir / "mods"
|
||||
mods_dir.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
for source in files:
|
||||
shutil.copy2(source, mods_dir / Path(source).name)
|
||||
except OSError as error:
|
||||
self.app.widget_manager.signal.show_error_message.emit(f"Unable to import mod: {error}")
|
||||
return
|
||||
self.app.widget_manager.signal.show_info_message.emit(
|
||||
f"Imported {len(files)} mod(s) into {mods_dir}."
|
||||
)
|
||||
|
||||
def duplicate_profile(self) -> None:
|
||||
if self.selected_profile_id is None:
|
||||
return
|
||||
new_id = self.profile_manager.duplicate_profile(self.selected_profile_id)
|
||||
if new_id:
|
||||
self.selected_profile_id = new_id
|
||||
self.load_profiles()
|
||||
self.profile_manager.save()
|
||||
|
||||
def delete_profile(self) -> None:
|
||||
if self.selected_profile_id is None:
|
||||
return
|
||||
answer = QMessageBox.question(
|
||||
self, "Delete Profile", "Delete this profile? Game files will not be removed.",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||
QMessageBox.StandardButton.No,
|
||||
)
|
||||
if answer == QMessageBox.StandardButton.Yes:
|
||||
profile_id = self.selected_profile_id
|
||||
self.selected_profile_id = None
|
||||
if self.profile_manager.remove_profile(profile_id):
|
||||
self.profile_manager.save()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,33 @@
|
||||
QLabel#manageTitle {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
padding: 4px 2px 8px 2px;
|
||||
}
|
||||
|
||||
QScrollArea#manageProfileListScroll,
|
||||
QScrollArea#manageProfileOptionsScroll {
|
||||
background: palette(base);
|
||||
border: 1px solid palette(mid);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
QPushButton#manageProfileItem {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
QLabel#itemVersion {
|
||||
color: #aeb6c2;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
QPushButton#manageProfileItem:hover { background: palette(midlight); }
|
||||
QPushButton#manageProfileItem:checked { background: #3d6fb4; }
|
||||
|
||||
QLabel#itemName { font-size: 15px; font-weight: 600; }
|
||||
|
||||
QFrame#profileEditor { background: transparent; }
|
||||
QPushButton#saveProfileButton { min-width: 130px; font-weight: 600; }
|
||||
QPushButton#dangerButton { color: #e56b6f; }
|
||||
@@ -0,0 +1,84 @@
|
||||
QWidget#settingsPage,
|
||||
QWidget#settingsMainPage,
|
||||
QWidget#settingsScrollContent {
|
||||
background-color: palette(window);
|
||||
}
|
||||
|
||||
QScrollArea#settingsScrollArea {
|
||||
border: none;
|
||||
background-color: palette(window);
|
||||
}
|
||||
|
||||
QScrollArea#settingsScrollArea > QWidget > QWidget {
|
||||
background-color: palette(window);
|
||||
}
|
||||
|
||||
QLabel#settingsPageTitle {
|
||||
font-size: 18pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QPushButton#settingsItem {
|
||||
min-height: 68px;
|
||||
border: 1px solid palette(mid);
|
||||
border-radius: 8px;
|
||||
background-color: palette(button);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
QPushButton#settingsItem:hover {
|
||||
background-color: palette(midlight);
|
||||
}
|
||||
|
||||
QPushButton#settingsItem:pressed {
|
||||
background-color: palette(dark);
|
||||
}
|
||||
|
||||
QLabel#settingsItemTitle {
|
||||
color: palette(button-text);
|
||||
font-size: 11pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QLabel#settingsItemDescription {
|
||||
color: palette(placeholder-text);
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
QLabel#settingsHelpText {
|
||||
color: palette(placeholder-text);
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
QPushButton#settingsBackButton {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background-color: transparent;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
QPushButton#settingsBackButton:hover {
|
||||
background-color: palette(button);
|
||||
}
|
||||
|
||||
QPushButton#settingsBackButton:pressed {
|
||||
background-color: palette(midlight);
|
||||
}
|
||||
|
||||
QLabel#settingsSubPageTitle {
|
||||
font-size: 15pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QLabel#settingsBrand {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
QLabel#settingsVersion {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
QPlainTextEdit#settingsDescription {
|
||||
font-size: 13px;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ from manager.widgets import AskForRequest, SelectPathRequest
|
||||
from pages.account import AccountPage
|
||||
from pages.create_profile import CreateProfilePage
|
||||
from pages.launch_profile import LaunchProfilePage
|
||||
from pages.manage_profile import ManageProfilePage
|
||||
from pages.test import TestPage
|
||||
from pages.settings import SettingsPage
|
||||
|
||||
@@ -163,6 +164,9 @@ class LauncherMainWindow(QMainWindow):
|
||||
# Profile page
|
||||
self.create_profile_page = CreateProfilePage(self.app, self)
|
||||
|
||||
# Profile management page
|
||||
self.manage_profile_page = ManageProfilePage(self.app, self)
|
||||
|
||||
# Settings page
|
||||
self.settings_page = SettingsPage(self.app, self)
|
||||
|
||||
@@ -172,6 +176,7 @@ class LauncherMainWindow(QMainWindow):
|
||||
self.central.addWidget(self.account_page)
|
||||
self.central.addWidget(self.settings_page)
|
||||
self.central.addWidget(self.create_profile_page)
|
||||
self.central.addWidget(self.manage_profile_page)
|
||||
self.central.addWidget(self.launch_profile_page)
|
||||
|
||||
# Bind toolbar and center widget
|
||||
@@ -193,24 +198,32 @@ class LauncherMainWindow(QMainWindow):
|
||||
icon=self.app.get_icon(Path(self.app.icon_dir, "profile_default.png"), True))
|
||||
|
||||
# Home btn
|
||||
self.home_button = self.toolbar.add_button(icon=self.app.get_icon(Path(self.app.icon_dir, "home.png")))
|
||||
self.home_button = self.toolbar.add_button(" Home", icon=self.app.get_icon(Path(self.app.icon_dir, "home.png")))
|
||||
|
||||
# Settings btn (will be moved to the bottom of the toolbar)
|
||||
self.open_settings_page = self.toolbar.add_button(icon=self.app.get_icon(Path(self.app.icon_dir, "settings.png")))
|
||||
self.open_settings_page = self.toolbar.add_button(" Settings", icon=self.app.get_icon(Path(self.app.icon_dir, "settings.png")))
|
||||
|
||||
# Account btn (will be moved to the bottom (or last one item) of the toolbar
|
||||
self.open_account_page = self.toolbar.add_button(icon=self.app.get_icon(Path(self.app.icon_dir, "head.png"), True))
|
||||
self.open_account_page = self.toolbar.add_button(" Accounts", icon=self.app.get_icon(Path(self.app.icon_dir, "head.png"), True))
|
||||
self.account_page.set_related_button(self.open_account_page) # AccountPage require this to set button icon to
|
||||
# current account's avatar
|
||||
|
||||
# Profile btn
|
||||
self.open_create_profile_page = self.toolbar.add_button(icon=self.app.get_icon(Path(self.app.icon_dir, "add.png")))
|
||||
self.open_create_profile_page = self.toolbar.add_button("Create Profile",
|
||||
icon=self.app.get_icon(Path(self.app.icon_dir, "add.png")))
|
||||
|
||||
# manage profile
|
||||
self.open_manage_profile_page = self.toolbar.add_button(
|
||||
" Manage Profiles",
|
||||
icon=self.app.get_icon(Path(self.app.icon_dir, "profile_edit.png"), True),
|
||||
)
|
||||
|
||||
# Bind tool buttons
|
||||
self.toolbar.addWidget(self.home_button)
|
||||
self.toolbar.addWidget(self.open_test_page)
|
||||
self.toolbar.addWidget(self.open_create_profile_page)
|
||||
self.toolbar.addWidget(self.open_launch_profile_page)
|
||||
self.toolbar.addWidget(self.open_manage_profile_page)
|
||||
self.toolbar.setMovable(True)
|
||||
self.toolbar.setFloatable(False)
|
||||
self.toolbar.setAllowedAreas(Qt.ToolBarArea.AllToolBarAreas)
|
||||
@@ -245,6 +258,10 @@ class LauncherMainWindow(QMainWindow):
|
||||
lambda: self.set_current_page(self.create_profile_page, self.open_create_profile_page)
|
||||
)
|
||||
|
||||
self.open_manage_profile_page.clicked.connect(
|
||||
lambda: self.set_current_page(self.manage_profile_page, self.open_manage_profile_page)
|
||||
)
|
||||
|
||||
# Bind signal event
|
||||
self.bind_event()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user