From 8bf96412b75689c578f5690dd0974304265d7fea Mon Sep 17 00:00:00 2001 From: emkael Date: Mon, 22 Jul 2019 11:39:02 +0200 Subject: Collecting and saving config file --- jfr_playoff/gui/__init__.py | 30 ++++++++++- jfr_playoff/gui/frames/match.py | 98 ++++++++++++++++++++++++++++++++++ jfr_playoff/gui/frames/network.py | 12 +++++ jfr_playoff/gui/frames/translations.py | 8 +++ jfr_playoff/gui/frames/visual.py | 55 ++++++++++++++++++- jfr_playoff/gui/tabs.py | 62 +++++++++++++++++++++ 6 files changed, 262 insertions(+), 3 deletions(-) (limited to 'jfr_playoff/gui') diff --git a/jfr_playoff/gui/__init__.py b/jfr_playoff/gui/__init__.py index 59821cb..551aec2 100644 --- a/jfr_playoff/gui/__init__.py +++ b/jfr_playoff/gui/__init__.py @@ -1,6 +1,6 @@ #coding=utf-8 -import json, os, sys +import codecs, copy, json, os, sys import tkinter as tk from tkinter import ttk @@ -122,7 +122,33 @@ class PlayoffGUI(tk.Tk): self.after(0, self._dirty.set, False) def saveFile(self, filepath): - pass + json.dump( + self.getConfig(), codecs.open(filepath, 'w', encoding='utf8'), + indent=4, ensure_ascii=False) + self._filepath = filepath + self._title.set(os.path.basename(filepath)) + self.after(0, self._dirty.set, False) + + def getConfig(self): + config = {} # TODO: OrderderDict, everywhere + for tab in self.tabs.values(): + tabConfig = tab.getConfig() + if tabConfig is not None: + config = self._mergeConfig(config, tab.getConfig()) + return config + + def _mergeConfig(self, base, update): + result = copy.copy(base) + for key, value in update.iteritems(): + if key in result: + if isinstance(result[key], dict): + result[key] = self._mergeConfig( + result[key], update[key]) + else: + result[key] = update[key] + else: + result[key] = value + return result def getDbConfig(self): return self.tabs['NetworkTab'].getDB() diff --git a/jfr_playoff/gui/frames/match.py b/jfr_playoff/gui/frames/match.py index 685d399..ad22a3b 100644 --- a/jfr_playoff/gui/frames/match.py +++ b/jfr_playoff/gui/frames/match.py @@ -170,6 +170,22 @@ class SwissSettingsFrame(RepeatableFrame): self.linkRelPath.set( value['relative_path'] if 'relative_path' in value else '') + def getValue(self): + config = {} + if self.source.get() == self.SOURCE_DB: + config['database'] = self.fetchDB.get() + if self.linkRelPath.get(): + config['relative_path'] = self.linkRelPath.get() + if self.source.get() == self.SOURCE_LINK: + config['link'] = self.fetchLink.get() + if self.linkLabel.get(): + config['label'] = self.linkLabel.get() + config['position'] = self.setFrom.get() + if self.setToEnabled.get(): + config['position_to'] = self.setTo.get() + if self.fetchFromEnabled.get(): + config['swiss_position'] = self.fetchFrom.get() + return config class SwissesFrame(ScrollableFrame): def renderContent(self, container): @@ -179,6 +195,9 @@ class SwissesFrame(ScrollableFrame): def setValues(self, values): self.swisses.setValue(values) + def getValues(self): + return self.swisses.getValue() + class MatchSelectionButton(SelectionButton): @property def defaultPrompt(self): @@ -390,6 +409,16 @@ class BracketMatchSettingsFrame(GuiFrame): self.selectedIndex.set(('none', '')) self.selected.set(0) + def getSelectedTeam(self): + if self.selected.get(): + try: + return self.bracketWidgets[7].getValues().index( + self.selectedIndex.get()) + except ValueError: + return -1 + else: + return -1 + def getConfig(self): if self.source.get() == self.SOURCE_TEAM: return self.teams @@ -406,6 +435,9 @@ class BracketMatchSettingsFrame(GuiFrame): config[key] = values return config + def getValue(self): + return self.getConfig() + class MatchSettingsFrame(RepeatableFrame): SCORE_SOURCE_DB = 0 SCORE_SOURCE_LINK = 1 @@ -665,6 +697,53 @@ class MatchSettingsFrame(RepeatableFrame): for idx in range(0, 2): self.bracketSettings[idx].setSelectedTeam(-1) + def getValue(self): + config = {} + config['id'] = self.matchID.get() + if self.link.get(): + config['link'] = self.link.get() + + config['teams'] = [bracket.getValue() + for bracket in self.bracketSettings] + + if len(self.winnerPositions): + config['winner'] = self.winnerPositions + if len(self.loserPositions): + config['loser'] = self.loserPositions + + selected = [bracket.getSelectedTeam() + for bracket in self.bracketSettings] + if len([s for s in selected if s > -1]): + config['selected_teams'] = selected + + if self.source.get() == self.SCORE_SOURCE_DB: + config['database'] = self.scoreDB.get() + config['round'] = self.scoreRound.get() + if self.source.get() != self.SCORE_SOURCE_CUSTOM: + config['table'] = self.scoreTable.get() + + if self.source.get() == self.SCORE_SOURCE_CUSTOM: + config['score'] = [] + for score in self.scoreCustom: + try: + config['score'].append(float(score.get())) + except ValueError: + config['score'].append(0.0) + if self.scoreNotFinished.get(): + config['running'] = self.scoreBoards.get() + + return config + + if 'selected_teams' in value \ + and isinstance(value['selected_teams'], list): + for idx, val in enumerate(value['selected_teams']): + if idx < 2: + self.bracketSettings[idx].setSelectedTeam(val) + else: + for idx in range(0, 2): + self.bracketSettings[idx].setSelectedTeam(-1) + + class MatchSeparator(RepeatableFrame): def renderContent(self): @@ -725,5 +804,24 @@ class MatchPhaseFrame(ScrollableFrame): self.winfo_toplevel().event_generate( '<>', when='tail') + def getConfig(self): + config = {} + if self.name.get(): + config['title'] = self.name.get() + if self.link.get(): + config['link'] = self.link.get() + values = self.matches.getValue() + dummies = [] + matches = [] + for idx, value in enumerate(values): + if value is None: + dummies.append(idx) + else: + matches.append(value) + if len(dummies): + config['dummies'] = dummies + config['matches'] = matches + return config + __all__ = ['SwissesFrame', 'MatchPhaseFrame', 'MatchSettingsFrame'] diff --git a/jfr_playoff/gui/frames/network.py b/jfr_playoff/gui/frames/network.py index d44ff49..fc00575 100644 --- a/jfr_playoff/gui/frames/network.py +++ b/jfr_playoff/gui/frames/network.py @@ -166,6 +166,15 @@ class GoniecConfigurationFrame(GuiFrame): values['port'] if 'port' in values else self.DEFAULT_PORT) self.enable.set(values['enabled'] if 'enabled' in values else 0) + def getValues(self): + config = { + 'enabled': self.enable.get() + } + if self.enable.get(): + config['host'] = self.host.get() + config['port'] = self.port.get() + return config + class RemoteConfigurationFrame(ScrollableFrame): def renderContent(self, container): frame = ttk.LabelFrame(container, text='Zdalne pliki konfiguracyjne:') @@ -178,4 +187,7 @@ class RemoteConfigurationFrame(ScrollableFrame): def setValues(self, values): self.repeater.setValue(values) + def getValues(self): + return self.repeater.getValue() + __all__ = ['MySQLConfigurationFrame', 'GoniecConfigurationFrame', 'RemoteConfigurationFrame'] diff --git a/jfr_playoff/gui/frames/translations.py b/jfr_playoff/gui/frames/translations.py index 3ba660f..e5b8940 100644 --- a/jfr_playoff/gui/frames/translations.py +++ b/jfr_playoff/gui/frames/translations.py @@ -23,6 +23,9 @@ class TranslationRow(RepeatableFrame): self.key.set(value[0]) self.value.set(value[1]) + def getValue(self): + return (self.key.get(), self.value.get()) + class TranslationConfigurationFrame(ScrollableFrame): def setTranslations(self, translations): @@ -33,6 +36,11 @@ class TranslationConfigurationFrame(ScrollableFrame): values.append(value) self.repeater.setValue(values) + def getTranslations(self): + return { + key: value for key, value in self.repeater.getValue() + } + def renderContent(self, container): self.repeater = WidgetRepeater(container, TranslationRow) self.repeater.pack(side=tk.TOP, fill=tk.BOTH, expand=True) diff --git a/jfr_playoff/gui/frames/visual.py b/jfr_playoff/gui/frames/visual.py index 6780e99..9bbe5f6 100644 --- a/jfr_playoff/gui/frames/visual.py +++ b/jfr_playoff/gui/frames/visual.py @@ -178,6 +178,25 @@ class VisualSettingsFrame(GuiFrame): self.teamNameSeparator.set(values['team_boxes']['name_separator']) self.teamNamePrefix.set(values['team_boxes']['name_prefix']) + def getValues(self): + return { + 'width': self.boxWidth.get(default=250), + 'height': self.boxHeight.get(default=80), + 'margin': self.boxMargin.get(default=60), + 'starting_position_indicators': self.startingPositionIndicators.get(), + 'finishing_position_indicators': self.finishingPositionIndicators.get(), + 'team_boxes': { + 'label_length_limit': self.teamNameLength.get(default=25) if self.shortenTeamNames else 0, + 'predict_teams': self.teamNamePredict.get(), + 'label_separator': self.teamLabelSeparator.get(), + 'label_placeholder': self.teamNamePlaceholder.get(), + 'label_ellipsis': self.teamNameEllipsis.get(), + 'name_separator': self.teamNameSeparator.get(), + 'name_prefix': self.teamNamePrefix.get(), + 'sort_eligible_first': self.teamNameSortPredictions.get() + } + } + class MatchList(RefreshableOptionMenu): def __init__(self, *args, **kwargs): @@ -235,6 +254,13 @@ class BoxPositionFrame(RepeatableFrame): self.vertical.set(0) self.horizontal.set(-1) + def getValue(self): + horizontal = self.horizontal.get(default=-1) + vertical = self.vertical.get(default=0) + return ( + self.match.get(), + [vertical, horizontal] if horizontal >= 0 else vertical) + class BoxPositionsFrame(ScrollableFrame): def renderContent(self, container): (ttk.Label(container, text='Pozycje tabelek meczów:')).pack( @@ -255,6 +281,9 @@ class BoxPositionsFrame(ScrollableFrame): values_to_set.append(value) self.positions.setValue(values_to_set) + def getValues(self): + return { match: config for match, config in self.positions.getValue() } + class LineStyle(GuiFrame): def _selectColour(self): colour = tkcc.askcolor(self._getColour()) @@ -288,6 +317,9 @@ class LineStyle(GuiFrame): self.hOffset.set(value[1]) self.vOffset.set(value[2]) + def getValue(self): + return [self._getColour(), self.hOffset.get(), self.vOffset.get()] + class LineStylesFrame(GuiFrame): DEFAULT_VALUES = [ ('winner', ('#00ff00', 5, -10), @@ -303,6 +335,7 @@ class LineStylesFrame(GuiFrame): ('finish_loser', ('#ff0000', 20, 10), 'Przegrani meczów kończący rozgrywki: ') ] + CONFIG_KEYS = ['colour', 'h_offset', 'v_offset'] def renderContent(self): self.lines = {} @@ -317,12 +350,20 @@ class LineStylesFrame(GuiFrame): def setValues(self, values): for line in self.DEFAULT_VALUES: value = list(line[1]) - for idx, key in enumerate(['colour', 'h_offset', 'v_offset']): + for idx, key in enumerate(self.CONFIG_KEYS): key = '%s_%s' % (line[0], key) if key in values: value[idx] = values[key] self.lines[line[0]].setValue(value) + def getValues(self): + config = {} + for line, widget in self.lines.iteritems(): + value = widget.getValue() + for idx, key in enumerate(self.CONFIG_KEYS): + config['%s_%s' % (line, key)] = value[idx] + return config + class PositionsSelectionFrame(SelectionFrame): COLUMN_COUNT=10 @@ -381,6 +422,15 @@ class PositionStyleFrame(RepeatableFrame): value['positions'] if 'positions' in value else []) self.description.set(value['caption'] if 'caption' in value else '') + def getValue(self): + config = { + 'class': self.name.get(), + 'positions': self.positions + } + caption = self.description.get() + if caption: + config['caption'] = caption + return config class PositionStylesFrame(ScrollableFrame): def renderContent(self, container): @@ -392,4 +442,7 @@ class PositionStylesFrame(ScrollableFrame): def setValues(self, values): self.styles.setValue(values) + def getValues(self): + return self.styles.getValue() + __all__ = ['VisualSettingsFrame', 'BoxPositionsFrame', 'LineStylesFrame', 'PositionStylesFrame'] diff --git a/jfr_playoff/gui/tabs.py b/jfr_playoff/gui/tabs.py index 8b66b25..2b316f4 100644 --- a/jfr_playoff/gui/tabs.py +++ b/jfr_playoff/gui/tabs.py @@ -39,6 +39,9 @@ class PlayoffTab(ttk.Frame): def setValues(self, config): pass + def getConfig(self): + pass + class MainSettingsTab(PlayoffTab): DEFAULT_INTERVAL = 60 @@ -145,6 +148,17 @@ class MainSettingsTab(PlayoffTab): container.columnconfigure(1, weight=1) container.rowconfigure(4, weight=1) + def getConfig(self): + return { + 'output': self.outputPath.get(), + 'page': { + 'title': self.pageTitle.get(), + 'logoh': self.pageLogoh.get(), + 'refresh': self.refreshInterval.get() \ + if self.refresh.get() > 0 else 0 + } + } + class TeamsTab(PlayoffTab): @property def title(self): @@ -218,6 +232,9 @@ class TeamsTab(PlayoffTab): config['teams']['ties'] if 'teams' in config and 'ties' in config['teams'] else []) + def getConfig(self): + return self.collectConfig() + class MatchesTab(PlayoffTab): @property def title(self): @@ -294,6 +311,11 @@ class MatchesTab(PlayoffTab): match.matchID.set( self.winfo_toplevel().getNewMatchID(match)) + def getConfig(self): + return { + 'phases': [phase.getConfig() for phase in self.phases.values()] + } + class SwissesTab(PlayoffTab): @property def title(self): @@ -306,6 +328,15 @@ class SwissesTab(PlayoffTab): def setValues(self, config): self.swisses.setValues(config['swiss'] if 'swiss' in config else []) + def getConfig(self): + swisses = self.swisses.getValues() + if len(swisses): + return { + 'swiss': swisses + } + else: + return None + class NetworkTab(PlayoffTab): @property def title(self): @@ -362,6 +393,16 @@ class NetworkTab(PlayoffTab): self.remoteFrame.setValues( config['remotes'] if 'remotes' in config else []) + def getConfig(self): + config = {} + mysql = self.getDB() + if mysql is not None: + config['database'] = mysql + config['goniec'] = self.goniecFrame.getValues() + remotes = self.remoteFrame.getValues() + if len(remotes): + config['remotes'] = remotes + return config class VisualTab(PlayoffTab): @property @@ -388,6 +429,16 @@ class VisualTab(PlayoffTab): else: self.positionFrame.setValues({}) + def getConfig(self): + config = { + 'page': self.settingsFrame.getValues() + } + boxConfig = self.positionFrame.getValues() + if boxConfig: + config['canvas'] = {} + config['canvas']['box_positioning'] = boxConfig + return config + class StyleTab(PlayoffTab): @property def title(self): @@ -414,6 +465,12 @@ class StyleTab(PlayoffTab): else: self.positionStylesFrame.setValues([]) + def getConfig(self): + return { + 'canvas': self.linesFrame.getValues(), + 'position_styles': self.positionStylesFrame.getValues() + } + class TranslationsTab(PlayoffTab): @property def title(self): @@ -430,5 +487,10 @@ class TranslationsTab(PlayoffTab): else: self.translationsFrame.setTranslations({}) + def getConfig(self): + return { + 'i18n': self.translationsFrame.getTranslations() + } + __all__ = ['MainSettingsTab', 'TeamsTab', 'MatchesTab', 'SwissesTab', 'NetworkTab', 'VisualTab', 'StyleTab', 'TranslationsTab'] -- cgit v1.2.3