import traceback, webbrowser from PyQt6.QtWidgets import ( QLabel, QPushButton, QWidget, QFrame, QSplitter, QStackedWidget, QListWidget, QListWidgetItem, QGraphicsScene, QGraphicsView, QGraphicsPixmapItem, QLayout, QScrollArea, QVBoxLayout, QHBoxLayout, QMessageBox ) from PyQt6.QtGui import QPixmap from PyQt6.QtCore import Qt, QAbstractListModel from dialogs import ErrorPopup, ListDialog from settings_widgets import SettingBox, SettingButton from extractor import CheckFFPROBE import os, sys, json from action_runner import ActionRunner, RunningDialog class SidebarPage(QFrame): def __init__(self, name): super().__init__() self.name = name self.setObjectName("SidebarPage") self.setStyleSheet("#SidebarPage { border: 1px solid #00000000; border-left-color: #444; }") self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) def AddWidget(self, widget) -> None: self.layout.addWidget(widget) def AddLayout(self, layout) -> None: self.layout.addLayout(layout) def AddSpacer(self) -> None: self.layout.addStretch(1) class SidebarButton(QPushButton): def __init__(self, text, parent): super().__init__(text, parent) self.defaultstyle = "border: 1px solid #00000000; padding: 4px 8px; color: #000; text-align: left;" self.setObjectName("SidebarButton") self.setStyleSheet("#SidebarButton { " + self.defaultstyle + " background-color: #00000000; }") def SetSelected(self, selected): if selected: self.setStyleSheet("#SidebarButton { " + self.defaultstyle + " background-color: #444; color: #fff; }") else: self.setStyleSheet("#SidebarButton { " + self.defaultstyle + " background-color: #00000000; }") class Sidebar(QFrame): def __init__(self): super().__init__() self.pages = [] self.setObjectName("Sidebar") self.mainlayout = QHBoxLayout() self.mainlayout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.mainlayout) self.left_base = QWidget() self.left_base.setFixedWidth(200) self.left = QVBoxLayout(self.left_base) # gap between buttons : 0px self.left.setSpacing(0) self.left.setAlignment(Qt.AlignmentFlag.AlignTop) self.left.setContentsMargins(0, 0, 0, 0) self.right_base = QWidget() self.right = QVBoxLayout(self.right_base) self.right.setAlignment(Qt.AlignmentFlag.AlignTop) self.right.setContentsMargins(0, 0, 0, 0) self.mainlayout.addWidget(self.left_base) self.mainlayout.addWidget(self.right_base) def swisthPage(self, index) -> QFrame: self.showPage(self.pages[index]) return self.pages[index] def AddButton(self, text) -> QPushButton: button = SidebarButton(text, self) self.left.addWidget(button) return button def showPage(self, page) -> None: for p in self.pages: p.hide() # get buttons for b in self.left_base.children(): if isinstance(b, QPushButton): b.SetSelected(False) if b.text() == page.name: b.SetSelected(True) page.show() def AddPage(self, name, page) -> None: # hide all pages button = self.AddButton(name) button.clicked.connect(lambda: self.showPage(page)) for p in self.pages: p.hide() self.right.addWidget(page) self.pages.append(page) return page class subpage_general(QFrame): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.setLayout(self.layout) self.setStyleSheet( "#subpage_general_title { font-size: 24px; font-weight: bold; }" ) header = QLabel("General") header.setObjectName("subpage_general_title") self.layout.addWidget(header) self.layout.addWidget(QLabel("General settings for the application.")) # settings self.layout.addWidget(SettingBox(self, "No general settings available.")) class subpage_requirements(QFrame): def __init__(self): super().__init__() self.layout = QVBoxLayout() self.setLayout(self.layout) self.setStyleSheet( "#subpage_requirements_title { font-size: 24px; font-weight: bold; }" ) header = QLabel("Requirements") header.setObjectName("subpage_requirements_title") self.layout.addWidget(header) self.layout.addWidget(QLabel("Important applications and libraries required for the application to function.")) setting_echo_test = SettingButton(self, "Echo Test", "Test the echo command.") setting_update_winget = SettingButton(self, "Manual download and install", "Download and install winget manually.") setting_install_ffprobe = SettingButton(self, "Install FFMPEG", "Install or update FFMPEG ( includes FFPROBE ) for media processing.") self.layout.addWidget(setting_echo_test) self.layout.addWidget(setting_update_winget) self.layout.addWidget(setting_install_ffprobe) if not CheckFFPROBE(): setting_install_ffprobe.SetText("Required: Install FFMPEG") setting_echo_test.SetButtonText("Run action") echo_test = ActionRunner("echo", ["Hello World!"]) FFMPEG_installer = ActionRunner("winget", ["install", "-e", "--id", "Gyan.FFmpeg"]) def echo_test_button(): run = echo_test.run() setting_echo_test.SetText("Echo Test Complete") setting_echo_test.SetDescription(run) setting_echo_test.SetButtonPressed(echo_test_button) setting_update_winget.SetButtonText("Start download") def update_winget(): # https://aka.ms/getwinget webbrowser.open("https://aka.ms/getwinget") setting_update_winget.SetButtonPressed(update_winget) setting_install_ffprobe.SetButtonText("Run action") def install_ffprobe(): warnmessage = QMessageBox() warnmessage.setWindowTitle("Winget Install") warnmessage.setIcon(QMessageBox.Icon.Warning) warnmessage.setText("It is recommended to install and update winget first.") warnmessage.setInformativeText("Do you want to continue?") warnmessage.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) warnmessage.setDefaultButton(QMessageBox.StandardButton.No) ret = warnmessage.exec() if ret == QMessageBox.StandardButton.No: return installed = CheckFFPROBE() print("Status:", installed) print(installed and "FFMPEG Upadting." or "FFMPEG Installing.") FFMPEG_installer.run() print(installed and "FFMPEG Upadted." or "FFMPEG Installed.") setting_install_ffprobe.SetText( installed and "FFPROBE Upadted." or "FFPROBE Installed." ) setting_install_ffprobe.SetButtonPressed(install_ffprobe) class SettingsTab(QFrame): def __init__(self): super().__init__() self.setStyleSheet( "#settinglabel { font-size: 16px; }" "#settingbutton, #settingbox { border: 1px solid #8c8c8c; padding: 4px 8px; border-radius: 4px;}" ) try: self.sidebar = Sidebar() # general = self.sidebar.AddButton("General") # general.clicked.connect(lambda: print("General")) # general = self.sidebar.AddButton("Requirements") # general.clicked.connect(lambda: print("Requirements")) page_general = SidebarPage( "General" ) page_general.AddWidget(subpage_general()) page_general.AddSpacer() page_requirements = SidebarPage( "Requirements" ) page_requirements.AddWidget(subpage_requirements()) page_requirements.AddSpacer() self.sidebar.AddPage("General", page_general) self.sidebar.AddPage("Requirements", page_requirements) self.sidebar.swisthPage(0) self.layout = QHBoxLayout() self.layout.addWidget(self.sidebar) self.setLayout(self.layout) self.setObjectName("Settings") except Exception as e: print("### SettingsTab Error ###") traceback.print_exc() self.layout = QVBoxLayout() self.layout.addWidget(QLabel("SettingsTab Error")) self.setLayout(self.layout)