# -*- coding: iso-8859-1 -*- import wx import gettext from win32com.shell import shell import win32con import pywintypes import os.path import sys from ConfigParser import SafeConfigParser, Error from uninstallcomponents import UninstallKey _ = wx.GetTranslation def isWin64(): return 'PROGRAMFILES(X86)' in os.environ def split_exe_args(command): if command.startswith('"'): second = command.find('"',1) f = command[1:second] args = command[second+1:].strip() return f, args try: index = command.index(" ") except ValueError: f = command args = "" return f, args while not os.path.isfile(command[:index]): try: index = command.index(" ", index+1) except ValueError: return None, "" return command[:index], command[index+1:] class Component(object): items = ('label','setup','uninstallpattern','setup64') @classmethod def fromConfig(cls, cp, component): try: kwds = dict(cp.items(component)) except Error: kwds = {} return cls(**kwds) def __init__(self, **kwds): for item in self.items: setattr(self, item, kwds.get(item,'')) if not self.setup64: self.setup64 = self.setup class Viewer(object): items = ('name','exe') @classmethod def fromConfig(cls, cp, component): try: kwds = dict(cp.items(component)) except Error: kwds = {} return cls(**kwds) def __init__(self, **kwds): for item in self.items: setattr(self, item, kwds.get(item,'')) class MyFrame(wx.Frame): languages = [ (wx.LANGUAGE_ENGLISH_US,'en','English'), (wx.LANGUAGE_GERMAN,'de','Deutsch'), (wx.LANGUAGE_FRENCH,'fr','Français') ] def __init__(self, *args, **kwargs): for key, default in ( ('language','en'), ('components',[]), ('manual',None), ('protextdir',os.path.normpath(os.path.join(executable(),'../protext'))),('exedir',os.path.dirname(executable())), ('viewer',None) ): try: setattr(self,key,kwargs[key]) del kwargs[key] except KeyError: setattr(self,key,default) kwargs["style"] = wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER wx.Frame.__init__(self, *args, **kwargs) wx.Locale.AddCatalogLookupPathPrefix(os.path.join(exedir,'locale')) self.language = wx.LANGUAGE_DEFAULT self.locale = None self.outer_panel = wx.Panel(self, -1) sizer = wx.BoxSizer() self.outer_panel.SetSizer(sizer) self.main_panel = wx.Panel(self.outer_panel, -1) sizer.Add(self.main_panel, 0, wx.ALL, 5) self.label_language = wx.StaticText(self.main_panel,-1) self.label_doc = wx.StaticText(self.main_panel,-1) self.choice_language = wx.Choice(self.main_panel, -1, choices=[label for id,code,label in self.languages]) self.labels = [wx.StaticText(self.main_panel,-1,c.label) for c in self.components] self.install_buttons = [wx.Button(self.main_panel,-1) for c in self.components] self.uninstall_buttons = [wx.Button(self.main_panel,-1) for c in self.components] self.button_doc = wx.Button(self.main_panel, -1) self.Bind(wx.EVT_BUTTON, self.OnOpenManual, self.button_doc) ## if self.viewer: ## self.button_doc_alternative = wx.Button(self.main_panel, -1) ## self.Bind(wx.EVT_BUTTON, self.OnOpenManual, self.button_doc_alternative) self.button_exit = wx.Button(self.main_panel, -1) self.Bind(wx.EVT_CHOICE, self.OnLanguageSelect, self.choice_language) for button in self.install_buttons: self.Bind(wx.EVT_BUTTON, self.OnInstallButton, button) for button in self.uninstall_buttons: self.Bind(wx.EVT_BUTTON, self.OnUninstallButton, button) self.Bind(wx.EVT_BUTTON, self.OnExit, self.button_exit) self.UpdateLanguage(False) self.__set_properties() self.__do_layout() def __set_properties(self): icon_file = os.path.join("icons","tex.ico") if os.path.exists(icon_file): self.SetIcon(wx.IconFromLocation(wx.IconLocation(icon_file,0))) if self.locale: language = self.locale.GetName().split("_")[0] try: index = [code for id,code,label in self.languages].index(language) self.choice_language.SetSelection(index) except ValueError: self.choice_language.SetSelection(wx.NOT_FOUND) def __do_layout(self): gb_sizer = wx.GridBagSizer(5,5) self.main_panel.SetSizer(gb_sizer) row = 0 gb_sizer.Add(self.label_language, wx.GBPosition(row, 0)) gb_sizer.Add(self.choice_language, wx.GBPosition(row, 1), wx.GBSpan(colspan=2)) row += 1 gb_sizer.Add((1,1), wx.GBPosition(row,0)) row += 1 gb_sizer.Add(self.label_doc, wx.GBPosition(row, 0)) gb_sizer.Add(self.button_doc, wx.GBPosition(row, 1), wx.GBSpan(colspan=2)) ## if not self.viewer: ## gb_sizer.Add(self.button_doc, wx.GBPosition(row, 1), wx.GBSpan(colspan=2)) ## else: ## gb_sizer.Add(self.button_doc, wx.GBPosition(row, 1)) ## gb_sizer.Add(self.button_doc_alternative, wx.GBPosition(row, 2)) row += 1 gb_sizer.Add((1,1), wx.GBPosition(row,0)) for label, install_button, uninstall_button in zip(self.labels, self.install_buttons, self.uninstall_buttons): row += 1 gb_sizer.Add(label, wx.GBPosition(row, 0)) gb_sizer.Add(install_button, wx.GBPosition(row, 1)) gb_sizer.Add(uninstall_button, wx.GBPosition(row, 2)) row += 1 gb_sizer.Add((1,1), wx.GBPosition(row,0)) row += 1 gb_sizer.Add(self.button_exit, wx.GBPosition(row, 0), wx.GBSpan(colspan=3), wx.ALIGN_RIGHT) #gb_sizer.Fit(self) self.outer_panel.GetSizer().Fit(self) self.Layout() def OnOpenManual(self, event): source = event.GetEventObject() code = self.languages[self.choice_language.GetSelection()][1] if self.manual: manual = os.path.join(self.protextdir,self.manual%code) #wx.MessageBox(u"Öffne %s"%manual, "Debug") if self.viewer: # and source is self.button_doc_alternative: viewer = os.path.normpath(os.path.join(self.protextdir,self.viewer.exe)) self.Execute(viewer,args='"%s"'%manual,elevate='never') else: self.Execute(manual,elevate='never') event.Skip() def OnInstallButton(self, event): source = event.GetEventObject() index = self.install_buttons.index(source) setup = self.components[index].setup64 if isWin64() else self.components[index].setup #wx.MessageBox("Starte %s"%setup,"Debug") cmd, args = split_exe_args(setup) cmd = os.path.normpath(os.path.join(self.protextdir, cmd)) #print cmd # Debug if cmd and os.path.exists(cmd): self.Execute(cmd, args) elif cmd: msgbox = wx.MessageDialog(self,_('Cannot execute: ')+cmd, _('Error'), style=wx.OK|wx.CENTER|wx.ICON_ERROR) msgbox.ShowModal() else: msgbox = wx.MessageDialog(self,_('Cannot execute: ')+setup, _('Error'), style=wx.OK|wx.CENTER|wx.ICON_ERROR) msgbox.ShowModal() event.Skip() def OnUninstallButton(self, event): source = event.GetEventObject() index = self.uninstall_buttons.index(source) keys = UninstallKey.fetchUninstallablePrograms(self.components[index].uninstallpattern) if keys: dlg = wx.SingleChoiceDialog(self, _('Select component for uninstallation and click OK'), _('Uninstall component'), [key.name for key in keys]) dlg.SetSelection(0) result = dlg.ShowModal() if result == wx.ID_OK: index = dlg.GetSelection() cmd = keys[index].command cmd, args = split_exe_args(cmd) if cmd: self.Execute(cmd, args) else: msgbox = wx.MessageDialog(self,_('No installed version found'), _('Info'), style=wx.OK|wx.CENTER) msgbox.ShowModal() event.Skip() def OnLanguageSelect(self, event=None): index = self.choice_language.GetSelection() try: self.language = [id for id, code, lan in self.languages][index] except IndexError: self.language = self.languages[0][0] wx.CallAfter(self.UpdateLanguage) if event: event.Skip() def OnExit(self, event): event.Skip() wx.CallAfter(self.Close) def UpdateLanguage(self, redraw=True): if self.locale: del self.locale self.locale = wx.Locale(self.language) if not self.locale.IsOk(): del self.locale self.locale = wx.Locale(self.languages[0][0]) self.locale.AddCatalog('protext') if not self.locale.IsLoaded('protext'): del self.locale self.locale = wx.Locale(self.languages[0][0]) self.locale.AddCatalog('protext') self.label_language.SetLabel(_("Language:")) self.label_doc.SetLabel(_("Manual:")) for button in self.install_buttons: button.SetLabel(_("Install")) for button in self.uninstall_buttons: button.SetLabel(_("Uninstall")) self.button_doc.SetLabel(_("Open")) ## if self.viewer: ## self.button_doc_alternative.SetLabel("%s (%s %s)"%(_("Open"),_("with"),viewer.name)) self.button_exit.SetLabel(_("Exit")) if redraw: self.outer_panel.GetSizer().Fit(self) self.Layout() self.Update() def Execute(self, path, args="", **kwargs): elevate = kwargs.get('elevate','ifneeded') action = "runas" if elevate=='always' else "open" try: shell.ShellExecuteEx( fMask = 0, nShow = win32con.SW_NORMAL, lpVerb = action, lpFile = path, lpDirectory = os.path.dirname(path), lpParameters = args ) except pywintypes.error, error: if elevate=='ifneeded' and error.winerror==5: self.Execute(path, *args, elevate='always') else: msgbox = wx.MessageDialog(self,_("Running %s failed with the following error:")%" ".join([path,args])+"\n\n%s"%error.strerror,_("Error"), style=wx.OK|wx.CENTER|wx.ICON_ERROR) msgbox.ShowModal() msgbox.Destroy() def executable(): if hasattr(sys,'frozen'): path = sys.executable else: path = sys.argv[0] path = os.path.abspath(path) return path if __name__ == "__main__": #gettext.install('protext','./locale', unicode=False) cp = SafeConfigParser() exedir = os.path.dirname(executable()) cp.read([os.path.join(exedir,'protext.ini')]) protextdir = os.path.normpath(os.path.join(exedir,cp.get('General','protextdir'))) #print protextdir components = cp.get('General', 'components').split() components = [Component.fromConfig(cp, component) for component in components] manual = cp.get('General','manual',raw=True) viewer = Viewer.fromConfig(cp, 'PdfViewer') if not viewer.exe or not os.path.exists(os.path.join(protextdir,viewer.exe)): viewer = None app = wx.PySimpleApp(0) wx.InitAllImageHandlers() frame_main = MyFrame(None, -1, "proTeXt", protextdir=protextdir, exedir=exedir, manual=manual, components=components, language='de', viewer=viewer) app.SetTopWindow(frame_main) frame_main.Show() app.MainLoop()