napari-plugin-manager 0.1.0a2__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ from qtpy.QtCore import Signal
2
+ from qtpy.QtGui import QMouseEvent
3
+ from qtpy.QtWidgets import QLabel
4
+
5
+
6
+ class ClickableLabel(QLabel):
7
+ clicked = Signal()
8
+
9
+ def __init__(self, parent=None):
10
+ super().__init__(parent=parent)
11
+
12
+ def mouseReleaseEvent(self, event: QMouseEvent):
13
+ super().mouseReleaseEvent(event)
14
+ self.clicked.emit()
@@ -0,0 +1,383 @@
1
+ /* ------------ Plugin Dialog ------------ */
2
+ /*
3
+
4
+ To be able to use this custom qss, we must use the `get_current_stylesheet` helper that napari provides.
5
+ By using that function we can replace the variables that are used in this stylesheet, e.g. `foreground`.
6
+
7
+ To use `get_current_stylesheet` you can import from:
8
+
9
+ ```python
10
+ from napari._qt.qt_resources import get_current_stylesheet
11
+ ```
12
+
13
+ */
14
+ QCollapsible#install_info_button {
15
+ background-color: {{ darken(foreground, 20) }};
16
+ color: {{ darken(text, 15) }};
17
+ }
18
+ QWidget#info_widget {
19
+ background-color: {{ darken(foreground, 20) }};
20
+ margin: 0px;
21
+ padding: 0px;
22
+ font: 11px;
23
+ }
24
+
25
+ QLabel#author_text {
26
+ color: {{ darken(text, 35) }};
27
+ }
28
+
29
+ QElidingLabel#summary_text {
30
+ color: {{ darken(text, 35) }};
31
+ }
32
+
33
+
34
+ QLabel#install_choice {
35
+ background-color: {{ current }};
36
+ color: {{ darken(text, 35) }};
37
+ }
38
+
39
+ QLabel#plugin_name_web {
40
+ background-color: {{ darken(foreground, 20) }};
41
+ }
42
+
43
+ QLabel#plugin_name_web:hover {
44
+ background-color: {{ foreground }}
45
+ }
46
+
47
+ QLabel#plugin_name {
48
+ background-color: {{ darken(foreground, 20) }};
49
+ }
50
+ QLabel#plugin_name:hover {
51
+ background-color: {{ darken(foreground, 20) }};
52
+ }
53
+
54
+ QWidget#install_choice_widget {
55
+ background-color: {{ darken(foreground, 20) }};
56
+ color: {{ darken(text, 35) }};
57
+ margin: 0px;
58
+ padding: 0px;
59
+ font: 11px;
60
+ }
61
+
62
+ QPluginList {
63
+ background-color: {{ console }};
64
+ }
65
+
66
+ PluginListItem {
67
+ background: {{ darken(foreground, 20) }};
68
+ padding: 0;
69
+ margin: 2px 4px;
70
+ border-radius: 3px;
71
+ }
72
+
73
+ PluginListItem#unavailable {
74
+ background: {{ lighten(foreground, 20) }};
75
+ padding: 0;
76
+ margin: 2px 4px;
77
+ border-radius: 3px;
78
+ }
79
+
80
+ PluginListItem QCheckBox::indicator:disabled {
81
+ background-color: {{ opacity(foreground, 127) }};
82
+ image: url("theme_{{ id }}:/check_50.svg");
83
+ }
84
+
85
+ QPushButton#install_button {
86
+ background-color: {{ current }}
87
+ }
88
+
89
+ QPushButton#install_button:hover {
90
+ background-color: {{ lighten(current, 10) }}
91
+ }
92
+
93
+ QPushButton#install_button:pressed {
94
+ background-color: {{ darken(current, 10) }}
95
+ }
96
+
97
+ QPushButton#install_button:disabled {
98
+ background-color: {{ lighten(current, 20) }}
99
+ }
100
+
101
+ QPushButton#remove_button {
102
+ background-color: {{ error }}
103
+ }
104
+
105
+ QPushButton#remove_button:hover {
106
+ background-color: {{ lighten(error, 10) }}
107
+ }
108
+
109
+ QPushButton#remove_button:pressed {
110
+ background-color: {{ darken(error, 10) }}
111
+ }
112
+
113
+ QPushButton#busy_button:pressed {
114
+ background-color: {{ darken(secondary, 10) }}
115
+ }
116
+
117
+ QPushButton#busy_button {
118
+ background-color: {{ secondary }}
119
+ }
120
+
121
+ QPushButton#busy_button:hover {
122
+ background-color: {{ lighten(secondary, 10) }}
123
+ }
124
+
125
+ QPushButton#busy_button:pressed {
126
+ background-color: {{ darken(secondary, 10) }}
127
+ }
128
+
129
+ QPushButton#close_button:disabled {
130
+ background-color: {{ lighten(secondary, 10) }}
131
+ }
132
+
133
+ QPushButton#refresh_button:disabled {
134
+ background-color: {{ lighten(secondary, 10) }}
135
+ }
136
+
137
+ #small_text {
138
+ color: {{ opacity(text, 150) }};
139
+ font-size: {{ decrease(font_size, 2) }};
140
+ }
141
+
142
+ #small_italic_text {
143
+ color: {{ opacity(text, 150) }};
144
+ font-size: {{ font_size }};
145
+ font-style: italic;
146
+ }
147
+
148
+ #plugin_manager_process_status{
149
+ background: {{ background }};
150
+ color: {{ opacity(text, 200) }};
151
+ }
152
+
153
+ #info_icon {
154
+ image: url("theme_{{ id }}:/info.svg");
155
+ min-width: 18px;
156
+ min-height: 18px;
157
+ margin: 2px;
158
+ }
159
+
160
+ #warning_icon {
161
+ image: url("theme_{{ id }}:/warning.svg");
162
+ max-width: 14px;
163
+ max-height: 14px;
164
+ min-width: 14px;
165
+ min-height: 14px;
166
+ margin: 0px;
167
+ margin-left: 1px;
168
+ padding: 2px;
169
+ background: darken(foreground, 20);
170
+ }
171
+
172
+ #warning_icon:hover{
173
+ background: {{ foreground }};
174
+ }
175
+
176
+ #warning_icon:pressed{
177
+ background: {{ primary }};
178
+ }
179
+
180
+ #error_label {
181
+ image: url("theme_{{ id }}:/warning.svg");
182
+ max-width: 18px;
183
+ max-height: 18px;
184
+ min-width: 18px;
185
+ min-height: 18px;
186
+ margin: 0px;
187
+ margin-left: 1px;
188
+ padding: 2px;
189
+ }
190
+
191
+ #success_label {
192
+ image: url("theme_{{ id }}:/check.svg");
193
+ max-width: 18px;
194
+ max-height: 18px;
195
+ min-width: 18px;
196
+ min-height: 18px;
197
+ margin: 0px;
198
+ margin-left: 1px;
199
+ padding: 2px;
200
+ }
201
+
202
+ #help_label {
203
+ image: url("theme_{{ id }}:/help.svg");
204
+ max-width: 18px;
205
+ max-height: 18px;
206
+ min-width: 18px;
207
+ min-height: 18px;
208
+ margin: 0px;
209
+ margin-left: 1px;
210
+ padding: 2px;
211
+ }
212
+
213
+
214
+ QtPluginDialog QSplitter{
215
+ padding-right: 2;
216
+ }
217
+
218
+
219
+ QtPluginSorter {
220
+ padding: 20px;
221
+ }
222
+
223
+
224
+ QtFontSizePreview {
225
+ border: 1px solid {{ foreground }};
226
+ border-radius: 5px;
227
+ }
228
+
229
+ QListWidget#Preferences {
230
+ background: {{ background }};
231
+ }
232
+
233
+
234
+ QtWelcomeWidget, QtWelcomeWidget[drag=false] {
235
+ background: {{ canvas }};
236
+ }
237
+
238
+ QtWelcomeWidget[drag=true] {
239
+ background: {{ highlight }};
240
+ }
241
+
242
+ QtWelcomeLabel {
243
+ color: {{ foreground }};
244
+ font-size: {{ increase(font_size, 8) }};
245
+ }
246
+
247
+ QtShortcutLabel {
248
+ color: {{ foreground }};
249
+ font-size: {{ increase(font_size, 4) }};
250
+ }
251
+
252
+
253
+ /* ------------- Narrow scrollbar for qtlayer list --------- */
254
+
255
+ QtListView {
256
+ background: {{ background }};
257
+ }
258
+
259
+ QtListView QScrollBar:vertical {
260
+ max-width: 8px;
261
+ }
262
+
263
+ QtListView QScrollBar::add-line:vertical,
264
+ QtListView QScrollBar::sub-line:vertical {
265
+ height: 10px;
266
+ width: 8px;
267
+ margin-top: 2px;
268
+ margin-bottom: 2px;
269
+ }
270
+
271
+ QtListView QScrollBar:up-arrow,
272
+ QtListView QScrollBar:down-arrow {
273
+ min-height: 6px;
274
+ min-width: 6px;
275
+ max-height: 6px;
276
+ max-width: 6px;
277
+ }
278
+
279
+ QtListView::item {
280
+ padding: 4px;
281
+ margin: 2px 2px 2px 2px;
282
+ background-color: {{ foreground }};
283
+ border: 1px solid {{ foreground }};
284
+ }
285
+
286
+ QtListView::item:hover {
287
+ background-color: {{ lighten(foreground, 3) }};
288
+ }
289
+
290
+ /* in the QSS context "active" means the window is active */
291
+ /* (as opposed to focused on another application) */
292
+ QtListView::item:selected:active{
293
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 {{ current }}, stop: 1 {{ darken(current, 15) }});
294
+ }
295
+
296
+
297
+ QtListView::item:selected:!active {
298
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 {{ darken(current, 10) }}, stop: 1 {{ darken(current, 25) }});
299
+ }
300
+
301
+
302
+ QtListView QLineEdit {
303
+ background-color: {{ darken(current, 20) }};
304
+ selection-background-color: {{ lighten(current, 20) }};
305
+ font-size: {{ font_size }};
306
+ }
307
+
308
+ QtLayerList::item {
309
+ margin: 2px 2px 2px 28px;
310
+ border-top-right-radius: 2px;
311
+ border-bottom-right-radius: 2px;
312
+ border: 0;
313
+ }
314
+
315
+ /* the first one is the "partially checked" state */
316
+ QtLayerList::indicator {
317
+ width: 16px;
318
+ height: 16px;
319
+ position: absolute;
320
+ left: 0px;
321
+ image: url("theme_{{ id }}:/visibility_off.svg");
322
+ }
323
+
324
+ QtLayerList::indicator:unchecked {
325
+ image: url("theme_{{ id }}:/visibility_off_50.svg");
326
+
327
+ }
328
+
329
+ QtLayerList::indicator:checked {
330
+ image: url("theme_{{ id }}:/visibility.svg");
331
+ }
332
+
333
+
334
+ #error_icon_btn {
335
+ qproperty-icon: url("theme_{{ id }}:/error.svg");
336
+ }
337
+
338
+ #warning_icon_btn {
339
+ qproperty-icon: url("theme_{{ id }}:/warning.svg");
340
+ }
341
+
342
+ #warning_icon_element {
343
+ image: url("theme_{{ id }}:/warning.svg");
344
+ min-height: 36px;
345
+ min-width: 36px;
346
+ }
347
+
348
+ #error_icon_element {
349
+ image: url("theme_{{ id }}:/error.svg");
350
+ min-height: 36px;
351
+ min-width: 36px;
352
+ }
353
+
354
+ QToolButton {
355
+ background-color: {{ darken(foreground, 20) }};
356
+ color: {{ darken(text, 15) }};
357
+ padding: 3 12px;
358
+ font: 14px;
359
+ }
360
+
361
+ QToolButton:hover {
362
+ background-color: {{ lighten(foreground, 10) }}
363
+ }
364
+
365
+ QToolButton:pressed {
366
+ background-color: {{ lighten(foreground, 20) }}
367
+ }
368
+
369
+ QToolButton::menu-arrow {
370
+ image: url("theme_{{ id }}:/down_arrow.svg");
371
+ top: 0px;
372
+ left: 0px;
373
+ width: 8px;
374
+ height: 8px;
375
+ }
376
+
377
+ QToolButton[popupMode="1"]{
378
+ padding-right: 20px;
379
+ }
380
+
381
+ QToolButton::menu-button {
382
+ width: 16px;
383
+ }
@@ -0,0 +1,22 @@
1
+ import re
2
+ import sys
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+
7
+ def is_conda_package(pkg: str, prefix: Optional[str] = None) -> bool:
8
+ """Determines if plugin was installed through conda.
9
+
10
+ Returns
11
+ -------
12
+ bool
13
+ ``True` if a conda package, ``False`` if not.
14
+ """
15
+ # Installed conda packages within a conda installation and environment can
16
+ # be identified as files with the template ``<package-name>-<version>-<build-string>.json``
17
+ # saved within a ``conda-meta`` folder within the given environment of interest.
18
+ conda_meta_dir = Path(prefix or sys.prefix) / 'conda-meta'
19
+ return any(
20
+ re.match(rf"{pkg}-[^-]+-[^-]+.json", p.name)
21
+ for p in conda_meta_dir.glob(f"{pkg}-*-*.json")
22
+ )
@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.1
2
+ Name: napari-plugin-manager
3
+ Version: 0.1.2
4
+ Summary: Install plugins for napari, in napari.
5
+ Author-email: napari team <napari-steering-council@googlegroups.com>
6
+ License: BSD 3-Clause License
7
+
8
+ Copyright (c) 2018, Napari
9
+ All rights reserved.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ * Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimer.
16
+
17
+ * Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ * Neither the name of the copyright holder nor the names of its
22
+ contributors may be used to endorse or promote products derived from
23
+ this software without specific prior written permission.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+
36
+ Project-URL: homepage, https://github.com/napari/napari-plugin-manager
37
+ Classifier: Development Status :: 3 - Alpha
38
+ Classifier: Environment :: X11 Applications :: Qt
39
+ Classifier: Framework :: napari
40
+ Classifier: Intended Audience :: Education
41
+ Classifier: Intended Audience :: Science/Research
42
+ Classifier: License :: OSI Approved :: BSD License
43
+ Classifier: Programming Language :: C
44
+ Classifier: Programming Language :: Python
45
+ Classifier: Programming Language :: Python :: 3 :: Only
46
+ Classifier: Programming Language :: Python :: 3.9
47
+ Classifier: Programming Language :: Python :: 3.10
48
+ Classifier: Programming Language :: Python :: 3.11
49
+ Classifier: Topic :: Scientific/Engineering
50
+ Classifier: Topic :: Scientific/Engineering :: Visualization
51
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
52
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
53
+ Classifier: Topic :: Utilities
54
+ Classifier: Operating System :: Microsoft :: Windows
55
+ Classifier: Operating System :: POSIX
56
+ Classifier: Operating System :: Unix
57
+ Classifier: Operating System :: MacOS
58
+ Requires-Python: >=3.8
59
+ Description-Content-Type: text/markdown
60
+ License-File: LICENSE
61
+ Requires-Dist: npe2
62
+ Requires-Dist: qtpy
63
+ Requires-Dist: superqt
64
+ Requires-Dist: pip
65
+ Provides-Extra: dev
66
+ Requires-Dist: PyQt5; extra == "dev"
67
+ Requires-Dist: pre-commit; extra == "dev"
68
+ Provides-Extra: docs
69
+ Requires-Dist: sphinx>6; extra == "docs"
70
+ Requires-Dist: sphinx-autobuild; extra == "docs"
71
+ Requires-Dist: sphinx-external-toc; extra == "docs"
72
+ Requires-Dist: sphinx-copybutton; extra == "docs"
73
+ Requires-Dist: sphinx-favicon; extra == "docs"
74
+ Requires-Dist: myst-nb; extra == "docs"
75
+ Requires-Dist: napari-sphinx-theme>=0.3.0; extra == "docs"
76
+ Provides-Extra: testing
77
+ Requires-Dist: flaky; extra == "testing"
78
+ Requires-Dist: pytest; extra == "testing"
79
+ Requires-Dist: pytest-cov; extra == "testing"
80
+ Requires-Dist: pytest-qt; extra == "testing"
81
+ Requires-Dist: virtualenv; extra == "testing"
82
+
83
+ # napari-plugin-manager
84
+
85
+ [![License](https://img.shields.io/pypi/l/napari-plugin-manager.svg?color=green)](https://github.com/napari/napari-plugin-manager/raw/main/LICENSE)
86
+ [![PyPI](https://img.shields.io/pypi/v/napari-plugin-manager.svg?color=green)](https://pypi.org/project/napari-plugin-manager)
87
+ [![Python Version](https://img.shields.io/pypi/pyversions/napari-plugin-manager.svg?color=green)](https://python.org)
88
+ [![tests](https://github.com/napari/napari-plugin-manager/actions/workflows/test_and_deploy.yml/badge.svg)](https://github.com/napari/napari-plugin-manager/actions/workflows/test_and_deploy.yml)
89
+ [![codecov](https://codecov.io/gh/napari/napari-plugin-manager/branch/main/graph/badge.svg)](https://codecov.io/gh/napari/napari-plugin-manager)
90
+
91
+ [napari] plugin manager to provide a graphical user interface for installing
92
+ [napari] plugins.
93
+
94
+ You can read the documentation at [napari.org/napari-plugin-manager](https://napari.org/napari-plugin-manager).
95
+
96
+ ## Overview
97
+
98
+ The `napari-plugin-manager` used to be part of the [napari] codebase before the 0.5.x release
99
+ series. It's now maintained as a separate project and package to allow uncoupled iterations outside
100
+ of the `napari` release cycle.
101
+
102
+ Future work will allow other applications with a plugin ecosytem to customize and
103
+ use the `plugin-manager`. This package remains under active development and contributions
104
+ are very welcome. Please [open an issue] to discuss potential improvements.
105
+
106
+ This package currently provides:
107
+
108
+ - A package installer process queue that supports both [pip] and [conda] installs.
109
+ - An easy to use GUI for searching, installing, uninstalling and updating plugins that make part of
110
+ the napari ecosystem. Each plugin entry provides a summary and information on the authors that
111
+ created the package. The REST API used to query for plugins and plugin information is provided by
112
+ the [npe2api service](https://api.napari.org).
113
+ - The ability to install other packages via URL of by dragging and dropping artifacts from [PyPI].
114
+
115
+ ![Screenshot of the napari-plugin-manager interface, showcasing the plugin descriptions](https://raw.githubusercontent.com/napari/napari-plugin-manager/refs/heads/main/images/description.png)
116
+
117
+ `napari-plugin-manager` knows how to detect if napari was installed using `conda` or `pip` and
118
+ provide the appropriate default installer tool on the `Installation Info` dropdown for each plugin.
119
+
120
+ `conda` provides an efficient dependency solver that guarantees the stability and correctness of
121
+ the napari installation and work environment. This is the reason why `conda` is the default tool
122
+ used for the [napari
123
+ bundle](https://napari.org/stable/tutorials/fundamentals/installation_bundle_conda.html), a 1-click
124
+ installer available for Mac, Linux and Windows. This installation method is best if you mainly want
125
+ to use napari as a standalone GUI app. However, certain plugins may not be supported.
126
+
127
+ ## Installation
128
+
129
+ ### PyPI
130
+
131
+ `napari-plugin-manager` is available through the Python Package Index and can be installed using [pip].
132
+
133
+ ```bash
134
+ pip install napari-plugin-manager
135
+ ```
136
+
137
+ ### Conda
138
+
139
+ `napari-plugin-manager` is also available for install using [conda] through the [conda-forge channel](https://conda-forge.org/docs/#what-is-conda-forge).
140
+
141
+
142
+ ```bash
143
+ conda install napari-plugin-manager -c conda-forge
144
+ ```
145
+
146
+ ## Using the napari plugin manager
147
+
148
+ ### Enabling/Disabling plugins
149
+
150
+ Installed plugins found on the current napari installation are displayed on the top list of the UI.
151
+
152
+ Users of napari can choose to enable/disable a specific plugin by checking/unchecking the checkbox
153
+ to the left of each plugin item in the list.
154
+
155
+ ### Filtering
156
+
157
+ You can filter available plugins by name or description by typing on the search box
158
+ on the top left corner of the UI. Only plugins that match the filter criteria will be shown.
159
+
160
+ In the image below filtering by the word `arcos` yields a single plugin, the
161
+ `arcos-gui` plugin. Notice that plugins that provide a display name, will show
162
+ the package name to the right in parenthesis.
163
+
164
+ ![Screenshot of the napari-plugin-manager interface showcasing the filtering features with the query 'arcos'](https://raw.githubusercontent.com/napari/napari-plugin-manager/main/images/filter.png)
165
+
166
+ ### Refreshing
167
+
168
+ If a new plugin has been released but it is not available on the list, you can click on the
169
+ `Refresh` button located at the top right corner, to clear the cache and load all newly
170
+ available plugins.
171
+
172
+ ### Installing a plugin
173
+
174
+ To install a plugin:
175
+
176
+ 1. Select it by scrolling the available plugins list on the bottom, or by directly
177
+ filtering by name or description.
178
+ 2. Select the tool (`conda` or `pip`) and version on the `Installation Info` dropdown.
179
+ 3. Start the installation process by clicking on the `Install` button.
180
+
181
+ You can cancel the process at any time by clicking the `Cancel` button of each plugin.
182
+
183
+ **Note**: Not all napari plugins are currently available on conda via the
184
+ [conda-forge channel](https://anaconda.org/conda-forge/). Some plugins will require
185
+ a restart to be properly configured.
186
+
187
+ ![Screenshot of the napari-plugin-manager showing the process of installing a plugin](https://raw.githubusercontent.com/napari/napari-plugin-manager/main/images/install.png)
188
+
189
+ ### Uninstalling a plugin
190
+
191
+ To uninstall a plugin:
192
+
193
+ 1. Select it by scrolling the installed plugins list on the top, or by directly
194
+ filtering by name or description.
195
+ 2. Start the removal process by clicking on the `Uninstall` button.
196
+
197
+ You can cancel the process at any time by clicking the `Cancel` button of each plugin.
198
+
199
+ **Note**: Some plugins will require a restart to be properly removed.
200
+
201
+ ![Screenshot of the napari-plugin-manager showing the process of uninstalling a plugin](https://raw.githubusercontent.com/napari/napari-plugin-manager/main/images/uninstall.png)
202
+
203
+ ### Updating a plugin
204
+
205
+ When a new version of an installed plugin is available, an `Update (vX.Y.Z)`
206
+ button will appear to the left of the `Installation Info` dropdown.
207
+
208
+ To update a plugin:
209
+
210
+ 1. Select it by scrolling the install plugins list on the top, or by directly
211
+ filtering by name or description.
212
+ 2. Start the update process by clicking on the `Update (vX.Y.Z)` button.
213
+
214
+ You can cancel the process at any time by clicking the `Cancel` button of each plugin.
215
+
216
+ ![Screenshot of the napari-plugin-manager showing the process of updating a plugin](https://raw.githubusercontent.com/napari/napari-plugin-manager/main/images/update.png)
217
+
218
+ ### Batch actions
219
+
220
+ You don't need wait for one action to finish before you can start another one. You can add more
221
+ tasks to the queue (install/uninstall/update) by clicking on the corresponding action buttons
222
+ plugin by plugin. The actions will be carried out sequentially and in the order in which you
223
+ started them.
224
+
225
+ You can cancel all the started installer actions at any time by clicking `Cancel all`
226
+ button at the bottom of the UI.
227
+
228
+ ## Troubleshooting
229
+
230
+ In order to visualize more detailed information on the installer process output, you can
231
+ click on the `Show status` button located at the bottom left corner of the UI. To hide
232
+ this detailed information you can click on the `Hide status` button.
233
+
234
+ Some issues that you might experience when using the installer include:
235
+
236
+ * Incompatible packages due to conflicting dependencies.
237
+ * Network connectivity errors.
238
+
239
+ ![Screenshot of the napari-plugin-manager interface showcasing the status information, which is initially hidden by default.](https://raw.githubusercontent.com/napari/napari-plugin-manager/main/images/status.png)
240
+
241
+ ## License
242
+
243
+ Distributed under the terms of the [BSD-3] license, "napari-plugin-manager" is free and open source
244
+ software.
245
+
246
+ ## Issues
247
+
248
+ If you encounter any problems, please [file an issue] along with a detailed description.
249
+
250
+ [napari]: https://github.com/napari/napari
251
+ [@napari]: https://github.com/napari
252
+ [BSD-3]: http://opensource.org/licenses/BSD-3-Clause
253
+ [file an issue]: https://github.com/napari/napari-plugin-manager/issues
254
+ [open an issue]: https://github.com/napari/napari-plugin-manager/issues
255
+ [pip]: https://pypi.org/project/pip/
256
+ [conda]: https://conda.org
257
+ [PyPI]: https://pypi.org/
@@ -0,0 +1,19 @@
1
+ napari_plugin_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ napari_plugin_manager/_version.py,sha256=SFCDdrYA67D1Je-jHgVVh4LOopkPvuV6NMtqSJ7Tfhg,411
3
+ napari_plugin_manager/npe2api.py,sha256=lpanAxjpvEfGkHwTwVXmTSXWlMrjBxHOJ-p_-LbTW2o,4093
4
+ napari_plugin_manager/qt_package_installer.py,sha256=WPZZY3BQxH1OHm2-TBLf0-brzqV7Wh_Gnwk9hwFPmtQ,21454
5
+ napari_plugin_manager/qt_plugin_dialog.py,sha256=R2oPapmCdr0HHf3LZDcjKgbWeUFpaR7D3BlrciyI7hg,57035
6
+ napari_plugin_manager/qt_widgets.py,sha256=O8t5CbN8r_16cQzshyjvhTEYdUcj7OX0-bfYIiN2uSs,356
7
+ napari_plugin_manager/styles.qss,sha256=9ODPba2IorJybWObWoEO9VGq4AO0IYlAa8brN14tgZU,7379
8
+ napari_plugin_manager/utils.py,sha256=wG_lGPaMmbfyH-q7oTWDYSI2iAKiZ3cqxyjlRlbvFJo,753
9
+ napari_plugin_manager/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ napari_plugin_manager/_tests/conftest.py,sha256=OvzenfBP2oIS6x8ksr9FhPXdsLV3Q_3Kzr6PRJe45Uc,1885
11
+ napari_plugin_manager/_tests/test_installer_process.py,sha256=fgO8OwYcCAz-OlGT_1G_eb4B69DPbnQdzjCrwTIeCpE,10523
12
+ napari_plugin_manager/_tests/test_npe2api.py,sha256=_YPo4jaA9cZ9OeeXn8HMJzijQ7OoWXnSiEN81NEzvhI,1031
13
+ napari_plugin_manager/_tests/test_qt_plugin_dialog.py,sha256=GMQjSWFr_Z-mc47nLNcHowR_hNWc2SkKGhqAqJDXZPs,18866
14
+ napari_plugin_manager/_tests/test_utils.py,sha256=7EilxmDkRjU6UO2AnaqyYovdAs18D0ZA5GCVGN62-3M,720
15
+ napari_plugin_manager-0.1.2.dist-info/LICENSE,sha256=8dAlKbOqTMYe9L-gL_kEx5Xr1Sd0AbaWQDUkpiOp3vI,1506
16
+ napari_plugin_manager-0.1.2.dist-info/METADATA,sha256=gJ0PPHYmsRpdBmLr3UMdxqvyI-C60pKY8A8qV0U8DSs,11967
17
+ napari_plugin_manager-0.1.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
18
+ napari_plugin_manager-0.1.2.dist-info/top_level.txt,sha256=pmCqLetuumhY1CKSuTZ5eQsitzazrSvc7V_mkugEPTY,22
19
+ napari_plugin_manager-0.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5