#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2007 Pâris Quentin # Copyright (C) 2007-2010 PlayOnLinux Team # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import wxversion, os, getopt, sys, urllib, signal, socket, codecs, string, shutil, time, urllib, urllib2 import wx, wx.animate import lib.Variables as Variables import lib.lng, threading if(os.environ["POL_OS"] == "Mac"): os_pref = "darwin" else: os_pref = "linux" lib.lng.Lang() timeout = 2 #socket.setdefaulttimeout(timeout) def SetWineVersion(game, version): cfile = Variables.playonlinux_rep+"shortcuts/"+game fichier = open(cfile,"r").readlines() i = 0 line = [] while(i < len(fichier)): # On retire l'eventuel fichier[i] = fichier[i].replace("\n","") if("PATH=" not in fichier[i] or "WineVersions" not in fichier[i]): line.append(fichier[i]) i += 1 fichier_write = open(cfile,"w") if(version != "System"): # On insere if(os.environ["POL_OS"] == "Mac"): line.insert(1,"PATH=\""+Variables.playonlinux_rep+"WineVersions/"+version+"/bin/:$PATH\"") line.insert(1,"LD_LIBRARY_PATH=\""+Variables.playonlinux_rep+"WineVersions/"+version+"/lib/:$LD_LIBRARY_PATH\"") else: line.insert(1,"PATH=\""+Variables.playonlinux_rep+"WineVersions/"+version+"/usr/bin/:$PATH\"") line.insert(1,"LD_LIBRARY_PATH=\""+Variables.playonlinux_rep+"WineVersions/"+version+"/usr/lib/:$LD_LIBRARY_PATH\"") i = 0 while(i < len(line)): # On ecrit fichier_write.write(line[i]+"\n") i+=1 def GetWineVersion(game): cfile = Variables.playonlinux_rep+"shortcuts/"+game fichier = open(cfile,"r").readlines() i = 0 line = "" while(i < len(fichier)): fichier[i] = fichier[i].replace("\n","") if("PATH=" in fichier[i] and "WineVersions" in fichier[i]): line = fichier[i].replace("//","/") i += 1 if(line == ""): version = "System" else: version=line.replace("PATH=","").replace("\"","").replace(Variables.playonlinux_rep,"").replace("//","/") version = string.split(version,"/") version = version[1] return(version) def keynat(string): r'''A natural sort helper function for sort() and sorted() without using regular expressions or exceptions. >>> items = ('Z', 'a', '10th', '1st', '9') >>> sorted(items) ['10th', '1st', '9', 'Z', 'a'] >>> sorted(items, key=keynat) ['1st', '9', '10th', 'a', 'Z'] Borrowed from http://code.activestate.com/recipes/285264/#c6 by paul clinch. License is the PSF Python License, http://www.python.org/psf/license/ (GPL compatible) ''' it = type(1) r = [] for c in string: if c.isdigit(): d = int(c) if r and type( r[-1] ) == it: r[-1] = r[-1] * 10 + d else: r.append(d) else: r.append(c.lower()) return r class getVersions(threading.Thread): def __init__(self, arch="x86"): threading.Thread.__init__(self) self.thread_message = "#WAIT#" self.versions = [] self.architecture = arch self.start() def download(self, game): self.getDescription = game def run(self): self.thread_running = True while(self.thread_running): if(self.thread_message == "get"): wfolder = os_pref+"-"+self.architecture try : socket.setdefaulttimeout(timeout) url = os.environ["WINE_SITE"]+"/"+wfolder+".lst" #print(url) req = urllib2.Request(url) handle = urllib2.urlopen(req) time.sleep(1) socket.setdefaulttimeout(None) available_versions = handle.read() available_versions = string.split(available_versions,"\n") self.i = 0 self.versions_ = [] while(self.i < len(available_versions) - 1): informations = string.split(available_versions[self.i], ";") version = informations[1] package = informations[0] sha1sum = informations[2] if(not os.path.exists(Variables.playonlinux_rep+"/wine/"+wfolder+"/"+version)): self.versions_.append(version) self.i += 1 self.versions_.reverse() self.versions = self.versions_[:] self.thread_message = "Ok" except : time.sleep(1) self.thread_message = "Err" self.versions = ["Wine packages website is unavailable"] socket.setdefaulttimeout(None) else: time.sleep(0.2) class Onglets(wx.Notebook): # Classe dérivée du wx.Notebook def __init__(self, parent): self.notebook = wx.Notebook.__init__(self, parent, -1) self.images_onglets = wx.ImageList(16, 16) self.images_onglets.Add(wx.Bitmap(Variables.playonlinux_env+"/etc/onglet/wine.png")) self.SetImageList(self.images_onglets) self.panelFenp = {} self.imagesapps = {} self.imagesapps_i = {} self.list_apps = {} self.new_panel = {} self.list_ver_installed = {} self.button_rm = {} self.button_in = {} def liste_versions(self, arch="x86"): if(arch == "amd64"): add=100 else: add=0 self.panelFenp[arch] = wx.Panel(self, -1) self.imagesapps[arch] = wx.ImageList(22, 22) self.imagesapps_i[arch] = wx.ImageList(22, 22) self.list_apps[arch] = wx.TreeCtrl(self.panelFenp[arch], 106+add, style=wx.TR_HIDE_ROOT|wx.TR_FULL_ROW_HIGHLIGHT|Variables.widget_borders, size=(320, 300), pos=(10,35)) self.list_apps[arch].SetImageList(self.imagesapps[arch]) self.list_apps[arch].SetSpacing(0); self.new_panel[arch] = wx.Panel(self.panelFenp[arch], -1, pos=(10,505), size=(100,100)) self.list_ver_installed[arch] = wx.TreeCtrl(self.panelFenp[arch], 107+add, style=wx.TR_HIDE_ROOT|wx.TR_FULL_ROW_HIGHLIGHT|Variables.widget_borders, size=(320, 300), pos=(400,35)) self.list_ver_installed[arch].SetImageList(self.imagesapps_i[arch]) self.list_ver_installed[arch].SetSpacing(0); wx.StaticText(self.panelFenp[arch], -1, _("Installed Wine versions: "),(395,10)) wx.StaticText(self.panelFenp[arch], -1, _("Available Wine versions: "),(5,10)) self.button_rm[arch] = wx.Button(self.panelFenp[arch], 108+add, "<", pos=(340, 175), size=(50,30)) self.button_in[arch] = wx.Button(self.panelFenp[arch], 109+add,">", pos=(340, 125), size=(50,30)) self.button_rm[arch].Enable(False) self.button_in[arch].Enable(False) self.AddPage(self.panelFenp[arch], _("Wine versions")+" ("+arch+")", imageId=0) class MainWindow(wx.Frame): def __init__(self,parent,id,title): self.download32 = getVersions("x86") if(os.environ["AMD64_COMPATIBLE"] == "True"): self.download64 = getVersions("amd64") wx.Frame.__init__(self, parent, -1, title, size = (750, 400+Variables.windows_add_size), style = wx.CLOSE_BOX | wx.CAPTION | wx.MINIMIZE_BOX) self.timer = wx.Timer(self, 1) self.SetIcon(wx.Icon(Variables.playonlinux_env+"/etc/playonlinux.png", wx.BITMAP_TYPE_ANY)) #self.panel = wx.Panel(self, -1) self.onglets = Onglets(self) #self.sizer = wx.BoxSizer(wx.VERTICAL) #self.sizer.Add(self.onglets, 15, wx.EXPAND|wx.ALL, 2) self.getVersions("x86") if(os.environ["AMD64_COMPATIBLE"] == "True"): self.getVersions("amd64") #self.panel.SetSizer(self.sizer) #self.panel.SetAutoLayout(True) self.onglets.liste_versions() if(os.environ["AMD64_COMPATIBLE"] == "True"): self.onglets.liste_versions("amd64") self.oldreload32="" if(os.environ["AMD64_COMPATIBLE"] == "True"): self.oldreload64="" self.oldversions32 = [] if(os.environ["AMD64_COMPATIBLE"] == "True"): self.oldversions64 = [] #self.button = wx.Button(self.panels_buttons, wx.ID_CLOSE, _("Close"), pos=(510, 5), size=wx.DefaultSize) wx.EVT_BUTTON(self, wx.ID_CLOSE, self.closeapp) wx.EVT_CLOSE(self, self.closeapp) wx.EVT_TREE_SEL_CHANGED(self, 106, self.unselect32) wx.EVT_TREE_SEL_CHANGED(self, 107, self.unselect32) wx.EVT_BUTTON(self, 108, self.delete32) wx.EVT_BUTTON(self, 109, self.install32) wx.EVT_TREE_SEL_CHANGED(self, 206, self.unselect64) wx.EVT_TREE_SEL_CHANGED(self, 207, self.unselect64) wx.EVT_BUTTON(self, 208, self.delete64) wx.EVT_BUTTON(self, 209, self.install64) self.Bind(wx.EVT_TIMER, self.AutoReload, self.timer) self.timer.Start(200) def AutoReload(self, event): reload32 = os.listdir(Variables.playonlinux_rep+"/wine/"+os_pref+"-x86") if(os.environ["AMD64_COMPATIBLE"] == "True"): reload64 = os.listdir(Variables.playonlinux_rep+"/wine/"+os_pref+"-amd64") if(self.download32.thread_message == "Ok" or self.download32.thread_message == "Err"): self.onglets.new_panel["x86"].Hide() self.WriteVersion() self.download32.thread_message = "Wait" else: if(self.download32.thread_message != "Wait"): self.onglets.new_panel["x86"].Show() if(os.environ["AMD64_COMPATIBLE"] == "True"): if(self.download64.thread_message == "Ok" or self.download64.thread_message == "Err"): self.onglets.new_panel["amd64"].Hide() self.WriteVersion("amd64") self.download64.thread_message = "Wait" else: if(self.download64.thread_message != "Wait"): self.onglets.new_panel["amd64"].Show() if(os.environ["AMD64_COMPATIBLE"] == "True"): if(reload64 != self.oldreload64): self.getVersions("amd64") self.oldreload64 = reload64 if(reload32 != self.oldreload32): self.getVersions() self.oldreload32 = reload32 if(self.download32.versions != self.oldversions32): self.oldversions32 = self.download32.versions[:] if(os.environ["AMD64_COMPATIBLE"] == "True"): if(self.download64.versions != self.oldversions64): self.oldversions64 = self.download64.versions[:] def sizedirectory(self, path): size = 0 for root, dirs, files in os.walk(path): for fic in files: size += os.path.getsize(os.path.join(root, fic)) return size def unselect32(self, event): if(event.GetId() == 106): self.onglets.list_ver_installed["x86"].UnselectAll() self.onglets.button_rm["x86"].Enable(False) self.onglets.button_in["x86"].Enable(True) if(event.GetId() == 107): self.onglets.list_apps["x86"].UnselectAll() self.onglets.button_rm["x86"].Enable(True) self.onglets.button_in["x86"].Enable(False) def delete32(self, event): version = self.onglets.list_ver_installed["x86"].GetItemText(self.onglets.list_ver_installed["x86"].GetSelection()).encode('utf-8') if(wx.YES == wx.MessageBox(_('Are you sure you want to delete wine {0}?').format(version).decode("utf-8"), style=wx.YES_NO | wx.ICON_QUESTION)): shutil.rmtree(Variables.playonlinux_rep+"/wine/"+os_pref+"-x86/"+version) def install32(self, event): install = self.onglets.list_apps["x86"].GetItemText(self.onglets.list_apps["x86"].GetSelection()).encode('utf-8') os.system("bash \""+Variables.playonlinux_env+"/bash/install_wver\" "+install+" x86 &") def unselect64(self, event): if(event.GetId() == 206): self.onglets.list_ver_installed["amd64"].UnselectAll() self.onglets.button_rm["amd64"].Enable(False) self.onglets.button_in["amd64"].Enable(True) if(event.GetId() == 207): self.onglets.list_apps["amd64"].UnselectAll() self.onglets.button_rm["amd64"].Enable(True) self.onglets.button_in["amd64"].Enable(False) def delete64(self, event): version = self.onglets.list_ver_installed["amd64"].GetItemText(self.onglets.list_ver_installed["amd64"].GetSelection()).encode('utf-8') if(wx.YES == wx.MessageBox("Are you sure you want to delete wine "+version+"?", style=wx.YES_NO | wx.ICON_QUESTION)): shutil.rmtree(Variables.playonlinux_rep+"/wine/"+os_pref+"-amd64/"+version) def install64(self, event): install = self.onglets.list_apps["amd64"].GetItemText(self.onglets.list_apps["amd64"].GetSelection()).encode('utf-8') os.system("bash \""+Variables.playonlinux_env+"/bash/install_wver\" "+install+" amd64 &") def getVersions(self, arch="x86"): if(arch == "x86"): self.download32.thread_message = "get" if(arch == "amd64"): self.download64.thread_message = "get" def WriteVersion(self, arch="x86"): self.onglets.imagesapps[arch].RemoveAll() self.onglets.imagesapps_i[arch].RemoveAll() self.onglets.list_apps[arch].DeleteAllItems() self.onglets.list_ver_installed[arch].DeleteAllItems() root = self.onglets.list_apps[arch].AddRoot("") self.i = 0 if(arch == "x86"): while(self.i < len(self.download32.versions)): self.onglets.imagesapps[arch].Add(wx.Bitmap(Variables.playonlinux_env+"/etc/install/wine-packages.png")) self.onglets.list_apps[arch].AppendItem(root,self.download32.versions[self.i],self.i) self.i += 1 if(arch == "amd64"): while(self.i < len(self.download64.versions)): self.onglets.imagesapps[arch].Add(wx.Bitmap(Variables.playonlinux_env+"/etc/install/wine-packages.png")) self.onglets.list_apps[arch].AppendItem(root,self.download64.versions[self.i],self.i) self.i += 1 root2 = self.onglets.list_ver_installed[arch].AddRoot("") wfolder = os_pref+"-"+arch installed_versions = os.listdir(Variables.playonlinux_rep+"/wine/"+wfolder) installed_versions.sort(key=keynat) installed_versions.reverse() self.i = 0 self.j = 0 while(self.i < len(installed_versions)): if(os.path.isdir(Variables.playonlinux_rep+"/wine/"+wfolder+"/"+installed_versions[self.i])): if(len(os.listdir(Variables.playonlinux_rep+"/wine/"+wfolder+"/"+installed_versions[self.i])) == 0): self.onglets.imagesapps_i[arch].Add(wx.Bitmap(Variables.playonlinux_env+"/etc/install/wine-warning.png")) else: self.onglets.imagesapps_i[arch].Add(wx.Bitmap(Variables.playonlinux_env+"/etc/install/wine.png")) self.onglets.list_ver_installed[arch].AppendItem(root2,installed_versions[self.i],self.j) self.j += 1 self.i += 1 try : if(versions[0] == "Wine packages website is unavailable"): self.onglets.list_apps[arch].Enable(False) self.onglets.imagesapps[arch].RemoveAll() except : pass self.onglets.button_rm[arch].Enable(False) self.onglets.button_in[arch].Enable(False) def closeapp(self, event): self.download32.thread_running = False if(os.environ["AMD64_COMPATIBLE"] == "True"): self.download64.thread_running = False self.Destroy()