1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
from typing import List, Union
from gi.repository import GObject, Gtk, Gio
from gfeeds.confManager import ConfManager
from gfeeds.feed import Feed
class TagObj(GObject.Object):
__gsignals__ = {
'empty_changed': (
GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()
)
}
def __init__(self, name: str):
super().__init__()
self.name = name
self.__unread_count = 0
@GObject.Property(type=int)
def unread_count(self) -> int: # type: ignore
return self.__unread_count
@unread_count.setter
def unread_count(self, c: int):
self.__unread_count = c
def increment_unread_count(self, v: int):
prev = self.unread_count
self.unread_count += v
if self.__unread_count == 0 and prev > 0:
self.emit('empty_changed')
elif self.__unread_count > 0 and prev == 0:
self.emit('empty_changed')
class TagStore(Gtk.FilterListModel):
__gsignals__ = {
'item-removed': (
GObject.SignalFlags.RUN_LAST,
None,
(GObject.TYPE_PYOBJECT,)
)
}
def __init__(self):
self.sorter = Gtk.CustomSorter()
self.sorter.set_sort_func(self._sort_func)
self.filter = Gtk.CustomFilter()
self.filter.set_filter_func(self._filter_func)
self.list_store = Gio.ListStore(item_type=TagObj)
self.sort_store = Gtk.SortListModel(
model=self.list_store, sorter=self.sorter
)
self.confman = ConfManager()
self.confman.connect(
'gfeeds_show_empty_feeds_changed',
lambda *_: self.invalidate_filter()
)
# Hiding read articles can result in empty feeds which should
# be hidden
self.confman.connect(
'gfeeds_show_read_changed',
lambda *_: self.invalidate_filter()
)
super().__init__(model=self.sort_store, filter=self.filter)
self.populate()
def populate(self):
self.empty()
for tag in self.confman.nconf.tags:
n_tag = TagObj(tag)
self.list_store.append(n_tag)
n_tag.connect(
'empty_changed', lambda *_: self.invalidate_filter()
)
def _sort_func(self, t1: TagObj, t2: TagObj, *_) -> int:
return -1 if t1.name.lower() < t2.name.lower() else 1
def empty(self):
return self.list_store.remove_all()
def add_tag(
self, n_tag_: Union[TagObj, str], target_feeds: List[Feed] = []
):
n_tag = TagObj(n_tag_) if isinstance(n_tag_, str) else n_tag_
existing_tag = self.get_tag(n_tag.name)
if existing_tag:
n_tag = existing_tag
else:
self.list_store.append(n_tag)
target_feed_urls = []
for feed in target_feeds:
target_feed_urls.append(feed.rss_link)
if n_tag not in feed.tags:
feed.tags.append(n_tag)
n_tag.unread_count += feed.unread_count
n_tag.connect(
'empty_changed', lambda *_: self.invalidate_filter()
)
self.confman.add_tag(n_tag.name, target_feed_urls)
def remove_by_index(self, index: int):
to_rm = self.list_store[index]
self.emit('item-removed', to_rm)
self.list_store.remove(index)
self.confman.delete_tag(to_rm.name)
def remove_tag(self, tag: str):
for i, tag_o in enumerate(self.list_store):
if tag == tag_o.name:
self.remove_by_index(i)
return
def _filter_func(self, item: TagObj, *_) -> bool:
if not self.confman.nconf.show_empty_feeds and \
not self.confman.nconf.show_read_items:
return item.unread_count > 0
return True
def invalidate_filter(self):
self.filter.set_filter_func(self._filter_func)
def get_tag(self, tag: str):
for t in self.list_store:
if t.name == tag:
return t
return None
|