home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / hplip / ui / printerform.py < prev    next >
Encoding:
Python Source  |  2006-08-30  |  16.8 KB  |  489 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2001-2006 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Authors: Don Welch
  20.  
  21.  
  22. from qt import *
  23. from printerform_base import PrinterForm_base
  24. from base.g import *
  25. from base.codes import *
  26. from base import utils, device, magic
  27. from prnt import cups
  28. import glob
  29.  
  30.  
  31. class RangeValidator(QValidator):
  32.     def __init__(self, parent=None, name=None):
  33.         QValidator.__init__(self, parent, name)
  34.  
  35.     def validate(self, input, pos):
  36.         for x in str(input)[pos-1:]:
  37.             if x not in '0123456789,-':
  38.                 return QValidator.Invalid, pos
  39.  
  40.         return QValidator.Acceptable, pos
  41.  
  42.  
  43. class PrinterForm(PrinterForm_base):
  44.  
  45.     def __init__(self, sock, bus='cups', device_uri=None, printer_name=None, args=None, 
  46.                  parent=None,name=None,modal=0,fl=0):
  47.  
  48.         PrinterForm_base.__init__(self,parent,name,modal,fl)
  49.         self.sock = sock
  50.         self.device_uri = device_uri
  51.         self.printer_name = printer_name
  52.         self.file_list = []
  53.         self.auto_duplex_button_group = 0
  54.         self.orientation_button_group = 0
  55.         self.pages_button_group = 0
  56.         self.init_failed = False
  57.  
  58.         self.pageRangeEdit.setValidator(RangeValidator(self.pageRangeEdit))
  59.  
  60.         icon = QPixmap(os.path.join(prop.image_dir, 'HPmenu.png'))
  61.         self.setIcon(icon)
  62.         pix = QPixmap(os.path.join(prop.image_dir, 'folder_open.png'))
  63.         self.addFileButton.setPixmap(pix)
  64.         pix = QPixmap(os.path.join(prop.image_dir, 'folder_remove.png'))
  65.         self.delFileButton.setPixmap(pix)
  66.         pix = QPixmap(os.path.join(prop.image_dir, 'status_refresh.png'))
  67.         self.refreshToolButton.setPixmap(pix)
  68.         self.fileListView.setSorting(-1)
  69.  
  70.         self.allowable_mime_types = cups.getAllowableMIMETypes()
  71.         log.debug(self.allowable_mime_types)
  72.  
  73.         self.MIME_TYPES_DESC = \
  74.         {
  75.             "application/pdf" : self.__tr("PDF Document"),
  76.             "application/postscript" : self.__tr("Postscript Document"),
  77.             "application/vnd.hp-HPGL" : self.__tr("HP Graphics Language File"),
  78.             "application/x-cshell" : self.__tr("C Shell Script"),
  79.             "application/x-perl" : self.__tr("Perl Script"),
  80.             "application/x-python" : self.__tr("Python Program"),
  81.             "application/x-shell" : self.__tr("Shell Script"),
  82.             "text/plain" : self.__tr("Plain Text"),
  83.             "text/html" : self.__tr("HTML Dcoument"),
  84.             "image/gif" : self.__tr("GIF Image"),
  85.             "image/png" : self.__tr("PNG Image"),
  86.             "image/jpeg" : self.__tr("JPEG Image"),
  87.             "image/tiff" : self.__tr("TIFF Image"),
  88.             "image/x-bitmap" : self.__tr("Bitmap (BMP) Image"),
  89.             "image/x-photocd" : self.__tr("Photo CD Image"),
  90.             "image/x-portable-anymap" : self.__tr("Portable Image (PNM)"),
  91.             "image/x-portable-bitmap" : self.__tr("Portable B&W Image (PBM)"),
  92.             "image/x-portable-graymap" : self.__tr("Portable Grayscale Image (PGM)"),
  93.             "image/x-portable-pixmap" : self.__tr("Portable Color Image (PPM)"),
  94.             "image/x-sgi-rgb" : self.__tr("SGI RGB"),
  95.             "image/x-xbitmap" : self.__tr("X11 Bitmap (XBM)"),
  96.             "image/x-xpixmap" : self.__tr("X11 Pixmap (XPM)"),
  97.             "image/x-sun-raster" : self.__tr("Sun Raster Format"),
  98.         }
  99.  
  100.         if args is not None:
  101.             for f in args:
  102.                 self.addFile(f)
  103.  
  104.         icon = QPixmap(os.path.join(prop.image_dir, 'HPmenu.png'))
  105.         self.setIcon(icon)
  106.  
  107.         pix = QPixmap(os.path.join(prop.image_dir, 'folder_open.png'))
  108.         self.addFileButton.setPixmap(pix)
  109.  
  110.         pix = QPixmap(os.path.join(prop.image_dir, 'folder_remove.png'))
  111.         self.delFileButton.setPixmap(pix)
  112.  
  113.         pix = QPixmap(os.path.join(prop.image_dir, 'status_refresh.png'))
  114.         self.refreshToolButton.setPixmap(pix)
  115.  
  116.         self.fileListView.setSorting(-1)
  117.  
  118.  
  119.         if self.device_uri and self.printer_name:
  120.             log.error("You may not specify both a printer (-p) and a device (-d).")
  121.             self.FailureUI(self.__tr("<p><b>You may not specify both a printer (-p) and a device (-d)."))
  122.             self.device_uri, self.printer_name = None, None
  123.             self.init_failed = True
  124.  
  125.         self.cups_printers = cups.getPrinters()
  126.         log.debug(self.cups_printers)
  127.  
  128.         if not self.device_uri and not self.printer_name:
  129.             t = device.probeDevices(self.sock, bus=bus, filter='none')
  130.             probed_devices = []
  131.             
  132.             for d in t:
  133.                 if d.startswith('hp:'):
  134.                     probed_devices.append(d)
  135.             
  136.             log.debug(probed_devices)
  137.  
  138.             max_deviceid_size, x, devices = 0, 0, {}
  139.  
  140.             for d in probed_devices:
  141.                 printers = []
  142.                 for p in self.cups_printers:
  143.                     if p.device_uri == d:
  144.                         printers.append(p.name)
  145.                 devices[x] = (d, printers)
  146.                 x += 1
  147.                 max_deviceid_size = max(len(d), max_deviceid_size)
  148.  
  149.             if x == 0:
  150.                 from nodevicesform import NoDevicesForm
  151.                 self.FailureUI(self.__tr("<p><b>No devices found.</b><p>Please make sure your device is properly installed and try again."))
  152.                 self.init_failed = True
  153.  
  154.             elif x == 1:
  155.                 log.info(utils.bold("Using device: %s" % devices[0][0]))
  156.                 self.device_uri = devices[0][0]
  157.  
  158.  
  159.             else:
  160.                 from chooseprinterdlg import ChoosePrinterDlg
  161.                 dlg = ChoosePrinterDlg(self.cups_printers)
  162.                 
  163.                 if dlg.exec_loop() == QDialog.Accepted:
  164.                     self.device_uri = dlg.device_uri
  165.                 else:
  166.                     self.init_failed = True
  167.  
  168.  
  169.         QTimer.singleShot(0, self.InitialUpdate)
  170.  
  171.  
  172.     def InitialUpdate(self):
  173.         if self.init_failed:
  174.             #log.error("Init failed")
  175.             self.close()
  176.             return        
  177.  
  178.         self.printer_list = []
  179.  
  180.         self.dev = device.Device(device_uri=self.device_uri, 
  181.                                  printer_name=self.printer_name, 
  182.                                  hpssd_sock=self.sock)
  183.  
  184.         self.device_uri = self.dev.device_uri
  185.  
  186.         log.debug(self.device_uri)
  187.         self.DeviceURIText.setText(self.device_uri)
  188.  
  189.         for p in self.cups_printers:
  190.             if p.device_uri == self.device_uri:
  191.                 self.printer_list.append(p.name)
  192.  
  193.         for p in self.printer_list:
  194.             self.printerNameComboBox.insertItem(p)
  195.  
  196.         self.UpdatePrinterStatus()
  197.  
  198.         if self.printer_name is None:
  199.             self.printerNameComboBox.setCurrentItem(0)
  200.  
  201.         elif self.printer_name in self.printer_list:
  202.             self.printerNameComboBox.setCurrentText(self.printer_name)
  203.  
  204.         self.current_printer = str(self.printerNameComboBox.currentText())
  205.  
  206.         self.UpdatePrinterInfo()
  207.  
  208.     def UpdatePrinterStatus(self):
  209.         QApplication.setOverrideCursor(QApplication.waitCursor)
  210.         
  211.         try:
  212.             try:
  213.                 self.dev.open()
  214.             except Error, e:
  215.                 log.warn(e.msg)
  216.  
  217.             try:
  218.                 self.dev.queryDevice(quick=True)
  219.             except Error, e:
  220.                 log.error("Query device error (%s)." % e.msg)
  221.                 self.dev.error_state = ERROR_STATE_ERROR
  222.  
  223.         finally:
  224.             self.dev.close()
  225.             QApplication.restoreOverrideCursor()
  226.         
  227.         
  228.         if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
  229.             self.FailureUI(self.__tr("<b>Unable to communicate with device:</b><p>%s" % self.device_uri))
  230.  
  231.         try:
  232.             self.StateText.setText(self.dev.status_desc)
  233.         except AttributeError:
  234.             pass
  235.         
  236.  
  237.  
  238.     def EventUI(self, event_code, event_type, error_string_short,
  239.                 error_string_long, retry_timeout, job_id,
  240.                 device_uri):
  241.  
  242.         log.debug("Event: device_uri=%s code=%d type=%s string=%s timeout=%d id=%d uri=%s" %
  243.                  (device_uri, event_code, event_type,  
  244.                   error_string_short, retry_timeout, job_id, device_uri))
  245.  
  246.         if device_uri == self.dev.device_uri:
  247.             self.StateText.setText(error_string_short)
  248.  
  249.  
  250.     def addFile(self, path):
  251.         path = os.path.realpath(path)
  252.         if os.path.exists(path):
  253.             mime_type = magic.mime_type(path)
  254.             mime_type_desc = mime_type
  255.  
  256.             try:
  257.                 mime_type_desc = self.MIME_TYPES_DESC[mime_type]
  258.             except KeyError:
  259.                 self.WarningUI(self.__tr("<b>You are trying to add a file that cannot be directly printed with this utility.</b><p>To print this file, use the print command in the application that created it."))
  260.             else:
  261.                 log.debug("Adding file %s (%s,%s)" % (path, mime_type, mime_type_desc))
  262.                 self.file_list.append((path, mime_type, mime_type_desc))
  263.         else:
  264.             self.FailureUI(self.__tr("<b>Unable to add file '%s' to file list.</b><p>Check the file name and try again." % path))
  265.  
  266.         self.UpdateFileList()
  267.  
  268.     def UpdateFileList(self):
  269.         self.fileListView.clear()
  270.         temp = self.file_list[:]
  271.         temp.reverse()
  272.  
  273.         for p, t, d in temp:
  274.             i = QListViewItem(self.fileListView, os.path.basename(p), d, p)
  275.             #self.fileListView.setSelected( i, True )
  276.  
  277.         non_empty_file_list = self.fileListView.childCount() > 0
  278.         ##self.delFileButton.setEnabled( non_empty_file_list )
  279.         self.printPushButton.setEnabled(non_empty_file_list)
  280.  
  281.     def addFileButton_clicked(self):
  282.         self.setFocus()
  283.  
  284.         log.debug("isTopLevel %d" % self.isTopLevel())
  285.         log.debug("hasFocus %d" % self.hasFocus())
  286.         log.debug("isEnabled %d" % self.isEnabled())
  287.  
  288.         workingDirectory = os.path.expanduser("~")
  289.  
  290.         log.debug("workingDirectory: %s" % workingDirectory)
  291.  
  292.         dlg = QFileDialog(workingDirectory, QString.null, None, None, True)
  293.  
  294.         dlg.setCaption("openfile")
  295.         dlg.setMode(QFileDialog.ExistingFile)
  296.         dlg.show()
  297.  
  298.         if dlg.exec_loop() == QDialog.Accepted:
  299.                 results = dlg.selectedFile()
  300.                 workingDirectory = dlg.url()
  301.                 log.debug("results: %s" % results)
  302.                 log.debug("workingDirectory: %s" % workingDirectory)
  303.  
  304.                 if results:
  305.                     self.addFile(str(results))
  306.  
  307.  
  308.  
  309.     def delFileButton_clicked(self):
  310.         try:
  311.             path = self.fileListView.currentItem().text(2)
  312.         except AttributeError:
  313.             return
  314.         else:
  315.             temp = self.file_list[:]
  316.             index = 0
  317.             for p, t, d in temp:
  318.                 if p == path:
  319.                     del self.file_list[index]
  320.                     break
  321.                 index += 1
  322.  
  323.             self.UpdateFileList()
  324.  
  325.  
  326.     def fileListView_currentChanged(self,item):
  327.         #print item
  328.         pass
  329.  
  330.     def printerNameComboBox_highlighted(self,a0):
  331.         self.current_printer = str(a0)
  332.         self.UpdatePrinterInfo()
  333.  
  334.     def UpdatePrinterInfo(self):
  335.         for p in self.cups_printers:
  336.             if p.name == self.current_printer:
  337.  
  338.                 try:
  339.                     self.LocationText.setText(p.location)
  340.                 except AttributeError:
  341.                     self.LocationText.setText('')
  342.  
  343.                 try:
  344.                     self.CommentText.setText(p.info)
  345.                 except AttributeError:
  346.                     self.CommentText.setText('')
  347.  
  348.                 cups.openPPD(p.name)
  349.                 self.UpdateDuplex()
  350.                 cups.closePPD()
  351.                 break
  352.  
  353.     def UpdateDuplex(self):
  354.         duplex = cups.getPPDOption("Duplex")
  355.         if duplex is not None:
  356.             if duplex.startswith("long"):
  357.                 self.duplexButtonGroup.setButton(1)
  358.                 self.auto_duplex_button_group = 1
  359.             elif duplex.startswith("short"):
  360.                 self.duplexButtonGroup.setButton(2)
  361.                 self.auto_duplex_button_group = 2
  362.             else:
  363.                 self.duplexButtonGroup.setButton(0)
  364.                 self.auto_duplex_button_group = 0
  365.         else:
  366.             self.duplexButtonGroup.setEnabled(False)
  367.  
  368.  
  369.     def pagesButtonGroup_clicked(self,item):
  370.         self.pageRangeEdit.setEnabled(item == 1)
  371.  
  372.     def printPushButton_clicked(self):
  373.         copies = int(self.copiesSpinBox.value())
  374.         rev = bool(self.reverseCheckBox.isChecked())
  375.         collate = bool(self.collateCheckBox.isChecked())
  376.         all_pages = self.pages_button_group == 0
  377.         page_range = str(self.pageRangeEdit.text())
  378.         page_set = int(self.pageSetComboBox.currentItem())
  379.         nup = int(str(self.nUpComboBox.currentText()))
  380.         mirror = bool(self.mirrorCheckBox.isChecked())
  381.  
  382.         for p, t, d in self.file_list:
  383.             
  384.             alt_nup = (nup > 1 and t == 'application/postscript' and utils.which('psnup'))
  385.                 
  386.             if alt_nup:
  387.                 cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.current_printer])
  388.             else:
  389.                 cmd = ' '.join(['lp -c -d', self.current_printer])
  390.  
  391.             if copies > 1:
  392.                 cmd = ' '.join([cmd, '-n%d' % copies])
  393.  
  394.             if not all_pages and len(page_range) > 0:
  395.                 cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
  396.  
  397.             if page_set > 0:
  398.                 if page_set == 1:
  399.                     cmd = ' '.join([cmd, '-o page-set=even'])
  400.                 else:
  401.                     cmd = ' '.join([cmd, '-o page-set=odd'])
  402.  
  403.             if rev:
  404.                 cmd = ' '.join([cmd, '-o outputorder=reverse'])
  405.                 
  406.             if mirror:
  407.                 cmd = ' '.join([cmd, '-o mirror'])
  408.  
  409.             if collate and copies > 1:
  410.                 cmd = ' '.join([cmd, '-o Collate=True'])
  411.  
  412.             if t in ["application/x-cshell",
  413.                      "application/x-perl",
  414.                      "application/x-python",
  415.                      "application/x-shell",
  416.                      "text/plain",]:
  417.                      
  418.                 cmd = ' '.join([cmd, '-o prettyprint'])
  419.  
  420.             if nup > 1 and not alt_nup:
  421.                 cmd = ' '.join([cmd, '-o number-up=%d' % nup])
  422.  
  423.             if self.auto_duplex_button_group == 1: # long
  424.                 cmd = ' '.join([cmd, '-o sides=two-sided-long-edge'])
  425.             elif self.auto_duplex_button_group == 2: # short
  426.                 cmd = ' '.join([cmd, '-o sides=two-sided-short-edge'])
  427.             else:
  428.                 cmd = ' '.join([cmd, '-o sides=one-sided'])
  429.  
  430.             if self.orientation_button_group == 1:
  431.                 cmd = ' '.join([cmd, '-o landscape'])
  432.  
  433.             if not alt_nup:
  434.                 cmd = ''.join([cmd, ' "', p, '"'])
  435.  
  436.             log.debug("Printing: %s" % cmd)
  437.  
  438.             if os.system(cmd) != 0:
  439.                 log.error("Print command failed.")
  440.                 self.FailureUI(self.__tr("Print command failed."))
  441.         
  442.         del self.file_list[:]
  443.         self.UpdateFileList()
  444.  
  445.     def pagesButtonGroup_clicked(self,a0):
  446.         self.pages_button_group = a0
  447.         self.pageRangeEdit.setEnabled(a0 == 1)
  448.  
  449.  
  450.     def duplexButtonGroup_clicked(self,a0):
  451.         self.auto_duplex_button_group = a0
  452.  
  453.     def orientationButtonGroup_clicked(self,a0):
  454.         self.orientation_button_group = a0
  455.  
  456.     def refreshToolButton_clicked(self):
  457.         self.UpdatePrinterStatus()
  458.  
  459.  
  460.     def SuccessUI(self):
  461.         QMessageBox.information(self,
  462.                              self.caption(),
  463.                              self.__tr("<p><b>The operation completed successfully.</b>"),
  464.                               QMessageBox.Ok,
  465.                               QMessageBox.NoButton,
  466.                               QMessageBox.NoButton)
  467.  
  468.     def FailureUI(self, error_text):
  469.         QMessageBox.critical(self,
  470.                              self.caption(),
  471.                              error_text,
  472.                               QMessageBox.Ok,
  473.                               QMessageBox.NoButton,
  474.                               QMessageBox.NoButton)
  475.  
  476.     def WarningUI(self, msg):
  477.         QMessageBox.warning(self,
  478.                              self.caption(),
  479.                              msg,
  480.                               QMessageBox.Ok,
  481.                               QMessageBox.NoButton,
  482.                               QMessageBox.NoButton)
  483.  
  484.  
  485.     def __tr(self,s,c = None):
  486.         return qApp.translate("PrinterForm",s,c)
  487.  
  488.  
  489.