File alacarte_system_edit_mode.patch of Package alacarte

Index: configure.ac
===================================================================
--- configure.ac.orig
+++ configure.ac
@@ -70,6 +70,7 @@ AC_CONFIG_FILES([
         Makefile
         po/Makefile.in
         Alacarte/Makefile
+        data/alacarte-system.desktop.in
         data/alacarte.desktop.in
 	data/Makefile
 	data/icons/Makefile
Index: data/alacarte-system.desktop.in.in
===================================================================
--- /dev/null
+++ data/alacarte-system.desktop.in.in
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Encoding=UTF-8
+_Name=Main Menu - System view
+_Comment=Change which applications are shown on the main menu system wide
+Exec=alacarte --system-view=/etc/alacarte_system
+Terminal=false
+Type=Application
+StartupNotify=false
+Categories=GNOME;Settings;DesktopSettings;
+NotShowIn=KDE;
+Icon=alacarte
+X-GNOME-Bugzilla-Bugzilla=GNOME
+X-GNOME-Bugzilla-Product=alacarte
+X-GNOME-Bugzilla-Component=general
+X-GNOME-Bugzilla-Version=@VERSION@
Index: data/alacarte.glade
===================================================================
--- data/alacarte.glade.orig
+++ data/alacarte.glade
@@ -139,6 +139,110 @@
       </child>
 
       <child>
+	<widget class="GtkVBox" id="vbox7">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">3</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label25">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Editing Mode</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox22">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkCheckButton" id="system_view_button">
+		  <property name="visible">True</property>
+		  <property name="sensitive">False</property>
+		  <property name="can_focus">True</property>
+		  <property name="label" translatable="yes">System View</property>
+		  <property name="use_underline">True</property>
+		  <property name="relief">GTK_RELIEF_NORMAL</property>
+		  <property name="focus_on_click">False</property>
+		  <property name="active">True</property>
+		  <property name="inconsistent">False</property>
+		  <property name="draw_indicator">True</property>
+		</widget>
+		<packing>
+		  <property name="padding">20</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox23">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkCheckButton" id="user_view_button">
+		  <property name="visible">True</property>
+		  <property name="sensitive">False</property>
+		  <property name="can_focus">True</property>
+		  <property name="label" translatable="yes">User View</property>
+		  <property name="use_underline">True</property>
+		  <property name="relief">GTK_RELIEF_NORMAL</property>
+		  <property name="focus_on_click">False</property>
+		  <property name="active">False</property>
+		  <property name="inconsistent">False</property>
+		  <property name="draw_indicator">True</property>
+		</widget>
+		<packing>
+		  <property name="padding">20</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
 	<widget class="GtkAlignment" id="alignment9">
 	  <property name="border_width">5</property>
 	  <property name="visible">True</property>
@@ -704,6 +808,64 @@
 	  <property name="fill">True</property>
 	</packing>
       </child>
+
+      <child>
+	<widget class="GtkHBox" id="hbox21">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">7</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label26">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Application Browser: Max items in &quot;New Applications&quot; Group</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkSpinButton" id="ab_newapps_max_spin">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="climb_rate">1</property>
+	      <property name="digits">0</property>
+	      <property name="numeric">True</property>
+	      <property name="update_policy">GTK_UPDATE_IF_VALID</property>
+	      <property name="snap_to_ticks">True</property>
+	      <property name="wrap">False</property>
+	      <property name="adjustment">1 0 1000 1 10 10</property>
+	      <signal name="value_changed" handler="on_ab_newapps_max_activate" last_modification_time="Thu, 11 Jan 2007 22:09:29 GMT"/>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
     </widget>
   </child>
 </widget>
Index: data/Makefile.am
===================================================================
--- data/Makefile.am.orig
+++ data/Makefile.am
@@ -3,7 +3,7 @@ SUBDIRS = icons
 @INTLTOOL_DESKTOP_RULE@
 
 desktopdir = $(datadir)/applications
-desktop_in_files = alacarte.desktop.in
+desktop_in_files = alacarte.desktop.in alacarte-system.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 pkgdata_DATA = alacarte.glade
Index: data/alacarte.desktop.in.in
===================================================================
--- data/alacarte.desktop.in.in.orig
+++ data/alacarte.desktop.in.in
@@ -1,6 +1,6 @@
 [Desktop Entry]
 Encoding=UTF-8
-_Name=Main Menu
+_Name=Main Menu - User view
 _Comment=Change which applications are shown on the main menu
 Exec=alacarte
 Terminal=false
Index: Alacarte/MenuEditor.py
===================================================================
--- Alacarte/MenuEditor.py.orig
+++ Alacarte/MenuEditor.py
@@ -19,6 +19,8 @@
 import os, re, xml.dom.minidom, locale
 import gmenu
 from Alacarte import util
+import gettext
+_ = gettext.gettext
 
 class Menu:
 	tree = None
@@ -31,15 +33,54 @@ class MenuEditor:
 	__undo = []
 	__redo = []
 
-	def __init__(self):
+	cur_menu_names, orig_menu_names = None, None;
+
+	def __init__(self, m_names):
+		print "Enter " + __name__ + ":__init__"
 		self.locale = locale.getdefaultlocale()[0]
+		self.cur_menu_names = m_names[:]
+		self.orig_menu_names = m_names[:]
+		self.using_absolute_menu_names = False
 		self.__loadMenus()
 
+	def set_absolute_menu_names(self, prefix):
+		self.cur_menu_names[0] = prefix + self.orig_menu_names[0]
+		self.cur_menu_names[1] = prefix + self.orig_menu_names[1]
+		self.using_absolute_menu_names = True
+		self.__loadMenus();
+
+	def remove_absolute_menu_names(self):
+		self.cur_menu_names[0] = self.orig_menu_names[0]
+		self.cur_menu_names[1] = self.orig_menu_names[1]
+		self.using_absolute_menu_names = False
+		self.__loadMenus();
+
 	def __loadMenus(self):
+		print "Enter " + __name__ + ":__loadMenus"
+		if hasattr(self, "applications"):
+			if hasattr(self.applications, "tree"):
+				print "have a tree"
+				#print self.applications.tree.get_root_directory();
+				#self.applications.tree.tree_dealloc();
+
 		self.applications = Menu()
-		self.applications.tree = gmenu.lookup_tree('applications.menu', gmenu.FLAGS_SHOW_EMPTY|gmenu.FLAGS_INCLUDE_EXCLUDED|gmenu.FLAGS_INCLUDE_NODISPLAY|gmenu.FLAGS_SHOW_ALL_SEPARATORS)
-		self.applications.visible_tree = gmenu.lookup_tree('applications.menu')
-		self.applications.path = os.path.join(util.getUserMenuPath(), self.applications.tree.get_menu_file())
+
+		self.applications.tree = gmenu.lookup_tree(self.cur_menu_names[0], gmenu.FLAGS_SHOW_EMPTY|gmenu.FLAGS_INCLUDE_EXCLUDED|gmenu.FLAGS_INCLUDE_NODISPLAY)
+		self.applications.visible_tree = gmenu.lookup_tree(self.cur_menu_names[0])
+		if self.applications.tree.root == None:
+			if self.using_absolute_menu_names:
+				print "custom system menu file does not exist " + self.cur_menu_names[0]
+				print "loading default system menu " + self.orig_menu_names[0]
+				self.applications.tree = gmenu.lookup_tree(self.orig_menu_names[0], gmenu.FLAGS_SHOW_EMPTY|gmenu.FLAGS_INCLUDE_EXCLUDED|gmenu.FLAGS_INCLUDE_NODISPLAY)
+				self.applications.visible_tree = gmenu.lookup_tree(self.orig_menu_names[0])
+		if self.applications.tree.root == None:
+			raise Exception(_('Cant find menu file - ') + self.cur_menu_names[0])
+
+		if self.using_absolute_menu_names:
+			self.applications.path = self.cur_menu_names[0]
+		else:
+			self.applications.path = os.path.join(util.getUserMenuPath(), self.applications.tree.get_menu_file())
+
 		if not os.path.isfile(self.applications.path):
 			self.applications.dom = xml.dom.minidom.parseString(util.getUserMenuXml(self.applications.tree))
 		else:
@@ -47,8 +88,10 @@ class MenuEditor:
 		self.__remove_whilespace_nodes(self.applications.dom)
 
 		self.settings = Menu() 	 
-		self.settings.tree = gmenu.lookup_tree('settings.menu', gmenu.FLAGS_SHOW_EMPTY|gmenu.FLAGS_INCLUDE_EXCLUDED|gmenu.FLAGS_INCLUDE_NODISPLAY|gmenu.FLAGS_SHOW_ALL_SEPARATORS)
-		self.settings.visible_tree = gmenu.lookup_tree('settings.menu') 	 
+		self.settings.tree = gmenu.lookup_tree(self.cur_menu_names[1], gmenu.FLAGS_SHOW_EMPTY|gmenu.FLAGS_INCLUDE_EXCLUDED|gmenu.FLAGS_INCLUDE_NODISPLAY) 	 
+		self.settings.visible_tree = gmenu.lookup_tree(self.cur_menu_names[1]) 	 
+		if self.settings.tree.root == None:
+			raise Exception(_('Cant find menu file - ') + self.cur_menu_names[1])
 		self.settings.path = os.path.join(util.getUserMenuPath(), self.settings.tree.get_menu_file()) 	 
 		if not os.path.isfile(self.settings.path): 	 
 			self.settings.dom = xml.dom.minidom.parseString(util.getUserMenuXml(self.settings.tree)) 	 
@@ -59,6 +102,7 @@ class MenuEditor:
 		self.save(True)
 
 	def save(self, from_loading=False):
+		print "Enter " + __name__ + ":save"
 		for menu in ('applications', 'settings'):
 			fd = open(getattr(self, menu).path, 'w')
 			fd.write(re.sub("\n[\s]*([^\n<]*)\n[\s]*</", "\\1</", getattr(self, menu).dom.toprettyxml().replace('<?xml version="1.0" ?>\n', '')))
Index: Alacarte/MainWindow.py
===================================================================
--- Alacarte/MainWindow.py.orig
+++ Alacarte/MainWindow.py
@@ -19,6 +19,7 @@
 import gtk, gtk.glade, gmenu, gobject, gio, gnome.ui
 import cgi, os
 import gettext
+from optparse import OptionParser
 import subprocess
 import urllib
 try:
@@ -32,6 +33,7 @@ gtk.glade.textdomain('alacarte')
 _ = gettext.gettext
 from Alacarte.MenuEditor import MenuEditor
 from Alacarte import util
+from Alacarte.SysAdmin import SysAdmin
 
 class MainWindow:
 	timer = None
@@ -42,19 +44,87 @@ class MainWindow:
 	dnd_menus = [('ALACARTE_MENU_ROW', gtk.TARGET_SAME_APP, 0)]
 	dnd_both = [dnd_items[0],] + dnd_menus
 	drag_data = None
+	orig_config_home = None
 	edit_pool = []
 
 	def __init__(self, datadir, version, argv):
+		#print "Enter " + __name__ + ":__init__"
+
+		self.checkRights(argv)
+
 		self.file_path = datadir
 		self.version = version
-		self.editor = MenuEditor()
+		#print "args are ",
+		#print argv
+		print "options are ",
+		print self.options
+		if os.environ.has_key('XDG_CONFIG_HOME'):
+			self.orig_config_home = os.environ['XDG_CONFIG_HOME']
+
+		if(self.options.systemview):
+			print 'setting up system view with dir ',
+			print self.options.systemview
+			if not self.options.systemview.startswith('/'):
+				raise Exception(_('Invalid --system-view path given: ') + self.options.systemview + _('. Relative paths are a security risk'))
+			os.environ['XDG_CONFIG_HOME'] = self.options.systemview
+			os.environ['XDG_DATA_HOME'] = self.options.systemview
+
+			#remove possible duplicate entry - causes gmenu parse errors
+			print 'XDG_CONFIG_DIRS before:' + os.environ['XDG_CONFIG_DIRS']
+			print 'XDG_DATA_DIRS before:' + os.environ['XDG_DATA_DIRS']
+			path_components = os.environ['XDG_CONFIG_DIRS'].split(':')
+			if path_components[0] == self.options.systemview :
+				os.environ['XDG_CONFIG_DIRS'] = ':'.join(path_components[1:])
+			path_components = os.environ['XDG_DATA_DIRS'].split(':')
+			if path_components[0] == self.options.systemview :
+				os.environ['XDG_DATA_DIRS'] = ':'.join(path_components[1:])
+			print 'XDG_CONFIG_DIRS after:' + os.environ['XDG_CONFIG_DIRS']
+			print 'XDG_DATA_DIRS after:' + os.environ['XDG_DATA_DIRS']
+
+			#Fixme - how do I get this filename generically for different distros.
+			fd = open('/etc/profile.d/xdg-environment.sh', 'a+')
+			already_added = False
+			try:
+				for line in fd:
+					if line.startswith('#START  SECTION ADDED BY ALACARTE'):
+						already_added = True
+						continue
+					if already_added:
+						if not line.startswith("export XDG_DATA_DIRS=" + self.options.systemview) :
+							raise Exception(_('Multiple directories not supported. Clear the existing alacarte section from xdg-enviroment'))
+						print 'already got it'
+						break
+				if not already_added:
+					print 'about to add'
+					fd.seek(0, 2) #move to end of file
+					fd.write('#START  SECTION ADDED BY ALACARTE\n')
+					fd.write('export XDG_DATA_DIRS=' + self.options.systemview + ':$XDG_DATA_DIRS\n')
+					fd.write('export XDG_CONFIG_DIRS=' + self.options.systemview + ':$XDG_CONFIG_DIRS\n')
+					fd.write('#END    SECTION ADDED BY ALACARTE\n')
+			finally:
+				fd.close()
+			
+		self.editor = MenuEditor([self.options.menu1, self.options.menu2])
+		self.sysadmin = SysAdmin(self.options.systemview)
+		#self.sysadmin = SysAdmin(False)
+		
 		self.gnome_program = gnome.init('alacarte', version)
+		print "After gnome.init"
 		gtk.window_set_default_icon_name('alacarte')
-		self.tree = gtk.glade.XML(os.path.join(self.file_path, 'alacarte.glade'))
+		print "After set_def_icon"
+		print "self.file_path=" + self.file_path
+
+		self.gladefiledude = os.path.join(self.file_path, 'alacarte.glade')
+		print self.gladefiledude
+		self.tree = gtk.glade.XML(self.gladefiledude)
+		#self.tree = gtk.glade.XML(os.path.join(self.file_path, 'alacarte.glade'))
+
+		print "After glade"
 		signals = {}
 		for attr in dir(self):
 			signals[attr] = getattr(self, attr)
 		self.tree.signal_autoconnect(signals)
+		print "after autoconnect"
 		self.setupMenuTree()
 		self.setupItemTree()
 		self.tree.get_widget('edit_delete').set_sensitive(False)
@@ -63,6 +133,8 @@ class MainWindow:
 		self.tree.get_widget('move_up_button').set_sensitive(False)
 		self.tree.get_widget('move_down_button').set_sensitive(False)
 		self.tree.get_widget('new_separator_button').set_sensitive(False)
+		self.sysadmin.setup_ab(self.tree)
+		self.sysadmin.setup_viewmode(self.tree, self.options.systemview)
 		accelgroup = gtk.AccelGroup()
 		keyval, modifier = gtk.accelerator_parse('<Ctrl>Z')
 		accelgroup.connect_group(keyval, modifier, gtk.ACCEL_VISIBLE, self.on_mainwindow_undo)
@@ -72,21 +144,92 @@ class MainWindow:
 		accelgroup.connect_group(keyval, modifier, gtk.ACCEL_VISIBLE, self.on_help_button_clicked)
 		self.tree.get_widget('mainwindow').add_accel_group(accelgroup)
 		gnome.ui.authentication_manager_init()
+		print "Leave MainWindow:__init__"
+
+	def checkRights(self, argv):
+		#print "Enter checkRights with argv",
+		#print argv
+		gnomesu_option = "--Special_Internal_Only_Option_Indicating_gnomesu_Launch"
+		first_menu = "applications.menu"
+		second_menu = "preferences.menu"
+		
+		parser = OptionParser()
+		#parser.add_option("-s", "--SystemView", action="store_true", dest="systemview",
+		#	default=False, help="Run in system view mode")
+		parser.add_option("--system-view", dest="systemview", metavar="<system_dir>",
+			help="Run in system view mode and use <system_dir>")
+		parser.add_option("--menufile1", dest="menu1", metavar="<menufile1>",
+			help="Filename of menu to display - defaults to " + first_menu)
+		parser.add_option("--menufile2", dest="menu2", metavar="<menufile2>",
+			help="Filename of additional menu to display - defaults to " + second_menu)
+		parser.add_option(gnomesu_option, action="store_true",
+			dest="gnomesu_launched", default=False)
+		
+		(self.options, args) = parser.parse_args()
+		
+		if self.options.systemview and not self.options.gnomesu_launched:
+			print "system view mode requested: launching gnomesu " + argv[0]
+			new_argv = argv[:]
+			new_argv.insert(0, '--')
+			new_argv.insert(1, 'python')
+			new_argv.insert(3, '--')
+			new_argv.append(gnomesu_option)
+			print "args are now ",
+			print new_argv
+		
+			os.execvp("gnomesu", new_argv)
+		
+			#os.execlp("gnomesu", new_argv[0], new_argv[1], new_argv[2], new_argv[3])
+			#args_str = new_argv[0] + " \"" + new_argv[1] + " " + new_argv[2] + " " + new_argv[3] + "\""
+			#print "dude new args_str is " + args_str
+			#os.execlp("gnomesu", new_argv[0] + " " + new_argv[1] + " " + new_argv[2] + " " + new_argv[3])
+			print "SHOULD NEVER NEVER NEVER GET HERE"
+
+		if(not self.options.menu1):
+			self.options.menu1 = first_menu
+		if(not self.options.menu2):
+			self.options.menu2 = second_menu
 
 	def run(self):
+		print "Enter MainWindow:run"
 		self.loadMenus()
 		self.editor.applications.tree.add_monitor(self.menuChanged, None)
 		self.editor.settings.tree.add_monitor(self.menuChanged, None)
 		self.tree.get_widget('mainwindow').show_all()
 		gtk.main()
+		print "Leave MainWindow:run"
+
+	def on_ab_newapps_max_activate (self, entry):
+		print "Enter " + __name__ + ":on_ab_newapps_max_activate"
+		print "text entry is " + entry.get_text()
+		self.sysadmin.setGConfValue(SysAdmin.ab_max_newapps_key, int(entry.get_text()))
+		
+	def on_editing_mode_toggled(self, toggle_button, *a):
+		print toggle_button.get_label()
+		if toggle_button.get_label() == "System view":
+			if toggle_button.get_active():
+				print "system set to active"
+				os.environ['XDG_CONFIG_HOME'] = '/home/user1/mymenus'
+				self.editor.set_absolute_menu_names('/home/user1/mymenus/menus/')
+			else:
+				print "system set to inactive"
+				if self.orig_config_home:
+					os.environ['XDG_CONFIG_HOME'] = self.orig_config_home
+				else:
+					if os.environ.has_key('XDG_CONFIG_HOME'):
+						del os.environ['XDG_CONFIG_HOME']
+				self.editor.remove_absolute_menu_names()
+			self.loadUpdates();
 
 	def menuChanged(self, *a):
+		print "Enter " + __name__ + ":menuChanged"
 		if self.timer:
 			gobject.source_remove(self.timer)
 			self.timer = None
 		self.timer = gobject.timeout_add(3, self.loadUpdates)
 
 	def loadUpdates(self):
+		print "Enter " + __name__ + ":loadUpdates"
 		if not self.allow_update:
 			return False
 		menu_tree = self.tree.get_widget('menu_tree')
@@ -212,6 +355,7 @@ class MainWindow:
 			renderer.set_property('visible', True)
 
 	def loadMenus(self):
+		print "Enter " + __name__ + ":loadMenus"
 		self.menu_store.clear()
 		for menu in self.editor.getMenus():
 			iters = [None]*20
@@ -262,6 +406,8 @@ class MainWindow:
 	def waitForNewItemProcess(self, process, parent_id, file_path):
 		if process.poll() != None:
 			if os.path.isfile(file_path):
+				#hack for broken gnome-desktop-item-edit - makes the file '700'
+				# update - should not need this on 11.0 subprocess.Popen(['chmod', '644', file_path])
 				self.editor.insertExternalItem(os.path.split(file_path)[1], parent_id)
 			return False
 		return True
@@ -273,13 +419,19 @@ class MainWindow:
 			if os.path.isfile(broken_path):
 				os.rename(broken_path, file_path)
 			if os.path.isfile(file_path):
+				#hack for broken gnome-desktop-item-edit - makes the file '700'
+				#update - should not need this on 11.0 subprocess.Popen(['chmod', '644', file_path])
 				self.editor.insertExternalMenu(os.path.split(file_path)[1], parent_id)
 			return False
 		return True
 
 	#this callback keeps you from editing the same item twice
-	def waitForEditProcess(self, process, file_path):
+	def waitForEditProcess(self, process, file_path, broken_path):
 		if process.poll() != None:
+			#hack for broken gnome-desktop-item-edit - see on_edit_properties_activate
+			if broken_path != file_path:
+				if os.path.isfile(broken_path):
+					os.rename(broken_path, file_path)
 			self.edit_pool.remove(file_path)
 			return False
 		return True
@@ -347,6 +499,7 @@ class MainWindow:
 			self.editor.revertMenu(item)
 
 	def on_edit_properties_activate(self, menu):
+		print 'Enter on_edit_properties_activate'
 		item_tree = self.tree.get_widget('item_tree')
 		items, iter = item_tree.get_selection().get_selected()
 		if not iter:
@@ -378,8 +531,21 @@ class MainWindow:
 			self.editor._MenuEditor__addUndo([item,])
 		if file_path not in self.edit_pool:
 			self.edit_pool.append(file_path)
-			process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
-			gobject.timeout_add(100, self.waitForEditProcess, process, file_path)
+
+			#nasty hack for broken gnome-desktop-item-edit in gnome 2.12
+			#when editing a *.directory file it reads/writes
+			#to a hardcoded ".directory" file in the filepath dir and ignores the filename
+			#update - should not need this on 11.0. will test and if confirmed will remove this
+			if file_type == 'Menu' and False:
+				broken_path = os.path.join(os.path.split(file_path)[0], '.directory')
+				data = open(file_path).read()
+				open(broken_path, 'w').write(data)
+			else:
+				broken_path = file_path
+			
+			process = subprocess.Popen(['gnome-desktop-item-edit', broken_path], env=os.environ)
+			#process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
+			gobject.timeout_add(100, self.waitForEditProcess, process, file_path, broken_path)
 
 	def on_menu_tree_cursor_changed(self, treeview):
 		menus, iter = treeview.get_selection().get_selected()
Index: Alacarte/Makefile.am
===================================================================
--- Alacarte/Makefile.am.orig
+++ Alacarte/Makefile.am
@@ -1,7 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 
 appdir = $(pythondir)/Alacarte
-app_PYTHON = __init__.py MainWindow.py MenuEditor.py util.py
+app_PYTHON = __init__.py MainWindow.py MenuEditor.py util.py SysAdmin.py
 nodist_app_PYTHON = config.py
 
 config.py: config.py.in
Index: Alacarte/SysAdmin.py
===================================================================
--- /dev/null
+++ Alacarte/SysAdmin.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+#   Alacarte Menu Editor - Simple fd.o Compliant Menu Editor
+#   Copyright (C) 2006  Novell.
+#
+#   This library is free software; you can redistribute it and/or
+#   modify it under the terms of the GNU Library General Public
+#   License as published by the Free Software Foundation; either
+#   version 2 of the License, or (at your option) any later version.
+#
+#   This library is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   Library General Public License for more details.
+#
+#   You should have received a copy of the GNU Library General Public
+#   License along with this library; if not, write to the Free Software
+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import gtk, gconf
+
+class SysAdmin:
+	ab_max_newapps_prefix = '/desktop/gnome/applications/main-menu'
+	ab_max_newapps_key = ab_max_newapps_prefix + '/ab_new_apps_max_items'
+
+	#Fixme - how do I get this programatically - maybe gconftool-2 --get-default-source
+	#sp1 -  DEFAULTS_SOURCE = 'xml::/etc/opt/gnome/gconf/gconf.xml.defaults'
+	#10.3 - DEFAULTS_SOURCE = 'xml::/etc/gconf/gconf.xml.schemas'
+	DEFAULTS_SOURCE = 'xml::/etc/gconf/gconf.xml.schemas'
+	
+	def __init__(self, system_view):
+		print "SysAdmin::system_view = " + str(system_view)
+		self.system_view = system_view
+		if(self.system_view):
+			engine = gconf.engine_get_for_address(self.DEFAULTS_SOURCE)
+			self.gconf_client = gconf.client_get_for_engine(engine)
+			#engine.unref()
+		else:
+			self.gconf_client = gconf.client_get_default()
+		self.gconf_client.add_dir(self.ab_max_newapps_prefix, gconf.CLIENT_PRELOAD_NONE)
+		print type(self.gconf_client)
+		print "Leave SysAdmin::__init__"
+
+	def getGConfValue (self, key):
+		print "Enter getGConfValue"
+		#if(self.system_view):
+		#	value = self.gconf_client.get_default_from_schema(key);
+		#	retval = value.get_int()
+		#else:
+		#	retval = self.gconf_client.get_int(key)
+
+		retval = self.gconf_client.get_int(key)
+		return retval
+
+	def setGConfValue (self, key, value):
+		print "Enter setGConfValue"
+		#val = self.gconf_client.get_default_from_schema(key);
+		#val.set_int(value)
+		#self.gconf_client.set(key, val)
+
+		self.gconf_client.set_int(key, value)
+
+	def ab_key_changed (self, client, cnxn_id, entry, glade_tree):
+		print "Enter " + __name__ + ":ab_key_changed"
+		if entry.value and entry.value.type == gconf.VALUE_INT:
+			glade_tree.get_widget('ab_newapps_max_spin').set_text(entry.value.to_string())
+		
+	def setup_ab (self, glade_tree):
+		print "Enter setup_ab"
+		glade_tree.get_widget('ab_newapps_max_spin').set_text(str(self.getGConfValue(SysAdmin.ab_max_newapps_key)))
+		self.gconf_client.notify_add(self.ab_max_newapps_key, self.ab_key_changed, glade_tree)
+
+	def setup_viewmode (self, glade_tree, systemview):
+		print "Enter setup_viewmode"
+		if systemview:
+			label = glade_tree.get_widget('system_view_button').get_label()
+			label = label + ':  ' + systemview
+			print label
+			glade_tree.get_widget('system_view_button').set_label(label)
+		else:
+			glade_tree.get_widget('system_view_button').set_active(False)
+			glade_tree.get_widget('user_view_button').set_active(True)
+