diff --git a/i18n.py b/i18n.py new file mode 100644 index 0000000..2f1ffaf --- /dev/null +++ b/i18n.py @@ -0,0 +1,40 @@ +import os +import polib +from collections import defaultdict + +localedir = "katrain/i18n/locales" +locales = set(os.listdir(localedir)) +print("locales found:",locales) + +strings_to_langs = defaultdict(dict) +lang_to_strings = defaultdict(set) + +DEFAULT_LANG = "en" + +po = {} +for lang in locales: + pofile = os.path.join(localedir, lang, 'LC_MESSAGES', 'katrain.po') + po[lang] = polib.pofile(pofile) + for entry in po[lang].translated_entries(): + if 'TODO' in entry.comment: + print(lang,'/',entry.msgid,'is TODO') + else: + strings_to_langs[entry.msgid][lang] = entry.msgstr + lang_to_strings[lang].add(entry.msgid) + + +for lang in locales: + for msgid in strings_to_langs.keys() - lang_to_strings[lang]: + if lang==DEFAULT_LANG: + print("Message id",msgid,"found as ",strings_to_langs[msgid],"but missing in default",DEFAULT_LANG) + elif DEFAULT_LANG in strings_to_langs[msgid]: + print("Message id", msgid, "missing in ",lang,'-> Adding it from',DEFAULT_LANG) + entry = polib.POEntry(msgid=msgid,msgstr=strings_to_langs[msgid][DEFAULT_LANG],comment="TODO") + po[lang].append(entry) + else: + print(f"MISSING IN DEFAULT AND {lang}",strings_to_langs[msgid]) + po[lang].save(pofile) + mofile = pofile.replace('.po', '.mo') + po[lang].save_as_mofile(mofile) + print('Fixed',pofile,'and converted ->',mofile) + diff --git a/katrain/__main__.py b/katrain/__main__.py index b677496..f1c7de7 100644 --- a/katrain/__main__.py +++ b/katrain/__main__.py @@ -29,7 +29,7 @@ from katrain.core.game import Game, IllegalMoveException, KaTrainSGF from katrain.core.sgf_parser import Move, ParseError from katrain.gui.kivyutils import * from katrain.gui.graph import ScoreGraph -from katrain.gui.badukpan import BadukPanWidget +from katrain.gui.badukpan import BadukPanWidget, AnalysisControls, BadukPanControls from katrain.gui.controlspanel import ControlsPanel, RightButtonControls from katrain.gui.popups import NewGamePopup, ConfigPopup, LoadSGFPopup from katrain.core.common import Lang @@ -294,9 +294,9 @@ class KaTrainGui(Screen): "r": self.analysis_controls.ownership, "t": self.analysis_controls.policy, "enter": ("ai-move",), - "a": self.analysis_controls.analyze_extra, - "s": self.analysis_controls.analyze_equalize, - "d": self.analysis_controls.analyze_sweep, + "a": ("analyze-extra", "extra"), + "s": ("analyze-extra", "equalize"), + "d": ("analyze-extra", "sweep"), "p": ("play", None), "right": ("switch-branch", 1), "left": ("switch-branch", -1), diff --git a/katrain/core/game_node.py b/katrain/core/game_node.py index e1b0824..050322b 100644 --- a/katrain/core/game_node.py +++ b/katrain/core/game_node.py @@ -94,13 +94,24 @@ class GameNode(SGFNode): def analysis_ready(self): return self.analysis["root"] is not None + + @property + def score(self) -> Optional[float]: + if self.analysis_ready: + return self.analysis["root"].get("scoreLead") + def format_score(self, score=None): score = score or self.score if score is not None: return f"{'B' if score >= 0 else 'W'}+{abs(score):.1f}" - def format_win_rate(self, win_rate=None): - win_rate = win_rate or self.analysis["root"].get("winrate") + @property + def winrate(self) -> Optional[float]: + if self.analysis_ready: + return self.analysis["root"].get("winrate") + + def format_winrate(self, win_rate=None): + win_rate = win_rate or self.winrate if win_rate is not None: return f"{'B' if win_rate > 0.5 else 'W'} {max(win_rate,1-win_rate):.1%}" @@ -120,7 +131,7 @@ class GameNode(SGFNode): score = self.score if sgf: text += f"Score: {self.format_score(score)}\n" - text += f"Win Rate: {self.format_win_rate()}\n" + text += f"Win Rate: {self.format_winrate()}\n" if self.parent and self.parent.analysis_ready: previous_top_move = self.parent.candidate_moves[0] if sgf or hints: @@ -168,10 +179,6 @@ class GameNode(SGFNode): score = self.score return self.player_sign(single_move.player) * (score - parent_parent_score) - @property - def score(self) -> Optional[float]: - if self.analysis_ready: - return self.analysis["root"]["scoreLead"] @staticmethod def player_sign(player): diff --git a/katrain/gui.kv b/katrain/gui.kv index f3f60ae..1f9a127 100644 --- a/katrain/gui.kv +++ b/katrain/gui.kv @@ -67,6 +67,7 @@ : text_color: WHITE + md_bg_color: BOX_BACKGROUND_COLOR label: label Label: id: label @@ -74,7 +75,6 @@ size_hint_x: None color: root.text_color font_size: root.font_size - font_name: root.font_name or self.font_name halign: root.halign : @@ -91,14 +91,25 @@ : # only wants height width: self.label.texture_size[0] + self.hor_padding * 2 + font_size: 0.75 * self.height / len(self.label.text.split('\n')) : # only wants height width: self.label.texture_size[0] + self.hor_padding * 2 - + font_size: 0.75 * self.height / len(self.label.text.split('\n')) : background_color: BOX_BACKGROUND_COLOR +: + background_normal: '' + background_color: (0,0,0,0) + icon_size: self.icon_size or [min(self.size[0],self.size[1]),min(self.size[0],self.size[1])] + Image: + size: root.icon_size + pos: [root.pos[i] + (root.size[i] - root.icon_size[i])/2 for i in [0,1]] + source: root.icon + mipmap: True + # -- old widgets @@ -142,10 +153,6 @@ : max_lines: 1 -: - bold: True - radius: (self.size[1]/3,self.size[1]/3,0,0) - : : @@ -183,17 +190,6 @@ mipmap: True -: - background_normal: '' - background_color: (0,0,0,0) - icon_size: self.icon_size or [min(self.size[0],self.size[1]),min(self.size[0],self.size[1])] - image: image - Image: - id: image - size: root.icon_size - pos: [root.pos[i] + (root.size[i] - root.icon_size[i])/2 for i in [0,1]] - source: root.icon - mipmap: True : color: TEXT_COLOR @@ -269,63 +265,18 @@ katrain: app.gui : - md_bg_color: BOX_BACKGROUND_COLOR -: - eval: eval - policy: policy - hints: hints - ownership: ownership - analyze_extra: analyze_extra - analyze_equalize: analyze_equalize - analyze_sweep: analyze_sweep - ButtonBoxHolder: - size_hint_y: INFO_BOX_HEIGHT * 0.75 - ButtonBox: - RHSToggleButton: - id: eval - text: 'Dots' - color: WHITE - RHSToggleButton: - id: ownership - text: 'Territory' - color: WHITE - RHSToggleButton: - id: policy - text: 'Policy' - color: WHITE - RHSToggleButton: - id: hints - text: 'Top Moves' - color: WHITE - RHSButton: - id: analyze_extra - text: 'Extra' - tooltip_text: '[a]\nExtra analysis\nto increase accuracy\nof top move predictions\nand score difference' - on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","extra") - RHSButton: - id: analyze_equalize - text: 'Equalize' - tooltip_text: '[s]\nAnalysis of all\npredicted top moves\nwith the same accuracy' - on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","equalize") - RHSButton: - id: analyze_sweep - text: 'Sweep' - tooltip_text: '[d]\nFast analysis\nof all legal moves' - on_left_press: if not self.last_touch or self.last_touch.button=="left": root.katrain("analyze-extra","sweep") : size_hint: 0.06, 0.5 pos_hint: {'center_y': 0.5} - : katrain: app.gui circles: [black_circle,white_circle] mid_circles_container: mid_circles_container pass_btn: pass_btn hamburger: hamburger - analysis_button: analysis_button adaptive_height: True HamburgerButton: id: hamburger @@ -333,14 +284,13 @@ width: self.height pos_hint: {'x': 0} on_press: app.gui.nav_drawer.set_state("open") - StyledButton: + SizedMDFlatRectangleButton: + id: pass_btn text: i18n._('pass-button-text') tooltip_text: i18n._('pass-button-tooltip') - id: pass_btn size_hint: None, 0.5 + width: 2*self.height pos_hint: {'x': 0.1,'center_y':0.5} - width: self.height * 2 - font_size: 0.6*self.size[1] on_left_release: root.katrain("play",None) canvas.before: Color: @@ -419,26 +369,12 @@ on_press: root.katrain('redo',999) NavIconButton: icon: 'img/flaticon/route.png' - StyledButton: - size_hint: None, 0.5 - pos_hint: {'right': 1,'center_y':0.5} - width: self.height * 4 - font_size: 0.6*self.size[1] - id: analysis_button - text: 'Analysis Settings' - icon: 'settings' - on_press: root.open_analysis_menu() - canvas.before: - Color: - rgba: RED - Line: - rectangle: (*self.pos,*self.size) - width: 1 -: - icon: 'menu' +: + icon: 'img/hamburger.png' size_hint: None, 1 width: self.height + icon_size: [self.height * 0.8, self.height * 0.8] # ---------- components of right pane ------- @@ -527,7 +463,6 @@ valign: 'bottom' halign: 'left' text: '+0' - color: SCORE_COLOR size: self.texture_size : @@ -536,60 +471,82 @@ bhalf: root.pos[1]+self.height*0.75 mid: root.pos[1]+self.height*0.5 right_edge: root.pos[0] + root.width + marker_font_size: 0.1 * root.height canvas: Color: rgba: GRAPH_CENTER_COLOR Line: points: [root.pos[0],root.whalf,root.pos[0]+root.width,root.whalf] width: 1 - dashes: [2,2] +# dashes: [2,2] Line: points: [root.pos[0],root.mid,root.pos[0]+root.width,root.mid] width: 1 - dashes: [4,4] +# dashes: [4,4] Line: points: [root.pos[0],root.bhalf,root.pos[0]+root.width,root.bhalf] width: 1 - dashes: [2,2] +# dashes: [2,2] canvas.after: Color: rgba: SCORE_COLOR Line: - points: root.score_points + points: root.score_points if root.show_score else [] width: 1.1 Color: rgba: WINRATE_COLOR Line: - points: root.winrate_points + points: root.winrate_points if root.show_winrate else [] width: 1.1 + Color: rgba: GRAPH_DOT_COLOR Ellipse: id: dot pos: root.dot_pos size: self.highlight_size,self.highlight_size + # score ticks GraphMarkerLabel: - font_size: 0.1 * root.height - id: range_label_top - pos: root.right_edge - self.width-1, root.pos[1]+root.height - self.font_size - text: 'B+' + str(int(root.y_scale)) + font_size: root.marker_font_size + color: SCORE_COLOR + pos: root.right_edge - self.width-1, root.pos[1]+root.height - self.font_size - 1 + text: 'B+{}'.format(root.score_scale) + opacity: int(root.show_score) GraphMarkerLabel: - font_size: 0.1 * root.height + font_size: root.marker_font_size + color: SCORE_COLOR pos: root.right_edge - self.width-1, root.mid - self.height/2 + 2 text: 'Jigo' + opacity: int(root.show_score) GraphMarkerLabel: - font_size: 0.1 * root.height + font_size: root.marker_font_size + color: SCORE_COLOR pos: root.right_edge - self.width-1, root.pos[1] - text: 'W+' + str(int(root.y_scale)) + text: 'W+' + str(int(root.score_scale)) + opacity: int(root.show_score) + # wr ticks + GraphMarkerLabel: + font_size: root.marker_font_size + color: WINRATE_COLOR + pos: root.pos[0]+1, root.pos[1]+root.height - self.font_size - 1 + text: "{}%".format(50 + root.winrate_scale) + opacity: int(root.show_winrate) + GraphMarkerLabel: + font_size: root.marker_font_size + color: WINRATE_COLOR + pos:root.pos[0]+1, root.pos[1] + text: "{}%".format(50 - root.winrate_scale) + opacity: int(root.show_winrate) + orientation: 'vertical' background_color: BOX_BACKGROUND_COLOR score: score - win_rate: win_rate + winrate: winrate score_change: score_change CensorableLabel: - id: win_rate + id: winrate label: 'Win rate' text: '' color: WINRATE_COLOR @@ -625,15 +582,15 @@ on_ref_press: root.dispatch('on_ref_press',args[1]) -#:set PLAYER_BOX_HEIGHT 0.15 -#:set TIMER_BOX_HEIGHT 0.3 -#:set GRAPH_BOX_HEIGHT 0.37 +#:set player_box_height 0.15 +#:set timer_box_height 0.3 +#:set graph_box_height 0.37 #:set STATS_BOX_HEIGHT 0.27 #:set INFO_BOX_HEIGHT 1 #:set CP_SPACING 6 #:set CP_SMALL_SPACING 3 -#:set CP_PADDING 4 +#:set CP_PADDING 6 : katrain: app.gui @@ -648,9 +605,14 @@ status: status padding: CP_PADDING spacing: CP_SPACING - tab_option_height: 20 + player_box_height: max(50, 0.1 * root.height) + timer_box_height: max(50, 0.125 * root.height) + graph_box_height: max(100, 0.2 * root.height) + stats_box_height: max(50, 0.125 * root.height) + tab_option_height: max(15,root.height / 30) BoxLayout: # -- Players - size_hint_y: PLAYER_BOX_HEIGHT + size_hint_y: None + height: root.player_box_height PlayerInfo: id: B_player player: 'Black' @@ -658,7 +620,8 @@ id: W_player player: 'White' BoxLayout: - size_hint_y: TIMER_BOX_HEIGHT + size_hint_y: None + height: root.timer_box_height spacing: CP_SPACING PonderInfo: id: ponder @@ -668,27 +631,28 @@ id: timer size_hint_x: 0.7 CollapsablePanel: - size_hint_y_open: GRAPH_BOX_HEIGHT - closed_label: 'Score Graph' - options: ['Score','Win Rate','PtLoss'] + height_open: root.graph_box_height + closed_label: 'closedlabel:scoregraph' + options: ['score','winrate','points'] option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR] option_default_active: [True,False,False] options_height: root.tab_option_height + on_option_state: graph.show_graphs(args[1]) ScoreGraph: id: graph CollapsablePanel: - size_hint_y_open: STATS_BOX_HEIGHT - closed_label: 'Move Stats' - options: ['Score','Win Rate','PtLoss'] + height_open: root.stats_box_height + closed_label: 'closedlabel:movestats' + options: ['score','winrate','points'] option_colors: [SCORE_COLOR,WINRATE_COLOR,POINTLOSS_COLOR] option_default_active: [True,True,True] options_height: root.tab_option_height StatsBox: id: stats CollapsablePanel: - size_hint_y: INFO_BOX_HEIGHT - closed_label: 'Move Info & Notes' - options: ['Info','Notes'] + size_hint_y_open: 1 + closed_label: 'closedlabel:info¬es' + options: ['info','notes'] option_colors: [RED,GREEN] option_default_active: [True,False] options_height: root.tab_option_height @@ -711,7 +675,8 @@ on_text: root.katrain.set_note(self.text) hint_text: 'Your SGF notes for this position here.' height: min( (len(self._lines)+0.7) * self.line_height, self.parent.height - status.height - 2.7*self.line_height) - + Label: + size_hint_y: 1e-9 # takes up remaining space if info is closed : md_bg_color: BOX_BACKGROUND_COLOR @@ -722,7 +687,7 @@ on_press: app.gui.update_state() size_hint_y: 1 -: +: katrain: app.gui orientation: 'horizontal' padding: CP_PADDING, CP_PADDING @@ -732,9 +697,8 @@ policy: policy hints: hints ownership: ownership - analyze_extra: analyze_extra - analyze_equalize: analyze_equalize - analyze_sweep: analyze_sweep + analysis_button: analysis_button + Label: RHSToggleButton: id: show_children text: 'Next\nMoves' @@ -757,21 +721,10 @@ text: 'Top\nMoves' color: WHITE RHSButton: - id: analyze_extra - text: 'Extra' - tooltip_text: '[a]\nExtra analysis\nto increase accuracy\nof top move predictions\nand score difference' - on_left_press: root.katrain("analyze-extra","extra") - RHSButton: - id: analyze_equalize - text: 'Equalize' - tooltip_text: '[s]\nAnalysis of all\npredicted top moves\nwith the same accuracy' - on_left_press: root.katrain("analyze-extra","equalize") - RHSButton: - id: analyze_sweep - text: 'Sweep' - tooltip_text: '[d]\nFast analysis\nof all legal moves' - on_left_press: root.katrain("analyze-extra","sweep") - + id: analysis_button + on_press: root.open_analysis_menu() + text: 'Analysis' + Label: @@ -884,18 +837,26 @@ AnalysisControls: id: analysis_controls size_hint_y: None - height: min(100,self.width / 13.5) if not root.zen else 1 + height: min(100,self.width / 13.5) if not root.zen else 0 + opacity: 0 if root.zen else 1 BadukPanWidget: id: board_gui BadukPanControls: id: board_controls size_hint_y: None height: min(100,self.width / 13.5) - ControlsPanel: - id: controls + MDBoxLayout: size_hint_x: None - width: 0 if root.zen else self.height * 0.35 + width: 0 if root.zen else self.height * 0.4 opacity: 0 if root.zen else 1 + orientation: 'vertical' + MDBoxLayout: + size_hint_y: None + height: analysis_controls.height + Label: + text: 'BlaBla' + ControlsPanel: + id: controls MyNavigationDrawer: id: nav_drawer state: "close" diff --git a/katrain/gui/badukpan.py b/katrain/gui/badukpan.py index 86d7724..92001e5 100644 --- a/katrain/gui/badukpan.py +++ b/katrain/gui/badukpan.py @@ -401,17 +401,18 @@ class BadukPanWidget(Widget): def show_pv_from_comments(self, pv_str): self.set_animating_pv(pv_str[1:].split(" "), self.katrain.controls.active_comment_node.parent) - -class BadukPanControls(MDFloatLayout): +class AnalysisControls(MDBoxLayout): def __init__(self, **kwargs): super().__init__(**kwargs) - self.analysis_menu = None - Clock.schedule_once(self.init_menus, 1) + self.analysis_menu=None + Clock.schedule_once(self.build_menu,0) - def init_menus(self, _dt): + def build_menu(self,_dt): menu_items = [{"icon": "git", "text": f"Item {i}"} for i in range(5)] self.analysis_menu = MDDropdownMenu(caller=self.analysis_button, items=menu_items, width_mult=4) def open_analysis_menu(self): - if self.analysis_menu: - self.analysis_menu.open() + self.analysis_menu.open() + +class BadukPanControls(MDFloatLayout): + pass \ No newline at end of file diff --git a/katrain/gui/controlspanel.py b/katrain/gui/controlspanel.py index 3157a9c..d48ee88 100644 --- a/katrain/gui/controlspanel.py +++ b/katrain/gui/controlspanel.py @@ -84,7 +84,7 @@ class ControlsPanel(BoxLayout): if current_node.analysis_ready: self.stats.score.text = current_node.format_score() - self.stats.win_rate.text = current_node.format_win_rate() + self.stats.winrate.text = current_node.format_winrate() if move and last_player_was_human_or_both_robots: # don't immediately hide this when an ai moves comes in points_lost = current_node.points_lost self.stats.score_change.label = f"Points lost" if points_lost and points_lost > 0 else f"Points gained" @@ -98,7 +98,7 @@ class ControlsPanel(BoxLayout): self.stats.score_change.text = f"{current_node.parent.move.player}: {abs(points_lost):.1f}" if points_lost else "-" elif both_players_are_robots and current_node.parent and current_node.parent.analysis_ready: self.stats.score.text = current_node.parent.format_score() - self.stats.win_rate.text = current_node.parent.format_win_rate() + self.stats.winrate.text = current_node.parent.format_winrate() self.graph.update_value(current_node) self.note.text = current_node.note diff --git a/katrain/gui/graph.py b/katrain/gui/graph.py index 4565607..3808600 100644 --- a/katrain/gui/graph.py +++ b/katrain/gui/graph.py @@ -1,19 +1,26 @@ import math -from kivy.properties import ListProperty, NumericProperty +from kivy.properties import ListProperty, NumericProperty, BooleanProperty from katrain.gui.kivyutils import BackgroundColor class ScoreGraph(BackgroundColor): + show_score = BooleanProperty(True) + show_winrate = BooleanProperty(True) + show_pointloss = BooleanProperty(True) + nodes = ListProperty([]) score_points = ListProperty([]) winrate_points = ListProperty([]) + dot_pos = ListProperty([0, 0]) highlighted_index = NumericProperty(None) - y_scale = NumericProperty(5) highlight_size = NumericProperty(5) + score_scale = NumericProperty(5) + winrate_scale = NumericProperty(5) + def __init__(self, **kwargs): super().__init__(**kwargs) self.bind(pos=self.update_graph, size=self.update_graph) @@ -26,26 +33,41 @@ class ScoreGraph(BackgroundColor): self.nodes.append(node) self.highlighted_index = 0 + def show_graphs(self,keys): + self.show_score = keys['score'] + self.show_winrate = keys['winrate'] + self.show_pointloss = keys['points'] + def update_graph(self, *args): nodes = self.nodes if nodes: - values = [n.score if n and n.score else math.nan for n in nodes] - nn_values = [n.score for n in nodes if n and n.score] - val_range = min(nn_values or [0]), max(nn_values or [0]) + score_values = [n.score if n and n.score else math.nan for n in nodes] + score_nn_values = [n.score for n in nodes if n and n.score] + score_values_range = min(score_nn_values or [0]), max(score_nn_values or [0]) - self.y_scale = math.ceil(max(5, max(-val_range[0], val_range[1])) / 5) * 5 + winrate_values = [(n.winrate-0.5)*100 if n and n.winrate else math.nan for n in nodes] + winrate_nn_values = [(n.winrate-0.5)*100 for n in nodes if n and n.winrate] + winrate_values_range = min(winrate_nn_values or [0]), max(winrate_nn_values or [0]) - xscale = self.width / max(len(values) - 1, 15) + score_granularity = 5 + winrate_granularity = 10 + self.score_scale = max(math.ceil( max(-score_values_range[0], score_values_range[1]) / score_granularity),1) * score_granularity + self.winrate_scale = max(math.ceil(max(-winrate_values_range[0], winrate_values_range[1]) / winrate_granularity), 1) * winrate_granularity + + print(self.score_scale,score_values_range,score_values) + + xscale = self.width / max(len(score_values) - 1, 15) available_height = self.height - line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.y_scale)] for i, val in enumerate(values)] - self.score_points = sum(line_points, []) - self.winrate_points = self.score_points # TODO + score_line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.score_scale)] for i, val in enumerate(score_values)] + winrate_line_points = [[self.pos[0] + i * xscale, self.pos[1] + self.height / 2 + available_height / 2 * (val / self.winrate_scale)] for i, val in enumerate(winrate_values)] + self.score_points = sum(score_line_points, []) + self.winrate_points = sum(winrate_line_points,[]) if self.highlighted_index is not None: - self.highlighted_index = min(self.highlighted_index, len(values) - 1) - dot_point = line_points[self.highlighted_index] + self.highlighted_index = min(self.highlighted_index, len(score_values) - 1) + dot_point = score_line_points[self.highlighted_index] if math.isnan(dot_point[1]): - dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((nn_values or [0])[-1] / self.y_scale) + dot_point[1] = self.pos[1] + self.height / 2 + available_height / 2 * ((score_nn_values or [0])[-1] / self.score_scale) self.dot_pos = [c - self.highlight_size / 2 for c in dot_point] def update_value(self, node): diff --git a/katrain/gui/kivyutils.py b/katrain/gui/kivyutils.py index 6b1cf9b..7a40204 100644 --- a/katrain/gui/kivyutils.py +++ b/katrain/gui/kivyutils.py @@ -20,7 +20,7 @@ from kivy.uix.widget import Widget # --new from kivymd.app import MDApp -from kivymd.uix.behaviors import RectangularRippleBehavior +from kivymd.uix.behaviors import RectangularRippleBehavior, CircularRippleBehavior from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.button import BasePressedButton, BaseFlatButton from kivymd.uix.floatlayout import MDFloatLayout @@ -98,7 +98,7 @@ class AutoSizedMDFlatRectangleToggleButton(SizedMDFlatRectangleToggleButton): hor_padding = NumericProperty(3) -class TransparentIconButton(Button): +class TransparentIconButton(CircularRippleBehavior,Button): icon_size = ListProperty([25, 25]) icon = StringProperty("") @@ -179,9 +179,9 @@ class CollapsablePanel(MDBoxLayout): def build_options(self, *args, **kwargs): self.header = MDBoxLayout(height=self.options_height,size_hint_y=None, - padding=[self.options_left_padding, 0, 0, 0], spacing=2) + padding=[self.options_left_padding, 0, 0, 0], spacing=3) self.option_buttons = [] - option_labels = self.option_labels or [i18n._(opt) for opt in self.options] + option_labels = self.option_labels or [i18n._(f"tab:{opt}") for opt in self.options] for lbl, opt_col, active in zip(option_labels, self.option_colors, self.option_default_active): button = AutoSizedMDFlatRectangleToggleButton(text=lbl,color=opt_col, height=self.options_height, on_press=self.trigger_select, state="down" if active else "normal") @@ -228,7 +228,6 @@ class CollapsablePanel(MDBoxLayout): self.build() def set_state(self, state="toggle"): - print("SS",state) if state == "toggle": state = "close" if self.state == "open" else "open" self.state = state @@ -238,7 +237,7 @@ class CollapsablePanel(MDBoxLayout): def trigger_select(self, *_args): if self.state == "open": - self.on_option_state({opt:btn.state == "down" for opt,btn in zip(self.options,self.option_buttons)}) + self.dispatch("on_option_state",{opt:btn.state == "down" for opt,btn in zip(self.options,self.option_buttons)}) def on_option_state(self, options): pass diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo index 8150181..4b8d375 100644 Binary files a/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/en/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po index 23947a6..8fb09d7 100644 --- a/katrain/i18n/locales/en/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/en/LC_MESSAGES/katrain.po @@ -22,6 +22,31 @@ msgid "pass-button-text" msgstr "Pass" msgid "pass-button-tooltip" -msgstr "[space]\nPass" +msgstr "" +"[space]\n" +"Pass" + +msgid "tab:score" +msgstr "Score" + +msgid "tab:winrate" +msgstr "Win Rate" + +msgid "tab:points" +msgstr "Point Loss" + +msgid "tab:info" +msgstr "Info" + +msgid "tab:notes" +msgstr "Notes" + +msgid 'closedlabel:scoregraph' +msgstr 'Score Graph' +msgid 'closedlabel:movestats' +msgstr 'Move Stats' + +msgid 'closedlabel:info¬es' +msgstr 'Move Info & Notes' \ No newline at end of file diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo new file mode 100644 index 0000000..ccb1075 Binary files /dev/null and b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po new file mode 100644 index 0000000..aa9b05d --- /dev/null +++ b/katrain/i18n/locales/ko/LC_MESSAGES/katrain.po @@ -0,0 +1,59 @@ +# KaTrain i18n file +msgid "" +msgstr "" +"Language: Nederlands\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Hello World" +msgstr "안녕하세요 여러분" + +msgid "English" +msgstr "영어" + +msgid "Dutch" +msgstr "네덜란드어" + +msgid "pass-button-text" +msgstr "페스" + +msgid "pass-button-tooltip" +msgstr "" +"[스페이스 바]\n" +"페스" + +msgid "KataGo" +msgstr "카타고" + +#. TODO +msgid "tab:winrate" +msgstr "Win Rate" + +#. TODO +msgid "tab:info" +msgstr "Info" + +#. TODO +msgid "tab:points" +msgstr "Point Loss" + +#. TODO +msgid "tab:notes" +msgstr "Notes" + +#. TODO +msgid "closedlabel:scoregraph" +msgstr "Score Graph" + +#. TODO +msgid "closedlabel:movestats" +msgstr "Move Stats" + +#. TODO +msgid "tab:score" +msgstr "Score" + +#. TODO +msgid "closedlabel:info¬es" +msgstr "Move Info & Notes" diff --git a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo index 67a39b3..4a12adc 100644 Binary files a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo and b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.mo differ diff --git a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po index 36e20ad..19adcae 100644 --- a/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po +++ b/katrain/i18n/locales/nl/LC_MESSAGES/katrain.po @@ -19,5 +19,42 @@ msgid "pass-button-text" msgstr "Pas" msgid "pass-button-tooltip" -msgstr "[spatiebalk]\nPas" +msgstr "" +"[spatiebalk]\n" +"Pas" +#. TODO +msgid "KataGo" +msgstr "KataGo" + +#. TODO +msgid "tab:winrate" +msgstr "Win Rate" + +#. TODO +msgid "tab:points" +msgstr "Point Loss" + +#. TODO +msgid "tab:score" +msgstr "Score" + +#. TODO +msgid "tab:notes" +msgstr "Notes" + +#. TODO +msgid "tab:info" +msgstr "Info" + +#. TODO +msgid "closedlabel:scoregraph" +msgstr "Score Graph" + +#. TODO +msgid "closedlabel:info¬es" +msgstr "Move Info & Notes" + +#. TODO +msgid "closedlabel:movestats" +msgstr "Move Stats" diff --git a/katrain/img/hamburger.png b/katrain/img/hamburger.png new file mode 100644 index 0000000..0877347 Binary files /dev/null and b/katrain/img/hamburger.png differ