mirror of
https://git.srhtnin.garden/sarah/SaraView.git
synced 2026-10-14 02:38:11 +02:00
Client: Windows support
This commit is contained in:
1 parent
de362bacd0
commit
954bf39c8f
3 files changed
+58
-7
No files matched your search
+54
-6
@@ -44,8 +44,20 @@ AppName = "SaraView"
|
|||||||
BundledFontFamily = "Fixedsys Excelsior"
|
BundledFontFamily = "Fixedsys Excelsior"
|
||||||
ActiveFontFamily = BundledFontFamily # set by ApplyAppearance, read by BuildTheme
|
ActiveFontFamily = BundledFontFamily # set by ApplyAppearance, read by BuildTheme
|
||||||
|
|
||||||
|
IsWindows = sys.platform == "win32"
|
||||||
|
|
||||||
|
# Each system's own per-user folders, like SaraSuite's: ~/.config, ~/.cache
|
||||||
|
# and ~/.local/share on Linux; %APPDATA% and %LOCALAPPDATA% on Windows.
|
||||||
Home = Path.home()
|
Home = Path.home()
|
||||||
SharedConfigDir = Home / ".config" / "SaraSuite"
|
if IsWindows:
|
||||||
|
ConfigHome = Path(os.environ.get("APPDATA") or Home / "AppData" / "Roaming")
|
||||||
|
DataHome = Path(os.environ.get("LOCALAPPDATA") or Home / "AppData" / "Local")
|
||||||
|
CacheHome = DataHome
|
||||||
|
else:
|
||||||
|
ConfigHome = Path(os.environ.get("XDG_CONFIG_HOME") or Home / ".config")
|
||||||
|
DataHome = Path(os.environ.get("XDG_DATA_HOME") or Home / ".local" / "share")
|
||||||
|
CacheHome = Path(os.environ.get("XDG_CACHE_HOME") or Home / ".cache")
|
||||||
|
SharedConfigDir = ConfigHome / "SaraSuite"
|
||||||
ThemesDir = SharedConfigDir / "Themes"
|
ThemesDir = SharedConfigDir / "Themes"
|
||||||
SharedConfigPath = SharedConfigDir / "Config.toml"
|
SharedConfigPath = SharedConfigDir / "Config.toml"
|
||||||
ConfigDir = SharedConfigDir / AppName
|
ConfigDir = SharedConfigDir / AppName
|
||||||
@@ -54,8 +66,7 @@ ConfigPath = ConfigDir / "Config.toml"
|
|||||||
# never carries it.
|
# never carries it.
|
||||||
SessionPath = ConfigDir / "Session.toml"
|
SessionPath = ConfigDir / "Session.toml"
|
||||||
# Server files opened in another program are downloaded here first.
|
# Server files opened in another program are downloaded here first.
|
||||||
CacheDir = Home / ".cache" / AppName
|
CacheDir = CacheHome / AppName / "Cache" if IsWindows else CacheHome / AppName
|
||||||
DataHome = Home / ".local" / "share"
|
|
||||||
|
|
||||||
# Inside a PyInstaller build, bundled files are unpacked to sys._MEIPASS.
|
# Inside a PyInstaller build, bundled files are unpacked to sys._MEIPASS.
|
||||||
BundleDir = Path(getattr(sys, "_MEIPASS", Path(__file__).resolve().parent))
|
BundleDir = Path(getattr(sys, "_MEIPASS", Path(__file__).resolve().parent))
|
||||||
@@ -307,16 +318,53 @@ def ChildEnvironment() -> dict[str, str]:
|
|||||||
Environment.pop("LD_LIBRARY_PATH", None)
|
Environment.pop("LD_LIBRARY_PATH", None)
|
||||||
for Key in ("PYTHONHOME", "PYTHONPATH"):
|
for Key in ("PYTHONHOME", "PYTHONPATH"):
|
||||||
Environment.pop(Key, None)
|
Environment.pop(Key, None)
|
||||||
|
if IsWindows:
|
||||||
|
Environment["PYTHONUTF8"] = "1" # every Sara program reads and writes UTF-8
|
||||||
return Environment
|
return Environment
|
||||||
|
|
||||||
|
|
||||||
def OpenExternally(FilePath: Path) -> None:
|
def OpenExternally(FilePath: Path) -> None:
|
||||||
"""Hands a file to the system's default program. Raises OSError."""
|
"""Hands a file to the system's default program. Raises OSError."""
|
||||||
|
if IsWindows:
|
||||||
|
os.startfile(str(FilePath))
|
||||||
|
return
|
||||||
subprocess.Popen(["xdg-open", str(FilePath)], env=ChildEnvironment(), start_new_session=True)
|
subprocess.Popen(["xdg-open", str(FilePath)], env=ChildEnvironment(), start_new_session=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _WindowsFonts() -> set[str]:
|
||||||
|
"""Font families from the system and per-user Fonts registry keys
|
||||||
|
("Arial Bold (TrueType)" -> "Arial")."""
|
||||||
|
import re
|
||||||
|
import winreg
|
||||||
|
|
||||||
|
Families: set[str] = set()
|
||||||
|
Key = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
|
||||||
|
for Root in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER):
|
||||||
|
try:
|
||||||
|
with winreg.OpenKey(Root, Key) as Fonts:
|
||||||
|
Index = 0
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
Name = winreg.EnumValue(Fonts, Index)[0]
|
||||||
|
except OSError:
|
||||||
|
break
|
||||||
|
Index += 1
|
||||||
|
Name = re.sub(r"\s*\(.*\)$", "", Name)
|
||||||
|
Name = re.sub(r"\s+(Bold|Italic|Light|Semibold|SemiBold|Black|Regular|Medium|Thin)\b.*$", "", Name)
|
||||||
|
if Name and "&" not in Name:
|
||||||
|
Families.add(Name.strip())
|
||||||
|
except OSError:
|
||||||
|
continue
|
||||||
|
return Families
|
||||||
|
|
||||||
|
|
||||||
def InstalledFontFamilies() -> list[str]:
|
def InstalledFontFamilies() -> list[str]:
|
||||||
"""Font families fontconfig knows about, with the bundled font first."""
|
"""Font families fontconfig (or, on Windows, the registry) knows about,
|
||||||
|
with the bundled font first."""
|
||||||
|
if IsWindows:
|
||||||
|
Families = _WindowsFonts()
|
||||||
|
Families.discard(BundledFontFamily)
|
||||||
|
return [BundledFontFamily] + sorted(Families, key=str.lower)
|
||||||
try:
|
try:
|
||||||
Result = subprocess.run(
|
Result = subprocess.run(
|
||||||
["fc-list", ":", "family"], capture_output=True, text=True, timeout=5, env=ChildEnvironment(),
|
["fc-list", ":", "family"], capture_output=True, text=True, timeout=5, env=ChildEnvironment(),
|
||||||
@@ -489,9 +537,9 @@ def HumanSize(NumBytes: Optional[int]) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def DisplayPath(PathText: str) -> str:
|
def DisplayPath(PathText: str) -> str:
|
||||||
"""/home/sarah/Notes -> ~/Notes, for labels."""
|
"""/home/sarah/Notes -> ~/Notes, for labels (C:\\Users\\x\\Notes -> ~\\Notes)."""
|
||||||
HomeText = str(Home)
|
HomeText = str(Home)
|
||||||
if PathText == HomeText or PathText.startswith(HomeText + "/"):
|
if PathText == HomeText or PathText.startswith(HomeText + os.sep):
|
||||||
return "~" + PathText[len(HomeText):]
|
return "~" + PathText[len(HomeText):]
|
||||||
return PathText
|
return PathText
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -5,6 +5,7 @@ the right."""
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import flet as ft
|
import flet as ft
|
||||||
@@ -22,7 +23,7 @@ from Settings import ShowSettingsDialog
|
|||||||
def _SetCursorThemeFallback() -> None:
|
def _SetCursorThemeFallback() -> None:
|
||||||
"""GTK reads XCURSOR_THEME directly and doesn't always inherit it (shows as
|
"""GTK reads XCURSOR_THEME directly and doesn't always inherit it (shows as
|
||||||
'Unable to load ... from the cursor theme'). Same fix as SaraFem's."""
|
'Unable to load ... from the cursor theme'). Same fix as SaraFem's."""
|
||||||
if os.environ.get("XCURSOR_THEME"):
|
if os.environ.get("XCURSOR_THEME") or sys.platform == "win32": # GTK/GNOME only
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
Result = subprocess.run(["gsettings", "get", "org.gnome.desktop.interface", "cursor-theme"],
|
Result = subprocess.run(["gsettings", "get", "org.gnome.desktop.interface", "cursor-theme"],
|
||||||
@@ -48,6 +49,8 @@ def Main(Page: ft.Page) -> None:
|
|||||||
Page.bgcolor = Palette.Base
|
Page.bgcolor = Palette.Base
|
||||||
Page.window.width = 1180
|
Page.window.width = 1180
|
||||||
Page.window.height = 760
|
Page.window.height = 760
|
||||||
|
if sys.platform == "win32":
|
||||||
|
Page.window.icon = str(AssetsDir / "Icon.ico") # taskbar/title bar (Linux: the desktop entry)
|
||||||
Page.window.min_width = 720
|
Page.window.min_width = 720
|
||||||
Page.window.min_height = 480
|
Page.window.min_height = 480
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
Reference in new issue
Block a user