Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello β I'm @olemoritz on Twitter.
Pythonista special key row problems in IOS 14
-
It appears IpadOS 14 broke the special key row in Pythonista. After editing for a short while the center section of keys disappears. A while later the remaining keys shrink further to the sides. It also appears the cursor positioning by sliding over the key row does not work in the center portion, even when the keys are still showing.
-
@dthomson, looks like something related to the split keyboard option on iPadOS. How does that work if you try to use it on purpose?
-
I got sometimes the same problem and it does not look like the split keyboard, only the supplementary row.
The problem occurs when I run a script in a editor's tab where the keyboard is visible.
But not in other tabs, or not if I run a script where the keyboard is hidden. -
Has someone found a solution ? π₯΅ the problem appears quite all the time for me and itβs really difficult to type text in rhe reduced special key row - Iβve got an iPad mini and the keyboard is small ;-)
-
@Enez-Houad no solution found, except if I restart Pythonista π’
-
I turned on and off the βExtra Key Rowβ option in the βSettings>Keyboard and Typingβ option.seems to fix it if it happens.Annoying though!
-
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 ?
-
My new special key row !
-
@cvp Please, how do you insert directly your pictures in comments ?
-
@Enez-Houad I use
import pyimgur,photos,clipboard,os,console i=photos.pick_image() if i: print(i.format) format = 'gif' if (i.format == 'GIF') else 'jpg' i.save('img.'+format) clipboard.set(pyimgur.Imgur("303d632d723a549").upload_image('img.'+format, title="Uploaded-Image").link) console.hud_alert("link copied!") os.remove('img.'+format)
With pyImgur from here
-
@Enez-Houad I don't know which code of mines you use to add keys to Pythonista keyboard, but you can add these lines at end to replace the extra row of Pythonista by only undo and redo keys...
And that after 3 full hours of searching π. . . . @on_main_thread def AddButtonsToPythonistaKeyboard(pad=None): if not pad: pad = [ {'key':'next word','width':2}, {'key':'find','icon':'iob:ios7_search_32'}, {'key':'nul'}, {'key':'>'}, # {'key':'new row'}, {'key':'nul'}, {'key':'nul'}, {'key':'#'}, {'key':'nul'}, {'key':'"'}, {'key':'nul'}, {'key':'left','icon':'iob:arrow_left_a_32'}, {'key':'right','icon':'iob:arrow_right_a_32'}, {'key':'down','icon':'iob:arrow_down_a_32'}, {'key':'\\'}, {'key':'nul'}, {'key':'delete','title':'Del'}] ev = editor._get_editor_tab().editorView() tv = ev.textView() #print(tv._get_objc_classname()) #print(dir(tv)) # create ui.View for InputAccessoryView above keyboard v = MyView(pad) # view above keyboard vo = ObjCInstance(v) # get ObjectiveC object of v retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view tv.setInputAccessoryView_(vo) # attach accessory to textview tv.strfind = '' #====================== UIBarButtonItem = ObjCClass('UIBarButtonItem') UIBarButtonItemGroup = ObjCClass('UIBarButtonItemGroup') def btnActionUndo(_self, _cmd): tv = ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder() tv.undoManager().undo() ActionTargetUndo = create_objc_class('ActionTarget', methods=[btnActionUndo]) targetUndo = ActionTargetUndo.new().autorelease() bUndo = UIBarButtonItem.alloc().initWithTitle_style_target_action_('βͺοΈ', 0, targetUndo, 'btnActionUndo').autorelease() def btnActionRedo(_self, _cmd): tv = ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder() tv.undoManager().redo() ActionTargetRedo = create_objc_class('ActionTarget', methods=[btnActionRedo]) targetRedo = ActionTargetRedo.new().autorelease() bRedo = UIBarButtonItem.alloc().initWithTitle_style_target_action_('β©οΈ', 0, targetRedo, 'btnActionRedo').autorelease() group = UIBarButtonItemGroup.alloc().initWithBarButtonItems_representativeItem_([bUndo, bRedo], None).autorelease() ObjCInstance(tv).inputAssistantItem().leadingBarButtonGroups = [group] ObjCInstance(tv).inputAssistantItem().trailingBarButtonGroups = [] #====================== if __name__ == '__main__': AddButtonsToPythonistaKeyboard()
-
@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.
-
@Enez-Houad said:
. I regret that itβs not possible to assign the fonction to a normal ui button.
I think it is also possible, let me some time today
-
@Enez-Houad much easier, if I would know π
import editor from objc_util import * import ui @on_main_thread def test(tv): import console import re import ui tv.strfind = console.input_alert('text or regex to search', '', tv.strfind, hide_cancel_button=True) txt = tv.strfind for sv in tv.subviews(): if 'SUIButton_PY3' in str(sv._get_objc_classname()): sv.removeFromSuperview() if txt == '': return t = str(tv.text()) #print('search',txt,'in',t) #for m in re.finditer('(?i)'+txt, t): 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) # CGRect x,y = rect.origin.x,rect.origin.y w,h = rect.size.width,rect.size.height #print(x,y,w,h) 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): import ui from objc_util import ObjCClass tv = sender.objc_instance.firstResponder() # associated TextView # get actual cursor position cursor = tv.offsetFromPosition_toPosition_(tv.beginningOfDocument(), tv.selectedTextRange().start()) if sender.name == 'left': if cursor == 0: return # already first character cursor = cursor - 1 elif sender.name == 'right': if cursor == (len(str(tv.text()))-1): return # already after last character cursor = cursor + 1 elif sender.name == 'down': # surely not correct because not tested in limit cases, # just to show for topic https://forum.omz-software.com/topic/6408/defining-a-line-up-line-down-keyboard-function # count position in line c = str(tv.text()).rfind('\n',0,cursor) # begin of current line p = cursor - c e = str(tv.text()).find('\n',cursor) # end of current line cursor = e + 1 # begin of next line e = str(tv.text()).find('\n',cursor) # end of next line cursor = cursor + min(p-1,e-cursor) elif sender.name == 'next word': t = str(tv.text())[cursor+1:] for i in range(0,len(t)): # search 1st separator if t[i] in ' _.\n\t': # search 1st not separator ch_found = False for j in range(i+1,len(t)): if t[j] not in ' _.\n\t': ch_found = True cursor = cursor + 1 + j break if ch_found: break elif sender.name == 'delete': # delete at right = delete at left of next character if cursor == (len(str(tv.text()))-1): return # already after last character cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor+1) tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position) tv.deleteBackward() elif sender.name == 'find': test(tv) elif sender.name == 'undo': #tv = ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder() tv.undoManager().undo() elif sender.name == 'redo': tv.undoManager().redo() else: # normal key tv.insertText_(sender.title) return # set cursor cursor_position = tv.positionFromPosition_offset_(tv.beginningOfDocument(), cursor) tv.selectedTextRange = tv.textRangeFromPosition_toPosition_(cursor_position, cursor_position) class MyView(ui.View): def __init__(self, pad, *args, **kwargs): #super().__init__(self, *args, **kwargs) self.width = ui.get_screen_size()[0] # width of keyboard = screen self.background_color = 'lightgray'#(0,1,0,0.2) self.h_button = 32 self.pad = pad #================================================ for the fun begin # cable for road self.road = ui.Label() self.road.frame = (0,40,self.width,1) self.road.border_width = 1 self.road.border_color = 'green' self.road.flex = 'W' self.add_subview(self.road) # cable for tramway self.line = ui.Label() self.line.frame = (0,12,self.width,1) self.line.border_width = 1 self.line.border_color = 'gray' self.line.flex = 'W' self.line.hidden = True self.add_subview(self.line) # moving emoji behind buttons self.moving = ui.Button() self.moving.font = ('<system>',self.h_button-4) self.moving.frame = (0,10,self.h_button,self.h_button) self.moving.icons = ['emj:Delivery_Truck', 'emj:Car_1','emj:Car_2', 'emj:Bus', 'emj:Police_Car', 'emj:Railway_Car','emj:Speedboat'] self.moving.action = self.fun self.moving.index = 0 self.add_subview(self.moving) self.update_interval = 0.06 #================================================ for the fun end # build buttons for pad_elem in self.pad: if pad_elem['key'] in ('nul', 'new row'): # free space or new row continue button = ui.Button() # Button for user functionnality button.name = pad_elem['key'] button.background_color = 'white' # or any other color button.tint_color = 'black' button.corner_radius = 5 button.font = ('<system>',self.h_button - 8) button.title = '' if 'title' in pad_elem: button.title = pad_elem['title'] elif 'icon' in pad_elem: button.image = ui.Image.named(pad_elem['icon']).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL) else: button.title = pad_elem['key'] button.action = key_pressed retain_global(button) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view self.add_subview(button) self.layout() #================================================ for the fun begin def fun(self,sender): self.update_interval = 0.06 - self.update_interval def update(self): import ui x = self.moving.x - 5 if x < -self.moving.width: x = ui.get_screen_size()[0] self.moving.index = self.moving.index+1 if self.moving.index == len(self.moving.icons): self.moving.index = 0 emoji = self.moving.icons[self.moving.index] self.moving.image = ui.Image.named(emoji).with_rendering_mode(ui.RENDERING_MODE_ORIGINAL) self.line.hidden = not (emoji == 'emj:Railway_Car') self.road.border_color = 'blue' if emoji == 'emj:Speedboat' else 'green' self.moving.x = x #================================================ for the fun end def layout(self): import ui #print('layout') # supports changing orientation #print(ui.get_screen_size()) dx = 8 dy = 2 x0 = 15 y0 = 10 dx_middle = 25 y = y0 x = x0 w_button = (ui.get_screen_size()[0] - 2*x0 - 17*dx - dx_middle)/18 for pad_elem in self.pad: nw = pad_elem.get('width', 1) wb = w_button*nw + dx*(nw-1) if (x + wb + dx) > self.width: y = y + self.h_button + dy x = x0 if pad_elem['key'] == 'nul': # let free space x = x + wb + dx continue elif pad_elem['key'] == 'new row': # new row y = y + self.h_button + dy x = x0 continue button = self[pad_elem['key']] xb = x + dx_middle if (x+wb) > self.width/2 else x button.frame = (xb,y,wb,self.h_button) if button.title != '': font_size = self.h_button - 8 while True: d = ui.measure_string(button.title,font=(button.font[0],font_size))[0]+4 if d <= wb: break font_size = font_size - 1 button.font = (button.font[0],font_size) x = x + wb + dx self.height = y + self.h_button + dy @on_main_thread def AddButtonsToPythonistaKeyboard(pad=None): if not pad: pad = [ {'key':'undo','title':'βͺοΈ'}, {'key':'redo','title':'β©οΈ'}, {'key':'next word','width':2}, {'key':'find','icon':'iob:ios7_search_32'}, {'key':'nul'}, {'key':'>'}, # {'key':'new row'}, # {'key':'nul'}, # {'key':'nul'}, {'key':'#'}, {'key':'nul'}, {'key':'"'}, {'key':'nul'}, {'key':'left','icon':'iob:arrow_left_a_32'}, {'key':'right','icon':'iob:arrow_right_a_32'}, {'key':'down','icon':'iob:arrow_down_a_32'}, {'key':'\\'}, {'key':'nul'}, {'key':'delete','title':'Del'}] ev = editor._get_editor_tab().editorView() tv = ev.textView() #print(tv._get_objc_classname()) #print(dir(tv)) # create ui.View for InputAccessoryView above keyboard v = MyView(pad) # view above keyboard vo = ObjCInstance(v) # get ObjectiveC object of v retain_global(v) # see https://forum.omz-software.com/topic/4653/button-action-not-called-when-view-is-added-to-native-view tv.setInputAccessoryView_(vo) # attach accessory to textview tv.strfind = '' if __name__ == '__main__': AddButtonsToPythonistaKeyboard()
-
@cvp Thankβs a lot Magic cvpπππ π
-
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() ```
-
@Enez-Houad Good job. I let real Python specialists like @ccc, @mikael and other ones advice you about Python it-self, they are far ahead of me
For those who want to see the keyboard
And even horizontally scroll this first row, whaaaa
-
@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 withtv.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)
-
@Enez-Houad try
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) @on_main_thread def disp_kbd(): from editor import _get_editor_tab tab = _get_editor_tab() if tab: tab.editorView().textView().becomeFirstResponder() disp_kbd()
-
@Enez-Houad said:
my/your script to add a keyboard icon in the titlebar
I must admit with humulity that the most complex part of this code comes from @JonB π€«