# Copyright (C) 2004 Henning Jacobs # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # $Id: JournalEditWidget.py 82 2004-07-11 13:01:44Z henning $ from Tkinter import * import Pmw import string import debug import IconImages import broadcaster import broker from AbstractJournalView import AbstractJournalView import ToolTip PADX = PADY = 1 # stores the handle of the journal under edit: affectedJournal = None def _broadcast_journal_modify(): broadcaster.Broadcast('Journal', 'Modified', {'handle':affectedJournal}, onceonly=1) currentEditControl = None def _setcurrentEditControl(event): global currentEditControl currentEditControl = event.widget import InputWidgets from InputWidgets import MultiRecordEdit class DateEdit(InputWidgets.DateEdit): def __init__(self, master, **kws): InputWidgets.DateEdit.__init__(self, master, **kws) self.add_save_hook(_broadcast_journal_modify) self.component('entry').bind('', _setcurrentEditControl) class TimeWrapperVar: "Wraps a vC_datetime var" def __init__(self, datetime): self.datetime = datetime def set(self, time): self.datetime.setTime(time) def get(self): return self.datetime.getTime() class DateWrapperVar: "Wraps a vC_datetime var" def __init__(self, datetime): self.datetime = datetime def set(self, date): self.datetime.setDate(date) def get(self): return self.datetime.getDate() class TimeEdit(InputWidgets.TimeEdit): def __init__(self, master, **kws): InputWidgets.TimeEdit.__init__(self, master, **kws) self.add_save_hook(_broadcast_journal_modify) class MemoEdit(InputWidgets.MemoEdit): def __init__(self, master): InputWidgets.MemoEdit.__init__(self, master) self.add_save_hook(_broadcast_journal_modify) self.bind('', _setcurrentEditControl) class TextEdit(InputWidgets.TextEdit): def __init__(self, master, **kws): InputWidgets.TextEdit.__init__(self, master, **kws) self.add_save_hook(_broadcast_journal_modify) self.bind('', _setcurrentEditControl) class TextComboEdit(InputWidgets.TextComboEdit): def __init__(self, master, **kws): InputWidgets.TextComboEdit.__init__(self, master, **kws) self.add_save_hook(_broadcast_journal_modify) self.component('entry').bind('', _setcurrentEditControl) class MultiSelectButtons(InputWidgets.MultiSelectButtons): def __init__(self, master, buttondefs, icons, iconsgrey): InputWidgets.MultiSelectButtons.__init__(self, master, buttondefs, icons, iconsgrey) self.add_save_hook(_broadcast_journal_modify) class UTCOffsetPropEdit(InputWidgets.AbstractSingleVarEdit, Pmw.EntryField): import re _utcoffsetregex = re.compile('[-+][0-2][0-9]:[0-5][0-9]') def __init__(self, master, title, descr): InputWidgets.AbstractSingleVarEdit.__init__(self) Pmw.EntryField.__init__(self, master, entry_width = 10, entry_justify = LEFT, value = "+00:00", validate = {'validator' : self.validate}, modifiedcommand=self.save) ToolTip.ToolTip(self, descr) def validate(self, str): if str: if not str[0] in "0123456789+-:": return 0 #ERROR elif self._utcoffsetregex.match(str) is None: return -1 #PARTIAL else: return 1 #OK else: return -1 #PARTIAL def get(self): return self.getvalue() # inherited from Pmw.EntryField def set(self, val): self.setvalue(val) class LatLongPropEdit(InputWidgets.AbstractSingleVarEdit, Frame): def __init__(self, master, title, descr): InputWidgets.AbstractSingleVarEdit.__init__(self) Frame.__init__(self, master) self.edtLat = Pmw.EntryField(self, entry_width = 8, entry_justify = LEFT, value = "0.0", validate = {'validator' : 'real', 'min':-90.0,'max':90.0}, modifiedcommand=self.save) ToolTip.ToolTip(self.edtLat, "Latitude as Float (53.5)") self.edtLat.grid(row=0, column=0) self.edtLon = Pmw.EntryField(self, entry_width = 8, entry_justify = LEFT, value = "0.0", validate = {'validator' : 'real', 'min':-90.0,'max':90.0}, modifiedcommand=self.save) ToolTip.ToolTip(self.edtLon, "Longitude as Float (10.0)") self.edtLon.grid(row=0, column=1) def clear(self): self.edtLat.clear() self.edtLon.clear() def get(self): ret= str(self.edtLat.getvalue())+";"+str(self.edtLon.getvalue()) if ret==";": ret = "" return ret def set(self, val): parts = val.split(";") if len(parts)<2: parts = ["",""] self.edtLat.setvalue(parts[0]) self.edtLon.setvalue(parts[1]) class URLEdit(Pmw.Group): def __init__(self, master): Pmw.Group.__init__(self, master, tag_text = "URL") master = self.interior() self.edtURL = TextEdit(master) self.edtURL.add_save_hook(self.updatestate) self.btnGotoURL = Button(master, command=self.gotoURL, image=IconImages.IconImages["webbrowser"], state=DISABLED) self.btnGotoURL.bind("", self.updatestate) master.columnconfigure(0, weight=1) master.rowconfigure(0, weight=1) self.edtURL.grid(sticky=W+E+S+N, padx=PADX, pady=PADY) self.btnGotoURL.grid(row=0, column=1, padx=PADX, pady=PADY) def gotoURL(self): import webbrowser webbrowser.open(self.edtURL.get(), 1) def updatestate(self, event=None): if self.edtURL.get(): self.btnGotoURL["state"] = NORMAL else: self.btnGotoURL["state"] = DISABLED def bindto(self, var): self.edtURL.bindto(var) self.updatestate() class AttendeeEdit(MultiRecordEdit): from vcalendar import vC_attendee def __init__(self, master): MultiRecordEdit.__init__(self, master, self.vC_attendee, "Attendees", "Attendee") defaultlabel = "*Click here to add current contact as attendee*" def createBody(self): master = self.body self.__lblContact = Label(master, cursor='hand2', text=self.defaultlabel) self.__lblContact.grid(column=0,row=1,sticky=W+E) self.__lblContact.bind('<1>', self.onMouseClick) def onRecordAdd(self, rec): contact = broker.Request('Current Contact') # Assign Attendee's Values from vCard: rec.assignFromCard(contact) if not contact.uid.is_empty(): uid = "[%s]" % (contact.uid.get()) else: uid = '' self.__lblContact["text"] = "%s <%s> %s" % (contact.fn.get(), rec.get(), uid) _broadcast_journal_modify() def onRecordDel(self): if self.state == DISABLED: self.bindtorec(None) _broadcast_journal_modify() def onMouseClick(self, event=None): if self.state == DISABLED: self._AddRecord() elif self._attendee_uid or self._attendee_fn: broadcaster.Broadcast('Journal', 'Attendee Clicked', data={'uid':self._attendee_uid, 'fn':self._attendee_fn}) _attendee_uid = None _attendee_fn = None def bindtorec(self, rec): if rec is None: self._attendee_uid = None self.__lblContact["text"] = self.defaultlabel else: fn = rec.params.get('cn') if fn is None: fn = "" else: fn = fn[0] uid = rec.getUID() if not uid: uidstr = "" else: uidstr = "[%s]" % uid self._attendee_uid = uid self._attendee_fn = fn self.__lblContact["text"] = "%s <%s> %s" % (fn, rec.get(), uidstr) class JournalEditWidget(AbstractJournalView, Frame): def __init__(self, master, **kws): AbstractJournalView.__init__(self, **kws) Frame.__init__(self, master, class_="JournalEdit") self.__createWidgets() # Catch every Mouse-Click: self.bind_all('<1>', self.__EditControlSave) self.bind_all('<2>', self.__EditControlSave) self.bind_all('<3>', self.__EditControlSave) def __EditControlSave(self, event=None): if currentEditControl: try: currentEditControl.save() except: pass def bind_journal(self, journal): global affectedJournal if journal: affectedJournal = journal.handle() else: affectedJournal = None AbstractJournalView.bind_journal(self, journal) self.rebindWidgets() def rebindWidgets(self): self.edtDateStart.bindto(DateWrapperVar(self._journal.dtstart)) self.edtTimeStart.bindto(TimeWrapperVar(self._journal.dtstart)) self.edtTimeEnd.bindto(TimeWrapperVar(self._journal.dtend)) self.edtSummary.bindto(self._journal.summary) self.edtCategories.bindto(self._journal.categories) self.edtLocation.bindto(self._journal.location) self.edtDescr.bindto(self._journal.description) self.edtAttendee.bindto(self._journal.attendee) self.lblRev["text"] = "Created: %s Last-Modification: %s" % (self._journal.created.get(), self._journal.last_mod.get()) def _onTimeEndSave(self): if self._journal.dtend.getTime(): # If End-Time is set: # Set End-Date to Start-Date: self._journal.dtend.setDate(self._journal.dtstart.getDate()) else: self._journal.dtend.set(None) def __createWidgets(self): self.columnconfigure(1, weight=1) self.rowconfigure(1, weight=1) # Row 0: self.edtDateStart = DateEdit(self) ToolTip.ToolTip(self.edtDateStart, 'Date') self.edtDateStart.grid(padx=PADX, pady=PADY) self.edtSummary = TextEdit(self) ToolTip.ToolTip(self.edtSummary, 'Summary') self.edtSummary.grid(row=0, column=1, sticky=W+E, padx=PADX, pady=PADY) # Row 1: self.edtCategories = TextComboEdit(self, entry_width=10) ToolTip.ToolTip(self.edtCategories, 'Categories (separate with \',\')') self.edtCategories.grid(row=1, column=0, sticky=W+E, padx=PADX, pady=PADY) self.edtCategories.setlist(['Appointment','Birthday','Business', 'Charge','Education','Holiday','Invoice','Meeting', 'Miscellaneous','Personal', 'Phone Call','Special Occasion','Travel','Vacation']) self.edtDescr = MemoEdit(self) ToolTip.ToolTip(self.edtDescr, 'Description') # MemoEdit is Pmw.ScrolledText: self.edtDescr["text_height"] = 2 self.edtDescr.grid(row=1, rowspan=2, column=1, sticky=W+E+S+N, padx=PADX, pady=PADY) # Row 2: self.edtLocation = TextEdit(self, entry_width=10) ToolTip.ToolTip(self.edtLocation, 'Location') self.edtLocation.grid(row=2, column=0, sticky=W+E, padx=PADX, pady=PADY) # Row 3: timeframe = Pmw.Group(self, tag_text='Start/End Time') self.edtTimeStart = TimeEdit(timeframe.interior(), increment=900) # increment by 15 min ToolTip.ToolTip(self.edtTimeStart, 'Time Start') self.edtTimeStart.grid(row=0, column=0, padx=PADX, pady=PADY) self.edtTimeEnd = TimeEdit(timeframe.interior(), increment=900) # increment by 15 min self.edtTimeEnd.add_save_hook(self._onTimeEndSave) ToolTip.ToolTip(self.edtTimeEnd, 'Time End') self.edtTimeEnd.grid(row=1, column=0, padx=PADX, pady=PADY) timeframe.grid(row=3, column=0, sticky=W+E+S+N, padx=PADX, pady=PADY) self.edtAttendee = AttendeeEdit(self) self.edtAttendee.grid(row=3, column=1, sticky=W+E+S+N, padx=PADX, pady=PADY) # Row 4: self.lblRev = Label(self, anchor=W) self.lblRev.grid(row=4, column=0, columnspan=2, sticky=W+E, padx=PADX, pady=PADY) def focus_set(self): self.edtSummary.selection_range(0,END) self.edtSummary.focus_set() if __name__ == "__main__": tk = Tk() wdgt = JournalEditWidget(tk) wdgt.pack(fill=BOTH) tk.mainloop()