Nils
5 years ago
1 changed files with 142 additions and 0 deletions
@ -0,0 +1,142 @@ |
|||||
|
#! /usr/bin/env python3 |
||||
|
# -*- coding: utf-8 -*- |
||||
|
""" |
||||
|
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net ) |
||||
|
|
||||
|
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ), |
||||
|
|
||||
|
This 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/>. |
||||
|
""" |
||||
|
|
||||
|
import logging; logger = logging.getLogger(__name__); logger.info("import") |
||||
|
|
||||
|
from os import getenv |
||||
|
import os |
||||
|
import pathlib |
||||
|
import re |
||||
|
|
||||
|
""" |
||||
|
https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html |
||||
|
https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#icon_lookup |
||||
|
|
||||
|
$HOME/.icons (for backwards compatibility) |
||||
|
$XDG_DATA_DIRS/icons |
||||
|
/usr/share/pixmaps |
||||
|
""" |
||||
|
|
||||
|
SEARCH_DIRECTORIES = [pathlib.Path(pathlib.Path.home(), ".icons")] |
||||
|
|
||||
|
XDG_DATA_DIRS = getenv("XDG_DATA_DIRS") #colon : separated, most likely empty |
||||
|
if XDG_DATA_DIRS: |
||||
|
SEARCH_DIRECTORIES += [pathlib.Path(p, "icons") for p in XDG_DATA_DIRS.split(":")] |
||||
|
else: |
||||
|
#If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used. |
||||
|
SEARCH_DIRECTORIES += [pathlib.Path(p, "icons") for p in "/usr/local/share/:/usr/share/".split(":")] |
||||
|
|
||||
|
SEARCH_DIRECTORIES.append(pathlib.Path("/usr/share/pixmaps")) |
||||
|
|
||||
|
|
||||
|
def run_fast_scandir(dir, ext): |
||||
|
""" |
||||
|
https://stackoverflow.com/questions/18394147/recursive-sub-folder-search-and-return-files-in-a-list-python |
||||
|
""" |
||||
|
subfolders, files = [], [] |
||||
|
|
||||
|
try: |
||||
|
for f in os.scandir(dir): |
||||
|
if f.is_dir(): |
||||
|
subfolders.append(f.path) |
||||
|
if f.is_file(): |
||||
|
if os.path.splitext(f.name)[1].lower() in ext: |
||||
|
files.append(f.path) |
||||
|
|
||||
|
for dir in list(subfolders): |
||||
|
sf, f = run_fast_scandir(dir, ext) |
||||
|
subfolders.extend(sf) |
||||
|
files.extend(f) |
||||
|
|
||||
|
except PermissionError: |
||||
|
pass |
||||
|
|
||||
|
except FileNotFoundError: |
||||
|
pass |
||||
|
|
||||
|
return subfolders, files |
||||
|
|
||||
|
|
||||
|
def _buildCache()->set: |
||||
|
result = [] |
||||
|
for basePath in SEARCH_DIRECTORIES: |
||||
|
forget, files = run_fast_scandir(basePath, [".png", ".xpm", ".svg"]) |
||||
|
result += files |
||||
|
|
||||
|
#Convert str to real paths |
||||
|
result = [pathlib.Path(r) for r in result if pathlib.Path(r).is_file()] |
||||
|
|
||||
|
return set(result) |
||||
|
|
||||
|
_cache = _buildCache() |
||||
|
|
||||
|
|
||||
|
rePattern = re.compile("\d+x\d+") #we don't put .* around this because we are searching for the subpattern |
||||
|
|
||||
|
def findIconPath(executableName:str)->list: |
||||
|
"""Return order is: svg first, then highest resolution first, then the rest unordered. |
||||
|
so you can use result[0] for the best variant. |
||||
|
It is not guaranteed that [1], or even [0] exists. |
||||
|
This is not a sorted list, these extra variants are just added to the front of the list again""" |
||||
|
|
||||
|
executableName = executableName.lower() |
||||
|
|
||||
|
svg = None |
||||
|
bestr = 0 #resolution |
||||
|
best = None |
||||
|
|
||||
|
result = [] |
||||
|
for f in _cache: |
||||
|
if f.stem == executableName: |
||||
|
if f.suffix == ".svg": |
||||
|
svg = f |
||||
|
else: |
||||
|
match = re.search(rePattern, str(f)) #find resolution dir like /48x48/ |
||||
|
if match: |
||||
|
resolutionAsNumber = int(match.group().split("x")[0]) |
||||
|
if resolutionAsNumber > bestr: #new best one |
||||
|
bestr = resolutionAsNumber |
||||
|
best = f |
||||
|
result.append(f) |
||||
|
|
||||
|
if best: |
||||
|
result.insert(0, best) |
||||
|
if svg: |
||||
|
result.insert(0, svg) |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
"""Example that tries to find a few icons""" |
||||
|
|
||||
|
print("Search paths:") |
||||
|
print(SEARCH_DIRECTORIES) |
||||
|
print() |
||||
|
|
||||
|
for exe in ("ZynAddSubFx", "patroneo", "jack_mixer", "carla", "ardour6", "synthv1"): |
||||
|
r = findIconPath(exe) |
||||
|
if r: |
||||
|
print (f"{exe} Best resolution: {r[0]}") |
||||
|
else: |
||||
|
print (f"{exe}: No icon found ") |
||||
|
|
||||
|
|
||||
|
|
Loading…
Reference in new issue