Highlight newly installed applications

This commit is contained in:
Clement Lefebvre 2010-09-13 15:54:23 +01:00
parent b6f3353305
commit ec963baeab
3 changed files with 487 additions and 484 deletions

1
debian/changelog vendored
View File

@ -5,6 +5,7 @@ mintmenu (5.0.6) julia; urgency=low
* 150ms default hover delay * 150ms default hover delay
* Fixed empty application list bug * Fixed empty application list bug
* Fixed mouse grab issue * Fixed mouse grab issue
* Highlights newly installed applications
-- Clement Lefebvre <root@linuxmint.com> Mon, 13 Sep 2010 12:09:00 +0000 -- Clement Lefebvre <root@linuxmint.com> Mon, 13 Sep 2010 12:09:00 +0000

View File

@ -222,7 +222,6 @@ class pluginclass( object ):
@print_timing @print_timing
def __init__( self, mintMenuWin, toggleButton ): def __init__( self, mintMenuWin, toggleButton ):
os.system("echo `date` > /var/tmp/mintmenu.log")
self.apt_cache = None self.apt_cache = None
try: try:
self.apt_cache = apt.Cache() self.apt_cache = apt.Cache()
@ -587,7 +586,6 @@ class pluginclass( object ):
self.searchEntry.select_region( sel[0], sel[1] ) self.searchEntry.select_region( sel[0], sel[1] )
def buildButtonList( self ): def buildButtonList( self ):
os.system("echo buildButtonList >> /var/tmp/mintmenu.log")
if self.buildingButtonList: if self.buildingButtonList:
self.stopBuildingButtonList = True self.stopBuildingButtonList = True
gobject.timeout_add( 100, self.buildButtonList ) gobject.timeout_add( 100, self.buildButtonList )
@ -595,7 +593,7 @@ class pluginclass( object ):
self.stopBuildingButtonList = False self.stopBuildingButtonList = False
self.updateBoxes() self.updateBoxes(False)
def categoryBtnFocus( self, widget, event, category ): def categoryBtnFocus( self, widget, event, category ):
self.scrollItemIntoView( widget ) self.scrollItemIntoView( widget )
@ -1556,34 +1554,28 @@ class pluginclass( object ):
if self.menuChangedTimer: if self.menuChangedTimer:
gobject.source_remove( self.menuChangedTimer ) gobject.source_remove( self.menuChangedTimer )
self.menuChangedTimer = gobject.timeout_add( 100, self.updateBoxes ) self.menuChangedTimer = gobject.timeout_add( 100, self.updateBoxes, True )
def updateBoxes( self ): def updateBoxes( self, menu_has_changed ):
os.system("echo updateboxes >> /var/tmp/mintmenu.log")
# FIXME: This is really bad! # FIXME: This is really bad!
if self.rebuildLock: if self.rebuildLock:
os.system("echo rebuildLock >> /var/tmp/mintmenu.log")
return return
self.rebuildLock = True self.rebuildLock = True
self.menuChangedTimer = None self.menuChangedTimer = None
os.system("echo step1 >> /var/tmp/mintmenu.log")
self.loadMenuFiles() self.loadMenuFiles()
os.system("echo step2 >> /var/tmp/mintmenu.log")
# Find added and removed categories than update the category list # Find added and removed categories than update the category list
newCategoryList = self.buildCategoryList() newCategoryList = self.buildCategoryList()
os.system("echo \"%d categories\" >> /var/tmp/mintmenu.log" % len(newCategoryList))
addedCategories = [] addedCategories = []
removedCategories = [] removedCategories = []
# TODO: optimize this!!! # TODO: optimize this!!!
if not self.categoryList: if not self.categoryList:
os.system("echo a >> /var/tmp/mintmenu.log")
addedCategories = newCategoryList addedCategories = newCategoryList
else: else:
os.system("echo b >> /var/tmp/mintmenu.log")
for item in newCategoryList: for item in newCategoryList:
found = False found = False
for item2 in self.categoryList: for item2 in self.categoryList:
@ -1611,17 +1603,12 @@ class pluginclass( object ):
else: else:
categoryIconSize = 0 categoryIconSize = 0
os.system("echo c >> /var/tmp/mintmenu.log")
for key in removedCategories: for key in removedCategories:
self.categoryList[key]["button"].destroy() self.categoryList[key]["button"].destroy()
del self.categoryList[key] del self.categoryList[key]
os.system("echo d >> /var/tmp/mintmenu.log")
if addedCategories: if addedCategories:
sortedCategoryList = [] sortedCategoryList = []
os.system("echo e >> /var/tmp/mintmenu.log")
for item in self.categoryList: for item in self.categoryList:
self.categoriesBox.remove( item["button"] ) self.categoriesBox.remove( item["button"] )
sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) ) sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) )
@ -1642,10 +1629,8 @@ class pluginclass( object ):
self.categoryList.append( item ) self.categoryList.append( item )
sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) ) sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) )
os.system("echo f >> /var/tmp/mintmenu.log")
sortedCategoryList.sort() sortedCategoryList.sort()
os.system("echo g >> /var/tmp/mintmenu.log")
for item in sortedCategoryList: for item in sortedCategoryList:
self.categoriesBox.pack_start( item[1], False ) self.categoriesBox.pack_start( item[1], False )
@ -1655,13 +1640,10 @@ class pluginclass( object ):
addedApplications = [] addedApplications = []
removedApplications = [] removedApplications = []
os.system("echo h >> /var/tmp/mintmenu.log")
# TODO: optimize this!!! # TODO: optimize this!!!
if not self.applicationList: if not self.applicationList:
os.system("echo i >> /var/tmp/mintmenu.log")
addedApplications = newApplicationList addedApplications = newApplicationList
else: else:
os.system("echo j >> /var/tmp/mintmenu.log")
for item in newApplicationList: for item in newApplicationList:
found = False found = False
for item2 in self.applicationList: for item2 in self.applicationList:
@ -1685,25 +1667,22 @@ class pluginclass( object ):
# because when it is removed the index of all later items is # because when it is removed the index of all later items is
# going to be decreased # going to be decreased
key += 1 key += 1
os.system("echo k >> /var/tmp/mintmenu.log")
for key in removedApplications: for key in removedApplications:
self.applicationList[key]["button"].destroy() self.applicationList[key]["button"].destroy()
del self.applicationList[key] del self.applicationList[key]
os.system("echo l >> /var/tmp/mintmenu.log")
if addedApplications: if addedApplications:
sortedApplicationList = [] sortedApplicationList = []
for item in self.applicationList: for item in self.applicationList:
self.applicationsBox.remove( item["button"] ) self.applicationsBox.remove( item["button"] )
sortedApplicationList.append( ( item["button"].appName, item["button"] ) ) sortedApplicationList.append( ( item["button"].appName, item["button"] ) )
os.system("echo \"%d added apps\" >> /var/tmp/mintmenu.log" % len(addedApplications))
for item in addedApplications: for item in addedApplications:
item["button"] = MenuApplicationLauncher( item["entry"].get_desktop_file_path(), self.iconSize, item["category"], self.showapplicationcomments ) item["button"] = MenuApplicationLauncher( item["entry"].get_desktop_file_path(), self.iconSize, item["category"], self.showapplicationcomments, highlight=(True and menu_has_changed) )
if item["button"].appExec: if item["button"].appExec:
self.mintMenuWin.setTooltip( item["button"], item["button"].getTooltip() ) self.mintMenuWin.setTooltip( item["button"], item["button"].getTooltip() )
item["button"].connect( "button-release-event", self.menuPopup ) item["button"].connect( "button-release-event", self.menuPopup )
item["button"].connect( "focus-in-event", self.scrollItemIntoView ) item["button"].connect( "focus-in-event", self.scrollItemIntoView )
item["button"].connect( "clicked", lambda w: self.mintMenuWin.hide() ) item["button"].connect( "clicked", lambda w: self.mintMenuWin.hide() )
os.system("echo \"%s '%s' filter\" >> /var/tmp/mintmenu.log" % (self.activeFilter[0], self.activeFilter[1]))
if self.activeFilter[0] == 0: if self.activeFilter[0] == 0:
item["button"].filterText( self.activeFilter[1] ) item["button"].filterText( self.activeFilter[1] )
else: else:
@ -1715,13 +1694,10 @@ class pluginclass( object ):
sortedApplicationList.sort() sortedApplicationList.sort()
os.system("echo \"%d apps\" >> /var/tmp/mintmenu.log" % len(sortedApplicationList))
for item in sortedApplicationList: for item in sortedApplicationList:
self.applicationsBox.pack_start( item[1], False ) self.applicationsBox.pack_start( item[1], False )
self.rebuildLock = False self.rebuildLock = False
os.system("echo fin >> /var/tmp/mintmenu.log")
# Reload the menufiles from the filesystem # Reload the menufiles from the filesystem
def loadMenuFiles( self ): def loadMenuFiles( self ):

View File

@ -12,543 +12,569 @@ from execute import *
import xdg.DesktopEntry import xdg.DesktopEntry
import xdg.Menu import xdg.Menu
from filemonitor import monitor as filemonitor from filemonitor import monitor as filemonitor
import glib
class IconManager(gobject.GObject): class IconManager(gobject.GObject):
__gsignals__ = { __gsignals__ = {
"changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () ) "changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, () )
} }
def __init__( self ): def __init__( self ):
gobject.GObject.__init__( self ) gobject.GObject.__init__( self )
self.icons = { } self.icons = { }
self.count = 0 self.count = 0
# Some apps don't put a default icon in the default theme folder, so we will search all themes # Some apps don't put a default icon in the default theme folder, so we will search all themes
def createTheme( d ): def createTheme( d ):
theme = gtk.IconTheme() theme = gtk.IconTheme()
theme.set_custom_theme( d ) theme.set_custom_theme( d )
return theme return theme
# This takes to much time and there are only a very few applications that use icons from different themes # 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.themes = map( createTheme, [ d for d in os.listdir( "/usr/share/icons" ) if os.path.isdir( os.path.join( "/usr/share/icons", d ) ) ] )
defaultTheme = gtk.icon_theme_get_default() defaultTheme = gtk.icon_theme_get_default()
defaultKdeTheme = createTheme( "kde.default" ) defaultKdeTheme = createTheme( "kde.default" )
# Themes with the same content as the default them aren't needed # 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 = [ theme for theme in self.themes if theme.list_icons() != defaultTheme.list_icons() ]
self.themes = [ defaultTheme, defaultKdeTheme ] self.themes = [ defaultTheme, defaultKdeTheme ]
self.cache = {} self.cache = {}
# Listen for changes in the themes # Listen for changes in the themes
for theme in self.themes: for theme in self.themes:
theme.connect("changed", self.themeChanged ) theme.connect("changed", self.themeChanged )
def getIcon( self, iconName, iconSize ): def getIcon( self, iconName, iconSize ):
if not iconName: if not iconName:
return None return None
try: try:
[ iconWidth, iconHeight ] = self.getIconSize( iconSize ) [ iconWidth, iconHeight ] = self.getIconSize( iconSize )
if iconWidth <= 0 or iconHeight <= 0: if iconWidth <= 0 or iconHeight <= 0:
return None return None
if iconName in self.cache and iconSize in self.cache[iconName]: if iconName in self.cache and iconSize in self.cache[iconName]:
iconFileName = self.cache[iconName][iconSize] iconFileName = self.cache[iconName][iconSize]
elif os.path.isabs( iconName ): elif os.path.isabs( iconName ):
iconFileName = iconName iconFileName = iconName
else: else:
if iconName[-4:] in [".png", ".xpm", ".svg", ".gif"]: if iconName[-4:] in [".png", ".xpm", ".svg", ".gif"]:
realIconName = iconName[:-4] realIconName = iconName[:-4]
else: else:
realIconName = iconName realIconName = iconName
tmp = None tmp = None
for theme in self.themes: for theme in self.themes:
if theme.has_icon( realIconName ): if theme.has_icon( realIconName ):
tmp = theme.lookup_icon( realIconName, iconWidth, 0 ) tmp = theme.lookup_icon( realIconName, iconWidth, 0 )
if tmp: if tmp:
break break
if tmp: if tmp:
iconFileName = tmp.get_filename() iconFileName = tmp.get_filename()
else: else:
iconFileName = "" iconFileName = ""
if iconFileName and os.path.exists( iconFileName ): if iconFileName and os.path.exists( iconFileName ):
icon = gtk.gdk.pixbuf_new_from_file_at_size( iconFileName, iconWidth, iconHeight ) icon = gtk.gdk.pixbuf_new_from_file_at_size( iconFileName, iconWidth, iconHeight )
else: else:
icon = None icon = None
# if the actual icon size is to far from the desired size resize it # if the actual icon size is to far from the desired size resize it
if icon and (( icon.get_width() - iconWidth ) > 5 or ( icon.get_height() - iconHeight ) > 5): if icon and (( icon.get_width() - iconWidth ) > 5 or ( icon.get_height() - iconHeight ) > 5):
if icon.get_width() > icon.get_height(): if icon.get_width() > icon.get_height():
newIcon = icon.scale_simple( iconWidth, icon.get_height() * iconWidth / icon.get_width(), gtk.gdk.INTERP_BILINEAR ) newIcon = icon.scale_simple( iconWidth, icon.get_height() * iconWidth / icon.get_width(), gtk.gdk.INTERP_BILINEAR )
else: else:
newIcon = icon.scale_simple( icon.get_width() * iconHeight / icon.get_height(), iconWidth, gtk.gdk.INTERP_BILINEAR ) newIcon = icon.scale_simple( icon.get_width() * iconHeight / icon.get_height(), iconWidth, gtk.gdk.INTERP_BILINEAR )
del icon del icon
icon = newIcon icon = newIcon
if iconName in self.cache: if iconName in self.cache:
self.cache[iconName][iconSize] = iconFileName self.cache[iconName][iconSize] = iconFileName
else: else:
self.cache[iconName] = { iconSize : iconFileName } self.cache[iconName] = { iconSize : iconFileName }
return icon return icon
except Exception, e: except Exception, e:
print "Excpetion " + e.__class__.__name__ + ": " + e.message print "Exception " + e.__class__.__name__ + ": " + e.message
return None return None
def getIconSize( self, iconSize ): def getIconSize( self, iconSize ):
if isinstance(iconSize, int): if isinstance(iconSize, int):
if iconSize >= 4: if iconSize >= 4:
iconSize = gtk.ICON_SIZE_DIALOG iconSize = gtk.ICON_SIZE_DIALOG
elif iconSize == 3: elif iconSize == 3:
iconSize = gtk.ICON_SIZE_DND iconSize = gtk.ICON_SIZE_DND
elif iconSize == 2: elif iconSize == 2:
iconSize = gtk.ICON_SIZE_BUTTON iconSize = gtk.ICON_SIZE_BUTTON
elif iconSize == 1: elif iconSize == 1:
iconSize = gtk.ICON_SIZE_MENU iconSize = gtk.ICON_SIZE_MENU
elif iconSize <= 0: elif iconSize <= 0:
return ( 0, 0 ) return ( 0, 0 )
return gtk.icon_size_lookup( iconSize ) return gtk.icon_size_lookup( iconSize )
def themeChanged( self, theme ): def themeChanged( self, theme ):
self.cache = { } self.cache = { }
self.emit( "changed" ) self.emit( "changed" )
gobject.type_register(IconManager) gobject.type_register(IconManager)
class easyButton( gtk.Button ): class easyButton( gtk.Button ):
def __init__( self, iconName, iconSize, labels = None, buttonWidth = -1, buttonHeight = -1 ): def __init__( self, iconName, iconSize, labels = None, buttonWidth = -1, buttonHeight = -1 ):
gtk.Button.__init__( self ) gtk.Button.__init__( self )
self.connections = [ ] self.connections = [ ]
self.iconName = iconName self.iconName = iconName
self.iconSize = iconSize self.iconSize = iconSize
self.showIcon = True self.showIcon = True
self.set_relief( gtk.RELIEF_NONE ) self.set_relief( gtk.RELIEF_NONE )
self.set_size_request( buttonWidth, buttonHeight ) self.set_size_request( buttonWidth, buttonHeight )
Align1 = gtk.Alignment( 0, 0.5, 1.0, 0 ) Align1 = gtk.Alignment( 0, 0.5, 1.0, 0 )
HBox1 = gtk.HBox() HBox1 = gtk.HBox()
self.labelBox = gtk.VBox( False, 2 ) self.labelBox = gtk.VBox( False, 2 )
self.buttonImage = gtk.Image() self.buttonImage = gtk.Image()
icon = self.getIcon( self.iconSize ) icon = self.getIcon( self.iconSize )
if icon: if icon:
self.buttonImage.set_from_pixbuf( icon ) self.buttonImage.set_from_pixbuf( icon )
del icon del icon
else: else:
[ iW, iH ] = iconManager.getIconSize( self.iconSize ) [ iW, iH ] = iconManager.getIconSize( self.iconSize )
self.buttonImage.set_size_request( iW, iH ) self.buttonImage.set_size_request( iW, iH )
self.buttonImage.show() self.buttonImage.show()
HBox1.pack_start( self.buttonImage, False, False, 5 ) HBox1.pack_start( self.buttonImage, False, False, 5 )
if labels:
for label in labels:
if isinstance( label, basestring ):
self.addLabel( label )
elif isinstance( label, list ):
self.addLabel( label[0], label[1] )
self.labelBox.show()
HBox1.pack_start( self.labelBox )
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.set_state(gtk.STATE_NORMAL)
def onDestroy( self, widget ):
self.buttonImage.clear()
iconManager.disconnect( self.themeChangedHandlerId )
for connection in self.connections:
self.disconnect( connection )
del self.connections
if labels: def addLabel( self, text, styles = None ):
for label in labels: label = gtk.Label()
if isinstance( label, basestring ): if "<b>" in text:
self.addLabel( label ) label.set_markup(text) # don't remove our pango
elif isinstance( label, list ): else:
self.addLabel( label[0], label[1] ) label.set_markup(glib.markup_escape_text(text))
self.labelBox.show() if styles:
HBox1.pack_start( self.labelBox ) labelStyle = pango.AttrList()
HBox1.show() for attr in styles:
Align1.add( HBox1 ) labelStyle.insert( attr )
Align1.show() label.set_attributes( labelStyle )
self.add( Align1 )
self.connectSelf( "destroy", self.onDestroy ) label.set_ellipsize( pango.ELLIPSIZE_END )
self.connect( "released", self.onRelease ) label.set_alignment( 0.0, 1.0 )
# Reload icons when the theme changed label.show()
self.themeChangedHandlerId = iconManager.connect("changed", self.themeChanged ) self.labelBox.pack_start( label )
def connectSelf( self, event, callback ):
self.connections.append( self.connect( event, callback ) )
def onRelease( self, widget ):
widget.set_state(gtk.STATE_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 ): def getIcon ( self, iconSize ):
label = gtk.Label( text ) if not self.iconName:
return None
if styles: icon = iconManager.getIcon( self.iconName, iconSize )
labelStyle = pango.AttrList() if not icon:
for attr in styles: icon = iconManager.getIcon( "application-default-icon", iconSize )
labelStyle.insert( attr )
label.set_attributes( labelStyle )
label.set_ellipsize( pango.ELLIPSIZE_END ) return icon
label.set_alignment( 0.0, 1.0 )
label.show()
self.labelBox.pack_start( label )
def setIcon ( self, iconName ):
self.iconName = iconName
self.iconChanged()
def getIcon ( self, iconSize ): # IconTheme changed, setup new button icons
if not self.iconName: def themeChanged( self, theme ):
return None self.iconChanged()
icon = iconManager.getIcon( self.iconName, iconSize ) def iconChanged( self ):
if not icon: icon = self.getIcon( self.iconSize )
icon = iconManager.getIcon( "application-default-icon", iconSize ) self.buttonImage.clear()
if icon:
self.buttonImage.set_from_pixbuf( icon )
self.buttonImage.set_size_request( -1, -1 )
del icon
else:
[iW, iH ] = iconManager.getIconSize( self.iconSize )
self.buttonImage.set_size_request( iW, iH )
return icon def setIconSize( self, size ):
self.iconSize = size
def setIcon ( self, iconName ): icon = self.getIcon( self.iconSize )
self.iconName = iconName self.buttonImage.clear()
self.iconChanged() if icon:
self.buttonImage.set_from_pixbuf( icon )
# IconTheme changed, setup new button icons self.buttonImage.set_size_request( -1, -1 )
def themeChanged( self, theme ): del icon
self.iconChanged() elif self.iconSize:
[ iW, iH ] = iconManager.getIconSize( self.iconSize )
def iconChanged( self ): self.buttonImage.set_size_request( iW, iH )
icon = self.getIcon( self.iconSize )
self.buttonImage.clear()
if icon:
self.buttonImage.set_from_pixbuf( icon )
self.buttonImage.set_size_request( -1, -1 )
del icon
else:
[iW, iH ] = iconManager.getIconSize( self.iconSize )
self.buttonImage.set_size_request( iW, iH )
def setIconSize( self, size ):
self.iconSize = size
icon = self.getIcon( self.iconSize )
self.buttonImage.clear()
if icon:
self.buttonImage.set_from_pixbuf( icon )
self.buttonImage.set_size_request( -1, -1 )
del icon
elif self.iconSize:
[ iW, iH ] = iconManager.getIconSize( self.iconSize )
self.buttonImage.set_size_request( iW, iH )
class ApplicationLauncher( easyButton ): class ApplicationLauncher( easyButton ):
def __init__( self, desktopFile, iconSize ): def __init__( self, desktopFile, iconSize):
if isinstance( desktopFile, xdg.Menu.MenuEntry ): if isinstance( desktopFile, xdg.Menu.MenuEntry ):
desktopItem = desktopFile.DesktopEntry desktopItem = desktopFile.DesktopEntry
desktopFile = desktopItem.filename desktopFile = desktopItem.filename
self.appDirs = desktop.desktopFile.AppDirs self.appDirs = desktop.desktopFile.AppDirs
elif isinstance( desktopFile, xdg.Menu.DesktopEntry ): elif isinstance( desktopFile, xdg.Menu.DesktopEntry ):
desktopItem = desktopFile desktopItem = desktopFile
desktopFile = desktopItem.filename desktopFile = desktopItem.filename
self.appDirs = [ os.path.dirname( desktopItem.filename ) ] self.appDirs = [ os.path.dirname( desktopItem.filename ) ]
else: else:
desktopItem = xdg.DesktopEntry.DesktopEntry( desktopFile ) desktopItem = xdg.DesktopEntry.DesktopEntry( desktopFile )
self.appDirs = [ os.path.dirname( desktopFile ) ] self.appDirs = [ os.path.dirname( desktopFile ) ]
self.desktopFile = desktopFile self.desktopFile = desktopFile
self.startupMonitorId = 0 self.startupMonitorId = 0
self.loadDesktopEntry( desktopItem ) self.loadDesktopEntry( desktopItem )
self.desktopEntryMonitors = [] self.desktopEntryMonitors = []
base = os.path.basename( self.desktopFile ) base = os.path.basename( self.desktopFile )
for dir in self.appDirs: for dir in self.appDirs:
self.desktopEntryMonitors.append( filemonitor.addMonitor( os.path.join(dir, base) , self.onDesktopEntryFileChanged ) ) self.desktopEntryMonitors.append( filemonitor.addMonitor( os.path.join(dir, base) , self.onDesktopEntryFileChanged ) )
easyButton.__init__( self, self.appIconName, iconSize ) easyButton.__init__( self, self.appIconName, iconSize )
self.setupLabels() self.setupLabels()
# Drag and Drop # Drag and Drop
self.connectSelf( "drag_data_get", self.dragDataGet ) self.connectSelf( "drag_data_get", self.dragDataGet )
self.drag_source_set( gtk.gdk.BUTTON1_MASK , [ ( "text/plain", 0, 100 ), ( "text/uri-list", 0, 101 ) ], gtk.gdk.ACTION_COPY ) self.drag_source_set( gtk.gdk.BUTTON1_MASK , [ ( "text/plain", 0, 100 ), ( "text/uri-list", 0, 101 ) ], gtk.gdk.ACTION_COPY )
icon = self.getIcon( gtk.ICON_SIZE_DND ) icon = self.getIcon( gtk.ICON_SIZE_DND )
if icon: if icon:
self.drag_source_set_icon_pixbuf( icon ) self.drag_source_set_icon_pixbuf( icon )
del icon del icon
self.connectSelf( "focus-in-event", self.onFocusIn ) self.connectSelf( "focus-in-event", self.onFocusIn )
self.connectSelf( "focus-out-event", self.onFocusOut ) self.connectSelf( "focus-out-event", self.onFocusOut )
self.connectSelf( "enter-notify-event", self.onEnterNotify ) self.connectSelf( "enter-notify-event", self.onEnterNotify )
self.connectSelf( "clicked", self.execute ) self.connectSelf( "clicked", self.execute )
def loadDesktopEntry( self, desktopItem ): def loadDesktopEntry( self, desktopItem ):
try: try:
self.appName = desktopItem.getName() self.appName = desktopItem.getName()
self.appGenericName = desktopItem.getGenericName() self.appGenericName = desktopItem.getGenericName()
self.appComment = desktopItem.getComment() self.appComment = desktopItem.getComment()
self.appExec = desktopItem.getExec() self.appExec = desktopItem.getExec()
self.appIconName = desktopItem.getIcon() self.appIconName = desktopItem.getIcon()
self.appCategories = desktopItem.getCategories() self.appCategories = desktopItem.getCategories()
self.appGnomeDocPath = desktopItem.get( "X-GNOME-DocPath" ) or "" self.appGnomeDocPath = desktopItem.get( "X-GNOME-DocPath" ) or ""
self.useTerminal = desktopItem.getTerminal() self.useTerminal = desktopItem.getTerminal()
if not self.appGnomeDocPath: if not self.appGnomeDocPath:
self.appKdeDocPath = desktopItem.getDocPath() or "" self.appKdeDocPath = desktopItem.getDocPath() or ""
self.appName = self.appName.strip() self.appName = self.appName.strip()
self.appGenericName = self.appGenericName.strip() self.appGenericName = self.appGenericName.strip()
self.appComment = self.appComment.strip() self.appComment = self.appComment.strip()
basename = os.path.basename( self.desktopFile ) basename = os.path.basename( self.desktopFile )
self.startupFilePath = os.path.join( os.path.expanduser("~"), ".config", "autostart", basename ) self.startupFilePath = os.path.join( os.path.expanduser("~"), ".config", "autostart", basename )
if self.startupMonitorId: if self.startupMonitorId:
filemonitor.removeMonitor( self.startupMonitorId ) filemonitor.removeMonitor( self.startupMonitorId )
self.startupMonitorId = filemonitor.addMonitor( self.startupFilePath, self.startupFileChanged ) self.startupMonitorId = filemonitor.addMonitor( self.startupFilePath, self.startupFileChanged )
#self.inStartup = os.path.exists( self.startupFilePath ) #self.inStartup = os.path.exists( self.startupFilePath )
except Exception, e: except Exception, e:
print e print e
self.appName = "" self.appName = ""
self.appGenericName = "" self.appGenericName = ""
self.appComment = "" self.appComment = ""
self.appExec = "" self.appExec = ""
self.appIconName = "" self.appIconName = ""
self.appCategories = "" self.appCategories = ""
self.appDocPath = "" self.appDocPath = ""
self.startupMonitorId = 0 self.startupMonitorId = 0
def onFocusIn( self, widget, event ): def onFocusIn( self, widget, event ):
self.set_relief( gtk.RELIEF_HALF ) self.set_relief( gtk.RELIEF_HALF )
def onFocusOut( self, widget, event ): def onFocusOut( self, widget, event ):
self.set_relief( gtk.RELIEF_NONE ) self.set_relief( gtk.RELIEF_NONE )
def onEnterNotify( self, widget, event ): def onEnterNotify( self, widget, event ):
self.grab_focus() self.grab_focus()
def setupLabels( self ): def setupLabels( self ):
self.addLabel( self.appName ) self.addLabel( self.appName )
def filterText( self, text ): def filterText( self, text ):
keywords = text.lower().split() keywords = text.lower().split()
appName = self.strip_accents(self.appName.lower()) appName = self.strip_accents(self.appName.lower())
appGenericName = self.strip_accents(self.appGenericName.lower()) appGenericName = self.strip_accents(self.appGenericName.lower())
appComment = self.strip_accents(self.appComment.lower()) appComment = self.strip_accents(self.appComment.lower())
appExec = self.strip_accents(self.appExec.lower()) appExec = self.strip_accents(self.appExec.lower())
for keyword in keywords: for keyword in keywords:
keyw = self.strip_accents(keyword) keyw = self.strip_accents(keyword)
if keyw != "" and appName.find( keyw ) == -1 and appGenericName.find( keyw ) == -1 and appComment.find( keyw ) == -1 and appExec.find( keyw ) == -1: if keyw != "" and appName.find( keyw ) == -1 and appGenericName.find( keyw ) == -1 and appComment.find( keyw ) == -1 and appExec.find( keyw ) == -1:
self.hide() self.hide()
return False return False
self.show() self.show()
return True return True
def strip_accents(self, string): def strip_accents(self, string):
import unicodedata import unicodedata
return unicodedata.normalize('NFKD', unicode(string)).encode('ASCII', 'ignore') return unicodedata.normalize('NFKD', unicode(string)).encode('ASCII', 'ignore')
def getTooltip( self ): def getTooltip( self ):
tooltip = self.appName tooltip = self.appName
if self.appComment != "" and self.appComment != self.appName: if self.appComment != "" and self.appComment != self.appName:
tooltip = tooltip + "\n" + self.appComment tooltip = tooltip + "\n" + self.appComment
return tooltip return tooltip
def dragDataGet( self, widget, context, selection, targetType, eventTime ): def dragDataGet( self, widget, context, selection, targetType, eventTime ):
if targetType == 100: # text/plain if targetType == 100: # text/plain
selection.set_text( "'" + self.desktopFile + "'", -1 ) selection.set_text( "'" + self.desktopFile + "'", -1 )
elif targetType == 101: # text/uri-list elif targetType == 101: # text/uri-list
if self.desktopFile[0:7] == "file://": if self.desktopFile[0:7] == "file://":
selection.set_uris( [ self.desktopFile ] ) selection.set_uris( [ self.desktopFile ] )
else: else:
selection.set_uris( [ "file://" + self.desktopFile ] ) selection.set_uris( [ "file://" + self.desktopFile ] )
def execute( self, *args ): def execute( self, *args ):
if self.appExec: if self.appExec:
if self.useTerminal: if self.useTerminal:
cmd = "x-terminal-emulator -e \"" + self.appExec + "\"" cmd = "x-terminal-emulator -e \"" + self.appExec + "\""
Execute(cmd) Execute(cmd)
else: else:
Execute(self.appExec) Execute(self.appExec)
def uninstall (self, *args ): def uninstall (self, *args ):
Execute("gksu /usr/lib/linuxmint/mintMenu/mintRemove.py " + self.desktopFile) Execute("gksu /usr/lib/linuxmint/mintMenu/mintRemove.py " + self.desktopFile)
# IconTheme changed, setup new icons for button and drag 'n drop # IconTheme changed, setup new icons for button and drag 'n drop
def iconChanged( self ): def iconChanged( self ):
easyButton.iconChanged( self ) easyButton.iconChanged( self )
icon = self.getIcon( gtk.ICON_SIZE_DND ) icon = self.getIcon( gtk.ICON_SIZE_DND )
if icon: if icon:
self.drag_source_set_icon_pixbuf( icon ) self.drag_source_set_icon_pixbuf( icon )
del icon del icon
def startupFileChanged( self, *args ): def startupFileChanged( self, *args ):
self.inStartup = os.path.exists( self.startupFilePath ) self.inStartup = os.path.exists( self.startupFilePath )
def addToStartup( self ): def addToStartup( self ):
startupDir = os.path.join( os.path.expanduser("~"), ".config", "autostart" ); startupDir = os.path.join( os.path.expanduser("~"), ".config", "autostart" );
if not os.path.exists( startupDir ): if not os.path.exists( startupDir ):
os.makedirs( startupDir ) os.makedirs( startupDir )
shutil.copyfile( self.desktopFile, self.startupFilePath ) shutil.copyfile( self.desktopFile, self.startupFilePath )
# Remove %u, etc. from Exec entry, because gnome will not replace them when it starts the app # Remove %u, etc. from Exec entry, because gnome will not replace them when it starts the app
item = gnomedesktop.item_new_from_uri( self.startupFilePath, gnomedesktop.LOAD_ONLY_IF_EXISTS ) item = gnomedesktop.item_new_from_uri( self.startupFilePath, gnomedesktop.LOAD_ONLY_IF_EXISTS )
if item: if item:
r = re.compile("%[A-Za-z]"); r = re.compile("%[A-Za-z]");
tmp = r.sub("", item.get_string( gnomedesktop.KEY_EXEC ) ).strip() tmp = r.sub("", item.get_string( gnomedesktop.KEY_EXEC ) ).strip()
item.set_string( gnomedesktop.KEY_EXEC, tmp ) item.set_string( gnomedesktop.KEY_EXEC, tmp )
item.save( self.startupFilePath, 0 ) item.save( self.startupFilePath, 0 )
def removeFromStartup( self ): def removeFromStartup( self ):
if os.path.exists( self.startupFilePath ): if os.path.exists( self.startupFilePath ):
os.remove( self.startupFilePath ) os.remove( self.startupFilePath )
def addToFavourites( self ): def addToFavourites( self ):
favouritesDir = os.path.join( os.path.expanduser("~"), ".linuxmint", "mintMenu", "applications" ); favouritesDir = os.path.join( os.path.expanduser("~"), ".linuxmint", "mintMenu", "applications" );
if not os.path.exists( favouritesDir ): if not os.path.exists( favouritesDir ):
os.makedirs( favouritesDir ) os.makedirs( favouritesDir )
shutil.copyfile( self.desktopFile, self.favouritesFilePath ) shutil.copyfile( self.desktopFile, self.favouritesFilePath )
def removeFromFavourites( self ): def removeFromFavourites( self ):
if os.path.exists( self.favouritesFilePath ): if os.path.exists( self.favouritesFilePath ):
os.remove( self.favouritesFilePath ) os.remove( self.favouritesFilePath )
def isInStartup( self ): def isInStartup( self ):
#return self.inStartup #return self.inStartup
return os.path.exists( self.startupFilePath ) return os.path.exists( self.startupFilePath )
def hasHelp( self ): def hasHelp( self ):
return self.appGnomeDocPath or self.appKdeDocPath return self.appGnomeDocPath or self.appKdeDocPath
def launchHelp( self ): def launchHelp( self ):
if self.appGnomeDocPath: if self.appGnomeDocPath:
bn = os.path.basename( self.appGnomeDocPath ) bn = os.path.basename( self.appGnomeDocPath )
dn = os.path.dirname( self.appGnomeDocPath ) dn = os.path.dirname( self.appGnomeDocPath )
if self.appGnomeDocPath[0:6] != "ghelp:": if self.appGnomeDocPath[0:6] != "ghelp:":
self.appGnomeDocPath = "ghelp:" + self.appGnomeDocPath self.appGnomeDocPath = "ghelp:" + self.appGnomeDocPath
gnomevfs.url_show( self.appGnomeDocPath ) gnomevfs.url_show( self.appGnomeDocPath )
elif self.appKdeDocPath: elif self.appKdeDocPath:
if self.appKdeDocPath[0:6] != "help:/" and self.appKdeDocPath[0:6] != "file:/": if self.appKdeDocPath[0:6] != "help:/" and self.appKdeDocPath[0:6] != "file:/":
self.appKdeDocPath = "help:/" + self.appKdeDocPath self.appKdeDocPath = "help:/" + self.appKdeDocPath
if self.appKdeDocPath[0:6] == "file:/": if self.appKdeDocPath[0:6] == "file:/":
gnomevfs.url_show( self.appKdeDocPath ) gnomevfs.url_show( self.appKdeDocPath )
else: else:
Execute( [ "khelpcenter", self.appKdeDocPath ] ) Execute( [ "khelpcenter", self.appKdeDocPath ] )
def onDestroy( self, widget ): def onDestroy( self, widget ):
easyButton.onDestroy( self, widget ) easyButton.onDestroy( self, widget )
if self.startupMonitorId: if self.startupMonitorId:
filemonitor.removeMonitor( self.startupMonitorId ) filemonitor.removeMonitor( self.startupMonitorId )
for id in self.desktopEntryMonitors: for id in self.desktopEntryMonitors:
filemonitor.removeMonitor( id ) filemonitor.removeMonitor( id )
def onDesktopEntryFileChanged( self ): def onDesktopEntryFileChanged( self ):
exists = False exists = False
base = os.path.basename( self.desktopFile ) base = os.path.basename( self.desktopFile )
for dir in self.appDirs: for dir in self.appDirs:
if os.path.exists( os.path.join( dir, base ) ): if os.path.exists( os.path.join( dir, base ) ):
print os.path.join( dir, base ), self.desktopFile print os.path.join( dir, base ), self.desktopFile
self.loadDesktopEntry( xdg.DesktopEntry.DesktopEntry( os.path.join( dir, base ) ) ) self.loadDesktopEntry( xdg.DesktopEntry.DesktopEntry( os.path.join( dir, base ) ) )
for child in self.labelBox: for child in self.labelBox:
child.destroy() child.destroy()
self.iconName = self.appIconName self.iconName = self.appIconName
self.setupLabels() self.setupLabels()
self.iconChanged() self.iconChanged()
exists = True exists = True
break break
if not exists: if not exists:
# FIXME: What to do in this case? # FIXME: What to do in this case?
self.destroy() self.destroy()
class MenuApplicationLauncher( ApplicationLauncher ): class MenuApplicationLauncher( ApplicationLauncher ):
def __init__( self, desktopFile, iconSize, category, showComment ): def __init__( self, desktopFile, iconSize, category, showComment, highlight=False ):
self.showComment = showComment self.showComment = showComment
self.appCategory = category self.appCategory = category
self.highlight = highlight
ApplicationLauncher.__init__( self, desktopFile, iconSize ) ApplicationLauncher.__init__( self, desktopFile, iconSize )
def filterCategory( self, category ): def filterCategory( self, category ):
if self.appCategory == category or category == "": if self.appCategory == category or category == "":
self.show() self.show()
else: else:
self.hide() self.hide()
def setupLabels( self ): def setupLabels( self ):
if self.showComment and self.appComment != "": appName = self.appName
if self.iconSize <= 2: appComment = self.appComment
self.addLabel( self.appName, [ pango.AttrScale( pango.SCALE_SMALL, 0, -1 ) ] ) if self.highlight:
self.addLabel( self.appComment, [ pango.AttrScale( pango.SCALE_X_SMALL, 0, -1 ) ] ) try:
else: color = self.labelBox.rc_get_style().fg[ gtk.STATE_SELECTED ].to_string()
self.addLabel( self.appName ) if len(color) > 0 and color[0] == "#":
self.addLabel( self.appComment, [ pango.AttrScale( pango.SCALE_SMALL, 0, -1 ) ] ) appName = "<span foreground=\"%s\"><b>%s</b></span>" % (color, appName);
else: appComment = "<span foreground=\"%s\"><b>%s</b></span>" % (color, appComment);
self.addLabel( self.appName ) else:
appName = "<b>%s</b>" % (appName);
appComment = "<b>%s</b>" % (appComment);
except Exception, detail:
print detail
pass
def setShowComment( self, showComment ): if self.showComment and self.appComment != "":
self.showComment = showComment if self.iconSize <= 2:
for child in self.labelBox: self.addLabel( appName, [ pango.AttrScale( pango.SCALE_SMALL, 0, -1 ) ] )
child.destroy() self.addLabel( appComment, [ pango.AttrScale( pango.SCALE_X_SMALL, 0, -1 ) ] )
self.setupLabels() else:
self.addLabel( appName )
self.addLabel( appComment, [ pango.AttrScale( pango.SCALE_SMALL, 0, -1 ) ] )
else:
self.addLabel( appName )
def execute( self, *args ):
self.highlight = False
for child in self.labelBox:
child.destroy()
self.setupLabels()
return super(MenuApplicationLauncher, self).execute(*args)
def setShowComment( self, showComment ):
self.showComment = showComment
for child in self.labelBox:
child.destroy()
self.setupLabels()
class FavApplicationLauncher( ApplicationLauncher ): class FavApplicationLauncher( ApplicationLauncher ):
def __init__( self, desktopFile, iconSize, swapGeneric = False ): def __init__( self, desktopFile, iconSize, swapGeneric = False ):
self.swapGeneric = swapGeneric self.swapGeneric = swapGeneric
ApplicationLauncher.__init__( self, desktopFile, iconSize ) ApplicationLauncher.__init__( self, desktopFile, iconSize )
def setupLabels( self ): def setupLabels( self ):
if self.appGenericName: if self.appGenericName:
if self.swapGeneric: if self.swapGeneric:
self.addLabel( self.appName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] ) self.addLabel( self.appName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] )
self.addLabel( self.appGenericName ) self.addLabel( self.appGenericName )
else: else:
self.addLabel( self.appGenericName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] ) self.addLabel( self.appGenericName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] )
self.addLabel( self.appName ) self.addLabel( self.appName )
else: else:
if self.appComment != "": if self.appComment != "":
self.addLabel( self.appName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] ) self.addLabel( self.appName, [ pango.AttrWeight( pango.WEIGHT_BOLD, 0, -1 ) ] )
self.addLabel( self.appComment ) self.addLabel( self.appComment )
else: else:
self.addLabel( self.appName ) self.addLabel( self.appName )
def setSwapGeneric( self, swapGeneric ): def setSwapGeneric( self, swapGeneric ):
self.swapGeneric = swapGeneric self.swapGeneric = swapGeneric
for child in self.labelBox: for child in self.labelBox:
child.destroy() child.destroy()
self.setupLabels() self.setupLabels()
class CategoryButton( easyButton ): class CategoryButton( easyButton ):
def __init__( self, iconName, iconSize, labels , f ): def __init__( self, iconName, iconSize, labels , f ):
easyButton.__init__( self, iconName, iconSize, labels ) easyButton.__init__( self, iconName, iconSize, labels )
self.filter = f self.filter = f
iconManager = IconManager() iconManager = IconManager()