Back to index

system-config-printer  1.3.9+20120706
__init__.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 ## Printing troubleshooter
00004 
00005 ## Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
00006 ## Author: Tim Waugh <twaugh@redhat.com>
00007 
00008 ## This program is free software; you can redistribute it and/or modify
00009 ## it under the terms of the GNU General Public License as published by
00010 ## the Free Software Foundation; either version 2 of the License, or
00011 ## (at your option) any later version.
00012 
00013 ## This program is distributed in the hope that it will be useful,
00014 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 ## GNU General Public License for more details.
00017 
00018 ## You should have received a copy of the GNU General Public License
00019 ## along with this program; if not, write to the Free Software
00020 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00021 
00022 import gtk
00023 import pprint
00024 import sys
00025 import traceback
00026 
00027 if __name__ == "__main__":
00028     import os.path
00029     import gettext
00030     gettext.textdomain ('system-config-printer')
00031 
00032     if sys.argv[0][0] != '/':
00033         cwd = os.getcwd ()
00034         path = cwd + os.path.sep + sys.argv[0]
00035     else:
00036         path = sys.argv[0]
00037     sub = os.path.dirname (path)
00038     root = os.path.dirname (sub)
00039     sys.path.append (root)
00040 
00041 import base
00042 from base import *
00043 
00044 class Troubleshooter:
00045     def __init__ (self, quitfn=None, parent=None):
00046         self._in_module_call = False
00047 
00048         main = gtk.Window ()
00049         if parent:
00050             main.set_transient_for (parent)
00051             main.set_position (gtk.WIN_POS_CENTER_ON_PARENT)
00052             main.set_modal (True)
00053 
00054         main.set_title (_("Printing troubleshooter"))
00055         main.set_property ("default-width", 400)
00056         main.set_property ("default-height", 350)
00057         main.connect ("delete_event", self.quit)
00058         self.main = main
00059         self.quitfn = quitfn
00060 
00061         vbox = gtk.VBox ()
00062         main.add (vbox)
00063         ntbk = gtk.Notebook ()
00064         ntbk.set_border_width (6)
00065         vbox.pack_start (ntbk, True, True, 0)
00066         vbox.pack_start (gtk.HSeparator (), False, False, 0)
00067         box = gtk.HButtonBox ()
00068         box.set_border_width (6)
00069         box.set_spacing (3)
00070         box.set_layout (gtk.BUTTONBOX_END)
00071 
00072         back = gtk.Button (stock=gtk.STOCK_GO_BACK)
00073         back.connect ('clicked', self._on_back_clicked)
00074         back.set_sensitive (False)
00075         self.back = back
00076 
00077         close = gtk.Button (stock=gtk.STOCK_CLOSE)
00078         close.connect ('clicked', self.quit)
00079         self.close = close
00080 
00081         cancel = gtk.Button (stock=gtk.STOCK_CANCEL)
00082         cancel.connect ('clicked', self.quit)
00083         self.cancel = cancel
00084 
00085         forward = gtk.Button (stock=gtk.STOCK_GO_FORWARD)
00086         forward.connect ('clicked', self._on_forward_clicked)
00087         forward.set_flags (gtk.CAN_DEFAULT | gtk.HAS_DEFAULT)
00088         self.forward = forward
00089 
00090         box.pack_start (back, False, False, 0)
00091         box.pack_start (cancel, False, False, 0)
00092         box.pack_start (close, False, False, 0)
00093         box.pack_start (forward, False, False, 0)
00094         vbox.pack_start (box, False, False, 0)
00095 
00096         ntbk.set_current_page (0)
00097         ntbk.set_show_tabs (False)
00098         self.ntbk = ntbk
00099         self.current_page = 0
00100 
00101         self.questions = []
00102         self.question_answers = []
00103         self.answers = {}
00104         self.moving_backwards = False
00105 
00106         main.show_all ()
00107 
00108     def quit (self, *args):
00109         if self._in_module_call:
00110             try:
00111                 self.questions[self.current_page].cancel_operation ()
00112             except:
00113                 self._report_traceback ()
00114 
00115             return
00116 
00117         try:
00118             self.questions[self.current_page].disconnect_signals ()
00119         except:
00120             self._report_traceback ()
00121 
00122         # Delete the questions so that their __del__ hooks can run.
00123         # Do this in reverse order of creation.
00124         for i in xrange (len (self.questions)):
00125             self.questions.pop ()
00126 
00127         self.main.hide ()
00128         if self.quitfn:
00129             self.quitfn (self)
00130 
00131     def get_window (self):
00132         # Any error dialogs etc from the modules need to be able
00133         # to set themselves transient for this window.
00134         return self.main
00135 
00136     def no_more_questions (self, question):
00137         page = self.questions.index (question)
00138         debugprint ("Page %d: No more questions." % page)
00139         self.questions = self.questions[:page + 1]
00140         self.question_answers = self.question_answers[:page + 1]
00141         for p in range (self.ntbk.get_n_pages () - 1, page, -1):
00142             self.ntbk.remove_page (p)
00143         self._set_back_forward_buttons ()
00144 
00145     def new_page (self, widget, question):
00146         page = len (self.questions)
00147         debugprint ("Page %d: new: %s" % (page, str (question)))
00148         self.questions.append (question)
00149         self.question_answers.append ([])
00150         self.ntbk.insert_page (widget, position=page)
00151         widget.show_all ()
00152         if page == 0:
00153             try:
00154                 question.connect_signals (self._set_back_forward_buttons)
00155             except:
00156                 self._report_traceback ()
00157 
00158             self.ntbk.set_current_page (page)
00159             self.current_page = page
00160         self._set_back_forward_buttons ()
00161         return page
00162 
00163     def is_moving_backwards (self):
00164         return self.moving_backwards
00165 
00166     def answers_as_text (self):
00167         text = ""
00168         n = 1
00169         for i in range (self.current_page):
00170             answers = self.question_answers[i].copy ()
00171             for hidden in filter (lambda x: x.startswith ("_"), answers.keys()):
00172                 del answers[hidden]
00173             if len (answers.keys ()) == 0:
00174                 continue
00175             text += "Page %d (%s):" % (n, self.questions[i]) + '\n'
00176             text += pprint.pformat (answers) + '\n'
00177             n += 1
00178         return text.rstrip () + '\n'
00179 
00180     def busy (self):
00181         self._in_module_call = True
00182         self.forward.set_sensitive (False)
00183         self.back.set_sensitive (False)
00184         gdkwin = self.get_window ().window
00185         if gdkwin:
00186             gdkwin.set_cursor (gtk.gdk.Cursor (gtk.gdk.WATCH))
00187             while gtk.events_pending ():
00188                 gtk.main_iteration ()
00189 
00190     def ready (self):
00191         self._in_module_call = False
00192         gdkwin = self.get_window ().window
00193         if gdkwin:
00194             gdkwin.set_cursor (gtk.gdk.Cursor (gtk.gdk.LEFT_PTR))
00195 
00196         self._set_back_forward_buttons ()
00197 
00198     def _set_back_forward_buttons (self, *args):
00199         page = self.current_page
00200         self.back.set_sensitive (page != 0)
00201         if len (self.questions) == page + 1:
00202             # Out of questions.
00203             debugprint ("Out of questions")
00204             self.forward.set_sensitive (False)
00205             self.close.show ()
00206             self.cancel.hide ()
00207         else:
00208             can = self._can_click_forward (self.questions[page])
00209             debugprint ("Page %d: can click forward? %s" % (page, can))
00210             self.forward.set_sensitive (can)
00211             self.close.hide ()
00212             self.cancel.show ()
00213 
00214     def _on_back_clicked (self, widget):
00215         self.busy ()
00216         self.moving_backwards = True
00217         try:
00218             self.questions[self.current_page].disconnect_signals ()
00219         except:
00220             self._report_traceback ()
00221 
00222         self.current_page -= 1
00223         question = self.questions[self.current_page]
00224         while not self._display (question):
00225             # Skip this one.            
00226             debugprint ("Page %d: skip" % (self.current_page))
00227             self.current_page -= 1
00228             question = self.questions[self.current_page]
00229 
00230         self.ntbk.set_current_page (self.current_page)
00231         answers = {}
00232         for i in range (self.current_page):
00233             answers.update (self.question_answers[i])
00234         self.answers = answers
00235 
00236         try:
00237             self.questions[self.current_page].\
00238                 connect_signals (self._set_back_forward_buttons)
00239         except:
00240             self._report_traceback ()
00241 
00242         self.moving_backwards = False
00243         self.ready ()
00244 
00245     def _on_forward_clicked (self, widget):
00246         self.busy ()
00247         answer_dict = self._collect_answer (self.questions[self.current_page])
00248         self.question_answers[self.current_page] = answer_dict
00249         self.answers.update (answer_dict)
00250 
00251         try:
00252             self.questions[self.current_page].disconnect_signals ()
00253         except:
00254             self._report_traceback ()
00255 
00256         self.current_page += 1
00257         question = self.questions[self.current_page]
00258         while not self._display (question):
00259             # Skip this one, but collect its answers.
00260             answer_dict = self._collect_answer (question)
00261             self.question_answers[self.current_page] = answer_dict
00262             self.answers.update (answer_dict)
00263             debugprint ("Page %d: skip" % (self.current_page))
00264             self.current_page += 1
00265             question = self.questions[self.current_page]
00266 
00267         self.ntbk.set_current_page (self.current_page)
00268         try:
00269             question.connect_signals (self._set_back_forward_buttons)
00270         except:
00271             self._report_traceback ()
00272 
00273         self.ready ()
00274         if get_debugging ():
00275             self._dump_answers ()
00276 
00277     def _dump_answers (self):
00278         debugprint (self.answers_as_text ())
00279 
00280     def _report_traceback (self):
00281         try:
00282             print "Traceback:"
00283             (type, value, tb) = sys.exc_info ()
00284             tblast = traceback.extract_tb (tb, limit=None)
00285             if len (tblast):
00286                 tblast = tblast[:len (tblast) - 1]
00287             extxt = traceback.format_exception_only (type, value)
00288             for line in traceback.format_tb(tb):
00289                 print line.strip ()
00290             print extxt[0].strip ()
00291         except:
00292             pass
00293 
00294     def _display (self, question):
00295         result = False
00296         try:
00297             result = question.display ()
00298         except:
00299             self._report_traceback ()
00300 
00301         question.displayed = result
00302         return result
00303 
00304     def _can_click_forward (self, question):
00305         try:
00306             return question.can_click_forward ()
00307         except:
00308             self._report_traceback ()
00309             return True
00310 
00311     def _collect_answer (self, question):
00312         answer = {}
00313         try:
00314             answer = question.collect_answer ()
00315         except:
00316             self._report_traceback ()
00317 
00318         return answer
00319 
00320 QUESTIONS = ["Welcome",
00321              "SchedulerNotRunning",
00322              "CheckLocalServerPublishing",
00323              "ChoosePrinter",
00324              "CheckPrinterSanity",
00325              "CheckPPDSanity",
00326 
00327              "LocalOrRemote",
00328              "DeviceListed",
00329              "CheckUSBPermissions",
00330 
00331              "RemoteAddress",
00332              "CheckNetworkServerSanity",
00333              "ChooseNetworkPrinter",
00334 
00335              "NetworkCUPSPrinterShared",
00336 
00337              "QueueNotEnabled",
00338              "QueueRejectingJobs",
00339              "PrinterStateReasons",
00340 
00341              "VerifyPackages",
00342              "CheckSELinux",
00343              "ServerFirewalled",
00344              "ErrorLogCheckpoint",
00345              "PrintTestPage",
00346              "ErrorLogFetch",
00347              "PrinterStateReasons",
00348              "ErrorLogParse",
00349              "Locale",
00350              "Shrug"]
00351 
00352 def run (quitfn=None, parent=None):
00353     troubleshooter = Troubleshooter (quitfn, parent=parent)
00354     modules_imported = []
00355     for module in QUESTIONS:
00356         try:
00357             if not module in modules_imported:
00358                 exec ("from %s import %s" % (module, module))
00359                 modules_imported.append (module)
00360 
00361             exec ("%s (troubleshooter)" % module)
00362         except:
00363             troubleshooter._report_traceback ()
00364     return troubleshooter
00365 
00366 if __name__ == "__main__":
00367     import sys, getopt
00368     try:
00369         opts, args = getopt.gnu_getopt (sys.argv[1:], '',
00370                                         ['debug'])
00371         for opt, optarg in opts:
00372             if opt == '--debug':
00373                 set_debugging (True)
00374     except getopt.GetoptError:
00375         pass
00376     gtk.gdk.threads_init()
00377     run (gtk.main_quit)
00378     gtk.gdk.threads_enter ()
00379     gtk.main ()
00380     gtk.gdk.threads_leave ()