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