Skip to content

Commit

Permalink
Merge pull request qupath#1318 from petebankhead/detach-viewers
Browse files Browse the repository at this point in the history
Make viewers 'detachable'
  • Loading branch information
petebankhead committed Sep 11, 2023
2 parents 9a86e32 + 00f07b9 commit 42c2aec
Show file tree
Hide file tree
Showing 53 changed files with 1,148 additions and 600 deletions.
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ This is a work-in-progress for the next QuPath release.
### Enhancements
* New toolbar buttons for script editor `</>` and log viewer
* *File &rarr; Export snapshots* supports PNG, JPEG and TIFF (not just PNG)
* New preference to control whether the 'system menubar' is used globally, or just for the main window
* Makes a difference on macOS, doesn't on Windows... on Linux it depends

### Bugs fixed
* Rendered image export does not support opacity (https://github.com/qupath/qupath/issues/1292)
Expand All @@ -19,6 +17,7 @@ This is a work-in-progress for the next QuPath release.
* PathIO doesn't restore backup if writing ImageData fails (https://github.com/qupath/qupath/issues/1252)
* Scripts open with the caret at the bottom of the text rather than the top (https://github.com/qupath/qupath/issues/1258)
* 'Synchronize viewers' ignores z and t positions (https://github.com/qupath/qupath/issues/1220)
* Menubars and shortcuts are confused when ImageJ is open but QuPath is in focus in macOS (https://github.com/qupath/qupath/issues/6)

### Dependency updates
* Bio-Formats 7.0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -92,9 +92,9 @@ public class SubcellularDetection extends AbstractInteractivePlugin<BufferedImag


@Override
public boolean runPlugin(final PluginRunner<BufferedImage> pluginRunner, final String arg) {
boolean success = super.runPlugin(pluginRunner, arg);
getHierarchy(pluginRunner).fireHierarchyChangedEvent(this);
public boolean runPlugin(final PluginRunner pluginRunner, final ImageData<BufferedImage> imageData, final String arg) {
boolean success = super.runPlugin(pluginRunner, imageData, arg);
imageData.getHierarchy().fireHierarchyChangedEvent(this);
return success;
}

Expand Down Expand Up @@ -441,10 +441,10 @@ public String getDescription() {
}

@Override
protected Collection<PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
protected Collection<PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
Collection<Class<? extends PathObject>> parentClasses = getSupportedParentObjectClasses();
List<PathObject> parents = new ArrayList<>();
for (PathObject parent : getHierarchy(runner).getSelectionModel().getSelectedObjects()) {
for (PathObject parent : imageData.getHierarchy().getSelectionModel().getSelectedObjects()) {
for (Class<? extends PathObject> cls : parentClasses) {
if (cls.isAssignableFrom(parent.getClass())) {
parents.add(parent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -55,7 +55,6 @@
import qupath.lib.plugins.AbstractInteractivePlugin;
import qupath.lib.plugins.ObjectDetector;
import qupath.lib.plugins.PathPlugin;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.plugins.workflow.SimplePluginWorkflowStep;
import qupath.lib.plugins.workflow.WorkflowStep;
Expand Down Expand Up @@ -377,8 +376,8 @@ public String getDescription() {


@Override
protected Collection<? extends PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
return Collections.singletonList(runner.getImageData().getHierarchy().getRootObject());
protected Collection<? extends PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
return Collections.singletonList(imageData.getHierarchy().getRootObject());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -63,7 +63,6 @@
import qupath.lib.plugins.AbstractDetectionPlugin;
import qupath.lib.plugins.DetectionPluginTools;
import qupath.lib.plugins.ObjectDetector;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.ImagePlane;
import qupath.lib.regions.RegionRequest;
Expand Down Expand Up @@ -442,9 +441,9 @@ protected void addRunnableTasks(ImageData<BufferedImage> imageData, PathObject p


@Override
protected Collection<? extends PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
protected Collection<? extends PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {

PathObjectHierarchy hierarchy = getHierarchy(runner);
PathObjectHierarchy hierarchy = imageData.getHierarchy();
if (hierarchy.getTMAGrid() == null)
return Collections.singleton(hierarchy.getRootObject());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -52,7 +52,6 @@
import qupath.lib.objects.PathObjects;
import qupath.lib.plugins.AbstractTileableDetectionPlugin;
import qupath.lib.plugins.ObjectDetector;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.RegionRequest;
import qupath.lib.roi.RoiTools;
Expand Down Expand Up @@ -269,8 +268,8 @@ public String getDescription() {


@Override
protected synchronized Collection<? extends PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
Collection<? extends PathObject> parents = super.getParentObjects(runner);
protected synchronized Collection<? extends PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
Collection<? extends PathObject> parents = super.getParentObjects(imageData);
return parents;

// Exploring the use of hidden objects...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -52,7 +52,6 @@
import qupath.lib.objects.PathObjects;
import qupath.lib.plugins.AbstractTileableDetectionPlugin;
import qupath.lib.plugins.ObjectDetector;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.RegionRequest;
import qupath.lib.roi.RoiTools;
Expand Down Expand Up @@ -549,8 +548,8 @@ public String getDescription() {


@Override
protected synchronized Collection<? extends PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
Collection<? extends PathObject> parents = super.getParentObjects(runner);
protected synchronized Collection<? extends PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
Collection<? extends PathObject> parents = super.getParentObjects(imageData);
return parents;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ public String getDescription() {
}

@Override
protected Collection<PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
return runner.getImageData().getHierarchy().getDetectionObjects();
protected Collection<PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
return imageData.getHierarchy().getDetectionObjects();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -57,7 +57,6 @@
import qupath.lib.objects.PathObject;
import qupath.lib.objects.TMACoreObject;
import qupath.lib.plugins.AbstractInteractivePlugin;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.RegionRequest;
import qupath.lib.roi.interfaces.ROI;
Expand Down Expand Up @@ -476,8 +475,8 @@ public String getDescription() {
}

@Override
protected Collection<PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
return runner.getImageData().getHierarchy().getSelectionModel().getSelectedObjects();
protected Collection<PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
return imageData.getHierarchy().getSelectionModel().getSelectedObjects();
// return runner.getImageData().getHierarchy().getSelectionModel().getSelectedObjects();
// return runner.getImageData().getHierarchy().getObjects(null, PathDetectionObject.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -351,9 +351,9 @@ public float[] getTransformedPixels(final BufferedImage img, int[] buf, final Co


@Override
public boolean runPlugin(final PluginRunner<BufferedImage> pluginRunner, final String arg) {
boolean success = super.runPlugin(pluginRunner, arg);
getHierarchy(pluginRunner).fireHierarchyChangedEvent(this);
public boolean runPlugin(final PluginRunner pluginRunner, final ImageData<BufferedImage> imageData, final String arg) {
boolean success = super.runPlugin(pluginRunner, imageData, arg);
imageData.getHierarchy().fireHierarchyChangedEvent(this);
return success;
}

Expand Down Expand Up @@ -716,8 +716,8 @@ public String getDescription() {
}

@Override
protected Collection<PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
return runner.getImageData().getHierarchy().getSelectionModel().getSelectedObjects();
protected Collection<PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
return imageData.getHierarchy().getSelectionModel().getSelectedObjects();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -50,7 +50,6 @@
import qupath.lib.objects.PathDetectionObject;
import qupath.lib.objects.PathObject;
import qupath.lib.plugins.AbstractInteractivePlugin;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.RegionRequest;
import qupath.lib.roi.interfaces.ROI;
Expand Down Expand Up @@ -310,8 +309,8 @@ public String getDescription() {
}

@Override
protected Collection<PathObject> getParentObjects(final PluginRunner<BufferedImage> runner) {
return runner.getImageData().getHierarchy().getDetectionObjects();
protected Collection<PathObject> getParentObjects(final ImageData<BufferedImage> imageData) {
return imageData.getHierarchy().getDetectionObjects();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -44,7 +44,6 @@
import qupath.lib.objects.PathObjects;
import qupath.lib.objects.hierarchy.PathObjectHierarchy;
import qupath.lib.plugins.AbstractInteractivePlugin;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.regions.ImagePlane;
import qupath.lib.roi.GeometryTools;
Expand Down Expand Up @@ -135,24 +134,24 @@ public ParameterList getDefaultParameterList(ImageData<T> imageData) {
}

@Override
protected Collection<? extends PathObject> getParentObjects(PluginRunner<T> runner) {
return getHierarchy(runner).getSelectionModel().getSelectedObjects().stream().filter(p -> p.isAnnotation()).toList();
protected Collection<? extends PathObject> getParentObjects(ImageData<T> imageData) {
return imageData.getHierarchy().getSelectionModel().getSelectedObjects().stream().filter(p -> p.isAnnotation()).toList();
}

@Override
protected void addRunnableTasks(ImageData<T> imageData, PathObject parentObject, List<Runnable> tasks) {}

@Override
protected Collection<Runnable> getTasks(final PluginRunner<T> runner) {
Collection<? extends PathObject> parentObjects = getParentObjects(runner);
protected Collection<Runnable> getTasks(final ImageData<T> imageData) {
Collection<? extends PathObject> parentObjects = getParentObjects(imageData);
if (parentObjects == null || parentObjects.isEmpty())
return Collections.emptyList();

// Add a single task, to avoid multithreading - which may complicate setting parents
List<Runnable> tasks = new ArrayList<>(parentObjects.size());
ImageServer<T> server = getServer(runner);
ImageServer<T> server = imageData.getServer();
Rectangle bounds = new Rectangle(0, 0, server.getWidth(), server.getHeight());
PathObjectHierarchy hierarchy = getHierarchy(runner);
PathObjectHierarchy hierarchy = imageData.getHierarchy();

double radiusPixels;
PixelCalibration cal = server.getPixelCalibration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import qupath.lib.objects.PathROIObject;
import qupath.lib.objects.hierarchy.PathObjectHierarchy;
import qupath.lib.plugins.AbstractInteractivePlugin;
import qupath.lib.plugins.PluginRunner;
import qupath.lib.plugins.parameters.ParameterList;
import qupath.lib.roi.RoiTools;
import qupath.lib.roi.interfaces.ROI;
Expand Down Expand Up @@ -80,22 +79,22 @@ public ParameterList getDefaultParameterList(ImageData<T> imageData) {
}

@Override
protected Collection<? extends PathObject> getParentObjects(PluginRunner<T> runner) {
return getHierarchy(runner).getSelectionModel().getSelectedObjects().stream().filter(p -> p.isAnnotation()).toList();
protected Collection<? extends PathObject> getParentObjects(ImageData<T> imageData) {
return imageData.getHierarchy().getSelectionModel().getSelectedObjects().stream().filter(p -> p.isAnnotation()).toList();
}

@Override
protected void addRunnableTasks(ImageData<T> imageData, PathObject parentObject, List<Runnable> tasks) {}

@Override
protected Collection<Runnable> getTasks(final PluginRunner<T> runner) {
Collection<? extends PathObject> parentObjects = getParentObjects(runner);
protected Collection<Runnable> getTasks(final ImageData<T> imageData) {
Collection<? extends PathObject> parentObjects = getParentObjects(imageData);
if (parentObjects == null || parentObjects.isEmpty())
return Collections.emptyList();

// Add a single task, to avoid multithreading - which may complicate setting parents
List<Runnable> tasks = new ArrayList<>(1);
PathObjectHierarchy hierarchy = getHierarchy(runner);
PathObjectHierarchy hierarchy = imageData.getHierarchy();

// Want to reset selection
PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* %%
* Copyright (C) 2014 - 2016 The Queen's University of Belfast, Northern Ireland
* Contact: IP Management (ipmanagement@qub.ac.uk)
* Copyright (C) 2018 - 2020 QuPath developers, The University of Edinburgh
* Copyright (C) 2018 - 2023 QuPath developers, The University of Edinburgh
* %%
* QuPath is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
Expand Down Expand Up @@ -113,8 +113,8 @@ public String getLastResultsDescription() {
}

@Override
protected Collection<? extends PathObject> getParentObjects(PluginRunner<T> runner) {
PathObjectHierarchy hierarchy = getHierarchy(runner);
protected Collection<? extends PathObject> getParentObjects(ImageData<T> imageData) {
PathObjectHierarchy hierarchy = imageData.getHierarchy();
PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
if (selected instanceof TMACoreObject)
return Collections.singleton(selected);
Expand All @@ -138,9 +138,9 @@ public ParameterList getDefaultParameterList(ImageData<T> imageData) {


@Override
public boolean runPlugin(final PluginRunner<T> pluginRunner, final String arg) {
public boolean runPlugin(final PluginRunner pluginRunner, final ImageData<T> imageData, final String arg) {
nObjectsRemoved.set(0);
return super.runPlugin(pluginRunner, arg);
return super.runPlugin(pluginRunner, imageData, arg);
}


Expand Down
Loading

0 comments on commit 42c2aec

Please sign in to comment.