Back to index

system-config-printer  1.3.9+20120706
optionwidgets.py
Go to the documentation of this file.
00001 ## system-config-printer
00002 
00003 ## Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
00004 ## Copyright (C) 2006 Florian Festi <ffesti@redhat.com>
00005 ## Copyright (C) 2007, 2008, 2009 Tim Waugh <twaugh@redhat.com>
00006 
00007 ## This program is free software; you can redistribute it and/or modify
00008 ## it under the terms of the GNU General Public License as published by
00009 ## the Free Software Foundation; either version 2 of the License, or
00010 ## (at your option) any later version.
00011 
00012 ## This program is distributed in the hope that it will be useful,
00013 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 ## GNU General Public License for more details.
00016 
00017 ## You should have received a copy of the GNU General Public License
00018 ## along with this program; if not, write to the Free Software
00019 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020 
00021 import gtk
00022 import cups
00023 from gettext import gettext as _
00024 import ppdippstr
00025 
00026 def OptionWidget(option, ppd, gui, tab_label=None):
00027     """Factory function"""
00028     ui = option.ui
00029     if (ui == cups.PPD_UI_BOOLEAN and
00030         len (option.choices) != 2):
00031         # This option is advertised as a Boolean but in fact has more
00032         # than two choices.
00033         print "Treating Boolean option %s as PickOne" % option.keyword
00034         ui = cups.PPD_UI_PICKONE
00035 
00036     if ui == cups.PPD_UI_BOOLEAN:
00037         return OptionBool(option, ppd, gui, tab_label=tab_label)
00038     elif ui == cups.PPD_UI_PICKONE:
00039         return OptionPickOne(option, ppd, gui, tab_label=tab_label)
00040     elif ui == cups.PPD_UI_PICKMANY:
00041         return OptionPickMany(option, ppd, gui, tab_label=tab_label)
00042 
00043 # ---------------------------------------------------------------------------
00044 
00045 class Option:
00046     def __init__(self, option, ppd, gui, tab_label=None):
00047         self.option = option
00048         self.ppd = ppd
00049         self.gui = gui
00050         self.enabled = True
00051         self.tab_label = tab_label
00052 
00053         vbox = gtk.VBox()
00054         
00055         self.btnConflict = gtk.Button()
00056         icon = gtk.image_new_from_stock(gtk.STOCK_DIALOG_WARNING,
00057                                         gtk.ICON_SIZE_SMALL_TOOLBAR)
00058         self.btnConflict.add(icon)
00059         self.btnConflict.set_no_show_all(True) #avoid the button taking
00060                                                # over control again
00061         vbox.add(self.btnConflict)    # vbox reserves space while button
00062         #vbox.set_size_request(32, 28) # is hidden
00063         self.conflictIcon = vbox
00064 
00065         self.btnConflict.connect("clicked", self.on_btnConflict_clicked)
00066         icon.show()
00067 
00068         self.constraints = [c for c in ppd.constraints
00069                             if (c.option1 == option.keyword or
00070                                 c.option2 == option.keyword)]
00071         #for c in self.constraints:
00072         #    if not c.choice1 or not c.choice2:
00073         #        print c.option1, repr(c.choice1), c.option2, repr(c.choice2)
00074         self.conflicts = set()
00075         self.conflict_message = ""
00076 
00077     def enable(self, enabled=True):
00078         self.selector.set_sensitive (enabled)
00079         self.enabled = enabled
00080 
00081     def disable(self):
00082         self.enable (False)
00083 
00084     def is_enabled(self):
00085         return self.enabled
00086 
00087     def get_current_value(self):
00088         raise NotImplemented
00089 
00090     def is_changed(self):
00091         return self.get_current_value()!= self.option.defchoice
00092     
00093     def writeback(self):
00094         #print repr(self.option.keyword), repr(self.get_current_value())
00095         if self.enabled:
00096             self.ppd.markOption(self.option.keyword, self.get_current_value())
00097 
00098     def checkConflicts(self, update_others=True):
00099         value = self.get_current_value()
00100         for constraint in self.constraints:
00101             if constraint.option1 == self.option.keyword:
00102                 option2 = self.gui.options.get(constraint.option2, None)
00103                 choice1 = constraint.choice1
00104                 choice2 = constraint.choice2
00105             else:
00106                 option2 = self.gui.options.get(constraint.option1, None)
00107                 choice1 = constraint.choice2
00108                 choice2 = constraint.choice1
00109 
00110             if option2 is None: continue
00111 
00112             def matches (constraint_choice, value):
00113                 if constraint_choice != '':
00114                     return constraint_choice == value
00115                 return value not in ['None', 'False', 'Off']
00116 
00117             if (matches (choice1, value) and
00118                 matches (choice2, option2.get_current_value())):
00119                 # conflict
00120                 self.conflicts.add(constraint)
00121                 if update_others:
00122                     option2.checkConflicts(update_others=False)
00123             elif constraint in self.conflicts:
00124                 # remove conflict
00125                 self.conflicts.remove(constraint)
00126                 option2.checkConflicts(update_others=False)
00127 
00128 
00129         tooltip = [_("Conflicts with:")]
00130         conflicting_options = dict()
00131         for c in self.conflicts:
00132             if c.option1 == self.option.keyword:
00133                 option = self.gui.options.get(c.option2)
00134             else:
00135                 option = self.gui.options.get(c.option1)
00136 
00137             conflicting_options[option.option.keyword] = option
00138 
00139         for option in conflicting_options.values ():
00140             opt = option.option.text
00141             val = option.get_current_value ()
00142             for choice in option.option.choices:
00143                 if choice['choice'] == val:
00144                     val = ppdippstr.ppd.get (choice['text'])
00145 
00146             tooltip.append ("%s: %s" % (opt, val))
00147             
00148         tooltip = "\n".join(tooltip)
00149 
00150         self.conflict_message = tooltip # XXX more verbose
00151             
00152         if self.conflicts:
00153             self.btnConflict.set_tooltip_text (tooltip)
00154             self.btnConflict.show()
00155         else:
00156             self.btnConflict.hide()
00157 
00158         self.gui.option_changed(self)
00159         return self.conflicts
00160             
00161     def on_change(self, widget):
00162         self.checkConflicts()
00163 
00164     def on_btnConflict_clicked(self, button):
00165         parent = self.btnConflict
00166         while parent != None and not isinstance (parent, gtk.Window):
00167             parent = parent.get_parent ()
00168 
00169         dialog = gtk.MessageDialog (parent,
00170                                     gtk.DIALOG_DESTROY_WITH_PARENT |
00171                                     gtk.DIALOG_MODAL,
00172                                     gtk.MESSAGE_WARNING,
00173                                     gtk.BUTTONS_CLOSE,
00174                                     self.conflict_message)
00175         dialog.run()
00176         dialog.destroy()
00177         
00178 # ---------------------------------------------------------------------------
00179 
00180 class OptionBool(Option):
00181 
00182     def __init__(self, option, ppd, gui, tab_label=None):
00183         self.selector = gtk.CheckButton(ppdippstr.ppd.get (option.text))
00184         self.label = None
00185         self.false = u"False" # hack to allow "None" instead of "False"
00186         self.true = u"True"
00187         for c in option.choices:
00188             if c["choice"] in ("None", "False", "Off"):
00189                 self.false = c["choice"]
00190             if c["choice"] in ("True", "On"):
00191                 self.true = c["choice"]
00192         self.selector.set_active(option.defchoice == self.true)
00193         self.selector.set_alignment(0.0, 0.5)
00194         self.selector.connect("toggled", self.on_change)
00195         Option.__init__(self, option, ppd, gui, tab_label=tab_label)
00196 
00197     def get_current_value(self):
00198         return (self.false, self.true)[self.selector.get_active()]
00199 
00200 # ---------------------------------------------------------------------------
00201 
00202 class OptionPickOne(Option):
00203     widget_name = "OptionPickOne"
00204 
00205     def __init__(self, option, ppd, gui, tab_label=None):
00206         self.selector = gtk.combo_box_new_text()
00207         #self.selector.set_alignment(0.0, 0.5)
00208 
00209         label = ppdippstr.ppd.get (option.text)
00210         if not label.endswith (':'):
00211             label += ':'
00212         self.label = gtk.Label(label)
00213         self.label.set_alignment(0.0, 0.5)
00214         
00215         selected = None
00216         for nr, choice in enumerate(option.choices):
00217             self.selector.append_text(ppdippstr.ppd.get (choice['text']))
00218             if option.defchoice == choice['choice']:
00219                 selected = nr
00220         if selected is not None:
00221             self.selector.set_active(selected)
00222         else:
00223             print option.text, "unknown value:", option.defchoice
00224         self.selector.connect("changed", self.on_change)
00225 
00226         Option.__init__(self, option, ppd, gui, tab_label=tab_label)
00227 
00228     def get_current_value(self):
00229         return self.option.choices[self.selector.get_active()]['choice']
00230         
00231 # ---------------------------------------------------------------------------
00232 
00233 class OptionPickMany(OptionPickOne):
00234     widget_name = "OptionPickMany"
00235 
00236     def __init__(self, option, ppd, gui, tab_label=None):
00237         raise NotImplemented
00238         Option.__init__(self, option, ppd, gui, tab_label=tab_label)
00239