home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / printsettingstoolbox.py < prev    next >
Encoding:
Python Source  |  2009-04-14  |  73.8 KB  |  1,946 lines

  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
  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.         self.cur_device = cur_device
  321.         self.cur_printer = cur_printer
  322.  
  323.         while self.count():
  324.             self.removeItem(0)
  325.  
  326.         self.loading = True
  327.         cups.resetOptions()
  328.         cups.openPPD(self.cur_printer)
  329.  
  330.         try:
  331.             if 1:
  332.             #try:
  333.                 current_options = dict(cups.getOptions())
  334.  
  335.                 if self.include_job_options:
  336.                     self.beginControlGroup("job_options", self.__tr("Job Options"))
  337.  
  338.                     # Num. copies (SPINNER)
  339.                     try:
  340.                         current = int(current_options.get('copies', '1'))
  341.                     except ValueError:
  342.                         current = 1
  343.  
  344.                     self.addControlRow("copies", self.__tr("Number of copies"),
  345.                         cups.UI_SPINNER, current, (1, 99), 1, job_option=True)
  346.                     self.job_options['copies'] = current
  347.  
  348.                     # page range RADIO + RANGE (custom)
  349.                     current = current_options.get('pagerange', '')
  350.  
  351.                     self.addControlRow("pagerange", self.__tr("Page Range"),
  352.                         cups.UI_PAGE_RANGE, current, None, None, job_option=True)
  353.  
  354.                     self.job_options['pagerange'] = current
  355.  
  356.                     # page set (COMBO/PICKONE)
  357.                     current = current_options.get('pageset', '')
  358.                     self.addControlRow("pageset", self.__tr("Page Set"),
  359.                         cups.PPD_UI_PICKONE, current,
  360.                         [('', self.__tr("All pages")),
  361.                          ('even', self.__tr("Even pages")),
  362.                          ('odd', self.__tr("Odd pages"))], '', job_option=True)
  363.  
  364.                     self.job_options['pageset'] = current
  365. #                    if current == u'even':
  366. #                        self.job_options["pageset"] = PAGE_SET_EVEN
  367. #                    elif current == u'odd':
  368. #                        self.job_options["pageset"] = PAGE_SET_ODD
  369. #                    else:
  370. #                        self.job_options["pageset"] = PAGE_SET_ALL
  371.  
  372.                     self.endControlGroup() # job_options
  373.  
  374.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  375.                     self.beginControlGroup("basic", self.__tr("Basic"))
  376.  
  377.                     # Basic
  378.                         # PageSize (in PPD section)
  379.                         # orientation-requested
  380.                         # sides
  381.                         # outputorder
  382.                         # Collate
  383.  
  384.                     current = current_options.get('orientation-requested', '3')
  385.  
  386.                     self.addControlRow("orientation-requested", self.__tr("Page Orientation"),
  387.                         cups.PPD_UI_PICKONE, current,
  388.                         [('3', self.__tr('Portrait')),
  389.                          ('4', self.__tr('Landscape')),
  390.                          ('5', self.__tr('Reverse landscape')),
  391.                          ('6', self.__tr('Reverse portrait'))], '3')
  392.  
  393.                     log.debug("Option: orientation-requested")
  394.                     log.debug("Current value: %s" % current)
  395.  
  396.                     duplexer = self.cur_device.dq.get('duplexer', 0)
  397.                     log.debug("Duplexer = %d" % duplexer)
  398.  
  399.                     if duplexer:
  400.                         current = current_options.get('sides', 'one-sided')
  401.                         self.addControlRow("sides",
  402.                             self.__tr("Duplex (Print on both sides of the page)"),
  403.                             cups.PPD_UI_PICKONE, current,
  404.                             [('one-sided',self.__tr('Single sided')),
  405.                              ('two-sided-long-edge', self.__tr('Two sided (long edge)')),
  406.                              ('two-sided-short-edge', self.__tr('Two sided (short edge)'))], 'one-sided')
  407.  
  408.                         log.debug("Option: sides")
  409.                         log.debug("Current value: %s" % current)
  410.  
  411.                     current = current_options.get('outputorder', 'normal')
  412.  
  413.                     self.addControlRow("outputorder",
  414.                         self.__tr("Output Order (Print last page first)"),
  415.                         cups.PPD_UI_PICKONE, current,
  416.                         [('normal', self.__tr('Normal (Print first page first)')),
  417.                          ('reverse', self.__tr('Reversed (Print last page first)'))], 'normal')
  418.  
  419.                     log.debug("Option: outputorder")
  420.                     log.debug("Current value: %s" % current)
  421.  
  422.                     current = utils.to_bool(current_options.get('Collate', '0'))
  423.  
  424.                     self.addControlRow("Collate",
  425.                         self.__tr("Collate (Group together multiple copies)"),
  426.                         cups.PPD_UI_BOOLEAN, current,
  427.                         [], 0)
  428.  
  429.                     log.debug("Option: Collate")
  430.                     log.debug("Current value: %s" % current)
  431.  
  432.                     self.endControlGroup()
  433.  
  434.                 groups = cups.getGroupList()
  435.  
  436.                 #print groups
  437.  
  438.                 for g in groups:
  439.                     if 'jobretention' in g.lower():
  440.                         log.debug("HPJobRetention skipped.")
  441.                         continue
  442.  
  443.                     try:
  444.                         text, num_subgroups = cups.getGroup(g)
  445.                     except TypeError:
  446.                         log.warn("Group %s returned None" % g)
  447.                         continue
  448.  
  449.                     read_only = 'install' in g.lower()
  450.  
  451.                     try:
  452.                         text = text.decode('utf-8')
  453.                     except UnicodeDecodeError:
  454.                         pass
  455.  
  456.                     if g.lower() == 'printoutmode':
  457.                         text = self.__tr("Quality (also see 'Printout Mode' under 'General')")
  458.  
  459.                     self.beginControlGroup(g, QString(text))
  460.  
  461.                     log.debug("  Text: %s" % unicode(text))
  462.                     log.debug("Num subgroups: %d" % num_subgroups)
  463.  
  464.                     options = cups.getOptionList(g)
  465.  
  466.                     #print options
  467.  
  468.                     for o in options:
  469.                         log.debug("  Option: %s" % repr(o))
  470.  
  471.                         if 'pageregion' in o.lower():
  472.                             log.debug("Page Region skipped.")
  473.                             continue
  474.  
  475.                         try:
  476.                             option_text, defchoice, conflicted, ui  = cups.getOption(g, o)
  477.                         except TypeError:
  478.                             log.warn("Option %s in group %s returned None" % (o, g))
  479.                             continue
  480.  
  481.                         try:
  482.                             option_text = option_text.decode('utf-8')
  483.                         except UnicodeDecodeError:
  484.                             pass
  485.  
  486.                         if o.lower() == 'quality':
  487.                             option_text = self.__tr("Quality")
  488.  
  489.                         log.debug("    Text: %s" % repr(option_text))
  490.                         log.debug("    Defchoice: %s" % repr(defchoice))
  491.  
  492.                         choices = cups.getChoiceList(g, o)
  493.  
  494.                         value = None
  495.                         choice_data = []
  496.                         for c in choices:
  497.                             log.debug("    Choice: %s" % repr(c))
  498.  
  499.                             # TODO: Add custom paper size controls
  500.                             if 'pagesize' in o.lower() and 'custom' in c.lower():
  501.                                 log.debug("Skipped.")
  502.                                 continue
  503.  
  504.                             choice_text, marked = cups.getChoice(g, o, c)
  505.  
  506.                             try:
  507.                                 choice_text = choice_text.decode('utf-8')
  508.                             except UnicodeDecodeError:
  509.                                 pass
  510.  
  511.                             log.debug("      Text: %s" % repr(choice_text))
  512.  
  513.                             if marked:
  514.                                 value = c
  515.  
  516.                             choice_data.append((c, choice_text))
  517.  
  518.                         self.addControlRow(o, option_text, ui, value, choice_data, defchoice, read_only)
  519.  
  520.                     self.endControlGroup()
  521.  
  522. ##                        if 'pagesize' in o.lower(): # and 'custom' in c.lower():
  523. ##                            current = 0.0
  524. ##                            width_widget = self.addControlRow(widget, "custom", "custom-width", self.__tr("Custom Paper Width"), cups.UI_UNITS_SPINNER,
  525. ##                                current, (0.0, 0.0), 0.0)
  526. ##
  527. ##                            current = 0.0
  528. ##                            height_widget = self.addControlRow("custom", "custom-height", self.__tr("Custom Paper Height"), cups.UI_UNITS_SPINNER,
  529. ##                                current, (0.0, 0.0), 0.0)
  530. ##
  531. ##                            if value.lower() == 'custom':
  532. ##                                pass
  533.  
  534.                 # N-Up
  535.                     # number-up
  536.                     # number-up-layout
  537.                     # page-border
  538.  
  539.                 self.beginControlGroup("nup", self.__tr("N-Up (Multiple document pages per printed page)"))
  540.                 current = current_options.get('number-up', '1')
  541.  
  542.                 self.addControlRow("number-up", self.__tr("Pages per Sheet"),
  543.                     cups.PPD_UI_PICKONE, current,
  544.                     [('1', self.__tr('1 page per sheet')),
  545.                      ('2', self.__tr('2 pages per sheet')),
  546.                      ('4', self.__tr('4 pages per sheet'))], '1')
  547.  
  548.                 log.debug("  Option: number-up")
  549.                 log.debug("  Current value: %s" % current)
  550.  
  551.                 current = current_options.get('number-up-layout', 'lrtb')
  552.  
  553.                 self.addControlRow("number-up-layout", self.__tr("Layout"),
  554.                     cups.PPD_UI_PICKONE, current,
  555.                     [('btlr', self.__tr('Bottom to top, left to right')),
  556.                      ('btrl', self.__tr('Bottom to top, right to left')),
  557.                      ('lrbt', self.__tr('Left to right, bottom to top')),
  558.                      ('lrtb', self.__tr('Left to right, top to bottom')),
  559.                      ('rlbt', self.__tr('Right to left, bottom to top')),
  560.                      ('rltb', self.__tr('Right to left, top to bottom')),
  561.                      ('tblr', self.__tr('Top to bottom, left to right')),
  562.                      ('tbrl', self.__tr('Top to bottom, right to left')) ], 'lrtb')
  563.  
  564.                 log.debug("  Option: number-up-layout")
  565.                 log.debug("  Current value: %s" % current)
  566.  
  567.                 current = current_options.get('page-border', 'none')
  568.  
  569.                 self.addControlRow("page-border",
  570.                     self.__tr("Printed Border Around Each Page"),
  571.                     cups.PPD_UI_PICKONE, current,
  572.                     [('double', self.__tr("Two thin borders")),
  573.                      ("double-thick", self.__tr("Two thick borders")),
  574.                      ("none", self.__tr("No border")),
  575.                      ("single", self.__tr("One thin border")),
  576.                      ("single-thick", self.__tr("One thick border"))], 'none')
  577.  
  578.                 log.debug("  Option: page-border")
  579.                 log.debug("  Current value: %s" % current)
  580.  
  581.                 self.endControlGroup()
  582.  
  583.                 # Adjustment
  584.                     # brightness
  585.                     # gamma
  586.  
  587.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  588.                     self.beginControlGroup("adjustment", self.__tr("Printout Appearance"))
  589.  
  590.                     current = int(current_options.get('brightness', 100))
  591.  
  592.                     log.debug("  Option: brightness")
  593.                     log.debug("  Current value: %s" % current)
  594.  
  595.                     self.addControlRow("brightness", self.__tr("Brightness"),
  596.                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
  597.  
  598.                     current = int(current_options.get('gamma', 1000))
  599.  
  600.                     log.debug("  Option: gamma")
  601.                     log.debug("  Current value: %s" % current)
  602.  
  603.                     self.addControlRow("gamma", self.__tr("Gamma"), cups.UI_SPINNER, current,
  604.                         (1, 10000), 1000)
  605.  
  606.                     self.endControlGroup()
  607.  
  608.                 # Margins (pts)
  609.                     # page-left
  610.                     # page-right
  611.                     # page-top
  612.                     # page-bottom
  613.  
  614. ##                if 0:
  615. ##                    # TODO: cupsPPDPageSize() fails on LaserJets. How do we get margins in this case? Defaults?
  616. ##                    # PPD file for LJs has a HWMargin entry...
  617. ##                    page, page_width, page_len, left, bottom, right, top = cups.getPPDPageSize()
  618. ##
  619. ##                    right = page_width - right
  620. ##                    top = page_len - top
  621. ##
  622. ##                    self.addGroupHeading("margins", self.__tr("Margins"))
  623. ##                    current_top = current_options.get('page-top', 0) # pts
  624. ##                    current_bottom = current_options.get('page-bottom', 0) # pts
  625. ##                    current_left = current_options.get('page-left', 0) # pts
  626. ##                    current_right = current_options.get('page-right', 0) # pts
  627. ##
  628. ##                    log.debug("  Option: page-top")
  629. ##                    log.debug("  Current value: %s" % current_top)
  630. ##
  631. ##                    self.addControlRow("margins", "page-top", self.__tr("Top margin"),
  632. ##                        cups.UI_UNITS_SPINNER, current_top,
  633. ##                        (0, page_len), top)
  634. ##
  635. ##                    self.addControlRow("margins", "page-bottom", self.__tr("Bottom margin"),
  636. ##                        cups.UI_UNITS_SPINNER, current_bottom,
  637. ##                        (0, page_len), bottom)
  638. ##
  639. ##                    self.addControlRow("margins", "page-left", self.__tr("Right margin"),
  640. ##                        cups.UI_UNITS_SPINNER, current_left,
  641. ##                        (0, page_width), left)
  642. ##
  643. ##                    self.addControlRow("margins", "page-right", self.__tr("Left margin"),
  644. ##                        cups.UI_UNITS_SPINNER, current_right,
  645. ##                        (0, page_width), right)
  646.  
  647.                 # Image Printing
  648.                     # position
  649.                     # natural-scaling
  650.                     # saturation
  651.                     # hue
  652.  
  653.                 self.beginControlGroup("image", self.__tr("Image Printing"))
  654.  
  655.                 current = utils.to_bool(current_options.get('fitplot', 'false'))
  656.  
  657.                 self.addControlRow("fitplot",
  658.                     self.__tr("Fit to Page"),
  659.                     cups.PPD_UI_BOOLEAN, current,
  660.                     [], 0)
  661.  
  662.                 current = current_options.get('position', 'center')
  663.  
  664.                 self.addControlRow("position", self.__tr("Position on Page"),
  665.                     cups.PPD_UI_PICKONE, current,
  666.                     [('center', self.__tr('Centered')),
  667.                      ('top', self.__tr('Top')),
  668.                      ('left', self.__tr('Left')),
  669.                      ('right', self.__tr('Right')),
  670.                      ('top-left', self.__tr('Top left')),
  671.                      ('top-right', self.__tr('Top right')),
  672.                      ('bottom', self.__tr('Bottom')),
  673.                      ('bottom-left', self.__tr('Bottom left')),
  674.                      ('bottom-right', self.__tr('Bottom right'))], 'center')
  675.  
  676.                 log.debug("  Option: position")
  677.                 log.debug("  Current value: %s" % current)
  678.  
  679.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  680.                     current = int(current_options.get('saturation', 100))
  681.  
  682.                     log.debug("  Option: saturation")
  683.                     log.debug("  Current value: %s" % current)
  684.  
  685.                     self.addControlRow("saturation", self.__tr("Saturation"),
  686.                         cups.UI_SPINNER, current, (0, 200), 100, suffix=" %")
  687.  
  688.                     current = int(current_options.get('hue', 0))
  689.  
  690.                     log.debug("  Option: hue")
  691.                     log.debug("  Current value: %s" % current)
  692.  
  693.                     self.addControlRow("hue", self.__tr("Hue (color shift/rotation)"),
  694.                         cups.UI_SPINNER, current,
  695.                         (-100, 100), 0)
  696.  
  697.                 current = int(current_options.get('natural-scaling', 100))
  698.  
  699.                 log.debug("  Option: natural-scaling")
  700.                 log.debug("  Current value: %s" % current)
  701.  
  702.                 self.addControlRow("natural-scaling",
  703.                     self.__tr('"Natural" Scaling (relative to image)'),
  704.                     cups.UI_SPINNER, current, (1, 800), 100, suffix=" %")
  705.  
  706.                 current = int(current_options.get('scaling', 100))
  707.  
  708.                 log.debug("  Option: scaling")
  709.                 log.debug("  Current value: %s" % current)
  710.  
  711.                 self.addControlRow("scaling", self.__tr("Scaling (relative to page)"),
  712.                     cups.UI_SPINNER, current,
  713.                     (1, 800), 100, suffix=" %")
  714.  
  715.                 self.endControlGroup()
  716.  
  717.                 # Misc
  718.                     # PrettyPrint
  719.                     # job-sheets
  720.                     # mirror
  721.  
  722.                 self.beginControlGroup("misc", self.__tr("Miscellaneous"))
  723.  
  724.                 log.debug("Group: Misc")
  725.  
  726.                 current = utils.to_bool(current_options.get('prettyprint', '0'))
  727.  
  728.                 self.addControlRow("prettyprint",
  729.                     self.__tr('"Pretty Print" Text Documents (Add headers and formatting)'),
  730.                     cups.PPD_UI_BOOLEAN, current, [], 0)
  731.  
  732.                 log.debug("  Option: prettyprint")
  733.                 log.debug("  Current value: %s" % current)
  734.  
  735.                 if not self.cur_device.device_type == DEVICE_TYPE_FAX:
  736.                     current = current_options.get('job-sheets', 'none').split(',')
  737.  
  738.                     try:
  739.                         start = current[0]
  740.                     except IndexError:
  741.                         start = 'none'
  742.  
  743.                     try:
  744.                         end = current[1]
  745.                     except IndexError:
  746.                         end = 'none'
  747.  
  748.                     # TODO: Look for locally installed banner pages beyond the default CUPS ones?
  749.                     self.addControlRow("job-sheets", self.__tr("Banner Pages"), cups.UI_BANNER_JOB_SHEETS,
  750.                         (start, end),
  751.                         [("none", self.__tr("No banner page")),
  752.                          ('classified', self.__tr("Classified")),
  753.                          ('confidential', self.__tr("Confidential")),
  754.                          ('secret', self.__tr("Secret")),
  755.                          ('standard', self.__tr("Standard")),
  756.                          ('topsecret', self.__tr("Top secret")),
  757.                          ('unclassified', self.__tr("Unclassified"))], ('none', 'none'))
  758.  
  759.                     log.debug("  Option: job-sheets")
  760.                     log.debug("  Current value: %s,%s" % (start, end))
  761.  
  762.                 current = utils.to_bool(current_options.get('mirror', '0'))
  763.  
  764.                 self.addControlRow("mirror", self.__tr('Mirror Printing'),
  765.                     cups.PPD_UI_BOOLEAN, current, [], 0)
  766.  
  767.                 log.debug("  Option: mirror")
  768.                 log.debug("  Current value: %s" % current)
  769.  
  770.                 self.endControlGroup()
  771.  
  772.                 self.job_storage_enable = self.cur_device.mq.get('job-storage', JOB_STORAGE_DISABLE) == JOB_STORAGE_ENABLE
  773.  
  774.  
  775.                 if self.job_storage_enable:
  776.                     self.job_storage_pin = unicode(current_options.get('HOLDKEY', '0000')[:4])
  777.                     self.job_storage_username = unicode(current_options.get('USERNAME', prop.username)[:16])
  778.                     self.job_storage_jobname = unicode(current_options.get('JOBNAME', u'Untitled')[:16])
  779.                     hold = unicode(current_options.get('HOLD', u'OFF'))
  780.                     holdtype = unicode(current_options.get('HOLDTYPE', u'PUBLIC'))
  781.                     self.job_storage_use_pin = False
  782.                     duplicate = unicode(current_options.get('DUPLICATEJOB', u'REPLACE'))
  783.                     self.job_storage_auto_username = True
  784.                     self.job_storage_auto_jobname = True
  785.                     self.job_storage_mode = JOB_STORAGE_TYPE_OFF
  786.  
  787.                     if hold == 'OFF':
  788.                         self.job_storage_mode = JOB_STORAGE_TYPE_OFF
  789.  
  790.                     elif hold == 'ON':
  791.                         if holdtype == u'PUBLIC':
  792.                             self.job_storage_mode = JOB_STORAGE_TYPE_QUICK_COPY
  793.  
  794.                         else: # 'PRIVATE'
  795.                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
  796.                             self.job_storage_use_pin = True
  797.  
  798.                     elif hold == u'PROOF':
  799.                         if holdtype == u'PUBLIC':
  800.                             self.job_storage_mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD
  801.                         else:
  802.                             self.job_storage_mode = JOB_STORAGE_TYPE_PERSONAL
  803.                             self.job_storage_use_pin = True
  804.  
  805.                     elif hold == u'STORE':
  806.                         self.job_storage_mode = JOB_STORAGE_TYPE_STORE
  807.                         self.job_storage_use_pin = (holdtype == u'PRIVATE')
  808.  
  809.                     if duplicate == u'REPLACE':
  810.                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_REPLACE
  811.                     else: # u'APPEND'
  812.                         self.job_storage_job_exist = JOB_STORAGE_EXISTING_JOB_APPEND_1_99
  813.  
  814.                     # option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False)
  815.  
  816.                     self.beginControlGroup("jobstorage", self.__tr("Job Storage and Secure Printing"))
  817.  
  818.                     self.addControlRow("job-storage-mode", self.__tr("Mode"),
  819.                                        cups.UI_JOB_STORAGE_MODE, None, None, None)
  820.  
  821.                     self.addControlRow("job-storage-pin", self.__tr("Make job private (use PIN to print)"),
  822.                                       cups.UI_JOB_STORAGE_PIN, None, None, None )
  823.  
  824.                     self.addControlRow("job-storage-username", self.__tr("User name (for job identification)"),
  825.                                        cups.UI_JOB_STORAGE_USERNAME, None, None, None)
  826.  
  827.                     self.addControlRow("job-storage-id", self.__tr("Job name/ID (for job identification)"),
  828.                                       cups.UI_JOB_STORAGE_ID, None, None, None)
  829.  
  830.                     self.addControlRow("job-storage-id-exists", self.__tr("If job name/ID already exists..."),
  831.                                        cups.UI_JOB_STORAGE_ID_EXISTS, None, None, None)
  832.  
  833.                     self.endControlGroup()
  834.                     self.updateJobStorageControls()
  835.  
  836.                 # use: self.job_options['xxx'] so that values can be picked up by getPrintCommand(
  837.  
  838.  
  839.             #except Exception, e:
  840.                 #log.exception()
  841.             #    pass
  842.  
  843.         finally:
  844.             cups.closePPD()
  845.             self.loading = False
  846.  
  847.  
  848.     def beginControlGroup(self, group, text):
  849.         log.debug("BeginGroup: %s" % group)
  850.         self.row = 0
  851.         self.widget = QWidget()
  852.         self.gridlayout = QGridLayout(self.widget)
  853.         self.group = group
  854.         self.text = text
  855.  
  856.  
  857.     def endControlGroup(self):
  858.         log.debug("EndGroup: %s" % self.group)
  859.         spacer = QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
  860.         self.row += 1
  861.         self.gridlayout.addItem(spacer, self.row, 0, 1, 1)
  862.         i = self.addItem(self.widget, self.text)
  863.  
  864.         if i:
  865.             self.setItemIcon(i, self.plus_icon)
  866.         else:
  867.             self.setItemIcon(i, self.minus_icon)
  868.  
  869.         self.widget, self.gridlayout = None, None
  870.  
  871.  
  872.     def addControlRow(self, option, text, typ, value, choices, default, read_only=False, suffix="", job_option=False):
  873.  
  874.         if typ == cups.PPD_UI_BOOLEAN: # () On (*) Off widget
  875.             HBoxLayout = QHBoxLayout()
  876.             HBoxLayout.setObjectName("HBoxLayout")
  877.  
  878.             OptionLabel = QLabel(self.widget)
  879.             OptionLabel.setObjectName("OptionLabel")
  880.             HBoxLayout.addWidget(OptionLabel)
  881.  
  882.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  883.             HBoxLayout.addItem(SpacerItem)
  884.  
  885.             GroupBox = QFrame(self.widget)
  886.  
  887.             gridlayout1 = QGridLayout(GroupBox)
  888.             OnRadioButton = OptionRadioButton(GroupBox, "OnRadioButton", self.group,
  889.                                               option, default, job_option)
  890.             gridlayout1.addWidget(OnRadioButton,0,0,1,1)
  891.             OffRadioButton = OptionRadioButton(GroupBox, "OffRadioButton", self.group,
  892.                                                option, default, job_option)
  893.             gridlayout1.addWidget(OffRadioButton,0,1,1,1)
  894.             HBoxLayout.addWidget(GroupBox)
  895.  
  896.             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
  897.                 choices, default, (OnRadioButton, OffRadioButton), typ, job_option)
  898.  
  899.             #GroupBox.setDefaultPushbutton(DefaultButton)
  900.             OnRadioButton.setDefaultPushbutton(DefaultButton)
  901.             OffRadioButton.setDefaultPushbutton(DefaultButton)
  902.  
  903.             HBoxLayout.addWidget(DefaultButton)
  904.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  905.  
  906.             OptionLabel.setText(text)
  907.             OnRadioButton.setText(self.__tr("On"))
  908.             OffRadioButton.setText(self.__tr("Off"))
  909.  
  910.             DefaultButton.setText("Default")
  911.  
  912.             if value == default:
  913.                 DefaultButton.setEnabled(False)
  914.  
  915.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  916.             self.connect(OnRadioButton, SIGNAL("toggled(bool)"), self.BoolRadioButtons_clicked)
  917.  
  918.  
  919.             if value:
  920.                 OnRadioButton.setChecked(True)
  921.             else:
  922.                 OffRadioButton.setChecked(True)
  923.  
  924.             if read_only:
  925.                 OnRadioButton.setEnabled(False)
  926.                 OffRadioButton.setEnabled(False)
  927.                 DefaultButton.setEnabled(False)
  928.  
  929.  
  930.  
  931.         elif typ == cups.PPD_UI_PICKONE: # Combo box widget
  932.             #print option, job_option
  933.             HBoxLayout = QHBoxLayout()
  934.             HBoxLayout.setObjectName("HBoxLayout")
  935.  
  936.             OptionLabel = QLabel(self.widget)
  937.             OptionLabel.setObjectName("OptionLabel")
  938.             HBoxLayout.addWidget(OptionLabel)
  939.  
  940.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  941.             HBoxLayout.addItem(SpacerItem)
  942.  
  943.             ComboBox = OptionComboBox(0, self.widget, "ComboBox", self.group, option,
  944.                                       choices, default, typ, None, job_option)
  945.  
  946.             HBoxLayout.addWidget(ComboBox)
  947.  
  948.             DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
  949.                 choices, default, ComboBox, typ, job_option)
  950.  
  951.             ComboBox.setDefaultPushbutton(DefaultButton)
  952.             HBoxLayout.addWidget(DefaultButton)
  953.  
  954.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  955.  
  956.             OptionLabel.setText(text)
  957.             DefaultButton.setText("Default")
  958.  
  959.             i, x, y = 0, None, None
  960.             for c, t in choices:
  961.                 d = c.lower()
  962.                 if value is not None and d == value.lower():
  963.                     x = i
  964.  
  965.                 if d == default.lower():
  966.                     y = t
  967.  
  968.                 ComboBox.insertItem(i, t)
  969.                 i += 1
  970.  
  971.             if x is not None:
  972.                 ComboBox.setCurrentIndex(x)
  973.             else:
  974.                 ComboBox.setCurrentIndex(0)
  975.  
  976.             if value is not None and value.lower() == default.lower():
  977.                 DefaultButton.setEnabled(False)
  978.  
  979.             #self.linkPrintoutModeAndQuality(option, value)
  980. #
  981. #            if read_only:
  982. #                optionComboBox.setEnabled(False)
  983. #                defaultPushButton.setEnabled(False)
  984. #            elif y is not None:
  985. #                QToolTip.add(defaultPushButton, self.__tr('Set to default value of "%1".').arg(y))
  986. #
  987.  
  988.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  989.             self.connect(ComboBox, SIGNAL("highlighted(const QString &)"), self.ComboBox_highlighted)
  990.  
  991.             control = ComboBox
  992.  
  993.         elif typ == cups.UI_SPINNER: # Spinner widget
  994.  
  995.             HBoxLayout = QHBoxLayout()
  996.             HBoxLayout.setObjectName("HBoxLayout")
  997.  
  998.             OptionLabel = QLabel(self.widget)
  999.             OptionLabel.setObjectName("OptionLabel")
  1000.             HBoxLayout.addWidget(OptionLabel)
  1001.  
  1002.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1003.             HBoxLayout.addItem(SpacerItem)
  1004.  
  1005.             SpinBox = OptionSpinBox(self.widget,"SpinBox", self.group, option, default, job_option)
  1006.             HBoxLayout.addWidget(SpinBox)
  1007.  
  1008.             DefaultButton = DefaultPushButton(self.widget,"DefaultButton", self.group, option,
  1009.                 choices, default, SpinBox, typ, job_option)
  1010.  
  1011.             SpinBox.setDefaultPushbutton(DefaultButton)
  1012.             HBoxLayout.addWidget(DefaultButton)
  1013.  
  1014.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1015.  
  1016.             min, max = choices
  1017.             SpinBox.setMinimum(min)
  1018.             SpinBox.setMaximum(max)
  1019.             SpinBox.setValue(value)
  1020.  
  1021.             if suffix:
  1022.                 SpinBox.setSuffix(suffix)
  1023.  
  1024.             OptionLabel.setText(text)
  1025.             DefaultButton.setText("Default")
  1026.  
  1027.             self.connect(SpinBox, SIGNAL("valueChanged(int)"), self.SpinBox_valueChanged)
  1028.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1029.  
  1030.             DefaultButton.setEnabled(not value == default)
  1031.  
  1032.             if read_only:
  1033.                 SpinBox.setEnabled(False)
  1034.                 DefaultButton.setEnabled(False)
  1035.  
  1036.         elif typ == cups.UI_BANNER_JOB_SHEETS:  # Job sheets widget
  1037.             HBoxLayout = QHBoxLayout()
  1038.             HBoxLayout.setObjectName("HBoxLayout")
  1039.  
  1040.             OptionLabel = QLabel(self.widget)
  1041.             OptionLabel.setObjectName("OptionLabel")
  1042.             HBoxLayout.addWidget(OptionLabel)
  1043.  
  1044.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1045.             HBoxLayout.addItem(SpacerItem)
  1046.  
  1047.             StartLabel = QLabel(self.widget)
  1048.             HBoxLayout.addWidget(StartLabel)
  1049.  
  1050.             StartComboBox = OptionComboBox(0, self.widget, "StartComboBox", self.group,
  1051.                 "start", choices, default, typ)
  1052.  
  1053.             HBoxLayout.addWidget(StartComboBox)
  1054.  
  1055.             EndLabel = QLabel(self.widget)
  1056.             HBoxLayout.addWidget(EndLabel)
  1057.  
  1058.             EndComboBox = OptionComboBox(0, self.widget, "EndComboBox", self.group, "end", choices,
  1059.                 default, typ, StartComboBox)
  1060.  
  1061.             HBoxLayout.addWidget(EndComboBox)
  1062.  
  1063.             StartComboBox.setOther(EndComboBox)
  1064.  
  1065.             DefaultButton = DefaultPushButton(self.widget, "DefaultButton", self.group, option, choices,
  1066.                 default, (StartComboBox, EndComboBox), typ, job_option)
  1067.  
  1068.             HBoxLayout.addWidget(DefaultButton)
  1069.  
  1070.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1071.  
  1072.             StartComboBox.setDefaultPushbutton(DefaultButton)
  1073.             EndComboBox.setDefaultPushbutton(DefaultButton)
  1074.  
  1075.             OptionLabel.setText(text)
  1076.             DefaultButton.setText("Default")
  1077.  
  1078.             StartLabel.setText(self.__tr("Start:"))
  1079.             EndLabel.setText(self.__tr("End:"))
  1080.  
  1081.             s, e, y, z = None, None, None, None
  1082.             for c, t in choices:
  1083.                 d = c.lower()
  1084.                 if value is not None:
  1085.                     if d == value[0].lower():
  1086.                         s = t
  1087.  
  1088.                     if d == value[1].lower():
  1089.                         e = t
  1090.  
  1091.                 if d == default[0].lower():
  1092.                     y = t
  1093.  
  1094.                 if d == default[1].lower():
  1095.                     z = t
  1096.  
  1097.                 StartComboBox.insertItem(0, t)
  1098.                 EndComboBox.insertItem(0, t)
  1099.  
  1100.             if s is not None:
  1101.                 StartComboBox.setCurrentIndex(StartComboBox.findText(s))
  1102.  
  1103.             if e is not None:
  1104.                 EndComboBox.setCurrentIndex(EndComboBox.findText(e))
  1105.  
  1106.             if value is not None and \
  1107.                 value[0].lower() == default[0].lower() and \
  1108.                 value[1].lower() == default[1].lower():
  1109.  
  1110.                 DefaultButton.setEnabled(False)
  1111.  
  1112.             self.connect(StartComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
  1113.             self.connect(EndComboBox, SIGNAL("activated(const QString&)"), self.BannerComboBox_activated)
  1114.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1115.  
  1116.         elif typ == cups.PPD_UI_PICKMANY:
  1117.             log.error("Unrecognized type: pickmany")
  1118.  
  1119.         elif typ == cups.UI_UNITS_SPINNER:
  1120.             log.error("Unrecognized type: units spinner")
  1121.  
  1122.         elif typ == cups.UI_PAGE_RANGE:
  1123.             HBoxLayout = QHBoxLayout()
  1124.             HBoxLayout.setObjectName("HBoxLayout")
  1125.  
  1126.             OptionLabel = QLabel(self.widget)
  1127.             OptionLabel.setObjectName("OptionLabel")
  1128.             HBoxLayout.addWidget(OptionLabel)
  1129.  
  1130.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1131.             HBoxLayout.addItem(SpacerItem)
  1132.  
  1133.             GroupBox = QFrame(self.widget)
  1134.  
  1135.             gridlayout1 = QGridLayout(GroupBox)
  1136.  
  1137.             AllRadioButton = PageRangeRadioButton(GroupBox, "AllRadioButton",
  1138.                                                self.group, option, default)
  1139.  
  1140.             gridlayout1.addWidget(AllRadioButton,0,0,1,1)
  1141.             RangeRadioButton = PageRangeRadioButton(GroupBox, "RangeRadioButton",
  1142.                                                  self.group, option, default)
  1143.  
  1144.             gridlayout1.addWidget(RangeRadioButton,0,1,1,1)
  1145.             HBoxLayout.addWidget(GroupBox)
  1146.  
  1147.             PageRangeEdit = QLineEdit(self.widget)
  1148.             HBoxLayout.addWidget(PageRangeEdit)
  1149.             PageRangeEdit.setValidator(RangeValidator(PageRangeEdit))
  1150.  
  1151.             AllRadioButton.setRangeEdit(PageRangeEdit)
  1152.             RangeRadioButton.setRangeEdit(PageRangeEdit)
  1153.  
  1154.             DefaultButton = DefaultPushButton(self.widget, "defaultPushButton", self.group, option,
  1155.                 choices, default, (AllRadioButton, RangeRadioButton, PageRangeEdit), typ, job_option)
  1156.  
  1157.             AllRadioButton.setDefaultPushbutton(DefaultButton)
  1158.             RangeRadioButton.setDefaultPushbutton(DefaultButton)
  1159.  
  1160.             HBoxLayout.addWidget(DefaultButton)
  1161.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1162.  
  1163.             OptionLabel.setText(text)
  1164.             AllRadioButton.setText(self.__tr("All pages"))
  1165.             RangeRadioButton.setText(self.__tr("Page Range:"))
  1166.  
  1167.             DefaultButton.setText("Default")
  1168.             DefaultButton.setEnabled(False)
  1169.  
  1170.             AllRadioButton.setChecked(True)
  1171.             PageRangeEdit.setEnabled(False)
  1172.  
  1173.             # TODO: Set current
  1174.  
  1175.             self.connect(AllRadioButton, SIGNAL("toggled(bool)"), self.PageRangeAllRadio_toggled)
  1176.             self.connect(RangeRadioButton, SIGNAL("toggled(bool)"), self.PageRangeRangeRadio_toggled)
  1177.             self.connect(DefaultButton, SIGNAL("clicked()"), self.DefaultButton_clicked)
  1178.             self.connect(PageRangeEdit, SIGNAL("textChanged(const QString &)"), self.PageRangeEdit_textChanged)
  1179.             self.connect(PageRangeEdit, SIGNAL("editingFinished()"), self.PageRangeEdit_editingFinished)
  1180.  
  1181.         elif typ == cups.UI_JOB_STORAGE_MODE:
  1182.             HBoxLayout = QHBoxLayout()
  1183.             HBoxLayout.setObjectName("HBoxLayout")
  1184.  
  1185.             OptionLabel = QLabel(self.widget)
  1186.             OptionLabel.setObjectName("OptionLabel")
  1187.             HBoxLayout.addWidget(OptionLabel)
  1188.  
  1189.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1190.             HBoxLayout.addItem(SpacerItem)
  1191.  
  1192.             self.JobStorageModeComboBox = QComboBox(self.widget)
  1193.             HBoxLayout.addWidget(self.JobStorageModeComboBox)
  1194.  
  1195.             self.JobStorageModeDefaultButton = QPushButton(self.widget)
  1196.             HBoxLayout.addWidget(self.JobStorageModeDefaultButton)
  1197.  
  1198.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1199.  
  1200.             OptionLabel.setText(text)
  1201.             self.JobStorageModeDefaultButton.setText(self.__tr("Default"))
  1202.  
  1203.             self.JobStorageModeComboBox.addItem(self.__tr("Off/Disabled"), QVariant(JOB_STORAGE_TYPE_OFF))
  1204.             self.JobStorageModeComboBox.addItem(self.__tr("Proof and Hold"), QVariant(JOB_STORAGE_TYPE_PROOF_AND_HOLD))
  1205.             self.JobStorageModeComboBox.addItem(self.__tr("Personal/Private Job"), QVariant(JOB_STORAGE_TYPE_PERSONAL))
  1206.             self.JobStorageModeComboBox.addItem(self.__tr("Quick Copy"), QVariant(JOB_STORAGE_TYPE_QUICK_COPY))
  1207.             self.JobStorageModeComboBox.addItem(self.__tr("Stored Job"), QVariant(JOB_STORAGE_TYPE_STORE))
  1208.  
  1209.             self.connect(self.JobStorageModeComboBox, SIGNAL("activated(int)"),
  1210.                         self.JobStorageModeComboBox_activated)
  1211.  
  1212.             self.connect(self.JobStorageModeDefaultButton, SIGNAL("clicked()"),
  1213.                         self.JobStorageModeDefaultButton_clicked)
  1214.  
  1215.  
  1216.         elif typ == cups.UI_JOB_STORAGE_PIN:
  1217.             HBoxLayout = QHBoxLayout()
  1218.             HBoxLayout.setObjectName("HBoxLayout")
  1219.  
  1220.             OptionLabel = QLabel(self.widget)
  1221.             OptionLabel.setObjectName("OptionLabel")
  1222.             HBoxLayout.addWidget(OptionLabel)
  1223.  
  1224.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1225.             HBoxLayout.addItem(SpacerItem)
  1226.  
  1227.             self.JobStoragePinGroupBox = QFrame(self.widget)
  1228.  
  1229.             gridlayout1 = QGridLayout(self.JobStoragePinGroupBox)
  1230.             self.JobStoragePinOffRadioButton = QRadioButton(self.JobStoragePinGroupBox)
  1231.             gridlayout1.addWidget(self.JobStoragePinOffRadioButton, 0, 0, 1, 1)
  1232.  
  1233.             self.JobStoragePinPrivateRadioButton = QRadioButton(self.JobStoragePinGroupBox)
  1234.             gridlayout1.addWidget(self.JobStoragePinPrivateRadioButton, 0, 1, 1, 1)
  1235.  
  1236.             self.JobStoragePinEdit = QLineEdit(self.JobStoragePinGroupBox)
  1237.             self.JobStoragePinEdit.setMaxLength(4)
  1238.             self.JobStoragePinEdit.setValidator(PinValidator(self.JobStoragePinEdit))
  1239.             gridlayout1.addWidget(self.JobStoragePinEdit, 0, 2, 1, 1)
  1240.  
  1241.             HBoxLayout.addWidget(self.JobStoragePinGroupBox)
  1242.  
  1243.             self.JobStoragePinDefaultButton = QPushButton(self.widget)
  1244.             HBoxLayout.addWidget(self.JobStoragePinDefaultButton)
  1245.  
  1246.             self.JobStoragePinOffRadioButton.setText(self.__tr("Public/Off"))
  1247.             self.JobStoragePinPrivateRadioButton.setText(self.__tr("Private/Use PIN:"))
  1248.  
  1249.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1250.  
  1251.             OptionLabel.setText(text)
  1252.             self.JobStoragePinDefaultButton.setText(self.__tr("Default"))
  1253.  
  1254.             self.connect(self.JobStoragePinOffRadioButton, SIGNAL("toggled(bool)"),
  1255.                             self.JobStoragePinOffRadioButton_toggled)
  1256.  
  1257.             self.connect(self.JobStoragePinPrivateRadioButton, SIGNAL("toggled(bool)"),
  1258.                             self.JobStoragePinPrivateRadioButton_toggled)
  1259.  
  1260.             self.connect(self.JobStoragePinDefaultButton, SIGNAL("clicked()"),
  1261.                             self.JobStoragePinDefaultButton_clicked)
  1262.  
  1263.             self.connect(self.JobStoragePinEdit, SIGNAL("textEdited(const QString &)"),
  1264.                         self.JobStoragePinEdit_textEdited)
  1265.  
  1266.  
  1267.         elif typ == cups.UI_JOB_STORAGE_USERNAME:
  1268.             HBoxLayout = QHBoxLayout()
  1269.             HBoxLayout.setObjectName("HBoxLayout")
  1270.  
  1271.             OptionLabel = QLabel(self.widget)
  1272.             OptionLabel.setObjectName("OptionLabel")
  1273.             HBoxLayout.addWidget(OptionLabel)
  1274.             OptionLabel.setText(text)
  1275.  
  1276.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1277.             HBoxLayout.addItem(SpacerItem)
  1278.  
  1279.             self.JobStorageUsernameGroupBox = QFrame(self.widget)
  1280.  
  1281.             gridlayout1 = QGridLayout(self.JobStorageUsernameGroupBox)
  1282.             self.JobStorageUsernameAutoRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
  1283.             gridlayout1.addWidget(self.JobStorageUsernameAutoRadioButton, 0, 0, 1, 1)
  1284.  
  1285.             self.JobStorageUsernameCustomRadioButton = QRadioButton(self.JobStorageUsernameGroupBox)
  1286.             gridlayout1.addWidget(self.JobStorageUsernameCustomRadioButton, 0, 1, 1, 1)
  1287.  
  1288.             self.JobStorageUsernameEdit = QLineEdit(self.JobStorageUsernameGroupBox)
  1289.             self.JobStorageUsernameEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageUsernameEdit))
  1290.             self.JobStorageUsernameEdit.setMaxLength(16)
  1291.             gridlayout1.addWidget(self.JobStorageUsernameEdit, 0, 2, 1, 1)
  1292.  
  1293.             HBoxLayout.addWidget(self.JobStorageUsernameGroupBox)
  1294.  
  1295.             self.JobStorageUsernameDefaultButton = QPushButton(self.widget)
  1296.             HBoxLayout.addWidget(self.JobStorageUsernameDefaultButton)
  1297.  
  1298.             self.JobStorageUsernameAutoRadioButton.setText(self.__tr("Automatic"))
  1299.             self.JobStorageUsernameCustomRadioButton.setText(self.__tr("Custom:"))
  1300.             self.JobStorageUsernameDefaultButton.setText(self.__tr("Default"))
  1301.  
  1302.             self.connect(self.JobStorageUsernameAutoRadioButton, SIGNAL("toggled(bool)"),
  1303.                             self.JobStorageUsernameAutoRadioButton_toggled)
  1304.  
  1305.             self.connect(self.JobStorageUsernameCustomRadioButton, SIGNAL("toggled(bool)"),
  1306.                             self.JobStorageUsernameCustomRadioButton_toggled)
  1307.  
  1308.             self.connect(self.JobStorageUsernameDefaultButton, SIGNAL("clicked()"),
  1309.                         self.JobStorageUsernameDefaultButton_clicked)
  1310.  
  1311.             self.connect(self.JobStorageUsernameEdit, SIGNAL("textEdited(const QString &)"),
  1312.                         self.JobStorageUsernameEdit_textEdited)
  1313.  
  1314.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1315.  
  1316.         elif typ == cups.UI_JOB_STORAGE_ID:
  1317.             HBoxLayout = QHBoxLayout()
  1318.             HBoxLayout.setObjectName("HBoxLayout")
  1319.  
  1320.             OptionLabel = QLabel(self.widget)
  1321.             OptionLabel.setObjectName("OptionLabel")
  1322.             HBoxLayout.addWidget(OptionLabel)
  1323.             OptionLabel.setText(text)
  1324.  
  1325.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1326.             HBoxLayout.addItem(SpacerItem)
  1327.  
  1328.             self.JobStorageIDGroupBox = QFrame(self.widget)
  1329.  
  1330.             gridlayout1 = QGridLayout(self.JobStorageIDGroupBox)
  1331.             self.JobStorageIDAutoRadioButton = QRadioButton(self.JobStorageIDGroupBox)
  1332.             gridlayout1.addWidget(self.JobStorageIDAutoRadioButton, 0, 0, 1, 1)
  1333.  
  1334.             self.JobStorageIDCustomRadioButton = QRadioButton(self.JobStorageIDGroupBox)
  1335.             gridlayout1.addWidget(self.JobStorageIDCustomRadioButton, 0, 1, 1, 1)
  1336.  
  1337.             self.JobStorageIDEdit = QLineEdit(self.JobStorageIDGroupBox)
  1338.             self.JobStorageIDEdit.setValidator(UsernameAndJobnameValidator(self.JobStorageIDEdit))
  1339.             self.JobStorageIDEdit.setMaxLength(16)
  1340.             gridlayout1.addWidget(self.JobStorageIDEdit, 0, 2, 1, 1)
  1341.  
  1342.             HBoxLayout.addWidget(self.JobStorageIDGroupBox)
  1343.  
  1344.             self.JobStorageIDDefaultButton = QPushButton(self.widget)
  1345.             HBoxLayout.addWidget(self.JobStorageIDDefaultButton)
  1346.  
  1347.             self.JobStorageIDAutoRadioButton.setText(self.__tr("Automatic"))
  1348.             self.JobStorageIDCustomRadioButton.setText(self.__tr("Custom:"))
  1349.             self.JobStorageIDDefaultButton.setText(self.__tr("Default"))
  1350.  
  1351.             self.connect(self.JobStorageIDAutoRadioButton, SIGNAL("toggled(bool)"),
  1352.                             self.JobStorageIDAutoRadioButton_toggled)
  1353.  
  1354.             self.connect(self.JobStorageIDCustomRadioButton, SIGNAL("toggled(bool)"),
  1355.                             self.JobStorageIDCustomRadioButton_toggled)
  1356.  
  1357.             self.connect(self.JobStorageIDDefaultButton, SIGNAL("clicked()"),
  1358.                         self.JobStorageIDDefaultButton_clicked)
  1359.  
  1360.             self.connect(self.JobStorageIDEdit, SIGNAL("textEdited(const QString &)"),
  1361.                         self.JobStorageIDEdit_textEdited)
  1362.  
  1363.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1364.  
  1365.         elif typ == cups.UI_JOB_STORAGE_ID_EXISTS:
  1366.             HBoxLayout = QHBoxLayout()
  1367.             HBoxLayout.setObjectName("HBoxLayout")
  1368.  
  1369.             OptionLabel = QLabel(self.widget)
  1370.             OptionLabel.setObjectName("OptionLabel")
  1371.             HBoxLayout.addWidget(OptionLabel)
  1372.             OptionLabel.setText(text)
  1373.  
  1374.             SpacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1375.             HBoxLayout.addItem(SpacerItem)
  1376.  
  1377.             self.JobStorageExistingComboBox = QComboBox(self.widget)
  1378.             HBoxLayout.addWidget(self.JobStorageExistingComboBox)
  1379.  
  1380.             self.JobStorageExistingDefaultButton = QPushButton(self.widget)
  1381.             HBoxLayout.addWidget(self.JobStorageExistingDefaultButton)
  1382.  
  1383.             self.JobStorageExistingComboBox.addItem(self.__tr("Replace existing job"),
  1384.                              QVariant(JOB_STORAGE_EXISTING_JOB_REPLACE))
  1385.  
  1386.             self.JobStorageExistingComboBox.addItem(self.__tr("Use job name appended with 1-99"),
  1387.                              QVariant(JOB_STORAGE_EXISTING_JOB_APPEND_1_99))
  1388.  
  1389.             self.JobStorageExistingDefaultButton.setText(self.__tr("Default"))
  1390.  
  1391.             self.gridlayout.addLayout(HBoxLayout, self.row, 0, 1, 1)
  1392.  
  1393.             self.connect(self.JobStorageExistingComboBox, SIGNAL("activated(int)"),
  1394.                         self.JobStorageExistingComboBox_activated)
  1395.  
  1396.             self.connect(self.JobStorageExistingDefaultButton, SIGNAL("clicked()"),
  1397.                         self.JobStorageExistingDefaultButton_clicked)
  1398.  
  1399.         else:
  1400.             log.error("Invalid UI value: %s/%s" % (self.group, option))
  1401.  
  1402.         self.row += 1
  1403.  
  1404.  
  1405.  
  1406.     def BannerComboBox_activated(self, a): # cups.UI_BANNER_JOB_SHEETS
  1407.         a = unicode(a)
  1408.         sender = self.sender()
  1409.         choice = None
  1410.  
  1411.         start, end = None, None
  1412.         for c, t in sender.choices:
  1413.             if t == a:
  1414.                 start = c
  1415.                 break
  1416.  
  1417.         for c, t in sender.other.choices:
  1418.             if t == sender.other.currentText():
  1419.                 end = c
  1420.                 break
  1421.  
  1422.         if sender.option == 'end':
  1423.             start, end = end, start
  1424.  
  1425.         if start is not None and \
  1426.             end is not None and \
  1427.             start.lower() == sender.default[0].lower() and \
  1428.             end.lower() == sender.default[1].lower():
  1429.                 self.removePrinterOption('job-sheets')
  1430.                 sender.pushbutton.setEnabled(False)
  1431.         else:
  1432.             sender.pushbutton.setEnabled(True)
  1433.  
  1434.             if start is not None and \
  1435.                 end is not None:
  1436.  
  1437.                 self.setPrinterOption('job-sheets', ','.join([start, end]))
  1438.  
  1439.  
  1440.     def ComboBox_highlighted(self, t):
  1441.         t = unicode(t)
  1442.         sender = self.sender()
  1443.         choice = None
  1444.  
  1445.         #print sender, sender.option, sender.job_option
  1446.  
  1447.         choice = None
  1448.         for c, a in sender.choices:
  1449.             if a == t:
  1450.                 choice = c
  1451.                 break
  1452.  
  1453.         if choice is not None and choice == sender.default:
  1454.             if sender.job_option:
  1455.                 self.job_options[sender.option] = sender.default
  1456.             else:
  1457.                 self.removePrinterOption(sender.option)
  1458.             sender.pushbutton.setEnabled(False)
  1459.  
  1460.         else:
  1461.             sender.pushbutton.setEnabled(True)
  1462.  
  1463.             if choice is not None:
  1464.                 if sender.job_option:
  1465.                     self.job_options[sender.option] = choice
  1466.                 else:
  1467.                     self.setPrinterOption(sender.option, choice)
  1468.  
  1469.             #self.linkPrintoutModeAndQuality(sender.option, choice)
  1470.  
  1471.     if 0:
  1472.         pass
  1473.         #    def linkPrintoutModeAndQuality(self, option, choice):
  1474.         #        if option.lower() == 'quality' and \
  1475.         #            choice is not None:
  1476.         #
  1477.         #            try:
  1478.         #                c = self.items['o:PrintoutMode'].control
  1479.         #            except KeyError:
  1480.         #                return
  1481.         #            else:
  1482.         #                if c is not None:
  1483.         #                    if choice.lower() == 'fromprintoutmode':
  1484.         #                        # from printoutmode selected
  1485.         #                        # determine printoutmode option combo enable state
  1486.         #                        c.setEnabled(True)
  1487.         #                        QToolTip.remove(c)
  1488.         #                        a = unicode(c.currentText())
  1489.         #
  1490.         #                        # determine printoutmode default button state
  1491.         #                        link_choice = None
  1492.         #                        for x, t in c.choices:
  1493.         #                            if t == a:
  1494.         #                                link_choice = x
  1495.         #                                break
  1496.         #
  1497.         #                        if link_choice is not None and \
  1498.         #                            link_choice.lower() == c.default.lower():
  1499.         #
  1500.         #                            c.pushbutton.setEnabled(False)
  1501.         #                        else:
  1502.         #                            c.pushbutton.setEnabled(True)
  1503.         #
  1504.         #                    else: # fromprintoutmode not selected, disable printoutmode
  1505.         #                        c.setEnabled(False)
  1506.         #                        QToolTip.add(c, self.__tr("""Set Quality to "Controlled by 'Printout Mode'" to enable."""))
  1507.         #                        c.pushbutton.setEnabled(False)
  1508.         #
  1509.  
  1510.     def SpinBox_valueChanged(self, i): # cups.UI_SPINNER
  1511.         sender = self.sender()
  1512.  
  1513.         if not sender.job_option:
  1514.             if i == sender.default:
  1515.                 self.removePrinterOption(sender.option)
  1516.                 sender.pushbutton.setEnabled(False)
  1517.             else:
  1518.                 sender.pushbutton.setEnabled(True)
  1519.                 self.setPrinterOption(sender.option, str(i))
  1520.  
  1521.         else:
  1522.             try:
  1523.                 self.job_options[sender.option] = int(i)
  1524.             except ValueError:
  1525.                 self.job_options[sender.option] = sender.default
  1526.  
  1527.  
  1528.     def BoolRadioButtons_clicked(self, b): # cups.PPD_UI_BOOLEAN
  1529.         sender = self.sender()
  1530.         b = int(b)
  1531.  
  1532.         if b == sender.default:
  1533.             self.removePrinterOption(sender.option)
  1534.             sender.pushbutton.setEnabled(False)
  1535.         else:
  1536.             sender.pushbutton.setEnabled(True)
  1537.  
  1538.             if b:
  1539.                 self.setPrinterOption(sender.option, "true")
  1540.             else:
  1541.                 self.setPrinterOption(sender.option, "false")
  1542.  
  1543.  
  1544.     def DefaultButton_clicked(self):
  1545.         sender = self.sender()
  1546.         sender.setEnabled(False)
  1547.  
  1548.         if sender.typ == cups.PPD_UI_BOOLEAN: # () On  (*) Off
  1549.             if sender.default:
  1550.                 sender.control[0].setChecked(True)
  1551.                 sender.control[0].setFocus(Qt.OtherFocusReason)
  1552.             else:
  1553.                 sender.control[1].setChecked(True)
  1554.                 sender.control[1].setFocus(Qt.OtherFocusReason)
  1555.  
  1556.             if not sender.job_option:
  1557.                 self.removePrinterOption(sender.option)
  1558.  
  1559.         elif sender.typ == cups.PPD_UI_PICKONE: # [     \/]
  1560.             choice, text = None, None
  1561.  
  1562.             for c, t in sender.choices:
  1563.                 if c == sender.default:
  1564.                     choice = c
  1565.                     text = t
  1566.                     self.job_options[sender.option] = t
  1567.                     break
  1568.  
  1569.             if choice is not None:
  1570.                 if not sender.job_option:
  1571.                     self.removePrinterOption(sender.option)
  1572.                     index = sender.control.findText(text)
  1573.                     sender.control.setCurrentIndex(index)
  1574.  
  1575.                 #self.linkPrintoutModeAndQuality(sender.option, choice) # TODO:
  1576.                 sender.control.setFocus(Qt.OtherFocusReason)
  1577.  
  1578.         elif sender.typ == cups.UI_SPINNER: # [ x /\|\/]
  1579.             sender.control.setValue(sender.default)
  1580.             if not sender.job_option:
  1581.                 self.removePrinterOption(sender.option)
  1582.  
  1583.             sender.control.setFocus(Qt.OtherFocusReason)
  1584.  
  1585.         elif sender.typ == cups.UI_BANNER_JOB_SHEETS: # start: [     \/]  end: [     \/]
  1586.             start, end, start_text, end_text = None, None, None, None
  1587.             for c, t in sender.choices:
  1588.                 if c == sender.default[0]:
  1589.                     start = c
  1590.                     start_text = t
  1591.  
  1592.                 if c == sender.default[1]:
  1593.                     end = c
  1594.                     end_text = t
  1595.  
  1596.             if start is not None:
  1597.                 index = sender.control[0].findText(start_text)
  1598.                 sender.control[0].setCurrentIndex(index)
  1599.  
  1600.             if end is not None:
  1601.                 index = sender.control[1].findText(end_text)
  1602.                 sender.control[1].setCurrentIndex(index)
  1603.  
  1604.             if not sender.job_option:
  1605.                 self.removePrinterOption('job-sheets')
  1606.  
  1607.             sender.control[0].setFocus(Qt.OtherFocusReason)
  1608.  
  1609.         elif sender.typ == cups.UI_PAGE_RANGE: # (*) All () Pages: [    ]
  1610.             sender.control[0].setChecked(True) # all radio button
  1611.             sender.control[0].setFocus(Qt.OtherFocusReason)
  1612.             sender.control[2].setEnabled(False) # range edit box
  1613.  
  1614.  
  1615.     def PageRangeAllRadio_toggled(self, b):
  1616.         if b:
  1617.             sender = self.sender()
  1618.             sender.edit_control.setEnabled(False)
  1619.             sender.pushbutton.setEnabled(False)
  1620.             self.job_options['pagerange'] = ''
  1621.  
  1622.  
  1623.     def PageRangeRangeRadio_toggled(self, b):
  1624.         if b:
  1625.             sender = self.sender()
  1626.             sender.pushbutton.setEnabled(True)
  1627.             sender.edit_control.setEnabled(True)
  1628.             self.job_options['pagerange'] = unicode(sender.edit_control.text())
  1629.  
  1630.  
  1631.     def PageRangeEdit_editingFinished(self):
  1632.         sender, x = self.sender(), []
  1633.         t, ok = unicode(sender.text()), True
  1634.         try:
  1635.             x = utils.expand_range(t)
  1636.         except ValueError:
  1637.             ok = False
  1638.  
  1639.         if ok:
  1640.             if 0 in x:
  1641.                 ok = False
  1642.  
  1643.             if ok:
  1644.                 for y in x:
  1645.                     if y > 999:
  1646.                         ok = False
  1647.                         break
  1648.  
  1649.         if ok:
  1650.             t = utils.collapse_range(x)
  1651.             sender.setText(QString(t))
  1652.             self.job_options['pagerange'] = t
  1653.  
  1654.         else:
  1655.             self.job_options['pagerange'] = ''
  1656.             log.error("Invalid page range: %s" % t)
  1657.             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>"))
  1658.             sender.setFocus(Qt.OtherFocusReason)
  1659.  
  1660.  
  1661.     def PageRangeEdit_textChanged(self, t):
  1662.         sender, x, t = self.sender(), [], unicode(t)
  1663.         try:
  1664.             x = utils.expand_range(t)
  1665.         except ValueError:
  1666.             self.job_options['pagerange'] = ''
  1667.             log.error("Invalid page range: %s" % t)
  1668.         else:
  1669.             self.job_options['pagerange'] = t
  1670.  
  1671.  
  1672.     #
  1673.     # Job Storage
  1674.     #
  1675.  
  1676.     def updateJobStorageControls(self):
  1677.         beginWaitCursor()
  1678.         try:
  1679.             # Mode
  1680.             self.JobStorageModeComboBox.setCurrentIndex(self.JobStorageModeComboBox.findData(QVariant(self.job_storage_mode)))
  1681.             self.JobStorageModeDefaultButton.setEnabled(self.job_storage_mode != JOB_STORAGE_TYPE_OFF)
  1682.  
  1683.             # PIN
  1684.             self.JobStoragePinPrivateRadioButton.setChecked(self.job_storage_use_pin)
  1685.  
  1686.             # Username
  1687.             self.JobStorageUsernameAutoRadioButton.setChecked(self.job_storage_auto_username)
  1688.  
  1689.             # Jobname/ID
  1690.             self.JobStorageIDAutoRadioButton.setChecked(self.job_storage_auto_jobname)
  1691.  
  1692.             # Dup/existing ID
  1693.             self.JobStorageExistingComboBox.setCurrentIndex(self.JobStorageExistingComboBox.findData(QVariant(self.job_storage_job_exist)))
  1694.  
  1695.             if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
  1696.                 # PIN
  1697.                 self.JobStoragePinGroupBox.setEnabled(False)
  1698.                 self.JobStoragePinEdit.setEnabled(False)
  1699.                 self.JobStoragePinDefaultButton.setEnabled(False)
  1700.                 self.JobStoragePinEdit.setText(QString())
  1701.  
  1702.                 # Username
  1703.                 self.JobStorageUsernameGroupBox.setEnabled(False)
  1704.                 self.JobStorageUsernameEdit.setEnabled(False)
  1705.                 self.JobStorageUsernameDefaultButton.setEnabled(False)
  1706.  
  1707.                 # Jobname/ID
  1708.                 self.JobStorageIDGroupBox.setEnabled(False)
  1709.                 self.JobStorageIDEdit.setEnabled(False)
  1710.                 self.JobStorageIDDefaultButton.setEnabled(False)
  1711.  
  1712.                 # Duplicate/existing Jobname/ID
  1713.                 self.JobStorageExistingComboBox.setEnabled(False)
  1714.  
  1715.             else:
  1716.                 # PIN
  1717.                 if self.job_storage_mode in (JOB_STORAGE_TYPE_PERSONAL, JOB_STORAGE_TYPE_STORE):
  1718.                     self.JobStoragePinGroupBox.setEnabled(True)
  1719.                     self.JobStoragePinDefaultButton.setEnabled(self.job_storage_use_pin)
  1720.                     self.JobStoragePinEdit.setEnabled(self.job_storage_use_pin)
  1721.                     self.JobStoragePinEdit.setText(QString(self.job_storage_pin))
  1722.                 else:
  1723.                     self.JobStoragePinGroupBox.setEnabled(False)
  1724.                     self.JobStoragePinEdit.setEnabled(False)
  1725.                     self.JobStoragePinDefaultButton.setEnabled(False)
  1726.                     self.JobStoragePinEdit.setText(QString())
  1727.  
  1728.                 # Username
  1729.                 self.JobStorageUsernameGroupBox.setEnabled(True)
  1730.                 self.JobStorageUsernameEdit.setEnabled(not self.job_storage_auto_username)
  1731.                 self.JobStorageUsernameDefaultButton.setEnabled(not self.job_storage_auto_username)
  1732.                 self.JobStorageUsernameEdit.setText(QString(self.job_storage_username))
  1733.  
  1734.                 # Jobname/ID
  1735.                 self.JobStorageIDGroupBox.setEnabled(True)
  1736.                 self.JobStorageIDEdit.setEnabled(not self.job_storage_auto_jobname)
  1737.                 self.JobStorageIDDefaultButton.setEnabled(not self.job_storage_auto_jobname)
  1738.                 self.JobStorageIDEdit.setText(QString(self.job_storage_jobname))
  1739.  
  1740.                 # Duplicate/existing JobName/ID
  1741.                 self.JobStorageExistingComboBox.setEnabled(not self.job_storage_auto_jobname)
  1742.                 self.JobStorageExistingDefaultButton.setEnabled(not self.job_storage_auto_jobname and self.job_storage_job_exist != JOB_STORAGE_EXISTING_JOB_REPLACE)
  1743.  
  1744.         finally:
  1745.             endWaitCursor()
  1746.  
  1747.  
  1748.     def saveJobStorageOptions(self):
  1749.         beginWaitCursor()
  1750.         try:
  1751.             log.debug("Saving job storage options...")
  1752.  
  1753.             if self.job_storage_mode == JOB_STORAGE_TYPE_OFF:
  1754.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_OFF")
  1755.                 self.setPrinterOption('HOLD', 'OFF')
  1756.                 self.removePrinterOption('HOLDTYPE')
  1757.                 self.removePrinterOption('USERNAME')
  1758.                 self.removePrinterOption('JOBNAME')
  1759.                 self.removePrinterOption('DUPLICATEJOB')
  1760.  
  1761.             elif self.job_storage_mode == JOB_STORAGE_TYPE_PROOF_AND_HOLD:
  1762.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_PROOF_AND_HOLD")
  1763.                 self.setPrinterOption('HOLD', 'PROOF')
  1764.                 #self.removePrinterOption('HOLDTYPE')
  1765.                 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1766.  
  1767.             elif self.job_storage_mode == JOB_STORAGE_TYPE_PERSONAL:
  1768.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_PERSONAL")
  1769.  
  1770.                 if self.job_storage_use_pin:
  1771.                     self.setPrinterOption('HOLD', 'ON')
  1772.                 else:
  1773.                     self.setPrinterOption('HOLD', 'PROOF')
  1774.                     self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1775.  
  1776.  
  1777.             elif self.job_storage_mode == JOB_STORAGE_TYPE_QUICK_COPY:
  1778.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_QUICK_COPY")
  1779.                 self.setPrinterOption('HOLD', 'ON')
  1780.                 self.setPrinterOption('HOLDTYPE', 'PUBLIC')
  1781.  
  1782.             elif self.job_storage_mode == JOB_STORAGE_TYPE_STORE:
  1783.                 log.debug("Job storage mode = JOB_STORAGE_TYPE_STORE")
  1784.                 self.setPrinterOption('HOLD', 'STORE')
  1785.  
  1786.                 if not self.job_storage_use_pin:
  1787.                     self.removePrinterOption('HOLDTYPE')
  1788.  
  1789.             # PIN
  1790.             log.debug("Job storage use pin = %d" % self.job_storage_use_pin)
  1791.             if self.job_storage_use_pin:
  1792.                 self.setPrinterOption('HOLDTYPE', 'PRIVATE')
  1793.  
  1794.             #else:
  1795.             #    self.removePrinterOption('HOLDKEY')
  1796.  
  1797.             # Dup/exisiting
  1798.             if self.job_storage_job_exist == JOB_STORAGE_EXISTING_JOB_REPLACE:
  1799.                 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_REPLACE")
  1800.                 self.setPrinterOption('DUPLICATEJOB', 'REPLACE')
  1801.  
  1802.             else: # JOB_STORAGE_EXISTING_JOB_APPEND_1_99
  1803.                 log.debug("Job storage duplicate = JOB_STORAGE_EXISTING_JOB_APPEND_1_99")
  1804.                 self.setPrinterOption('DUPLICATEJOB', 'APPEND')
  1805.  
  1806.  
  1807.         finally:
  1808.             endWaitCursor()
  1809.  
  1810.  
  1811.     #
  1812.     # Mode
  1813.     #
  1814.  
  1815.     def JobStorageModeComboBox_activated(self, i):
  1816.         sender = self.sender()
  1817.         mode, ok = sender.itemData(i).toInt()
  1818.         if ok:
  1819.             self.job_storage_mode = mode
  1820.             self.saveJobStorageOptions()
  1821.             self.updateJobStorageControls()
  1822.  
  1823.  
  1824.     def JobStorageModeDefaultButton_clicked(self):
  1825.         self.JobStorageModeComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_TYPE_OFF)
  1826.  
  1827.  
  1828.     #
  1829.     # PIN
  1830.     #
  1831.  
  1832.     def JobStoragePinOffRadioButton_toggled(self, b):
  1833.         self.job_storage_use_pin = not b
  1834.         self.updateJobStorageControls()
  1835.         self.saveJobStorageOptions()
  1836.  
  1837.  
  1838.     def JobStoragePinPrivateRadioButton_toggled(self, b):
  1839.         self.job_storage_use_pin = b
  1840.         self.updateJobStorageControls()
  1841.         self.saveJobStorageOptions()
  1842.  
  1843.  
  1844.     def JobStoragePinDefaultButton_clicked(self):
  1845.         self.JobStoragePinOffRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1846.  
  1847.  
  1848.     def JobStoragePinEdit_textEdited(self, s):
  1849.         self.job_storage_pin = unicode(s)
  1850.         self.setPrinterOption('HOLDKEY', self.job_storage_pin.encode('ascii'))
  1851.  
  1852.  
  1853.  
  1854.     #
  1855.     # Username
  1856.     #
  1857.  
  1858.     def JobStorageUsernameAutoRadioButton_toggled(self, b):
  1859.         self.job_storage_auto_username = b
  1860.         self.updateJobStorageControls()
  1861.         self.saveJobStorageOptions()
  1862.  
  1863.  
  1864.     def JobStorageUsernameCustomRadioButton_toggled(self, b):
  1865.         self.job_storage_auto_username = not b
  1866.         self.updateJobStorageControls()
  1867.         self.saveJobStorageOptions()
  1868.  
  1869.  
  1870.     def JobStorageUsernameDefaultButton_clicked(self):
  1871.         self.JobStorageUsernameAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1872.  
  1873.  
  1874.     def JobStorageUsernameEdit_textEdited(self, s):
  1875.         self.job_storage_username = unicode(s)
  1876.         self.setPrinterOption('USERNAME', self.job_storage_username.encode('ascii'))
  1877.  
  1878.     #
  1879.     # Jobname/ID
  1880.     #
  1881.  
  1882.     def JobStorageIDAutoRadioButton_toggled(self, b):
  1883.         self.job_storage_auto_jobname = b
  1884.         self.updateJobStorageControls()
  1885.         self.saveJobStorageOptions()
  1886.  
  1887.  
  1888.     def JobStorageIDCustomRadioButton_toggled(self, b):
  1889.         self.job_storage_auto_jobname = not b
  1890.         self.updateJobStorageControls()
  1891.         self.saveJobStorageOptions()
  1892.  
  1893.  
  1894.     def JobStorageIDDefaultButton_clicked(self):
  1895.         self.JobStorageIDAutoRadioButton.emit(SIGNAL("toggled(bool)"), True)
  1896.  
  1897.  
  1898.     def JobStorageIDEdit_textEdited(self, s):
  1899.         self.job_storage_jobname = unicode(s)
  1900.         self.setPrinterOption('JOBNAME', self.job_storage_jobname.encode('ascii'))
  1901.  
  1902.     #
  1903.     # Duplicate/existing Jobname/ID
  1904.     #
  1905.  
  1906.     def JobStorageExistingComboBox_activated(self, i):
  1907.         sender = self.sender()
  1908.         opt, ok = sender.itemData(i).toInt()
  1909.         if ok:
  1910.             self.job_storage_job_exist = opt
  1911.             self.updateJobStorageControls()
  1912.             self.saveJobStorageOptions()
  1913.  
  1914.  
  1915.     def JobStorageExistingDefaultButton_clicked(self):
  1916.         self.JobStorageExistingComboBox.emit(SIGNAL("activated(int)"), JOB_STORAGE_EXISTING_JOB_REPLACE)
  1917.  
  1918.  
  1919.     #
  1920.     # Printer I/O
  1921.     #
  1922.  
  1923.     def setPrinterOption(self, option, value):
  1924.         log.debug("setPrinterOption(%s, %s)" % (option, value))
  1925.         cups.openPPD(self.cur_printer)
  1926.  
  1927.         try:
  1928.             cups.addOption("%s=%s" % (option, value))
  1929.             cups.setOptions()
  1930.         finally:
  1931.             cups.closePPD()
  1932.  
  1933.     def removePrinterOption(self, option):
  1934.         log.debug("removePrinterOption(%s)" % option)
  1935.         cups.openPPD(self.cur_printer)
  1936.  
  1937.         try:
  1938.             cups.removeOption(option)
  1939.             cups.setOptions()
  1940.         finally:
  1941.             cups.closePPD()
  1942.  
  1943.  
  1944.     def __tr(self,s,c = None):
  1945.         return qApp.translate("PrintSettingsToolbox",s,c)
  1946.