Repository: napari/napari

Issue:
Progress bar does not quit if new viewer is opened
## 🐛 Bug

When I use `worker.returned.connect` to open a new viewer, the progress bar in the old viewer kept working after worker finished.
This bug did not happen when I use `v0.4.12`.

## To Reproduce

Steps to reproduce the behavior:

1. create a viewer
```python
import napari
from napari.qt import create_worker
viewer = napari.Viewer()
```
2. start worker
```python
worker = create_worker(np.random.random, (100, 100), _progress={"total": 0})
worker.returned.connect(napari.view_image)
worker.start()
```

3. Progress bar is busy.

## Expected behavior

<!-- A clear and concise description of what you expected to happen. -->

## Environment

 - Please copy and paste the information at napari info option in help menubar here:

```
napari: 0.4.13rc2
Platform: Windows-10-10.0.22000-SP0
Python: 3.9.7 (default, Sep 16 2021, 16:59:28) [MSC v.1916 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.6
NumPy: 1.21.5
SciPy: 1.7.3
Dask: 2021.11.1
VisPy: 0.9.4

OpenGL:
- GL version: 4.6.0 - Build 27.20.100.9621
- MAX_TEXTURE_SIZE: 16384

Screens:
- screen 1: resolution 1368x912, scale 2.0

Plugins:
- animation: 0.0.2
- console: 0.0.4
- napari-multitask: 0.0.2
- napari-roi: 0.1.0
- scikit-image: 0.4.13rc2
- svg: 0.1.5
```
 - Any other relevant information:

## Additional context

I could not find a way to reproduce this in simple code but when I use workers and progress bar like above in my plugin widget, I got following error:

```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\progress.py:127, in progress.close(self)
    125 if self.disable:
    126     return
--> 127 progress._all_instances.remove(self)
    128 super().close()

File ~\Anaconda3\envs\mt\lib\_collections_abc.py:686, in MutableSet.remove(self, value)
    684 if value not in self:
    685     raise KeyError(value)
--> 686 self.discard(value)

File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\events\containers\_set.py:77, in EventedSet.discard(self, value)
     75 if value in self:
     76     self._set.discard(value)
---> 77     self._emit_change(added={}, removed={value})

File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\events\containers\_set.py:61, in EventedSet._emit_change(self, added, removed)
     59 def _emit_change(self, added=set(), removed=set()):
     60     # provides a hook for subclasses to update internal state before emit
---> 61     self.events.changed(added=added, removed=removed)

File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\events\event.py:715, in EventEmitter.__call__(self, *args, **kwargs)
    712     self._block_counter.update([cb])
    713     continue
--> 715 self._invoke_callback(cb, event if pass_event else None)
    716 if event.blocked:
    717     break

File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\events\event.py:752, in EventEmitter._invoke_callback(self, cb, event)
    750     self.disconnect(cb)
    751     return
--> 752 _handle_exception(
    753     self.ignore_callback_errors,
    754     self.print_callback_errors,
    755     self,
    756     cb_event=(cb, event),
    757 )

File ~\Anaconda3\envs\mt\lib\site-packages\napari\utils\events\event.py:739, in EventEmitter._invoke_callback(self, cb, event)
    737 try:
    738     if event is not None:
--> 739         cb(event)
    740     else:
    741         cb()

File ~\Anaconda3\envs\mt\lib\site-packages\napari\_qt\dialogs\qt_activity_dialog.py:132, in QtActivityDialog.handle_progress_change(self, event)
    124 """Handle addition and/or removal of new progress objects
    125 
    126 Parameters
   (...)
    129     EventedSet `changed` event with `added` and `removed` objects
    130 """
    131 for prog in event.removed:
--> 132     self.close_progress_bar(prog)
    133 for prog in event.added:
    134     self.make_new_pbar(prog)

File ~\Anaconda3\envs\mt\lib\site-packages\napari\_qt\dialogs\qt_activity_dialog.py:240, in QtActivityDialog.close_progress_bar(self, prog)
    232 """Close `QtLabeledProgressBar` and parent `QtProgressBarGroup` if needed
    233 
    234 Parameters
   (...)
    237     progress object whose QtLabeledProgressBar to close
    238 """
    239 current_pbar = self.get_pbar_from_prog(prog)
--> 240 parent_widget = current_pbar.parent()
    241 current_pbar.close()
    242 current_pbar.deleteLater()

AttributeError: 'NoneType' object has no attribute 'parent'
```



Discussion:

Resolving patch:
diff --git a/napari/_qt/dialogs/qt_activity_dialog.py b/napari/_qt/dialogs/qt_activity_dialog.py
--- a/napari/_qt/dialogs/qt_activity_dialog.py
+++ b/napari/_qt/dialogs/qt_activity_dialog.py
@@ -237,6 +237,8 @@ def close_progress_bar(self, prog):
             progress object whose QtLabeledProgressBar to close
         """
         current_pbar = self.get_pbar_from_prog(prog)
+        if not current_pbar:
+            return
         parent_widget = current_pbar.parent()
         current_pbar.close()
         current_pbar.deleteLater()


Test patch: