1from pathlib import Path
2from textwrap import dedent
3from typing import List, Optional
4
5from xdg import BaseDirectory # type: ignore
6from xdg.DesktopEntry import DesktopEntry # type: ignore
7
8from qpm.utils import error, user_config_dir
9
10
11class Profile:
12 name: str
13 profile_dir: Path
14 set_app_id: bool
15 root: Path
16
17 def __init__(
18 self, name: str, profile_dir: Optional[Path], set_app_id: bool = False
19 ) -> None:
20 self.name = name
21 self.profile_dir = profile_dir or Path(
22 BaseDirectory.save_data_path("qutebrowser-profiles")
23 )
24 self.set_app_id = set_app_id
25 self.root = self.profile_dir / name
26
27 def check(self) -> Optional["Profile"]:
28 if "/" in self.name:
29 error("profile name cannot contain slashes")
30 return None
31 if not self.profile_dir.resolve().is_dir():
32 error(f"{self.profile_dir} is not a directory")
33 return None
34 if self.profile_dir.resolve() not in self.root.resolve().parents:
35 error("will not create profile outside of profile dir. consider using -P")
36 return None
37 if self.root.exists():
38 error(f"{self.root} already exists")
39 return None
40 for parent in self.root.parents:
41 if parent == self.profile_dir:
42 break
43 if parent.exists():
44 error(f"{parent} already exists")
45 return None
46 return self
47
48 def exists(self) -> bool:
49 return self.root.exists() and self.root.is_dir()
50
51 def cmdline(self) -> List[str]:
52 return ["qutebrowser", "-B", str(self.root), "--qt-arg", "name", self.name] + (
53 ["--desktop-file-name", self.name] if self.set_app_id else []
54 )
55
56
57def create_profile(profile: Profile) -> bool:
58 if not profile.check():
59 return False
60
61 config_dir = profile.root / "config"
62 config_dir.mkdir(parents=True)
63 print(profile.root)
64 return True
65
66
67def create_config(profile: Profile, home_page: Optional[str] = None) -> None:
68 user_config = profile.root / "config" / "config.py"
69 with user_config.open(mode="x") as dest_config:
70 title_prefix = "{perc}{current_title}{title_sep}"
71 config = (
72 f"c.window.title_format = '{title_prefix} qutebrowser ({profile.name})'"
73 )
74 if home_page:
75 config = config + f"\nc.url.default_page = '{home_page}'"
76 config = config + f"\nc.url.start_pages = ['{home_page}']"
77 main_config_dir = user_config_dir()
78 print(dedent(config), file=dest_config)
79 print(f"config.source('{main_config_dir / 'config.py'}')", file=dest_config)
80 for conf in main_config_dir.glob("conf.d/*.py"):
81 print(f"config.source('{conf}')", file=dest_config)
82
83
84application_dir = Path(BaseDirectory.xdg_data_home) / "applications" / "qpm"
85
86
87def create_desktop_file(profile: Profile):
88 desktop = DesktopEntry(str(application_dir / f"{profile.name}.desktop"))
89 desktop.set("Name", f"{profile.name} (qutebrowser profile)")
90 # TODO allow passing in an icon value
91 desktop.set("Icon", "qutebrowser")
92 desktop.set("Exec", " ".join(profile.cmdline()) + " %u")
93 desktop.set("Categories", ["Network"])
94 desktop.set("Terminal", False)
95 desktop.set("StartupNotify", True)
96 desktop.write()
97
98
99def ensure_profile_exists(profile: Profile, create: bool = True) -> bool:
100 if profile.root.exists() and not profile.root.is_dir():
101 error(f"{profile.root} is not a directory")
102 return False
103 if not profile.root.exists() and create:
104 return new_profile(profile)
105 if not profile.root.exists():
106 error(f"{profile.root} does not exist")
107 return False
108 return True
109
110
111def new_profile(
112 profile: Profile, home_page: Optional[str] = None, desktop_file: bool = True
113) -> bool:
114 if create_profile(profile):
115 create_config(profile, home_page)
116 if desktop_file:
117 create_desktop_file(profile)
118 return True
119 return False