Repository: napari/napari

Issue:
Napari taskbar icon on Windows is generic python logo
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->
On Windows, the windows icon is different from the taskbar icon, so Napari shows up as a generic Python application:

![image](https://user-images.githubusercontent.com/23343812/80260241-49a60c00-863c-11ea-8c07-e18fe25ccbab.png)

## Expected behavior

<!-- A clear and concise description of what you expected to happen. -->
It would be nice to have the Napari logo show in the taskbar, and I assume this is a Windows specific issue. From this [Stack Overflow answer](https://stackoverflow.com/a/1552105/2337392), adding this to `Viewer()` class does this trick:

```python
import ctypes
myappid = 'mycompany.myproduct.subproduct.version' # arbitrary string
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
```
![image](https://user-images.githubusercontent.com/23343812/80260482-dfda3200-863c-11ea-95bc-59fdd00308fe.png)

`myappid` seems to not really matter, and we could just set that to `"napari"`
## Environment

```
napari: 0.2.12+71.gb2a95d6.dirty
Platform: Windows-10-10.0.19041-SP0
Python: 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
Qt: 5.14.1
PySide2: 5.14.1
NumPy: 1.18.1
SciPy: 1.4.1
Dask: 2.12.0
VisPy: 0.6.4

GL version: 4.6.0 NVIDIA 441.45
MAX_TEXTURE_SIZE: 32768

Plugins: None
```


Discussion:
Thanks for flagging, I'm surprised Qt didn't handle that correctly for us - it works nicely on a mac. Maybe @tlambert03 can take a look
definitely want to make this work.  slightly curious as to why it's _not_ working for you though, on my windows system it does work!  (though I do remember using that ctypes workaround for previous Qt windows app now that you mention it).    just out of curiosity, how exactly do you tend to launch napari (within an interactive ipython, a notebook, a script, cli)?  and does anything change if you try other ways?
Hi @tlambert03 I almost always launch `napari` from `cli`. I just confirmed that launching from within `ipython` or `jupyter lab` results in the same generic python logo. I'm also always launching from a `napari` repo in developer mode.
As I fast check you only set icon for QApplication 

https://github.com/napari/napari/blob/0f94ec10ebf2b0869d542d8d8f28b8136e998279/napari/viewer.py#L59

From my experience also may be needed to set icon for window.

https://github.com/napari/napari/blob/0f94ec10ebf2b0869d542d8d8f28b8136e998279/napari/viewer.py#L68

```python
self.window.setWindowIcon(QIcon(logopath))
```

There is inconsistency between systems with icon set. 
thanks, would you like to submit a PR?
@tlambert03 I wrote this from memory. I do not have option to verify it now. If there is some Windows user who can verify it (ex. @hectormz). 

But in few days I will have access to windows machine with development environment.  
@Czaki @tlambert03 
Just tested out but doesn't work:
```bash
AttributeError: 'Window' object has no attribute 'setWindowIcon'
```

I can try out other possibilities for you.
thanks for trying @hectormz, the window we probably need to target is not the one on line 68 in viewer.py but rather the `QMainWindow` instance at `self.window._qt_window`
Argh. 
Custom wrapper for `QMainWindow`
set it on `QMainWindow` object 
https://github.com/napari/napari/blob/0f94ec10ebf2b0869d542d8d8f28b8136e998279/napari/_qt/qt_main_window.py#L72
Well, no error, but didn't work with:
```python
self._qt_window.setWindowIcon(QIcon(logopath))
```
after line 72 in `qt_main_window.py`

Sorry I'm not more familiar with `Qt`
Not work means no logo or fail execute? 
@Czaki sorry.

`napari` runs properly with no errors, but fails to update logo.
Ok. I check my repo history. My solution solves some strange cases for bundled code (with pyinstaller). 

It looks like windows ignore setting icon because identify it as python. 

Solution suggested in first comment works, but I suggest to use it  in `gui_qt` instead of `Viewer` https://github.com/napari/napari/blob/0f94ec10ebf2b0869d542d8d8f28b8136e998279/napari/_qt/event_loop.py#L10

> It would be nice to have the Napari logo show in the taskbar, and I assume this is a Windows specific issue. From this [Stack Overflow answer](https://stackoverflow.com/a/1552105/2337392), adding this to `Viewer()` class does this trick:
> 
> ```python
> import ctypes
> myappid = 'mycompany.myproduct.subproduct.version' # arbitrary string
> ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
> ```


Got it, thanks for looking into it @Czaki . What do you think of this solution @tlambert03?

Resolving patch:
diff --git a/napari/viewer.py b/napari/viewer.py
--- a/napari/viewer.py
+++ b/napari/viewer.py
@@ -1,3 +1,5 @@
+import platform
+import sys
 from os.path import dirname, join
 
 from qtpy.QtGui import QIcon
@@ -7,6 +9,7 @@
 from ._qt.qt_main_window import Window
 from ._qt.qt_viewer import QtViewer
 from .components import ViewerModel
+from . import __version__
 
 
 class Viewer(ViewerModel):
@@ -28,6 +31,10 @@ class Viewer(ViewerModel):
         Whether to show the viewer after instantiation. by default True.
     """
 
+    # set _napari_app_id to False to avoid overwriting dock icon on windows
+    # set _napari_app_id to custom string to prevent grouping different base viewer
+    _napari_app_id = 'napari.napari.viewer.' + str(__version__)
+
     def __init__(
         self,
         title='napari',
@@ -55,6 +62,17 @@ def __init__(
             )
             raise RuntimeError(message)
 
+        if (
+            platform.system() == "Windows"
+            and not getattr(sys, 'frozen', False)
+            and self._napari_app_id
+        ):
+            import ctypes
+
+            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
+                self._napari_app_id
+            )
+
         logopath = join(dirname(__file__), 'resources', 'logo.png')
         app.setWindowIcon(QIcon(logopath))
 


Test patch: