1 # -*- coding: utf-8 -*-
3 # (c) Copyright 2001-2009 Hewlett-Packard Development Company, L.P.
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.
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.
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
25 from base import device, utils
27 from base.codes import *
28 from ui_utils import *
31 from PyQt4.QtCore import *
32 from PyQt4.QtGui import *
35 from printdialog_base import Ui_Dialog
36 from filetable import FileTable, FILETABLE_TYPE_PRINT
37 from printernamecombobox import PRINTERNAMECOMBOBOX_TYPE_PRINTER_ONLY
44 class PrintDialog(QDialog, Ui_Dialog):
45 def __init__(self, parent, printer_name, args=None):
46 QDialog.__init__(self, parent)
49 self.printer_name = printer_name
52 self.user_settings = UserSettings()
53 self.user_settings.load()
54 self.user_settings.debug()
61 self.Files.addFileFromUI(os.path.abspath(a))
66 QTimer.singleShot(0, self.updateFilePage)
70 self.OptionsToolBox.include_job_options = True
72 # connect signals/slots
73 self.connect(self.CancelButton, SIGNAL("clicked()"), self.CancelButton_clicked)
74 self.connect(self.BackButton, SIGNAL("clicked()"), self.BackButton_clicked)
75 self.connect(self.NextButton, SIGNAL("clicked()"), self.NextButton_clicked)
78 self.initOptionsPage()
81 self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128')))
84 self.PrinterName.setInitialPrinter(self.printer_name)
86 self.StackedWidget.setCurrentIndex(0)
93 def initFilePage(self):
94 self.Files.setType(FILETABLE_TYPE_PRINT)
95 #self.Files.setWorkingDir(user_conf.workingDirectory())
96 self.Files.setWorkingDir(self.user_settings.working_dir)
97 self.connect(self.Files, SIGNAL("isEmpty"), self.Files_isEmpty)
98 self.connect(self.Files, SIGNAL("isNotEmpty"), self.Files_isNotEmpty)
101 def updateFilePage(self):
102 self.NextButton.setText(self.__tr("Next >"))
103 self.NextButton.setEnabled(self.Files.isNotEmpty())
104 self.BackButton.setEnabled(False)
105 self.updateStepText(PAGE_FILE)
106 self.Files.updateUi()
108 def Files_isEmpty(self):
109 self.NextButton.setEnabled(False)
112 def Files_isNotEmpty(self):
113 self.NextButton.setEnabled(True)
120 def initOptionsPage(self):
121 self.BackButton.setEnabled(True)
122 self.PrinterName.setType(PRINTERNAMECOMBOBOX_TYPE_PRINTER_ONLY)
124 self.connect(self.PrinterName, SIGNAL("PrinterNameComboBox_currentChanged"),
125 self.PrinterNameComboBox_currentChanged)
127 self.connect(self.PrinterName, SIGNAL("PrinterNameComboBox_noPrinters"),
128 self.PrinterNameComboBox_noPrinters)
131 def updateOptionsPage(self):
132 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
134 self.PrinterName.updateUi()
135 self.BackButton.setEnabled(True)
136 num_files = len(self.Files.file_list)
139 self.NextButton.setText(self.__tr("Print %1 Files").arg(num_files))
141 self.NextButton.setText(self.__tr("Print File"))
143 self.updateStepText(PAGE_OPTIONS)
144 # TODO: Enable print button only if printer is accepting and all options are OK (esp. page range)
146 QApplication.restoreOverrideCursor()
149 def PrinterNameComboBox_currentChanged(self, device_uri, printer_name):
151 self.devices[device_uri]
153 self.devices[device_uri] = device.Device(device_uri)
155 self.OptionsToolBox.updateUi(self.devices[device_uri], printer_name)
158 def PrinterNameComboBox_noPrinters(self):
159 FailureUI(self, self.__tr("<b>No printers found.</b><p>Please setup a printer and try again."))
167 def executePrint(self):
168 for cmd in self.OptionsToolBox.getPrintCommands(self.Files.file_list):
170 status, output = utils.run(cmd, log_output=True, password_func=None, timeout=1)
172 FailureUI(self, self.__tr("<b>Print command failed with status code %1.</b><p>%2</p>").arg(status).arg(cmd))
175 #print file('/home/dwelch/.cups/lpoptions', 'r').read()
181 def CancelButton_clicked(self):
185 def BackButton_clicked(self):
186 p = self.StackedWidget.currentIndex()
187 if p == PAGE_OPTIONS:
188 self.StackedWidget.setCurrentIndex(PAGE_FILE)
189 self.updateFilePage()
192 log.error("Invalid page!") # shouldn't happen!
195 def NextButton_clicked(self):
196 p = self.StackedWidget.currentIndex()
198 self.StackedWidget.setCurrentIndex(PAGE_OPTIONS)
199 self.updateOptionsPage()
201 elif p == PAGE_OPTIONS:
205 def updateStepText(self, p):
206 self.StepText.setText(self.__tr("Step %1 of %2").arg(p+1).arg(PAGE_MAX+1))
209 def __tr(self,s,c = None):
210 return qApp.translate("PrintDialog",s,c)
215 def printButton_clicked(self):
216 if self.invalid_page_range:
217 self.form.FailureUI(self.__tr("<b>Cannot print: Invalid page range: %1</b><p>A valid page range is a list of pages or ranges of pages separated by commas (e.g., 1-2,4,6-7)").arg(self.pageRangeEdit.text()))
222 self.cur_device.open()
224 self.form.FailureUI(self.__tr("<b>Cannot print: Device is busy or not available.</b><p>Please check device and try again."))
227 if 1: # Go ahead and allow - print will be queued in CUPS if not rejecting
228 printers = cups.getPrinters()
230 if p.name == self.cur_printer:
233 if p.state == cups.IPP_PRINTER_STATE_STOPPED:
234 self.form.FailureUI(self.__tr("<b>Cannot print: Printer is stopped.</b><p>Please START the printer to continue this print. Job will begin printing once printer is started."))
237 self.form.FailureUI(self.__tr("<b>Cannot print: Printer is not accepting jobs.</b><p>Please set the printer to ACCEPTING JOBS to continue printing."))
240 copies = int(self.copiesSpinBox.value())
241 all_pages = self.pages_button_group == 0
242 page_range = unicode(self.pageRangeEdit.text())
243 page_set = int(self.pageSetComboBox.currentItem())
246 cups.openPPD(self.cur_printer)
247 current_options = dict(cups.getOptions())
250 nup = int(current_options.get("number-up", 1))
252 for p, t, d in self.file_list:
254 alt_nup = (nup > 1 and t == 'application/postscript' and utils.which('psnup'))
256 if utils.which('lpr'):
258 cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lpr -P', self.cur_printer])
260 cmd = ' '.join(['lpr -P', self.cur_printer])
263 cmd = ' '.join([cmd, '-#%d' % copies])
267 cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.cur_printer])
269 cmd = ' '.join(['lp -c -d', self.cur_printer])
272 cmd = ' '.join([cmd, '-n%d' % copies])
275 if not all_pages and len(page_range) > 0:
276 cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
280 cmd = ' '.join([cmd, '-o page-set=even'])
282 cmd = ' '.join([cmd, '-o page-set=odd'])
286 # self.job_storage_mode = (0=Off, 1=P&H, 2=PJ, 3=QC, 4=SJ)
287 # self.job_storage_pin = u"" (dddd)
288 # self.job_storage_use_pin = True|False
289 # self.job_storage_username = u""
290 # self.job_storage_auto_username = True|False
291 # self.job_storage_jobname = u""
292 # self.job_storage_auto_jobname = True|False
293 # self.job_storage_job_exist = (0=replace, 1=job name+(1-99))
295 if self.job_storage_avail:
296 if self.job_storage_mode: # On
298 if self.job_storage_mode == 1: # Proof and Hold
299 cmd = ' '.join([cmd, '-o HOLD=PROOF'])
301 elif self.job_storage_mode == 2: # Private Job
302 if self.job_storage_use_pin:
303 cmd = ' '.join([cmd, '-o HOLD=ON'])
304 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
305 cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
307 cmd = ' '.join([cmd, '-o HOLD=PROOF'])
308 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
310 elif self.job_storage_mode == 3: # Quick Copy
311 cmd = ' '.join([cmd, '-o HOLD=ON'])
312 cmd = ' '.join([cmd, '-o HOLDTYPE=PUBLIC'])
314 elif self.job_storage_mode == 4: # Store Job
315 if self.job_storage_use_pin:
316 cmd = ' '.join([cmd, '-o HOLD=STORE'])
317 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
318 cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
320 cmd = ' '.join([cmd, '-o HOLD=STORE'])
322 cmd = ' '.join([cmd, '-o USERNAME=%s' % self.job_storage_username.encode('ascii')\
325 cmd = ' '.join([cmd, '-o JOBNAME=%s' % self.job_storage_jobname.encode('ascii')\
328 if self.job_storage_job_exist == 1:
329 cmd = ' '.join([cmd, '-o DUPLICATEJOB=APPEND'])
331 cmd = ' '.join([cmd, '-o DUPLICATEJOB=REPLACE'])
334 cmd = ' '.join([cmd, '-o HOLD=OFF'])
338 cmd = ''.join([cmd, ' "', p, '"'])
340 log.debug("Printing: %s" % cmd)
342 code = os.system(cmd)
344 log.error("Print command failed.")
345 self.form.FailureUI(self.__tr("Print command failed with error code %1").arg(code))
350 self.cur_device.close()