Scott Rowley
Scott Rowley

Reputation: 484

Pass input value to dialog and send to screen

I have the following code where I would like to be able to click on the navigation drawer, select Status under Users, input the name and then be sent to a given screen with the current_user now populated.

main.py

from kivy.uix.behaviors import CoverBehavior
from kivy import utils
from kivy.properties import ObjectProperty, ListProperty, NumericProperty, StringProperty, BooleanProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.screenmanager import ScreenManager
from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivymd.theming import ThemableBehavior
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.list import MDList
#from models import ServerInfo
from navigation_drawer import navigation_helper
Window.fullscreen = 'auto'
class ItemWidget(BoxLayout):
    sid = NumericProperty()
    name = StringProperty()
    work = NumericProperty()
    is_disabled = BooleanProperty()
    description = StringProperty()
    has_issue = BooleanProperty()

class MainWidget(FloatLayout):
    recycleView = ObjectProperty()
    items = ListProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.items = [
            #ServerInfo(1, "server1", 95, "desc", is_disabled=False, has_issue=False),
        ]
        # Put the servers with issues on top, otherwise sort by name
        self.items = sorted((s for s in self.items), key=lambda x: (not(x.has_issue),x.name))

    # Load the server information when the recycleView is called
    def on_recycleView(self, widget, parent):

        self.recycleView.data = [
            m.get_dictionary() for m in self.items
        ]


class Content(BoxLayout):
    pass


class DemoApp(MDApp):
    class ContentNavigationDrawer(BoxLayout):
        pass

    class DrawerList(ThemableBehavior, MDList):
        pass

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.dialog = None
        # set main interface
        self.manager = ScreenManager()
        self.current_user = ""

        # return main interface
        #return self.manager

    def build(self):
        screen = Builder.load_string(navigation_helper)
        return screen

    def on_start(self):
        pass

    def dialog_close(self, *args):
        self.dialog.dismiss(force=True)

    def set_current_user(self,user,sm):
        self.current_user = user
        # Send over to given screen
        # ???? = sm


    def show_user_input_dialog(self,user,screen):
        #print(sm.current)
        if not self.dialog:
            self.dialog = MDDialog(
                title="Input Username:",
                type="custom",
                content_cls=Content(),
                buttons=[
                    MDFlatButton(
                        text="CANCEL",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        on_release=self.dialog_close
                    ),
                    MDFlatButton(
                        text="OK",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        #on_release=self.set_current_user(user,screen)
                        on_release=self.dialog_close
                    ),
                ],
            )
            # Send to user management page with current user now populated
            # Fails as sm is a str instead of ScreenManager()
            #sm.current = 'user_management'
        self.dialog.open()


DemoApp().run()

navigation_drawer.py

navigation_helper = """
Screen:
    MDNavigationLayout:
        ScreenManager:
            id: screenManager
            Screen:
                name: "monitor"
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: 'Administration'
                        left_action_items: [["menu", lambda x: nav_drawer.set_state('toggle')]]
                        elevation:5
                    MainWidget:
            Screen:
                name: "user_management"
                BoxLayout:
                    orientation: 'vertical'
                    MDToolbar:
                        title: 'Administration'
                        left_action_items: [["menu", lambda x: nav_drawer.set_state('toggle')]]
                        elevation:5
                    UserManagement:
            

        MDNavigationDrawer:
            id: nav_drawer

            ContentNavigationDrawer:
                orientation: 'vertical'
                padding: "2dp"
                spacing: "2dp"
                ScrollView:
                    DrawerList:
                        id: md_list
                        MDList:
                            TwoLineIconListItem:
                                text: "Monitor"
                                secondary_text: "Monitor servers"
                                on_release: screenManager.current = 'monitor'
                                IconLeftWidget:
                                    icon: "monitor"
                            MDLabel:
                                padding: dp(10), dp(0)
                                text: "Users"
                                bold: True
                                font_size: dp(22)
                                size_hint_y: None
                            OneLineIconListItem:
                                text: "Status"
                                on_release: app.show_user_input_dialog('abc999','user_management')
                            
                            
<Content>
    orientation: "vertical"
    spacing: "12dp"
    size_hint_y: None
    height: "60dp"
    MDTextField:
        id: username_input
        hint_text: "Username"

<UserManagement@BoxLayout>:
    Label:
        text: "Users"

                               
<MainWidget>:
    id: mainWidgetId2
    recycleView: recycleView
    CoverImage:
        source: 'images/monitor.png'
        # Darken the photo
        canvas:
            Color:
                rgba: 0, 0, 0, .6
            Rectangle:
                pos: self.pos
                size: self.size
    BoxLayout:
        padding: dp(20)
        spacing: dp(10)
        BoxLayout:
            orientation: "horizontal"
            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                RecycleView:
                    id: recycleView
                    viewclass: 'ItemWidget'
                    RecycleGridLayout:
                        cols: 1
                        default_size: self.parent.width / 5, dp(60)
                        default_size_hint: 1, None
                        size_hint_y: None
                        height: self.minimum_height
                        width: self.minimum_width
                        spacing: dp(155), dp(0)
        BoxLayout:
            orientation: "vertical"
            spacing: dp(10)
            BoxLayout:
                spacing: dp(10)
                BoxLayout:
                    canvas.before:
                        Color:
                            rgba: 1,1,1,.1
                        # Use a float layout to round the corners
                        RoundedRectangle:
                            pos: self.pos
                            size: self.size
                    Label:
                        text: "APPS"
                BoxLayout:
                    canvas.before:
                        Color:
                            rgba: 1,1,1,.1
                        # Use a float layout to round the corners
                        RoundedRectangle:
                            pos: self.pos
                            size: self.size
                    Label:
                        text: "OTHER"
            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                Label:
                    text: "MOUNTS"

            BoxLayout:
                canvas.before:
                    Color:
                        rgba: 1,1,1,.1
                    # Use a float layout to round the corners
                    RoundedRectangle:
                        pos: self.pos
                        size: self.size
                Label:
                    text: "RECENT ACTIVITY"

<CoverImage@CoverBehavior+Image>:
    reference_size: self.texture_size

<ItemWidget>:
    BoxLayout:
        #size_hint_max_x: dp(360)
        size_hint_min_x: dp(150)
        orientation: "horizontal"
        BoxLayout:
            orientation: "horizontal"
            Button:
                # Use the on_press to print troubleshooting info, otherwise comment out
                on_press: print(self.background_color)
                padding: dp(10), dp(10)
                text_size: self.size
                font_size: dp(22) if root.has_issue else dp(18)
                background_color: .5,1,1,.6 #utils.get_random_color(alpha=.6)
                halign: "left"
                valign: "top"
                size: 1,1
                # Show last 4 of server name
                text: str(root.name).upper()[-4:]
                bold: True
                color: (1,0,0) if root.has_issue else (1,1,1)
            Button:
                background_color: .5,1,1,.6
                text_size: self.size
                valign: "center"
                halign: "center"
                text: str(root.work)
                padding: dp(8), dp(8)
                bold: True if root.work > 90 else False
                color: (1,0,0) if root.work > 90 else (1,1,1) # Red if greater than 90


"""

Questions:

  1. How do I get the value from this so that I can pass the value instead of the hardcoded username of abc999
MDTextField:
        id: username_input
  1. How do I send to the given screen (user_management here) from
    def set_current_user(self,user,sm):
        self.current_user = user
        # Send over to given screen
        # ???? = sm

You can toggle commenting on the two on_release below to see the issue

                    MDFlatButton(
                        text="OK",
                        theme_text_color="Custom",
                        text_color=self.theme_cls.primary_color,
                        #on_release=self.set_current_user(user,screen)
                        on_release=self.dialog_close

Upvotes: 0

Views: 421

Answers (1)

John Anderson
John Anderson

Reputation: 39012

You can do what you want by modifying set_current_user() to:

def set_current_user(self, button):
    self.current_user = self.dialog.content_cls.ids.username_input.text
    self.dialog_close()
    self.root.ids.users.add_widget(Label(text=self.current_user))
    sm = self.root.ids.screenManager
    sm.current = 'user_management'

The above code requires the addition of an id to the UserManagerment in the kv:

                UserManagement:
                    id: users

This just adds a new Label with the name of the user.

Upvotes: 2

Related Questions