From da1b9d7e4bc9ee73b9e239724a1856b772a8aa2a Mon Sep 17 00:00:00 2001 From: Tim Waugh Date: Thu, 3 Sep 2009 16:53:27 +0000 Subject: [PATCH] - Speed improvement when fetching devices. --- system-config-printer-get-devices.patch | 498 ++++++++++++++++++++++++ system-config-printer.spec | 3 + 2 files changed, 501 insertions(+) create mode 100644 system-config-printer-get-devices.patch diff --git a/system-config-printer-get-devices.patch b/system-config-printer-get-devices.patch new file mode 100644 index 0000000..12130c1 --- /dev/null +++ b/system-config-printer-get-devices.patch @@ -0,0 +1,498 @@ +diff -up system-config-printer-1.1.12/cupshelpers/cupshelpers.py.get-devices system-config-printer-1.1.12/cupshelpers/cupshelpers.py +--- system-config-printer-1.1.12/cupshelpers/cupshelpers.py.get-devices 2009-08-25 15:01:40.000000000 +0100 ++++ system-config-printer-1.1.12/cupshelpers/cupshelpers.py 2009-09-03 17:44:32.610304039 +0100 +@@ -541,7 +541,7 @@ class Device: + + return result + +-def getDevices(connection): ++def getDevices(connection, **kw): + """ + Obtain a list of available CUPS devices. + +@@ -550,7 +550,7 @@ def getDevices(connection): + @returns: a list of L{Device} objects + @raise cups.IPPError: IPP Error + """ +- devices = connection.getDevices() ++ devices = connection.getDevices(**kw) + for uri, data in devices.iteritems(): + device = Device(uri, **data) + devices[uri] = device +diff -up system-config-printer-1.1.12/cupspk.py.get-devices system-config-printer-1.1.12/cupspk.py +--- system-config-printer-1.1.12/cupspk.py.get-devices 2009-09-03 17:44:32.513304908 +0100 ++++ system-config-printer-1.1.12/cupspk.py 2009-09-03 17:44:32.612310211 +0100 +@@ -311,12 +311,13 @@ class Connection: + def getDevices(self, *args, **kwds): + use_pycups = False + +- timeout = 0 ++ limit = 0 + include_schemes = '' + exclude_schemes = '' ++ timeout = 0 + +- if len(args) == 3: +- (use_pycups, timeout, include_schemes, exclude_schemes) = self._args_to_tuple([int, str, str], *args) ++ if len(args) == 4: ++ (use_pycups, limit, include_schemes, exclude_schemes, timeout) = self._args_to_tuple([int, str, str, int], *args) + else: + if kwds.has_key('timeout'): + timeout = kwds['timeout'] +@@ -327,6 +328,17 @@ class Connection: + if kwds.has_key('exclude_schemes'): + exclude_schemes = kwds['exclude_schemes'] + ++ # Convert from list to string ++ if len (include_schemes) > 0: ++ include_schemes = reduce (lambda x, y: x + "," + y, include_schemes) ++ else: ++ include_schemes = "" ++ ++ if len (exclude_schemes) > 0: ++ exclude_schemes = reduce (lambda x, y: x + "," + y, exclude_schemes) ++ else: ++ exclude_schemes = "" ++ + pk_args = (timeout, include_schemes, exclude_schemes) + + result = self._call_with_pk_and_fallback(use_pycups, +diff -up system-config-printer-1.1.12/gtkspinner.py.get-devices system-config-printer-1.1.12/gtkspinner.py +--- system-config-printer-1.1.12/gtkspinner.py.get-devices 2009-08-25 15:01:40.000000000 +0100 ++++ system-config-printer-1.1.12/gtkspinner.py 2009-09-03 17:44:32.614305510 +0100 +@@ -65,7 +65,7 @@ class Spinner: + def _next_frame (self): + n = self._current_frame + 1 + if n >= self.n_frames: +- n = 0 ++ n = 1 + + self._set_frame (n) + return True +diff -up system-config-printer-1.1.12/system-config-printer.py.get-devices system-config-printer-1.1.12/system-config-printer.py +--- system-config-printer-1.1.12/system-config-printer.py.get-devices 2009-09-03 17:44:32.601305285 +0100 ++++ system-config-printer-1.1.12/system-config-printer.py 2009-09-03 17:45:23.411307659 +0100 +@@ -3681,6 +3681,7 @@ class NewPrinterGUI(GtkGUI): + self.ntbkNPDownloadableDriverProperties.set_show_tabs(False) + + self.spinner = gtkspinner.Spinner (self.imgProcessWorking) ++ self.spinner_count = 0 + + # Set up OpenPrinting widgets. + self.openprinting = cupshelpers.openprinting.OpenPrinting () +@@ -3716,6 +3717,7 @@ class NewPrinterGUI(GtkGUI): + slct.set_select_function (self.device_select_function) + self.tvNPDevices.set_row_separator_func (self.device_row_separator_fn) + self.tvNPDevices.connect ("row-activated", self.device_row_activated) ++ self.tvNPDevices.connect ("row-expanded", self.device_row_expanded) + + # Devices expander + self.expNPDeviceURIs.connect ("notify::expanded", +@@ -3765,6 +3767,19 @@ class NewPrinterGUI(GtkGUI): + ppd_filter.add_pattern("*") + self.filechooserPPD.add_filter(ppd_filter) + ++ def inc_spinner_task (self): ++ if self.spinner_count == 0: ++ self.imgProcessWorking.show () ++ self.spinner.start () ++ ++ self.spinner_count += 1 ++ ++ def dec_spinner_task (self): ++ self.spinner_count -= 1 ++ if self.spinner_count == 0: ++ self.imgProcessWorking.hide () ++ self.spinner.stop () ++ + def show_IPP_Error (self, exception, message): + return show_IPP_Error (exception, message, parent=self.NewPrinterWindow) + +@@ -4611,45 +4626,48 @@ class NewPrinterGUI(GtkGUI): + self.btnNPForward.set_sensitive( + self.mainapp.checkNPName(new_text)) + +- def fetchDevices(self, parent=None): ++ def fetchDevices(self, parent=None, network=False): + debugprint ("fetchDevices") +- self.lblWait.set_markup ('' + +- _('Searching') + '\n\n' + +- _('Searching for printers')) +- if parent == None: +- parent = self.mainapp.PrintersWindow +- self.WaitWindow.set_transient_for (parent) +- self.WaitWindow.show_now () +- self.busy (self.WaitWindow) + +- if self.mainapp.cups._use_pk and config.WITH_POLKIT_1: +- def get_devices(): +- c = authconn.Connection (host=self.mainapp.connect_server, +- parent=parent, lock=True) +- c._begin_operation (_("fetching device list")) +- ret = cupshelpers.getDevices (c) +- c._end_operation () +- return ret ++ have_polkit_1 = self.mainapp.cups._use_pk and config.WITH_POLKIT_1 ++ if not have_polkit_1: ++ if network: ++ return {} + +- op = TimedOperation (get_devices) +- try: +- devices = op.run () +- except (OperationCanceled, RuntimeError, cups.IPPError): +- self.WaitWindow.hide () +- raise +- else: +- self.mainapp.cups._begin_operation (_("fetching device list")) +- try: +- devices = cupshelpers.getDevices (self.mainapp.cups) +- self.mainapp.cups._end_operation () +- except cups.IPPError: +- self.mainapp.cups._end_operation () +- self.WaitWindow.hide () +- raise ++ network = True + +- self.WaitWindow.hide () ++ network_schemes = ["dnssd", "snmp"] ++ try: ++ c = authconn.Connection (host=self.mainapp.connect_server, ++ parent=parent, lock=True) ++ debugprint ("in get_devices: connected") ++ c._begin_operation (_("fetching device list")) ++ try: ++ if network: ++ debugprint ("Fetching network devices") ++ ret = cupshelpers.getDevices (c, ++ include_schemes=network_schemes) ++ else: ++ debugprint ("Fetching local devices") ++ ret = cupshelpers.getDevices (c, ++ exclude_schemes=network_schemes) ++ except TypeError: ++ # include_schemes/exclude_schemes requires pycups >= 1.9.46 ++ if network: ++ ret = {} ++ else: ++ debugprint ("Fetching all devices") ++ debugprint ("in get_devices: getDevices") ++ ret = cupshelpers.getDevices (c) ++ except RuntimeError: ++ raise ++ except cups.IPPError: ++ c._end_operation () ++ raise ++ ++ c._end_operation () + debugprint ("Got devices") +- return devices ++ return ret + + def install_hplip_plugin(self, uri): + """ +@@ -4962,23 +4980,53 @@ class NewPrinterGUI(GtkGUI): + return (host, uri) + + def fillDeviceTab(self, current_uri=None): +- try: +- devices = self.fetchDevices() +- except cups.IPPError, (e, msg): +- self.show_IPP_Error(e, msg) +- devices = {} +- except: +- nonfatalException() +- devices = {} ++ self.device_selected = -1 ++ model = gtk.TreeStore (gobject.TYPE_STRING, # device-info ++ gobject.TYPE_PYOBJECT, # PhysicalDevice obj ++ gobject.TYPE_BOOLEAN) # Separator? ++ other = cupshelpers.Device('', **{'device-info' :_("Other")}) ++ physother = PhysicalDevice (other) ++ self.devices = [physother] ++ model.append (None, row=[physother.get_info (), physother, False]) ++ network_iter = model.append (None, row=[_("Network Printer"), ++ None, ++ False]) ++ network_dict = { 'device-class': 'network', ++ 'device-info': _("Find Network Printer") } ++ network = cupshelpers.Device ('network', **network_dict) ++ find_nw_iter = model.append (network_iter, ++ row=[network_dict['device-info'], ++ PhysicalDevice (network), False]) ++ model.insert_after (network_iter, find_nw_iter, row=['', None, True]) ++ self.devices_find_nw_iter = find_nw_iter ++ self.devices_network_iter = network_iter ++ self.devices_network_fetched = False ++ self.tvNPDevices.set_model (model) ++ self.entNPTDevice.set_text ('') ++ self.expNPDeviceURIs.hide () ++ self.inc_spinner_task () ++ ++ TimedOperation (self.fetchDevices, ++ kwargs={"network": False}, ++ callback=self.got_devices, ++ context=current_uri) ++ ++ def got_devices (self, result, exception, current_uri=None): ++ self.dec_spinner_task () ++ if exception: ++ try: ++ raise exception ++ except: ++ nonfatalException() ++ return + ++ devices = result + if current_uri: + if devices.has_key (current_uri): + current = devices.pop(current_uri) +- current.info += _(" (Current)") + elif devices.has_key (current_uri.replace (":9100", "")): + current_uri = current_uri.replace (":9100", "") + current = devices.pop(current_uri) +- current.info += _(" (Current)") + else: + current = cupshelpers.Device (current_uri) + current.info = "Current device" +@@ -5021,7 +5069,7 @@ class NewPrinterGUI(GtkGUI): + "hal", "beh", + "scsi", "http", "delete"), + devices) +- self.devices = [] ++ newdevices = [] + for device in devices: + physicaldevice = PhysicalDevice (device) + try: +@@ -5029,43 +5077,32 @@ class NewPrinterGUI(GtkGUI): + self.devices[i].add_device (device) + except ValueError: + self.devices.append (physicaldevice) ++ newdevices.append (physicaldevice) + + self.devices.sort() +- other = cupshelpers.Device('', **{'device-info' :_("Other")}) +- self.devices.append (PhysicalDevice (other)) +- device_select_index = 0 + if current_uri: + current_device = PhysicalDevice (current) + try: + i = self.devices.index (current_device) + self.devices[i].add_device (current) +- device_select_index = i +- devs = self.devices[i].get_devices () ++ current_device = self.devices[i] + except ValueError: +- self.devices.insert(0, current_device) ++ self.devices.append (current_device) ++ newdevices.append (current_device) ++ else: ++ current_device = None + +- model = gtk.TreeStore (gobject.TYPE_STRING, # device-info +- gobject.TYPE_PYOBJECT, # PhysicalDevice obj +- gobject.TYPE_BOOLEAN) # Separator? +- network_iter = model.append (None, row=[_("Network Printer"), +- None, +- False]) +- network_dict = { 'device-class': 'network', +- 'device-info': _("Find Network Printer") } +- network = cupshelpers.Device ('network', **network_dict) +- find_nw_iter = model.append (network_iter, +- row=[network_dict['device-info'], +- PhysicalDevice (network), False]) +- model.insert_after (network_iter, find_nw_iter, row=['', None, True]) +- self.devices_find_nw_iter = find_nw_iter +- self.tvNPDevices.set_model (model) ++ model = self.tvNPDevices.get_model () + +- i = 0 +- device_select_path = None +- for device in self.devices: ++ network_iter = self.devices_network_iter ++ find_nw_iter = self.devices_find_nw_iter ++ for device in newdevices: + devs = device.get_devices () + network = devs[0].device_class == 'network' +- row=[device.get_info (), device, False] ++ info = device.get_info () ++ if device == current_device: ++ info += _(" (Current)") ++ row=[info, device, False] + if network: + if devs[0].uri != devs[0].type: + # An actual network printer device. Put this at the top. +@@ -5075,24 +5112,31 @@ class NewPrinterGUI(GtkGUI): + # If this is the currently selected device we need + # to expand the "Network Printer" row so that it + # is visible. +- if device_select_index == i: ++ if device == current_device: + network_path = model.get_path (network_iter) + self.tvNPDevices.expand_row (network_path, False) + else: + # Just a method of finding one. + iter = model.append (network_iter, row=row) + else: +- iter = model.insert_before(None, network_iter, row=row) ++ # Insert this local device in order. ++ iter = model.get_iter_first () ++ while iter != network_iter: ++ physdev = model.get_value (iter, 1) ++ if physdev > device: ++ break ++ ++ iter = model.iter_next (iter) ++ ++ iter = model.insert_before (None, iter, row=row) + +- if device_select_index == i: ++ if device == current_device: + device_select_path = model.get_path (iter) + self.tvNPDevices.scroll_to_cell (device_select_path, + row_align=0.5) + column = self.tvNPDevices.get_column (0) + self.tvNPDevices.set_cursor (device_select_path, column) + +- i += 1 +- + connection_select_path = 0 + if current_uri: + model = self.tvNPDeviceURIs.get_model () +@@ -5106,6 +5150,9 @@ class NewPrinterGUI(GtkGUI): + + iter = model.iter_next (iter) + i += 1 ++ elif not self.device_selected: ++ column = self.tvNPDevices.get_column (0) ++ self.tvNPDevices.set_cursor ((0,), column) + + column = self.tvNPDeviceURIs.get_column (0) + self.tvNPDeviceURIs.set_cursor (connection_select_path, column) +@@ -5551,6 +5598,13 @@ class NewPrinterGUI(GtkGUI): + else: + view.expand_row (path, False) + ++ def device_row_expanded (self, view, iter, path): ++ if not self.devices_network_fetched: ++ self.devices_network_fetched = True ++ self.inc_spinner_task () ++ TimedOperation (self.fetchDevices, kwargs={'network': True}, ++ callback=self.got_devices) ++ + def device_select_function (self, path): + """ + Allow this path to be selected as long as there +@@ -5565,6 +5619,7 @@ class NewPrinterGUI(GtkGUI): + return False + + def on_tvNPDevices_cursor_changed(self, widget): ++ self.device_selected += 1 + path, column = widget.get_cursor () + if path == None: + return +@@ -5868,8 +5923,7 @@ class NewPrinterGUI(GtkGUI): + self.network_found = 0 + self.lblNetworkFindSearching.show_all () + finder = probe_printer.PrinterFinder () +- self.imgProcessWorking.show () +- self.spinner.start () ++ self.inc_spinner_task () + finder.find (host, found_callback) + + def found_network_printer_callback (self, new_device): +@@ -5898,8 +5952,7 @@ class NewPrinterGUI(GtkGUI): + path = model.get_path (iter) + self.tvNPDevices.set_cursor (path) + else: +- self.imgProcessWorking.hide () +- self.spinner.stop () ++ self.dec_spinner_task () + self.lblNetworkFindSearching.hide () + self.entNPTNetworkHostname.set_sensitive (True) + self.btnNetworkFind.set_sensitive (True) +diff -up system-config-printer-1.1.12/timedops.py.get-devices system-config-printer-1.1.12/timedops.py +--- system-config-printer-1.1.12/timedops.py.get-devices 2009-08-25 15:01:41.000000000 +0100 ++++ system-config-printer-1.1.12/timedops.py 2009-09-03 17:44:32.629302805 +0100 +@@ -152,16 +152,24 @@ class OperationThread(threading.Thread): + + class TimedOperation(Timed): + def __init__ (self, target, args=(), kwargs={}, parent=None, +- show_dialog=False): ++ show_dialog=False, callback=None, context=None): + self.wait_window = None + self.parent = parent + self.show_dialog = show_dialog ++ self.callback = callback ++ self.context = context + self.thread = OperationThread (target=target, + args=args, + kwargs=kwargs) + self.thread.start () + ++ if self.callback: ++ self.timeout_source = gobject.timeout_add (50, self._check_thread) ++ + def run (self): ++ if self.callback: ++ raise RuntimeError ++ + if self.show_dialog: + wait = gtk.MessageDialog (self.parent, + gtk.DIALOG_MODAL | +@@ -170,7 +178,7 @@ class TimedOperation(Timed): + gtk.BUTTONS_CANCEL, + _("Please wait")) + wait.connect ("delete_event", lambda *args: False) +- wait.connect ("response", self.wait_window_response) ++ wait.connect ("response", self._wait_window_response) + if self.parent: + wait.set_transient_for (self.parent) + +@@ -178,7 +186,7 @@ class TimedOperation(Timed): + wait.format_secondary_text (_("Gathering information")) + wait.show_all () + +- self.timeout_source = gobject.timeout_add (50, self.check_thread) ++ self.timeout_source = gobject.timeout_add (50, self._check_thread) + gtk.main () + gobject.source_remove (self.timeout_source) + if self.show_dialog: +@@ -186,20 +194,32 @@ class TimedOperation(Timed): + + return self.thread.collect_result () + +- def check_thread (self): ++ def _check_thread (self): + if self.thread.isAlive (): + # Thread still running. + return True + +- # Thread has finished. Stop the sub-loop. +- gtk.main_quit () ++ # Thread has finished. Stop the sub-loop or trigger callback. ++ if self.callback: ++ if self.context != None: ++ self.callback (self.thread.result, self.thread.exception, ++ self.context) ++ else: ++ self.callback (self.thread.result, self.thread.exception) ++ else: ++ gtk.main_quit () ++ + return False + +- def wait_window_response (self, dialog, response): ++ def _wait_window_response (self, dialog, response): + if response == gtk.RESPONSE_CANCEL: + self.cancel () + + def cancel (self): + debugprint ("Command canceled") +- gtk.main_quit () ++ if self.callback: ++ self.callback = None ++ else: ++ gtk.main_quit () ++ + return False diff --git a/system-config-printer.spec b/system-config-printer.spec index e0eb150..660552e 100644 --- a/system-config-printer.spec +++ b/system-config-printer.spec @@ -21,6 +21,7 @@ Patch4: system-config-printer-polkit-1.patch Patch5: system-config-printer-proxy-auth.patch Patch6: system-config-printer-ppdippstr.patch Patch7: system-config-printer-raw-device-change.patch +Patch8: system-config-printer-get-devices.patch BuildRequires: cups-devel >= 1.2 BuildRequires: python-devel >= 2.4 @@ -89,6 +90,7 @@ printers. %patch5 -p1 -b .proxy-auth %patch6 -p1 -b .ppdippstr %patch7 -p1 -b .raw-device-change +%patch8 -p1 -b .get-devices %build aclocal @@ -204,6 +206,7 @@ exit 0 %changelog * Thu Sep 3 2009 Tim Waugh 1.1.12-7 +- Speed improvement when fetching devices. - Allow raw devices to be changed. * Fri Aug 28 2009 Tim Waugh 1.1.12-6