Advertisement
13minutes-yt

obamenu

Jan 27th, 2022
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.97 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. # Version 1.1.7
  5. # ---- config ---
  6. applications_dirs = ("/usr/share/applications", )
  7. image_dir_base = "/usr/share" # without "pixmaps" -/usr/local/share in FreeBSD, /usr/share on linux
  8. icon_Theme = "Humanity"
  9. image_cat_prefix = "applications-" # if empty will create no icon text only menu
  10. application_groups = ("Office", "Development", "Graphics", "Internet", "Games", "System", "Multimedia", "Utilities", "Settings")
  11. group_aliases = {"Audio":"Multimedia","AudioVideo":"Multimedia","Network":"Internet","Game":"Games", "Utility":"Utilities", "GTK":"", "GNOME":""}
  12. ignoreList = ("evince-previewer", "Ted", "wingide3.2", "python3.4", "feh","xfce4-power-manager-settings" )
  13. terminal_string = "evte -e" # your favourites terminal exec string
  14. simpleOBheader = False # print full xml style OB header
  15. # --- End of user config ---
  16.  
  17. import glob
  18.  
  19. class dtItem(object):
  20. def __init__(self, fName):
  21. self.fileName = fName
  22. self.Name = ""
  23. self.Comment = ""
  24. self.Exec = ""
  25. self.Terminal = None
  26. self.Type = ""
  27. self.Icon = ""
  28. self.Categories = ()
  29.  
  30. def addName(self, data):
  31. self.Name = xescape(data)
  32.  
  33. def addComment(self, data):
  34. self.Comment = data
  35.  
  36. def addExec(self, data):
  37. if len(data) > 3 and data[-2] == '%': # get rid of filemanager arguments in dt files
  38. data = data[:-2].strip()
  39. self.Exec = data
  40.  
  41. def addIcon(self, data):
  42. self.Icon = ""
  43. if image_cat_prefix == "":
  44. return
  45. image_dir = image_dir_base + "/pixmaps/"
  46. di = data.strip()
  47. if len(di) < 3:
  48. #"Error in %s: Invalid or no icon '%s'" % (self.fileName, di)
  49. return
  50. dix = di.find("/") # is it a full path?
  51. if dix >= 0 and dix <= 2: # yes, its a path (./path or ../path or /path ...)
  52. self.Icon = di
  53. return
  54. #else a short name like "myapp"
  55. tmp = image_dir + di + ".*"
  56. tmp = glob.glob(tmp)
  57. if len(tmp) > 0:
  58. self.Icon = tmp[0]
  59. return
  60.  
  61. def addTerminal(self, data):
  62. if data == "True" or data == "true":
  63. self.Terminal = True
  64. else:
  65. self.Terminal = False
  66.  
  67. def addType(self, data):
  68. self.Type = data
  69.  
  70. def addCategories(self, data):
  71. self.Categories = data
  72.  
  73. def getCatIcon(cat):
  74. iconDir = image_dir_base + "/icons/" + icon_Theme + "/categories/24/"
  75. cat = image_cat_prefix + cat.lower()
  76. tmp = glob.glob(iconDir + cat + ".*")
  77. if len(tmp) > 0:
  78. return tmp[0]
  79. return ""
  80.  
  81. def xescape(s):
  82. Rep = {"&":"&amp;", "<":"&lt;", ">":"&gt;", "'":"&apos;", "\"":"&quot;"}
  83. for p in ("&", "<", ">", "'","\""):
  84. sl = len(s); last = -1
  85. while last < sl:
  86. i = s.find(p, last+1)
  87. if i < 0:
  88. done = True
  89. break
  90. last = i
  91. l = s[:i]
  92. r = s[i+1:]
  93. s = l + Rep[p] + r
  94. return s
  95.  
  96. def process_category(cat, curCats, appGroups = application_groups, aliases = group_aliases ):
  97. # first process aliases
  98. if cat in aliases:
  99. if aliases[cat] == "":
  100. return "" # ignore this one
  101. cat = aliases[cat]
  102. if cat in appGroups and cat not in curCats: # valid categories only and no doublettes, please
  103. curCats.append(cat)
  104. return cat
  105. return ""
  106.  
  107.  
  108. def process_dtfile(dtf, catDict): # process this file & extract relevant info
  109. active = False # parse only after "[Desktop Entry]" line
  110. fh = open(dtf, "r")
  111. lines = fh.readlines()
  112. this = dtItem(dtf)
  113. for l in lines:
  114. l = l.strip()
  115. if l == "[Desktop Entry]":
  116. active = True
  117. continue
  118. if active == False: # we don't care about licenses or other comments
  119. continue
  120. if l == None or len(l) < 1 or l[0] == '#':
  121. continue
  122. if l[0]== '[' and l != "[Desktop Entry]":
  123. active = False
  124. continue
  125. # else
  126. eqi = l.split('=')
  127. if len(eqi) < 2:
  128. print("Error: Invalid .desktop line'" + l + "'")
  129. continue
  130. # Check what it is ...
  131. if eqi[0] == "Name":
  132. this.addName(eqi[1])
  133. elif eqi[0] == "Comment":
  134. this.addComment(eqi[1])
  135. elif eqi[0] == "Exec":
  136. this.addExec(eqi[1])
  137. elif eqi[0] == "Icon":
  138. this.addIcon(eqi[1])
  139. elif eqi[0] == "Terminal":
  140. this.addTerminal(eqi[1])
  141. elif eqi[0] == "Type":
  142. if eqi[1] != "Application":
  143. continue
  144. this.addType(eqi[1])
  145. elif eqi[0] == "Categories":
  146. if eqi[1] and eqi[1][-1] == ';':
  147. eqi[1] = eqi[1][0:-1]
  148. cats = []
  149. # DEBUG
  150. dtCats = eqi[1].split(';')
  151. for cat in dtCats:
  152. result = process_category(cat, cats)
  153. this.addCategories(cats)
  154. else:
  155. continue
  156. # add to catDict
  157. #this.dprint()
  158. if len(this.Categories) > 0: # don't care about stuff w/o category
  159. for cat in this.Categories:
  160. catDict[cat].append(this)
  161.  
  162. categoryDict = {}
  163.  
  164. if __name__ == "__main__":
  165. # init the application group dict (which will contain list of apps)
  166. for appGroup in application_groups:
  167. categoryDict[appGroup] = []
  168.  
  169. # now let's look into the app dirs ...
  170. for appDir in applications_dirs:
  171. appDir += "/*.desktop"
  172. dtFiles = glob.glob(appDir)
  173.  
  174. # process each .desktop file in dir
  175. for dtf in dtFiles:
  176. skipFlag = False
  177. for ifn in ignoreList:
  178. if dtf.find(ifn) >= 0:
  179. skipFlag = True
  180. if skipFlag == False:
  181. process_dtfile(dtf, categoryDict)
  182.  
  183. # now, generate jwm menu include
  184. if simpleOBheader == True:
  185. print('<openbox_pipe_menu>') # magic header
  186. else:
  187. print('<?xml version="1.0" encoding="UTF-8" ?><openbox_pipe_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/" >') # magic header
  188. appGroupLen = len(application_groups)
  189. for ag in range(appGroupLen ):
  190. catList = categoryDict[application_groups[ag]]
  191. if len(catList) < 1:
  192. continue # don't create empty menus
  193. catStr = "<menu id=\"openbox-%s\" label=\"%s\" " % (application_groups[ag], application_groups[ag])
  194. tmp = getCatIcon(application_groups[ag])
  195. if tmp != "":
  196. catStr += "icon=\"%s\"" % tmp
  197. print(catStr, ">")
  198. for app in catList:
  199. progStr = "<item "
  200. progStr += "label=\"%s\" " % app.Name
  201. if app.Icon != "":
  202. progStr += "icon=\"%s\" " % app.Icon
  203. progStr += "><action name=\"Execute\"><command><![CDATA["
  204. if app.Terminal == True:
  205. progStr += terminal_string + " "
  206. progStr += "%s]]></command></action></item>" % app.Exec
  207. print(progStr)
  208. print("</menu>")
  209. print("</openbox_pipe_menu>") # magic footer
  210. pass # done/debug break
  211.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement