#!/usr/bin/python ######################################################################### # # Author : Choopan RATTANAPOKA, Jie Yang, Arno Bakker # # Description : Main ABC [Yet Another Bittorrent Client] python script. # you can run from source code by using # >python abc.py # need Python, WxPython in order to run from source code. ######################################################################### # Arno: G*dd*mn M2Crypto overrides the method for https:// in the # standard Python libraries. This causes msnlib to fail and makes Tribler # freakout when "http://www.tribler.org/version" is redirected to # "https://www.tribler.org/version/" (which happened during our website # changeover) Until M2Crypto 0.16 is patched I'll restore the method to the # original, as follows. # # This must be done in the first python file that is started. # import urllib original_open_https = urllib.URLopener.open_https import M2Crypto urllib.URLopener.open_https = original_open_https import sys, locale import os import wx, commands from wx import xrc #import hotshot if sys.platform == "darwin": # on Mac, we can only load VLC libraries # relative to the location of tribler.py os.chdir(os.path.abspath(os.path.dirname(sys.argv[0]))) from threading import Thread, Timer, Event,currentThread,enumerate from time import time, ctime, sleep from traceback import print_exc, print_stack from cStringIO import StringIO import urllib from interconn import ServerListener, ClientPassParam from launchmanycore import ABCLaunchMany from ABC.Toolbars.toolbars import ABCBottomBar2, ABCStatusBar, ABCMenuBar, ABCToolBar from ABC.GUI.menu import ABCMenu from ABC.Scheduler.scheduler import ABCScheduler from webservice import WebListener if (sys.platform == 'win32'): from Dialogs.regdialog import RegCheckDialog from ABC.GUI.list import ManagedList from Utility.utility import Utility from Utility.constants import * #IGNORE:W0611 from Tribler.__init__ import tribler_init, tribler_done from BitTornado.__init__ import product_name from safeguiupdate import DelayedInvocation,FlaglessDelayedInvocation import webbrowser from Tribler.Dialogs.MugshotManager import MugshotManager from Tribler.vwxGUI.GuiUtility import GUIUtility import Tribler.vwxGUI.updateXRC as updateXRC from Tribler.Video.VideoPlayer import VideoPlayer,return_feasible_playback_modes,PLAYBACKMODE_INTERNAL from Tribler.Video.VideoServer import VideoHTTPServer from Tribler.Dialogs.GUIServer import GUIServer from Tribler.vwxGUI.TasteHeart import set_tasteheart_bitmaps from Tribler.vwxGUI.perfBar import set_perfBar_bitmaps from Tribler.Dialogs.BandwidthSelector import BandwidthSelector from Tribler.Subscriptions.rss_client import TorrentFeedThread from Tribler.Dialogs.activities import * from Tribler.notification import init as notification_init from Tribler.vwxGUI.font import * from Tribler.Web2.util.update import Web2Updater DEBUG = False ALLOW_MULTIPLE = False start_time = 0 start_time2 = 0 ################################################################ # # Class: FileDropTarget # # To enable drag and drop for ABC list in main menu # ################################################################ class FileDropTarget(wx.FileDropTarget): def __init__(self, utility): # Initialize the wsFileDropTarget Object wx.FileDropTarget.__init__(self) # Store the Object Reference for dropped files self.utility = utility def OnDropFiles(self, x, y, filenames): for filename in filenames: self.utility.queue.addtorrents.AddTorrentFromFile(filename) return True ############################################################## # # Class : ABCList # # ABC List class that contains the torrent list # ############################################################## class ABCList(ManagedList): def __init__(self, parent): style = wx.LC_REPORT|wx.LC_VRULES|wx.CLIP_CHILDREN prefix = 'column' minid = 4 maxid = 26 exclude = [] rightalign = [COL_PROGRESS, COL_SIZE, COL_DLSPEED, COL_ULSPEED, COL_RATIO, COL_PEERPROGRESS, COL_DLSIZE, COL_ULSIZE, COL_TOTALSPEED] ManagedList.__init__(self, parent, style, prefix, minid, maxid, exclude, rightalign) dragdroplist = FileDropTarget(self.utility) self.SetDropTarget(dragdroplist) self.lastcolumnsorted = -1 self.reversesort = 0 self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColLeftClick) self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnItemSelected) # Bring up advanced details on left double click self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick) # Bring up local settings on middle double click self.Bind(wx.EVT_MIDDLE_DCLICK, self.utility.actions[ACTION_LOCALUPLOAD].action) # Do thing when keys are pressed down def OnKeyDown(self, event): keycode = event.GetKeyCode() if event.CmdDown(): if keycode == ord('a') or keycode == ord('A'): # Select all files (CTRL-A) self.selectAll() elif keycode == ord('x') or keycode == ord('X'): # Invert file selection (CTRL-X) self.invertSelection() elif keycode == wx.WXK_RETURN or keycode == wx.WXK_NUMPAD_ENTER: # Open advanced details (Enter) self.utility.actions[ACTION_DETAILS].action() elif keycode == wx.WXK_SPACE: # Open local settings (Space) self.utility.actions[ACTION_LOCALUPLOAD].action() elif keycode == 399: # Open right-click menu (windows menu key) self.OnItemSelected() event.Skip() def OnColLeftClick(self, event): rank = event.GetColumn() colid = self.columns.getIDfromRank(rank) if colid == self.lastcolumnsorted: self.reversesort = 1 - self.reversesort else: self.reversesort = 0 self.lastcolumnsorted = colid self.utility.queue.sortList(colid, self.reversesort) def selectAll(self): self.updateSelected(select = range(0, self.GetItemCount())) def updateSelected(self, unselect = None, select = None): if unselect is not None: for index in unselect: self.SetItemState(index, 0, wx.LIST_STATE_SELECTED) if select is not None: for index in select: self.Select(index) self.SetFocus() def getTorrentSelected(self, firstitemonly = False, reverse = False): queue = self.utility.queue torrentselected = [] for index in self.getSelected(firstitemonly, reverse): ABCTorrentTemp = queue.getABCTorrent(index = index) if ABCTorrentTemp is not None: torrentselected.append(ABCTorrentTemp) return torrentselected def OnItemSelected(self, event = None): selected = self.getTorrentSelected() if not selected: return popupmenu = ABCMenu(self.utility, 'menu_listrightclick') # Popup the menu. If an item is selected then its handler # will be called before PopupMenu returns. if event is None: # use the position of the first selected item (key event) ABCTorrentTemp = selected[0] position = self.GetItemPosition(ABCTorrentTemp.listindex) else: # use the cursor position (mouse event) position = event.GetPosition() self.PopupMenu(popupmenu, position) def OnLeftDClick(self, event): event.Skip() try: self.utility.actions[ACTION_DETAILS].action() except: print_exc() ############################################################## # # Class : ABCPanel # # Main ABC Panel class # ############################################################## class ABCPanel(wx.Panel): def __init__(self, parent): style = wx.CLIP_CHILDREN wx.Panel.__init__(self, parent, -1, style = style) #Debug Output. sys.stdout.write('Preparing GUI.\n'); self.utility = parent.utility self.utility.window = self self.queue = self.utility.queue # List of deleting torrents events that occur when the RateManager is active # Such events are processed after the RateManager finishes # postponedevents is a list of tupples : each tupple contains the method of ABCPanel to be called to # deal with the event and the event. self.postponedevents = [] #Manual Bittorrent Adding UI ############################## colSizer = wx.BoxSizer(wx.VERTICAL) self.list = ABCList(self) self.utility.list = self.list colSizer.Add(self.list, 1, wx.ALL|wx.EXPAND, 3) """ # Add status bar statbarbox = wx.BoxSizer(wx.HORIZONTAL) self.sb_buttons = ABCStatusButtons(self,self.utility) statbarbox.Add(self.sb_buttons, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 0) self.abc_sb = ABCStatusBar(self,self.utility) statbarbox.Add(self.abc_sb, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 0) colSizer.Add(statbarbox, 0, wx.ALL|wx.EXPAND, 0) """ #colSizer.Add(self.contentPanel, 1, wx.ALL|wx.EXPAND, 3) self.SetSizer(colSizer) self.SetAutoLayout(True) self.list.SetFocus() def getSelectedList(self, event = None): return self.list ###################################### # Update ABC on-the-fly ###################################### def updateColumns(self, force = False): # Update display in column for inactive torrent for ABCTorrentTemp in self.utility.torrents["all"]: ABCTorrentTemp.updateColumns(force = force) ############################################################## # # Class : ABCTaskBarIcon # # Task Bar Icon # ############################################################## class ABCTaskBarIcon(wx.TaskBarIcon): def __init__(self, parent): wx.TaskBarIcon.__init__(self) self.utility = parent.utility self.TBMENU_RESTORE = wx.NewId() # setup a taskbar icon, and catch some events from it self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, parent.onTaskBarActivate) self.Bind(wx.EVT_MENU, parent.onTaskBarActivate, id = self.TBMENU_RESTORE) self.updateIcon(False) def updateIcon(self,iconifying = False): remove = True mintray = self.utility.config.Read('mintray', "int") if (mintray >= 2) or ((mintray >= 1) and iconifying): remove = False if remove and self.IsIconInstalled(): self.RemoveIcon() elif not remove and not self.IsIconInstalled(): self.SetIcon(self.utility.icon, product_name) def CreatePopupMenu(self): menu = wx.Menu() self.utility.actions[ACTION_STOPALL].addToMenu(menu, bindto = self) self.utility.actions[ACTION_UNSTOPALL].addToMenu(menu, bindto = self) menu.AppendSeparator() menu.Append(self.TBMENU_RESTORE, self.utility.lang.get('showabcwindow')) self.utility.actions[ACTION_EXIT].addToMenu(menu, bindto = self) return menu ############################################################## # # Class : ABColdFrame # # Main ABC Frame class that contains menu and menu bar management # and contains ABCPanel # ############################################################## class ABCOldFrame(wx.Frame,FlaglessDelayedInvocation): def __init__(self, ID, params, utility): self.utility = utility #self.utility.frame = self title = "Old Interface" # Get window size and position from config file size = (400,400) style = wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN wx.Frame.__init__(self, None, ID, title, size = size, style = style) FlaglessDelayedInvocation.__init__(self) self.GUIupdate = True self.window = ABCPanel(self) self.Bind(wx.EVT_SET_FOCUS, self.onFocus) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) self.tb = ABCToolBar(self) # new Tribler gui has no toolbar self.SetToolBar(self.tb) def onFocus(self, event = None): if event is not None: event.Skip() self.window.getSelectedList(event).SetFocus() def OnCloseWindow(self, event = None): self.Hide() # Custom class loaded by XRC class ABCFrame(wx.Frame, DelayedInvocation): def __init__(self, *args): if len(args) == 0: pre = wx.PreFrame() # the Create step is done by XRC. self.PostCreate(pre) self.Bind(wx.EVT_WINDOW_CREATE, self.OnCreate) else: wx.Frame.__init__(self, args[0], args[1], args[2], args[3]) self._PostInit() def OnCreate(self, event): self.Unbind(wx.EVT_WINDOW_CREATE) wx.CallAfter(self._PostInit) event.Skip() return True def _PostInit(self): # Do all init here self.guiUtility = GUIUtility.getInstance() self.utility = self.guiUtility.utility self.params = self.guiUtility.params self.utility.frame = self title = self.utility.lang.get('title') + \ " " + \ self.utility.lang.get('version') # Get window size and position from config file size, position = self.getWindowSettings() style = wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN self.SetSize(size) self.SetPosition(position) self.SetTitle(title) tt = self.GetToolTip() if tt is not None: tt.SetTip('') #wx.Frame.__init__(self, None, ID, title, position, size, style = style) self.doneflag = Event() DelayedInvocation.__init__(self) dragdroplist = FileDropTarget(self.utility) self.SetDropTarget(dragdroplist) self.tbicon = None # Arno: see ABCPanel #self.abc_sb = ABCStatusBar(self,self.utility) #self.SetStatusBar(self.abc_sb) """ # Add status bar statbarbox = wx.BoxSizer(wx.HORIZONTAL) self.sb_buttons = ABCStatusButtons(self,self.utility) statbarbox.Add(self.sb_buttons, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 0) self.abc_sb = ABCStatusBar(self,self.utility) statbarbox.Add(self.abc_sb, 1, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 0) #colSizer.Add(statbarbox, 0, wx.ALL|wx.EXPAND, 0) self.SetStatusBar(statbarbox) """ try: self.SetIcon(self.utility.icon) except: pass # Don't update GUI as often when iconized self.GUIupdate = True # Start the scheduler before creating the ListCtrl self.utility.queue = ABCScheduler(self.utility) #self.window = ABCPanel(self) #self.abc_sb = self.window.abc_sb self.oldframe = ABCOldFrame(-1, self.params, self.utility) self.oldframe.Refresh() self.oldframe.Layout() #self.oldframe.Show(True) self.window = self.GetChildren()[0] self.window.utility = self.utility """ self.list = ABCList(self.window) self.list.Show(False) self.utility.list = self.list print self.window.GetName() self.window.list = self.list self.utility.window = self.window """ #self.window.sb_buttons = ABCStatusButtons(self,self.utility) self.utility.window.postponedevents = [] # Menu Options ############################ menuBar = ABCMenuBar(self) if sys.platform == "darwin": wx.App.SetMacExitMenuItemId(wx.ID_CLOSE) self.SetMenuBar(menuBar) #self.tb = ABCToolBar(self) # new Tribler gui has no toolbar #self.SetToolBar(self.tb) self.buddyFrame = None self.fileFrame = None self.buddyFrame_page = 0 self.buddyFrame_size = (800, 500) self.buddyFrame_pos = None self.fileFrame_size = (800, 500) self.fileFrame_pos = None # Menu Events ############################ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) # self.Bind(wx.EVT_MENU, self.OnMenuExit, id = wx.ID_CLOSE) # leaving here for the time being: # wxMSW apparently sends the event to the App object rather than # the top-level Frame, but there seemed to be some possibility of # change self.Bind(wx.EVT_QUERY_END_SESSION, self.OnCloseWindow) self.Bind(wx.EVT_END_SESSION, self.OnCloseWindow) try: self.tbicon = ABCTaskBarIcon(self) except: pass self.Bind(wx.EVT_ICONIZE, self.onIconify) self.Bind(wx.EVT_SET_FOCUS, self.onFocus) self.Bind(wx.EVT_SIZE, self.onSize) #self.Bind(wx.EVT_IDLE, self.onIdle) # Start up the controller self.utility.controller = ABCLaunchMany(self.utility) self.utility.controller.start() # Give GUI time to set up stuff wx.Yield() #if server start with params run it ##################################### if DEBUG: print >>sys.stderr,"abc: wxFrame: params is",self.params if self.params[0] != "": success, msg, ABCTorrentTemp = self.utility.queue.addtorrents.AddTorrentFromFile(self.params[0],caller=CALLER_ARGV) self.utility.queue.postInitTasks(self.params) if self.params[0] != "": # Update torrent.list, but after having read the old list of torrents, otherwise we get interference ABCTorrentTemp.torrentconfig.writeSrc(False) self.utility.torrentconfig.Flush() self.videoFrame = None feasible = return_feasible_playback_modes() if PLAYBACKMODE_INTERNAL in feasible: # This means vlc is available from Tribler.Video.EmbeddedPlayer import VideoFrame self.videoFrame = VideoFrame(self) #self.videores = xrc.XmlResource("Tribler/vwxGUI/MyPlayer.xrc") #self.videoframe = self.videores.LoadFrame(None, "MyPlayer") #self.videoframe.Show() videoplayer = VideoPlayer.getInstance() videoplayer.set_parentwindow(self.videoFrame) else: videoplayer = VideoPlayer.getInstance() videoplayer.set_parentwindow(self) sys.stdout.write('GUI Complete.\n') self.Show(True) # Check to see if ABC is associated with torrents ####################################################### if (sys.platform == 'win32'): if self.utility.config.Read('associate', "boolean"): if not self.utility.regchecker.testRegistry(): dialog = RegCheckDialog(self) dialog.ShowModal() dialog.Destroy() self.checkVersion() def checkVersion(self): t = Timer(2.0, self._checkVersion) t.start() def _checkVersion(self): my_version = self.utility.getVersion() try: curr_status = urllib.urlopen('http://tribler.org/version').readlines() line1 = curr_status[0] if len(curr_status) > 1: self.update_url = curr_status[1].strip() else: self.update_url = 'http://tribler.org' _curr_status = line1.split() self.curr_version = _curr_status[0] if self.newversion(self.curr_version, my_version): # Arno: we are a separate thread, delegate GUI updates to MainThread self.upgradeCallback() # Also check new version of web2definitions for youtube etc. search Web2Updater(self.utility).checkUpdate() except Exception,e: print >> sys.stderr, "Tribler: Version check failed", ctime(time()), str(e) #print_exc() def newversion(self, curr_version, my_version): curr = curr_version.split('.') my = my_version.split('.') if len(my) >= len(curr): nversion = len(my) else: nversion = len(curr) for i in range(nversion): if i < len(my): my_v = int(my[i]) else: my_v = 0 if i < len(curr): curr_v = int(curr[i]) else: curr_v = 0 if curr_v > my_v: return True elif curr_v < my_v: return False return False def upgradeCallback(self): self.invokeLater(self.OnUpgrade) def OnUpgrade(self, event=None): s = self.utility.lang.get('upgradeabc') title = self.utility.lang.get('upgradeabctitle') mainpage = self.utility.lang.get('mainpage') dlg = wx.MessageDialog(self, s, title + self.curr_version, wx.YES_NO|wx.ICON_EXCLAMATION #wx.OK | wx.ICON_INFORMATION | #wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION ) result = dlg.ShowModal() dlg.Destroy() if result == wx.ID_YES: t = Timer(0.1, self.openBrowserForUpgrade) t.start() def openBrowserForUpgrade(self): webbrowser.open_new(self.update_url) def onFocus(self, event = None): if event is not None: event.Skip() #self.window.getSelectedList(event).SetFocus() def setGUIupdate(self, update): oldval = self.GUIupdate self.GUIupdate = update if self.GUIupdate and not oldval: # Force an update of all torrents for torrent in self.utility.torrents["all"]: torrent.updateColumns() torrent.updateColor() def taskbarCallback(self): self.invokeLater(self.onTaskBarActivate,[]) ####################################### # minimize to tray bar control ####################################### def onTaskBarActivate(self, event = None): self.Iconize(False) self.Show(True) self.Raise() if self.tbicon is not None: self.tbicon.updateIcon(False) #self.window.list.SetFocus() # Resume updating GUI self.setGUIupdate(True) def onIconify(self, event = None): # This event handler is called both when being minimalized # and when being restored. if DEBUG: if event is not None: print >> sys.stderr,"abc: onIconify(",event.Iconized() else: print >> sys.stderr,"abc: onIconify event None" if event.Iconized(): if (self.utility.config.Read('mintray', "int") > 0 and self.tbicon is not None): self.tbicon.updateIcon(True) self.Show(False) # Don't update GUI while minimized self.setGUIupdate(False) else: self.setGUIupdate(True) if event is not None: event.Skip() def onSize(self, event = None): # Arno: On Windows when I enable the tray icon and then change # virtual desktop (see MS DeskmanPowerToySetup.exe) # I get a onIconify(event.Iconized()==True) event, but when # I switch back, I don't get an event. As a result the GUIupdate # remains turned off. The wxWidgets wiki on the TaskBarIcon suggests # catching the onSize event. if DEBUG: if event is not None: print >> sys.stderr,"abc: onSize:",event.GetSize() else: print >> sys.stderr,"abc: onSize: None" self.setGUIupdate(True) if event is not None: #self.window.SetSize(self.GetSize()) event.Skip() # Refresh subscreens self.refreshNeeded = True self.guiUtility.refreshOnResize() def onIdle(self, event = None): """ Only refresh screens (especially detailsPanel) when resizes are finished This gives less flickering, but doesnt look pretty, so i commented it out """ if self.refreshNeeded: self.guiUtility.refreshOnResize() self.refreshNeeder = False def getWindowSettings(self): width = self.utility.config.Read("window_width") height = self.utility.config.Read("window_height") try: size = wx.Size(int(width), int(height)) except: size = wx.Size(710, 400) x = self.utility.config.Read("window_x") y = self.utility.config.Read("window_y") if (x == "" or y == ""): position = wx.DefaultPosition else: position = wx.Point(int(x), int(y)) return size, position def saveWindowSettings(self): width, height = self.GetSizeTuple() x, y = self.GetPositionTuple() self.utility.config.Write("window_width", width) self.utility.config.Write("window_height", height) self.utility.config.Write("window_x", x) self.utility.config.Write("window_y", y) self.utility.config.Flush() ################################## # Close Program ################################## def OnCloseWindow(self, event = None): if event != None: nr = event.GetEventType() lookup = { wx.EVT_CLOSE.evtType[0]: "EVT_CLOSE", wx.EVT_QUERY_END_SESSION.evtType[0]: "EVT_QUERY_END_SESSION", wx.EVT_END_SESSION.evtType[0]: "EVT_END_SESSION" } if nr in lookup: nr = lookup[nr] print "Closing due to event ",nr print >>sys.stderr,"Closing due to event ",nr else: print "Closing untriggered by event" # Don't do anything if the event gets called twice for some reason if self.utility.abcquitting: return # Check to see if we can veto the shutdown # (might not be able to in case of shutting down windows) if event is not None: try: if event.CanVeto() and self.utility.config.Read('confirmonclose', "boolean"): dialog = wx.MessageDialog(None, self.utility.lang.get('confirmmsg'), self.utility.lang.get('confirm'), wx.OK|wx.CANCEL) result = dialog.ShowModal() dialog.Destroy() if result != wx.ID_OK: event.Veto() return except: data = StringIO() print_exc(file = data) sys.stderr.write(data.getvalue()) pass self.utility.abcquitting = True self.GUIupdate = False self.guiUtility.guiOpen.clear() # Close the Torrent Maker self.utility.actions[ACTION_MAKETORRENT].closeWin() try: self.utility.webserver.stop() except: data = StringIO() print_exc(file = data) sys.stderr.write(data.getvalue()) pass try: # tell scheduler to close all active thread self.utility.queue.clearScheduler() except: data = StringIO() print_exc(file = data) sys.stderr.write(data.getvalue()) pass try: # Restore the window before saving size and position # (Otherwise we'll get the size of the taskbar button and a negative position) self.onTaskBarActivate() self.saveWindowSettings() except: #print_exc(file=sys.stderr) print_exc() try: if self.buddyFrame is not None: self.buddyFrame.Destroy() if self.fileFrame is not None: self.fileFrame.Destroy() if self.videoFrame is not None: self.videoFrame.Destroy() except: pass self.oldframe.Destroy() try: if self.tbicon is not None: self.tbicon.RemoveIcon() self.tbicon.Destroy() self.Destroy() except: data = StringIO() print_exc(file = data) sys.stderr.write(data.getvalue()) pass # Arno: at the moment, Tribler gets a segmentation fault when the # tray icon is always enabled. This SEGV occurs in the wx mainloop # which is entered as soon as we leave this method. Hence I placed # tribler_done() here, so the database are closed properly # before the crash. # # Arno, 2007-02-28: Preferably this should be moved to the main # run() method below, that waits a while to allow threads to finish. # Ideally, the database should still be open while they finish up. # Because of the crash problem with the icontray this is the safer # place. # # Arno, 2007-08-10: When a torrentfile is passed on the command line, # the client will crash just after this point due to unknown reasons # (it even does it when we don't look at the cmd line args at all!) # Hence, for safety, I close the DB here already. #if sys.platform == 'linux2': # tribler_done(self.utility.getConfigPath()) if DEBUG: ts = enumerate() for t in ts: print >>sys.stderr,"abc: Thread still running",t.getName(),"daemon",t.isDaemon() if DEBUG: print >>sys.stderr,"abc: OnCloseWindow END" # if event is not None: # event.Skip() def onWarning(self,exc): msg = self.utility.lang.get('tribler_startup_nonfatalerror') msg += str(exc.__class__)+':'+str(exc) dlg = wx.MessageDialog(None, msg, self.utility.lang.get('tribler_warning'), wx.OK|wx.ICON_WARNING) result = dlg.ShowModal() dlg.Destroy() def onUPnPError(self,upnp_type,listenport,error_type,exc=None): if error_type == 0: errormsg = unicode(' UPnP mode '+str(upnp_type)+' ')+self.utility.lang.get('tribler_upnp_error1') elif error_type == 1: errormsg = unicode(' UPnP mode '+str(upnp_type)+' ')+self.utility.lang.get('tribler_upnp_error2')+unicode(str(exc))+self.utility.lang.get('tribler_upnp_error2_postfix') elif error_type == 2: errormsg = unicode(' UPnP mode '+str(upnp_type)+' ')+self.utility.lang.get('tribler_upnp_error3') else: errormsg = unicode(' UPnP mode '+str(upnp_type)+' Unknown error') msg = self.utility.lang.get('tribler_upnp_error_intro') msg += str(listenport) msg += self.utility.lang.get('tribler_upnp_error_intro_postfix') msg += errormsg msg += self.utility.lang.get('tribler_upnp_error_extro') dlg = wx.MessageDialog(None, msg, self.utility.lang.get('tribler_warning'), wx.OK|wx.ICON_WARNING) result = dlg.ShowModal() dlg.Destroy() def onReachable(self,event=None): """ Called by GUI thread """ if self.firewallStatus is not None: self.firewallStatus.setToggled(True) tt = self.firewallStatus.GetToolTip() if tt is not None: if reach: tt.SetTip(self.utility.lang.get('reachable_tooltip')) else: tt.SetTip(self.utility.lang.get('unknownreac_tooltip')) GUIUtility.getInstance().isReachable = True def setActivity(self,type,msg=u''): if currentThread().getName() != "MainThread": print >> sys.stderr,"abc: setActivity thread",currentThread().getName(),"is NOT MAIN THREAD" print_stack() if type == ACT_NONE: prefix = u'' msg = u'' elif type == ACT_UPNP: prefix = self.utility.lang.get('act_upnp') elif type == ACT_REACHABLE: prefix = self.utility.lang.get('act_reachable') elif type == ACT_GET_EXT_IP_FROM_PEERS: prefix = self.utility.lang.get('act_get_ext_ip_from_peers') elif type == ACT_MEET: prefix = self.utility.lang.get('act_meet') elif type == ACT_GOT_METADATA: prefix = self.utility.lang.get('act_got_metadata') elif type == ACT_RECOMMEND: prefix = self.utility.lang.get('act_recommend') elif type == ACT_DISK_FULL: prefix = self.utility.lang.get('act_disk_full') if msg == u'': text = prefix else: text = unicode( prefix+u' '+msg) if DEBUG: print >> sys.stderr,"abc: Setting activity",`text`,"EOT" self.messageField.SetLabel(text) ############################################################## # # Class : ABCApp # # Main ABC application class that contains ABCFrame Object # ############################################################## class ABCApp(wx.App,FlaglessDelayedInvocation): def __init__(self, x, params, single_instance_checker, abcpath): global start_time, start_time2 start_time2 = time() #print "[StartUpDebug]----------- from ABCApp.__init__ ----------Tribler starts up at", ctime(start_time2), "after", start_time2 - start_time self.params = params self.single_instance_checker = single_instance_checker self.abcpath = abcpath self.error = None wx.App.__init__(self, x) def OnInit(self): try: self.utility = Utility(self.abcpath) # Set locale to determine localisation locale.setlocale(locale.LC_ALL, '') sys.stdout.write('Client Starting Up.\n') sys.stdout.write('Build: ' + self.utility.lang.get('build') + '\n') bm = wx.Bitmap(os.path.join(self.utility.getPath(),'icons','splash.jpg'),wx.BITMAP_TYPE_JPEG) self.splash = wx.SplashScreen(bm, wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT, 1000, None, -1) wx.CallAfter(self.PostInit) return True except Exception,e: print_exc() self.error = e self.onError() return False def PostInit(self): try: tribler_init(self.utility.getConfigPath(),self.utility.getPath(),self.db_exception_handler) self.utility.setTriblerVariables() self.utility.postAppInit() # Singleton for executing tasks that are too long for GUI thread and # network thread self.guiserver = GUIServer.getInstance() self.guiserver.register() # Singleton for management of user's mugshots (i.e. icons/display pictures) self.mm = MugshotManager.getInstance() self.mm.register(self.utility.getConfigPath(),self.utility.getPath()) # H4x0r a bit set_tasteheart_bitmaps(self.utility.getPath()) set_perfBar_bitmaps(self.utility.getPath()) # Put it here so an error is shown in the startup-error popup self.serverlistener = ServerListener(self.utility) # Check webservice for autostart webservice ####################################################### WebListener(self.utility) if self.utility.webconfig.Read("webautostart", "boolean"): self.utility.webserver.start() # Start single instance server listenner ############################################ self.serverthread = Thread(target = self.serverlistener.start) self.serverthread.setDaemon(True) self.serverthread.start() self.videoplayer = VideoPlayer.getInstance() self.videoplayer.register(self.utility) self.videoserver = VideoHTTPServer.getInstance() self.videoserver.background_serve() notification_init( self.utility ) #self.frame = ABCFrame(-1, self.params, self.utility) self.guiUtility = GUIUtility.getInstance(self.utility, self.params) updateXRC.main([os.path.join(self.utility.getPath(),'Tribler','vwxGUI')]) self.res = xrc.XmlResource(os.path.join(self.utility.getPath(),'Tribler','vwxGUI','MyFrame.xrc')) self.guiUtility.xrcResource = self.res self.frame = self.res.LoadFrame(None, "MyFrame") self.guiUtility.frame = self.frame self.scrollWindow = xrc.XRCCTRL(self.frame, "level0") self.guiUtility.mainSizer = self.scrollWindow.GetSizer() self.frame.topBackgroundRight = xrc.XRCCTRL(self.frame, "topBG3") self.scrollWindow.SetScrollbars(1,1,1024,768) self.frame.mainButtonPersons = xrc.XRCCTRL(self.frame, "mainButtonPersons") self.frame.numberPersons = xrc.XRCCTRL(self.frame, "numberPersons") numperslabel = xrc.XRCCTRL(self.frame, "persons") self.frame.numberFiles = xrc.XRCCTRL(self.frame, "numberFiles") numfileslabel = xrc.XRCCTRL(self.frame, "files") self.frame.messageField = xrc.XRCCTRL(self.frame, "messageField") self.frame.firewallStatus = xrc.XRCCTRL(self.frame, "firewallStatus") tt = self.frame.firewallStatus.GetToolTip() if tt is not None: SetTip(self.utility.lang.get('unknownreac_tooltip')) if sys.platform == "linux2": self.frame.numberPersons.SetFont(wx.Font(9,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE)) self.frame.numberFiles.SetFont(wx.Font(9,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE)) self.frame.messageField.SetFont(wx.Font(9,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE)) numperslabel.SetFont(wx.Font(9,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE)) numfileslabel.SetFont(wx.Font(9,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE)) """ searchfilebut = xrc.XRCCTRL(self.frame, "bt257cC") searchfilebut.Bind(wx.EVT_LEFT_UP, self.guiUtility.buttonClicked) searchpersbut = xrc.XRCCTRL(self.frame, "bt258cC") searchpersbut.Bind(wx.EVT_LEFT_UP, self.guiUtility.buttonClicked) self.frame.searchtxtctrl = xrc.XRCCTRL(self.frame, "tx220cCCC") """ #self.frame.Refresh() #self.frame.Layout() self.frame.Show(True) #=============================================================================== # global start_time2 # current_time = time() # print "\n\n[StartUpDebug]-----------------------------------------" # print "[StartUpDebug]" # print "[StartUpDebug]----------- from ABCApp.OnInit ----------Tribler frame is shown after", current_time-start_time2 # print "[StartUpDebug]" # print "[StartUpDebug]-----------------------------------------\n\n" #=============================================================================== # GUI start # - load myFrame # - load standardGrid # - gui utility > button mainButtonFiles = clicked self.Bind(wx.EVT_QUERY_END_SESSION, self.frame.OnCloseWindow) self.Bind(wx.EVT_END_SESSION, self.frame.OnCloseWindow) asked = self.utility.config.Read('askeduploadbw', 'boolean') if not asked: dlg = BandwidthSelector(self.frame,self.utility) result = dlg.ShowModal() if result == wx.ID_OK: ulbw = dlg.getUploadBandwidth() self.utility.config.Write('maxuploadrate',ulbw) self.utility.config.Write('maxseeduploadrate',ulbw) self.utility.config.Write('askeduploadbw','1') dlg.Destroy() # Arno, 2007-05-03: wxWidgets 2.8.3.0 and earlier have the MIME-type for .bmp # files set to 'image/x-bmp' whereas 'image/bmp' is the official one. try: bmphand = None hands = wx.Image.GetHandlers() for hand in hands: #print "Handler",hand.GetExtension(),hand.GetType(),hand.GetMimeType() if hand.GetMimeType() == 'image/x-bmp': bmphand = hand break #wx.Image.AddHandler() if bmphand is not None: bmphand.SetMimeType('image/bmp') except: # wx < 2.7 don't like wx.Image.GetHandlers() print_exc() # Must be after ABCLaunchMany is created self.torrentfeed = TorrentFeedThread.getInstance() self.torrentfeed.register(self.utility) self.torrentfeed.start() #print "DIM",wx.GetDisplaySize() #print "MM",wx.GetDisplaySizeMM() wx.CallAfter(self.startWithRightView) except Exception,e: print_exc() self.error = e self.onError() return False return True def onError(self,source=None): # Don't use language independence stuff, self.utility may not be # valid. msg = "Unfortunately, Tribler ran into an internal error:\n\n" if source is not None: msg += source msg += str(self.error.__class__)+':'+str(self.error) msg += '\n' msg += 'Please see the FAQ on www.tribler.org on how to act.' dlg = wx.MessageDialog(None, msg, "Tribler Fatal Error", wx.OK|wx.ICON_ERROR) result = dlg.ShowModal() print_exc() dlg.Destroy() def MacOpenFile(self,filename): self.utility.queue.addtorrents.AddTorrentFromFile(filename) def OnExit(self): self.torrentfeed.shutdown() if not ALLOW_MULTIPLE: del self.single_instance_checker ClientPassParam("Close Connection") return 0 def db_exception_handler(self,e): if DEBUG: print >> sys.stderr,"abc: Database Exception handler called",e,"value",e.args,"#" try: if e.args[1] == "DB object has been closed": return # We caused this non-fatal error, don't show. if self.error is not None and self.error.args[1] == e.args[1]: return # don't repeat same error except: print >> sys.stderr, "abc: db_exception_handler error", e, type(e) print_exc() print_stack() self.error = e self.invokeLater(self.onError,[],{'source':"The database layer reported: "}) def getConfigPath(self): return self.utility.getConfigPath() def startWithRightView(self): if self.params[0] != "": self.guiUtility.standardLibraryOverview() class DummySingleInstanceChecker: def __init__(self,basename): pass def IsAnotherRunning(self): "Uses pgrep to find other tribler.py processes" # If no pgrep available, it will always start tribler progressInfo = commands.getoutput('pgrep -fl tribler.py | grep -v pgrep') numProcesses = len(progressInfo.split('\n')) if DEBUG: print 'ProgressInfo: %s, num: %d' % (progressInfo, numProcesses) return numProcesses > 1 ############################################################## # # Main Program Start Here # ############################################################## def run(params = None): global start_time start_time = time() if params is None: params = [""] if len(sys.argv) > 1: params = sys.argv[1:] # Create single instance semaphore # Arno: On Linux and wxPython-2.8.1.1 the SingleInstanceChecker appears # to mess up stderr, i.e., I get IOErrors when writing to it via print_exc() # # TEMPORARILY DISABLED on Linux if sys.platform != 'linux2': single_instance_checker = wx.SingleInstanceChecker("tribler-" + wx.GetUserId()) else: single_instance_checker = DummySingleInstanceChecker("tribler-") #print "[StartUpDebug]---------------- 1", time()-start_time if not ALLOW_MULTIPLE and single_instance_checker.IsAnotherRunning(): #Send torrent info to abc single instance ClientPassParam(params[0]) #print "[StartUpDebug]---------------- 2", time()-start_time else: abcpath = os.path.abspath(os.path.dirname(sys.argv[0])) # Arno: don't chdir to allow testing as other user from other dir. #os.chdir(abcpath) # Launch first abc single instance app = ABCApp(0, params, single_instance_checker, abcpath) configpath = app.getConfigPath() # print "[StartUpDebug]---------------- 3", time()-start_time app.MainLoop() print "Client shutting down. Sleeping for a few seconds to allow other threads to finish" sleep(4) # This is the right place to close the database, unfortunately Linux has # a problem, see ABCFrame.OnCloseWindow # #if sys.platform != 'linux2': # tribler_done(configpath) os._exit(0) if __name__ == '__main__': run()