1426 lines
54 KiB
Python
1426 lines
54 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# (c) Copyright 2001-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
|
|
#
|
|
# Authors: Don Welch, Naga Samrat Chowdary Narla
|
|
#
|
|
|
|
# StdLib
|
|
import socket
|
|
import operator
|
|
import subprocess
|
|
import signal
|
|
|
|
# Local
|
|
from base.g import *
|
|
from base import device, utils, models, pkit
|
|
from prnt import cups
|
|
from base.codes import *
|
|
from .ui_utils import *
|
|
from installer import pluginhandler
|
|
from base.sixext import to_unicode, PY3, from_unicode_to_str
|
|
# Qt
|
|
try:
|
|
from PyQt5.QtCore import *
|
|
from PyQt5.QtGui import *
|
|
except ImportError:
|
|
from PyQt5.QtCore import *
|
|
from PyQt5.QtGui import *
|
|
from PyQt5.QtWidgets import *
|
|
|
|
|
|
# Ui
|
|
from .setupdialog_base import Ui_Dialog
|
|
from .plugindialog import PluginDialog
|
|
from .wifisetupdialog import WifiSetupDialog, SUCCESS_CONNECTED
|
|
|
|
# Fax
|
|
try:
|
|
from fax import fax
|
|
fax_import_ok = True
|
|
except ImportError:
|
|
# This can fail on Python < 2.3 due to the datetime module
|
|
fax_import_ok = False
|
|
log.warning("Fax setup disabled - Python 2.3+ required.")
|
|
|
|
|
|
PAGE_DISCOVERY = 0
|
|
PAGE_DEVICES = 1
|
|
PAGE_ADD_PRINTER = 2
|
|
PAGE_REMOVE = 3
|
|
|
|
|
|
BUTTON_NEXT = 0
|
|
BUTTON_FINISH = 1
|
|
BUTTON_ADD_PRINTER = 2
|
|
BUTTON_REMOVE = 3
|
|
|
|
ADVANCED_SHOW = 0
|
|
ADVANCED_HIDE = 1
|
|
|
|
DEVICE_DESC_ALL = 0
|
|
DEVICE_DESC_SINGLE_FUNC = 1
|
|
DEVICE_DESC_MULTI_FUNC = 2
|
|
|
|
|
|
class PasswordDialog(QDialog):
|
|
def __init__(self, prompt, parent=None, name=None, modal=0, fl=0):
|
|
QDialog.__init__(self, parent)
|
|
# Application icon
|
|
self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128')))
|
|
self.prompt = prompt
|
|
|
|
Layout= QGridLayout(self)
|
|
Layout.setContentsMargins(11, 11, 11, 11)
|
|
Layout.setSpacing(6)
|
|
|
|
self.PromptTextLabel = QLabel(self)
|
|
Layout.addWidget(self.PromptTextLabel,0,0,1,3)
|
|
|
|
self.UsernameTextLabel = QLabel(self)
|
|
Layout.addWidget(self.UsernameTextLabel,1,0)
|
|
|
|
self.UsernameLineEdit = QLineEdit(self)
|
|
self.UsernameLineEdit.setEchoMode(QLineEdit.Normal)
|
|
Layout.addWidget(self.UsernameLineEdit,1,1,1,2)
|
|
|
|
self.PasswordTextLabel = QLabel(self)
|
|
Layout.addWidget(self.PasswordTextLabel,2,0)
|
|
|
|
self.PasswordLineEdit = QLineEdit(self)
|
|
self.PasswordLineEdit.setEchoMode(QLineEdit.Password)
|
|
Layout.addWidget(self.PasswordLineEdit,2,1,1,2)
|
|
|
|
self.OkPushButton = QPushButton(self)
|
|
Layout.addWidget(self.OkPushButton,3,2)
|
|
|
|
self.languageChange()
|
|
|
|
self.resize(QSize(420,163).expandedTo(self.minimumSizeHint()))
|
|
|
|
self.OkPushButton.clicked.connect(self.accept)
|
|
self.PasswordLineEdit.returnPressed.connect(self.accept)
|
|
|
|
def setDefaultUsername(self, defUser, allowUsernameEdit = True):
|
|
self.UsernameLineEdit.setText(defUser)
|
|
if not allowUsernameEdit:
|
|
self.UsernameLineEdit.setReadOnly(True)
|
|
self.UsernameLineEdit.setStyleSheet("QLineEdit {background-color: lightgray}")
|
|
|
|
def getUsername(self):
|
|
return to_unicode(self.UsernameLineEdit.text())
|
|
|
|
|
|
def getPassword(self):
|
|
return to_unicode(self.PasswordLineEdit.text())
|
|
|
|
|
|
def languageChange(self):
|
|
self.setWindowTitle(self.__tr("HP Device Manager - Enter Username/Password"))
|
|
self.PromptTextLabel.setText(self.__tr(self.prompt))
|
|
self.UsernameTextLabel.setText(self.__tr("Username:"))
|
|
self.PasswordTextLabel.setText(self.__tr("Password:"))
|
|
self.OkPushButton.setText(self.__tr("OK"))
|
|
|
|
|
|
def __tr(self,s,c = None):
|
|
return qApp.translate("SetupDialog",s,c)
|
|
|
|
|
|
def FailureMessageUI(prompt):
|
|
try:
|
|
dlg = PasswordDialog(prompt, None)
|
|
FailureUI(dlg, prompt)
|
|
finally:
|
|
pass
|
|
|
|
|
|
def showPasswordUI(prompt, userName=None, allowUsernameEdit=True):
|
|
try:
|
|
dlg = PasswordDialog(prompt, None)
|
|
|
|
if userName != None:
|
|
dlg.setDefaultUsername(userName, allowUsernameEdit)
|
|
|
|
if dlg.exec_() == QDialog.Accepted:
|
|
return (dlg.getUsername(), dlg.getPassword())
|
|
|
|
finally:
|
|
pass
|
|
|
|
return ("", "")
|
|
|
|
|
|
|
|
class DeviceTableWidgetItem(QTableWidgetItem):
|
|
def __init__(self, text, device_uri):
|
|
QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
|
|
self.device_uri = device_uri
|
|
|
|
|
|
|
|
class SetupDialog(QDialog, Ui_Dialog):
|
|
def __init__(self, parent, param, jd_port, device_uri=None, remove=False):
|
|
QDialog.__init__(self, parent)
|
|
self.setupUi(self)
|
|
|
|
self.param = param
|
|
self.jd_port = jd_port
|
|
self.device_uri = device_uri
|
|
self.remove = remove
|
|
|
|
if device_uri:
|
|
log.info("Using device: %s" % device_uri)
|
|
|
|
self.initUi()
|
|
|
|
if self.remove:
|
|
QTimer.singleShot(0, self.showRemovePage)
|
|
else:
|
|
if self.skip_discovery:
|
|
self.discovery_method = 0 # SLP
|
|
QTimer.singleShot(0, self.showDevicesPage)
|
|
else:
|
|
QTimer.singleShot(0, self.showDiscoveryPage)
|
|
|
|
cups.setPasswordCallback(showPasswordUI)
|
|
|
|
|
|
#
|
|
# INIT
|
|
#
|
|
|
|
def initUi(self):
|
|
self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128')))
|
|
|
|
# connect signals/slots
|
|
self.CancelButton.clicked.connect(self.CancelButton_clicked)
|
|
self.BackButton.clicked.connect(self.BackButton_clicked)
|
|
self.NextButton.clicked.connect(self.NextButton_clicked)
|
|
self.ManualGroupBox.clicked.connect(self.ManualGroupBox_clicked)
|
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
|
|
if self.remove:
|
|
self.initRemovePage()
|
|
self.max_page = 1
|
|
else:
|
|
self.initDiscoveryPage()
|
|
self.initDevicesPage()
|
|
self.initAddPrinterPage()
|
|
self.max_page = PAGE_ADD_PRINTER
|
|
|
|
#
|
|
# DISCOVERY PAGE
|
|
#
|
|
|
|
def initDiscoveryPage(self):
|
|
self.UsbRadioButton.setChecked(True)
|
|
self.setUsbRadioButton(True)
|
|
self.ManualGroupBox.setChecked(False)
|
|
|
|
self.advanced = False
|
|
self.manual = False
|
|
self.skip_discovery = False
|
|
self.discovery_method = 0
|
|
self.NetworkRadioButton.setEnabled(prop.net_build)
|
|
self.WirelessButton.setEnabled(prop.net_build)
|
|
self.ParallelRadioButton.setEnabled(prop.par_build)
|
|
self.devices = {}
|
|
self.bus = 'usb'
|
|
self.timeout = 5
|
|
self.ttl = 4
|
|
self.search = ''
|
|
self.print_test_page = False
|
|
self.device_desc = DEVICE_DESC_ALL
|
|
|
|
if self.param:
|
|
log.info("Searching for device...")
|
|
self.manual = True
|
|
self.advanced = True
|
|
self.ManualParamLineEdit.setText(self.param)
|
|
self.JetDirectSpinBox.setValue(self.jd_port)
|
|
self.ManualGroupBox.setChecked(True)
|
|
self.DiscoveryOptionsGroupBox.setEnabled(False)
|
|
|
|
if self.manualDiscovery():
|
|
self.skip_discovery = True
|
|
else:
|
|
FailureUI(self, self.__tr("<b>Device not found.</b> <p>Please make sure your printer is properly connected and powered-on."))
|
|
|
|
match = device.usb_pat.match(self.param)
|
|
if match is not None:
|
|
self.UsbRadioButton.setChecked(True)
|
|
self.setUsbRadioButton(True)
|
|
|
|
else:
|
|
match = device.dev_pat.match(self.param)
|
|
if match is not None and prop.par_build:
|
|
self.ParallelRadioButton.setChecked(True)
|
|
self.setParallelRadioButton(True)
|
|
|
|
else:
|
|
match = device.ip_pat.match(self.param)
|
|
if match is not None and prop.net_build:
|
|
self.NetworkRadioButton.setChecked(True)
|
|
self.setNetworkRadioButton(True)
|
|
|
|
else:
|
|
FailureUI(self, self.__tr("<b>Invalid manual discovery parameter.</b>"))
|
|
|
|
elif self.device_uri: # If device URI specified on the command line, skip discovery
|
|
# if the device URI is well-formed (but not necessarily valid)
|
|
try:
|
|
back_end, is_hp, self.bus, model, serial, dev_file, host, zc, port = \
|
|
device.parseDeviceURI(self.device_uri)
|
|
|
|
except Error:
|
|
log.error("Invalid device URI specified: %s" % self.device_uri)
|
|
|
|
else:
|
|
name = host
|
|
if self.bus == 'net':
|
|
try:
|
|
log.debug("Trying to get hostname for device...")
|
|
name = socket.gethostbyaddr(host)[0]
|
|
except socket.herror:
|
|
log.debug("Failed.")
|
|
else:
|
|
log.debug("Host name=%s" % name)
|
|
|
|
self.devices = {self.device_uri : (model, model, name)}
|
|
self.skip_discovery = True
|
|
|
|
# If no network or parallel, usb is only option, skip initial page...
|
|
elif not prop.par_build and not prop.net_build:
|
|
self.skip_discovery = True
|
|
self.bus = 'usb'
|
|
self.UsbRadioButton.setChecked(True)
|
|
self.setUsbRadioButton(True)
|
|
|
|
if prop.fax_build and prop.scan_build:
|
|
self.DeviceTypeComboBox.addItem("All devices/printers", DEVICE_DESC_ALL)
|
|
self.DeviceTypeComboBox.addItem("Single function printers only", DEVICE_DESC_SINGLE_FUNC)
|
|
self.DeviceTypeComboBox.addItem("All-in-one/MFP devices only", DEVICE_DESC_MULTI_FUNC)
|
|
else:
|
|
self.DeviceTypeComboBox.setEnabled(False)
|
|
|
|
self.AdvancedButton.clicked.connect(self.AdvancedButton_clicked)
|
|
self.UsbRadioButton.toggled.connect(self.UsbRadioButton_toggled)
|
|
self.NetworkRadioButton.toggled.connect(self.NetworkRadioButton_toggled)
|
|
self.WirelessButton.toggled.connect(self.WirelessButton_toggled)
|
|
self.ParallelRadioButton.toggled.connect(self.ParallelRadioButton_toggled)
|
|
self.NetworkTTLSpinBox.valueChanged.connect(self.NetworkTTLSpinBox_valueChanged)
|
|
self.NetworkTimeoutSpinBox.valueChanged.connect(self.NetworkTimeoutSpinBox_valueChanged)
|
|
self.ManualGroupBox.toggled.connect(self.ManualGroupBox_toggled)
|
|
|
|
self.showAdvanced()
|
|
|
|
|
|
def ManualGroupBox_toggled(self, checked):
|
|
self.DiscoveryOptionsGroupBox.setEnabled(not checked)
|
|
|
|
|
|
def manualDiscovery(self):
|
|
# Validate param...
|
|
device_uri, sane_uri, fax_uri = device.makeURI(self.param, self.jd_port)
|
|
|
|
if device_uri:
|
|
log.info("Found device: %s" % device_uri)
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
|
|
device.parseDeviceURI(device_uri)
|
|
|
|
name = host
|
|
if bus == 'net':
|
|
try:
|
|
if device.ip_pat.search(name) is not None:
|
|
log.debug("Getting host name from IP address (%s)" % name)
|
|
name = socket.gethostbyaddr(host)[0]
|
|
except (socket.herror, socket.gaierror):
|
|
pass
|
|
|
|
self.devices = {device_uri : (model, model, name)}
|
|
|
|
if bus == 'usb':
|
|
self.UsbRadioButton.setChecked(True)
|
|
self.setUsbRadioButton(True)
|
|
|
|
elif bus == 'net' and prop.net_build:
|
|
self.NetworkRadioButton.setChecked(True)
|
|
self.setNetworkRadioButton(True)
|
|
|
|
elif bus == 'par' and prop.par_build:
|
|
self.ParallelRadioButton.setChecked(True)
|
|
self.setParallelRadioButton(True)
|
|
|
|
return True
|
|
|
|
|
|
return False
|
|
|
|
|
|
def ManualGroupBox_clicked(self, checked):
|
|
self.manual = checked
|
|
network = self.NetworkRadioButton.isChecked()
|
|
self.setJetDirect(network)
|
|
|
|
|
|
def showDiscoveryPage(self):
|
|
self.BackButton.setEnabled(False)
|
|
self.NextButton.setEnabled(True)
|
|
self.setNextButton(BUTTON_NEXT)
|
|
self.displayPage(PAGE_DISCOVERY)
|
|
|
|
|
|
def AdvancedButton_clicked(self):
|
|
self.advanced = not self.advanced
|
|
self.showAdvanced()
|
|
|
|
|
|
def showAdvanced(self):
|
|
if self.advanced:
|
|
self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_SHOW)
|
|
self.AdvancedButton.setText(self.__tr("Hide Advanced Options"))
|
|
self.AdvancedButton.setIcon(QIcon(load_pixmap("minus", "16x16")))
|
|
else:
|
|
self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_HIDE)
|
|
self.AdvancedButton.setText(self.__tr("Show Advanced Options"))
|
|
self.AdvancedButton.setIcon(QIcon(load_pixmap("plus", "16x16")))
|
|
|
|
|
|
def setJetDirect(self, enabled):
|
|
self.JetDirectLabel.setEnabled(enabled and self.manual)
|
|
self.JetDirectSpinBox.setEnabled(enabled and self.manual)
|
|
|
|
|
|
def setNetworkOptions(self, enabled):
|
|
self.NetworkTimeoutLabel.setEnabled(enabled)
|
|
self.NetworkTimeoutSpinBox.setEnabled(enabled)
|
|
self.NetworkTTLLabel.setEnabled(enabled)
|
|
self.NetworkTTLSpinBox.setEnabled(enabled)
|
|
|
|
|
|
def setSearchOptions(self, enabled):
|
|
self.SearchLineEdit.setEnabled(enabled)
|
|
self.DeviceTypeComboBox.setEnabled(enabled)
|
|
self.DeviceTypeLabel.setEnabled(enabled)
|
|
|
|
|
|
def setManualDiscovery(self, enabled):
|
|
self.ManualGroupBox.setEnabled(enabled)
|
|
|
|
|
|
def setNetworkDiscovery(self, enabled):
|
|
self.NetworkDiscoveryMethodLabel.setEnabled(enabled)
|
|
self.NetworkDiscoveryMethodComboBox.setEnabled(enabled)
|
|
self.NetworkDiscoveryMethodComboBox.setCurrentIndex(0)
|
|
|
|
|
|
def UsbRadioButton_toggled(self, radio_enabled):
|
|
self.setUsbRadioButton(radio_enabled)
|
|
|
|
|
|
def setUsbRadioButton(self, checked):
|
|
self.setNetworkDiscovery(not checked)
|
|
self.setJetDirect(not checked)
|
|
self.setNetworkOptions(not checked)
|
|
self.setSearchOptions(checked)
|
|
self.setManualDiscovery(checked)
|
|
|
|
if checked:
|
|
self.ManualParamLabel.setText(self.__tr("USB bus ID:device ID (bbb:ddd):"))
|
|
self.bus = 'usb'
|
|
# TODO: Set bbb:ddd validator
|
|
|
|
|
|
def NetworkRadioButton_toggled(self, radio_enabled):
|
|
self.setNetworkRadioButton(radio_enabled)
|
|
|
|
|
|
def setNetworkRadioButton(self, checked):
|
|
self.setNetworkDiscovery(checked)
|
|
self.setJetDirect(checked)
|
|
self.setNetworkOptions(checked)
|
|
self.setSearchOptions(checked)
|
|
self.setManualDiscovery(checked)
|
|
|
|
|
|
if checked:
|
|
self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
|
|
self.bus = 'net'
|
|
# TODO: Reset validator
|
|
|
|
def WirelessButton_toggled(self, radio_enabled):
|
|
self.setWirelessButton(radio_enabled)
|
|
|
|
|
|
def setWirelessButton(self, checked):
|
|
self.setNetworkDiscovery(not checked)
|
|
self.setJetDirect(not checked)
|
|
self.setNetworkOptions(not checked)
|
|
self.setSearchOptions(not checked)
|
|
self.setManualDiscovery(not checked)
|
|
|
|
|
|
if checked:
|
|
self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
|
|
self.bus = 'net'
|
|
|
|
|
|
def ParallelRadioButton_toggled(self, radio_enabled):
|
|
self.setParallelRadioButton(radio_enabled)
|
|
|
|
|
|
def setParallelRadioButton(self, checked):
|
|
self.setNetworkDiscovery(not checked)
|
|
self.setJetDirect(not checked)
|
|
self.setNetworkOptions(not checked)
|
|
self.setSearchOptions(not checked)
|
|
self.setManualDiscovery(not checked)
|
|
|
|
|
|
if checked:
|
|
self.ManualParamLabel.setText(self.__tr("Device node (/dev/...):"))
|
|
self.bus = 'par'
|
|
# TODO: Set /dev/... validator
|
|
|
|
|
|
def NetworkTTLSpinBox_valueChanged(self, ttl):
|
|
self.ttl = ttl
|
|
|
|
|
|
def NetworkTimeoutSpinBox_valueChanged(self, timeout):
|
|
self.timeout = timeout
|
|
|
|
#
|
|
# DEVICES PAGE
|
|
#
|
|
|
|
def initDevicesPage(self):
|
|
self.RefreshButton.clicked.connect(self.RefreshButton_clicked)
|
|
|
|
|
|
def showDevicesPage(self):
|
|
self.BackButton.setEnabled(True)
|
|
self.setNextButton(BUTTON_NEXT)
|
|
search = ""
|
|
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
try:
|
|
if not self.devices:
|
|
if self.manual and self.param: # manual, but not passed-in on command line
|
|
self.manualDiscovery()
|
|
|
|
else: # probe
|
|
net_search_type = ''
|
|
|
|
if self.bus == 'net':
|
|
if self.discovery_method == 0:
|
|
net_search_type = "slp"
|
|
elif self.discovery_method == 1:
|
|
net_search_type = "mdns"
|
|
else:
|
|
net_search_type = "avahi"
|
|
|
|
log.info("Searching... (bus=%s, timeout=%d, ttl=%d, search=%s desc=%d, method=%s)" %
|
|
(self.bus, self.timeout, self.ttl, self.search or "(None)",
|
|
self.device_desc, net_search_type))
|
|
else:
|
|
log.info("Searching... (bus=%s, search=%s, desc=%d)" %
|
|
(self.bus, self.search or "(None)", self.device_desc))
|
|
|
|
if self.device_desc == DEVICE_DESC_SINGLE_FUNC:
|
|
filter_dict = {'scan-type' : (operator.le, SCAN_TYPE_NONE)}
|
|
|
|
elif self.device_desc == DEVICE_DESC_MULTI_FUNC:
|
|
filter_dict = {'scan-type': (operator.gt, SCAN_TYPE_NONE)}
|
|
|
|
else: # DEVICE_DESC_ALL
|
|
filter_dict = {}
|
|
|
|
if self.bus == 'usb':
|
|
try:
|
|
from base import smart_install
|
|
except ImportError:
|
|
log.error("Failed to Import smart_install.py from base")
|
|
else: #if no Smart Install device found, ignores.
|
|
QApplication.restoreOverrideCursor()
|
|
smart_install.disable(GUI_MODE, 'qt4')
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
|
|
self.devices = device.probeDevices([self.bus], self.timeout, self.ttl,
|
|
filter_dict, self.search, net_search=net_search_type)
|
|
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
self.clearDevicesTable()
|
|
|
|
if self.devices:
|
|
self.NextButton.setEnabled(True)
|
|
self.DevicesFoundIcon.setPixmap(load_pixmap('info', '16x16'))
|
|
|
|
if len(self.devices) == 1:
|
|
self.DevicesFoundLabel.setText(self.__tr("<b>1 device found.</b> Click <i>Next</i> to continue."))
|
|
else:
|
|
self.DevicesFoundLabel.setText(self.__tr("<b>%s devices found.</b> Select the device to install and click <i>Next</i> to continue."%(len(self.devices))))
|
|
|
|
self.loadDevicesTable()
|
|
|
|
else:
|
|
self.NextButton.setEnabled(False)
|
|
self.DevicesFoundIcon.setPixmap(load_pixmap('error', '16x16'))
|
|
log.error("No devices found on bus: %s" % self.bus)
|
|
self.DevicesFoundLabel.setText(self.__tr("<b>No devices found.</b><br>Click <i>Back</i> to change discovery options, or <i>Refresh</i> to search again."))
|
|
if self.bus == 'net' and utils.check_lan():
|
|
FailureUI(self, self.__tr('''<b>HPLIP cannot detect printers in your network.</b><p>This may be due to existing firewall settings blocking the required ports.
|
|
When you are in a trusted network environment, you may open the ports for network services like mdns and slp in the firewall. For detailed steps follow the link.
|
|
<b>https://developers.hp.com/hp-linux-imaging-and-printing/KnowledgeBase/Troubleshooting/TroubleshootNetwork</b></p>'''),
|
|
self.__tr("HP Device Manager"))
|
|
|
|
|
|
self.displayPage(PAGE_DEVICES)
|
|
|
|
|
|
def loadDevicesTable(self):
|
|
self.DevicesTableWidget.setRowCount(len(self.devices))
|
|
|
|
if self.bus == 'net':
|
|
if self.discovery_method == 0:
|
|
headers = [self.__tr('Model'), self.__tr('IP Address'), self.__tr('Host Name'), self.__tr('Device URI')]
|
|
device_uri_col = 3
|
|
else:
|
|
headers = [self.__tr('Model'), self.__tr('Host Name'), self.__tr('Device URI')]
|
|
device_uri_col = 2
|
|
else:
|
|
headers = [self.__tr('Model'), self.__tr('Device URI')]
|
|
device_uri_col = 1
|
|
|
|
self.DevicesTableWidget.setColumnCount(len(headers))
|
|
self.DevicesTableWidget.setHorizontalHeaderLabels(headers)
|
|
flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
|
|
|
|
for row, d in enumerate(self.devices):
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(d)
|
|
model_ui = models.normalizeModelUIName(model)
|
|
|
|
i = DeviceTableWidgetItem(str(model_ui), d)
|
|
i.setFlags(flags)
|
|
self.DevicesTableWidget.setItem(row, 0, i)
|
|
|
|
i = QTableWidgetItem(str(d))
|
|
i.setFlags(flags)
|
|
self.DevicesTableWidget.setItem(row, device_uri_col, i)
|
|
|
|
if self.bus == 'net':
|
|
i = QTableWidgetItem(str(host))
|
|
i.setFlags(flags)
|
|
self.DevicesTableWidget.setItem(row, 1, i)
|
|
|
|
if self.discovery_method == 0:
|
|
i = QTableWidgetItem(str(self.devices[d][2]))
|
|
i.setFlags(flags)
|
|
self.DevicesTableWidget.setItem(row, 2, i)
|
|
|
|
self.DevicesTableWidget.resizeColumnsToContents()
|
|
self.DevicesTableWidget.selectRow(0)
|
|
self.DevicesTableWidget.setSortingEnabled(True)
|
|
self.DevicesTableWidget.sortItems(0)
|
|
|
|
|
|
def clearDevicesTable(self):
|
|
self.DevicesTableWidget.clear()
|
|
self.DevicesTableWidget.setRowCount(0)
|
|
self.DevicesTableWidget.setColumnCount(0)
|
|
|
|
|
|
def RefreshButton_clicked(self):
|
|
self.clearDevicesTable()
|
|
self.devices = []
|
|
QTimer.singleShot(0, self.showDevicesPage)
|
|
|
|
#
|
|
# ADD PRINTER PAGE
|
|
#
|
|
|
|
def initAddPrinterPage(self):
|
|
self.mq = {}
|
|
|
|
self.PrinterNameLineEdit.textEdited.connect(self.PrinterNameLineEdit_textEdited)
|
|
|
|
self.FaxNameLineEdit.textEdited.connect(self.FaxNameLineEdit_textEdited)
|
|
|
|
self.SetupPrintGroupBox.clicked.connect(self.SetupPrintGroupBox_clicked)
|
|
self.SetupFaxGroupBox.clicked.connect(self.SetupFaxGroupBox_clicked)
|
|
self.PrinterNameLineEdit.setValidator(PrinterNameValidator(self.PrinterNameLineEdit))
|
|
self.FaxNameLineEdit.setValidator(PrinterNameValidator(self.FaxNameLineEdit))
|
|
self.FaxNumberLineEdit.setValidator(PhoneNumValidator(self.FaxNumberLineEdit))
|
|
self.OtherPPDButton.setIcon(QIcon(load_pixmap('folder_open', '16x16')))
|
|
self.OtherPPDButton.clicked.connect(self.OtherPPDButton_clicked)
|
|
|
|
self.OtherPPDButton.setToolTip(self.__tr("Browse for an alternative PPD file for this printer."))
|
|
|
|
self.printer_fax_names_same = False
|
|
self.printer_name = ''
|
|
self.fax_name = ''
|
|
self.fax_setup_ok = True
|
|
self.fax_setup = False
|
|
self.print_setup = False
|
|
|
|
|
|
def showAddPrinterPage(self):
|
|
# Install the plugin if needed...
|
|
pluginObj = pluginhandler.PluginHandle()
|
|
plugin = self.mq.get('plugin', PLUGIN_NONE)
|
|
plugin_reason = self.mq.get('plugin-reason', PLUGIN_REASON_NONE)
|
|
if plugin > PLUGIN_NONE:
|
|
|
|
if pluginObj.getStatus() != pluginhandler.PLUGIN_INSTALLED:
|
|
ok, sudo_ok = pkit.run_plugin_command(plugin == PLUGIN_REQUIRED, plugin_reason)
|
|
if not sudo_ok:
|
|
FailureUI(self, self.__tr("<b>Unable to find an appropriate su/sudo utiltity to run hp-plugin.</b><p>Install kdesu, gnomesu, or gksu.</p>"))
|
|
return
|
|
if not ok or pluginObj.getStatus() != pluginhandler.PLUGIN_INSTALLED:
|
|
if plugin == PLUGIN_REQUIRED:
|
|
FailureUI(self, self.__tr("<b>The device you are trying to setup requires a binary plug-in. Some functionalities may not work as expected without plug-ins.<p> Please run 'hp-plugin' as normal user to install plug-ins.</b></p><p>Visit <u>http://hplipopensource.com</u> for more infomation.</p>"))
|
|
return
|
|
else:
|
|
WarningUI(self, self.__tr("Either you have chosen to skip the installation of the optional plug-in or that installation has failed. Your printer may not function at optimal performance."))
|
|
|
|
self.setNextButton(BUTTON_ADD_PRINTER)
|
|
self.print_setup = self.setDefaultPrinterName()
|
|
if self.print_setup:
|
|
self.SetupPrintGroupBox.setCheckable(True)
|
|
self.SetupPrintGroupBox.setEnabled(True)
|
|
self.SendTestPageCheckBox.setCheckable(True)
|
|
self.SendTestPageCheckBox.setEnabled(True)
|
|
self.findPrinterPPD()
|
|
self.updatePPD()
|
|
else:
|
|
self.print_ppd = None
|
|
self.SetupPrintGroupBox.setCheckable(False)
|
|
self.SetupPrintGroupBox.setEnabled(False)
|
|
self.SendTestPageCheckBox.setCheckable(False)
|
|
self.SendTestPageCheckBox.setEnabled(False)
|
|
|
|
if fax_import_ok and prop.fax_build and \
|
|
self.mq.get('fax-type', FAX_TYPE_NONE) not in (FAX_TYPE_NONE, FAX_TYPE_NOT_SUPPORTED):
|
|
self.fax_setup = True
|
|
self.SetupFaxGroupBox.setChecked(True)
|
|
self.SetupFaxGroupBox.setEnabled(True)
|
|
|
|
self.fax_setup = self.setDefaultFaxName()
|
|
if self.fax_setup:
|
|
self.findFaxPPD()
|
|
self.readwriteFaxInformation()
|
|
else:
|
|
self.fax_setup = False
|
|
self.SetupFaxGroupBox.setChecked(False)
|
|
self.SetupFaxGroupBox.setEnabled(False)
|
|
|
|
else:
|
|
self.SetupFaxGroupBox.setChecked(False)
|
|
self.SetupFaxGroupBox.setEnabled(False)
|
|
self.fax_name = ''
|
|
self.fax_name_ok = True
|
|
self.fax_setup = False
|
|
self.fax_setup_ok = True
|
|
|
|
|
|
|
|
if self.print_setup or self.fax_setup:
|
|
self.setAddPrinterButton()
|
|
self.displayPage(PAGE_ADD_PRINTER)
|
|
else:
|
|
log.info("Exiting the setup...")
|
|
self.close()
|
|
|
|
|
|
|
|
|
|
def updatePPD(self):
|
|
if self.print_ppd is None:
|
|
log.error("No appropriate print PPD file found for model %s" % self.model)
|
|
self.PPDFileLineEdit.setText(self.__tr('(Not found. Click browse button to select a PPD file.)'))
|
|
try:
|
|
self.PPDFileLineEdit.setStyleSheet("background-color: yellow")
|
|
except AttributeError:
|
|
pass
|
|
self.PrinterDescriptionLineEdit.setText(str(""))
|
|
|
|
else:
|
|
self.PPDFileLineEdit.setText(self.print_ppd[0])
|
|
self.PrinterDescriptionLineEdit.setText(self.print_ppd[1])
|
|
try:
|
|
self.PPDFileLineEdit.setStyleSheet("")
|
|
except AttributeError:
|
|
pass
|
|
|
|
|
|
def OtherPPDButton_clicked(self, b):
|
|
ppd_file = to_unicode(QFileDialog.getOpenFileName(self, self.__tr("Select PPD File"),
|
|
sys_conf.get('dirs', 'ppd'),
|
|
self.__tr("PPD Files (*.ppd *.ppd.gz);;All Files (*)")))
|
|
|
|
if ppd_file and os.path.exists(ppd_file):
|
|
self.print_ppd = (ppd_file, cups.getPPDDescription(ppd_file))
|
|
self.updatePPD()
|
|
self.setAddPrinterButton()
|
|
|
|
|
|
def findPrinterPPD(self):
|
|
"""
|
|
for ubuntu 20.10 not able get ppd list from cups server.
|
|
so fetching ppds hplip ppds directly
|
|
"""
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
try:
|
|
self.print_ppd = None
|
|
self.ppds = cups.getSystemPPDs()
|
|
self.ppd_name = ""
|
|
# if ppd list from cups server is empty searching for hplip ppds.
|
|
if not self.ppds:
|
|
ppdName = cups.getPpdName(self.model)
|
|
self.path = cups.getPPDPath1()
|
|
# path for hplip ppds in local system
|
|
self.ppd_name = str(self.path + '/' + ppdName)
|
|
self.print_ppd = (self.ppd_name, '')
|
|
|
|
else :
|
|
|
|
self.print_ppd = cups.getPPDFile2(self.mq, self.model, self.ppds)
|
|
if "scanjet" in self.model or "digital_sender" in self.model:
|
|
self.print_ppd = None
|
|
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
|
|
def findFaxPPD(self):
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
try:
|
|
self.fax_ppd, fax_ppd_name, nick = cups.getFaxPPDFile(self.mq, self.model)
|
|
if self.fax_ppd:
|
|
self.fax_setup_ok = True
|
|
else:
|
|
self.fax_setup_ok = False
|
|
FailureUI(self, self.__tr("<b>Unable to locate the HPLIP Fax PPD file:</b><p>%s.ppd.gz</p><p>Fax setup has been disabled."%fax_ppd_name))
|
|
self.fax_setup = False
|
|
self.SetupFaxGroupBox.setChecked(False)
|
|
self.SetupFaxGroupBox.setEnabled(False)
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
|
|
def setDefaultPrinterName(self):
|
|
self.installed_print_devices = device.getSupportedCUPSDevices(['hp'])
|
|
log.debug(self.installed_print_devices)
|
|
|
|
self.installed_queues = [p.name for p in cups.getPrinters()]
|
|
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
|
|
default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
|
|
|
|
printer_name = default_model
|
|
installed_printer_names = device.getSupportedCUPSPrinterNames(['hp'])
|
|
# Check for duplicate names
|
|
if (self.device_uri in self.installed_print_devices and printer_name in self.installed_print_devices[self.device_uri]) \
|
|
or (printer_name in installed_printer_names):
|
|
warn_text = self.__tr("<b>One or more print queues already exist for this device: %s</b>.<br> <b>Would you like to install another print queue for this device ?</b>" %
|
|
', '.join([printer for printer in installed_printer_names if printer_name in printer]))
|
|
if ( QMessageBox.warning(self,
|
|
self.windowTitle(),
|
|
warn_text,
|
|
QMessageBox.Yes|\
|
|
QMessageBox.No,
|
|
QMessageBox.NoButton) == QMessageBox.Yes ):
|
|
|
|
i = 2
|
|
while True:
|
|
t = printer_name + "_%d" % i
|
|
if (t not in installed_printer_names) and (self.device_uri not in self.installed_print_devices or t not in self.installed_print_devices[self.device_uri]):
|
|
printer_name += "_%d" % i
|
|
break
|
|
i += 1
|
|
else:
|
|
self.printer_name_ok = False
|
|
return False
|
|
|
|
self.printer_name_ok = True
|
|
self.PrinterNameLineEdit.setText(printer_name)
|
|
log.debug(printer_name)
|
|
self.printer_name = printer_name
|
|
return True
|
|
|
|
|
|
def setDefaultFaxName(self):
|
|
self.installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])
|
|
log.debug(self.installed_fax_devices)
|
|
|
|
self.fax_uri = self.device_uri.replace('hp:', 'hpfax:')
|
|
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.fax_uri)
|
|
default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
|
|
|
|
fax_name = default_model + "_fax"
|
|
installed_fax_names = device.getSupportedCUPSPrinterNames(['hpfax'])
|
|
# Check for duplicate names
|
|
if (self.fax_uri in self.installed_fax_devices and fax_name in self.installed_fax_devices[self.fax_uri]) \
|
|
or (fax_name in installed_fax_names):
|
|
warn_text = self.__tr(
|
|
"<b>One or more fax queues already exist for this device: %s</b>.<br> <b>Would you like to install another fax queue for this device ?</b>" %
|
|
', '.join([fax_device for fax_device in installed_fax_names if fax_name in fax_device]))
|
|
if ( QMessageBox.warning(self,
|
|
self.windowTitle(),
|
|
warn_text,
|
|
QMessageBox.Yes|\
|
|
QMessageBox.No,
|
|
QMessageBox.NoButton) == QMessageBox.Yes ):
|
|
i = 2
|
|
while True:
|
|
t = fax_name + "_%d" % i
|
|
if (t not in installed_fax_names) and (self.fax_uri not in self.installed_fax_devices or t not in self.installed_fax_devices[self.fax_uri]):
|
|
fax_name += "_%d" % i
|
|
break
|
|
i += 1
|
|
else:
|
|
self.fax_name_ok = False
|
|
return False
|
|
|
|
self.fax_name_ok = True
|
|
self.FaxNameLineEdit.setText(fax_name)
|
|
self.fax_name = fax_name
|
|
return True
|
|
|
|
|
|
def PrinterNameLineEdit_textEdited(self, t):
|
|
self.printer_name = to_unicode(t)
|
|
self.printer_name_ok = True
|
|
|
|
if not self.printer_name:
|
|
self.PrinterNameLineEdit.setToolTip(self.__tr('You must enter a name for the printer.'))
|
|
self.printer_name_ok = False
|
|
|
|
elif self.fax_name == self.printer_name:
|
|
s = self.__tr('The printer name and fax name must be different. Please choose different names.')
|
|
self.PrinterNameLineEdit.setToolTip(s)
|
|
self.FaxNameLineEdit.setToolTip(s)
|
|
self.fax_name_ok = False
|
|
self.printer_name_ok = False
|
|
self.printer_fax_names_same = True
|
|
|
|
elif self.printer_name in self.installed_queues:
|
|
self.PrinterNameLineEdit.setToolTip(self.__tr('A printer already exists with this name. Please choose a different name.'))
|
|
self.printer_name_ok = False
|
|
|
|
elif self.printer_fax_names_same:
|
|
if self.fax_name != self.printer_name:
|
|
self.printer_fax_names_same = False
|
|
self.printer_name_ok = True
|
|
|
|
self.FaxNameLineEdit.emit(SIGNAL("textEdited(const QString &)"),
|
|
self.FaxNameLineEdit.text())
|
|
|
|
self.setIndicators()
|
|
self.setAddPrinterButton()
|
|
|
|
|
|
def FaxNameLineEdit_textEdited(self, t):
|
|
self.fax_name = to_unicode(t)
|
|
self.fax_name_ok = True
|
|
|
|
if not self.fax_name:
|
|
self.FaxNameLineEdit.setToolTip(self.__tr('You must enter a fax name.'))
|
|
self.fax_name_ok = False
|
|
|
|
elif self.fax_name == self.printer_name:
|
|
s = self.__tr('The printer name and fax name must be different. Please choose different names.')
|
|
self.PrinterNameLineEdit.setToolTip(s)
|
|
self.FaxNameLineEdit.setToolTip(s)
|
|
self.printer_name_ok = False
|
|
self.fax_name_ok = False
|
|
self.printer_fax_names_same = True
|
|
|
|
elif self.fax_name in self.installed_queues:
|
|
self.FaxNameLineEdit.setToolTip(self.__tr('A fax already exists with this name. Please choose a different name.'))
|
|
self.fax_name_ok = False
|
|
|
|
elif self.printer_fax_names_same:
|
|
if self.fax_name != self.printer_name:
|
|
self.printer_fax_names_same = False
|
|
self.fax_name_ok = True
|
|
|
|
self.PrinterNameLineEdit.emit(SIGNAL("textEdited(const QString&)"),
|
|
self.PrinterNameLineEdit.text())
|
|
|
|
self.setIndicators()
|
|
self.setAddPrinterButton()
|
|
|
|
def SetupPrintGroupBox_clicked(self):
|
|
if not self.SetupPrintGroupBox.isChecked():
|
|
self.SendTestPageCheckBox.setCheckable(False)
|
|
self.SendTestPageCheckBox.setEnabled(False)
|
|
else:
|
|
self.SendTestPageCheckBox.setCheckable(True)
|
|
self.SendTestPageCheckBox.setEnabled(True)
|
|
self.setAddPrinterButton()
|
|
|
|
def SetupFaxGroupBox_clicked(self):
|
|
self.setAddPrinterButton()
|
|
|
|
|
|
def setIndicators(self):
|
|
if self.printer_name_ok:
|
|
self.PrinterNameLineEdit.setToolTip(str(""))
|
|
try:
|
|
self.PrinterNameLineEdit.setStyleSheet("")
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
try:
|
|
self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
|
|
except AttributeError:
|
|
pass
|
|
|
|
if self.fax_name_ok:
|
|
self.FaxNameLineEdit.setToolTip(str(""))
|
|
try:
|
|
self.PrinterNameLineEdit.setStyleSheet("")
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
try:
|
|
self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
|
|
except AttributeError:
|
|
pass
|
|
|
|
|
|
def setAddPrinterButton(self):
|
|
'''
|
|
If the device is on usb and os doesn't supports ipp-usb we assign new ipp uri to the printer.
|
|
this is for driverless usb printer held by ippusbxd service on ubuntu 20 and above.
|
|
For network devices follow the old code.
|
|
'''
|
|
if(self.bus == "usb" and not os.path.isdir('/usr/share/ipp-usb/quirks')):
|
|
from base import local
|
|
from base.local import detectLocalDevices
|
|
try:
|
|
detected_devices = local.detectLocalDevices(ttl=4, timeout=10)
|
|
log.debug(" Detected devices from local.py ")
|
|
log.debug(detected_devices)
|
|
current_printer = self.model.replace('_'," ")
|
|
log.debug(" current pritner is: ")
|
|
#log.debug(detected_devices['printer_uri'])
|
|
log.debug(current_printer)
|
|
for key in detected_devices:
|
|
if(detected_devices[key].lower() == current_printer.lower()):
|
|
log.debug("Assign ipp URI to the current printer")
|
|
#self.device_uri = Ipp_uri
|
|
self.device_uri = detected_devices['printer_uri']
|
|
else:
|
|
return
|
|
except Error as socket_error:
|
|
socket.error = socket_error
|
|
log.error("An error occured during network probe.[%s]"%socket_error)
|
|
raise ERROR_INTERNAL
|
|
|
|
if self.SetupPrintGroupBox.isChecked() or self.SetupFaxGroupBox.isChecked():
|
|
self.NextButton.setEnabled((self.print_setup and self.printer_name_ok and self.print_ppd is not None) or
|
|
(self.fax_setup and self.fax_name_ok))
|
|
else:
|
|
self.NextButton.setEnabled(False)
|
|
|
|
|
|
#
|
|
# ADD PRINTER
|
|
#
|
|
|
|
def addPrinter(self):
|
|
if self.print_setup:
|
|
print_sts = self.setupPrinter()
|
|
if print_sts == cups.IPP_FORBIDDEN or print_sts == cups.IPP_NOT_AUTHENTICATED or print_sts == cups.IPP_NOT_AUTHORIZED:
|
|
pass # User doesn't have sufficient permissions so ignored.
|
|
if print_sts == cups.IPP_OK:
|
|
self.flashFirmware()
|
|
if self.print_test_page:
|
|
self.printTestPage()
|
|
|
|
if self.fax_setup:
|
|
if self.setupFax() == cups.IPP_OK:
|
|
self.readwriteFaxInformation(False)
|
|
|
|
self.close()
|
|
|
|
|
|
#
|
|
# Updating firmware download for supported devices.
|
|
#
|
|
def flashFirmware(self):
|
|
if self.mq.get('fw-download', False):
|
|
try:
|
|
d = device.Device(self.device_uri)
|
|
except Error as e:
|
|
FailureUI(self, self.__tr("<b>Error opening device. Firmware download is Failed.</b><p>%s (%s)." % (e.msg, e.opt)))
|
|
else:
|
|
if d.downloadFirmware():
|
|
log.info("Firmware download successful.\n")
|
|
else:
|
|
FailureUI(self, self.__tr("<b>Firmware download is Failed.</b>"))
|
|
d.close()
|
|
|
|
#
|
|
# SETUP PRINTER/FAX
|
|
#
|
|
|
|
def setupPrinter(self):
|
|
status = cups.IPP_BAD_REQUEST
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
try:
|
|
if not os.path.exists(self.print_ppd[0]): # assume foomatic: or some such
|
|
add_prnt_args = (from_unicode_to_str(self.printer_name), self.device_uri, self.print_location, '', self.print_ppd[0], self.print_desc)
|
|
else:
|
|
add_prnt_args = (from_unicode_to_str(self.printer_name), self.device_uri, self.print_location, self.print_ppd[0], '', self.print_desc)
|
|
|
|
status, status_str = cups.cups_operation(cups.addPrinter, GUI_MODE, 'qt4', self, *add_prnt_args)
|
|
log.debug(device.getSupportedCUPSDevices(['hp']))
|
|
|
|
if status != cups.IPP_OK:
|
|
QApplication.restoreOverrideCursor()
|
|
FailureUI(self, self.__tr("<b>Printer queue setup failed.</b> <p>Error : %s"%status_str))
|
|
else:
|
|
# sending Event to add this device in hp-systray
|
|
utils.sendEvent(EVENT_CUPS_QUEUES_ADDED,self.device_uri, self.printer_name)
|
|
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
return status
|
|
|
|
|
|
def setupFax(self):
|
|
status = cups.IPP_BAD_REQUEST
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
try:
|
|
if not os.path.exists(self.fax_ppd):
|
|
status, status_str = cups.addPrinter(self.fax_name,
|
|
self.fax_uri, self.fax_location, '', self.fax_ppd, self.fax_desc)
|
|
else:
|
|
status, status_str = cups.addPrinter(self.fax_name,
|
|
self.fax_uri, self.fax_location, self.fax_ppd, '', self.fax_desc)
|
|
|
|
log.debug(device.getSupportedCUPSDevices(['hpfax']))
|
|
|
|
if status != cups.IPP_OK:
|
|
QApplication.restoreOverrideCursor()
|
|
FailureUI(self, self.__tr("<b>Fax queue setup failed.</b><p>Error : %s"%status_str))
|
|
else:
|
|
# sending Event to add this device in hp-systray
|
|
utils.sendEvent(EVENT_CUPS_QUEUES_ADDED,self.fax_uri, self.fax_name)
|
|
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
return status
|
|
|
|
|
|
def readwriteFaxInformation(self, read=True):
|
|
try:
|
|
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
|
|
|
|
d = fax.getFaxDevice(self.fax_uri, disable_dbus=True)
|
|
|
|
while True:
|
|
try:
|
|
d.open()
|
|
except Error:
|
|
error_text = self.__tr("Unable to communicate with the device. Please check the device and try again.")
|
|
log.error(to_unicode(error_text))
|
|
if QMessageBox.critical(self,
|
|
self.windowTitle(),
|
|
error_text,
|
|
QMessageBox.Retry | QMessageBox.Default |\
|
|
QMessageBox.Cancel | QMessageBox.Escape,
|
|
QMessageBox.NoButton) == QMessageBox.Cancel:
|
|
break
|
|
|
|
else:
|
|
try:
|
|
tries = 0
|
|
ok = True
|
|
|
|
while True:
|
|
tries += 1
|
|
|
|
try:
|
|
if read:
|
|
#self.fax_number = str(d.getPhoneNum())
|
|
#self.fax_name_company = str(d.getStationName())
|
|
self.fax_number = to_unicode(d.getPhoneNum())
|
|
self.fax_name_company = to_unicode(d.getStationName())
|
|
else:
|
|
d.setStationName(self.fax_name_company)
|
|
d.setPhoneNum(self.fax_number)
|
|
|
|
except Error:
|
|
error_text = self.__tr("<b>Device I/O Error</b><p>Could not communicate with device. Device may be busy.")
|
|
log.error(to_unicode(error_text))
|
|
|
|
if QMessageBox.critical(self,
|
|
self.windowTitle(),
|
|
error_text,
|
|
QMessageBox.Retry | QMessageBox.Default |\
|
|
QMessageBox.Cancel | QMessageBox.Escape,
|
|
QMessageBox.NoButton) == QMessageBox.Cancel:
|
|
break
|
|
|
|
|
|
time.sleep(5)
|
|
ok = False
|
|
|
|
if tries > 12:
|
|
break
|
|
|
|
else:
|
|
ok = True
|
|
break
|
|
|
|
finally:
|
|
d.close()
|
|
|
|
if ok and read:
|
|
self.FaxNumberLineEdit.setText(self.fax_number)
|
|
self.NameCompanyLineEdit.setText(self.fax_name_company)
|
|
|
|
break
|
|
|
|
finally:
|
|
QApplication.restoreOverrideCursor()
|
|
|
|
|
|
def printTestPage(self):
|
|
try:
|
|
d = device.Device(self.device_uri)
|
|
except Error as e:
|
|
FailureUI(self, self.__tr("<b>Device error:</b><p>%s (%s)." % (e.msg, e.opt)))
|
|
|
|
else:
|
|
try:
|
|
d.open()
|
|
except Error:
|
|
FailureUI(self, self.__tr("<b>Unable to print to printer.</b><p>Please check device and try again."))
|
|
else:
|
|
if d.isIdleAndNoError():
|
|
d.close()
|
|
|
|
try:
|
|
d.printTestPage(self.printer_name)
|
|
except Error as e:
|
|
if e.opt == ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE:
|
|
FailureUI(self, self.__tr("<b>No CUPS queue found for device.</b><p>Please install the printer in CUPS and try again."))
|
|
else:
|
|
FailureUI(self, self.__tr("<b>Printer Error</b><p>An error occured: %s (code=%d)." % (e.msg, e.opt)))
|
|
else:
|
|
FailureUI(self, self.__tr("<b>Printer Error.</b><p>Printer is busy, offline, or in an error state. Please check the device and try again."))
|
|
d.close()
|
|
|
|
#
|
|
# Remove Page
|
|
#
|
|
|
|
def initRemovePage(self):
|
|
pass
|
|
|
|
|
|
def showRemovePage(self):
|
|
self.displayPage(PAGE_REMOVE)
|
|
self.StepText.setText(self.__tr("Step 1 of 1"))
|
|
self.setNextButton(BUTTON_REMOVE)
|
|
self.BackButton.setEnabled(False)
|
|
self.NextButton.setEnabled(False)
|
|
|
|
self.RemoveDevicesTableWidget.verticalHeader().hide()
|
|
|
|
self.installed_printers = device.getSupportedCUPSPrinters(['hp', 'hpfax'])
|
|
log.debug(self.installed_printers)
|
|
|
|
if not self.installed_printers:
|
|
FailureUI(self, self.__tr("<b>No printers or faxes found to remove.</b><p>You must setup a least one printer or fax before you can remove it."))
|
|
self.close()
|
|
return
|
|
|
|
self.RemoveDevicesTableWidget.setRowCount(len(self.installed_printers))
|
|
|
|
headers = [self.__tr("Select"), self.__tr('Printer (Queue) Name'), self.__tr('Type'), self.__tr('Device URI')]
|
|
|
|
self.RemoveDevicesTableWidget.setColumnCount(len(headers))
|
|
self.RemoveDevicesTableWidget.setHorizontalHeaderLabels(headers)
|
|
flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
|
|
|
|
row = 0
|
|
for p in self.installed_printers:
|
|
widget = QCheckBox(self.RemoveDevicesTableWidget)
|
|
widget.stateChanged.connect(self.CheckBox_stateChanged)
|
|
self.RemoveDevicesTableWidget.setCellWidget(row, 0, widget)
|
|
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
|
|
device.parseDeviceURI(p.device_uri)
|
|
|
|
if self.device_uri is not None and self.device_uri == p.device_uri:
|
|
widget.setCheckState(Qt.Checked)
|
|
|
|
i = QTableWidgetItem(str(p.name))
|
|
i.setFlags(flags)
|
|
i.setData(Qt.UserRole, p.name)
|
|
self.RemoveDevicesTableWidget.setItem(row, 1, i)
|
|
|
|
if back_end == 'hpfax':
|
|
typ = self.__tr("Fax")
|
|
else:
|
|
typ = self.__tr("Printer")
|
|
|
|
i = QTableWidgetItem(typ)
|
|
i.setFlags(flags)
|
|
self.RemoveDevicesTableWidget.setItem(row, 2, i)
|
|
|
|
i = QTableWidgetItem(str(p.device_uri))
|
|
i.setFlags(flags)
|
|
self.RemoveDevicesTableWidget.setItem(row, 3, i)
|
|
|
|
row += 1
|
|
|
|
self.RemoveDevicesTableWidget.resizeColumnsToContents()
|
|
|
|
|
|
def CheckBox_stateChanged(self, i):
|
|
for row in range(self.RemoveDevicesTableWidget.rowCount()):
|
|
widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
|
|
if widget.checkState() == Qt.Checked:
|
|
self.NextButton.setEnabled(True)
|
|
break
|
|
else:
|
|
self.NextButton.setEnabled(False)
|
|
|
|
|
|
#
|
|
# Misc
|
|
#
|
|
|
|
def NextButton_clicked(self):
|
|
p = self.StackedWidget.currentIndex()
|
|
if p == PAGE_DISCOVERY:
|
|
self.manual = self.ManualGroupBox.isChecked()
|
|
self.param = to_unicode(self.ManualParamLineEdit.text())
|
|
self.jd_port = self.JetDirectSpinBox.value()
|
|
self.search = to_unicode(self.SearchLineEdit.text())
|
|
self.device_desc = value_int(self.DeviceTypeComboBox.itemData(self.DeviceTypeComboBox.currentIndex()))[0]
|
|
self.discovery_method = self.NetworkDiscoveryMethodComboBox.currentIndex()
|
|
|
|
if self.WirelessButton.isChecked():
|
|
dlg = WifiSetupDialog(self, device_uri=None, standalone=False)
|
|
dlg.exec_()
|
|
|
|
if dlg.success == SUCCESS_CONNECTED:
|
|
self.manual = True
|
|
self.param = dlg.hn
|
|
self.bus = 'net'
|
|
if not self.WirelessButton.isChecked():
|
|
self.showDevicesPage()
|
|
|
|
elif p == PAGE_DEVICES:
|
|
row = self.DevicesTableWidget.currentRow()
|
|
self.device_uri = self.DevicesTableWidget.item(row, 0).device_uri
|
|
self.mq = device.queryModelByURI(self.device_uri)
|
|
back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
|
|
self.model = models.normalizeModelName(model).lower()
|
|
self.showAddPrinterPage()
|
|
|
|
elif p == PAGE_ADD_PRINTER:
|
|
self.print_test_page = self.SendTestPageCheckBox.isChecked()
|
|
self.print_setup = self.SetupPrintGroupBox.isChecked()
|
|
self.fax_setup = self.SetupFaxGroupBox.isChecked()
|
|
self.print_location = from_unicode_to_str(to_unicode(self.PrinterLocationLineEdit.text()))
|
|
self.print_desc = from_unicode_to_str(to_unicode(self.PrinterDescriptionLineEdit.text()))
|
|
self.fax_desc = from_unicode_to_str(to_unicode(self.FaxDescriptionLineEdit.text()))
|
|
self.fax_location = from_unicode_to_str(to_unicode(self.FaxLocationLineEdit.text()))
|
|
self.fax_name_company = to_unicode(self.NameCompanyLineEdit.text())
|
|
self.fax_number = to_unicode(self.FaxNumberLineEdit.text())
|
|
self.addPrinter()
|
|
|
|
elif p == PAGE_REMOVE:
|
|
for row in range(self.RemoveDevicesTableWidget.rowCount()):
|
|
widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
|
|
if widget.checkState() == Qt.Checked:
|
|
item = self.RemoveDevicesTableWidget.item(row, 1)
|
|
printer = to_unicode(value_str(item.data(Qt.UserRole)))
|
|
uri = device.getDeviceURIByPrinterName(printer)
|
|
log.debug("Removing printer: %s" % printer)
|
|
status, status_str = cups.cups_operation(cups.delPrinter, GUI_MODE, 'qt4', self, printer)
|
|
|
|
if status != cups.IPP_OK:
|
|
FailureUI(self, self.__tr("<b>Unable to delete '%s' queue. </b><p>Error : %s"%(printer,status_str)))
|
|
if status == cups.IPP_FORBIDDEN or status == cups.IPP_NOT_AUTHENTICATED or status == cups.IPP_NOT_AUTHORIZED:
|
|
break
|
|
else:
|
|
# sending Event to add this device in hp-systray
|
|
utils.sendEvent(EVENT_CUPS_QUEUES_REMOVED, uri, printer)
|
|
|
|
self.close()
|
|
|
|
else:
|
|
log.error("Invalid page!") # shouldn't happen!
|
|
|
|
|
|
def BackButton_clicked(self):
|
|
p = self.StackedWidget.currentIndex()
|
|
if p == PAGE_DEVICES:
|
|
self.devices = {}
|
|
self.showDiscoveryPage()
|
|
|
|
elif p == PAGE_ADD_PRINTER:
|
|
self.showDevicesPage()
|
|
|
|
else:
|
|
log.error("Invalid page!") # shouldn't happen!
|
|
|
|
|
|
def CancelButton_clicked(self):
|
|
self.close()
|
|
|
|
|
|
def displayPage(self, page):
|
|
self.StackedWidget.setCurrentIndex(page)
|
|
self.updateStepText(page)
|
|
|
|
|
|
def setNextButton(self, typ=BUTTON_FINISH):
|
|
if typ == BUTTON_ADD_PRINTER:
|
|
self.NextButton.setText(self.__tr("Add Printer"))
|
|
elif typ == BUTTON_NEXT:
|
|
self.NextButton.setText(self.__tr("Next >"))
|
|
elif typ == BUTTON_FINISH:
|
|
self.NextButton.setText(self.__tr("Finish"))
|
|
elif typ == BUTTON_REMOVE:
|
|
self.NextButton.setText(self.__tr("Remove"))
|
|
|
|
|
|
def updateStepText(self, p):
|
|
self.StepText.setText(self.__tr("Step %s of %s"%(p+1, self.max_page+1))) #Python 3.2
|
|
|
|
|
|
def __tr(self,s,c = None):
|
|
return qApp.translate("SetupDialog",s,c)
|
|
|
|
|