# Python imports import subprocess import threading import os import json from os.path import isdir, isfile, join from os import listdir # Lib imports import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk as gtk from gi.repository import GLib as glib from xdg.DesktopEntry import DesktopEntry # Application imports def threaded(fn): def wrapper(*args, **kwargs): threading.Thread(target=fn, args=args, kwargs=kwargs).start() return wrapper class MainMenuMixin: def toggleProgramMenu(self, widget): pos = self.menuWindow.get_position() posX = pos[0] + 32 posY = pos[1] + 72 if self.menuWindow.get_visible() == False: self.menuWindow.move(posX, posY) glib.idle_add(self.menuWindow.show_all) else: glib.idle_add(self.menuWindow.hide) def setListGroup(self, widget): self.progGroup = widget.get_label().strip() self.getSubgroup(self.progGroup) self.generateListView() def searchForEntry(self, widget, data=None): self.progGroup = "[ Search ]" query = widget.get_text().strip() if not query: self.progGroup = self.grpDefault self.getSubgroup() self.generateListView() return self.getSubgroup(query) self.generateListView() @threaded def generateListView(self): widget = self.builder.get_object("programListBttns") # Should have this as a useful method...But, I don't want to import Glib everywhere children = widget.get_children() for child in children: glib.idle_add(widget.remove, (child)) for obj in self.desktopObjs: title = obj[0] dirPath = obj[1] if self.showIcons: image = self.iconFactory.parseDesktopFiles(dirPath) # .get_pixbuf() self.addToProgramListView(widget, title, image) else: self.addToProgramListViewAsText(widget, title) @threaded def addToProgramListView(self, widget, title, icon): button = gtk.Button(label=title) button.set_image(icon) button.connect("clicked", self.executeProgram) children = button.get_children() alignment1 = children[0] box = alignment1.get_children()[0] label = box.get_children()[1] alignment1.set(0.0, 0.0, 0.0, 0.0) label.set_halign(1) label.set_line_wrap(True) label.set_max_width_chars(38) label.set_size_request(640, 64) button.show_all() glib.idle_add(widget.add, (button)) @threaded def addToProgramListViewAsText(self, widget, title): button = gtk.Button(label=title) button.connect("clicked", self.executeProgram) children = button.get_children() label = children[0] label.set_halign(1) label.set_line_wrap(True) label.set_max_width_chars(38) label.set_size_request(640, 64) button.show_all() glib.idle_add(widget.add, (button)) def executeProgram(self, widget): """ # TODO: Need to refactor and pull out the sub loop that is used in both cases... """ entry = widget.get_label().strip() group = self.progGroup parts = entry.split("||") program = parts[0].strip() comment = parts[1].strip() if "[ Search ]" in group: gkeys = self.menuData.keys() for gkey in gkeys: for opt in self.menuData[gkey]: if program in opt["title"]: keys = opt.keys() if comment in opt["comment"] or comment in opt["fileName"]: DEVNULL = open(os.devnull, 'w') execFailed = False try: command = opt["tryExec"].split("%")[0] # self.logger.debug(command) subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL) break except Exception as e: execFailed = True if execFailed: try: if "exec" in keys and len(opt["exec"]): command = opt["exec"].split("%")[0] # self.logger.debug(command) subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL) break except Exception as e: print( repr(e) ) # self.logger.debug(e) else: for opt in self.menuData[group]: if program in opt["title"]: keys = opt.keys() if comment in opt["comment"] or comment in opt["fileName"]: DEVNULL = open(os.devnull, 'w') execFailed = False try: command = opt["tryExec"].split("%")[0] # self.logger.debug(command) subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL) except Exception as e: execFailed = True if execFailed: try: if "exec" in keys and len(opt["exec"]): command = opt["exec"].split("%")[0] # self.logger.debug(command) subprocess.Popen(command.split(), start_new_session=True, stdout=DEVNULL, stderr=DEVNULL) except Exception as e: print( repr(e) ) # self.logger.debug(e) # Supoport methods def getDesktopFilesInfo(self, paths): menuObjs = { "Accessories": [], "Multimedia": [], "Graphics": [], "Game": [], "Office": [], "Development": [], "Internet": [], "Settings": [], "System": [], "Wine": [], "Other": [] } for path in paths: if not "/opt/" in path: self.listAndUpdateDesktopFiles(path, menuObjs); else: for folder in listdir(path): try: fPath = path + folder + "/" self.listAndUpdateDesktopFiles(fPath, menuObjs); except Exception as e: print( repr(e) ) return menuObjs def listAndUpdateDesktopFiles(self, path, menuObjs): for f in listdir(path): fPath = path + f if isfile(fPath) and f.endswith(".desktop"): xdgObj = DesktopEntry(fPath) title = xdgObj.getName() groups = xdgObj.getCategories() comment = xdgObj.getComment() icon = xdgObj.getIcon() mainExec = xdgObj.getExec() tryExec = xdgObj.getTryExec() group = "" if "Accessories" in groups or "Utility" in groups: group = "Accessories" elif "Multimedia" in groups or "Video" in groups or "Audio" in groups: group = "Multimedia" elif "Development" in groups: group = "Development" elif "Game" in groups: group = "Game" elif "Internet" in groups or "Network" in groups: group = "Internet" elif "Graphics" in groups: group = "Graphics" elif "Office" in groups: group = "Office" elif "System" in groups: group = "System" elif "Settings" in groups: group = "Settings" elif "Wine" in groups: group = "Wine" else: group = "Other" menuObjs[group].append( {"title": title, "groups": groups, "comment": comment, "exec": mainExec, "tryExec": tryExec, "fileName": f, "filePath": fPath, "icon": icon}) def getSubgroup(self, query = ""): """ Need to refactor and pull out the sub logic that is used in both cases... """ group = self.progGroup self.desktopObjs.clear() if "[ Search ]" in group: gkeys = self.menuData.keys() for gkey in gkeys: for opt in self.menuData[gkey]: keys = opt.keys() if "comment" in keys and len(opt["comment"]) > 0 : if query.lower() in opt["comment"].lower(): title = opt["title"] + " || " + opt["comment"] fPath = opt["filePath"] self.desktopObjs.append([title, fPath]) continue if query.lower() in opt["title"].lower() or \ query.lower() in opt["fileName"].lower(): title = opt["title"] + " || " + opt["fileName"].replace(".desktop", "") fPath = opt["filePath"] self.desktopObjs.append([title, fPath]) else: for opt in self.menuData[group]: keys = opt.keys() if "comment" in keys and len(opt["comment"]) > 0 : title = opt["title"] + " || " + opt["comment"] fPath = opt["filePath"] self.desktopObjs.append([title, fPath]) else: title = opt["title"] + " || " + opt["fileName"].replace(".desktop", "") fPath = opt["filePath"] self.desktopObjs.append([title, fPath]) return self.desktopObjs