qutebrowser profile manager

generate desktop file manually

+1
pyproject.toml
··· 84 84 [tool.ruff.lint.per-file-ignores] 85 85 "tests/test_main.py" = [ "S101", "ANN201"] 86 86 "tests/test_profiles.py" = [ "S101", "ANN201"] 87 + "tests/test_desktop.py" = [ "S101", "ANN201"]
+59
src/qbpm/desktop.py
··· 1 + import textwrap 2 + from pathlib import Path 3 + from typing import Optional 4 + 5 + from xdg_base_dirs import xdg_data_dirs, xdg_data_home 6 + 7 + from . import Profile 8 + 9 + MIME_TYPES = [ 10 + "text/html", 11 + "text/xml", 12 + "application/xhtml+xml", 13 + "application/xml", 14 + "application/rdf+xml", 15 + "image/gif", 16 + "image/jpeg", 17 + "image/png", 18 + "x-scheme-handler/http", 19 + "x-scheme-handler/https", 20 + "x-scheme-handler/qute", 21 + ] 22 + 23 + 24 + # TODO disable when not on linux? 25 + # TODO expose application_dir through config 26 + def create_desktop_file( 27 + profile: Profile, application_dir: Optional[Path] = None 28 + ) -> None: 29 + text = textwrap.dedent(f"""\ 30 + [Desktop Entry] 31 + Name={profile.name} (qutebrowser profile) 32 + StartupWMClass=qutebrowser 33 + GenericName={profile.name} 34 + Icon=qutebrowser 35 + Type=Application 36 + Categories=Network;WebBrowser; 37 + Exec={" ".join([*profile.cmdline(), "--untrusted-args", "%u"])} 38 + Terminal=false 39 + StartupNotify=true 40 + MimeType={";".join(MIME_TYPES)}; 41 + Keywords=Browser 42 + Actions=new-window;preferences; 43 + 44 + [Desktop Action new-window] 45 + Name=New Window 46 + Exec={" ".join(profile.cmdline())} 47 + 48 + [Desktop Action preferences] 49 + Name=Preferences 50 + Exec={" ".join([*profile.cmdline(), '"qute://settings"'])} 51 + """) 52 + application_dir = application_dir or default_qbpm_application_dir() 53 + (application_dir / f"{profile.name}.desktop").write_text(text) 54 + 55 + 56 + def default_qbpm_application_dir() -> Path: 57 + path = xdg_data_home() / "applications" / "qbpm" 58 + path.mkdir(parents=True, exist_ok=True) 59 + return path
+2 -6
src/qbpm/operations.py
··· 5 5 from sys import platform 6 6 from typing import Optional 7 7 8 - from xdg import BaseDirectory 9 - 10 8 from . import Profile, profiles 9 + from .desktop import create_desktop_file 11 10 from .utils import env_menus, error, installed_menus, or_phrase, qutebrowser_exe 12 11 13 12 ··· 59 58 return True 60 59 61 60 62 - application_dir = Path(BaseDirectory.xdg_data_home) / "applications" / "qbpm" 63 - 64 - 65 61 def desktop(profile: Profile) -> bool: 66 62 exists = profile.exists() 67 63 if exists: 68 - profiles.create_desktop_file(profile) 64 + create_desktop_file(profile) 69 65 else: 70 66 error(f"profile {profile.name} not found at {profile.root}") 71 67 return exists
+1 -22
src/qbpm/profiles.py
··· 2 2 from pathlib import Path 3 3 from typing import Optional 4 4 5 - from xdg import BaseDirectory 6 - from xdg.DesktopEntry import DesktopEntry 7 - 8 5 from . import Profile 6 + from .desktop import create_desktop_file 9 7 from .utils import error, or_phrase, user_config_dirs 10 8 11 9 MIME_TYPES = [ ··· 54 52 out(f"config.source(r'{qb_config_dir / 'config.py'}')") 55 53 for conf in qb_config_dir.glob("conf.d/*.py"): 56 54 out(f"config.source(r'{conf}')") 57 - 58 - 59 - application_dir = Path(BaseDirectory.xdg_data_home) / "applications" / "qbpm" 60 - 61 - 62 - def create_desktop_file(profile: Profile) -> None: 63 - desktop = DesktopEntry(str(application_dir / f"{profile.name}.desktop")) 64 - desktop.set("Name", f"{profile.name} (qutebrowser profile)") 65 - desktop.set("GenericName", f"{profile.name}") 66 - # TODO allow passing in an icon value 67 - desktop.set("Icon", "qutebrowser") 68 - desktop.set("Exec", " ".join(profile.cmdline()) + " --untrusted-args %u") 69 - desktop.set("Type", "Application") 70 - desktop.set("Categories", "Network;WebBrowser") 71 - desktop.set("Terminal", "false") 72 - desktop.set("StartupNotify", "true") 73 - desktop.set("StartupWMClass", "qutebrowser") 74 - desktop.set("MimeType", ";".join(MIME_TYPES)) 75 - desktop.write() 76 55 77 56 78 57 def exists(profile: Profile) -> bool:
+178
tests/qutebrowser.desktop
··· 1 + [Desktop Entry] 2 + Name=qutebrowser 3 + StartupWMClass=qutebrowser 4 + GenericName=Web Browser 5 + GenericName[ar]=ﻢﺘﺼﻔﺣ ﺎﻠﺸﺒﻛﺓ 6 + GenericName[bg]=Уеб браузър 7 + GenericName[ca]=Navegador web 8 + GenericName[cs]=WWW prohlížeč 9 + GenericName[da]=Browser 10 + GenericName[de]=Web-Browser 11 + GenericName[el]=Περιηγητής ιστού 12 + GenericName[en_GB]=Web Browser 13 + GenericName[es]=Navegador web 14 + GenericName[et]=Veebibrauser 15 + GenericName[fi]=WWW-selain 16 + GenericName[fr]=Navigateur Web 17 + GenericName[gu]=વેબ બ્રાઉઝર 18 + GenericName[he]=דפדפן אינטרנט 19 + GenericName[hi]=वेब ब्राउज़र 20 + GenericName[hu]=Webböngésző 21 + GenericName[it]=Browser Web 22 + GenericName[ja]=ウェブブラウザ 23 + GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ 24 + GenericName[ko]=웹 브라우저 25 + GenericName[lt]=Žiniatinklio naršyklė 26 + GenericName[lv]=Tīmekļa pārlūks 27 + GenericName[ml]=വെബ് ബ്രൌസര്<200d> 28 + GenericName[mr]=वेब ब्राऊजर 29 + GenericName[nb]=Nettleser 30 + GenericName[nl]=Webbrowser 31 + GenericName[pl]=Przeglądarka WWW 32 + GenericName[pt]=Navegador Web 33 + GenericName[pt_BR]=Navegador da Internet 34 + GenericName[ro]=Navigator de Internet 35 + GenericName[ru]=Веб-браузер 36 + GenericName[sl]=Spletni brskalnik 37 + GenericName[sv]=Webbläsare 38 + GenericName[ta]=இணைய உலாவி 39 + GenericName[th]=เว็บเบราว์เซอร์ 40 + GenericName[tr]=Web Tarayıcı 41 + GenericName[uk]=Навігатор Тенет瀏覽器 42 + Comment=A keyboard-driven, vim-like browser based on Python and Qt 43 + Comment[de]=Ein Tastatur-gesteuerter, vim-ähnlicher Browser basierend auf Python und Qt 44 + Comment[it]= Un browser web vim-like utilizzabile da tastiera basato su Python e Qt 45 + Icon=qutebrowser 46 + Type=Application 47 + Categories=Network;WebBrowser; 48 + Exec=qutebrowser --untrusted-args %u 49 + Terminal=false 50 + StartupNotify=true 51 + MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/qute; 52 + Keywords=Browser 53 + Actions=new-window;preferences; 54 + 55 + [Desktop Action new-window] 56 + Name=New Window 57 + Name[am]=አዲስ መስኮት 58 + Name[ar]=ﻥﺎﻓﺫﺓ ﺝﺪﻳﺩﺓ 59 + Name[bg]=Нов прозорец 60 + Name[bn]=নতুন উইন্ডো 61 + Name[ca]=Finestra nova 62 + Name[cs]=Nové okno 63 + Name[da]=Nyt vindue 64 + Name[de]=Neues Fenster 65 + Name[el]=Νέο Παράθυρο 66 + Name[en_GB]=New Window 67 + Name[es]=Nueva ventana 68 + Name[et]=Uus aken 69 + Name[fa]=پﻦﺟﺮﻫ ﺝﺩیﺩ 70 + Name[fi]=Uusi ikkuna 71 + Name[fil]=New Window 72 + Name[fr]=Nouvelle fenêtre 73 + Name[gu]=નવી વિંડો 74 + Name[hi]=नई विंडो 75 + Name[hr]=Novi prozor 76 + Name[hu]=Új ablak 77 + Name[id]=Jendela Baru 78 + Name[it]=Nuova finestra 79 + Name[iw]=חלון חדש 80 + Name[ja]=新規ウインドウ 81 + Name[kn]=ಹೊಸ ವಿಂಡೊ 82 + Name[ko]=새 창 83 + Name[lt]=Naujas langas 84 + Name[lv]=Jauns logs 85 + Name[ml]=പുതിയ വിന്<200d>ഡോ 86 + Name[mr]=नवीन विंडो 87 + Name[nl]=Nieuw venster 88 + Name[no]=Nytt vindu 89 + Name[pl]=Nowe okno 90 + Name[pt]=Nova janela 91 + Name[pt_BR]=Nova janela 92 + Name[ro]=Fereastră nouă 93 + Name[ru]=Новое окно 94 + Name[sk]=Nové okno 95 + Name[sl]=Novo okno 96 + Name[sr]=Нови прозор 97 + Name[sv]=Nytt fönster 98 + Name[sw]=Dirisha Jipya 99 + Name[ta]=புதிய சாளரம் 100 + Name[te]=క్రొత్త విండో 101 + Name[th]=หน้าต่างใหม่ 102 + Name[tr]=Yeni Pencere 103 + Name[uk]=Нове вікно 104 + Name[vi]=Cửa sổ Mới 105 + Exec=qutebrowser 106 + 107 + [Desktop Action preferences] 108 + Name=Preferences 109 + Name[an]=Preferencias 110 + Name[ar]=ﺎﻠﺘﻔﻀﻳﻼﺗ 111 + Name[as]=পছন্দসমূহ 112 + Name[be]=Настройкі 113 + Name[bg]=Настройки 114 + Name[bn_IN]=পছন্দ 115 + Name[bs]=Postavke 116 + Name[ca]=Preferències 117 + Name[ca@valencia]=Preferències 118 + Name[cs]=Předvolby 119 + Name[da]=Indstillinger 120 + Name[de]=Einstellungen 121 + Name[el]=Προτιμήσεις 122 + Name[en_GB]=Preferences 123 + Name[eo]=Agordoj 124 + Name[es]=Preferencias 125 + Name[et]=Eelistused 126 + Name[eu]=Hobespenak 127 + Name[fa]=ﺕﺮﺟیﺡﺎﺗ 128 + Name[fi]=Asetukset 129 + Name[fr]=Préférences 130 + Name[fur]=Preferencis 131 + Name[ga]=Sainroghanna 132 + Name[gd]=Roghainnean 133 + Name[gl]=Preferencias 134 + Name[gu]=પસંદગીઓ 135 + Name[he]=העדפות 136 + Name[hi]=वरीयताएँ 137 + Name[hr]=Osobitosti 138 + Name[hu]=Beállítások 139 + Name[id]=Preferensi 140 + Name[is]=Kjörstillingar 141 + Name[it]=Preferenze 142 + Name[ja]=設定 143 + Name[kk]=Баптаулар 144 + Name[km]=ចំណូលចិត្ត 145 + Name[kn]=ಆದ್ಯತೆಗಳು 146 + Name[ko]=기본 설정 147 + Name[lt]=Nuostatos 148 + Name[lv]=Iestatījumi 149 + Name[ml]=മുന്<200d>ഗണനകള്<200d> 150 + Name[mr]=पसंती 151 + Name[nb]=Brukervalg 152 + Name[ne]=प्राथमिकताहरू 153 + Name[nl]=Voorkeuren 154 + Name[oc]=Preferéncias 155 + Name[or]=ପସନ୍ଦ 156 + Name[pa]=ਮੇਰੀ ਪਸੰਦ 157 + Name[pl]=Preferencje 158 + Name[pt]=Preferências 159 + Name[pt_BR]=Preferências 160 + Name[ro]=Preferințe 161 + Name[ru]=Параметры 162 + Name[sk]=Nastavenia 163 + Name[sl]=Možnosti 164 + Name[sr]=Поставке 165 + Name[sr@latin]=Postavke 166 + Name[sv]=Inställningar 167 + Name[ta]=விருப்பங்கள் 168 + Name[te]=అభీష్టాలు 169 + Name[tg]=Хусусиятҳо 170 + Name[th]=ปรับแต่ง 171 + Name[tr]=Tercihler 172 + Name[ug]=ﻡﺎﻳﻰﻠﻟﻰﻗ 173 + Name[uk]=Параметри 174 + Name[vi]=Tùy thích 175 + Name[zh_CN]=首选项 176 + Name[zh_HK]=偏好設定 177 + Name[zh_TW]=偏好設定 178 + Exec=qutebrowser "qute://settings"
+21
tests/test.desktop
··· 1 + [Desktop Entry] 2 + Name=test (qutebrowser profile) 3 + StartupWMClass=qutebrowser 4 + GenericName=test 5 + Icon=qutebrowser 6 + Type=Application 7 + Categories=Network;WebBrowser; 8 + Exec={qbpm} --untrusted-args %u 9 + Terminal=false 10 + StartupNotify=true 11 + MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/qute; 12 + Keywords=Browser 13 + Actions=new-window;preferences; 14 + 15 + [Desktop Action new-window] 16 + Name=New Window 17 + Exec={qbpm} 18 + 19 + [Desktop Action preferences] 20 + Name=Preferences 21 + Exec={qbpm} "qute://settings"
+16
tests/test_desktop.py
··· 1 + from pathlib import Path 2 + 3 + from qbpm import Profile 4 + from qbpm.desktop import create_desktop_file 5 + 6 + TEST_DIR = Path(__file__).resolve().parent 7 + 8 + 9 + def test_create_desktop_file(tmp_path: Path): 10 + application_path = tmp_path / "applications" 11 + application_path.mkdir() 12 + profile = Profile("test", tmp_path) 13 + create_desktop_file(profile, application_path) 14 + assert (application_path / "test.desktop").read_text() == ( 15 + TEST_DIR / "test.desktop" 16 + ).read_text().replace("{qbpm}", " ".join(profile.cmdline()))