def __getattr__(self, name): if hasattr(self.parser, name): return getattr(self.parser, name) elif hasattr(self, name): return getattr(self, name) Logger.warning("Couldn't find attribute {}".format(name)) return None
def select(self): """Show a select option for the backup of each application.""" backup_folders = self.get_backup_folders() total = len(backup_folders) if total != 0: backup_folders.sort() self._display_choices(backup_folders) print(_("(Q)uit to cancel")) has_chosen = False stopped = False while not has_chosen and not stopped: try: selected = input("Select a restore date : ") if selected in ["q", "quit", "exit"]: stopped = True selected = int(selected) if 1 <= selected <= total: has_chosen = True self._exists = True self._selected_backup = backup_folders[selected - 1] except ValueError: pass except KeyboardInterrupt: exit() if stopped: Logger.debug("The user stopped the " "reversion for {}".format(self.app.name)) else: Logger.debug("No backup folder found for " "the application {0}".format(self.app.name))
def factory(colors, conversion_tool=None): """Create a SVG to PNG object.""" def load(conversion_tool): """Load Objects dynamically.""" module = ConversionTools.choices()[conversion_tool].lower() svg = import_module("HardcodeTray.modules.svg." + module) return getattr(svg, conversion_tool) svg = None if conversion_tool: try: svg = load(conversion_tool)(colors) except SVGNotInstalled: exit(_("The selected conversion tool is not installed.")) else: for tool in ConversionTools.choices(): try: svg = load(tool)(colors) Logger.debug("SVG Factory: Import {}".format(tool)) break except SVGNotInstalled: Logger.debug("SVG Factory: Failed {}".format(tool)) if svg: return svg exit(_("Failed to load any SVG module."))
def _validate_with_callback(self, key, callback): module = import_module("HardcodeTray.path") if hasattr(module, callback): method = getattr(module, callback) self.path = get_exact_folder(key, self.path, method) Logger.debug("Path with condition: " "{} {}".format(callback, self.path))
def set_value(self, key, value): """Set a value in the resources list using a key.""" try: self._resources[int(key)] = value except KeyError: Logger.warning("The key {0} dosen't seem to" " be found on {1}".format(key, self._filename))
def blacklist(self): """Return a list of blacklist apps.""" blacklist = self._blacklist if blacklist: Logger.debug("Config/Blacklist: " "{}".format(",".join(blacklist))) return blacklist
def nwjs(self): """Return nwjs sdk path.""" nwjs = self._nwjs if nwjs and path.exists(nwjs): Logger.debug("Config/NWJS SDK: {}".format(nwjs)) return nwjs return None
def pack(self, icon_path): """Recreate the zip file from the tmp directory.""" from HardcodeTray.app import App nwjs_sdk = App.get("nwjs") if nwjs_sdk: binary_file = path.join(gettempdir(), self.binary) Logger.debug("NWJS Application: Creating new archive {}".format( self.binary)) make_archive(binary_file, "zip", self.tmp_path) move(binary_file + ".zip", binary_file + ".nw") local_binary_file = path.join(nwjs_sdk, self.binary) move(binary_file + ".nw", local_binary_file + ".nw") Logger.debug("NWJS Application: Creating executable file.") execute(["cat which nw " + self.binary + ".nw > " + self.binary], True, True, nwjs_sdk) remove(local_binary_file + ".nw") move(local_binary_file, path.join(str(icon_path), self.binary)) execute(["chmod", "+x", path.join(str(icon_path), self.binary)]) rmtree(self.tmp_path)
def pack(self, icon_path): """Recreate the zip file from the tmp directory.""" from HardcodeTray.app import App nwjs_sdk = App.get("nwjs") if nwjs_sdk: binary_file = path.join(gettempdir(), self.binary) Logger.debug( "NWJS Application: Creating new archive {}".format(self.binary)) make_archive(binary_file, "zip", self.tmp_path) move(binary_file + ".zip", binary_file + ".nw") local_binary_file = path.join(nwjs_sdk, self.binary) move(binary_file + ".nw", local_binary_file + ".nw") Logger.debug("NWJS Application: Creating executable file.") execute(["cat which nw " + self.binary + ".nw > " + self.binary], True, True, nwjs_sdk) remove(local_binary_file + ".nw") move(local_binary_file, path.join(str(icon_path), self.binary)) execute(["chmod", "+x", path.join(str(icon_path), self.binary)]) rmtree(self.tmp_path)
def _read(self): """ Read the json file and parse it. """ from HardcodeTray.app import App do_later = ["app_path", "icons_path", "icons"] try: with open(self._db_file, 'r') as db_obj: data = json.load(db_obj) for key, value in data.items(): if key not in do_later: setattr(self, key, value) except (FileNotFoundError, ValueError, KeyError): Logger.error("Application file is broken: {}".format(self._db_file)) self._parse_paths(data["app_path"], "app_path") self._parse_paths(data["icons_path"], "icons_path") self._parse_icons(data["icons"]) if len(App.get("only")) == 1 and App.path(): self.app_path.append(App.path()) found = self.icons and self.app_path if self.force_create_folder and found: for icon_path in self.icons_path: create_dir(str(icon_path)) self.dont_install = False else: self.dont_install = not (found and self.icons_path) # NWJS special case if self.get_type() == "nwjs" and not self.dont_install: self.dont_install = not App.get("nwjs")
def icon_size(): """Return the icon size.""" if DESKTOP_ENV in ("pantheon", "xfce"): icon_size = 24 else: icon_size = 22 Logger.debug("System/Icon Size: {}".format(icon_size)) return icon_size
def install_icon(self, icon, icon_path): """Install the icon.""" png_bytes = get_pngbytes(icon) if png_bytes: icon = ElectronApplication.get_real_path(icon.original) self.set_icon(icon, icon_path, png_bytes, True) else: Logger.error("PNG file was not found.")
def only(self): """Return list of apps to be fixed.""" only = self._args.only if only: only = only.lower().strip() Logger.debug("Arguments/Only: {}".format(only)) return only.split(",") return []
def get_value(self, key): """Get the value of a specific key in the resources list.""" try: return self._resources.get(int(key)) except KeyError: Logger.warning("The key {0} dosen't seem to" " be found on {1}".format(key, self._filename)) return None
def symlink_file(source, link_name): """Symlink a file, remove the dest file if already exists.""" try: symlink(source, link_name) except FileExistsError: remove(link_name) symlink_file(source, link_name) except FileNotFoundError: Logger.warning("File not found: {0}".format(source))
def extract(self, icon_path): """Extract the zip file in /tmp directory.""" if path.exists(self.tmp_path): rmtree(self.tmp_path) Logger.debug("NWJS Application: Extracting of {}".format(self.binary)) execute(["unzip", path.join(str(icon_path), self.binary), "-d", self.tmp_path])
def create_dir(directory): """ Create a directory and fix folder permissions. Args : folder (str): folder path """ if not path.exists(directory): Logger.debug("Creating directory: {}".format(directory)) makedirs(directory, exist_ok=True)
def theme(): """Return a theme object.""" theme_name = Gtk.Settings.get_default().get_property("gtk-icon-theme-name") theme = None if theme_name: Logger.debug("System/Theme: {}".format(theme_name)) theme = Theme(theme_name) else: Logger.error("System/Theme: Not detected.") return theme
def revert_icon(self, icon, icon_path): """Revert to the original icon.""" target = B64ElectronApplication.get_real_path(self.file) backup_file = "|".join(target.split("/")) bytes = self.get_backup_file(backup_file) if bytes: self.set_icon(target, icon_path, bytes) else: Logger.error("Backup file of {0} was not found".format(self.name))
def revert_icon(self, icon, icon_path): """Revert to the original icon.""" asar_icon_path = ElectronApplication.get_real_path(icon.original) backup_file = "|".join(asar_icon_path.split("/")) png_bytes = self.get_backup_file(backup_file) if png_bytes: self.set_icon(icon.original, icon_path, png_bytes) else: Logger.error("Backup file of {0} was not found".format(self.name))
def get_gnome_scaling_factor(): """Return gnome scaling factor.""" source = Gio.SettingsSchemaSource.get_default() if source.lookup('org.gnome.desktop.interface', True): gsettings = Gio.Settings.new('org.gnome.desktop.interface') scaling_factor = gsettings.get_uint('scaling-factor') + 1 Logger.debug("Scaling Factor/GNOME: {}".format(scaling_factor)) return scaling_factor else: Logger.debug("Scaling Factor/Gnome not detected.") return 1
def get_gnome_scaling_factor(): """Return gnome scaling factor.""" source = Gio.SettingsSchemaSource.get_default() if source.lookup("org.gnome.desktop.interface", True): gsettings = Gio.Settings.new("org.gnome.desktop.interface") scaling_factor = gsettings.get_uint('scaling-factor') + 1 Logger.debug("Scaling Factor/GNOME: {}".format(scaling_factor)) return scaling_factor else: Logger.debug("Scaling Factor/Gnome not detected.") return 1
def extract(self, icon_path): """Extract the zip file in /tmp directory.""" if path.exists(self.tmp_path): rmtree(self.tmp_path) Logger.debug("NWJS Application: Extracting of {}".format(self.binary)) execute([ "unzip", path.join(str(icon_path), self.binary), "-d", self.tmp_path ])
def theme(): """Return a theme object.""" theme_name = Gtk.Settings.get_default().get_property( "gtk-icon-theme-name") theme = None if theme_name: Logger.debug("System/Theme: {}".format(theme_name)) theme = Theme(theme_name) else: Logger.error("System/Theme: Not detected.") return theme
def scaling_factor(): """ Returns the scaling factor. """ if not App._scaling_factor: scaling_factor = App.get("scaling_factor") if scaling_factor and scaling_factor > 1: # Change icon size by * it by the scaling factor App._icon_size = round(App.icon_size() * scaling_factor, 0) Logger.debug("Icon Size: {}".format(App._icon_size)) App._scaling_factor = scaling_factor return App._scaling_factor
def extract(self, icon_path): """Extract the zip file in /tmp directory.""" if path.exists(self.tmp_path): rmtree(self.tmp_path) makedirs(self.tmp_path, exist_ok=True) Logger.debug("Zip Application: Extracting of {} started".format(self.binary)) with ZipFile(path.join(str(icon_path), self.binary)) as zip_object: zip_object.extractall(self.tmp_path) Logger.debug("Zip Application: Extracting is done.")
def pack(self, icon_path): """Recreate the zip file from the tmp directory.""" zip_file = path.join(str(icon_path), self.binary) if path.isfile(zip_file): Logger.debug("Zip Application: Removing old binary file {}".format(zip_file)) remove(zip_file) make_archive(zip_file.replace(".zip", ""), 'zip', self.tmp_path) Logger.debug("Zip Application: Creating a new zip archive.") if path.exists(self.tmp_path): rmtree(self.tmp_path)
def extract(self, icon_path): """Extract the zip file in /tmp directory.""" if path.exists(self.tmp_path): rmtree(self.tmp_path) makedirs(self.tmp_path, exist_ok=True) Logger.debug("Zip Application: Extracting of " "{} started".format(self.binary)) with ZipFile(path.join(str(icon_path), self.binary)) as zip_object: zip_object.extractall(self.tmp_path) Logger.debug("Zip Application: Extracting is done.")
def detect_de(de_list): """Detect the desktop environment, used to choose the proper icons size.""" try: desktop_env = [environ.get("DESKTOP_SESSION", "").lower(), environ.get("XDG_CURRENT_DESKTOP", "").lower()] except AttributeError: desktop_env = [] for desktop in desktop_env: if desktop in de_list: Logger.debug("DE: {0}".format(desktop.title())) return desktop Logger.debug("DE not detected.") return "other"
def pack(self, icon_path): """Recreate the zip file from the tmp directory.""" zip_file = path.join(str(icon_path), self.binary) if path.isfile(zip_file): Logger.debug("Zip Application: Removing " "old binary file {}".format(zip_file)) remove(zip_file) make_archive(zip_file.replace(".zip", ""), 'zip', self.tmp_path) Logger.debug("Zip Application: Creating a new zip archive.") if path.exists(self.tmp_path): rmtree(self.tmp_path)
def reinstall(self): """Overwrite the reinstall function, and remove the whole dir.""" done = False for icon_path in self.icons_path: icon_path = str(icon_path) if path.isdir(icon_path): rmtree(icon_path) Logger.debug("Qt Application: Reverting" " {} is done.".format(self.name)) done = True if not done: Logger.debug("Qt Application: Reverting " "{} is not done.".format(self.name)) self.success = done
def reinstall(self): """Overwrite the reinstall function, and remove the whole dir.""" done = False for icon_path in self.icons_path: icon_path = str(icon_path) if path.isdir(icon_path): rmtree(icon_path) Logger.debug("Qt Application: Reverting {} is done.".format( self.name)) done = True if not done: Logger.debug("Qt Application: Reverting {} is not done.".format( self.name)) self.success = done
def get_cinnamon_scaling_factor(): """Return Cinnamon desktop scaling factor.""" source = Gio.SettingsSchemaSource.get_default() if source.lookup('org.cinnamon.desktop.interface', True): gsettings = Gio.Settings.new('org.cinnamon.desktop.interface') scaling_factor = gsettings.get_uint('scaling-factor') if scaling_factor == 0: # Cinnamon does have an auto scaling feature which we can't use scaling_factor = 1 Logger.debug("Scaling Factor/Cinnamon: {}".format(scaling_factor)) return scaling_factor else: Logger.debug("Scaling Factor/Cinnamon not detected") return 1
def get_cinnamon_scaling_factor(): """Return Cinnamon desktop scaling factor.""" source = Gio.SettingsSchemaSource.get_default() if source.lookup("org.cinnamon.desktop.interface", True): gsettings = Gio.Settings.new("org.cinnamon.desktop.interface") scaling_factor = gsettings.get_uint('scaling-factor') if scaling_factor == 0: # Cinnamon does have an auto scaling feature which we can't use scaling_factor = 1 Logger.debug("Scaling Factor/Cinnamon: {}".format(scaling_factor)) return scaling_factor else: Logger.debug("Scaling Factor/Cinnamon not detected") return 1
def create(self, filename): """Backup functions.""" from HardcodeTray.app import App if not App.get('backup_ignore'): if not self.backup_dir: self.create_backup_dir() backup_file = path.join(self.backup_dir, path.basename(filename)) if path.exists(filename): Logger.debug("Backup file: {0} to: {1}".format( filename, backup_file)) copy_file(filename, backup_file, True)
def create(self, filename): """Backup functions.""" from HardcodeTray.app import App if not App.get("backup_ignore"): if not self.backup_dir: self.create_backup_dir() backup_file = path.join(self.backup_dir, path.basename(filename)) if path.exists(filename): Logger.debug("Backup file: {0} to: {1}".format(filename, backup_file)) copy_file(filename, backup_file, True)
def set_icon(self, icon, icon_path, pngbytes, backup=False): """Update the icon bytes with the new one.""" self.set_binary_file(path.join(str(icon_path), self.binary)) if self.pak: icon_name = icon.original if pngbytes and self.pak.haskey(icon_name): if backup: self.backup.file(icon_name, self.pak.get_value(icon_name)) self.pak.set_value(icon_name, pngbytes) self.pak.write() else: Logger.error("Couldn't find a PNG file.") else: Logger.warning("The file {0} was not found".format( self.binary_file))
def set_icon(self, icon, icon_path, pngbytes, backup=False): """Update the icon bytes with the new one.""" self.set_binary_file(path.join(str(icon_path), self.binary)) if self.pak: icon_name = icon.original if pngbytes and self.pak.haskey(icon_name): if backup: self.backup.file(icon_name, self.pak.get_value(icon_name)) self.pak.set_value(icon_name, pngbytes) self.pak.write() else: Logger.error("Couldn't find a PNG file.") else: Logger.warning( "The file {0} was not found".format(self.binary_file))
def detect_de(de_list): """Detect the desktop environment, used to choose the proper icons size.""" try: desktop_env = [ environ.get("DESKTOP_SESSION", "").lower(), environ.get("XDG_CURRENT_DESKTOP", "").lower() ] except AttributeError: desktop_env = [] for desktop in desktop_env: if desktop in de_list: Logger.debug("DE: {0}".format(desktop.title())) return desktop Logger.debug("DE not detected.") return "other"
def execute(command_list, verbose=True, shell=False, working_directory=None): """ Run a command using "Popen". Args : command_list(list) verbose(bool) """ Logger.debug("Executing command: {0}".format(" ".join(command_list))) if working_directory: cmd = Popen(command_list, stdout=PIPE, stderr=PIPE, shell=shell, cwd=working_directory) else: cmd = Popen(command_list, stdout=PIPE, stderr=PIPE, shell=shell) output, error = cmd.communicate() if verbose and error: Logger.error(error.decode("utf-8").strip()) return output
def create_backup_dir(self): """Create a backup directory for an application (application_name).""" backup_dir = path.join(BACKUP_FOLDER, self.app.name, strftime(BACKUP_FILE_FORMAT), "") exists = True new_backup_dir = backup_dir i = 1 while exists: if path.exists(new_backup_dir): new_backup_dir = backup_dir + "_" + str(i) if not path.isdir(new_backup_dir): Logger.debug("Create new backup folder " "for {}".format(self.app.name)) create_dir(new_backup_dir) exists = False i += 1 self._backup_dir = new_backup_dir
def _get_header(self): asarfile = open(self._asar_file, 'rb') try: asarfile.seek(4) # header size is stored in byte 12:16 self._hb[0] = unpack('I', asarfile.read(4))[0] self._hb[1] = unpack('I', asarfile.read(4))[0] self._hb[2] = unpack('I', asarfile.read(4))[0] self._zeros = (self._hb[1] - 4 - self._hb[2]) header = asarfile.read(self._hb[2]).decode('utf-8') self._header = loads(header) self._offset = asarfile.tell() + self._zeros asarfile.close() except StructError: Logger.error( "Electron: Couldn't read asar file {}".format(self._asar_file)) self.success = False
def get_kde_scaling_factor(): """Return the widgets scaling factor on KDE.""" scaling_factor = None was_found = False try: with open(KDE_CONFIG_FILE, 'r') as kde_obj: data = kde_obj.readlines() for line in data: line = list(map(lambda x: x.strip(), line.split("="))) if len(line) == 1: was_found = match( r'\[Containments\]\[[0-9]+\]\[General\]', line[0]) if len(line) > 1 and was_found and line[0].lower() == "iconsize": scaling_factor = int(line[1]) break if scaling_factor: Logger.debug("Scaling Factor/KDE: {}".format(scaling_factor)) return scaling_factor except (FileNotFoundError, KeyError) as kde_error: Logger.debug("Scaling Factor/KDE not detected.") Logger.error(kde_error) return None