Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ You can install `napari-spatialdata` via [pip]:

pip install napari-spatialdata[all]

The `all` command will install the qt bindings `PyQt5`.
The `all` extra also installs the Qt bindings `PyQt6` (via `napari[pyqt6]`).

Napari now also includes multiple triangulation backends. These improve the speed by which a napari 'Shapes' layer gets
loaded (this does not improve the speed of editing large numbers of shapes yet!). See also the napari
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pre =
spatialdata>=0.7.3a1

all =
napari[pyqt5]
napari[pyqt6]

[options.packages.find]
where = src
Expand Down
28 changes: 16 additions & 12 deletions src/napari_spatialdata/_scatterwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,11 +923,11 @@ def mousePressEvent(self, event: Any) -> None:
logger.debug("Left press detected")

# Get the position of the click in the scene
scene_pos = event.pos()
scene_pos = self.mapToScene(event.pos())

# Check if the click is within the scatter plot view box
if not self.scatter_plot.vb.sceneBoundingRect().contains(scene_pos):
logger.debug("Click outside scatter plot view box, scene position: {scene_pos}")
logger.debug(f"Click outside scatter plot view box, scene position: {scene_pos}")
return

pen = pg.mkPen(color="gray", width=2)
Expand All @@ -938,23 +938,23 @@ def mousePressEvent(self, event: Any) -> None:

if self.drawing:

plot_pos = self.scatter_plot.vb.mapSceneToView(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(scene_pos)

self.current_roi = pg.PolyLineROI(
[], closed=True, removable=True, pen=pen, handlePen=handlePen, hoverPen=hoverPen
)
self.scatter_plot.addItem(self.current_roi)

self.current_points = [(plot_pos.x(), plot_pos.y())]
self.last_pos = (event.pos().x(), event.pos().y())
self.last_pos = (scene_pos.x(), scene_pos.y())

event.accept()

if self.rectangle:

logger.info("Rectangle")

plot_pos = self.scatter_plot.vb.mapSceneToView(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(scene_pos)
self.current_roi = pg.RectROI(
pos=(plot_pos.x(), plot_pos.y()),
size=(0, 0),
Expand All @@ -979,24 +979,25 @@ def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
if self.drawing and self.current_roi is not None:

if self.last_pos is not None:
dist = np.sqrt((event.pos().x() - self.last_pos[0]) ** 2 + (event.pos().y() - self.last_pos[1]) ** 2)
scene_pos = self.mapToScene(event.pos())
dist = np.sqrt((scene_pos.x() - self.last_pos[0]) ** 2 + (scene_pos.y() - self.last_pos[1]) ** 2)

if dist > self.vertex_add_threshold:

plot_pos = self.scatter_plot.vb.mapSceneToView(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(scene_pos)
self.current_points.append((plot_pos.x(), plot_pos.y()))

self.current_roi.setPoints(self.current_points)

self.last_pos = (event.pos().x(), event.pos().y())
self.last_pos = (scene_pos.x(), scene_pos.y())

logger.debug(f"Updated points for PolyLineROI: {self.current_points}")

event.accept()

elif self.rectangle and self.current_roi is not None and self.initial_pos is not None:

plot_pos = self.scatter_plot.vb.mapSceneToView(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(self.mapToScene(event.pos()))
width = plot_pos.x() - self.initial_pos.x() # type: ignore[attr-defined]
height = plot_pos.y() - self.initial_pos.y() # type: ignore[attr-defined]
self.current_roi.setSize([width, height])
Expand All @@ -1010,7 +1011,7 @@ def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
super().mouseMoveEvent(event)

# Get cursor position
scene_pos = event.pos()
scene_pos = self.mapToScene(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(scene_pos)

# Update the cursor position label
Expand All @@ -1021,7 +1022,10 @@ def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:

def mouseReleaseEvent(self, event: Any) -> None:

logger.debug(f"Mouse release event detected at {self.scatter_plot.vb.mapSceneToView(event.pos())}")
# also called by scene().sigMouseClicked with a pyqtgraph MouseClickEvent, whose pos() mapToScene can't take
if isinstance(event, QtGui.QMouseEvent):
scene_pos = self.mapToScene(event.pos())
logger.debug(f"Mouse release event detected at {self.scatter_plot.vb.mapSceneToView(scene_pos)}")

if self.drawing and event.button() == Qt.LeftButton:

Expand Down Expand Up @@ -1049,7 +1053,7 @@ def mouseReleaseEvent(self, event: Any) -> None:
def mouseDoubleClickEvent(self, event: Any) -> None:
if event.button() == Qt.LeftButton:

plot_pos = self.scatter_plot.vb.mapSceneToView(event.pos())
plot_pos = self.scatter_plot.vb.mapSceneToView(self.mapToScene(event.pos()))
point = Point(plot_pos.x(), plot_pos.y())

self.remove_roi(point=point)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_scatterwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ def plot_coords_to_viewport(plot_widget, x, y):

def send_mouse_event(event_type, widget, pos, button=QtCore.Qt.LeftButton):
"""Send a mouse event to a widget."""
# necessary because of https://bugreports.qt.io/browse/QTBUG-5232
event = QtGui.QMouseEvent(event_type, pos, button, button, QtCore.Qt.NoModifier)
# necessary because of https://bugreports.qt.io/browse/QTBUG-5232; Qt6 bindings need a QPointF position
event = QtGui.QMouseEvent(event_type, QtCore.QPointF(pos), button, button, QtCore.Qt.NoModifier)
QtWidgets.QApplication.sendEvent(widget, event)


Expand Down
2 changes: 1 addition & 1 deletion tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def test_old_annotation(adata_labels, annotation_values, mocker):
col_name = scatter_widget.model.adata.obs.columns[0]
mocker.patch.object(scatter_widget, "open_annotation_dialog", return_value=col_name)
mocker.patch.object(scatter_widget.plot_widget, "get_selection", return_value=annotation_values)
mocker.patch("PyQt5.QtWidgets.QMessageBox.question", return_value=QtWidgets.QMessageBox.Yes)
mocker.patch.object(QtWidgets.QMessageBox, "question", return_value=QtWidgets.QMessageBox.Yes)

scatter_widget.export()

Expand Down
1 change: 0 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ deps =
pytest-cov
pytest-qt
pytest-mock
PyQt5
passenv =
CI
GITHUB_ACTIONS
Expand Down
Loading