aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2015-04-04 14:40:34 +0200
committerMattias Andrée <maandree@operamail.com>2015-04-04 14:40:34 +0200
commit0d65a9c9faca8f06dc70c577e7ddb42fba5359fd (patch)
tree89473b4253c9f9630f1601dd891026b0119e02e1 /src
parentm (diff)
downloadxpybar-0d65a9c9faca8f06dc70c577e7ddb42fba5359fd.tar.gz
xpybar-0d65a9c9faca8f06dc70c577e7ddb42fba5359fd.tar.bz2
xpybar-0d65a9c9faca8f06dc70c577e7ddb42fba5359fd.tar.xz
.desktop file support
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/application.py147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/plugins/application.py b/src/plugins/application.py
new file mode 100644
index 0000000..6af7227
--- /dev/null
+++ b/src/plugins/application.py
@@ -0,0 +1,147 @@
+# -*- python -*-
+'''
+xpybar – xmobar replacement written in python
+Copyright © 2014, 2015 Mattias Andrée (maandree@member.fsf.org)
+
+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/>.
+'''
+
+
+class Application:
+ '''
+ Applications and .desktop files
+
+ @variable desktop_file:str The .desktop file for the application
+ @variable settings:dict<str?, dict<str, dict<str?, str>>> Section → key → locale → value map of settings
+ '''
+
+
+ def __init__(self, file):
+ '''
+ Constructor
+
+ @param file:str The .desktop file if it contains '/', otherwise the name of the application
+ '''
+ import os
+ if '/' not in file:
+ import pwd
+ directories = []
+ home = pwd.getpwuid(os.getuid()).pw_dir
+ directories.append('%s/.local/share/applications' % home)
+ if 'HOME' in os.environ:
+ if not os.environ['HOME'] == home:
+ home = os.environ['HOME']
+ directories.append('%s/.local/share/applications' % home)
+ directories += ['/usr/local/share/applications', '/usr/share/applications', '/share/applications']
+ directories = [d for d in directories if os.path.exists(d) and os.path.isdir(d)]
+
+ file = ['%s/%s.desktop' % (d, file) for d in directories]
+ file = [f for f in file if os.path.exists(f) and os.path.isfile(f)]
+ if len(file) == 0:
+ raise Exception('Application not found')
+ file = file[0]
+
+ self.desktop_file = file
+ with open(self.desktop_file, 'rb') as file:
+ data = file.read()
+ data = [l for l in data.decode('utf-8', 'replace').replace('\r', '\n').split('\n') if not l == '']
+
+ section = None
+ self.settings = {}
+ for line in data:
+ line = line.strip()
+ if line.startswith('[') and line.endswith(']'):
+ section = line[1 : -1]
+ elif line.startswith(';') or line.startswith('#'):
+ pass
+ elif (':' in line) or ('=' in line):
+ line_e = line.split('=')
+ line_c = line.split(':')
+ if len(line_e[0]) < len(line_c[0]):
+ first = '='
+ line = line_e
+ else:
+ first = ':'
+ line = line_c
+ key, value = line[0].rstrip(), first.join(line[1:]).lstrip()
+ locale = None
+ if ('[' in key) and key.endswith(']'):
+ key = key[:-1].split('[')
+ key, locale = '['.join(key[:-1]), key[-1]
+ if section not in self.settings:
+ self.settings[section] = {}
+ section_map = self.settings[section]
+ if key not in section_map:
+ section_map[key] = {}
+ key_map = section_map[key]
+ if locale not in key_map:
+ key_map[locale] = value
+
+ self.locales = [None]
+ if 'LANG' in os.environ:
+ locale = os.environ['LANG']
+ elif 'LOCALE' in os.environ:
+ locale = os.environ['LOCALE']
+ else:
+ return
+ locale = locale.split(' ')[0].split('.')[0].split('_')
+ for i in range(len(locale)):
+ self.locales.append('_'.join(locale[:i]))
+ self.locales.reverse()
+
+
+ def get_setting(self, key, section = 'Desktop Entry', locales = None):
+ '''
+ Read a setting in the application's .desktop file
+
+ @param key:str The key
+ @param section:str? The section where the key is located
+ @param locale:list<str?>? Acceptable locales in order of preference,
+ `None` to use the default for your locale
+ '''
+ map = self.settings
+ if section not in map:
+ return None
+ map = map[section]
+ if key not in map:
+ return None
+ map = map[key]
+ if locales is None:
+ locales = self.locales
+ for locale in locales:
+ if locale in map:
+ return map[locale]
+ return None
+
+
+ @staticmethod
+ def strip_placeholders(text):
+ '''
+ Remove placeholders form an exec string
+
+ @param text:str The exec string with placeholders
+ @return :str The exec string without placeholders
+ '''
+ buf, esc = '', False
+ for c in text:
+ if esc:
+ esc = False
+ if c == '%':
+ buf += c
+ elif c == '%':
+ esc = True
+ else:
+ buf += c
+ return buf
+