Tizen 2.1 base
[platform/upstream/hplip.git] / ui4 / printsettingstoolbox.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2001-2008 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Authors: Don Welch, Yashwant Kumar Sahu, Sanjay Kumar Sharma
20 #
21
22 # Std Lib
23 import sys
24
25 # Local
26 from base.g import *
27 from base import utils
28 from prnt import cups
29 from base.codes import *
30 from ui_utils import *
31
32 # Qt
33 from PyQt4.QtCore import *
34 from PyQt4.QtGui import *
35
36
37
38 class RangeValidator(QValidator):
39     def __init__(self, parent=None, name=None):
40         QValidator.__init__(self, parent) #, name)
41
42
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
47
48         return QValidator.Acceptable, pos
49
50
51
52 class PinValidator(QValidator):
53     def __init__(self, parent=None, name=None):
54         QValidator.__init__(self, parent) #, name)
55
56
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
61
62         return QValidator.Acceptable, pos
63
64
65
66 class UsernameAndJobnameValidator(QValidator):
67     def __init__(self, parent=None, name=None):
68         QValidator.__init__(self, parent) #, name)
69
70
71     def validate(self, input, pos):
72         for x in unicode(input)[pos-1:]:
73             if x in u' /=,.:;\'"[]{}-+!@#$%^&*()':
74                 return QValidator.Invalid, pos
75
76         return QValidator.Acceptable, pos
77
78
79
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)
84         # rw?
85         self.group = group
86         self.option = option
87         self.choices = choices
88         self.default = default
89         self.typ = typ
90         self.other = other
91         self.job_option = job_option
92         self.setObjectName(name)
93
94
95     def setDefaultPushbutton(self, pushbutton):
96         self.pushbutton = pushbutton
97
98
99     def setOther(self, other):
100         self.other = other
101
102
103
104 class OptionSpinBox(QSpinBox):
105     def __init__(self,  parent, name, group, option, default, job_option=False):
106         QSpinBox.__init__(self, parent)
107         self.group = group
108         self.option = option
109         self.default = default
110         self.job_option = job_option
111         self.setObjectName(name)
112
113
114     def setDefaultPushbutton(self, pushbutton):
115         self.pushbutton = pushbutton
116
117
118
119 class OptionRadioButton(QRadioButton):
120     def __init__(self, parent, name, group, option, default, job_option=False):
121         QRadioButton.__init__(self, parent)
122         self.group = group
123         self.option = option
124         self.default = default
125         self.job_option = job_option
126         self.setObjectName(name)
127
128
129     def setDefaultPushbutton(self, pushbutton):
130         self.pushbutton = pushbutton
131
132
133
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)
138         self.group = group
139         self.option = option
140         self.default = default
141         self.control = control
142         self.typ = typ
143         self.choices = choices
144         self.job_option = job_option
145         self.setObjectName(name)
146
147
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
152
153
154 class PageRangeRadioButton(QRadioButton):
155     def __init__(self, parent, name, group, option, default): #, edit_control=None ):
156         QRadioButton.__init__(self, parent)
157         self.group = group
158         self.option = option
159         self.default = default
160         self.job_option = True
161         self.setObjectName(name)
162
163
164     def setRangeEdit(self, edit_control):
165         self.edit_control = edit_control
166
167
168     def setDefaultPushbutton(self, pushbutton):
169         self.pushbutton = pushbutton
170
171
172
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'))
179         self.last_item = 0
180         self.job_options = {}
181         self.job_storage_enable = False
182
183         self.connect(self, SIGNAL("currentChanged(int)"), self.PrintSettingsToolbox_currentChanged)
184
185
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:
189             return []
190
191         print_commands = []
192
193         try:
194             copies = int(self.job_options['copies'])
195         except ValueError:
196             copies = 1
197
198         if copies < 1:
199             copies = 1
200             log.warning("Copies < 1, setting to 1.")
201         elif copies > 99:
202             copies = 99
203             log.warning("Copies > 99, setting to 99.")
204
205         #page_range = unicode(self.pageRangeEdit.text())
206         page_range = self.job_options['pagerange']
207
208         try:
209             x = utils.expand_range(page_range)
210         except ValueError:
211             log.error("Invalid page range: %s" % page_range)
212             return []
213
214         all_pages = not page_range
215         #page_set = int(self.pageSetComboBox.currentItem())
216         page_set = self.job_options['pageset']
217
218         cups.resetOptions()
219         cups.openPPD(self.cur_printer)
220         current_options = dict(cups.getOptions())
221         cups.closePPD()
222
223         nup = int(current_options.get("number-up", 1))
224         psnup = utils.which('psnup')
225
226         for p, t, d, title, num_pages in file_list:
227             alt_nup = (nup > 1 and t == 'application/postscript' and psnup)
228
229             if utils.which('lpr'):
230                 if alt_nup:
231                     cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lpr -P', self.cur_printer])
232                 else:
233                     cmd = ' '.join(['lpr -P', self.cur_printer])
234
235                 if copies > 1:
236                     cmd = ' '.join([cmd, '-#%d' % copies])
237
238             else: # lp
239                 if alt_nup:
240                     cmd = ' '.join(['psnup', '-%d' % nup, ''.join(['"', p, '"']), '| lp -c -d', self.cur_printer])
241                 else:
242                     cmd = ' '.join(['lp -c -d', self.cur_printer])
243
244                 if copies > 1:
245                     cmd = ' '.join([cmd, '-n%d' % copies])
246
247
248             if not all_pages and page_range:
249                 cmd = ' '.join([cmd, '-o page-ranges=%s' % page_range])
250
251             if page_set:
252                 cmd = ' '.join([cmd, '-o page-set=%s' % page_set])
253
254             # Job Storage
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))
263
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'])
268
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')])
274                         else:
275                             cmd = ' '.join([cmd, '-o HOLD=PROOF'])
276                             cmd = ' '.join([cmd, '-o HOLDTYPE=PRIVATE'])
277
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'])
281
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')])
287                         else:
288                             cmd = ' '.join([cmd, '-o HOLD=STORE'])
289
290                     cmd = ' '.join([cmd, '-o USERNAME=%s' % self.job_storage_username.encode('ascii')\
291                         .replace(" ", "_")])
292
293                     cmd = ' '.join([cmd, '-o JOBNAME=%s' % self.job_storage_jobname.encode('ascii')\
294                         .replace(" ", "_")])
295
296                     if self.job_storage_job_exist == 1:
297                         cmd = ' '.join([cmd, '-o DUPLICATEJOB=APPEND'])
298                     else:
299                         cmd = ' '.join([cmd, '-o DUPLICATEJOB=REPLACE'])
300
301                 else: # Off
302                     cmd = ' '.join([cmd, '-o HOLD=OFF'])
303
304             if not alt_nup:
305                 cmd = ''.join([cmd, ' "', p, '"'])
306
307             print_commands.append(cmd)
308
309         return print_commands
310
311
312     def PrintSettingsToolbox_currentChanged(self, i):
313         if i != -1:
314             self.setItemIcon(self.last_item, self.plus_icon)
315             self.setItemIcon(i, self.minus_icon)
316             self.last_item = i
317
318
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
323         
324         while self.count():
325             self.removeItem(0)
326
327         self.loading = True
328         cups.resetOptions()
329         cups.openPPD(self.cur_printer)
330         cur_outputmode = ""
331
332         try:
333             if 1:
334             #try:
335                 current_options = dict(cups.getOptions())
336
337                 if self.include_job_options:
338                     self.beginControlGroup("job_options", self.__tr("Job Options"))
339
340                     # Num. copies (SPINNER)
341                     try:
342                         current = int(current_options.get('copies', '1'))
343                     except ValueError:
344                         current = 1
345
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
349
350                     # page range RADIO + RANGE (custom)
351                     current = current_options.get('pagerange', '')
352
353                     self.addControlRow("pagerange", self.__tr("Page Range"),
354                         cups.UI_PAGE_RANGE, current, None, None, job_option=True)
355
356                     self.job_options['pagerange'] = current
357
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)
365
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
371 #                    else:
372 #                        self.job_options["pageset"] = PAGE_SET_ALL
373
374                     self.endControlGroup() # job_options
375
376                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
377                     self.beginControlGroup("basic", self.__tr("Basic"))
378
379                     # Basic
380                         # PageSize (in PPD section)
381                         # orientation-requested
382                         # sides
383                         # outputorder
384                         # Collate
385
386                     current = current_options.get('orientation-requested', '3')
387
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')
394
395                     log.debug("Option: orientation-requested")
396                     log.debug("Current value: %s" % current)
397
398                     duplexer = self.cur_device.dq.get('duplexer', 0)
399                     log.debug("Duplexer = %d" % duplexer)
400
401                     if 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')
409
410                         log.debug("Option: sides")
411                         log.debug("Current value: %s" % current)
412
413                     current = current_options.get('outputorder', 'normal')
414
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')
420
421                     log.debug("Option: outputorder")
422                     log.debug("Current value: %s" % current)
423
424                     current = utils.to_bool(current_options.get('Collate', '0'))
425
426                     self.addControlRow("Collate",
427                         self.__tr("Collate (Group together multiple copies)"),
428                         cups.PPD_UI_BOOLEAN, current,
429                         [], 0)
430
431                     log.debug("Option: Collate")
432                     log.debug("Current value: %s" % current)
433
434                     self.endControlGroup()
435
436                 groups = cups.getGroupList()
437
438                 #print groups
439
440                 for g in groups:
441                     if 'jobretention' in g.lower():
442                         log.debug("HPJobRetention skipped.")
443                         continue
444
445                     try:
446                         text, num_subgroups = cups.getGroup(g)
447                     except TypeError:
448                         log.warn("Group %s returned None" % g)
449                         continue
450
451                     read_only = 'install' in g.lower()
452
453                     try:
454                         text = text.decode('utf-8')
455                     except UnicodeDecodeError:
456                         pass
457
458                     if g.lower() == 'printoutmode':
459                         text = self.__tr("Quality (also see 'Printout Mode' under 'General')")
460
461                     self.beginControlGroup(g, QString(text))
462
463                     log.debug("  Text: %s" % unicode(text))
464                     log.debug("Num subgroups: %d" % num_subgroups)
465
466                     options = cups.getOptionList(g)
467
468                     #print options
469
470                     for o in options:
471                         log.debug("  Option: %s" % repr(o))
472
473                         if 'pageregion' in o.lower():
474                             log.debug("Page Region skipped.")
475                             continue
476
477                         try:
478                             option_text, defchoice, conflicted, ui  = cups.getOption(g, o)
479                         except TypeError:
480                             log.warn("Option %s in group %s returned None" % (o, g))
481                             continue
482
483                         try:
484                             option_text = option_text.decode('utf-8')
485                         except UnicodeDecodeError:
486                             pass
487
488                         if o.lower() == 'quality':
489                             option_text = self.__tr("Quality")
490
491                         log.debug("    Text: %s" % repr(option_text))
492                         log.debug("    Defchoice: %s" % repr(defchoice))
493
494                         choices = cups.getChoiceList(g, o)
495
496                         value = None
497                         choice_data = []
498                         for c in choices:
499                             log.debug("    Choice: %s" % repr(c))
500
501                             # TODO: Add custom paper size controls
502                             if 'pagesize' in o.lower() and 'custom' in c.lower():
503                                 log.debug("Skipped.")
504                                 continue
505
506                             choice_text, marked = cups.getChoice(g, o, c)
507
508                             try:
509                                 choice_text = choice_text.decode('utf-8')
510                             except UnicodeDecodeError:
511                                 pass
512
513                             log.debug("      Text: %s" % repr(choice_text))
514
515                             if marked:
516                                 value = c
517
518                             choice_data.append((c, choice_text))
519
520                         if o.lower() == 'outputmode':
521                             if value is not None:
522                                 cur_outputmode = value
523                             else:
524                                 cur_outputmode = defchoice                                
525
526                         self.addControlRow(o, option_text, ui, value, choice_data, defchoice, read_only)
527
528                     self.endControlGroup()
529
530 ##                        if 'pagesize' in o.lower(): # and 'custom' in c.lower():
531 ##                            current = 0.0
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)
534 ##
535 ##                            current = 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)
538 ##
539 ##                            if value.lower() == 'custom':
540 ##                                pass
541
542                 # N-Up
543                     # number-up
544                     # number-up-layout
545                     # page-border
546
547                 self.beginControlGroup("nup", self.__tr("N-Up (Multiple document pages per printed page)"))
548                 current = current_options.get('number-up', '1')
549
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')
555
556                 log.debug("  Option: number-up")
557                 log.debug("  Current value: %s" % current)
558
559                 current = current_options.get('number-up-layout', 'lrtb')
560
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')
571
572                 log.debug("  Option: number-up-layout")
573                 log.debug("  Current value: %s" % current)
574
575                 current = current_options.get('page-border', 'none')
576
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')
585
586                 log.debug("  Option: page-border")
587                 log.debug("  Current value: %s" % current)
588
589                 self.endControlGroup()
590
591                 # Adjustment
592                     # brightness
593                     # gamma
594
595                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
596                     self.beginControlGroup("adjustment", self.__tr("Printout Appearance"))
597
598                     current = int(current_options.get('brightness', 100))
599
600                     log.debug("  Option: brightness")
601                     log.debug("  Current value: %s" % current)
602
603                     self.addControlRow("brightness", self.__tr("Brightness"),
604                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
605
606                     current = int(current_options.get('gamma', 1000))
607
608                     log.debug("  Option: gamma")
609                     log.debug("  Current value: %s" % current)
610
611                     self.addControlRow("gamma", self.__tr("Gamma"), cups.UI_SPINNER, current,
612                         (1, 10000), 1000)
613
614                     self.endControlGroup()
615
616                 # Margins (pts)
617                     # page-left
618                     # page-right
619                     # page-top
620                     # page-bottom
621
622 ##                if 0:
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()
626 ##
627 ##                    right = page_width - right
628 ##                    top = page_len - top
629 ##
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
635 ##
636 ##                    log.debug("  Option: page-top")
637 ##                    log.debug("  Current value: %s" % current_top)
638 ##
639 ##                    self.addControlRow("margins", "page-top", self.__tr("Top margin"),
640 ##                        cups.UI_UNITS_SPINNER, current_top,
641 ##                        (0, page_len), top)
642 ##
643 ##                    self.addControlRow("margins", "page-bottom", self.__tr("Bottom margin"),
644 ##                        cups.UI_UNITS_SPINNER, current_bottom,
645 ##                        (0, page_len), bottom)
646 ##
647 ##                    self.addControlRow("margins", "page-left", self.__tr("Right margin"),
648 ##                        cups.UI_UNITS_SPINNER, current_left,
649 ##                        (0, page_width), left)
650 ##
651 ##                    self.addControlRow("margins", "page-right", self.__tr("Left margin"),
652 ##                        cups.UI_UNITS_SPINNER, current_right,
653 ##                        (0, page_width), right)
654
655                 # Image Printing
656                     # position
657                     # natural-scaling
658                     # saturation
659                     # hue
660
661                 self.beginControlGroup("image", self.__tr("Image Printing"))
662
663                 current = utils.to_bool(current_options.get('fitplot', 'false'))
664
665                 self.addControlRow("fitplot",
666                     self.__tr("Fit to Page"),
667                     cups.PPD_UI_BOOLEAN, current,
668                     [], 0)
669
670                 current = current_options.get('position', 'center')
671
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')
683
684                 log.debug("  Option: position")
685                 log.debug("  Current value: %s" % current)
686
687                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
688                     current = int(current_options.get('saturation', 100))
689
690                     log.debug("  Option: saturation")
691                     log.debug("  Current value: %s" % current)
692
693                     self.addControlRow("saturation", self.__tr("Saturation"),
694                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
695
696                     current = int(current_options.get('hue', 0))
697
698                     log.debug("  Option: hue")
699                     log.debug("  Current value: %s" % current)
700
701                     self.addControlRow("hue", self.__tr("Hue (color shift/rotation)"),
702                         cups.UI_SPINNER, current,
703                         (-100, 100), 0)
704
705                 current = int(current_options.get('natural-scaling', 100))
706
707                 log.debug("  Option: natural-scaling")
708                 log.debug("  Current value: %s" % current)
709
710                 self.addControlRow("natural-scaling",
711                     self.__tr('"Natural" Scaling (relative to image)'),
712                     cups.UI_SPINNER, current, (1, 800), 100, suffix=" %")
713
714                 current = int(current_options.get('scaling', 100))
715
716                 log.debug("  Option: scaling")
717                 log.debug("  Current value: %s" % current)
718
719                 self.addControlRow("scaling", self.__tr("Scaling (relative to page)"),
720                     cups.UI_SPINNER, current,
721                     (1, 800), 100, suffix=" %")
722
723                 self.endControlGroup()
724
725                 # Misc
726                     # PrettyPrint
727                     # job-sheets
728                     # mirror
729
730                 self.beginControlGroup("misc", self.__tr("Miscellaneous"))
731
732                 log.debug("Group: Misc")
733
734                 current = utils.to_bool(current_options.get('prettyprint', '0'))
735
736                 self.addControlRow("prettyprint",
737                     self.__tr('"Pretty Print" Text Documents (Add headers and formatting)'),
738                     cups.PPD_UI_BOOLEAN, current, [], 0)
739
740                 log.debug("  Option: prettyprint")
741                 log.debug("  Current value: %s" % current)
742
743                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
744                     current = current_options.get('job-sheets', 'none').split(',')
745
746                     try:
747                         start = current[0]
748                     except IndexError:
749                         start = 'none'
750
751                     try:
752                         end = current[1]
753                     except IndexError:
754                         end = 'none'
755
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,
758                         (start, end),
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'))
766
767                     log.debug("  Option: job-sheets")
768                     log.debug("  Current value: %s,%s" % (start, end))
769
770                 current = utils.to_bool(current_options.get('mirror', '0'))
771
772                 self.addControlRow("mirror", self.__tr('Mirror Printing'),
773                     cups.PPD_UI_BOOLEAN, current, [], 0)
774
775                 log.debug("  Option: mirror")
776                 log.debug("  Current value: %s" % current)
777
778                 self.endControlGroup()
779                 
780                 #Summary
781                     #color input
782                     #quality
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")
795                    
796
797                 self.job_storage_enable = self.cur_device.mq.get('job-storage', JOB_STORAGE_DISABLE) == JOB_STORAGE_ENABLE
798
799
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
811
812                     if hold == 'OFF':
813                         self.job_storage_mode = JOB_STORAGE_TYPE_OFF
814
815                     elif hold == 'ON':
816                         if holdtype == u'PUBLIC':
817                             self.job_storage_mode = JOB_STORAGE_TYPE_QUICK_COPY
818
819                         else: # 'PRIVATE'
820                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
821                             self.job_storage_use_pin = True
822
823                     elif hold == u'PROOF':
824                         if holdtype == u'PUBLIC':
825                             self.job_storage_mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD
826                         else:
827                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
828                             self.job_storage_use_pin = True
829
830                     elif hold == u'STORE':
831                         self.job_storage_mode = JOB_STORAGE_TYPE_STORE
832                         self.job_storage_use_pin = (holdtype == u'PRIVATE')
833
834                     if duplicate == u'REPLACE':
835                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_REPLACE
836                     else: # u'APPEND'
837                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_APPEND_1_99
838
839                     # option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False)
840
841                     self.beginControlGroup("jobstorage", self.__tr("Job Storage and Secure Printing"))
842
843                     self.addControlRow("job-storage-mode", self.__tr("Mode"),
844                                        cups.UI_JOB_STORAGE_MODE, None, None, None)
845
846                     self.addControlRow("job-storage-pin", self.__tr("Make job private (use PIN to print)"),
847                                       cups.UI_JOB_STORAGE_PIN, None, None, None )
848
849                     self.addControlRow("job-storage-username", self.__tr("User name (for job identification)"),
850                                        cups.UI_JOB_STORAGE_USERNAME, None, None, None)
851
852                     self.addControlRow("job-storage-id", self.__tr("Job name/ID (for job identification)"),
853                                       cups.UI_JOB_STORAGE_ID, None, None, None)
854
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)
857
858                     self.endControlGroup()
859                     self.updateJobStorageControls()
860
861                 # use: self.job_options['xxx'] so that values can be picked up by getPrintCommand(
862
863
864             #except Exception, e:
865                 #log.exception()
866             #    pass
867
868         finally:
869             cups.closePPD()
870             self.loading = False
871
872
873     def beginControlGroup(self, group, text):
874         log.debug("BeginGroup: %s" % group)
875         self.row = 0
876         self.widget = QWidget()
877         self.gridlayout = QGridLayout(self.widget)
878         self.group = group
879         self.text = text
880
881
882     def endControlGroup(self):
883         log.debug("EndGroup: %s" % self.group)
884         spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
885         self.row += 1
886         self.gridlayout.addItem(spacer, self.row, 0, 1, 1)
887         i = self.addItem(self.widget, self.text)
888
889         if i:
890             self.setItemIcon(i, self.plus_icon)
891         else:
892             self.setItemIcon(i, self.minus_icon)
893
894         self.widget, self.gridlayout = None, None
895
896
897     def addControlRow(self, option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False):
898
899         if typ == cups.PPD_UI_BOOLEAN: # () On (*) Off widget
900             HBoxLayout = QHBoxLayout()
901             HBoxLayout.setObjectName("HBoxLayout")
902
903             OptionLabel = QLabel(self.widget)
904             OptionLabel.setObjectName("OptionLabel")
905             HBoxLayout.addWidget(OptionLabel)
906
907             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
908             HBoxLayout.addItem(SpacerItem)
909
910             GroupBox = QFrame(self.widget)
911
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)
920
921             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
922                 choices, default, (OnRadioButton, OffRadioButton), typ, job_option)
923
924             #GroupBox.setDefaultPushbutton(DefaultButton)
925             OnRadioButton.setDefaultPushbutton(DefaultButton)
926             OffRadioButton.setDefaultPushbutton(DefaultButton)
927
928             HBoxLayout.addWidget(DefaultButton)
929             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
930
931             OptionLabel.setText(text)
932             OnRadioButton.setText(self.__tr("On"))
933             OffRadioButton.setText(self.__tr("Off"))
934
935             DefaultButton.setText("Default")
936
937             if value == default:
938                 DefaultButton.setEnabled(False)
939             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
940
941             if value:
942                 OnRadioButton.setChecked(True)
943             else:
944                 OffRadioButton.setChecked(True)
945             self.connect(OnRadioButton, SIGNAL("toggled(bool)"), self.BoolRadioButtons_clicked)
946
947             if read_only:
948                 OnRadioButton.setEnabled(False)
949                 OffRadioButton.setEnabled(False)
950                 DefaultButton.setEnabled(False)
951
952
953
954         elif typ == cups.PPD_UI_PICKONE: # Combo box widget
955             #print option, job_option
956             HBoxLayout = QHBoxLayout()
957             HBoxLayout.setObjectName("HBoxLayout")
958
959             OptionLabel = QLabel(self.widget)
960             OptionLabel.setObjectName("OptionLabel")
961             HBoxLayout.addWidget(OptionLabel)
962
963             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
964             HBoxLayout.addItem(SpacerItem)
965
966             ComboBox = OptionComboBox(0, self.widget, "ComboBox", self.group, option,
967                                       choices, default, typ, None, job_option)
968
969             HBoxLayout.addWidget(ComboBox)
970
971             DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option,
972                 choices, default, ComboBox, typ, job_option)
973
974             ComboBox.setDefaultPushbutton(DefaultButton)
975             HBoxLayout.addWidget(DefaultButton)
976
977             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
978
979             OptionLabel.setText(text)
980             DefaultButton.setText("Default")
981
982             i, x, y = 0, None, None
983             for c, t in choices:
984                 d = c.lower()
985                 if value is not None and d == value.lower():
986                     x = i
987
988                 if d == default.lower():
989                     y = t
990
991                 ComboBox.insertItem(i, t)
992                 i += 1
993
994             if x is not None:
995                 ComboBox.setCurrentIndex(x)
996             else:
997                 ComboBox.setCurrentIndex(0)
998
999             if value is not None and value.lower() == default.lower():
1000                 DefaultButton.setEnabled(False)
1001
1002             #self.linkPrintoutModeAndQuality(option, value)
1003 #
1004 #            if read_only:
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))
1009 #
1010
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)
1014
1015             control = ComboBox
1016
1017         elif typ == cups.UI_SPINNER: # Spinner widget
1018
1019             HBoxLayout = QHBoxLayout()
1020             HBoxLayout.setObjectName("HBoxLayout")
1021
1022             OptionLabel = QLabel(self.widget)
1023             OptionLabel.setObjectName("OptionLabel")
1024             HBoxLayout.addWidget(OptionLabel)
1025
1026             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1027             HBoxLayout.addItem(SpacerItem)
1028
1029             SpinBox = OptionSpinBox(self.widget,"SpinBox", self.group, option, default, job_option)
1030             HBoxLayout.addWidget(SpinBox)
1031
1032             DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
1033                 choices, default, SpinBox, typ, job_option)
1034
1035             SpinBox.setDefaultPushbutton(DefaultButton)
1036             HBoxLayout.addWidget(DefaultButton)
1037
1038             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1039
1040             min, max = choices
1041             SpinBox.setMinimum(min)
1042             SpinBox.setMaximum(max)
1043             SpinBox.setValue(value)
1044
1045             if suffix:
1046                 SpinBox.setSuffix(suffix)
1047
1048             OptionLabel.setText(text)
1049             DefaultButton.setText("Default")
1050
1051             self.connect(SpinBox, SIGNAL("valueChanged(int)"), self.SpinBox_valueChanged)
1052             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
1053
1054             DefaultButton.setEnabled(not value == default)
1055
1056             if read_only:
1057                 SpinBox.setEnabled(False)
1058                 DefaultButton.setEnabled(False)
1059
1060         elif typ == cups.UI_BANNER_JOB_SHEETS:  # Job sheets widget
1061             HBoxLayout = QHBoxLayout()
1062             HBoxLayout.setObjectName("HBoxLayout")
1063
1064             OptionLabel = QLabel(self.widget)
1065             OptionLabel.setObjectName("OptionLabel")
1066             HBoxLayout.addWidget(OptionLabel)
1067
1068             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1069             HBoxLayout.addItem(SpacerItem)
1070
1071             StartLabel = QLabel(self.widget)
1072             HBoxLayout.addWidget(StartLabel)
1073
1074             StartComboBox = OptionComboBox(0, self.widget, "StartComboBox", self.group,
1075                 "start", choices, default, typ)
1076
1077             HBoxLayout.addWidget(StartComboBox)
1078
1079             EndLabel = QLabel(self.widget)
1080             HBoxLayout.addWidget(EndLabel)
1081
1082             EndComboBox = OptionComboBox(0, self.widget, "EndComboBox", self.group, "end", choices,
1083                 default, typ, StartComboBox)
1084
1085             HBoxLayout.addWidget(EndComboBox)
1086
1087             StartComboBox.setOther(EndComboBox)
1088
1089             DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option, choices,
1090                 default, (StartComboBox, EndComboBox), typ, job_option)
1091
1092             HBoxLayout.addWidget(DefaultButton)
1093
1094             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1095
1096             StartComboBox.setDefaultPushbutton(DefaultButton)
1097             EndComboBox.setDefaultPushbutton(DefaultButton)
1098
1099             OptionLabel.setText(text)
1100             DefaultButton.setText("Default")
1101
1102             StartLabel.setText(self.__tr("Start:"))
1103             EndLabel.setText(self.__tr("End:"))
1104
1105             s, e, y, z = None, None, None, None
1106             for c, t in choices:
1107                 d = c.lower()
1108                 if value is not None:
1109                     if d == value[0].lower():
1110                         s = t
1111
1112                     if d == value[1].lower():
1113                         e = t
1114
1115                 if d == default[0].lower():
1116                     y = t
1117
1118                 if d == default[1].lower():
1119                     z = t
1120
1121                 StartComboBox.insertItem(0, t)
1122                 EndComboBox.insertItem(0, t)
1123
1124             if s is not None:
1125                 StartComboBox.setCurrentIndex(StartComboBox.findText(s))
1126
1127             if e is not None:
1128                 EndComboBox.setCurrentIndex(EndComboBox.findText(e))
1129
1130             if value is not None and \
1131                 value[0].lower() == default[0].lower() and \
1132                 value[1].lower() == default[1].lower():
1133
1134                 DefaultButton.setEnabled(False)
1135
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)
1139
1140         elif typ == cups.PPD_UI_PICKMANY:
1141             log.error("Unrecognized type: pickmany")
1142
1143         elif typ == cups.UI_UNITS_SPINNER:
1144             log.error("Unrecognized type: units spinner")
1145
1146         elif typ == cups.UI_PAGE_RANGE:
1147             HBoxLayout = QHBoxLayout()
1148             HBoxLayout.setObjectName("HBoxLayout")
1149
1150             OptionLabel = QLabel(self.widget)
1151             OptionLabel.setObjectName("OptionLabel")
1152             HBoxLayout.addWidget(OptionLabel)
1153
1154             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1155             HBoxLayout.addItem(SpacerItem)
1156
1157             GroupBox = QFrame(self.widget)
1158
1159             gridlayout1 = QGridLayout(GroupBox)
1160
1161             AllRadioButton = PageRangeRadioButton(GroupBox, "AllRadioButton",
1162                                                self.group, option, default)
1163
1164             gridlayout1.addWidget(AllRadioButton,0,0,1,1)
1165             RangeRadioButton = PageRangeRadioButton(GroupBox, "RangeRadioButton",
1166                                                  self.group, option, default)
1167
1168             gridlayout1.addWidget(RangeRadioButton,0,1,1,1)
1169             HBoxLayout.addWidget(GroupBox)
1170
1171             PageRangeEdit = QLineEdit(self.widget)
1172             HBoxLayout.addWidget(PageRangeEdit)
1173             PageRangeEdit.setValidator(RangeValidator(PageRangeEdit))
1174
1175             AllRadioButton.setRangeEdit(PageRangeEdit)
1176             RangeRadioButton.setRangeEdit(PageRangeEdit)
1177
1178             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
1179                 choices, default, (AllRadioButton, RangeRadioButton, PageRangeEdit), typ, job_option)
1180
1181             AllRadioButton.setDefaultPushbutton(DefaultButton)
1182             RangeRadioButton.setDefaultPushbutton(DefaultButton)
1183
1184             HBoxLayout.addWidget(DefaultButton)
1185             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1186
1187             OptionLabel.setText(text)
1188             AllRadioButton.setText(self.__tr("All pages"))
1189             RangeRadioButton.setText(self.__tr("Page Range:"))
1190
1191             DefaultButton.setText("Default")
1192             DefaultButton.setEnabled(False)
1193
1194             AllRadioButton.setChecked(True)
1195             PageRangeEdit.setEnabled(False)
1196
1197             # TODO: Set current
1198
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)
1204
1205         elif typ == cups.UI_JOB_STORAGE_MODE:
1206             HBoxLayout = QHBoxLayout()
1207             HBoxLayout.setObjectName("HBoxLayout")
1208
1209             OptionLabel = QLabel(self.widget)
1210             OptionLabel.setObjectName("OptionLabel")
1211             HBoxLayout.addWidget(OptionLabel)
1212
1213             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1214             HBoxLayout.addItem(SpacerItem)
1215
1216             self.JobStorageModeComboBox = QComboBox(self.widget)
1217             HBoxLayout.addWidget(self.JobStorageModeComboBox)
1218
1219             self.JobStorageModeDefaultButton = QPushButton(self.widget)
1220             HBoxLayout.addWidget(self.JobStorageModeDefaultButton)
1221
1222             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1223
1224             OptionLabel.setText(text)
1225             self.JobStorageModeDefaultButton.setText(self.__tr("Default"))
1226
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))
1232
1233             self.connect(self.JobStorageModeComboBox, SIGNAL("activated(int)"),
1234                         self.JobStorageModeComboBox_activated)
1235
1236             self.connect(self.JobStorageModeDefaultButton, SIGNAL("clicked()"),
1237                         self.JobStorageModeDefaultButton_clicked)
1238
1239
1240         elif typ == cups.UI_JOB_STORAGE_PIN:
1241             HBoxLayout = QHBoxLayout()
1242             HBoxLayout.setObjectName("HBoxLayout")
1243
1244             OptionLabel = QLabel(self.widget)
1245             OptionLabel.setObjectName("OptionLabel")
1246             HBoxLayout.addWidget(OptionLabel)
1247
1248             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1249             HBoxLayout.addItem(SpacerItem)
1250
1251             self.JobStoragePinGroupBox = QFrame(self.widget)
1252
1253             gridlayout1 = QGridLayout(self.JobStoragePinGroupBox)
1254             self.JobStoragePinOffRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1255             gridlayout1.addWidget(self.JobStoragePinOffRadioButton, 0, 0, 1, 1)
1256
1257             self.JobStoragePinPrivateRadioButton = QRadioButton(self.JobStoragePinGroupBox)
1258             gridlayout1.addWidget(self.JobStoragePinPrivateRadioButton, 0, 1, 1, 1)
1259
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)
1264
1265             HBoxLayout.addWidget(self.JobStoragePinGroupBox)
1266
1267             self.JobStoragePinDefaultButton = QPushButton(self.widget)
1268             HBoxLayout.addWidget(self.JobStoragePinDefaultButton)
1269
1270             self.JobStoragePinOffRadioButton.setText(self.__tr("Public/Off"))
1271             self.JobStoragePinPrivateRadioButton.setText(self.__tr("Private/Use PIN:"))
1272
1273             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1274
1275             OptionLabel.setText(text)
1276             self.JobStoragePinDefaultButton.setText(self.__tr("Default"))
1277
1278             self.connect(self.JobStoragePinOffRadioButton, SIGNAL("toggled(bool)"),
1279                             self.JobStoragePinOffRadioButton_toggled)
1280
1281             self.connect(self.JobStoragePinPrivateRadioButton, SIGNAL("toggled(bool)"),
1282                             self.JobStoragePinPrivateRadioButton_toggled)
1283
1284             self.connect(self.JobStoragePinDefaultButton, SIGNAL("clicked()"),
1285                             self.JobStoragePinDefaultButton_clicked)
1286
1287             self.connect(self.JobStoragePinEdit, SIGNAL("textEdited(const QString &)"),
1288                         self.JobStoragePinEdit_textEdited)
1289
1290
1291         elif typ == cups.UI_JOB_STORAGE_USERNAME:
1292             HBoxLayout = QHBoxLayout()
1293             HBoxLayout.setObjectName("HBoxLayout")
1294
1295             OptionLabel = QLabel(self.widget)
1296             OptionLabel.setObjectName("OptionLabel")
1297             HBoxLayout.addWidget(OptionLabel)
1298             OptionLabel.setText(text)
1299
1300             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1301             HBoxLayout.addItem(SpacerItem)
1302
1303             self.JobStorageUsernameGroupBox = QFrame(self.widget)
1304
1305             gridlayout1 = QGridLayout(self.JobStorageUsernameGroupBox)
1306             self.JobStorageUsernameAutoRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1307             gridlayout1.addWidget(self.JobStorageUsernameAutoRadioButton, 0, 0, 1, 1)
1308
1309             self.JobStorageUsernameCustomRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
1310             gridlayout1.addWidget(self.JobStorageUsernameCustomRadioButton, 0, 1, 1, 1)
1311
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)
1316
1317             HBoxLayout.addWidget(self.JobStorageUsernameGroupBox)
1318
1319             self.JobStorageUsernameDefaultButton = QPushButton(self.widget)
1320             HBoxLayout.addWidget(self.JobStorageUsernameDefaultButton)
1321
1322             self.JobStorageUsernameAutoRadioButton.setText(self.__tr("Automatic"))
1323             self.JobStorageUsernameCustomRadioButton.setText(self.__tr("Custom:"))
1324             self.JobStorageUsernameDefaultButton.setText(self.__tr("Default"))
1325
1326             self.connect(self.JobStorageUsernameAutoRadioButton, SIGNAL("toggled(bool)"),
1327                             self.JobStorageUsernameAutoRadioButton_toggled)
1328
1329             self.connect(self.JobStorageUsernameCustomRadioButton, SIGNAL("toggled(bool)"),
1330                             self.JobStorageUsernameCustomRadioButton_toggled)
1331
1332             self.connect(self.JobStorageUsernameDefaultButton, SIGNAL("clicked()"),
1333                         self.JobStorageUsernameDefaultButton_clicked)
1334
1335             self.connect(self.JobStorageUsernameEdit, SIGNAL("textEdited(const QString &)"),
1336                         self.JobStorageUsernameEdit_textEdited)
1337
1338             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1339
1340         elif typ == cups.UI_JOB_STORAGE_ID:
1341             HBoxLayout = QHBoxLayout()
1342             HBoxLayout.setObjectName("HBoxLayout")
1343
1344             OptionLabel = QLabel(self.widget)
1345             OptionLabel.setObjectName("OptionLabel")
1346             HBoxLayout.addWidget(OptionLabel)
1347             OptionLabel.setText(text)
1348
1349             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1350             HBoxLayout.addItem(SpacerItem)
1351
1352             self.JobStorageIDGroupBox = QFrame(self.widget)
1353
1354             gridlayout1 = QGridLayout(self.JobStorageIDGroupBox)
1355             self.JobStorageIDAutoRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1356             gridlayout1.addWidget(self.JobStorageIDAutoRadioButton, 0, 0, 1, 1)
1357
1358             self.JobStorageIDCustomRadioButton = QRadioButton(self.JobStorageIDGroupBox)
1359             gridlayout1.addWidget(self.JobStorageIDCustomRadioButton, 0, 1, 1, 1)
1360
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)
1365
1366             HBoxLayout.addWidget(self.JobStorageIDGroupBox)
1367
1368             self.JobStorageIDDefaultButton = QPushButton(self.widget)
1369             HBoxLayout.addWidget(self.JobStorageIDDefaultButton)
1370
1371             self.JobStorageIDAutoRadioButton.setText(self.__tr("Automatic"))
1372             self.JobStorageIDCustomRadioButton.setText(self.__tr("Custom:"))
1373             self.JobStorageIDDefaultButton.setText(self.__tr("Default"))
1374
1375             self.connect(self.JobStorageIDAutoRadioButton, SIGNAL("toggled(bool)"),
1376                             self.JobStorageIDAutoRadioButton_toggled)
1377
1378             self.connect(self.JobStorageIDCustomRadioButton, SIGNAL("toggled(bool)"),
1379                             self.JobStorageIDCustomRadioButton_toggled)
1380
1381             self.connect(self.JobStorageIDDefaultButton, SIGNAL("clicked()"),
1382                         self.JobStorageIDDefaultButton_clicked)
1383
1384             self.connect(self.JobStorageIDEdit, SIGNAL("textEdited(const QString &)"),
1385                         self.JobStorageIDEdit_textEdited)
1386
1387             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1388
1389         elif typ == cups.UI_JOB_STORAGE_ID_EXISTS:
1390             HBoxLayout = QHBoxLayout()
1391             HBoxLayout.setObjectName("HBoxLayout")
1392
1393             OptionLabel = QLabel(self.widget)
1394             OptionLabel.setObjectName("OptionLabel")
1395             HBoxLayout.addWidget(OptionLabel)
1396             OptionLabel.setText(text)
1397
1398             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1399             HBoxLayout.addItem(SpacerItem)
1400
1401             self.JobStorageExistingComboBox = QComboBox(self.widget)
1402             HBoxLayout.addWidget(self.JobStorageExistingComboBox)
1403
1404             self.JobStorageExistingDefaultButton = QPushButton(self.widget)
1405             HBoxLayout.addWidget(self.JobStorageExistingDefaultButton)
1406
1407             self.JobStorageExistingComboBox.addItem(self.__tr("Replace existing job"),
1408                              QVariant(JOB_STORAGE_EXISTING_JOB_REPLACE))
1409
1410             self.JobStorageExistingComboBox.addItem(self.__tr("Use job name appended with 1-99"),
1411                              QVariant(JOB_STORAGE_EXISTING_JOB_APPEND_1_99))
1412
1413             self.JobStorageExistingDefaultButton.setText(self.__tr("Default"))
1414
1415             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1416
1417             self.connect(self.JobStorageExistingComboBox, SIGNAL("activated(int)"),
1418                         self.JobStorageExistingComboBox_activated)
1419
1420             self.connect(self.JobStorageExistingDefaultButton, SIGNAL("clicked()"),
1421                         self.JobStorageExistingDefaultButton_clicked)
1422                         
1423         elif typ == cups.UI_INFO:
1424             HBoxLayout = QHBoxLayout()
1425             HBoxLayout.setObjectName("HBoxLayout")
1426
1427             OptionName = QLabel(self.widget)
1428             OptionName.setObjectName("OptionLabel")
1429             HBoxLayout.addWidget(OptionName)
1430             OptionName.setText(text)
1431
1432             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
1433             HBoxLayout.addItem(SpacerItem)
1434             
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)
1445             else:
1446                 OptionValue = QLabel(self.widget)
1447                 OptionValue.setObjectName("OptionValue")
1448                 HBoxLayout.addWidget(OptionValue)
1449                 OptionValue.setText(value)
1450                 
1451             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
1452
1453         else:
1454             log.error("Invalid UI value: %s/%s" % (self.group, option))
1455
1456         self.row += 1
1457
1458
1459
1460     def BannerComboBox_activated(self, a): # cups.UI_BANNER_JOB_SHEETS
1461         a = unicode(a)
1462         sender = self.sender()
1463         choice = None
1464
1465         start, end = None, None
1466         for c, t in sender.choices:
1467             if t == a:
1468                 start = c
1469                 break
1470
1471         for c, t in sender.other.choices:
1472             if t == sender.other.currentText():
1473                 end = c
1474                 break
1475
1476         if sender.option == 'end':
1477             start, end = end, start
1478
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)
1485         else:
1486             sender.pushbutton.setEnabled(True)
1487
1488             if start is not None and \
1489                 end is not None:
1490
1491                 self.setPrinterOption('job-sheets', ','.join([start, end]))
1492
1493
1494     def ComboBox_highlighted(self, t):
1495         t = unicode(t)
1496         sender = self.sender()
1497         choice = None
1498
1499         #print sender, sender.option, sender.job_option
1500
1501         choice = None
1502         for c, a in sender.choices:
1503             if a == t:
1504                 choice = c
1505                 break
1506
1507         if choice is not None and choice == sender.default:
1508             if sender.job_option:
1509                 self.job_options[sender.option] = sender.default
1510             else:
1511                 self.removePrinterOption(sender.option)
1512             sender.pushbutton.setEnabled(False)
1513
1514         else:
1515             sender.pushbutton.setEnabled(True)
1516
1517             if choice is not None:
1518                 if sender.job_option:
1519                     self.job_options[sender.option] = choice
1520                 else:
1521                     self.setPrinterOption(sender.option, choice)
1522
1523             #self.linkPrintoutModeAndQuality(sender.option, choice)
1524
1525     if 0:
1526         pass
1527         #    def linkPrintoutModeAndQuality(self, option, choice):
1528         #        if option.lower() == 'quality' and \
1529         #            choice is not None:
1530         #
1531         #            try:
1532         #                c = self.items['o:PrintoutMode'].control
1533         #            except KeyError:
1534         #                return
1535         #            else:
1536         #                if c is not None:
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())
1543         #
1544         #                        # determine printoutmode default button state
1545         #                        link_choice = None
1546         #                        for x, t in c.choices:
1547         #                            if t == a:
1548         #                                link_choice = x
1549         #                                break
1550         #
1551         #                        if link_choice is not None and \
1552         #                            link_choice.lower() == c.default.lower():
1553         #
1554         #                            c.pushbutton.setEnabled(False)
1555         #                        else:
1556         #                            c.pushbutton.setEnabled(True)
1557         #
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)
1562         #
1563
1564     def SpinBox_valueChanged(self, i): # cups.UI_SPINNER
1565         sender = self.sender()
1566
1567         if not sender.job_option:
1568             if i == sender.default:
1569                 self.removePrinterOption(sender.option)
1570                 sender.pushbutton.setEnabled(False)
1571             else:
1572                 sender.pushbutton.setEnabled(True)
1573                 self.setPrinterOption(sender.option, str(i))
1574
1575         else:
1576             try:
1577                 self.job_options[sender.option] = int(i)
1578             except ValueError:
1579                 self.job_options[sender.option] = sender.default
1580
1581
1582     def BoolRadioButtons_clicked(self, b): # cups.PPD_UI_BOOLEAN
1583         sender = self.sender()
1584         b = int(b)
1585
1586         if b == sender.default:
1587             self.removePrinterOption(sender.option)
1588             sender.pushbutton.setEnabled(False)
1589         else:
1590             sender.pushbutton.setEnabled(True)
1591
1592             if b:
1593                 self.setPrinterOption(sender.option, "true")
1594             else:
1595                 self.setPrinterOption(sender.option, "false")
1596
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)
1607             
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)
1614             cups.closePPD()            
1615             self.PQColorInputLabel.setText(outputmode_dpi)
1616             
1617             log.debug("Outputmode changed, setting value outputmode: %s" % currentItem)            
1618
1619     def DefaultButton_clicked(self):
1620         sender = self.sender()
1621         sender.setEnabled(False)
1622
1623         if sender.typ == cups.PPD_UI_BOOLEAN: # () On  (*) Off
1624             if sender.default:
1625                 sender.control[0].setChecked(True)
1626                 sender.control[0].setFocus(Qt.OtherFocusReason)
1627             else:
1628                 sender.control[1].setChecked(True)
1629                 sender.control[1].setFocus(Qt.OtherFocusReason)
1630
1631             if not sender.job_option:
1632                 self.removePrinterOption(sender.option)
1633
1634         elif sender.typ == cups.PPD_UI_PICKONE: # [     \/]
1635             choice, text = None, None
1636
1637             for c, t in sender.choices:
1638                 if c == sender.default:
1639                     choice = c
1640                     text = t
1641                     self.job_options[sender.option] = t
1642                     break
1643
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)
1649
1650                 #self.linkPrintoutModeAndQuality(sender.option, choice) # TODO:
1651                 sender.control.setFocus(Qt.OtherFocusReason)
1652
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)
1657
1658             sender.control.setFocus(Qt.OtherFocusReason)
1659
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]:
1664                     start = c
1665                     start_text = t
1666
1667                 if c == sender.default[1]:
1668                     end = c
1669                     end_text = t
1670
1671             if start is not None:
1672                 index = sender.control[0].findText(start_text)
1673                 sender.control[0].setCurrentIndex(index)
1674
1675             if end is not None:
1676                 index = sender.control[1].findText(end_text)
1677                 sender.control[1].setCurrentIndex(index)
1678
1679             if not sender.job_option:
1680                 self.removePrinterOption('job-sheets')
1681
1682             sender.control[0].setFocus(Qt.OtherFocusReason)
1683
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
1688
1689
1690     def PageRangeAllRadio_toggled(self, b):
1691         if b:
1692             sender = self.sender()
1693             sender.edit_control.setEnabled(False)
1694             sender.pushbutton.setEnabled(False)
1695             self.job_options['pagerange'] = ''
1696
1697
1698     def PageRangeRangeRadio_toggled(self, b):
1699         if 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())
1704
1705
1706     def PageRangeEdit_editingFinished(self):
1707         sender = self.sender()
1708         t, ok, x = self.job_options['pagerange'], True, []
1709
1710         #[Sanjay]Start Range Validation here as the editing is finished
1711         try:
1712             x = utils.expand_range(t)   
1713         except ValueError:
1714             ok = False
1715
1716         if t == '':
1717             ok = False
1718
1719         if ok:
1720             if 0 in x:
1721                 ok = False
1722
1723             if ok:
1724                 for y in x:
1725                     if y > 999:
1726                         ok = False
1727                         break
1728
1729         if not ok:
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)
1734
1735
1736     def PageRangeEdit_textChanged(self, t):
1737         self.job_options['pagerange'] = unicode(t) # Do range validation only in PageRangeEdit_editingFinished method
1738
1739     #
1740     # Job Storage
1741     #
1742
1743     def updateJobStorageControls(self):
1744         beginWaitCursor()
1745         try:
1746             # Mode
1747             self.JobStorageModeComboBox.setCurrentIndex(self.JobStorageModeComboBox.findData(QVariant(self.job_storage_mode)))
1748             self.JobStorageModeDefaultButton.setEnabled(self.job_storage_mode != JOB_STORAGE_TYPE_OFF)
1749
1750             # PIN
1751             self.JobStoragePinPrivateRadioButton.setChecked(self.job_storage_use_pin)
1752
1753             # Username
1754             self.JobStorageUsernameAutoRadioButton.setChecked(self.job_storage_auto_username)
1755
1756             # Jobname/ID
1757             self.JobStorageIDAutoRadioButton.setChecked(self.job_storage_auto_jobname)
1758
1759             # Dup/existing ID
1760             self.JobStorageExistingComboBox.setCurrentIndex(self.JobStorageExistingComboBox.findData(QVariant(self.job_storage_job_exist)))
1761
1762             if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
1763                 # PIN
1764                 self.JobStoragePinGroupBox.setEnabled(False)
1765                 self.JobStoragePinEdit.setEnabled(False)
1766                 self.JobStoragePinDefaultButton.setEnabled(False)
1767                 self.JobStoragePinEdit.setText(QString())
1768
1769                 # Username
1770                 self.JobStorageUsernameGroupBox.setEnabled(False)
1771                 self.JobStorageUsernameEdit.setEnabled(False)
1772                 self.JobStorageUsernameDefaultButton.setEnabled(False)
1773
1774                 # Jobname/ID
1775                 self.JobStorageIDGroupBox.setEnabled(False)
1776                 self.JobStorageIDEdit.setEnabled(False)
1777                 self.JobStorageIDDefaultButton.setEnabled(False)
1778
1779                 # Duplicate/existing Jobname/ID
1780                 self.JobStorageExistingComboBox.setEnabled(False)
1781
1782             else:
1783                 # PIN
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))
1789                 else:
1790                     self.JobStoragePinGroupBox.setEnabled(False)
1791                     self.JobStoragePinEdit.setEnabled(False)
1792                     self.JobStoragePinDefaultButton.setEnabled(False)
1793                     self.JobStoragePinEdit.setText(QString())
1794
1795                 # Username
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))
1800
1801                 # Jobname/ID
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))
1806
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)
1810
1811         finally:
1812             endWaitCursor()
1813
1814
1815     def saveJobStorageOptions(self):
1816         beginWaitCursor()
1817         try:
1818             log.debug("Saving job storage options...")
1819
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')
1827
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')
1833
1834             elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
1835                 log.debug("Job storage mode = JOB_STORAGE_TYPE_PERSONAL")
1836
1837                 if self.job_storage_use_pin:
1838                     self.setPrinterOption('HOLD', 'ON')
1839                 else:
1840                     self.setPrinterOption('HOLD', 'PROOF')
1841                     self.setPrinterOption('HOLDTYPE', 'PUBLIC')
1842
1843
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')
1848
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')
1852
1853                 if not self.job_storage_use_pin:
1854                     self.removePrinterOption('HOLDTYPE')
1855
1856             # PIN
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')
1860
1861             #else:
1862             #    self.removePrinterOption('HOLDKEY')
1863
1864             # Dup/exisiting
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')
1868
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')
1872
1873
1874         finally:
1875             endWaitCursor()
1876
1877
1878     #
1879     # Mode
1880     #
1881
1882     def JobStorageModeComboBox_activated(self, i):
1883         sender = self.sender()
1884         mode, ok = sender.itemData(i).toInt()
1885         if ok:
1886             self.job_storage_mode = mode
1887             self.saveJobStorageOptions()
1888             self.updateJobStorageControls()
1889
1890
1891     def JobStorageModeDefaultButton_clicked(self):
1892         self.JobStorageModeComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_TYPE_OFF)
1893
1894
1895     #
1896     # PIN
1897     #
1898
1899     def JobStoragePinOffRadioButton_toggled(self, b):
1900         self.job_storage_use_pin = not b
1901         self.updateJobStorageControls()
1902         self.saveJobStorageOptions()
1903
1904
1905     def JobStoragePinPrivateRadioButton_toggled(self, b):
1906         self.job_storage_use_pin = b
1907         self.updateJobStorageControls()
1908         self.saveJobStorageOptions()
1909
1910
1911     def JobStoragePinDefaultButton_clicked(self):
1912         self.JobStoragePinOffRadioButton.emit(SIGNAL("toggled(bool)"), True)
1913
1914
1915     def JobStoragePinEdit_textEdited(self, s):
1916         self.job_storage_pin = unicode(s)
1917         self.setPrinterOption('HOLDKEY', self.job_storage_pin.encode('ascii'))
1918
1919
1920
1921     #
1922     # Username
1923     #
1924
1925     def JobStorageUsernameAutoRadioButton_toggled(self, b):
1926         self.job_storage_auto_username = b
1927         self.updateJobStorageControls()
1928         self.saveJobStorageOptions()
1929
1930
1931     def JobStorageUsernameCustomRadioButton_toggled(self, b):
1932         self.job_storage_auto_username = not b
1933         self.updateJobStorageControls()
1934         self.saveJobStorageOptions()
1935
1936
1937     def JobStorageUsernameDefaultButton_clicked(self):
1938         self.JobStorageUsernameAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1939
1940
1941     def JobStorageUsernameEdit_textEdited(self, s):
1942         self.job_storage_username = unicode(s)
1943         self.setPrinterOption('USERNAME', self.job_storage_username.encode('ascii'))
1944
1945     #
1946     # Jobname/ID
1947     #
1948
1949     def JobStorageIDAutoRadioButton_toggled(self, b):
1950         self.job_storage_auto_jobname = b
1951         self.updateJobStorageControls()
1952         self.saveJobStorageOptions()
1953
1954
1955     def JobStorageIDCustomRadioButton_toggled(self, b):
1956         self.job_storage_auto_jobname = not b
1957         self.updateJobStorageControls()
1958         self.saveJobStorageOptions()
1959
1960
1961     def JobStorageIDDefaultButton_clicked(self):
1962         self.JobStorageIDAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
1963
1964
1965     def JobStorageIDEdit_textEdited(self, s):
1966         self.job_storage_jobname = unicode(s)
1967         self.setPrinterOption('JOBNAME', self.job_storage_jobname.encode('ascii'))
1968
1969     #
1970     # Duplicate/existing Jobname/ID
1971     #
1972
1973     def JobStorageExistingComboBox_activated(self, i):
1974         sender = self.sender()
1975         opt, ok = sender.itemData(i).toInt()
1976         if ok:
1977             self.job_storage_job_exist = opt
1978             self.updateJobStorageControls()
1979             self.saveJobStorageOptions()
1980
1981
1982     def JobStorageExistingDefaultButton_clicked(self):
1983         self.JobStorageExistingComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_EXISTING_JOB_REPLACE)
1984
1985
1986     #
1987     # Printer I/O
1988     #
1989
1990     def setPrinterOption(self, option, value):
1991         log.debug("setPrinterOption(%s, %s)" % (option, value))
1992         cups.openPPD(self.cur_printer)
1993
1994         try:
1995             cups.addOption("%s=%s" % (option, value))
1996             cups.setOptions()
1997         finally:
1998             cups.closePPD()
1999
2000     def removePrinterOption(self, option):
2001         log.debug("removePrinterOption(%s)" % option)
2002         cups.openPPD(self.cur_printer)
2003
2004         try:
2005             cups.removeOption(option)
2006             cups.setOptions()
2007         finally:
2008             cups.closePPD()
2009
2010
2011     def __tr(self,s,c = None):
2012         return qApp.translate("PrintSettingsToolbox",s,c)
2013