Seregon/PkgToolBox

Toolbox for analyzing and editing pkg application files for psp,ps3, ps4 and ps5, includes the most useful functions you might need.

Python/57.3 KB/No license
GraphicUserInterface/utils/style_manager.py
PkgToolBox / GraphicUserInterface / utils / style_manager.py
1import json
2from PyQt5.QtGui import QFont, QColor
3from PyQt5.QtCore import Qt
4from PyQt5.QtWidgets import QWidget
5import os
6import logging
7 
8class StyleManager:
9 DEFAULT_SETTINGS = {
10 "appearance": {
11 "theme": "Light",
12 "night_mode": False,
13 "font_family": "Arial",
14 "font_size": 12,
15 "colors": {
16 "background": "#ffffff",
17 "text": "#000000",
18 "accent": "#3498db"
19 }
20 }
21 }
22 
23 # Temi predefiniti
24 THEMES = {
25 'Light': {
26 'background': '#ffffff',
27 'secondary_bg': '#f5f6fa',
28 'text': '#2c3e50',
29 'secondary_text': '#7f8c8d',
30 'accent': '#3498db',
31 'accent_hover': '#2980b9',
32 'border': '#bdc3c7',
33 'selection': '#3498db',
34 'hover': '#e8f0fe',
35 'error': '#e74c3c',
36 'success': '#2ecc71',
37 'warning': '#f1c40f'
38 },
39 'Dark': {
40 'background': '#1e1e1e',
41 'secondary_bg': '#2d2d2d',
42 'text': '#ffffff',
43 'secondary_text': '#cccccc',
44 'accent': '#3498db',
45 'accent_hover': '#2980b9',
46 'border': '#3d3d3d',
47 'selection': '#0d47a1',
48 'hover': '#353535',
49 'error': '#e74c3c',
50 'success': '#2ecc71',
51 'warning': '#f1c40f'
52 },
53 'Custom': {
54 'background': '#ffffff',
55 'secondary_bg': '#f5f6fa',
56 'text': '#2c3e50',
57 'secondary_text': '#7f8c8d',
58 'accent': '#3498db',
59 'accent_hover': '#2980b9',
60 'border': '#bdc3c7',
61 'selection': '#3498db',
62 'hover': '#e8f0fe',
63 'error': '#e74c3c',
64 'success': '#2ecc71',
65 'warning': '#f1c40f'
66 }
67 }
68 
69 @staticmethod
70 def get_theme_colors(theme_name, custom_colors=None):
71 """Get colors for specified theme"""
72 if theme_name == 'Custom' and custom_colors:
73 colors = StyleManager.THEMES['Custom'].copy()
74 colors.update({
75 'background': custom_colors.get('bg_color', colors['background']),
76 'text': custom_colors.get('text_color', colors['text']),
77 'accent': custom_colors.get('accent_color', colors['accent'])
78 })
79 return colors
80 return StyleManager.THEMES.get(theme_name, StyleManager.THEMES['Light'])
81 
82 @staticmethod
83 def load_settings(filename="settings.json"):
84 """Load settings from file"""
85 try:
86 config_dir = os.path.join(os.path.expanduser("~"), ".pkgtoolbox")
87 config_file = os.path.join(config_dir, filename)
88
89 if os.path.exists(config_file):
90 with open(config_file, "r", encoding='utf-8') as f:
91 settings = json.load(f)
92 # Assicurati che tutte le chiavi necessarie esistano
93 if "appearance" not in settings:
94 settings["appearance"] = StyleManager.DEFAULT_SETTINGS["appearance"]
95 if "colors" not in settings["appearance"]:
96 settings["appearance"]["colors"] = StyleManager.DEFAULT_SETTINGS["appearance"]["colors"]
97 return settings
98 return StyleManager.DEFAULT_SETTINGS
99 except Exception as e:
100 logging.error(f"Error loading settings: {e}")
101 return StyleManager.DEFAULT_SETTINGS
102 
103 @staticmethod
104 def save_settings(settings, filename="settings.json"):
105 """Save settings to file"""
106 try:
107 config_dir = os.path.join(os.path.expanduser("~"), ".pkgtoolbox")
108 if not os.path.exists(config_dir):
109 os.makedirs(config_dir)
110
111 config_file = os.path.join(config_dir, filename)
112
113 # Assicurati che le impostazioni siano nel formato corretto
114 if "appearance" not in settings:
115 settings["appearance"] = {}
116 if "colors" not in settings["appearance"]:
117 settings["appearance"]["colors"] = {}
118
119 # Salva le impostazioni
120 with open(config_file, "w", encoding='utf-8') as f:
121 json.dump(settings, f, indent=4, ensure_ascii=False)
122 except Exception as e:
123 logging.error(f"Error saving settings: {e}")
124 raise
125 
126 @staticmethod
127 def apply_theme(widget, settings):
128 """Apply theme to widget"""
129 # Estrai i colori dalle impostazioni
130 appearance = settings.get("appearance", {})
131 colors = appearance.get("colors", {})
132
133 # Colori predefiniti
134 default_colors = {
135 'background': colors.get("background", "#ffffff"),
136 'text': colors.get("text", "#000000"),
137 'accent': colors.get("accent", "#3498db"),
138 'secondary_bg': colors.get("background", "#ffffff"), # Usa il colore di sfondo come fallback
139 'secondary_text': colors.get("text", "#000000"), # Usa il colore del testo come fallback
140 'accent_hover': "#2980b9",
141 'border': "#bdc3c7",
142 'selection': "#3498db",
143 'hover': "#e8f0fe",
144 'error': "#e74c3c",
145 'success': "#2ecc71",
146 'warning': "#f1c40f"
147 }
148
149 # Applica lo stile
150 widget.setStyleSheet(f"""
151 /* Base */
152 QMainWindow, QWidget {{
153 background-color: {default_colors['background']};
154 color: {default_colors['text']};
155 }}
156
157 /* Input Fields */
158 QLineEdit, QTextEdit, QPlainTextEdit {{
159 background-color: {default_colors['secondary_bg']};
160 color: {default_colors['text']};
161 border: 1px solid {default_colors['border']};
162 border-radius: 4px;
163 padding: 5px;
164 selection-background-color: {default_colors['selection']};
165 selection-color: white;
166 }}
167
168 /* Buttons */
169 QPushButton {{
170 background-color: {default_colors['accent']};
171 color: white;
172 border: none;
173 padding: 8px;
174 border-radius: 4px;
175 }}
176 QPushButton:hover {{
177 background-color: {default_colors['accent_hover']};
178 }}
179 QPushButton:pressed {{
180 background-color: {default_colors['selection']};
181 }}
182 QPushButton:disabled {{
183 background-color: {default_colors['secondary_bg']};
184 color: {default_colors['secondary_text']};
185 }}
186
187 /* Tree/List Widgets */
188 QTreeWidget, QListWidget {{
189 background-color: {default_colors['background']};
190 alternate-background-color: {default_colors['secondary_bg']};
191 color: {default_colors['text']};
192 border: 1px solid {default_colors['border']};
193 border-radius: 4px;
194 }}
195 QTreeWidget::item:hover, QListWidget::item:hover {{
196 background-color: {default_colors['hover']};
197 }}
198 QTreeWidget::item:selected, QListWidget::item:selected {{
199 background-color: {default_colors['selection']};
200 color: white;
201 }}
202
203 /* Headers */
204 QHeaderView::section {{
205 background-color: {default_colors['secondary_bg']};
206 color: {default_colors['text']};
207 padding: 5px;
208 border: none;
209 }}
210
211 /* Tabs */
212 QTabWidget::pane {{
213 border: 1px solid {default_colors['border']};
214 border-radius: 4px;
215 }}
216 QTabBar::tab {{
217 background: {default_colors['secondary_bg']};
218 color: {default_colors['text']};
219 padding: 8px;
220 margin: 2px;
221 border-radius: 4px;
222 }}
223 QTabBar::tab:selected {{
224 background: {default_colors['accent']};
225 color: white;
226 }}
227 QTabBar::tab:hover {{
228 background: {default_colors['hover']};
229 }}
230
231 /* Menus */
232 QMenuBar {{
233 background-color: {default_colors['background']};
234 color: {default_colors['text']};
235 }}
236 QMenuBar::item:selected {{
237 background-color: {default_colors['hover']};
238 }}
239 QMenu {{
240 background-color: {default_colors['background']};
241 color: {default_colors['text']};
242 border: 1px solid {default_colors['border']};
243 }}
244 QMenu::item:selected {{
245 background-color: {default_colors['selection']};
246 color: white;
247 }}
248
249 /* Combo/Spin Boxes */
250 QComboBox, QSpinBox {{
251 background-color: {default_colors['secondary_bg']};
252 color: {default_colors['text']};
253 border: 1px solid {default_colors['border']};
254 border-radius: 4px;
255 padding: 5px;
256 }}
257 QComboBox::drop-down {{
258 border: none;
259 }}
260 QComboBox::down-arrow {{
261 image: none;
262 }}
263
264 /* Scroll Bars */
265 QScrollBar:vertical {{
266 background-color: {default_colors['secondary_bg']};
267 width: 12px;
268 margin: 0px;
269 border-radius: 6px;
270 }}
271 QScrollBar::handle:vertical {{
272 background-color: {default_colors['accent']};
273 min-height: 20px;
274 border-radius: 6px;
275 }}
276 QScrollBar:horizontal {{
277 background-color: {default_colors['secondary_bg']};
278 height: 12px;
279 margin: 0px;
280 border-radius: 6px;
281 }}
282 QScrollBar::handle:horizontal {{
283 background-color: {default_colors['accent']};
284 min-width: 20px;
285 border-radius: 6px;
286 }}
287
288 /* Group Box */
289 QGroupBox {{
290 border: 1px solid {default_colors['border']};
291 border-radius: 4px;
292 margin-top: 1ex;
293 padding: 5px;
294 color: {default_colors['text']};
295 }}
296 QGroupBox::title {{
297 subcontrol-origin: margin;
298 subcontrol-position: top left;
299 padding: 0 3px;
300 color: {default_colors['text']};
301 }}
302
303 /* Tool Tips */
304 QToolTip {{
305 background-color: {default_colors['background']};
306 color: {default_colors['text']};
307 border: 1px solid {default_colors['border']};
308 border-radius: 4px;
309 padding: 5px;
310 }}
311
312 /* Progress Bar */
313 QProgressBar {{
314 border: 1px solid {default_colors['border']};
315 border-radius: 4px;
316 text-align: center;
317 }}
318 QProgressBar::chunk {{
319 background-color: {default_colors['accent']};
320 }}
321 """)
322
323 # Forza l'aggiornamento dello stile per tutti i widget figli
324 for child in widget.findChildren(QWidget):
325 child.setStyleSheet(child.styleSheet())
326 
327 @staticmethod
328 def adjust_color(color, amount):
329 """Adjust color brightness"""
330 if color.startswith('#'):
331 color = color[1:]
332 rgb = tuple(int(color[i:i+2], 16) for i in (0, 2, 4))
333 rgb = tuple(min(255, max(0, c + amount)) for c in rgb)
334 return f"#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}"