Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation mapping visual UI with code structure, modules and classes #93

Open
dalthviz opened this issue Jan 18, 2023 · 19 comments · May be fixed by #114
Open

Add documentation mapping visual UI with code structure, modules and classes #93

dalthviz opened this issue Jan 18, 2023 · 19 comments · May be fixed by #114
Labels
content Ideas for new or improved content

Comments

@dalthviz
Copy link
Member

dalthviz commented Jan 18, 2023

📚 New content request

After helping around fixing bugs, I was thinking that maybe having some sort of mapping from the visual elements/UI to its related source code (directory structure, modules and classes) could be a good way to document the Napari GUI. This could help with the task of onboarding contributors and also document the general way things are currently working in terms of the GUI.

I think it could be nice to create documentation per interface section (layers controls, layers list, viewer, menus, dialogs, etc) and show for each of them the corresponding subset of the Napari source code directory layout: only the most related directories/files as well as some sort of dependency diagram(s) to show how the modules and classes depend between each other in that subset of the Napari source code.

Checking, seems like some exploration to do mappings of the source code have been done in a more or less automatic manner as well as an exploration of tooling to create diagrams (napari/napari#1389). I would say that finding a way to at least semiautomatically create this documentation should be explored.

Also, talking about this with @melissawm a suggestion I got is asking core developers about the current code layout and the decisions behind the current code layout to document this, and seems like @psobolewskiPhD and @goanpeca did some notes about things that could be nice to document related to the Napari source code that could also apply to the idea here of creating some documentation for the visual UI/frontend (https://hackmd.io/2iq_CmjHR8mK0UL7e4bYaw#napari-codebase-related).

This effort could be related also with #49

Outline

  • UI sections:
    • Application menus
    • Application status bar
    • Layer controls
    • Layer list
    • Viewer
    • Console (probably plugins dockwidgets in general using the Console plugin as example)
    • Dialogs:
      • Preferences
      • Plugins
      • About
      • Warning/Error/Information notifications dialogs

The sections above come from what I have explored from the source code but probably there are more UI sections.

Creating an issue for this as discussed with @potating-potato

@dalthviz dalthviz added the content Ideas for new or improved content label Jan 18, 2023
@dalthviz dalthviz changed the title Add documentation mapping visual UI, code structure, modules and classes Add documentation mapping visual UI with code structure, modules and classes Jan 18, 2023
@dalthviz
Copy link
Member Author

As an update on this, I have been checking/playing around with some packages/utilities to generate diagrams:

As an example running the following command (setting the path to the napari/napari/_qt/containers/qt_layer_list.py module) you can get a graph telling you dependencies between modules with pydeps for the layer list UI section and a .json representation of the detected dependencies (uploading it here as .txtdue to GitHub constraints):

pydeps <path to /napari/napari/_qt/containers/qt_layer_list.py> --rankdir BT --exclude napari.utils napari._qt.containers.qt_tree* --exclude-exact napari napari._lazy napari._version napari._qt napari._qt.qt_event_loop napari._qt.qt_main_window --only napari -T png -o layer_list_ui.png --reverse --start-color 180 --show-deps > pydeps_deps_output.json

layer_list_ui

pydeps_deps_output.txt

And running the following (setting the path to the napari directory) you can get a class diagram for the related class that contains the layer list (QtLayerList) with pyreverse:

pyreverse -ASmy -c napari._qt.containers.qt_layer_list.QtLayerList <path to napari module> -o png

napari _qt containers qt_layer_list QtLayerList

However, seems like some relations are not shown unless I change the code to add attributes like the delegate. If I add a layer_delegate attribute to the QtLayerList class I get a more interesting class diagram:

napari _qt containers qt_layer_list QtLayerList

For the moment I will try to programmatically use pydeps, further refine/add missing things to the diagram and check ways to reuse the dependencies calculation from pydeps to create a directory layout related to a specific UI section.

If you have any other tools suggestions let me know!

@melissawm
Copy link
Member

Did you have a look at mermaid? Probably a lot less powerful than the options you looked at, but has the advantage of being a lot more readable.

@dalthviz
Copy link
Member Author

Will take a look at it, thanks for the suggestion!

@psobolewskiPhD
Copy link
Member

Those look pretty cool @dalthviz but very much 🤯

@dalthviz
Copy link
Member Author

dalthviz commented Jan 30, 2023

Is quite interesting what you can generate with some tools although seems like the generation process needs some level of refinement to actually be useful most of the time :)

I started checking @melissawm mermaid suggestion and seems like the syntax is quite similar to markdown, Github supports rendering it and can be added to the documentation with the sphinxcontrib.mermaid extension. The only thing is that I haven't found something that generates diagrams from code with mermaid (the diagrams will need to be created manually from what I have checked).

Also, seems like pyreverse and pydeps can output the graphs as .dot files which I think can be included in the docs with the sphinx.ext.graphviz extension (although it requires having the dot executable for it to work). Maybe it could be nice to generate the graphs as .dot and try to translate those to mermaid syntax to enable easy rendering on the current docs?

@dalthviz
Copy link
Member Author

dalthviz commented Jan 30, 2023

Dot vs mermaid representation:

Dot representation of the modules dependencies graph Mermaid representation of the modules dependencies graph without styling (rendered by GitHub when setting mermaid as language)
digraph G {
    concentrate = true;
rankdir = LR;
node [style=filled,fillcolor="#ffffff",fontcolor="#000000",fontname=Helvetica,fontsize=10];

napari__qt_containers [fillcolor="#05c7c7",label="napari\.\n_qt\.\ncontainers"];
napari__qt_containers__base_item_model [fillcolor="#3bcece",label="napari\.\n_qt\.\ncontainers\.\n_base_item_model"];
napari__qt_containers__factory [fillcolor="#46a4a4",label="napari\.\n_qt\.\ncontainers\.\n_factory"];
napari__qt_containers__layer_delegate [fillcolor="#409696",fontcolor="#ffffff",label="napari\.\n_qt\.\ncontainers\.\n_layer_delegate"];
napari__qt_containers_qt_layer_list [fillcolor="#3a8888",fontcolor="#ffffff",label="napari\.\n_qt\.\ncontainers\.\nqt_layer_list"];
napari__qt_containers_qt_layer_model [fillcolor="#3ab0b0",label="napari\.\n_qt\.\ncontainers\.\nqt_layer_model"];
napari__qt_containers_qt_list_model [fillcolor="#31c4c4",label="napari\.\n_qt\.\ncontainers\.\nqt_list_model"];
napari__qt_containers_qt_list_view [fillcolor="#3db8b8",label="napari\.\n_qt\.\ncontainers\.\nqt_list_view"];
napari_components [fillcolor="#24d0d0",label="napari\.\ncomponents"];
napari_components_layerlist [fillcolor="#26d9d9",label="napari\.\ncomponents\.\nlayerlist"];
napari_layers [fillcolor="#26d9d9",label="napari.layers"];
napari__qt_containers__layer_delegate -> napari__qt_containers__base_item_model [fillcolor="#409696",weight="3"];
napari__qt_containers_qt_layer_list -> napari__qt_containers__base_item_model [fillcolor="#3a8888",weight="3"];
napari__qt_containers_qt_list_model -> napari__qt_containers__base_item_model [fillcolor="#31c4c4",weight="3"];
napari__qt_containers -> napari__qt_containers__factory [fillcolor="#05c7c7",weight="3"];
napari__qt_containers_qt_layer_list -> napari__qt_containers__layer_delegate [fillcolor="#3a8888",weight="3"];
napari__qt_containers -> napari__qt_containers_qt_layer_list [fillcolor="#05c7c7",weight="3"];
napari__qt_containers -> napari__qt_containers_qt_layer_model [fillcolor="#05c7c7",weight="3"];
napari__qt_containers__layer_delegate -> napari__qt_containers_qt_layer_model [fillcolor="#409696",weight="3"];
napari__qt_containers -> napari__qt_containers_qt_list_model [fillcolor="#05c7c7",weight="3"];
napari__qt_containers_qt_layer_model -> napari__qt_containers_qt_list_model [fillcolor="#3ab0b0",weight="3"];
napari__qt_containers_qt_list_view -> napari__qt_containers_qt_list_model [fillcolor="#3db8b8",weight="3"];
napari__qt_containers -> napari__qt_containers_qt_list_view [fillcolor="#05c7c7",weight="3"];
napari__qt_containers_qt_layer_list -> napari__qt_containers_qt_list_view [fillcolor="#3a8888",weight="3"];
napari__qt_containers__factory -> napari_components [fillcolor="#46a4a4",minlen="3"];
napari__qt_containers__layer_delegate -> napari_components [fillcolor="#409696",minlen="3"];
napari__qt_containers_qt_layer_list -> napari_components [fillcolor="#3a8888",minlen="3"];
napari__qt_containers__factory -> napari_components_layerlist [fillcolor="#46a4a4",minlen="3"];
napari__qt_containers__layer_delegate -> napari_components_layerlist [fillcolor="#409696",minlen="3"];
napari__qt_containers_qt_layer_list -> napari_components_layerlist [fillcolor="#3a8888",minlen="3"];
napari_components -> napari_components_layerlist [fillcolor="#24d0d0",weight="2"];
napari__qt_containers_qt_layer_list -> napari_layers [fillcolor="#3a8888",minlen="3"];
napari__qt_containers_qt_layer_model -> napari_layers [fillcolor="#3ab0b0",minlen="3"];
napari_components_layerlist -> napari_layers [fillcolor="#26d9d9",minlen="2"];

}

imagen

flowchart LR

napari._qt.containers._layer_delegate --> napari._qt.containers._base_item_model
napari._qt.containers.qt_layer_list --> napari._qt.containers._base_item_model
napari._qt.containers.qt_list_model --> napari._qt.containers._base_item_model
napari._qt.containers --> napari._qt.containers._factory
napari._qt.containers.qt_layer_list --> napari._qt.containers._layer_delegate
napari._qt.containers --> napari._qt.containers.qt_layer_list
napari._qt.containers --> napari._qt.containers.qt_layer_model
napari._qt.containers._layer_delegate --> napari._qt.containers.qt_layer_model
napari._qt.containers --> napari._qt.containers.qt_list_model
napari._qt.containers.qt_layer_model --> napari._qt.containers.qt_list_model
napari._qt.containers.qt_list_view --> napari._qt.containers.qt_list_model
napari._qt.containers --> napari._qt.containers.qt_list_view
napari._qt.containers.qt_layer_list --> napari._qt.containers.qt_list_view
napari._qt.containers._factory --> napari.components
napari._qt.containers._layer_delegate --> napari.components
napari._qt.containers.qt.layer_list --> napari.components
napari._qt.containers._factory --> napari.components.layerlist
napari._qt.containers._layer_delegate --> napari.components.layerlist
napari._qt.containers.qt_layer_list --> napari.components.layerlist
napari.components --> napari.components.layerlist
napari._qt.containers.qt_layer_list --> napari.layers
napari._qt.containers.qt_layer_model --> napari.layers
napari.components.layerlist --> napari.layers

flowchart LR

   napari._qt.containers._layer_delegate --> napari._qt.containers._base_item_model
    napari._qt.containers.qt_layer_list --> napari._qt.containers._base_item_model
    napari._qt.containers.qt_list_model --> napari._qt.containers._base_item_model
    napari._qt.containers --> napari._qt.containers._factory
    napari._qt.containers.qt_layer_list --> napari._qt.containers._layer_delegate
    napari._qt.containers --> napari._qt.containers.qt_layer_list
    napari._qt.containers --> napari._qt.containers.qt_layer_model
    napari._qt.containers._layer_delegate --> napari._qt.containers.qt_layer_model
    napari._qt.containers --> napari._qt.containers.qt_list_model
    napari._qt.containers.qt_layer_model --> napari._qt.containers.qt_list_model
    napari._qt.containers.qt_list_view --> napari._qt.containers.qt_list_model
    napari._qt.containers --> napari._qt.containers.qt_list_view
    napari._qt.containers.qt_layer_list --> napari._qt.containers.qt_list_view
    napari._qt.containers._factory --> napari.components
    napari._qt.containers._layer_delegate --> napari.components
    napari._qt.containers.qt.layer_list --> napari.components
    napari._qt.containers._factory --> napari.components.layerlist
    napari._qt.containers._layer_delegate --> napari.components.layerlist
    napari._qt.containers.qt_layer_list --> napari.components.layerlist
    napari.components --> napari.components.layerlist
    napari._qt.containers.qt_layer_list --> napari.layers
    napari._qt.containers.qt_layer_model --> napari.layers
    napari.components.layerlist --> napari.layers
Loading

@dalthviz
Copy link
Member Author

dalthviz commented Feb 3, 2023

After playing around a little bit more I was able to generate the directory layout using the dependency graph generated by pydeps with the seedir package and a simple mermaid diagram inside a .md file that looks like this:

Layers list

Dependencies diagram (related modules)

graph LR
	napari._qt.containers._base_item_model(napari._qt.containers._base_item_model)
	napari._qt.containers._layer_delegate(napari._qt.containers._layer_delegate)
	napari._qt.containers._layer_delegate --> napari._qt.containers._base_item_model
	napari._qt.containers._layer_delegate --> napari._qt.containers.qt_layer_model
	napari._qt.containers._layer_delegate --> napari.components
	napari._qt.containers._layer_delegate --> napari.components.layerlist
	napari._qt.containers.qt_layer_list(napari._qt.containers.qt_layer_list)
	napari._qt.containers.qt_layer_list --> napari._qt.containers._base_item_model
	napari._qt.containers.qt_layer_list --> napari._qt.containers._layer_delegate
	napari._qt.containers.qt_layer_list --> napari._qt.containers.qt_list_view
	napari._qt.containers.qt_layer_list --> napari.components
	napari._qt.containers.qt_layer_list --> napari.components.layerlist
	napari._qt.containers.qt_layer_list --> napari.layers
	napari._qt.containers.qt_layer_model(napari._qt.containers.qt_layer_model)
	napari._qt.containers.qt_layer_model --> napari._qt.containers.qt_list_model
	napari._qt.containers.qt_layer_model --> napari.layers
	napari._qt.containers.qt_list_model(napari._qt.containers.qt_list_model)
	napari._qt.containers.qt_list_model --> napari._qt.containers._base_item_model
	napari._qt.containers.qt_list_view(napari._qt.containers.qt_list_view)
	napari._qt.containers.qt_list_view --> napari._qt.containers.qt_list_model
	napari.components(napari.components)
	napari.components --> napari.components.layerlist
	napari.components.layerlist(napari.components.layerlist)
	napari.components.layerlist --> napari.layers
	napari.layers(napari.layers)
Loading

Source code directory layout

napari/
├─components/
│ ├─layerlist.py
│ └─__init__.py
├─layers/
│ └─__init__.py
└─_qt/
  └─containers/
    ├─qt_layer_list.py
    ├─qt_layer_model.py
    ├─qt_list_model.py
    ├─qt_list_view.py
    ├─_base_item_model.py
    └─_layer_delegate.py

layers_list_ui_doc_page.zip

The script I'm using to generate the page:

ui_sections_docs.zip

To run the code above you need to have GraphViz installed/the dot exectuable in your path and install pydeps, seedir and napari in your env (if you are using conda I would suggest to create an env with conda with only Python in it and install everything with pip since seedir is not available from conda-forge)

Running the script should generate a .md and a .png file inside a layers list directory relative to your current working directory.

I will check now what I can generate for the other sections and maybe explore adding some style to the mermaid diagram but if anyone has suggestions, comments or ideas about this let me know!

@liu-ziyang
Copy link

This looks great! Would we be able to infer connection between the GUI and this graph in some way? It would be awesome to be able to answer "I want to edit the size of this button but where is the code for it?"

@dalthviz
Copy link
Member Author

dalthviz commented Feb 6, 2023

That's an interesting idea! I'm not sure how something like that can be done but I will check 👍

Also, I was checking and seems like you can add links to an URL inside the mermaid diagram so for each node we could add a link to the module file on GitHub or a link to get further information but I guess that's a different idea from the GUI to code above 😅 (at least in terms of granularity)

@dalthviz
Copy link
Member Author

dalthviz commented Feb 9, 2023

Playing around a little bit with the definition of an eventFilter and the idea of having a way to check where things are defined by interacting with the GUI, I was able to capture some info. Basically, if you want to now the related classes for a specific thing in the GUI, you could define that an event like Ctrl + mouse right click should be captured and using the info related to the event show in, for example the console you launched Napari, something like the above (module, class and in general info of the objects related with the click event):

info_press

So, for example you could Ctrl +mouse right click the trash push button in the layer list section and learn that is an instance of the QtDeleteButton class which is defined at napari._qt.widgets.qt_viewer_buttons

Here how the eventFilter code looks:

https://github.com/dalthviz/napari/blob/68cb9f9f5054c2357da69049f78ae34c506d1926/napari/_qt/qt_main_window.py#L198-L226

Branch with the eventFilter code if you want to play with it locally: https://github.com/dalthviz/napari/tree/event_filter

Maybe a more polished way to do this could be worthy to explore? Like showing the output in a dockwidget and activating the functionality through a setting like with NAPARI_PERFMON or something like that?

@liu-ziyang
Copy link

I think this can be useful as a debugging/info option

@psobolewskiPhD
Copy link
Member

Wow that looks super useful!
I think making it easier to connect what GUI items live where in the codebase like this would be really cool and helpful to new contributors/core devs.
I wonder if it's something to implement as a plugin maybe? like the console?
Then we could make it part of [dev] for example.
Just spitballing, curious what other folks think.

@andy-sweet
Copy link
Member

Agreed this would be super useful developer/debugging tool.

I think adding a setting section for developer settings might make sense, then I think we could add one for this (as well perfmon), so that it can be easily enabled either through the GUI or with an environment variable.

@dalthviz
Copy link
Member Author

So I went for the plugin approach and created a simple plugin with a widget that can show the output of the event and install/uninstall the event filter (I used the cookiecutter template to create it). I put the code in a repo just in case someone wants to check it.

Screenshot 2023-02-17 at 1 40 02 PM

@dalthviz
Copy link
Member Author

An update regarding the docs generation part (generating a .md file for each section mentioned in the OP and adding links to the mermaid diagrams to GitHub). So for example for the layers list you can get:

Layers list

Dependencies diagram (related napari modules)

graph LR
	napari._qt(napari._qt)
	napari._qt --> napari._qt.qt_main_window
	click napari._qt "https://github.com/napari/napari/tree/main/napari/_qt/__init__.py" _blank
	napari._qt._qapp_model(napari._qt._qapp_model)
	napari._qt._qapp_model --> napari._qt._qapp_model._menus
	click napari._qt._qapp_model "https://github.com/napari/napari/tree/main/napari/_qt/_qapp_model/__init__.py" _blank
	napari._qt._qapp_model._menus(napari._qt._qapp_model._menus)
	click napari._qt._qapp_model._menus "https://github.com/napari/napari/tree/main/napari/_qt/_qapp_model/_menus.py" _blank
	napari._qt.containers(napari._qt.containers)
	napari._qt.containers --> napari._qt.containers._factory
	napari._qt.containers --> napari._qt.containers.qt_layer_list
	napari._qt.containers --> napari._qt.containers.qt_layer_model
	napari._qt.containers --> napari._qt.containers.qt_list_model
	napari._qt.containers --> napari._qt.containers.qt_list_view
	click napari._qt.containers "https://github.com/napari/napari/tree/main/napari/_qt/containers/__init__.py" _blank
	napari._qt.containers._base_item_model(napari._qt.containers._base_item_model)
	click napari._qt.containers._base_item_model "https://github.com/napari/napari/tree/main/napari/_qt/containers/_base_item_model.py" _blank
	napari._qt.containers._base_item_view(napari._qt.containers._base_item_view)
	napari._qt.containers._base_item_view --> napari._qt.containers._base_item_model
	napari._qt.containers._base_item_view --> napari._qt.containers._factory
	click napari._qt.containers._base_item_view "https://github.com/napari/napari/tree/main/napari/_qt/containers/_base_item_view.py" _blank
	napari._qt.containers._factory(napari._qt.containers._factory)
	napari._qt.containers._factory --> napari.components
	napari._qt.containers._factory --> napari.components.layerlist
	click napari._qt.containers._factory "https://github.com/napari/napari/tree/main/napari/_qt/containers/_factory.py" _blank
	napari._qt.containers._layer_delegate(napari._qt.containers._layer_delegate)
	napari._qt.containers._layer_delegate --> napari._qt._qapp_model
	napari._qt.containers._layer_delegate --> napari._qt.containers._base_item_model
	napari._qt.containers._layer_delegate --> napari._qt.containers.qt_layer_model
	napari._qt.containers._layer_delegate --> napari._qt.qt_resources
	napari._qt.containers._layer_delegate --> napari.components
	napari._qt.containers._layer_delegate --> napari.components.layerlist
	click napari._qt.containers._layer_delegate "https://github.com/napari/napari/tree/main/napari/_qt/containers/_layer_delegate.py" _blank
	napari._qt.containers.qt_layer_list(napari._qt.containers.qt_layer_list)
	napari._qt.containers.qt_layer_list --> napari._qt.containers._base_item_model
	napari._qt.containers.qt_layer_list --> napari._qt.containers._layer_delegate
	napari._qt.containers.qt_layer_list --> napari._qt.containers.qt_list_view
	napari._qt.containers.qt_layer_list --> napari.components
	napari._qt.containers.qt_layer_list --> napari.components.layerlist
	napari._qt.containers.qt_layer_list --> napari.layers
	click napari._qt.containers.qt_layer_list "https://github.com/napari/napari/tree/main/napari/_qt/containers/qt_layer_list.py" _blank
	napari._qt.containers.qt_layer_model(napari._qt.containers.qt_layer_model)
	napari._qt.containers.qt_layer_model --> napari._qt.containers.qt_list_model
	napari._qt.containers.qt_layer_model --> napari.layers
	click napari._qt.containers.qt_layer_model "https://github.com/napari/napari/tree/main/napari/_qt/containers/qt_layer_model.py" _blank
	napari._qt.containers.qt_list_model(napari._qt.containers.qt_list_model)
	napari._qt.containers.qt_list_model --> napari._qt.containers._base_item_model
	click napari._qt.containers.qt_list_model "https://github.com/napari/napari/tree/main/napari/_qt/containers/qt_list_model.py" _blank
	napari._qt.containers.qt_list_view(napari._qt.containers.qt_list_view)
	napari._qt.containers.qt_list_view --> napari._qt.containers._base_item_view
	napari._qt.containers.qt_list_view --> napari._qt.containers.qt_list_model
	click napari._qt.containers.qt_list_view "https://github.com/napari/napari/tree/main/napari/_qt/containers/qt_list_view.py" _blank
	napari._qt.qt_main_window(napari._qt.qt_main_window)
	napari._qt.qt_main_window --> napari._qt._qapp_model
	napari._qt.qt_main_window --> napari._qt.qt_resources
	napari._qt.qt_main_window --> napari._qt.qt_viewer
	napari._qt.qt_main_window --> napari._qt.utils
	napari._qt.qt_main_window --> napari._qt.widgets.qt_viewer_dock_widget
	click napari._qt.qt_main_window "https://github.com/napari/napari/tree/main/napari/_qt/qt_main_window.py" _blank
	napari._qt.qt_resources(napari._qt.qt_resources)
	napari._qt.qt_resources --> napari._qt.qt_resources._svg
	click napari._qt.qt_resources "https://github.com/napari/napari/tree/main/napari/_qt/qt_resources/__init__.py" _blank
	napari._qt.qt_resources._svg(napari._qt.qt_resources._svg)
	click napari._qt.qt_resources._svg "https://github.com/napari/napari/tree/main/napari/_qt/qt_resources/_svg.py" _blank
	napari._qt.qt_viewer(napari._qt.qt_viewer)
	napari._qt.qt_viewer --> napari._qt.containers
	napari._qt.qt_viewer --> napari._qt.utils
	napari._qt.qt_viewer --> napari._qt.widgets.qt_viewer_buttons
	napari._qt.qt_viewer --> napari._qt.widgets.qt_viewer_dock_widget
	napari._qt.qt_viewer --> napari.components
	napari._qt.qt_viewer --> napari.components.layerlist
	napari._qt.qt_viewer --> napari.layers
	click napari._qt.qt_viewer "https://github.com/napari/napari/tree/main/napari/_qt/qt_viewer.py" _blank
	napari._qt.utils(napari._qt.utils)
	click napari._qt.utils "https://github.com/napari/napari/tree/main/napari/_qt/utils.py" _blank
	napari._qt.widgets.qt_viewer_buttons(napari._qt.widgets.qt_viewer_buttons)
	click napari._qt.widgets.qt_viewer_buttons "https://github.com/napari/napari/tree/main/napari/_qt/widgets/qt_viewer_buttons.py" _blank
	napari._qt.widgets.qt_viewer_dock_widget(napari._qt.widgets.qt_viewer_dock_widget)
	napari._qt.widgets.qt_viewer_dock_widget --> napari._qt.qt_viewer
	napari._qt.widgets.qt_viewer_dock_widget --> napari._qt.utils
	click napari._qt.widgets.qt_viewer_dock_widget "https://github.com/napari/napari/tree/main/napari/_qt/widgets/qt_viewer_dock_widget.py" _blank
	napari.components(napari.components)
	napari.components --> napari.components.layerlist
	click napari.components "https://github.com/napari/napari/tree/main/napari/components/__init__.py" _blank
	napari.components.layerlist(napari.components.layerlist)
	napari.components.layerlist --> napari.layers
	click napari.components.layerlist "https://github.com/napari/napari/tree/main/napari/components/layerlist.py" _blank
	napari.layers(napari.layers)
	click napari.layers "https://github.com/napari/napari/tree/main/napari/layers/__init__.py" _blank
	classDef default fill:#00c3ff,color:black;
	linkStyle default stroke:#00c3ff
	classDef external fill:#ffa600,color:black;
Loading

Source code directory layout (related to modules inside napari)

napari/
├─components/
│ ├─layerlist.py
│ └─__init__.py
├─layers/
│ └─__init__.py
└─_qt/
  ├─containers/
  │ ├─qt_layer_list.py
  │ ├─qt_layer_model.py
  │ ├─qt_list_model.py
  │ ├─qt_list_view.py
  │ ├─_base_item_model.py
  │ ├─_base_item_view.py
  │ ├─_factory.py
  │ ├─_layer_delegate.py
  │ └─__init__.py
  ├─qt_main_window.py
  ├─qt_resources/
  │ ├─_svg.py
  │ └─__init__.py
  ├─qt_viewer.py
  ├─utils.py
  ├─widgets/
  │ ├─qt_viewer_buttons.py
  │ └─qt_viewer_dock_widget.py
  ├─_qapp_model/
  │ ├─_menus.py
  │ └─__init__.py
  └─__init__.py

Any comment or suggestion is appreciated :)

@dalthviz dalthviz linked a pull request Feb 23, 2023 that will close this issue
4 tasks
@dalthviz
Copy link
Member Author

dalthviz commented Mar 6, 2023

Another update regarding the plugin, after checking the code to debug events pointed out by @brisvag that is at https://github.com/napari/napari/blob/397ef2c4f978e60a0cb231887f46d9de2d76a002/napari/utils/events/debugging.py#L69 I tried adding that functionality to the plugin (adding a way to activate the events logging and show the output inside the plugin while adding support for linking the stacktrace entry to open corresponding file):

napari-ui-tracer-debug-events

If you want to give it a try you can check the code from the debug_events branch of the plugin repo: https://github.com/dalthviz/napari-ui-tracer/tree/debug_events

The implementation patches things to work so probably that needs to be improved but happy to hear any feedback about how something like that could be done properly :)

@imagesc-bot
Copy link

This issue has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/napari-how-to-distinguish-between-shape-added-removed-by-user-and-back-end/78529/2

@dalthviz
Copy link
Member Author

Just in case, I released an initial version of the napari-ui-tracer plugin on PyPI 🎉 : https://pypi.org/project/napari-ui-tracer/ Should I try to publish it also in conda-forge?

Also, the PR related with adding the UI sections in the documentation is at #114 I added there some functionality to zoom the diagrams and organized the nodes a little bit more following the given feedback: #114 (comment)

Any other suggestion or comment is appreciated :)

@dalthviz
Copy link
Member Author

Quick update, the plugin is now available also on conda/conda-forge 🎉 : https://anaconda.org/conda-forge/napari-ui-tracer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content Ideas for new or improved content
Projects
Development

Successfully merging a pull request may close this issue.

6 participants