• Enez Houad

    @mikael Thanks for your reactivity !

    posted in Pythonista read more
  • Enez Houad

    @mikael , I regularly use your modules and I thank you for it. Unfortunately, since the last version of ui3, I have an error when I want to use it.
    Here is the Traceback :

    Traceback (most recent call last):
      File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/sheet.py", line 7, in <module>
        from ui3.anchor import *
      File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/ui3/__init__.py", line 12, in <module>
        from ui3.anchor import *
      File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/ui3-master/ui3/anchor/__init__.py", line 821, in <module>
        via_screen,
    NameError: name 'via_screen' is not defined ```

    posted in Pythonista read more
  • Enez Houad

    @cvp Thanks a lot ! I’m happy to see that I progress slowly…
    I had found textView().becomeFirstResponder() but couldn’t find to witch element it had to be applied. The _get_editor_tab is not documented ! To find it, do you open editor.py in the site-packages of Standard Library ?
    It's very instructive πŸ€“, I'm going to end up managing on my own. πŸ˜‰

    posted in Pythonista read more
  • Enez Houad

    @cvp I learn a lot adapting your scripts to my needs !
    You will find after this message my/your script to add a keyboard icon in the titlebar to call my script to add my special key row to the keyboard.
    The system is rather practical, but to make the handling as transparent as possible : when I add my key row, I hide the keyboard with tv.endEditing(True), and I would like to make it reappear with my special key row : but I’ve not found a command as simple as tv.startEditing πŸ™ ; it’s perharps possible to simulate a touch in the TextView, but I neither can’t find a solution to do it πŸ₯Ά
    After several hours of searching, I throw in the towel and ask for help…πŸ₯΅

    from objc_util import *
    import ui
    from ui3.sfsymbol import *
    
    w = ObjCClass('UIApplication').sharedApplication().keyWindow()
    main_view = w.rootViewController().view()
    
    def get_toolbar(view):
        # get main editor toolbar, by recursively walking the view
        sv = view.subviews()
        for v in sv:
            if v._get_objc_classname().startswith(b'OMTabViewToolbar'):
                return v
            tb = get_toolbar(v)
            if tb:
                return tb
                
    # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    
    def keyboard_btn_action(sender):
        
        def run_script(scriptPath):
            import os
            from objc_util import ObjCInstance,ObjCClass
        
            dir = os.path.expanduser(scriptPath)
            I3=ObjCClass('PYK3Interpreter').sharedInterpreter()
            I3.runScriptAtPath_argv_resetEnvironment_(dir, [''], True)
    
        iCloudPath = "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents/"
        iPadPath = '~/Documents/'
        scriptPath = 'PROJETS/KEYBOARD/my_special_key_row.py'
        run_script(iCloudPath + scriptPath)
                
    # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    
    def create_keyboard_button(action,index=0):
        global __persistent_views
        
        assert(callable(action))
        tb = get_toolbar(main_view)
            
        try:
            __persistent_views
        except NameError:
            __persistent_views={}
            
        #check for existing button in this index and delete if needed
        remove_toolbar_button(index)    
        btn = ui.Button()
        btn.frame = (110, 24, 40, 40)
        
        if ui.get_ui_style() == 'dark':
            btn.tint_color = 'white' 
        else:
            btn.tint_color = '#0D89B5' 
        btn.image = SymbolImage('keyboard', point_size=14, weight=THIN, scale=SMALL)
        btn.image = btn.image.with_rendering_mode(ui.RENDERING_MODE_AUTOMATIC)
                
        btn.action=action
        btn_obj=ObjCInstance(btn)
        __persistent_views[index]=(btn,action)
        tb.superview().superview().addSubview_(btn_obj) # in front of all buttons
        
        return btn
        
    # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
        
    def remove_toolbar_button(index):
        global __persistent_views
        
        try:
            btn,action = __persistent_views.pop(index)
            btn.action= None
            ObjCInstance(btn).removeFromSuperview()
        except KeyError:
            pass
    
    # ===================================================================
    
    #if __name__=='__main__': # if imported by pythonista startup   
            
    create_keyboard_button(keyboard_btn_action) 
            
    create_keyboard_button(keyboard_btn_action)
    
    

    posted in Pythonista read more
  • Enez Houad

    Here is my scrolling special key row to replace the standard one.
    This script is a mix between @cvpe's script AddButtonsToPythonistaKeyboard https://github.com/cvpe/Pythonista-scripts/blob/master/AddButtonsToPythonistaKeyboard.py
    and my own work.
    It uses module ui3.sfsymbol of @mikaelho https://github.com/mikaelho/ui3
    Thanks for all their work for Pythonista's community.
    It certainly contains errors as I am not an expert coder like the majority of you but it does work for me πŸ˜‰
    Feel free to improve and adapt it to your needs!

    # =================================================================
    # This script is a mix between @cvpe's script AddButtonsToPythonistaKeyboard 
    # https://github.com/cvpe/Pythonista-scripts/blob/master/AddButtonsToPythonistaKeyboard.py
    # and my own work.
    # It uses module ui3.sfsymbol of @mikaelho
    # https://github.com/mikaelho/ui3
    # 
    # enez.houad@free.fr
    # =================================================================
    
    import ui, editor, clipboard
    from objc_util import *
    from ui3.sfsymbol import *
    
    @on_main_thread
    def tv_find(tv):
        import console, re
        
        tv.find = console.input_alert('Expression Γ  rechercher :', '', tv.find, hide_cancel_button=True)
        txt = tv.find
        
        for sv in tv.subviews():
            if 'SUIButton_PY3' in str(sv._get_objc_classname()):
                sv.removeFromSuperview()
        if txt == '':
            return
        t = str(tv.text())
        
        for m in re.finditer(txt, t):
            st,en = m.span()
            p1 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), st)
            p2 = tv.positionFromPosition_offset_(tv.beginningOfDocument(), en)
            rge = tv.textRangeFromPosition_toPosition_(p1,p2)
            rect = tv.firstRectForRange_(rge)
            x,y = rect.origin.x,rect.origin.y
            w,h = rect.size.width,rect.size.height
            
            l = ui.Button()
            l.frame = (x,y,w,h)
            if '|' not in txt:
                l.background_color = (1,0,0,0.2)
            else:
                # search multiple strings
                wrds = txt.split('|')
                idx = wrds.index(t[st:en])
                cols = [(1,0,0,0.2), (0,1,0,0.2), (0,0,1,0.2), (1,1,0,0.2), (1,0,1,0.2), (0,1,1,0.2)]
                col = cols[idx % len(cols)]
                l.background_color = col
            l.corner_radius = 4
            l.border_width = 1
            tv.addSubview_(l)       
        
    # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    
    def key_pressed(sender):
        
        tv = sender.objc_instance.firstResponder() # associated TextView  
        
        cursor = tv.offsetFromPosition_toPosition_(tv.beginningOfDocument(),     tv.selectedTextRange().start()) # get actual cursor position
    
        if sender.name == 'tab':
            tv.insertText_('\t')
        
        elif sender.name == 'paste':
            tv.insertText_(clipboard.get()) 
            
        elif sender.name == 'undo':
            tv.undoManager().undo()
            
        elif sender.name == 'redo':
            tv.undoManager().redo()
        
        elif sender.name == 'del_right':
            # delete at right = delete at left of next
            if cursor == (len(str(tv.text()))-1): # already after last character
                return
            cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor+1)
            tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position)
            tv.deleteBackward()     
            
        elif sender.name == 'find':
            tv_find(tv)
            
        elif sender.name == 'line-':
            tv.insertText_('# ' + 65 * 'β€”')
        elif sender.name == 'line=':
            tv.insertText_('# ' + 65 * '=')
        elif sender.name == 'line#':
            tv.insertText_(67 * '#')
            
        else: # all other keys > insert button title
            tv.insertText_(sender.title)
        
    # ===================================================================
        
    class SpecialKeyRow(ui.View):
        
        def __init__(self, pad, *args, **kwargs):
            
            self.pad = pad
        
            sw, sh = ui.get_screen_size()   
            self.uiStyle = ui.get_ui_style()
            
            self.buttonsList = []
            self.buttonWidth = (sw - (2*8) - (24*4)) / 25
            self.buttonHeight = 40
            
            # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
            # MAIN VIEW 
        
            self.width, self.height = sw, 50
            self.alpha = 0.98
            
            # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
            # SCROLL VIEW
            
            sv = ui.ScrollView(name='scrollview')
            sv.width, sv.height = (sw, 50)
            sv.content_size = (2*sw, 50)
            sv.bounces = False
            sv.shows_horizontal_scroll_indicator = False
            sv.paging_enabled = True
            sv.x, sv.y = (0, 0)
            colorDict = {'light':'#D6D8DD', 'dark':'#343639'}
            sv.background_color = colorDict[self.uiStyle]
            
            self.add_subview(sv)
            
            # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
            # BUTTONS IN SCROLL VIEW
            # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    
            for pad_elem in self.pad:
                if not 'style' in pad_elem: bStyle = 'light'
                else: bStyle = pad_elem['style']
                if 'title' in pad_elem:
                    b = self.add_text_button(name=pad_elem['key'], title=pad_elem['title'], style=bStyle)
                elif 'symbol' in pad_elem:
                    b = self.add_symbol_button(name=pad_elem['key'], symbol_name=pad_elem['symbol'], style=bStyle)
                self.add_scrollview_button(b)
            
        # ===================================================================
             
        def add_scrollview_button(self, b):
            b.y = 10
            if self.buttonsList == []: b.x = 8 # 1er bouton
            else:
                lastButton = self.buttonsList[-1]
                b.x = lastButton.x + lastButton.width + 4 # intervalle 4 px
                if len(self.buttonsList) == 25: b.x += 12 # 2e page
            b.action = key_pressed
            retain_global(b)
            self['scrollview'].add_subview(b)
            self.buttonsList.append(b)
                
        # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
        
        def add_text_button(self, name='', title='', width=40, style='light'):
            b = self.add_button(name, style)
            b.title = title
            b.font = ('<system>', 18)
            if width == None: b.width = ui.measure_string(b.title,font=b.font)[0] + 28
            else: b.width = self.buttonWidth        
            return b
            
        # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
        
        def add_symbol_button(self, name='', symbol_name='', style='light'):
            b = self.add_button(name, style)
            symbol_image = SymbolImage(symbol_name, point_size=11, weight=LIGHT, scale=SMALL)
            b.image = symbol_image  
            b.width = self.buttonWidth  
            return b
            
        # β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
        
        def add_button(self, name='', backgroundStyle='light'):
            
            b = ui.Button(name=name)
            b.corner_radius = 8
            
            colorsDict = {  'light' :({'light':'#FFFFFF', 'dark':'#B4B9C1'}, 'black'), 
                            'dark'  :({'light':'#717274', 'dark':'#4D4F50'}, 'white') }
            b.background_color = colorsDict[self.uiStyle][0][backgroundStyle]
            b.tint_color = colorsDict[self.uiStyle][1]
            
            b.alpha = self.alpha
            
            b.font = ('<system>', 18)
            b.height = self.buttonHeight        
            return b
                    
    # ===================================================================
    
    @on_main_thread
    def AddButtonsToPythonistaKeyboard(pad=None):
        
        def numeric_keys(): 
            list = []
            for i in range(1, 10):
                list.append({'key':str(i), 'title':str(i)})
            list.append({'key':'0', 'title':'0'})
            return list
            
        if not pad:     
            pad = [
                    {'key':'tab', 'symbol':'arrow.right.to.line.alt'},              
                
                    {'key':'undo', 'symbol':'arrow.uturn.left', 'style':'dark'},
                    {'key':'redo','symbol':'arrow.uturn.right', 'style':'dark'},
                    
                    {'key':'paste', 'symbol':'doc.on.clipboard'},
                
                    {'key':'#', 'title':'#'},
                    {'key':'_', 'title':'_'},
                
                    {'key':"'", 'title':"'"},
                    {'key':'"', 'title':'"'},
                    {'key':"'''", 'title':"'''"},
                
                    {'key':'(', 'title':'('},
                    {'key':')', 'title':')'},           
                    {'key':'[', 'title':'['},
                    {'key':']', 'title':']'},
                    {'key':'{', 'title':'{'},
                    {'key':'}', 'title':'}'},
                
                    {'key':'+', 'title':'+'},
                    {'key':'-', 'title':'-'},
                    {'key':'*', 'title':'*'},
                    {'key':'/', 'title':'/'},
                    {'key':"\\", 'title':"\\"},
                
                    {'key':'<', 'title':'<'},
                    {'key':'>', 'title':'>'},
                    {'key':'=', 'title':'='},
                    {'key':':', 'title':':'},
                
                    {'key':'del_right', 'symbol':'delete.right', 'style':'dark'},
                
                    {'key':'find', 'symbol':'magnifyingglass', 'style':'dark'}
                    ]
                    
            pad += numeric_keys() 
            
            pad += [
                    {'key':'+', 'title':'+'},
                    {'key':'-', 'title':'-'},
                    {'key':'*', 'title':'*'},
                    {'key':'/', 'title':'/'},
                    {'key':'<', 'title':'<'},
                    {'key':'>', 'title':'>'},
                    {'key':'=', 'title':'='},
                
                    {'key':'line-', 'title':'---'},
                    {'key':'line=', 'title':'==='},
                    {'key':'line#', 'title':'###'}
                    ]   
            
        ev = editor._get_editor_tab().editorView()
        tv = ev.textView()
        
        v = SpecialKeyRow(pad)                        
        vo = ObjCInstance(v)  
    
        retain_global(v)
        
        tv.setInputAccessoryView_(vo)   # attach accessory to textview
        tv.find = ''
        
    # ===================================================================
        
    if __name__ == '__main__':
        AddButtonsToPythonistaKeyboard() ```

    posted in Pythonista read more
  • Enez Houad

    @cvp Thank’s a lot Magic cvpπŸ‘πŸ‘πŸ‘ πŸ™

    posted in Pythonista read more
  • Enez Houad

    @cvp Thanks a lot for your work. But my goal is to get a reduced row of keys as I think that the original one is to large for the small screen of my iPad mini 4. I regret that it’s not possible to assign the fonction to a normal ui button.

    posted in Pythonista read more
  • Enez Houad

    @cvp Please, how do you insert directly your pictures in comments ?

    posted in Pythonista read more
  • Enez Houad

    The only solution I've found is to make my own special key row with the help of the cvp example ;-). It's quite easy for normal keys, but I don't find solution to implement the undo/redo key? Perhaps with objC ?

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!