def ShowSearching(self, max): if not self or not self.go: return self.go.SetRange(max + 16) cancelWorker(u"FakeResult") startWorker(None, self.FakeResult, uId=u"FakeResult", delay=0.25, workerType="ThreadPool")
def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) def db_callback(): self.uelog.addEvent(message="SRstatusbar: user toggled family filter", type=2) startWorker(None, db_callback, retryOnBusy=True)
def OnMultipleMove(self, event): button = event.GetEventObject() button.Enable(False) wx.CallLater(5000, button.Enable, True) start = button == self.elements['batchstart'] def do_db(): choices = [] dstates = [] _,_,downloads = self.guiUtility.library_manager.getHitsInCategory() def sort_by_name(a, b): return cmp(a.name, b.name) downloads.sort(cmp = sort_by_name) for item in downloads: if item.ds: choices.append(item.name) dstates.append(item.ds.get_download()) return choices, dstates def do_gui(delayedResult): choices, dstates = delayedResult.get() dlg = MoveTorrents(self, choices, dstates) if dlg.ShowModal() == wx.ID_OK: selectedDownloads, new_dir, moveFiles, ignoreIfExists = dlg.GetSettings() for download in selectedDownloads: self.moveDownload(download, new_dir, moveFiles, ignoreIfExists) dlg.Destroy() startWorker(do_gui, do_db, uId="OnMultipleMove")
def showChannelFromPermid(self, channel_permid): def db_callback(): channel = self.channelsearch_manager.getChannelByPermid( channel_permid) self.showChannel(channel) startWorker(None, db_callback)
def UpdateStats(self, infohash): def db_callback(): torrent = self.torrentdb.getTorrent(infohash, include_mypref=False) if torrent: self._UpdateStats(torrent) startWorker(None, db_callback, uId ="NewTorrentPanel_UpdateStats")
def _save_torrent(self, tdef, callback = None): tmp_handle, tmp_filename = mkstemp() tdef.save(tmp_filename) os.close(tmp_handle) sdef, swiftpath = self._write_to_collected(tmp_filename) try: os.remove(tmp_filename) except: atexit.register(lambda tmp_filename=tmp_filename: os.remove(tmp_filename)) def do_db(callback): #add this new torrent to db infohash = tdef.get_infohash() if self.torrent_db.hasTorrent(infohash): self.torrent_db.updateTorrent(infohash, swift_torrent_hash = sdef.get_roothash(), torrent_file_name = swiftpath) else: self.torrent_db.addExternalTorrent(tdef, extra_info = {'filename': swiftpath, 'swift_torrent_hash':sdef.get_roothash(), 'status':'good'}) #notify all self.notify_possible_torrent_infohash(infohash, True) if callback: callback() startWorker(None, do_db, wargs = (callback, ))
def _save_torrent(self, tdef, callback = None): tmp_filename = os.path.join(self.session.get_torrent_collecting_dir(), "tmp_"+get_collected_torrent_filename(tdef.get_infohash())) filename_index = 0 while os.path.exists(tmp_filename): filename_index += 1 tmp_filename = os.path.join(self.session.get_torrent_collecting_dir(), ("tmp_%d_"%filename_index)+get_collected_torrent_filename(tdef.get_infohash())) tdef.save(tmp_filename) sdef, swiftpath = self._write_to_collected(tmp_filename) try: os.remove(tmp_filename) except: atexit.register(lambda tmp_filename=tmp_filename: os.remove(tmp_filename)) def do_db(callback): #add this new torrent to db infohash = tdef.get_infohash() if self.torrent_db.hasTorrent(infohash): self.torrent_db.updateTorrent(infohash, swift_torrent_hash = sdef.get_roothash(), torrent_file_name = swiftpath) else: self.torrent_db.addExternalTorrent(tdef, extra_info = {'filename': swiftpath, 'swift_torrent_hash':sdef.get_roothash(), 'status':'good'}) #notify all self.notify_possible_torrent_infohash(infohash, True) if callback: callback() startWorker(None, do_db, wargs = (callback, ))
def OnMultipleMove(self, event): button = event.GetEventObject() button.Enable(False) wx.CallLater(5000, button.Enable, True) start = button == self.elements['batchstart'] def do_db(): choices = [] dstates = [] _,downloads = self.guiUtility.library_manager.getHitsInCategory() def sort_by_name(a, b): return cmp(a.name, b.name) downloads.sort(cmp = sort_by_name) for item in downloads: if item.ds: choices.append(item.name) dstates.append(item.ds) return choices, dstates def do_gui(delayedResult): choices, dstates = delayedResult.get() dlg = MoveTorrents(self, choices, dstates) if dlg.ShowModal() == wx.ID_OK: selectedDownloads, new_dir, moveFiles, ignoreIfExists = dlg.GetSettings() for download in selectedDownloads: self.moveDownload(download, new_dir, moveFiles, ignoreIfExists) dlg.Destroy() startWorker(do_gui, do_db, uId="OnMultipleMove",priority=GUI_PRI_DISPERSY)
def SetData(self, delayedResult): if not self or not self.list: return data = [] torrents = delayedResult.get() for torrent in torrents: # FIXME(lipu): fix the thumbnail path to use metadata thumb_path = os.path.join(u"", binascii.hexlify(torrent.infohash)) if os.path.isdir(thumb_path): if not self.guiutility.getFamilyFilter() or not self.IsXXX( torrent, thumb_path): data.append((torrent.infohash, [torrent.name], torrent, ThumbnailListItemNoTorrent)) self.list.SetData(data) self.list.SetupScrolling() if len(data) < self.max_torrents: interval = self.update_interval / 4 else: interval = self.update_interval startWorker(self.SetData, self.GetTorrents, delay=interval, uId=u"ArtworkPanel_refresh")
def UpdateStats(self): def db_callback(): stats = self.torrentdb.getTorrentsStats() nr_channels = self.channelcastdb.getNrChannels() self._UpdateStats(stats, nr_channels) startWorker(None, db_callback, uId ="NetworkPanel_UpdateStats")
def notify_possible_torrent_roothash(self, roothash): keys = self.callbacks.keys() for key in keys: if key[1] == roothash: handle_lambda = lambda key=key: self._handleCallback(key, True) self.scheduletask(handle_lambda) def do_db(tdef): if self.torrent_db.hasTorrent(tdef.get_infohash()): self.torrent_db.updateTorrent( tdef.get_infohash(), swift_torrent_hash=sdef.get_roothash(), torrent_file_name=swiftpath) else: self.torrent_db._addTorrentToDB(tdef, source="SWIFT", extra_info={ 'filename': swiftpath, 'swift_torrent_hash': roothash, 'status': 'good' }, commit=True) sdef = SwiftDef(roothash) swiftpath = os.path.join(self.session.get_torrent_collecting_dir(), sdef.get_roothash_as_hex()) if os.path.exists(swiftpath): try: tdef = TorrentDef.load(swiftpath) startWorker(None, do_db, wargs=(tdef, )) except: #ignore if tdef loading fails pass
def UpdateStats(self): def db_callback(): stats = self.torrentdb.getTorrentsStats() nr_channels = self.channelcastdb.getNrChannels() self._UpdateStats(stats, nr_channels) startWorker(None, db_callback, uId="NetworkPanel_UpdateStats")
def UpdateStats(self, infohash): def db_callback(): torrent = self.torrentdb.getTorrent(infohash, include_mypref=False) if torrent: self._UpdateStats(torrent) startWorker(None, db_callback, uId="NewTorrentPanel_UpdateStats")
def set_reputation(self): def do_db(): nr_connections = 0 nr_channel_connections = 0 if self.dispersy: for community in self.dispersy.get_communities(): from Tribler.community.search.community import SearchCommunity from Tribler.community.allchannel.community import AllChannelCommunity if isinstance(community, SearchCommunity): nr_connections = community.get_nr_connections() elif isinstance(community, AllChannelCommunity): nr_channel_connections = community.get_nr_connections() return nr_connections, nr_channel_connections def do_wx(delayedResult): if not self.frame: return nr_connections, nr_channel_connections = delayedResult.get() # self.frame.SRstatusbar.set_reputation(myRep, total_down, total_up) # bitmap is 16px wide, -> but first and last pixel do not add anything. percentage = min(1.0, (nr_connections + 1) / 16.0) self.frame.SRstatusbar.SetConnections(percentage, nr_connections, nr_channel_connections) """ set the reputation in the GUI""" if self._frame_and_ready(): startWorker(do_wx, do_db, uId=u"tribler.set_reputation") startWorker(None, self.set_reputation, delay=5.0, workerType="ThreadPool")
def UpdateStats(self): includeStuffs = self.includeStuffs.GetValue() def db_callback(): info = self.dispersy.info(database_sync=includeStuffs) self._UpdateStats(info) startWorker(None, db_callback, uId ="DispersyPanel_UpdateStats")
def UpdateStats(self): includeStuffs = self.includeStuffs.GetValue() def db_callback(): info = self.dispersy.info(database_sync=includeStuffs) self._UpdateStats(info) startWorker(None, db_callback, uId="DispersyPanel_UpdateStats")
def __toggleFF(self, newvalue): if newvalue != self.guiutility.getFamilyFilter(): self.guiutility.toggleFamilyFilter(newvalue) def db_callback(): self.uelog.addEvent( message="SRstatusbar: user toggled family filter", type=2) startWorker(None, db_callback, retryOnBusy=True)
def updateChannel(self, query_permid, query, hits, callback = None): """ This function is called when there is a reply from remote peer regarding updating of a channel @param query_permid: the peer who returned the results @param query: the query string (None if this is not the results of a query) @param hits: details of all matching results related to the query @param callback: callback function which will receive delayedResult, query_permid and query """ startWorker(callback, self._updateChannelInternal, wargs = (query_permid, query, hits), cargs = (query_permid, query))
def invoke_func(*args,**kwargs): if onWorkerThread(): func(*args, **kwargs) else: if TRHEADING_DEBUG: caller = inspect.stack()[1] callerstr = "%s %s:%s"%(caller[3],caller[1],caller[2]) print >> sys.stderr, long(time()), "SWITCHING TO DBTHREAD %s %s:%s called by %s"%(func.__name__, func.func_code.co_filename, func.func_code.co_firstlineno, callerstr) startWorker(None, func, wargs=args, wkwargs=kwargs)
def UpdateStats(self): includeStuffs = self.includeStuffs.GetValue() includeDebug = self.includeDebug.GetValue() def db_callback(): self.dispersy.statistics.enable_debug_statistics(includeDebug) self.dispersy.statistics.update(database=includeStuffs) self._UpdateStats(self.dispersy.statistics) startWorker(None, db_callback, uId ="DispersyPanel_UpdateStats",priority=GUI_PRI_DISPERSY)
def RefreshList(self): def db_callback(): familyfilter_sql = Category.getInstance().get_family_filter_sql(self.torrentdb._getCategoryID) if familyfilter_sql: familyfilter_sql = familyfilter_sql[4:] topTen = self.torrentdb._db.getAll("CollectedTorrent", ("infohash", "name", "(num_seeders+num_leechers) as popularity"), where = familyfilter_sql , order_by = "(num_seeders+num_leechers) DESC", limit= 10) self._RefreshList(topTen) startWorker(None, db_callback, uId ="PopularTorrentPanel_RefreshList")
def FakeResult(self, times=1): if not self: return newValue = min(self.go.GetValue() + 1, self.go.GetRange()) if times < 16: self.go.SetValue(newValue) startWorker(None, self.FakeResult, wargs=(times + 1,), uId=u"FakeResult", delay=0.25, workerType="ThreadPool")
def load_more(self): """ load more channels to the list """ self._logger.info("getting new channels..") self.getting_channels = True def do_query_channels(): """ querying channels in the background. Only return as much as RETURNED_CHANNELS """ _, channels = self.guiutility.channelsearch_manager.getPopularChannels( 20) dict_channels = { channel.dispersy_cid: channel for channel in channels } new_channels_ids = list( set(dict_channels.keys()) - set(self.channel_list.keys())) return_list = [ dict_channels.get(new_channels_ids[i]) for i in xrange( 0, min(len(new_channels_ids), RETURNED_CHANNELS)) ] if return_list: return [ l for l in sorted(return_list, key=lambda x: x.nr_favorites, reverse=True) ] def do_update_gui(delayed_result): """ add fetched channels to GUI """ channels = delayed_result.get() if channels: for channel in channels: # s is channel object self.channel_list[channel.dispersy_cid] = channel self.create_source_item(channel) self.getting_channels = False self.refresh_sourcelist_data() self.Layout() startWorker(do_update_gui, do_query_channels, retryOnBusy=True, priority=GUI_PRI_DISPERSY)
def UpdateStats(self): includeStuffs = self.includeStuffs.GetValue() includeDebug = self.includeDebug.GetValue() def db_callback(): self.dispersy.statistics.enable_debug_statistics(includeDebug) self.dispersy.statistics.update(database=includeStuffs) self._UpdateStats(self.dispersy.statistics) startWorker(None, db_callback, uId="DispersyPanel_UpdateStats", priority=GUI_PRI_DISPERSY)
def FakeResult(self, times=1): if not self: return newValue = min(self.go.GetValue() + 1, self.go.GetRange()) if times < 16: self.go.SetValue(newValue) startWorker(None, self.FakeResult, wargs=(times + 1, ), uId=u"FakeResult", delay=0.25, workerType="ThreadPool")
def GetBuzzFromDB(self, doRefresh=False, samplesize = NetworkBuzzDBHandler.DEFAULT_SAMPLE_SIZE): def do_db(): if self.nbdb == None: self.nbdb = NetworkBuzzDBHandler.getInstance() self.buzz_cache = [[],[],[]] buzz = self.nbdb.getBuzz(samplesize, with_freq=True, flat=True) for i in range(len(buzz)): random.shuffle(buzz[i]) self.buzz_cache[i] = buzz[i] if len(self.tags) <= 1 and len(buzz) > 0 or doRefresh: self.OnRefreshTimer(force = True, fromDBThread = True) startWorker(None, do_db, uId="NetworkBuzz.GetBuzzFromDB")
def _save_torrent(self, tdef, callback=None): tmp_filename = os.path.join( self.session.get_torrent_collecting_dir(), "tmp_" + get_collected_torrent_filename(tdef.get_infohash())) filename_index = 0 while os.path.exists(tmp_filename): filename_index += 1 tmp_filename = os.path.join( self.session.get_torrent_collecting_dir(), ("tmp_%d_" % filename_index) + get_collected_torrent_filename(tdef.get_infohash())) tdef.save(tmp_filename) sdef, swiftpath = self._write_to_collected(tmp_filename) try: os.remove(tmp_filename) except: atexit.register( lambda tmp_filename=tmp_filename: os.remove(tmp_filename)) def do_db(callback): #add this new torrent to db infohash = tdef.get_infohash() if self.torrent_db.hasTorrent(infohash): self.torrent_db.updateTorrent( infohash, swift_torrent_hash=sdef.get_roothash(), torrent_file_name=swiftpath) else: self.torrent_db.addExternalTorrent(tdef, extra_info={ 'filename': swiftpath, 'swift_torrent_hash': sdef.get_roothash(), 'status': 'good' }) #notify all self.notify_possible_torrent_infohash(infohash, True) if callback: callback() startWorker(None, do_db, wargs=(callback, ))
def GetBuzzFromDB(self, doRefresh=False, samplesize=NetworkBuzzDBHandler.DEFAULT_SAMPLE_SIZE): def do_db(): if self.nbdb == None: self.nbdb = NetworkBuzzDBHandler.getInstance() self.buzz_cache = [[], [], []] buzz = self.nbdb.getBuzz(samplesize, with_freq=True, flat=True) for i in range(len(buzz)): random.shuffle(buzz[i]) self.buzz_cache[i] = buzz[i] if len(self.tags) <= 1 and len(buzz) > 0 or doRefresh: self.OnRefreshTimer(force=True, fromDBThread=True) startWorker(None, do_db, uId="NetworkBuzz.GetBuzzFromDB")
def RefreshList(self): def db_callback(): familyfilter_sql = Category.getInstance().get_family_filter_sql( self.torrentdb._getCategoryID) if familyfilter_sql: familyfilter_sql = familyfilter_sql[4:] topTen = self.torrentdb._db.getAll( "CollectedTorrent", ("infohash", "name", "(num_seeders+num_leechers) as popularity"), where=familyfilter_sql, order_by="(num_seeders+num_leechers) DESC", limit=10) self._RefreshList(topTen) startWorker(None, db_callback, uId="PopularTorrentPanel_RefreshList")
def register(self, dispersy, session, max_num_torrents): self.session = session self.dispersy = dispersy self.max_num_torrents = max_num_torrents self.tor_col_dir = self.session.get_torrent_collecting_dir() from Tribler.Utilities.TimedTaskQueue import TimedTaskQueue self.tqueue = TimedTaskQueue("RemoteTorrentHandler") self.scheduletask = self.tqueue.add_task self.torrent_db = session.open_dbhandler('torrents') self.channel_db = self.session.open_dbhandler(NTFY_CHANNELCAST) self.drequesters[0] = MagnetRequester(self, 0) self.drequesters[1] = MagnetRequester(self, 1) self.tnrequester = ThumbnailRequester(self, self.session) self.registered = True startWorker(None, self.__check_overflow)
def updateMySubscribedChannels(self): def update(channel_ids, perm_ids): channel_id = channel_ids.pop() perm_id = perm_ids.pop() self.updateAChannel(channel_id, perm_id) if len(channel_ids) > 0: self.overlay_bridge.add_task(lambda: update(channel_ids, perm_ids), 20) self.overlay_bridge.add_task(self.updateMySubscribedChannels, RELOAD_FREQUENCY) def db_call(): subscribed_channels = self.channelcastdb.getMySubscribedChannels() channel_ids = [values[0] for values in subscribed_channels if values[2] == -1] if len(channel_ids) > 0: perm_ids = self.channelcastdb.getPermidForChannels(channel_ids) update(channel_ids, perm_ids) startWorker(None, db_call)
def EnteredText(self, event): text = event.GetString() if text != self.text: self.text = text if self.entrycallback: def wx_callback(delayedResult, text): choices = delayedResult.get() if text == self.text: self.SetChoices(choices) if len(self.choices) == 0: self.ShowDropDown(False) else: self.ShowDropDown(True) def db_callback(text): if text == self.text: return self.entrycallback(text) startWorker(wx_callback, db_callback, cargs = (text,), wargs = (text, ))
def UpdateInfo(self, event=None): def do_db(): self.__dispersy.statistics.update(database=self.__incstuff_checkbox.GetValue()) return self.__dispersy.statistics def do_gui(delayedResult): if not self: return stats = delayedResult.get() # can contain an exception enabled = bool(self.__incstuff_checkbox.GetValue()) self.__summary_panel.UpdateInfo(stats) self.__community_panel.UpdateInfo(stats) self.__rawinfo_panel.UpdateInfo(stats) self.__runtime_panel.UpdateInfo(stats) self.__sharedstatistics_panel.UpdateInfo(_barter_statistics) self.Layout() startWorker(do_gui, do_db, uId=u"DispersyDebugFrame_UpdateInfo", priority=GUI_PRI_DISPERSY)
def PostInit2(self): self.frame.Raise() self.startWithRightView() self.set_reputation() s = self.utility.session s.add_observer(self.sesscb_ntfy_reachable, NTFY_REACHABLE, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_activities, NTFY_ACTIVITIES, [NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_CHANNELCAST, [NTFY_INSERT, NTFY_UPDATE, NTFY_CREATE, NTFY_STATE, NTFY_MODIFIED], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_VOTECAST, [NTFY_UPDATE], cache=10) s.add_observer(self.sesscb_ntfy_myprefupdates, NTFY_MYPREFERENCES, [NTFY_INSERT, NTFY_UPDATE, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_torrentupdates, NTFY_TORRENTS, [NTFY_UPDATE, NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_playlistupdates, NTFY_PLAYLISTS, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_commentupdates, NTFY_COMMENTS, [NTFY_INSERT, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_modificationupdates, NTFY_MODIFICATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_moderationupdats, NTFY_MODERATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_markingupdates, NTFY_MARKINGS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_torrentfinished, NTFY_TORRENTS, [NTFY_FINISHED]) s.add_observer(self.sesscb_ntfy_magnet, NTFY_TORRENTS, [NTFY_MAGNET_GOT_PEERS, NTFY_MAGNET_STARTED, NTFY_MAGNET_CLOSE]) # TODO(emilon): Use the LogObserver I already implemented # self.dispersy.callback.attach_exception_handler(self.frame.exceptionHandler) startWorker(None, self.loadSessionCheckpoint, delay=5.0, workerType="ThreadPool") # initialize the torrent feed thread channelcast = s.open_dbhandler(NTFY_CHANNELCAST) def db_thread(): return channelcast.getMyChannelId() def wx_thread(delayedResult): my_channel = delayedResult.get() if my_channel: self.torrentfeed.register(self.utility.session, my_channel) self.torrentfeed.addCallback(my_channel, self.guiUtility.channelsearch_manager.createTorrentFromDef) startWorker(wx_thread, db_thread, delay=5.0)
def _save_torrent(self, tdef, callback=None): tmp_handle, tmp_filename = mkstemp() tdef.save(tmp_filename) os.close(tmp_handle) sdef, swiftpath = self._write_to_collected(tmp_filename) try: os.remove(tmp_filename) except: atexit.register( lambda tmp_filename=tmp_filename: os.remove(tmp_filename)) def do_db(callback): #add this new torrent to db infohash = tdef.get_infohash() if self.torrent_db.hasTorrent(infohash): self.torrent_db.updateTorrent( infohash, swift_torrent_hash=sdef.get_roothash(), torrent_file_name=swiftpath) else: self.torrent_db.addExternalTorrent(tdef, extra_info={ 'filename': swiftpath, 'swift_torrent_hash': sdef.get_roothash(), 'status': 'good' }) #notify all self.notify_possible_torrent_infohash(infohash, True) if callback: callback() startWorker(None, do_db, wargs=(callback, ))
def notify_possible_torrent_roothash(self, roothash): keys = self.callbacks.keys() for key in keys: if key[1] == roothash: handle_lambda = lambda key=key: self._handleCallback(key, True) self.scheduletask(handle_lambda) def do_db(tdef): if self.torrent_db.hasTorrent(tdef.get_infohash()): self.torrent_db.updateTorrent(tdef.get_infohash(), swift_torrent_hash = sdef.get_roothash(), torrent_file_name = swiftpath) else: self.torrent_db._addTorrentToDB(tdef, source = "SWIFT", extra_info = {'filename': swiftpath, 'swift_torrent_hash':roothash, 'status':'good'}, commit = True) sdef = SwiftDef(roothash) swiftpath = os.path.join(self.session.get_torrent_collecting_dir(),sdef.get_roothash_as_hex()) if os.path.exists(swiftpath): try: tdef = TorrentDef.load(swiftpath) startWorker(None, do_db, wargs = (tdef, )) except: #ignore if tdef loading fails pass
def UpdateInfo(self, event=None): def do_db(): self.__dispersy.statistics.update( database=self.__incstuff_checkbox.GetValue()) return self.__dispersy.statistics def do_gui(delayedResult): if not self: return stats = delayedResult.get() # can contain an exception enabled = bool(self.__incstuff_checkbox.GetValue()) self.__summary_panel.UpdateInfo(stats) self.__community_panel.UpdateInfo(stats) self.__rawinfo_panel.UpdateInfo(stats) self.__runtime_panel.UpdateInfo(stats) self.__sharedstatistics_panel.UpdateInfo(_barter_statistics) self.Layout() startWorker(do_gui, do_db, uId=u"DispersyDebugFrame_UpdateInfo", priority=GUI_PRI_DISPERSY)
def SetData(self, delayedResult): if not self or not self.list: return data = [] torrents = delayedResult.get() for torrent in torrents: # FIXME(lipu): fix the thumbnail path to use metadata thumb_path = os.path.join( u"", binascii.hexlify(torrent.infohash)) if os.path.isdir(thumb_path): if not self.guiutility.getFamilyFilter() or not self.IsXXX(torrent, thumb_path): data.append((torrent.infohash, [torrent.name], torrent, ThumbnailListItemNoTorrent)) self.list.SetData(data) self.list.SetupScrolling() if len(data) < self.max_torrents: interval = self.update_interval / 4 else: interval = self.update_interval startWorker(self.SetData, self.GetTorrents, delay=interval, uId=u"ArtworkPanel_refresh")
def EnteredText(self, event): text = event.GetString() if text != self.text: self.text = text if self.entrycallback: def wx_callback(delayedResult, text): choices = delayedResult.get() if text == self.text: self.SetChoices(choices) if len(self.choices) == 0: self.ShowDropDown(False) else: self.ShowDropDown(True) def db_callback(text): if text == self.text: return self.entrycallback(text) startWorker(wx_callback, db_callback, cargs=(text, ), wargs=(text, ))
def dorequest(): if peers: if len(peers[0]) == 2: permid, selversion = peers[0] else: permid = peers[0] selversion = OLPROTO_VER_THIRTEENTH q = "CHANNEL p "+publisher_id if timeframe or not channel_id: record = timeframe else: record = startWorker(None, self.channelcastdb.getTimeframeForChannel, wargs = (channel_id, )) record = record.get() if record: q+= " "+" ".join(map(str,record)) self.session.query_peers(q,[permid],usercallback = seqcallback) self.overlay_bridge.add_task(lambda: seqtimeout(permid), 30)
def dosearch(self, input=None): if input == None: sf = self.frame.top_bg.searchField if sf is None: return input = sf.GetValue() if input: input = input.strip() if input == '': return else: return self.frame.top_bg.searchField.SetValue(input) if input.startswith("http://"): if self.frame.startDownloadFromUrl(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') elif input.startswith("magnet:"): if self.frame.startDownloadFromMagnet(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') elif input.startswith(SWIFT_URL_SCHEME): if self.frame.startDownloadFromSwift(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') else: keywords = split_into_keywords(input) keywords = [keyword for keyword in keywords if len(keyword) > 1] if len(keywords) == 0: self.Notify('Please enter a search term', wx.ART_INFORMATION) else: self.frame.top_bg.StartSearch() self.current_search_query = keywords if DEBUG: print >> sys.stderr, "GUIUtil: searchFiles:", keywords, time( ) self.frame.searchlist.Freeze() self.torrentsearch_manager.setSearchKeywords(keywords) self.channelsearch_manager.setSearchKeywords(keywords) self.frame.searchlist.Reset() self.ShowPage('search_results', keywords) #We now have to call thaw, otherwise loading message will not be shown. self.frame.searchlist.Thaw() #Peform local search self.torrentsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) self.channelsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) def db_thread(): self.torrentsearch_manager.refreshGrid() nr_peers_connected = self.torrentsearch_manager.searchDispersy( ) self.channelsearch_manager.searchDispersy() return nr_peers_connected def wx_thread(delayedResult): nr_peers_connected = delayedResult.get() self.frame.searchlist.SetMaxResults( nr_peers_connected + 1, keywords) self.frame.searchlist.NewResult() startWorker(wx_thread, db_thread, priority=1024)
def dosearch(self, input = None): if input == None: sf = self.frame.top_bg.searchField if sf is None: return input = sf.GetValue() if input: input = input.strip() if input == '': return else: return self.frame.top_bg.searchField.SetValue(input) if input.startswith("http://"): if self.frame.startDownloadFromUrl(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') elif input.startswith("magnet:"): if self.frame.startDownloadFromMagnet(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') elif input.startswith(SWIFT_URL_SCHEME) or input.startswith("ppsp://"): if self.frame.startDownloadFromSwift(str(input)): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') else: keywords = split_into_keywords(input) keywords = [keyword for keyword in keywords if len(keyword) > 1] if len(keywords) == 0: self.Notify('Please enter a search term', "Your search term '%s' was either to small or to general." % input , icon = wx.ART_INFORMATION) else: self.frame.top_bg.StartSearch() self.current_search_query = keywords if DEBUG: print >>sys.stderr,"GUIUtil: searchFiles:", keywords, time() self.frame.searchlist.Freeze() self.torrentsearch_manager.setSearchKeywords(keywords) self.channelsearch_manager.setSearchKeywords(keywords) # We set oldkeywords to '', which will trigger a reset in SetKeywords (called from ShowPage). This avoid calling reset twice. # Niels: 17-09-2012, unfortunately showpage calls show(true) which results in the dirty items being refreshed. # We need to call Reset in order to prevent this from happening self.frame.searchlist.Reset() self.ShowPage('search_results', keywords) #We now have to call thaw, otherwise loading message will not be shown. self.frame.searchlist.Thaw() #Peform local search self.torrentsearch_manager.set_gridmgr(self.frame.searchlist.GetManager()) self.channelsearch_manager.set_gridmgr(self.frame.searchlist.GetManager()) def db_thread(): self.torrentsearch_manager.refreshGrid() nr_peers_connected = self.torrentsearch_manager.searchDispersy() self.channelsearch_manager.searchDispersy() return nr_peers_connected def wx_thread(delayedResult): nr_peers_connected = delayedResult.get() self.frame.searchlist.SetMaxResults(nr_peers_connected+1, keywords) self.frame.searchlist.NewResult() startWorker(wx_thread, db_thread, priority = 1024)
def refreshNow(self): startWorker(self.SetData, self.GetTorrents)
def dosearch(self, input=None): if input is None: sf = self.frame.top_bg.searchField if sf is None: return input = sf.GetValue() if input: input = input.strip() if input == '': return else: return self.frame.top_bg.searchField.SetValue(input) if self.frame.startDownloadFromArg(input): self.frame.top_bg.searchField.Clear() self.ShowPage('my_files') else: keywords = split_into_keywords(input) keywords = [keyword for keyword in keywords if len(keyword) > 1] if len(keywords) == 0: self.Notify( 'Please enter a search term', "Your search term '%s' was either to small or to general." % input, icon=wx.ART_INFORMATION) else: self.frame.top_bg.StartSearch() self.current_search_query = keywords self._logger.debug("GUIUtil: searchFiles: %s %s", keywords, time()) self.frame.searchlist.Freeze() self.torrentsearch_manager.setSearchKeywords(keywords) self.channelsearch_manager.setSearchKeywords(keywords) # We set oldkeywords to '', which will trigger a reset in SetKeywords (called from ShowPage). # This avoids calling reset twice. # Niels: 17-09-2012, unfortunately showpage calls show(true) # which results in the dirty items being refreshed. # We need to call Reset in order to prevent this from happening self.frame.searchlist.Reset() self.ShowPage('search_results', keywords) # We now have to call thaw, otherwise loading message will not be shown. self.frame.searchlist.Thaw() # Peform local search self.torrentsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) self.channelsearch_manager.set_gridmgr( self.frame.searchlist.GetManager()) def db_thread(): self.torrentsearch_manager.refreshGrid() nr_peers_connected = self.torrentsearch_manager.searchDispersy( ) self.channelsearch_manager.searchDispersy() return nr_peers_connected def wx_thread(delayedResult): nr_peers_connected = delayedResult.get() if self and self.frame and self.frame.searchlist: self.frame.searchlist.SetMaxResults( nr_peers_connected + 1, keywords) self.frame.searchlist.NewResult() startWorker(wx_thread, db_thread, priority=1024)
def RefreshList(self): def db_callback(): topTen = self.barterdb.getTopNPeers(10) self._RefreshList(topTen) startWorker(None, db_callback, uId="TopContributorsPanel_RefreshList")
def PostInit2(self): self.frame.Raise() self.startWithRightView() self.set_reputation() s = self.utility.session s.add_observer(self.sesscb_ntfy_reachable, NTFY_REACHABLE, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_activities, NTFY_ACTIVITIES, [NTFY_INSERT], cache=10) s.add_observer( self.sesscb_ntfy_channelupdates, NTFY_CHANNELCAST, [NTFY_INSERT, NTFY_UPDATE, NTFY_CREATE, NTFY_STATE, NTFY_MODIFIED], cache=10) s.add_observer(self.sesscb_ntfy_channelupdates, NTFY_VOTECAST, [NTFY_UPDATE], cache=10) s.add_observer(self.sesscb_ntfy_myprefupdates, NTFY_MYPREFERENCES, [NTFY_INSERT, NTFY_UPDATE, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_torrentupdates, NTFY_TORRENTS, [NTFY_UPDATE, NTFY_INSERT], cache=10) s.add_observer(self.sesscb_ntfy_playlistupdates, NTFY_PLAYLISTS, [NTFY_INSERT, NTFY_UPDATE]) s.add_observer(self.sesscb_ntfy_commentupdates, NTFY_COMMENTS, [NTFY_INSERT, NTFY_DELETE]) s.add_observer(self.sesscb_ntfy_modificationupdates, NTFY_MODIFICATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_moderationupdats, NTFY_MODERATIONS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_markingupdates, NTFY_MARKINGS, [NTFY_INSERT]) s.add_observer(self.sesscb_ntfy_torrentfinished, NTFY_TORRENTS, [NTFY_FINISHED]) s.add_observer( self.sesscb_ntfy_magnet, NTFY_TORRENTS, [NTFY_MAGNET_GOT_PEERS, NTFY_MAGNET_STARTED, NTFY_MAGNET_CLOSE]) # TODO(emilon): Use the LogObserver I already implemented # self.dispersy.callback.attach_exception_handler(self.frame.exceptionHandler) startWorker(None, self.loadSessionCheckpoint, delay=5.0, workerType="ThreadPool") # initialize the torrent feed thread channelcast = s.open_dbhandler(NTFY_CHANNELCAST) def db_thread(): return channelcast.getMyChannelId() def wx_thread(delayedResult): my_channel = delayedResult.get() if my_channel: self.torrentfeed.register(self.utility.session, my_channel) self.torrentfeed.addCallback( my_channel, self.guiUtility.channelsearch_manager.createTorrentFromDef) startWorker(wx_thread, db_thread, delay=5.0)
def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread( ), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir( self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick( 'Starting session and upgrading database (it may take a while)' ) s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer( self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame( self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon( wx.Icon( os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame( self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # 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() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread( 0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance( self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e)
def do_schedule(filename): if not filename: self._save_torrent(tdef, callback) elif callback: startWorker(None, callback)
def RefreshList(self): def db_callback(): topTen = self.barterdb.getTopNPeers(10) self._RefreshList(topTen) startWorker(None, db_callback, uId ="TopContributorsPanel_RefreshList")
def has_torrent(self, infohash, callback): startWorker(None, self._has_torrent, wargs = (infohash, self.tor_col_dir, callback))
def showChannelFromId(self, channel_id): def db_callback(): channel = self.channelsearch_manager.getChannel(channel_id) self.showChannel(channel) startWorker(None, db_callback, priority=GUI_PRI_DISPERSY)
def __init__(self, abc, parent, internalvideo): self.abc = abc self._logger = logging.getLogger(self.__class__.__name__) self._logger.info('GUI started') # Do all init here self.ready = False self.guiUtility = GUIUtility.getInstance() self.guiUtility.frame = self self.utility = self.guiUtility.utility self.params = self.guiUtility.params self.utility.frame = self self.videoframe = None self.category = self.utility.session.lm.category self.shutdown_and_upgrade_notes = None title = "Tribler %s" % version_id # Get window size and (sash) position from config file size, position, sashpos = self.getWindowSettings() style = wx.DEFAULT_DIALOG_STYLE | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN wx.Frame.__init__(self, parent, wx.ID_ANY, title, position, size, style) if sys.platform == 'linux2': font = self.GetFont() if font.GetPointSize() > 9: font.SetPointSize(9) self.SetFont(font) self.Freeze() self.SetDoubleBuffered(True) self.SetBackgroundColour(DEFAULT_BACKGROUND) themeColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) r, g, b = themeColour.Get(False) if r > 190 or g > 190 or b > 190: # Grey == 190,190,190 self.SetForegroundColour(wx.BLACK) if internalvideo: self.videoparentpanel = wx.Panel(self) self.videoparentpanel.Hide() else: self.videoparentpanel = None # Create all components self.utility.session.notifier.notify(NTFY_STARTUP_TICK, NTFY_INSERT, None, 'Creating panels') self.actlist = ActivitiesList(self) self.top_bg = TopSearchPanel(self) self.home = Home(self) self.splitter = wx.SplitterWindow(self, style=wx.SP_NOBORDER) self.splitter.SetMinimumPaneSize(1) self.splitter.SetForegroundColour(self.GetForegroundColour()) self.splitter_top_window = wx.Panel(self.splitter, style=wx.NO_BORDER) self.splitter_top_window.SetForegroundColour( self.GetForegroundColour()) self.splitter_top = wx.BoxSizer(wx.HORIZONTAL) self.splitter_top_window.SetSizer(self.splitter_top) self.splitter_bottom_window = wx.Panel(self.splitter) self.splitter_bottom_window.SetMinSize((-1, 25)) self.splitter_bottom_window.SetForegroundColour( self.GetForegroundColour()) self.splitter_bottom_window.OnChange = lambda: self.splitter_bottom.Layout( ) self.splitter_bottom_window.parent_list = self.splitter_bottom_window self.networkgraph = NetworkGraphPanel(self) self.networkgraph.Show(False) self.searchlist = SearchList(self.splitter_top_window) self.searchlist.Show(False) self.librarylist = LibraryList(self.splitter_top_window) self.librarylist.Show(False) self.channellist = ChannelList(self.splitter_top_window) self.channellist.Show(False) self.selectedchannellist = SelectedChannelList( self.splitter_top_window) self.selectedchannellist.Show(False) self.playlist = Playlist(self.splitter_top_window) self.playlist.Show(False) self.creditminingpanel = CreditMiningPanel(self) self.creditminingpanel.Show(False) # Populate the bottom window self.splitter_bottom = wx.BoxSizer(wx.HORIZONTAL) self.torrentdetailspanel = TorrentDetails(self.splitter_bottom_window) self.torrentdetailspanel.Show(False) self.librarydetailspanel = LibraryDetails(self.splitter_bottom_window) self.librarydetailspanel.Show(False) self.channeldetailspanel = ChannelDetails(self.splitter_bottom_window) self.channeldetailspanel.Show(False) self.playlistdetailspanel = PlaylistDetails( self.splitter_bottom_window) self.playlistdetailspanel.Show(False) self.searchinfopanel = SearchInfoPanel(self.splitter_bottom_window) self.searchinfopanel.Show(False) self.channelinfopanel = ChannelInfoPanel(self.splitter_bottom_window) self.channelinfopanel.Show(False) self.libraryinfopanel = LibraryInfoPanel(self.splitter_bottom_window) self.libraryinfopanel.Show(False) self.playlistinfopanel = PlaylistInfoPanel(self.splitter_bottom_window) self.playlistinfopanel.Show(False) self.selectedchannelinfopanel = SelectedchannelInfoPanel( self.splitter_bottom_window) self.selectedchannelinfopanel.Show(False) self.splitter_bottom.Add(self.torrentdetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.librarydetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.channeldetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.playlistdetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.searchinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.channelinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.libraryinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.playlistinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.selectedchannelinfopanel, 1, wx.EXPAND) self.splitter_bottom_window.SetSizer(self.splitter_bottom) self.splitter.SetSashGravity(0.8) self.splitter.SplitHorizontally(self.splitter_top_window, self.splitter_bottom_window, sashpos) self.splitter.Show(False) # Reset the sash position after the splitter has been made visible def OnShowSplitter(event): wx.CallAfter(self.splitter.SetSashPosition, sashpos) self.splitter.Unbind(wx.EVT_SHOW) event.Skip() self.splitter.Bind(wx.EVT_SHOW, OnShowSplitter) self.stats = Stats(self) self.stats.Show(False) self.managechannel = ManageChannel(self) self.managechannel.Show(False) self.utility.session.notifier.notify(NTFY_STARTUP_TICK, NTFY_INSERT, None, 'Positioning') # position all elements vSizer = wx.BoxSizer(wx.VERTICAL) vSizer.Add(self.top_bg, 0, wx.EXPAND) hSizer = wx.BoxSizer(wx.HORIZONTAL) vSizer.Add(hSizer, 1, wx.EXPAND) hSizer.Add(self.actlist, 0, wx.EXPAND) separator = wx.Panel(self, size=(1, -1)) separator.SetBackgroundColour(SEPARATOR_GREY) hSizer.Add(separator, 0, wx.EXPAND) hSizer.Add(self.home, 1, wx.EXPAND) hSizer.Add(self.stats, 1, wx.EXPAND) hSizer.Add(self.networkgraph, 1, wx.EXPAND) hSizer.Add(self.splitter, 1, wx.EXPAND) hSizer.Add(self.managechannel, 1, wx.EXPAND) if self.videoparentpanel: hSizer.Add(self.videoparentpanel, 1, wx.EXPAND) hSizer.Add(self.creditminingpanel, 1, wx.EXPAND) self.SetSizer(vSizer) # set sizes self.top_bg.SetMinSize((-1, 45)) self.actlist.SetMinSize((200, -1)) self.SRstatusbar = SRstatusbar(self) self.SetStatusBar(self.SRstatusbar) def preload_data(): self.guiUtility.showChannelCategory('All', False) self.guiUtility.showLibrary(False) startWorker(None, preload_data, delay=1.5, workerType="ThreadPool") if sys.platform != 'darwin': dragdroplist = FileDropTarget(self) self.SetDropTarget(dragdroplist) try: self.SetIcon( wx.Icon( os.path.join(self.utility.getPath(), 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) except: pass self.tbicon = None try: self.tbicon = ABCTaskBarIcon(self) except: print_exc() # Don't update GUI as often when iconized self.GUIupdate = True self.window = self.GetChildren()[0] self.window.utility = self.utility self.utility.session.notifier.notify(NTFY_STARTUP_TICK, NTFY_INSERT, None, 'Binding events') # Menu Events # self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) # 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) self.Bind(wx.EVT_ICONIZE, self.onIconify) self.Bind(wx.EVT_SIZE, self.onSize) self.Bind(wx.EVT_MAXIMIZE, self.onSize) findId = wx.NewId() quitId = wx.NewId() nextId = wx.NewId() prevId = wx.NewId() dispId = wx.NewId() wxId = wx.NewId() anonId = wx.NewId() DISPERSY_DEBUG_FRAME_ID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnFind, id=findId) self.Bind(wx.EVT_MENU, lambda event: self.Close(), id=quitId) self.Bind(wx.EVT_MENU, self.OnNext, id=nextId) self.Bind(wx.EVT_MENU, self.OnPrev, id=prevId) self.Bind(wx.EVT_MENU, lambda evt: self.guiUtility.ShowPage('stats'), id=dispId) self.Bind(wx.EVT_MENU, lambda evt: self.OpenInspectionTool(), id=wxId) self.Bind(wx.EVT_MENU, lambda evt: self.guiUtility.ShowPage('networkgraph'), id=anonId) self.Bind(wx.EVT_MENU, self.OnOpenDebugFrame, id=DISPERSY_DEBUG_FRAME_ID) accelerators = [(wx.ACCEL_CTRL, ord('f'), findId)] accelerators.append((wx.ACCEL_CTRL, ord('d'), dispId)) accelerators.append((wx.ACCEL_CTRL, ord('i'), wxId)) accelerators.append((wx.ACCEL_CTRL, ord('n'), anonId)) accelerators.append((wx.ACCEL_CTRL, wx.WXK_TAB, nextId)) accelerators.append( (wx.ACCEL_CTRL | wx.ACCEL_SHIFT, wx.WXK_TAB, prevId)) accelerators.append( (wx.ACCEL_CTRL | wx.ACCEL_ALT, ord('d'), DISPERSY_DEBUG_FRAME_ID)) if sys.platform == 'linux2': accelerators.append((wx.ACCEL_CTRL, ord('q'), quitId)) accelerators.append((wx.ACCEL_CTRL, ord('/'), findId)) self.SetAcceleratorTable(wx.AcceleratorTable(accelerators)) # Init video player self.utility.session.notifier.notify(NTFY_STARTUP_TICK, NTFY_INSERT, None, 'GUI complete') self.Thaw() self.ready = True self.SetMinSize((800, 600)) def post(): self.startCMDLineTorrent() # If the user passed a torrentfile on the cmdline, load it. wx.CallAfter(post)
def __init__(self, abc, parent, internalvideo, progress): self.abc = abc self._logger = logging.getLogger(self.__class__.__name__) self._logger.info('GUI started') # Do all init here self.ready = False self.guiUtility = GUIUtility.getInstance() self.guiUtility.frame = self self.utility = self.guiUtility.utility self.params = self.guiUtility.params self.utility.frame = self self.torrentfeed = None self.videoframe = None self.category = Category.getInstance() self.shutdown_and_upgrade_notes = None title = "Tribler %s" % version_id # Get window size and (sash) position from config file size, position, sashpos = self.getWindowSettings() style = wx.DEFAULT_DIALOG_STYLE | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_CHILDREN wx.Frame.__init__(self, parent, wx.ID_ANY, title, position, size, style) if sys.platform == 'linux2': font = self.GetFont() if font.GetPointSize() > 9: font.SetPointSize(9) self.SetFont(font) self.Freeze() self.SetDoubleBuffered(True) self.SetBackgroundColour(DEFAULT_BACKGROUND) themeColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) r, g, b = themeColour.Get(False) if r > 190 or g > 190 or b > 190: # Grey == 190,190,190 self.SetForegroundColour(wx.BLACK) if internalvideo: self.videoparentpanel = wx.Panel(self) self.videoparentpanel.Hide() else: self.videoparentpanel = None # Create all components progress('Creating panels') self.actlist = ActivitiesList(self) self.top_bg = TopSearchPanel(self) self.home = Home(self) self.splitter = wx.SplitterWindow(self, style=wx.SP_NOBORDER) self.splitter.SetMinimumPaneSize(1) self.splitter.SetForegroundColour(self.GetForegroundColour()) self.splitter_top_window = wx.Panel(self.splitter, style=wx.NO_BORDER) self.splitter_top_window.SetForegroundColour(self.GetForegroundColour()) self.splitter_top = wx.BoxSizer(wx.HORIZONTAL) self.splitter_top_window.SetSizer(self.splitter_top) self.splitter_bottom_window = wx.Panel(self.splitter) self.splitter_bottom_window.SetMinSize((-1, 25)) self.splitter_bottom_window.SetForegroundColour(self.GetForegroundColour()) self.splitter_bottom_window.OnChange = lambda: self.splitter_bottom.Layout() self.splitter_bottom_window.parent_list = self.splitter_bottom_window self.networkgraph = NetworkGraphPanel(self) self.networkgraph.Show(False) self.searchlist = SearchList(self.splitter_top_window) self.searchlist.Show(False) self.librarylist = LibraryList(self.splitter_top_window) self.librarylist.Show(False) self.channellist = ChannelList(self.splitter_top_window) self.channellist.Show(False) self.selectedchannellist = SelectedChannelList(self.splitter_top_window) self.selectedchannellist.Show(False) self.playlist = Playlist(self.splitter_top_window) self.playlist.Show(False) # Populate the bottom window self.splitter_bottom = wx.BoxSizer(wx.HORIZONTAL) self.torrentdetailspanel = TorrentDetails(self.splitter_bottom_window) self.torrentdetailspanel.Show(False) self.librarydetailspanel = LibraryDetails(self.splitter_bottom_window) self.librarydetailspanel.Show(False) self.channeldetailspanel = ChannelDetails(self.splitter_bottom_window) self.channeldetailspanel.Show(False) self.playlistdetailspanel = PlaylistDetails(self.splitter_bottom_window) self.playlistdetailspanel.Show(False) self.searchinfopanel = SearchInfoPanel(self.splitter_bottom_window) self.searchinfopanel.Show(False) self.channelinfopanel = ChannelInfoPanel(self.splitter_bottom_window) self.channelinfopanel.Show(False) self.libraryinfopanel = LibraryInfoPanel(self.splitter_bottom_window) self.libraryinfopanel.Show(False) self.playlistinfopanel = PlaylistInfoPanel(self.splitter_bottom_window) self.playlistinfopanel.Show(False) self.selectedchannelinfopanel = SelectedchannelInfoPanel(self.splitter_bottom_window) self.selectedchannelinfopanel.Show(False) self.splitter_bottom.Add(self.torrentdetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.librarydetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.channeldetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.playlistdetailspanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.searchinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.channelinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.libraryinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.playlistinfopanel, 1, wx.EXPAND) self.splitter_bottom.Add(self.selectedchannelinfopanel, 1, wx.EXPAND) self.splitter_bottom_window.SetSizer(self.splitter_bottom) self.splitter.SetSashGravity(0.8) self.splitter.SplitHorizontally(self.splitter_top_window, self.splitter_bottom_window, sashpos) self.splitter.Show(False) # Reset the sash position after the splitter has been made visible def OnShowSplitter(event): wx.CallAfter(self.splitter.SetSashPosition, sashpos) self.splitter.Unbind(wx.EVT_SHOW) event.Skip() self.splitter.Bind(wx.EVT_SHOW, OnShowSplitter) self.stats = Stats(self) self.stats.Show(False) self.managechannel = ManageChannel(self) self.managechannel.Show(False) progress('Positioning') # position all elements vSizer = wx.BoxSizer(wx.VERTICAL) vSizer.Add(self.top_bg, 0, wx.EXPAND) hSizer = wx.BoxSizer(wx.HORIZONTAL) vSizer.Add(hSizer, 1, wx.EXPAND) hSizer.Add(self.actlist, 0, wx.EXPAND) separator = wx.Panel(self, size=(1, -1)) separator.SetBackgroundColour(SEPARATOR_GREY) hSizer.Add(separator, 0, wx.EXPAND) hSizer.Add(self.home, 1, wx.EXPAND) hSizer.Add(self.stats, 1, wx.EXPAND) hSizer.Add(self.networkgraph, 1, wx.EXPAND) hSizer.Add(self.splitter, 1, wx.EXPAND) hSizer.Add(self.managechannel, 1, wx.EXPAND) if self.videoparentpanel: hSizer.Add(self.videoparentpanel, 1, wx.EXPAND) self.SetSizer(vSizer) # set sizes self.top_bg.SetMinSize((-1, 45)) self.actlist.SetMinSize((200, -1)) self.SRstatusbar = SRstatusbar(self) self.SetStatusBar(self.SRstatusbar) def preload_data(): self.guiUtility.showChannelCategory('All', False) self.guiUtility.showLibrary(False) startWorker(None, preload_data, delay=1.5, workerType="ThreadPool") if sys.platform != 'darwin': dragdroplist = FileDropTarget(self) self.SetDropTarget(dragdroplist) try: self.SetIcon( wx.Icon(os.path.join(self.utility.getPath(), 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) except: pass self.tbicon = None try: self.tbicon = ABCTaskBarIcon(self) except: print_exc() # Don't update GUI as often when iconized self.GUIupdate = True self.window = self.GetChildren()[0] self.window.utility = self.utility progress('Binding events') # Menu Events # self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) # 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) self.Bind(wx.EVT_ICONIZE, self.onIconify) self.Bind(wx.EVT_SIZE, self.onSize) self.Bind(wx.EVT_MAXIMIZE, self.onSize) findId = wx.NewId() quitId = wx.NewId() nextId = wx.NewId() prevId = wx.NewId() dispId = wx.NewId() anonId = wx.NewId() DISPERSY_DEBUG_FRAME_ID = wx.NewId() self.Bind(wx.EVT_MENU, self.OnFind, id=findId) self.Bind(wx.EVT_MENU, lambda event: self.Close(), id=quitId) self.Bind(wx.EVT_MENU, self.OnNext, id=nextId) self.Bind(wx.EVT_MENU, self.OnPrev, id=prevId) self.Bind(wx.EVT_MENU, lambda evt: self.guiUtility.ShowPage('stats'), id=dispId) self.Bind(wx.EVT_MENU, lambda evt: self.guiUtility.ShowPage('networkgraph'), id=anonId) self.Bind(wx.EVT_MENU, self.OnOpenDebugFrame, id=DISPERSY_DEBUG_FRAME_ID) accelerators = [(wx.ACCEL_CTRL, ord('f'), findId)] accelerators.append((wx.ACCEL_CTRL, ord('d'), dispId)) accelerators.append((wx.ACCEL_CTRL, ord('n'), anonId)) accelerators.append((wx.ACCEL_CTRL, wx.WXK_TAB, nextId)) accelerators.append((wx.ACCEL_CTRL | wx.ACCEL_SHIFT, wx.WXK_TAB, prevId)) accelerators.append((wx.ACCEL_CTRL | wx.ACCEL_ALT, ord('d'), DISPERSY_DEBUG_FRAME_ID)) if sys.platform == 'linux2': accelerators.append((wx.ACCEL_CTRL, ord('q'), quitId)) accelerators.append((wx.ACCEL_CTRL, ord('/'), findId)) self.SetAcceleratorTable(wx.AcceleratorTable(accelerators)) # Init video player progress('GUI complete') self.Thaw() self.ready = True def post(): self.startCMDLineTorrent() # If the user passed a torrentfile on the cmdline, load it. wx.CallAfter(post)
def __init__(self, parent, tdef, defaultdir, defaultname, configfile, selectedFiles = None): wx.Dialog.__init__(self, parent, -1, 'Please specify a target directory', size=(600,450)) self.filehistory = wx.FileHistory(25) self.config = wx.FileConfig(appName = "Tribler", localFilename = configfile) self.filehistory.Load(self.config) self.defaultdir = defaultdir self.guiutility = GUIUtility.getInstance() self.listCtrl = None self.collected = None if self.filehistory.GetCount() > 0: lastUsed = self.filehistory.GetHistoryFile(0) else: lastUsed = defaultdir vSizer = wx.BoxSizer(wx.VERTICAL) if tdef: line = 'Please select a directory where to save:' else: line = 'Please select a directory where to save this torrent' firstLine = wx.StaticText(self, -1, line) _set_font(firstLine, fontweight=wx.FONTWEIGHT_BOLD) vSizer.Add(firstLine, 0, wx.EXPAND|wx.BOTTOM, 3) if tdef: torrentName = wx.StaticText(self, -1, tdef.get_name_as_unicode()) torrentName.SetMinSize((1, -1)) vSizer.Add(torrentName, 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT, 3) hSizer = wx.BoxSizer(wx.HORIZONTAL) hSizer.Add(wx.StaticText(self, -1, 'Save as:'), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.BOTTOM, 3) choices = [self.filehistory.GetHistoryFile(i) for i in range(self.filehistory.GetCount())] if defaultdir not in choices: choices.append(defaultdir) if defaultname: choices.insert(0, os.path.join(lastUsed, defaultname)) self.dirTextCtrl = wx.ComboBox(self, -1, os.path.join(lastUsed, defaultname), choices = choices, style = wx.CB_DROPDOWN) else: self.dirTextCtrl = wx.ComboBox(self, -1, lastUsed, choices = choices, style = wx.CB_DROPDOWN) self.dirTextCtrl.Select(0) hSizer.Add(self.dirTextCtrl, 1, wx.EXPAND|wx.RIGHT|wx.BOTTOM, 3) browseButton = wx.Button(self, -1, 'Browse') browseButton.Bind(wx.EVT_BUTTON, self.OnBrowseDir) hSizer.Add(browseButton) vSizer.Add(hSizer, 0, wx.EXPAND|wx.BOTTOM, 3) if tdef and tdef.get_files(): self.AddFileList(tdef, selectedFiles, vSizer, len(vSizer.GetChildren())) elif isinstance(tdef, TorrentDefNoMetainfo): text = wx.StaticText(self, -1, "Attempting to retrieve .torrent...") _set_font(text, size_increment = 1) ag = wx.animate.GIFAnimationCtrl(self, -1, os.path.join(self.guiutility.utility.getPath(), LIBRARYNAME, 'Main', 'vwxGUI', 'images', 'search_new.gif')) ag.Play() sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.AddStretchSpacer() sizer.Add(text, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 10) sizer.Add(ag, 0, wx.ALIGN_CENTER_VERTICAL) sizer.AddStretchSpacer() vSizer.Add(sizer, 1, wx.EXPAND|wx.BOTTOM, 3) self.SetSize((600,150)) url = tdef.get_url() if url and url.startswith("magnet:"): retrieve_from_magnet = lambda: TorrentDef.retrieve_from_magnet(url, lambda tdef: wx.CallAfter(self.SetCollected, tdef)) startWorker(None, retrieve_from_magnet, retryOnBusy = True, priority = GUI_PRI_DISPERSY) else: torrentsearch_manager = self.guiutility.torrentsearch_manager def do_collect(delayedResult): torrent = delayedResult.get() if torrent: def callback(): torrent_filename = torrentsearch_manager.getCollectedFilename(torrent) tdef = TorrentDef.load(torrent_filename) wx.CallAfter(self.SetCollected, tdef) torrentsearch_manager.getTorrent(torrent, callback) def do_db(): return torrentsearch_manager.getTorrentByInfohash(tdef.get_infohash()) startWorker(do_collect, do_db, retryOnBusy = True, priority = GUI_PRI_DISPERSY) cancel = wx.Button(self, wx.ID_CANCEL) cancel.Bind(wx.EVT_BUTTON, self.OnCancel) ok = wx.Button(self, wx.ID_OK) ok.Bind(wx.EVT_BUTTON, self.OnOk) bSizer = wx.StdDialogButtonSizer() bSizer.AddButton(cancel) bSizer.AddButton(ok) bSizer.Realize() vSizer.Add(bSizer, 0, wx.EXPAND|wx.BOTTOM, 3) sizer = wx.BoxSizer() sizer.Add(vSizer, 1, wx.EXPAND|wx.ALL, 10) self.SetSizer(sizer)
def showChannelFromPermid(self, channel_permid): def db_callback(): channel = self.channelsearch_manager.getChannelByPermid(channel_permid) self.showChannel(channel) startWorker(None, db_callback,priority=GUI_PRI_DISPERSY)
def __init__(self, params, installdir, autoload_discovery=True, use_torrent_search=True, use_channel_search=True): assert not isInIOThread(), "isInIOThread() seems to not be working correctly" self._logger = logging.getLogger(self.__class__.__name__) self.params = params self.installdir = installdir self.state_dir = None self.error = None self.last_update = 0 self.ready = False self.done = False self.frame = None self.upgrader = None self.said_start_playback = False self.decodeprogress = 0 self.old_reputation = 0 # DISPERSY will be set when available self.dispersy = None # BARTER_COMMUNITY will be set when both Dispersy and the EffortCommunity are available self.barter_community = None self.tunnel_community = None self.torrentfeed = None self.webUI = None self.utility = None # Stage 1 start session = self.InitStage1(installdir, autoload_discovery=autoload_discovery, use_torrent_search=use_torrent_search, use_channel_search=use_channel_search) self.splash = None try: bm = self.gui_image_manager.getImage(u'splash.png') self.splash = GaugeSplash(bm, "Loading...", 13) self.splash.Show() self._logger.info('Client Starting Up.') self._logger.info("Tribler is using %s as working directory", self.installdir) # Stage 2: show the splash window and start the session self.splash.tick('Starting API') s = self.startAPI(session, self.splash.tick) self.utility = Utility(self.installdir, s.get_state_dir()) if self.utility.read_config(u'saveas', u'downloadconfig'): DefaultDownloadStartupConfig.getInstance().set_dest_dir(self.utility.read_config(u'saveas', u'downloadconfig')) self.utility.set_app(self) self.utility.set_session(s) self.guiUtility = GUIUtility.getInstance(self.utility, self.params, self) GUIDBProducer.getInstance() self._logger.info('Tribler Version: %s Build: %s', version_id, commit_id) version_info = self.utility.read_config('version_info') if version_info.get('version_id', None) != version_id: # First run of a different version version_info['first_run'] = int(time()) version_info['version_id'] = version_id self.utility.write_config('version_info', version_info) self.splash.tick('Starting session and upgrading database (it may take a while)') s.start() self.dispersy = s.lm.dispersy self.splash.tick('Loading userdownloadchoice') from Tribler.Main.vwxGUI.UserDownloadChoice import UserDownloadChoice UserDownloadChoice.get_singleton().set_utility(self.utility) self.splash.tick('Initializing Family Filter') cat = Category.getInstance(session) state = self.utility.read_config('family_filter') if state in (1, 0): cat.set_family_filter(state == 1) else: self.utility.write_config('family_filter', 1) self.utility.flush_config() cat.set_family_filter(True) # Create global speed limits self.splash.tick('Setting up speed limits') # Counter to suppress some event from occurring self.ratestatecallbackcount = 0 maxup = self.utility.read_config('maxuploadrate') maxdown = self.utility.read_config('maxdownloadrate') # set speed limits using LibtorrentMgr s.set_max_upload_speed(maxup) s.set_max_download_speed(maxdown) # Only allow updates to come in after we defined ratelimiter self.prevActiveDownloads = [] s.set_download_states_callback(self.sesscb_states_callback) # Schedule task for checkpointing Session, to avoid hash checks after # crashes. startWorker(consumer=None, workerFn=self.guiservthread_checkpoint_timer, delay=SESSION_CHECKPOINT_INTERVAL) if not ALLOW_MULTIPLE: # Put it here so an error is shown in the startup-error popup # Start server for instance2instance communication Instance2InstanceServer(self.utility.read_config('i2ilistenport'), self.i2ithread_readlinecallback) self.splash.tick('GUIUtility register') self.guiUtility.register() self.frame = MainFrame(self, None, PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(), self.splash.tick) self.frame.SetIcon(wx.Icon(os.path.join(self.installdir, 'Tribler', 'Main', 'vwxGUI', 'images', 'tribler.ico'), wx.BITMAP_TYPE_ICO)) # Arno, 2011-06-15: VLC 1.1.10 pops up separate win, don't have two. self.frame.videoframe = None if PLAYBACKMODE_INTERNAL in return_feasible_playback_modes(): vlcwrap = s.lm.videoplayer.get_vlcwrap() wx.CallLater(3000, vlcwrap._init_vlc) self.frame.videoframe = VideoDummyFrame(self.frame.videoparentpanel, self.utility, vlcwrap) if sys.platform == 'win32': wx.CallAfter(self.frame.top_bg.Refresh) wx.CallAfter(self.frame.top_bg.Layout) else: self.frame.top_bg.Layout() # 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() self.splash.Destroy() self.frame.Show(True) session.lm.threadpool.call_in_thread(0, self.guiservthread_free_space_check) self.torrentfeed = RssParser.getInstance() self.webUI = None if self.utility.read_config('use_webui'): try: from Tribler.Main.webUI.webUI import WebUI self.webUI = WebUI.getInstance(self.guiUtility.library_manager, self.guiUtility.torrentsearch_manager, self.utility.read_config('webui_port')) self.webUI.start() except Exception: print_exc() self.emercoin_mgr = None try: from Tribler.Main.Emercoin.EmercoinMgr import EmercoinMgr self.emercoin_mgr = EmercoinMgr(self.utility) except Exception: print_exc() wx.CallAfter(self.PostInit2) # 08/02/10 Boudewijn: Working from home though console # doesn't allow me to press close. The statement below # gracefully closes Tribler after 120 seconds. # wx.CallLater(120*1000, wx.GetApp().Exit) self.ready = True except Exception as e: if self.splash: self.splash.Destroy() self.onError(e)