%PDF- %PDF-
Direktori : /usr/share/hplip/ui5/ |
Current File : //usr/share/hplip/ui5/setupdialog.py |
# -*- 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.CancelPushButton = QPushButton(self) Layout.addWidget(self.CancelPushButton, 3, 1) self.languageChange() self.resize(QSize(420, 163).expandedTo(self.minimumSizeHint())) self.OkPushButton.clicked.connect(self.accept) self.CancelPushButton.clicked.connect(self.reject) 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")) self.CancelPushButton.setText(self.__tr("Cancel")) 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 # mDNS 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) self.faxnumberChanged = False self.faxCompanyNameChanged = False 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 = "mdns" elif self.discovery_method == 1: net_search_type = "slp" 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': 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('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) 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("") 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.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: if self.FaxNumberLineEdit.text() != self.fax_number: self.faxnumberChanged = True if self.NameCompanyLineEdit.text() != self.fax_name_company: self.faxCompanyNameChanged = True if self.faxnumberChanged or self.faxCompanyNameChanged: self.fax_name_company = to_unicode( self.NameCompanyLineEdit.text()) self.fax_number = to_unicode(self.FaxNumberLineEdit.text()) 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: # assume foomatic: or some such if not os.path.exists(self.print_ppd[0]): 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()) try: self.fax_number = to_unicode(d.getPhoneNum()) self.fax_name_company = to_unicode(d.getStationName()) except: log.debug("IO Error") self.fax_number = "" self.fax_name_company = "" else: if d.isAuthRequired() == True: promptText = "Enter the printer's username password password\n" while(True): username, password = showPasswordUI( promptText) if username == '' or password == '': return respCode = d.getCDMToken( username, password) if respCode != 200: promptText = "Invalid Username or Password!.\nRernter the printer's username password password\n" continue break if self.faxCompanyNameChanged: d.setStationName(self.fax_name_company) if self.faxnumberChanged: 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)