0

Q1 所需的图像

你好,

我是这个新手(请像我这样回答)。修复我的(第二个)问题后,所有代码都应该可以轻松运行。它实际上在我的机器上运行良好,但可能还不是你的。我试图在任何地方为您发表评论,以使某人更容易阅读。这在 Ubuntu 12.10 机器上运行,但您不需要运行 Linux 来解决我的问题!

已解决 1. 代码审查:当您浏览代码时,我将不胜感激任何有关如何以更好、更合适的方式浓缩或做事的意见。我剩下的问题实际上只是我已经知道应该解决的问题。但是,如果您在我的编码风格等中发现了其他东西,坦率地说。为所有好的评论点赞。

已解决:2.相对图标路径:在以下位置:

/home/mh00h/workspace/issindicator/src/International_Space_Station_clip_art.svg

这是与此脚本相同的文件夹的绝对路径。我不希望这样,我希望这个脚本可以在任何人的机器上运行。我试过这些:

$HOME/workspace...
(nothing in front) International_Space_Station_clip_art.svg
./International_Space_Station_clip_art.svg

但那些没有用。上面的图片是我正在尝试使用的(是的,我知道我列出了 SVG 而不是 png,imgur 限制)。是文档。它谈到了“图标主题路径”......也许会以某种方式做到这一点?或者也许有一个标准目录,所有程序员都应该存储图标?

3. 集中我的日期时间功能:真的,我很幸运能够让它工作。我的方式是迂回,但据我所知,它有效。我非常有信心有更好的方法来解决这个烂摊子!你会在脚本的底部找到一堆日期时间的东西。

已解决:4. Appindicator3 Hook:我希望 GTK 仅在调用菜单时刷新,而不是每秒运行一次。这部分回答here,但我真的不明白如何实现“实现”。(希望这是问这个问题的正确地方吗?)

谢谢!

#!/usr/bin/env python
import json, urllib2, time, math, datetime, os, webbrowser
from dateutil import tz

#indicator
from gi.repository import Gtk, GObject
from gi.repository import AppIndicator3 as appindicator

class indicator():
    def __init__(self):

        #######Set this to "False" if IssIndicator should hide it's icon during normal runtime (default = True)
        self.isiconhidden = True
        #

        #create indicator
        self.ind = appindicator.Indicator.new (
                        "issindicator",
                        "/home/mh00h/workspace/issindicator/src/International_Space_Station_clip_art.svg",
                        #"indicator-messages",
                        appindicator.IndicatorCategory.APPLICATION_STATUS)
        if self.isiconhidden == True:
            self.ind.set_status (appindicator.IndicatorStatus.PASSIVE)
        else:
            self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)

        #this is used to keep track of the gtk refresh period
        self.refreshvalue = False

        #dropdown menu
        #current pass menu 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 pass items
        self.futpass = Gtk.MenuItem(" ")
        self.futpass.connect("activate", self.onurl)
        self.menu.append(self.futpass)

        self.sep2 = Gtk.SeparatorMenuItem()
        self.menu.append(self.sep2)

        #Options items

        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 at first run
        self.updatecache()
        self.checkiss()

        Gtk.main()


    #functions
    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()

    #open browser for more tracking info
    def onurl(self, w=None):
        webbrowser.open("http://www.n2yo.com/passes/")

    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 <http://www.gnu.org/licenses/>.')
        ad.set_website('https://launchpad.net/~mh00h/+archive/issindicator')
        ad.set_website_label('ISSIndicator Homepage')
        ad.set_authors(['mh00h <abcd@abcd.com'])
        ad.run()
        ad.destroy()
        widget.set_sensitive(True)

    #how often to run checkiss
    def setrefresh(self, r):
        #this clause is required to keep script from hanging
        if r != self.refreshvalue:
            self.refreshvalue = r
            try:
                self.reftime = GObject.source_remove(True)
            except:
                pass        
            try:
                self.reftime = GObject.timeout_add(r, self.checkiss)
            except:
                pass

    #
    def updatecache(self, w=None):
        #this will show in the menu until the update process completes
        self.passingstatus = 'not updated 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"])+"&lon="+str(self.geoip["longitude"])+"&alt=280&n=47"))
        self.data = {"message": "success", "request": {"latitude": 45.0, "passes": 3, "altitude": 280, "longitude": -81.0, "datetime": 1361502063}, 
                 "response": [{"duration": 542, "risetime": time.time()+10}, {"duration": 642, "risetime": 1361560774}, {"duration": 593, "risetime": 1361566621}]}


    def checkiss(self, w=None):
        #so as to not overload api servers, this runs as a separate process
        #this updates the timers
        self.n = 0
        self.passingstatus = "ISS Zarya is below the horizon"

        #check if we've gone through cached iss passings and update api if needed
        try:
            #ignore errors in case internet is not accessible
            #have a buffer of 5 passes remaining before updating cache
            #at 2 passes left, stop the program to prevent the rest of the program from throwing codes
            if time.time() > self.data['response'][len(self.data['response'])-5]['risetime']:
                self.updatecache
        except:
            if time.time() > self.data['response'][len(self.data['response'])-2]['risetime']:
                os.system("notify-send 'ISS Indicator tried multiple times to update its satellite cache but has run out of its cached track.' 'This may be due to a bad internet connection. The application will now quit.'")
                Gtk.main_quit()

        #get current time
        current_utc = datetime.datetime.utcnow()
        current_utc = current_utc.replace(tzinfo=tz.gettz('UTC'))

        #iterate over all iss passes
        for k in self.data['response']:
            duration = self.data['response'][self.n]['duration']
            risetime = self.data['response'][self.n]['risetime']
            settime = risetime + duration

            #if this iteration matches with the current time, do...
            if risetime <= time.time() <= settime:
                #make the countdown values for the current pass tick
                #rise time calculations and date conversions to string format
                currisetime_utc = datetime.datetime.utcfromtimestamp(self.data['response'][self.n]['risetime'])
                currisetime_utc = currisetime_utc.replace(tzinfo=tz.gettz('UTC'))
                currisetime_tz = currisetime_utc.astimezone(tz.tzlocal())
                currisetime_tzstr = str("%02d" % (currisetime_tz.hour))+':'+str("%02d" % (currisetime_tz.minute))+':'+str("%02d" % (currisetime_tz.second))
                #set time calculations and durations
                cursettime_utc = datetime.datetime.utcfromtimestamp(self.data['response'][self.n]['risetime']+self.data['response'][self.n]['duration'])
                cursettime_utc = cursettime_utc.replace(tzinfo=tz.gettz('UTC'))
                cursettime_tz = cursettime_utc.astimezone(tz.tzlocal())
                curremainingtimeleft = cursettime_utc - current_utc
                curduration = cursettime_utc - currisetime_utc

                z= curremainingtimeleft.seconds
                zhours = z/60/60
                zminutes = z/60-zhours*60
                zseconds = z-zhours*60*60-zminutes*60
                curremainingtimeleftstr = str(zhours)+':'+str("%02d" % (zminutes))+':'+str("%02d" % (zseconds))

                z= curduration.seconds
                zhours = z/60/60
                zminutes = z/60-zhours*60
                zseconds = z-zhours*60*60-zminutes*60
                curdurationstr = str(zhours)+':'+str("%02d" % (zminutes))+':'+str("%02d" % (zseconds))

                cursettime_tzstr = str("%02d" % (cursettime_tz.hour))+':'+str("%02d" % (cursettime_tz.minute))+':'+str("%02d" % (cursettime_tz.second))

                #since the ISS is presently overhead, show the icon and update GTK menuitems to show timers on the ISS pass
                self.showicon()
                self.passingstatus = "ISS Zarya is above the horizon!"
                self.curpass.get_child().set_text(self.passingstatus)
                self.curpassdur.get_child().set_text("Duration: "+curdurationstr+" ("+curremainingtimeleftstr+" remaining)")
                self.curpassdur.show()
                self.curpassrise.get_child().set_text("Rise time: "+currisetime_tzstr)
                self.curpassrise.show()
                self.curpassset.get_child().set_text("Set time: "+cursettime_tzstr)
                self.curpassset.show()
                break
            else:
                #if this iteration of ISS passes does not match with current time, then increase self.n
                self.n += 1

        #regardless of results show the next pass time
        #if the ISS is overhead, use the next dictionary key for data 
        if self.n != len(self.data['response']):
            nextrisetime_utc = datetime.datetime.utcfromtimestamp(self.data['response'][self.n+1]['risetime'])
        else:
            #if the ISS is not overhead, use the first key in the dictionary
            nextrisetime_utc = datetime.datetime.utcfromtimestamp(self.data['response'][0]['risetime'])
        #calculate the next rise time and make timers
        nextrisetime_utc = nextrisetime_utc.replace(tzinfo=tz.gettz('UTC'))
        nextrisetime_tz = nextrisetime_utc.astimezone(tz.tzlocal())
        remainingtimeleft = nextrisetime_utc - current_utc
        z= remainingtimeleft.seconds
        zhours = z/60/60
        zminutes = z/60-zhours*60
        zseconds = z-zhours*60*60-zminutes*60
        remainingtimeleftstr = str(zhours)+':'+str("%02d" % (zminutes))+':'+str("%02d" % (zseconds))
        nextrisetime_tzstr = str("%02d" % (nextrisetime_tz.hour))+':'+str("%02d" % (nextrisetime_tz.minute))+':'+str("%02d" % (nextrisetime_tz.second))

        #update GTK menuitem
        self.futpass.get_child().set_text("Next Pass: "+nextrisetime_tzstr+" ("+remainingtimeleftstr+")")

        #if the ISS is not above the horizon, refresh GTK only once its time for the icon to be visible 
        if self.passingstatus != "ISS Zarya is above the horizon!":
            self.setrefresh(remainingtimeleft.seconds*1000+100)
            #self.setrefresh(1000)
            self.curpass.get_child().set_text(self.passingstatus)
            self.curpassdur.hide()
            self.curpassrise.hide()
            self.curpassset.hide()
            if self.isiconhidden == True:
                self.hideicon()
        else:
            #otherwise, refresh once a second to show the timers ticking in the menu
            #test if the menu is active instead of always running like in this example
            ####MISSING CODE HERE#####  DONT KNOW HOW TO DO IT, SO JUST SETTING TO 1 SEC
            self.setrefresh(1000)

        #for when setrefresh calls this function
        return True

if __name__ == '__main__':
    issindicator = indicator()
4

0 回答 0