How to remove last row from list of rows


I am trying to make an app that has a stack of rows that you can add to/remove from at the press of buttons.

I have got the 'Add Row' button working well, now I need the 'Remove Row' functionality.

I have the rows in lists '(self.rows.content.children)', I just need to know how to pop the last one from the list, then keep adding/subtracting at will.

Thanks for looking.

test.py

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.properties import ObjectProperty, StringProperty, ListProperty
from kivy.clock import Clock

from sql_update_data import update_db

kivy.require('1.10.1')


class GUILayout(BoxLayout, GridLayout):
    rows = ObjectProperty(None)

    def add_more(self):
        self.ids.rows.add_row()

    def remove_row(self):
        print("Remove last row")

    def insert_value(self):
        values = [row.values for row in reversed(self.rows.content.children)]

    for category, id, strap in values:
        update_db(category, id, strap)


class Row(BoxLayout):
    button_text = StringProperty("")
    id = ObjectProperty(None)
    values = ListProperty()


class Rows(ScrollView):
    row_count = 0
    content = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(Rows, self).__init__(**kwargs)
        Clock.schedule_once(self.add_row)

    def add_row(self, *args):
        self.row_count += 1
        self.content.add_widget(Row(button_text=str(self.row_count),
                            id=str(self.row_count)))


class TestApp(App):

    def build(self):
        return GUILayout()


GUIApp = TestApp()
GUIApp.run()

test.kv

#: import main test
<Row>:
    values: row_id.text, col1.text, col2.text
    orientation: "horizontal"
    spacing: 0, 5
    size_hint_y: None
    height: "60dp"
    spacing: 2
    pos_hint: {'center_x': .50, 'y': .80}

    Button:
        id: row_id
        text: root.button_text
        size_hint_x: .1
    Spinner:
        id: col1
        text: 'Select Category'
        values: ['One', 'Two', 'Three']
        size_hint_x: .3
    TextInput:
        id: col2
        size_hint_x: .8

<Rows>:
    content: content
    BoxLayout:
        id: content
        orientation: "vertical"
        size_hint_y: None
        height: self.minimum_height


GUILayout:


<GUILayout>:
    rows: rows
    orientation: "vertical"
    padding: 10
    spacing: 10

    BoxLayout:
        orientation: "horizontal"
        height: 60

        BoxLayout:
            orientation: "horizontal"
            size_hint_x: .25

            TabbedPanel:
                do_default_tab: False


                # ----------- TAB 1 ------------

                TabbedPanelItem:
                    text: "tab1"
                    BoxLayout:
                        orientation: 'vertical'

                        Rows:
                            id: rows

                        GridLayout:
                            rows: 1
                            cols: 6
                            padding: 1
                            spacing: 5
                            size_hint_y: None
                            height: 50

                            # --------- MINUS ---------
                            Button:
                                text: " - "
                                font_size: 70
                                size_hint_x: .1
                                on_press: root.remove_row()

                            # -------- SUBTRACT -------
                            Button:
                                text: " + "
                                font_size: 50
                                size_hint_x: .1
                                on_press: root.add_more()


                            # ----- UPDATE MAESTRO -----
                            Button:
                                text: "Update Maestro"
                                size_hint_x: .4
                                on_press: root.insert_value()


                            # -------- SETTINGS --------
                            Button:
                                text: "Settings"
                                font_size: 30
                                size_hint_x: .2

Answer

What you should do is remove the last child widget from content using the remove_widget method, on the other hand do not use id as the name of a variable since it is a reserved word:

On the other hand GUILayout must not inherit 2 widgets, it is only necessary that it be from BoxLayout.

# ..

class GUILayout(BoxLayout):
    rows = ObjectProperty(None)

    def add_more(self):
        self.rows.add_row()

    def remove_row(self):
        self.rows.remove_row()

    def insert_value(self):
        values = [row.values for row in reversed(self.rows.content.children)]
        for category, _id, strap in values:
            update_db(category, _id, strap)

#...

class Rows(ScrollView):
    content = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(Rows, self).__init__(**kwargs)
        self.row_count = 0
        Clock.schedule_once(lambda _: self.add_row())

    def add_row(self):
        self.row_count += 1
        self.content.add_widget(Row(button_text=str(self.row_count), 
            id=str(self.row_count)))

    def remove_row(self):
        if self.content.children:
            self.content.remove_widget(self.content.children[0])
            self.row_count -= 1
# ...