Приложение пиктограммы в системном трее PyGTK запускает два экземпляра и закрывает оба, когда пользователь выходит только один - PullRequest
1 голос
/ 11 марта 2012

Добрый вечер!

Я пишу простое приложение в системном трее для Linux, которое проверяет наличие обновлений системы, используя Python и GTK.Пока у меня есть основные функции, приложение запускается, отображает значок, и при щелчке правой кнопкой мыши появляется меню с несколькими дополнительными параметрами.Проблема возникает, когда я пытаюсь изменить gtk.StatusIcon на другое изображение, вместо того, чтобы «менять» исходный значок на значок «оповещения», он создает второй значок в трее (так что теперь стандартный значок и предупреждениезначок рядом друг с другом) и при выходе из экземпляра значка оповещения приложения закрывает оба.

Это конкретное приложение состоит из двух частей (код ниже), внутренний сценарий, который выполняется в рамках ежечасного задания cronи графический интерфейс пользователя (значок на панели задач), который можно запускать как автоматически запускаемый и / или через меню приложений.

Я прочитал документацию PyGTK, но ничего, что я видел, не объясняет, как переключаться (своп)) значки "на месте".Я уверен, что что-то упустил и был бы признателен за любой конструктивный вклад со второй пары глаз.

Вот код "back-end":

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

А вотКод "GUI" для приложения systray:

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 голосов
/ 04 апреля 2012

Вы пытались установить имя и заголовок для значка?

...