SHARE
TWEET

PyHamclock - Martin S. Ewing, AA6E

yo9gjx Mar 20th, 2012 46 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # PyHamClock version 0.2, 12/6/2009
  5.  
  6. #   PyHamClock displays UTC date and time, along with your local time.
  7. #   Copyright (C) 2009 Martin S. Ewing, AA6E
  8. #
  9. #    This program is free software: you can redistribute it and/or modify
  10. #    it under the terms of the GNU General Public License as published by
  11. #    the Free Software Foundation, either version 3 of the License, or
  12. #    (at your option) any later version.
  13. #
  14. #    This program is distributed in the hope that it will be useful,
  15. #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. #    GNU General Public License for more details.
  18. #
  19. #    You should have received a copy of the GNU General Public License
  20. #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21.  
  22. # Developed with Python 2.6.2 on Ubuntu Linux 9.04.  Also tested on Windows XP & 7.
  23.  
  24. import wx, sys, time, ConfigParser, os
  25.  
  26. BG1 = wx.Colour(0,0,0)
  27. FG2 = wx.Colour(0,130,0)        # dim green
  28. FG1 = wx.Colour(255, 128, 0)    # orange
  29. INTERVAL = 200                  # msec timer period
  30.  
  31. # Performance check:  On Intel Core 7-920 with INTERVAL=200, CPU load (one thread)
  32. # is 0.12% over 4 min., after python startup.  Atom 230 -> 0.4%
  33.  
  34. # We support 3 number size formats, using wxIDs from menu radio buttons.
  35. F_SMALL =  1000
  36. F_MEDIUM = 1001
  37. F_LARGE =  1002
  38. # These are the actual font sizes to use for each format.
  39. F_SIZE = { F_SMALL:14, F_MEDIUM:18, F_LARGE:22 }
  40. # Frame sizes could / should be calculated from the font sizes, but it is
  41. # easier to wire them in for now...
  42. FRAME_SIZE = { F_SMALL:(192,50), F_MEDIUM:(234,62), F_LARGE:(282,74) }
  43.  
  44. CFG_SECTION = 'pyhamclock'
  45. CFG_DEFAULTS = { 'hpos': 0, 'vpos': 0, 'format': F_MEDIUM }
  46. CFG_FILE = 'config.conf'
  47.  
  48. # Get human-readable time strings
  49. def capture():
  50.     time_now = time.time()                  # use same instant for both conversions
  51.     myformat = "%m/%d %H:%M:%S"   # mm/dd HH:MM:SS
  52.     utc_s   = time.strftime(myformat, time.gmtime(time_now))    
  53.     local_s = time.strftime(myformat, time.localtime(time_now))
  54.     return utc_s, local_s
  55.  
  56. # ---- Config. file handler (for window position & size)
  57. # file name: $HOME/.config/pyhamclock/config.conf
  58. # File format:
  59. # [pyhamclock]
  60. # hpos: nnn     # initial frame position (h)
  61. # vpos: nnn     # initial frame position (v)
  62. # format: n     # format (F_SMALL, F_MEDIUM, F_LARGE)
  63.  
  64. class PHC_configurator(object):
  65.    
  66.     def __init__(self):
  67.         cfgdpath = os.path.expanduser('~/.config/pyhamclock')
  68.         if not os.access(cfgdpath, os.W_OK):
  69.             os.makedirs(cfgdpath, 0744)             # make dir if needed
  70.         self.cfgpath = os.path.join(cfgdpath,CFG_FILE)
  71.         self.config = ConfigParser.RawConfigParser(CFG_DEFAULTS)
  72.         # Does config.conf file exist & readable?   if not, create it with defaults.
  73.         if not os.access(self.cfgpath, os.R_OK):
  74.             self.config.add_section(CFG_SECTION)
  75.             for x in CFG_DEFAULTS:
  76.                 self.config.set(CFG_SECTION, x, CFG_DEFAULTS[x])
  77.             with open(self.cfgpath, 'wb') as cfgfile:
  78.                 self.config.write(cfgfile)
  79.         else:
  80.             self.config.read(self.cfgpath)
  81.         return None
  82.  
  83.     def getpos(self):
  84.         hp = self.config.getint(CFG_SECTION, 'hpos')
  85.         vp = self.config.getint(CFG_SECTION, 'vpos')
  86.         return (hp,vp)
  87.  
  88.     def getformat(self):
  89.         return self.config.getint(CFG_SECTION, 'format')
  90.  
  91.     def setpos(self, pos):
  92.         self.config.set(CFG_SECTION, 'hpos', pos[0])
  93.         self.config.set(CFG_SECTION, 'vpos', pos[1])
  94.  
  95.     def setformat(self, fmt):
  96.         self.config.set(CFG_SECTION, 'format', fmt)
  97.  
  98.     def write(self):
  99.         with open(self.cfgpath, 'wb') as cfgfile:
  100.             self.config.write(cfgfile)
  101.  
  102. class MyFrame(wx.Frame):
  103.     def __init__(self, *args, **kwds):
  104.         kwds["style"] = \
  105.             wx.MINIMIZE_BOX|wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN|wx.RESIZE_BORDER
  106.         wx.Frame.__init__(self, *args, **kwds)
  107.        
  108.         self.menubar = wx.MenuBar()
  109.         self.f_menu = wx.Menu()
  110.         self.f_menu.AppendRadioItem(F_SMALL, "Small")
  111.         self.f_menu.AppendRadioItem(F_MEDIUM, "Medium")
  112.         self.f_menu.AppendRadioItem(F_LARGE, "Large")
  113.         self.f_menu.AppendSeparator()
  114.         quitter = self.f_menu.Append(-1, "Quit", "", wx.ITEM_NORMAL)
  115.         self.menubar.Append(self.f_menu, "File")
  116.         tmp_menu = wx.Menu()
  117.         abouter = tmp_menu.Append(-1, "About", "", wx.ITEM_NORMAL)
  118.         self.menubar.Append(tmp_menu, "Help")
  119.         self.SetMenuBar(self.menubar)
  120.  
  121.         self.cfg = PHC_configurator()   # check $HOME/.config/pyhamclock/config.conf
  122.         posreq = self.cfg.getpos()      # position requested by conf file
  123.         scrnsize = wx.GetDisplaySize()  # ensure clock is on screen
  124.         posclip = (min(posreq[0], scrnsize[0] - 50),
  125.                     min(posreq[1], scrnsize[1] - 50))
  126.         self.SetPosition(posclip)
  127.         # Note that self.format is the wxID of its corresponding menu radio button.
  128.         f = self.cfg.getformat()
  129.         self.format = max(F_SMALL,min(F_LARGE,f))
  130.         # set the corresponding radio button in menu
  131.         for x in F_SIZE:
  132.             self.f_menu.Check(x, self.format == x)
  133.            
  134.         self.SetTitle("PyHamClock")
  135. #        self.SetToolTipString("PyHamClock!")
  136.  
  137.         self.Bind(wx.EVT_MENU, self.DoFormat, id=1000, id2=1002)
  138.         self.Bind(wx.EVT_MENU, self.DoQuit, quitter)
  139.         self.Bind(wx.EVT_MENU, self.DoAbout, abouter)
  140.         self.Bind(wx.EVT_CLOSE, self.DoQuit)    # (event from close box)
  141.  
  142.         self.label_utc = wx.StaticText(self, -1, "UTC")
  143.         self.label_utc.SetForegroundColour(FG2)
  144.         self.label_local = wx.StaticText(self, -1, "Local")
  145.         self.label_local.SetForegroundColour(FG2)
  146.  
  147.         t_utc, t_loc = capture()        # Get current times
  148.        
  149.         self.text_ctrl_utc = wx.StaticText(self,-1, t_utc,
  150.             style=wx.ALIGN_LEFT)
  151.         self.text_ctrl_utc.SetBackgroundColour(BG1)
  152.         self.text_ctrl_utc.SetForegroundColour(FG1)
  153.         self.text_ctrl_local = wx.StaticText(self, -1, t_loc,
  154.             style=wx.ALIGN_LEFT)
  155.         self.text_ctrl_local.SetBackgroundColour(BG1)
  156.         self.text_ctrl_local.SetForegroundColour(FG1)
  157.  
  158.         self.__do_layout()
  159.        
  160.         # Set up interval timer
  161.         self.old_time = int(time.time())
  162.         self.timer = wx.Timer(self)
  163.         self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
  164.         self.timer.Start(INTERVAL) # continuous
  165.  
  166.     def __do_layout(self):
  167.         self.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, 0, ""))
  168.         self.SetBackgroundColour(BG1)
  169.         self.SetForegroundColour(FG1)
  170.         time_font = wx.Font(F_SIZE[self.format], wx.SWISS, wx.NORMAL, wx.NORMAL, 0, "")
  171.         self.text_ctrl_utc.SetFont(time_font)
  172.         self.text_ctrl_local.SetFont(time_font)
  173.         self.SetClientSize(FRAME_SIZE[self.format])
  174.        
  175.         sizer_1 = wx.FlexGridSizer(rows=2, cols=2, hgap=5, vgap=0)
  176.         sizer_1.AddGrowableCol(1)
  177.         sizer_1.Add(self.label_utc, border=4, flag=wx.LEFT|wx.TOP)
  178.         sizer_1.Add(self.text_ctrl_utc)
  179.         sizer_1.Add(self.label_local, border=4, flag=wx.LEFT|wx.TOP)
  180.         sizer_1.Add(self.text_ctrl_local)
  181.         self.SetSizer(sizer_1)
  182.         self.Layout()
  183.  
  184.     def DoFormat(self, event):      # Find which format item is now checked.
  185.         for x in F_SIZE:
  186.             if self.f_menu.IsChecked(x):
  187.                 self.format = x     # requested format option
  188.         self.__do_layout()          # rearrange based on chosen format
  189.         return
  190.  
  191.     def OnTimer(self, event):       # The timer INTERVAL should be <= abt 250 ms
  192.                                     # to keep well synced with UTC seconds transition.
  193.         int_time = int(time.time()) # int. seconds
  194.         if int_time >= self.old_time + 1:   # on most interrupts, nothing happens
  195.             self.old_time = int_time        # but we will update display
  196.             utc, loc = capture()            # when we pass a 1 sec boundary
  197.             self.text_ctrl_utc.SetLabel(utc)
  198.             self.text_ctrl_local.SetLabel(loc)
  199.             event.Skip()
  200.         event.Skip()
  201.    
  202.     def DoQuit(self, event):
  203.         # Save our .config info
  204.         self.cfg.setpos(self.GetPosition())
  205.         self.cfg.setformat(self.format)
  206.         self.cfg.write()
  207.         sys.exit()
  208.  
  209.     def DoAbout(self, event):
  210.         wx.MessageBox(
  211. """PyHamClock v 0.2
  212. (c) 2009 Martin Ewing AA6E
  213. http://aa6e.net, aa6e@arrl.net""")
  214.         event.Skip()
  215.  
  216. # end of class MyFrame
  217.  
  218. if __name__ == "__main__":
  219.     app = wx.PySimpleApp(0)
  220.     wx.InitAllImageHandlers()
  221.     frame_pyhamclock = MyFrame(None, -1, "")
  222.     app.SetTopWindow(frame_pyhamclock)
  223.     frame_pyhamclock.Show()
  224.     app.MainLoop()
RAW Paste Data
Want to get better at Python?
Learn to code Python in 2017
Pastebin PRO Summer Special!
Get 40% OFF on Pastebin PRO accounts!
Top