input-remapper/inputremapper/configs/global_config.py
2023-02-27 17:07:42 +01:00

134 lines
4.6 KiB
Python

# -*- coding: utf-8 -*-
# input-remapper - GUI for device specific keyboard mappings
# Copyright (C) 2023 sezanzeb <proxima@sezanzeb.de>
#
# This file is part of input-remapper.
#
# input-remapper 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.
#
# input-remapper 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 input-remapper. If not, see <https://www.gnu.org/licenses/>.
"""Store which presets should be enabled for which device on login."""
import copy
import json
import os
from typing import Optional
from inputremapper.configs.base_config import ConfigBase, INITIAL_CONFIG
from inputremapper.configs.paths import CONFIG_PATH, USER, touch
from inputremapper.logger import logger
MOUSE = "mouse"
WHEEL = "wheel"
BUTTONS = "buttons"
NONE = "none"
class GlobalConfig(ConfigBase):
"""Global default configuration.
It can also contain some extra stuff not relevant for presets, like the
autoload stuff. If presets have a config key set, it will ignore
the default global configuration for that one. If none of the configs
have the key set, a hardcoded default value will be used.
"""
def __init__(self):
self.path = os.path.join(CONFIG_PATH, "config.json")
super().__init__()
def get_dir(self) -> str:
"""The folder containing this config."""
return os.path.split(self.path)[0]
def set_autoload_preset(self, group_key: str, preset: Optional[str]):
"""Set a preset to be automatically applied on start.
Parameters
----------
group_key
the unique identifier of the group. This is used instead of the
name to enable autoloading two different presets when two similar
devices are connected.
preset
if None, don't autoload something for this device.
"""
if preset is not None:
self.set(["autoload", group_key], preset)
else:
logger.info('Not injecting for "%s" automatically anmore', group_key)
self.remove(["autoload", group_key])
self._save_config()
def iterate_autoload_presets(self):
"""Get tuples of (device, preset)."""
return self._config.get("autoload", {}).items()
def is_autoloaded(self, group_key: Optional[str], preset: Optional[str]):
"""Should this preset be loaded automatically?"""
if group_key is None or preset is None:
raise ValueError("Expected group_key and preset to not be None")
return self.get(["autoload", group_key], log_unknown=False) == preset
def load_config(self, path: Optional[str] = None):
"""Load the config from the file system.
Parameters
----------
path
If set, will change the path to load from and save to.
"""
if path is not None:
if not os.path.exists(path):
logger.error('Config at "%s" not found', path)
return
self.path = path
self.clear_config()
if not os.path.exists(self.path):
# treated like an empty config
logger.debug('Config "%s" doesn\'t exist yet', self.path)
self.clear_config()
self._config = copy.deepcopy(INITIAL_CONFIG)
self._save_config()
return
with open(self.path, "r") as file:
try:
self._config.update(json.load(file))
logger.info('Loaded config from "%s"', self.path)
except json.decoder.JSONDecodeError as error:
logger.error(
'Failed to parse config "%s": %s. Using defaults',
self.path,
str(error),
)
# uses the default configuration when the config object
# is empty automatically
def _save_config(self):
"""Save the config to the file system."""
if USER == "root":
logger.debug("Skipping config file creation for the root user")
return
touch(self.path)
with open(self.path, "w") as file:
json.dump(self._config, file, indent=4)
logger.info("Saved config to %s", self.path)
file.write("\n")
global_config = GlobalConfig()