From 145bb74c63027309f5cfeab003567e6bd500b581 Mon Sep 17 00:00:00 2001 From: jaimergp Date: Wed, 7 Aug 2024 10:10:16 +0200 Subject: [PATCH] Fix `xdg-mime` default registration (#227) * xdg-mime accepts the .desktop filename, not the full path * add news * Less invasive default registration, cleanup on removal * clarify role of %f in the docs * Update menuinst/platforms/linux.py --- docs/source/defining-shortcuts.md | 7 +++-- menuinst/platforms/linux.py | 49 +++++++++++++++++++++++++++---- news/227-xdg-mime-default | 19 ++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 news/227-xdg-mime-default diff --git a/docs/source/defining-shortcuts.md b/docs/source/defining-shortcuts.md index f502f057..4d3f3799 100644 --- a/docs/source/defining-shortcuts.md +++ b/docs/source/defining-shortcuts.md @@ -105,9 +105,10 @@ Each operating system has a slightly different way of associating a file type to Unix systems have the notion of MIME types, while Windows relies more on file name extensions. - On Linux, use the `MimeType` option. Remember to add the `%f` (single file) or `%F` (several - files) placeholders to your command so the paths are passed adequately. If you are defining a new - MIME type, you must fill the `glob_patterns` field by mapping the new MIME type to the file - extensions you want to associate with it. + files) placeholders to your command so the paths are passed adequately. Otherwise, your shortcut + might be deemed invalid and won't show up in "Open With" menus or similar UI elements of your + desktop. If you are defining a new MIME type, you must fill the `glob_patterns` field by mapping + the new MIME type to the file extensions you want to associate with it. - On Windows, use `file_extensions`. Remember to add the `%1` or `%*` placeholders to your command so the path of the opened file(s) is passed adequately. - On macOS, use `CFBundleDocumentTypes`. Requires no placeholder. The opened document will be diff --git a/menuinst/platforms/linux.py b/menuinst/platforms/linux.py index 76e99667..73d72fc8 100644 --- a/menuinst/platforms/linux.py +++ b/menuinst/platforms/linux.py @@ -1,10 +1,10 @@ -""" -""" +""" """ import os import shlex import shutil import time +from configparser import ConfigParser from logging import getLogger from pathlib import Path from subprocess import CalledProcessError @@ -286,11 +286,48 @@ def _register_mime_types(self, mime_types: Iterable[str], register: bool = True) if glob_pattern: self._glob_pattern_for_mime_type(mime_type, glob_pattern, install=register) + mimeapps = self.menu.config_directory / "mimeapps.list" if register: - xdg_mime = shutil.which("xdg-mime") - if not xdg_mime: - log.debug("xdg-mime not found, not registering mime types as default.") - logged_run([xdg_mime, "default", self.location, *mime_types]) + config = ConfigParser(default_section=None) + if mimeapps.is_file(): + config.read(mimeapps) + log.debug("Registering %s to %s...", mime_types, mimeapps) + if "Default Applications" not in config.sections(): + config.add_section("Default Applications") + if "Added Associations" not in config.sections(): + config.add_section("Added Associations") + defaults = config["Default Applications"] + added = config["Added Associations"] + for mime_type in mime_types: + if mime_type not in defaults: + # Do not override existing defaults + defaults[mime_type] = self.location.name + if mime_type in added and self.location.name not in added[mime_type]: + added[mime_type] = f"{added[mime_type]};{self.location.name}" + else: + added[mime_type] = self.location.name + with open(mimeapps, "w") as f: + config.write(f, space_around_delimiters=False) + elif mimeapps.is_file(): + # Remove entries + config = ConfigParser(default_section=None) + config.read(mimeapps) + log.debug("Deregistering %s from %s...", mime_types, mimeapps) + for section_name in "Default Applications", "Added Associations": + if section_name not in config.sections(): + continue + section = config[section_name] + for mimetype, desktop_files in section.items(): + if self.location.name == desktop_files: + section.pop(mimetype) + elif self.location.name in desktop_files.split(";"): + section[mimetype] = ";".join( + [x for x in desktop_files.split(";") if x != self.location.name] + ) + if not section.keys(): + config.remove_section(section_name) + with open(mimeapps, "w") as f: + config.write(f, space_around_delimiters=False) update_mime_database = shutil.which("update-mime-database") if update_mime_database: diff --git a/news/227-xdg-mime-default b/news/227-xdg-mime-default new file mode 100644 index 00000000..d9e6bd73 --- /dev/null +++ b/news/227-xdg-mime-default @@ -0,0 +1,19 @@ +### Enhancements + +* + +### Bug fixes + +* Fix default MIME type registration on Linux. (#226 via #227) + +### Deprecations + +* + +### Docs + +* + +### Other + +*