Move reloading functions to separate module.

This commit is contained in:
luxick
2018-03-01 21:05:57 +01:00
parent a78c20f078
commit cb129eddd1
8 changed files with 157 additions and 119 deletions

View File

@@ -1,14 +1,9 @@
from collections import Counter
import gi import gi
import math
import os import os
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk
from dsst_gtk3.handlers import handlers from dsst_gtk3.handlers import handlers
from dsst_gtk3 import util from dsst_gtk3 import util, reload
from dsst_sql import sql, sql_func from dsst_sql import sql, sql_func
@@ -36,109 +31,24 @@ class GtkUi:
self.set_db_status_label(db_config) self.set_db_status_label(db_config)
# Create database if not exists # Create database if not exists
sql_func.create_tables() sql_func.create_tables()
self.reload()
self.reload_base_data() def reload(self):
reload.reload_base_data(self.ui, self)
season_id = self.get_selected_season_id()
if season_id:
reload.reload_episodes(self.ui, self, season_id)
reload.reload_season_stats(self.ui, self, season_id)
else:
return
episode_id = self.get_selected_episode_id()
if episode_id:
reload.reload_episode_stats(self.ui, self, episode_id)
def set_db_status_label(self, db_conf: dict): def set_db_status_label(self, db_conf: dict):
self.ui.get_object('connection_label').set_text(f'{db_conf["user"]}@{db_conf["host"]}') self.ui.get_object('connection_label').set_text(f'{db_conf["user"]}@{db_conf["host"]}')
self.ui.get_object('db_label').set_text(f'{db_conf["db_name"]}') self.ui.get_object('db_label').set_text(f'{db_conf["db_name"]}')
def reload_base_data(self):
"""Reload function for all base data witch is not dependant on selected season or episode"""
# Rebuild all players store
self.ui.get_object('all_players_store').clear()
for player in sql.Player.select():
self.ui.get_object('all_players_store').append([player.id, player.name, player.hex_id])
# Rebuild drink store
self.ui.get_object('drink_store').clear()
for drink in sql.Drink.select():
self.ui.get_object('drink_store').append([drink.id, drink.name, '{:.2f}%'.format(drink.vol)])
# Rebuild seasons store
store = self.ui.get_object('seasons_store')
store.clear()
for season in sql.Season.select().order_by(sql.Season.number):
store.append([season.id, season.game_name])
# Reload after season was changed ##################################################################################
def reload_for_season(self):
"""Reload all data that is dependant on a selected season"""
season_id = self.get_selected_season_id()
if season_id is None or season_id == -1:
return
# Rebuild episodes store
selection = self.ui.get_object('episodes_tree_view').get_selection()
selection.handler_block_by_func(self.handlers.on_selected_episode_changed)
model, selected_paths = selection.get_selected_rows()
model.clear()
for episode in sql_func.get_episodes_for_season(season_id):
model.append([episode.id, episode.name, str(episode.date), episode.number])
if selected_paths:
selection.select_path(selected_paths[0])
selection.handler_unblock_by_func(self.handlers.on_selected_episode_changed)
# Load player stats for season
player_stats = {}
for episode in sql_func.get_episodes_for_season(season_id):
for player in episode.players:
player_stats[player.name] = [sql_func.get_player_deaths_for_season(season_id, player.id),
sql_func.get_player_victories_for_season(season_id, player.id)]
store = self.ui.get_object('player_season_store')
store.clear()
for name, stats in player_stats.items():
store.append([name, stats[0], stats[1]])
# Load enemy stats for season
season = sql.Season.get(sql.Season.id == season_id)
enemy_stats = {
enemy.name: [False, len(sql.Death.select().where(sql.Death.enemy == enemy)), enemy.id]
for enemy in season.enemies}
store = self.ui.get_object('enemy_season_store')
store.clear()
for name, stats in enemy_stats.items():
store.append([name, stats[0], stats[1], stats[2]])
# Reload after episode was changed #################################################################################
def reload_for_episode(self):
"""Reload all data that is dependant on a selected episode"""
episode_id = self.get_selected_episode_id()
if not episode_id:
return
episode = sql.Episode.get(sql.Episode.id == episode_id)
store = self.ui.get_object('episode_players_store')
store.clear()
for player in episode.players:
store.append([player.id, player.name, player.hex_id])
# Reload death store for notebook view
store = self.ui.get_object('episode_deaths_store')
store.clear()
for death in episode.deaths:
penalties = [x.drink.name for x in death.penalties]
penalties = [f'{number}x {drink}' for drink, number in Counter(penalties).items()]
penalty_string = ', '.join(penalties)
store.append([death.id, death.player.name, death.enemy.name, penalty_string])
# Reload victory store for notebook view
store = self.ui.get_object('episode_victories_store')
store.clear()
for victory in episode.victories:
store.append([victory.id, victory.player.name, victory.enemy.name, victory.info])
# Stat grid
self.ui.get_object('ep_stat_title').set_text('Stats for episode {}\n{}'.format(episode.number, episode.name))
self.ui.get_object('ep_death_count_label').set_text(str(len(episode.deaths)))
drink_count = sum(len(death.penalties) for death in episode.deaths)
self.ui.get_object('ep_drinks_label').set_text(str(drink_count))
self.ui.get_object('ep_player_drinks_label').set_text(str(len(episode.deaths)))
dl_booze = sum(len(death.penalties) * death.penalties[0].size for death in episode.deaths)
l_booze = round(dl_booze / 10, 2)
self.ui.get_object('ep_booze_label').set_text('{}l'.format(l_booze))
dl_booze = sum(len(death.penalties) * death.penalties[0].size for death in episode.deaths)
ml_booze = round(dl_booze * 10, 0)
self.ui.get_object('ep_player_booze_label').set_text('{}ml'.format(ml_booze))
enemy_list = [death.enemy.name for death in episode.deaths]
sorted_list = Counter(enemy_list).most_common(1)
if sorted_list:
enemy_name, deaths = sorted_list[0]
self.ui.get_object('ep_enemy_name_label').set_text(f'{enemy_name} ({deaths} Deaths)')
def get_selected_season_id(self) -> int: def get_selected_season_id(self) -> int:
"""Read ID of the selected season from the UI """Read ID of the selected season from the UI
:return: ID of the selected season :return: ID of the selected season

View File

@@ -14,7 +14,7 @@ class BaseDataHandlers:
if entry.get_text(): if entry.get_text():
sql.Player.create(name=entry.get_text()) sql.Player.create(name=entry.get_text())
entry.set_text('') entry.set_text('')
self.app.reload_base_data() self.app.reload()
def do_manage_enemies(self, *_): def do_manage_enemies(self, *_):
dialogs.show_manage_enemies_dialog(self.app.ui, self.app.get_selected_season_id()) dialogs.show_manage_enemies_dialog(self.app.ui, self.app.get_selected_season_id())
@@ -24,31 +24,31 @@ class BaseDataHandlers:
sql.Player.update(name=value)\ sql.Player.update(name=value)\
.where(sql.Player.id == row[0])\ .where(sql.Player.id == row[0])\
.execute() .execute()
self.app.reload_base_data() self.app.reload()
def on_player_hex_edited(self, _, index, value): def on_player_hex_edited(self, _, index, value):
row = self.app.ui.get_object('all_players_store')[index] row = self.app.ui.get_object('all_players_store')[index]
sql.Player.update(hex_id=value)\ sql.Player.update(hex_id=value)\
.where(sql.Player.id == row[0])\ .where(sql.Player.id == row[0])\
.execute() .execute()
self.app.reload_base_data() self.app.reload()
def do_add_drink(self, entry): def do_add_drink(self, entry):
if entry.get_text(): if entry.get_text():
sql.Drink.create(name=entry.get_text(), vol=0) sql.Drink.create(name=entry.get_text(), vol=0)
entry.set_text('') entry.set_text('')
self.app.reload_base_data() self.app.reload()
def on_drink_name_edited(self, _, index, value): def on_drink_name_edited(self, _, index, value):
row = self.app.ui.get_object('drink_store')[index] row = self.app.ui.get_object('drink_store')[index]
sql.Drink.update(name=value)\ sql.Drink.update(name=value)\
.where(sql.Drink.id == row[0])\ .where(sql.Drink.id == row[0])\
.execute() .execute()
self.app.reload_base_data() self.app.reload()
def on_drink_vol_edited(self, _, index, value): def on_drink_vol_edited(self, _, index, value):
row = self.app.ui.get_object('drink_store')[index] row = self.app.ui.get_object('drink_store')[index]
sql.Drink.update(vol=value) \ sql.Drink.update(vol=value) \
.where(sql.Drink.id == row[0]) \ .where(sql.Drink.id == row[0]) \
.execute() .execute()
self.app.reload_base_data() self.app.reload()

View File

@@ -13,8 +13,7 @@ class DeathHandlers:
return return
result = dialogs.show_edit_death_dialog(self.app.ui, ep_id) result = dialogs.show_edit_death_dialog(self.app.ui, ep_id)
if result == Gtk.ResponseType.OK: if result == Gtk.ResponseType.OK:
self.app.reload_for_season() self.app.reload()
self.app.reload_for_episode()
def on_penalty_drink_changed(self, _, path, text): def on_penalty_drink_changed(self, _, path, text):
self.app.ui.get_object('player_penalties_store')[path][2] = text self.app.ui.get_object('player_penalties_store')[path][2] = text

View File

@@ -6,7 +6,7 @@ from dsst_gtk3.handlers.base_data_handlers import BaseDataHandlers
from dsst_gtk3.handlers.dialog_handlers import DialogHandlers from dsst_gtk3.handlers.dialog_handlers import DialogHandlers
from dsst_gtk3.handlers.death_handlers import DeathHandlers from dsst_gtk3.handlers.death_handlers import DeathHandlers
from dsst_gtk3.handlers.victory_handlers import VictoryHandlers from dsst_gtk3.handlers.victory_handlers import VictoryHandlers
from dsst_sql import sql_func from dsst_sql import sql, sql_func
class Handlers(SeasonHandlers, BaseDataHandlers, DialogHandlers, DeathHandlers, VictoryHandlers): class Handlers(SeasonHandlers, BaseDataHandlers, DialogHandlers, DeathHandlers, VictoryHandlers):
@@ -28,6 +28,7 @@ class Handlers(SeasonHandlers, BaseDataHandlers, DialogHandlers, DeathHandlers,
""" Signal will be sent when app should close """ Signal will be sent when app should close
:param _: Arguments to the delete event :param _: Arguments to the delete event
""" """
sql.db.close()
Gtk.main_quit() Gtk.main_quit()
# DEBUG Functions ################################################################################################## # DEBUG Functions ##################################################################################################

View File

@@ -11,21 +11,20 @@ class SeasonHandlers:
name = dialogs.enter_string_dialog(self.app.ui, 'Name for the new Season') name = dialogs.enter_string_dialog(self.app.ui, 'Name for the new Season')
if name: if name:
sql.Season.create(game_name=name, number=1) sql.Season.create(game_name=name, number=1)
self.app.reload_base_data() self.app.reload()
def do_season_selected(self, *_): def do_season_selected(self, *_):
self.app.reload_for_season() self.app.reload()
def do_add_episode(self, *_): def do_add_episode(self, *_):
season_id = self.app.get_selected_season_id() season_id = self.app.get_selected_season_id()
if not season_id: if not season_id:
return return
dialogs.show_episode_dialog(self.app.ui, 'Create new Episode', season_id) dialogs.show_episode_dialog(self.app.ui, 'Create new Episode', season_id)
self.app.reload_for_season() self.app.reload()
def on_selected_episode_changed(self, *_): def on_selected_episode_changed(self, *_):
self.app.reload_for_episode() self.app.reload()
def on_episode_double_click(self, *_): def on_episode_double_click(self, *_):
self.app.reload_for_episode()
self.app.ui.get_object('stats_notebook').set_current_page(1) self.app.ui.get_object('stats_notebook').set_current_page(1)

View File

@@ -13,5 +13,4 @@ class VictoryHandlers:
return return
result = dialogs.show_edit_victory_dialog(self.app.ui, ep_id) result = dialogs.show_edit_victory_dialog(self.app.ui, ep_id)
if result == Gtk.ResponseType.OK: if result == Gtk.ResponseType.OK:
self.app.reload_for_season() self.app.reload()
self.app.reload_for_episode()

116
dsst/dsst_gtk3/reload.py Normal file
View File

@@ -0,0 +1,116 @@
from collections import Counter
from gi.repository import Gtk
from dsst_gtk3 import gtk_ui
from dsst_sql import sql, sql_func
from dsst_gtk3 import util
def reload_base_data(builder: Gtk.Builder, app: 'gtk_ui.GtkUi'):
"""Reload function for all base data witch is not dependant on a selected season or episode
:param app: GtkUi instance
:param builder: Gtk.Builder with loaded UI
"""
# Rebuild all players store
builder.get_object('all_players_store').clear()
for player in sql.Player.select():
builder.get_object('all_players_store').append([player.id, player.name, player.hex_id])
# Rebuild drink store
builder.get_object('drink_store').clear()
for drink in sql.Drink.select():
builder.get_object('drink_store').append([drink.id, drink.name, '{:.2f}%'.format(drink.vol)])
# Rebuild seasons store
combo = builder.get_object('season_combo_box') # type: Gtk.ComboBox
active = combo.get_active()
with util.block_handler(combo, app.handlers.do_season_selected):
store = builder.get_object('seasons_store')
store.clear()
for season in sql.Season.select().order_by(sql.Season.number):
store.append([season.id, season.game_name])
combo.set_active(active)
def reload_episodes(builder: Gtk.Builder, app: 'gtk_ui.GtkUi', season_id: int):
"""Reload all data that is dependant on a selected season
:param app: GtkUi instance
:param builder: Gtk.Builder with loaded UI
:param season_id: ID of the season for witch to load data
"""
# Rebuild episodes store
selection = builder.get_object('episodes_tree_view').get_selection()
with util.block_handler(selection, app.handlers.on_selected_episode_changed):
model, selected_paths = selection.get_selected_rows()
model.clear()
for episode in sql_func.get_episodes_for_season(season_id):
model.append([episode.id, episode.name, str(episode.date), episode.number])
if selected_paths:
selection.select_path(selected_paths[0])
def reload_season_stats(builder: Gtk.Builder, app: 'gtk_ui.GtkUi', season_id: int):
"""Load statistic data for selected season
:param builder: Gtk.Builder with loaded UI
:param app: GtkUi instance
:param season_id: ID of the season for witch to load data
"""
player_stats = {}
for episode in sql_func.get_episodes_for_season(season_id):
for player in episode.players:
player_stats[player.name] = [sql_func.get_player_deaths_for_season(season_id, player.id),
sql_func.get_player_victories_for_season(season_id, player.id)]
store = builder.get_object('player_season_store')
store.clear()
for name, stats in player_stats.items():
store.append([name, stats[0], stats[1]])
# Load enemy stats for season
season = sql.Season.get(sql.Season.id == season_id)
enemy_stats = {
enemy.name: [False, len(sql.Death.select().where(sql.Death.enemy == enemy)), enemy.id]
for enemy in season.enemies}
store = builder.get_object('enemy_season_store')
store.clear()
for name, stats in enemy_stats.items():
store.append([name, stats[0], stats[1], stats[2]])
def reload_episode_stats(builder: Gtk.Builder, app: 'gtk_ui.GtkUi', episode_id: int):
"""Reload all data that is dependant on a selected episode
:param builder: builder: Gtk.Builder with loaded UI
:param app: app: GtkUi instance
:param episode_id: ID of the episode for witch to load data
"""
episode = sql.Episode.get(sql.Episode.id == episode_id)
store = builder.get_object('episode_players_store')
store.clear()
for player in episode.players:
store.append([player.id, player.name, player.hex_id])
# Reload death store for notebook view
store = builder.get_object('episode_deaths_store')
store.clear()
for death in episode.deaths:
penalties = [x.drink.name for x in death.penalties]
penalties = [f'{number}x {drink}' for drink, number in Counter(penalties).items()]
penalty_string = ', '.join(penalties)
store.append([death.id, death.player.name, death.enemy.name, penalty_string])
# Reload victory store for notebook view
store = builder.get_object('episode_victories_store')
store.clear()
for victory in episode.victories:
store.append([victory.id, victory.player.name, victory.enemy.name, victory.info])
# Stat grid
builder.get_object('ep_stat_title').set_text('Stats for episode {}\n{}'.format(episode.number, episode.name))
builder.get_object('ep_death_count_label').set_text(str(len(episode.deaths)))
drink_count = sum(len(death.penalties) for death in episode.deaths)
builder.get_object('ep_drinks_label').set_text(str(drink_count))
builder.get_object('ep_player_drinks_label').set_text(str(len(episode.deaths)))
dl_booze = sum(len(death.penalties) * death.penalties[0].size for death in episode.deaths)
l_booze = round(dl_booze / 10, 2)
builder.get_object('ep_booze_label').set_text('{}l'.format(l_booze))
dl_booze = sum(len(death.penalties) * death.penalties[0].size for death in episode.deaths)
ml_booze = round(dl_booze * 10, 0)
builder.get_object('ep_player_booze_label').set_text('{}ml'.format(ml_booze))
enemy_list = [death.enemy.name for death in episode.deaths]
sorted_list = Counter(enemy_list).most_common(1)
if sorted_list:
enemy_name, deaths = sorted_list[0]
builder.get_object('ep_enemy_name_label').set_text(f'{enemy_name} ({deaths} Deaths)')

View File

@@ -3,6 +3,9 @@ This modules contains general utilities for the GTK application to use.
""" """
import json import json
import os import os
from contextlib import contextmanager
from gi.repository import Gtk
from typing import Callable
from zipfile import ZipFile from zipfile import ZipFile
CONFIG_PATH = os.path.join(os.path.expanduser('~'), '.config', 'dsst', 'config.json') CONFIG_PATH = os.path.join(os.path.expanduser('~'), '.config', 'dsst', 'config.json')
@@ -18,6 +21,17 @@ DEFAULT_CONFIG = {
} }
@contextmanager
def block_handler(widget: 'Gtk.Widget', handler_func: Callable):
"""Run an operation while a signal handler for a widget is blocked
:param widget: A Gtk widget
:param handler_func: Signal handler of the widget to block
"""
widget.handler_block_by_func(handler_func)
yield
widget.handler_unblock_by_func(handler_func)
def get_combo_value(combo, index: int): def get_combo_value(combo, index: int):
""" Retrieve the selected value of a combo box at the selected index in the model """ Retrieve the selected value of a combo box at the selected index in the model
:param combo: Any Gtk Widget that supports 'get_active_iter()' :param combo: Any Gtk Widget that supports 'get_active_iter()'