KivyMD icon indicating copy to clipboard operation
KivyMD copied to clipboard

[Bug] datatables' on_check_press Does not return MDI content for use with remove_row or other

Open Jeremy-EpicHomeTech opened this issue 2 years ago • 6 comments

https://github.com/kivymd/KivyMD/blob/82cde89a4b055f70b983b791592d8554c404615a/kivymd/uix/datatables/datatables.py#L1492

Description of the Bug

The provided example in the markup contains row_data with values such as ("alert", [255 / 256, 165 / 256, 0, 1], "No Signal") which doesn't return properly from the on_check_press or on_row_press. This results in a scenario where you will never be able to remove the row when you submit to remove_row

def on_check_press(self, instance_table, current_row):
    '''Called when the check box in the table row is checked.'''
    self.data_tables.remove_row(tuple(current_row))

Versions

  • OS: Ubuntu 20.04
  • Python: 3.8.10
  • Kivy: v2.1.0
  • KivyMD: commit @ e0e4870

Jeremy-EpicHomeTech avatar Mar 08 '22 15:03 Jeremy-EpicHomeTech

The description of the behavior is not reproduced.

HeaTTheatR avatar Mar 10 '22 21:03 HeaTTheatR

from kivy.metrics import dp

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen


class Example(MDApp):
    def build(self):
        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)
        screen = MDScreen()
        screen.add_widget(self.data_tables)
        return screen

    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.'''

        self.data_tables.remove_row(tuple(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]))


Example().run()
[INFO   ] [Logger      ] Record log in /home/administrator/.kivy/logs/kivy_22-03-11_1.txt
[INFO   ] [Kivy        ] v2.1.0
[INFO   ] [Kivy        ] Installed at "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/__init__.py"
[INFO   ] [Python      ] v3.8.10 (default, Nov 26 2021, 20:14:08) 
[GCC 9.3.0]
[INFO   ] [Python      ] Interpreter at "/home/administrator/Documents/app/env/bin/python3"
[INFO   ] [Logger      ] Purge log fired. Processing...
[INFO   ] [Logger      ] Purge finished!
[INFO   ] [KivyMD      ] 1.0.0.dev0, git-e0e4870, 2022-03-08 (installed at "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/__init__.py")
[INFO   ] [Factory     ] 189 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil (img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <sdl2>
[INFO   ] [GL          ] OpenGL version <b'4.6 (Compatibility Profile) Mesa 21.2.6'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Mesa Intel(R) Xe Graphics (TGL GT2)'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [GL          ] NPOT texture support is available
[WARNING] Deprecated property "<OptionProperty name=theme_text_color>" of object "<kivymd.uix.datatables.datatables.SortButton object at 0x7f1097efb740>" was accessed, it will be removed in a future version
[WARNING] Deprecated property "<ColorProperty name=text_color>" of object "<kivymd.uix.datatables.datatables.SortButton object at 0x7f1097efb740>" was accessed, it will be removed in a future version
[WARNING] Deprecated property "<NumericProperty name=user_font_size>" of object "<kivymd.uix.datatables.datatables.SortButton object at 0x7f1097efb740>" was accessed, it will be removed in a future version
[INFO   ] [ProbeSysfs  ] device match: /dev/input/event11
[INFO   ] [MTD         ] Read event from </dev/input/event11>
[INFO   ] [Base        ] Start application main loop
[INFO   ] [Base        ] Leaving application in progress...
 Traceback (most recent call last):
   File "./test.py", line 132, in <module>
     Example().run()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/app.py", line 955, in run
     runTouchApp()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/base.py", line 339, in mainloop
     self.idle()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/base.py", line 383, in idle
     self.dispatch_input()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/base.py", line 334, in dispatch_input
     post_dispatch_input(*pop(0))
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/base.py", line 263, in post_dispatch_input
     listener.dispatch('on_motion', etype, me)
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/core/window/__init__.py", line 1664, in on_motion
     self.dispatch('on_touch_up', me)
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/core/window/__init__.py", line 1701, in on_touch_up
     if w.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/relativelayout.py", line 322, in on_touch_up
     ret = super(RelativeLayout, self).on_touch_up(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 611, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 611, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/behaviors/ripple_behavior.py", line 311, in on_touch_up
     return super().on_touch_up(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/behaviors/button.py", line 163, in on_touch_up
     return super(ButtonBehavior, self).on_touch_up(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 611, in on_touch_up
     if child.dispatch('on_touch_up', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/scrollview.py", line 968, in on_touch_up
     if self.dispatch('on_scroll_stop', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/scrollview.py", line 1005, in on_scroll_stop
     self.simulate_touch_down(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/scrollview.py", line 668, in simulate_touch_down
     ret = super(ScrollView, self).on_touch_down(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 589, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/behaviors/focus.py", line 464, in on_touch_down
     return super(FocusBehavior, self).on_touch_down(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 589, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/datatables/datatables.py", line 1737, in on_touch_down
     if super().on_touch_down(touch):
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/behaviors/button.py", line 138, in on_touch_down
     if super(ButtonBehavior, self).on_touch_down(touch):
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 589, in on_touch_down
     if child.dispatch('on_touch_down', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/widget.py", line 589, in on_touch_down
[WARNING] [MTD         ] Unable to open device "/dev/input/event11". Please ensure you have the appropriate permissions.
     if child.dispatch('on_touch_down', touch):
   File "kivy/_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/behaviors/ripple_behavior.py", line 259, in on_touch_down
     super().on_touch_down(touch)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/behaviors/button.py", line 150, in on_touch_down
     self._do_press()
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivy/uix/behaviors/togglebutton.py", line 118, in _do_press
     self.state = 'normal' if self.state == 'down' else 'down'
   File "kivy/properties.pyx", line 520, in kivy.properties.Property.__set__
   File "kivy/properties.pyx", line 567, in kivy.properties.Property.set
   File "kivy/properties.pyx", line 606, in kivy.properties.Property._dispatch
   File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1213, in kivy._event.EventObservers._dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/selectioncontrol/selectioncontrol.py", line 328, in on_state
     self.active = True
   File "kivy/properties.pyx", line 520, in kivy.properties.Property.__set__
   File "kivy/properties.pyx", line 567, in kivy.properties.Property.set
   File "kivy/properties.pyx", line 606, in kivy.properties.Property._dispatch
   File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1213, in kivy._event.EventObservers._dispatch
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/datatables/datatables.py", line 1625, in notify_checkbox_click
     self.table.get_select_row(self.index)
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/datatables/datatables.py", line 500, in get_select_row
     self._parent.dispatch("on_check_press", row)
   File "kivy/_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1231, in kivy._event.EventObservers._dispatch
   File "./test.py", line 99, in on_check_press
     self.data_tables.remove_row(tuple(current_row))
   File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/datatables/datatables.py", line 1502, in remove_row
     self.row_data.remove(data)
   File "kivy/properties.pyx", line 853, in kivy.properties.ObservableList.remove
 ValueError: list.remove(x): x not in list

Jeremy-EpicHomeTech avatar Mar 11 '22 10:03 Jeremy-EpicHomeTech

line 99, in on_check_press self.data_tables.remove_row(tuple(current_row)) File "/home/administrator/Documents/app/env/lib/python3.8/site-packages/kivymd/uix/datatables/datatables.py", line 1502, in remove_row self.row_data.remove(data) File "kivy/properties.pyx", line 853, in kivy.properties.ObservableList.remove ValueError: list.remove(x): x not in list

Jeremy-EpicHomeTech avatar Mar 11 '22 10:03 Jeremy-EpicHomeTech

@Jeremy-SohOvercomplicated Why didn't you provide an algorithm of actions in the description of the issue to reproduce the error?

HeaTTheatR avatar Mar 11 '22 11:03 HeaTTheatR

Didn't think it was necessary. The only change made to your provided example were already listed in description. Sorry. Hopefully the additional information helps reproduce the issue.

Jeremy-EpicHomeTech avatar Mar 11 '22 11:03 Jeremy-EpicHomeTech

I am experiencing the same issue. KivyMD version is latest cloned from github master branch Steps to reproduce

  1. Run the code provided by @Jeremy-EpicHomeTech (or) a simpler one taken from kivymd docs and slightly modified to add icons to the row data
from kivy.metrics import dp
from kivy.lang import Builder
from kivy.clock import Clock

from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivymd.uix.screen import MDScreen

KV = """
MDBoxLayout:
    orientation: "vertical"
    padding: "56dp"
    spacing: "24dp"

    MDData:
        id: table_screen

    MDRaisedButton:
        text: "DELETE CHECKED ROWS"
        on_release: table_screen.delete_checked_rows()
"""


class MDData(MDScreen):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.data = [
            [
                "1",
                "Asep Sudrajat",
                (
                    "human-male",
                    "Male",
                ),
                "Soccer",
            ],
            [
                "2",
                "Egy",
                (
                    "human-male",
                    "Male",
                ),
                "Soccer",
            ],
            [
                "3",
                "Tanos",
                (
                    "human-female",
                    "Female",
                ),
                "Soccer",
            ],
        ]
        self.data_tables = MDDataTable(
            use_pagination=True,
            check=True,
            column_data=[
                ("No", dp(30)),
                ("No Urut.", dp(30)),
                ("Alamat Pengirim", dp(30)),
                ("No Surat", dp(60)),
            ],
        )
        self.data_tables.row_data = self.data
        self.add_widget(self.data_tables)

    def delete_checked_rows(self):
        def deselect_rows(*args):
            self.data_tables.table_data.select_all("normal")

        for data in self.data_tables.get_row_checks():
            self.data_tables.remove_row(data)

        Clock.schedule_once(deselect_rows)


class MyApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "Orange"
        return Builder.load_string(KV)


MyApp().run()

On press of the delete button the row is to be deleted but instead an error is thrown that the element does not exist

Traceback (most recent call last):
   File "z:\MR.DM\temp.py", line 86, in <module>
     MyApp().run()
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\app.py", line 956, in run
     runTouchApp()
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\base.py", line 339, in mainloop
     self.idle()
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\base.py", line 383, in idle
     self.dispatch_input()
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\base.py", line 334, in dispatch_input
     post_dispatch_input(*pop(0))
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\base.py", line 302, in post_dispatch_input
     wid.dispatch('on_touch_up', me)
   File "kivy\_event.pyx", line 731, in kivy._event.EventDispatcher.dispatch
   File "Z:\MR.DM\.venv\lib\site-packages\kivymd\uix\button\button.py", line 1145, in on_touch_up
     return super().on_touch_up(touch)
   File "Z:\MR.DM\.venv\lib\site-packages\kivymd\uix\behaviors\ripple_behavior.py", line 404, in on_touch_up
     return super().on_touch_up(touch)
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
     self.dispatch('on_release')
   File "kivy\_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
   File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
   File "kivy\_event.pyx", line 1191, in kivy._event.EventObservers._dispatch
   File "Z:\MR.DM\.venv\lib\site-packages\kivy\lang\builder.py", line 55, in custom_callback
     exec(__kvlang__.co_value, idmap)
   File "<string>", line 12, in <module>
   File "z:\MR.DM\temp.py", line 74, in delete_checked_rows
     self.data_tables.remove_row(data)
   File "Z:\MR.DM\.venv\lib\site-packages\kivymd\uix\datatables\datatables.py", line 1782, in remove_row
     self.row_data.remove(data)
   File "kivy\properties.pyx", line 853, in kivy.properties.ObservableList.remove
 ValueError: list.remove(x): x not in list

On further inspection the function get_row_checks() does not return icon nor color data. What is returned: [['1', 'Asep Sudrajat', 'Male', 'Soccer']] What should be returned [['1', 'Asep Sudrajat', ('human_male', 'Male'), 'Soccer']

Guhan-SenSam avatar Dec 30 '23 17:12 Guhan-SenSam