1
# -*- coding: utf-8 -*-
3
# (c) Copyright 2001-2015 HP 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 *
31
from base.sixext import PY3
32
from base.sixext import to_unicode
35
from PyQt5.QtCore import *
36
from PyQt5.QtGui import *
37
from PyQt5.QtWidgets import *
41
class RangeValidator(QValidator):
42
def __init__(self, parent=None, name=None):
43
QValidator.__init__(self, parent) #, name)
46
def validate(self, input, pos):
47
for x in to_unicode(input)[pos-1:]:
48
if x not in to_unicode('0123456789,- '):
49
return QValidator.Invalid, input, pos
50
return QValidator.Acceptable, input, pos
53
class PinValidator(QValidator):
54
def __init__(self, parent=None, name=None):
55
QValidator.__init__(self, parent) #, name)
58
def validate(self, input, pos):
59
for x in to_unicode(input)[pos-1:]:
60
if x not in to_unicode('0123456789'):
61
return QValidator.Invalid, input, pos
63
return QValidator.Acceptable, input, 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 to_unicode(input)[pos-1:]:
73
if x in to_unicode(' /=,.:;\'"[]{}-+!@#$%^&*()'):
74
return QValidator.Invalid, input, pos
75
return QValidator.Acceptable, input, pos
78
class OptionComboBox(QComboBox):
79
def __init__(self, rw, parent, name, group, option, choices, default,
80
typ=cups.PPD_UI_PICKONE, other=None, job_option=False):
81
QComboBox.__init__(self, parent)
85
self.choices = choices
86
self.default = default
89
self.job_option = job_option
90
self.setObjectName(name)
93
def setDefaultPushbutton(self, pushbutton):
94
self.pushbutton = pushbutton
97
def setOther(self, other):
102
class OptionSpinBox(QSpinBox):
103
def __init__(self, parent, name, group, option, default, job_option=False):
104
QSpinBox.__init__(self, parent)
107
self.default = default
108
self.job_option = job_option
109
self.setObjectName(name)
112
def setDefaultPushbutton(self, pushbutton):
113
self.pushbutton = pushbutton
117
class OptionRadioButton(QRadioButton):
118
def __init__(self, parent, name, group, option, default, job_option=False):
119
QRadioButton.__init__(self, parent)
122
self.default = default
123
self.job_option = job_option
124
self.setObjectName(name)
127
def setDefaultPushbutton(self, pushbutton):
128
self.pushbutton = pushbutton
132
class DefaultPushButton(QPushButton):
133
def __init__(self, parent, name, group, option, choices,
134
default, control, typ, job_option=False):
135
QPushButton.__init__(self, parent)
138
self.default = default
139
self.control = control
141
self.choices = choices
142
self.job_option = job_option
143
self.setObjectName(name)
146
#class PageRangeRadioButton(QRadioButton):
147
# def __init__(self, parent, page_range_edit):
148
# QRadioButton.__init__(self, parent):
149
# self.page_range_edit = page_range_edit
152
class PageRangeRadioButton(QRadioButton):
153
def __init__(self, parent, name, group, option, default): #, edit_control=None ):
154
QRadioButton.__init__(self, parent)
157
self.default = default
158
self.job_option = True
159
self.setObjectName(name)
162
def setRangeEdit(self, edit_control):
163
self.edit_control = edit_control
166
def setDefaultPushbutton(self, pushbutton):
167
self.pushbutton = pushbutton
171
class PrintSettingsToolbox(QToolBox):
172
def __init__(self, parent, include_job_options=False):
173
QToolBox.__init__(self, parent)
174
self.include_job_options = include_job_options
175
self.plus_icon = QIcon(load_pixmap('plus', '16x16'))
176
self.minus_icon = QIcon(load_pixmap('minus', '16x16'))
178
self.job_options = {}
179
self.job_storage_enable = False
181
# self.currentChanged[int].connect(self.PrintSettingsToolbox_currentChanged)
182
self.currentChanged[int].connect(self.PrintSettingsToolbox_currentChanged)
185
def getPrintCommands(self, file_list=None):
186
# File list: [(path, mime_type, mime_desc, title, num_pages), ...]
187
if file_list is None or not file_list:
193
copies = int(self.job_options['copies'])
199
log.warning("Copies < 1, setting to 1.")
202
log.warning("Copies > 99, setting to 99.")
204
#page_range = unicode(self.pageRangeEdit.text())
205
page_range = self.job_options['pagerange']
208
x = utils.expand_range(page_range)
210
log.error("Invalid page range: %s" % page_range)
213
all_pages = not page_range
214
#page_set = int(self.pageSetComboBox.currentItem())
215
page_set = self.job_options['pageset']
218
cups.openPPD(self.cur_printer)
219
current_options = dict(cups.getOptions())
222
nup = int(current_options.get("number-up", 1))
223
psnup = utils.which('psnup')
225
for p, t, d, title, num_pages in file_list:
226
alt_nup = (nup > 1 and t == 'application/postscript' and psnup)
228
if utils.which('lpr'):
230
cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lpr -P', self.cur_printer])
232
cmd = ' '.join(['lpr -P', self.cur_printer])
235
cmd = ' '.join([cmd, '-#%d' % copies])
239
cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.cur_printer])
241
cmd = ' '.join(['lp -c -d', self.cur_printer])
244
cmd = ' '.join([cmd, '-n%d' % copies])
247
if not all_pages and page_range:
248
cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
251
cmd = ' '.join([cmd, '-o page-set=%s' % page_set])
254
# self.job_storage_mode = (0=Off, 1=P&H, 2=PJ, 3=QC, 4=SJ)
255
# self.job_storage_pin = u"" (dddd)
256
# self.job_storage_use_pin = True|False
257
# self.job_storage_username = u""
258
# self.job_storage_auto_username = True|False
259
# self.job_storage_jobname = u""
260
# self.job_storage_auto_jobname = True|False
261
# self.job_storage_job_exist = (0=replace, 1=job name+(1-99))
263
if self.job_storage_enable:
264
if self.job_storage_mode != JOB_STORAGE_TYPE_OFF:
265
if self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
266
cmd = ' '.join([cmd, '-o HOLD=PROOF'])
268
elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
269
if self.job_storage_use_pin:
270
cmd = ' '.join([cmd, '-o HOLD=ON'])
271
cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
272
cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
274
cmd = ' '.join([cmd, '-o HOLD=PROOF'])
275
cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
277
elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
278
cmd = ' '.join([cmd, '-o HOLD=ON'])
279
cmd = ' '.join([cmd, '-o HOLDTYPE=PUBLIC'])
281
elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
282
if self.job_storage_use_pin:
283
cmd = ' '.join([cmd, '-o HOLD=STORE'])
284
cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
285
cmd = ' '.join([cmd, '-o HOLDKEY=%s' % self.job_storage_pin.encode('ascii')])
287
cmd = ' '.join([cmd, '-o HOLD=STORE'])
289
cmd = ' '.join([cmd, '-o USERNAME=%s' % self.job_storage_username.encode('ascii')\
292
cmd = ' '.join([cmd, '-o JOBNAME=%s' % self.job_storage_jobname.encode('ascii')\
295
if self.job_storage_job_exist == 1:
296
cmd = ' '.join([cmd, '-o DUPLICATEJOB=APPEND'])
298
cmd = ' '.join([cmd, '-o DUPLICATEJOB=REPLACE'])
301
cmd = ' '.join([cmd, '-o HOLD=OFF'])
304
cmd = ''.join([cmd, ' "', p, '"'])
306
print_commands.append(cmd)
308
return print_commands
311
def PrintSettingsToolbox_currentChanged(self, i):
313
self.setItemIcon(self.last_item, self.plus_icon)
314
self.setItemIcon(i, self.minus_icon)
318
def updateUi(self, cur_device, cur_printer):
319
#print "updateUi(%s, %s)" % (cur_device, cur_printer)
320
self.cur_device = cur_device
321
self.cur_printer = cur_printer
328
cups.openPPD(self.cur_printer)
334
current_options = dict(cups.getOptions())
336
if self.include_job_options:
337
self.beginControlGroup("job_options", self.__tr("Job Options"))
339
# Num. copies (SPINNER)
341
current = int(current_options.get('copies', '1'))
345
self.addControlRow("copies", self.__tr("Number of copies"),
346
cups.UI_SPINNER, current, (1, 99), 1, job_option=True)
347
self.job_options['copies'] = current
349
# page range RADIO + RANGE (custom)
350
current = current_options.get('pagerange', '')
352
self.addControlRow("pagerange", self.__tr("Page Range"),
353
cups.UI_PAGE_RANGE, current, None, None, job_option=True)
355
self.job_options['pagerange'] = current
357
# page set (COMBO/PICKONE)
358
current = current_options.get('pageset', 'all')
359
self.addControlRow("pageset", self.__tr("Page Set"),
360
cups.PPD_UI_PICKONE, current,
361
[('all', self.__tr("AllPages")),
362
('even', self.__tr("Even")),
363
('odd', self.__tr("Odd"))], 'all', job_option=True)
365
self.job_options['pageset'] = current
366
# if current == u'even':
367
# self.job_options["pageset"] = PAGE_SET_EVEN
368
# elif current == u'odd':
369
# self.job_options["pageset"] = PAGE_SET_ODD
371
# self.job_options["pageset"] = PAGE_SET_ALL
373
self.endControlGroup() # job_options
375
if not self.cur_device.device_type == DEVICE_TYPE_FAX:
376
self.beginControlGroup("basic", self.__tr("Basic"))
379
# PageSize (in PPD section)
380
# orientation-requested
385
current = current_options.get('orientation-requested', '3')
387
self.addControlRow("orientation-requested", self.__tr("Page Orientation"),
388
cups.PPD_UI_PICKONE, current,
389
[('3', self.__tr('Portrait')),
390
('4', self.__tr('Landscape')),
391
('5', self.__tr('Reverse landscape')),
392
('6', self.__tr('Reverse portrait'))], '3')
394
log.debug("Option: orientation-requested")
395
log.debug("Current value: %s" % current)
397
duplexer = self.cur_device.dq.get('duplexer', 0)
398
log.debug("Duplexer = %d" % duplexer)
401
current = current_options.get('sides', 'one-sided')
402
self.addControlRow("sides",
403
self.__tr("Duplex (Print on both sides of the page)"),
404
cups.PPD_UI_PICKONE, current,
405
[('one-sided',self.__tr('Single sided')),
406
('two-sided-long-edge', self.__tr('Two sided (long edge)')),
407
('two-sided-short-edge', self.__tr('Two sided (short edge)'))], 'one-sided')
409
log.debug("Option: sides")
410
log.debug("Current value: %s" % current)
412
current = current_options.get('outputorder', 'normal')
414
self.addControlRow("outputorder",
415
self.__tr("Output Order"),
416
cups.PPD_UI_PICKONE, current,
417
[('normal', self.__tr('Normal (Print first page first)')),
418
('reverse', self.__tr('Reversed (Print last page first)'))], 'normal')
420
log.debug("Option: outputorder")
421
log.debug("Current value: %s" % current)
423
#If collate section is not in the PPD, only then add a collate section.
424
to_add = cups.duplicateSection("collate")
426
current = utils.to_bool(current_options.get('Collate', '0'))
428
self.addControlRow("Collate",
429
self.__tr("Collate (Group together multiple copies)"),
430
cups.PPD_UI_BOOLEAN, current,
433
log.debug("Option: Collate")
434
log.debug("Current value: %s" % current)
436
self.endControlGroup()
438
groups = cups.getGroupList()
443
if 'jobretention' in g.lower():
444
log.debug("HPJobRetention skipped.")
448
text, num_subgroups = cups.getGroup(g)
450
log.warn("Group %s returned None" % g)
453
read_only = 'install' in g.lower()
456
if g.lower() == 'printoutmode':
457
text = self.__tr("Quality (also see 'Printout Mode' under 'General')")
459
self.beginControlGroup(g, str(text))
461
log.debug(" Text: %s" % str(text))
462
log.debug("Num subgroups: %d" % num_subgroups)
464
options = cups.getOptionList(g)
469
log.debug(" Option: %s" % repr(o))
471
if 'pageregion' in o.lower():
472
log.debug("Page Region skipped.")
476
option_text, defchoice, conflicted, ui = cups.getOption(g, o)
478
log.warn("Option %s in group %s returned None" % (o, g))
482
if o.lower() == 'quality':
483
option_text = self.__tr("Quality")
485
log.debug(" Text: %s" % repr(option_text))
486
log.debug(" Defchoice: %s" % repr(defchoice))
488
choices = cups.getChoiceList(g, o)
493
log.debug(" Choice: %s" % repr(c))
495
# TODO: Add custom paper size controls
496
if 'pagesize' in o.lower() and 'custom' in c.lower():
497
log.debug("Skipped.")
500
choice_text, marked = cups.getChoice(g, o, c)
503
log.debug(" Text: %s" % repr(choice_text))
508
choice_data.append((c, choice_text))
510
if o.lower() == 'outputmode':
511
if value is not None:
512
cur_outputmode = value
514
cur_outputmode = defchoice
516
self.addControlRow(o, option_text, ui, value, choice_data, defchoice, read_only)
518
self.endControlGroup()
520
## if 'pagesize' in o.lower(): # and 'custom' in c.lower():
522
## width_widget = self.addControlRow(widget, "custom", "custom-width", self.__tr("Custom Paper Width"), cups.UI_UNITS_SPINNER,
523
## current, (0.0, 0.0), 0.0)
526
## height_widget = self.addControlRow("custom", "custom-height", self.__tr("Custom Paper Height"), cups.UI_UNITS_SPINNER,
527
## current, (0.0, 0.0), 0.0)
529
## if value.lower() == 'custom':
537
self.beginControlGroup("nup", self.__tr("N-Up (Multiple document pages per printed page)"))
538
current = current_options.get('number-up', '1')
540
self.addControlRow("number-up", self.__tr("Pages per Sheet"),
541
cups.PPD_UI_PICKONE, current,
542
[('1', self.__tr('1 page per sheet')),
543
('2', self.__tr('2 pages per sheet')),
544
('4', self.__tr('4 pages per sheet'))], '1')
546
log.debug(" Option: number-up")
547
log.debug(" Current value: %s" % current)
549
current = current_options.get('number-up-layout', 'lrtb')
551
self.addControlRow("number-up-layout", self.__tr("Layout"),
552
cups.PPD_UI_PICKONE, current,
553
[('btlr', self.__tr('Bottom to top, left to right')),
554
('btrl', self.__tr('Bottom to top, right to left')),
555
('lrbt', self.__tr('Left to right, bottom to top')),
556
('lrtb', self.__tr('Left to right, top to bottom')),
557
('rlbt', self.__tr('Right to left, bottom to top')),
558
('rltb', self.__tr('Right to left, top to bottom')),
559
('tblr', self.__tr('Top to bottom, left to right')),
560
('tbrl', self.__tr('Top to bottom, right to left')) ], 'lrtb')
562
log.debug(" Option: number-up-layout")
563
log.debug(" Current value: %s" % current)
565
current = current_options.get('page-border', 'none')
567
self.addControlRow("page-border",
568
self.__tr("Printed Border Around Each Page"),
569
cups.PPD_UI_PICKONE, current,
570
[('double', self.__tr("Two thin borders")),
571
("double-thick", self.__tr("Two thick borders")),
572
("none", self.__tr("No border")),
573
("single", self.__tr("One thin border")),
574
("single-thick", self.__tr("One thick border"))], 'none')
576
log.debug(" Option: page-border")
577
log.debug(" Current value: %s" % current)
579
self.endControlGroup()
585
if not self.cur_device.device_type == DEVICE_TYPE_FAX:
586
self.beginControlGroup("adjustment", self.__tr("Printout Appearance"))
588
current = int(current_options.get('brightness', 100))
590
log.debug(" Option: brightness")
591
log.debug(" Current value: %s" % current)
593
self.addControlRow("brightness", self.__tr("Brightness"),
594
cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
596
current = int(current_options.get('gamma', 1000))
598
log.debug(" Option: gamma")
599
log.debug(" Current value: %s" % current)
601
self.addControlRow("gamma", self.__tr("Gamma"), cups.UI_SPINNER, current,
604
self.endControlGroup()
613
## # TODO: cupsPPDPageSize() fails on LaserJets. How do we get margins in this case? Defaults?
614
## # PPD file for LJs has a HWMargin entry...
615
## page, page_width, page_len, left, bottom, right, top = cups.getPPDPageSize()
617
## right = page_width - right
618
## top = page_len - top
620
## self.addGroupHeading("margins", self.__tr("Margins"))
621
## current_top = current_options.get('page-top', 0) # pts
622
## current_bottom = current_options.get('page-bottom', 0) # pts
623
## current_left = current_options.get('page-left', 0) # pts
624
## current_right = current_options.get('page-right', 0) # pts
626
## log.debug(" Option: page-top")
627
## log.debug(" Current value: %s" % current_top)
629
## self.addControlRow("margins", "page-top", self.__tr("Top margin"),
630
## cups.UI_UNITS_SPINNER, current_top,
631
## (0, page_len), top)
633
## self.addControlRow("margins", "page-bottom", self.__tr("Bottom margin"),
634
## cups.UI_UNITS_SPINNER, current_bottom,
635
## (0, page_len), bottom)
637
## self.addControlRow("margins", "page-left", self.__tr("Right margin"),
638
## cups.UI_UNITS_SPINNER, current_left,
639
## (0, page_width), left)
641
## self.addControlRow("margins", "page-right", self.__tr("Left margin"),
642
## cups.UI_UNITS_SPINNER, current_right,
643
## (0, page_width), right)
651
self.beginControlGroup("image", self.__tr("Image Printing"))
653
current = utils.to_bool(current_options.get('fitplot', 'false'))
655
self.addControlRow("fitplot",
656
self.__tr("Fit to Page"),
657
cups.PPD_UI_BOOLEAN, current,
660
current = current_options.get('position', 'center')
662
self.addControlRow("position", self.__tr("Position on Page"),
663
cups.PPD_UI_PICKONE, current,
664
[('center', self.__tr('Centered')),
665
('top', self.__tr('Top')),
666
('left', self.__tr('Left')),
667
('right', self.__tr('Right')),
668
('top-left', self.__tr('Top left')),
669
('top-right', self.__tr('Top right')),
670
('bottom', self.__tr('Bottom')),
671
('bottom-left', self.__tr('Bottom left')),
672
('bottom-right', self.__tr('Bottom right'))], 'center')
674
log.debug(" Option: position")
675
log.debug(" Current value: %s" % current)
677
if not self.cur_device.device_type == DEVICE_TYPE_FAX:
678
current = int(current_options.get('saturation', 100))
680
log.debug(" Option: saturation")
681
log.debug(" Current value: %s" % current)
683
self.addControlRow("saturation", self.__tr("Saturation"),
684
cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
686
current = int(current_options.get('hue', 0))
688
log.debug(" Option: hue")
689
log.debug(" Current value: %s" % current)
691
self.addControlRow("hue", self.__tr("Hue (color shift/rotation)"),
692
cups.UI_SPINNER, current,
695
current = int(current_options.get('natural-scaling', 100))
697
log.debug(" Option: natural-scaling")
698
log.debug(" Current value: %s" % current)
700
self.addControlRow("natural-scaling",
701
self.__tr('"Natural" Scaling (relative to image)'),
702
cups.UI_SPINNER, current, (1, 800), 100, suffix=" %")
704
current = int(current_options.get('scaling', 100))
706
log.debug(" Option: scaling")
707
log.debug(" Current value: %s" % current)
709
self.addControlRow("scaling", self.__tr("Scaling (relative to page)"),
710
cups.UI_SPINNER, current,
711
(1, 800), 100, suffix=" %")
713
self.endControlGroup()
720
self.beginControlGroup("misc", self.__tr("Miscellaneous"))
722
log.debug("Group: Misc")
724
current = utils.to_bool(current_options.get('prettyprint', '0'))
726
self.addControlRow("prettyprint",
727
self.__tr('"Pretty Print" Text Documents (Add headers and formatting)'),
728
cups.PPD_UI_BOOLEAN, current, [], 0)
730
log.debug(" Option: prettyprint")
731
log.debug(" Current value: %s" % current)
733
if not self.cur_device.device_type == DEVICE_TYPE_FAX:
734
current = current_options.get('job-sheets', 'none').split(',')
746
# TODO: Look for locally installed banner pages beyond the default CUPS ones?
747
self.addControlRow("job-sheets", self.__tr("Banner Pages"), cups.UI_BANNER_JOB_SHEETS,
749
[("none", self.__tr("No banner page")),
750
('classified', self.__tr("Classified")),
751
('confidential', self.__tr("Confidential")),
752
('secret', self.__tr("Secret")),
753
('standard', self.__tr("Standard")),
754
('topsecret', self.__tr("Top secret")),
755
('unclassified', self.__tr("Unclassified"))], ('none', 'none'))
757
log.debug(" Option: job-sheets")
758
log.debug(" Current value: %s,%s" % (start, end))
760
current = utils.to_bool(current_options.get('mirror', '0'))
762
self.addControlRow("mirror", self.__tr('Mirror Printing'),
763
cups.PPD_UI_BOOLEAN, current, [], 0)
765
log.debug(" Option: mirror")
766
log.debug(" Current value: %s" % current)
768
self.endControlGroup()
773
quality_attr_name = "OutputModeDPI"
774
cur_outputmode_dpi = cups.findPPDAttribute(quality_attr_name, cur_outputmode)
775
if cur_outputmode_dpi is not None:
776
log.debug("Adding Group: Summary outputmode is : %s" % cur_outputmode)
777
log.debug("Adding Group: Summary outputmode dpi is : %s" % to_unicode (cur_outputmode_dpi))
778
self.beginControlGroup("sumry", self.__tr("Summary"))
779
self.addControlRow("colorinput", self.__tr('Color Input / Black Render'),
780
cups.UI_INFO, to_unicode (cur_outputmode_dpi), [], read_only)
781
self.addControlRow("quality", self.__tr('Print Quality'),
782
cups.UI_INFO, cur_outputmode, [], read_only)
783
self.endControlGroup()
784
log.debug("End adding Group: Summary")
787
self.job_storage_enable = 0 #self.cur_device.mq.get('job-storage', JOB_STORAGE_DISABLE) == JOB_STORAGE_ENABLE
790
if self.job_storage_enable:
791
self.job_storage_pin = to_unicode(current_options.get('HOLDKEY', '0000')[:4])
792
self.job_storage_username = to_unicode(current_options.get('USERNAME', prop.username)[:16])
793
self.job_storage_jobname = to_unicode(current_options.get('JOBNAME', to_unicode('Untitled'))[:16])
794
hold = to_unicode(current_options.get('HOLD', to_unicode('OFF')))
795
holdtype = to_unicode(current_options.get('HOLDTYPE', to_unicode('PUBLIC')))
796
self.job_storage_use_pin = False
797
duplicate = to_unicode(current_options.get('DUPLICATEJOB', to_unicode('REPLACE')))
798
self.job_storage_auto_username = True
799
self.job_storage_auto_jobname = True
800
self.job_storage_mode = JOB_STORAGE_TYPE_OFF
803
self.job_storage_mode = JOB_STORAGE_TYPE_OFF
806
if holdtype == to_unicode('PUBLIC'):
807
self.job_storage_mode = JOB_STORAGE_TYPE_QUICK_COPY
810
self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
811
self.job_storage_use_pin = True
813
elif hold == to_unicode('PROOF'):
814
if holdtype == to_unicode('PUBLIC'):
815
self.job_storage_mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD
817
self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
818
self.job_storage_use_pin = True
820
elif hold == to_unicode('STORE'):
821
self.job_storage_mode = JOB_STORAGE_TYPE_STORE
822
self.job_storage_use_pin = (holdtype == 'PRIVATE')
824
if duplicate == to_unicode('REPLACE'):
825
self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_REPLACE
827
self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_APPEND_1_99
829
# option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False)
831
self.beginControlGroup("jobstorage", self.__tr("Job Storage and Secure Printing"))
833
self.addControlRow("job-storage-mode", self.__tr("Mode"),
834
cups.UI_JOB_STORAGE_MODE, None, None, None)
836
self.addControlRow("job-storage-pin", self.__tr("Make job private (use PIN to print)"),
837
cups.UI_JOB_STORAGE_PIN, None, None, None )
839
self.addControlRow("job-storage-username", self.__tr("User name (for job identification)"),
840
cups.UI_JOB_STORAGE_USERNAME, None, None, None)
842
self.addControlRow("job-storage-id", self.__tr("Job name/ID (for job identification)"),
843
cups.UI_JOB_STORAGE_ID, None, None, None)
845
self.addControlRow("job-storage-id-exists", self.__tr("If job name/ID already exists..."),
846
cups.UI_JOB_STORAGE_ID_EXISTS, None, None, None)
848
self.endControlGroup()
849
self.updateJobStorageControls()
851
# use: self.job_options['xxx'] so that values can be picked up by getPrintCommand(
854
#except Exception, e:
863
def beginControlGroup(self, group, text):
864
log.debug("BeginGroup: %s" % group)
866
self.widget = QWidget()
867
self.gridlayout = QGridLayout(self.widget)
872
def endControlGroup(self):
873
log.debug("EndGroup: %s" % self.group)
874
spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
876
self.gridlayout.addItem(spacer, self.row, 0, 1, 1)
877
i = self.addItem(self.widget, self.text)
880
self.setItemIcon(i, self.plus_icon)
882
self.setItemIcon(i, self.minus_icon)
884
self.widget, self.gridlayout = None, None
887
def addControlRow(self, option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False):
889
if typ == cups.PPD_UI_BOOLEAN: # () On (*) Off widget
890
HBoxLayout = QHBoxLayout()
891
HBoxLayout.setObjectName("HBoxLayout")
893
OptionLabel = QLabel(self.widget)
894
OptionLabel.setObjectName("OptionLabel")
895
HBoxLayout.addWidget(OptionLabel)
897
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
898
HBoxLayout.addItem(SpacerItem)
900
GroupBox = QFrame(self.widget)
902
gridlayout1 = QGridLayout(GroupBox)
903
OnRadioButton = OptionRadioButton(GroupBox, "OnRadioButton", self.group,
904
option, default, job_option)
905
gridlayout1.addWidget(OnRadioButton,0,0,1,1)
906
OffRadioButton = OptionRadioButton(GroupBox, "OffRadioButton", self.group,
907
option, default, job_option)
908
gridlayout1.addWidget(OffRadioButton,0,1,1,1)
909
HBoxLayout.addWidget(GroupBox)
911
DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
912
choices, default, (OnRadioButton, OffRadioButton), typ, job_option)
914
#GroupBox.setDefaultPushbutton(DefaultButton)
915
OnRadioButton.setDefaultPushbutton(DefaultButton)
916
OffRadioButton.setDefaultPushbutton(DefaultButton)
918
HBoxLayout.addWidget(DefaultButton)
919
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
921
OptionLabel.setText(text)
922
OnRadioButton.setText(self.__tr("On"))
923
OffRadioButton.setText(self.__tr("Off"))
925
DefaultButton.setText("Default")
927
#type of 'value' and 'default' can be unicode (ppd values), str, int or boolean, so we need to typecast it to bool for easy comparison
928
if value == True or value == 'True' or value == 'true':
933
if default == True or default == 'True' or default == 'true':
939
DefaultButton.setEnabled(False)
940
DefaultButton.clicked.connect(self.DefaultButton_clicked)
943
OnRadioButton.setChecked(True)
945
OffRadioButton.setChecked(True)
946
OnRadioButton.toggled[bool].connect(self.BoolRadioButtons_clicked)
949
OnRadioButton.setEnabled(False)
950
OffRadioButton.setEnabled(False)
951
DefaultButton.setEnabled(False)
955
elif typ == cups.PPD_UI_PICKONE: # Combo box widget
956
#print option, job_option
957
HBoxLayout = QHBoxLayout()
958
HBoxLayout.setObjectName("HBoxLayout")
960
OptionLabel = QLabel(self.widget)
961
OptionLabel.setObjectName("OptionLabel")
962
HBoxLayout.addWidget(OptionLabel)
964
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
965
HBoxLayout.addItem(SpacerItem)
967
ComboBox = OptionComboBox(0, self.widget, "ComboBox", self.group, option,
968
choices, default, typ, None, job_option)
970
HBoxLayout.addWidget(ComboBox)
972
DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option,
973
choices, default, ComboBox, typ, job_option)
975
ComboBox.setDefaultPushbutton(DefaultButton)
976
HBoxLayout.addWidget(DefaultButton)
978
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
980
OptionLabel.setText(text)
981
DefaultButton.setText("Default")
983
i, x, y = 0, None, None
986
if value is not None and d == value.lower():
989
if d == default.lower():
992
ComboBox.insertItem(i, t)
996
ComboBox.setCurrentIndex(x)
998
ComboBox.setCurrentIndex(0)
1000
if value is not None and value.lower() == default.lower():
1001
DefaultButton.setEnabled(False)
1003
#self.linkPrintoutModeAndQuality(option, value)
1006
# optionComboBox.setEnabled(False)
1007
# defaultPushButton.setEnabled(False)
1008
# elif y is not None:
1009
# QToolTip.add(defaultPushButton, self.__tr('Set to default value of "%1".').arg(y))
1012
DefaultButton.clicked.connect(self.DefaultButton_clicked)
1013
ComboBox.currentIndexChanged["const QString &"].connect(self.ComboBox_indexChanged)
1014
ComboBox.highlighted["const QString &"].connect(self.ComboBox_highlighted)
1018
elif typ == cups.UI_SPINNER: # Spinner widget
1020
HBoxLayout = QHBoxLayout()
1021
HBoxLayout.setObjectName("HBoxLayout")
1023
OptionLabel = QLabel(self.widget)
1024
OptionLabel.setObjectName("OptionLabel")
1025
HBoxLayout.addWidget(OptionLabel)
1027
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1028
HBoxLayout.addItem(SpacerItem)
1030
SpinBox = OptionSpinBox(self.widget,"SpinBox", self.group, option, default, job_option)
1031
HBoxLayout.addWidget(SpinBox)
1033
DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
1034
choices, default, SpinBox, typ, job_option)
1036
SpinBox.setDefaultPushbutton(DefaultButton)
1037
HBoxLayout.addWidget(DefaultButton)
1039
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1042
SpinBox.setMinimum(min)
1043
SpinBox.setMaximum(max)
1044
SpinBox.setValue(value)
1047
SpinBox.setSuffix(suffix)
1049
OptionLabel.setText(text)
1050
DefaultButton.setText("Default")
1052
SpinBox.valueChanged[int].connect(self.SpinBox_valueChanged)
1053
DefaultButton.clicked.connect(self.DefaultButton_clicked)
1055
DefaultButton.setEnabled(not value == default)
1058
SpinBox.setEnabled(False)
1059
DefaultButton.setEnabled(False)
1061
elif typ == cups.UI_BANNER_JOB_SHEETS: # Job sheets widget
1062
HBoxLayout = QHBoxLayout()
1063
HBoxLayout.setObjectName("HBoxLayout")
1065
OptionLabel = QLabel(self.widget)
1066
OptionLabel.setObjectName("OptionLabel")
1067
HBoxLayout.addWidget(OptionLabel)
1069
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1070
HBoxLayout.addItem(SpacerItem)
1072
StartLabel = QLabel(self.widget)
1073
HBoxLayout.addWidget(StartLabel)
1075
StartComboBox = OptionComboBox(0, self.widget, "StartComboBox", self.group,
1076
"start", choices, default, typ)
1078
HBoxLayout.addWidget(StartComboBox)
1080
EndLabel = QLabel(self.widget)
1081
HBoxLayout.addWidget(EndLabel)
1083
EndComboBox = OptionComboBox(0, self.widget, "EndComboBox", self.group, "end", choices,
1084
default, typ, StartComboBox)
1086
HBoxLayout.addWidget(EndComboBox)
1088
StartComboBox.setOther(EndComboBox)
1090
DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option, choices,
1091
default, (StartComboBox, EndComboBox), typ, job_option)
1093
HBoxLayout.addWidget(DefaultButton)
1095
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1097
StartComboBox.setDefaultPushbutton(DefaultButton)
1098
EndComboBox.setDefaultPushbutton(DefaultButton)
1100
OptionLabel.setText(text)
1101
DefaultButton.setText("Default")
1103
StartLabel.setText(self.__tr("Start:"))
1104
EndLabel.setText(self.__tr("End:"))
1106
s, e, y, z = None, None, None, None
1107
for c, t in choices:
1109
if value is not None:
1110
if d == value[0].lower():
1113
if d == value[1].lower():
1116
if d == default[0].lower():
1119
if d == default[1].lower():
1122
StartComboBox.insertItem(0, t)
1123
EndComboBox.insertItem(0, t)
1126
StartComboBox.setCurrentIndex(StartComboBox.findText(s))
1129
EndComboBox.setCurrentIndex(EndComboBox.findText(e))
1131
if value is not None and \
1132
value[0].lower() == default[0].lower() and \
1133
value[1].lower() == default[1].lower():
1135
DefaultButton.setEnabled(False)
1137
StartComboBox.activated["const QString&"].connect(self.BannerComboBox_activated)
1138
EndComboBox.activated["const QString&"].connect(self.BannerComboBox_activated)
1139
DefaultButton.clicked.connect(self.DefaultButton_clicked)
1141
elif typ == cups.PPD_UI_PICKMANY:
1142
log.error("Unrecognized type: pickmany")
1144
elif typ == cups.UI_UNITS_SPINNER:
1145
log.error("Unrecognized type: units spinner")
1147
elif typ == cups.UI_PAGE_RANGE:
1148
HBoxLayout = QHBoxLayout()
1149
HBoxLayout.setObjectName("HBoxLayout")
1151
OptionLabel = QLabel(self.widget)
1152
OptionLabel.setObjectName("OptionLabel")
1153
HBoxLayout.addWidget(OptionLabel)
1155
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1156
HBoxLayout.addItem(SpacerItem)
1158
GroupBox = QFrame(self.widget)
1160
gridlayout1 = QGridLayout(GroupBox)
1162
AllRadioButton = PageRangeRadioButton(GroupBox, "AllRadioButton",
1163
self.group, option, default)
1165
gridlayout1.addWidget(AllRadioButton,0,0,1,1)
1166
RangeRadioButton = PageRangeRadioButton(GroupBox, "RangeRadioButton",
1167
self.group, option, default)
1169
gridlayout1.addWidget(RangeRadioButton,0,1,1,1)
1170
HBoxLayout.addWidget(GroupBox)
1172
PageRangeEdit = QLineEdit(self.widget)
1173
HBoxLayout.addWidget(PageRangeEdit)
1174
PageRangeEdit.setValidator(RangeValidator(PageRangeEdit))
1176
AllRadioButton.setRangeEdit(PageRangeEdit)
1177
RangeRadioButton.setRangeEdit(PageRangeEdit)
1179
DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
1180
choices, default, (AllRadioButton, RangeRadioButton, PageRangeEdit), typ, job_option)
1182
AllRadioButton.setDefaultPushbutton(DefaultButton)
1183
RangeRadioButton.setDefaultPushbutton(DefaultButton)
1185
HBoxLayout.addWidget(DefaultButton)
1186
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1188
OptionLabel.setText(text)
1189
AllRadioButton.setText(self.__tr("All pages"))
1190
RangeRadioButton.setText(self.__tr("Page Range:"))
1192
DefaultButton.setText("Default")
1193
DefaultButton.setEnabled(False)
1195
AllRadioButton.setChecked(True)
1196
PageRangeEdit.setEnabled(False)
1200
AllRadioButton.toggled[bool].connect(self.PageRangeAllRadio_toggled)
1201
RangeRadioButton.toggled[bool].connect(self.PageRangeRangeRadio_toggled)
1202
DefaultButton.clicked.connect(self.DefaultButton_clicked)
1203
PageRangeEdit.textChanged["const QString &"].connect(self.PageRangeEdit_textChanged)
1204
PageRangeEdit.editingFinished.connect(self.PageRangeEdit_editingFinished)
1206
elif typ == cups.UI_JOB_STORAGE_MODE:
1207
HBoxLayout = QHBoxLayout()
1208
HBoxLayout.setObjectName("HBoxLayout")
1210
OptionLabel = QLabel(self.widget)
1211
OptionLabel.setObjectName("OptionLabel")
1212
HBoxLayout.addWidget(OptionLabel)
1214
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1215
HBoxLayout.addItem(SpacerItem)
1217
self.JobStorageModeComboBox = QComboBox(self.widget)
1218
HBoxLayout.addWidget(self.JobStorageModeComboBox)
1220
self.JobStorageModeDefaultButton = QPushButton(self.widget)
1221
HBoxLayout.addWidget(self.JobStorageModeDefaultButton)
1223
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1225
OptionLabel.setText(text)
1226
self.JobStorageModeDefaultButton.setText(self.__tr("Default"))
1228
self.JobStorageModeComboBox.addItem(self.__tr("Off/Disabled"), JOB_STORAGE_TYPE_OFF)
1229
self.JobStorageModeComboBox.addItem(self.__tr("Proof and Hold"), JOB_STORAGE_TYPE_PROOF_AND_HOLD)
1230
self.JobStorageModeComboBox.addItem(self.__tr("Personal/Private Job"), JOB_STORAGE_TYPE_PERSONAL)
1231
self.JobStorageModeComboBox.addItem(self.__tr("Quick Copy"), JOB_STORAGE_TYPE_QUICK_COPY)
1232
self.JobStorageModeComboBox.addItem(self.__tr("Stored Job"), JOB_STORAGE_TYPE_STORE)
1234
self.JobStorageModeComboBox.activated[int].connect( self.JobStorageModeComboBox_activated)
1236
self.JobStorageModeDefaultButton.clicked.connect( self.JobStorageModeDefaultButton_clicked)
1239
elif typ == cups.UI_JOB_STORAGE_PIN:
1240
HBoxLayout = QHBoxLayout()
1241
HBoxLayout.setObjectName("HBoxLayout")
1243
OptionLabel = QLabel(self.widget)
1244
OptionLabel.setObjectName("OptionLabel")
1245
HBoxLayout.addWidget(OptionLabel)
1247
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1248
HBoxLayout.addItem(SpacerItem)
1250
self.JobStoragePinGroupBox = QFrame(self.widget)
1252
gridlayout1 = QGridLayout(self.JobStoragePinGroupBox)
1253
self.JobStoragePinOffRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1254
gridlayout1.addWidget(self.JobStoragePinOffRadioButton, 0, 0, 1, 1)
1256
self.JobStoragePinPrivateRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1257
gridlayout1.addWidget(self.JobStoragePinPrivateRadioButton, 0, 1, 1, 1)
1259
self.JobStoragePinEdit = QLineEdit(self.JobStoragePinGroupBox)
1260
self.JobStoragePinEdit.setMaxLength(4)
1261
self.JobStoragePinEdit.setValidator(PinValidator(self.JobStoragePinEdit))
1262
gridlayout1.addWidget(self.JobStoragePinEdit, 0, 2, 1, 1)
1264
HBoxLayout.addWidget(self.JobStoragePinGroupBox)
1266
self.JobStoragePinDefaultButton = QPushButton(self.widget)
1267
HBoxLayout.addWidget(self.JobStoragePinDefaultButton)
1269
self.JobStoragePinOffRadioButton.setText(self.__tr("Public/Off"))
1270
self.JobStoragePinPrivateRadioButton.setText(self.__tr("Private/Use PIN:"))
1272
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1274
OptionLabel.setText(text)
1275
self.JobStoragePinDefaultButton.setText(self.__tr("Default"))
1277
self.JobStoragePinOffRadioButton.toggled[bool].connect( self.JobStoragePinOffRadioButton_toggled)
1279
self.JobStoragePinPrivateRadioButton.toggled[bool].connect( self.JobStoragePinPrivateRadioButton_toggled)
1281
self.JobStoragePinDefaultButton.clicked.connect( self.JobStoragePinDefaultButton_clicked)
1283
self.JobStoragePinEdit.textEdited["const QString &"].connect( self.JobStoragePinEdit_textEdited)
1286
elif typ == cups.UI_JOB_STORAGE_USERNAME:
1287
HBoxLayout = QHBoxLayout()
1288
HBoxLayout.setObjectName("HBoxLayout")
1290
OptionLabel = QLabel(self.widget)
1291
OptionLabel.setObjectName("OptionLabel")
1292
HBoxLayout.addWidget(OptionLabel)
1293
OptionLabel.setText(text)
1295
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1296
HBoxLayout.addItem(SpacerItem)
1298
self.JobStorageUsernameGroupBox = QFrame(self.widget)
1300
gridlayout1 = QGridLayout(self.JobStorageUsernameGroupBox)
1301
self.JobStorageUsernameAutoRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1302
gridlayout1.addWidget(self.JobStorageUsernameAutoRadioButton, 0, 0, 1, 1)
1304
self.JobStorageUsernameCustomRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1305
gridlayout1.addWidget(self.JobStorageUsernameCustomRadioButton, 0, 1, 1, 1)
1307
self.JobStorageUsernameEdit = QLineEdit(self.JobStorageUsernameGroupBox)
1308
self.JobStorageUsernameEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageUsernameEdit))
1309
self.JobStorageUsernameEdit.setMaxLength(16)
1310
gridlayout1.addWidget(self.JobStorageUsernameEdit, 0, 2, 1, 1)
1312
HBoxLayout.addWidget(self.JobStorageUsernameGroupBox)
1314
self.JobStorageUsernameDefaultButton = QPushButton(self.widget)
1315
HBoxLayout.addWidget(self.JobStorageUsernameDefaultButton)
1317
self.JobStorageUsernameAutoRadioButton.setText(self.__tr("Automatic"))
1318
self.JobStorageUsernameCustomRadioButton.setText(self.__tr("Custom:"))
1319
self.JobStorageUsernameDefaultButton.setText(self.__tr("Default"))
1321
self.JobStorageUsernameAutoRadioButton.toggled[bool].connect( self.JobStorageUsernameAutoRadioButton_toggled)
1323
self.JobStorageUsernameCustomRadioButton.toggled[bool].connect( self.JobStorageUsernameCustomRadioButton_toggled)
1325
self.JobStorageUsernameDefaultButton.clicked.connect( self.JobStorageUsernameDefaultButton_clicked)
1327
self.JobStorageUsernameEdit.textEdited["const QString &"].connect( self.JobStorageUsernameEdit_textEdited)
1329
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1331
elif typ == cups.UI_JOB_STORAGE_ID:
1332
HBoxLayout = QHBoxLayout()
1333
HBoxLayout.setObjectName("HBoxLayout")
1335
OptionLabel = QLabel(self.widget)
1336
OptionLabel.setObjectName("OptionLabel")
1337
HBoxLayout.addWidget(OptionLabel)
1338
OptionLabel.setText(text)
1340
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1341
HBoxLayout.addItem(SpacerItem)
1343
self.JobStorageIDGroupBox = QFrame(self.widget)
1345
gridlayout1 = QGridLayout(self.JobStorageIDGroupBox)
1346
self.JobStorageIDAutoRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1347
gridlayout1.addWidget(self.JobStorageIDAutoRadioButton, 0, 0, 1, 1)
1349
self.JobStorageIDCustomRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1350
gridlayout1.addWidget(self.JobStorageIDCustomRadioButton, 0, 1, 1, 1)
1352
self.JobStorageIDEdit = QLineEdit(self.JobStorageIDGroupBox)
1353
self.JobStorageIDEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageIDEdit))
1354
self.JobStorageIDEdit.setMaxLength(16)
1355
gridlayout1.addWidget(self.JobStorageIDEdit, 0, 2, 1, 1)
1357
HBoxLayout.addWidget(self.JobStorageIDGroupBox)
1359
self.JobStorageIDDefaultButton = QPushButton(self.widget)
1360
HBoxLayout.addWidget(self.JobStorageIDDefaultButton)
1362
self.JobStorageIDAutoRadioButton.setText(self.__tr("Automatic"))
1363
self.JobStorageIDCustomRadioButton.setText(self.__tr("Custom:"))
1364
self.JobStorageIDDefaultButton.setText(self.__tr("Default"))
1366
self.JobStorageIDAutoRadioButton.toggled[bool].connect( self.JobStorageIDAutoRadioButton_toggled)
1368
self.JobStorageIDCustomRadioButton.toggled[bool].connect( self.JobStorageIDCustomRadioButton_toggled)
1370
self.JobStorageIDDefaultButton.clicked.connect( self.JobStorageIDDefaultButton_clicked)
1372
self.JobStorageIDEdit.textEdited["const QString &"].connect( self.JobStorageIDEdit_textEdited)
1374
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1376
elif typ == cups.UI_JOB_STORAGE_ID_EXISTS:
1377
HBoxLayout = QHBoxLayout()
1378
HBoxLayout.setObjectName("HBoxLayout")
1380
OptionLabel = QLabel(self.widget)
1381
OptionLabel.setObjectName("OptionLabel")
1382
HBoxLayout.addWidget(OptionLabel)
1383
OptionLabel.setText(text)
1385
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1386
HBoxLayout.addItem(SpacerItem)
1388
self.JobStorageExistingComboBox = QComboBox(self.widget)
1389
HBoxLayout.addWidget(self.JobStorageExistingComboBox)
1391
self.JobStorageExistingDefaultButton = QPushButton(self.widget)
1392
HBoxLayout.addWidget(self.JobStorageExistingDefaultButton)
1394
self.JobStorageExistingComboBox.addItem(self.__tr("Replace existing job"),
1395
JOB_STORAGE_EXISTING_JOB_REPLACE)
1397
self.JobStorageExistingComboBox.addItem(self.__tr("Use job name appended with 1-99"),
1398
JOB_STORAGE_EXISTING_JOB_APPEND_1_99)
1400
self.JobStorageExistingDefaultButton.setText(self.__tr("Default"))
1402
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1404
self.JobStorageExistingComboBox.activated[int].connect( self.JobStorageExistingComboBox_activated)
1406
self.JobStorageExistingDefaultButton.clicked.connect( self.JobStorageExistingDefaultButton_clicked)
1408
elif typ == cups.UI_INFO:
1409
HBoxLayout = QHBoxLayout()
1410
HBoxLayout.setObjectName("HBoxLayout")
1412
OptionName = QLabel(self.widget)
1413
OptionName.setObjectName("OptionLabel")
1414
HBoxLayout.addWidget(OptionName)
1415
OptionName.setText(text)
1417
SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1418
HBoxLayout.addItem(SpacerItem)
1420
if text == 'Print Quality':
1421
self.PQValueLabel = QLabel(self.widget)
1422
self.PQValueLabel.setObjectName("PQValueLabel")
1423
HBoxLayout.addWidget(self.PQValueLabel)
1424
self.PQValueLabel.setText(value)
1425
elif text == 'Color Input / Black Render':
1426
self.PQColorInputLabel = QLabel(self.widget)
1427
self.PQColorInputLabel.setObjectName("PQColorInputLabel")
1428
HBoxLayout.addWidget(self.PQColorInputLabel)
1429
self.PQColorInputLabel.setText(value)
1431
OptionValue = QLabel(self.widget)
1432
OptionValue.setObjectName("OptionValue")
1433
HBoxLayout.addWidget(OptionValue)
1434
OptionValue.setText(value)
1436
self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1439
log.error("Invalid UI value: %s/%s" % (self.group, option))
1445
def BannerComboBox_activated(self, a): # cups.UI_BANNER_JOB_SHEETS
1447
sender = self.sender()
1450
start, end = None, None
1451
for c, t in sender.choices:
1456
for c, t in sender.other.choices:
1457
if t == sender.other.currentText():
1461
if sender.option == 'end':
1462
start, end = end, start
1464
if start is not None and \
1465
end is not None and \
1466
start.lower() == sender.default[0].lower() and \
1467
end.lower() == sender.default[1].lower():
1468
self.removePrinterOption('job-sheets')
1469
sender.pushbutton.setEnabled(False)
1471
sender.pushbutton.setEnabled(True)
1473
if start is not None and \
1476
self.setPrinterOption('job-sheets', ','.join([start, end]))
1479
def ComboBox_highlighted(self, t):
1481
sender = self.sender()
1484
#print sender, sender.option, sender.job_option
1487
for c, a in sender.choices:
1492
if choice is not None and choice == sender.default:
1493
if sender.job_option:
1494
self.job_options[sender.option] = sender.default
1496
self.removePrinterOption(sender.option)
1497
sender.pushbutton.setEnabled(False)
1500
sender.pushbutton.setEnabled(True)
1502
if choice is not None:
1503
if sender.job_option:
1504
self.job_options[sender.option] = choice
1506
self.setPrinterOption(sender.option, choice)
1508
#self.linkPrintoutModeAndQuality(sender.option, choice)
1512
# def linkPrintoutModeAndQuality(self, option, choice):
1513
# if option.lower() == 'quality' and \
1514
# choice is not None:
1517
# c = self.items['o:PrintoutMode'].control
1522
# if choice.lower() == 'fromprintoutmode':
1523
# # from printoutmode selected
1524
# # determine printoutmode option combo enable state
1525
# c.setEnabled(True)
1526
# QToolTip.remove(c)
1527
# a = unicode(c.currentText())
1529
# # determine printoutmode default button state
1530
# link_choice = None
1531
# for x, t in c.choices:
1536
# if link_choice is not None and \
1537
# link_choice.lower() == c.default.lower():
1539
# c.pushbutton.setEnabled(False)
1541
# c.pushbutton.setEnabled(True)
1543
# else: # fromprintoutmode not selected, disable printoutmode
1544
# c.setEnabled(False)
1545
# QToolTip.add(c, self.__tr("""Set Quality to "Controlled by 'Printout Mode'" to enable."""))
1546
# c.pushbutton.setEnabled(False)
1549
def SpinBox_valueChanged(self, i): # cups.UI_SPINNER
1550
sender = self.sender()
1552
if not sender.job_option:
1553
if i == sender.default:
1554
self.removePrinterOption(sender.option)
1555
sender.pushbutton.setEnabled(False)
1557
sender.pushbutton.setEnabled(True)
1558
self.setPrinterOption(sender.option, str(i))
1562
self.job_options[sender.option] = int(i)
1564
self.job_options[sender.option] = sender.default
1567
def BoolRadioButtons_clicked(self, b): # cups.PPD_UI_BOOLEAN
1568
sender = self.sender()
1570
if sender.default == True or sender.default == "True" or sender.default == "true":
1571
sender.default = int(True)
1573
sender.default = int(False)
1575
if b == sender.default:
1576
self.removePrinterOption(sender.option)
1577
sender.pushbutton.setEnabled(False)
1579
sender.pushbutton.setEnabled(True)
1582
self.setPrinterOption(sender.option, "true")
1584
self.setPrinterOption(sender.option, "false")
1586
def ComboBox_indexChanged(self, currentItem):
1587
sender = self.sender()
1588
currentItem = to_unicode(currentItem)
1589
# Checking for summary control
1590
labelPQValaue = getattr(self, 'PQValueLabel', None)
1591
labelPQColorInput = getattr(self, 'PQColorInputLabel', None)
1592
# When output mode combo item is changed, we need to update the summary information
1593
if currentItem is not None and sender.option == 'OutputMode' and labelPQValaue is not None and labelPQColorInput is not None:
1594
# Setting output mode
1595
self.PQValueLabel.setText(currentItem)
1597
# Getting DPI custom attributefrom the PPD
1598
# Setting color input
1599
quality_attr_name = "OutputModeDPI"
1600
cups.openPPD(self.cur_printer)
1601
outputmode_dpi = cups.findPPDAttribute(quality_attr_name, currentItem)
1602
log.debug("Outputmode changed, setting outputmode_dpi: %s" % outputmode_dpi)
1604
self.PQColorInputLabel.setText(outputmode_dpi)
1606
log.debug("Outputmode changed, setting value outputmode: %s" % currentItem)
1608
def DefaultButton_clicked(self):
1609
sender = self.sender()
1610
sender.setEnabled(False)
1612
if sender.typ == cups.PPD_UI_BOOLEAN: # () On (*) Off
1613
if sender.default == True or sender.default == 'True' or sender.default == 'true':
1614
sender.default = True
1616
sender.default = False
1618
sender.control[0].setChecked(True)
1619
sender.control[0].setFocus(Qt.OtherFocusReason)
1621
sender.control[1].setChecked(True)
1622
sender.control[1].setFocus(Qt.OtherFocusReason)
1624
if not sender.job_option:
1625
self.removePrinterOption(sender.option)
1627
elif sender.typ == cups.PPD_UI_PICKONE: # [ \/]
1628
choice, text = None, None
1630
for c, t in sender.choices:
1631
if c == sender.default:
1634
self.job_options[sender.option] = t
1637
if choice is not None:
1638
if not sender.job_option:
1639
self.removePrinterOption(sender.option)
1640
index = sender.control.findText(text)
1641
sender.control.setCurrentIndex(index)
1643
#self.linkPrintoutModeAndQuality(sender.option, choice) # TODO:
1644
sender.control.setFocus(Qt.OtherFocusReason)
1646
elif sender.typ == cups.UI_SPINNER: # [ x /\|\/]
1647
sender.control.setValue(sender.default)
1648
if not sender.job_option:
1649
self.removePrinterOption(sender.option)
1651
sender.control.setFocus(Qt.OtherFocusReason)
1653
elif sender.typ == cups.UI_BANNER_JOB_SHEETS: # start: [ \/] end: [ \/]
1654
start, end, start_text, end_text = None, None, None, None
1655
for c, t in sender.choices:
1656
if c == sender.default[0]:
1660
if c == sender.default[1]:
1664
if start is not None:
1665
index = sender.control[0].findText(start_text)
1666
sender.control[0].setCurrentIndex(index)
1669
index = sender.control[1].findText(end_text)
1670
sender.control[1].setCurrentIndex(index)
1672
if not sender.job_option:
1673
self.removePrinterOption('job-sheets')
1675
sender.control[0].setFocus(Qt.OtherFocusReason)
1677
elif sender.typ == cups.UI_PAGE_RANGE: # (*) All () Pages: [ ]
1678
sender.control[0].setChecked(True) # all radio button
1679
sender.control[0].setFocus(Qt.OtherFocusReason)
1680
sender.control[2].setEnabled(False) # range edit box
1683
def PageRangeAllRadio_toggled(self, b):
1685
sender = self.sender()
1686
sender.edit_control.setEnabled(False)
1687
sender.pushbutton.setEnabled(False)
1688
self.job_options['pagerange'] = ''
1691
def PageRangeRangeRadio_toggled(self, b):
1693
sender = self.sender()
1694
sender.pushbutton.setEnabled(True)
1695
sender.edit_control.setEnabled(True)
1696
self.job_options['pagerange'] = to_unicode(sender.edit_control.text())
1699
def PageRangeEdit_editingFinished(self):
1700
sender = self.sender()
1701
t, ok, x = self.job_options['pagerange'], True, []
1705
x = utils.expand_range(t)
1711
if y <= 0 or y > 999:
1716
self.job_options['pagerange'] = ''
1717
log.error("Invalid page range: %s" % t)
1718
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>"))
1719
sender.setFocus(Qt.OtherFocusReason)
1722
def PageRangeEdit_textChanged(self, t):
1723
self.job_options['pagerange'] = to_unicode(t) # Do range validation only in PageRangeEdit_editingFinished method
1729
def updateJobStorageControls(self):
1733
self.JobStorageModeComboBox.setCurrentIndex(self.JobStorageModeComboBox.findData(self.job_storage_mode))
1734
self.JobStorageModeDefaultButton.setEnabled(self.job_storage_mode != JOB_STORAGE_TYPE_OFF)
1737
self.JobStoragePinPrivateRadioButton.setChecked(self.job_storage_use_pin)
1740
self.JobStorageUsernameAutoRadioButton.setChecked(self.job_storage_auto_username)
1743
self.JobStorageIDAutoRadioButton.setChecked(self.job_storage_auto_jobname)
1746
self.JobStorageExistingComboBox.setCurrentIndex(self.JobStorageExistingComboBox.findData(self.job_storage_job_exist))
1748
if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
1750
self.JobStoragePinGroupBox.setEnabled(False)
1751
self.JobStoragePinEdit.setEnabled(False)
1752
self.JobStoragePinDefaultButton.setEnabled(False)
1753
self.JobStoragePinEdit.setText(str())
1756
self.JobStorageUsernameGroupBox.setEnabled(False)
1757
self.JobStorageUsernameEdit.setEnabled(False)
1758
self.JobStorageUsernameDefaultButton.setEnabled(False)
1761
self.JobStorageIDGroupBox.setEnabled(False)
1762
self.JobStorageIDEdit.setEnabled(False)
1763
self.JobStorageIDDefaultButton.setEnabled(False)
1765
# Duplicate/existing Jobname/ID
1766
self.JobStorageExistingComboBox.setEnabled(False)
1770
if self.job_storage_mode in (JOB_STORAGE_TYPE_PERSONAL, JOB_STORAGE_TYPE_STORE):
1771
self.JobStoragePinGroupBox.setEnabled(True)
1772
self.JobStoragePinDefaultButton.setEnabled(self.job_storage_use_pin)
1773
self.JobStoragePinEdit.setEnabled(self.job_storage_use_pin)
1774
self.JobStoragePinEdit.setText(str(self.job_storage_pin))
1776
self.JobStoragePinGroupBox.setEnabled(False)
1777
self.JobStoragePinEdit.setEnabled(False)
1778
self.JobStoragePinDefaultButton.setEnabled(False)
1779
self.JobStoragePinEdit.setText(str())
1782
self.JobStorageUsernameGroupBox.setEnabled(True)
1783
self.JobStorageUsernameEdit.setEnabled(not self.job_storage_auto_username)
1784
self.JobStorageUsernameDefaultButton.setEnabled(not self.job_storage_auto_username)
1785
self.JobStorageUsernameEdit.setText(str(self.job_storage_username))
1788
self.JobStorageIDGroupBox.setEnabled(True)
1789
self.JobStorageIDEdit.setEnabled(not self.job_storage_auto_jobname)
1790
self.JobStorageIDDefaultButton.setEnabled(not self.job_storage_auto_jobname)
1791
self.JobStorageIDEdit.setText(str(self.job_storage_jobname))
1793
# Duplicate/existing JobName/ID
1794
self.JobStorageExistingComboBox.setEnabled(not self.job_storage_auto_jobname)
1795
self.JobStorageExistingDefaultButton.setEnabled(not self.job_storage_auto_jobname and self.job_storage_job_exist != JOB_STORAGE_EXISTING_JOB_REPLACE)
1801
def saveJobStorageOptions(self):
1804
log.debug("Saving job storage options...")
1806
if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
1807
log.debug("Job storage mode = JOB_STORAGE_TYPE_OFF")
1808
self.setPrinterOption('HOLD', 'OFF')
1809
self.removePrinterOption('HOLDTYPE')
1810
self.removePrinterOption('USERNAME')
1811
self.removePrinterOption('JOBNAME')
1812
self.removePrinterOption('DUPLICATEJOB')
1814
elif self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
1815
log.debug("Job storage mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD")
1816
self.setPrinterOption('HOLD', 'PROOF')
1817
#self.removePrinterOption('HOLDTYPE')
1818
self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1820
elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
1821
log.debug("Job storage mode = JOB_STORAGE_TYPE_PERSONAL")
1823
if self.job_storage_use_pin:
1824
self.setPrinterOption('HOLD', 'ON')
1826
self.setPrinterOption('HOLD', 'PROOF')
1827
self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1830
elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
1831
log.debug("Job storage mode = JOB_STORAGE_TYPE_QUICK_COPY")
1832
self.setPrinterOption('HOLD', 'ON')
1833
self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1835
elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
1836
log.debug("Job storage mode = JOB_STORAGE_TYPE_STORE")
1837
self.setPrinterOption('HOLD', 'STORE')
1839
if not self.job_storage_use_pin:
1840
self.removePrinterOption('HOLDTYPE')
1843
log.debug("Job storage use pin = %d" % self.job_storage_use_pin)
1844
if self.job_storage_use_pin:
1845
self.setPrinterOption('HOLDTYPE', 'PRIVATE')
1848
# self.removePrinterOption('HOLDKEY')
1851
if self.job_storage_job_exist == JOB_STORAGE_EXISTING_JOB_REPLACE:
1852
log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_REPLACE")
1853
self.setPrinterOption('DUPLICATEJOB', 'REPLACE')
1855
else: # JOB_STORAGE_EXISTING_JOB_APPEND_1_99
1856
log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_APPEND_1_99")
1857
self.setPrinterOption('DUPLICATEJOB', 'APPEND')
1868
def JobStorageModeComboBox_activated(self, i):
1869
sender = self.sender()
1870
mode, ok = value_int(sender.itemData(i))
1872
self.job_storage_mode = mode
1873
self.saveJobStorageOptions()
1874
self.updateJobStorageControls()
1877
def JobStorageModeDefaultButton_clicked(self):
1878
self.JobStorageModeComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_TYPE_OFF)
1885
def JobStoragePinOffRadioButton_toggled(self, b):
1886
self.job_storage_use_pin = not b
1887
self.updateJobStorageControls()
1888
self.saveJobStorageOptions()
1891
def JobStoragePinPrivateRadioButton_toggled(self, b):
1892
self.job_storage_use_pin = b
1893
self.updateJobStorageControls()
1894
self.saveJobStorageOptions()
1897
def JobStoragePinDefaultButton_clicked(self):
1898
self.JobStoragePinOffRadioButton.emit(SIGNAL("toggled(bool)"), True)
1901
def JobStoragePinEdit_textEdited(self, s):
1902
self.job_storage_pin = to_unicode(s)
1903
self.setPrinterOption('HOLDKEY', self.job_storage_pin.encode('ascii'))
1911
def JobStorageUsernameAutoRadioButton_toggled(self, b):
1912
self.job_storage_auto_username = b
1913
self.updateJobStorageControls()
1914
self.saveJobStorageOptions()
1917
def JobStorageUsernameCustomRadioButton_toggled(self, b):
1918
self.job_storage_auto_username = not b
1919
self.updateJobStorageControls()
1920
self.saveJobStorageOptions()
1923
def JobStorageUsernameDefaultButton_clicked(self):
1924
self.JobStorageUsernameAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1927
def JobStorageUsernameEdit_textEdited(self, s):
1928
self.job_storage_username = to_unicode(s)
1929
self.setPrinterOption('USERNAME', self.job_storage_username.encode('ascii'))
1935
def JobStorageIDAutoRadioButton_toggled(self, b):
1936
self.job_storage_auto_jobname = b
1937
self.updateJobStorageControls()
1938
self.saveJobStorageOptions()
1941
def JobStorageIDCustomRadioButton_toggled(self, b):
1942
self.job_storage_auto_jobname = not b
1943
self.updateJobStorageControls()
1944
self.saveJobStorageOptions()
1947
def JobStorageIDDefaultButton_clicked(self):
1948
self.JobStorageIDAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1951
def JobStorageIDEdit_textEdited(self, s):
1952
self.job_storage_jobname = to_unicode(s)
1953
self.setPrinterOption('JOBNAME', self.job_storage_jobname.encode('ascii'))
1956
# Duplicate/existing Jobname/ID
1959
def JobStorageExistingComboBox_activated(self, i):
1960
sender = self.sender()
1961
opt, ok = value_int(sender.itemData(i))
1963
self.job_storage_job_exist = opt
1964
self.updateJobStorageControls()
1965
self.saveJobStorageOptions()
1968
def JobStorageExistingDefaultButton_clicked(self):
1969
self.JobStorageExistingComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_EXISTING_JOB_REPLACE)
1976
def setPrinterOption(self, option, value):
1977
log.debug("setPrinterOption(%s, %s)" % (option, value))
1978
cups.openPPD(self.cur_printer)
1981
cups.addOption("%s=%s" % (option, value))
1986
def removePrinterOption(self, option):
1987
log.debug("removePrinterOption(%s)" % option)
1988
cups.openPPD(self.cur_printer)
1991
cups.removeOption(option)
1997
def __tr(self,s,c = None):
1998
return qApp.translate("PrintSettingsToolbox",s,c)