MoleditPy-linux 4.6.0__tar.gz → 4.7.0__tar.gz
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.
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/PKG-INFO +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/pyproject.toml +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/SOURCES.txt +1 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/angle_dialog.py +4 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/atom_item.py +29 -28
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/bond_item.py +17 -12
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/bond_length_dialog.py +4 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/custom_interactor_style.py +8 -3
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/dihedral_dialog.py +4 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/edit_3d_logic.py +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/edit_actions_logic.py +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/io_logic.py +36 -15
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/main_window_init.py +1 -1
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/molecular_scene_handler.py +14 -2
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/molecule_scene.py +2 -2
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +9 -5
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/zoomable_view.py +31 -1
- moleditpy_linux-4.7.0/src/moleditpy_linux/utils/hit_radius.py +32 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/LICENSE +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/README.md +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/setup.cfg +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/core/mol_geometry.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/core/molecular_data.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_manager.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/about_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/analysis_window.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/app_state.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/atom_picking.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/chain_mixin.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/compute_logic.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/export_logic.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/main_window.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/string_importers.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/ui_manager.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/constants.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/default_settings.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/suppress_log.py +0 -0
- {moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/system_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.7.0
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.7.0
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -75,6 +75,7 @@ src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py
|
|
|
75
75
|
src/moleditpy_linux/utils/__init__.py
|
|
76
76
|
src/moleditpy_linux/utils/constants.py
|
|
77
77
|
src/moleditpy_linux/utils/default_settings.py
|
|
78
|
+
src/moleditpy_linux/utils/hit_radius.py
|
|
78
79
|
src/moleditpy_linux/utils/sip_isdeleted_safe.py
|
|
79
80
|
src/moleditpy_linux/utils/suppress_log.py
|
|
80
81
|
src/moleditpy_linux/utils/system_utils.py
|
|
@@ -487,7 +487,10 @@ class AngleDialog(GeometryBaseDialog):
|
|
|
487
487
|
if abs(achieved - requested) < 0.5:
|
|
488
488
|
return
|
|
489
489
|
with suppress_log(AttributeError, RuntimeError, TypeError):
|
|
490
|
-
self.main_window.statusBar()
|
|
490
|
+
status_bar = self.main_window.statusBar()
|
|
491
|
+
if status_bar is None:
|
|
492
|
+
return
|
|
493
|
+
status_bar.showMessage(
|
|
491
494
|
f"Angle unchanged ({achieved:.2f} deg): the three atoms rotate "
|
|
492
495
|
"together, which happens for an angle inside a ring.",
|
|
493
496
|
5000,
|
|
@@ -34,10 +34,10 @@ from PyQt6.QtWidgets import (
|
|
|
34
34
|
from ..utils.constants import (
|
|
35
35
|
ATOM_RADIUS,
|
|
36
36
|
CPK_COLORS,
|
|
37
|
-
DESIRED_ATOM_PIXEL_RADIUS,
|
|
38
37
|
FONT_FAMILY,
|
|
39
38
|
FONT_WEIGHT_BOLD,
|
|
40
39
|
)
|
|
40
|
+
from ..utils.hit_radius import scene_hit_radius
|
|
41
41
|
from ..utils.sip_isdeleted_safe import sip_isdeleted_safe
|
|
42
42
|
|
|
43
43
|
if TYPE_CHECKING:
|
|
@@ -112,8 +112,8 @@ class AtomItem(QGraphicsItem):
|
|
|
112
112
|
font_italic = False
|
|
113
113
|
font_underline = False
|
|
114
114
|
|
|
115
|
-
scene = self.scene()
|
|
116
|
-
if scene is not None
|
|
115
|
+
scene: Any = self.scene()
|
|
116
|
+
if scene is not None:
|
|
117
117
|
font_size = scene.get_setting("atom_font_size_2d", 20)
|
|
118
118
|
font_family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
119
119
|
font_bold = scene.get_setting("atom_font_bold_2d", True)
|
|
@@ -134,15 +134,15 @@ class AtomItem(QGraphicsItem):
|
|
|
134
134
|
)
|
|
135
135
|
self.update()
|
|
136
136
|
|
|
137
|
-
def
|
|
138
|
-
"""
|
|
137
|
+
def visual_rect(self) -> QRectF:
|
|
138
|
+
"""Return the rectangle the atom draws into; highlights use this."""
|
|
139
139
|
font_size = 20
|
|
140
140
|
font_family = FONT_FAMILY
|
|
141
141
|
font_bold = True
|
|
142
142
|
font_italic = False
|
|
143
143
|
font_underline = False
|
|
144
|
-
scene = self.scene()
|
|
145
|
-
if scene is not None
|
|
144
|
+
scene: Any = self.scene()
|
|
145
|
+
if scene is not None:
|
|
146
146
|
font_size = scene.get_setting("atom_font_size_2d", 20)
|
|
147
147
|
font_family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
148
148
|
font_bold = scene.get_setting("atom_font_bold_2d", True)
|
|
@@ -252,6 +252,13 @@ class AtomItem(QGraphicsItem):
|
|
|
252
252
|
# 3. Add final margins for selection highlights, etc.
|
|
253
253
|
return full_visual_rect.adjusted(-3, -3, 3, 3)
|
|
254
254
|
|
|
255
|
+
def boundingRect(self) -> QRectF:
|
|
256
|
+
"""Return the drawn rect plus the hit shape, which Qt requires it to cover."""
|
|
257
|
+
hit_r = self.hit_radius()
|
|
258
|
+
return self.visual_rect().united(
|
|
259
|
+
QRectF(-hit_r, -hit_r, hit_r * 2.0, hit_r * 2.0)
|
|
260
|
+
)
|
|
261
|
+
|
|
255
262
|
def get_bg_ellipse_path(self) -> QPainterPath:
|
|
256
263
|
"""Return the elliptical background path used for bond endpoint clipping."""
|
|
257
264
|
path = QPainterPath()
|
|
@@ -263,8 +270,8 @@ class AtomItem(QGraphicsItem):
|
|
|
263
270
|
font_bold = True
|
|
264
271
|
font_italic = False
|
|
265
272
|
font_underline = False
|
|
266
|
-
scene = self.scene()
|
|
267
|
-
if scene is not None
|
|
273
|
+
scene: Any = self.scene()
|
|
274
|
+
if scene is not None:
|
|
268
275
|
font_size = scene.get_setting("atom_font_size_2d", 20)
|
|
269
276
|
font_family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
270
277
|
font_bold = scene.get_setting("atom_font_bold_2d", True)
|
|
@@ -331,19 +338,13 @@ class AtomItem(QGraphicsItem):
|
|
|
331
338
|
path.addEllipse(bg_rect)
|
|
332
339
|
return path
|
|
333
340
|
|
|
334
|
-
def
|
|
335
|
-
"""
|
|
336
|
-
|
|
337
|
-
if not scene or not scene.views():
|
|
338
|
-
path = QPainterPath()
|
|
339
|
-
hit_r = max(4.0, ATOM_RADIUS - 6.0) * 2
|
|
340
|
-
path.addEllipse(QRectF(-hit_r, -hit_r, hit_r * 2.0, hit_r * 2.0))
|
|
341
|
-
return path
|
|
341
|
+
def hit_radius(self) -> float:
|
|
342
|
+
"""Return the hit/snap radius in scene units for the current zoom."""
|
|
343
|
+
return scene_hit_radius(self.scene(), fallback=max(4.0, ATOM_RADIUS - 6.0) * 2)
|
|
342
344
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
scene_radius = DESIRED_ATOM_PIXEL_RADIUS / scale
|
|
345
|
+
def shape(self) -> QPainterPath:
|
|
346
|
+
"""Define the collision area: a fixed pixel radius, never the drawn label."""
|
|
347
|
+
scene_radius = self.hit_radius()
|
|
347
348
|
|
|
348
349
|
path = QPainterPath()
|
|
349
350
|
path.addEllipse(QPointF(0, 0), scene_radius, scene_radius)
|
|
@@ -361,11 +362,11 @@ class AtomItem(QGraphicsItem):
|
|
|
361
362
|
# Color logic: check if we should use bond color (uniform) or CPK (element-specific)
|
|
362
363
|
color = CPK_COLORS.get(self.symbol, CPK_COLORS["DEFAULT"])
|
|
363
364
|
# Use bond color if specified in settings
|
|
364
|
-
scene = self.scene()
|
|
365
|
-
if
|
|
366
|
-
self.symbol == "H" or scene.get_setting("atom_use_bond_color_2d", False)
|
|
365
|
+
scene: Any = self.scene()
|
|
366
|
+
if scene is not None and (
|
|
367
|
+
self.symbol == "H" or scene.get_setting("atom_use_bond_color_2d", False)
|
|
367
368
|
):
|
|
368
|
-
custom_color = scene.get_setting("bond_color_2d", "#222222")
|
|
369
|
+
custom_color = scene.get_setting("bond_color_2d", "#222222")
|
|
369
370
|
if isinstance(custom_color, str):
|
|
370
371
|
color = QColor(custom_color)
|
|
371
372
|
|
|
@@ -520,17 +521,17 @@ class AtomItem(QGraphicsItem):
|
|
|
520
521
|
if self.has_problem:
|
|
521
522
|
painter.setBrush(Qt.BrushStyle.NoBrush)
|
|
522
523
|
painter.setPen(QPen(QColor(255, 0, 0, 200), 4))
|
|
523
|
-
painter.drawRect(self.
|
|
524
|
+
painter.drawRect(self.visual_rect())
|
|
524
525
|
elif self.isSelected():
|
|
525
526
|
painter.setBrush(Qt.BrushStyle.NoBrush)
|
|
526
527
|
painter.setPen(QPen(QColor(0, 100, 255), 3))
|
|
527
|
-
painter.drawRect(self.
|
|
528
|
+
painter.drawRect(self.visual_rect())
|
|
528
529
|
if (not self.isSelected()) and getattr(self, "hovered", False):
|
|
529
530
|
pen = QPen(QColor(144, 238, 144, 200), 3)
|
|
530
531
|
pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin)
|
|
531
532
|
painter.setBrush(Qt.BrushStyle.NoBrush)
|
|
532
533
|
painter.setPen(pen)
|
|
533
|
-
painter.drawRect(self.
|
|
534
|
+
painter.drawRect(self.visual_rect())
|
|
534
535
|
|
|
535
536
|
def itemChange(self, change: QGraphicsItem.GraphicsItemChange, value: Any) -> Any:
|
|
536
537
|
"""Propagate position and scene changes to connected bond items."""
|
|
@@ -13,7 +13,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
import math
|
|
15
15
|
import logging
|
|
16
|
-
from typing import TYPE_CHECKING, Optional, Tuple, Union
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
|
|
17
17
|
|
|
18
18
|
from PyQt6.QtCore import QLineF, QPointF, QRectF, Qt
|
|
19
19
|
from PyQt6.QtGui import (
|
|
@@ -36,7 +36,6 @@ from PyQt6.QtWidgets import (
|
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
from ..utils.constants import (
|
|
39
|
-
DESIRED_BOND_PIXEL_WIDTH,
|
|
40
39
|
EZ_LABEL_BOX_SIZE,
|
|
41
40
|
EZ_LABEL_MARGIN,
|
|
42
41
|
EZ_LABEL_TEXT_OUTLINE,
|
|
@@ -44,6 +43,7 @@ from ..utils.constants import (
|
|
|
44
43
|
FONT_WEIGHT_BOLD,
|
|
45
44
|
HOVER_PEN_WIDTH,
|
|
46
45
|
)
|
|
46
|
+
from ..utils.hit_radius import scene_hit_radius
|
|
47
47
|
|
|
48
48
|
if TYPE_CHECKING:
|
|
49
49
|
from .atom_item import AtomItem
|
|
@@ -232,6 +232,10 @@ class BondItem(QGraphicsItem):
|
|
|
232
232
|
# return zero line to prevent downstream crashes.
|
|
233
233
|
return QLineF(0, 0, 0, 0)
|
|
234
234
|
|
|
235
|
+
def hit_radius(self) -> float:
|
|
236
|
+
"""Return the click/hover half-width in scene units for the current zoom."""
|
|
237
|
+
return scene_hit_radius(self.scene())
|
|
238
|
+
|
|
235
239
|
def boundingRect(self) -> QRectF:
|
|
236
240
|
"""Return the bounding rect encompassing all visual bond representations."""
|
|
237
241
|
try:
|
|
@@ -240,10 +244,10 @@ class BondItem(QGraphicsItem):
|
|
|
240
244
|
line = QLineF(0, 0, 0, 0)
|
|
241
245
|
|
|
242
246
|
# Get dynamic bond offset (spacing)
|
|
243
|
-
scene = self.scene()
|
|
247
|
+
scene: Any = self.scene()
|
|
244
248
|
bond_offset = 3.5
|
|
245
249
|
wedge_width = 6.0
|
|
246
|
-
if scene is not None
|
|
250
|
+
if scene is not None:
|
|
247
251
|
key = (
|
|
248
252
|
"bond_spacing_triple_2d"
|
|
249
253
|
if getattr(self, "order", 1) == 3
|
|
@@ -252,7 +256,9 @@ class BondItem(QGraphicsItem):
|
|
|
252
256
|
bond_offset = scene.get_setting(key, 3.5)
|
|
253
257
|
wedge_width = scene.get_setting("bond_wedge_width_2d", 6.0)
|
|
254
258
|
|
|
259
|
+
# Qt prunes clicks whose shape() escapes boundingRect().
|
|
255
260
|
extra = (getattr(self, "order", 1) - 1) * bond_offset + 50 + wedge_width
|
|
261
|
+
extra = max(extra, self.hit_radius() + 2.0)
|
|
256
262
|
rect = (
|
|
257
263
|
QRectF(line.p1(), line.p2())
|
|
258
264
|
.normalized()
|
|
@@ -263,7 +269,7 @@ class BondItem(QGraphicsItem):
|
|
|
263
269
|
if self.order == 2 and self.stereo in [3, 4]:
|
|
264
270
|
font_size = 20
|
|
265
271
|
font_family = FONT_FAMILY
|
|
266
|
-
if scene is not None
|
|
272
|
+
if scene is not None:
|
|
267
273
|
font_size = scene.get_setting("atom_font_size_2d", 20)
|
|
268
274
|
font_family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
269
275
|
|
|
@@ -293,10 +299,9 @@ class BondItem(QGraphicsItem):
|
|
|
293
299
|
path.moveTo(line.p1())
|
|
294
300
|
path.lineTo(line.p2())
|
|
295
301
|
|
|
296
|
-
# Stroke it to give it some width (
|
|
297
|
-
# even if the visual width is smaller.
|
|
302
|
+
# Stroke it to give it some width (width is a diameter, so 2 * radius)
|
|
298
303
|
stroker = QPainterPathStroker()
|
|
299
|
-
stroker.setWidth(
|
|
304
|
+
stroker.setWidth(self.hit_radius() * 2.0)
|
|
300
305
|
path = stroker.createStroke(path)
|
|
301
306
|
|
|
302
307
|
# If there's an E/Z label, add its rect to the selection shape
|
|
@@ -348,8 +353,8 @@ class BondItem(QGraphicsItem):
|
|
|
348
353
|
bond_color = QColor("#222222")
|
|
349
354
|
|
|
350
355
|
try:
|
|
351
|
-
scene = self.scene()
|
|
352
|
-
if scene is not None
|
|
356
|
+
scene: Any = self.scene()
|
|
357
|
+
if scene is not None:
|
|
353
358
|
# Color
|
|
354
359
|
if self.isSelected():
|
|
355
360
|
bond_color = QColor("blue")
|
|
@@ -524,8 +529,8 @@ class BondItem(QGraphicsItem):
|
|
|
524
529
|
# --- Label Settings ---
|
|
525
530
|
font_size = 20
|
|
526
531
|
font_family = FONT_FAMILY
|
|
527
|
-
_sc = self.scene()
|
|
528
|
-
if _sc is not None
|
|
532
|
+
_sc: Any = self.scene()
|
|
533
|
+
if _sc is not None:
|
|
529
534
|
font_size = _sc.get_setting("atom_font_size_2d", 20)
|
|
530
535
|
font_family = _sc.get_setting(
|
|
531
536
|
"atom_font_family_2d", FONT_FAMILY
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/bond_length_dialog.py
RENAMED
|
@@ -441,7 +441,10 @@ class BondLengthDialog(GeometryBaseDialog):
|
|
|
441
441
|
if abs(worst_delta) < 1e-4:
|
|
442
442
|
return
|
|
443
443
|
with suppress_log(AttributeError, RuntimeError, TypeError):
|
|
444
|
-
self.main_window.statusBar()
|
|
444
|
+
status_bar = self.main_window.statusBar()
|
|
445
|
+
if status_bar is None:
|
|
446
|
+
return
|
|
447
|
+
status_bar.showMessage(
|
|
445
448
|
f"Bond {worst_label} also changed by {worst_delta:+.3f} A: a bond "
|
|
446
449
|
"inside a ring cannot be resized on its own.",
|
|
447
450
|
5000,
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/custom_interactor_style.py
RENAMED
|
@@ -51,8 +51,9 @@ _GROUP_ROTATION_RADIANS_PER_PIXEL = 0.008
|
|
|
51
51
|
def _rodrigues_matrix(axis: np.ndarray, angle: float) -> np.ndarray:
|
|
52
52
|
"""Return the rotation matrix for `angle` radians about `axis` (Rodrigues)."""
|
|
53
53
|
norm = float(np.linalg.norm(axis))
|
|
54
|
+
identity: np.ndarray = np.eye(3)
|
|
54
55
|
if norm < 1e-6 or abs(angle) < 1e-6:
|
|
55
|
-
return
|
|
56
|
+
return identity
|
|
56
57
|
unit = axis / norm
|
|
57
58
|
k_mat = np.array(
|
|
58
59
|
[
|
|
@@ -61,7 +62,10 @@ def _rodrigues_matrix(axis: np.ndarray, angle: float) -> np.ndarray:
|
|
|
61
62
|
[-unit[1], unit[0], 0.0],
|
|
62
63
|
]
|
|
63
64
|
)
|
|
64
|
-
|
|
65
|
+
rotation: np.ndarray = (
|
|
66
|
+
identity + np.sin(angle) * k_mat + (1.0 - np.cos(angle)) * (k_mat @ k_mat)
|
|
67
|
+
)
|
|
68
|
+
return rotation
|
|
65
69
|
|
|
66
70
|
|
|
67
71
|
class CustomInteractorStyle(vtkInteractorStyleTrackballCamera):
|
|
@@ -944,7 +948,8 @@ class CustomInteractorStyle(vtkInteractorStyleTrackballCamera):
|
|
|
944
948
|
speed = _GROUP_ROTATION_RADIANS_PER_PIXEL * self._rotation_sensitivity()
|
|
945
949
|
rot_y = _rodrigues_matrix(view_up, float(dx) * speed)
|
|
946
950
|
rot_x = _rodrigues_matrix(right, -float(dy) * speed)
|
|
947
|
-
|
|
951
|
+
combined: np.ndarray = rot_x @ rot_y
|
|
952
|
+
return combined
|
|
948
953
|
except (AttributeError, RuntimeError, TypeError, ValueError):
|
|
949
954
|
logging.debug("Suppressed non-critical error", exc_info=True)
|
|
950
955
|
return None
|
|
@@ -489,7 +489,10 @@ class DihedralDialog(GeometryBaseDialog):
|
|
|
489
489
|
if min(difference, 360.0 - difference) < 0.5:
|
|
490
490
|
return
|
|
491
491
|
with suppress_log(AttributeError, RuntimeError, TypeError):
|
|
492
|
-
self.main_window.statusBar()
|
|
492
|
+
status_bar = self.main_window.statusBar()
|
|
493
|
+
if status_bar is None:
|
|
494
|
+
return
|
|
495
|
+
status_bar.showMessage(
|
|
493
496
|
f"Dihedral unchanged ({achieved:.2f}°): the four atoms rotate "
|
|
494
497
|
"together, which happens for a bond inside a ring.",
|
|
495
498
|
5000,
|
|
@@ -242,7 +242,7 @@ class Edit3DManager:
|
|
|
242
242
|
|
|
243
243
|
# Position near top-right of atom
|
|
244
244
|
atom_pos = atom_item.pos()
|
|
245
|
-
atom_rect = atom_item.
|
|
245
|
+
atom_rect = atom_item.visual_rect()
|
|
246
246
|
label_pos = QPointF(
|
|
247
247
|
atom_pos.x() + atom_rect.width() / 4 + 2,
|
|
248
248
|
atom_pos.y() - atom_rect.height() / 4 - 8,
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/edit_actions_logic.py
RENAMED
|
@@ -1045,7 +1045,7 @@ class EditActionsManager:
|
|
|
1045
1045
|
# Only prepare a geometry change if the implicit H count
|
|
1046
1046
|
# changes (this may affect the item's bounding rect).
|
|
1047
1047
|
need_geometry = current != new_count
|
|
1048
|
-
if need_geometry
|
|
1048
|
+
if need_geometry:
|
|
1049
1049
|
item.prepareGeometryChange()
|
|
1050
1050
|
item.implicit_h_count = new_count
|
|
1051
1051
|
item.has_problem = bool(desired_prob)
|
|
@@ -495,22 +495,20 @@ class IOManager:
|
|
|
495
495
|
self.host.statusBar().showMessage("Error: Nothing to save.")
|
|
496
496
|
return
|
|
497
497
|
|
|
498
|
-
|
|
499
|
-
if
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
498
|
+
current_path = self.host.init_manager.current_file_path
|
|
499
|
+
if current_path and current_path.lower().endswith(".pmeraw"):
|
|
500
|
+
# Never write the legacy pickle back; Save As only emits .pmeprj.
|
|
501
|
+
self.host.update_status_message(
|
|
502
|
+
"Raw (.pmeraw) files are read-only — saving as .pmeprj instead."
|
|
503
|
+
)
|
|
504
|
+
self.save_project_as()
|
|
505
|
+
return
|
|
506
|
+
|
|
507
|
+
if current_path and current_path.lower().endswith(".pmeprj"):
|
|
503
508
|
try:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
pickle.dump(save_data, f)
|
|
508
|
-
else:
|
|
509
|
-
json_data = self.host.state_manager.create_json_data()
|
|
510
|
-
with open(
|
|
511
|
-
self.host.init_manager.current_file_path, "w", encoding="utf-8"
|
|
512
|
-
) as f:
|
|
513
|
-
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
|
509
|
+
json_data = self.host.state_manager.create_json_data()
|
|
510
|
+
with open(current_path, "w", encoding="utf-8") as f:
|
|
511
|
+
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
|
514
512
|
|
|
515
513
|
self.host.set_has_unsaved_changes(False)
|
|
516
514
|
self.host.state_manager.update_window_title()
|
|
@@ -1109,6 +1107,25 @@ class IOManager:
|
|
|
1109
1107
|
except (OSError, IOError, ValueError, RuntimeError, AttributeError) as e:
|
|
1110
1108
|
self.host.statusBar().showMessage(f"Error saving XYZ: {e}")
|
|
1111
1109
|
|
|
1110
|
+
def _confirm_pickle_load(self, file_path: str) -> bool:
|
|
1111
|
+
"""Ask before unpickling a .pmeraw file, which can run arbitrary code."""
|
|
1112
|
+
box = QMessageBox(self.host)
|
|
1113
|
+
box.setIcon(QMessageBox.Icon.Warning)
|
|
1114
|
+
box.setWindowTitle("Open Raw Project File?")
|
|
1115
|
+
box.setText("This file is in the legacy raw (pickle) format.")
|
|
1116
|
+
box.setInformativeText(
|
|
1117
|
+
f"{os.path.basename(file_path)}\n\n"
|
|
1118
|
+
"Raw project files can execute arbitrary code when opened. "
|
|
1119
|
+
"Only open .pmeraw files that you created yourself or received "
|
|
1120
|
+
"from a source you trust.\n\n"
|
|
1121
|
+
"The .pmeprj format is safe and is recommended instead."
|
|
1122
|
+
)
|
|
1123
|
+
open_button = box.addButton("Open", QMessageBox.ButtonRole.AcceptRole)
|
|
1124
|
+
cancel_button = box.addButton(QMessageBox.StandardButton.Cancel)
|
|
1125
|
+
box.setDefaultButton(cancel_button)
|
|
1126
|
+
box.exec()
|
|
1127
|
+
return box.clickedButton() is open_button
|
|
1128
|
+
|
|
1112
1129
|
def load_raw_data(self, file_path: Optional[str] = None) -> None:
|
|
1113
1130
|
"""Open a .pmeraw pickle project file."""
|
|
1114
1131
|
if not self.host.state_manager.check_unsaved_changes():
|
|
@@ -1129,6 +1146,10 @@ class IOManager:
|
|
|
1129
1146
|
if not file_path:
|
|
1130
1147
|
return
|
|
1131
1148
|
|
|
1149
|
+
if not self._confirm_pickle_load(file_path):
|
|
1150
|
+
self.host.update_status_message("Opening raw project file cancelled.")
|
|
1151
|
+
return
|
|
1152
|
+
|
|
1132
1153
|
if not self.host.edit_actions_manager.clear_all(skip_check=True):
|
|
1133
1154
|
return
|
|
1134
1155
|
|
|
@@ -223,7 +223,7 @@ class MainInitManager:
|
|
|
223
223
|
"""Resolve the atom-label font now, in the user's configured family."""
|
|
224
224
|
scene = getattr(self, "scene", None)
|
|
225
225
|
font = None
|
|
226
|
-
if scene is not None
|
|
226
|
+
if scene is not None:
|
|
227
227
|
family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
228
228
|
size = scene.get_setting("atom_font_size_2d", 20)
|
|
229
229
|
bold = scene.get_setting("atom_font_bold_2d", True)
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/molecular_scene_handler.py
RENAMED
|
@@ -856,7 +856,10 @@ class KeyboardMixin:
|
|
|
856
856
|
return
|
|
857
857
|
|
|
858
858
|
view = self.views()[0]
|
|
859
|
-
|
|
859
|
+
# mapToScene expects viewport coordinates. Mapping to the view widget directly
|
|
860
|
+
# includes the widget's frame margins, introducing a cursor offset that gets
|
|
861
|
+
# magnified when zooming.
|
|
862
|
+
cursor_pos = view.mapToScene(view.viewport().mapFromGlobal(QCursor.pos()))
|
|
860
863
|
transform = view.transform()
|
|
861
864
|
key = event.key()
|
|
862
865
|
modifiers = event.modifiers()
|
|
@@ -1393,6 +1396,7 @@ class SceneQueryMixin:
|
|
|
1393
1396
|
items: Any
|
|
1394
1397
|
update_all_items: Any
|
|
1395
1398
|
window: Any
|
|
1399
|
+
views: Any
|
|
1396
1400
|
addItem: Any
|
|
1397
1401
|
removeItem: Any
|
|
1398
1402
|
|
|
@@ -1587,9 +1591,17 @@ class SceneQueryMixin:
|
|
|
1587
1591
|
return False
|
|
1588
1592
|
|
|
1589
1593
|
def find_atom_near(self, pos: Any, tol: float = 14.0) -> Any:
|
|
1590
|
-
"""Return the AtomItem within tolerance distance of pos, or None.
|
|
1594
|
+
"""Return the AtomItem within tolerance distance of pos, or None.
|
|
1595
|
+
|
|
1596
|
+
``tol`` is in screen pixels, divided by the view scale to match shape().
|
|
1597
|
+
"""
|
|
1591
1598
|
if pos is None:
|
|
1592
1599
|
return None
|
|
1600
|
+
# Convert screen-pixel tolerance to scene units (zoom-aware).
|
|
1601
|
+
if self.views():
|
|
1602
|
+
scale = self.views()[0].transform().m11()
|
|
1603
|
+
if scale > 0:
|
|
1604
|
+
tol = tol / scale
|
|
1593
1605
|
# Create a small search rectangle around the position
|
|
1594
1606
|
search_rect = QRectF(pos.x() - tol, pos.y() - tol, 2 * tol, 2 * tol)
|
|
1595
1607
|
nearby_items = self.items(search_rect)
|
|
@@ -1002,8 +1002,8 @@ class MoleculeScene(
|
|
|
1002
1002
|
# Find the active view for this scene
|
|
1003
1003
|
for view in self.views():
|
|
1004
1004
|
if view.isVisible():
|
|
1005
|
-
# Map global cursor position to scene coordinates
|
|
1006
|
-
local_pos = view.mapFromGlobal(global_pos)
|
|
1005
|
+
# Map global cursor position to scene coordinates (via viewport)
|
|
1006
|
+
local_pos = view.viewport().mapFromGlobal(global_pos)
|
|
1007
1007
|
scene_pos = view.mapToScene(local_pos)
|
|
1008
1008
|
|
|
1009
1009
|
# If the mouse is within the viewport, trigger the preview update
|
|
@@ -190,18 +190,22 @@ class Settings2DTab(SettingsTabBase):
|
|
|
190
190
|
|
|
191
191
|
form_layout.addRow(self._create_separator())
|
|
192
192
|
|
|
193
|
-
# ---
|
|
194
|
-
form_layout.addRow(QLabel("<b>
|
|
193
|
+
# --- Atom Hit / Snap Settings ---
|
|
194
|
+
form_layout.addRow(QLabel("<b>Atom Hit / Snap Settings</b>"))
|
|
195
195
|
|
|
196
|
-
#
|
|
196
|
+
# Atom hit radius (also used for bond snapping) — internal key is
|
|
197
|
+
# kept as bond_snapping_distance_2d so existing settings files load.
|
|
197
198
|
self.bond_snapping_distance_2d_slider, self.bond_snapping_distance_2d_label = (
|
|
198
199
|
self._create_slider(5, 50, 1.0, is_int=True)
|
|
199
200
|
)
|
|
200
201
|
self.bond_snapping_distance_2d_slider.setToolTip(
|
|
201
|
-
"The distance in pixels within which
|
|
202
|
+
"The distance in screen pixels (zoom-independent) within which:\n"
|
|
203
|
+
"• Drawing a bond snaps to an existing atom\n"
|
|
204
|
+
"• Keyboard shortcuts instantly edit the atom under cursor\n"
|
|
205
|
+
"• Atoms and bonds show hover highlight and respond to clicks"
|
|
202
206
|
)
|
|
203
207
|
form_layout.addRow(
|
|
204
|
-
"
|
|
208
|
+
"Atom Hit / Snap Distance (px):",
|
|
205
209
|
self._wrap_layout(
|
|
206
210
|
self.bond_snapping_distance_2d_slider,
|
|
207
211
|
self.bond_snapping_distance_2d_label,
|
|
@@ -14,7 +14,7 @@ from __future__ import annotations
|
|
|
14
14
|
|
|
15
15
|
from typing import Optional, cast
|
|
16
16
|
|
|
17
|
-
from PyQt6.QtCore import QEvent, QPointF, Qt
|
|
17
|
+
from PyQt6.QtCore import QEvent, QPointF, Qt, QTimer
|
|
18
18
|
from PyQt6.QtGui import QMouseEvent, QWheelEvent, QNativeGestureEvent
|
|
19
19
|
from PyQt6.QtWidgets import QGraphicsScene, QGraphicsView, QWidget
|
|
20
20
|
|
|
@@ -38,6 +38,14 @@ class ZoomableView(QGraphicsView):
|
|
|
38
38
|
self._pan_start_scroll_h = 0
|
|
39
39
|
self._pan_start_scroll_v = 0
|
|
40
40
|
|
|
41
|
+
# Coalesces re-indexing to once per zoom gesture; doing it per wheel
|
|
42
|
+
# tick dirties every item and costs ~40x the zoom step on a large
|
|
43
|
+
# structure.
|
|
44
|
+
self._geometry_timer = QTimer(self)
|
|
45
|
+
self._geometry_timer.setSingleShot(True)
|
|
46
|
+
self._geometry_timer.setInterval(50)
|
|
47
|
+
self._geometry_timer.timeout.connect(self._invalidate_item_geometry)
|
|
48
|
+
|
|
41
49
|
def wheelEvent(self, event: Optional[QWheelEvent]) -> None:
|
|
42
50
|
"""Event handler for mouse wheel rotation"""
|
|
43
51
|
if event is None:
|
|
@@ -123,6 +131,28 @@ class ZoomableView(QGraphicsView):
|
|
|
123
131
|
else:
|
|
124
132
|
super().mouseReleaseEvent(event)
|
|
125
133
|
|
|
134
|
+
def _invalidate_item_geometry(self) -> None:
|
|
135
|
+
"""Re-index items: their pixel-sized hit geometry changes with zoom."""
|
|
136
|
+
scene = self.scene()
|
|
137
|
+
if scene is None:
|
|
138
|
+
return
|
|
139
|
+
for item in scene.items():
|
|
140
|
+
# A wrapper deleted mid-iteration (scene teardown) raises.
|
|
141
|
+
try:
|
|
142
|
+
item.prepareGeometryChange()
|
|
143
|
+
except RuntimeError:
|
|
144
|
+
continue
|
|
145
|
+
|
|
146
|
+
def scale(self, sx: float, sy: float) -> None:
|
|
147
|
+
"""Scale the view, then re-index items once the gesture settles."""
|
|
148
|
+
super().scale(sx, sy)
|
|
149
|
+
self._geometry_timer.start()
|
|
150
|
+
|
|
151
|
+
def resetTransform(self) -> None:
|
|
152
|
+
"""Reset the view transform and re-index items for the new scale."""
|
|
153
|
+
super().resetTransform()
|
|
154
|
+
self._geometry_timer.start()
|
|
155
|
+
|
|
126
156
|
def viewportEvent(self, event: Optional[QEvent]) -> bool:
|
|
127
157
|
"""Handle native gestures (like pinch zoom on trackpads)"""
|
|
128
158
|
if event is None:
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
MoleditPy — A Python-based molecular editing software
|
|
6
|
+
|
|
7
|
+
Author: Hiromichi Yokoyama
|
|
8
|
+
License: GPL-3.0 license
|
|
9
|
+
Repo: https://github.com/HiroYokoyama/python_molecular_editor
|
|
10
|
+
DOI: 10.5281/zenodo.17268532
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
DEFAULT_HIT_PX = 14.0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def scene_hit_radius(scene: Any, fallback: float = DEFAULT_HIT_PX) -> float:
|
|
19
|
+
"""Return the 2D hit/snap radius in scene units for the current zoom.
|
|
20
|
+
|
|
21
|
+
bond_snapping_distance_2d is in screen pixels, so it is divided by the view
|
|
22
|
+
scale; shape() and find_atom_near() share this to stay in step.
|
|
23
|
+
"""
|
|
24
|
+
if not scene or not scene.views():
|
|
25
|
+
return fallback
|
|
26
|
+
|
|
27
|
+
scale = scene.views()[0].transform().m11()
|
|
28
|
+
if scale <= 0.0:
|
|
29
|
+
scale = 1.0
|
|
30
|
+
|
|
31
|
+
hit_px = scene.get_setting("bond_snapping_distance_2d", DEFAULT_HIT_PX)
|
|
32
|
+
return float(hit_px / scale)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/MoleditPy_linux.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_manager.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/plugins/plugin_manager_window.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/align_plane_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/base_picking_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/calculation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/color_settings_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/custom_qt_interactor.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/geometry_base_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/periodic_table_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/plugin_menu_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/settings_tabs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/template_preview_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/template_preview_view.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/translation_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/ui/user_template_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/default_settings.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.6.0 → moleditpy_linux-4.7.0}/src/moleditpy_linux/utils/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|