|
17 | 17 | import os |
18 | 18 | import shlex |
19 | 19 | import shutil |
20 | | -from datetime import datetime |
21 | 20 | from gettext import gettext as _ |
22 | | -from glob import glob |
23 | 21 | from typing import Optional |
24 | 22 |
|
25 | 23 | import icoextract # type: ignore [import-untyped] |
26 | 24 |
|
| 25 | +from bottles.backend.params import APP_ID |
| 26 | + |
27 | 27 | from bottles.backend.globals import Paths |
28 | 28 | from bottles.backend.logger import Logger |
29 | 29 | from bottles.backend.models.config import BottleConfig |
|
32 | 32 | from bottles.backend.utils.generic import get_mime |
33 | 33 | from bottles.backend.utils.imagemagick import ImageMagickUtils |
34 | 34 |
|
| 35 | +from gi.repository import GLib, Gio, Xdp |
| 36 | + |
| 37 | +portal = Xdp.Portal() |
| 38 | + |
35 | 39 | logging = Logger() |
36 | 40 |
|
37 | 41 |
|
@@ -223,101 +227,53 @@ def create_desktop_entry( |
223 | 227 | program: dict, |
224 | 228 | skip_icon: bool = False, |
225 | 229 | custom_icon: str = "", |
226 | | - use_xdp: bool = False, |
227 | | - ) -> bool: |
228 | | - if not use_xdp: |
229 | | - try: |
230 | | - os.makedirs(Paths.applications, exist_ok=True) |
231 | | - except OSError: |
232 | | - return False |
233 | | - |
234 | | - cmd_legacy = "bottles" |
235 | | - cmd_cli = "bottles-cli" |
| 230 | + ): |
236 | 231 | icon = "com.usebottles.bottles-program" |
237 | 232 |
|
238 | | - if "FLATPAK_ID" in os.environ: |
239 | | - cmd_legacy = "flatpak run com.usebottles.bottles" |
240 | | - cmd_cli = "flatpak run --command=bottles-cli com.usebottles.bottles" |
241 | | - |
242 | 233 | if not skip_icon and not custom_icon: |
243 | 234 | icon = ManagerUtils.extract_icon( |
244 | 235 | config, program.get("name"), program.get("path") |
245 | 236 | ) |
246 | 237 | elif custom_icon: |
247 | 238 | icon = custom_icon |
248 | 239 |
|
249 | | - if not use_xdp: |
250 | | - file_name_template = "%s/%s--%s--%s.desktop" |
251 | | - existing_files = glob( |
252 | | - file_name_template |
253 | | - % (Paths.applications, config.Name, program.get("name"), "*") |
| 240 | + def prepare_install_cb (self, result): |
| 241 | + ret = portal.dynamic_launcher_prepare_install_finish(result) |
| 242 | + id = f"{config.get('Name')}.{program.get('name')}" |
| 243 | + sum_type = GLib.ChecksumType.SHA1 |
| 244 | + exec = "bottles-cli run -p {} -b '{}' -- %u".format( |
| 245 | + shlex.quote(program.get('name')), config.get('Name') |
254 | 246 | ) |
255 | | - desktop_file = file_name_template % ( |
256 | | - Paths.applications, |
257 | | - config.Name, |
258 | | - program.get("name"), |
259 | | - datetime.now().timestamp(), |
| 247 | + portal.dynamic_launcher_install( |
| 248 | + ret["token"], |
| 249 | + "{}.App_{}.desktop".format( |
| 250 | + APP_ID, GLib.compute_checksum_for_string(sum_type, id, -1) |
| 251 | + ), |
| 252 | + """[Desktop Entry] |
| 253 | + Exec={} |
| 254 | + Type=Application |
| 255 | + Terminal=false |
| 256 | + Categories=Application; |
| 257 | + Comment=Launch {} using Bottles. |
| 258 | + StartupWMClass={}""".format( |
| 259 | + exec, program.get("name"), program.get("name") |
| 260 | + ) |
260 | 261 | ) |
| 262 | + SignalManager.send(Signals.DesktopEntryCreated) |
261 | 263 |
|
262 | | - if existing_files: |
263 | | - for file in existing_files: |
264 | | - os.remove(file) |
265 | | - |
266 | | - # [Bug-]issue #4247 (single- to double-quotes in Desktop Entry spec -> "The Exec key"): |
267 | | - with open(desktop_file, "w") as f: |
268 | | - f.write("[Desktop Entry]\n") |
269 | | - f.write(f"Name={program.get('name')}\n") |
270 | | - f.write( |
271 | | - f"Exec={cmd_cli} run -p \"{program.get('name')}\" -b \"{config.get('Name')}\" -- %u\n" |
272 | | - ) |
273 | | - f.write("Type=Application\n") |
274 | | - f.write("Terminal=false\n") |
275 | | - f.write("Categories=Application;\n") |
276 | | - f.write(f"Icon={icon}\n") |
277 | | - f.write(f"Comment=Launch {program.get('name')} using Bottles.\n") |
278 | | - f.write(f"StartupWMClass={program.get('name')}\n") |
279 | | - # Actions |
280 | | - f.write("Actions=Configure;\n") |
281 | | - f.write("[Desktop Action Configure]\n") |
282 | | - f.write("Name=Configure in Bottles\n") |
283 | | - f.write(f"Exec={cmd_legacy} -b \"{config.get('Name')}\"\n") |
284 | | - |
285 | | - return True |
286 | | - ''' |
287 | | - WIP: the following code is not working yet, it raises an error: |
288 | | - GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod |
289 | | - import uuid |
290 | | - from gi.repository import Gio, Xdp |
291 | | -
|
292 | | - portal = Xdp.Portal() |
293 | 264 | if icon == "com.usebottles.bottles-program": |
294 | | - _icon = Gio.BytesIcon.new(icon.encode("utf-8")) |
| 265 | + icon += ".svg" |
| 266 | + _icon = Gio.File.new_for_uri( |
| 267 | + f"resource:/com/usebottles/bottles/icons/scalable/apps/{icon}" |
| 268 | + ) |
295 | 269 | else: |
296 | | - _icon = Gio.FileIcon.new(Gio.File.new_for_path(icon)) |
297 | | - icon_v = _icon.serialize() |
298 | | - token = portal.dynamic_launcher_request_install_token(program.get("name"), icon_v) |
299 | | - portal.dynamic_launcher_install( |
300 | | - token, |
301 | | - f"com.usebottles.bottles.{config.get('Name')}.{program.get('name')}.{str(uuid.uuid4())}.desktop", |
302 | | - """ |
303 | | - [Desktop Entry] |
304 | | - Exec={} |
305 | | - Type=Application |
306 | | - Terminal=false |
307 | | - Categories=Application; |
308 | | - Comment=Launch {} using Bottles. |
309 | | - Actions=Configure; |
310 | | - [Desktop Action Configure] |
311 | | - Name=Configure in Bottles |
312 | | - Exec={} |
313 | | - """.format( |
314 | | - f"{cmd_cli} run -p {shlex.quote(program.get('name'))} -b '{config.get('Path')}'", |
315 | | - program.get("name"), |
316 | | - f"{cmd_legacy} -b '{config.get('Name')}'" |
317 | | - ).encode("utf-8") |
318 | | - ) |
319 | | - ''' |
320 | | - return False |
| 270 | + _icon = Gio.File.new_for_path(icon) |
| 271 | + icon_v = Gio.BytesIcon.new(_icon.load_bytes()[0]).serialize() |
| 272 | + portal.dynamic_launcher_prepare_install(None, |
| 273 | + program.get("name"), icon_v, |
| 274 | + Xdp.LauncherType.APPLICATION, |
| 275 | + None, True, False, None, |
| 276 | + prepare_install_cb) |
321 | 277 |
|
322 | 278 | @staticmethod |
323 | 279 | def browse_wineprefix(wineprefix: dict): |
|
0 commit comments