MoleditPy-linux 4.2.1__tar.gz → 4.2.2__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.2.1 → moleditpy_linux-4.2.2}/PKG-INFO +1 -1
  2. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/pyproject.toml +1 -1
  3. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
  4. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/compute_logic.py +36 -2
  5. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/main_window_init.py +7 -0
  6. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/plugin_menu_manager.py +22 -6
  7. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/LICENSE +0 -0
  8. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/README.md +0 -0
  9. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/setup.cfg +0 -0
  10. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
  11. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
  12. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
  13. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
  14. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
  15. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/__init__.py +0 -0
  16. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/__main__.py +0 -0
  17. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/assets/file_icon.ico +0 -0
  18. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/assets/icon.icns +0 -0
  19. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/assets/icon.ico +0 -0
  20. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/assets/icon.png +0 -0
  21. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/core/__init__.py +0 -0
  22. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/core/mol_geometry.py +0 -0
  23. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/core/molecular_data.py +0 -0
  24. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/main.py +0 -0
  25. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/plugins/__init__.py +0 -0
  26. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
  27. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/plugins/plugin_manager.py +0 -0
  28. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
  29. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/__init__.py +0 -0
  30. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/about_dialog.py +0 -0
  31. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
  32. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
  33. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/analysis_window.py +0 -0
  34. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
  35. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/app_state.py +0 -0
  36. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/atom_item.py +0 -0
  37. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/atom_picking.py +0 -0
  38. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
  39. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/bond_item.py +0 -0
  40. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
  41. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
  42. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
  43. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
  44. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
  45. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
  46. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
  47. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
  48. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
  49. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
  50. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
  51. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/export_logic.py +0 -0
  52. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
  53. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/io_logic.py +0 -0
  54. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/main_window.py +0 -0
  55. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
  56. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
  57. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
  58. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
  59. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
  60. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
  61. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
  62. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
  63. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
  64. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
  65. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
  66. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
  67. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
  68. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/string_importers.py +0 -0
  69. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
  70. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
  71. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
  72. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/ui_manager.py +0 -0
  73. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
  74. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
  75. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
  76. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/utils/__init__.py +0 -0
  77. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/utils/constants.py +0 -0
  78. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/utils/default_settings.py +0 -0
  79. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
  80. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/src/moleditpy_linux/utils/suppress_log.py +0 -0
  81. {moleditpy_linux-4.2.1 → moleditpy_linux-4.2.2}/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.2.1
3
+ Version: 4.2.2
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.2.1"
8
+ version = "4.2.2"
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.2.1
3
+ Version: 4.2.2
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
@@ -45,6 +45,9 @@ class ComputeManager:
45
45
  self.halt_ids: Set[int] = set()
46
46
  self.next_conversion_id: int = 1
47
47
  self.active_worker_ids: Set[int] = set()
48
+ # worker_id -> (method_key, plugin_entry) for a plugin optimizer to run
49
+ # as a post-step once conversion's built-in pre-optimization completes.
50
+ self._pending_plugin_opt: Dict[int, Tuple[str, Dict[str, Any]]] = {}
48
51
 
49
52
  def reset_active_threads(self) -> None:
50
53
  """Reset active calculation threads list."""
@@ -239,6 +242,25 @@ class ComputeManager:
239
242
  self.next_conversion_id = run_id + 1
240
243
  self.active_worker_ids.add(run_id)
241
244
 
245
+ # The worker only runs built-in force fields. If the selected method is a
246
+ # plugin optimizer, pre-optimize with MMFF (RDKit) in the worker (which
247
+ # auto-falls-back to UFF if MMFF setup fails), then run the plugin
248
+ # callback as a post-step in on_calculation_finished.
249
+ effective_method = (
250
+ optimization_method
251
+ or self.host.init_manager.optimization_method
252
+ or "MMFF_RDKIT"
253
+ ).upper()
254
+ _reg = getattr(
255
+ getattr(self.host, "plugin_manager", None), "optimization_methods", None
256
+ )
257
+ plugin_entry = _reg.get(effective_method) if isinstance(_reg, dict) else None
258
+ if plugin_entry:
259
+ self._pending_plugin_opt[run_id] = (effective_method, plugin_entry)
260
+ worker_method = "MMFF_RDKIT"
261
+ else:
262
+ worker_method = effective_method
263
+
242
264
  # UI Updates
243
265
  self.host.init_manager.convert_button.setText("Halt conversion") # type: ignore[union-attr]
244
266
  self._safe_disconnect(self.host.init_manager.convert_button.clicked) # type: ignore[union-attr]
@@ -267,8 +289,7 @@ class ComputeManager:
267
289
  options = {
268
290
  "conversion_mode": conversion_mode
269
291
  or self.host.init_manager.settings.get("3d_conversion_mode", "fallback"),
270
- "optimization_method": optimization_method
271
- or self.host.init_manager.optimization_method,
292
+ "optimization_method": worker_method,
272
293
  "optimize_intermolecular_interaction_rdkit": self.host.init_manager.settings.get(
273
294
  "optimize_intermolecular_interaction_rdkit", True
274
295
  ),
@@ -285,6 +306,7 @@ class ComputeManager:
285
306
  if wids_to_halt:
286
307
  self.halt_ids.update(wids_to_halt)
287
308
  self.active_worker_ids.clear()
309
+ self._pending_plugin_opt.clear()
288
310
 
289
311
  self._restore_button_ui()
290
312
  self.host.init_manager.cleanup_button.setEnabled(True) # type: ignore[union-attr]
@@ -529,6 +551,16 @@ class ComputeManager:
529
551
  self.host.view_3d_manager.update_atom_id_menu_text()
530
552
  self.host.view_3d_manager.update_atom_id_menu_state()
531
553
 
554
+ # If the selected method was a plugin optimizer, the worker only did the
555
+ # built-in pre-optimization; run the plugin callback now on the result.
556
+ pending = (
557
+ self._pending_plugin_opt.pop(worker_id, None)
558
+ if worker_id is not None
559
+ else None
560
+ )
561
+ if pending and mol:
562
+ self._run_plugin_optimization(*pending)
563
+
532
564
  def on_calculation_error(self, message: Union[str, Tuple[int, str]]) -> None:
533
565
  """Handle an error or halt signal from the background optimization worker."""
534
566
  # Accept either a string or (worker_id, message) tuple from the worker signal
@@ -547,8 +579,10 @@ class ComputeManager:
547
579
  self.host.statusBar().showMessage( # type: ignore[union-attr]
548
580
  f"Ignored stale worker error: {msg} (ID = {worker_id})"
549
581
  )
582
+ self._pending_plugin_opt.pop(worker_id, None)
550
583
  return # stale worker, ignore
551
584
  self.active_worker_ids.discard(worker_id)
585
+ self._pending_plugin_opt.pop(worker_id, None)
552
586
  else:
553
587
  msg = str(message)
554
588
 
@@ -1723,6 +1723,13 @@ class MainInitManager:
1723
1723
  self.opt_group.addAction(action)
1724
1724
  self.opt3d_actions[key_upper] = action
1725
1725
 
1726
+ # Plugins register after menu-init, so restore the saved default here
1727
+ # if it names this method (menu-init fell back to MMFF_RDKIT).
1728
+ saved_opt = (self.settings.get("optimization_method") or "").upper()
1729
+ if key_upper == saved_opt:
1730
+ action.setChecked(True)
1731
+ self.optimization_method = key_upper
1732
+
1726
1733
  def _init_help_menu(self, menu_bar: Any) -> None:
1727
1734
  """Initialize the Help menu."""
1728
1735
  help_menu = menu_bar.addMenu("&Help")
@@ -369,14 +369,30 @@ class PluginMenuManager:
369
369
  menu.addAction(a)
370
370
 
371
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"):
372
+ """Inject plugin optimization methods into the 3D Optimization Settings menu.
373
+
374
+ Idempotent: previously-added plugin methods are purged first, so a menu
375
+ rebuild (install/uninstall/reload) re-adds only the currently registered
376
+ ones. Without this, _clean_menu removes the menu action while
377
+ opt3d_actions still holds it, and add_optimization_method's dedupe guard
378
+ would then skip re-adding a still-installed method.
379
+ """
380
+ im = self._im
381
+ methods = getattr(im.host.plugin_manager, "optimization_methods", None)
382
+ if not isinstance(methods, dict):
374
383
  return
375
384
 
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")
385
+ for key, action in list(im.opt3d_actions.items()):
386
+ if action.data() == "plugin_managed":
387
+ im.opt_group.removeAction(action)
388
+ im.optimization_menu.removeAction(action)
389
+ del im.opt3d_actions[key]
390
+ im.opt3d_method_labels.pop(key, None)
391
+
392
+ for key, entry in methods.items():
393
+ im.add_optimization_method(entry["label"], key)
394
+ if key in im.opt3d_actions:
395
+ im.opt3d_actions[key].setData("plugin_managed")
380
396
 
381
397
  def integrate_plugin_file_openers(self) -> None:
382
398
  """Inject plugin file-opener entries into the File > Import menu."""
File without changes