PyGTK系统托盘图标应用程序运行两个实例,并在用户只退出一个时关闭它们

时间:2012-03-11 03:54:06

标签: python pygtk

晚上好!

我正在为Linux编写一个简单的系统托盘应用程序,它使用Python和GTK检查系统更新。到目前为止,我有基本的功能,应用程序运行,显示一个图标,右键单击有一个菜单,其中包含更多选项。当我尝试将gtk.StatusIcon更改为其他图像而不是“交换”“alert”图标的原始图标时,会出现问题,它会在托盘中创建第二个图标(现在标准图标和警报图标是并排的)当退出应用程序的警报图标实例时,关闭它们。

这个特定的应用程序分为两部分(下面的代码),在每小时cron作业中运行的后端脚本,以及可以作为自动启动和/或通过应用程序运行的GUI(系统托盘图标)菜单。

我已经阅读了PyGTK文档,但我看到的任何内容都没有解释如何“就地”切换(交换)图标。我确信我错过了一些东西,并会欣赏来自第二双眼睛的任何建设性意见。

这是“后端”代码:

import time
import subprocess
import logging
import lupdater

# Create the log, set level to DEBUG so that all messages are available
logging.basicConfig(filename='/tmp/lupdater.log', level=logging.DEBUG)

# Global package list
paclist = []

class Pacman():
    '''Provides functions to call pacman and update the repos, as well as
    return a list with number of updates. '''
    def pac_update(self):
        '''Updates the repositories, notifies the user.'''
        subprocess.call(['/usr/bin/notify-send', 'Updating repositories for update check...'], shell=False)

        upd = subprocess.Popen('sudo pacman -Syy', shell=True, stdout=subprocess.PIPE)
        stdout, stderr = upd.communicate()

    def pac_list(self):
        '''Creates a list of packages needing to be updated and counts them,
        displays the count in a notification for user action.'''
        subprocess.call(['/usr/bin/notify-send', 'Checking for updates...'], shell=False)

        # Clean up the list from previous checks so that we keep an accurate count.
        if len(paclist) > 0:
            for i in paclist:
                paclist.remove(i)

        lst = subprocess.Popen('pacman -Qu', shell=True, stdout=subprocess.PIPE)

        for line in lst.stdout:
            line.rstrip('\r\n')
            paclist.append(line)

        numupdates = len(paclist)

        if numupdates >= 1:
            subprocess.call(['/usr/bin/notify-send', '%s %s %s' % ('You have', numupdates, 'updates available!')], shell=False)
            # Here we set the status icon to change and start blinking
            lupblinker = lupdater.SystrayApp()
            lupblinker.blinker()
            logging.info(time.ctime() + ': lupdater had %s updates available.\n' % (numupdates))
        else:
            subprocess.call(['/usr/bin/notify-send', 'Your system is already up to date! :)'], shell=False)
            logging.info(time.ctime() + ': No updates available, system is up to date.')
        # "Future-proofing"
        return numupdates, paclist

    def pac_check_list(self, paclist):
        # For now only checks for kernel updates, packages named "linux".
        # TODO: Check for kernel modules such as video drivers that require
        # a system restart or manual initialization.
        critical = []
        if len(paclist) > 0:
            for i in paclist:
                if i.startswith('linux'):
                    critical.append(i)

        if len(critical) >= 1:
            for i in critical:
                subprocess.call(['/usr/bin/notify-send',
                             '%s %s' % (i, 'is a critical update, it requires a system restart to take effect.')], shell=False)

                logging.info(time.ctime() + ': Critical update detected, user notified via notify-send.')
        return critical, paclist

def run_me(x):
    logging.info(time.ctime() + ': lupdater now running with sleep enabled process.')
    # Meat and Potatoes
    p = Pacman()
    p.pac_update()
    p.pac_list()
    p.pac_check_list(paclist)


if __name__ == '__main__':
    x = 0
    run_me(x)enter code here

这是systray应用程序的“GUI”代码:

import gtk
import subprocess
import lupdaterapi

class SystrayApp():

    def __init__(self):
        self.tray = gtk.StatusIcon()
        self.tray.set_from_file('/usr/share/icons/lupdater.png')
        self.tray.connect('popup-menu', self.on_right_click)
        self.tray.set_tooltip('Lemur Updater')
        self.lapi = lupdaterapi

    def blinker(self):
        self.tray.set_from_file('/usr/share/icons/lupdater-alert.png')
        self.tray.set_blinking(True)

    def on_right_click(self, icon, event_button, event_time):
        self.make_menu(event_button, event_time)
        if self.tray.set_blinking() == True:
        self.tray.set_blinking(False)
        self.tray.set_from_file('/usr/share/icons/lupdater.png')

    def make_menu(self, event_button, event_time):
        menu = gtk.Menu()

    # show about dialog
        about = gtk.MenuItem('About')
        about.show()
        menu.append(about)
        about.connect('activate', self.show_about_dialog)

    # add run item for manual updates
        run = gtk.MenuItem('Check Updates')
        run.show()
        menu.append(run)
        run.connect('activate', self.lapi.run_me)

        #add log checker, open in leafpad for now
        chklog = gtk.MenuItem('View Log')
        chklog.show()
        menu.append(chklog)
        chklog.connect('activate', self.show_log)

        # add quit item
        quit = gtk.MenuItem('Quit')
        quit.show()
        menu.append(quit)
        quit.connect('activate', gtk.main_quit)

        menu.popup(None, None, gtk.status_icon_position_menu,
                event_button, event_time, self.tray)

    def  show_about_dialog(self, widget):
        about_dialog = gtk.AboutDialog()
        about_dialog.set_destroy_with_parent (True)
        about_dialog.set_icon_name ('Lemur Updater')
        about_dialog.set_name('Lemur Updater')
        about_dialog.set_version('1.3b')
        about_dialog.set_comments((u'System Tray interface to the Lemur Updater'))
        about_dialog.set_authors([u'Brian Tomlinson <darthlukan@gmail.com>'])
        about_dialog.run()
        about_dialog.destroy()

    def show_log(self, widget):
        subprocess.Popen('/usr/bin/leafpad /tmp/lupdater.log', shell=True)

# Let's roll!
if __name__ == '__main__':
    SystrayApp()
    gtk.main()

提前再次感谢!

1 个答案:

答案 0 :(得分:0)

您是否尝试过设置图标的名称和标题?