title: Update GTK+ MenuItem Countdown Each Second, and Periodic Function Call
body: <p>This is my International Space Station indicator. I am trying to create a GTK MenuItem that displays a countdown. This wil be in an Ubuntu Unity indicator using AppIndicator3. I want this MenuItem (<code>futpass</code>)to refresh each second (i.e., countdown appears in real time), but also want it to stay inactive when the menu is not selected so as to not consume system resources. Problem is, I can't get it to refresh on its own.</p>
  
  <p>Because there is a long wait period between each time <code>checkiss</code> needs to be run, I also need to know the proper approach to calling this function at a set time with minimal CPU wakeups.</p>
  
  <p>Here is my (rough) code so far:</p>
  
  <pre><code>#!/usr/bin/env python
  #print time.localtime( time.time() )
  import json, urllib2, time, math
  
  #indicator
  from gi.repository import Gtk
  from gi.repository import AppIndicator3 as appindicator
  class indicator():
      def __init__(self):
          #create indicator
          self.ind = appindicator.Indicator.new (
                          "issindicator",
                          "indicator-messages",
                          #"indicator-messages",
                          appindicator.IndicatorCategory.APPLICATION_STATUS)
          self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)
  
          self.ind.set_attention_icon ("indicator-messages-new")
  
          #dropdown menu
          #now items
          self.menu = Gtk.Menu()
          self.curpass = Gtk.MenuItem("not refreshed")
          self.curpass.connect("activate", self.checkiss)
          self.menu.append(self.curpass)
  
          self.curpassdur = Gtk.MenuItem(" ")
          self.menu.append(self.curpassdur)
  
          self.curpassrise = Gtk.MenuItem(" ")
          self.menu.append(self.curpassrise)
  
          self.curpassset = Gtk.MenuItem(" ")
          self.menu.append(self.curpassset)
  
          self.sep1 = Gtk.SeparatorMenuItem()
          self.menu.append(self.sep1)
  
          #future items
          self.futpass = Gtk.MenuItem(" ")
          self.menu.append(self.futpass)
  
          self.sep2 = Gtk.SeparatorMenuItem()
          self.menu.append(self.sep2)
  
          #Options
  
          self.aboutmenu = Gtk.MenuItem("About")
          self.aboutmenu.connect("activate", self.onabout)
          self.menu.append(self.aboutmenu)
  
          self.quit = Gtk.MenuItem("Quit")
          self.quit.connect("activate", self.quitnow)
          self.menu.append(self.quit)
  
          self.curpass.show()
          self.sep1.show()
          self.futpass.show()
          self.sep2.show()
          self.aboutmenu.show()
          self.quit.show()
          self.ind.set_menu(self.menu)
  
          #get iss data
          self.updatecache()
          self.checkiss()
  
          Gtk.main()
  
  
      #define code to hide or show icon
      def hideicon(self, w=None):
          self.ind.set_status (appindicator.IndicatorStatus.PASSIVE)
  
      def showicon(self, w=None):
          self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)
  
      def quitnow(self, w=None):
          Gtk.main_quit()
  
      def onabout(self,widget):
          widget.set_sensitive(False)
          ad=Gtk.AboutDialog()
          ad.set_name("aboutdialog")
          ad.set_version("0.1")
          ad.set_copyright('Copyrignt (c) 2013 mh00h')
          ad.set_comments('Indicating ISS Zarya')
          ad.set_license(''+
          'This program is free software: you can redistribute it and/or modify it\n'+
          'under the terms of the GNU General Public License as published by the\n'+
          'Free Software Foundation, either version 3 of the License, or (at your option)\n'+
          'any later version.\n\n'+
          'This program is distributed in the hope that it will be useful, but\n'+
          'WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n'+
          'or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\n'+
          'more details.\n\n'+
          'You should have received a copy of the GNU General Public License along with\n'+
          'this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.')
          ad.set_website('https://launchpad.net/~mh00h/+archive/issindicator')
          ad.set_website_label('ISSIndicator Homepage')
          ad.set_authors(['mh00h'])
          ad.run()
          ad.destroy()
          widget.set_sensitive(True)
  
      def updatecache(self, w=None):
          self.passingstatus = 'not set yet'
          #get ISS data from api
          self.ip = urllib2.urlopen("http://api.exip.org/?call=ip").read()
          self.geoip = json.load(urllib2.urlopen("http://freegeoip.net/json/"+self.ip))
          self.data = json.load(urllib2.urlopen("http://api.open-notify.org/iss/?lat="+str(self.geoip["latitude"])+"&amp;lon="+str(self.geoip["longitude"])+"&amp;alt=280&amp;n=27"))
  
      def checkiss(self, w=None):
          self.n = 0
          self.passingstatus = "The ISS is not overhead."
  
          #check if cache is out of date and update if needed
          if time.time() &gt; self.data['response'][len(self.data['response'])-1]['risetime']:
              self.updatecache
          for k in self.data['response']:
              duration = self.data['response'][self.n]['duration']
              risetime = self.data['response'][self.n]['risetime']
              settime = risetime + duration
              #print risetime, time.time(), settime
              if risetime &lt;= time.time() &lt;= settime:
                  self.showicon()
                  self.passingstatus = "The ISS is overhead"
                  self.curpass.get_child().set_text(self.passingstatus)
                  self.curpassdur.get_child().set_text("Duration: "+
                                                       str(time.strftime('%M:%S', time.gmtime(duration)))+" ("+
                                                       str(time.strftime('%M:%S', time.gmtime(time.time()-duration)))+" remaining)")
                  self.curpassdur.show()
                  self.curpassrise.get_child().set_text("Rise time: "+time.strftime('%H:%M:%S', time.gmtime(risetime)))
                  self.curpassrise.show()
                  self.curpassset.get_child().set_text("Set time: "+time.strftime('%H:%M:%S', time.gmtime(settime)))
                  self.curpassset.show()
                  break
              else:
                  self.n += 1
  
          if self.passingstatus != "The ISS is overhead":
              self.curpass.get_child().set_text(self.passingstatus)
              self.curpassdur.hide()
              self.curpassrise.hide()
              self.curpassset.hide()
              #self.hideicon()
  
          #regardless of isspass, show the next pass time
          if self.n != len(self.data['response']):
              self.futpass.get_child().set_text("Next Pass: "+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][self.n]['risetime'])))+" ("+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][self.n+1]['risetime']-time.time())))+")")
          else:
              self.futpass.get_child().set_text("Next Pass: "+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][0]['risetime'])))+" ("+str(time.strftime('%H:%M:%S', time.gmtime(self.data['response'][0]['risetime']-time.time())))+")")
  
  if __name__ == '__main__':
      issindicator = indicator()
  </code></pre>