+ s.set_events(s.get_events() | gtk.gdk.KEY_PRESS_MASK)
+ def key(list, ev):
+ if len(ev.string) == 1:
+ self.gotsym(ev.string)
+ elif ev.keyval == 65288:
+ self.gotsym('<BS>')
+ else:
+ #print ev.keyval, len(ev.string), ev.string
+ pass
+ s.connect('key_press_event', key)
+ s.set_flags(gtk.CAN_FOCUS)
+ s.grab_focus()
+
+ v = gtk.VBox(); v.show()
+ v.pack_start(s, expand=True)
+ l = gtk.Label('')
+ l.modify_font(self.fd)
+ self.number_label = l
+ v.pack_start(l, expand=False)
+ return v
+
+ def editui(self):
+ ui = gtk.VBox()
+
+ self.fields = {}
+ self.field(ui, 'Name')
+ self.field(ui, 'Number')
+ self.field(ui, 'Speed Number')
+ return ui
+
+ def field(self, v, lbl):
+ h = gtk.HBox(); h.show()
+ l = gtk.Label(lbl); l.show()
+ l.modify_font(self.fd)
+ h.pack_start(l, expand=False)
+ e = gtk.Entry(); e.show()
+ e.modify_font(self.fd)
+ h.pack_start(e, expand=True)
+ e.connect('changed', self.field_update, lbl)
+ v.pack_start(h, expand=True, fill=True)
+ self.fields[lbl] = e
+ return e
+
+ def buttonlist(self, v):
+ b = gtk.HBox()
+ b.set_homogeneous(True)
+ b.hide()
+ v.pack_end(b, expand=False)
+ return b
+
+ def button(self, bl, label, func):
+ b = gtk.Button()
+ if label[0:3] == "gtk" :
+ img = gtk.image_new_from_stock(label, self.isize)
+ img.show()
+ b.add(img)
+ else:
+ b.set_label(label)
+ b.child.modify_font(self.fd)
+ b.show()
+ b.connect('clicked', func)
+ b.set_focus_on_click(False)
+ bl.pack_start(b, expand = True)
+
+ def close_win(self, widget):
+ gtk.main_quit()
+
+ def selected(self, list, item):
+ self.buttons.hide_some()
+
+ if item == None:
+ item = -1
+ if self.clist.show_deleted:
+ if item < 0 or (item == 0 and self.clist.str != ''):
+ self.del_none.show()
+ else:
+ self.del_sel.show()
+ i = self.clist.getitem(item)
+ self.current = i
+ elif item < 0:
+ self.list_none.show()
+ self.number_label.hide()
+ self.current = None
+ elif item == 0 and self.clist.str != '':
+ self.list_new.show()
+ self.number_label.hide()
+ self.current = None
+ else:
+ self.list_sel.show()
+ i = self.clist.getitem(item)
+ self.current = i
+ if i == None:
+ self.number_label.hide()
+ else:
+ self.number_label.set_text(self.list[i][1])
+ self.number_label.show()
+
+ def field_update(self, ev, fld):
+ if self.flds[fld] == self.fields[fld].get_text():
+ self.fields[fld].modify_base(gtk.STATE_NORMAL,None)
+ else:
+ self.fields[fld].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('yellow'))
+
+ same = True
+ for i in ['Name', 'Number', 'Speed Number']:
+ if self.fields[i].get_text() != self.flds[i]:
+ same = False
+ self.buttons.hide_some()
+ if self.current == None:
+ self.edit_new.show()
+ elif same:
+ self.edit_nil.show()
+ else:
+ self.edit_old.show()
+ pass
+
+ def load_book(self, file):
+ try:
+ f = open(file)
+ self.fname = file
+ except:
+ f = open('/home/neilb/home/mobile-numbers-jan-08')
+ self.fname = '/home/neilb/home/mobile-numbers-jan-08'
+ rv = []
+ speed = {}
+ for l in f:
+ x = l.split(';')
+ if len(x[0]) == 1:
+ speed[x[1]] = x[0]
+ else:
+ rv.append([x[0],x[1], ''])
+ if speed:
+ for i in range(len(rv)):
+ if rv[i][0] in speed:
+ rv[i][2] = speed[rv[i][0]]
+ rv.sort(lambda x,y: cmp(x[0].lower(),y[0].lower()))
+ self.list = rv
+ self.clist.set_list(rv)
+
+ def save_book(self):
+ try:
+ f = open(self.fname + '.new', 'w')
+ except:
+ return
+ for e in self.list:
+ name,num,speed = e
+ f.write(name+';'+num+';\n')
+ if speed:
+ f.write(speed+';'+name+';\n')
+ f.close()
+ os.rename(self.fname+'.new', self.fname)
+
+ def queue_save(self):
+ if self.timer:
+ gobject.source_remove(self.timer)
+ self.timer = gobject.timeout_add(15*1000, self.do_save)
+ def do_save(self):
+ if self.timer:
+ gobject.source_remove(self.timer)
+ self.timer = None
+ self.save_book()
+
+ def gotsym(self,sym):
+ if sym == '<BS>':
+ s = self.clist.str[:-1]
+ elif len(sym) > 1:
+ s = self.clist.str
+ elif ord(sym) >= 32:
+ s = self.clist.str + sym
+ else:
+ return
+ self.clist.set_str(s)
+ self.sel.list_changed()
+ self.sel.select(None)
+
+ def open(self, ev):
+ self.lst.hide()
+ self.ed.show()
+
+ self.buttons.hide_some()
+ if self.current == None:
+ self.edit_new.show()
+ else:
+ self.edit_nil.show()
+ self.flds = {}
+ self.flds['Name'] = ''
+ self.flds['Number'] = ''
+ self.flds['Speed Number'] = ''
+ if self.current != None:
+ self.flds['Name'] = self.list[self.current][0]
+ self.flds['Number'] = self.list[self.current][1]
+ self.flds['Speed Number'] = self.list[self.current][2]
+ elif self.clist.str:
+ self.flds['Name'] = self.clist.str
+
+ for f in ['Name', 'Number', 'Speed Number'] :
+ self.fields[f].set_text(self.flds[f])
+ self.fields[f].modify_base(gtk.STATE_NORMAL,None)
+
+ def all(self, ev):
+ self.clist.set_str('')
+ self.clist.show_deleted = False
+ self.sel.select(None)
+ self.sel.list_changed()
+ pass
+ def create(self, ev):
+ self.save(None)
+ def save(self,ev):
+ name = self.fields['Name'].get_text()
+ num = self.fields['Number'].get_text()
+ speed = self.fields['Speed Number'].get_text()
+ if name == '' or name.find(';') >= 0:
+ self.fields['Name'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('pink'))
+ return
+ if num == '' or num.find(';') >= 0:
+ self.fields['Number'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('pink'))
+ return
+ if len(speed) > 1 or speed.find(';') >= 0:
+ self.fields['Speed Number'].modify_base(gtk.STATE_NORMAL,gtk.gdk.color_parse('pink'))
+ return
+ if self.current == None or ev == None:
+ self.list.append([name, num, speed])
+ else:
+ self.list[self.current] = [name, num, speed]
+ self.flds['Name'] = name
+ self.flds['Number'] = num
+ self.flds['Speed Number'] = speed
+ self.list.sort(lambda x,y: cmp(x[0].lower(),y[0].lower()))
+ self.clist.set_list(self.list)
+ self.sel.list_changed()
+ self.close(ev)
+ self.queue_save()
+ pass
+
+ def delete(self, ev):
+ if self.current != None:
+ n = self.list[self.current][0]
+ if n[:8] == '!deleted':
+ p = n.find('-')
+ if p <= 0:
+ p = 7
+ n = n[p+1:]
+ else:
+ n = time.strftime('!deleted.%Y.%m.%d-') + n
+ self.list[self.current][0] = n
+ self.list.sort(lambda x,y: cmp(x[0].lower(),y[0].lower()))
+ self.clist.set_list(self.list)
+ self.sel.list_changed()
+ self.close(ev)
+ self.queue_save()
+ pass
+
+ def undelete(self, ev):
+ self.clist.show_deleted = True
+ self.clist.set_str('')
+ self.sel.list_changed()
+ self.sel.select(None)
+ pass
+ def call(self, ev):
+ pass
+ def sms(self, ev):
+ pass
+ def close(self, ev):
+ self.lst.show()
+ self.sel.grab_focus()
+ self.ed.hide()
+ if self.current != None and self.current >= len(self.clist):
+ self.current = None
+ self.selected(None, self.sel.selected)
+
+class contact_list:
+ def __init__(self):
+ self.list = []
+ self.match_start = []
+ self.match_word = []
+ self.match_any = []
+ self.deleted = []
+ self.valid = []
+ self.match_str = ''
+ self.match_deleted = False
+ self.str = ''
+ self.show_deleted = False
+ def set_list(self, list):
+ self.list = list
+ self.match_str = ''
+ self.deleted = []
+ self.valid = []
+ for i in range(len(self.list)):
+ name,number,speed = self.list[i]
+ name = name.lower()
+ if name[:8] == '!deleted':
+ self.deleted.append(i)
+ else:
+ self.valid.append(i)
+
+ def set_str(self,str):
+ self.str = str
+
+ def recalc(self):
+ if self.str == self.match_str and self.show_deleted == self.match_deleted:
+ return
+ if self.match_str != '' and self.str[:len(self.match_str)] == self.match_str and self.show_deleted == self.match_deleted:
+ # str is a bit longer
+ self.recalc_quick()
+ return
+ self.match_start = []
+ self.match_word = []
+ self.match_any = []
+ self.match_str = self.str
+ self.match_deleted = self.show_deleted
+ s = self.str.lower()
+ l = len(self.str)
+ for i in self.deleted if self.match_deleted else self.valid:
+ name,number,speed = self.list[i]
+ name = name.lower()
+ if name[0:l] == s:
+ self.match_start.append(i)
+ elif name.find(' '+s) >= 0:
+ self.match_word.append(i)
+ elif name.find(s) >= 0:
+ self.match_any.append(i)
+ self.total = len(self.match_start) + len(self.match_word) + len(self.match_any)
+
+ def recalc_quick(self):
+ # The string has been extended so we only look through what we already have
+ self.match_str = self.str
+ s = self.str.lower()
+ l = len(self.str)
+
+ lst = self.match_start
+ self.match_start = []
+ for i in lst:
+ name,number,speed = self.list[i]
+ name = name.lower()
+ if name[0:l] == s:
+ self.match_start.append(i)
+ else:
+ self.match_word.append(i)
+ self.match_word.sort()
+ lst = self.match_word
+ self.match_word = []
+ for i in lst:
+ name, number, speed = self.list[i]
+ name = name.lower()
+ if name.find(' '+s) >= 0:
+ self.match_word.append(i)
+ else:
+ self.match_any.append(i)
+ self.match_any.sort()
+ lst = self.match_any
+ self.match_any = []
+ for i in lst:
+ name, number, speed = self.list[i]
+ name = name.lower()
+ if name.find(s) >= 0:
+ self.match_any.append(i)
+ self.total = len(self.match_start) + len(self.match_word) + len(self.match_any)
+
+ def __len__(self):
+ self.recalc()
+ if self.str == '':
+ if self.match_deleted:
+ return len(self.deleted)
+ else:
+ return len(self.valid)
+ else:
+ return self.total + 1
+ def getitem(self, ind):
+ if ind < 0:
+ print '!!!!', ind
+ if self.str == '':
+ if self.match_deleted:
+ return self.deleted[ind]
+ else:
+ return self.valid[ind]