Add channel priority for display

This commit is contained in:
DevilXD committed 2022-01-25 22:42:45 +01:00
1 parent f7d836aa4f
commit 255fb55963
1 file changed
+92 -53
+92 -53
View File
@@ -537,7 +537,7 @@ class ChannelList:
scroll = ttk.Scrollbar(frame, orient="vertical") scroll = ttk.Scrollbar(frame, orient="vertical")
self._table = table = ttk.Treeview( self._table = table = ttk.Treeview(
frame, frame,
columns=("channel", "status", "game", "viewers", "points"), # columns definition is updated by _add_column
yscrollcommand=scroll.set, yscrollcommand=scroll.set,
) )
scroll.config(command=table.yview) scroll.config(command=table.yview)
@@ -548,15 +548,16 @@ class ChannelList:
table.tag_configure("watching", background="gray70") table.tag_configure("watching", background="gray70")
table.bind("<Button-1>", self._disable_column_resize) table.bind("<Button-1>", self._disable_column_resize)
table.bind("<<TreeviewSelect>>", self._selected) table.bind("<<TreeviewSelect>>", self._selected)
self._column("#0", '', width=0) self._add_column("#0", '', width=0)
self._column("channel", "Channel", width=100, anchor='w') self._add_column("channel", "Channel", width=100, anchor='w')
self._column("status", "Status", width_template="OFFLINE ❌") self._add_column("status", "Status", width_template="OFFLINE ❌")
self._column("game", "Game", width=50) self._add_column("game", "Game", width=50)
self._column("viewers", "Viewers", width_template="1234567") self._add_column("viewers", "Viewers", width_template="1234567")
self._column("points", "Points", width_template="1234567") self._add_column("points", "Points", width_template="1234567")
self._add_column("priority", "❗", width_template="✔")
self._channel_map: Dict[str, Channel] = {} self._channel_map: Dict[str, Channel] = {}
def _column( def _add_column(
self, self,
cid: str, cid: str,
name: str, name: str,
@@ -565,12 +566,32 @@ class ChannelList:
width: Optional[int] = None, width: Optional[int] = None,
width_template: Optional[str] = None, width_template: Optional[str] = None,
): ):
table = self._table
# we need to save the column settings and headings before modifying the columns...
columns: Tuple[str, ...] = table.cget("columns") or ()
column_settings: Dict[str, Tuple[str, tk._Anchor, int, int]] = {}
for s_cid in columns:
s_column = table.column(s_cid)
assert s_column is not None
s_heading = table.heading(s_cid)
assert s_heading is not None
column_settings[s_cid] = (
s_heading["text"], s_heading["anchor"], s_column["width"], s_column["minwidth"]
)
# ..., then add the column, but ensure we're not adding the icons column...
if cid != "#0":
table.config(columns=columns + (cid,))
# ..., and then restore column settings and headings afterwards
for s_cid, (s_name, s_anchor, s_width, s_minwidth) in column_settings.items():
table.heading(s_cid, text=s_name, anchor=s_anchor)
table.column(s_cid, minwidth=s_minwidth, width=s_width, stretch=False)
# set heading and column settings for the new column
if width_template is not None: if width_template is not None:
width = self._measure(width_template) width = self._measure(width_template)
self._const_width.add(cid) self._const_width.add(cid)
assert width is not None assert width is not None
self._table.column(cid, minwidth=width, width=width, stretch=False) table.heading(cid, text=name, anchor=anchor)
self._table.heading(cid, text=name, anchor=anchor) table.column(cid, minwidth=width, width=width, stretch=False)
def _disable_column_resize(self, event): def _disable_column_resize(self, event):
if self._table.identify_region(event.x, event.y) == "separator": if self._table.identify_region(event.x, event.y) == "separator":
@@ -627,10 +648,13 @@ class ChannelList:
self._table.set(iid, column, value) self._table.set(iid, column, value)
self._adjust_width(column, value) self._adjust_width(column, value)
def _insert(self, iid: str, *args: str): def _insert(self, iid: str, values: Dict[str, str]):
self._table.insert(parent='', index="end", iid=iid, values=args) to_insert: List[str] = []
for column, value in zip(self._table.cget("columns"), args): for cid in self._table.cget("columns"):
self._adjust_width(column, value) value = values[cid]
to_insert.append(value)
self._adjust_width(cid, value)
self._table.insert(parent='', index="end", iid=iid, values=to_insert)
def clear_watching(self): def clear_watching(self):
for iid in self._table.tag_has("watching"): for iid in self._table.tag_has("watching"):
@@ -652,33 +676,46 @@ class ChannelList:
self._table.selection_set('') self._table.selection_set('')
def display(self, channel: Channel): def display(self, channel: Channel):
# priority
priority = "✔" if channel.priority else "❌"
# status # status
if channel.online: if channel.online:
status_str = "ONLINE ✔" status = "ONLINE ✔"
elif channel.pending_online: elif channel.pending_online:
status_str = "OFFLINE ⏳" status = "OFFLINE ⏳"
else: else:
status_str = "OFFLINE ❌" status = "OFFLINE ❌"
# game # game
game_str = str(channel.game or '') game = str(channel.game or '')
# viewers # viewers
viewers_str = '' viewers = ''
if channel.viewers is not None: if channel.viewers is not None:
viewers_str = str(channel.viewers) viewers = str(channel.viewers)
# points # points
points_str = '' points = ''
if channel.points is not None: if channel.points is not None:
points_str = str(channel.points) points = str(channel.points)
iid = channel.iid iid = channel.iid
if self._table.exists(iid): if iid in self._channel_map:
self._set(iid, "status", status_str) self._set(iid, "game", game)
self._set(iid, "game", game_str) self._set(iid, "status", status)
self._set(iid, "viewers", viewers_str) self._set(iid, "viewers", viewers)
if points_str: self._set(iid, "priority", priority)
self._set(iid, "points", points_str) if points != '': # we still want to display 0
self._set(iid, "points", points)
else: else:
self._channel_map[iid] = channel self._channel_map[iid] = channel
self._insert(iid, channel.name, status_str, game_str, viewers_str, points_str) self._insert(
iid,
{
"channel": channel.name,
"priority": priority,
"status": status,
"game": game,
"viewers": viewers,
"points": points,
},
)
def remove(self, channel: Channel): def remove(self, channel: Channel):
iid = channel.iid iid = channel.iid
@@ -897,6 +934,7 @@ class GUIManager:
if __name__ == "__main__": if __name__ == "__main__":
# Everything below is for debug purposes only # Everything below is for debug purposes only
from functools import partial
from types import SimpleNamespace from types import SimpleNamespace
class StrNamespace(SimpleNamespace): class StrNamespace(SimpleNamespace):
@@ -905,27 +943,14 @@ if __name__ == "__main__":
return self._str__(self) return self._str__(self)
return super().__str__() return super().__str__()
def state_change(state: State):
def changer(state: State = state):
gui.print(f"State change: {state.value}")
return changer
loop = asyncio.get_event_loop()
gui: GUIManager
mock = SimpleNamespace(
_loop=loop,
_options=SimpleNamespace(game=None, tray=True),
state_change=state_change,
)
gui = GUIManager(mock) # type: ignore
mock.request_close = gui._root.destroy
def create_game(id: int, name: str): def create_game(id: int, name: str):
return StrNamespace(name=name, id=id, _str__=lambda s: s.name) return StrNamespace(name=name, id=id, _str__=lambda s: s.name)
iid = 0 iid = 0
def create_channel(name: str, online: int, game: Optional[str], viewers: int, points: int): def create_channel(
name: str, online: int, game: Optional[str], viewers: int, points: int, priority: bool
):
if online == 1: if online == 1:
online = False online = False
pending = True pending = True
@@ -944,6 +969,7 @@ if __name__ == "__main__":
pending_online=pending, pending_online=pending,
game=game_obj, game=game_obj,
viewers=viewers, viewers=viewers,
priority=priority,
) )
def create_drop( def create_drop(
@@ -978,20 +1004,31 @@ if __name__ == "__main__":
mock.campaign.timed_drops["0"] = mock mock.campaign.timed_drops["0"] = mock
return mock return mock
async def main(): async def main(exit_event: asyncio.Event):
# Initialize GUI debug
mock = SimpleNamespace(options=SimpleNamespace(game=None, tray=False), channels={})
mock.change_state = lambda state: mock.gui.print(f"State change: {state.value}")
mock.state_change = lambda state: partial(mock.change_state, state)
gui = GUIManager(mock) # type: ignore
mock.gui = gui
mock.request_close = gui.stop
gui.start()
assert gui._poll_task is not None
gui._poll_task.add_done_callback(lambda t: exit_event.set())
# Login form # Login form
gui.login.update("Login required", None) gui.login.update("Login required", None)
# Game selector # Game selector
gui.games.set_games([ gui.games.set_games([
create_game(491115, "Paladins"), create_game(123456, "Best Game"),
# create_game(460630, "Tom Clancy's Rainbow Six Siege"), # create_game(654321, "My Game Very Long Name"),
]) ])
# Channel list # Channel list
gui.channels.display(create_channel("PaladinsGame", 0, None, 0, 0)) gui.channels.display(create_channel("Thomus", 0, None, 0, 0, True))
channel = create_channel("Traitus", 1, None, 0, 0) channel = create_channel("Traitus", 1, None, 0, 0, True)
gui.channels.display(channel) gui.channels.display(channel)
gui.channels.display(create_channel("Testus", 2, "Paladins", 42, 1234567))
gui.channels.set_watching(channel) gui.channels.set_watching(channel)
gui.channels.display(create_channel("Testus", 2, "Best Game", 42, 1234567, False))
gui.channels.display(create_channel("Livus", 2, "Best Game", 69, 1234567, False))
gui._root.update() gui._root.update()
gui.channels.get_selection() gui.channels.get_selection()
# Tray # Tray
@@ -1017,5 +1054,7 @@ if __name__ == "__main__":
drop.progress = 0.0 drop.progress = 0.0
gui.progress.display(drop) gui.progress.display(drop)
loop.create_task(main()) loop = asyncio.get_event_loop()
loop.run_until_complete(gui._poll()) exit_event = asyncio.Event()
loop.create_task(main(exit_event))
loop.run_until_complete(exit_event.wait())