def _finished_update(self, *args): """Renders menu and shows notification after updating is finished.""" if self._feeds_thread is not None and self._feeds_thread.is_alive(): return if self._feeds_thread: self._feeds_thread.join() sleep(1) self._feeds_thread = None self._render_menu() if self._config_manager.show_notifications: with SQLite() as db: feeds = db.s('SELECT id, title, img FROM feeds WHERE ' + 'feed_url IN (SELECT feed_id FROM posts WHERE ' + 'read="false" GROUP BY feed_id LIMIT 50) ORDER' + ' BY (SELECT count(feed_id) AS c FROM posts ' + 'WHERE read="false" GROUP BY feed_id ORDER BY ' + 'c desc), UPPER(title)') for feed in feeds: img = os.path.join(config.app_cache_dir, feed[2]) if feed[2] else None posts = db.s( 'SELECT title FROM posts WHERE read=' + '"false" AND feed_id=? LIMIT 3', (feed[0], )) if len(posts) > 0: msg = '\n'.join('* %s' % p[0] for p in posts) self._notify(feed[1], msg, img) if len(feeds) == 0: if self._config_manager.show_update_notifications: self._notify(feedindicator.__app_name__, _('Finished updating feeds.'))
def _open_unread(self, widget, feed_id=None): """Opens all unread post of the given feed or all unread posts. Args: widget: Gtk widget feed_id: optional feed id, if not given opens all unread """ with SQLite() as db: if feed_id: posts = db.s( 'SELECT url FROM posts WHERE feed_id=? AND ' + 'read="false"', (feed_id, )) for post in posts: webbrowser.open(post[0]) sleep(0.6) db.s('UPDATE posts SET read="true" WHERE feed_id=?', (feed_id, )) else: for feed in db.s('SELECT id FROM feeds'): posts = db.s( 'SELECT url FROM posts WHERE feed_id=? AND ' + 'read="false"', feed) for post in posts: webbrowser.open(post[0]) sleep(0.6) db.s('UPDATE posts SET read="true" WHERE feed_id=?', feed) sleep(0.5) self._render_menu()
def _update(self, widget=None, timeroverride=False, starttimer=False): """Start updating feeds. Args: widget: Gtk widget timeroverride: if true timer will be overridden starttimer: if true timer will be started """ if self._config_manager.stoptimer and not timeroverride: return False with SQLite() as db: if db.s('SELECT COUNT(*) FROM feeds')[0][0] > 0: if starttimer: GLib.timeout_add_seconds(self._config_manager.refreshtime, self._update, True) self._loading_menu() if db.s('SELECT COUNT(*) FROM feeds')[0][0] != 0: self._feeds_thread = FeedThread(self._finished_update) self._feeds_thread.start() if self._config_manager.show_notifications: if self._config_manager.show_update_notifications: self._notify(feedindicator.__app_name__, _('Begin updating Feeds.')) else: self._render_menu() return True
def _mark_feed_as_unread(self, widget, feed_id=None): """Mark all posts of all feeds or a specific feed as read. Args: widget: Gtk widget feed_id: optinal feed id, if not given all will be updated """ with SQLite() as db: f = 'WHERE feed_id=?' if feed_id else '' db.d('UPDATE posts SET read="false" %s' % f, (feed_id, ) if feed_id else ()) sleep(0.5) self._render_menu()
def _mark_displayed_as_read(self, widget, feed_id): """Marks displayed posts of given feed as read. Args: widget: Gtk widget feed_id: feed id """ with SQLite() as db: db.s( 'UPDATE posts SET read="true" WHERE feed_id=? AND id IN ' + '(SELECT id FROM posts WHERE feed_id=? AND read="false" ' + 'ORDER BY id DESC LIMIT %d)' % self._config_manager.items_per_feed, (feed_id, feed_id)) sleep(0.5) self._render_menu()
def _open_website(self, widget, url, post_id=None): """Open website. Args: widget: Gtk widget url: url to open post_id: optional post id to change status to read """ webbrowser.open(url) if post_id: with SQLite() as db: db.s('UPDATE posts SET read="true" WHERE id=?', (post_id, )) sleep(0.5) self._render_menu()
def _render_menu(self): """Populate the menu.""" self._clear_menu() with SQLite() as db: feeds = db.s('SELECT id, title, url, feed_url, (SELECT COUNT(*) ' + 'FROM posts WHERE posts.feed_id=feeds.id AND ' + 'read="false") AS c FROM feeds ORDER BY c DESC, ' + 'UPPER(title)') if not self._config_manager.feeds_at_top: self._conf_menu(len(feeds) > 0) self._menu.append(Gtk.SeparatorMenuItem()) if len(feeds) > 0: self._feeds_menu_header() for feed in feeds: posts = db.s( 'SELECT id, title, url FROM posts WHERE ' + 'feed_id=? AND read="false" ORDER BY id ' + 'LIMIT %d' % self._config_manager.items_per_feed, (feed[0], )) if self._config_manager.show_unread_feeds: self._feed_submenu(feed, posts) else: if feed[4] > 0: self._feed_submenu(feed, posts) if db.s('SELECT COUNT(*) FROM posts WHERE ' + 'read="false"')[0][0] == 0: menu_notice = Gtk.MenuItem(label=_('No unread posts.')) menu_notice.set_sensitive(False) self._menu.append(menu_notice) else: item = Gtk.MenuItem(label=_('No feeds defined!')) item.set_sensitive(False) self._menu.append(item) if self._config_manager.feeds_at_top: self._menu.append(Gtk.SeparatorMenuItem()) self._conf_menu(len(feeds) > 0) self._menu.show_all() if appindicator: self._indicator.set_menu(self._menu) self._set_status( db.s('SELECT COUNT(*) FROM posts WHERE ' + 'read="false"')[0][0] > 0)
def _open_displayed(self, widget, feed_id): """Opens all unread post of the given feed or all unread posts. Args: widget: Gtk widget feed_id: optional feed id, if not given opens all unread """ with SQLite() as db: posts = db.s( 'SELECT id, url FROM posts WHERE feed_id=? AND ' + 'read="false" ORDER BY id DESC LIMIT %d' % self._config_manager.items_per_feed, (feed_id, )) for post in posts: webbrowser.open(post[1]) db.s('UPDATE posts SET read="true" WHERE id=?', (post[0], )) sleep(0.6) self._render_menu()
def _save(self, widget): """Save config and feeds and close dialog. Args: widget: Gtk widget """ self._config_manager.update(self._configs) self._config_manager.save() with SQLite() as db: for feed in self._feeds: if feed[0] == -1 and feed[2]: if not feed[1]: feed[1] = None db.s('INSERT INTO feeds (feed_url, title) VALUES (?,?)', (feed[2], feed[1])) else: db.s('UPDATE feeds set title=?, feed_url=? WHERE id=?', (feed[1], feed[2], feed[0])) self._close_window(widget) self._callback(self._callback_args)
def __init__(self, widget, config_manager, callback, *args): """Init dialog. Args: widget: Gtk widget configs: dict with configs callback: callback function after url has been added *args: callback function args """ Gtk.Window.__init__(self, title=_('Preferences')) self._config_manager = config_manager self._configs = self._config_manager.items() self._callback = callback self._callback_args = args self.set_position(Gtk.WindowPosition.CENTER) self.set_keep_above(True) self.set_icon_name(feedindicator.__app_name__) self.connect('delete_event', self._close_window) self.connect('key-press-event', self._keypress) vbox = Gtk.VBox(False, 1) vbox.set_border_width(1) self.add(vbox) notebook = Gtk.Notebook() notebook.set_tab_pos(Gtk.PositionType.LEFT) vbox.pack_start(notebook, False, True, 0) # Feed List frame = Gtk.Frame(label=_('Feed list')) frame.set_border_width(1) box = Gtk.VBox(False, 1) box.set_border_width(1) frame.add(box) label = Gtk.Label(label=_('Configure the feeds.')) label.set_justify(Gtk.Justification.LEFT) label.set_line_wrap(True) box.pack_start(label, False, True, 0) scrolled_window = Gtk.ScrolledWindow() scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.ALWAYS) scrolled_window.set_shadow_type(Gtk.ShadowType.IN) scrolled_window.set_min_content_height(500) scrolled_window.set_min_content_width(500) box.pack_start(scrolled_window, False, True, 0) self._feeds = Gtk.ListStore(int, str, str) with SQLite() as db: for feed in db.s('SELECT id, title, feed_url FROM feeds ORDER ' + 'BY UPPER(title)'): self._feeds.append(feed) self._treeview = Gtk.TreeView.new_with_model(self._feeds) for i, column_title in enumerate([_('ID'), _('Title'), _('URL')]): renderer = Gtk.CellRendererText() if i > 0: renderer.set_property('editable', True) renderer.connect('edited', self._cell_edited, i) column = Gtk.TreeViewColumn(column_title, renderer, text=i) self._treeview.append_column(column) self._treeview.set_headers_clickable(False) self._treeview.set_reorderable(True) self._treeview.connect('cursor-changed', self._selection_made) scrolled_window.add(self._treeview) hbox = Gtk.HBox(True, 1) box.pack_start(hbox, False, True, 0) btn = Gtk.Button(label=_('Add')) btn.connect('clicked', self._add_feed) hbox.pack_start(btn, False, True, 0) self._btn_remove_feed = Gtk.Button(label=_('Remove')) self._btn_remove_feed.connect('clicked', self._remove_feed) self._btn_remove_feed.set_sensitive(False) hbox.pack_start(self._btn_remove_feed, False, True, 0) notebook.append_page(frame, Gtk.Label(label=_('Feed list'))) # Options frame = Gtk.Frame(label=_('Options')) frame.set_border_width(1) box = Gtk.VBox(False, 1) box.set_border_width(1) frame.add(box) btn = Gtk.CheckButton(label=_('Auto update feeds')) btn.set_active(not self._configs['stoptimer']) btn.connect('toggled', self._toggle_config, 'stoptimer') box.pack_start(btn, False, True, 0) hbox = Gtk.HBox(True, 0) box.pack_start(hbox, False, True, 0) self._refreshtime_label = Gtk.Label(label='') hbox.pack_start(self._refreshtime_label, False, True, 0) adjtimer = Gtk.Adjustment(value=self._configs['refreshtime'] / 60, lower=1.0, upper=90.0, step_increment=1.0, page_increment=10.0, page_size=0.0) adjtimer.connect('value_changed', self._change_refreshtime) self._scaletime = Gtk.HScale(adjustment=adjtimer) self._scaletime.set_draw_value(False) self._scaletime.set_digits(0) self._scaletime.set_sensitive(not self._configs['stoptimer']) hbox.pack_start(self._scaletime, False, True, 0) self._change_refreshtime(adjtimer) hbox = Gtk.HBox(True, 0) box.pack_start(hbox, False, True, 0) self._items_per_feed_label = Gtk.Label(label='') hbox.pack_start(self._items_per_feed_label, False, False, 0) adjitems = Gtk.Adjustment(value=self._configs['items_per_feed'], lower=1.0, upper=30.0, step_increment=1.0, page_increment=10.0, page_size=0.0) adjitems.connect('value_changed', self._change_items_per_feed) scaleitems = Gtk.HScale(adjustment=adjitems) scaleitems.set_draw_value(False) scaleitems.set_digits(0) hbox.pack_start(scaleitems, True, True, 0) self._change_items_per_feed(adjitems) btn = Gtk.CheckButton(label=_('Show feeds at top of menu')) btn.set_active(self._configs['feeds_at_top']) btn.connect('toggled', self._toggle_config, 'feeds_at_top') box.pack_start(btn, False, True, 0) btn = Gtk.CheckButton(label=_('Show feeds with no unread posts')) btn.set_active(self._configs['show_unread_feeds']) btn.connect('toggled', self._toggle_config, 'show_unread_feeds') box.pack_start(btn, False, True, 0) btn = Gtk.CheckButton(label=_('Launch at system startup')) btn.set_active(self._configs['autostart']) btn.connect('toggled', self._toggle_config, 'autostart') box.pack_start(btn, False, True, 0) btn = Gtk.CheckButton(label=_('Show notifications')) btn.set_active(self._configs['show_notifications']) btn.connect('toggled', self._toggle_config, 'show_notifications') box.pack_start(btn, False, True, 0) self._btn_show_update_notifications = Gtk. \ CheckButton(label=_('Show notifications at beginning ' + 'and end of update')) self._btn_show_update_notifications. \ set_sensitive(self._configs['show_notifications']) self._btn_show_update_notifications. \ set_active(self._configs['show_update_notifications']) self._btn_show_update_notifications. \ connect('toggled', self._toggle_config, 'show_update_notifications') box.pack_start(self._btn_show_update_notifications, False, True, 0) notebook.append_page(frame, Gtk.Label(label=_('Options'))) box = Gtk.HBox(True, 0) vbox.pack_end(box, False, True, 0) btn = Gtk.Button(label=_('Cancel')) btn.connect('clicked', self._close_window) box.pack_start(btn, False, True, 0) btn = Gtk.Button(label=_('Save')) btn.connect('clicked', self._save) box.pack_start(btn, False, True, 0) self.show_all()