-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4766b66
commit 6d4fca7
Showing
4 changed files
with
131 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,4 +23,4 @@ repos: | |
rev: "v0.902" | ||
hooks: | ||
- id: mypy | ||
exclude: ^testing|^docs | ||
exclude: ^testing|^docs|_napari_plugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import warnings | ||
from typing import Union | ||
|
||
from napari_plugin_engine import napari_hook_implementation | ||
from qtpy.QtCore import QMimeData, Qt | ||
from qtpy.QtWidgets import QTreeWidget, QTreeWidgetItem | ||
|
||
from ome_types import OME | ||
|
||
|
||
@napari_hook_implementation | ||
def napari_experimental_provide_dock_widget(): | ||
return OMETree, {"name": "OME Metadata Viewer"} | ||
|
||
|
||
@napari_hook_implementation | ||
def napari_get_reader(path): | ||
"""Show OME XML if an ome.xml file is dropped on the viewer.""" | ||
if isinstance(path, str) and path.endswith("ome.xml"): | ||
return view_ome_xml | ||
|
||
|
||
def view_ome_xml(path): | ||
from napari._qt.qt_main_window import _QtMainWindow | ||
|
||
# close your eyes, or look away... | ||
# there is nothing worth looking at here! | ||
window = _QtMainWindow.current() | ||
if not window: | ||
return | ||
viewer = window.qt_viewer.viewer | ||
dw, widget = viewer.window.add_plugin_dock_widget("ome-types") | ||
widget.update(path) | ||
|
||
return [(None,)] # sentinel | ||
|
||
|
||
class OMETree(QTreeWidget): | ||
"""A Widget that can show OME XML""" | ||
|
||
def __init__(self, ome_dict: dict = None, parent=None) -> None: | ||
super().__init__(parent=parent) | ||
self.setAcceptDrops(True) | ||
self.setDropIndicatorShown(True) | ||
self.setHeaderHidden(True) | ||
self.update(ome_dict) | ||
|
||
def update(self, ome: Union[OME, str]): | ||
if not ome: | ||
return | ||
if isinstance(ome, str): | ||
try: | ||
if ome.endswith(".xml"): | ||
ome = OME.from_xml(ome) | ||
elif ome.lower().endswith((".tif", ".tiff")): | ||
ome = OME.from_tiff(ome) | ||
else: | ||
warnings.warn(f"Unrecognized file type: {ome}") | ||
return | ||
except Exception as e: | ||
warnings.warn(f"Could not parse OME metadata from {ome}: {e}") | ||
return | ||
|
||
self._fill_item(ome.dict(exclude_unset=True)) | ||
|
||
def _fill_item(self, obj, item: QTreeWidgetItem = None): | ||
if item is None: | ||
self.clear() | ||
item = self.invisibleRootItem() | ||
if isinstance(obj, dict): | ||
for key, val in sorted(obj.items()): | ||
child = QTreeWidgetItem([key]) | ||
item.addChild(child) | ||
self._fill_item(val, child) | ||
elif isinstance(obj, (list, tuple)): | ||
for n, val in enumerate(obj): | ||
text = val.get("id", n) if hasattr(val, "get") else n | ||
child = QTreeWidgetItem([str(text)]) | ||
item.addChild(child) | ||
self._fill_item(val, child) | ||
else: | ||
t = getattr(obj, "value", str(obj)) | ||
item.setText(0, f"{item.text(0)}: {t}") | ||
|
||
def dropMimeData( | ||
self, parent: QTreeWidgetItem, index: int, data: QMimeData, a | ||
) -> bool: | ||
if data.hasUrls(): | ||
for url in data.urls(): | ||
lf = url.toLocalFile() | ||
if lf.endswith((".xml", ".tiff", ".tif")): | ||
self.update(lf) | ||
return True | ||
return False | ||
|
||
def mimeTypes(self): | ||
return ["text/uri-list"] | ||
|
||
def supportedDropActions(self): | ||
return Qt.CopyAction | ||
|
||
|
||
if __name__ == "__main__": | ||
from qtpy.QtWidgets import QApplication | ||
|
||
app = QApplication([]) | ||
|
||
widget = OMETree() | ||
widget.show() | ||
|
||
app.exec() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from pathlib import Path | ||
|
||
import pytest | ||
|
||
nplg = pytest.importorskip("ome_types._napari_plugin") | ||
|
||
DATA = Path(__file__).parent / "data" | ||
|
||
|
||
@pytest.mark.parametrize("fname", DATA.iterdir(), ids=lambda x: x.stem) | ||
def test_widget(fname, qtbot): | ||
if fname.stem in ("bad.ome", "timestampannotation.ome"): | ||
pytest.xfail() | ||
nplg.OMETree(str(fname)) |