MoleditPy 4.2.0__tar.gz → 4.2.1__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-4.2.0 → moleditpy-4.2.1}/PKG-INFO +1 -1
  2. {moleditpy-4.2.0 → moleditpy-4.2.1}/pyproject.toml +1 -1
  3. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/PKG-INFO +1 -1
  4. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/plugins/plugin_manager.py +8 -2
  5. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/compute_logic.py +3 -13
  6. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/main_window_init.py +25 -7
  7. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/plugin_menu_manager.py +12 -0
  8. {moleditpy-4.2.0 → moleditpy-4.2.1}/LICENSE +0 -0
  9. {moleditpy-4.2.0 → moleditpy-4.2.1}/README.md +0 -0
  10. {moleditpy-4.2.0 → moleditpy-4.2.1}/setup.cfg +0 -0
  11. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/SOURCES.txt +0 -0
  12. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/dependency_links.txt +0 -0
  13. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/entry_points.txt +0 -0
  14. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/requires.txt +0 -0
  15. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/MoleditPy.egg-info/top_level.txt +0 -0
  16. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/__init__.py +0 -0
  17. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/__main__.py +0 -0
  18. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/assets/file_icon.ico +0 -0
  19. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/assets/icon.icns +0 -0
  20. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/assets/icon.ico +0 -0
  21. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/assets/icon.png +0 -0
  22. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/core/__init__.py +0 -0
  23. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/core/mol_geometry.py +0 -0
  24. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/core/molecular_data.py +0 -0
  25. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/main.py +0 -0
  26. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/plugins/__init__.py +0 -0
  27. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/plugins/plugin_interface.py +0 -0
  28. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/plugins/plugin_manager_window.py +0 -0
  29. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/__init__.py +0 -0
  30. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/about_dialog.py +0 -0
  31. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/align_plane_dialog.py +0 -0
  32. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/alignment_dialog.py +0 -0
  33. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/analysis_window.py +0 -0
  34. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/angle_dialog.py +0 -0
  35. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/app_state.py +0 -0
  36. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/atom_item.py +0 -0
  37. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/atom_picking.py +0 -0
  38. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/base_picking_dialog.py +0 -0
  39. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/bond_item.py +0 -0
  40. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/bond_length_dialog.py +0 -0
  41. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/calculation_worker.py +0 -0
  42. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/color_settings_dialog.py +0 -0
  43. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/constrained_optimization_dialog.py +0 -0
  44. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/custom_interactor_style.py +0 -0
  45. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/custom_qt_interactor.py +0 -0
  46. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/dialog_3d_picking_mixin.py +0 -0
  47. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/dialog_logic.py +0 -0
  48. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/dihedral_dialog.py +0 -0
  49. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/edit_3d_logic.py +0 -0
  50. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/edit_actions_logic.py +0 -0
  51. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/export_logic.py +0 -0
  52. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/geometry_base_dialog.py +0 -0
  53. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/io_logic.py +0 -0
  54. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/main_window.py +0 -0
  55. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/mirror_dialog.py +0 -0
  56. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/molecular_scene_handler.py +0 -0
  57. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/molecule_scene.py +0 -0
  58. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/move_group_dialog.py +0 -0
  59. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/move_selected_atoms_dialog.py +0 -0
  60. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/periodic_table_dialog.py +0 -0
  61. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/planarize_dialog.py +0 -0
  62. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_dialog.py +0 -0
  63. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_tabs/__init__.py +0 -0
  64. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_tabs/settings_2d_tab.py +0 -0
  65. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_tabs/settings_3d_tabs.py +0 -0
  66. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_tabs/settings_other_tab.py +0 -0
  67. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/settings_tabs/settings_tab_base.py +0 -0
  68. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/string_importers.py +0 -0
  69. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/template_preview_item.py +0 -0
  70. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/template_preview_view.py +0 -0
  71. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/translation_dialog.py +0 -0
  72. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/ui_manager.py +0 -0
  73. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/user_template_dialog.py +0 -0
  74. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/view_3d_logic.py +0 -0
  75. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/ui/zoomable_view.py +0 -0
  76. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/__init__.py +0 -0
  77. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/constants.py +0 -0
  78. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/default_settings.py +0 -0
  79. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/sip_isdeleted_safe.py +0 -0
  80. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/suppress_log.py +0 -0
  81. {moleditpy-4.2.0 → moleditpy-4.2.1}/src/moleditpy/utils/system_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy
3
- Version: 4.2.0
3
+ Version: 4.2.1
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"
7
7
 
8
- version = "4.2.0"
8
+ version = "4.2.1"
9
9
 
10
10
  license = {file = "LICENSE"}
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy
3
- Version: 4.2.0
3
+ Version: 4.2.1
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
@@ -485,12 +485,18 @@ class PluginManager:
485
485
  self, plugin_name: str, method_name: str, callback: Callable
486
486
  ) -> None:
487
487
  """Register a named 3D optimization method provided by a plugin."""
488
- # Key by upper-case method name for consistency
489
- self.optimization_methods[method_name.upper()] = {
488
+ method_key = method_name.upper()
489
+ self.optimization_methods[method_key] = {
490
490
  "plugin": plugin_name,
491
491
  "callback": callback,
492
492
  "label": method_name,
493
493
  }
494
+ if hasattr(self.main_window, "init_manager") and hasattr(
495
+ self.main_window.init_manager, "add_optimization_method"
496
+ ):
497
+ self.main_window.init_manager.add_optimization_method(
498
+ method_name, method_key
499
+ )
494
500
 
495
501
  def register_file_opener(
496
502
  self, plugin_name: str, extension: str, callback: Callable, priority: int = 0
@@ -178,20 +178,10 @@ class ComputeManager:
178
178
  return
179
179
 
180
180
  menu = QMenu(self.host)
181
- opt_list = [
182
- ("MMFF94s (RDKit)", "MMFF_RDKIT"),
183
- ("MMFF94 (RDKit)", "MMFF94_RDKIT"),
184
- ("UFF (RDKit)", "UFF_RDKIT"),
185
- ("MMFF94s (Open Babel)", "MMFF94s_OBABEL"),
186
- ("MMFF94 (Open Babel)", "MMFF94_OBABEL"),
187
- ("UFF (Open Babel)", "UFF_OBABEL"),
188
- ("GAFF (Open Babel)", "GAFF_OBABEL"),
189
- ("Ghemical (Open Babel)", "GHEMICAL_OBABEL"),
190
- ]
191
- for label, key in opt_list:
181
+ for key, source_action in self.host.init_manager.opt3d_actions.items():
182
+ label = source_action.text().replace("&", "")
192
183
  a = QAction(label, self.host)
193
- if key in self.host.init_manager.opt3d_actions:
194
- a.setEnabled(self.host.init_manager.opt3d_actions[key].isEnabled())
184
+ a.setEnabled(source_action.isEnabled())
195
185
  a.triggered.connect(
196
186
  lambda checked=False, k=key: self._trigger_optimize_with_temp_method(k)
197
187
  )
@@ -1648,7 +1648,7 @@ class MainInitManager:
1648
1648
  self.conv_actions[saved_conv].setChecked(True)
1649
1649
  self.settings["3d_conversion_mode"] = saved_conv
1650
1650
 
1651
- optimization_menu = settings_menu.addMenu("3D Optimization Settings")
1651
+ self.optimization_menu = settings_menu.addMenu("3D Optimization Settings")
1652
1652
  opt_methods = [
1653
1653
  ("MMFF94s (RDKit)", "MMFF_RDKIT"),
1654
1654
  ("MMFF94 (RDKit)", "MMFF94_RDKIT"),
@@ -1660,8 +1660,8 @@ class MainInitManager:
1660
1660
  ("Ghemical (Open Babel)", "GHEMICAL_OBABEL"),
1661
1661
  ]
1662
1662
  self.opt3d_method_labels = {key.upper(): label for (label, key) in opt_methods}
1663
- opt_group = QActionGroup(self.host)
1664
- opt_group.setExclusive(True)
1663
+ self.opt_group = QActionGroup(self.host)
1664
+ self.opt_group.setExclusive(True)
1665
1665
  self.opt3d_actions = {}
1666
1666
  for label, key in opt_methods:
1667
1667
  action = QAction(label, self.host)
@@ -1672,11 +1672,11 @@ class MainInitManager:
1672
1672
  lambda checked,
1673
1673
  m=key: self.host.compute_manager.set_optimization_method(m)
1674
1674
  )
1675
- optimization_menu.addAction(action)
1676
- opt_group.addAction(action)
1675
+ self.optimization_menu.addAction(action)
1676
+ self.opt_group.addAction(action)
1677
1677
  self.opt3d_actions[key] = action
1678
1678
 
1679
- optimization_menu.addSeparator()
1679
+ self.opt3d_separator = self.optimization_menu.addSeparator()
1680
1680
  self.host.intermolecular_rdkit_action = QAction(
1681
1681
  "Consider Intermolecular Interaction for RDKit", self.host
1682
1682
  )
@@ -1687,7 +1687,7 @@ class MainInitManager:
1687
1687
  self.host.intermolecular_rdkit_action.triggered.connect(
1688
1688
  self.host.compute_manager.toggle_intermolecular_interaction_rdkit
1689
1689
  )
1690
- optimization_menu.addAction(self.host.intermolecular_rdkit_action)
1690
+ self.optimization_menu.addAction(self.host.intermolecular_rdkit_action)
1691
1691
 
1692
1692
  saved_opt = (self.settings.get("optimization_method") or "MMFF_RDKIT").upper()
1693
1693
  if (
@@ -1705,6 +1705,24 @@ class MainInitManager:
1705
1705
  reset_settings_action.triggered.connect(self.reset_all_settings_menu)
1706
1706
  settings_menu.addAction(reset_settings_action)
1707
1707
 
1708
+ def add_optimization_method(self, label: str, key: str) -> None:
1709
+ """Dynamically add an optimization method to the menu."""
1710
+ key_upper = key.upper()
1711
+ if key_upper in self.opt3d_actions:
1712
+ return
1713
+
1714
+ self.opt3d_method_labels[key_upper] = label
1715
+ action = QAction(label, self.host)
1716
+ action.setCheckable(True)
1717
+ action.triggered.connect(
1718
+ lambda checked,
1719
+ m=key_upper: self.host.compute_manager.set_optimization_method(m)
1720
+ )
1721
+
1722
+ self.optimization_menu.insertAction(self.opt3d_separator, action)
1723
+ self.opt_group.addAction(action)
1724
+ self.opt3d_actions[key_upper] = action
1725
+
1708
1726
  def _init_help_menu(self, menu_bar: Any) -> None:
1709
1727
  """Initialize the Help menu."""
1710
1728
  help_menu = menu_bar.addMenu("&Help")
@@ -81,6 +81,7 @@ class PluginMenuManager:
81
81
  self.integrate_plugin_export_actions()
82
82
  self.integrate_plugin_file_openers()
83
83
  self.integrate_plugin_analysis_tools()
84
+ self.integrate_plugin_optimization_methods()
84
85
 
85
86
  def rebuild_plugin_menus(self) -> None:
86
87
  """Fully rebuild all plugin-managed UI after an install/uninstall.
@@ -120,6 +121,7 @@ class PluginMenuManager:
120
121
  (self.integrate_plugin_file_openers, "file openers"),
121
122
  (self.integrate_plugin_analysis_tools, "analysis tools"),
122
123
  (self.update_style_menu_with_plugins, "style menu"),
124
+ (self.integrate_plugin_optimization_methods, "optimization methods"),
123
125
  ]:
124
126
  try:
125
127
  method()
@@ -366,6 +368,16 @@ class PluginMenuManager:
366
368
  a.setData(PLUGIN_ACTION_TAG)
367
369
  menu.addAction(a)
368
370
 
371
+ def integrate_plugin_optimization_methods(self) -> None:
372
+ """Inject plugin optimization methods into the 3D Optimization Settings menu."""
373
+ if not hasattr(self._im.host.plugin_manager, "optimization_methods"):
374
+ return
375
+
376
+ for key, entry in self._im.host.plugin_manager.optimization_methods.items():
377
+ self._im.add_optimization_method(entry["label"], key)
378
+ if key in self._im.opt3d_actions:
379
+ self._im.opt3d_actions[key].setData("plugin_managed")
380
+
369
381
  def integrate_plugin_file_openers(self) -> None:
370
382
  """Inject plugin file-opener entries into the File > Import menu."""
371
383
  if not self._im.host.plugin_manager.file_openers:
File without changes
File without changes
File without changes