%PDF- %PDF-
Direktori : /usr/share/hplip/ui5/ |
Current File : //usr/share/hplip/ui5/systemtray.py |
# -*- coding: utf-8 -*- # # (c) Copyright 2003-2015 HP Development Company, L.P. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Don Welch # Std Lib import sys import struct import select import os import signal import os.path import time # Local from base.g import * from base import device, utils, models from base.codes import * from .ui_utils import * # PyQt try: from PyQt5.QtCore import * from PyQt5.QtGui import * except ImportError: log.error("Python bindings for Qt4 not found. Try using --qt3. Exiting!") sys.exit(1) from .systrayframe import SystrayFrame # dbus (required) try: import dbus from dbus import SessionBus, lowlevel except ImportError: log.error("Python bindings for dbus not found. Exiting!") sys.exit(1) import warnings # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04) warnings.simplefilter("ignore", DeprecationWarning) # pynotify (optional) have_pynotify = True try: import notify2 as pynotify except ImportError: try: import pynotify except ImportError: have_pynotify = False TRAY_MESSAGE_DELAY = 10000 HIDE_INACTIVE_DELAY = 5000 BLIP_DELAY = 2000 SET_MENU_DELAY = 1000 MAX_MENU_EVENTS = 10 UPGRADE_CHECK_DELAY=24*60*60*1000 #1 day #CLEAN_EXEC_DELAY=4*60*60*1000 #4 Hrs ERROR_STATE_TO_ICON = { ERROR_STATE_CLEAR: QSystemTrayIcon.Information, ERROR_STATE_OK: QSystemTrayIcon.Information, ERROR_STATE_WARNING: QSystemTrayIcon.Warning, ERROR_STATE_ERROR: QSystemTrayIcon.Critical, ERROR_STATE_LOW_SUPPLIES: QSystemTrayIcon.Warning, ERROR_STATE_BUSY: QSystemTrayIcon.Warning, ERROR_STATE_LOW_PAPER: QSystemTrayIcon.Warning, ERROR_STATE_PRINTING: QSystemTrayIcon.Information, ERROR_STATE_SCANNING: QSystemTrayIcon.Information, ERROR_STATE_PHOTOCARD: QSystemTrayIcon.Information, ERROR_STATE_FAXING: QSystemTrayIcon.Information, ERROR_STATE_COPYING: QSystemTrayIcon.Information, } if have_pynotify: info = getPynotifyIcon('info') warn = getPynotifyIcon('warning') err = getPynotifyIcon('error') ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY = { ERROR_STATE_CLEAR: (info, pynotify.URGENCY_LOW), ERROR_STATE_OK: (info, pynotify.URGENCY_LOW), ERROR_STATE_WARNING: (warn, pynotify.URGENCY_NORMAL), ERROR_STATE_ERROR: (err, pynotify.URGENCY_CRITICAL), ERROR_STATE_LOW_SUPPLIES: (warn, pynotify.URGENCY_NORMAL), ERROR_STATE_BUSY: (warn, pynotify.URGENCY_NORMAL), ERROR_STATE_LOW_PAPER: (warn, pynotify.URGENCY_NORMAL), ERROR_STATE_PRINTING: (info, pynotify.URGENCY_LOW), ERROR_STATE_SCANNING: (info, pynotify.URGENCY_LOW), ERROR_STATE_PHOTOCARD: (info, pynotify.URGENCY_LOW), ERROR_STATE_FAXING: (info, pynotify.URGENCY_LOW), ERROR_STATE_COPYING: (info, pynotify.URGENCY_LOW), } devices = {} # { <device_uri> : HistoryDevice(), ... } class DeviceMenu(QMenu): def __init__(self, title, parent, device_uri, device_hist, index): QMenu.__init__(self, title, parent) self.device_uri = device_uri self.device_hist = device_hist self.index = index def update(self): self.clear() if self.device_hist: first = True for e in self.device_hist: error_state = STATUS_TO_ERROR_STATE_MAP.get(e.event_code, ERROR_STATE_CLEAR) ess = device.queryString(e.event_code, 0) a = QAction(QIcon(getStatusListIcon(error_state)[self.index]), "%s %s"%(ess,getTimeDeltaDesc(e.timedate)), self) if first: f = a.font() f.setBold(True) a.setFont(f) self.setIcon(QIcon(getStatusListIcon(error_state)[self.index])) first = False self.addAction(a) else: self.addAction(QIcon(load_pixmap("warning", "16x16")), QApplication.translate("SystemTray", "(No events)", None)) class HistoryDevice(QObject): def __init__(self, device_uri, needs_update=True): self.needs_update = needs_update self.device_uri = device_uri back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(device_uri) if bus == 'usb': self.id = serial elif bus == 'net': self.id = host elif bus == 'par': self.id = dev_file else: self.id = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': self.device_type = DEVICE_TYPE_PRINTER self.menu_text = self.__tr("%s Printer (%s)"%(self.model,self.id)) elif back_end == 'hpaio': self.device_type = DEVICE_TYPE_SCANNER self.menu_text = self.__tr("%s Scanner (%s)"%(self.model,self.id)) elif back_end == 'hpfax': self.device_type = DEVICE_TYPE_FAX self.menu_text = self.__tr("%s Fax (%s)"%(self.model,self.id)) else: self.device_type = DEVICE_TYPE_UNKNOWN self.menu_text = self.__tr("%s (%s)"%(self.model,self.id)) self.mq = device.queryModelByURI(self.device_uri) self.index = 0 if self.mq.get('tech-type', TECH_TYPE_NONE) in (TECH_TYPE_MONO_LASER, TECH_TYPE_COLOR_LASER): self.index = 1 self.history = None def getHistory(self, service): if service is not None and self.needs_update: device_uri, h = service.GetHistory(self.device_uri) self.history = [device.Event(*tuple(e)) for e in list(h)[:-MAX_MENU_EVENTS:-1]] self.needs_update = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c) class SystraySettingsDialog(QDialog): def __init__(self, parent, systray_visible, polling, polling_interval, systray_messages, device_list=None, upgrade_notify=True, upgrade_pending_time=0, upgrade_last_update_time=0, upgrade_msg="" ): # upgrade_pending_update_time=0, QDialog.__init__(self, parent) self.systray_visible = systray_visible self.systray_messages = systray_messages if device_list is not None: self.device_list = device_list else: self.device_list = {} self.polling = polling self.polling_interval = polling_interval self.upgrade_notify =upgrade_notify self.upgrade_last_update_time=upgrade_last_update_time self.upgrade_pending_time=upgrade_pending_time self.upgrade_msg=upgrade_msg self.initUi() self.SystemTraySettings.updateUi() def initUi(self): self.setObjectName("SystraySettingsDialog") self.resize(QSize(QRect(0,0,488,565).size()).expandedTo(self.minimumSizeHint())) self.gridlayout = QGridLayout(self) self.gridlayout.setObjectName("gridlayout") self.SystemTraySettings = SystrayFrame(self) self.SystemTraySettings.initUi(self.systray_visible, self.polling, self.polling_interval, self.device_list, self.systray_messages, self.upgrade_notify, self.upgrade_pending_time, self.upgrade_msg) sizePolicy = QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.SystemTraySettings.sizePolicy().hasHeightForWidth()) self.SystemTraySettings.setSizePolicy(sizePolicy) self.SystemTraySettings.setFrameShadow(QFrame.Raised) self.SystemTraySettings.setObjectName("SystemTraySettings") self.gridlayout.addWidget(self.SystemTraySettings,0,0,1,2) spacerItem = QSpacerItem(301,20,QSizePolicy.Expanding,QSizePolicy.Minimum) self.gridlayout.addItem(spacerItem,1,0,1,1) self.StdButtons = QDialogButtonBox(self) self.StdButtons.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.NoButton|QDialogButtonBox.Ok) self.StdButtons.setCenterButtons(False) self.StdButtons.setObjectName("StdButtons") self.gridlayout.addWidget(self.StdButtons,1,1,1,1) # QObject.StdButtons.accepted.connect(self.acceptClicked) # QObject.StdButtons.rejected.connect(self.reject) self.StdButtons.accepted.connect(self.acceptClicked) self.StdButtons.rejected.connect(self.reject) #QMetaObject.connectSlotsByName(self) self.setWindowTitle(self.__tr("HP Device Manager - System Tray Settings")) self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128'))) # pm = load_pixmap("hp_logo", "32x32") # self.prop_icon = QIcon(pm) def acceptClicked(self): self.systray_visible = self.SystemTraySettings.systray_visible self.polling = self.SystemTraySettings.polling self.polling_interval = self.SystemTraySettings.polling_interval self.device_list = self.SystemTraySettings.device_list self.systray_messages = self.SystemTraySettings.systray_messages self.upgrade_notify =self.SystemTraySettings.upgrade_notify self.accept() def __tr(self, s, c=None): return QApplication.translate("SystraySettingsDialog", s, c) class SystemTrayApp(QApplication): def __init__(self, args, read_pipe): QApplication.__init__(self, args) self.menu = None self.read_pipe = read_pipe self.fmt = "80s80sI32sI80sf" self.fmt_size = struct.calcsize(self.fmt) self.timer_active = False self.active_icon = False self.user_settings = UserSettings() self.user_settings.load() self.user_settings.debug() self.tray_icon = QSystemTrayIcon() pm = load_pixmap("hp_logo", "32x32") self.prop_icon = QIcon(pm) a = load_pixmap('active', '16x16') painter = QPainter(pm) painter.drawPixmap(32, 0, a) painter.end() self.prop_active_icon = QIcon(pm) self.tray_icon.setIcon(self.prop_icon) self.session_bus = SessionBus() self.service = None for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.tray_icon.setToolTip(self.__tr("HPLIP Status Service")) # QObject.tray_icon.messageClicked.connect(self.messageClicked) self.tray_icon.messageClicked.connect(self.messageClicked) notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read) # QObject.notifier.activated[int].connect(self.notifierActivated) notifier.activated[int].connect(self.notifierActivated) # QObject.tray_icon.activated[QSystemTrayIcon::ActivationReason].connect(self.trayActivated) self.tray_icon.activated["QSystemTrayIcon::ActivationReason"].connect(self.trayActivated) signal.signal(signal.SIGINT, signal.SIG_DFL) self.tray_icon.show() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: self.tray_icon.setVisible(True) else: QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) # show icon for awhile @ startup self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True if "--ignore-update-firsttime" not in args: self.handle_hplip_updation() QTimer.singleShot(SET_MENU_DELAY, self.initDone) self.update_timer = QTimer() # self.update_timer.connect(self.update_timer,SIGNAL("timeout()"),self.handle_hplip_updation) self.update_timer.timeout.connect(self.handle_hplip_updation) self.update_timer.start(UPGRADE_CHECK_DELAY) # Cleans the /var/log/hp/tmp directory #self.handle_hplip_clean() #self.clean_timer = QTimer() #self.clean_timer.connect(self.clean_timer,SIGNAL("timeout()"),self.handle_hplip_clean) #self.clean_timer.start(CLEAN_EXEC_DELAY) def initDone(self): self.tray_icon.setIcon(self.prop_icon) self.active_icon = False self.setMenu() def resetDevice(self): devices.clear() def addDevice(self, device_uri): try: devices[device_uri] except KeyError: devices[device_uri] = HistoryDevice(device_uri) else: devices[device_uri].needs_update = True def handle_hplip_clean(self): log.debug("handle_hplip_clean ") home_dir = sys_conf.get('dirs', 'home') cmd = 'sh %s/hplip_clean.sh'%home_dir os.system(cmd) def handle_hplip_updation(self): log.debug("handle_hplip_updation upgrade_notify =%d"%(self.user_settings.upgrade_notify)) path = utils.which('hp-upgrade') if self.user_settings.upgrade_notify is False: log.debug("upgrade notification is disabled in systray ") if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) # this just updates the available version in conf file. But won't notify os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--check') time.sleep(5) try: os.waitpid(0, os.WNOHANG) except OSError: pass return current_time = time.time() if int(current_time) > self.user_settings.upgrade_pending_update_time: path = utils.which('hp-upgrade') if path: path = os.path.join(path, 'hp-upgrade') log.debug("Running hp-upgrade: %s " % (path)) os.spawnlp(os.P_NOWAIT, path, 'hp-upgrade', '--notify') time.sleep(5) else: log.error("Unable to find hp-upgrade --notify on PATH.") else: log.debug("upgrade schedule time is not yet completed. schedule time =%d current time =%d " %(self.user_settings.upgrade_pending_update_time, current_time)) try: os.waitpid(0, os.WNOHANG) except OSError: pass def setMenu(self): self.menu = QMenu() title = QAction(self.menu) #title.setDisabled(True) title.setText(self.__tr("HPLIP Status Service")) title.setIcon(self.prop_icon) title.setIconVisibleInMenu(True) self.menu.insertAction(None, title) if devices: if self.service is None: t = 0 while t < 3: try: self.service = self.session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") except dbus.DBusException: log.warn("Unable to connect to StatusService. Retrying...") t += 1 time.sleep(0.5) if self.service is not None: self.menu.addSeparator() for d in devices: devices[d].getHistory(self.service) menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index) self.menu.addMenu(menu) menu.update() self.menu.addSeparator() self.menu.addAction(self.__tr("HP Device Manager..."), self.toolboxTriggered) self.menu.addSeparator() self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self.__tr("Settings..."), self.settingsTriggered) self.menu.addSeparator() self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), "Quit", self.quitTriggered) self.tray_icon.setContextMenu(self.menu) def settingsTriggered(self): if self.menu is None: return self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING) # sys_conf cur_vers = sys_conf.get('hplip', 'version') self.user_settings.load() installed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_last_update_time)) if utils.Is_HPLIP_older_version(cur_vers, self.user_settings.latest_available_version): if int(time.time()) < self.user_settings.upgrade_pending_update_time : postponed_time =time.strftime("%d-%m-%Y", time.localtime(self.user_settings.upgrade_pending_update_time)) upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade. HPLIP upgrade is scheduled on %s." %(cur_vers,installed_time , self.user_settings.latest_available_version, postponed_time) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers,installed_time , self.user_settings.latest_available_version) else: upgrade_msg ="HPLIP-%s version was installed.\n\nNew version of HPLIP-%s is available for upgrade." %(cur_vers, self.user_settings.latest_available_version) elif self.user_settings.upgrade_last_update_time: upgrade_msg ="HPLIP-%s version was installed on %s."%(cur_vers, installed_time) else: upgrade_msg ="HPLIP-%s version was installed."%(cur_vers) try: dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.systray_messages, self.user_settings.polling_device_list, self.user_settings.upgrade_notify, self.user_settings.upgrade_pending_update_time, self.user_settings.upgrade_last_update_time, upgrade_msg) if dlg.exec_() == QDialog.Accepted: self.user_settings.systray_visible = dlg.systray_visible self.user_settings.systray_messages = dlg.systray_messages self.user_settings.upgrade_notify = dlg.upgrade_notify log.debug("HPLIP update notification = %d"%(self.user_settings.upgrade_notify)) self.user_settings.save() if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS: log.debug("Showing...") self.tray_icon.setVisible(True) else: log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED) finally: self.sendMessage('', '', EVENT_DEVICE_START_POLLING) def timeoutHideWhenInactive(self): log.debug("Hiding...") if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): self.tray_icon.setVisible(False) log.debug("Hidden") def updateMenu(self): if self.menu is None: return for a in self.menu.actions(): try: a.menu().update() except AttributeError: continue def trayActivated(self, reason): if reason == QSystemTrayIcon.Context: self.updateMenu() elif reason == QSystemTrayIcon.DoubleClick: #print "double click" self.toolboxTriggered() pass elif reason == QSystemTrayIcon.Trigger: #print "single click" self.updateMenu() if not self.menu is None: self.menu.popup(QCursor.pos()) pass elif reason == QSystemTrayIcon.MiddleClick: #print "middle click" pass def messageClicked(self): #print "\nPARENT: message clicked" pass def quitTriggered(self): log.debug("Exiting") self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT) self.quit() del self.tray_icon def toolboxTriggered(self): try: os.waitpid(-1, os.WNOHANG) except OSError: pass # See if it is already running... ok, lock_file = utils.lock_app('hp-toolbox', True) if ok: # able to lock, not running... utils.unlock(lock_file) path = utils.which('hp-toolbox') if path: path = os.path.join(path, 'hp-toolbox') else: self.tray_icon.showMessage(self.__tr("HPLIP Status Service"), self.__tr("Unable to locate hp-toolbox on system PATH."), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY) log.error("Unable to find hp-toolbox on PATH.") return #log.debug(path) log.debug("Running hp-toolbox: hp-toolbox") os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox') else: # ...already running, raise it self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface='com.hplip.Toolbox') def sendMessage(self, device_uri, printer_name, event_code, username=prop.username, job_id=0, title='', pipe_name='', interface='com.hplip.StatusService'): #device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(SessionBus(), interface) device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface) def notifierActivated(self, s): m = '' while True: try: r, w, e = select.select([self.read_pipe], [], [self.read_pipe], 1.0) except select.error: log.debug("Error in select()") break if e: log.error("Pipe error: %s" % e) break if r: #m = ''.join([m, os.read(self.read_pipe, self.fmt_size)]) m = os.read(self.read_pipe, self.fmt_size) while len(m) >= self.fmt_size: event = device.Event(*[x.rstrip(b'\x00').decode('utf-8') if isinstance(x, bytes) else x for x in struct.unpack(self.fmt, m[:self.fmt_size])]) m = m[self.fmt_size:] if event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: self.resetDevice() for d in device.getSupportedCUPSDevices(back_end_filter=['hp', 'hpfax']): self.addDevice(d) self.setMenu() if event.event_code == EVENT_USER_CONFIGURATION_CHANGED: log.debug("Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)") self.user_settings.load() self.user_settings.debug() elif event.event_code == EVENT_SYSTEMTRAY_EXIT: self.quit() return if self.user_settings.systray_visible in \ (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE): log.debug("Showing...") self.tray_icon.setVisible(True) if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True continue elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE: if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False continue elif event.event_code == EVENT_DEVICE_UPDATE_BLIP: if not self.active_icon: self.tray_icon.setIcon(self.prop_active_icon) self.active_icon = True QTimer.singleShot(BLIP_DELAY, self.blipTimeout) continue if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS): log.debug("Waiting to hide...") QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive) if event.event_code <= EVENT_MAX_USER_EVENT or \ event.event_code == EVENT_CUPS_QUEUES_REMOVED or event.event_code == EVENT_CUPS_QUEUES_ADDED: if event.event_code != EVENT_CUPS_QUEUES_REMOVED: self.addDevice(event.device_uri) self.setMenu() if self.tray_icon.supportsMessages(): log.debug("Tray icon message:") event.debug() error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR) desc = device.queryString(event.event_code) show_message = False if self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ALL: # OK, Busy show_message = True elif self.user_settings.systray_messages in (SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS, SYSTRAY_MESSAGES_SHOW_ERRORS_ONLY): if error_state == ERROR_STATE_ERROR: show_message = True elif self.user_settings.systray_messages == SYSTRAY_MESSAGES_SHOW_ERRORS_AND_WARNINGS and \ error_state in (ERROR_STATE_WARNING, ERROR_STATE_LOW_SUPPLIES, ERROR_STATE_LOW_PAPER): show_message = True if event.printer_name: d = event.printer_name else: back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \ device.parseDeviceURI(event.device_uri) if bus == 'usb': idd = serial elif bus == 'net': idd = host elif bus == 'par': idd = dev_file else: idd = 'unknown' self.model = models.normalizeModelUIName(model) if back_end == 'hp': d = self.__tr("%s Printer (%s)"%(model,idd)) elif back_end == 'hpaio': d = self.__tr("%s Scanner (%s)"%(model,idd)) elif back_end == 'hpfax': d = self.__tr("%s Fax (%s)"%(model,idd)) else: d = self.__tr("%s (%s)"%(model,idd)) if show_message: if have_pynotify and pynotify.init("hplip"): # Use libnotify/pynotify icon, urgency = ERROR_STATE_TO_ICON_AND_URGENCY_PYNOTIFY.get(error_state, (getPynotifyIcon('info'), pynotify.URGENCY_NORMAL)) if event.job_id and event.title: msg = "%s\n%s: %s\n(%s/%s)" % (to_unicode(d), desc, event.title, event.username, event.job_id) log.debug("Notify: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) else: msg = "%s\n%s (%s)" % (to_unicode(d), desc, event.event_code) log.debug("Notify: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) n = pynotify.Notification("HPLIP Device Status", msg, icon) # CRID: 11833 Debian Traceback error notification exceeded n.set_hint('transient', True) n.set_urgency(urgency) if error_state == ERROR_STATE_ERROR: n.set_timeout(pynotify.EXPIRES_NEVER) else: n.set_timeout(TRAY_MESSAGE_DELAY) n.show() else: # Use "standard" message bubbles icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information) if event.job_id and event.title: log.debug("Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d" % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), "%s\n%s: %s\n(%s/%s)"%(d,desc, event.title,event.username,event.job_id), icon, TRAY_MESSAGE_DELAY) else: log.debug("Bubble: uri=%s desc=%s code=%d" % (event.device_uri, desc, event.event_code)) self.tray_icon.showMessage(self.__tr("HPLIP Device Status"), "%s\n%s (%s)"%(d,desc,event.event_code), icon, TRAY_MESSAGE_DELAY) else: break # return def blipTimeout(self): if self.active_icon: self.tray_icon.setIcon(self.prop_icon) self.active_icon = False def __tr(self, s, c=None): return QApplication.translate("SystemTray", s, c) def run(read_pipe): log.set_module("hp-systray(qt5)") log.debug("PID=%d" % os.getpid()) try: app = SystemTrayApp(sys.argv, read_pipe) except dbus.DBusException as e: # No session bus log.debug("Caught exception: %s" % e) sys.exit(1) app.setQuitOnLastWindowClosed(False) # If not set, settings dlg closes app i = 0 while i < 60: if QSystemTrayIcon.isSystemTrayAvailable(): break time.sleep(1.0) i += 1 if QSystemTrayIcon.isSystemTrayAvailable(): notifier = QSocketNotifier(read_pipe, QSocketNotifier.Read) # QObject.notifier.activated[int].connect(app.notifierActivated) notifier.activated[int].connect(app.notifierActivated) app.exec_()