"""Masaüstü / uygulama menüsü kısayolu oluşturur (yalnızca standart kütüphane). Windows : Masaüstü + Başlat menüsü .lnk → baslat.bat macOS : ~/Desktop/Tablo2SQL.app (Terminal'de baslat.command'ı açar) + ~/Applications kopyası Linux : ~/.local/share/applications/tablo2sql.desktop + masaüstü kopyası Doğrudan: python scripts/kisayol.py """ from __future__ import annotations import os import platform import plistlib import shutil import stat import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parent.parent NAME = "Tablo2SQL" def _p(msg): print(" " + msg) def _exec_bit(p: Path): try: p.chmod(p.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) except OSError: pass # ------------------------------------------------------------------ Windows def windows() -> list[Path]: ps = r""" $ErrorActionPreference = 'Stop' $sh = New-Object -ComObject WScript.Shell $out = @() foreach ($dir in @([Environment]::GetFolderPath('Desktop'), [Environment]::GetFolderPath('Programs'))) { if (-not $dir) { continue } $lnk = Join-Path $dir ($env:T2S_NAME + '.lnk') $s = $sh.CreateShortcut($lnk) $s.TargetPath = Join-Path $env:T2S_ROOT 'baslat.bat' $s.WorkingDirectory = $env:T2S_ROOT $s.IconLocation = (Join-Path $env:T2S_ROOT 'assets\ikon.ico') + ',0' $s.Description = 'Tablo2SQL-TR: Turkce belge tablolarini sorgula' $s.Save() $out += $lnk } $out -join "`n" """ env = dict(os.environ, T2S_ROOT=str(ROOT), T2S_NAME=NAME) r = subprocess.run(["powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", ps], env=env, capture_output=True, text=True) if r.returncode != 0: raise RuntimeError(r.stderr.strip() or r.stdout.strip()) return [Path(x) for x in r.stdout.strip().splitlines() if x.strip()] # ------------------------------------------------------------------ macOS def _mac_app(target_dir: Path) -> Path: app = target_dir / f"{NAME}.app" if app.exists(): shutil.rmtree(app) macos = app / "Contents" / "MacOS" res = app / "Contents" / "Resources" macos.mkdir(parents=True) res.mkdir(parents=True) cmd_file = ROOT / "baslat.command" q = str(cmd_file).replace("'", "'\\''") launcher = macos / NAME launcher.write_text( "#!/bin/bash\n" f"CMD='{q}'\n" 'if [ ! -f "$CMD" ]; then\n' ' osascript -e \'display alert "Tablo2SQL" message "Proje klasörü taşınmış veya silinmiş. ' 'Klasördeki baslat.command dosyasını çalıştırıp kısayolu yeniden oluşturun."\'\n' " exit 1\nfi\n" 'chmod +x "$CMD" 2>/dev/null\n' 'open -a Terminal "$CMD"\n', encoding="utf-8") _exec_bit(launcher) shutil.copy(ROOT / "assets" / "ikon.icns", res / "ikon.icns") with open(app / "Contents" / "Info.plist", "wb") as f: plistlib.dump({ "CFBundleName": NAME, "CFBundleDisplayName": NAME, "CFBundleExecutable": NAME, "CFBundleIdentifier": "tr.tablo2sql.baslatici", "CFBundlePackageType": "APPL", "CFBundleIconFile": "ikon", "CFBundleShortVersionString": "1.0", "CFBundleVersion": "1", "LSMinimumSystemVersion": "10.13", "NSHighResolutionCapable": True, }, f) subprocess.run(["touch", str(app)], check=False) return app def macos() -> list[Path]: for f in ("baslat.command", "baslat.sh"): _exec_bit(ROOT / f) # İndirilen zip'ten gelen karantina işaretini kaldır (yoksa "geliştirici doğrulanamadı" uyarısı çıkar) subprocess.run(["xattr", "-dr", "com.apple.quarantine", str(ROOT)], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) out = [_mac_app(Path.home() / "Desktop")] apps = Path.home() / "Applications" try: apps.mkdir(exist_ok=True) out.append(_mac_app(apps)) except OSError: pass return out # ------------------------------------------------------------------ Linux def _desktop_dir() -> Path | None: try: d = subprocess.run(["xdg-user-dir", "DESKTOP"], capture_output=True, text=True).stdout.strip() if d and Path(d).is_dir() and Path(d) != Path.home(): return Path(d) except FileNotFoundError: pass for n in ("Desktop", "Masaüstü"): if (Path.home() / n).is_dir(): return Path.home() / n return None def _desktop_escape(s: str) -> str: return s.replace("\\", "\\\\").replace('"', '\\"').replace("`", "\\`").replace("$", "\\$") def linux() -> list[Path]: _exec_bit(ROOT / "baslat.sh") content = ( "[Desktop Entry]\n" "Type=Application\n" "Version=1.0\n" f"Name={NAME}\n" "Comment=Türkçe belge tablolarını çıkar ve doğal dille sorgula\n" f'Exec=bash "{_desktop_escape(str(ROOT / "baslat.sh"))}"\n' f"Path={ROOT}\n" f"Icon={ROOT / 'assets' / 'ikon.png'}\n" "Terminal=true\n" "Categories=Office;Development;\n" "StartupNotify=true\n") apps = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local" / "share")) / "applications" apps.mkdir(parents=True, exist_ok=True) out = [] menu = apps / "tablo2sql.desktop" menu.write_text(content, encoding="utf-8") _exec_bit(menu) out.append(menu) if shutil.which("update-desktop-database"): subprocess.run(["update-desktop-database", str(apps)], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) desk = _desktop_dir() if desk: d = desk / "tablo2sql.desktop" d.write_text(content, encoding="utf-8") _exec_bit(d) if shutil.which("gio"): # GNOME: "Başlatmaya izin ver" adımını atla subprocess.run(["gio", "set", str(d), "metadata::trusted", "true"], check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) out.append(d) return out def create() -> list[Path]: system = platform.system() try: made = {"Windows": windows, "Darwin": macos}.get(system, linux)() except Exception as e: _p(f"[UYARI] Kısayol oluşturulamadı: {e}") _p(" Bunun yerine proje klasöründeki başlatıcıyı doğrudan çalıştırabilirsiniz: " + {"Windows": "baslat.bat", "Darwin": "baslat.command"}.get(system, "baslat.sh")) return [] for p in made: _p(f"[TAMAM] Kısayol: {p}") if system == "Linux": _p(" Masaüstü simgesi ilk açılışta 'Güvenilir/Başlatmaya izin ver' onayı isteyebilir (sağ tık).") if system == "Darwin": _p(" İlk açılışta macOS onay isterse: Sistem Ayarları › Gizlilik ve Güvenlik › 'Yine de Aç'.") _p(" Proje klasörünü taşırsanız kısayolu yeniden oluşturun (kisayol_olustur).") return made if __name__ == "__main__": create()