MoleditPy-linux 4.4.1__tar.gz → 4.5.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.
Files changed (81) hide show
  1. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/PKG-INFO +1 -1
  2. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/pyproject.toml +1 -1
  3. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
  4. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/plugins/plugin_interface.py +23 -1
  5. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/plugins/plugin_manager.py +50 -1
  6. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/atom_item.py +2 -0
  7. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/custom_interactor_style.py +570 -183
  8. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/move_group_dialog.py +5 -5
  9. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +28 -0
  10. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/utils/constants.py +3 -0
  11. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/utils/default_settings.py +2 -0
  12. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/LICENSE +0 -0
  13. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/README.md +0 -0
  14. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/setup.cfg +0 -0
  15. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
  16. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
  17. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
  18. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
  19. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
  20. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/__init__.py +0 -0
  21. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/__main__.py +0 -0
  22. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/assets/file_icon.ico +0 -0
  23. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/assets/icon.icns +0 -0
  24. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/assets/icon.ico +0 -0
  25. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/assets/icon.png +0 -0
  26. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/core/__init__.py +0 -0
  27. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/core/mol_geometry.py +0 -0
  28. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/core/molecular_data.py +0 -0
  29. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/main.py +0 -0
  30. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/plugins/__init__.py +0 -0
  31. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
  32. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/__init__.py +0 -0
  33. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/about_dialog.py +0 -0
  34. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
  35. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
  36. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/analysis_window.py +0 -0
  37. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
  38. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/app_state.py +0 -0
  39. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/atom_picking.py +0 -0
  40. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
  41. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/bond_item.py +0 -0
  42. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
  43. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
  44. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
  45. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/compute_logic.py +0 -0
  46. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
  47. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
  48. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
  49. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
  50. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
  51. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
  52. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
  53. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/export_logic.py +0 -0
  54. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
  55. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/io_logic.py +0 -0
  56. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/main_window.py +0 -0
  57. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/main_window_init.py +0 -0
  58. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
  59. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
  60. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
  61. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
  62. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
  63. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
  64. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
  65. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
  66. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
  67. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
  68. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
  69. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
  70. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/string_importers.py +0 -0
  71. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
  72. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
  73. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
  74. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/ui_manager.py +0 -0
  75. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
  76. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
  77. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
  78. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/utils/__init__.py +0 -0
  79. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
  80. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.0}/src/moleditpy_linux/utils/suppress_log.py +0 -0
  81. {moleditpy_linux-4.4.1 → moleditpy_linux-4.5.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.4.1
3
+ Version: 4.5.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
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "MoleditPy-linux"
7
7
 
8
- version = "4.4.1"
8
+ version = "4.5.0"
9
9
 
10
10
  license = {file = "LICENSE"}
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy-linux
3
- Version: 4.4.1
3
+ Version: 4.5.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
@@ -11,7 +11,7 @@ DOI: 10.5281/zenodo.17268532
11
11
  """
12
12
 
13
13
  import logging
14
- from typing import Any, Callable, List, Optional, Union
14
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
15
15
 
16
16
 
17
17
  class PluginContext:
@@ -353,6 +353,28 @@ class PluginContext:
353
353
  """
354
354
  self._manager.register_document_reset_handler(self._plugin_name, callback)
355
355
 
356
+ def register_atom_drag_handler(
357
+ self,
358
+ callback: Callable[
359
+ [str, List[int], Dict[int, Tuple[float, float, float]]], None
360
+ ],
361
+ ) -> None:
362
+ """Register a handler called during 3D atom or group dragging.
363
+
364
+ The callback receives:
365
+ event_type (str): ``"start"``, ``"move"``, or ``"end"``.
366
+ atom_indices (List[int]): RDKit atom indices being dragged.
367
+ positions (dict[int, tuple[float, float, float]]):
368
+ Current 3D positions of the dragged atoms.
369
+ Empty dict on ``"start"``.
370
+ """
371
+ self._manager.register_atom_drag_handler(self._plugin_name, callback)
372
+
373
+ @property
374
+ def is_dragging_atom(self) -> bool:
375
+ """Return True if an atom or group is currently being dragged in 3D."""
376
+ return self._manager.is_dragging_atom() # type: ignore[no-any-return]
377
+
356
378
  def get_setting(self, key: str, default: Any = None) -> Any:
357
379
  """
358
380
  Get a plugin-specific persistent setting.
@@ -23,8 +23,9 @@ from typing import Any, Callable, Dict, List, Optional, Tuple
23
23
 
24
24
  from PyQt6.QtCore import QUrl
25
25
  from PyQt6.QtGui import QDesktopServices
26
- from PyQt6.QtWidgets import QMessageBox
26
+ from PyQt6.QtWidgets import QApplication, QMessageBox
27
27
 
28
+ from ..utils.constants import MOVE_DIALOG_TYPES
28
29
  from .plugin_interface import PluginContext
29
30
 
30
31
 
@@ -95,6 +96,7 @@ class PluginManager:
95
96
  self.load_handlers: Dict[str, Callable] = {}
96
97
  self.custom_3d_styles: Dict[str, Dict[str, Any]] = {}
97
98
  self.document_reset_handlers: List[Dict[str, Any]] = []
99
+ self.atom_drag_handlers: List[Dict[str, Any]] = []
98
100
  self.plugin_windows: Dict[
99
101
  str, Dict[str, Any]
100
102
  ] = {} # Map of plugin_name -> {window_id -> window}
@@ -247,6 +249,7 @@ class PluginManager:
247
249
  self.load_handlers = {}
248
250
  self.custom_3d_styles = {}
249
251
  self.document_reset_handlers = []
252
+ self.atom_drag_handlers = []
250
253
 
251
254
  if not os.path.exists(self.plugin_dir):
252
255
  return []
@@ -558,6 +561,10 @@ class PluginManager:
558
561
  {"plugin": plugin_name, "callback": callback}
559
562
  )
560
563
 
564
+ def register_atom_drag_handler(self, plugin_name: str, callback: Callable) -> None:
565
+ """Register a handler called during 3D atom/group dragging."""
566
+ self.atom_drag_handlers.append({"plugin": plugin_name, "callback": callback})
567
+
561
568
  # --- New API Implementation ---
562
569
  def show_status_message(self, message: str, timeout: int = 3000) -> None:
563
570
  """Display a message in the MainWindow status bar."""
@@ -653,6 +660,48 @@ class PluginManager:
653
660
  exc_info=True,
654
661
  )
655
662
 
663
+ def invoke_atom_drag_handlers(
664
+ self,
665
+ event_type: str,
666
+ atom_indices: List[int],
667
+ positions: Dict[int, tuple],
668
+ ) -> None:
669
+ """Call all registered atom drag handlers."""
670
+ for handler in self.atom_drag_handlers:
671
+ try:
672
+ handler["callback"](event_type, atom_indices, positions)
673
+ except Exception as e: # plugins have full app access; catch everything to keep the drag alive
674
+ logging.warning(
675
+ "Error in atom drag handler for %s: %s",
676
+ handler["plugin"],
677
+ e,
678
+ exc_info=True,
679
+ )
680
+
681
+ def is_dragging_atom(self) -> bool:
682
+ """Return True if an atom or group is currently being dragged in 3D."""
683
+ mw = self.main_window
684
+ if mw is None:
685
+ return False
686
+ if getattr(mw, "dragged_atom_info", None) is not None:
687
+ return True
688
+ return self._is_dragging_group()
689
+
690
+ @staticmethod
691
+ def _is_dragging_group() -> bool:
692
+ """Return True while a Move Group / Move Selected Atoms gesture is active."""
693
+ try:
694
+ for widget in QApplication.topLevelWidgets():
695
+ if type(widget).__name__ not in MOVE_DIALOG_TYPES:
696
+ continue
697
+ if getattr(widget, "is_dragging_group_vtk", False) or getattr(
698
+ widget, "is_rotating_group_vtk", False
699
+ ):
700
+ return True
701
+ except (AttributeError, RuntimeError, TypeError):
702
+ logging.debug("Suppressed non-critical error", exc_info=True)
703
+ return False
704
+
656
705
  def get_plugin_info_safe(self, file_path: str) -> Dict[str, str]:
657
706
  """Extracts plugin metadata using AST parsing (safe, no execution)."""
658
707
  info = {
@@ -63,6 +63,8 @@ class AtomItem(QGraphicsItem):
63
63
  self.setFlags(
64
64
  QGraphicsItem.GraphicsItemFlag.ItemIsMovable
65
65
  | QGraphicsItem.GraphicsItemFlag.ItemIsSelectable
66
+ # Without this Qt never calls itemChange for moves, so bonds lag.
67
+ | QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges
66
68
  )
67
69
  self.setZValue(1)
68
70
  self.update_style()