MoleditPy-linux 4.1.2__tar.gz → 4.1.3__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.1.2 → moleditpy_linux-4.1.3}/PKG-INFO +1 -1
  2. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/pyproject.toml +1 -1
  3. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
  4. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/__init__.py +0 -2
  5. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/plugins/plugin_interface.py +3 -5
  6. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/plugins/plugin_manager.py +2 -1
  7. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/main_window.py +1 -2
  8. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +102 -0
  9. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/view_3d_logic.py +1 -1
  10. moleditpy_linux-4.1.3/src/moleditpy_linux/utils/__init__.py +11 -0
  11. moleditpy_linux-4.1.2/src/moleditpy_linux/core/__init__.py +0 -0
  12. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/LICENSE +0 -0
  13. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/README.md +0 -0
  14. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/setup.cfg +0 -0
  15. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
  16. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
  17. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
  18. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
  19. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
  20. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/__main__.py +0 -0
  21. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/assets/file_icon.ico +0 -0
  22. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/assets/icon.icns +0 -0
  23. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/assets/icon.ico +0 -0
  24. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/assets/icon.png +0 -0
  25. {moleditpy_linux-4.1.2/src/moleditpy_linux/plugins → moleditpy_linux-4.1.3/src/moleditpy_linux/core}/__init__.py +0 -0
  26. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/core/mol_geometry.py +0 -0
  27. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/core/molecular_data.py +0 -0
  28. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/main.py +0 -0
  29. {moleditpy_linux-4.1.2/src/moleditpy_linux/ui/settings_tabs → moleditpy_linux-4.1.3/src/moleditpy_linux/plugins}/__init__.py +0 -0
  30. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
  31. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/__init__.py +0 -0
  32. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/about_dialog.py +0 -0
  33. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
  34. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
  35. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/analysis_window.py +0 -0
  36. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
  37. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/app_state.py +0 -0
  38. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/atom_item.py +0 -0
  39. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/atom_picking.py +0 -0
  40. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
  41. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/bond_item.py +0 -0
  42. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
  43. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
  44. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
  45. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/compute_logic.py +0 -0
  46. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
  47. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
  48. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
  49. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
  50. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
  51. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
  52. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
  53. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
  54. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/export_logic.py +0 -0
  55. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
  56. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/io_logic.py +0 -0
  57. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/main_window_init.py +0 -0
  58. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
  59. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
  60. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
  61. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
  62. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
  63. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
  64. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
  65. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
  66. {moleditpy_linux-4.1.2/src/moleditpy_linux/utils → moleditpy_linux-4.1.3/src/moleditpy_linux/ui/settings_tabs}/__init__.py +0 -0
  67. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
  68. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
  69. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
  70. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
  71. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/string_importers.py +0 -0
  72. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
  73. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
  74. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
  75. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/ui_manager.py +0 -0
  76. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
  77. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
  78. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/utils/constants.py +0 -0
  79. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/utils/default_settings.py +0 -0
  80. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
  81. {moleditpy_linux-4.1.2 → moleditpy_linux-4.1.3}/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.1.2
3
+ Version: 4.1.3
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.1.2"
8
+ version = "4.1.3"
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.1.2
3
+ Version: 4.1.3
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
@@ -8,8 +8,6 @@ Author: Hiromichi Yokoyama
8
8
  License: GPL-3.0 license
9
9
  Repo: https://github.com/HiroYokoyama/python_molecular_editor
10
10
  DOI: 10.5281/zenodo.17268532
11
-
12
- Top-level package for moleditpy_linux.
13
11
  """
14
12
 
15
13
  import importlib.util # noqa: F401
@@ -190,11 +190,9 @@ class PluginContext:
190
190
  Get or set the current molecule (RDKit Mol object). Shortcut for current_molecule.
191
191
  """
192
192
  mw = self.get_main_window()
193
- return (
194
- mw.view_3d_manager.current_mol
195
- if mw and hasattr(mw, "view_3d_manager")
196
- else None
197
- )
193
+ if mw and hasattr(mw, "view_3d_manager"):
194
+ return mw.view_3d_manager.current_mol
195
+ return None
198
196
 
199
197
  @current_mol.setter
200
198
  def current_mol(self, mol: Any) -> None:
@@ -588,7 +588,8 @@ class PluginManager:
588
588
  selected_atom_ids.add(item.atom_id)
589
589
 
590
590
  # Now map these editor IDs to RDKit indices
591
- mol = getattr(self.main_window, "current_mol", None)
591
+ v3d = getattr(self.main_window, "view_3d_manager", None)
592
+ mol = v3d.current_mol if v3d else None
592
593
  if mol and selected_atom_ids:
593
594
  for i in range(mol.GetNumAtoms()):
594
595
  atom = mol.GetAtomWithIdx(i)
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
19
19
  from rdkit import Chem
20
20
 
21
21
  # PyQt6 Modules
22
+ import copy
22
23
  from PyQt6.QtCore import pyqtSignal
23
24
  from PyQt6.QtWidgets import QMainWindow, QMessageBox
24
25
 
@@ -254,8 +255,6 @@ class MainWindow(QMainWindow):
254
255
 
255
256
  def save_state_snapshot(self) -> None:
256
257
  """Create a deep copy snapshot of the current state for undo/redo comparison."""
257
- import copy
258
-
259
258
  try:
260
259
  self.state_manager.saved_state = copy.deepcopy(
261
260
  self.state_manager.get_current_state()
@@ -56,6 +56,8 @@ class MoveSelectedAtomsDialog(BasePickingDialog):
56
56
  self.mouse_moved_during_drag: bool = False
57
57
  self._consume_next_left_release: bool = False
58
58
  self.highlight_actor: Optional[pv.Actor] = None
59
+ self.original_style: Optional[Any] = None
60
+ self.rubber_band_style: Optional[Any] = None
59
61
 
60
62
  self.widgets: dict[str, Any] = {}
61
63
 
@@ -211,6 +213,13 @@ class MoveSelectedAtomsDialog(BasePickingDialog):
211
213
  def _init_buttons_ui(self, layout: QVBoxLayout) -> None:
212
214
  """Initialize bottom buttons."""
213
215
  button_layout = QHBoxLayout()
216
+
217
+ box_select_btn = QPushButton("Box Selection: OFF")
218
+ box_select_btn.setCheckable(True)
219
+ box_select_btn.clicked.connect(self.toggle_box_selection)
220
+ self.widgets["box_select_btn"] = box_select_btn
221
+ button_layout.addWidget(box_select_btn)
222
+
214
223
  clear_btn = QPushButton("Clear Selection")
215
224
  clear_btn.clicked.connect(self.clear_selection)
216
225
  self.widgets["clear_button"] = clear_btn
@@ -238,6 +247,24 @@ class MoveSelectedAtomsDialog(BasePickingDialog):
238
247
 
239
248
  e_type = event.type()
240
249
 
250
+ btn = self.widgets.get("box_select_btn")
251
+ box_selection_on = btn is not None and btn.isChecked()
252
+
253
+ if e_type == QEvent.Type.MouseButtonPress:
254
+ self._click_press_pos = getattr(event, "pos", lambda: None)()
255
+ elif e_type == QEvent.Type.MouseButtonRelease:
256
+ if hasattr(self, "_click_press_pos") and self._click_press_pos is not None:
257
+ pos = getattr(event, "pos", lambda: None)()
258
+ if pos:
259
+ diff = pos - self._click_press_pos
260
+ if diff.manhattanLength() < 3:
261
+ if box_selection_on:
262
+ self.clear_selection()
263
+ self._click_press_pos = None
264
+
265
+ if box_selection_on:
266
+ return False
267
+
241
268
  if e_type == QEvent.Type.MouseButtonDblClick:
242
269
  # Ignore double clicks and reset state
243
270
  self.is_dragging_group = False
@@ -645,3 +672,78 @@ class MoveSelectedAtomsDialog(BasePickingDialog):
645
672
  self.update_display()
646
673
  self.is_dragging_group = False
647
674
  self.drag_start_pos = None
675
+
676
+ def toggle_box_selection(self, checked: bool) -> None:
677
+ """Toggle Box Selection mode using PyVista's rectangle picker."""
678
+ plotter = self.main_window.view_3d_manager.plotter
679
+ if plotter is None or plotter.interactor is None:
680
+ return
681
+
682
+ btn = self.widgets["box_select_btn"]
683
+ if checked:
684
+ btn.setText("Box Selection: ON")
685
+ # Save original style if not saved
686
+ if self.original_style is None:
687
+ self.original_style = plotter.interactor.GetInteractorStyle()
688
+
689
+ # Using PyVista's built-in picking which reliably draws the box correctly
690
+ plotter.enable_rectangle_picking(
691
+ callback=self.on_rectangle_picked,
692
+ show_message=False,
693
+ start=True,
694
+ color="red",
695
+ )
696
+ else:
697
+ btn.setText("Box Selection: OFF")
698
+ plotter.disable_picking()
699
+ # Restore original style
700
+ if self.original_style is not None:
701
+ plotter.interactor.SetInteractorStyle(self.original_style)
702
+ self.rubber_band_style = None
703
+
704
+ def on_rectangle_picked(self, selection: Any) -> None:
705
+ """Handle PyVista rectangle picking callback."""
706
+ if not hasattr(selection, "viewport"):
707
+ return
708
+
709
+ x0, y0, x1, y1 = selection.viewport
710
+ x_min = min(x0, x1)
711
+ x_max = max(x0, x1)
712
+ y_min = min(y0, y1)
713
+ y_max = max(y0, y1)
714
+
715
+ # If the drag box is small, treat it as a single click to clear selection
716
+ if abs(x_max - x_min) < 15 and abs(y_max - y_min) < 15:
717
+ self.clear_selection()
718
+ return
719
+
720
+ plotter = self.main_window.view_3d_manager.plotter
721
+ if plotter is None:
722
+ return
723
+ renderer = plotter.renderer
724
+
725
+ positions = self.main_window.view_3d_manager.atom_positions_3d
726
+ if positions is not None:
727
+ added = False
728
+ for atom_idx, pos in enumerate(positions):
729
+ renderer.SetWorldPoint(float(pos[0]), float(pos[1]), float(pos[2]), 1.0)
730
+ renderer.WorldToDisplay()
731
+ display = renderer.GetDisplayPoint()
732
+
733
+ if x_min <= display[0] <= x_max and y_min <= display[1] <= y_max:
734
+ if atom_idx not in self.selected_atoms:
735
+ self.selected_atoms.add(atom_idx)
736
+ added = True
737
+
738
+ if added:
739
+ self.show_atom_labels()
740
+ self.update_display()
741
+
742
+ def reject(self) -> None:
743
+ """Clean up when dialog closes."""
744
+ # Ensure we restore the interactor style if it was left in Box Selection mode
745
+ btn = self.widgets.get("box_select_btn")
746
+ if btn and btn.isChecked():
747
+ btn.setChecked(False)
748
+ self.toggle_box_selection(False)
749
+ super().reject()
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  """
5
- MoleditPy  EA Python-based molecular editing software
5
+ MoleditPy — A Python-based molecular editing software
6
6
 
7
7
  Author: Hiromichi Yokoyama
8
8
  License: GPL-3.0 license
@@ -0,0 +1,11 @@
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
+ """
File without changes