reorganize folders, add gitignore
This commit is contained in:
314
.gitignore
vendored
Normal file
314
.gitignore
vendored
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
!*.code-workspace
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[codz]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
# Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
# poetry.lock
|
||||||
|
# poetry.toml
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
||||||
|
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
||||||
|
# pdm.lock
|
||||||
|
# pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# pixi
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
||||||
|
# pixi.lock
|
||||||
|
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
||||||
|
# in the .venv directory. It is recommended not to include this directory in version control.
|
||||||
|
.pixi
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
*.rdb
|
||||||
|
*.aof
|
||||||
|
*.pid
|
||||||
|
|
||||||
|
# RabbitMQ
|
||||||
|
mnesia/
|
||||||
|
rabbitmq/
|
||||||
|
rabbitmq-data/
|
||||||
|
|
||||||
|
# ActiveMQ
|
||||||
|
activemq-data/
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.envrc
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
# .idea/
|
||||||
|
|
||||||
|
# Abstra
|
||||||
|
# Abstra is an AI-powered process automation framework.
|
||||||
|
# Ignore directories containing user credentials, local state, and settings.
|
||||||
|
# Learn more at https://abstra.io/docs
|
||||||
|
.abstra/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
||||||
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
||||||
|
# you could uncomment the following to ignore the entire vscode folder
|
||||||
|
# .vscode/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
# Marimo
|
||||||
|
marimo/_static/
|
||||||
|
marimo/_lsp/
|
||||||
|
__marimo__/
|
||||||
|
|
||||||
|
# Streamlit
|
||||||
|
.streamlit/secrets.toml
|
||||||
|
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, GoLand, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
.idea/sonarlint.xml # see https://community.sonarsource.com/t/is-the-file-idea-idea-idea-sonarlint-xml-intended-to-be-under-source-control/121119
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based HTTP Client
|
||||||
|
.idea/httpRequests
|
||||||
|
http-client.private.env.json
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
# Apifox Helper cache
|
||||||
|
.idea/.cache/.Apifox_Helper
|
||||||
|
.idea/ApifoxUploaderProjectSetting.xml
|
||||||
|
|
||||||
|
# Github Copilot persisted session migrations, see: https://github.com/microsoft/copilot-intellij-feedback/issues/712#issuecomment-3322062215
|
||||||
|
.idea/**/copilot.data.migration.*.xml
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
48
frameless.py
48
frameless.py
@@ -1,48 +0,0 @@
|
|||||||
import sys
|
|
||||||
import os
|
|
||||||
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
|
|
||||||
from PyQt6.QtCore import Qt, QPoint
|
|
||||||
|
|
||||||
# À placer tout en haut, avant les imports PyQt6 si possible
|
|
||||||
os.environ["QT_QPA_PLATFORM"] = "xcb"
|
|
||||||
|
|
||||||
class FenetreSansTitre(QMainWindow):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
|
||||||
self.resize(400, 300)
|
|
||||||
|
|
||||||
# IMPORTANT : On active le suivi de souris
|
|
||||||
self.setMouseTracking(True)
|
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
btn_quitter = QPushButton("Quitter")
|
|
||||||
btn_quitter.clicked.connect(self.close)
|
|
||||||
layout.addWidget(btn_quitter)
|
|
||||||
|
|
||||||
container = QWidget()
|
|
||||||
container.setLayout(layout)
|
|
||||||
self.setCentralWidget(container)
|
|
||||||
|
|
||||||
self._drag_pos = None
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
|
||||||
# On enregistre la position du clic RELATIVE au coin haut-gauche de la fenêtre
|
|
||||||
self._drag_pos = event.position().toPoint()
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
|
||||||
if self._drag_pos is not None:
|
|
||||||
# On déplace la fenêtre vers la position globale du curseur
|
|
||||||
# MOINS le décalage initial (offset) pour éviter que le curseur ne saute au centre
|
|
||||||
self.move(event.globalPosition().toPoint() - self._drag_pos)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
|
||||||
self._drag_pos = None
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
fenetre = FenetreSansTitre()
|
|
||||||
fenetre.show()
|
|
||||||
sys.exit(app.exec())
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import sys
|
|
||||||
import os
|
|
||||||
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
|
|
||||||
from PyQt6.QtCore import Qt, QPoint
|
|
||||||
|
|
||||||
# À placer tout en haut, avant les imports PyQt6 si possible
|
|
||||||
os.environ["QT_QPA_PLATFORM"] = "xcb"
|
|
||||||
|
|
||||||
class FenetreSansTitre(QMainWindow):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
# 1. Retirer la barre de titre
|
|
||||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
|
|
||||||
self.resize(400, 300)
|
|
||||||
|
|
||||||
# Interface simple
|
|
||||||
layout = QVBoxLayout()
|
|
||||||
btn_quitter = QPushButton("Fermer la fenêtre")
|
|
||||||
btn_quitter.clicked.connect(self.close)
|
|
||||||
layout.addWidget(btn_quitter)
|
|
||||||
|
|
||||||
container = QWidget()
|
|
||||||
container.setLayout(layout)
|
|
||||||
self.setCentralWidget(container)
|
|
||||||
|
|
||||||
# Variable pour stocker la position du clic
|
|
||||||
self.old_pos = None
|
|
||||||
|
|
||||||
# --- Logique de déplacement ---
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
|
||||||
if event.button() == Qt.MouseButton.LeftButton:
|
|
||||||
# On sauvegarde la position relative du curseur dans la fenêtre
|
|
||||||
self.old_pos = event.globalPosition().toPoint()
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
|
||||||
if self.old_pos is not None:
|
|
||||||
# Calcul de la distance parcourue
|
|
||||||
delta = QPoint(event.globalPosition().toPoint() - self.old_pos)
|
|
||||||
# Déplacement de la fenêtre
|
|
||||||
self.move(self.x() + delta.x(), self.y() + delta.y())
|
|
||||||
# Mise à jour de la position de référence
|
|
||||||
self.old_pos = event.globalPosition().toPoint()
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
|
||||||
self.old_pos = None
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
fenetre = FenetreSansTitre()
|
|
||||||
fenetre.show()
|
|
||||||
sys.exit(app.exec())
|
|
||||||
9
readme.md
Normal file
9
readme.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# LaTaniere Launcher UI
|
||||||
|
|
||||||
|
### First: create virtualenv
|
||||||
|
python -m venv .venv
|
||||||
|
|
||||||
|
### Second: install packages
|
||||||
|
pip install -r .\requirements.txt
|
||||||
|
|
||||||
|
Enjoy.
|
||||||
@@ -1,272 +0,0 @@
|
|||||||
from PyQt6.QtCore import Qt
|
|
||||||
from PyQt6.QtWidgets import (
|
|
||||||
QSlider, QProxyStyle, QStyle
|
|
||||||
)
|
|
||||||
from PyQt6.QtGui import QColor
|
|
||||||
|
|
||||||
class SliderGrooveColorStyle(QProxyStyle):
|
|
||||||
def __init__(self, base_style=None, groove_color=QColor("lightblue")):
|
|
||||||
super().__init__(base_style)
|
|
||||||
self.groove_color = groove_color
|
|
||||||
|
|
||||||
def drawComplexControl(self, control, option, painter, widget=None):
|
|
||||||
if control == QStyle.ComplexControl.CC_Slider and isinstance(widget, QSlider):
|
|
||||||
|
|
||||||
# Récupérer la zone du groove
|
|
||||||
groove_rect = self.subControlRect(
|
|
||||||
QStyle.ComplexControl.CC_Slider,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderGroove,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
# Dessiner notre fond
|
|
||||||
painter.save()
|
|
||||||
painter.setBrush(self.groove_color)
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
painter.drawRect(groove_rect)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
# Puis laisser Qt dessiner normalement (handle etc.)
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
return
|
|
||||||
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
|
|
||||||
class SliderSubPageColorStyle(QProxyStyle):
|
|
||||||
def __init__(self, base_style=None, color=QColor("#4CAF50")):
|
|
||||||
super().__init__(base_style)
|
|
||||||
self.color = color
|
|
||||||
|
|
||||||
def drawComplexControl(self, control, option, painter, widget=None):
|
|
||||||
if control == QStyle.ComplexControl.CC_Slider and isinstance(widget, QSlider):
|
|
||||||
|
|
||||||
# Laisser Qt dessiner le slider normalement
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
|
|
||||||
# Récupérer les rectangles du groove et du handle
|
|
||||||
groove_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderGroove,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
handle_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderHandle,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.save()
|
|
||||||
painter.setBrush(self.color)
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
|
|
||||||
if widget.orientation() == Qt.Orientation.Horizontal:
|
|
||||||
# Partie avant le handle (gauche → centre du handle)
|
|
||||||
sub_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
handle_rect.center().x() - groove_rect.right(),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Vertical (bas → centre du handle)
|
|
||||||
sub_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
handle_rect.center().y() - groove_rect.bottom(),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.drawRect(sub_rect)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
|
|
||||||
class SliderAddPageColorStyle(QProxyStyle):
|
|
||||||
def __init__(self, base_style=None, color=QColor("#FF9800")):
|
|
||||||
super().__init__(base_style)
|
|
||||||
self.color = color
|
|
||||||
|
|
||||||
def drawComplexControl(self, control, option, painter, widget=None):
|
|
||||||
if control == QStyle.ComplexControl.CC_Slider and isinstance(widget, QSlider):
|
|
||||||
|
|
||||||
# Récupérer groove + handle
|
|
||||||
groove_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderGroove,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
handle_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderHandle,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.save()
|
|
||||||
painter.setBrush(self.color)
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
|
|
||||||
if widget.orientation() == Qt.Orientation.Horizontal:
|
|
||||||
# Partie après le handle (centre → fin)
|
|
||||||
add_rect = groove_rect.adjusted(
|
|
||||||
handle_rect.center().x() - groove_rect.left(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# Vertical (centre → haut)
|
|
||||||
add_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
handle_rect.center().y() - groove_rect.top()
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.drawRect(add_rect)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
# IMPORTANT : Qt dessine ensuite le handle par-dessus
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
return
|
|
||||||
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
|
|
||||||
class ThinAddPageLineStyle(QProxyStyle):
|
|
||||||
def __init__(self, base_style=None, color=QColor("#E91E63")):
|
|
||||||
super().__init__(base_style)
|
|
||||||
self.color = color
|
|
||||||
|
|
||||||
def drawComplexControl(self, control, option, painter, widget=None):
|
|
||||||
if control == QStyle.ComplexControl.CC_Slider and isinstance(widget, QSlider):
|
|
||||||
|
|
||||||
groove_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderGroove,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
handle_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderHandle,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.save()
|
|
||||||
painter.setBrush(self.color)
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
|
|
||||||
if widget.orientation() == Qt.Orientation.Horizontal:
|
|
||||||
# Épaisseur fine (2 px)
|
|
||||||
thickness = 2
|
|
||||||
|
|
||||||
y = groove_rect.center().y() - thickness // 2
|
|
||||||
|
|
||||||
add_rect = groove_rect.adjusted(
|
|
||||||
handle_rect.center().x() - groove_rect.left(),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
add_rect.setTop(y)
|
|
||||||
add_rect.setHeight(thickness)
|
|
||||||
|
|
||||||
else:
|
|
||||||
thickness = 2
|
|
||||||
|
|
||||||
x = groove_rect.center().x() - thickness // 2
|
|
||||||
|
|
||||||
add_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
handle_rect.center().y() - groove_rect.top()
|
|
||||||
)
|
|
||||||
|
|
||||||
add_rect.setLeft(x)
|
|
||||||
add_rect.setWidth(thickness)
|
|
||||||
|
|
||||||
painter.drawRect(add_rect)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
# Dessiner ensuite le slider normalement (handle au-dessus)
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
return
|
|
||||||
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
|
|
||||||
class ThinSubPageLineStyle(QProxyStyle):
|
|
||||||
def __init__(self, base_style=None, color=QColor("#4CAF50")):
|
|
||||||
super().__init__(base_style)
|
|
||||||
self.color = color
|
|
||||||
|
|
||||||
def drawComplexControl(self, control, option, painter, widget=None):
|
|
||||||
if control == QStyle.ComplexControl.CC_Slider and isinstance(widget, QSlider):
|
|
||||||
|
|
||||||
groove_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderGroove,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
handle_rect = self.subControlRect(
|
|
||||||
control,
|
|
||||||
option,
|
|
||||||
QStyle.SubControl.SC_SliderHandle,
|
|
||||||
widget
|
|
||||||
)
|
|
||||||
|
|
||||||
painter.save()
|
|
||||||
painter.setBrush(self.color)
|
|
||||||
painter.setPen(Qt.PenStyle.NoPen)
|
|
||||||
|
|
||||||
# Épaisseur fine (ajuste si besoin)
|
|
||||||
thickness = 2
|
|
||||||
|
|
||||||
if widget.orientation() == Qt.Orientation.Horizontal:
|
|
||||||
|
|
||||||
y = groove_rect.center().y() - thickness // 2
|
|
||||||
|
|
||||||
sub_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
handle_rect.center().x() - groove_rect.right(),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
sub_rect.setTop(y)
|
|
||||||
sub_rect.setHeight(thickness)
|
|
||||||
|
|
||||||
else:
|
|
||||||
x = groove_rect.center().x() - thickness // 2
|
|
||||||
|
|
||||||
sub_rect = groove_rect.adjusted(
|
|
||||||
0,
|
|
||||||
handle_rect.center().y() - groove_rect.bottom(),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
sub_rect.setLeft(x)
|
|
||||||
sub_rect.setWidth(thickness)
|
|
||||||
|
|
||||||
painter.drawRect(sub_rect)
|
|
||||||
painter.restore()
|
|
||||||
|
|
||||||
# Qt redessine le slider (handle au-dessus)
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
return
|
|
||||||
|
|
||||||
super().drawComplexControl(control, option, painter, widget)
|
|
||||||
@@ -8,12 +8,10 @@ from PyQt6.QtWidgets import QApplication, QMainWindow
|
|||||||
|
|
||||||
from win11toast import toast, notify
|
from win11toast import toast, notify
|
||||||
|
|
||||||
from slidergroovecolorstyle import ThinSubPageLineStyle, ThinAddPageLineStyle
|
|
||||||
|
|
||||||
# Compile resources.qrc into resources_rc.py
|
# Compile resources.qrc into resources_rc.py
|
||||||
# rcc -g python resources.qrc -o resources_rc.py
|
# rcc -g python resources.qrc -o resources_rc.py
|
||||||
|
|
||||||
import resources # This is generated from the .qrc file # noqa: F401
|
import resources as resources # This is generated from the .qrc file # noqa: F401
|
||||||
|
|
||||||
# À placer tout en haut, avant les imports PyQt6 si possible
|
# À placer tout en haut, avant les imports PyQt6 si possible
|
||||||
if sys.platform.startswith('linux'):
|
if sys.platform.startswith('linux'):
|
||||||
@@ -23,6 +21,8 @@ if sys.platform.startswith('linux'):
|
|||||||
from fake_patch_notes import patch_note
|
from fake_patch_notes import patch_note
|
||||||
NO_STAFF = True
|
NO_STAFF = True
|
||||||
|
|
||||||
|
CURRENT = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
def load_custom_font():
|
def load_custom_font():
|
||||||
# Load font from Qt resource
|
# Load font from Qt resource
|
||||||
font_id = QFontDatabase.addApplicationFont(":/assets/Avocado-Cake-Demo.otf")
|
font_id = QFontDatabase.addApplicationFont(":/assets/Avocado-Cake-Demo.otf")
|
||||||
@@ -51,7 +51,7 @@ class MainWindow(QMainWindow):
|
|||||||
# Load font family from resource
|
# Load font family from resource
|
||||||
font_family = load_custom_font()
|
font_family = load_custom_font()
|
||||||
|
|
||||||
uic.loadUi("mainwindow.ui", self)
|
uic.loadUi(f"{os.path.dirname(CURRENT)}/ui/mainwindow.ui", self)
|
||||||
|
|
||||||
# Adjust UI
|
# Adjust UI
|
||||||
self.maintitle_label.setFont(QFont(font_family, 38))
|
self.maintitle_label.setFont(QFont(font_family, 38))
|
||||||
@@ -109,7 +109,7 @@ class MainWindow(QMainWindow):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
with open('styles.qss', 'r') as f:
|
with open(f"{os.path.dirname(CURRENT)}/styles/styles.qss", 'r') as f:
|
||||||
style = f.read()
|
style = f.read()
|
||||||
|
|
||||||
# Set the stylesheet of the application
|
# Set the stylesheet of the application
|
||||||
74
uv.lock
generated
74
uv.lock
generated
@@ -1,74 +0,0 @@
|
|||||||
version = 1
|
|
||||||
revision = 3
|
|
||||||
requires-python = ">=3.14"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "myproject"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = { virtual = "." }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "pyside6" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata]
|
|
||||||
requires-dist = [{ name = "pyside6", specifier = ">=6.10.2" }]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyside6"
|
|
||||||
version = "6.10.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "pyside6-addons" },
|
|
||||||
{ name = "pyside6-essentials" },
|
|
||||||
{ name = "shiboken6" },
|
|
||||||
]
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/35/0f/5736889fc850794623692cb369e295a994175e51295fa52134626f486296/pyside6-6.10.2-cp39-abi3-macosx_13_0_universal2.whl", hash = "sha256:4b084293caa7845d0064aaf6af258e0f7caae03a14a33537d0a552131afddaf0", size = 563185, upload-time = "2026-02-02T08:50:47.161Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/35/d3/ab5cd2fac3d34469c7376e0cd18eec92905dbe44748c70bda7699a2a7206/pyside6-6.10.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1b89ce8558d4b4f35b85bff1db90d680912e4d3ce9e79ff804d6fef1d1a151ef", size = 563357, upload-time = "2026-02-02T08:50:48.919Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ea/8c/55bbd50c138c8dc12edc9f25e9d94760a33e574905468e98dff399094baa/pyside6-6.10.2-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:0439f5e9b10ebe6177981bac9e219096ec970ac6ec215bef055279802ba50601", size = 563357, upload-time = "2026-02-02T08:50:50.077Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4f/d4/673b8112b4a260377f760be835c4e357163fdaf68a56a1aec59aeb8e584b/pyside6-6.10.2-cp39-abi3-win_amd64.whl", hash = "sha256:032bad6b18a17fcbf4dddd0397f49b07f8aae7f1a45b7e4de7037bf7fd6e0edf", size = 569554, upload-time = "2026-02-02T08:50:51.147Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/95/bda648fcccf61fe58cb417284716ae30acdddd44f7d4cbad6eea4ccaa872/pyside6-6.10.2-cp39-abi3-win_arm64.whl", hash = "sha256:65a59ad0bc92525639e3268d590948ce07a80ee97b55e7a9200db41d493cac31", size = 553828, upload-time = "2026-02-02T08:50:52.244Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyside6-addons"
|
|
||||||
version = "6.10.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "pyside6-essentials" },
|
|
||||||
{ name = "shiboken6" },
|
|
||||||
]
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/06/c283567628ffa2cefc3c72374ad607f1dfc9842a03db65f1347b9ae52bee/pyside6_addons-6.10.2-cp39-abi3-macosx_13_0_universal2.whl", hash = "sha256:0de7d0c9535e17d5e3b634b61314a1867f3b0f6d35c3d7cdc99efc353192faff", size = 322745605, upload-time = "2026-02-02T08:39:19.929Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a5/69/e1ab8c756fd3984b1fd7b186446227f524f6b561160bfbfdba8874b4709a/pyside6_addons-6.10.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:030a851163b51dbf0063be59e9ddb6a9e760bde89a28e461ccc81a224d286eaf", size = 170718434, upload-time = "2026-02-02T08:40:55.989Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/e5/18ba86ba86d1231c486d36f9accfe862ed6eb52ca0b698aeaf6e837a87ca/pyside6_addons-6.10.2-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:fcee0373e3fd7b98f014094e5e37b4a39e4de7c5a47c13f654a7d557d4a426ad", size = 166423836, upload-time = "2026-02-02T08:42:44.918Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/13/503bec9201881968c372cb634069535e80aec2489f3907d676e151a1023f/pyside6_addons-6.10.2-cp39-abi3-win_amd64.whl", hash = "sha256:c20150068525a17494f3b6576c5d61c417cf9a5870659e29f5ebd83cd20a78ea", size = 164712775, upload-time = "2026-02-02T08:43:23.729Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/39/44d6710b4dd18d745077b5fc6ded4ba6f32987a6e49c5834529e50f02155/pyside6_addons-6.10.2-cp39-abi3-win_arm64.whl", hash = "sha256:3d18db739b46946ba7b722d8ad4cc2097135033aa6ea57076e64d591e6a345f3", size = 34041396, upload-time = "2026-02-02T08:43:31.246Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyside6-essentials"
|
|
||||||
version = "6.10.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "shiboken6" },
|
|
||||||
]
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1d/2e/5f18a77f5e0bd730bacec93a690d0ef3c96a9711d213653eacecbf241b8d/pyside6_essentials-6.10.2-cp39-abi3-macosx_13_0_universal2.whl", hash = "sha256:1dee2cb9803ff135f881dadeb5c0edcef793d1ec4f8a9140a1348cecb71074e1", size = 105913067, upload-time = "2026-02-02T08:45:37.508Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/20/3a6ca95052e1744b5a3eba164e2dd451d358a3dcaf78179de4b45c8e3f47/pyside6_essentials-6.10.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:660aea45bfa36f1e06f799b934c2a7df963bd31abc5083e8bb8a5bfaef45686b", size = 77027153, upload-time = "2026-02-02T08:45:53.09Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/93/a6/6073e4ddc2a5c7b3941606e4bc8bbaadcf0737f57450620b0793041c8d22/pyside6_essentials-6.10.2-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:c2b028e4c6f8047a02c31f373408e23b4eedfd405f56c6aba8d0525c29472835", size = 76114242, upload-time = "2026-02-02T08:46:07.184Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/22/a8/616bbbd009efd3e17bf9a2db09d90c6764c010565cd2bdea2a240bfd18f7/pyside6_essentials-6.10.2-cp39-abi3-win_amd64.whl", hash = "sha256:0741018c2b6395038cad4c41775cfae3f13a409e87995ac9f7d89e5b1fb6b22a", size = 74546490, upload-time = "2026-02-02T08:46:26.395Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b9/f9/c9757a984c4ffb6d12fab69e966d95dfc862a5d44e12b7900f3a03780b76/pyside6_essentials-6.10.2-cp39-abi3-win_arm64.whl", hash = "sha256:db5f4913648bb6afddb8b347edae151ee2378f12bceb03c8b2515a530a4b38d9", size = 55258626, upload-time = "2026-02-02T08:46:36.788Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "shiboken6"
|
|
||||||
version = "6.10.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/38/3912eb08a3b865b5fcdb4bdce8076cacc211986cee587f5cb62e637791af/shiboken6-6.10.2-cp39-abi3-macosx_13_0_universal2.whl", hash = "sha256:3bd4e94e9a3c8c1fa8362fd752d399ef39265d5264e4e37bae61cdaa2a00c8c7", size = 479829, upload-time = "2026-02-02T08:50:22.495Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/52/88/292e0576489c46624ab419ee284ac5a59ae10e2eb34a58b6abca51dfd290/shiboken6-6.10.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ace0790032d9cb0adda644b94ee28d59410180d9773643bb6cf8438c361987ad", size = 273052, upload-time = "2026-02-02T08:50:24.539Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/06/c2/03d44d34e8264e1f25671677fece95b414c70fd85dcc2be8d5e821ee2628/shiboken6-6.10.2-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:f74d3ed1f92658077d0630c39e694eb043aeb1d830a5d275176c45d07147427f", size = 269868, upload-time = "2026-02-02T08:50:25.662Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/5d/5ca52c0ef86b3d01572131b6709bd531a080995f7e680720e9424328ce1d/shiboken6-6.10.2-cp39-abi3-win_amd64.whl", hash = "sha256:10f3c8c5e1b8bee779346f21c10dbc14cff068f0b0b4e62420c82a6bf36ac2e7", size = 1222052, upload-time = "2026-02-02T08:50:27.502Z" },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/52/421fd378313c89b67ee7d584bf4e9ec088fa1804891b8d74e02b16703457/shiboken6-6.10.2-cp39-abi3-win_arm64.whl", hash = "sha256:20c671645d70835af212ee05df60361d734c5305edb2746e9875c6a31283f963", size = 1784089, upload-time = "2026-02-02T08:50:29.069Z" },
|
|
||||||
]
|
|
||||||
Reference in New Issue
Block a user