#!/usr/bin/python3 import os.path import shutil import xdg.DesktopEntry import xdg.Menu import gi gi.require_version("Gtk", "3.0") gi.require_version("MateDesktop", "2.0") from gi.repository import Gtk, Gdk, GdkPixbuf, GLib, GObject, Pango, MateDesktop from plugins.execute import Execute from plugins.filemonitor import monitor as filemonitor class IconManager(GObject.GObject): __gsignals__ = { "changed" : (GObject.SignalFlags.RUN_LAST, None, ()) } def __init__(self): GObject.GObject.__init__(self) self.icons = {} self.count = 0 # Some apps don't put a default icon in the default theme folder, so we will search all themes # def createTheme(d): # theme = Gtk.IconTheme() # theme.set_custom_theme(d) # return theme # This takes to much time and there are only a very few applications that use icons from different themes #self.themes = map( createTheme, [d for d in os.listdir("/usr/share/icons") if os.path.isdir(os.path.join("/usr/share/icons", d))]) self.defaultTheme = Gtk.IconTheme.get_default() #defaultKdeTheme = createTheme("kde.default") # Setup and clean up the temp icon dir configDir = GLib.get_user_config_dir() self.iconDir = os.path.join(configDir, "mintmenu") if not os.path.exists(self.iconDir): os.makedirs(self.iconDir) contents = os.listdir(self.iconDir) for fn in contents: os.remove(os.path.join(self.iconDir, fn)) self.defaultTheme.append_search_path(self.iconDir) # Themes with the same content as the default them aren't needed #self.themes = [theme for theme in self.themes if theme.list_icons() != defaultTheme.list_icons()] #self.themes = [self.defaultTheme, defaultKdeTheme] self.themes = [self.defaultTheme] # Listen for changes in the themes # for theme in self.themes: # theme.connect("changed", self.themeChanged) def getIcon(self, iconName, iconSize): if not iconName: return None try: iconFileName = "" realIconName = "" needTempFile = False #[iconWidth, iconHeight] = self.getIconSize(iconSize) if iconSize <= 0: return None elif os.path.isabs(iconName): iconFileName = iconName needTempFile = True else: if iconName[-4:] in [".png", ".xpm", ".svg", ".gif"]: realIconName = iconName[:-4] else: realIconName = iconName if iconFileName and needTempFile and os.path.exists(iconFileName): tmpIconName = iconFileName.replace("/", "-") realIconName = tmpIconName[:-4] if not os.path.exists(os.path.join(self.iconDir, tmpIconName)): shutil.copyfile(iconFileName, os.path.join(self.iconDir, tmpIconName)) self.defaultTheme.append_search_path(self.iconDir) image = Gtk.Image.new_from_icon_name(realIconName, Gtk.IconSize.DND) image.set_pixel_size(iconSize) return image except Exception as e: print("Exception %s: %s" % (e.__class__.__name__, e)) return None def themeChanged(self, theme): self.emit("changed") GObject.type_register(IconManager) class easyButton(Gtk.Button): def __init__(self, iconName, iconSize, labels=None, buttonWidth=-1, buttonHeight=-1, ellipsis=True): GObject.GObject.__init__(self) self.connections = [] self.iconName = iconName self.iconSize = iconSize self.showIcon = True self.ellipsis = ellipsis self.set_relief(Gtk.ReliefStyle.NONE) self.set_size_request(buttonWidth, buttonHeight) Align1 = Gtk.Alignment.new(0, 0.5, 1.0, 0) HBox1 = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.labelBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) self.buttonImage = self.getIcon(self.iconSize) if not self.buttonImage: self.buttonImage = Gtk.Image() self.buttonImage.set_size_request(self.iconSize, self.iconSize) self.image_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self.image_box.pack_start(self.buttonImage, False, False, 5) self.image_box.show_all() HBox1.pack_start(self.image_box, False, False, 0) if labels: for label in labels: if isinstance(label, str): self.addLabel(label) elif isinstance(label, list): self.addLabel(label[0], label[1]) self.labelBox.show() HBox1.pack_start(self.labelBox , True, True, 0) HBox1.show() Align1.add(HBox1) Align1.show() self.add(Align1) self.connectSelf("destroy", self.onDestroy) self.connect("released", self.onRelease) # Reload icons when the theme changed # self.themeChangedHandlerId = iconManager.connect("changed", self.themeChanged) def connectSelf(self, event, callback): self.connections.append(self.connect(event, callback)) def onRelease(self, widget): widget.get_style_context().set_state(Gtk.StateFlags.NORMAL) def onDestroy(self, widget): self.buttonImage.clear() # iconManager.disconnect(self.themeChangedHandlerId) for connection in self.connections: self.disconnect(connection) del self.connections def addLabel(self, text, styles = None): label = Gtk.Label() if "" in text or "%s\n%s' % (appName, appComment)) else: self.addLabel('%s\n%s' % (appName, appComment)) else: self.addLabel(appName) def execute(self, *args, **kwargs): self.highlight = False for child in self.labelBox: child.destroy() self.setupLabels() return super(MenuApplicationLauncher, self).execute(*args, **kwargs) def setShowComment(self, showComment): self.showComment = showComment for child in self.labelBox: child.destroy() self.setupLabels() class FavApplicationLauncher(ApplicationLauncher): def __init__(self, desktopFile, iconSize, swapGeneric = False): self.swapGeneric = swapGeneric ApplicationLauncher.__init__(self, desktopFile, iconSize) def setupLabels(self): if self.appGenericName: if self.swapGeneric: self.addLabel('%s' % self.appName) self.addLabel(self.appGenericName) else: self.addLabel('%s' % self.appGenericName) self.addLabel(self.appName) else: self.addLabel('%s' % self.appName) if self.appComment != "": self.addLabel(self.appComment) else: self.addLabel("") def setSwapGeneric(self, swapGeneric): self.swapGeneric = swapGeneric for child in self.labelBox: child.destroy() self.setupLabels() class CategoryButton(easyButton): def __init__(self, iconName, iconSize, labels , f): easyButton.__init__(self, iconName, iconSize, labels, ellipsis=False) self.filter = f iconManager = IconManager()