1 # -*- coding: utf-8 -*-
3 # (c) Copyright 2001-2008 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
19 # Authors: Don Welch, Yashwant Kumar Sahu, Sanjay Kumar Sharma
27 from base import utils
29 from base.codes import *
30 from ui_utils import *
33 from PyQt4.QtCore import *
34 from PyQt4.QtGui import *
38 class RangeValidator(QValidator):
39 def __init__(self, parent=None, name=None):
40 QValidator.__init__(self, parent) #, name)
43 def validate(self, input, pos):
44 for x in unicode(input)[pos-1:]:
45 if x not in u'0123456789,- ':
46 return QValidator.Invalid, pos
48 return QValidator.Acceptable, pos
52 class PinValidator(QValidator):
53 def __init__(self, parent=None, name=None):
54 QValidator.__init__(self, parent) #, name)
57 def validate(self, input, pos):
58 for x in unicode(input)[pos-1:]:
59 if x not in u'0123456789':
60 return QValidator.Invalid, pos
62 return QValidator.Acceptable, pos
66 class UsernameAndJobnameValidator(QValidator):
67 def __init__(self, parent=None, name=None):
68 QValidator.__init__(self, parent) #, name)
71 def validate(self, input, pos):
72 for x in unicode(input)[pos-1:]:
73 if x in u' /=,.:;\'"[]{}-+!@#$%^&*()':
74 return QValidator.Invalid, pos
76 return QValidator.Acceptable, pos
80 class OptionComboBox(QComboBox):
81 def __init__(self, rw, parent, name, group, option, choices, default,
82 typ=cups.PPD_UI_PICKONE, other=None, job_option=False):
83 QComboBox.__init__(self, parent)
87 self.choices = choices
88 self.default = default
91 self.job_option = job_option
92 self.setObjectName(name)
95 def setDefaultPushbutton(self, pushbutton):
96 self.pushbutton = pushbutton
99 def setOther(self, other):
104 class OptionSpinBox(QSpinBox):
105 def __init__(self, parent, name, group, option, default, job_option=False):
106 QSpinBox.__init__(self, parent)
109 self.default = default
110 self.job_option = job_option
111 self.setObjectName(name)
114 def setDefaultPushbutton(self, pushbutton):
115 self.pushbutton = pushbutton
119 class OptionRadioButton(QRadioButton):
120 def __init__(self, parent, name, group, option, default, job_option=False):
121 QRadioButton.__init__(self, parent)
124 self.default = default
125 self.job_option = job_option
126 self.setObjectName(name)
129 def setDefaultPushbutton(self, pushbutton):
130 self.pushbutton = pushbutton
134 class DefaultPushButton(QPushButton):
135 def __init__(self, parent, name, group, option, choices,
136 default, control, typ, job_option=False):
137 QPushButton.__init__(self, parent)
140 self.default = default
141 self.control = control
143 self.choices = choices
144 self.job_option = job_option
145 self.setObjectName(name)
148 #class PageRangeRadioButton(QRadioButton):
149 # def __init__(self, parent, page_range_edit):
150 # QRadioButton.__init__(self, parent):
151 # self.page_range_edit = page_range_edit
154 class PageRangeRadioButton(QRadioButton):
155 def __init__(self, parent, name, group, option, default): #, edit_control=None ):
156 QRadioButton.__init__(self, parent)
159 self.default = default
160 self.job_option = True
161 self.setObjectName(name)
164 def setRangeEdit(self, edit_control):
165 self.edit_control = edit_control
168 def setDefaultPushbutton(self, pushbutton):
169 self.pushbutton = pushbutton
173 class PrintSettingsToolbox(QToolBox):
174 def __init__(self, parent, include_job_options=False):
175 QToolBox.__init__(self, parent)
176 self.include_job_options = include_job_options
177 self.plus_icon = QIcon(load_pixmap('plus', '16x16'))
178 self.minus_icon = QIcon(load_pixmap('minus', '16x16'))
180 self.job_options = {}
181 self.job_storage_enable = False
183 self.connect(self, SIGNAL("currentChanged(int)"), self.PrintSettingsToolbox_currentChanged)
186 def getPrintCommands(self, file_list=None):
187 # File list: [(path, mime_type, mime_desc, title, num_pages), ...]
188 if file_list is None or not file_list:
194 copies = int(self.job_options['copies'])
200 log.warning("Copies < 1, setting to 1.")
203 log.warning("Copies > 99, setting to 99.")
205 #page_range = unicode(self.pageRangeEdit.text())
206 page_range = self.job_options['pagerange']
209 x = utils.expand_range(page_range)
211 log.error("Invalid page range: %s" % page_range)
214 all_pages = not page_range
215 #page_set = int(self.pageSetComboBox.currentItem())
216 page_set = self.job_options['pageset']
219 cups.openPPD(self.cur_printer)
220 current_options = dict(cups.getOptions())
223 nup = int(current_options.get("number-up", 1))
224 psnup = utils.which('psnup')
226 for p, t, d, title, num_pages in file_list:
227 alt_nup = (nup > 1 and t == 'application/postscript' and psnup)
229 if utils.which('lpr'):
231 cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lpr -P', self.cur_printer])
233 cmd = ' '.join(['lpr -P', self.cur_printer])
236 cmd = ' '.join([cmd, '-#%d' % copies])
240 cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.cur_printer])
242 cmd = ' '.join(['lp -c -d', self.cur_printer])
245 cmd = ' '.join([cmd, '-n%d' % copies])
248 if not all_pages and page_range:
249 cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
252 cmd = ' '.join([cmd, '-o page-set=%s' % page_set])
255 # self.job_storage_mode = (0=Off, 1=P&H, 2=PJ, 3=QC, 4=SJ)
256 # self.job_storage_pin = u"" (dddd)
257 # self.job_storage_use_pin = True|False
258 # self.job_storage_username = u""
259 # self.job_storage_auto_username = True|False
260 # self.job_storage_jobname = u""
261 # self.job_storage_auto_jobname = True|False
262 # self.job_storage_job_exist = (0=replace, 1=job name+(1-99))
264 if self.job_storage_enable:
265 if self.job_storage_mode != JOB_STORAGE_TYPE_OFF:
266 if self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
267 cmd = ' '.join([cmd, '-o HOLD=PROOF'])
269 elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
270 if self.job_storage_use_pin:
271 cmd = ' '.join([cmd, '-o HOLD=ON'])
272 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
273 cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
275 cmd = ' '.join([cmd, '-o HOLD=PROOF'])
276 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
278 elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
279 cmd = ' '.join([cmd, '-o HOLD=ON'])
280 cmd = ' '.join([cmd, '-o HOLDTYPE=PUBLIC'])
282 elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
283 if self.job_storage_use_pin:
284 cmd = ' '.join([cmd, '-o HOLD=STORE'])
285 cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
286 cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
288 cmd = ' '.join([cmd, '-o HOLD=STORE'])
290 cmd = ' '.join([cmd, '-o USERNAME=%s' % self.job_storage_username.encode('ascii')\
293 cmd = ' '.join([cmd, '-o JOBNAME=%s' % self.job_storage_jobname.encode('ascii')\
296 if self.job_storage_job_exist == 1:
297 cmd = ' '.join([cmd, '-o DUPLICATEJOB=APPEND'])
299 cmd = ' '.join([cmd, '-o DUPLICATEJOB=REPLACE'])
302 cmd = ' '.join([cmd, '-o HOLD=OFF'])
305 cmd = ''.join([cmd, ' "', p, '"'])
307 print_commands.append(cmd)
309 return print_commands
312 def PrintSettingsToolbox_currentChanged(self, i):
314 self.setItemIcon(self.last_item, self.plus_icon)
315 self.setItemIcon(i, self.minus_icon)
319 def updateUi(self, cur_device, cur_printer):
320 #print "updateUi(%s, %s)" % (cur_device, cur_printer)
321 self.cur_device = cur_device
322 self.cur_printer = cur_printer
329 cups.openPPD(self.cur_printer)
335 current_options = dict(cups.getOptions())
337 if self.include_job_options:
338 self.beginControlGroup("job_options", self.__tr("Job Options"))
340 # Num. copies (SPINNER)
342 current = int(current_options.get('copies', '1'))
346 self.addControlRow("copies", self.__tr("Number of copies"),
347 cups.UI_SPINNER, current, (1, 99), 1, job_option=True)
348 self.job_options['copies'] = current
350 # page range RADIO + RANGE (custom)
351 current = current_options.get('pagerange', '')
353 self.addControlRow("pagerange", self.__tr("Page Range"),
354 cups.UI_PAGE_RANGE, current, None, None, job_option=True)
356 self.job_options['pagerange'] = current
358 # page set (COMBO/PICKONE)
359 current = current_options.get('pageset', 'all')
360 self.addControlRow("pageset", self.__tr("Page Set"),
361 cups.PPD_UI_PICKONE, current,
362 [('all', self.__tr("AllPages")),
363 ('even', self.__tr("Even")),
364 ('odd', self.__tr("Odd"))], 'all', job_option=True)
366 self.job_options['pageset'] = current
367 # if current == u'even':
368 # self.job_options["pageset"] = PAGE_SET_EVEN
369 # elif current == u'odd':
370 # self.job_options["pageset"] = PAGE_SET_ODD
372 # self.job_options["pageset"] = PAGE_SET_ALL
374 self.endControlGroup() # job_options
376 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
377 self.beginControlGroup("basic", self.__tr("Basic"))
380 # PageSize (in PPD section)
381 # orientation-requested
386 current = current_options.get('orientation-requested', '3')
388 self.addControlRow("orientation-requested", self.__tr("Page Orientation"),
389 cups.PPD_UI_PICKONE, current,
390 [('3', self.__tr('Portrait')),
391 ('4', self.__tr('Landscape')),
392 ('5', self.__tr('Reverse landscape')),
393 ('6', self.__tr('Reverse portrait'))], '3')
395 log.debug("Option: orientation-requested")
396 log.debug("Current value: %s" % current)
398 duplexer = self.cur_device.dq.get('duplexer', 0)
399 log.debug("Duplexer = %d" % duplexer)
402 current = current_options.get('sides', 'one-sided')
403 self.addControlRow("sides",
404 self.__tr("Duplex (Print on both sides of the page)"),
405 cups.PPD_UI_PICKONE, current,
406 [('one-sided',self.__tr('Single sided')),
407 ('two-sided-long-edge', self.__tr('Two sided (long edge)')),
408 ('two-sided-short-edge', self.__tr('Two sided (short edge)'))], 'one-sided')
410 log.debug("Option: sides")
411 log.debug("Current value: %s" % current)
413 current = current_options.get('outputorder', 'normal')
415 self.addControlRow("outputorder",
416 self.__tr("Output Order (Print last page first)"),
417 cups.PPD_UI_PICKONE, current,
418 [('normal', self.__tr('Normal (Print first page first)')),
419 ('reverse', self.__tr('Reversed (Print last page first)'))], 'normal')
421 log.debug("Option: outputorder")
422 log.debug("Current value: %s" % current)
424 current = utils.to_bool(current_options.get('Collate', '0'))
426 self.addControlRow("Collate",
427 self.__tr("Collate (Group together multiple copies)"),
428 cups.PPD_UI_BOOLEAN, current,
431 log.debug("Option: Collate")
432 log.debug("Current value: %s" % current)
434 self.endControlGroup()
436 groups = cups.getGroupList()
441 if 'jobretention' in g.lower():
442 log.debug("HPJobRetention skipped.")
446 text, num_subgroups = cups.getGroup(g)
448 log.warn("Group %s returned None" % g)
451 read_only = 'install' in g.lower()
454 text = text.decode('utf-8')
455 except UnicodeDecodeError:
458 if g.lower() == 'printoutmode':
459 text = self.__tr("Quality (also see 'Printout Mode' under 'General')")
461 self.beginControlGroup(g, QString(text))
463 log.debug(" Text: %s" % unicode(text))
464 log.debug("Num subgroups: %d" % num_subgroups)
466 options = cups.getOptionList(g)
471 log.debug(" Option: %s" % repr(o))
473 if 'pageregion' in o.lower():
474 log.debug("Page Region skipped.")
478 option_text, defchoice, conflicted, ui = cups.getOption(g, o)
480 log.warn("Option %s in group %s returned None" % (o, g))
484 option_text = option_text.decode('utf-8')
485 except UnicodeDecodeError:
488 if o.lower() == 'quality':
489 option_text = self.__tr("Quality")
491 log.debug(" Text: %s" % repr(option_text))
492 log.debug(" Defchoice: %s" % repr(defchoice))
494 choices = cups.getChoiceList(g, o)
499 log.debug(" Choice: %s" % repr(c))
501 # TODO: Add custom paper size controls
502 if 'pagesize' in o.lower() and 'custom' in c.lower():
503 log.debug("Skipped.")
506 choice_text, marked = cups.getChoice(g, o, c)
509 choice_text = choice_text.decode('utf-8')
510 except UnicodeDecodeError:
513 log.debug(" Text: %s" % repr(choice_text))
518 choice_data.append((c, choice_text))
520 if o.lower() == 'outputmode':
521 if value is not None:
522 cur_outputmode = value
524 cur_outputmode = defchoice
526 self.addControlRow(o, option_text, ui, value, choice_data, defchoice, read_only)
528 self.endControlGroup()
530 ## if 'pagesize' in o.lower(): # and 'custom' in c.lower():
532 ## width_widget = self.addControlRow(widget, "custom", "custom-width", self.__tr("Custom Paper Width"), cups.UI_UNITS_SPINNER,
533 ## current, (0.0, 0.0), 0.0)
536 ## height_widget = self.addControlRow("custom", "custom-height", self.__tr("Custom Paper Height"), cups.UI_UNITS_SPINNER,
537 ## current, (0.0, 0.0), 0.0)
539 ## if value.lower() == 'custom':
547 self.beginControlGroup("nup", self.__tr("N-Up (Multiple document pages per printed page)"))
548 current = current_options.get('number-up', '1')
550 self.addControlRow("number-up", self.__tr("Pages per Sheet"),
551 cups.PPD_UI_PICKONE, current,
552 [('1', self.__tr('1 page per sheet')),
553 ('2', self.__tr('2 pages per sheet')),
554 ('4', self.__tr('4 pages per sheet'))], '1')
556 log.debug(" Option: number-up")
557 log.debug(" Current value: %s" % current)
559 current = current_options.get('number-up-layout', 'lrtb')
561 self.addControlRow("number-up-layout", self.__tr("Layout"),
562 cups.PPD_UI_PICKONE, current,
563 [('btlr', self.__tr('Bottom to top, left to right')),
564 ('btrl', self.__tr('Bottom to top, right to left')),
565 ('lrbt', self.__tr('Left to right, bottom to top')),
566 ('lrtb', self.__tr('Left to right, top to bottom')),
567 ('rlbt', self.__tr('Right to left, bottom to top')),
568 ('rltb', self.__tr('Right to left, top to bottom')),
569 ('tblr', self.__tr('Top to bottom, left to right')),
570 ('tbrl', self.__tr('Top to bottom, right to left')) ], 'lrtb')
572 log.debug(" Option: number-up-layout")
573 log.debug(" Current value: %s" % current)
575 current = current_options.get('page-border', 'none')
577 self.addControlRow("page-border",
578 self.__tr("Printed Border Around Each Page"),
579 cups.PPD_UI_PICKONE, current,
580 [('double', self.__tr("Two thin borders")),
581 ("double-thick", self.__tr("Two thick borders")),
582 ("none", self.__tr("No border")),
583 ("single", self.__tr("One thin border")),
584 ("single-thick", self.__tr("One thick border"))], 'none')
586 log.debug(" Option: page-border")
587 log.debug(" Current value: %s" % current)
589 self.endControlGroup()
595 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
596 self.beginControlGroup("adjustment", self.__tr("Printout Appearance"))
598 current = int(current_options.get('brightness', 100))
600 log.debug(" Option: brightness")
601 log.debug(" Current value: %s" % current)
603 self.addControlRow("brightness", self.__tr("Brightness"),
604 cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
606 current = int(current_options.get('gamma', 1000))
608 log.debug(" Option: gamma")
609 log.debug(" Current value: %s" % current)
611 self.addControlRow("gamma", self.__tr("Gamma"), cups.UI_SPINNER, current,
614 self.endControlGroup()
623 ## # TODO: cupsPPDPageSize() fails on LaserJets. How do we get margins in this case? Defaults?
624 ## # PPD file for LJs has a HWMargin entry...
625 ## page, page_width, page_len, left, bottom, right, top = cups.getPPDPageSize()
627 ## right = page_width - right
628 ## top = page_len - top
630 ## self.addGroupHeading("margins", self.__tr("Margins"))
631 ## current_top = current_options.get('page-top', 0) # pts
632 ## current_bottom = current_options.get('page-bottom', 0) # pts
633 ## current_left = current_options.get('page-left', 0) # pts
634 ## current_right = current_options.get('page-right', 0) # pts
636 ## log.debug(" Option: page-top")
637 ## log.debug(" Current value: %s" % current_top)
639 ## self.addControlRow("margins", "page-top", self.__tr("Top margin"),
640 ## cups.UI_UNITS_SPINNER, current_top,
641 ## (0, page_len), top)
643 ## self.addControlRow("margins", "page-bottom", self.__tr("Bottom margin"),
644 ## cups.UI_UNITS_SPINNER, current_bottom,
645 ## (0, page_len), bottom)
647 ## self.addControlRow("margins", "page-left", self.__tr("Right margin"),
648 ## cups.UI_UNITS_SPINNER, current_left,
649 ## (0, page_width), left)
651 ## self.addControlRow("margins", "page-right", self.__tr("Left margin"),
652 ## cups.UI_UNITS_SPINNER, current_right,
653 ## (0, page_width), right)
661 self.beginControlGroup("image", self.__tr("Image Printing"))
663 current = utils.to_bool(current_options.get('fitplot', 'false'))
665 self.addControlRow("fitplot",
666 self.__tr("Fit to Page"),
667 cups.PPD_UI_BOOLEAN, current,
670 current = current_options.get('position', 'center')
672 self.addControlRow("position", self.__tr("Position on Page"),
673 cups.PPD_UI_PICKONE, current,
674 [('center', self.__tr('Centered')),
675 ('top', self.__tr('Top')),
676 ('left', self.__tr('Left')),
677 ('right', self.__tr('Right')),
678 ('top-left', self.__tr('Top left')),
679 ('top-right', self.__tr('Top right')),
680 ('bottom', self.__tr('Bottom')),
681 ('bottom-left', self.__tr('Bottom left')),
682 ('bottom-right', self.__tr('Bottom right'))], 'center')
684 log.debug(" Option: position")
685 log.debug(" Current value: %s" % current)
687 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
688 current = int(current_options.get('saturation', 100))
690 log.debug(" Option: saturation")
691 log.debug(" Current value: %s" % current)
693 self.addControlRow("saturation", self.__tr("Saturation"),
694 cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
696 current = int(current_options.get('hue', 0))
698 log.debug(" Option: hue")
699 log.debug(" Current value: %s" % current)
701 self.addControlRow("hue", self.__tr("Hue (color shift/rotation)"),
702 cups.UI_SPINNER, current,
705 current = int(current_options.get('natural-scaling', 100))
707 log.debug(" Option: natural-scaling")
708 log.debug(" Current value: %s" % current)
710 self.addControlRow("natural-scaling",
711 self.__tr('"Natural" Scaling (relative to image)'),
712 cups.UI_SPINNER, current, (1, 800), 100, suffix=" %")
714 current = int(current_options.get('scaling', 100))
716 log.debug(" Option: scaling")
717 log.debug(" Current value: %s" % current)
719 self.addControlRow("scaling", self.__tr("Scaling (relative to page)"),
720 cups.UI_SPINNER, current,
721 (1, 800), 100, suffix=" %")
723 self.endControlGroup()
730 self.beginControlGroup("misc", self.__tr("Miscellaneous"))
732 log.debug("Group: Misc")
734 current = utils.to_bool(current_options.get('prettyprint', '0'))
736 self.addControlRow("prettyprint",
737 self.__tr('"Pretty Print" Text Documents (Add headers and formatting)'),
738 cups.PPD_UI_BOOLEAN, current, [], 0)
740 log.debug(" Option: prettyprint")
741 log.debug(" Current value: %s" % current)
743 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
744 current = current_options.get('job-sheets', 'none').split(',')
756 # TODO: Look for locally installed banner pages beyond the default CUPS ones?
757 self.addControlRow("job-sheets", self.__tr("Banner Pages"), cups.UI_BANNER_JOB_SHEETS,
759 [("none", self.__tr("No banner page")),
760 ('classified', self.__tr("Classified")),
761 ('confidential', self.__tr("Confidential")),
762 ('secret', self.__tr("Secret")),
763 ('standard', self.__tr("Standard")),
764 ('topsecret', self.__tr("Top secret")),
765 ('unclassified', self.__tr("Unclassified"))], ('none', 'none'))
767 log.debug(" Option: job-sheets")
768 log.debug(" Current value: %s,%s" % (start, end))
770 current = utils.to_bool(current_options.get('mirror', '0'))
772 self.addControlRow("mirror", self.__tr('Mirror Printing'),
773 cups.PPD_UI_BOOLEAN, current, [], 0)
775 log.debug(" Option: mirror")
776 log.debug(" Current value: %s" % current)
778 self.endControlGroup()
783 quality_attr_name = "OutputModeDPI"
784 cur_outputmode_dpi = cups.findPPDAttribute(quality_attr_name, cur_outputmode)
785 if cur_outputmode_dpi is not None:
786 log.debug("Adding Group: Summary outputmode is : %s" % cur_outputmode)
787 log.debug("Adding Group: Summary outputmode dpi is : %s" % unicode (cur_outputmode_dpi))
788 self.beginControlGroup("sumry", self.__tr("Summary"))
789 self.addControlRow("colorinput", self.__tr('Color Input / Black Render'),
790 cups.UI_INFO, unicode (cur_outputmode_dpi), [], read_only)
791 self.addControlRow("quality", self.__tr('Print Quality'),
792 cups.UI_INFO, cur_outputmode, [], read_only)
793 self.endControlGroup()
794 log.debug("End adding Group: Summary")
797 self.job_storage_enable = self.cur_device.mq.get('job-storage', JOB_STORAGE_DISABLE) == JOB_STORAGE_ENABLE
800 if self.job_storage_enable:
801 self.job_storage_pin = unicode(current_options.get('HOLDKEY', '0000')[:4])
802 self.job_storage_username = unicode(current_options.get('USERNAME', prop.username)[:16])
803 self.job_storage_jobname = unicode(current_options.get('JOBNAME', u'Untitled')[:16])
804 hold = unicode(current_options.get('HOLD', u'OFF'))
805 holdtype = unicode(current_options.get('HOLDTYPE', u'PUBLIC'))
806 self.job_storage_use_pin = False
807 duplicate = unicode(current_options.get('DUPLICATEJOB', u'REPLACE'))
808 self.job_storage_auto_username = True
809 self.job_storage_auto_jobname = True
810 self.job_storage_mode = JOB_STORAGE_TYPE_OFF
813 self.job_storage_mode = JOB_STORAGE_TYPE_OFF
816 if holdtype == u'PUBLIC':
817 self.job_storage_mode = JOB_STORAGE_TYPE_QUICK_COPY
820 self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
821 self.job_storage_use_pin = True
823 elif hold == u'PROOF':
824 if holdtype == u'PUBLIC':
825 self.job_storage_mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD
827 self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
828 self.job_storage_use_pin = True
830 elif hold == u'STORE':
831 self.job_storage_mode = JOB_STORAGE_TYPE_STORE
832 self.job_storage_use_pin = (holdtype == u'PRIVATE')
834 if duplicate == u'REPLACE':
835 self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_REPLACE
837 self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_APPEND_1_99
839 # option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False)
841 self.beginControlGroup("jobstorage", self.__tr("Job Storage and Secure Printing"))
843 self.addControlRow("job-storage-mode", self.__tr("Mode"),
844 cups.UI_JOB_STORAGE_MODE, None, None, None)
846 self.addControlRow("job-storage-pin", self.__tr("Make job private (use PIN to print)"),
847 cups.UI_JOB_STORAGE_PIN, None, None, None )
849 self.addControlRow("job-storage-username", self.__tr("User name (for job identification)"),
850 cups.UI_JOB_STORAGE_USERNAME, None, None, None)
852 self.addControlRow("job-storage-id", self.__tr("Job name/ID (for job identification)"),
853 cups.UI_JOB_STORAGE_ID, None, None, None)
855 self.addControlRow("job-storage-id-exists", self.__tr("If job name/ID already exists..."),
856 cups.UI_JOB_STORAGE_ID_EXISTS, None, None, None)
858 self.endControlGroup()
859 self.updateJobStorageControls()
861 # use: self.job_options['xxx'] so that values can be picked up by getPrintCommand(
864 #except Exception, e:
873 def beginControlGroup(self, group, text):
874 log.debug("BeginGroup: %s" % group)
876 self.widget = QWidget()
877 self.gridlayout = QGridLayout(self.widget)
882 def endControlGroup(self):
883 log.debug("EndGroup: %s" % self.group)
884 spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
886 self.gridlayout.addItem(spacer, self.row, 0, 1, 1)
887 i = self.addItem(self.widget, self.text)
890 self.setItemIcon(i, self.plus_icon)
892 self.setItemIcon(i, self.minus_icon)
894 self.widget, self.gridlayout = None, None
897 def addControlRow(self, option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False):
899 if typ == cups.PPD_UI_BOOLEAN: # () On (*) Off widget
900 HBoxLayout = QHBoxLayout()
901 HBoxLayout.setObjectName("HBoxLayout")
903 OptionLabel = QLabel(self.widget)
904 OptionLabel.setObjectName("OptionLabel")
905 HBoxLayout.addWidget(OptionLabel)
907 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
908 HBoxLayout.addItem(SpacerItem)
910 GroupBox = QFrame(self.widget)
912 gridlayout1 = QGridLayout(GroupBox)
913 OnRadioButton = OptionRadioButton(GroupBox, "OnRadioButton", self.group,
914 option, default, job_option)
915 gridlayout1.addWidget(OnRadioButton,0,0,1,1)
916 OffRadioButton = OptionRadioButton(GroupBox, "OffRadioButton", self.group,
917 option, default, job_option)
918 gridlayout1.addWidget(OffRadioButton,0,1,1,1)
919 HBoxLayout.addWidget(GroupBox)
921 DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
922 choices, default, (OnRadioButton, OffRadioButton), typ, job_option)
924 #GroupBox.setDefaultPushbutton(DefaultButton)
925 OnRadioButton.setDefaultPushbutton(DefaultButton)
926 OffRadioButton.setDefaultPushbutton(DefaultButton)
928 HBoxLayout.addWidget(DefaultButton)
929 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
931 OptionLabel.setText(text)
932 OnRadioButton.setText(self.__tr("On"))
933 OffRadioButton.setText(self.__tr("Off"))
935 DefaultButton.setText("Default")
938 DefaultButton.setEnabled(False)
939 self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
942 OnRadioButton.setChecked(True)
944 OffRadioButton.setChecked(True)
945 self.connect(OnRadioButton, SIGNAL("toggled(bool)"), self.BoolRadioButtons_clicked)
948 OnRadioButton.setEnabled(False)
949 OffRadioButton.setEnabled(False)
950 DefaultButton.setEnabled(False)
954 elif typ == cups.PPD_UI_PICKONE: # Combo box widget
955 #print option, job_option
956 HBoxLayout = QHBoxLayout()
957 HBoxLayout.setObjectName("HBoxLayout")
959 OptionLabel = QLabel(self.widget)
960 OptionLabel.setObjectName("OptionLabel")
961 HBoxLayout.addWidget(OptionLabel)
963 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
964 HBoxLayout.addItem(SpacerItem)
966 ComboBox = OptionComboBox(0, self.widget, "ComboBox", self.group, option,
967 choices, default, typ, None, job_option)
969 HBoxLayout.addWidget(ComboBox)
971 DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option,
972 choices, default, ComboBox, typ, job_option)
974 ComboBox.setDefaultPushbutton(DefaultButton)
975 HBoxLayout.addWidget(DefaultButton)
977 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
979 OptionLabel.setText(text)
980 DefaultButton.setText("Default")
982 i, x, y = 0, None, None
985 if value is not None and d == value.lower():
988 if d == default.lower():
991 ComboBox.insertItem(i, t)
995 ComboBox.setCurrentIndex(x)
997 ComboBox.setCurrentIndex(0)
999 if value is not None and value.lower() == default.lower():
1000 DefaultButton.setEnabled(False)
1002 #self.linkPrintoutModeAndQuality(option, value)
1005 # optionComboBox.setEnabled(False)
1006 # defaultPushButton.setEnabled(False)
1007 # elif y is not None:
1008 # QToolTip.add(defaultPushButton, self.__tr('Set to default value of "%1".').arg(y))
1011 self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
1012 self.connect(ComboBox, SIGNAL("currentIndexChanged(const QString &)"), self.ComboBox_indexChanged)
1013 self.connect(ComboBox, SIGNAL("highlighted(const QString &)"), self.ComboBox_highlighted)
1017 elif typ == cups.UI_SPINNER: # Spinner widget
1019 HBoxLayout = QHBoxLayout()
1020 HBoxLayout.setObjectName("HBoxLayout")
1022 OptionLabel = QLabel(self.widget)
1023 OptionLabel.setObjectName("OptionLabel")
1024 HBoxLayout.addWidget(OptionLabel)
1026 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1027 HBoxLayout.addItem(SpacerItem)
1029 SpinBox = OptionSpinBox(self.widget,"SpinBox", self.group, option, default, job_option)
1030 HBoxLayout.addWidget(SpinBox)
1032 DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
1033 choices, default, SpinBox, typ, job_option)
1035 SpinBox.setDefaultPushbutton(DefaultButton)
1036 HBoxLayout.addWidget(DefaultButton)
1038 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1041 SpinBox.setMinimum(min)
1042 SpinBox.setMaximum(max)
1043 SpinBox.setValue(value)
1046 SpinBox.setSuffix(suffix)
1048 OptionLabel.setText(text)
1049 DefaultButton.setText("Default")
1051 self.connect(SpinBox, SIGNAL("valueChanged(int)"), self.SpinBox_valueChanged)
1052 self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
1054 DefaultButton.setEnabled(not value == default)
1057 SpinBox.setEnabled(False)
1058 DefaultButton.setEnabled(False)
1060 elif typ == cups.UI_BANNER_JOB_SHEETS: # Job sheets widget
1061 HBoxLayout = QHBoxLayout()
1062 HBoxLayout.setObjectName("HBoxLayout")
1064 OptionLabel = QLabel(self.widget)
1065 OptionLabel.setObjectName("OptionLabel")
1066 HBoxLayout.addWidget(OptionLabel)
1068 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1069 HBoxLayout.addItem(SpacerItem)
1071 StartLabel = QLabel(self.widget)
1072 HBoxLayout.addWidget(StartLabel)
1074 StartComboBox = OptionComboBox(0, self.widget, "StartComboBox", self.group,
1075 "start", choices, default, typ)
1077 HBoxLayout.addWidget(StartComboBox)
1079 EndLabel = QLabel(self.widget)
1080 HBoxLayout.addWidget(EndLabel)
1082 EndComboBox = OptionComboBox(0, self.widget, "EndComboBox", self.group, "end", choices,
1083 default, typ, StartComboBox)
1085 HBoxLayout.addWidget(EndComboBox)
1087 StartComboBox.setOther(EndComboBox)
1089 DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option, choices,
1090 default, (StartComboBox, EndComboBox), typ, job_option)
1092 HBoxLayout.addWidget(DefaultButton)
1094 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1096 StartComboBox.setDefaultPushbutton(DefaultButton)
1097 EndComboBox.setDefaultPushbutton(DefaultButton)
1099 OptionLabel.setText(text)
1100 DefaultButton.setText("Default")
1102 StartLabel.setText(self.__tr("Start:"))
1103 EndLabel.setText(self.__tr("End:"))
1105 s, e, y, z = None, None, None, None
1106 for c, t in choices:
1108 if value is not None:
1109 if d == value[0].lower():
1112 if d == value[1].lower():
1115 if d == default[0].lower():
1118 if d == default[1].lower():
1121 StartComboBox.insertItem(0, t)
1122 EndComboBox.insertItem(0, t)
1125 StartComboBox.setCurrentIndex(StartComboBox.findText(s))
1128 EndComboBox.setCurrentIndex(EndComboBox.findText(e))
1130 if value is not None and \
1131 value[0].lower() == default[0].lower() and \
1132 value[1].lower() == default[1].lower():
1134 DefaultButton.setEnabled(False)
1136 self.connect(StartComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
1137 self.connect(EndComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
1138 self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
1140 elif typ == cups.PPD_UI_PICKMANY:
1141 log.error("Unrecognized type: pickmany")
1143 elif typ == cups.UI_UNITS_SPINNER:
1144 log.error("Unrecognized type: units spinner")
1146 elif typ == cups.UI_PAGE_RANGE:
1147 HBoxLayout = QHBoxLayout()
1148 HBoxLayout.setObjectName("HBoxLayout")
1150 OptionLabel = QLabel(self.widget)
1151 OptionLabel.setObjectName("OptionLabel")
1152 HBoxLayout.addWidget(OptionLabel)
1154 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1155 HBoxLayout.addItem(SpacerItem)
1157 GroupBox = QFrame(self.widget)
1159 gridlayout1 = QGridLayout(GroupBox)
1161 AllRadioButton = PageRangeRadioButton(GroupBox, "AllRadioButton",
1162 self.group, option, default)
1164 gridlayout1.addWidget(AllRadioButton,0,0,1,1)
1165 RangeRadioButton = PageRangeRadioButton(GroupBox, "RangeRadioButton",
1166 self.group, option, default)
1168 gridlayout1.addWidget(RangeRadioButton,0,1,1,1)
1169 HBoxLayout.addWidget(GroupBox)
1171 PageRangeEdit = QLineEdit(self.widget)
1172 HBoxLayout.addWidget(PageRangeEdit)
1173 PageRangeEdit.setValidator(RangeValidator(PageRangeEdit))
1175 AllRadioButton.setRangeEdit(PageRangeEdit)
1176 RangeRadioButton.setRangeEdit(PageRangeEdit)
1178 DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
1179 choices, default, (AllRadioButton, RangeRadioButton, PageRangeEdit), typ, job_option)
1181 AllRadioButton.setDefaultPushbutton(DefaultButton)
1182 RangeRadioButton.setDefaultPushbutton(DefaultButton)
1184 HBoxLayout.addWidget(DefaultButton)
1185 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1187 OptionLabel.setText(text)
1188 AllRadioButton.setText(self.__tr("All pages"))
1189 RangeRadioButton.setText(self.__tr("Page Range:"))
1191 DefaultButton.setText("Default")
1192 DefaultButton.setEnabled(False)
1194 AllRadioButton.setChecked(True)
1195 PageRangeEdit.setEnabled(False)
1199 self.connect(AllRadioButton, SIGNAL("toggled(bool)"), self.PageRangeAllRadio_toggled)
1200 self.connect(RangeRadioButton, SIGNAL("toggled(bool)"), self.PageRangeRangeRadio_toggled)
1201 self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
1202 self.connect(PageRangeEdit, SIGNAL("textChanged(const QString &)"), self.PageRangeEdit_textChanged)
1203 self.connect(PageRangeEdit, SIGNAL("editingFinished()"), self.PageRangeEdit_editingFinished)
1205 elif typ == cups.UI_JOB_STORAGE_MODE:
1206 HBoxLayout = QHBoxLayout()
1207 HBoxLayout.setObjectName("HBoxLayout")
1209 OptionLabel = QLabel(self.widget)
1210 OptionLabel.setObjectName("OptionLabel")
1211 HBoxLayout.addWidget(OptionLabel)
1213 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1214 HBoxLayout.addItem(SpacerItem)
1216 self.JobStorageModeComboBox = QComboBox(self.widget)
1217 HBoxLayout.addWidget(self.JobStorageModeComboBox)
1219 self.JobStorageModeDefaultButton = QPushButton(self.widget)
1220 HBoxLayout.addWidget(self.JobStorageModeDefaultButton)
1222 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1224 OptionLabel.setText(text)
1225 self.JobStorageModeDefaultButton.setText(self.__tr("Default"))
1227 self.JobStorageModeComboBox.addItem(self.__tr("Off/Disabled"), QVariant(JOB_STORAGE_TYPE_OFF))
1228 self.JobStorageModeComboBox.addItem(self.__tr("Proof and Hold"), QVariant(JOB_STORAGE_TYPE_PROOF_AND_HOLD))
1229 self.JobStorageModeComboBox.addItem(self.__tr("Personal/Private Job"), QVariant(JOB_STORAGE_TYPE_PERSONAL))
1230 self.JobStorageModeComboBox.addItem(self.__tr("Quick Copy"), QVariant(JOB_STORAGE_TYPE_QUICK_COPY))
1231 self.JobStorageModeComboBox.addItem(self.__tr("Stored Job"), QVariant(JOB_STORAGE_TYPE_STORE))
1233 self.connect(self.JobStorageModeComboBox, SIGNAL("activated(int)"),
1234 self.JobStorageModeComboBox_activated)
1236 self.connect(self.JobStorageModeDefaultButton, SIGNAL("clicked()"),
1237 self.JobStorageModeDefaultButton_clicked)
1240 elif typ == cups.UI_JOB_STORAGE_PIN:
1241 HBoxLayout = QHBoxLayout()
1242 HBoxLayout.setObjectName("HBoxLayout")
1244 OptionLabel = QLabel(self.widget)
1245 OptionLabel.setObjectName("OptionLabel")
1246 HBoxLayout.addWidget(OptionLabel)
1248 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1249 HBoxLayout.addItem(SpacerItem)
1251 self.JobStoragePinGroupBox = QFrame(self.widget)
1253 gridlayout1 = QGridLayout(self.JobStoragePinGroupBox)
1254 self.JobStoragePinOffRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1255 gridlayout1.addWidget(self.JobStoragePinOffRadioButton, 0, 0, 1, 1)
1257 self.JobStoragePinPrivateRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1258 gridlayout1.addWidget(self.JobStoragePinPrivateRadioButton, 0, 1, 1, 1)
1260 self.JobStoragePinEdit = QLineEdit(self.JobStoragePinGroupBox)
1261 self.JobStoragePinEdit.setMaxLength(4)
1262 self.JobStoragePinEdit.setValidator(PinValidator(self.JobStoragePinEdit))
1263 gridlayout1.addWidget(self.JobStoragePinEdit, 0, 2, 1, 1)
1265 HBoxLayout.addWidget(self.JobStoragePinGroupBox)
1267 self.JobStoragePinDefaultButton = QPushButton(self.widget)
1268 HBoxLayout.addWidget(self.JobStoragePinDefaultButton)
1270 self.JobStoragePinOffRadioButton.setText(self.__tr("Public/Off"))
1271 self.JobStoragePinPrivateRadioButton.setText(self.__tr("Private/Use PIN:"))
1273 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1275 OptionLabel.setText(text)
1276 self.JobStoragePinDefaultButton.setText(self.__tr("Default"))
1278 self.connect(self.JobStoragePinOffRadioButton, SIGNAL("toggled(bool)"),
1279 self.JobStoragePinOffRadioButton_toggled)
1281 self.connect(self.JobStoragePinPrivateRadioButton, SIGNAL("toggled(bool)"),
1282 self.JobStoragePinPrivateRadioButton_toggled)
1284 self.connect(self.JobStoragePinDefaultButton, SIGNAL("clicked()"),
1285 self.JobStoragePinDefaultButton_clicked)
1287 self.connect(self.JobStoragePinEdit, SIGNAL("textEdited(const QString &)"),
1288 self.JobStoragePinEdit_textEdited)
1291 elif typ == cups.UI_JOB_STORAGE_USERNAME:
1292 HBoxLayout = QHBoxLayout()
1293 HBoxLayout.setObjectName("HBoxLayout")
1295 OptionLabel = QLabel(self.widget)
1296 OptionLabel.setObjectName("OptionLabel")
1297 HBoxLayout.addWidget(OptionLabel)
1298 OptionLabel.setText(text)
1300 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1301 HBoxLayout.addItem(SpacerItem)
1303 self.JobStorageUsernameGroupBox = QFrame(self.widget)
1305 gridlayout1 = QGridLayout(self.JobStorageUsernameGroupBox)
1306 self.JobStorageUsernameAutoRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1307 gridlayout1.addWidget(self.JobStorageUsernameAutoRadioButton, 0, 0, 1, 1)
1309 self.JobStorageUsernameCustomRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1310 gridlayout1.addWidget(self.JobStorageUsernameCustomRadioButton, 0, 1, 1, 1)
1312 self.JobStorageUsernameEdit = QLineEdit(self.JobStorageUsernameGroupBox)
1313 self.JobStorageUsernameEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageUsernameEdit))
1314 self.JobStorageUsernameEdit.setMaxLength(16)
1315 gridlayout1.addWidget(self.JobStorageUsernameEdit, 0, 2, 1, 1)
1317 HBoxLayout.addWidget(self.JobStorageUsernameGroupBox)
1319 self.JobStorageUsernameDefaultButton = QPushButton(self.widget)
1320 HBoxLayout.addWidget(self.JobStorageUsernameDefaultButton)
1322 self.JobStorageUsernameAutoRadioButton.setText(self.__tr("Automatic"))
1323 self.JobStorageUsernameCustomRadioButton.setText(self.__tr("Custom:"))
1324 self.JobStorageUsernameDefaultButton.setText(self.__tr("Default"))
1326 self.connect(self.JobStorageUsernameAutoRadioButton, SIGNAL("toggled(bool)"),
1327 self.JobStorageUsernameAutoRadioButton_toggled)
1329 self.connect(self.JobStorageUsernameCustomRadioButton, SIGNAL("toggled(bool)"),
1330 self.JobStorageUsernameCustomRadioButton_toggled)
1332 self.connect(self.JobStorageUsernameDefaultButton, SIGNAL("clicked()"),
1333 self.JobStorageUsernameDefaultButton_clicked)
1335 self.connect(self.JobStorageUsernameEdit, SIGNAL("textEdited(const QString &)"),
1336 self.JobStorageUsernameEdit_textEdited)
1338 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1340 elif typ == cups.UI_JOB_STORAGE_ID:
1341 HBoxLayout = QHBoxLayout()
1342 HBoxLayout.setObjectName("HBoxLayout")
1344 OptionLabel = QLabel(self.widget)
1345 OptionLabel.setObjectName("OptionLabel")
1346 HBoxLayout.addWidget(OptionLabel)
1347 OptionLabel.setText(text)
1349 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1350 HBoxLayout.addItem(SpacerItem)
1352 self.JobStorageIDGroupBox = QFrame(self.widget)
1354 gridlayout1 = QGridLayout(self.JobStorageIDGroupBox)
1355 self.JobStorageIDAutoRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1356 gridlayout1.addWidget(self.JobStorageIDAutoRadioButton, 0, 0, 1, 1)
1358 self.JobStorageIDCustomRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1359 gridlayout1.addWidget(self.JobStorageIDCustomRadioButton, 0, 1, 1, 1)
1361 self.JobStorageIDEdit = QLineEdit(self.JobStorageIDGroupBox)
1362 self.JobStorageIDEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageIDEdit))
1363 self.JobStorageIDEdit.setMaxLength(16)
1364 gridlayout1.addWidget(self.JobStorageIDEdit, 0, 2, 1, 1)
1366 HBoxLayout.addWidget(self.JobStorageIDGroupBox)
1368 self.JobStorageIDDefaultButton = QPushButton(self.widget)
1369 HBoxLayout.addWidget(self.JobStorageIDDefaultButton)
1371 self.JobStorageIDAutoRadioButton.setText(self.__tr("Automatic"))
1372 self.JobStorageIDCustomRadioButton.setText(self.__tr("Custom:"))
1373 self.JobStorageIDDefaultButton.setText(self.__tr("Default"))
1375 self.connect(self.JobStorageIDAutoRadioButton, SIGNAL("toggled(bool)"),
1376 self.JobStorageIDAutoRadioButton_toggled)
1378 self.connect(self.JobStorageIDCustomRadioButton, SIGNAL("toggled(bool)"),
1379 self.JobStorageIDCustomRadioButton_toggled)
1381 self.connect(self.JobStorageIDDefaultButton, SIGNAL("clicked()"),
1382 self.JobStorageIDDefaultButton_clicked)
1384 self.connect(self.JobStorageIDEdit, SIGNAL("textEdited(const QString &)"),
1385 self.JobStorageIDEdit_textEdited)
1387 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1389 elif typ == cups.UI_JOB_STORAGE_ID_EXISTS:
1390 HBoxLayout = QHBoxLayout()
1391 HBoxLayout.setObjectName("HBoxLayout")
1393 OptionLabel = QLabel(self.widget)
1394 OptionLabel.setObjectName("OptionLabel")
1395 HBoxLayout.addWidget(OptionLabel)
1396 OptionLabel.setText(text)
1398 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1399 HBoxLayout.addItem(SpacerItem)
1401 self.JobStorageExistingComboBox = QComboBox(self.widget)
1402 HBoxLayout.addWidget(self.JobStorageExistingComboBox)
1404 self.JobStorageExistingDefaultButton = QPushButton(self.widget)
1405 HBoxLayout.addWidget(self.JobStorageExistingDefaultButton)
1407 self.JobStorageExistingComboBox.addItem(self.__tr("Replace existing job"),
1408 QVariant(JOB_STORAGE_EXISTING_JOB_REPLACE))
1410 self.JobStorageExistingComboBox.addItem(self.__tr("Use job name appended with 1-99"),
1411 QVariant(JOB_STORAGE_EXISTING_JOB_APPEND_1_99))
1413 self.JobStorageExistingDefaultButton.setText(self.__tr("Default"))
1415 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1417 self.connect(self.JobStorageExistingComboBox, SIGNAL("activated(int)"),
1418 self.JobStorageExistingComboBox_activated)
1420 self.connect(self.JobStorageExistingDefaultButton, SIGNAL("clicked()"),
1421 self.JobStorageExistingDefaultButton_clicked)
1423 elif typ == cups.UI_INFO:
1424 HBoxLayout = QHBoxLayout()
1425 HBoxLayout.setObjectName("HBoxLayout")
1427 OptionName = QLabel(self.widget)
1428 OptionName.setObjectName("OptionLabel")
1429 HBoxLayout.addWidget(OptionName)
1430 OptionName.setText(text)
1432 SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1433 HBoxLayout.addItem(SpacerItem)
1435 if text == 'Print Quality':
1436 self.PQValueLabel = QLabel(self.widget)
1437 self.PQValueLabel.setObjectName("PQValueLabel")
1438 HBoxLayout.addWidget(self.PQValueLabel)
1439 self.PQValueLabel.setText(value)
1440 elif text == 'Color Input / Black Render':
1441 self.PQColorInputLabel = QLabel(self.widget)
1442 self.PQColorInputLabel.setObjectName("PQColorInputLabel")
1443 HBoxLayout.addWidget(self.PQColorInputLabel)
1444 self.PQColorInputLabel.setText(value)
1446 OptionValue = QLabel(self.widget)
1447 OptionValue.setObjectName("OptionValue")
1448 HBoxLayout.addWidget(OptionValue)
1449 OptionValue.setText(value)
1451 self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1454 log.error("Invalid UI value: %s/%s" % (self.group, option))
1460 def BannerComboBox_activated(self, a): # cups.UI_BANNER_JOB_SHEETS
1462 sender = self.sender()
1465 start, end = None, None
1466 for c, t in sender.choices:
1471 for c, t in sender.other.choices:
1472 if t == sender.other.currentText():
1476 if sender.option == 'end':
1477 start, end = end, start
1479 if start is not None and \
1480 end is not None and \
1481 start.lower() == sender.default[0].lower() and \
1482 end.lower() == sender.default[1].lower():
1483 self.removePrinterOption('job-sheets')
1484 sender.pushbutton.setEnabled(False)
1486 sender.pushbutton.setEnabled(True)
1488 if start is not None and \
1491 self.setPrinterOption('job-sheets', ','.join([start, end]))
1494 def ComboBox_highlighted(self, t):
1496 sender = self.sender()
1499 #print sender, sender.option, sender.job_option
1502 for c, a in sender.choices:
1507 if choice is not None and choice == sender.default:
1508 if sender.job_option:
1509 self.job_options[sender.option] = sender.default
1511 self.removePrinterOption(sender.option)
1512 sender.pushbutton.setEnabled(False)
1515 sender.pushbutton.setEnabled(True)
1517 if choice is not None:
1518 if sender.job_option:
1519 self.job_options[sender.option] = choice
1521 self.setPrinterOption(sender.option, choice)
1523 #self.linkPrintoutModeAndQuality(sender.option, choice)
1527 # def linkPrintoutModeAndQuality(self, option, choice):
1528 # if option.lower() == 'quality' and \
1529 # choice is not None:
1532 # c = self.items['o:PrintoutMode'].control
1537 # if choice.lower() == 'fromprintoutmode':
1538 # # from printoutmode selected
1539 # # determine printoutmode option combo enable state
1540 # c.setEnabled(True)
1541 # QToolTip.remove(c)
1542 # a = unicode(c.currentText())
1544 # # determine printoutmode default button state
1545 # link_choice = None
1546 # for x, t in c.choices:
1551 # if link_choice is not None and \
1552 # link_choice.lower() == c.default.lower():
1554 # c.pushbutton.setEnabled(False)
1556 # c.pushbutton.setEnabled(True)
1558 # else: # fromprintoutmode not selected, disable printoutmode
1559 # c.setEnabled(False)
1560 # QToolTip.add(c, self.__tr("""Set Quality to "Controlled by 'Printout Mode'" to enable."""))
1561 # c.pushbutton.setEnabled(False)
1564 def SpinBox_valueChanged(self, i): # cups.UI_SPINNER
1565 sender = self.sender()
1567 if not sender.job_option:
1568 if i == sender.default:
1569 self.removePrinterOption(sender.option)
1570 sender.pushbutton.setEnabled(False)
1572 sender.pushbutton.setEnabled(True)
1573 self.setPrinterOption(sender.option, str(i))
1577 self.job_options[sender.option] = int(i)
1579 self.job_options[sender.option] = sender.default
1582 def BoolRadioButtons_clicked(self, b): # cups.PPD_UI_BOOLEAN
1583 sender = self.sender()
1586 if b == sender.default:
1587 self.removePrinterOption(sender.option)
1588 sender.pushbutton.setEnabled(False)
1590 sender.pushbutton.setEnabled(True)
1593 self.setPrinterOption(sender.option, "true")
1595 self.setPrinterOption(sender.option, "false")
1597 def ComboBox_indexChanged(self, currentItem):
1598 sender = self.sender()
1599 currentItem = unicode(currentItem)
1600 # Checking for summary control
1601 labelPQValaue = getattr(self, 'PQValueLabel', None)
1602 labelPQColorInput = getattr(self, 'PQColorInputLabel', None)
1603 # When output mode combo item is changed, we need to update the summary information
1604 if currentItem is not None and sender.option == 'OutputMode' and labelPQValaue is not None and labelPQColorInput is not None:
1605 # Setting output mode
1606 self.PQValueLabel.setText(currentItem)
1608 # Getting DPI custom attributefrom the PPD
1609 # Setting color input
1610 quality_attr_name = "OutputModeDPI"
1611 cups.openPPD(self.cur_printer)
1612 outputmode_dpi = cups.findPPDAttribute(quality_attr_name, currentItem)
1613 log.debug("Outputmode changed, setting outputmode_dpi: %s" % outputmode_dpi)
1615 self.PQColorInputLabel.setText(outputmode_dpi)
1617 log.debug("Outputmode changed, setting value outputmode: %s" % currentItem)
1619 def DefaultButton_clicked(self):
1620 sender = self.sender()
1621 sender.setEnabled(False)
1623 if sender.typ == cups.PPD_UI_BOOLEAN: # () On (*) Off
1625 sender.control[0].setChecked(True)
1626 sender.control[0].setFocus(Qt.OtherFocusReason)
1628 sender.control[1].setChecked(True)
1629 sender.control[1].setFocus(Qt.OtherFocusReason)
1631 if not sender.job_option:
1632 self.removePrinterOption(sender.option)
1634 elif sender.typ == cups.PPD_UI_PICKONE: # [ \/]
1635 choice, text = None, None
1637 for c, t in sender.choices:
1638 if c == sender.default:
1641 self.job_options[sender.option] = t
1644 if choice is not None:
1645 if not sender.job_option:
1646 self.removePrinterOption(sender.option)
1647 index = sender.control.findText(text)
1648 sender.control.setCurrentIndex(index)
1650 #self.linkPrintoutModeAndQuality(sender.option, choice) # TODO:
1651 sender.control.setFocus(Qt.OtherFocusReason)
1653 elif sender.typ == cups.UI_SPINNER: # [ x /\|\/]
1654 sender.control.setValue(sender.default)
1655 if not sender.job_option:
1656 self.removePrinterOption(sender.option)
1658 sender.control.setFocus(Qt.OtherFocusReason)
1660 elif sender.typ == cups.UI_BANNER_JOB_SHEETS: # start: [ \/] end: [ \/]
1661 start, end, start_text, end_text = None, None, None, None
1662 for c, t in sender.choices:
1663 if c == sender.default[0]:
1667 if c == sender.default[1]:
1671 if start is not None:
1672 index = sender.control[0].findText(start_text)
1673 sender.control[0].setCurrentIndex(index)
1676 index = sender.control[1].findText(end_text)
1677 sender.control[1].setCurrentIndex(index)
1679 if not sender.job_option:
1680 self.removePrinterOption('job-sheets')
1682 sender.control[0].setFocus(Qt.OtherFocusReason)
1684 elif sender.typ == cups.UI_PAGE_RANGE: # (*) All () Pages: [ ]
1685 sender.control[0].setChecked(True) # all radio button
1686 sender.control[0].setFocus(Qt.OtherFocusReason)
1687 sender.control[2].setEnabled(False) # range edit box
1690 def PageRangeAllRadio_toggled(self, b):
1692 sender = self.sender()
1693 sender.edit_control.setEnabled(False)
1694 sender.pushbutton.setEnabled(False)
1695 self.job_options['pagerange'] = ''
1698 def PageRangeRangeRadio_toggled(self, b):
1700 sender = self.sender()
1701 sender.pushbutton.setEnabled(True)
1702 sender.edit_control.setEnabled(True)
1703 self.job_options['pagerange'] = unicode(sender.edit_control.text())
1706 def PageRangeEdit_editingFinished(self):
1707 sender = self.sender()
1708 t, ok, x = self.job_options['pagerange'], True, []
1710 #[Sanjay]Start Range Validation here as the editing is finished
1712 x = utils.expand_range(t)
1730 self.job_options['pagerange'] = ''
1731 log.error("Invalid page range: %s" % t)
1732 FailureUI(self, self.__tr("<b>Invalid page range.</b><p>Please enter a range using page numbers (1-999), dashes, and commas. For example: 1-2,3,5-7</p>"))
1733 sender.setFocus(Qt.OtherFocusReason)
1736 def PageRangeEdit_textChanged(self, t):
1737 self.job_options['pagerange'] = unicode(t) # Do range validation only in PageRangeEdit_editingFinished method
1743 def updateJobStorageControls(self):
1747 self.JobStorageModeComboBox.setCurrentIndex(self.JobStorageModeComboBox.findData(QVariant(self.job_storage_mode)))
1748 self.JobStorageModeDefaultButton.setEnabled(self.job_storage_mode != JOB_STORAGE_TYPE_OFF)
1751 self.JobStoragePinPrivateRadioButton.setChecked(self.job_storage_use_pin)
1754 self.JobStorageUsernameAutoRadioButton.setChecked(self.job_storage_auto_username)
1757 self.JobStorageIDAutoRadioButton.setChecked(self.job_storage_auto_jobname)
1760 self.JobStorageExistingComboBox.setCurrentIndex(self.JobStorageExistingComboBox.findData(QVariant(self.job_storage_job_exist)))
1762 if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
1764 self.JobStoragePinGroupBox.setEnabled(False)
1765 self.JobStoragePinEdit.setEnabled(False)
1766 self.JobStoragePinDefaultButton.setEnabled(False)
1767 self.JobStoragePinEdit.setText(QString())
1770 self.JobStorageUsernameGroupBox.setEnabled(False)
1771 self.JobStorageUsernameEdit.setEnabled(False)
1772 self.JobStorageUsernameDefaultButton.setEnabled(False)
1775 self.JobStorageIDGroupBox.setEnabled(False)
1776 self.JobStorageIDEdit.setEnabled(False)
1777 self.JobStorageIDDefaultButton.setEnabled(False)
1779 # Duplicate/existing Jobname/ID
1780 self.JobStorageExistingComboBox.setEnabled(False)
1784 if self.job_storage_mode in (JOB_STORAGE_TYPE_PERSONAL, JOB_STORAGE_TYPE_STORE):
1785 self.JobStoragePinGroupBox.setEnabled(True)
1786 self.JobStoragePinDefaultButton.setEnabled(self.job_storage_use_pin)
1787 self.JobStoragePinEdit.setEnabled(self.job_storage_use_pin)
1788 self.JobStoragePinEdit.setText(QString(self.job_storage_pin))
1790 self.JobStoragePinGroupBox.setEnabled(False)
1791 self.JobStoragePinEdit.setEnabled(False)
1792 self.JobStoragePinDefaultButton.setEnabled(False)
1793 self.JobStoragePinEdit.setText(QString())
1796 self.JobStorageUsernameGroupBox.setEnabled(True)
1797 self.JobStorageUsernameEdit.setEnabled(not self.job_storage_auto_username)
1798 self.JobStorageUsernameDefaultButton.setEnabled(not self.job_storage_auto_username)
1799 self.JobStorageUsernameEdit.setText(QString(self.job_storage_username))
1802 self.JobStorageIDGroupBox.setEnabled(True)
1803 self.JobStorageIDEdit.setEnabled(not self.job_storage_auto_jobname)
1804 self.JobStorageIDDefaultButton.setEnabled(not self.job_storage_auto_jobname)
1805 self.JobStorageIDEdit.setText(QString(self.job_storage_jobname))
1807 # Duplicate/existing JobName/ID
1808 self.JobStorageExistingComboBox.setEnabled(not self.job_storage_auto_jobname)
1809 self.JobStorageExistingDefaultButton.setEnabled(not self.job_storage_auto_jobname and self.job_storage_job_exist != JOB_STORAGE_EXISTING_JOB_REPLACE)
1815 def saveJobStorageOptions(self):
1818 log.debug("Saving job storage options...")
1820 if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
1821 log.debug("Job storage mode = JOB_STORAGE_TYPE_OFF")
1822 self.setPrinterOption('HOLD', 'OFF')
1823 self.removePrinterOption('HOLDTYPE')
1824 self.removePrinterOption('USERNAME')
1825 self.removePrinterOption('JOBNAME')
1826 self.removePrinterOption('DUPLICATEJOB')
1828 elif self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
1829 log.debug("Job storage mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD")
1830 self.setPrinterOption('HOLD', 'PROOF')
1831 #self.removePrinterOption('HOLDTYPE')
1832 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1834 elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
1835 log.debug("Job storage mode = JOB_STORAGE_TYPE_PERSONAL")
1837 if self.job_storage_use_pin:
1838 self.setPrinterOption('HOLD', 'ON')
1840 self.setPrinterOption('HOLD', 'PROOF')
1841 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1844 elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
1845 log.debug("Job storage mode = JOB_STORAGE_TYPE_QUICK_COPY")
1846 self.setPrinterOption('HOLD', 'ON')
1847 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1849 elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
1850 log.debug("Job storage mode = JOB_STORAGE_TYPE_STORE")
1851 self.setPrinterOption('HOLD', 'STORE')
1853 if not self.job_storage_use_pin:
1854 self.removePrinterOption('HOLDTYPE')
1857 log.debug("Job storage use pin = %d" % self.job_storage_use_pin)
1858 if self.job_storage_use_pin:
1859 self.setPrinterOption('HOLDTYPE', 'PRIVATE')
1862 # self.removePrinterOption('HOLDKEY')
1865 if self.job_storage_job_exist == JOB_STORAGE_EXISTING_JOB_REPLACE:
1866 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_REPLACE")
1867 self.setPrinterOption('DUPLICATEJOB', 'REPLACE')
1869 else: # JOB_STORAGE_EXISTING_JOB_APPEND_1_99
1870 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_APPEND_1_99")
1871 self.setPrinterOption('DUPLICATEJOB', 'APPEND')
1882 def JobStorageModeComboBox_activated(self, i):
1883 sender = self.sender()
1884 mode, ok = sender.itemData(i).toInt()
1886 self.job_storage_mode = mode
1887 self.saveJobStorageOptions()
1888 self.updateJobStorageControls()
1891 def JobStorageModeDefaultButton_clicked(self):
1892 self.JobStorageModeComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_TYPE_OFF)
1899 def JobStoragePinOffRadioButton_toggled(self, b):
1900 self.job_storage_use_pin = not b
1901 self.updateJobStorageControls()
1902 self.saveJobStorageOptions()
1905 def JobStoragePinPrivateRadioButton_toggled(self, b):
1906 self.job_storage_use_pin = b
1907 self.updateJobStorageControls()
1908 self.saveJobStorageOptions()
1911 def JobStoragePinDefaultButton_clicked(self):
1912 self.JobStoragePinOffRadioButton.emit(SIGNAL("toggled(bool)"), True)
1915 def JobStoragePinEdit_textEdited(self, s):
1916 self.job_storage_pin = unicode(s)
1917 self.setPrinterOption('HOLDKEY', self.job_storage_pin.encode('ascii'))
1925 def JobStorageUsernameAutoRadioButton_toggled(self, b):
1926 self.job_storage_auto_username = b
1927 self.updateJobStorageControls()
1928 self.saveJobStorageOptions()
1931 def JobStorageUsernameCustomRadioButton_toggled(self, b):
1932 self.job_storage_auto_username = not b
1933 self.updateJobStorageControls()
1934 self.saveJobStorageOptions()
1937 def JobStorageUsernameDefaultButton_clicked(self):
1938 self.JobStorageUsernameAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1941 def JobStorageUsernameEdit_textEdited(self, s):
1942 self.job_storage_username = unicode(s)
1943 self.setPrinterOption('USERNAME', self.job_storage_username.encode('ascii'))
1949 def JobStorageIDAutoRadioButton_toggled(self, b):
1950 self.job_storage_auto_jobname = b
1951 self.updateJobStorageControls()
1952 self.saveJobStorageOptions()
1955 def JobStorageIDCustomRadioButton_toggled(self, b):
1956 self.job_storage_auto_jobname = not b
1957 self.updateJobStorageControls()
1958 self.saveJobStorageOptions()
1961 def JobStorageIDDefaultButton_clicked(self):
1962 self.JobStorageIDAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1965 def JobStorageIDEdit_textEdited(self, s):
1966 self.job_storage_jobname = unicode(s)
1967 self.setPrinterOption('JOBNAME', self.job_storage_jobname.encode('ascii'))
1970 # Duplicate/existing Jobname/ID
1973 def JobStorageExistingComboBox_activated(self, i):
1974 sender = self.sender()
1975 opt, ok = sender.itemData(i).toInt()
1977 self.job_storage_job_exist = opt
1978 self.updateJobStorageControls()
1979 self.saveJobStorageOptions()
1982 def JobStorageExistingDefaultButton_clicked(self):
1983 self.JobStorageExistingComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_EXISTING_JOB_REPLACE)
1990 def setPrinterOption(self, option, value):
1991 log.debug("setPrinterOption(%s, %s)" % (option, value))
1992 cups.openPPD(self.cur_printer)
1995 cups.addOption("%s=%s" % (option, value))
2000 def removePrinterOption(self, option):
2001 log.debug("removePrinterOption(%s)" % option)
2002 cups.openPPD(self.cur_printer)
2005 cups.removeOption(option)
2011 def __tr(self,s,c = None):
2012 return qApp.translate("PrintSettingsToolbox",s,c)