Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
43b2793
Added controller helper, local database structure
Wolfy76700 Mar 16, 2024
80ba912
Update locale files
actions-user Mar 16, 2024
5669423
Update exe
actions-user Mar 16, 2024
1593a48
Merge commit '56694236cd511411d9f5540c21d8ab52dc7dea5c' into feature/…
Wolfy76700 May 5, 2025
839c5cc
Update exe and locale files
actions-user May 5, 2025
00c2482
Added loading logic for controllers
Wolfy76700 May 11, 2025
372c48c
Fix
Wolfy76700 May 11, 2025
142310d
Fix
Wolfy76700 May 11, 2025
bca9e42
Added controller selector
Wolfy76700 May 11, 2025
ef5e500
Fix autocompletion on controllers
Wolfy76700 May 11, 2025
15dfcc7
Merge commit '839c5cc655e36b2a4e95d12d889a92fea25411e5' into feature/…
Wolfy76700 May 11, 2025
8fb1a8b
Update exe and locale files
actions-user May 11, 2025
be9c7d4
Fix data loading
Wolfy76700 May 11, 2025
daaeaf4
Merge commit '8fb1a8be5a7ad57363092eccc3b65cb1ecfe6fe2' into feature/…
Wolfy76700 May 11, 2025
d9e6521
Update exe and locale files
actions-user May 11, 2025
11faa41
Added option to hide controller select
Wolfy76700 May 11, 2025
22362ee
Merge commit 'd9e65217c833266ffe0c577b90e584c077b9a365' into feature/…
Wolfy76700 May 11, 2025
52e0993
Update exe and locale files
actions-user May 11, 2025
c887087
Update French locale
Wolfy76700 May 11, 2025
4ea1ba0
Update exe and locale files
actions-user May 11, 2025
7015aa5
Fix french locale
Wolfy76700 May 11, 2025
bc4ca18
Update exe and locale files
actions-user May 11, 2025
95dd438
Fixed controller label
Wolfy76700 May 15, 2025
12d5987
Update exe and locale files
actions-user May 15, 2025
4443d2a
Fixed UI offset
Wolfy76700 May 15, 2025
12501de
Merge commit '12d598768c5b6686dfb3cfdd87dab489639fd602' into feature/…
Wolfy76700 May 15, 2025
9510596
Update exe and locale files
actions-user May 15, 2025
c4cfa80
Fix misalignment
Wolfy76700 May 16, 2025
e7e1ac3
Merge commit '9510596d7b4ffa994668fbcc3e2a329bead26ddb' into feature/…
Wolfy76700 May 16, 2025
f777c51
Update exe and locale files
actions-user May 16, 2025
86f35e7
Fix
Wolfy76700 May 19, 2025
15a0b56
Update exe and locale files
actions-user May 19, 2025
39ccdc0
Fix update logic
Wolfy76700 May 19, 2025
6ce54c0
Merge commit '15a0b56c00c41d11051b57c72b59cef73d8324c1' into feature/…
Wolfy76700 May 19, 2025
3151afb
Update exe and locale files
actions-user May 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,4 @@ logs/*
Pipfile*
env
desktop.ini
assets/controller/*
Binary file modified TSH.exe
Binary file not shown.
152 changes: 152 additions & 0 deletions src/Helpers/TSHControllerHelper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import re
import unicodedata
from qtpy.QtCore import *
from qtpy.QtGui import *
from qtpy.QtWidgets import *
import requests
import os
import shutil
import traceback
import zipfile
from .TSHDictHelper import deep_get
from ..TournamentDataProvider import TournamentDataProvider
from .TSHLocaleHelper import TSHLocaleHelper
import json
from loguru import logger
import glob


class TSHControllerHelperSignals(QObject):
controllersUpdated = Signal()


class TSHControllerHelper(QObject):
instance: "TSHControllerHelper" = None

signals = TSHControllerHelperSignals()

def __init__(self) -> None:
super().__init__()
self.controller_list = {}
self.controllerModel = QStandardItemModel()

self.UpdateControllerFile()
self.BuildControllerTree()
self.UpdateControllerModel()


def UpdateControllerFile(self):
try:
url = 'https://github.com/Wolfy76700/ControllerDatabase/archive/refs/heads/main.zip'
r = requests.get(url, allow_redirects=True)

with open('./assets/controller.zip.tmp', 'wb') as zip_file:
zip_file.write(r.content)

try:
# Extract ZIP
if os.path.exists("./assets/controller_tmp"):
shutil.rmtree("./assets/controller_tmp")
with zipfile.ZipFile('./assets/controller.zip.tmp', 'r') as zip_file:
os.mkdir('./assets/controller_tmp')
zip_file.extractall('./assets/controller_tmp')

# Remove ZIP
os.remove('./assets/controller.zip.tmp')

# Move directory
if os.path.exists("./assets/controller"):
shutil.rmtree("./assets/controller")
os.rename(
'./assets/controller_tmp',
'./assets/controller'
)

logger.info("Controller files updated")
except:
logger.error("Controller files download failed")
except Exception as e:
logger.error(
"Could not update /assets/controller: "+str(e))

def BuildControllerTree(self):
controller_list = {}
list_controller_directories = glob.glob("./assets/controller/ControllerDatabase-main/*/*/*/")
for controller_directory in list_controller_directories:
if os.path.exists(f"{controller_directory}/config.json"):
split = controller_directory.split("/")
controller_id = f"{split[-4]}/{split[-3]}/{split[-2]}"
print(f"Loading: {controller_id}")
with open(f"{controller_directory}/config.json", "rt", encoding="utf-8") as config_file:
config_json = json.loads(config_file.read())
if os.path.exists(f"{"/".join(split[:-2])}/config.json"):
with open(f"{"/".join(split[:-2])}/config.json", "rt", encoding="utf-8") as manufacturer_file:
manufacturer = json.loads(manufacturer_file.read()).get("name")
print(f"Manufacturer: {manufacturer}")
else:
manufacturer = None

if os.path.exists(f"{"/".join(split[:-3])}/config.json"):
with open(f"{"/".join(split[:-3])}/config.json", "rt", encoding="utf-8") as controller_type_file:
controller_type = json.loads(controller_type_file.read()).get("name")
print(f"Type: {controller_type}")
else:
controller_type = None

if os.path.exists(f"{controller_directory}/image.png"):
icon_path = f"{controller_directory}/image.png"
else:
icon_path = None

controller_json = {
"name": config_json.get("name"),
"manufacturer": manufacturer,
"type": controller_type,
"icon_path": icon_path,
"config_path": f"{controller_directory}/config.json"
}
controller_list[controller_id] = controller_json
self.controller_list = controller_list


def UpdateControllerModel(self):
try:
self.controllerModel = QStandardItemModel()

# Add one empty
item = QStandardItem("")
self.controllerModel.appendRow(item)

for c in self.controller_list.keys():
item = QStandardItem()
item.setData(c, Qt.ItemDataRole.EditRole)
print(c)

data = {
"name": self.controller_list[c].get("name"),
"manufacturer": self.controller_list[c].get("manufacturer"),
"type": self.controller_list[c].get("type"),
"codename": c
}


data["icon_path"] = self.controller_list[c].get("icon_path")
if data["icon_path"]:
item.setIcon(QIcon(QPixmap.fromImage(QImage(data["icon_path"])))
)
else:
item.setIcon(QIcon(QPixmap.fromImage(QImage('./assets/icons/cancel.svg')))
)

if self.controller_list[c].get("name") != c:
item.setData(
f'{self.controller_list[c].get("name")}', Qt.ItemDataRole.EditRole)

item.setData(data, Qt.ItemDataRole.UserRole)
self.controllerModel.appendRow(item)

self.controllerModel.sort(0)
except:
logger.error(traceback.format_exc())

TSHControllerHelper.instance = TSHControllerHelper()
2 changes: 1 addition & 1 deletion src/TSHPlayerDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class TSHPlayerDB:
database = {}
model: QStandardItemModel = None
fieldnames = ["prefix", "gamerTag", "name", "twitter",
"country_code", "state_code", "mains", "pronoun", "custom_textbox"] # Please always add the new fields at the end of the list
"country_code", "state_code", "mains", "pronoun", "custom_textbox", "controller"] # Please always add the new fields at the end of the list
modelLock = Lock()

def LoadDB():
Expand Down
62 changes: 61 additions & 1 deletion src/TSHScoreboardPlayerWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .Helpers.TSHCountryHelper import TSHCountryHelper
from .StateManager import StateManager
from .TSHGameAssetManager import TSHGameAssetManager
from .Helpers.TSHControllerHelper import TSHControllerHelper
from .TSHPlayerDB import TSHPlayerDB
from .TSHTournamentDataProvider import TSHTournamentDataProvider
from .Helpers.TSHLocaleHelper import TSHLocaleHelper
Expand Down Expand Up @@ -54,10 +55,12 @@ def __init__(self, index=0, teamNumber=0, path="", scoreboardNumber=1, customNam

uic.loadUi(TSHResolve("src/layout/TSHScoreboardPlayer.ui"), self)

self.LoadControllers()

custom_textbox_layout = QHBoxLayout()
self.custom_textbox = QPlainTextEdit()
custom_textbox_layout.addWidget(self.custom_textbox)
self.layout().addLayout(custom_textbox_layout, 98, 0, 1, 3)
self.layout().addLayout(custom_textbox_layout, 98, 2, 1, 1)
self.custom_textbox.setObjectName("custom_textbox")
self.custom_textbox.setPlaceholderText(QApplication.translate("app", "Additional information"))
self.custom_textbox.textChanged.connect(
Expand Down Expand Up @@ -526,6 +529,46 @@ def SwapCharacters(self, index1: int, index2: int):

StateManager.ReleaseSaving()

def LoadControllers(self):
try:
if TSHControllerHelper.instance.controllerModel == None:
TSHControllerHelper.BuildControllerTree()
TSHControllerHelper.UpdateControllerModel()

controller_layout = QVBoxLayout()

controller_label = QLabel()
controller_layout.addWidget(controller_label)
controller_label.setText(QApplication.translate("app", "Controller").upper())
controller_label.setStyleSheet("QLabel{font-weight: bold; font-size: 8pt;}")
controller_label.setObjectName("controllerLabel")

self.controller = QComboBox()

controller_layout.addWidget(self.controller)
self.layout().addLayout(controller_layout, 97, 2, 1, 1)

self.controller.setObjectName("controller")
self.controller.setEditable(True)
self.controller.completer().setFilterMode(Qt.MatchFlag.MatchContains)
self.controller.completer().setCompletionMode(QCompleter.PopupCompletion)
self.controller.completer().popup().setMinimumWidth(250)
self.controller.setIconSize(QSize(24, 24))
self.controller.setFixedHeight(32)
self.controller.setMinimumWidth(60)
# self.controller.setMaximumWidth(120)
self.controller.setFont(
QFont(self.controller.font().family(), 9))
self.controller.setModel(
TSHControllerHelper.instance.controllerModel)
view = QListView()
view.setIconSize(QSize(24, 24))
self.controller.setView(view)

except Exception as e:
logger.error(traceback.format_exc())
exit()

def LoadCountries(self):
try:
if TSHCountryHelper.countryModel == None:
Expand Down Expand Up @@ -743,6 +786,19 @@ def SetData(self, data, dontLoadFromDB=False, clear=True, no_mains=False):
if stateElement.currentIndex() != stateIndex:
stateElement.setCurrentIndex(stateIndex)

if data.get("controller"):
controllerElement: QComboBox = self.findChild(
QComboBox, "controller")
controllerIndex = 0
for i in range(controllerElement.model().rowCount()):
item = controllerElement.model().item(i).data(Qt.ItemDataRole.UserRole)
if item:
if data.get("controller") == item.get("codename"):
controllerIndex = i
break
if controllerElement.currentIndex() != controllerIndex:
controllerElement.setCurrentIndex(controllerIndex)

if data.get("mains") and no_mains != True:
if type(data.get("mains")) == list:
for element in self.character_elements:
Expand Down Expand Up @@ -858,6 +914,10 @@ def SavePlayerToDB(self):
if self.findChild(QComboBox, "state").currentData(Qt.ItemDataRole.UserRole):
playerData["state_code"] = self.findChild(
QComboBox, "state").currentData(Qt.ItemDataRole.UserRole).get("code")

if self.findChild(QComboBox, "controller").currentData(Qt.ItemDataRole.UserRole):
playerData["controller"] = self.findChild(
QComboBox, "controller").currentData(Qt.ItemDataRole.UserRole).get("codename")

TSHPlayerDB.AddPlayers([playerData], overwrite=True)

Expand Down
4 changes: 3 additions & 1 deletion src/TSHScoreboardWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,16 @@ def __init__(self, scoreboardNumber=1, *args):
["Location", ["locationLabel", "state", "country"]],
["Characters", ["characters"]],
["Pronouns", ["pronoun", "pronounLabel"]],
["Controller", ["controller", "controllerLabel"]],
["Additional information", ["custom_textbox"]],
]
self.elements[0][0] = QApplication.translate("app", "Real Name")
self.elements[1][0] = QApplication.translate("app", "Twitter")
self.elements[2][0] = QApplication.translate("app", "Location")
self.elements[3][0] = QApplication.translate("app", "Characters")
self.elements[4][0] = QApplication.translate("app", "Pronouns")
self.elements[5][0] = QApplication.translate("app", "Additional information")
self.elements[5][0] = QApplication.translate("app", "Controller")
self.elements[6][0] = QApplication.translate("app", "Additional information")
for element in self.elements:
action: QAction = self.eyeBt.menu().addAction(element[0])
action.setCheckable(True)
Expand Down
1 change: 1 addition & 0 deletions src/TournamentStreamHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def flush(self):
from .StateManager import StateManager
from .SettingsManager import SettingsManager
from .Helpers.TSHCountryHelper import TSHCountryHelper
from .Helpers.TSHControllerHelper import TSHControllerHelper
from .TSHScoreboardManager import TSHScoreboardManager
from .TSHThumbnailSettingsWidget import TSHThumbnailSettingsWidget
from src.TSHAssetDownloader import TSHAssetDownloader
Expand Down
Loading