Implement search provider (#201)

* Begin work on search provider

* Initial search provider work, organize meson

* Initial work on icons

* Implement LaunchSearch

* Don't hold arbitrary reference to service

I don't know why Lollypop does this

* Send notification, pad images

* Update translations

* Fix init_search_term typing
This commit is contained in:
kramo
2023-10-10 22:47:32 +02:00
committed by GitHub
parent 61e7e0274c
commit 69928a8b4f
52 changed files with 687 additions and 293 deletions

View File

@@ -19,11 +19,11 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
import os
import sys
import signal
import locale
import gettext
import locale
import os
import signal
import sys
VERSION = "@VERSION@"
if os.name == "nt":
@@ -32,29 +32,27 @@ if os.name == "nt":
os.environ["LANGUAGE"] = locale.windows_locale[
windll.kernel32.GetUserDefaultUILanguage()
]
pkgdatadir = os.path.join(os.path.dirname(__file__), "..", "share", "cartridges")
localedir = os.path.join(os.path.dirname(__file__), "..", "share", "locale")
PKGDATADIR = os.path.join(os.path.dirname(__file__), "..", "share", "cartridges")
LOCALEDIR = os.path.join(os.path.dirname(__file__), "..", "share", "locale")
else:
pkgdatadir = "@pkgdatadir@"
localedir = "@localedir@"
PKGDATADIR = "@pkgdatadir@"
LOCALEDIR = "@localedir@"
sys.path.insert(1, pkgdatadir)
sys.path.insert(1, PKGDATADIR)
signal.signal(signal.SIGINT, signal.SIG_DFL)
if os.name != "nt":
locale.bindtextdomain("cartridges", localedir)
locale.bindtextdomain("cartridges", LOCALEDIR)
locale.textdomain("cartridges")
gettext.install("cartridges", localedir)
gettext.install("cartridges", LOCALEDIR)
if __name__ == "__main__":
import gi
from gi.repository import Gio
resource = Gio.Resource.load(os.path.join(pkgdatadir, "cartridges.gresource"))
resource._register()
resource = Gio.Resource.load(os.path.join(PKGDATADIR, "cartridges.gresource"))
resource._register() # pylint: disable=protected-access
from src import main
from cartridges import main
sys.exit(main.main(VERSION))

View File

@@ -26,14 +26,14 @@ from typing import Any, Optional
from gi.repository import Adw, Gio, GLib, Gtk
from PIL import Image, UnidentifiedImageError
from src import shared
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.game_cover import GameCover
from src.store.managers.cover_manager import CoverManager
from src.store.managers.sgdb_manager import SgdbManager
from src.utils.create_dialog import create_dialog
from src.utils.save_cover import convert_cover, save_cover
from cartridges import shared
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
from cartridges.game_cover import GameCover
from cartridges.store.managers.cover_manager import CoverManager
from cartridges.store.managers.sgdb_manager import SgdbManager
from cartridges.utils.create_dialog import create_dialog
from cartridges.utils.save_cover import convert_cover, save_cover
@Gtk.Template(resource_path=shared.PREFIX + "/gtk/details-window.ui")

View File

@@ -17,18 +17,16 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
import os
import shlex
import subprocess
from pathlib import Path
from time import time
from typing import Any, Optional
from gi.repository import Adw, GObject, Gtk
from src import shared
from src.game_cover import GameCover
from cartridges import shared
from cartridges.game_cover import GameCover
from cartridges.utils.run_executable import run_executable
# pylint: disable=too-many-instance-attributes
@@ -118,21 +116,7 @@ class Game(Gtk.Box):
self.save()
self.update()
args = (
"flatpak-spawn --host /bin/sh -c " + shlex.quote(self.executable) # Flatpak
if os.getenv("FLATPAK_ID") == shared.APP_ID
else self.executable # Others
)
logging.info("Starting %s: %s", self.name, str(args))
# pylint: disable=consider-using-with
subprocess.Popen(
args,
cwd=shared.home,
shell=True,
start_new_session=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0, # type: ignore
)
run_executable(self.executable)
if shared.schema.get_boolean("exit-after-launch"):
self.app.quit()

View File

@@ -23,7 +23,7 @@ from typing import Optional
from gi.repository import Gdk, GdkPixbuf, Gio, GLib, Gtk
from PIL import Image, ImageFilter, ImageStat
from src import shared
from cartridges import shared
class GameCover:

View File

@@ -23,10 +23,10 @@ from typing import NamedTuple
import yaml
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import SourceIterable, URLExecutableSource
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import SourceIterable, URLExecutableSource
class BottlesSourceIterable(SourceIterable):

View File

@@ -25,9 +25,9 @@ from typing import NamedTuple
from gi.repository import GLib, Gtk
from src import shared
from src.game import Game
from src.importer.source import Source, SourceIterable
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.source import Source, SourceIterable
class DesktopSourceIterable(SourceIterable):

View File

@@ -22,10 +22,10 @@ from typing import NamedTuple
from gi.repository import GLib, Gtk
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import ExecutableFormatSource, SourceIterable
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import ExecutableFormatSource, SourceIterable
class FlatpakSourceIterable(SourceIterable):

View File

@@ -27,10 +27,10 @@ from json import JSONDecodeError
from pathlib import Path
from typing import Iterable, NamedTuple, Optional, TypedDict
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import (
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import (
SourceIterable,
SourceIterationResult,
URLExecutableSource,

View File

@@ -24,14 +24,14 @@ from typing import Any, Optional
from gi.repository import Adw, Gio, GLib, Gtk
from src import shared
from src.errors.error_producer import ErrorProducer
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.importer.location import UnresolvableLocationError
from src.importer.source import Source
from src.store.managers.async_manager import AsyncManager
from src.store.pipeline import Pipeline
from cartridges import shared
from cartridges.errors.error_producer import ErrorProducer
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
from cartridges.importer.location import UnresolvableLocationError
from cartridges.importer.source import Source
from cartridges.store.managers.async_manager import AsyncManager
from cartridges.store.pipeline import Pipeline
# pylint: disable=too-many-instance-attributes

View File

@@ -22,11 +22,11 @@ from shutil import rmtree
from sqlite3 import connect
from typing import NamedTuple
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import SourceIterable, URLExecutableSource
from src.utils.sqlite import copy_db
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import SourceIterable, URLExecutableSource
from cartridges.utils.sqlite import copy_db
class ItchSourceIterable(SourceIterable):

View File

@@ -22,10 +22,10 @@ import logging
from json import JSONDecodeError
from typing import NamedTuple
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import (
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import (
ExecutableFormatSource,
SourceIterable,
SourceIterationResult,

View File

@@ -3,7 +3,7 @@ from os import PathLike
from pathlib import Path
from typing import Iterable, Mapping, NamedTuple, Optional
from src import shared
from cartridges import shared
PathSegment = str | PathLike | Path
PathSegments = Iterable[PathSegment]

View File

@@ -21,11 +21,11 @@ from shutil import rmtree
from sqlite3 import connect
from typing import NamedTuple
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import SourceIterable, URLExecutableSource
from src.utils.sqlite import copy_db
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import SourceIterable, URLExecutableSource
from cartridges.utils.sqlite import copy_db
class LutrisSourceIterable(SourceIterable):

View File

@@ -26,12 +26,16 @@ from pathlib import Path
from shlex import quote as shell_quote
from typing import NamedTuple
from src import shared
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.importer.location import Location, LocationSubPath, UnresolvableLocationError
from src.importer.source import Source, SourceIterable
from src.importer.steam_source import SteamSource
from cartridges import shared
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
from cartridges.importer.location import (
Location,
LocationSubPath,
UnresolvableLocationError,
)
from cartridges.importer.source import Source, SourceIterable
from cartridges.importer.steam_source import SteamSource
class RetroarchSourceIterable(SourceIterable):

View File

@@ -22,8 +22,8 @@ from abc import abstractmethod
from collections.abc import Iterable
from typing import Any, Collection, Generator, Optional
from src.game import Game
from src.importer.location import Location
from cartridges.game import Game
from cartridges.importer.location import Location
# Type of the data returned by iterating on a Source
SourceIterationResult = Optional[Game | tuple[Game, tuple[Any]]]

View File

@@ -23,11 +23,11 @@ import re
from pathlib import Path
from typing import Iterable, NamedTuple
from src import shared
from src.game import Game
from src.importer.location import Location, LocationSubPath
from src.importer.source import SourceIterable, URLExecutableSource
from src.utils.steam import SteamFileHelper, SteamInvalidManifestError
from cartridges import shared
from cartridges.game import Game
from cartridges.importer.location import Location, LocationSubPath
from cartridges.importer.source import SourceIterable, URLExecutableSource
from cartridges.utils.steam import SteamFileHelper, SteamInvalidManifestError
class SteamSourceIterable(SourceIterable):

View File

@@ -25,7 +25,7 @@ from os import PathLike
from pathlib import Path
from typing import Optional
from src import shared
from cartridges import shared
class SessionFileHandler(StreamHandler):

View File

@@ -24,7 +24,7 @@ import platform
import subprocess
import sys
from src import shared
from cartridges import shared
def setup_logging() -> None:
@@ -47,12 +47,12 @@ def setup_logging() -> None:
},
"console_formatter": {
"format": "%(name)s %(levelname)s - %(message)s",
"class": "src.logging.color_log_formatter.ColorLogFormatter",
"class": "cartridges.logging.color_log_formatter.ColorLogFormatter",
},
},
"handlers": {
"file_handler": {
"class": "src.logging.session_file_handler.SessionFileHandler",
"class": "cartridges.logging.session_file_handler.SessionFileHandler",
"formatter": "file_formatter",
"level": "DEBUG",
"filename": log_filename,

View File

@@ -20,6 +20,7 @@
import json
import lzma
import os
import shlex
import sys
from typing import Any, Optional
@@ -31,39 +32,42 @@ gi.require_version("Adw", "1")
# pylint: disable=wrong-import-position
from gi.repository import Adw, Gio, GLib, Gtk
from src import shared
from src.details_window import DetailsWindow
from src.game import Game
from src.importer.bottles_source import BottlesSource
from src.importer.desktop_source import DesktopSource
from src.importer.flatpak_source import FlatpakSource
from src.importer.heroic_source import HeroicSource
from src.importer.importer import Importer
from src.importer.itch_source import ItchSource
from src.importer.legendary_source import LegendarySource
from src.importer.lutris_source import LutrisSource
from src.importer.retroarch_source import RetroarchSource
from src.importer.steam_source import SteamSource
from src.logging.setup import log_system_info, setup_logging
from src.preferences import PreferencesWindow
from src.store.managers.cover_manager import CoverManager
from src.store.managers.display_manager import DisplayManager
from src.store.managers.file_manager import FileManager
from src.store.managers.sgdb_manager import SgdbManager
from src.store.managers.steam_api_manager import SteamAPIManager
from src.store.store import Store
from src.utils.migrate_files_v1_to_v2 import migrate_files_v1_to_v2
from src.window import CartridgesWindow
from cartridges import shared
from cartridges.details_window import DetailsWindow
from cartridges.game import Game
from cartridges.importer.bottles_source import BottlesSource
from cartridges.importer.desktop_source import DesktopSource
from cartridges.importer.flatpak_source import FlatpakSource
from cartridges.importer.heroic_source import HeroicSource
from cartridges.importer.importer import Importer
from cartridges.importer.itch_source import ItchSource
from cartridges.importer.legendary_source import LegendarySource
from cartridges.importer.lutris_source import LutrisSource
from cartridges.importer.retroarch_source import RetroarchSource
from cartridges.importer.steam_source import SteamSource
from cartridges.logging.setup import log_system_info, setup_logging
from cartridges.preferences import PreferencesWindow
from cartridges.store.managers.cover_manager import CoverManager
from cartridges.store.managers.display_manager import DisplayManager
from cartridges.store.managers.file_manager import FileManager
from cartridges.store.managers.sgdb_manager import SgdbManager
from cartridges.store.managers.steam_api_manager import SteamAPIManager
from cartridges.store.store import Store
from cartridges.utils.migrate_files_v1_to_v2 import migrate_files_v1_to_v2
from cartridges.utils.run_executable import run_executable
from cartridges.window import CartridgesWindow
class CartridgesApplication(Adw.Application):
state = shared.AppState.DEFAULT
win: CartridgesWindow
init_search_term: Optional[str] = None
def __init__(self) -> None:
shared.store = Store()
super().__init__(
application_id=shared.APP_ID, flags=Gio.ApplicationFlags.FLAGS_NONE
application_id=shared.APP_ID,
flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE,
)
def do_activate(self) -> None: # pylint: disable=arguments-differ
@@ -147,8 +151,47 @@ class CartridgesApplication(Adw.Application):
sort_action, shared.state_schema.get_value("sort-mode")
)
if self.init_search_term: # For command line activation
shared.win.search_bar.set_search_mode(True)
shared.win.search_entry.set_text(self.init_search_term)
shared.win.search_entry.set_position(-1)
shared.win.present()
def do_command_line(self, command_line) -> int:
for index, arg in enumerate(args := command_line.get_arguments()):
if arg == "--search":
try:
self.init_search_term = args[index + 1]
except IndexError:
pass
break
if arg == "--launch":
try:
game_id = args[index + 1]
data = json.load((shared.games_dir / (game_id + ".json")).open("r"))
executable = (
shlex.join(data["executable"])
if isinstance(data["executable"], list)
else data["executable"]
)
name = data["name"]
run_executable(executable)
except (IndexError, KeyError, OSError, json.decoder.JSONDecodeError):
return 1
notification = Gio.Notification.new(_("Cartridges"))
notification.set_body(_("{} launched").format(name))
self.send_notification(
"launch",
notification,
)
return 0
self.activate()
return 0
def load_games_from_disk(self) -> None:
if shared.games_dir.is_dir():
for game_file in shared.games_dir.iterdir():

View File

@@ -1,4 +1,4 @@
moduledir = join_paths(pkgdatadir, 'src')
moduledir = join_paths(python_dir, 'cartridges')
configure_file(
input: 'cartridges.in',

View File

@@ -25,21 +25,21 @@ from typing import Any, Callable, Optional
from gi.repository import Adw, Gio, GLib, Gtk
from src import shared
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.importer.bottles_source import BottlesSource
from src.importer.flatpak_source import FlatpakSource
from src.importer.heroic_source import HeroicSource
from src.importer.itch_source import ItchSource
from src.importer.legendary_source import LegendarySource
from src.importer.location import UnresolvableLocationError
from src.importer.lutris_source import LutrisSource
from src.importer.retroarch_source import RetroarchSource
from src.importer.source import Source
from src.importer.steam_source import SteamSource
from src.store.managers.sgdb_manager import SgdbManager
from src.utils.create_dialog import create_dialog
from cartridges import shared
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
from cartridges.importer.bottles_source import BottlesSource
from cartridges.importer.flatpak_source import FlatpakSource
from cartridges.importer.heroic_source import HeroicSource
from cartridges.importer.itch_source import ItchSource
from cartridges.importer.legendary_source import LegendarySource
from cartridges.importer.location import UnresolvableLocationError
from cartridges.importer.lutris_source import LutrisSource
from cartridges.importer.retroarch_source import RetroarchSource
from cartridges.importer.source import Source
from cartridges.importer.steam_source import SteamSource
from cartridges.store.managers.sgdb_manager import SgdbManager
from cartridges.utils.create_dialog import create_dialog
@Gtk.Template(resource_path=shared.PREFIX + "/gtk/preferences.ui")

View File

@@ -51,13 +51,20 @@ games_dir = data_dir / "cartridges" / "games"
covers_dir = data_dir / "cartridges" / "covers"
appdata_dir = Path(os.getenv("appdata") or "C:\\Users\\Default\\AppData\\Roaming")
local_appdata_dir = Path(os.getenv("csidl_local_appdata") or "C:\\Users\\Default\\AppData\\Local")
local_appdata_dir = Path(
os.getenv("csidl_local_appdata") or "C:\\Users\\Default\\AppData\\Local"
)
programfiles32_dir = Path(os.getenv("programfiles(x86)") or "C:\\Program Files (x86)")
scale_factor = max(
monitor.get_scale_factor() for monitor in Gdk.Display.get_default().get_monitors()
)
image_size = (200 * scale_factor, 300 * scale_factor)
try:
scale_factor = max(
monitor.get_scale_factor()
for monitor in Gdk.Display.get_default().get_monitors()
)
except AttributeError: # If shared.py is imported by the search provider
pass
else:
image_size = (200 * scale_factor, 300 * scale_factor)
# pylint: disable=invalid-name
win = None

View File

@@ -21,8 +21,8 @@ from typing import Any, Callable
from gi.repository import Gio
from src.game import Game
from src.store.managers.manager import Manager
from cartridges.game import Game
from cartridges.store.managers.manager import Manager
class AsyncManager(Manager):

View File

@@ -25,11 +25,11 @@ import requests
from gi.repository import GdkPixbuf, Gio
from requests.exceptions import HTTPError, SSLError
from src import shared
from src.game import Game
from src.store.managers.manager import Manager
from src.store.managers.steam_api_manager import SteamAPIManager
from src.utils.save_cover import convert_cover, save_cover
from cartridges import shared
from cartridges.game import Game
from cartridges.store.managers.manager import Manager
from cartridges.store.managers.steam_api_manager import SteamAPIManager
from cartridges.utils.save_cover import convert_cover, save_cover
class ImageSize(NamedTuple):

View File

@@ -17,12 +17,12 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
from src import shared
from src.game import Game
from src.game_cover import GameCover
from src.store.managers.manager import Manager
from src.store.managers.sgdb_manager import SgdbManager
from src.store.managers.steam_api_manager import SteamAPIManager
from cartridges import shared
from cartridges.game import Game
from cartridges.game_cover import GameCover
from cartridges.store.managers.manager import Manager
from cartridges.store.managers.sgdb_manager import SgdbManager
from cartridges.store.managers.steam_api_manager import SteamAPIManager
class DisplayManager(Manager):

View File

@@ -19,10 +19,10 @@
import json
from src import shared
from src.game import Game
from src.store.managers.async_manager import AsyncManager
from src.store.managers.steam_api_manager import SteamAPIManager
from cartridges import shared
from cartridges.game import Game
from cartridges.store.managers.async_manager import AsyncManager
from cartridges.store.managers.steam_api_manager import SteamAPIManager
class FileManager(AsyncManager):

View File

@@ -22,9 +22,9 @@ from abc import abstractmethod
from time import sleep
from typing import Any, Callable, Container
from src.errors.error_producer import ErrorProducer
from src.errors.friendly_error import FriendlyError
from src.game import Game
from cartridges.errors.error_producer import ErrorProducer
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
class Manager(ErrorProducer):

View File

@@ -21,12 +21,12 @@ from json import JSONDecodeError
from requests.exceptions import HTTPError, SSLError
from src.errors.friendly_error import FriendlyError
from src.game import Game
from src.store.managers.async_manager import AsyncManager
from src.store.managers.cover_manager import CoverManager
from src.store.managers.steam_api_manager import SteamAPIManager
from src.utils.steamgriddb import SgdbAuthError, SgdbHelper
from cartridges.errors.friendly_error import FriendlyError
from cartridges.game import Game
from cartridges.store.managers.async_manager import AsyncManager
from cartridges.store.managers.cover_manager import CoverManager
from cartridges.store.managers.steam_api_manager import SteamAPIManager
from cartridges.utils.steamgriddb import SgdbAuthError, SgdbHelper
class SgdbManager(AsyncManager):

View File

@@ -20,9 +20,9 @@
from requests.exceptions import HTTPError, SSLError
from urllib3.exceptions import ConnectionError as Urllib3ConnectionError
from src.game import Game
from src.store.managers.async_manager import AsyncManager
from src.utils.steam import (
from cartridges.game import Game
from cartridges.store.managers.async_manager import AsyncManager
from cartridges.utils.steam import (
SteamAPIHelper,
SteamGameNotFoundError,
SteamNotAGameError,

View File

@@ -22,8 +22,8 @@ from typing import Iterable
from gi.repository import GObject
from src.game import Game
from src.store.managers.manager import Manager
from cartridges.game import Game
from cartridges.store.managers.manager import Manager
class Pipeline(GObject.Object):

View File

@@ -20,10 +20,10 @@
import logging
from typing import Any, Generator, MutableMapping, Optional
from src import shared
from src.game import Game
from src.store.managers.manager import Manager
from src.store.pipeline import Pipeline
from cartridges import shared
from cartridges.game import Game
from cartridges.store.managers.manager import Manager
from cartridges.store.pipeline import Pipeline
class Store:

View File

@@ -21,7 +21,7 @@ import json
import logging
from pathlib import Path
from src import shared
from cartridges import shared
old_data_dir = shared.home / ".local" / "share"
old_cartridges_data_dir = old_data_dir / "cartridges"

View File

@@ -0,0 +1,24 @@
import logging
import os
import subprocess
from shlex import quote
from cartridges import shared
def run_executable(executable) -> None:
args = (
"flatpak-spawn --host /bin/sh -c " + quote(executable) # Flatpak
if os.getenv("FLATPAK_ID") == shared.APP_ID
else executable # Others
)
logging.info("Launching `%s`", str(args))
# pylint: disable=consider-using-with
subprocess.Popen(
args,
cwd=shared.home,
shell=True,
start_new_session=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0, # type: ignore
)

View File

@@ -25,7 +25,7 @@ from typing import Optional
from gi.repository import Gdk, GdkPixbuf, Gio, GLib
from PIL import Image, ImageSequence, UnidentifiedImageError
from src import shared
from cartridges import shared
def convert_cover(

View File

@@ -27,8 +27,8 @@ from typing import TypedDict
import requests
from requests.exceptions import HTTPError
from src import shared
from src.utils.rate_limiter import RateLimiter
from cartridges import shared
from cartridges.utils.rate_limiter import RateLimiter
class SteamError(Exception):

View File

@@ -26,9 +26,9 @@ import requests
from gi.repository import Gio
from requests.exceptions import HTTPError
from src import shared
from src.game import Game
from src.utils.save_cover import convert_cover, save_cover
from cartridges import shared
from cartridges.game import Game
from cartridges.utils.save_cover import convert_cover, save_cover
class SgdbError(Exception):

View File

@@ -21,10 +21,10 @@ from typing import Any, Optional
from gi.repository import Adw, Gio, GLib, Gtk
from src import shared
from src.game import Game
from src.game_cover import GameCover
from src.utils.relative_date import relative_date
from cartridges import shared
from cartridges.game import Game
from cartridges.game_cover import GameCover
from cartridges.utils.relative_date import relative_date
@Gtk.Template(resource_path=shared.PREFIX + "/gtk/window.ui")

View File

@@ -8,7 +8,12 @@ i18n = import('i18n')
gnome = import('gnome')
python = import('python')
py_installation = python.find_installation('python3')
python_dir = join_paths(get_option('prefix'), py_installation.get_install_dir())
python_dir = join_paths(get_option('prefix'), py_installation.get_install_dir())
pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
libexecdir = join_paths(get_option('prefix'), get_option('libexecdir'))
profile = get_option('profile')
if profile == 'development'
@@ -20,21 +25,24 @@ elif profile == 'release'
endif
conf = configuration_data()
conf.set('PYTHON', python.find_installation('python3').full_path())
conf.set('PYTHON_VERSION', python.find_installation('python3').language_version())
conf.set('PYTHON', py_installation.full_path())
conf.set('PYTHON_VERSION', py_installation.language_version())
conf.set('APP_ID', app_id)
conf.set('PREFIX', prefix)
conf.set('VERSION', meson.project_version())
conf.set('PROFILE', profile)
conf.set('localedir', join_paths(get_option('prefix'), get_option('localedir')))
conf.set('pkgdatadir', pkgdatadir)
conf.set('libexecdir', libexecdir)
subdir('data')
subdir('src')
subdir('cartridges')
subdir('po')
if host_machine.system() == 'windows'
subdir('windows')
else
subdir('search-provider')
endif
gnome.post_install(

View File

@@ -8,25 +8,26 @@ data/gtk/help-overlay.blp
data/gtk/preferences.blp
data/gtk/window.blp
src/main.py
src/window.py
src/details_window.py
src/game.py
src/preferences.py
cartridges/main.py
cartridges/window.py
cartridges/details_window.py
cartridges/game.py
cartridges/preferences.py
src/utils/create_dialog.py
src/importer/importer.py
src/importer/sources/source.py
src/importer/sources/location.py
src/importer/sources/location.py
src/store/managers/sgdb_manager.py
cartridges/utils/create_dialog.py
src/importer/sources/bottles_source.py
src/importer/sources/desktop_source.py
src/importer/sources/flatpak_source.py
src/importer/sources/heroic_source.py
src/importer/sources/itch_source.py
src/importer/sources/legendary_source.py
src/importer/sources/lutris_source.py
src/importer/sources/retroarch_source.py
src/importer/sources/steam_source.py
cartridges/importer/importer.py
cartridges/importer/source.py
cartridges/importer/location.py
cartridges/importer/location.py
cartridges/importer/bottles_source.py
cartridges/importer/desktop_source.py
cartridges/importer/flatpak_source.py
cartridges/importer/heroic_source.py
cartridges/importer/itch_source.py
cartridges/importer/legendary_source.py
cartridges/importer/lutris_source.py
cartridges/importer/retroarch_source.py
cartridges/importer/steam_source.py
cartridges/store/managers/sgdb_manager.py

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Cartridges\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-26 13:51+0200\n"
"POT-Creation-Date: 2023-10-10 22:22+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -20,7 +20,7 @@ msgstr ""
#: data/hu.kramo.Cartridges.desktop.in:3
#: data/hu.kramo.Cartridges.metainfo.xml.in:6
#: data/hu.kramo.Cartridges.metainfo.xml.in:30 data/gtk/window.blp:47
#: data/gtk/window.blp:80
#: data/gtk/window.blp:80 cartridges/main.py:185
msgid "Cartridges"
msgstr ""
@@ -47,7 +47,7 @@ msgid ""
msgstr ""
#: data/hu.kramo.Cartridges.metainfo.xml.in:34 data/gtk/window.blp:288
#: src/details_window.py:71
#: cartridges/details_window.py:71
msgid "Game Details"
msgstr ""
@@ -56,8 +56,8 @@ msgid "Edit Game Details"
msgstr ""
#: data/hu.kramo.Cartridges.metainfo.xml.in:42 data/gtk/help-overlay.blp:19
#: data/gtk/window.blp:515 src/details_window.py:271
#: src/importer/importer.py:319 src/importer/importer.py:370
#: data/gtk/window.blp:515 cartridges/details_window.py:271
#: cartridges/importer/importer.py:319 cartridges/importer/importer.py:370
msgid "Preferences"
msgstr ""
@@ -73,7 +73,7 @@ msgstr ""
msgid "Delete Cover"
msgstr ""
#: data/gtk/details-window.blp:100 data/gtk/game.blp:80
#: data/gtk/details-window.blp:100 data/gtk/game.blp:81
msgid "Title"
msgstr ""
@@ -93,20 +93,20 @@ msgstr ""
msgid "More Info"
msgstr ""
#: data/gtk/game.blp:102 data/gtk/game.blp:121 data/gtk/window.blp:415
#: data/gtk/game.blp:103 data/gtk/game.blp:122 data/gtk/window.blp:415
msgid "Edit"
msgstr ""
#: data/gtk/game.blp:107 src/window.py:350
#: data/gtk/game.blp:108 cartridges/window.py:350
msgid "Hide"
msgstr ""
#: data/gtk/game.blp:112 data/gtk/game.blp:131 data/gtk/preferences.blp:40
#: data/gtk/game.blp:113 data/gtk/game.blp:132 data/gtk/preferences.blp:40
#: data/gtk/window.blp:435
msgid "Remove"
msgstr ""
#: data/gtk/game.blp:126 src/window.py:352
#: data/gtk/game.blp:127 cartridges/window.py:352
msgid "Unhide"
msgstr ""
@@ -123,8 +123,8 @@ msgstr ""
msgid "Keyboard Shortcuts"
msgstr ""
#: data/gtk/help-overlay.blp:29 src/game.py:105 src/preferences.py:125
#: src/importer/importer.py:394
#: data/gtk/help-overlay.blp:29 cartridges/game.py:103
#: cartridges/preferences.py:125 cartridges/importer/importer.py:394
msgid "Undo"
msgstr ""
@@ -178,7 +178,7 @@ msgstr ""
msgid "Swaps the behavior of the cover image and the play button"
msgstr ""
#: data/gtk/preferences.blp:25 src/details_window.py:85
#: data/gtk/preferences.blp:25 cartridges/details_window.py:85
msgid "Images"
msgstr ""
@@ -206,7 +206,7 @@ msgstr ""
msgid "Sources"
msgstr ""
#: data/gtk/preferences.blp:83 src/importer/sources/steam_source.py:114
#: data/gtk/preferences.blp:83 cartridges/importer/steam_source.py:114
msgid "Steam"
msgstr ""
@@ -217,7 +217,7 @@ msgstr ""
msgid "Install Location"
msgstr ""
#: data/gtk/preferences.blp:100 src/importer/sources/lutris_source.py:92
#: data/gtk/preferences.blp:100 cartridges/importer/lutris_source.py:92
msgid "Lutris"
msgstr ""
@@ -233,7 +233,7 @@ msgstr ""
msgid "Import Flatpak Games"
msgstr ""
#: data/gtk/preferences.blp:137 src/importer/sources/heroic_source.py:355
#: data/gtk/preferences.blp:137 cartridges/importer/heroic_source.py:355
msgid "Heroic"
msgstr ""
@@ -253,23 +253,23 @@ msgstr ""
msgid "Import Sideloaded Games"
msgstr ""
#: data/gtk/preferences.blp:170 src/importer/sources/bottles_source.py:86
#: data/gtk/preferences.blp:170 cartridges/importer/bottles_source.py:86
msgid "Bottles"
msgstr ""
#: data/gtk/preferences.blp:187 src/importer/sources/itch_source.py:81
#: data/gtk/preferences.blp:187 cartridges/importer/itch_source.py:81
msgid "itch"
msgstr ""
#: data/gtk/preferences.blp:204 src/importer/sources/legendary_source.py:97
#: data/gtk/preferences.blp:204 cartridges/importer/legendary_source.py:97
msgid "Legendary"
msgstr ""
#: data/gtk/preferences.blp:221 src/importer/sources/retroarch_source.py:142
#: data/gtk/preferences.blp:221 cartridges/importer/retroarch_source.py:142
msgid "RetroArch"
msgstr ""
#: data/gtk/preferences.blp:238 src/importer/sources/flatpak_source.py:118
#: data/gtk/preferences.blp:238 cartridges/importer/flatpak_source.py:118
msgid "Flatpak"
msgstr ""
@@ -277,7 +277,7 @@ msgstr ""
msgid "Import Game Launchers"
msgstr ""
#: data/gtk/preferences.blp:259 src/importer/sources/desktop_source.py:217
#: data/gtk/preferences.blp:259 cartridges/importer/desktop_source.py:215
msgid "Desktop Entries"
msgstr ""
@@ -345,11 +345,11 @@ msgstr ""
msgid "Games you hide will appear here."
msgstr ""
#: data/gtk/window.blp:75 data/gtk/window.blp:106 src/main.py:166
#: data/gtk/window.blp:75 data/gtk/window.blp:106 cartridges/main.py:207
msgid "All Games"
msgstr ""
#: data/gtk/window.blp:126 src/main.py:168
#: data/gtk/window.blp:126 cartridges/main.py:209
msgid "Added"
msgstr ""
@@ -401,62 +401,67 @@ msgstr ""
msgid "About Cartridges"
msgstr ""
#. The variable is the title of the game
#: cartridges/main.py:186 cartridges/game.py:125
msgid "{} launched"
msgstr ""
#. Translators: Replace this with your name for it to show up in the about window
#: src/main.py:208
#: cartridges/main.py:249
msgid "translator_credits"
msgstr ""
#. The variable is the date when the game was added
#: src/window.py:373
#: cartridges/window.py:373
msgid "Added: {}"
msgstr ""
#: src/window.py:376
#: cartridges/window.py:376
msgid "Never"
msgstr ""
#. The variable is the date when the game was last played
#: src/window.py:380
#: cartridges/window.py:380
msgid "Last played: {}"
msgstr ""
#: src/details_window.py:76
#: cartridges/details_window.py:76
msgid "Apply"
msgstr ""
#: src/details_window.py:82
#: cartridges/details_window.py:82
msgid "Add New Game"
msgstr ""
#: src/details_window.py:83
#: cartridges/details_window.py:83
msgid "Add"
msgstr ""
#: src/details_window.py:93
#: cartridges/details_window.py:93
msgid "Executables"
msgstr ""
#. Translate this string as you would translate "file"
#: src/details_window.py:108
#: cartridges/details_window.py:108
msgid "file.txt"
msgstr ""
#. As in software
#: src/details_window.py:110
#: cartridges/details_window.py:110
msgid "program"
msgstr ""
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:115 src/details_window.py:117
#: cartridges/details_window.py:115 cartridges/details_window.py:117
msgid "C:\\path\\to\\{}"
msgstr ""
#. Translate this string as you would translate "path to {}"
#: src/details_window.py:121 src/details_window.py:123
#: cartridges/details_window.py:121 cartridges/details_window.py:123
msgid "/path/to/{}"
msgstr ""
#: src/details_window.py:128
#: cartridges/details_window.py:128
msgid ""
"To launch the executable \"{}\", use the command:\n"
"\n"
@@ -469,141 +474,136 @@ msgid ""
"If the path contains spaces, make sure to wrap it in double quotes!"
msgstr ""
#: src/details_window.py:171 src/details_window.py:177
#: cartridges/details_window.py:171 cartridges/details_window.py:177
msgid "Couldn't Add Game"
msgstr ""
#: src/details_window.py:171 src/details_window.py:213
#: cartridges/details_window.py:171 cartridges/details_window.py:213
msgid "Game title cannot be empty."
msgstr ""
#: src/details_window.py:177 src/details_window.py:221
#: cartridges/details_window.py:177 cartridges/details_window.py:221
msgid "Executable cannot be empty."
msgstr ""
#: src/details_window.py:212 src/details_window.py:220
#: cartridges/details_window.py:212 cartridges/details_window.py:220
msgid "Couldn't Apply Preferences"
msgstr ""
#. The variable is the title of the game
#: src/game.py:141
msgid "{} launched"
msgstr ""
#. The variable is the title of the game
#: src/game.py:155
#: cartridges/game.py:139
msgid "{} hidden"
msgstr ""
#: src/game.py:155
#: cartridges/game.py:139
msgid "{} unhidden"
msgstr ""
#. The variable is the title of the game
#. The variable is the number of games removed
#: src/game.py:169 src/importer/importer.py:391
#: cartridges/game.py:153 cartridges/importer/importer.py:391
msgid "{} removed"
msgstr ""
#: src/preferences.py:124
#: cartridges/preferences.py:124
msgid "All games removed"
msgstr ""
#: src/preferences.py:172
#: cartridges/preferences.py:172
msgid ""
"An API key is required to use SteamGridDB. You can generate one {}here{}."
msgstr ""
#: src/preferences.py:184
#: cartridges/preferences.py:184
msgid "Downloading covers…"
msgstr ""
#: src/preferences.py:203
#: cartridges/preferences.py:203
msgid "Covers updated"
msgstr ""
#: src/preferences.py:335
#: cartridges/preferences.py:335
msgid "Installation Not Found"
msgstr ""
#: src/preferences.py:336
#: cartridges/preferences.py:336
msgid "Select a valid directory."
msgstr ""
#: src/preferences.py:372 src/importer/importer.py:317
#: cartridges/preferences.py:372 cartridges/importer/importer.py:317
msgid "Warning"
msgstr ""
#: src/preferences.py:406
#: cartridges/preferences.py:406
msgid "Invalid Directory"
msgstr ""
#: src/preferences.py:412
#: cartridges/preferences.py:412
msgid "Set Location"
msgstr ""
#: src/utils/create_dialog.py:33 src/importer/importer.py:318
#: cartridges/utils/create_dialog.py:33 cartridges/importer/importer.py:318
msgid "Dismiss"
msgstr ""
#: src/importer/importer.py:145
#: cartridges/importer/importer.py:145
msgid "Importing Games…"
msgstr ""
#: src/importer/importer.py:338
#: cartridges/importer/importer.py:338
msgid "The following errors occured during import:"
msgstr ""
#: src/importer/importer.py:367
#: cartridges/importer/importer.py:367
msgid "No new games found"
msgstr ""
#: src/importer/importer.py:379
#: cartridges/importer/importer.py:379
msgid "1 game imported"
msgstr ""
#. The variable is the number of games
#: src/importer/importer.py:383
#: cartridges/importer/importer.py:383
msgid "{} games imported"
msgstr ""
#. A single game removed
#: src/importer/importer.py:387
#: cartridges/importer/importer.py:387
msgid "1 removed"
msgstr ""
#. The variable is the name of the source
#: src/importer/sources/location.py:33
#: cartridges/importer/location.py:33
msgid "Select the {} cache directory."
msgstr ""
#. The variable is the name of the source
#: src/importer/sources/location.py:35
#: cartridges/importer/location.py:35
msgid "Select the {} configuration directory."
msgstr ""
#. The variable is the name of the source
#: src/importer/sources/location.py:37
#: cartridges/importer/location.py:37
msgid "Select the {} data directory."
msgstr ""
#: src/store/managers/sgdb_manager.py:46
msgid "Couldn't Authenticate SteamGridDB"
msgstr ""
#: src/store/managers/sgdb_manager.py:47
msgid "Verify your API key in preferences"
msgstr ""
#: src/importer/sources/retroarch_source.py:129
#: cartridges/importer/retroarch_source.py:129
msgid "No RetroArch Core Selected"
msgstr ""
#. The variable is a newline separated list of playlists
#: src/importer/sources/retroarch_source.py:131
#: cartridges/importer/retroarch_source.py:131
msgid "The following playlists have no default core:"
msgstr ""
#: src/importer/sources/retroarch_source.py:133
#: cartridges/importer/retroarch_source.py:133
msgid "Games with no core selected were not imported"
msgstr ""
#: cartridges/store/managers/sgdb_manager.py:46
msgid "Couldn't Authenticate SteamGridDB"
msgstr ""
#: cartridges/store/managers/sgdb_manager.py:47
msgid "Verify your API key in preferences"
msgstr ""

View File

@@ -0,0 +1,292 @@
#!@PYTHON@
# cartridges-search-provider.in
#
# Copyright 2023 kramo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
# Heavily inspired by:
# https://gitlab.gnome.org/World/lollypop/-/blob/master/search-provider/lollypop-sp.in
import json
import gi
gi.require_version("Gdk", "4.0")
gi.require_version("GdkPixbuf", "2.0")
# pylint: disable=wrong-import-position
from gi.repository import GdkPixbuf, Gio, GLib
from cartridges import shared
class Server:
def __init__(self, con, path):
method_outargs = {}
method_inargs = {}
for interface in Gio.DBusNodeInfo.new_for_xml(self.__doc__).interfaces:
for method in interface.methods:
method_outargs[method.name] = (
"(" + "".join([arg.signature for arg in method.out_args]) + ")"
)
method_inargs[method.name] = tuple(
arg.signature for arg in method.in_args
)
con.register_object(
object_path=path,
interface_info=interface,
method_call_closure=self.on_method_call,
)
self.method_inargs = method_inargs
self.method_outargs = method_outargs
def on_method_call(
self,
_connection,
_sender,
_object_path,
_interface_name,
method_name,
parameters,
invocation,
):
args = list(parameters.unpack())
for i, sig in enumerate(self.method_inargs[method_name]):
if sig == "h":
msg = invocation.get_message()
fd_list = msg.get_unix_fd_list()
args[i] = fd_list.get(args[i])
try:
result = getattr(self, method_name)(*args)
# out_args is atleast (signature1).
# We therefore always wrap the result as a tuple.
# Refer to https://bugzilla.gnome.org/show_bug.cgi?id=765603
result = (result,)
out_args = self.method_outargs[method_name]
if out_args != "()":
variant = GLib.Variant(out_args, result)
invocation.return_value(variant)
else:
invocation.return_value(None)
except Exception: # pylint: disable=broad-exception-caught
pass
class SearchCartridgesService(Server, Gio.Application):
"""
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<interface name="org.gnome.Shell.SearchProvider2">
<method name="GetInitialResultSet">
<arg type="as" name="terms" direction="in" />
<arg type="as" name="results" direction="out" />
</method>
<method name="GetSubsearchResultSet">
<arg type="as" name="previous_results" direction="in" />
<arg type="as" name="terms" direction="in" />
<arg type="as" name="results" direction="out" />
</method>
<method name="GetResultMetas">
<arg type="as" name="identifiers" direction="in" />
<arg type="aa{sv}" name="metas" direction="out" />
</method>
<method name="ActivateResult">
<arg type="s" name="identifier" direction="in" />
<arg type="as" name="terms" direction="in" />
<arg type="u" name="timestamp" direction="in" />
</method>
<method name="LaunchSearch">
<arg type="as" name="terms" direction="in" />
<arg type="u" name="timestamp" direction="in" />
</method>
</interface>
</node>
"""
# pylint: disable=invalid-name
__SEARCH_BUS = "org.gnome.Shell.SearchProvider2"
__PATH_BUS = "@PREFIX@/SearchProvider"
def __init__(self):
Gio.Application.__init__(
self,
application_id="@APP_ID@.SearchProvider",
flags=Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout=10000,
)
self.games = {}
self.load_games_from_disk()
self.__bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
Gio.bus_own_name_on_connection(
self.__bus, self.__SEARCH_BUS, Gio.BusNameOwnerFlags.NONE, None, None
)
Server.__init__(self, self.__bus, self.__PATH_BUS)
def load_games_from_disk(self):
if not shared.games_dir.is_dir():
return
for game_file in shared.games_dir.iterdir():
try:
data = json.load(game_file.open())
except (OSError, json.decoder.JSONDecodeError):
continue
try:
if any({data["hidden"], data["blacklisted"], data["removed"]}):
continue
self.games[data["game_id"]] = (data["name"], data["developer"])
except KeyError:
continue
def ActivateResult(self, game_id, _array, _utime):
argv = ["cartridges", "--launch", game_id]
(pid, _stdin, _stdout, _stderr) = GLib.spawn_async(
argv,
flags=GLib.SpawnFlags.SEARCH_PATH,
standard_input=False,
standard_output=False,
standard_error=False,
)
GLib.spawn_close_pid(pid)
def GetInitialResultSet(self, terms):
return self.__search(terms)
def GetResultMetas(self, game_ids):
results = []
try:
for game_id in game_ids:
empty_pixbuf = GdkPixbuf.Pixbuf.new(
GdkPixbuf.Colorspace.RGB, True, 8, 32, 32
)
pixbuf = None
if (path := shared.covers_dir / (game_id + ".tiff")).is_file():
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
str(path), -1, 32, True
)
except GLib.GError as e:
print(e)
continue
elif (path := shared.covers_dir / (game_id + ".gif")).is_file():
try:
pixbuf = GdkPixbuf.PixbufAnimation.new_from_file(
str(path)
).get_static_image()
except GLib.GError as e:
print(e)
continue
d = {
"id": GLib.Variant("s", game_id),
"name": GLib.Variant("s", self.games[game_id][0]),
}
if pixbuf:
pixbuf.composite(
empty_pixbuf,
6,
0,
21,
32,
6,
0,
21 / pixbuf.get_width(),
32 / pixbuf.get_height(),
GdkPixbuf.InterpType.NEAREST,
255,
)
d["icon-data"] = GLib.Variant(
"(iiibiiay)",
[
empty_pixbuf.get_width(),
empty_pixbuf.get_height(),
empty_pixbuf.get_rowstride(),
empty_pixbuf.get_has_alpha(),
empty_pixbuf.get_bits_per_sample(),
empty_pixbuf.get_n_channels(),
empty_pixbuf.read_pixel_bytes().get_data(),
],
)
if self.games[game_id][1]:
d["description"] = GLib.Variant(
"s", GLib.markup_escape_text(self.games[game_id][1])
)
results.append(d)
except Exception as e: # pylint: disable=broad-exception-caught
print("SearchCartridgesService::GetResultMetas():", e)
return []
return results
def GetSubsearchResultSet(self, _previous_results, new_terms):
return self.__search(new_terms)
def LaunchSearch(self, terms, _utime):
search = " ".join(terms)
argv = ["cartridges", "--search", search]
(pid, _stdin, _stdout, _stderr) = GLib.spawn_async(
argv,
flags=GLib.SpawnFlags.SEARCH_PATH,
standard_input=False,
standard_output=False,
standard_error=False,
)
GLib.spawn_close_pid(pid)
def __search(self, terms):
game_ids = []
search = " ".join(terms).lower()
try:
for game_id, data in self.games.items():
print(game_id, data)
if search in data[0].lower():
game_ids.append(game_id)
continue
if data[1] and search in data[1].lower():
game_ids.append(game_id)
continue
except Exception as e: # pylint: disable=broad-exception-caught
print("SearchCartridgesService::__search():", e)
return game_ids
def main():
service = SearchCartridgesService()
service.run()
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,5 @@
[Shell Search Provider]
DesktopId=@APP_ID@.desktop
BusName=@APP_ID@.SearchProvider
ObjectPath=@PREFIX@/SearchProvider
Version=2

View File

@@ -0,0 +1,3 @@
[D-BUS Service]
Name=@APP_ID@.SearchProvider
Exec=@libexecdir@/cartridges-search-provider

View File

@@ -0,0 +1,25 @@
# Heavily inspired by https://gitlab.gnome.org/World/lollypop/-/blob/master/search-provider/meson.build
service_dir = join_paths(get_option('datadir'), 'dbus-1', 'services')
serarch_provider_dir = join_paths(get_option('datadir'), 'gnome-shell', 'search-providers')
configure_file(
input: 'cartridges-search-provider.in',
output: 'cartridges-search-provider',
configuration: conf,
install_dir: libexecdir
)
configure_file(
input: 'hu.kramo.Cartridges.SearchProvider.service.in',
output: app_id + '.SearchProvider.service',
configuration: conf,
install_dir: service_dir
)
configure_file(
input: 'hu.kramo.Cartridges.SearchProvider.ini',
output: app_id + '.SearchProvider.ini',
configuration: conf,
install_dir: serarch_provider_dir
)