def cancel_all( self): for element in self.status_list: self.status_list[element]['iter']=None self.status_list[element]['thread'].cancel() # clear the tree model after cancelling util.idle_add(self.tree_model.clear) self.downloads_done_bytes=0
def cover_download_finished(self, channel, pixbuf): def set_cover(channel, pixbuf): if self.channel == channel: self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf)) self.gPodderChannel.show() util.idle_add(set_cover, channel, pixbuf)
def on_ui_initialized(self, model, update_podcast_callback, download_episode_callback): """ Connect to the woodchuck server and initialize any state. model is an instance of the podcast model. podcast_update is a function that is passed a single argument: the PodcastPodcast that should be updated. episode_download is a function that is passed a single argument: the PodcastEpisode that should be downloaded. If podcast_update and episode_download are None, then Woodchuck upcalls will be disabled. In this case, you don't need to specify the list of podcasts. Just specify None. """ logger.info('Got on_ui_initialized. Setting up woodchuck..') if not woodchuck_imported: return global _main_thread _main_thread = threading.currentThread() global woodchuck_instance woodchuck_instance = mywoodchuck(model, update_podcast_callback, download_episode_callback) if not woodchuck_instance.available(): logger.warn('Unable to contact Woodchuck server. Disabling.') logger.info('Connected to Woodchuck server.') idle_add(check_subscriptions)
def add_sync_tasks(self, tracklist, force_played=False, done_callback=None): for track in list(tracklist): # Filter tracks that are not meant to be synchronized does_not_exist = not track.was_downloaded(and_exists=True) exclude_played = (not track.is_new and self._config.device_sync.skip_played_episodes) wrong_type = track.file_type() not in self.allowed_types if does_not_exist or exclude_played or wrong_type: logger.info('Excluding %s from sync', track.title) tracklist.remove(track) if tracklist: for track in sorted(tracklist, key=lambda e: e.pubdate_prop): if self.cancelled: return False # XXX: need to check if track is added properly? sync_task = SyncTask(track) sync_task.status = sync_task.QUEUED sync_task.device = self # New Task, we must wait on the GTK Loop self.download_status_model.register_task(sync_task) # Executes after task has been registered util.idle_add(self.download_queue_manager.queue_task, sync_task) else: logger.warning("No episodes to sync") if done_callback: done_callback()
def name_owner_changed(name, old_owner, new_owner): logger.debug('name_owner_changed "%s" "%s" "%s"', name, old_owner, new_owner) if name == self.bus_name: logger.debug('MPRISResumer player %s is there', name) cancel.remove() util.idle_add(lambda: self.do_enqueue(filename, pos))
def thread_func(self, tab=0): if tab == 1: model = OpmlListModel(opml.Importer(my.TOPLIST_OPML)) if len(model) == 0: self.notification( _('The specified URL does not provide any valid OPML podcast items.' ), _('No feeds found')) elif tab == 2: model = OpmlListModel( youtube.find_youtube_channels( self.entryYoutubeSearch.get_text())) if len(model) == 0: self.notification( _('There are no YouTube channels that would match this query.' ), _('No channels found')) else: url = self.entryURL.get_text() if self.is_search_term(url): url = 'http://gpodder.net/search.opml?q=' + urllib.quote(url) model = OpmlListModel(opml.Importer(url)) if len(model) == 0: self.notification( _('The specified URL does not provide any valid OPML podcast items.' ), _('No feeds found')) util.idle_add(self.thread_finished, model, tab)
def wrapper(*args, **kwargs): if not woodchuck_instance.available(): return def doit(): @wraps(func) def it(): # Execute the function. # Assert that we are running in the main thread. assert _main_thread is not None assert threading.currentThread() == _main_thread, \ ("idle function executed in %s, not %s" % (threading.currentThread(), _main_thread)) try: func(*args, **kwargs) except KeyboardInterrupt: raise except: logger.error( "execute_in_main_thread: Executing %s: %s" % (func, traceback.format_exc())) return False return it if threading.currentThread() == _main_thread: logger.debug("Already in main thread. Executing %s" % (func,)) doit()() else: logger.debug("Queuing execution of %s from %s" % (func, threading.currentThread())) idle_add(doit())
def download_thread_func(): if url.startswith('youtube://'): importer = youtube.find_youtube_channels(\ url[len('youtube://'):]) else: importer = opml.Importer(url) if importer.items: model = OpmlListModel(importer) else: model = None def download_thread_finished(): self._is_updating = False self.treeview.queue_draw() hildon.hildon_gtk_window_set_progress_indicator(\ self.main_window, False) self.action_select_all.set_property('visible', \ model is not None) self.action_select_none.set_property('visible', \ model is not None) self.treeview.set_model(model) self.set_subscribe_button_sensitive() if model is None: self.show_message(_('No podcasts found. Try another source.'), \ important=True) self.main_window.destroy() util.idle_add(download_thread_finished)
def wrapper(*args, **kwargs): if not woodchuck_instance.available(): return def doit(): @wraps(func) def it(): # Execute the function. # Assert that we are running in the main thread. assert _main_thread is not None assert threading.currentThread() == _main_thread, \ ("idle function executed in %s, not %s" % (threading.currentThread(), _main_thread)) try: func(*args, **kwargs) except KeyboardInterrupt: raise except: logger.error("execute_in_main_thread: Executing %s: %s" % (func, traceback.format_exc())) return False return it if threading.currentThread() == _main_thread: logger.debug("Already in main thread. Executing %s" % (func, )) doit()() else: logger.debug("Queuing execution of %s from %s" % (func, threading.currentThread())) idle_add(doit())
def notify(self, signal_name, *args): if signal_name in self.observers: for observer in self.observers[signal_name]: util.idle_add(observer, *args) return True return False
def execute(): try: generator.next() idle_add(execute) except StopIteration: return except Exception, e: logger.exception("Running %s: %s" % (str(func), str(e)))
def on_web_request(self, web_view, web_frame, web_resource, request, response): uri = request.get_uri() if uri.startswith(self.flattr.CALLBACK): if not self.flattr.process_retrieved_code(uri): self.show_message(query["error_description"][0], _("Error"), important=True) # Destroy the window later util.idle_add(self.main_window.destroy)
def replace_from_channel(self, channel, downloading=None, \ include_description=False, generate_thumbnails=False, \ treeview=None): """ Add episode from the given channel to this model. Downloading should be a callback. include_description should be a boolean value (True if description is to be added to the episode row, or False if not) """ # Remove old episodes in the list store self.clear() if treeview is not None: util.idle_add(treeview.queue_draw) self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False) # Avoid gPodder bug 1291 if channel is None: episodes = [] else: episodes = channel.get_all_episodes() if not isinstance(episodes, list): episodes = list(episodes) count = len(episodes) for position, episode in enumerate(episodes): iter = self.append((episode.url, \ episode.title, \ self._format_filesize(episode), \ episode, \ None, \ episode.cute_pubdate(), \ '', \ '', \ True, \ True, \ True, \ episode.length, \ episode.pubDate, \ episode.get_play_info_string(), \ episode.total_time and not episode.current_position, \ episode.total_time and episode.current_position, \ episode.is_locked)) self.update_by_iter(iter, downloading, include_description, \ generate_thumbnails, reload_from_db=False) self._on_filter_changed(self.has_episodes()) log("updated model") def hello(): log("idle again") gtk.idle_add(hello)
def on_web_request(self, web_view, web_frame, web_resource, request, response): uri = request.get_uri() if uri.startswith(self.flattr.CALLBACK): if not self.flattr.process_retrieved_code(uri): self.show_message(query['error_description'][0], _('Error'), important=True) # Destroy the window later util.idle_add(self.main_window.destroy)
def cover_download_finished(self, channel, pixbuf): def set_cover(channel, pixbuf): if self.channel == channel: self.imgCover.set_from_pixbuf(self.scale_pixbuf(pixbuf)) if self.show_on_cover_load: self.main_window.show() self.show_on_cover_load = False util.idle_add(set_cover, channel, pixbuf)
def convert(): ffmpeg = subprocess.Popen(['ffmpeg', '-f', 'concat', '-nostdin', '-y', '-i', list_filename, '-c', 'copy', out_filename]) result = ffmpeg.wait() util.delete_file(list_filename) util.idle_add(lambda: indicator.on_finished()) util.idle_add(lambda: self.gpodder.show_message( _('Videos successfully converted') if result == 0 else _('Error converting videos'), _('Concatenation result'), important=True))
def connect_gtk_window( self, window, config_prefix='main_window'): ( x, y, width, height )=map( lambda x: config_prefix + '_' + x, [ 'x', 'y', 'width', 'height' ]) if set( ( x, y, width, height )).issubset( set( self.Settings)): window.resize( getattr( self, width), getattr( self, height)) window.move( getattr( self, x), getattr( self, y)) self.disable_window_events() util.idle_add(self.enable_window_events) window.connect( 'configure-event', self.receive_configure_event, config_prefix) else: raise ValueError( 'Missing settings in set: %s' % ', '.join( ( x, y, width, height )))
def convert(): ffmpeg = util.Popen(['ffmpeg', '-f', 'concat', '-nostdin', '-y', '-i', list_filename, '-c', 'copy', out_filename], close_fds=True) result = ffmpeg.wait() util.delete_file(list_filename) util.idle_add(lambda: indicator.on_finished()) util.idle_add(lambda: self.gpodder.show_message( _('Videos successfully converted') if result == 0 else _('Error converting videos'), _('Concatenation result'), important=True))
def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) if gpodder.ui.win32: window.set_gravity(Gdk.Gravity.STATIC) if cfg.width != -1 and cfg.height != -1: window.resize(cfg.width, cfg.height) # Not all platforms can natively restore position, gPodder must handle it. # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693 if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # From Gtk docs: most window managers ignore requests for initial window # positions (instead using a user-defined placement algorithm) and honor # requests after the window has already been shown. # Move it a second time after the window has been shown. # The first move reduces chance of window jumping. util.idle_add(window.move, cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True # Get window state, correct size comes from window.get_size(), # see https://developer.gnome.org/SaveWindowState/ def _receive_configure_event(widget, event): x_pos, y_pos = widget.get_position() width_size, height_size = widget.get_size() maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) if not self.__ignore_window_events and not maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED) cfg.maximized = new_value window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()
def subscribeEvent_reply_(self, event, reply): """ handles a 'Subscribe to...' event""" filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject)) fileURLData = filelist.data() url = buffer(fileURLData.bytes(),0,fileURLData.length()) url = str(url) print >>sys.stderr,("Subscribe to :"+url) util.idle_add(self.gp.subscribe_to_url, url) result = NSAppleEventDescriptor.descriptorWithInt32_(42) reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
def subscribeEvent_reply_(self, event, reply): """ handles a 'Subscribe to...' event""" filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject)) fileURLData = filelist.data() url = buffer(fileURLData.bytes(),0,fileURLData.length()) url = str(url) print(("Subscribe to :" + url), file=sys.stderr) util.idle_add(self.gp.subscribe_to_url, url) result = NSAppleEventDescriptor.descriptorWithInt32_(42) reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) if gpodder.ui.win32: window.set_gravity(Gdk.Gravity.STATIC) if cfg.width != -1 and cfg.height != -1: window.resize(cfg.width, cfg.height) # Not all platforms can natively restore position, gPodder must handle it. # https://github.com/gpodder/gpodder/pull/933#issuecomment-818039693 if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True # Get window state, correct size comes from window.get_size(), # see https://developer.gnome.org/SaveWindowState/ def _receive_configure_event(widget, event): x_pos, y_pos = widget.get_position() width_size, height_size = widget.get_size() maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) if not self.__ignore_window_events and not maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): # ELL: why is it commented out? # new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED) # cfg.maximized = new_value pass window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()
def replace_from_channel(self, channel, include_description=False, treeview=None): """ Add episode from the given channel to this model. Downloading should be a callback. include_description should be a boolean value (True if description is to be added to the episode row, or False if not) """ # Remove old episodes in the list store self.clear() if treeview is not None: util.idle_add(treeview.queue_draw) self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False) # Avoid gPodder bug 1291 if channel is None: episodes = [] else: episodes = channel.get_all_episodes() if not isinstance(episodes, list): episodes = list(episodes) count = len(episodes) for position, episode in enumerate(episodes): iter = self.append((episode.url, \ episode.title, \ self._format_filesize(episode), \ episode, \ None, \ episode.cute_pubdate(), \ '', \ '', \ True, \ True, \ True, \ episode.file_size, \ episode.published, \ episode.get_play_info_string(), \ bool(episode.total_time), \ episode.total_time, \ episode.archive)) self.update_by_iter(iter, include_description) self._on_filter_changed(self.has_episodes())
def thread_proc(): try: devices = self.mygpo_client.get_devices() except Exception, e: indicator.on_finished() def show_error(e): if str(e): message = str(e) else: message = e.__class__.__name__ self.show_message(message, _('Error getting list'), important=True) util.idle_add(show_error, e) return
def on_web_request(self, web_view, web_frame, web_resource, request, response): uri = request.get_uri() if uri.startswith(self.flattr.CALLBACK): uri_parsed = urlparse.urlparse(uri) query = urlparse.parse_qs(uri_parsed.path[2:]) if 'code' in query: code = query['code'][0] token = self.flattr.request_access_token(code) self._config.flattr.token = token else: self.show_message(query['error_description'][0], _('Error'), important=True) # Destroy the window later util.idle_add(self.main_window.destroy)
def _run_and_log(self, cmd): """Utility: get cmd's output in real time and log it through logger""" p = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, ) for line in iter(p.stdout.readline, b''): util.idle_add(self.logger._log,"\t"+line.rstrip()) p.stdout.close() status = p.wait() if status != 0: self.logger.error("%r exited with code %i" % (cmd, status)) return (status == 0)
def thread_func(self, tab=0): if tab == 1: model = OpmlListModel(opml.Importer(self._config.toplist_url)) if len(model) == 0: self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found')) elif tab == 2: model = OpmlListModel(youtube.find_youtube_channels(self.entryYoutubeSearch.get_text())) if len(model) == 0: self.notification(_('There are no YouTube channels that would match this query.'), _('No channels found')) else: url = self.entryURL.get_text() model = OpmlListModel(opml.Importer(url)) if len(model) == 0: self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found')) util.idle_add(self.thread_finished, model, tab)
def use_provider(self, provider): self.podcasts_model.clear() self.current_provider = provider if provider.kind == directory.Provider.PROVIDER_SEARCH: self.lb_search.set_text("Search:") self.bt_search.set_label("Search") elif provider.kind == directory.Provider.PROVIDER_URL: self.lb_search.set_text("URL:") self.bt_search.set_label("Download") elif provider.kind == directory.Provider.PROVIDER_FILE: self.lb_search.set_text("Filename:") self.bt_search.set_label("Open") elif provider.kind == directory.Provider.PROVIDER_TAGCLOUD: self.tag_cloud.clear_tags() @util.run_in_background def load_tags(): try: tags = [(t.tag, t.weight) for t in provider.get_tags()] except Exception as e: logger.warn("Got exception while loading tags: %s", e) tags = [] @util.idle_add def update_ui(): self.tag_cloud.set_tags(tags) elif provider.kind == directory.Provider.PROVIDER_STATIC: self.obtain_podcasts_with(provider.on_static) if provider.kind in ( directory.Provider.PROVIDER_SEARCH, directory.Provider.PROVIDER_URL, directory.Provider.PROVIDER_FILE, ): self.en_query.set_text("") self.hb_text_entry.show() util.idle_add(self.en_query.grab_focus) else: self.hb_text_entry.hide() if provider.kind == directory.Provider.PROVIDER_TAGCLOUD: self.sw_tagcloud.show() else: self.sw_tagcloud.hide()
def openFileEvent_reply_(self, event, reply): """ handles an 'Open With...' event""" urls = [] filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject)) numberOfItems = filelist.numberOfItems() for i in range(1,numberOfItems+1): fileAliasDesc = filelist.descriptorAtIndex_(i) fileURLDesc = fileAliasDesc.coerceToDescriptorType_(aeKeyword(typeFileURL)) fileURLData = fileURLDesc.data() url = buffer(fileURLData.bytes(),0,fileURLData.length()) url = str(url) util.idle_add(self.gp.on_item_import_from_file_activate, None,url) urls.append(str(url)) print >>sys.stderr,("open Files :",urls) result = NSAppleEventDescriptor.descriptorWithInt32_(42) reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
def openFileEvent_reply_(self, event, reply): """ handles an 'Open With...' event""" urls = [] filelist = event.paramDescriptorForKeyword_(aeKeyword(keyDirectObject)) numberOfItems = filelist.numberOfItems() for i in range(1, numberOfItems + 1): fileAliasDesc = filelist.descriptorAtIndex_(i) fileURLDesc = fileAliasDesc.coerceToDescriptorType_(aeKeyword(typeFileURL)) fileURLData = fileURLDesc.data() url = buffer(fileURLData.bytes(),0,fileURLData.length()) url = str(url) util.idle_add(self.gp.on_item_import_from_file_activate, None,url) urls.append(str(url)) print(("open Files :",urls), file=sys.stderr) result = NSAppleEventDescriptor.descriptorWithInt32_(42) reply.setParamDescriptor_forKeyword_(result, aeKeyword('----'))
def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) if gpodder.ui.win32: window.set_gravity(Gdk.GRAVITY_STATIC) window.resize(cfg.width, cfg.height) if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True def _receive_configure_event(widget, event): x_pos, y_pos = event.x, event.y width_size, height_size = event.width, event.height maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) if not self.__ignore_window_events and not maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): # ELL: why is it commented out? #new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED) #cfg.maximized = new_value pass window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()
def update_status( self, id, **kwargs): if not id in self.status_list: return iter=self.status_list[id]['iter'] if iter: self.tree_model_lock.acquire() for ( column, key ) in self.COLUMN_NAMES.items(): if key in kwargs: util.idle_add(self.tree_model.set, iter, column, kwargs[key]) self.status_list[id][key]=kwargs[key] self.tree_model_lock.release() if 'progress' in kwargs and 'speed' in kwargs and 'url' in self.status_list[id]: self.notify( 'progress-detail', self.status_list[id]['url'], kwargs['progress'], kwargs['speed']) self.notify_progress()
def connect_gtk_window(self, window, config_prefix, show_window=False): x, y, width, height, maximized = map(lambda x: config_prefix+'_'+x, \ ('x', 'y', 'width', 'height', 'maximized')) if set((x, y, width, height)).issubset(set(self.Settings)): window.resize(getattr(self, width), getattr(self, height)) if getattr(self, x) == -1 or getattr(self, y) == -1: window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) else: window.move(getattr(self, x), getattr(self, y)) # Ignore events while we're connecting to the window self.__ignore_window_events = True def _receive_configure_event(widget, event): x_pos, y_pos = widget.get_position() width_size, height_size = widget.get_size() if not self.__ignore_window_events and not \ (hasattr(self, maximized) and getattr(self, maximized)): setattr(self, x, x_pos) setattr(self, y, y_pos) setattr(self, width, width_size) setattr(self, height, height_size) window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): new_value = bool(event.new_window_state & \ gtk.gdk.WINDOW_STATE_MAXIMIZED) if hasattr(self, maximized): setattr(self, maximized, new_value) window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if getattr(self, maximized, False): window.maximize() else: raise ValueError('Cannot connect %s', config_prefix, sender=self)
def do_startup(self): Gtk.Application.do_startup(self) self.create_actions() builder = Gtk.Builder() builder.set_translation_domain(gpodder.textdomain) for ui_folder in gpodder.ui_folders: filename = os.path.join(ui_folder, 'gtk/menus.ui') if os.path.exists(filename): builder.add_from_file(filename) break menubar = builder.get_object('menubar') if menubar is None: logger.error('Cannot find gtk/menus.ui in %r, exiting' % gpodder.ui_folders) sys.exit(1) self.menu_view_columns = builder.get_object('menuViewColumns') self.set_menubar(menubar) self.set_app_menu(builder.get_object('app-menu')) Gtk.Window.set_default_icon_name('gpodder') try: dbus_main_loop = DBusGMainLoop(set_as_default=True) gpodder.dbus_session_bus = dbus.SessionBus(dbus_main_loop) self.bus_name = dbus.service.BusName(gpodder.dbus_bus_name, bus=gpodder.dbus_session_bus) except dbus.exceptions.DBusException as dbe: logger.warn('Cannot get "on the bus".', exc_info=True) dlg = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, _('Cannot start gPodder')) dlg.format_secondary_markup(_('D-Bus error: %s') % (str(dbe), )) dlg.set_title('gPodder') dlg.run() dlg.destroy() sys.exit(0) util.idle_add(self.check_root_folder_path_gui)
def thread_func(self, tab=0): if tab == 1: model = OpmlListModel(opml.Importer(my.TOPLIST_OPML)) if len(model) == 0: self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found')) elif tab == 2: model = OpmlListModel(youtube.find_youtube_channels(self.entryYoutubeSearch.get_text())) if len(model) == 0: self.notification(_('There are no YouTube channels that would match this query.'), _('No channels found')) else: url = self.entryURL.get_text() if self.is_search_term(url): url = 'http://gpodder.net/search.opml?q=' + urllib.quote(url) model = OpmlListModel(opml.Importer(url)) if len(model) == 0: self.notification(_('The specified URL does not provide any valid OPML podcast items.'), _('No feeds found')) util.idle_add(self.thread_finished, model, tab)
def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) if gpodder.ui.win32: window.set_gravity(Gdk.Gravity.STATIC) window.resize(cfg.width, cfg.height) if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True def _receive_configure_event(widget, event): x_pos, y_pos = event.x, event.y width_size, height_size = event.width, event.height maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) if not self.__ignore_window_events and not maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): # ELL: why is it commented out? # new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED) # cfg.maximized = new_value pass window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()
def use_provider(self, provider): self.podcasts_model.clear() self.current_provider = provider if provider.kind == directory.Provider.PROVIDER_SEARCH: self.lb_search.set_text(_('Search:')) self.bt_search.set_label(_('Search')) elif provider.kind == directory.Provider.PROVIDER_URL: self.lb_search.set_text(_('URL:')) self.bt_search.set_label(_('Download')) elif provider.kind == directory.Provider.PROVIDER_FILE: self.lb_search.set_text(_('Filename:')) self.bt_search.set_label(_('Open')) elif provider.kind == directory.Provider.PROVIDER_TAGCLOUD: self.tag_cloud.clear_tags() @util.run_in_background def load_tags(): try: tags = [(t.tag, t.weight) for t in provider.get_tags()] except Exception as e: logger.warn('Got exception while loading tags: %s', e) tags = [] @util.idle_add def update_ui(): self.tag_cloud.set_tags(tags) elif provider.kind == directory.Provider.PROVIDER_STATIC: self.obtain_podcasts_with(provider.on_static) if provider.kind in (directory.Provider.PROVIDER_SEARCH, directory.Provider.PROVIDER_URL, directory.Provider.PROVIDER_FILE): self.en_query.set_text('') self.hb_text_entry.show() util.idle_add(self.en_query.grab_focus) else: self.hb_text_entry.hide() if provider.kind == directory.Provider.PROVIDER_TAGCLOUD: self.sw_tagcloud.show() else: self.sw_tagcloud.hide()
def cleanup_episodes(): # 'skip_played_episodes' must be used or else all the # played tracks will be copied then immediately deleted if (self._config.device_sync.delete_played_episodes and self._config.device_sync.skip_played_episodes): all_episodes = self._filter_sync_episodes(channels, only_downloaded=False) for local_episode in all_episodes: episode = device.episode_on_device(local_episode) if episode is None: continue if local_episode.state == gpodder.STATE_DELETED: logger.info('Removing episode from device: %s', episode.title) device.remove_track(episode) # When this is done, start the callback in the UI code util.idle_add(check_free_space)
def remove_download_id( self, id): if not id in self.status_list: return iter=self.status_list[id]['iter'] if iter is not None: self.tree_model_lock.acquire() util.idle_add(self.remove_iter, iter) self.tree_model_lock.release() self.status_list[id]['iter']=None self.status_list[id]['thread'].cancel() del self.status_list[id] if not self.has_items(): # Reset the counter now self.downloads_done_bytes=0 if self.batch_mode_enabled: self.batch_mode_notify_flag=True else: self.notify('list-changed') self.notify_progress()
def add_from_channel(self, channel, downloading=None, \ include_description=False, generate_thumbnails=False, \ treeview=None): """ Add episode from the given channel to this model. Downloading should be a callback. include_description should be a boolean value (True if description is to be added to the episode row, or False if not) """ self._update_progress = 0. self._last_redraw_progress = 0. if treeview is not None: util.idle_add(treeview.queue_draw) self._all_episodes_view = getattr(channel, 'ALL_EPISODES_PROXY', False) episodes = channel.get_all_episodes() if not isinstance(episodes, list): episodes = list(episodes) count = len(episodes) for position, episode in enumerate(episodes): iter = self.append() self.set(iter, \ self.C_URL, episode.url, \ self.C_TITLE, episode.title, \ self.C_FILESIZE_TEXT, self._format_filesize(episode), \ self.C_EPISODE, episode, \ self.C_PUBLISHED_TEXT, episode.cute_pubdate()) self.update_by_iter(iter, downloading, include_description, \ generate_thumbnails, reload_from_db=False) self._update_progress = float(position+1)/count if treeview is not None and \ (self._update_progress > self._last_redraw_progress + self._UI_UPDATE_STEP or position+1 == count): def in_gtk_main_thread(): treeview.queue_draw() while gtk.events_pending(): gtk.main_iteration(False) util.idle_add(in_gtk_main_thread) self._last_redraw_progress = self._update_progress
def download_thread_func(): if use_youtube: importer = youtube.find_youtube_channels(url) else: importer = opml.Importer(url) if importer.items: model = OpmlListModel(importer) else: model = None self.show_message(_('Please pick another source.'), _('No podcasts found')) def download_thread_finished(): if banner is not None: banner.destroy() self.treeview.set_model(model) self.treeview.set_sensitive(True) self.button_cancel.set_sensitive(True) self.set_subscribe_button_sensitive() util.idle_add(download_thread_finished)
def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) window.resize(cfg.width, cfg.height) if cfg.x == -1 or cfg.y == -1: window.set_position(gtk.WIN_POS_CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True def _receive_configure_event(widget, event): x_pos, y_pos = event.x, event.y width_size, height_size = event.width, event.height if not self.__ignore_window_events and not cfg.maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): new_value = bool(event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED) cfg.maximized = new_value window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()
def cleanup_episodes(): # 'only_sync_not_played' must be used or else all the # played tracks will be copied then immediately deleted if self._config.mp3_player_delete_played and \ self._config.only_sync_not_played: all_episodes = self._filter_sync_episodes(channels, \ only_downloaded=False) episodes_on_device = device.get_all_tracks() for local_episode in all_episodes: episode = device.episode_on_device(local_episode) if episode is None: continue if local_episode.state == gpodder.STATE_DELETED \ or (local_episode.is_played and \ not local_episode.is_locked): log('Removing episode from device: %s', episode.title, sender=self) device.remove_track(episode) # When this is done, start the callback in the UI code util.idle_add(check_free_space)
def after_device_sync_callback(device, successful_sync): if device.cancelled: log('Cancelled by user.', sender=self) elif successful_sync: title = _('Device synchronized') message = _('Your device has been synchronized.') self.notification(message, title) else: title = _('Error closing device') message = _('Please check settings and permission.') self.notification(message, title, important=True) # Update the UI to reflect changes from the sync process episode_urls = set() channel_urls = set() for episode in episodes: episode_urls.add(episode.url) channel_urls.add(episode.channel.url) util.idle_add(self.update_episode_list_icons, episode_urls) util.idle_add(self.update_podcast_list_model, channel_urls) util.idle_add(self.commit_changes_to_database)
def notification(self, message, title=None, important=False, widget=None): util.idle_add(self.show_message, message, title, important, widget)
def register_task(self, task): util.idle_add(self.__add_new_task, task)
def get_next(self): dqr = DequeueRequest() util.idle_add(self.__get_next, dqr) return dqr.dequeue()