Beispiel #1
0
    def __init__(self,
                 names,
                 action=None,
                 label=None,
                 selected_button=None,
                 button_height=50,
                 **kwargs):
        super(SignupButtonList, self).__init__(**kwargs)
        self.size_hint = [1, None]
        self.height = button_height
        self.cols = len(names)
        self.spacing = [10, 0]
        self.all_buttons = []
        if label is not None:
            self.cols += 1
            text_label = Label(text=label,
                               font_size=20,
                               size_hint=[1 / self.cols, None],
                               height=button_height,
                               halign="center",
                               valign="center")
            text_label.color = (0, 0, 0, 1)
            self.add_widget(text_label)

        for i in range(len(names)):
            button = SignupButton(names[i], action)
            button.size_hint, button.height = [1 / self.cols,
                                               None], button_height
            button.bind(on_release=lambda button: self.button_selected(button))
            self.add_widget(button)
            self.all_buttons.append(button)

        if selected_button is not None:
            self.button_selected(self.all_buttons[selected_button])
 def __init__(self, simulacion, **kwargs):
     super(ResultadoScreenLayout, self).__init__(**kwargs)
     self.orientation = 'vertical'
     boxtitular = BoxLayout(size_hint=(1.0, None), height=40)
     boxtitular.orientation = 'horizontal'
     boxtitular.add_widget(
         Label(text="Resultado General:",
               size_hint=(1.0, None),
               height=20,
               color=textcolor))
     boxtitular.barraderesultado = BoxLayout()
     boxtitular.barraderesultado.orientation = 'vertical'
     boxtitular.barraderesultado.add_widget(
         Label(text="Barra", size_hint=(1.0, None), height=20))
     boxtitular.barraderesultado.add_widget(
         Label(text="Porcentaje", size_hint=(1.0, None), height=20))
     boxtitular.add_widget(boxtitular.barraderesultado)
     boxtitular.add_widget(
         Label(text="Usuario", size_hint=(1.0, 1.0), height=20))
     self.add_widget(boxtitular)
     self.add_widget(TabbedPanelResultados(simulacion))
     btn = WidgetCreator.newbutton("Volver")
     btn.bind(on_press=self.callback_volver)
     self.add_widget(btn)
     self.guardarsimulacionalsalir = True
    def makeSettingsPage(self):
        page = Screen(name='Settings')

        layout = BoxLayout(orientation='vertical')
        page.add_widget(layout)
        label = MDToolbar(title="Settings and Tools")
        layout.add_widget(label)

        layout.add_widget(self.makeBackButton())

        log = Button(text='System Logs')

        btn1 = Button(text='Local Services')
        label1 = Label(halign="center",
                       text='Share a local webservice with the world')

        log.bind(on_release=self.gotoLogs)
        btn1.bind(on_press=self.goToLocalServices)
        layout.add_widget(log)

        layout.add_widget(btn1)
        layout.add_widget(label1)

        btn = Button(text='Global Settings')

        btn.bind(on_press=self.goToGlobalSettings)
        layout.add_widget(btn)

        # Start/Stop
        btn3 = Button(text='Stop')
        btn3.bind(on_press=self.stop_service)
        label3 = Label(
            size_hint=(1, None),
            halign="center",
            text=
            'Stop the background process.  It must be running to acess hardline sites.  Starting may take a few seconds.'
        )
        layout.add_widget(btn3)
        layout.add_widget(label3)

        btn4 = Button(text='Start or Restart.')
        btn4.bind(on_press=self.start_service)
        label4 = Label(
            size_hint=(1, None),
            halign="center",
            text='Restart the process. It will show in your notifications.')
        layout.add_widget(btn4)
        layout.add_widget(label4)

        layout.add_widget(Widget())

        return page
Beispiel #4
0
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            Window.bind(on_keyboard=self.on_key)
            self.app = MDApp.get_running_app()
            self.screen_list = []
            self.nav_state = False
            self.store = JsonStore(
                os.path.join(abs_root, "assets", 'settings.json'))
            self.abs_root = abs_root
            self.logo = self.store.get("Settings")["Logo"]
            self.club_striped = self.strip_name()
            self.levels = levels

            #Used for global sheet manipulation
            self.sheet = None

            # Create folder
            from googleapiclient.discovery import build
            drive_service = build(u'drive',
                                  u'v3',
                                  credentials=self.get_creds())

            # Try to get sheet if accessable. Already handling the situation
            #where no sheet is loaded later in 'on_start' and 'changeScreen'
            try:
                self.sheet = self.get_spread()

                # Create needed folder(s)
                self.create_folders()

            except Exception as e:
                print(e)
                pass

            # Popup used for updates
            content = BoxLayout(orientation='vertical')
            label = Label(text=self.updates,
                          size_hint=(1, 0.5),
                          halign='center',
                          font_size='15sp')
            self.bind(updates=label.setter('text'))
            button = Button(text="OK", size_hint=(1, 0.5))
            content.add_widget(label)
            content.add_widget(button)
            size_hint = (.3, .3) if platform in 'win,linux' else (.6, .3)
            self.popup = Popup(title="Update",
                               content=content,
                               size_hint=size_hint,
                               auto_dismiss=True)
            button.bind(on_release=self.popup.dismiss)
    def goToGlobalSettings(self, *a):
        if os.path.exists(hardline.globalSettingsPath):
            with open(hardline.globalSettingsPath) as f:
                globalConfig = toml.load(f)
        else:
            globalConfig = {}

        self.localSettingsBox.clear_widgets()

        self.localSettingsBox.add_widget(
            Label(size_hint=(1, 6), halign="center", text='OpenDHT Proxies'))
        self.localSettingsBox.add_widget(
            Label(size_hint=(1, None),
                  text='Proxies are tried in order from 1-3'))

        self.localSettingsBox.add_widget(
            self.settingButton(globalConfig, "DHTProxy", 'server1'))
        self.localSettingsBox.add_widget(
            self.settingButton(globalConfig, "DHTProxy", 'server2'))
        self.localSettingsBox.add_widget(
            self.settingButton(globalConfig, "DHTProxy", 'server3'))

        self.localSettingsBox.add_widget(
            Label(size_hint=(1, 6), halign="center", text='Stream Server'))
        self.localSettingsBox.add_widget(
            Label(
                size_hint=(1, None),
                text=
                'To allow others to sync to this node as a DrayerDB Stream server, set a server title to expose a service'
            ))

        self.localSettingsBox.add_widget(
            self.settingButton(globalConfig, "DrayerDB", 'serverName'))

        btn1 = Button(text='Save')

        def save(*a):
            with open(hardline.globalSettingsPath, 'w') as f:
                toml.dump(globalConfig, f)
            if platform == 'android':
                self.stop_service()
                self.start_service()
            else:
                daemonconfig.loadDrayerServerConfig()

            self.screenManager.current = "Main"

        btn1.bind(on_press=save)
        self.localSettingsBox.add_widget(btn1)
        self.screenManager.current = "GlobalSettings"
Beispiel #6
0
    def makeDiscoveryPage(self):

        # Discovery Page

        screen = Screen(name='Discovery')
        self.discoveryScreen = screen

        layout = BoxLayout(orientation='vertical', spacing=10)
        screen.add_widget(layout)

        label = Label(
            size_hint=(1, None),
            halign="center",
            text=
            'Browsing your local network.\nWarning: anyone on your network\ncan advertise a site with any title they want.'
        )

        layout.add_widget(self.makeBackButton())

        layout.add_widget(label)

        self.discoveryScroll = ScrollView(size_hint=(1, 1))

        self.discoveryListbox = BoxLayout(orientation='vertical',
                                          size_hint=(1, None))
        self.discoveryListbox.bind(
            minimum_height=self.discoveryListbox.setter('height'))

        self.discoveryScroll.add_widget(self.discoveryListbox)
        layout.add_widget(self.discoveryScroll)

        return screen
 def __init__(self, **kwargs):
     super(MenuPrincipalLayout, self).__init__(**kwargs)
     Window.clearcolor = getcolor(backgroundColor)
     Window.size = (800, 600)
     Window.minimum_width, Window.minimum_height = Window.size
     self.orientation = 'vertical'
     self.padding = padding
     self.add_widget(
         WidgetCreator.newlabel('Cultura Objetivo:', size_hint=(1.0, None)))
     values = []
     for x in culturas:
         values.append(x.nombre)
     self.culturaObjetivo = WidgetCreator.newspinner(
         'Elija la cultura objetivo...', values)
     self.culturaObjetivo.bind(text=self.callback_spinner_culturas)
     self.add_widget(self.culturaObjetivo)
     self.add_widget(
         WidgetCreator.newlabel('Conversación:', size_hint=(1.0, None)))
     self.conversación = WidgetCreator.newspinner(
         'Elija la conversación a simular...', ())
     self.conversación.bind(text=self.callback_spinner_conversaciones)
     self.conversación.disabled = True
     self.add_widget(self.conversación)
     self.add_widget(
         WidgetCreator.newlabel('Estado Sensores:', size_hint=(1.0, None)))
     self.add_widget(EstadoSensores(height=176, size_hint_y=None))
     # Llenar pantalla hacia abajo
     self.add_widget(Label(size_hint=(1.0, 1.0)))
     self.add_widget(LowerButtonsRow())
    def makeLocalServiceEditPage(self):

        screen = Screen(name='EditLocalService')
        self.servicesScreen = screen

        layout = BoxLayout(orientation='vertical', spacing=10)
        screen.add_widget(layout)
        self.localServiceEditorName = Label(size_hint=(1, None),
                                            halign="center",
                                            text="??????????")

        layout.add_widget(self.makeBackButton())

        self.localServiceEditPanelScroll = ScrollView(size_hint=(1, 1))

        self.localServiceEditPanel = BoxLayout(orientation='vertical',
                                               size_hint=(1, None))
        self.localServiceEditPanel.bind(
            minimum_height=self.localServiceEditPanel.setter('height'))

        self.localServiceEditPanelScroll.add_widget(self.localServiceEditPanel)

        layout.add_widget(self.localServiceEditPanelScroll)

        return screen
 def __init__(self, **kwargs):
     print("Before super")
     super(Selection, self).__init__(**kwargs)
     print("After super")
     self.orientation = "vertical"
     self.text_box = Label(text="...", color=(0, 0, 0, 1))
     #self.layout = BoxLayout(orientation='vertical')
     self.picker_btn = Button(text="Browse")
     self.add_widget(self.picker_btn)
     self.add_widget(self.text_box)
     # Set up background colors
     with self.text_box.canvas.before:
         Color(rbg=(1, 1, 1))
         self.text_box.rect = Rectangle(size=self.text_box.size,
                                        pos=self.text_box.pos)
     # Bind the background colors location to text_box
     self.text_box.bind(size=self.update_rect, pos=self.update_rect)
 def newlabel(innertext, **kwargs):
     label = Label(color=getcolor(textColor),
                   text=innertext,
                   markup=True,
                   **kwargs)
     label.height = 44
     label.bind(size=label.setter('text_size'))
     return label
    def makeLocalServicesPage(self):

        screen = Screen(name='LocalServices')
        self.servicesScreen = screen

        layout = BoxLayout(orientation='vertical', spacing=10)
        screen.add_widget(layout)

        label = Label(
            size_hint=(1, None),
            halign="center",
            text=
            'WARNING: Running a local service may use a lot of data and battery.\nChanges may require service restart.'
        )

        labelw = Label(
            size_hint=(1, None),
            halign="center",
            text=
            'WARNING 2: This app currently prefers the external SD card for almost everything including the keys.'
        )

        layout.add_widget(self.makeBackButton())

        layout.add_widget(label)
        layout.add_widget(labelw)

        btn2 = Button(text='Create a service')

        btn2.bind(on_press=self.promptAddService)
        layout.add_widget(btn2)

        self.localServicesListBoxScroll = ScrollView(size_hint=(1, 1))

        self.localServicesListBox = BoxLayout(orientation='vertical',
                                              size_hint=(1, None),
                                              spacing=10)
        self.localServicesListBox.bind(
            minimum_height=self.localServicesListBox.setter('height'))

        self.localServicesListBoxScroll.add_widget(self.localServicesListBox)

        layout.add_widget(self.localServicesListBoxScroll)

        return screen
Beispiel #12
0
    def saneLabel(self, text, container):
        bodyText = Label(text=text, size_hint=(1, None), valign="top")

        def setWidth(*a):
            bodyText.text_size = (container.width), None
            bodyText.texture_update()
            bodyText.height = bodyText.texture_size[1]

        container.bind(width=setWidth)

        kivy.clock.Clock.schedule_once(setWidth)
        return bodyText
 def on_start(self):
     ingredient_list = self.root.ids['home'].ids['ingredient_list']
     url = 'https://www.themealdb.com/api/json/v1/1/random.php'
     recipe = requests.get(url).json()
     # print("MealName",recipe['meals'][0]['strMeal'])
     # print("MealCategory", recipe['meals'][0]['strCategory'])
     # print("Origin", recipe['meals'][0]['strArea'])
     # print("Meal Image", recipe['meals'][0]['strMealThumb'])
     # print("Meal Source", recipe['meals'][0]['strSource'])
     self.MealName = recipe['meals'][0]['strMeal']
     self.MealCategory = recipe['meals'][0]['strCategory']
     self.Origin = recipe['meals'][0]['strArea']
     self.MealImage = recipe['meals'][0]['strMealThumb']
     if recipe['meals'][0]['strSource'] != None:
         self.MealSource = recipe['meals'][0]['strSource']
     else:
         self.MealSource = ""
     for i in range(1, 21):
         if recipe['meals'][0][f'strIngredient{i}'] != "":
             l = Label(text=recipe['meals'][0][f'strIngredient{i}'],
                       color=(1, 1, 1, 1))
             ingredient_list.add_widget(l)
Beispiel #14
0
class FileBrowser(Selection):
    '''
    This class is used to find files on the system.
    Currently it is only set to find image files
    '''
    text_box = Label(text="...", color=(0, 0, 0, 1))

    def __init__(self, **kwargs):
        print("In FileBrowser")
        super(FileBrowser, self).__init__(**kwargs)
        self.app = MDApp.get_running_app()
        self.Browser = Popup(size_hint=(0.75, 0.75))
        fc = FileChooserListView()
        fc.rootpath = os.environ["PULSO_APP_ROOT"]
        exit = Button(text='Cancel',
                      size_hint=(1, 0.1),
                      on_release=self.Browser.dismiss)
        layout = BoxLayout(orientation='vertical')
        layout.add_widget(fc)
        layout.add_widget(exit)
        self.Browser.add_widget(layout)

        fc.bind(selection=lambda instance, x: self.set_select(x))
        self.picker_btn.bind(
            on_release=lambda x: self.Browser.open(self.Browser))

    def set_select(self, x):
        '''
        Sets inherted 'selection' if a file selection was made 
        and it is an image
        '''
        img_types = ['jpg', 'jpeg', 'png']
        if len(x) > 0:
            check = x[0].lower()
            # Check if jpg or png
            if any(img_type in check for img_type in img_types):
                setattr(self, 'selection', x[0])
                self.Browser.dismiss()
Beispiel #15
0
    def gotoStreamRow(self,
                      stream,
                      postID,
                      document=None,
                      noBack=False,
                      template=None):
        "Editor/viewer for ONE specific row"
        self.streamEditPanel.clear_widgets()
        self.streamEditPanel.add_widget(
            MDToolbar(title="Table Row in " + stream))

        self.streamEditPanel.add_widget(self.makeBackButton())

        if not noBack:

            def goHere():
                self.gotoStreamRow(stream, postID)

            self.backStack.append(goHere)
            self.backStack = self.backStack[-50:]

        document = document or daemonconfig.userDatabases[
            stream].getDocumentByID(postID, allowOrphans=True)
        if 'type' in document and not document['type'] == 'row':
            raise RuntimeError("Document is not a row")
        document['type'] = 'row'

        title = Label(text=document.get("name", ''), font_size='22sp')

        #Our default template if none exists
        #Give it a name because eventually we may want to have multiple templates.
        #Give it an ID so it can override any existing children of that template.
        #Use only the direct ID of the parent record in cade we want to move it eventually.
        oldTemplate = {
            'type':
            "row.template",
            'leafNode':
            True,
            'parent':
            document['parent'],
            'name':
            'default',
            'id':
            uuid.uuid5(uuid.UUID(document['parent'].split("/")[-1]),
                       ".rowtemplate.default")
        }

        for i in daemonconfig.userDatabases[stream].getDocumentsByType(
                "row.template",
                parent=document['parent'],
                limit=1,
                allowOrphans=True):
            oldTemplate = i

        template = template or oldTemplate

        def post(*a):
            with daemonconfig.userDatabases[stream]:
                #Make sure system knows this is not an old document
                try:
                    del document['time']
                except:
                    pass
                daemonconfig.userDatabases[stream].setDocument(document)

                #If the template has changed, that is how we know we need to save template changes at the same time as data changes
                if not template.get('time', 0) == oldTemplate.get('time', 1):
                    daemonconfig.userDatabases[stream].setDocument(template)
                daemonconfig.userDatabases[stream].commit()
                self.unsavedDataCallback = None

            self.goBack()

        btn1 = Button(text='Save Changes')
        btn1.bind(on_release=post)

        self.streamEditPanel.add_widget(title)

        buttons = BoxLayout(orientation="horizontal",
                            spacing=10,
                            adaptive_height=True)

        if daemonconfig.userDatabases[stream].writePassword:
            self.streamEditPanel.add_widget(buttons)
            buttons.add_widget(btn1)

        def delete(*a):
            def reallyDelete(v):
                if v == postID:
                    with daemonconfig.userDatabases[stream]:
                        daemonconfig.userDatabases[stream].setDocument({
                            'type':
                            'null',
                            'id':
                            postID
                        })
                        daemonconfig.userDatabases[stream].commit()
                    self.gotoStreamPosts(stream)

            self.askQuestion("Delete table row permanently on all nodes?",
                             postID, reallyDelete)

        btn1 = Button(text='Delete')
        btn1.bind(on_release=delete)

        if daemonconfig.userDatabases[stream].writePassword:
            buttons.add_widget(btn1)

        names = {}

        self.streamEditPanel.add_widget(MDToolbar(title="Data Columns:"))

        for i in template:
            if i.startswith('row.'):
                names[i] = ''

        for i in document:
            if i.startswith('row.'):
                if i in template:
                    names[i] = ''
                else:
                    #In the document but not the template, it is an old/obsolete column, show that to user.
                    names[i] = '(removed)'

        for i in names:
            self.streamEditPanel.add_widget(Button(text=i[4:]))
            d = document.get(i, '')
            try:
                d = float(d)
            except:
                pass

            x = MDTextField(text=str(d) + names[i],
                            mode='fill',
                            multiline=False,
                            font_size='22sp')

            def oc(*a, i=i, x=x):
                d = x.text.strip()
                if isinstance(d, str):
                    d = d.strip()
                try:
                    d = float(d or 0)
                except:
                    pass
                document[i] = d

            x.bind(text=oc)
            self.streamEditPanel.add_widget(x)

            if isinstance(d, float) or not d.strip():
                l = BoxLayout(orientation="horizontal",
                              spacing=10,
                              adaptive_height=True)
                b = MDRoundFlatButton(text="--")

                def f(*a, i=i, x=x):
                    d = document.get(i, '')
                    if isinstance(d, str):
                        d = d.strip()
                    try:
                        d = float(d or 0)
                    except:
                        return
                    document[i] = d - 1
                    x.text = str(d - 1)

                b.bind(on_release=f)

                b2 = MDRoundFlatButton(text="++")

                def f(*a, i=i, x=x):
                    d = document.get(i, '')
                    if isinstance(d, str):
                        d = d.strip()
                    try:
                        d = float(d or 0)
                    except:
                        return
                    document[i] = d + 1
                    x.text = str(document[i])

                b2.bind(on_release=f)

                l.add_widget(b)
                l.add_widget(b2)
                self.streamEditPanel.add_widget(l)

        b = MDRoundFlatButton(text="Add Column")

        def f(*a):
            def f2(r):
                if r:
                    template['row.' + r] = ''
                    #Remove time field which marks it as a new record that will get a new timestamp rather than
                    #being ignored when we go to save it, for being old.
                    template.pop('time', None)
                    #Redraw the whole page, it is lightweight, no DB operation needed.
                    self.gotoStreamRow(stream,
                                       postID,
                                       document=document,
                                       noBack=True,
                                       template=template)

            self.askQuestion("Name of new column?", cb=f2)

        b.bind(on_release=f)
        self.streamEditPanel.add_widget(b)

        b = MDRoundFlatButton(text="Del Column")

        def f(*a):
            def f2(r):
                if r:
                    try:
                        del template['row.' + r]
                        template.pop('time', None)
                    except:
                        pass
                    #Redraw the whole page, it is lightweight, no DB operation needed.
                    self.gotoStreamRow(stream,
                                       postID,
                                       document=document,
                                       noBack=True,
                                       template=template)

            self.askQuestion("Column to delete?", cb=f2)

        b.bind(on_release=f)
        self.streamEditPanel.add_widget(b)

        self.screenManager.current = "EditStream"
Beispiel #16
0
    def editStreamSettings(self, name):
        db = daemonconfig.userDatabases[name]
        c = db.config

        self.streamEditPanel.clear_widgets()

        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None), halign="center", text=name))
        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None),
                  halign="center",
                  text="file:" + db.filename))

        self.streamEditPanel.add_widget(self.makeBackButton())

        def save(*a):
            logging.info("SAVE BUTTON WAS PRESSED")
            # On android this is the bg service's job
            db.saveConfig()

            if platform == 'android':
                self.stop_service()
                self.start_service()
            else:
                db.close()
                daemonconfig.loadUserDatabases(
                    None,
                    only=name,
                    callbackFunction=self.onDrayerRecordChange)

        def delete(*a):
            def f(n):
                if n and n == name:
                    daemonconfig.delDatabase(None, n)
                    if platform == 'android':
                        self.stop_service()
                        self.start_service()
                    self.goToStreams()

            self.askQuestion("Really delete?", name, f)

        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None),
                  halign="center",
                  font_size="24sp",
                  text='Sync'))

        self.streamEditPanel.add_widget(
            keyBox := self.settingButton(c, "Sync", "syncKey"))

        self.streamEditPanel.add_widget(
            pBox := self.settingButton(c, "Sync", "writePassword"))

        self.streamEditPanel.add_widget(
            Label(
                size_hint=(1, None),
                halign="center",
                font_size="12sp",
                text=
                'Keys have a special format, you must use the generator to change them.'
            ))

        def promptNewKeys(*a, **k):
            def makeKeys(a):
                if a == 'yes':
                    import base64
                    vk, sk = libnacl.crypto_sign_keypair()
                    vk = base64.b64encode(vk).decode()
                    sk = base64.b64encode(sk).decode()
                    keyBox.text = vk
                    pBox.text = sk

            self.askQuestion("Overwrite with random keys?", 'yes', makeKeys)

        keyButton = Button(text='Generate New Keys')
        keyButton.bind(on_press=promptNewKeys)
        self.streamEditPanel.add_widget(keyButton)

        self.streamEditPanel.add_widget(
            serverBox := self.settingButton(c, "Sync", "server"))

        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None),
                  halign="center",
                  text='Do not include the http:// '))

        self.streamEditPanel.add_widget(
            self.settingButton(c, "Sync", "serve", 'yes'))

        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None),
                  halign="center",
                  text='Set serve=no to forbid clients to sync'))

        self.streamEditPanel.add_widget(
            Label(size_hint=(1, None),
                  halign="center",
                  font_size="24sp",
                  text='Application'))

        self.streamEditPanel.add_widget(
            self.settingButton(c, "Application", "notifications", 'no'))

        def f(*a):
            def g(a):
                try:
                    import json
                    a = json.loads(a)
                    serverBox.text = c['Sync'][
                        'server'] = a['sv'] or c['Sync']['server']
                    keyBox.text = c['Sync']['syncKey'] = a['vk']
                    pBox.text = c['Sync']['writePassword'] = a['sk']

                except:
                    pass

            self.askQuestion("Enter Sharing Code", cb=g, multiline=True)

        keyButton = Button(text='Load from Code')
        keyButton.bind(on_press=f)
        self.streamEditPanel.add_widget(keyButton)

        def f(*a):
            self.showSharingCode(name, c)

        keyButton = Button(text='Show Sharing Code')
        keyButton.bind(on_press=f)
        self.streamEditPanel.add_widget(keyButton)

        def f(*a):
            self.showSharingCode(name, c, wp=False)

        keyButton = Button(text='Readonly Sharing Code')
        keyButton.bind(on_press=f)
        self.streamEditPanel.add_widget(keyButton)

        btn1 = Button(text='Save Changes')

        btn1.bind(on_press=save)
        self.streamEditPanel.add_widget(btn1)

        btn2 = Button(text='Delete this stream')

        btn2.bind(on_press=delete)
        self.streamEditPanel.add_widget(btn2)

        def gotoOrphans(*a, **k):
            self.gotoStreamPosts(name, orphansMode=True)

        oButton = Button(text='Show Unreachable Garbage')
        oButton.bind(on_press=gotoOrphans)
        self.streamEditPanel.add_widget(oButton)

        noSpreadsheet = Button(text="Spreadsheet on/off")

        def promptSet(*a):
            from .kivymdfmfork import MDFileManager
            from .. import directories
            try:
                #Needed for android
                self.getPermission('files')
            except:
                logging.exception("cant ask permission")

            def f(selection):
                if selection == 'on':
                    daemonconfig.userDatabases[
                        name].enableSpreadsheetEval = True
                else:
                    daemonconfig.userDatabases[
                        name].enableSpreadsheetEval = False

            if hasattr(daemonconfig.userDatabases[name],
                       'enableSpreadsheetEval'):
                esf = daemonconfig.userDatabases[name].enableSpreadsheetEval
            else:
                esf = True

            self.askQuestion("Allow Spreadsheet Functions?",
                             'on' if esf else 'off', f)

        noSpreadsheet.bind(on_release=promptSet)
        self.streamEditPanel.add_widget(noSpreadsheet)
        self.streamEditPanel.add_widget(
            self.saneLabel(
                "Disabling only takes effect for this session. Use this feature if a stream is loading too slowly, to allow you to fix the offending expression.",
                self.streamEditPanel))

        self.screenManager.current = "EditStream"
    def __init__(self, resultado: LineaResultado, fase, nrodefase: Fase,
                 **kwargs):
        super(TabbedPanelItemResultados, self).__init__(**kwargs)
        self.text = f"Fase {nrodefase}"
        content = BoxLayout(padding=gridpadding)
        # content = BoxLayout(halign='left', valign="middle")
        content.orientation = 'vertical'
        content.add_widget(
            Label(text=f"{fase.nombre}", size_hint=(1.0, None), height=20))
        content.add_widget(
            Label(text="Captura de usuario:", size_hint=(1.0, None),
                  height=20))

        grid = GridLayout(
            cols=2,
            row_force_default=True,
            row_default_height=40,
            size_hint=(1.0, None),
            height=240,
            spacing=5,
            padding=gridpadding,
        )
        label = Label(text="Rostro", size_hint=(None, 1), width=100)
        with label.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        rostro = BoxLayout(orientation='horizontal')
        rostro.add_widget(Label(text=resultado.captura.rostro.name))
        rostro.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconoderostro(
                      resultado.captura.rostro)))
        with rostro.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            rostro.rect = Rectangle(size=self.size, pos=self.pos)
        rostro.bind(pos=WidgetCreator.update_rect,
                    size=WidgetCreator.update_rect)
        grid.add_widget(rostro)

        label = Label(text="Mirada", size_hint=(None, 1), width=100)
        with label.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        mirada = BoxLayout(orientation='horizontal')
        mirada.add_widget(Label(text=resultado.captura.mirada.name))
        mirada.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconodemirada(
                      resultado.captura.mirada)))
        with mirada.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            mirada.rect = Rectangle(size=self.size, pos=self.pos)
        mirada.bind(pos=WidgetCreator.update_rect,
                    size=WidgetCreator.update_rect)
        grid.add_widget(mirada)

        label = Label(text="Cabeza", size_hint=(None, 1), width=100)
        with label.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        cabeza = BoxLayout(orientation='horizontal')
        cabeza.add_widget(Label(text=resultado.captura.cabeza.name))
        cabeza.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconodecabeza(
                      resultado.captura.cabeza)))
        with cabeza.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            cabeza.rect = Rectangle(size=self.size, pos=self.pos)
        cabeza.bind(pos=WidgetCreator.update_rect,
                    size=WidgetCreator.update_rect)
        grid.add_widget(cabeza)

        label = Label(text="Brazos", size_hint=(None, 1), width=100)
        with label.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        brazos = BoxLayout(orientation='horizontal')
        brazos.add_widget(Label(text=resultado.captura.posicionbrazos.name))
        brazos.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconodebrazos(
                      resultado.captura.posicionbrazos)))
        with brazos.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            brazos.rect = Rectangle(size=self.size, pos=self.pos)
        brazos.bind(pos=WidgetCreator.update_rect,
                    size=WidgetCreator.update_rect)
        grid.add_widget(brazos)

        label = Label(text="Volumen de Voz", size_hint=(None, 1), width=100)
        with label.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        volumen = BoxLayout(orientation='horizontal')
        volumen.add_widget(Label(text=str(resultado.captura.volumendevoz)))
        volumen.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconodevolumen(
                      resultado.captura.volumendevoz)))
        with volumen.canvas.before:
            Color(firstrowcolor[0], firstrowcolor[1], firstrowcolor[2])
            volumen.rect = Rectangle(size=self.size, pos=self.pos)
        volumen.bind(pos=WidgetCreator.update_rect,
                     size=WidgetCreator.update_rect)
        grid.add_widget(volumen)

        label = Label(text="Palabras por minuto",
                      size_hint=(None, 1),
                      width=100)
        with label.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            label.rect = Rectangle(size=self.size, pos=self.pos)
        label.bind(pos=WidgetCreator.update_rect,
                   size=WidgetCreator.update_rect)
        grid.add_widget(label)

        velocidad = BoxLayout(orientation='horizontal')
        velocidad.add_widget(
            Label(text=str(resultado.captura.palabrasporsegundo)))
        velocidad.add_widget(
            Image(size_hint=(None, 0.9),
                  width=40,
                  source=SelectorDeIconos.iconodevelocidad(
                      resultado.captura.palabrasporsegundo)))
        with velocidad.canvas.before:
            Color(secondrowcolor[0], secondrowcolor[1], secondrowcolor[2])
            velocidad.rect = Rectangle(size=self.size, pos=self.pos)
        velocidad.bind(pos=WidgetCreator.update_rect,
                       size=WidgetCreator.update_rect)
        grid.add_widget(velocidad)

        content.add_widget(grid)

        box = BoxLayout()
        box.add_widget(
            Label(text=f"Interpretación: {resultado.interpretacion.lectura}",
                  size_hint=(1.0, None),
                  height=20))
        content.add_widget(box)

        scrollableInfo = ScrollView(size_hint=(1.0, 1.0))
        scrollableInfo.add_widget(
            Label(text=f"{resultado.interpretacion.masinfo}"))
        content.add_widget(scrollableInfo)
        self.add_widget(content)
    def editLocalService(self, name, c=None):
        if not c:
            c = configparser.RawConfigParser(
                dict_type=cidict.CaseInsensitiveDict)

        try:
            c.add_section("Service")
        except:
            pass
        try:
            c.add_section("Info")
        except:
            pass

        self.localServiceEditPanel.clear_widgets()

        self.localServiceEditorName.text = name

        def save(*a):
            logging.info("SAVE BUTTON WAS PRESSED")
            # On android this is the bg service's job
            daemonconfig.makeUserService(
                None,
                name,
                title=c['Info'].get("title", 'Untitled'),
                service=c['Service'].get("service", ""),
                port=c['Service'].get("port", ""),
                cacheInfo=c['Cache'],
                noStart=(platform == 'android'),
                useDHT=c['Access'].get("useDHT", "yes"))
            if platform == 'android':
                self.stop_service()
                self.start_service()

            self.goToLocalServices()

        def delete(*a):
            def f(n):
                if n and n == name:
                    daemonconfig.delUserService(None, n)
                    if platform == 'android':
                        self.stop_service()
                        self.start_service()
                    self.goToLocalServices()

            self.askQuestion("Really delete?", name, f)

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None), halign="center", text='Service'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Service", "service"))
        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Service", "port"))
        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Info", "title"))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None), halign="center", text='Cache'))
        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None),
                  text='Cache mode only works for static content'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "directory"))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "maxAge"))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None),
                  text='Try to refresh after maxAge seconds(default 1 week)'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "maxSize", '256'))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None),
                  text='Max size to use for the cache in MB'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "downloadRateLimit", '1200'))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None), text='Max MB per hour to download'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "dynamicContent", 'no'))

        self.localServiceEditPanel.add_widget(
            Label(
                size_hint=(1, None),
                text=
                'Allow executing code in protected @mako files in the cache dir. yes to enable. Do not use with untrusted @mako'
            ))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Cache", "allowListing", 'no'))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None),
                  text='Allow directory listing of cached content'))

        self.localServiceEditPanel.add_widget(
            Label(
                size_hint=(1, None),
                text=
                'Directory names are subfolders within the HardlineP2P cache folder,\nand can also be used to share\nstatic files by leaving the service blank.'
            ))

        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None), halign="center",
                  text='Access Settings'))
        self.localServiceEditPanel.add_widget(
            Label(size_hint=(1, None),
                  text='Cache mode only works for static content'))

        self.localServiceEditPanel.add_widget(
            self.settingButton(c, "Access", "useDHT", 'yes'))

        self.localServiceEditPanel.add_widget(
            Label(
                size_hint=(1, None),
                text=
                'DHT Discovery uses a proxy server on Android. \nDisabling this saves bandwidth but makes access from outside your network\nunreliable.'
            ))

        btn1 = Button(text='Save Changes')

        btn1.bind(on_press=save)
        self.localServiceEditPanel.add_widget(btn1)

        btn2 = Button(text='Delete this service')

        btn2.bind(on_press=delete)
        self.localServiceEditPanel.add_widget(btn2)

        self.screenManager.current = "EditLocalService"
class Selection(BoxLayout):
    '''The class is used as an class type for things that use some type of selection
    
    Usage:
    When initializing your subclass update the 'text_box' and 'picker_btn'
    to for your specific task
    
    'picket_btn': Button that starts the function of the new subclass
    
    'text_box': The Label that dislays a message, usually of the 
    action of the subclass
    '''

    selection = StringProperty('')

    def __init__(self, **kwargs):
        print("Before super")
        super(Selection, self).__init__(**kwargs)
        print("After super")
        self.orientation = "vertical"
        self.text_box = Label(text="...", color=(0, 0, 0, 1))
        #self.layout = BoxLayout(orientation='vertical')
        self.picker_btn = Button(text="Browse")
        self.add_widget(self.picker_btn)
        self.add_widget(self.text_box)
        # Set up background colors
        with self.text_box.canvas.before:
            Color(rbg=(1, 1, 1))
            self.text_box.rect = Rectangle(size=self.text_box.size,
                                           pos=self.text_box.pos)
        # Bind the background colors location to text_box
        self.text_box.bind(size=self.update_rect, pos=self.update_rect)

    def on_start(self):
        pass

    '''
    Using this creattion function to initialize attributes because
    if done from the __init__() function the super's attributes are not
    linked for some reason
    '''
    '''
    def __new__(self, *args, **kwargs):
        self.text_box = Label(text="...", color=(0,0,0,1))
        self.layout = BoxLayout(orientation='vertical')
        self.picker_btn = Button(text="Browse")
        self.layout.add_widget(self.picker_btn)
        self.layout.add_widget(self.text_box)
        # Set up background colors
        with self.text_box.canvas.before:
            Color(rbg=(1,1,1) )
            self.text_box.rect = Rectangle(size=self.text_box.size, pos=self.text_box.pos)
        # Bind the background colors location to text_box
        self.text_box.bind(size=self.update_rect, pos=self.update_rect)
        
        inst = super(Selection, self).__new__(self, *args, **kwargs)
        self.layout.root = inst
        return inst
        '''

    def dismiss(self):
        pass

    # Change text_box background color
    #def update_rect(self, caller, val):
    def update_rect(self, text_box, _):
        try:
            text_box.rect.pos = text_box.pos
            text_box.rect.size = text_box.size
        except Exception as e:
            print(e)
            pass

    # Change text_box background color size
    def update_rect_size(self, sizeX, sizeY):
        #print("*args =", *args)
        print("Inside update_rect")
        print("self.text_box.rect.size = ", self.text_box.rect.size)
        try:
            self.text_box.rect.size = (sizeX, sizeY)
        except Exception as e:
            print(e)
            pass

    # Change text_box background color position
    def update_rect_pos(self, posX, posY):
        #print("*args =", *args)
        print("Inside update_rect")
        print("self.text_box.rect.pos = ", self.text_box.rect.pos)
        try:
            self.text_box.rect.pos = (posX, posY)
        except Exception as e:
            print(e)
            pass
    def __init__(self, master, level, **kwargs):
        super().__init__(**kwargs)

        if platform != "android":
            self._keyboard = Window.request_keyboard(self._keyboard_closed,
                                                     self, 'text')
            if self._keyboard.widget:
                # If it exists, this widget is a VKeyboard object which you can use to change the keyboard layout.
                pass
            self._keyboard.bind(on_key_down=self._on_keyboard_down)

        self.master = master
        self.level = level
        self.dialog = None

        self.effect_cls = "ScrollEffect"
        self.scroll_type = ["bars"]
        self.bar_width = "10dp"
        self.pos_hint = {"top": .9}

        self.kanji_layout = MDRelativeLayout()

        self.kanji_data = get_kanji_from_level(self.level)

        if self.kanji_data is {} or self.kanji_data is None:
            toast(
                "Error has occured; No internet connection; Site may be blocked"
            )
            self.kanji_layout.add_widget(
                Label(
                    text=
                    "Can't connect to the internet\nthe API may be blocked\nor poor connection",
                    halign="center"))
        else:
            for k, v in self.kanji_data.items():
                setattr(self, k, v)

            self.btn_texts = [
                "     Show Meanings     ", "       Show Radicals       ",
                "Show Example Words"
            ]

            #self.kanji_layout.add_widget(Label(text=str(self.kanji), font_size=75,halign="center", pos_hint={"center_y":.8}))
            #self.kanji_layout.add_widget(Label(text=str(self.stroke_count), font_size=20,halign="center", pos_hint={"center_y":.7}))

            self.kanji_layout.add_widget(
                HighlightableText(
                    text=f"{str(self.kanji)}: {self.stroke_count}",
                    font_size="40sp",
                    pos_hint={
                        "center_x": .5,
                        "center_y": .9
                    }))
            self.carousel = KanjiStrokeImageCarousel(self.stroke_order_images)
            self.kanji_layout.add_widget(self.carousel)

            if platform != "android":
                self.prev_btn = MDIconButton(
                    icon="menu-left",
                    user_font_size="200sp",
                    on_release=lambda x: self.carousel.load_previous(),
                    pos_hint={
                        "center_x": .1,
                        "center_y": .6
                    })  # pos_hint={"left":.2, "y":.5},
                self.next_btn = MDIconButton(
                    icon="menu-right",
                    user_font_size="200sp",
                    on_release=lambda x: self.carousel.load_next(),
                    pos_hint={
                        "center_x": .9,
                        "center_y": .6
                    })  # pos_hint={"right":.8, "y":.5}
                self.kanji_layout.add_widget(self.prev_btn)
                self.kanji_layout.add_widget(self.next_btn)
            """
            for i, reading in enumerate(self.readings):
                # HighlightableText(text=reading, font_size=20, pos_hint={"center_x":.5,"center_y":.3-(i/20)})
                self.kanji_layout.add_widget(
                    HighlightableText(text=reading, font_size=20, pos_hint={"center_x":.4,"center_y":.3-(i/30)})
                )
            """
            self.readings_formatted = "\n".join(
                [f"{k}: {v}" for k, v in self.readings.items()])
            self.kanji_layout.add_widget(
                HighlightableText(text=f"{self.readings_formatted}",
                                  font_size="20sp",
                                  pos_hint={
                                      "center_x": .5,
                                      "center_y": .35
                                  }))

            #print(" ".join([j for j in [" ".join(i) for i in self.radicals_data]]))
            formated_radicals = " \n".join([
                rad for rad in [" :".join(tup) for tup in self.radicals_data]
            ])

            formated_word_examples = "\n".join(self.example_words)

            #self.kanji_layout.add_widget(Label(text=formated_radicals,halign="center", font_size=15, pos_hint={"center_x":.5,"center_y":.1}))
            self.meanings_btn = MDRaisedButton(
                text=self.btn_texts[0],
                pos_hint={
                    "center_x": .1,
                    "center_y": .2
                },
                on_release=lambda x: self.showDialog("Meanings", self.meanings
                                                     ))

            self.radicals_btn = MDRaisedButton(
                text=self.btn_texts[1],
                pos_hint={
                    "center_x": .5,
                    "center_y": .2
                },
                on_release=lambda x: self.showDialog("Radicals",
                                                     formated_radicals))
            #self.kanji_layout.add_widget(self.radicals_btn)
            self.examples_btn = MDRaisedButton(
                text=self.btn_texts[2],
                pos_hint={
                    "center_x": .9,
                    "center_y": .2
                },
                on_release=lambda x: self.showDialog("Example Words",
                                                     formated_word_examples))
            #self.kanji_layout.add_widget(self.examples_btn)

            for btn in [
                    self.meanings_btn, self.radicals_btn, self.examples_btn
            ]:
                self.kanji_layout.add_widget(btn)
            self.add_widget(self.kanji_layout)