pynotify: «закрытый» сигнал обратного вызова никогда не срабатывает - PullRequest
1 голос
/ 23 декабря 2011

Я пытаюсь написать программу с pynotify, привязками Python для libnotify.Я хочу вызвать критическое уведомление в какой-то момент и обновлять его каждые несколько секунд по мере изменения информации, пока пользователь не щелкнет его.Это все работает, за исключением обработки того, что происходит, когда пользователь отклоняет его.

Чтобы обновить уведомление, мне нужно позвонить Notification.show после Notification.update.Это нормально, но это означает, что мне нужно отслеживать, отклонил ли пользователь уведомление, в противном случае оно будет просто появляться снова.

Это должно быть возможно двумя способами, которые я могу придумать:

  1. Определение, является ли уведомление видимым или нет.Я не нашел никакого способа выяснить это.
  2. Сохранение некоторой переменной при закрытии уведомления, затем проверка ее перед обновлением и повторный вызов Notification.show.

Эта секундаметод должен быть возможным.Пример кода, который я обнаружил (похоже, нет никакой надлежащей документации для pynotify), заставил меня позвонить Notification.connect, чтобы подключить сигнал "closed" к обратному вызову.Я пытался сделать это, но обратный вызов так и не был запущен.

Я долго гуглял и отлаживал, но не мог добиться прогресса.В конце концов я нашел несколько примеров скриптов, которые поставляются с pynotify.Один из них прикрепляет обработчик к сигналу "closed": test-xy-stress.py

Его содержимое выглядит следующим образом:

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gobject
import gtk
import gtk.gdk
import pynotify
import sys
import random

exposed_signal_id = 0
count = 0

def handle_closed(n):
    print "Closing."

def emit_notification(x, y):
    n = pynotify.Notification("X, Y Test",
        "This notification should point to %d, %d." % (x, y))
    n.set_hint("x", x)
    n.set_hint("y", y)
    n.connect('closed', handle_closed)
    n.show()

def popup_random_bubble():
    display = gtk.gdk.display_get_default()
    screen = display.get_default_screen()
    screen_x2 = screen.get_width() - 1
    screen_y2 = screen.get_height() - 1

    x = random.randint(0, screen_x2)
    y = random.randint(0, screen_y2)
    emit_notification(x, y)
    return True


if __name__ == '__main__':
    if not pynotify.init("XY Stress"):
        sys.exit(1)

    gobject.timeout_add(1000, popup_random_bubble)

    gtk.main()

Я запустил это и обнаружил, что обратные вызовы здесьникогда не запускайте.

Может ли это быть только моей системой, или есть ошибка в pynotify или libnotify где-нибудь?Если сейчас это что-то непоправимое, как насчет варианта 1 выше - есть ли способ сделать это?

Кажется, у меня есть libnotify 0.4.5 и pynotify 0.1.1.

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Я искал то же самое.Я нашел кого-то, кто использовал gobject.MainLoop вместо gtk.main, чтобы помочь: linuxquestions.org .

Я обнаружил, что это работает для меня:

#!/usr/bin/python

import pynotify
import gobject

def OnClicked(notification, signal_text):
    print '1: ' + str(notification)
    print '2: ' + str(signal_text)
    notification.close()
    global loop
    loop.quit()

def OnClosed(notification):
    print 'Ignoring fire'
    notification.close()
    global loop
    loop.quit()

def Main():
    pynotify.init('ProgramName')

    global loop
    loop = gobject.MainLoop()

    notify = pynotify.Notification('Fire!', 'I\'m just kidding...')
    # optionalm, just changes notification color
    notify.set_urgency(pynotify.URGENCY_CRITICAL)
    # optional, it will expire eventually
    notify.set_timeout(pynotify.EXPIRES_NEVER)

    notify.add_action('You Clicked The Button', 'Remove Fire', OnClicked)
    notify.connect("closed",OnClosed)

    notify.show()

    loop.run()

if __name__ == '__main__':
    Main()
0 голосов
/ 23 декабря 2011

попробуйте следующее:

добавьте:

from time import  sleep

и в конце вашего emit_notification:

sleep(2)
n.close()

(Обновлено после обсуждения сОП:) Это должно запустить ваш обратный вызов!Таким образом, вы можете протестировать вместе с dbus-monitor, если ваш DBus-Server делает то, что должен. (Идея из ОП.)

Это по-прежнему не то, что вы действительно ищете, но пока объясняет, по крайней мере, ваше недоумение по поводу пропущенного сигнала.Что вы, вероятно, должны посмотреть, это свойства действия.Я нашел кое-что интересное здесь .Похоже, вы можете взаимодействовать с пользователем непосредственно в своих уведомлениях.

Поскольку pynotify - это просто оболочка для связи с DBus, вы можете также попробовать обходной путь:

from dbus import SessionBus, Interface
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

notify_busname = 'org.freedesktop.Notifications'
notify_obj_path ='/org/freedesktop/Notifications'
lbus = SessionBus()

notify_server = lbus.get_object(notify_busname, notify_obj_path)

и после определенияваш обработчик:

notify_server.connect_to_signal(None, handle_closed)

я также изменил в целях тестирования сигнатуру вашей функции для соответствия сигналу DBus:

def handle_closed(*arg, **kwargs):
...