Last active
May 19, 2023 14:54
-
-
Save sbbosco/be4d1a1b63ad5f983927fa0dacce712e to your computer and use it in GitHub Desktop.
Alternate dialogs module for Pythonista 3.4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
from threading import current_thread | |
from datetime import date, datetime | |
from dateutil.tz import tzutc, tzlocal | |
from objc_util import ObjCClass | |
import ui | |
""" | |
Alternate dialogs module for Pythonista 3.4 | |
modify import: | |
#import dialogs | |
from uidialogs import dialogs | |
""" | |
debuglevel = 0 | |
def dprint(*args): | |
if debuglevel > 0: | |
print('debug: ', args) | |
dprint('ui dialogs') | |
class waitModal(): | |
def __init__(self): | |
self.done = False | |
self.result = None | |
def wait(self): | |
waitcount = 0 | |
for n in range(10): | |
try: | |
time.sleep(1.0) | |
dprint('wait -|-') | |
if self.done: | |
dprint('modal waited') | |
break | |
waitcount += 1 | |
if waitcount == 10: | |
self.done = [-1, 'none', 'none'] | |
break | |
except: | |
print("Exception ",str(sys.exc_info())) | |
break | |
dprint('modal waited') | |
def set_result(self, value): | |
self.result = value | |
dprint('wait result', self.result) | |
self.done = True | |
NSIndexPath = ObjCClass('NSIndexPath') | |
class _FormView(ui.View): | |
def __init__(self): | |
self.delegate = None | |
class dialogs(): | |
def __init__(self): | |
pass | |
def form_dialog(title='', fields=[], sections=None, done_button_title='Done', frame=None, callback=None): | |
result = {} | |
form_title = title | |
done_title = done_button_title | |
if fields: | |
sections = [('', fields)] | |
xmark = ui.Image.named('iob:ios7_close_32') | |
class TextFieldDelegate (object): | |
def textfield_should_begin_editing(textfield): | |
result = did_begin(textfield) | |
return result | |
def textfield_did_end_editing(textfield): | |
result = did_edit(textfield) | |
return result | |
def close_view(sender, result=None): | |
wait.set_result(result) | |
form.close() | |
container.close() | |
time.sleep(.2) | |
def submit(sender): | |
dprint('submit') | |
parms = {} | |
f = 0 | |
for sec in sections: | |
fields = sec[1] | |
for i in range(len(fields)): | |
item = fields[i] | |
if not fields[i].get('key', None): | |
fields[i]['key'] = fields[i]['title'] | |
if item['type'] == 'switch': | |
parms[fields[i]['key']] = True if fld[f].value else False | |
elif item['type'] == 'list': | |
parms[fields[i]['key']] = int(fields[i]['id']) | |
elif item['type'] == 'date': | |
dateobj = fld[f].date | |
datestr = dateobj.strftime('%Y-%m-%d') | |
parms[fields[i]['key']] = datestr | |
elif item['type'] == 'int': | |
parms[fields[i]['key']] = fields[i]['value'] | |
elif item['type'] == 'textarea': | |
parms[fields[i]['key']] = str(fld[f].text) | |
elif item['type'] == 'check': | |
if fldvalues[f] > 0: | |
parms[fields[i]['key']] = True | |
else: | |
parms[fields[i]['key']] = False | |
else: | |
if item.get('hidden', False): | |
parms[fields[i]['key']] = fields[i]['value'] | |
else: | |
parms[fields[i]['key']] = str(fld[f].text) | |
f += 1 | |
if item.get('hidden', False): continue | |
close_view(None, parms) | |
if callback: | |
callback(parms) | |
def did_begin(sender): | |
dprint('begin', sender.tag) | |
item = sections[0][1][sender.tag] | |
print(item) | |
return True | |
def fromutc(dt): | |
dt_offset = dt.utcoffset() | |
dt_dst = dt.dst() | |
delta = dt_offset - dt_dst | |
if delta: | |
dt += delta | |
dtdst = dt.dst() | |
if dtdst: | |
return dt + dtdst | |
else: | |
return dt | |
def did_edit(sender): | |
dprint('end') | |
ui.end_editing() | |
def list_end(result): | |
dprint('end', result) | |
def tableview_cell_for_row(tableview, section, row): | |
if form.data[section][row][2] == 'check': | |
cell = ui.TableViewCell(style='default') | |
cell.text_label.text = form.data[section][row][1] | |
if fldvalues[form.data[section][row][0]] > 0: | |
cell.accessory_type = 'checkmark' | |
else: | |
cell.accessory_type = 'none' | |
return cell | |
else: | |
cell = ui.TableViewCell(style='value1') | |
cell.text_label.text = form.data[section][row][1] | |
cell.content_view.add_subview(form.data[section][row][2]) | |
return cell | |
def tableview_did_select(tableview, section, row): | |
if form.data[section][row][2] == 'check': | |
dprint('check') | |
if int(toggle_check(section, row)) > 0: | |
dprint('checked', form.data[section][row][0]) | |
fldvalues[form.data[section][row][0]] = 1 | |
else: | |
fldvalues[form.data[section][row][0]] = 0 | |
ui.end_editing() | |
form.selected_row = -1 | |
def tableview_number_of_sections(tableview): | |
return len(sections) | |
def tableview_title_for_header(tableview, section): | |
return sections[section][0] | |
def tableview_number_of_rows(tableview, section): | |
return secrows[section] | |
def toggle_check(section, row): | |
index_path = NSIndexPath.indexPathForRow(row, inSection=section) | |
cell = form.objc_instance.cellForRowAtIndexPath_(index_path) | |
if cell.accessoryType() == 0: | |
cell.setAccessoryType_(3) | |
else: | |
cell.setAccessoryType_(0) | |
return cell.accessoryType() | |
def kb_frame_will_change(f): | |
r = ui.convert_rect(f, to_view=container) | |
if r[3] > 0: | |
kbh = form.height - r[1] | |
else: | |
kbh = 0 | |
update_kb_height(kbh) | |
def update_kb_height(h): | |
form.content_inset = (0, 0, h, 0) | |
form.scroll_indicator_insets = (0, 0, h, 0) | |
container = _FormView() | |
form = ui.TableView() | |
ds = ui.ListDataSource([]) | |
form.data_source = form.delegate = ds | |
form.title = title | |
form.background_color = 'lightgray' | |
ds.tableview_cell_for_row = tableview_cell_for_row | |
ds.tableview_did_select = tableview_did_select | |
ds.tableview_number_of_sections = tableview_number_of_sections | |
ds.tableview_title_for_header = tableview_title_for_header | |
ds.tableview_number_of_rows = tableview_number_of_rows | |
container.keyboard_frame_will_change = kb_frame_will_change | |
tbldata = [] | |
if frame: | |
x, y, w, h = frame | |
dprint('frame', frame) | |
else: | |
winw, winh = ui.get_window_size() | |
if winw < 580 or winh < 640: | |
x, y, w, h = (0, 0, winw, winh) | |
else: | |
x, y, w, h = (0, 0, 580, 640) | |
dprint('auto', frame) | |
i = 0 | |
fld = [] | |
fldvalues = [] | |
fldidx = {} | |
secrows = [] | |
dprint('len', len(sections)) | |
for section in sections: | |
secdata = [] | |
for item in section[1]: | |
fld.append(0) | |
fldvalues.append(0) | |
if item.get('hidden', False): | |
i += 1 | |
continue | |
if item['type'] == 'textarea': | |
fld[i] = ui.TextView() | |
fld[i].text = item.get('value', '') | |
fld[i].tag = i | |
fld[i].font = ('Menlo', 14) | |
fld[i].frame = (125, 15, 250, 280) | |
elif item['type'] == 'switch': | |
fld[i] = ui.Switch() | |
fld[i].value = item.get('value', False) | |
fld[i].tag = i | |
#fld[i].frame = (125, 15, 100, 30) | |
elif item['type'] == 'date': | |
fld[i] = ui.DatePicker() | |
fld[i].mode = ui.DATE_PICKER_MODE_DATE | |
fld[i].date = item.get('value', datetime.today) | |
fld[i].tag = i | |
elif item['type'] == 'list': | |
fld[i] = ui.TextField() | |
fld[i].text = item.get('value', []) | |
fld[i].tag = i | |
fld[i].textfield_should_begin_editing = did_begin | |
elif item['type'] == 'decimal': | |
fld[i] = ui.TextField() | |
fld[i].text = item.get('value', '') | |
fld[i].tag = i | |
fld[i].keyboard_type = ui.KEYBOARD_DECIMAL_PAD | |
elif item['type'] == 'check': | |
fld[i] = 'check' | |
if item.get('value', None): | |
fldvalues[i] = 3 | |
elif item['type'] in ('text', 'url', 'email','number', 'password'): | |
fld[i] = ui.TextField() | |
fld[i].text = item.get('value', '') | |
fld[i].tag = i | |
fld[i].clear_button_mode = 'while_editing' | |
if item['type'] == 'text': | |
fld[i].autocorrection_type = item.get('autocorrection', None) | |
fld[i].autocapitalization_type = item.get('autocapitalization', ui.AUTOCAPITALIZE_SENTENCES) | |
fld[i].spellchecking_type = item.get('spellchecking', None) | |
elif item['type'] == 'url': | |
fld[i].keyboard_type = ui.KEYBOARD_URL | |
fld[i].autocapitalization_type = ui.AUTOCAPITALIZE_NONE | |
fld[i].autocorrection_type = False | |
fld[i].spellchecking_type = False | |
elif item['type'] == 'email': | |
fld[i].keyboard_type = ui.KEYBOARD_EMAIL | |
fld[i].autocapitalization_type = ui.AUTOCAPITALIZE_NONE | |
fld[i].autocorrection_type = False | |
fld[i].spellchecking_type = False | |
elif item['type'] == 'number': | |
#fld[i].keyboard_type = ui.KEYBOARD_NUMBERS | |
fld[i].keyboard_type = ui.KEYBOARD_NUMBER_PAD | |
fld[i].autocapitalization_type = ui.AUTOCAPITALIZE_NONE | |
fld[i].autocorrection_type = False | |
fld[i].spellchecking_type = False | |
elif item['type'] == 'password': | |
fld[i].secure = True | |
if not item['type'] in ('check', 'textarea'): | |
if len(item['title']) > 24: | |
fld[i].frame = (260, 6, w - 275, 32) | |
elif len(item['title']) > 5: | |
fld[i].frame = (140, 6, w - 155 , 32) | |
else: | |
fld[i].frame = (120, 6, w - 135 , 32) | |
secdata.append([i, item['title'], fld[i]]) | |
i += 1 | |
tbldata.append(secdata) | |
secrows.append(len(secdata)) | |
form.data = tbldata | |
ds.items = tbldata | |
form.name = form_title | |
container.left_button_items = [ui.ButtonItem(image=xmark, action=close_view)] | |
container.right_button_items = [ui.ButtonItem(title=done_title, action=submit)] | |
form.frame = (0, 0, w, h) | |
form.flex = 'WH' | |
container.frame = (0, 0, w, h) | |
container.flex = 'WH' | |
container.add_subview(form) | |
container.present('sheet', hide_close_button=True) | |
dprint('present') | |
dprint(current_thread().name) | |
wait = waitModal() | |
form.wait_modal() | |
return wait.result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment