From c6ba96970224b346d1bde31dd8b5d67f43bb9a37 Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Sun, 31 Dec 2023 19:53:59 +0100 Subject: [PATCH 1/8] Main screen layout, just for fun https://github.com/MathNodes/meile-gui/issues/64 --- tests/v2/main_screen.py | 188 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 tests/v2/main_screen.py diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py new file mode 100644 index 00000000..2ddf0ead --- /dev/null +++ b/tests/v2/main_screen.py @@ -0,0 +1,188 @@ +from kivy.lang import Builder +from kivymd.app import MDApp +from kivy.core.window import Window +from kivy.utils import get_color_from_hex +from kivymd.uix.boxlayout import MDBoxLayout +from kivy.uix.screenmanager import ScreenManager, Screen + +from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine + +KV = """ +#:import get_color_from_hex kivy.utils.get_color_from_hex + +WindowManager: + + + adaptive_height: True + orientation: 'vertical' + + OneLineListItem: + text: "Node1" + text_color: "white" + theme_text_color: "Custom" + font_style: "Overline" + bg_color: "black" + + OneLineListItem: + text: "Node 2" + text_color: "white" + theme_text_color: "Custom" + font_style: "Overline" + bg_color: "black" + + OneLineListItem: + text: "Node 3" + text_color: "white" + theme_text_color: "Custom" + font_style: "Overline" + bg_color: "black" + +: + name: "main" + MDGridLayout: + md_bg_color: get_color_from_hex("#121212") + rows: 2 + + MDBoxLayout: + md_bg_color: get_color_from_hex("#212221") + size_hint_y: None + height: 50 + + MDLabel: + padding: 10 + text: "Meile" + font_style: "H4" + text_color: "white" + theme_text_color: "Custom" + + MDGridLayout: + cols: 2 + md_bg_color: get_color_from_hex("#212221") + + MDGridLayout: + rows: 4 + padding: 10 + size_hint_x: None + width: 250 + md_bg_color: get_color_from_hex("#060606") + align: "center" + + MDRectangleFlatIconButton: + size_hint_y: None + + text: "Connect" + text_color: "black" + icon: "lightning-bolt" + icon_color: "black" + md_bg_color: get_color_from_hex("#FCB70C") + line_color: 0, 0, 0, 0 + font_size: "16sp" + size_hint: 1, 0 + + MDTextField: + icon_left: "magnify" + line_color_normal: get_color_from_hex("#FCB70C") + line_color_focus: get_color_from_hex("#FCB70C") + icon_left_color_normal: get_color_from_hex("#FCB70C") + icon_left_color_focus: get_color_from_hex("#FCB70C") + text_color_normal: get_color_from_hex("#FCB70C") + text_color_focus: get_color_from_hex("#FCB70C") + + MDScrollView: + MDList: + id: countries_list + spacing: 3 + padding: 10 + + MDBoxLayout: + size_hint_y: None + height: 50 + + MDIconButton: + icon: "wallet" + theme_text_color: "Custom" + text_color: "white" + + MDIconButton: + icon: "cog" + theme_text_color: "Custom" + text_color: "white" + + MDIconButton: + icon: "help-circle" + theme_text_color: "Custom" + text_color: "white" + + + + MDFloatLayout: + orientation: "horizontal" + md_bg_color: get_color_from_hex("#131313") +""" + +class WindowManager(ScreenManager): + pass + + +class Content(MDBoxLayout): + pass + + +class MainScreen(Screen): + def __init__(self, **kwargs): + super().__init__() + self.build() + + def build(self): + import random + countries = ["France", "Italy", "Brasil", "Egypt", "Belgium", "Deutschland", "Canada"] + for _ in range(0, 100): + country = random.choice(countries) + + # item = TwoLineAvatarListItem( + # radius = [10, 10, 10, 10], + # bg_color = get_color_from_hex("#212221"), + # text = country, + # text_color = "white", + # theme_text_color = "Custom", + # font_style = "Subtitle1", + # secondary_text = f"{random.randint(1, 100)} servers", + # secondary_text_color = "white", + # secondary_theme_text_color = "Custom", + # secondary_font_style = "Caption", + # ) + # item.add_widget(ImageLeftWidget(source=f"../../src/imgs/{country[:2].lower()}.png")) + + item = MDExpansionPanel( + icon=f"../../src/imgs/{country[:2].lower()}.png", + content=Content(), + panel_cls=MDExpansionPanelTwoLine( + radius = [10, 10, 10, 10], + bg_color = get_color_from_hex("#212221"), + text = country, + text_color = "white", + theme_text_color = "Custom", + font_style = "Subtitle1", + secondary_text = f"{random.randint(1, 100)} servers", + secondary_text_color = "white", + secondary_theme_text_color = "Custom", + secondary_font_style = "Caption", + ) + ) + self.ids.countries_list.add_widget(item) + + + +Builder.load_string(KV) +class Test(MDApp): + title = "MainScreen v2" + + def build(self): + Window.size = (1280,720) + + manager = WindowManager() + manager.add_widget(MainScreen()) + return manager + +if __name__ == "__main__": + Test().run() \ No newline at end of file From 00686f6e95ba188a51e85a394c8a2e95be59e0ea Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Thu, 4 Jan 2024 13:17:19 +0100 Subject: [PATCH 2/8] Custom MDExpansionPanelRoundIcon and MDExpansionPanelTwoLineSmall (round icon with small size) --- tests/v2/main_screen.py | 271 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 267 insertions(+), 4 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index 2ddf0ead..a6ee161e 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -5,7 +5,37 @@ from kivymd.uix.boxlayout import MDBoxLayout from kivy.uix.screenmanager import ScreenManager, Screen -from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelTwoLine +from kivymd.uix.expansionpanel import MDExpansionPanelOneLine, MDExpansionPanelThreeLine, MDExpansionPanelLabel + +from kivymd.uix.behaviors import RoundedRectangularElevationBehavior, CommonElevationBehavior, RectangularRippleBehavior, CircularRippleBehavior +from kivy.uix.behaviors import ButtonBehavior +from kivymd.uix.fitimage.fitimage import FitImage + +import os +from typing import Union + +from kivy.animation import Animation +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.metrics import dp +from kivy.properties import NumericProperty, ObjectProperty, StringProperty +from kivy.uix.relativelayout import RelativeLayout +from kivy.uix.widget import WidgetException + +import kivymd.material_resources as m_res +from kivymd import uix_path +from kivymd.icon_definitions import md_icons +from kivymd.uix.button import MDIconButton +from kivymd.uix.list import ( + IconLeftWidget, + ImageLeftWidget, + IRightBodyTouch, + OneLineAvatarIconListItem, + ThreeLineAvatarIconListItem, + TwoLineAvatarIconListItem, + TwoLineListItem, +) + KV = """ #:import get_color_from_hex kivy.utils.get_color_from_hex @@ -118,6 +148,28 @@ MDFloatLayout: orientation: "horizontal" md_bg_color: get_color_from_hex("#131313") + +: + icon: "chevron-down" + theme_text_color: "Custom" + text_color: "white" + + disabled: True + md_bg_color_disabled: 0, 0, 0, 0 + + canvas.before: + PushMatrix + Rotate: + angle: self._angle + axis: (0, 0, 1) + origin: self.center + canvas.after: + PopMatrix + + + + size_hint_y: None + # height: dp(68) """ class WindowManager(ScreenManager): @@ -127,6 +179,217 @@ class WindowManager(ScreenManager): class Content(MDBoxLayout): pass +class MDExpansionChevronRight(IRightBodyTouch, MDIconButton): + _angle = NumericProperty(0) + +class DisplayPic(CommonElevationBehavior, FitImage): + pass + +class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): + """ + Two-line panel. + + For more information, see in the + :class:`~kivymd.uix.list.TwoLineAvatarIconListItem` class documentation. + """ + + _txt_top_pad = NumericProperty("20dp") + _txt_bot_pad = NumericProperty("6dp") + _txt_left_pad = NumericProperty("50dp") + _height = NumericProperty("50dp") + _num_lines = 2 + +# https://raw.githubusercontent.com/kivymd/KivyMD/master/kivymd/uix/expansionpanel/expansionpanel.py +class MDExpansionPanelRoundIcon(RelativeLayout): + content = ObjectProperty() + icon = StringProperty() + #TODO: icon size(?) + opening_transition = StringProperty("out_cubic") + opening_time = NumericProperty(0.2) + closing_transition = StringProperty("out_sine") + closing_time = NumericProperty(0.2) + panel_cls = ObjectProperty() + + _state = StringProperty("close") + _anim_playing = False + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.register_event_type("on_open") + self.register_event_type("on_close") + + if self.panel_cls and isinstance( + self.panel_cls, + ( + MDExpansionPanelOneLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ), + ): + self.panel_cls.pos_hint = {"top": 1} + + self.panel_cls._no_ripple_effect = True + self.panel_cls.bind( + on_release=lambda x: self.check_open_panel(self.panel_cls) + ) + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + self.chevron = MDExpansionChevronRight() + self.panel_cls.add_widget(self.chevron) + if self.icon: + if self.icon in md_icons.keys(): + self.panel_cls.add_widget( + IconLeftWidget( + icon=self.icon, + pos_hint={"center_y": 0.5}, + ) + ) + else: + # self.panel_cls.add_widget(ImageLeftWidget(source=self.icon, pos_hint={"center_y": 0.5})) + self.panel_cls.add_widget(DisplayPic( + source=self.icon, + elevation=dp(3), + size_hint=(None, None), + size=(dp(30), dp(30)), + radius=dp(360), + pos_hint={'center_x': .12, 'center_y': .5} + )) + else: + self.panel_cls.remove_widget( + self.panel_cls.ids._left_container + ) + self.panel_cls._txt_left_pad = 0 + else: + # if no icon + self.panel_cls._txt_left_pad = m_res.HORIZ_MARGINS + self.add_widget(self.panel_cls) + else: + raise ValueError( + "KivyMD: `panel_cls` object must be must be one of the " + "objects from the list\n" + "[MDExpansionPanelOneLine, MDExpansionPanelTwoLineSmall, " + "MDExpansionPanelThreeLine]" + ) + + def on_open(self, *args): + """Called when a panel is opened.""" + + def on_close(self, *args): + """Called when a panel is closed.""" + + def check_open_panel( + self, + instance_panel: [ + MDExpansionPanelThreeLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ], + ) -> None: + """ + Called when you click on the panel. Called methods to open or close + a panel. + """ + + press_current_panel = False + for panel in self.parent.children: + if isinstance(panel, MDExpansionPanelRoundIcon): + if len(panel.children) == 2: + if instance_panel is panel.children[1]: + press_current_panel = True + panel.remove_widget(panel.children[0]) + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + chevron = panel.children[0].children[1].children[0] # Fix [0/1] + self.set_chevron_up(chevron) + self.close_panel(panel, press_current_panel) + self.dispatch("on_close") + break + if not press_current_panel: + self.set_chevron_down() + + def set_chevron_down(self) -> None: + """Sets the chevron down.""" + + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + Animation(_angle=-90, d=self.opening_time).start(self.chevron) + self.open_panel() + self.dispatch("on_open") + + def set_chevron_up(self, instance_chevron: MDExpansionChevronRight) -> None: + """Sets the chevron up.""" + + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + Animation(_angle=0, d=self.closing_time).start(instance_chevron) + + def close_panel( + self, instance_expansion_panel, press_current_panel: bool + ) -> None: + """Method closes the panel.""" + + if self._anim_playing: + return + + if press_current_panel: + self._anim_playing = True + + self._state = "close" + + anim = Animation( + height=self.panel_cls.height, + d=self.closing_time, + t=self.closing_transition, + ) + anim.bind(on_complete=self._disable_anim) + anim.start(instance_expansion_panel) + + def open_panel(self, *args) -> None: + """Method opens a panel.""" + + if self._anim_playing: + return + + self._anim_playing = True + self._state = "open" + + anim = Animation( + height=self.content.height + self.height, + d=self.opening_time, + t=self.opening_transition, + ) + anim.bind(on_complete=self._add_content) + anim.bind(on_complete=self._disable_anim) + anim.start(self) + + def get_state(self) -> str: + """Returns the state of panel. Can be `close` or `open` .""" + + return self._state + + def add_widget(self, widget, index=0, canvas=None): + if isinstance( + widget, + ( + MDExpansionPanelOneLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ), + ): + self.height = widget.height + return super().add_widget(widget) + + def _disable_anim(self, *args): + self._anim_playing = False + + def _add_content(self, *args): + if self.content: + try: + if isinstance(self.panel_cls, MDExpansionPanelLabel): + self.content.y = dp(36) + self.add_widget(self.content) + except WidgetException: + pass + class MainScreen(Screen): def __init__(self, **kwargs): @@ -136,7 +399,7 @@ def __init__(self, **kwargs): def build(self): import random countries = ["France", "Italy", "Brasil", "Egypt", "Belgium", "Deutschland", "Canada"] - for _ in range(0, 100): + for _ in range(0, 10): country = random.choice(countries) # item = TwoLineAvatarListItem( @@ -153,10 +416,10 @@ def build(self): # ) # item.add_widget(ImageLeftWidget(source=f"../../src/imgs/{country[:2].lower()}.png")) - item = MDExpansionPanel( + item = MDExpansionPanelRoundIcon( icon=f"../../src/imgs/{country[:2].lower()}.png", content=Content(), - panel_cls=MDExpansionPanelTwoLine( + panel_cls=MDExpansionPanelTwoLineSmall( radius = [10, 10, 10, 10], bg_color = get_color_from_hex("#212221"), text = country, From 8dde9a832a9557fa2ce16ae21c451244f0814e4b Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Fri, 5 Jan 2024 17:04:03 +0100 Subject: [PATCH 3/8] MDExpansionPanelRoundIcon and MDExpansionPanelTwoLineSmall, to separate file --- tests/v2/main_screen.py | 233 +----------------------------- tests/v2/uix/__init__.py | 0 tests/v2/uix/expansionpanel.py | 253 +++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 231 deletions(-) create mode 100644 tests/v2/uix/__init__.py create mode 100644 tests/v2/uix/expansionpanel.py diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index a6ee161e..fe1c86d0 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -37,6 +37,8 @@ ) +from uix.expansionpanel import MDExpansionPanelRoundIcon, MDExpansionPanelTwoLineSmall + KV = """ #:import get_color_from_hex kivy.utils.get_color_from_hex @@ -149,27 +151,7 @@ orientation: "horizontal" md_bg_color: get_color_from_hex("#131313") -: - icon: "chevron-down" - theme_text_color: "Custom" - text_color: "white" - - disabled: True - md_bg_color_disabled: 0, 0, 0, 0 - - canvas.before: - PushMatrix - Rotate: - angle: self._angle - axis: (0, 0, 1) - origin: self.center - canvas.after: - PopMatrix - - - size_hint_y: None - # height: dp(68) """ class WindowManager(ScreenManager): @@ -179,217 +161,6 @@ class WindowManager(ScreenManager): class Content(MDBoxLayout): pass -class MDExpansionChevronRight(IRightBodyTouch, MDIconButton): - _angle = NumericProperty(0) - -class DisplayPic(CommonElevationBehavior, FitImage): - pass - -class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): - """ - Two-line panel. - - For more information, see in the - :class:`~kivymd.uix.list.TwoLineAvatarIconListItem` class documentation. - """ - - _txt_top_pad = NumericProperty("20dp") - _txt_bot_pad = NumericProperty("6dp") - _txt_left_pad = NumericProperty("50dp") - _height = NumericProperty("50dp") - _num_lines = 2 - -# https://raw.githubusercontent.com/kivymd/KivyMD/master/kivymd/uix/expansionpanel/expansionpanel.py -class MDExpansionPanelRoundIcon(RelativeLayout): - content = ObjectProperty() - icon = StringProperty() - #TODO: icon size(?) - opening_transition = StringProperty("out_cubic") - opening_time = NumericProperty(0.2) - closing_transition = StringProperty("out_sine") - closing_time = NumericProperty(0.2) - panel_cls = ObjectProperty() - - _state = StringProperty("close") - _anim_playing = False - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.register_event_type("on_open") - self.register_event_type("on_close") - - if self.panel_cls and isinstance( - self.panel_cls, - ( - MDExpansionPanelOneLine, - MDExpansionPanelTwoLineSmall, - MDExpansionPanelThreeLine, - MDExpansionPanelLabel, - ), - ): - self.panel_cls.pos_hint = {"top": 1} - - self.panel_cls._no_ripple_effect = True - self.panel_cls.bind( - on_release=lambda x: self.check_open_panel(self.panel_cls) - ) - if not isinstance(self.panel_cls, MDExpansionPanelLabel): - self.chevron = MDExpansionChevronRight() - self.panel_cls.add_widget(self.chevron) - if self.icon: - if self.icon in md_icons.keys(): - self.panel_cls.add_widget( - IconLeftWidget( - icon=self.icon, - pos_hint={"center_y": 0.5}, - ) - ) - else: - # self.panel_cls.add_widget(ImageLeftWidget(source=self.icon, pos_hint={"center_y": 0.5})) - self.panel_cls.add_widget(DisplayPic( - source=self.icon, - elevation=dp(3), - size_hint=(None, None), - size=(dp(30), dp(30)), - radius=dp(360), - pos_hint={'center_x': .12, 'center_y': .5} - )) - else: - self.panel_cls.remove_widget( - self.panel_cls.ids._left_container - ) - self.panel_cls._txt_left_pad = 0 - else: - # if no icon - self.panel_cls._txt_left_pad = m_res.HORIZ_MARGINS - self.add_widget(self.panel_cls) - else: - raise ValueError( - "KivyMD: `panel_cls` object must be must be one of the " - "objects from the list\n" - "[MDExpansionPanelOneLine, MDExpansionPanelTwoLineSmall, " - "MDExpansionPanelThreeLine]" - ) - - def on_open(self, *args): - """Called when a panel is opened.""" - - def on_close(self, *args): - """Called when a panel is closed.""" - - def check_open_panel( - self, - instance_panel: [ - MDExpansionPanelThreeLine, - MDExpansionPanelTwoLineSmall, - MDExpansionPanelThreeLine, - MDExpansionPanelLabel, - ], - ) -> None: - """ - Called when you click on the panel. Called methods to open or close - a panel. - """ - - press_current_panel = False - for panel in self.parent.children: - if isinstance(panel, MDExpansionPanelRoundIcon): - if len(panel.children) == 2: - if instance_panel is panel.children[1]: - press_current_panel = True - panel.remove_widget(panel.children[0]) - if not isinstance(self.panel_cls, MDExpansionPanelLabel): - chevron = panel.children[0].children[1].children[0] # Fix [0/1] - self.set_chevron_up(chevron) - self.close_panel(panel, press_current_panel) - self.dispatch("on_close") - break - if not press_current_panel: - self.set_chevron_down() - - def set_chevron_down(self) -> None: - """Sets the chevron down.""" - - if not isinstance(self.panel_cls, MDExpansionPanelLabel): - Animation(_angle=-90, d=self.opening_time).start(self.chevron) - self.open_panel() - self.dispatch("on_open") - - def set_chevron_up(self, instance_chevron: MDExpansionChevronRight) -> None: - """Sets the chevron up.""" - - if not isinstance(self.panel_cls, MDExpansionPanelLabel): - Animation(_angle=0, d=self.closing_time).start(instance_chevron) - - def close_panel( - self, instance_expansion_panel, press_current_panel: bool - ) -> None: - """Method closes the panel.""" - - if self._anim_playing: - return - - if press_current_panel: - self._anim_playing = True - - self._state = "close" - - anim = Animation( - height=self.panel_cls.height, - d=self.closing_time, - t=self.closing_transition, - ) - anim.bind(on_complete=self._disable_anim) - anim.start(instance_expansion_panel) - - def open_panel(self, *args) -> None: - """Method opens a panel.""" - - if self._anim_playing: - return - - self._anim_playing = True - self._state = "open" - - anim = Animation( - height=self.content.height + self.height, - d=self.opening_time, - t=self.opening_transition, - ) - anim.bind(on_complete=self._add_content) - anim.bind(on_complete=self._disable_anim) - anim.start(self) - - def get_state(self) -> str: - """Returns the state of panel. Can be `close` or `open` .""" - - return self._state - - def add_widget(self, widget, index=0, canvas=None): - if isinstance( - widget, - ( - MDExpansionPanelOneLine, - MDExpansionPanelTwoLineSmall, - MDExpansionPanelThreeLine, - MDExpansionPanelLabel, - ), - ): - self.height = widget.height - return super().add_widget(widget) - - def _disable_anim(self, *args): - self._anim_playing = False - - def _add_content(self, *args): - if self.content: - try: - if isinstance(self.panel_cls, MDExpansionPanelLabel): - self.content.y = dp(36) - self.add_widget(self.content) - except WidgetException: - pass - class MainScreen(Screen): def __init__(self, **kwargs): diff --git a/tests/v2/uix/__init__.py b/tests/v2/uix/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/v2/uix/expansionpanel.py b/tests/v2/uix/expansionpanel.py new file mode 100644 index 00000000..52beac5b --- /dev/null +++ b/tests/v2/uix/expansionpanel.py @@ -0,0 +1,253 @@ +# https://raw.githubusercontent.com/kivymd/KivyMD/master/kivymd/uix/expansionpanel/expansionpanel.py + + +import os +from typing import Union + +from kivy.animation import Animation +from kivy.clock import Clock +from kivy.lang import Builder +from kivy.metrics import dp +from kivy.properties import NumericProperty, ObjectProperty, StringProperty +from kivy.uix.relativelayout import RelativeLayout +from kivy.uix.widget import WidgetException + +import kivymd.material_resources as m_res +from kivymd import uix_path +from kivymd.icon_definitions import md_icons +from kivymd.uix.button import MDIconButton +from kivymd.uix.list import ( + IconLeftWidget, + ImageLeftWidget, + IRightBodyTouch, + OneLineAvatarIconListItem, + ThreeLineAvatarIconListItem, + TwoLineAvatarIconListItem, + TwoLineListItem, +) + +from kivymd.uix.expansionpanel import MDExpansionPanelOneLine, MDExpansionPanelThreeLine, MDExpansionPanelLabel + +from kivymd.uix.behaviors import RoundedRectangularElevationBehavior, CommonElevationBehavior, RectangularRippleBehavior, CircularRippleBehavior +from kivy.uix.behaviors import ButtonBehavior +from kivymd.uix.fitimage.fitimage import FitImage + + +KV = """ + size_hint_y: None + # height: dp(68) +""" +Builder.load_string(KV) + +class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): + """ + Two-line panel. + + For more information, see in the + :class:`~kivymd.uix.list.TwoLineAvatarIconListItem` class documentation. + """ + + _txt_top_pad = NumericProperty("20dp") + _txt_bot_pad = NumericProperty("6dp") + _txt_left_pad = NumericProperty("50dp") + _height = NumericProperty("50dp") + _num_lines = 2 + +class DisplayPic(CommonElevationBehavior, FitImage): + pass + + +class MDExpansionChevronRight(IRightBodyTouch, MDIconButton): + _angle = NumericProperty(0) + + + +class MDExpansionPanelRoundIcon(RelativeLayout): + content = ObjectProperty() + icon = StringProperty() + #TODO: icon size(?) + opening_transition = StringProperty("out_cubic") + opening_time = NumericProperty(0.2) + closing_transition = StringProperty("out_sine") + closing_time = NumericProperty(0.2) + panel_cls = ObjectProperty() + + _state = StringProperty("close") + _anim_playing = False + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.register_event_type("on_open") + self.register_event_type("on_close") + + if self.panel_cls and isinstance( + self.panel_cls, + ( + MDExpansionPanelOneLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ), + ): + self.panel_cls.pos_hint = {"top": 1} + + self.panel_cls._no_ripple_effect = True + self.panel_cls.bind( + on_release=lambda x: self.check_open_panel(self.panel_cls) + ) + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + self.chevron = MDExpansionChevronRight() + self.panel_cls.add_widget(self.chevron) + if self.icon: + if self.icon in md_icons.keys(): + self.panel_cls.add_widget( + IconLeftWidget( + icon=self.icon, + pos_hint={"center_y": 0.5}, + ) + ) + else: + # self.panel_cls.add_widget(ImageLeftWidget(source=self.icon, pos_hint={"center_y": 0.5})) + self.panel_cls.add_widget(DisplayPic( + source=self.icon, + elevation=dp(3), + size_hint=(None, None), + size=(dp(30), dp(30)), + radius=dp(360), + pos_hint={'center_x': .12, 'center_y': .5} + )) + else: + self.panel_cls.remove_widget( + self.panel_cls.ids._left_container + ) + self.panel_cls._txt_left_pad = 0 + else: + # if no icon + self.panel_cls._txt_left_pad = m_res.HORIZ_MARGINS + self.add_widget(self.panel_cls) + else: + raise ValueError( + "KivyMD: `panel_cls` object must be must be one of the " + "objects from the list\n" + "[MDExpansionPanelOneLine, MDExpansionPanelTwoLineSmall, " + "MDExpansionPanelThreeLine]" + ) + + def on_open(self, *args): + """Called when a panel is opened.""" + + def on_close(self, *args): + """Called when a panel is closed.""" + + def check_open_panel( + self, + instance_panel: [ + MDExpansionPanelThreeLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ], + ) -> None: + """ + Called when you click on the panel. Called methods to open or close + a panel. + """ + + press_current_panel = False + for panel in self.parent.children: + if isinstance(panel, MDExpansionPanelRoundIcon): + if len(panel.children) == 2: + if instance_panel is panel.children[1]: + press_current_panel = True + panel.remove_widget(panel.children[0]) + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + chevron = panel.children[0].children[1].children[0] # Fix [0/1] + self.set_chevron_up(chevron) + self.close_panel(panel, press_current_panel) + self.dispatch("on_close") + break + if not press_current_panel: + self.set_chevron_down() + + def set_chevron_down(self) -> None: + """Sets the chevron down.""" + + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + Animation(_angle=-90, d=self.opening_time).start(self.chevron) + self.open_panel() + self.dispatch("on_open") + + def set_chevron_up(self, instance_chevron: MDExpansionChevronRight) -> None: + """Sets the chevron up.""" + + if not isinstance(self.panel_cls, MDExpansionPanelLabel): + Animation(_angle=0, d=self.closing_time).start(instance_chevron) + + def close_panel( + self, instance_expansion_panel, press_current_panel: bool + ) -> None: + """Method closes the panel.""" + + if self._anim_playing: + return + + if press_current_panel: + self._anim_playing = True + + self._state = "close" + + anim = Animation( + height=self.panel_cls.height, + d=self.closing_time, + t=self.closing_transition, + ) + anim.bind(on_complete=self._disable_anim) + anim.start(instance_expansion_panel) + + def open_panel(self, *args) -> None: + """Method opens a panel.""" + + if self._anim_playing: + return + + self._anim_playing = True + self._state = "open" + + anim = Animation( + height=self.content.height + self.height, + d=self.opening_time, + t=self.opening_transition, + ) + anim.bind(on_complete=self._add_content) + anim.bind(on_complete=self._disable_anim) + anim.start(self) + + def get_state(self) -> str: + """Returns the state of panel. Can be `close` or `open` .""" + + return self._state + + def add_widget(self, widget, index=0, canvas=None): + if isinstance( + widget, + ( + MDExpansionPanelOneLine, + MDExpansionPanelTwoLineSmall, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, + ), + ): + self.height = widget.height + return super().add_widget(widget) + + def _disable_anim(self, *args): + self._anim_playing = False + + def _add_content(self, *args): + if self.content: + try: + if isinstance(self.panel_cls, MDExpansionPanelLabel): + self.content.y = dp(36) + self.add_widget(self.content) + except WidgetException: + pass From 271ae9e3598e65f01deb0ace465c0fe1f3d2a120 Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Fri, 5 Jan 2024 17:11:17 +0100 Subject: [PATCH 4/8] Clear code, remove unused import, PEP8 Black --- tests/v2/main_screen.py | 71 ++++++++++++++-------------------- tests/v2/uix/expansionpanel.py | 49 ++++++++++------------- 2 files changed, 50 insertions(+), 70 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index fe1c86d0..eee8017e 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -5,38 +5,13 @@ from kivymd.uix.boxlayout import MDBoxLayout from kivy.uix.screenmanager import ScreenManager, Screen -from kivymd.uix.expansionpanel import MDExpansionPanelOneLine, MDExpansionPanelThreeLine, MDExpansionPanelLabel -from kivymd.uix.behaviors import RoundedRectangularElevationBehavior, CommonElevationBehavior, RectangularRippleBehavior, CircularRippleBehavior -from kivy.uix.behaviors import ButtonBehavior -from kivymd.uix.fitimage.fitimage import FitImage - -import os -from typing import Union - -from kivy.animation import Animation -from kivy.clock import Clock from kivy.lang import Builder from kivy.metrics import dp -from kivy.properties import NumericProperty, ObjectProperty, StringProperty -from kivy.uix.relativelayout import RelativeLayout -from kivy.uix.widget import WidgetException - -import kivymd.material_resources as m_res -from kivymd import uix_path -from kivymd.icon_definitions import md_icons -from kivymd.uix.button import MDIconButton -from kivymd.uix.list import ( - IconLeftWidget, - ImageLeftWidget, - IRightBodyTouch, - OneLineAvatarIconListItem, - ThreeLineAvatarIconListItem, - TwoLineAvatarIconListItem, - TwoLineListItem, -) +from kivymd.uix.list import ImageLeftWidget +# meil uix from tests from uix.expansionpanel import MDExpansionPanelRoundIcon, MDExpansionPanelTwoLineSmall KV = """ @@ -154,6 +129,7 @@ """ + class WindowManager(ScreenManager): pass @@ -169,7 +145,16 @@ def __init__(self, **kwargs): def build(self): import random - countries = ["France", "Italy", "Brasil", "Egypt", "Belgium", "Deutschland", "Canada"] + + countries = [ + "France", + "Italy", + "Brasil", + "Egypt", + "Belgium", + "Deutschland", + "Canada", + ] for _ in range(0, 10): country = random.choice(countries) @@ -191,32 +176,34 @@ def build(self): icon=f"../../src/imgs/{country[:2].lower()}.png", content=Content(), panel_cls=MDExpansionPanelTwoLineSmall( - radius = [10, 10, 10, 10], - bg_color = get_color_from_hex("#212221"), - text = country, - text_color = "white", - theme_text_color = "Custom", - font_style = "Subtitle1", - secondary_text = f"{random.randint(1, 100)} servers", - secondary_text_color = "white", - secondary_theme_text_color = "Custom", - secondary_font_style = "Caption", - ) + radius=[10, 10, 10, 10], + bg_color=get_color_from_hex("#212221"), + text=country, + text_color="white", + theme_text_color="Custom", + font_style="Subtitle1", + secondary_text=f"{random.randint(1, 100)} servers", + secondary_text_color="white", + secondary_theme_text_color="Custom", + secondary_font_style="Caption", + ), ) self.ids.countries_list.add_widget(item) - Builder.load_string(KV) + + class Test(MDApp): title = "MainScreen v2" def build(self): - Window.size = (1280,720) + Window.size = (1280, 720) manager = WindowManager() manager.add_widget(MainScreen()) return manager + if __name__ == "__main__": - Test().run() \ No newline at end of file + Test().run() diff --git a/tests/v2/uix/expansionpanel.py b/tests/v2/uix/expansionpanel.py index 52beac5b..79214f75 100644 --- a/tests/v2/uix/expansionpanel.py +++ b/tests/v2/uix/expansionpanel.py @@ -1,11 +1,8 @@ # https://raw.githubusercontent.com/kivymd/KivyMD/master/kivymd/uix/expansionpanel/expansionpanel.py -import os -from typing import Union from kivy.animation import Animation -from kivy.clock import Clock from kivy.lang import Builder from kivy.metrics import dp from kivy.properties import NumericProperty, ObjectProperty, StringProperty @@ -13,23 +10,20 @@ from kivy.uix.widget import WidgetException import kivymd.material_resources as m_res -from kivymd import uix_path from kivymd.icon_definitions import md_icons from kivymd.uix.button import MDIconButton from kivymd.uix.list import ( - IconLeftWidget, - ImageLeftWidget, IRightBodyTouch, - OneLineAvatarIconListItem, - ThreeLineAvatarIconListItem, TwoLineAvatarIconListItem, - TwoLineListItem, ) -from kivymd.uix.expansionpanel import MDExpansionPanelOneLine, MDExpansionPanelThreeLine, MDExpansionPanelLabel +from kivymd.uix.expansionpanel import ( + MDExpansionPanelOneLine, + MDExpansionPanelThreeLine, + MDExpansionPanelLabel, +) -from kivymd.uix.behaviors import RoundedRectangularElevationBehavior, CommonElevationBehavior, RectangularRippleBehavior, CircularRippleBehavior -from kivy.uix.behaviors import ButtonBehavior +from kivymd.uix.behaviors import CommonElevationBehavior from kivymd.uix.fitimage.fitimage import FitImage @@ -39,6 +33,7 @@ """ Builder.load_string(KV) + class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): """ Two-line panel. @@ -53,6 +48,7 @@ class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): _height = NumericProperty("50dp") _num_lines = 2 + class DisplayPic(CommonElevationBehavior, FitImage): pass @@ -61,11 +57,10 @@ class MDExpansionChevronRight(IRightBodyTouch, MDIconButton): _angle = NumericProperty(0) - class MDExpansionPanelRoundIcon(RelativeLayout): content = ObjectProperty() icon = StringProperty() - #TODO: icon size(?) + # TODO: icon size(?) opening_transition = StringProperty("out_cubic") opening_time = NumericProperty(0.2) closing_transition = StringProperty("out_sine") @@ -108,18 +103,18 @@ def __init__(self, **kwargs): ) else: # self.panel_cls.add_widget(ImageLeftWidget(source=self.icon, pos_hint={"center_y": 0.5})) - self.panel_cls.add_widget(DisplayPic( - source=self.icon, - elevation=dp(3), - size_hint=(None, None), - size=(dp(30), dp(30)), - radius=dp(360), - pos_hint={'center_x': .12, 'center_y': .5} - )) + self.panel_cls.add_widget( + DisplayPic( + source=self.icon, + elevation=dp(3), + size_hint=(None, None), + size=(dp(30), dp(30)), + radius=dp(360), + pos_hint={"center_x": 0.12, "center_y": 0.5}, + ) + ) else: - self.panel_cls.remove_widget( - self.panel_cls.ids._left_container - ) + self.panel_cls.remove_widget(self.panel_cls.ids._left_container) self.panel_cls._txt_left_pad = 0 else: # if no icon @@ -183,9 +178,7 @@ def set_chevron_up(self, instance_chevron: MDExpansionChevronRight) -> None: if not isinstance(self.panel_cls, MDExpansionPanelLabel): Animation(_angle=0, d=self.closing_time).start(instance_chevron) - def close_panel( - self, instance_expansion_panel, press_current_panel: bool - ) -> None: + def close_panel(self, instance_expansion_panel, press_current_panel: bool) -> None: """Method closes the panel.""" if self._anim_playing: From 58081546308ca3fdbbc77b04101115870b5673fa Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Fri, 5 Jan 2024 17:49:38 +0100 Subject: [PATCH 5/8] white MDExpansionChevronRight --- tests/v2/main_screen.py | 1 + tests/v2/uix/expansionpanel.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index eee8017e..eff859da 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -174,6 +174,7 @@ def build(self): item = MDExpansionPanelRoundIcon( icon=f"../../src/imgs/{country[:2].lower()}.png", + icon_size=(25, 25), content=Content(), panel_cls=MDExpansionPanelTwoLineSmall( radius=[10, 10, 10, 10], diff --git a/tests/v2/uix/expansionpanel.py b/tests/v2/uix/expansionpanel.py index 79214f75..bf4a4e82 100644 --- a/tests/v2/uix/expansionpanel.py +++ b/tests/v2/uix/expansionpanel.py @@ -5,7 +5,7 @@ from kivy.animation import Animation from kivy.lang import Builder from kivy.metrics import dp -from kivy.properties import NumericProperty, ObjectProperty, StringProperty +from kivy.properties import NumericProperty, ObjectProperty, StringProperty, ListProperty from kivy.uix.relativelayout import RelativeLayout from kivy.uix.widget import WidgetException @@ -15,6 +15,7 @@ from kivymd.uix.list import ( IRightBodyTouch, TwoLineAvatarIconListItem, + IconLeftWidget ) from kivymd.uix.expansionpanel import ( @@ -27,7 +28,8 @@ from kivymd.uix.fitimage.fitimage import FitImage -KV = """ +KV = """ + size_hint_y: None # height: dp(68) """ @@ -42,7 +44,7 @@ class MDExpansionPanelTwoLineSmall(TwoLineAvatarIconListItem): :class:`~kivymd.uix.list.TwoLineAvatarIconListItem` class documentation. """ - _txt_top_pad = NumericProperty("20dp") + # _txt_top_pad = NumericProperty("20dp") _txt_bot_pad = NumericProperty("6dp") _txt_left_pad = NumericProperty("50dp") _height = NumericProperty("50dp") @@ -60,7 +62,7 @@ class MDExpansionChevronRight(IRightBodyTouch, MDIconButton): class MDExpansionPanelRoundIcon(RelativeLayout): content = ObjectProperty() icon = StringProperty() - # TODO: icon size(?) + icon_size = ListProperty((25, 25)) opening_transition = StringProperty("out_cubic") opening_time = NumericProperty(0.2) closing_transition = StringProperty("out_sine") @@ -91,7 +93,12 @@ def __init__(self, **kwargs): on_release=lambda x: self.check_open_panel(self.panel_cls) ) if not isinstance(self.panel_cls, MDExpansionPanelLabel): - self.chevron = MDExpansionChevronRight() + self.chevron = MDExpansionChevronRight( + icon_color="white", + theme_icon_color="Custom", + md_bg_color_disabled="white", + disabled=False + ) self.panel_cls.add_widget(self.chevron) if self.icon: if self.icon in md_icons.keys(): @@ -108,7 +115,7 @@ def __init__(self, **kwargs): source=self.icon, elevation=dp(3), size_hint=(None, None), - size=(dp(30), dp(30)), + size=self.icon_size, radius=dp(360), pos_hint={"center_x": 0.12, "center_y": 0.5}, ) From 2a20868f8b10c9f01c4e41579b8f0305f8000364 Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Fri, 5 Jan 2024 18:16:36 +0100 Subject: [PATCH 6/8] organge border for bottom toolbar, outline icons --- tests/v2/main_screen.py | 29 ++++++++++++++++++++++++++--- tests/v2/uix/expansionpanel.py | 3 +++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index eff859da..168ce0fe 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -102,21 +102,44 @@ padding: 10 MDBoxLayout: + orientation: 'horizontal' + # padding: [20, 0, 0, 0] size_hint_y: None height: 50 + spacing: 10 + + canvas: + # draw a background of red. This will be the border + Color: + rgba: get_color_from_hex("#453103") + RoundedRectangle: + pos: self.pos + size: self.size + + # draw over the above except for 1 pixels around edges, leaving the orange border showing + Color: + rgba: get_color_from_hex("#212221") + RoundedRectangle: + pos: self.x+1, self.y+1 + size: self.width-2, self.height-2 MDIconButton: - icon: "wallet" + icon: "wallet-outline" theme_text_color: "Custom" text_color: "white" MDIconButton: - icon: "cog" + icon: "book-open-outline" theme_text_color: "Custom" text_color: "white" MDIconButton: - icon: "help-circle" + icon: "cog-outline" + theme_text_color: "Custom" + text_color: "white" + + MDIconButton: + icon: "help-circle-outline" theme_text_color: "Custom" text_color: "white" diff --git a/tests/v2/uix/expansionpanel.py b/tests/v2/uix/expansionpanel.py index bf4a4e82..2c6ac8d3 100644 --- a/tests/v2/uix/expansionpanel.py +++ b/tests/v2/uix/expansionpanel.py @@ -99,7 +99,10 @@ def __init__(self, **kwargs): md_bg_color_disabled="white", disabled=False ) + self.chevron.ripple_scale = 0 + self.chevron._no_ripple_effect = True self.panel_cls.add_widget(self.chevron) + if self.icon: if self.icon in md_icons.keys(): self.panel_cls.add_widget( From 3f89598151660105075d7634791c1d0968fdd485 Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Sun, 7 Jan 2024 22:50:49 +0100 Subject: [PATCH 7/8] Just copy the example of MDDataTable (https://kivymd.readthedocs.io/en/1.1.1/components/datatables/index.html) --- tests/v2/main_screen.py | 128 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index 168ce0fe..672bc878 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -11,6 +11,8 @@ from kivymd.uix.list import ImageLeftWidget +from kivymd.uix.datatables import MDDataTable + # meil uix from tests from uix.expansionpanel import MDExpansionPanelRoundIcon, MDExpansionPanelTwoLineSmall @@ -143,12 +145,10 @@ theme_text_color: "Custom" text_color: "white" - - - MDFloatLayout: + AnchorLayout: orientation: "horizontal" md_bg_color: get_color_from_hex("#131313") - + id: servers_datatable """ @@ -215,6 +215,126 @@ def build(self): self.ids.countries_list.add_widget(item) + self.data_tables = MDDataTable( + use_pagination=True, + check=True, + column_data=[ + ("No.", dp(30)), + ("Status", dp(30)), + ("Signal Name", dp(60), self.sort_on_signal), + ("Severity", dp(30)), + ("Stage", dp(30)), + ("Schedule", dp(30), self.sort_on_schedule), + ("Team Lead", dp(30), self.sort_on_team), + ], + row_data=[ + ( + "1", + ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"), + "Astrid: NE shared managed", + "Medium", + "Triaged", + "0:33", + "Chase Nguyen", + ), + ( + "2", + ("alert-circle", [1, 0, 0, 1], "Offline"), + "Cosmo: prod shared ares", + "Huge", + "Triaged", + "0:39", + "Brie Furman", + ), + ( + "3", + ( + "checkbox-marked-circle", + [39 / 256, 174 / 256, 96 / 256, 1], + "Online", + ), + "Phoenix: prod shared lyra-lists", + "Minor", + "Not Triaged", + "3:12", + "Jeremy lake", + ), + ( + "4", + ( + "checkbox-marked-circle", + [39 / 256, 174 / 256, 96 / 256, 1], + "Online", + ), + "Sirius: NW prod shared locations", + "Negligible", + "Triaged", + "13:18", + "Angelica Howards", + ), + ( + "5", + ( + "checkbox-marked-circle", + [39 / 256, 174 / 256, 96 / 256, 1], + "Online", + ), + "Sirius: prod independent account", + "Negligible", + "Triaged", + "22:06", + "Diane Okuma", + ), + ], + sorted_on="Schedule", + sorted_order="ASC", + elevation=2, + ) + self.data_tables.bind(on_row_press=self.on_row_press) + self.data_tables.bind(on_check_press=self.on_check_press) + + self.ids.servers_datatable.add_widget(self.data_tables) + + def on_row_press(self, instance_table, instance_row): + '''Called when a table row is clicked.''' + + print(instance_table, instance_row) + + def on_check_press(self, instance_table, current_row): + '''Called when the check box in the table row is checked.''' + + print(instance_table, current_row) + + # Sorting Methods: + # since the https://github.com/kivymd/KivyMD/pull/914 request, the + # sorting method requires you to sort out the indexes of each data value + # for the support of selections. + # + # The most common method to do this is with the use of the builtin function + # zip and enumerate, see the example below for more info. + # + # The result given by these funcitons must be a list in the format of + # [Indexes, Sorted_Row_Data] + + def sort_on_signal(self, data): + return zip(*sorted(enumerate(data), key=lambda l: l[1][2])) + + def sort_on_schedule(self, data): + return zip( + *sorted( + enumerate(data), + key=lambda l: sum( + [ + int(l[1][-2].split(":")[0]) * 60, + int(l[1][-2].split(":")[1]), + ] + ), + ) + ) + + def sort_on_team(self, data): + return zip(*sorted(enumerate(data), key=lambda l: l[1][-1])) + Builder.load_string(KV) From a097e1315033298912fcf25fffe5f011aaa141b4 Mon Sep 17 00:00:00 2001 From: Alessandro Maggio Date: Sun, 7 Jan 2024 23:29:22 +0100 Subject: [PATCH 8/8] Populate a datatables with dummy data (moniker, location, speed, status, price, protocol, type). We should implement all the sort methods (by column). Note: what about the price denom? up and down with ascii icon? Location should be the city? Login for speedometer? https://github.com/MathNodes/meile-gui/issues/65 --- tests/v2/main_screen.py | 113 +++++++++++++++------------------------- 1 file changed, 42 insertions(+), 71 deletions(-) diff --git a/tests/v2/main_screen.py b/tests/v2/main_screen.py index 672bc878..54fc5759 100644 --- a/tests/v2/main_screen.py +++ b/tests/v2/main_screen.py @@ -167,7 +167,7 @@ def __init__(self, **kwargs): self.build() def build(self): - import random + import random, string countries = [ "France", @@ -217,82 +217,49 @@ def build(self): self.data_tables = MDDataTable( use_pagination=True, - check=True, + check=False, column_data=[ - ("No.", dp(30)), - ("Status", dp(30)), - ("Signal Name", dp(60), self.sort_on_signal), - ("Severity", dp(30)), - ("Stage", dp(30)), - ("Schedule", dp(30), self.sort_on_schedule), - ("Team Lead", dp(30), self.sort_on_team), + ("Moniker", dp(45)), + ("Location", dp(20)), + ("Speed", dp(50)), + ("Status", dp(20)), + ("Price", dp(40)), + ("Protocol", dp(20)), + ("Type", dp(20)), ], - row_data=[ - ( - "1", - ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal"), - "Astrid: NE shared managed", - "Medium", - "Triaged", - "0:33", - "Chase Nguyen", - ), - ( - "2", - ("alert-circle", [1, 0, 0, 1], "Offline"), - "Cosmo: prod shared ares", - "Huge", - "Triaged", - "0:39", - "Brie Furman", - ), - ( - "3", - ( - "checkbox-marked-circle", - [39 / 256, 174 / 256, 96 / 256, 1], - "Online", - ), - "Phoenix: prod shared lyra-lists", - "Minor", - "Not Triaged", - "3:12", - "Jeremy lake", - ), - ( - "4", - ( - "checkbox-marked-circle", - [39 / 256, 174 / 256, 96 / 256, 1], - "Online", - ), - "Sirius: NW prod shared locations", - "Negligible", - "Triaged", - "13:18", - "Angelica Howards", - ), - ( - "5", - ( - "checkbox-marked-circle", - [39 / 256, 174 / 256, 96 / 256, 1], - "Online", - ), - "Sirius: prod independent account", - "Negligible", - "Triaged", - "22:06", - "Diane Okuma", - ), - ], - sorted_on="Schedule", + sorted_on="Moniker", sorted_order="ASC", elevation=2, + rows_num=10 ) - self.data_tables.bind(on_row_press=self.on_row_press) - self.data_tables.bind(on_check_press=self.on_check_press) + row_data = [] + for _ in range(0, 150): + upload = random.uniform(100, 900) + download = random.uniform(100, 900) + bandwith = "speedometer-medium" + if upload + download > 1200: + bandwith = "speedometer" + elif upload + download < 400: + bandwith = "speedometer-slow" + + healthcheck = random.choice([True, False]) + + row_data.append( + ( + ''.join(random.choices(string.printable[:-6], k=random.randint(5, 15))), # Moniker + random.choice(countries), + (bandwith, [1, 1, 1, 1] ,f"[size=12][color=#00FF00]up[/color] {round(upload, 2)}mb/s[color=#f44336]down[/color] {round(download, 2)}mb/s[/size]"), + ("shield-plus", [39 / 256, 174 / 256, 96 / 256, 1], "Health") if healthcheck is True else ("emoticon-sick", [1, 0, 0, 1], "Sick"), + f"[size=12]{random.randint(1, 100)}dvpn, {random.randint(1, 100)}atom, {random.randint(1, 100)}osmo, {random.randint(1, 100)}srct, {random.randint(1, 100)}dec[/size]", + random.choice(["Wireguard", "V2RAY"]), + random.choice(["Residential", "Datacenter", "Unknown"]) + ) + ) + + self.data_tables.row_data = row_data + + self.data_tables.bind(on_row_press=self.on_row_press) self.ids.servers_datatable.add_widget(self.data_tables) def on_row_press(self, instance_table, instance_row): @@ -344,6 +311,10 @@ class Test(MDApp): def build(self): Window.size = (1280, 720) + # TODO: review this values + self.theme_cls.theme_style = "Dark" # (?) + self.theme_cls.primary_palette = "Orange" # (?) + manager = WindowManager() manager.add_widget(MainScreen()) return manager