18a491a38c
Renamed "Edit" to "Prop" throughout to indicate Properties of the menu item Added code in to copy the .desktop file in the /usr directory structure to the user's local directory before editing properties Updated menuPopup function to include the new functionality as well
1275 lines
45 KiB
Python
Executable File
1275 lines
45 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import gtk
|
|
import gtk.glade
|
|
import gobject
|
|
import os
|
|
import gconf
|
|
import fnmatch
|
|
import time
|
|
import string
|
|
import gettext
|
|
import gnomevfs
|
|
import threading
|
|
import commands
|
|
|
|
from easybuttons import *
|
|
from execute import Execute
|
|
from easygconf import EasyGConf
|
|
from easyfiles import *
|
|
|
|
from filemonitor import monitor as filemonitor
|
|
|
|
#import xdg.Menu
|
|
import gmenu
|
|
|
|
# i18n
|
|
gettext.install("mintmenu", "/usr/share/linuxmint/locale")
|
|
|
|
# Evil patching
|
|
#def xdgParsePatched(filename=None):
|
|
# # conver to absolute path
|
|
# if filename and not os.path.isabs(filename):
|
|
# filename = xdg.Menu.__getFileName(filename)
|
|
#
|
|
# # use default if no filename given
|
|
# if not filename:
|
|
# filename = xdg.Menu.__getFileName("applications.menu")
|
|
#
|
|
# if not filename:
|
|
# raise xdg.Menu.ParsingError(_("File not found"), "/etc/xdg/menus/applications.menu")
|
|
#
|
|
# # check if it is a .menu file
|
|
# if not os.path.splitext(filename)[1] == ".menu":
|
|
# raise xdg.Menu.ParsingError(_("Not a .menu file"), filename)
|
|
#
|
|
# # create xml parser
|
|
# try:
|
|
# doc = xdg.Menu.xml.dom.minidom.parse(filename)
|
|
# except xdg.Menu.xml.parsers.expat.ExpatError:
|
|
# raise xdg.Menu.ParsingError(_("Not a valid .menu file"), filename)
|
|
#
|
|
# # parse menufile
|
|
# xdg.Menu.tmp["Root"] = ""
|
|
# xdg.Menu.tmp["mergeFiles"] = []
|
|
# xdg.Menu.tmp["DirectoryDirs"] = []
|
|
# xdg.Menu.tmp["cache"] = xdg.Menu.MenuEntryCache()
|
|
#
|
|
# xdg.Menu.__parse(doc, filename, xdg.Menu.tmp["Root"])
|
|
# xdg.Menu.__parsemove(xdg.Menu.tmp["Root"])
|
|
# xdg.Menu.__postparse(xdg.Menu.tmp["Root"])
|
|
#
|
|
# xdg.Menu.tmp["Root"].Doc = doc
|
|
# xdg.Menu.tmp["Root"].Filename = filename
|
|
#
|
|
# # generate the menu
|
|
# xdg.Menu.__genmenuNotOnlyAllocated(xdg.Menu.tmp["Root"])
|
|
# xdg.Menu.__genmenuOnlyAllocated(xdg.Menu.tmp["Root"])
|
|
#
|
|
# # and finally sort
|
|
# xdg.Menu.sort(xdg.Menu.tmp["Root"])
|
|
# xdg.Menu.tmp["Root"].Files = xdg.Menu.tmp["mergeFiles"] + [ xdg.Menu.tmp["Root"].Filename ]
|
|
# return xdg.Menu.tmp["Root"]
|
|
#
|
|
#xdg.Menu.parse = xdgParsePatched
|
|
|
|
# Helper function for retrieving the user's location for storing new or modified menu items
|
|
def getUserItemPath():
|
|
item_dir = None
|
|
|
|
if os.environ.has_key('XDG_DATA_HOME'):
|
|
item_dir = os.path.join(os.environ['XDG_DATA_HOME'], 'applications')
|
|
else:
|
|
item_dir = os.path.join(os.environ['HOME'], '.local', 'share', 'applications')
|
|
|
|
if not os.path.isdir(item_dir):
|
|
os.makedirs(item_dir)
|
|
|
|
return item_dir
|
|
|
|
class Menu:
|
|
def __init__( self, MenuToLookup ):
|
|
self.tree = gmenu.lookup_tree( MenuToLookup )
|
|
self.directory = self.tree.get_root_directory()
|
|
|
|
def getMenus( self, parent=None ):
|
|
if parent == None:
|
|
#gives top-level "Applications" item
|
|
yield self.tree.root
|
|
else:
|
|
for menu in parent.get_contents():
|
|
if menu.get_type() == gmenu.TYPE_DIRECTORY and self.__isVisible( menu ):
|
|
yield menu
|
|
|
|
def getItems( self, menu ):
|
|
for item in menu.get_contents():
|
|
if item.get_type() == gmenu.TYPE_ENTRY and item.get_desktop_file_id()[-19:] != '-usercustom.desktop' and self.__isVisible( item ):
|
|
yield item
|
|
|
|
def __isVisible( self, item ):
|
|
if item.get_type() == gmenu.TYPE_ENTRY:
|
|
return not ( item.get_is_excluded() or item.get_is_nodisplay() )
|
|
if item.get_type() == gmenu.TYPE_DIRECTORY and len( item.get_contents() ):
|
|
return True
|
|
|
|
|
|
|
|
class SuggestionButton ( gtk.Button ):
|
|
|
|
def __init__( self, iconName, iconSize, label ):
|
|
gtk.Button.__init__( self )
|
|
iconSize = self.get_icon_size(iconSize)
|
|
self.iconName = iconName
|
|
self.set_relief( gtk.RELIEF_NONE )
|
|
self.set_size_request( 10, 10 )
|
|
Align1 = gtk.Alignment( 0, 0.5, 1.0, 0 )
|
|
HBox1 = gtk.HBox()
|
|
labelBox = gtk.VBox( False, 2 )
|
|
self.image = gtk.Image()
|
|
self.image.set_from_stock( self.iconName, iconSize )
|
|
self.image.show()
|
|
HBox1.pack_start( self.image, False, False, 5 )
|
|
self.label = gtk.Label()
|
|
self.label.set_ellipsize( pango.ELLIPSIZE_END )
|
|
self.label.set_alignment( 0.0, 1.0 )
|
|
self.label.show()
|
|
labelBox.pack_start( self.label )
|
|
labelBox.show()
|
|
HBox1.pack_start( labelBox )
|
|
HBox1.show()
|
|
Align1.add( HBox1 )
|
|
Align1.show()
|
|
self.add( Align1 )
|
|
self.show()
|
|
|
|
def get_icon_size (self, iconSize):
|
|
if isinstance(iconSize, int):
|
|
if iconSize >= 4:
|
|
iconSize = gtk.ICON_SIZE_DIALOG
|
|
elif iconSize == 3:
|
|
iconSize = gtk.ICON_SIZE_DND
|
|
elif iconSize == 2:
|
|
iconSize = gtk.ICON_SIZE_BUTTON
|
|
elif iconSize == 1:
|
|
iconSize = gtk.ICON_SIZE_MENU
|
|
return iconSize
|
|
|
|
def set_text( self, text):
|
|
self.label.set_text(text)
|
|
|
|
def set_icon_size (self, size):
|
|
size = self.get_icon_size(size)
|
|
self.image.set_from_stock( self.iconName, size )
|
|
|
|
class pluginclass( object ):
|
|
TARGET_TYPE_TEXT = 80
|
|
toButton = [ ( "text/uri-list", 0, TARGET_TYPE_TEXT ) ]
|
|
TARGET_TYPE_FAV = 81
|
|
toFav = [ ( "FAVORITES", gtk.TARGET_SAME_APP, TARGET_TYPE_FAV ), ( "text/plain", 0, 100 ), ( "text/uri-list", 0, 101 ) ]
|
|
fromFav = [ ( "FAVORITES", gtk.TARGET_SAME_APP, TARGET_TYPE_FAV ) ]
|
|
|
|
def __init__( self, mintMenuWin, toggleButton ):
|
|
|
|
self.mintMenuWin = mintMenuWin
|
|
|
|
self.mainMenus = [ ]
|
|
|
|
self.toggleButton = toggleButton
|
|
# The Glade file for the plugin
|
|
self.gladefile = os.path.join( os.path.dirname( __file__ ), "applications.glade" )
|
|
|
|
# Read GLADE file
|
|
self.wTree = gtk.glade.XML( self.gladefile, "mainWindow" )
|
|
self.searchEntry = self.wTree.get_widget( "searchEntry" )
|
|
self.searchButton = self.wTree.get_widget( "searchButton" )
|
|
self.showAllAppsButton = self.wTree.get_widget( "showAllAppsButton" )
|
|
self.showFavoritesButton = self.wTree.get_widget( "showFavoritesButton" )
|
|
self.applicationsBox = self.wTree.get_widget( "applicationsBox" )
|
|
self.categoriesBox = self.wTree.get_widget( "categoriesBox" )
|
|
self.favoritesBox = self.wTree.get_widget( "favoritesBox" )
|
|
self.applicationsScrolledWindow = self.wTree.get_widget( "applicationsScrolledWindow" )
|
|
|
|
#i18n
|
|
self.wTree.get_widget("searchLabel").set_text("<span weight='bold'>" + _("Filter:") + "</span>")
|
|
self.wTree.get_widget("searchLabel").set_use_markup(True)
|
|
self.wTree.get_widget("label6").set_text("<span weight='bold'>" + _("Favorites") + "</span>")
|
|
self.wTree.get_widget("label6").set_use_markup(True)
|
|
self.wTree.get_widget("label7").set_text(_("All applications"))
|
|
self.wTree.get_widget("label2").set_text("<span weight='bold'>" + _("All applications") + "</span>")
|
|
self.wTree.get_widget("label2").set_use_markup(True)
|
|
self.wTree.get_widget("label3").set_text(_("Favorites"))
|
|
|
|
self.numApps = 0
|
|
# These properties are NECESSARY to maintain consistency
|
|
|
|
# Set 'window' property for the plugin (Must be the root widget)
|
|
self.window = self.wTree.get_widget( "mainWindow" )
|
|
|
|
# Set 'heading' property for plugin
|
|
self.heading = _("Applications")
|
|
|
|
# This should be the first item added to the window in glade
|
|
self.content_holder = self.wTree.get_widget( "Applications" )
|
|
|
|
# Items to get custom colors
|
|
self.itemstocolor = [ self.wTree.get_widget( "viewport1" ), self.wTree.get_widget( "viewport2" ), self.wTree.get_widget( "viewport3" ), self.wTree.get_widget( "notebook2" ) ]
|
|
|
|
# Unset all timers
|
|
self.filterTimer = None
|
|
self.menuChangedTimer = None
|
|
# Hookup for text input
|
|
self.content_holder.connect( "key-press-event", self.keyPress )
|
|
|
|
self.favoritesBox.connect( "drag_data_received", self.ReceiveCallback )
|
|
self.favoritesBox.drag_dest_set( gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, self.toButton, gtk.gdk.ACTION_COPY )
|
|
self.showFavoritesButton.connect( "drag_data_received", self.ReceiveCallback )
|
|
self.showFavoritesButton.drag_dest_set( gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, self.toButton, gtk.gdk.ACTION_COPY )
|
|
|
|
self.searchButton.connect( "button_release_event", self.SearchWithButton )
|
|
|
|
self.gconfHandlers = []
|
|
# Gconf stuff
|
|
self.gconf = EasyGConf( "/apps/mintMenu/plugins/applications/" )
|
|
self.GetGconfEntries()
|
|
self.gconf.notifyAdd( "icon_size", self.changeIconSize )
|
|
self.gconf.notifyAdd( "favicon_size", self.changeFavIconSize )
|
|
self.gconf.notifyAdd( "height", self.changePluginSize )
|
|
self.gconf.notifyAdd( "width", self.changePluginSize )
|
|
self.gconf.notifyAdd( "categories_mouse_over", self.changeCategoriesMouseOver )
|
|
self.gconf.notifyAdd( "swap_generic_name", self.changeSwapGenericName )
|
|
self.gconf.notifyAdd( "show_category_icons", self.changeShowCategoryIcons )
|
|
self.gconf.notifyAdd( "show_application_comments", self.changeShowApplicationComments )
|
|
self.gconf.notifyAdd( "fav_cols", self.changeFavCols )
|
|
|
|
self.gconf.bindGconfEntryToVar( "int", "category_hover_delay", self, "categoryhoverdelay" )
|
|
self.gconf.bindGconfEntryToVar( "bool", "do_not_filter", self, "donotfilterapps" )
|
|
self.gconf.bindGconfEntryToVar( "string", "search_command", self, "searchtool" )
|
|
self.gconf.bindGconfEntryToVar( "int", "default_tab", self, "defaultTab" )
|
|
|
|
self.currentFavCol = 0
|
|
self.favorites = []
|
|
|
|
self.content_holder.set_size_request( self.width, self.height )
|
|
self.categoriesBox.set_size_request( self.width / 3, -1 )
|
|
self.applicationsBox.set_size_request( self.width / 2, -1 )
|
|
|
|
self.buildingButtonList = False
|
|
self.stopBuildingButtonList = False
|
|
|
|
self.categoryList = []
|
|
self.applicationList = []
|
|
self.menuFileMonitors = []
|
|
|
|
self.rebuildLock = False
|
|
self.activeFilter = (1, "")
|
|
|
|
self.adminMenu = None
|
|
|
|
for mainitems in [ "applications.menu", "settings.menu" ]:
|
|
mymenu = Menu( mainitems )
|
|
mymenu.tree.add_monitor( self.menuChanged, None )
|
|
#for f in mymenu.directory.Files:
|
|
# self.menuFileMonitors.append( filemonitor.addMonitor(f, self.onMenuChanged, mymenu.directory.Filename ) )
|
|
#for f in mymenu.directory.AppDirs:
|
|
# self.menuFileMonitors.append( filemonitor.addMonitor(f, self.onMenuChanged, mymenu.directory.Filename ) )
|
|
|
|
sizeIcon = 0
|
|
if isinstance(self.iconSize, int):
|
|
if self.iconSize >= 4:
|
|
sizeIcon = gtk.ICON_SIZE_DIALOG
|
|
elif self.iconSize == 3:
|
|
sizeIcon = gtk.ICON_SIZE_DND
|
|
elif self.iconSize == 2:
|
|
sizeIcon = gtk.ICON_SIZE_BUTTON
|
|
elif self.iconSize == 1:
|
|
sizeIcon = gtk.ICON_SIZE_MENU
|
|
elif self.iconSize <= 0:
|
|
return ( 0, 0 )
|
|
|
|
#sizeIcon = gtk.icon_size_lookup( sizeIcon )
|
|
|
|
self.suggestSearchAppButton = SuggestionButton(gtk.STOCK_FIND, self.iconSize, "")
|
|
self.suggestSearchButton = SuggestionButton(gtk.STOCK_FIND, self.iconSize, "")
|
|
self.suggestShowButton = SuggestionButton(gtk.STOCK_INFO, self.iconSize, "")
|
|
self.suggestInstallButton = SuggestionButton(gtk.STOCK_ADD, self.iconSize, "")
|
|
|
|
self.suggestSearchAppButton.connect("clicked", self.search_mint)
|
|
self.suggestSearchButton.connect("clicked", self.search_apt)
|
|
self.suggestShowButton.connect("clicked", self.show_apt)
|
|
self.suggestInstallButton.connect("clicked", self.install_apt)
|
|
|
|
def search_mint(self, widget):
|
|
os.system("/usr/bin/mint-search-portal " + self.suggestion + " &")
|
|
self.mintMenuWin.hide()
|
|
|
|
def search_apt(self, widget):
|
|
os.system("/usr/bin/mint-search-apt " + self.suggestion + " &")
|
|
self.mintMenuWin.hide()
|
|
|
|
def show_apt(self, widget):
|
|
os.system("/usr/bin/mint-show-apt " + self.suggestion + " &")
|
|
self.mintMenuWin.hide()
|
|
|
|
def install_apt(self, widget):
|
|
os.system("/usr/bin/mint-make-cmd " + self.suggestion + " &")
|
|
self.mintMenuWin.hide()
|
|
|
|
def __del__( self ):
|
|
print u"Applications plugin deleted"
|
|
|
|
def wake (self) :
|
|
pass
|
|
|
|
def destroy( self ):
|
|
self.content_holder.destroy()
|
|
self.searchEntry.destroy()
|
|
self.searchButton.destroy()
|
|
self.showAllAppsButton.destroy()
|
|
self.showFavoritesButton.destroy()
|
|
self.applicationsBox.destroy()
|
|
self.categoriesBox.destroy()
|
|
self.favoritesBox.destroy()
|
|
|
|
self.gconf.notifyRemoveAll()
|
|
|
|
for mId in self.menuFileMonitors:
|
|
filemonitor.removeMonitor( mId )
|
|
|
|
def changePluginSize( self, client, connection_id, entry, args ):
|
|
if entry.get_key() == self.gconf.gconfDir+"width":
|
|
self.width = entry.get_value().get_int()
|
|
self.categoriesBox.set_size_request( self.width / 3, -1 )
|
|
self.applicationsBox.set_size_request( self.width / 2, -1 )
|
|
|
|
elif entry.get_key() == self.gconf.gconfDir+"height":
|
|
self.heigth = entry.get_value().get_int()
|
|
self.content_holder.set_size_request( self.width, self.height )
|
|
|
|
def changeSwapGenericName( self, client, connection_id, entry, args ):
|
|
self.swapgeneric = entry.get_value().get_bool()
|
|
|
|
for child in self.favoritesBox:
|
|
if isinstance( child, FavApplicationLauncher):
|
|
child.setSwapGeneric( self.swapgeneric )
|
|
|
|
def changeShowCategoryIcons( self, client, connection_id, entry, args ):
|
|
self.showcategoryicons = entry.get_value().get_bool()
|
|
|
|
if self.showcategoryicons:
|
|
categoryIconSize = self.iconSize
|
|
else:
|
|
categoryIconSize = 0
|
|
|
|
for child in self.categoriesBox:
|
|
child.setIconSize( categoryIconSize )
|
|
|
|
def changeIconSize( self, client, connection_id, entry, args ):
|
|
self.iconSize = entry.get_value().get_int()
|
|
|
|
if self.showcategoryicons:
|
|
categoryIconSize = self.iconSize
|
|
else:
|
|
categoryIconSize = 0
|
|
|
|
for child in self.categoriesBox:
|
|
child.setIconSize( categoryIconSize )
|
|
|
|
for child in self.applicationsBox:
|
|
try:
|
|
child.setIconSize( self.iconSize )
|
|
except:
|
|
pass
|
|
|
|
self.suggestSearchAppButton.set_icon_size( self.iconSize )
|
|
self.suggestSearchButton.set_icon_size( self.iconSize )
|
|
self.suggestShowButton.set_icon_size( self.iconSize )
|
|
self.suggestInstallButton.set_icon_size( self.iconSize )
|
|
|
|
|
|
def changeFavIconSize( self, client, connection_id, entry, args ):
|
|
self.faviconsize = entry.get_value().get_int()
|
|
|
|
for child in self.favoritesBox:
|
|
if isinstance( child, FavApplicationLauncher):
|
|
child.setIconSize( self.faviconsize )
|
|
|
|
def changeShowApplicationComments( self, client, connection_id, entry, args ):
|
|
self.showapplicationcomments = entry.get_value().get_bool()
|
|
for child in self.applicationsBox:
|
|
child.setShowComment( self.showapplicationcomments )
|
|
|
|
def changeCategoriesMouseOver( self, client, connection_id, entry, args ):
|
|
self.categories_mouse_over = entry.get_value().get_bool()
|
|
for child in self.categoriesBox:
|
|
if self.categories_mouse_over and not child.mouseOverHandlerIds:
|
|
startId = child.connect( "enter", self.StartFilter, child.filter )
|
|
stopId = child.connect( "leave", self.StopFilter )
|
|
child.mouseOverHandlerIds = ( startId, stopId )
|
|
elif self.categories_mouse_over and child.mouseOverHandlerIds:
|
|
child.disconnect( child.mouseOverHandlerIds[0] )
|
|
child.disconnect( child.mouseOverHandlerIds[1] )
|
|
child.mouseOverHandlerIds = None
|
|
|
|
def changeFavCols(self, client, connection_id, entry, args):
|
|
self.favCols = entry.get_value().get_int()
|
|
for fav in self.favorites:
|
|
self.favoritesBox.remove( fav )
|
|
self.favoritesPositionOnGrid( fav )
|
|
|
|
def RegenPlugin( self, *args, **kargs ):
|
|
# save old config - this is necessary because the app will notified when it sets the default values and you don't want the to reload itself several times
|
|
oldcategories_mouse_over = self.categories_mouse_over
|
|
oldtotalrecent = self.totalrecent
|
|
oldsticky = self.sticky
|
|
oldminimized = self.minimized
|
|
oldicon = self.icon
|
|
oldhideseparator = self.hideseparator
|
|
oldshowapplicationcomments = self.showapplicationcomments
|
|
|
|
self.GetGconfEntries()
|
|
|
|
# if the config hasn't changed return
|
|
if oldcategories_mouse_over == self.categories_mouse_over and oldiconsize == self.iconSize and oldfaviconsize == self.faviconsize and oldtotalrecent == self.totalrecent and oldswapgeneric == self.swapgeneric and oldshowcategoryicons == self.showcategoryicons and oldcategoryhoverdelay == self.categoryhoverdelay and oldsticky == self.sticky and oldminimized == self.minimized and oldicon == self.icon and oldhideseparator == self.hideseparator and oldshowapplicationcomments == self.showapplicationcomments:
|
|
return
|
|
|
|
self.Todos()
|
|
self.buildFavorites()
|
|
self.RebuildPlugin()
|
|
|
|
def GetGconfEntries( self ):
|
|
|
|
self.categories_mouse_over = self.gconf.get( "bool", "categories_mouse_over", True )
|
|
self.width = self.gconf.get( "int", "width", 480 )
|
|
self.height = self.gconf.get( "int", "height", 410 )
|
|
self.donotfilterapps = self.gconf.get( "bool", "do_not_filter", False )
|
|
self.iconSize = self.gconf.get( "int", "icon_size", 2 )
|
|
self.faviconsize = self.gconf.get( "int", "favicon_size", 3 )
|
|
self.favCols = self.gconf.get( "int", "fav_cols", 2 )
|
|
self.swapgeneric = self.gconf.get( "bool", "swap_generic_name", False )
|
|
self.showcategoryicons = self.gconf.get( "bool", "show_category_icons", True )
|
|
self.categoryhoverdelay = self.gconf.get( "int", "category_hover_delay", 50 )
|
|
self.showapplicationcomments = self.gconf.get( "bool", "show_application_comments", True )
|
|
|
|
self.lastActiveTab = self.gconf.get( "int", "last_active_tab", 0 )
|
|
self.defaultTab = self.gconf.get( "int", "default_tab", -1 )
|
|
|
|
|
|
# Allow plugin to be minimized to the left plugin pane
|
|
self.sticky = self.gconf.get( "bool", "sticky", False )
|
|
self.minimized = self.gconf.get( "bool", "minimized", False )
|
|
|
|
# Search tool
|
|
self.searchtool = self.gconf.get( "string", "search_command", "gnome-search-tool --named \"%s\" --start" )
|
|
if self.searchtool == "beagle-search SEARCH_STRING":
|
|
self.searchtool = "gnome-search-tool --named \"%s\" --start"
|
|
self.gconf.set( "string", "search_command", "gnome-search-tool --named \"%s\" --start" )
|
|
|
|
# Plugin icon
|
|
self.icon = self.gconf.get( "string", "icon", "applications-accessories" )
|
|
|
|
# Hide vertical dotted separator
|
|
self.hideseparator = self.gconf.get( "bool", "hide_separator", False )
|
|
|
|
def SetHidden( self, state ):
|
|
if state == True:
|
|
self.gconf.set( "bool", "minimized", True )
|
|
else:
|
|
self.gconf.set( "bool", "minimized", False )
|
|
|
|
def RebuildPlugin(self):
|
|
self.content_holder.set_size_request( self.width, self.height )
|
|
|
|
def checkMintMenuFolder( self ):
|
|
if os.path.exists( os.path.join( os.path.expanduser( "~" ), ".linuxmint", "mintMenu", "applications" ) ):
|
|
return True
|
|
try:
|
|
os.makedirs( os.path.join( os.path.expanduser( "~" ), ".linuxmint", "mintMenu", "applications" ) )
|
|
return True
|
|
except:
|
|
pass
|
|
|
|
return False
|
|
|
|
def onShowMenu( self ):
|
|
if len( self.favorites ):
|
|
if self.defaultTab == -1:
|
|
self.changeTab( self.lastActiveTab)
|
|
else:
|
|
self.changeTab( (self.defaultTab - 1) * -1 )
|
|
else:
|
|
self.changeTab( 1 )
|
|
|
|
self.searchEntry.select_region( 0, -1 )
|
|
|
|
def onHideMenu( self ):
|
|
self.gconf.set( "int", "last_active_tab", self.lastActiveTab )
|
|
|
|
def changeTab( self, tabNum ):
|
|
notebook = self.wTree.get_widget( "notebook2" )
|
|
if tabNum == 0:
|
|
notebook.set_current_page( 0 )
|
|
elif tabNum == 1:
|
|
notebook.set_current_page( 1 )
|
|
|
|
self.lastActiveTab = tabNum
|
|
|
|
self.focusSearchEntry()
|
|
|
|
def Todos( self ):
|
|
|
|
self.searchEntry.connect( "changed", self.Filter )
|
|
self.searchEntry.connect( "activate", self.Search )
|
|
self.showAllAppsButton.connect( "clicked", lambda widget: self.changeTab( 1 ) )
|
|
self.showFavoritesButton.connect( "clicked", lambda widget: self.changeTab( 0 ) )
|
|
self.buildButtonList()
|
|
|
|
def focusSearchEntry( self ):
|
|
# grab_focus() does select all text, as this is an unwanted behaviour we restore the old selection
|
|
sel = self.searchEntry.get_selection_bounds()
|
|
if len(sel) == 0: # no selection
|
|
sel = ( self.searchEntry.get_position(), self.searchEntry.get_position() )
|
|
self.searchEntry.grab_focus()
|
|
self.searchEntry.select_region( sel[0], sel[1] )
|
|
|
|
def buildButtonList( self ):
|
|
if self.buildingButtonList:
|
|
self.stopBuildingButtonList = True
|
|
gobject.timeout_add( 100, self.buildButtonList )
|
|
return
|
|
|
|
self.stopBuildingButtonList = False
|
|
|
|
gobject.idle_add( self.updateBoxes )
|
|
|
|
def categoryBtnFocus( self, widget, event, category ):
|
|
self.scrollItemIntoView( widget )
|
|
self.StartFilter( widget, category )
|
|
|
|
def StartFilter( self, widget, category ):
|
|
# if there is a timer for a different category running stop it
|
|
if self.filterTimer:
|
|
gobject.source_remove( self.filterTimer )
|
|
self.filterTimer = gobject.timeout_add( self.categoryhoverdelay, self.Filter, widget, category )
|
|
|
|
def StopFilter( self, widget ):
|
|
if self.filterTimer:
|
|
gobject.source_remove( self.filterTimer )
|
|
self.filterTimer = None
|
|
|
|
def Filter( self, widget, category = None ):
|
|
self.filterTimer = None
|
|
|
|
start = time.time()
|
|
#print "FILTER"
|
|
self.applicationsBox.remove(self.suggestSearchAppButton)
|
|
self.applicationsBox.remove(self.suggestSearchButton)
|
|
self.applicationsBox.remove(self.suggestShowButton)
|
|
self.applicationsBox.remove(self.suggestInstallButton)
|
|
|
|
if widget == self.searchEntry:
|
|
if self.donotfilterapps:
|
|
widget.set_text( "" )
|
|
else:
|
|
self.changeTab( 1 )
|
|
text = widget.get_text()
|
|
showns = False # Are any app shown?
|
|
for i in self.applicationsBox.get_children():
|
|
shown = i.filterText( text )
|
|
if (shown):
|
|
showns = True
|
|
|
|
if (not showns and os.path.exists("/usr/lib/linuxmint/mintInstall/icon.svg")):
|
|
self.suggestion = text
|
|
|
|
self.applicationsBox.add(self.suggestSearchAppButton)
|
|
self.suggestSearchAppButton.set_text(_("Search portal for '%s'") % text)
|
|
self.suggestSearchAppButton.set_tooltip_text(_("Search portal for '%s'") % text)
|
|
|
|
self.applicationsBox.add(self.suggestSearchButton)
|
|
self.suggestSearchButton.set_text(_("Search repositories for '%s'") % text)
|
|
self.suggestSearchButton.set_tooltip_text(_("Search repositories for '%s'") % text)
|
|
|
|
self.applicationsBox.add(self.suggestShowButton)
|
|
self.suggestShowButton.set_text(_("Show package '%s'") % text)
|
|
self.suggestShowButton.set_tooltip_text(_("Show package '%s'") % text)
|
|
|
|
self.applicationsBox.add(self.suggestInstallButton)
|
|
self.suggestInstallButton.set_text(_("Install package '%s'") % text)
|
|
self.suggestInstallButton.set_tooltip_text(_("Install package '%s'") % text)
|
|
|
|
for i in self.categoriesBox.get_children():
|
|
i.set_relief( gtk.RELIEF_NONE )
|
|
|
|
allButton = self.categoriesBox.get_children()[0];
|
|
allButton.set_relief( gtk.RELIEF_HALF )
|
|
self.activeFilter = (0, text)
|
|
else:
|
|
#print "CATFILTER"
|
|
self.activeFilter = (1, category)
|
|
if category == "":
|
|
for i in self.applicationsBox.get_children():
|
|
i.show_all()
|
|
else:
|
|
for i in self.applicationsBox.get_children():
|
|
i.filterCategory( category )
|
|
for i in self.applicationsBox.get_children():
|
|
i.filterCategory( category )
|
|
|
|
for i in self.categoriesBox.get_children():
|
|
i.set_relief( gtk.RELIEF_NONE )
|
|
widget.set_relief( gtk.RELIEF_HALF )
|
|
widget.grab_focus()
|
|
|
|
self.searchEntry.set_text( "" )
|
|
|
|
self.applicationsScrolledWindow.get_vadjustment().set_value( 0 )
|
|
#print u"Filtertime: ", (time.time() - start), "s"
|
|
|
|
# Forward all text to the search box
|
|
def keyPress( self, widget, event ):
|
|
if event.string.strip() != "" or event.keyval == gtk.keysyms.BackSpace:
|
|
self.searchEntry.event( event )
|
|
return True
|
|
|
|
if event.keyval == gtk.keysyms.Down and self.searchEntry.is_focus():
|
|
self.applicationsBox.get_children()[0].grab_focus()
|
|
|
|
return False
|
|
|
|
def favPopup( self, widget, ev ):
|
|
if ev.button == 3:
|
|
if ev.y > widget.get_allocation().height / 2:
|
|
insertBefore = False
|
|
else:
|
|
insertBefore = True
|
|
|
|
if widget.type == "location":
|
|
mTree = gtk.glade.XML( self.gladefile, "favoritesMenu" )
|
|
#i18n
|
|
launchMenuItem = gtk.MenuItem(_("Launch"))
|
|
propsMenuItem = gtk.MenuItem(_("Properties"))
|
|
removeFromFavMenuItem = gtk.MenuItem(_("Remove from favorites"))
|
|
startupMenuItem = gtk.CheckMenuItem(_("Launch when I log in"))
|
|
separator = gtk.SeparatorMenuItem()
|
|
insertSpaceMenuItem = gtk.MenuItem(_("Insert space"))
|
|
insertSeparatorMenuItem = gtk.MenuItem(_("Insert separator"))
|
|
|
|
|
|
launchMenuItem.connect( "activate", self.onLaunchApp, widget)
|
|
propsMenuItem.connect( "activate", self.onPropsApp, widget)
|
|
removeFromFavMenuItem.connect( "activate", self.onFavoritesRemove, widget )
|
|
insertSpaceMenuItem.connect( "activate", self.onFavoritesInsertSpace, widget, insertBefore )
|
|
insertSeparatorMenuItem.connect( "activate", self.onFavoritesInsertSeparator, widget, insertBefore )
|
|
|
|
mTree.get_widget("favoritesMenu").append(launchMenuItem)
|
|
mTree.get_widget("favoritesMenu").append(propsMenuItem)
|
|
mTree.get_widget("favoritesMenu").append(removeFromFavMenuItem)
|
|
mTree.get_widget("favoritesMenu").append(startupMenuItem)
|
|
mTree.get_widget("favoritesMenu").append(separator)
|
|
mTree.get_widget("favoritesMenu").append(insertSpaceMenuItem)
|
|
mTree.get_widget("favoritesMenu").append(insertSeparatorMenuItem)
|
|
mTree.get_widget("favoritesMenu").show_all()
|
|
|
|
mTree.get_widget( "favoritesMenu" ).popup( None, None, None, ev.button, ev.time )
|
|
|
|
if widget.isInStartup():
|
|
startupMenuItem.set_active( True )
|
|
startupMenuItem.connect( "toggled", self.onRemoveFromStartup, widget )
|
|
else:
|
|
startupMenuItem.set_active( False )
|
|
startupMenuItem.connect( "toggled", self.onAddToStartup, widget )
|
|
|
|
else:
|
|
mTree = gtk.glade.XML( self.gladefile, "favoritesMenuExtra" )
|
|
#i18n
|
|
removeMenuItem = gtk.MenuItem(_("Remove"))
|
|
insertSpaceMenuItem = gtk.MenuItem(_("Insert space"))
|
|
insertSeparatorMenuItem = gtk.MenuItem(_("Insert separator"))
|
|
mTree.get_widget("favoritesMenuExtra").append(removeMenuItem)
|
|
mTree.get_widget("favoritesMenuExtra").append(insertSpaceMenuItem)
|
|
mTree.get_widget("favoritesMenuExtra").append(insertSeparatorMenuItem)
|
|
mTree.get_widget("favoritesMenuExtra").show_all()
|
|
|
|
removeMenuItem.connect( "activate", self.onFavoritesRemove, widget )
|
|
insertSpaceMenuItem.connect( "activate", self.onFavoritesInsertSpace, widget, insertBefore )
|
|
insertSeparatorMenuItem.connect( "activate", self.onFavoritesInsertSeparator, widget, insertBefore )
|
|
mTree.get_widget( "favoritesMenuExtra" ).popup( None, None, None, ev.button, ev.time )
|
|
|
|
def menuPopup( self, widget, event ):
|
|
if event.button == 3:
|
|
mTree = gtk.glade.XML( self.gladefile, "applicationsMenu" )
|
|
|
|
#i18n
|
|
launchMenuItem = gtk.MenuItem(_("Launch"))
|
|
propsMenuItem = gtk.MenuItem(_("Properties"))
|
|
favoriteMenuItem = gtk.CheckMenuItem(_("Show in my favorites"))
|
|
startupMenuItem = gtk.CheckMenuItem(_("Launch when I log in"))
|
|
separator = gtk.SeparatorMenuItem()
|
|
uninstallMenuItem = gtk.MenuItem(_("Uninstall"))
|
|
mTree.get_widget("applicationsMenu").append(launchMenuItem)
|
|
mTree.get_widget("applicationsMenu").append(propsMenuItem)
|
|
mTree.get_widget("applicationsMenu").append(favoriteMenuItem)
|
|
mTree.get_widget("applicationsMenu").append(startupMenuItem)
|
|
mTree.get_widget("applicationsMenu").append(separator)
|
|
mTree.get_widget("applicationsMenu").append(uninstallMenuItem)
|
|
mTree.get_widget("applicationsMenu").show_all()
|
|
|
|
launchMenuItem.connect( "activate", self.onLaunchApp, widget )
|
|
propsMenuItem.connect( "activate", self.onPropsApp, widget)
|
|
uninstallMenuItem.connect ( "activate", self.onUninstallApp, widget )
|
|
|
|
if self.isLocationInFavorites( widget.desktopFile ):
|
|
favoriteMenuItem.set_active( True )
|
|
favoriteMenuItem.connect( "toggled", self.onRemoveFromFavorites, widget )
|
|
else:
|
|
favoriteMenuItem.set_active( False )
|
|
favoriteMenuItem.connect( "toggled", self.onAddToFavorites, widget )
|
|
|
|
if widget.isInStartup():
|
|
startupMenuItem.set_active( True )
|
|
startupMenuItem.connect( "toggled", self.onRemoveFromStartup, widget )
|
|
else:
|
|
startupMenuItem.set_active( False )
|
|
startupMenuItem.connect( "toggled", self.onAddToStartup, widget )
|
|
|
|
mTree.get_widget( "applicationsMenu" ).popup( None, None, None, event.button, event.time )
|
|
|
|
def onLaunchApp( self, menu, widget ):
|
|
widget.execute()
|
|
self.mintMenuWin.hide()
|
|
|
|
def onPropsApp( self, menu, widget ):
|
|
|
|
# Building a path to the .desktop file in the user's home directory
|
|
file_path = os.path.join(getUserItemPath(), os.path.basename(widget.desktopFile))
|
|
|
|
if not os.path.isfile(file_path):
|
|
data = open(widget.desktopFile).read()
|
|
open(file_path, 'w').write(data)
|
|
|
|
os.system('gnome-desktop-item-edit ' + file_path)
|
|
self.mintMenuWin.hide()
|
|
|
|
|
|
def onUninstallApp( self, menu, widget ):
|
|
widget.uninstall()
|
|
self.mintMenuWin.hide()
|
|
|
|
def onFavoritesInsertSpace( self, menu, widget, insertBefore ):
|
|
if insertBefore:
|
|
self.favoritesAdd( self.favoritesBuildSpace(), widget.position )
|
|
else:
|
|
self.favoritesAdd( self.favoritesBuildSpace(), widget.position + 1 )
|
|
|
|
def onFavoritesInsertSeparator( self, menu, widget, insertBefore ):
|
|
if insertBefore:
|
|
self.favoritesAdd( self.favoritesBuildSeparator(), widget.position )
|
|
else:
|
|
self.favoritesAdd( self.favoritesBuildSeparator(), widget.position + 1 )
|
|
|
|
def onFavoritesRemove( self, menu, widget ):
|
|
self.favoritesRemove( widget.position )
|
|
|
|
def onAddToStartup( self, menu, widget ):
|
|
widget.addToStartup()
|
|
|
|
def onRemoveFromStartup( self, menu, widget ):
|
|
widget.removeFromStartup()
|
|
|
|
def onAddToFavorites( self, menu, widget ):
|
|
self.favoritesAdd( self.favoritesBuildLauncher( widget.desktopFile ) )
|
|
|
|
def onRemoveFromFavorites( self, menu, widget ):
|
|
self.favoritesRemoveLocation( widget.desktopFile )
|
|
|
|
def ReceiveCallback( self, widget, context, x, y, selection, targetType, time ):
|
|
if targetType == self.TARGET_TYPE_TEXT:
|
|
for uri in selection.get_uris():
|
|
self.favoritesAdd( self.favoritesBuildLauncher( uri ) )
|
|
|
|
def Search( self, widget ):
|
|
text = self.searchEntry.get_text().strip()
|
|
if text != "":
|
|
self.searchEntry.set_text( "" )
|
|
self.mintMenuWin.hide()
|
|
fullstring = self.searchtool.replace( "%s", text )
|
|
newstring = fullstring.split()
|
|
Execute( newstring )
|
|
|
|
def SearchWithButton( self, widget, event ):
|
|
self.Search( widget )
|
|
|
|
def do_plugin( self ):
|
|
self.Todos()
|
|
self.buildFavorites()
|
|
|
|
# Scroll button into view
|
|
def scrollItemIntoView( self, widget, event = None ):
|
|
viewport = widget.parent
|
|
while not isinstance( viewport, gtk.Viewport ):
|
|
if not viewport.parent:
|
|
return
|
|
viewport = viewport.parent
|
|
aloc = widget.get_allocation()
|
|
viewport.get_vadjustment().clamp_page(aloc.y, aloc.y + aloc.height)
|
|
|
|
def favoritesBuildSpace( self ):
|
|
space = gtk.EventBox()
|
|
space.set_size_request( -1, 20 )
|
|
space.connect( "button_release_event", self.favPopup )
|
|
space.type = "space"
|
|
|
|
self.mintMenuWin.SetPaneColors( [ space ] )
|
|
space.show()
|
|
|
|
return space
|
|
|
|
def favoritesBuildSeparator( self ):
|
|
separator = gtk.EventBox()
|
|
separator.add( gtk.HSeparator() )
|
|
separator.set_size_request( -1, 20 )
|
|
separator.connect( "button_release_event", self.favPopup )
|
|
separator.type = "separator"
|
|
|
|
self.mintMenuWin.SetPaneColors( [ separator ] )
|
|
separator.show_all()
|
|
return separator
|
|
|
|
def favoritesBuildLauncher( self, location ):
|
|
try:
|
|
ButtonIcon = None
|
|
# For Folders and Network Shares
|
|
location = string.join( location.split( "%20" ) )
|
|
|
|
if location.startswith( "file" ):
|
|
ButtonIcon = "gnome-fs-directory"
|
|
|
|
if location.startswith( "smb" ) or location.startswith( "ssh" ) or location.startswith( "network" ):
|
|
ButtonIcon = "gnome-fs-network"
|
|
|
|
#For Special locations
|
|
if location == "x-nautilus-desktop:///computer":
|
|
location = "/usr/share/applications/nautilus-computer.desktop"
|
|
elif location == "x-nautilus-desktop:///home":
|
|
location = "/usr/share/applications/nautilus-home.desktop"
|
|
elif location == "x-nautilus-desktop:///network":
|
|
location = "/usr/share/applications/network-scheme.desktop"
|
|
elif location.startswith( "x-nautilus-desktop:///" ):
|
|
location = "/usr/share/applications/nautilus-computer.desktop"
|
|
|
|
if location.startswith( "file://" ):
|
|
location = location[7:]
|
|
|
|
# Don't add a location twice
|
|
for fav in self.favorites:
|
|
if fav.type == "location" and fav.desktopFile == location:
|
|
return None
|
|
|
|
favButton = FavApplicationLauncher( location, self.faviconsize, self.swapgeneric )
|
|
if favButton.appExec:
|
|
favButton.show()
|
|
favButton.connect( "popup-menu", self.favPopup )
|
|
favButton.connect( "button_release_event", self.favPopup )
|
|
favButton.connect( "focus-in-event", self.scrollItemIntoView )
|
|
favButton.connect( "clicked", lambda w: self.mintMenuWin.hide() )
|
|
|
|
self.mintMenuWin.setTooltip( favButton, favButton.getTooltip() )
|
|
favButton.type = "location"
|
|
return favButton
|
|
except Exception, e:
|
|
print u"File in favorites not found: '" + location + "'", e
|
|
|
|
return None
|
|
|
|
def buildFavorites( self ):
|
|
try:
|
|
from user import home
|
|
if (not os.path.exists(home + "/.linuxmint/mintMenu/applications.list")):
|
|
os.system("mkdir -p " + home + "/.linuxmint/mintMenu/applications")
|
|
os.system("cp /usr/lib/linuxmint/mintMenu/applications.list " + home + "/.linuxmint/mintMenu/applications.list")
|
|
|
|
applicationsFile = open ( os.path.join( os.path.expanduser( "~" ), ".linuxmint", "mintMenu", "applications.list" ), "r" )
|
|
applicationsList = applicationsFile.readlines()
|
|
|
|
self.favorites = []
|
|
|
|
for child in self.favoritesBox:
|
|
child.destroy()
|
|
|
|
position = 0
|
|
|
|
for app in applicationsList :
|
|
app = app.strip()
|
|
|
|
if app[0:9] == "location:":
|
|
favButton = self.favoritesBuildLauncher( app[9:] )
|
|
elif app == "space":
|
|
favButton = self.favoritesBuildSpace()
|
|
elif app == "separator":
|
|
favButton = self.favoritesBuildSeparator()
|
|
else:
|
|
if ( app.endswith( ".desktop" ) ):
|
|
favButton = self.favoritesBuildLauncher( app )
|
|
else:
|
|
favButton = None
|
|
|
|
|
|
if favButton:
|
|
favButton.position = position
|
|
self.favorites.append( favButton )
|
|
self.favoritesPositionOnGrid( favButton )
|
|
favButton.connect( "drag_data_received", self.onFavButtonDragReorder )
|
|
favButton.drag_dest_set( gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, self.fromFav, gtk.gdk.ACTION_MOVE )
|
|
favButton.connect( "drag_data_get", self.onFavButtonDragReorderGet )
|
|
favButton.drag_source_set( gtk.gdk.BUTTON1_MASK, self.toFav, gtk.gdk.ACTION_MOVE )
|
|
position += 1
|
|
|
|
self.favoritesSave()
|
|
except Exception, e:
|
|
print e
|
|
|
|
def favoritesGetNumRows( self ):
|
|
rows = 0
|
|
col = 0
|
|
for fav in self.favorites:
|
|
if ( fav.type == "separator" or fav.type == "space" ) and col != 0:
|
|
rows += 1
|
|
col = 0
|
|
col += 1
|
|
if fav.type == "separator" or fav.type == "space":
|
|
rows += 1
|
|
col = 0
|
|
|
|
if col >= self.favCols:
|
|
rows += 1
|
|
col = 0
|
|
return rows
|
|
|
|
def favoritesPositionOnGrid( self, favorite ):
|
|
row = 0
|
|
col = 0
|
|
for fav in self.favorites:
|
|
if ( fav.type == "separator" or fav.type == "space" ) and col != 0:
|
|
row += 1
|
|
col = 0
|
|
if fav.position == favorite.position:
|
|
break
|
|
col += 1
|
|
if fav.type == "separator" or fav.type == "space":
|
|
row += 1
|
|
col = 0
|
|
|
|
if col >= self.favCols:
|
|
row += 1
|
|
col = 0
|
|
|
|
if favorite.type == "separator" or favorite.type == "space":
|
|
self.favoritesBox.attach( favorite, col, col + self.favCols, row, row + 1, yoptions = 0 )
|
|
else:
|
|
self.favoritesBox.attach( favorite, col, col + 1, row, row + 1, yoptions = 0 )
|
|
|
|
def favoritesReorder( self, oldposition, newposition ):
|
|
if oldposition == newposition:
|
|
return
|
|
|
|
tmp = self.favorites[ oldposition ]
|
|
if newposition > oldposition:
|
|
if ( self.favorites[ newposition - 1 ].type == "space" or self.favorites[ newposition - 1 ].type == "separator" ) and self.favCols > 1:
|
|
newposition = newposition - 1
|
|
for i in range( oldposition, newposition ):
|
|
self.favorites[ i ] = self.favorites[ i + 1 ]
|
|
self.favorites[ i ].position = i
|
|
elif newposition < oldposition:
|
|
for i in range( 0, oldposition - newposition ):
|
|
self.favorites[ oldposition - i ] = self.favorites[ oldposition - i - 1 ]
|
|
self.favorites[ oldposition - i ] .position = oldposition - i
|
|
self.favorites[ newposition ] = tmp
|
|
self.favorites[ newposition ].position = newposition
|
|
|
|
for fav in self.favorites:
|
|
self.favoritesBox.remove( fav )
|
|
self.favoritesPositionOnGrid( fav )
|
|
|
|
self.favoritesSave()
|
|
self.favoritesBox.resize( self.favoritesGetNumRows(), self.favCols )
|
|
|
|
def favoritesAdd( self, favButton, position = -1 ):
|
|
if favButton:
|
|
favButton.position = len( self.favorites )
|
|
self.favorites.append( favButton )
|
|
self.favoritesPositionOnGrid( favButton )
|
|
|
|
favButton.connect( "drag_data_received", self.onFavButtonDragReorder )
|
|
favButton.drag_dest_set( gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, self.toFav, gtk.gdk.ACTION_MOVE )
|
|
favButton.connect( "drag_data_get", self.onFavButtonDragReorderGet )
|
|
favButton.drag_source_set( gtk.gdk.BUTTON1_MASK, self.toFav, gtk.gdk.ACTION_MOVE )
|
|
|
|
if position >= 0:
|
|
self.favoritesReorder( favButton.position, position )
|
|
|
|
self.favoritesSave()
|
|
|
|
def favoritesRemove( self, position ):
|
|
tmp = self.favorites[ position ]
|
|
self.favorites.remove( self.favorites[ position ] )
|
|
tmp.destroy()
|
|
|
|
for i in range( position, len( self.favorites ) ):
|
|
self.favorites[ i ].position = i
|
|
self.favoritesBox.remove( self.favorites[ i ] )
|
|
self.favoritesPositionOnGrid( self.favorites[ i ] )
|
|
self.favoritesSave()
|
|
self.favoritesBox.resize( self.favoritesGetNumRows(), self.favCols )
|
|
|
|
def favoritesRemoveLocation( self, location ):
|
|
for fav in self.favorites:
|
|
if fav.type == "location" and fav.desktopFile == location:
|
|
self.favoritesRemove( fav.position )
|
|
|
|
def favoritesSave( self ):
|
|
try:
|
|
self.checkMintMenuFolder()
|
|
appListFile = open( os.path.join( os.path.expanduser( "~"), ".linuxmint", "mintMenu", "applications.list" ) , "w" )
|
|
|
|
for favorite in self.favorites:
|
|
if favorite.type == "location":
|
|
appListFile.write( "location:" + favorite.desktopFile + "\n" )
|
|
else:
|
|
appListFile.write( favorite.type + "\n" )
|
|
|
|
appListFile.close( )
|
|
except Exception, e:
|
|
msgDlg = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Couldn't save favorites. Check if you have write access to ~/.linuxmint/mintMenu")+"\n(" + e.__str__() + ")" )
|
|
msgDlg.run();
|
|
msgDlg.destroy();
|
|
|
|
def isLocationInFavorites( self, location ):
|
|
for fav in self.favorites:
|
|
if fav.type == "location" and fav.desktopFile == location:
|
|
return True
|
|
|
|
return False
|
|
|
|
def onFavButtonDragReorderGet( self, widget, context, selection, targetType, eventTime ):
|
|
if targetType == self.TARGET_TYPE_FAV:
|
|
selection.set( selection.target, 8, str(widget.position) )
|
|
|
|
def onFavButtonDragReorder( self, widget, context, x, y, selection, targetType, time ):
|
|
if targetType == self.TARGET_TYPE_FAV:
|
|
self.favoritesReorder( int(selection.data), widget.position )
|
|
|
|
def menuChanged( self, x, y ):
|
|
# wait some miliseconds because there a multiple events send at the same time and we don't want to rebuild the menu for each
|
|
if self.menuChangedTimer:
|
|
gobject.source_remove( self.menuChangedTimer )
|
|
|
|
self.menuChangedTimer = gobject.timeout_add( 100, self.updateBoxes )
|
|
|
|
def updateBoxes( self ):
|
|
# FIXME: This is really bad!
|
|
if self.rebuildLock:
|
|
return
|
|
|
|
self.rebuildLock = True
|
|
|
|
self.menuChangedTimer = None
|
|
|
|
self.loadMenuFiles()
|
|
|
|
# Find added and removed categories than update the category list
|
|
newCategoryList = self.buildCategoryList()
|
|
|
|
addedCategories = []
|
|
removedCategories = []
|
|
|
|
# TODO: optimize this!!!
|
|
if not self.categoryList:
|
|
addedCategories = newCategoryList
|
|
else:
|
|
for item in newCategoryList:
|
|
found = False
|
|
for item2 in self.categoryList:
|
|
pass
|
|
if item["name"] == item2["name"] and item["icon"] == item2["icon"] and item["tooltip"] == item2["tooltip"] and item["index"] == item2["index"]:
|
|
found = True
|
|
break
|
|
if not found:
|
|
addedCategories.append(item)
|
|
|
|
key = 0
|
|
for item in self.categoryList:
|
|
found = False
|
|
for item2 in newCategoryList:
|
|
if item["name"] == item2["name"] and item["icon"] == item2["icon"] and item["tooltip"] == item2["tooltip"] and item["index"] == item2["index"]:
|
|
found = True
|
|
break
|
|
if not found:
|
|
removedCategories.append( key )
|
|
else:
|
|
key += 1
|
|
|
|
if self.showcategoryicons == True:
|
|
categoryIconSize = self.iconSize
|
|
else:
|
|
categoryIconSize = 0
|
|
|
|
|
|
for key in removedCategories:
|
|
self.categoryList[key]["button"].destroy()
|
|
del self.categoryList[key]
|
|
|
|
if addedCategories:
|
|
sortedCategoryList = []
|
|
|
|
for item in self.categoryList:
|
|
self.categoriesBox.remove( item["button"] )
|
|
sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) )
|
|
|
|
# Create new category buttons and add the to the list
|
|
for item in addedCategories:
|
|
item["button"] = CategoryButton( item["icon"], categoryIconSize, [ item["name"] ], item["filter"] )
|
|
self.mintMenuWin.setTooltip( item["button"], item["tooltip"] )
|
|
|
|
if self.categories_mouse_over:
|
|
startId = item["button"].connect( "enter", self.StartFilter, item["filter"] )
|
|
stopId = item["button"].connect( "leave", self.StopFilter )
|
|
item["button"].mouseOverHandlerIds = ( startId, stopId )
|
|
|
|
item["button"].connect( "clicked", self.Filter, item["filter"] )
|
|
item["button"].connect( "focus-in-event", self.categoryBtnFocus, item["filter"] )
|
|
item["button"].show()
|
|
|
|
self.categoryList.append( item )
|
|
sortedCategoryList.append( ( str(item["index"]) + item["name"], item["button"] ) )
|
|
|
|
sortedCategoryList.sort()
|
|
|
|
for item in sortedCategoryList:
|
|
self.categoriesBox.pack_start( item[1], False )
|
|
|
|
|
|
# Find added and removed applications add update the application list
|
|
newApplicationList = self.buildApplicationList()
|
|
addedApplications = []
|
|
removedApplications = []
|
|
|
|
# TODO: optimize this!!!
|
|
if not self.applicationList:
|
|
addedApplications = newApplicationList
|
|
else:
|
|
for item in newApplicationList:
|
|
found = False
|
|
for item2 in self.applicationList:
|
|
if item["entry"].get_desktop_file_path() == item2["entry"].get_desktop_file_path():
|
|
found = True
|
|
break
|
|
if not found:
|
|
addedApplications.append(item)
|
|
|
|
key = 0
|
|
for item in self.applicationList:
|
|
found = False
|
|
for item2 in newApplicationList:
|
|
if item["entry"].get_desktop_file_path() == item2["entry"].get_desktop_file_path():
|
|
found = True
|
|
break
|
|
if not found:
|
|
removedApplications.append(key)
|
|
else:
|
|
# don't increment the key if this item is going to be removed
|
|
# because when it is removed the index of all later items is
|
|
# going to be decreased
|
|
key += 1
|
|
|
|
for key in removedApplications:
|
|
self.applicationList[key]["button"].destroy()
|
|
del self.applicationList[key]
|
|
|
|
if addedApplications:
|
|
sortedApplicationList = []
|
|
for item in self.applicationList:
|
|
self.applicationsBox.remove( item["button"] )
|
|
sortedApplicationList.append( ( item["button"].appName, item["button"] ) )
|
|
|
|
for item in addedApplications:
|
|
item["button"] = MenuApplicationLauncher( item["entry"].get_desktop_file_path(), self.iconSize, item["category"], self.showapplicationcomments )
|
|
if item["button"].appExec:
|
|
self.mintMenuWin.setTooltip( item["button"], item["button"].getTooltip() )
|
|
item["button"].connect( "button-release-event", self.menuPopup )
|
|
item["button"].connect( "focus-in-event", self.scrollItemIntoView )
|
|
item["button"].connect( "clicked", lambda w: self.mintMenuWin.hide() )
|
|
if self.activeFilter[0] == 0:
|
|
item["button"].filterText( self.activeFilter[1] )
|
|
else:
|
|
item["button"].filterCategory( self.activeFilter[1] )
|
|
sortedApplicationList.append( ( item["button"].appName.upper(), item["button"] ) )
|
|
self.applicationList.append( item )
|
|
else:
|
|
item["button"].destroy()
|
|
|
|
|
|
sortedApplicationList.sort()
|
|
for item in sortedApplicationList:
|
|
self.applicationsBox.pack_start( item[1], False )
|
|
self.rebuildLock = False
|
|
|
|
|
|
# Reload the menufiles from the filesystem
|
|
def loadMenuFiles( self ):
|
|
self.menuFiles = []
|
|
for mainitems in [ "applications.menu", "settings.menu" ]:
|
|
self.menuFiles.append( Menu( mainitems) )
|
|
|
|
# Build a list of all categories in the menu ( [ { "name", "icon", tooltip" } ]
|
|
def buildCategoryList( self ):
|
|
newCategoryList = [ { "name": _("All"), "icon": self.mintMenuWin.icon, "tooltip": _("Show all applications"), "filter":"", "index": 0 } ]
|
|
|
|
num = 1
|
|
|
|
for menu in self.menuFiles:
|
|
for child in menu.directory.get_contents():
|
|
if child.get_type() == gmenu.TYPE_DIRECTORY:
|
|
icon = str(child.icon)
|
|
#if (icon == "preferences-system"):
|
|
# self.adminMenu = child.name
|
|
#if (icon != "applications-system" and icon != "applications-other"):
|
|
newCategoryList.append( { "name": child.name, "icon": child.icon, "tooltip": child.name, "filter": child.name, "index": num } )
|
|
num += 1
|
|
|
|
return newCategoryList
|
|
|
|
# Build a list containing the DesktopEntry object and the category of each application in the menu
|
|
def buildApplicationList( self ):
|
|
|
|
newApplicationsList = []
|
|
|
|
def find_applications_recursively(app_list, directory, catName):
|
|
for item in directory.get_contents():
|
|
if item.get_type() == gmenu.TYPE_ENTRY:
|
|
print "=======>>> " + str(item.name) + " = " + str(catName)
|
|
app_list.append( { "entry": item, "category": catName } )
|
|
elif item.get_type() == gmenu.TYPE_DIRECTORY:
|
|
find_applications_recursively(app_list, item, catName)
|
|
|
|
for menu in self.menuFiles:
|
|
directory = menu.directory
|
|
for entry in directory.get_contents():
|
|
if entry.get_type() == gmenu.TYPE_DIRECTORY and len(entry.get_contents()):
|
|
#Entry is a top-level category
|
|
#catName = entry.name
|
|
#icon = str(entry.icon)
|
|
#if (icon == "applications-system" or icon == "applications-other"):
|
|
# catName = self.adminMenu
|
|
for item in entry.get_contents():
|
|
if item.get_type() == gmenu.TYPE_DIRECTORY:
|
|
find_applications_recursively(newApplicationsList, item, entry.name)
|
|
elif item.get_type() == gmenu.TYPE_ENTRY:
|
|
newApplicationsList.append( { "entry": item, "category": entry.name } )
|
|
#elif entry.get_type() == gmenu.TYPE_ENTRY:
|
|
# if not (entry.get_is_excluded() or entry.get_is_nodisplay()):
|
|
# print "=======>>> " + item.name + " = top level"
|
|
# newApplicationsList.append( { "entry": item, "category": "" } )
|
|
|
|
return newApplicationsList
|
|
|