PackageManager.py 8.63 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
import W
import Wapplication
from Carbon import Evt
import EasyDialogs
import FrameWork

import sys
import string
import os

import pimp

ELIPSES = '...'
		
15
class PackageManagerMain(Wapplication.Application):
16 17
	
	def __init__(self):
18
		self.preffilepath = os.path.join("Python", "Package Install Manager Prefs")
19 20 21 22 23 24 25 26 27 28 29 30
		Wapplication.Application.__init__(self, 'Pimp')
		from Carbon import AE
		from Carbon import AppleEvents
		
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments, 
				self.ignoreevent)
		AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication, 
				self.quitevent)
31
		if 1:
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
			import PyConsole
			# With -D option (OSX command line only) keep stderr, for debugging the IDE
			# itself.
			debug_stderr = None
			if len(sys.argv) >= 2 and sys.argv[1] == '-D':
				debug_stderr = sys.stderr
				del sys.argv[1]
			PyConsole.installoutput()
			if debug_stderr:
				sys.stderr = debug_stderr
		self.opendoc(None)
		self.mainloop()
		
	def makeusermenus(self):
		m = Wapplication.Menu(self.menubar, "File")
47
##		newitem = FrameWork.MenuItem(m, "Open Standard Database", "N", 'openstandard')
48 49 50 51 52
##		openitem = FrameWork.MenuItem(m, "Open"+ELIPSES, "O", 'open')
##		openbynameitem = FrameWork.MenuItem(m, "Open URL"+ELIPSES, "D", 'openbyname')
		FrameWork.Separator(m)
		closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
##		saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
53
##		saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
		FrameWork.Separator(m)
		
		m = Wapplication.Menu(self.menubar, "Edit")
		undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
		FrameWork.Separator(m)
		cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
		copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
		pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
		FrameWork.MenuItem(m, "Clear", None,  "clear")
		FrameWork.Separator(m)
		selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
		
		m = Wapplication.Menu(self.menubar, "Package")
		runitem = FrameWork.MenuItem(m, "Install", "I", 'install')
		homepageitem = FrameWork.MenuItem(m, "Visit Homepage", None, 'homepage')
		
		self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
		self.makeopenwindowsmenu()
		self._menustocheck = [closeitem, saveasitem, 
				undoitem, cutitem, copyitem, pasteitem, 
				selallitem,
				runitem, homepageitem]
			
	def quitevent(self, theAppleEvent, theReply):
		from Carbon import AE
		AE.AEInteractWithUser(50000000)
		self._quit()
		
	def ignoreevent(self, theAppleEvent, theReply):
		pass
	
	def opendocsevent(self, theAppleEvent, theReply):
		W.SetCursor('watch')
		import aetools
		parameters, args = aetools.unpackevent(theAppleEvent)
		docs = parameters['----']
		if type(docs) <> type([]):
			docs = [docs]
		for doc in docs:
			fsr, a = doc.FSResolveAlias(None)
			path = fsr.as_pathname()
			path = urllib.pathname2url(path)
			self.opendoc(path)
	
	def opendoc(self, url):
		PackageBrowser(url)
	
	def getabouttext(self):
102
		return "About Package Manager"+ELIPSES
103 104
	
	def do_about(self, id, item, window, event):
105
		EasyDialogs.Message("Package Install Manager for Python")
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
			
	def domenu_open(self, *args):
		filename = EasyDialogs.AskFileForOpen(typeList=("TEXT",))
		if filename:
			filename = urllib.pathname2url(filename)
			self.opendoc(filename)
	
	def domenu_openbyname(self, *args):
		url = EasyDialogs.AskString("Open URL:", ok="Open")
		if url:
			self.opendoc(url)
		
	def makeopenwindowsmenu(self):
		for i in range(len(self.openwindowsmenu.items)):
			self.openwindowsmenu.menu.DeleteMenuItem(1)
			self.openwindowsmenu.items = []
		windows = []
		self._openwindows = {}
		for window in self._windows.keys():
			title = window.GetWTitle()
			if not title:
				title = "<no title>"
			windows.append((title, window))
		windows.sort()
		for title, window in windows:
			shortcut = None
			item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
			self._openwindows[item.item] = window
		self._openwindowscheckmark = 0
		self.checkopenwindowsmenu()
		
	def domenu_openwindows(self, id, item, window, event):
		w = self._openwindows[item]
		w.ShowWindow()
		w.SelectWindow()
	
	def domenu_quit(self):
		self._quit()
	
	def domenu_save(self, *args):
		print "Save"
	
	def _quit(self):
##		import PyConsole, PyEdit
		for window in self._windows.values():
			try:
				rv = window.close() # ignore any errors while quitting
			except:
				rv = 0   # (otherwise, we can get stuck!)
			if rv and rv > 0:
				return
##		try:
##			PyConsole.console.writeprefs()
##			PyConsole.output.writeprefs()
##			PyEdit.searchengine.writeprefs()
##		except:
##			# Write to __stderr__ so the msg end up in Console.app and has
##			# at least _some_ chance of getting read...
##			# But: this is a workaround for way more serious problems with
##			# the Python 2.2 Jaguar addon.
##			sys.__stderr__.write("*** PythonIDE: Can't write preferences ***\n")
		self.quitting = 1
		
class PimpInterface:

	def setuppimp(self, url):
		self.pimpprefs = pimp.PimpPreferences()
		self.pimpdb = pimp.PimpDatabase(self.pimpprefs)
174
		self.pimpinstaller = pimp.PimpInstaller(self.pimpdb)
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
		if not url:
			url = self.pimpprefs.pimpDatabase
		self.pimpdb.appendURL(url)

	def getbrowserdata(self):
		self.packages = self.pimpdb.list()
		rv = []
		for pkg in self.packages:
			name = pkg.fullname()
			status, _ = pkg.installed()
			description = pkg.description()
			rv.append((status, name, description))
		return rv
		
	def getstatus(self, number):
		pkg = self.packages[number]
		return pkg.installed()
192 193 194 195 196 197 198 199
		
	def installpackage(self, sel, output, recursive, force):
		pkg = self.packages[sel]
		list, messages = self.pimpinstaller.prepareInstall(pkg, force, recursive)
		if messages:
			return messages
		messages = self.pimpinstaller.install(list, output)
		return messages
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
			
class PackageBrowser(PimpInterface):
	
	def __init__(self, url = None):
		self.ic = None
		self.setuppimp(url)
		self.setupwidgets()
		self.updatestatus()
	
	def setupwidgets(self): 
		self.w = W.Window((580, 400), "Python Install Manager", minsize = (300, 200), tabbable = 0)
##		self.w.divline = W.HorizontalLine((0, 20, 0, 0))
		self.w.titlebar = W.TextBox((4, 4, 40, 12), 'Packages:')
		data = self.getbrowserdata()
		self.w.packagebrowser = W.MultiList((4, 20, 0, -70), data, self.listhit, cols=3)
		self.w.installed_l = W.TextBox((4, -66, 60, 12), 'Installed:')
		self.w.installed = W.TextBox((64, -66, 0, 12), '')
		self.w.message_l = W.TextBox((4, -48, 60, 12), 'Status:')
		self.w.message = W.TextBox((64, -48, 0, 12), '')
		self.w.homepage_button = W.Button((4, -28, 96, 18), 'View homepage', self.do_homepage)
220 221 222
		self.w.verbose_button = W.CheckBox((-288, -26, 60, 18), 'Verbose')
		self.w.recursive_button = W.CheckBox((-224, -26, 80, 18), 'Recursive', self.updatestatus)
		self.w.recursive_button.set(1)
223 224 225 226 227 228
		self.w.force_button = W.CheckBox((-140, -26, 60, 18), 'Force', self.updatestatus)
		self.w.install_button = W.Button((-76, -28, 56, 18), 'Install', self.do_install)
		self.w.open()
		
	def updatestatus(self):
		sel = self.w.packagebrowser.getselection()
229 230
		data = self.getbrowserdata()
		self.w.packagebrowser.setitems(data)
231 232 233 234 235 236
		if len(sel) != 1:
			self.w.installed.set('')
			self.w.message.set('')
			self.w.install_button.enable(0)
			self.w.homepage_button.enable(0)
			self.w.verbose_button.enable(0)
237
			self.w.recursive_button.enable(0)
238 239 240
			self.w.force_button.enable(0)
		else:
			sel = sel[0]
241
			self.w.packagebrowser.setselection([sel])
242 243 244 245 246 247
			installed, message = self.getstatus(sel)
			self.w.installed.set(installed)
			self.w.message.set(message)
			self.w.install_button.enable(installed != "yes" or self.w.force_button.get())
			self.w.homepage_button.enable(not not self.packages[sel].homepage())
			self.w.verbose_button.enable(1)
248
			self.w.recursive_button.enable(1)
249 250 251 252 253 254
			self.w.force_button.enable(1)
		
	def listhit(self, *args, **kwargs):
		self.updatestatus()
		
	def do_install(self):
255 256 257 258 259 260 261 262 263 264 265
		sel = self.w.packagebrowser.getselection()[0]
		if self.w.verbose_button.get():
			output = sys.stdout
		else:
			output = None
		recursive = self.w.recursive_button.get()
		force = self.w.force_button.get()
		messages = self.installpackage(sel, output, recursive, force)
		self.updatestatus()
		if messages:
			EasyDialogs.Message('\n'.join(messages))
266 267 268 269 270 271 272 273 274 275
		
	def do_homepage(self):
		sel = self.w.packagebrowser.getselection()[0]
		if not self.ic:
			import ic
			
			self.ic = ic.IC()
		self.ic.launchurl(self.packages[sel].homepage())
		
if __name__ == '__main__':
276
	PackageManagerMain()