Skip to content

Commit

Permalink
[VERY WIP] refactor: Use lazy importing throughout the codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
kleidis committed Oct 21, 2024
1 parent 17a0ad9 commit d7a1cd0
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 160 deletions.
157 changes: 45 additions & 112 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,58 +1,46 @@
from imports import *
from ui_init import *

class Online:
def init (self):
self.troppical_database = self.fetch_data()

def fetch_data(self):
url = "https://raw.githubusercontent.com/kleidis/test/main/troppical-data.json"
response = requests.get(url)
if response.status_code == 200:
all_data = response.json()
self.troppical_database = [item for item in all_data if item.get('emulator_platform') != 'android']
return self.troppical_database
else:
print("Failed to fetch data:", response.status_code)

def get_latest_git_tag():
tag = "1.0"
github_token = os.getenv("GITHUB_TOKEN", "")
try:
command = f"GH_TOKEN={github_token} gh release list --limit 1 --json tagName --jq '.[0].tagName'"
process = subprocess.Popen(['bash', '-c', command], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
if process.returncode == 0:
tag = out.decode('utf-8').strip()
if tag.startswith("v"):
tag = tag[1:]
else:
print(f"Failed to get latest GitHub release tag: {err.decode('utf-8')}")
except Exception as e:
print(f"Failed to get latest GitHub release tag: {e}")
return tag

class Logic:
from PyQt6.QtWidgets import QApplication, QMessageBox, QFileDialog, QInputDialog
from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot
import requests
import os
import subprocess
import sys
from zipfile import ZipFile
import shutil
import tempfile
from icons import styledark_rc
import win32com.client
import winreg
from pathlib import Path
from init_instances import inst

class Main():
def __init__(self):
self.regvalue = None
self.install_mode = None
self.emulator = None

def initialize_app(self):
version = inst.online.get_latest_git_tag()
app = QApplication(sys.argv)
ui_main = inst.ui
ui_main.show()
sys.exit(app.exec())

# Set which emulator to use for the installer depeanding on the selected emulator
def set_emulator(self):
selected_item = MainWindow.instances().selection_page.emulatorTreeWidget.currentItem()
print (selected_item)
def set_emulator(self, selection_page):
selected_item = selection_page.emulatorTreeWidget.currentItem()
print(selected_item)
if not selected_item or not selected_item.parent():
QMessageBox.warning(SelectionPage.window, "Selection Error", "Please select an emulator.")
print ("Please select an emulator.")
QMessageBox.warning(selection_page.window, "Selection Error", "Please select an emulator.")
print("Please select an emulator.")
return

emulator_name = selected_item.text(0)
if self.emulator != emulator_name:
# Clear previous emulator settings
qtui.labeldown.setText("Downloading: ")
qtui.labelext.setText("Extracting: ")
qtui.welcomerLabel.setText("")
inst.progress_bar_page_instance.labeldown.setText("Downloading: ")
inst.ui.labelext.setText("Extracting: ")
inst.ui.welcomerLabel.setText("")

# Set new emulator
self.emulator = emulator_name
Expand All @@ -64,48 +52,27 @@ def set_emulator(self):
# Update UI components with new emulator settings
reg_result = self.checkreg()
installed_emulator = "Not Installed" if reg_result is None else reg_result[1]
qtui.installationPathLineEdit.setText(os.path.join(os.environ['LOCALAPPDATA'], self.emulator))
qtui.labeldown.setText("Downloading: " + self.emulator)
qtui.labelext.setText("Extracting: " + self.emulator)
qtui.welcomerLabel.setText(f'<big>Your currently selected emulator is <b>{self.emulator}</b> and current version is <b>{installed_emulator}</b>.</big>')
inst.ui.installationPathLineEdit.setText(os.path.join(os.environ['LOCALAPPDATA'], self.emulator))
inst.ui.labeldown.setText("Downloading: " + self.emulator)
inst.ui.labelext.setText("Extracting: " + self.emulator)
inst.ui.welcomerLabel.setText(f'<big>Your currently selected emulator is <b>{self.emulator}</b> and current version is <b>{installed_emulator}</b>.</big>')

print (self.emulator)
print(self.emulator)
self.checkreg()
self.disable_qt_buttons_if_installed()
qtui.layout.setCurrentIndex(1)
inst.ui.layout.setCurrentIndex(1)

# Disable buttons depanding on if it the program is already installed
def disable_qt_buttons_if_installed(self):
regvalue = self.checkreg()
if regvalue is None:
qtui.installButton.setEnabled(True)
qtui.updateButton.setEnabled(False)
qtui.uninstallButton.setEnabled(False)
inst.ui.installButton.setEnabled(True)
inst.ui.updateButton.setEnabled(False)
inst.ui.uninstallButton.setEnabled(False)
else:
qtui.installButton.setEnabled(False)
qtui.updateButton.setEnabled(True)
qtui.uninstallButton.setEnabled(True)

# Button clinking function
def qt_button_click(self):
button = qtui.sender()
if button is qtui.installButton:
self.install_mode = "Install"
qtui.layout.setCurrentIndex(2)
self.Add_releases_to_combobox()
elif button is qtui.updateButton:
self.emulator_updates()
elif button is qtui.uninstallButton:
self.install_mode = "Uninstall" # Unused for now
self.uninstall()
if button is qtui.install_emu_button:
qtui.layout.setCurrentIndex(3)
self.Prepare_Download()
if button is qtui.backButton:
current_index = qtui.layout.currentIndex()
if current_index > 0:
qtui.layout.setCurrentIndex(current_index - 1)
return self.install_mode
inst.ui.installButton.setEnabled(False)
inst.ui.updateButton.setEnabled(True)
inst.ui.uninstallButton.setEnabled(True)

# Select installation path function
def InstallPath(self):
Expand Down Expand Up @@ -394,40 +361,6 @@ def uninstall(self):
QMessageBox.critical(qtui, "Error",("Failed to read the registry key. Try and reinstall again!"))
qtui.layout.setCurrentIndex(1)

# Download Worker class to download the files
class DownloadWorker(QThread):
progress = pyqtSignal(int)

def __init__(self, url, dest):
super().__init__()
self.url = url
self.dest = dest


@pyqtSlot()
def do_download(self):
try:
response = requests.get(self.url, stream=True)
total_size = int(response.headers.get('content-length', 0))
if total_size == 0:
print("The content-length of the response is zero.")
return

downloaded_size = 0
with open(self.dest, 'wb') as file:
for data in response.iter_content(1024):
downloaded_size += len(data)
file.write(data)
progress_percentage = (downloaded_size / total_size) * 100
self.progress.emit(int(progress_percentage))
self.finished.emit()
except Exception as e:
QMessageBox.critical(QtUi, "Error",("Error doing download."))
self.finished.emit()

if __name__ == "__main__":
version = Online.get_latest_git_tag()
app = QApplication(sys.argv)
ui_window = MainWindow()
ui_window.show()
sys.exit(app.exec())
main = Main()
main.initialize_app()
14 changes: 6 additions & 8 deletions ui/install_page.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Install page
from imports import *
from main import Logic as main
from header import Header
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton, QHBoxLayout, QGroupBox, QComboBox, QCheckBox, QLineEdit
from PyQt6.QtCore import Qt
from init_instances import inst
from ui.header import Header

class InstallPage(QWidget):
def __init__(self):
Expand All @@ -23,10 +23,8 @@ def __init__(self):
self.startMenuShortcutCheckbox = QCheckBox("Create a start menu shortcut")
self.installationPathLineEdit = QLineEdit() # Browse for installation path widget
self.browseButton = QPushButton("Browse")
self.browseButton.clicked.connect(main.InstallPath)
self.install_emu_button = QPushButton('Install') # Install button
self.install_emu_button.clicked.connect(main.qt_button_click)
## Add widgets / layouts
self.browseButton.clicked.connect(inst.main.InstallPath)
self.install_emu_button = QPushButton('Install') # Install button ## Add widgets / layouts
installLayout.addLayout(self.header) ### Icon self.header
installLayout.addWidget(InstalOpt) ### Instalation Option Label
installLayout.addWidget(self.installationSourceComboBox) ## Install Sorce Widget
Expand Down
4 changes: 2 additions & 2 deletions ui/progress_bar.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from imports import *
from header import Header
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QProgressBar, QLabel
from ui.header import Header

# Progress bar page
class ProgressBarPage(QWidget):
Expand Down
84 changes: 46 additions & 38 deletions ui/selection_page.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from imports import *
from main import Online
from main import Logic
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QGroupBox, QTreeWidget, QTreeWidgetItem, QPushButton, QMessageBox
from PyQt6.QtGui import QIcon
from PyQt6.QtCore import Qt
from init_instances import inst

# Emulator Select Page
# Emulator Select Page

class SelectionPage(QWidget):
def __init__(self):
super().__init__()
self.troppical_database = Online.fetch_data(self)
self.emulatorSelectPage = QWidget()
emulatorSelectLayout = QVBoxLayout()
emulatorSelectGroup = QGroupBox("Select your emulator from the list")
Expand All @@ -20,57 +20,65 @@ def __init__(self):

emulatorSelectGroupLayout.addWidget(self.emulatorTreeWidget)

# Keep track of emulator systems
system_items = {}

for troppical_api_data in self.troppical_database:
emulator_system = troppical_api_data['emulator_system']
emulator_name = troppical_api_data['emulator_name']
emulator_desc = troppical_api_data.get('emulator_desc', '')

# Fetch and decode the logo
logo_url = troppical_api_data['emulator_logo']
response = requests.get(logo_url)
if response.status_code == 200:
image_bytes = response.content
qimage = QImage.fromData(QByteArray(image_bytes))
pixmap = QPixmap.fromImage(qimage).scaled(32, 32, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
icon = QIcon(pixmap)
print(logo_url)
else:
QMessageBox.critical(self, "Failed to fetch logo", f"Failed to fetch logo for {emulator_name}. Status code: {response.status_code}")
icon = QIcon()
# Set layout for the group and add to the main layout
emulatorSelectGroup.setLayout(emulatorSelectGroupLayout)
emulatorSelectLayout.addWidget(emulatorSelectGroup)
self.emulatorSelectPage.setLayout(emulatorSelectLayout) # Set the layout for the emulator selection page

# Next button to confirm selection
self.nextButton = QPushButton("Next")
self.nextButton.clicked.connect(lambda: inst.main_instance.set_emulator(self))
emulatorSelectLayout.addWidget(self.nextButton)

# Show initializing message
self.initializing_msg = QMessageBox(self)
self.initializing_msg.setWindowTitle("Troppical API")
self.initializing_msg.setText("Getting emulator data...")
self.initializing_msg.setStandardButtons(QMessageBox.StandardButton.NoButton)
self.initializing_msg.show()

# Start the secondary thread with the task and callback
inst.ui.start_secondary_thread(inst.online.filter_emulator_data, self.populate_emulator_tree)

def populate_emulator_tree(self, emulator_data):
# Iterate over each emulator item and add it to the tree
for emulator_name, data in emulator_data.items():
emulator_system = data['system']
emulator_desc = data['description']
icon = data['icon']
print(f"Fetching data for {emulator_name}")

# Check if the emulator system already has a tree item, if not create one
if emulator_system not in system_items:
system_item = None
for i in range(self.emulatorTreeWidget.topLevelItemCount()):
item = self.emulatorTreeWidget.topLevelItem(i)
if item.text(0) == emulator_system:
system_item = item
break

if not system_item:
system_item = QTreeWidgetItem(self.emulatorTreeWidget)
system_item.setText(0, emulator_system)
system_item.setExpanded(True) # Uncollapse the category by default
system_items[emulator_system] = system_item
else:
system_item = system_items[emulator_system]
system_item.setExpanded(True)
# Make the system item unselectable
system_item.setFlags(system_item.flags() & ~Qt.ItemFlag.ItemIsSelectable)

# Add the emulator to the appropriate tree item
emulator_item = QTreeWidgetItem(system_item)
emulator_item.setText(0, emulator_name)
emulator_item.setIcon(0, icon)
emulator_item.setToolTip(0, emulator_desc)

# Close the initializing message
self.initializing_msg.hide()

# Sort the systems and emulators alphabetically
self.emulatorTreeWidget.sortItems(0, Qt.SortOrder.AscendingOrder)
for i in range(self.emulatorTreeWidget.topLevelItemCount()):
system_item = self.emulatorTreeWidget.topLevelItem(i)
system_item.sortChildren(0, Qt.SortOrder.AscendingOrder)

# Set layout for the group and add to the main layout
emulatorSelectGroup.setLayout(emulatorSelectGroupLayout)
emulatorSelectLayout.addWidget(emulatorSelectGroup)
self.emulatorSelectPage.setLayout(emulatorSelectLayout) # Set the layout for the emulator selection page

# Next button to confirm selection
self.nextButton = QPushButton("Next")
self.nextButton.clicked.connect(Logic.set_emulator)
emulatorSelectLayout.addWidget(self.nextButton)

def get_selected_emulator(self):
selected_item = self.emulatorTreeWidget.currentItem()
Expand Down
Loading

0 comments on commit d7a1cd0

Please sign in to comment.