few adjustments
This commit is contained in:
parent
7ffb1cd50d
commit
7c157255f4
@ -1,4 +1,5 @@
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
from typing import Optional
|
||||
|
||||
class AlertManager:
|
||||
|
||||
@ -20,6 +21,10 @@ class AlertManager:
|
||||
QMessageBox.critical(parent, error_title, error_text)
|
||||
|
||||
def show_choice(self, message: str, parent=None) -> bool:
|
||||
"""
|
||||
Affiche une boîte de dialogue Oui/Non.
|
||||
Si detailed_text est fourni, l'ajoute comme texte détaillé (affichable par l'utilisateur).
|
||||
"""
|
||||
box = QMessageBox(parent)
|
||||
box.setWindowTitle(self.language_manager.get_text("confirmation"))
|
||||
box.setText(message)
|
||||
|
@ -9,6 +9,7 @@ from app.ui.widgets.loading_bar import LoadingBar
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from typing import List, Dict
|
||||
|
||||
class UpdateManager:
|
||||
def __init__(self, settings_manager: SettingsManager, language_manager: LanguageManager, alert_manager: AlertManager) -> None:
|
||||
@ -20,35 +21,51 @@ class UpdateManager:
|
||||
self.app_os = self.settings_manager.get_config("app_os")
|
||||
self.arch = self.settings_manager.get_config("architecture")
|
||||
|
||||
def get_latest_release_with_asset(self) -> dict:
|
||||
# Récupère la release la plus récente qui contient le bon fichier
|
||||
def get_releases_with_asset(self) -> List[Dict]:
|
||||
"""
|
||||
Retourne la liste des releases (dict) qui contiennent un asset correspondant
|
||||
à l'OS/architecture attendus. Chaque dict contient: tag_name, download_url, body.
|
||||
"""
|
||||
releases_list: List[Dict] = []
|
||||
try:
|
||||
if "gitea" in self.repo_url:
|
||||
owner_repo = self.repo_url.split("/")[-2:]
|
||||
api_url = self.repo_url.replace(owner_repo[0], "api/v1/repos/" + owner_repo[0]) + "/releases"
|
||||
# Gitea: construire URL API (essai basique)
|
||||
owner_repo = self.repo_url.rstrip("/").split("/")[-2:]
|
||||
api_base = self.repo_url.replace("/" + owner_repo[0] + "/" + owner_repo[1], "/api/v1/repos/" + owner_repo[0] + "/" + owner_repo[1])
|
||||
api_url = api_base + "/releases"
|
||||
resp = requests.get(api_url)
|
||||
resp.raise_for_status()
|
||||
releases = resp.json()
|
||||
else:
|
||||
owner_repo = self.repo_url.split("/")[-2:]
|
||||
owner_repo = self.repo_url.rstrip("/").split("/")[-2:]
|
||||
api_url = f"https://api.github.com/repos/{owner_repo[0]}/{owner_repo[1]}/releases"
|
||||
resp = requests.get(api_url)
|
||||
resp.raise_for_status()
|
||||
releases = resp.json()
|
||||
# Cherche le bon asset dans chaque release
|
||||
expected_filename = f"{self.app_name}-{self.app_os}-{self.arch}"
|
||||
|
||||
expected_filename_frag = f"{self.app_name}-{self.app_os}-{self.arch}"
|
||||
for release in releases:
|
||||
tag = release.get("tag_name") or release.get("name")
|
||||
body = release.get("body", "") or ""
|
||||
for asset in release.get("assets", []):
|
||||
if expected_filename in asset.get("name", ""):
|
||||
return {
|
||||
"tag_name": release.get("tag_name"),
|
||||
"download_url": asset.get("browser_download_url")
|
||||
}
|
||||
name = asset.get("name", "")
|
||||
if expected_filename_frag in name:
|
||||
downloads = asset.get("browser_download_url") or asset.get("url")
|
||||
releases_list.append({
|
||||
"tag_name": tag,
|
||||
"download_url": downloads,
|
||||
"body": body
|
||||
})
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
# En cas d'erreur, retourner liste vide (on ne lève pas pour ne pas bloquer l'app)
|
||||
return []
|
||||
return releases_list
|
||||
|
||||
def check_for_update(self, parent=None) -> bool:
|
||||
current_version = self.settings_manager.get_config("app_version")
|
||||
release = self.get_latest_release_with_asset()
|
||||
releases = self.get_releases_with_asset()
|
||||
release = releases[0] if releases else None
|
||||
if release and version.parse(release["tag_name"]) > version.parse(current_version):
|
||||
choice = self.alert_manager.show_choice(
|
||||
self.language_manager.get_text("update_found").replace("{latest_tag}", release["tag_name"]),
|
||||
|
@ -1,11 +1,11 @@
|
||||
from PyQt6.QtWidgets import QApplication, QMainWindow
|
||||
from PyQt6.QtGui import QIcon, QResizeEvent, QCloseEvent
|
||||
from PyQt6.QtCore import QSize, QEvent
|
||||
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QLabel, QFrame
|
||||
from PyQt6.QtGui import QResizeEvent, QCloseEvent
|
||||
from PyQt6.QtCore import QSize, QEvent, Qt
|
||||
from app.core.main_manager import MainManager, NotificationType
|
||||
from app.ui.widgets.tabs_widget import TabsWidget, MenuDirection, ButtonPosition, BorderSide
|
||||
from app.ui.windows.settings_window import SettingsWindow
|
||||
from app.ui.windows.suggestion_window import SuggestionWindow
|
||||
import app.utils.paths as paths
|
||||
import app.utils.paths as paths, shutil
|
||||
from typing import Optional
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
@ -28,6 +28,7 @@ class MainWindow(QMainWindow):
|
||||
self.side_menu: TabsWidget
|
||||
self.settings_window: SettingsWindow
|
||||
self.suggestion_window: SuggestionWindow
|
||||
self.footer_label: QLabel # Ajout d'un attribut pour le footer
|
||||
|
||||
app: Optional[QApplication] = QApplication.instance()
|
||||
size: QSize = app.primaryScreen().size()
|
||||
@ -77,16 +78,35 @@ class MainWindow(QMainWindow):
|
||||
self.current_size.height()
|
||||
)
|
||||
|
||||
# Nettoyage des icônes temporaires générées (supprime tout le dossier temp_icons à la fermeture)
|
||||
try:
|
||||
shutil.rmtree(paths.get_user_temp(self.settings_manager.get_config("app_name")))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def setup_ui(self) -> None:
|
||||
self.side_menu = TabsWidget(self,MenuDirection.HORIZONTAL,70,None,10,1,BorderSide.TOP)
|
||||
self.side_menu = TabsWidget(self, MenuDirection.HORIZONTAL, 70, None, 10, 1, BorderSide.TOP)
|
||||
|
||||
self.settings_window = SettingsWindow(self)
|
||||
self.side_menu.add_widget(self.settings_window,"",paths.get_asset_svg_path("settings"), position=ButtonPosition.CENTER)
|
||||
self.side_menu.add_widget(self.settings_window, "", paths.get_asset_svg_path("settings"), position=ButtonPosition.CENTER)
|
||||
|
||||
self.suggestion_window = SuggestionWindow(self)
|
||||
self.side_menu.add_widget(self.suggestion_window,"",paths.get_asset_svg_path("suggestion"), position=ButtonPosition.CENTER)
|
||||
self.side_menu.add_widget(self.suggestion_window, "", paths.get_asset_svg_path("suggestion"), position=ButtonPosition.CENTER)
|
||||
|
||||
self.setCentralWidget(self.side_menu)
|
||||
# Ajout du footer
|
||||
central_widget = QFrame(self)
|
||||
layout = QVBoxLayout(central_widget)
|
||||
layout.addWidget(self.side_menu)
|
||||
|
||||
self.footer_label = QLabel(self.language_manager.get_text("footer_text"), self)
|
||||
self.footer_label.setAlignment(Qt.AlignmentFlag.AlignRight)
|
||||
self.footer_label.setStyleSheet("padding: 5px; font-size: 12px; color: gray;")
|
||||
layout.addWidget(self.footer_label)
|
||||
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
def update_theme(self) -> None:
|
||||
self.setStyleSheet(self.theme_manager.get_sheet())
|
||||
|
||||
def update_language(self) -> None:
|
||||
self.footer_label.setText(self.language_manager.get_text("footer_text"))
|
@ -2,6 +2,9 @@ from PyQt6.QtWidgets import QLayout, QWidget, QHBoxLayout, QVBoxLayout, QPushBut
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtCore import QSize
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
import hashlib
|
||||
import app.utils.paths as paths
|
||||
from app.core.main_manager import MainManager, NotificationType
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
@ -38,7 +41,7 @@ class TabsWidget(QWidget):
|
||||
self.widgets = []
|
||||
self.button_positions = []
|
||||
self.button_size_ratios = [] # Individual ratios for each button
|
||||
|
||||
self._icon_cache = {}
|
||||
# Track alignment zones
|
||||
self.start_buttons = []
|
||||
self.center_buttons = []
|
||||
@ -448,25 +451,81 @@ class TabsWidget(QWidget):
|
||||
button.style().polish(button)
|
||||
|
||||
def apply_color_to_svg_icon(self, icon_path, color) -> QIcon:
|
||||
"""
|
||||
Create or reuse a colored copy of the SVG in the user's data folder (temp_icons)
|
||||
and return a QIcon that points to it. Original SVG is preserved.
|
||||
|
||||
# Define namespace mapping (based on your SVG)
|
||||
ns = {'ns0': 'http://www.w3.org/2000/svg'}
|
||||
Caching: deterministic filename based on sha256(icon_path + color) so repeated calls reuse files.
|
||||
"""
|
||||
try:
|
||||
if not icon_path:
|
||||
return QIcon()
|
||||
|
||||
# Parse the SVG file
|
||||
tree = ET.parse(icon_path)
|
||||
root = tree.getroot()
|
||||
# deterministic filename based on hash to avoid duplicates
|
||||
hasher = hashlib.sha256()
|
||||
hasher.update(str(Path(icon_path).resolve()).encode('utf-8'))
|
||||
hasher.update(str(color).encode('utf-8'))
|
||||
digest = hasher.hexdigest()
|
||||
new_name = f"{Path(icon_path).stem}_{digest}.svg"
|
||||
|
||||
# Change the fill attribute on the root <svg> element
|
||||
root.attrib['fill'] = color
|
||||
root.attrib['stroke'] = color
|
||||
# Optionally, change fill for all <path> elements as well
|
||||
for path in root.findall('.//ns0:path', ns):
|
||||
path.attrib['fill'] = color
|
||||
path.attrib['stroke'] = color
|
||||
app_name = self.main_manager.get_settings_manager().get_config("app_name")
|
||||
temp_dir = Path(paths.get_user_temp_icons(app_name))
|
||||
temp_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Save the modified SVG
|
||||
tree.write(icon_path)
|
||||
return QIcon(icon_path)
|
||||
tmp_path = temp_dir / new_name
|
||||
|
||||
# If exists in cache and file exists on disk, return immediately
|
||||
cache_key = (str(Path(icon_path).resolve()), color)
|
||||
if cache_key in self._icon_cache:
|
||||
cached_path = Path(self._icon_cache[cache_key])
|
||||
if cached_path.exists():
|
||||
return QIcon(str(cached_path))
|
||||
else:
|
||||
# stale cache entry -> remove
|
||||
del self._icon_cache[cache_key]
|
||||
|
||||
# If file already exists (from previous run), reuse it
|
||||
if tmp_path.exists():
|
||||
self._icon_cache[cache_key] = str(tmp_path)
|
||||
return QIcon(str(tmp_path))
|
||||
|
||||
# Parse original SVG
|
||||
tree = ET.parse(icon_path)
|
||||
root = tree.getroot()
|
||||
|
||||
# Apply fill/stroke to root and to all relevant elements.
|
||||
for el in root.iter():
|
||||
tag = el.tag
|
||||
if not isinstance(tag, str):
|
||||
continue
|
||||
lname = tag.split('}')[-1] # local name
|
||||
if lname in ("svg", "g", "path", "rect", "circle", "ellipse", "polygon", "line", "polyline"):
|
||||
if 'fill' in el.attrib:
|
||||
el.attrib['fill'] = color
|
||||
if 'stroke' in el.attrib:
|
||||
el.attrib['stroke'] = color
|
||||
|
||||
style = el.attrib.get('style')
|
||||
if style:
|
||||
parts = [p.strip() for p in style.split(';') if p.strip()]
|
||||
parts = [p for p in parts if not p.startswith('fill:') and not p.startswith('stroke:')]
|
||||
parts.append(f'fill:{color}')
|
||||
parts.append(f'stroke:{color}')
|
||||
el.attrib['style'] = ';'.join(parts)
|
||||
|
||||
# Write to deterministic file
|
||||
tree.write(tmp_path, encoding='utf-8', xml_declaration=True)
|
||||
|
||||
# Update cache
|
||||
self._icon_cache[cache_key] = str(tmp_path)
|
||||
|
||||
return QIcon(str(tmp_path))
|
||||
except Exception:
|
||||
# On any error, fallback to original icon (do not crash)
|
||||
try:
|
||||
return QIcon(icon_path)
|
||||
except Exception:
|
||||
return QIcon()
|
||||
|
||||
def update_buttons_size(self, size):
|
||||
"""Update all buttons to a specific pixel size (overrides ratio-based sizing)"""
|
||||
|
@ -47,3 +47,11 @@ def get_user_data_dir(app_name: str) -> str:
|
||||
if not path.exists(user_data_path):
|
||||
mkdir(user_data_path)
|
||||
return user_data_path
|
||||
|
||||
def get_user_temp_icons(app_name: str) -> str:
|
||||
user_data_path = get_user_data_dir(app_name)
|
||||
return path.join(user_data_path, "temp", "icons")
|
||||
|
||||
def get_user_temp(app_name: str) -> str:
|
||||
user_data_path = get_user_data_dir(app_name)
|
||||
return path.join(user_data_path, "temp")
|
@ -1 +1 @@
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="100px" height="100px" fill="#4A4A4A" stroke="#4A4A4A"><ns0:path d="M 22.205078 2 A 1.0001 1.0001 0 0 0 21.21875 2.8378906 L 20.246094 8.7929688 C 19.076509 9.1331971 17.961243 9.5922728 16.910156 10.164062 L 11.996094 6.6542969 A 1.0001 1.0001 0 0 0 10.708984 6.7597656 L 6.8183594 10.646484 A 1.0001 1.0001 0 0 0 6.7070312 11.927734 L 10.164062 16.873047 C 9.583454 17.930271 9.1142098 19.051824 8.765625 20.232422 L 2.8359375 21.21875 A 1.0001 1.0001 0 0 0 2.0019531 22.205078 L 2.0019531 27.705078 A 1.0001 1.0001 0 0 0 2.8261719 28.691406 L 8.7597656 29.742188 C 9.1064607 30.920739 9.5727226 32.043065 10.154297 33.101562 L 6.6542969 37.998047 A 1.0001 1.0001 0 0 0 6.7597656 39.285156 L 10.648438 43.175781 A 1.0001 1.0001 0 0 0 11.927734 43.289062 L 16.882812 39.820312 C 17.936999 40.39548 19.054994 40.857928 20.228516 41.201172 L 21.21875 47.164062 A 1.0001 1.0001 0 0 0 22.205078 48 L 27.705078 48 A 1.0001 1.0001 0 0 0 28.691406 47.173828 L 29.751953 41.1875 C 30.920633 40.838997 32.033372 40.369697 33.082031 39.791016 L 38.070312 43.291016 A 1.0001 1.0001 0 0 0 39.351562 43.179688 L 43.240234 39.287109 A 1.0001 1.0001 0 0 0 43.34375 37.996094 L 39.787109 33.058594 C 40.355783 32.014958 40.813915 30.908875 41.154297 29.748047 L 47.171875 28.693359 A 1.0001 1.0001 0 0 0 47.998047 27.707031 L 47.998047 22.207031 A 1.0001 1.0001 0 0 0 47.160156 21.220703 L 41.152344 20.238281 C 40.80968 19.078827 40.350281 17.974723 39.78125 16.931641 L 43.289062 11.933594 A 1.0001 1.0001 0 0 0 43.177734 10.652344 L 39.287109 6.7636719 A 1.0001 1.0001 0 0 0 37.996094 6.6601562 L 33.072266 10.201172 C 32.023186 9.6248101 30.909713 9.1579916 29.738281 8.8125 L 28.691406 2.828125 A 1.0001 1.0001 0 0 0 27.705078 2 L 22.205078 2 z M 23.056641 4 L 26.865234 4 L 27.861328 9.6855469 A 1.0001 1.0001 0 0 0 28.603516 10.484375 C 30.066026 10.848832 31.439607 11.426549 32.693359 12.185547 A 1.0001 1.0001 0 0 0 33.794922 12.142578 L 38.474609 8.7792969 L 41.167969 11.472656 L 37.835938 16.220703 A 1.0001 1.0001 0 0 0 37.796875 17.310547 C 38.548366 18.561471 39.118333 19.926379 39.482422 21.380859 A 1.0001 1.0001 0 0 0 40.291016 22.125 L 45.998047 23.058594 L 45.998047 26.867188 L 40.279297 27.871094 A 1.0001 1.0001 0 0 0 39.482422 28.617188 C 39.122545 30.069817 38.552234 31.434687 37.800781 32.685547 A 1.0001 1.0001 0 0 0 37.845703 33.785156 L 41.224609 38.474609 L 38.53125 41.169922 L 33.791016 37.84375 A 1.0001 1.0001 0 0 0 32.697266 37.808594 C 31.44975 38.567585 30.074755 39.148028 28.617188 39.517578 A 1.0001 1.0001 0 0 0 27.876953 40.3125 L 26.867188 46 L 23.052734 46 L 22.111328 40.337891 A 1.0001 1.0001 0 0 0 21.365234 39.53125 C 19.90185 39.170557 18.522094 38.59371 17.259766 37.835938 A 1.0001 1.0001 0 0 0 16.171875 37.875 L 11.46875 41.169922 L 8.7734375 38.470703 L 12.097656 33.824219 A 1.0001 1.0001 0 0 0 12.138672 32.724609 C 11.372652 31.458855 10.793319 30.079213 10.427734 28.609375 A 1.0001 1.0001 0 0 0 9.6328125 27.867188 L 4.0019531 26.867188 L 4.0019531 23.052734 L 9.6289062 22.117188 A 1.0001 1.0001 0 0 0 10.435547 21.373047 C 10.804273 19.898143 11.383325 18.518729 12.146484 17.255859 A 1.0001 1.0001 0 0 0 12.111328 16.164062 L 8.8261719 11.46875 L 11.523438 8.7734375 L 16.185547 12.105469 A 1.0001 1.0001 0 0 0 17.28125 12.148438 C 18.536908 11.394293 19.919867 10.822081 21.384766 10.462891 A 1.0001 1.0001 0 0 0 22.132812 9.6523438 L 23.056641 4 z M 25 17 C 20.593567 17 17 20.593567 17 25 C 17 29.406433 20.593567 33 25 33 C 29.406433 33 33 29.406433 33 25 C 33 20.593567 29.406433 17 25 17 z M 25 19 C 28.325553 19 31 21.674447 31 25 C 31 28.325553 28.325553 31 25 31 C 21.674447 31 19 28.325553 19 25 C 19 21.674447 21.674447 19 25 19 z" fill="#4A4A4A" stroke="#4A4A4A" /></ns0:svg>
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="100px" height="100px"><ns0:path d="M 22.205078 2 A 1.0001 1.0001 0 0 0 21.21875 2.8378906 L 20.246094 8.7929688 C 19.076509 9.1331971 17.961243 9.5922728 16.910156 10.164062 L 11.996094 6.6542969 A 1.0001 1.0001 0 0 0 10.708984 6.7597656 L 6.8183594 10.646484 A 1.0001 1.0001 0 0 0 6.7070312 11.927734 L 10.164062 16.873047 C 9.583454 17.930271 9.1142098 19.051824 8.765625 20.232422 L 2.8359375 21.21875 A 1.0001 1.0001 0 0 0 2.0019531 22.205078 L 2.0019531 27.705078 A 1.0001 1.0001 0 0 0 2.8261719 28.691406 L 8.7597656 29.742188 C 9.1064607 30.920739 9.5727226 32.043065 10.154297 33.101562 L 6.6542969 37.998047 A 1.0001 1.0001 0 0 0 6.7597656 39.285156 L 10.648438 43.175781 A 1.0001 1.0001 0 0 0 11.927734 43.289062 L 16.882812 39.820312 C 17.936999 40.39548 19.054994 40.857928 20.228516 41.201172 L 21.21875 47.164062 A 1.0001 1.0001 0 0 0 22.205078 48 L 27.705078 48 A 1.0001 1.0001 0 0 0 28.691406 47.173828 L 29.751953 41.1875 C 30.920633 40.838997 32.033372 40.369697 33.082031 39.791016 L 38.070312 43.291016 A 1.0001 1.0001 0 0 0 39.351562 43.179688 L 43.240234 39.287109 A 1.0001 1.0001 0 0 0 43.34375 37.996094 L 39.787109 33.058594 C 40.355783 32.014958 40.813915 30.908875 41.154297 29.748047 L 47.171875 28.693359 A 1.0001 1.0001 0 0 0 47.998047 27.707031 L 47.998047 22.207031 A 1.0001 1.0001 0 0 0 47.160156 21.220703 L 41.152344 20.238281 C 40.80968 19.078827 40.350281 17.974723 39.78125 16.931641 L 43.289062 11.933594 A 1.0001 1.0001 0 0 0 43.177734 10.652344 L 39.287109 6.7636719 A 1.0001 1.0001 0 0 0 37.996094 6.6601562 L 33.072266 10.201172 C 32.023186 9.6248101 30.909713 9.1579916 29.738281 8.8125 L 28.691406 2.828125 A 1.0001 1.0001 0 0 0 27.705078 2 L 22.205078 2 z M 23.056641 4 L 26.865234 4 L 27.861328 9.6855469 A 1.0001 1.0001 0 0 0 28.603516 10.484375 C 30.066026 10.848832 31.439607 11.426549 32.693359 12.185547 A 1.0001 1.0001 0 0 0 33.794922 12.142578 L 38.474609 8.7792969 L 41.167969 11.472656 L 37.835938 16.220703 A 1.0001 1.0001 0 0 0 37.796875 17.310547 C 38.548366 18.561471 39.118333 19.926379 39.482422 21.380859 A 1.0001 1.0001 0 0 0 40.291016 22.125 L 45.998047 23.058594 L 45.998047 26.867188 L 40.279297 27.871094 A 1.0001 1.0001 0 0 0 39.482422 28.617188 C 39.122545 30.069817 38.552234 31.434687 37.800781 32.685547 A 1.0001 1.0001 0 0 0 37.845703 33.785156 L 41.224609 38.474609 L 38.53125 41.169922 L 33.791016 37.84375 A 1.0001 1.0001 0 0 0 32.697266 37.808594 C 31.44975 38.567585 30.074755 39.148028 28.617188 39.517578 A 1.0001 1.0001 0 0 0 27.876953 40.3125 L 26.867188 46 L 23.052734 46 L 22.111328 40.337891 A 1.0001 1.0001 0 0 0 21.365234 39.53125 C 19.90185 39.170557 18.522094 38.59371 17.259766 37.835938 A 1.0001 1.0001 0 0 0 16.171875 37.875 L 11.46875 41.169922 L 8.7734375 38.470703 L 12.097656 33.824219 A 1.0001 1.0001 0 0 0 12.138672 32.724609 C 11.372652 31.458855 10.793319 30.079213 10.427734 28.609375 A 1.0001 1.0001 0 0 0 9.6328125 27.867188 L 4.0019531 26.867188 L 4.0019531 23.052734 L 9.6289062 22.117188 A 1.0001 1.0001 0 0 0 10.435547 21.373047 C 10.804273 19.898143 11.383325 18.518729 12.146484 17.255859 A 1.0001 1.0001 0 0 0 12.111328 16.164062 L 8.8261719 11.46875 L 11.523438 8.7734375 L 16.185547 12.105469 A 1.0001 1.0001 0 0 0 17.28125 12.148438 C 18.536908 11.394293 19.919867 10.822081 21.384766 10.462891 A 1.0001 1.0001 0 0 0 22.132812 9.6523438 L 23.056641 4 z M 25 17 C 20.593567 17 17 20.593567 17 25 C 17 29.406433 20.593567 33 25 33 C 29.406433 33 33 29.406433 33 25 C 33 20.593567 29.406433 17 25 17 z M 25 19 C 28.325553 19 31 21.674447 31 25 C 31 28.325553 28.325553 31 25 31 C 21.674447 31 19 28.325553 19 25 C 19 21.674447 21.674447 19 25 19 z" fill="#D1D1D6"/></ns0:svg>
|
@ -1,8 +1,8 @@
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" fill="#D1D1D6" width="800px" height="800px" viewBox="0 0 64 64" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" version="1.1" xml:space="preserve" stroke="#D1D1D6">
|
||||
<ns0:svg xmlns:ns0="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 64 64" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" version="1.1" xml:space="preserve">
|
||||
|
||||
<ns0:g id="ICON">
|
||||
|
||||
<ns0:path d="M59,43l-54,0l-0,-9c-0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1c-0,5.651 -0,11.154 -0,14c-0,0.796 0.316,1.559 0.879,2.121c0.562,0.563 1.325,0.879 2.121,0.879l4,0c0.552,0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-4,0c-0.265,-0 -0.52,-0.105 -0.707,-0.293c-0.188,-0.187 -0.293,-0.442 -0.293,-0.707l-0,-3l54,0l-0,3c0,0.265 -0.105,0.52 -0.293,0.707c-0.187,0.188 -0.442,0.293 -0.707,0.293l-44,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1l12.606,0c-0.16,2.682 -0.855,6.147 -3.417,8l-1.689,0c-0.552,-0 -1,0.448 -1,1c-0,0.552 0.448,1 1,1l21,0c0.552,-0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-1.689,0c-2.562,-1.854 -3.257,-5.318 -3.417,-8l20.606,0c0.796,-0 1.559,-0.316 2.121,-0.879c0.563,-0.562 0.879,-1.325 0.879,-2.121c-0,-6.028 -0,-23.972 -0,-30c0,-0.796 -0.316,-1.559 -0.879,-2.121c-0.562,-0.563 -1.325,-0.879 -2.121,-0.879l-11,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1l11,-0c0.265,0 0.52,0.105 0.707,0.293c0.188,0.187 0.293,0.442 0.293,0.707l-0,25Zm-23.606,8l-6.788,0c-0.155,2.531 -0.785,5.68 -2.585,8l11.958,0c-1.8,-2.32 -2.43,-5.47 -2.585,-8Zm-6.394,-9l6.5,0c0.552,0 1,-0.448 1,-1c0,-0.552 -0.448,-1 -1,-1l-6.5,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1Zm-22,-4l0,2c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1l0,-2c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1Zm20.5,1l9.5,0c0.552,-0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-9.5,0c-0.552,-0 -1,0.448 -1,1c-0,0.552 0.448,1 1,1Zm2.501,-3l-3.406,0c-0.261,0 -0.511,-0.102 -0.698,-0.284c-3.344,-3.257 -6.897,-8.272 -6.897,-14.756c0,-7.152 5.824,-12.96 13,-12.96c7.176,0 13,5.808 13,12.96c-0,6.484 -3.553,11.499 -6.897,14.756c-0.187,0.182 -0.437,0.284 -0.698,0.284l-3.405,0c0,0 -1,-0.003 -1,-1l0,-11l-2,0l0,10.999c0,0.652 -0.447,1.001 -0.999,1.001Zm-21.001,-1l0,-13c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1l0,13c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1Zm26,-1c0.871,-0 1.995,-0 1.995,-0c2.941,-2.949 6.005,-7.36 6.005,-13.04c0,-6.05 -4.93,-10.96 -11,-10.96c-6.07,0 -11,4.91 -11,10.96c-0,5.68 3.064,10.091 6.005,13.04l1.995,0l0,-10l-2,0c-2.208,0 -4,-1.792 -4,-4c0,-2.208 1.792,-4 4,-4c2.208,0 4,1.792 4,4l0,2l2,0l0,-2c0,-2.208 1.792,-4 4,-4c2.208,0 4,1.792 4,4c0,2.208 -1.792,4 -4,4l-2,0l0,10Zm-18,-19l-11,0c-0.796,0 -1.559,0.316 -2.121,0.879c-0.563,0.562 -0.879,1.325 -0.879,2.121c-0,2.509 -0,7.081 -0,12c-0,0.552 0.448,1 1,1c0.552,0 1,-0.448 1,-1l-0,-12c-0,-0.265 0.105,-0.52 0.293,-0.707c0.187,-0.188 0.442,-0.293 0.707,-0.293c0,0 11,0 11,0c0.552,0 1,-0.448 1,-1c0,-0.552 -0.448,-1 -1,-1Zm18,7l2,0c1.104,0 2,-0.896 2,-2c0,-1.104 -0.896,-2 -2,-2c-1.104,0 -2,0.896 -2,2l0,2Zm-6,0l0,-2c0,-1.104 -0.896,-2 -2,-2c-1.104,0 -2,0.896 -2,2c0,1.104 0.896,2 2,2l2,0Zm-2.509,-14.792l-1,-1.732c-0.276,-0.478 -0.888,-0.642 -1.366,-0.366c-0.478,0.276 -0.642,0.888 -0.366,1.366l1,1.732c0.276,0.478 0.888,0.642 1.366,0.366c0.478,-0.276 0.642,-0.888 0.366,-1.366Zm12.75,1l1,-1.732c0.276,-0.478 0.112,-1.09 -0.366,-1.366c-0.478,-0.276 -1.09,-0.112 -1.366,0.366l-1,1.732c-0.276,0.478 -0.112,1.09 0.366,1.366c0.478,0.276 1.09,0.112 1.366,-0.366Zm-6.241,-2.208l0,-2c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1l0,2c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1Z" fill="#D1D1D6" stroke="#D1D1D6" />
|
||||
<ns0:path d="M59,43l-54,0l-0,-9c-0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1c-0,5.651 -0,11.154 -0,14c-0,0.796 0.316,1.559 0.879,2.121c0.562,0.563 1.325,0.879 2.121,0.879l4,0c0.552,0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-4,0c-0.265,-0 -0.52,-0.105 -0.707,-0.293c-0.188,-0.187 -0.293,-0.442 -0.293,-0.707l-0,-3l54,0l-0,3c0,0.265 -0.105,0.52 -0.293,0.707c-0.187,0.188 -0.442,0.293 -0.707,0.293l-44,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1l12.606,0c-0.16,2.682 -0.855,6.147 -3.417,8l-1.689,0c-0.552,-0 -1,0.448 -1,1c-0,0.552 0.448,1 1,1l21,0c0.552,-0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-1.689,0c-2.562,-1.854 -3.257,-5.318 -3.417,-8l20.606,0c0.796,-0 1.559,-0.316 2.121,-0.879c0.563,-0.562 0.879,-1.325 0.879,-2.121c-0,-6.028 -0,-23.972 -0,-30c0,-0.796 -0.316,-1.559 -0.879,-2.121c-0.562,-0.563 -1.325,-0.879 -2.121,-0.879l-11,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1l11,-0c0.265,0 0.52,0.105 0.707,0.293c0.188,0.187 0.293,0.442 0.293,0.707l-0,25Zm-23.606,8l-6.788,0c-0.155,2.531 -0.785,5.68 -2.585,8l11.958,0c-1.8,-2.32 -2.43,-5.47 -2.585,-8Zm-6.394,-9l6.5,0c0.552,0 1,-0.448 1,-1c0,-0.552 -0.448,-1 -1,-1l-6.5,0c-0.552,0 -1,0.448 -1,1c0,0.552 0.448,1 1,1Zm-22,-4l0,2c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1l0,-2c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1Zm20.5,1l9.5,0c0.552,-0 1,-0.448 1,-1c-0,-0.552 -0.448,-1 -1,-1l-9.5,0c-0.552,-0 -1,0.448 -1,1c-0,0.552 0.448,1 1,1Zm2.501,-3l-3.406,0c-0.261,0 -0.511,-0.102 -0.698,-0.284c-3.344,-3.257 -6.897,-8.272 -6.897,-14.756c0,-7.152 5.824,-12.96 13,-12.96c7.176,0 13,5.808 13,12.96c-0,6.484 -3.553,11.499 -6.897,14.756c-0.187,0.182 -0.437,0.284 -0.698,0.284l-3.405,0c0,0 -1,-0.003 -1,-1l0,-11l-2,0l0,10.999c0,0.652 -0.447,1.001 -0.999,1.001Zm-21.001,-1l0,-13c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1l0,13c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1Zm26,-1c0.871,-0 1.995,-0 1.995,-0c2.941,-2.949 6.005,-7.36 6.005,-13.04c0,-6.05 -4.93,-10.96 -11,-10.96c-6.07,0 -11,4.91 -11,10.96c-0,5.68 3.064,10.091 6.005,13.04l1.995,0l0,-10l-2,0c-2.208,0 -4,-1.792 -4,-4c0,-2.208 1.792,-4 4,-4c2.208,0 4,1.792 4,4l0,2l2,0l0,-2c0,-2.208 1.792,-4 4,-4c2.208,0 4,1.792 4,4c0,2.208 -1.792,4 -4,4l-2,0l0,10Zm-18,-19l-11,0c-0.796,0 -1.559,0.316 -2.121,0.879c-0.563,0.562 -0.879,1.325 -0.879,2.121c-0,2.509 -0,7.081 -0,12c-0,0.552 0.448,1 1,1c0.552,0 1,-0.448 1,-1l-0,-12c-0,-0.265 0.105,-0.52 0.293,-0.707c0.187,-0.188 0.442,-0.293 0.707,-0.293c0,0 11,0 11,0c0.552,0 1,-0.448 1,-1c0,-0.552 -0.448,-1 -1,-1Zm18,7l2,0c1.104,0 2,-0.896 2,-2c0,-1.104 -0.896,-2 -2,-2c-1.104,0 -2,0.896 -2,2l0,2Zm-6,0l0,-2c0,-1.104 -0.896,-2 -2,-2c-1.104,0 -2,0.896 -2,2c0,1.104 0.896,2 2,2l2,0Zm-2.509,-14.792l-1,-1.732c-0.276,-0.478 -0.888,-0.642 -1.366,-0.366c-0.478,0.276 -0.642,0.888 -0.366,1.366l1,1.732c0.276,0.478 0.888,0.642 1.366,0.366c0.478,-0.276 0.642,-0.888 0.366,-1.366Zm12.75,1l1,-1.732c0.276,-0.478 0.112,-1.09 -0.366,-1.366c-0.478,-0.276 -1.09,-0.112 -1.366,0.366l-1,1.732c-0.276,0.478 -0.112,1.09 0.366,1.366c0.478,0.276 1.09,0.112 1.366,-0.366Zm-6.241,-2.208l0,-2c0,-0.552 -0.448,-1 -1,-1c-0.552,-0 -1,0.448 -1,1l0,2c0,0.552 0.448,1 1,1c0.552,-0 1,-0.448 1,-1Z" fill="#FFFFFF" stroke="#FFFFFF" />
|
||||
|
||||
</ns0:g>
|
||||
|
||||
|
@ -23,5 +23,6 @@
|
||||
"update_downloaded": "Update downloaded to {local_path}",
|
||||
"update_download_error": "Error downloading update",
|
||||
"downloading_update": "Downloading update...",
|
||||
"update": "Update"
|
||||
"update": "Update",
|
||||
"footer_text": "© 2025 Louis Mazin. All rights reserved."
|
||||
}
|
@ -23,5 +23,6 @@
|
||||
"update_downloaded": "Mise à jour téléchargée dans {local_path}",
|
||||
"update_download_error": "Erreur lors du téléchargement de la mise à jour",
|
||||
"downloading_update": "Téléchargement de la mise à jour...",
|
||||
"update": "Mise à jour"
|
||||
"update": "Mise à jour",
|
||||
"footer_text": "© 2025 Louis Mazin. Tous droits réservés."
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user