|
1 | 1 | import os |
2 | | -import re |
3 | 2 | import shutil |
4 | 3 | import ssl |
5 | 4 | import subprocess |
6 | 5 | import sys |
7 | 6 | import urllib.request |
8 | | -from typing import Dict |
9 | 7 |
|
10 | 8 | import certifi |
11 | 9 | from PyQt6.QtCore import QPropertyAnimation, Qt, QThread, QTimer, QUrl, pyqtSignal |
12 | | -from PyQt6.QtGui import QDesktopServices, QFont, QFontDatabase, QIcon, QPixmap |
| 10 | +from PyQt6.QtGui import QDesktopServices, QFont, QIcon, QPixmap |
13 | 11 | from PyQt6.QtWidgets import ( |
14 | 12 | QApplication, |
15 | 13 | QDialog, |
@@ -227,14 +225,15 @@ def install_theme(self): |
227 | 225 | layout = QVBoxLayout(self.dialog) |
228 | 226 |
|
229 | 227 | confirmation_message = QLabel( |
230 | | - f"Are you sure you want to install the theme <b>{self.theme_data['name']}</b>?<br>This will overwrite your current config and styles files." |
| 228 | + f"Are you sure you want to install the theme <b>{self.theme_data['name']}</b>?<br>" |
| 229 | + f"This will overwrite your current config and styles files." |
231 | 230 | ) |
232 | 231 | confirmation_message.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) |
233 | 232 | layout.addWidget(confirmation_message) |
234 | 233 |
|
235 | 234 | self.compat_label = QLabel("Checking compatibility...") |
236 | 235 | layout.addWidget(self.compat_label) |
237 | | - QTimer.singleShot(1000, lambda: self._check_font_families(self.theme_data["id"])) |
| 236 | + QTimer.singleShot(0, self._show_font_guidance) |
238 | 237 | # Add Yes and No buttons |
239 | 238 | button_layout = QHBoxLayout() |
240 | 239 | self.yes_button = QPushButton("Install") |
@@ -300,82 +299,37 @@ def install_theme(self): |
300 | 299 | except Exception as e: |
301 | 300 | QMessageBox.critical(self, "Error", f"Failed to install theme: {str(e)}") |
302 | 301 |
|
303 | | - def _check_font_families(self, theme_id): |
304 | | - try: |
305 | | - styles_url = f"https://raw.githubusercontent.com/amnweb/yasb-themes/main/themes/{theme_id}/styles.css" |
306 | | - context = ssl.create_default_context(cafile=certifi.where()) |
307 | | - with urllib.request.urlopen(styles_url, context=context, timeout=5) as resp: |
308 | | - css = resp.read().decode("utf-8") |
309 | | - css = self._extract_and_replace_variables(css) |
310 | | - available_fonts = set(QFontDatabase.families()) |
311 | | - font_families = set() |
312 | | - missing_fonts = set() |
313 | | - matches = re.findall(r"font-family\s*:\s*([^;}\n]+)\s*[;}]+", css, flags=re.IGNORECASE) |
314 | | - for match in matches: |
315 | | - fonts = [f.strip(" '\"\t\r\n") for f in match.split(",")] |
316 | | - for font in fonts: |
317 | | - if font: |
318 | | - font_families.add(font) |
319 | | - if font not in available_fonts: |
320 | | - missing_fonts.add(font) |
321 | | - |
322 | | - if missing_fonts: |
323 | | - missing_fonts_label = "Some theme fonts are missing from your system" |
324 | | - self.compat_label.setStyleSheet(""" |
325 | | - QLabel { |
326 | | - font-size: 12px; |
327 | | - padding: 10px; |
328 | | - margin: 0px 10px 10px 10px; |
329 | | - font-family: 'Segoe UI'; |
330 | | - color: #f1e1c9; |
331 | | - background-color:#34291c; |
332 | | - border: 1px solid #955816; |
333 | | - border-radius: 4px |
334 | | - } |
335 | | - """) |
336 | | - self.compat_label.setText(f"{missing_fonts_label}<br><b>{'<br>'.join(sorted(missing_fonts))}</b>") |
337 | | - self.yes_button.setText("Install anyway") |
338 | | - else: |
339 | | - self.compat_label.hide() |
340 | | - except Exception as e: |
341 | | - self.compat_label.setStyleSheet(""" |
342 | | - QLabel { |
343 | | - font-size: 12px; |
344 | | - padding: 10px; |
345 | | - font-family: 'Segoe UI'; |
346 | | - color: #fff; |
347 | | - background-color: #a00; |
348 | | - border: 1px solid #c33; |
349 | | - border-radius: 4px |
350 | | - } |
351 | | - """) |
352 | | - self.compat_label.setText(f"Error checking fonts: {str(e)}") |
353 | | - self.compat_label.setWordWrap(True) |
354 | | - self.yes_button.setText("Install anyway") |
355 | | - finally: |
356 | | - self.dialog.adjustSize() |
357 | | - |
358 | | - def _extract_and_replace_variables(self, css: str) -> str: |
359 | | - # Extract variables from :root |
360 | | - root_vars: Dict[str, str] = {} |
361 | | - |
362 | | - def root_replacer(match): |
363 | | - content = match.group(1) |
364 | | - for var_match in re.finditer(r"--([\w-]+)\s*:\s*([^;]+);", content): |
365 | | - var_name = f"--{var_match.group(1).strip()}" |
366 | | - var_value = var_match.group(2).strip() |
367 | | - root_vars[var_name] = var_value |
368 | | - return "" # Remove :root block |
369 | | - |
370 | | - css = re.sub(r":root\s*{([^}]*)}", root_replacer, css, flags=re.DOTALL) |
371 | | - |
372 | | - # Replace var(--name) with value |
373 | | - def var_replacer(match): |
374 | | - var_name = match.group(1).strip() |
375 | | - return root_vars.get(var_name, match.group(0)) |
| 302 | + def _show_font_guidance(self): |
| 303 | + theme_id = self.theme_data.get("id", "") |
| 304 | + repo_url = ( |
| 305 | + f"https://github.com/amnweb/yasb-themes/tree/main/themes/{theme_id}" |
| 306 | + if theme_id |
| 307 | + else "https://github.com/amnweb/yasb-themes" |
| 308 | + ) |
376 | 309 |
|
377 | | - css = re.sub(r"var\((--[\w-]+)\)", var_replacer, css) |
378 | | - return css |
| 310 | + self.compat_label.setStyleSheet(""" |
| 311 | + QLabel { |
| 312 | + font-size: 12px; |
| 313 | + padding: 10px; |
| 314 | + margin: 0px 10px 10px 10px; |
| 315 | + font-family: 'Segoe UI'; |
| 316 | + color: #f1e1c9; |
| 317 | + background-color:#34291c; |
| 318 | + border: 1px solid #955816; |
| 319 | + border-radius: 4px |
| 320 | + } |
| 321 | + QLabel a { |
| 322 | + text-decoration: none; |
| 323 | + } |
| 324 | + """) |
| 325 | + self.compat_label.setWordWrap(True) |
| 326 | + self.compat_label.setOpenExternalLinks(True) |
| 327 | + self.compat_label.setText( |
| 328 | + "Note: Some themes require additional fonts.<br>Review the " |
| 329 | + f"<a href='{repo_url}'>theme</a> or <a href='{repo_url}/styles.css'>styles.css</a> " |
| 330 | + f"to confirm font requirements before installing." |
| 331 | + ) |
| 332 | + self.dialog.adjustSize() |
379 | 333 |
|
380 | 334 |
|
381 | 335 | class ThemeViewer(QMainWindow): |
|
0 commit comments