MoleditPy-linux 1.16.1a3__tar.gz → 1.16.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.
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/PKG-INFO +16 -2
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/README.md +15 -1
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/pyproject.toml +1 -1
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/PKG-INFO +16 -2
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/constants.py +1 -1
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_main_init.py +3 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_molecular_parsers.py +147 -66
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_view_3d.py +61 -13
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/molecule_scene.py +92 -23
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/settings_dialog.py +39 -2
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/setup.cfg +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/__init__.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/about_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/align_plane_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/alignment_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/analysis_window.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/angle_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.icns +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.ico +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.png +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/atom_item.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/bond_item.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/bond_length_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/calculation_worker.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/color_settings_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/custom_interactor_style.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/custom_qt_interactor.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/dialog3_d_picking_mixin.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/dihedral_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_app_state.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_compute.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_dialog_manager.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_edit_3d.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_edit_actions.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_export.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_project_io.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_string_importers.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_ui_manager.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window_view_loaders.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/mirror_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/molecular_data.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/move_group_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/periodic_table_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/planarize_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/template_preview_item.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/template_preview_view.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/translation_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/user_template_dialog.py +0 -0
- {moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/zoomable_view.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 1.16.
|
|
3
|
+
Version: 1.16.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
|
Project-URL: Homepage, https://github.com/HiroYokoyama/python_molecular_editor
|
|
@@ -109,7 +109,14 @@ For detailed instructions, please refer to the project [Wiki](https://github.com
|
|
|
109
109
|
moleditpy-installer
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
To enable Open Babel features (e.g., alternative 3D structure generation), please install the package manually.
|
|
114
|
+
**Note:** Open Babel is licensed under **GPL v2**. Installing this package combines GPL code with this software.
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install "moleditpy[openbabel]"
|
|
119
|
+
```
|
|
113
120
|
|
|
114
121
|
#### Running the Application
|
|
115
122
|
|
|
@@ -225,6 +232,13 @@ This project is licensed under the **Apache-2.0 License**. See the `LICENSE` fil
|
|
|
225
232
|
moleditpy-installer
|
|
226
233
|
```
|
|
227
234
|
|
|
235
|
+
Open Babel 機能(代替的な3D構造生成など)を有効にする場合は、以下のコマンドで個別にインストールしてください。
|
|
236
|
+
**注意:** Open Babel は **GPL v2** ライセンスです。このパッケージをインストールすると、GPLの条項が適用される可能性があります。
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
pip install "moleditpy[openbabel]"
|
|
240
|
+
```
|
|
241
|
+
|
|
228
242
|
#### アプリケーションの起動
|
|
229
243
|
|
|
230
244
|
```bash
|
|
@@ -84,7 +84,14 @@ For detailed instructions, please refer to the project [Wiki](https://github.com
|
|
|
84
84
|
moleditpy-installer
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
|
|
88
|
+
To enable Open Babel features (e.g., alternative 3D structure generation), please install the package manually.
|
|
89
|
+
**Note:** Open Babel is licensed under **GPL v2**. Installing this package combines GPL code with this software.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pip install "moleditpy[openbabel]"
|
|
94
|
+
```
|
|
88
95
|
|
|
89
96
|
#### Running the Application
|
|
90
97
|
|
|
@@ -200,6 +207,13 @@ This project is licensed under the **Apache-2.0 License**. See the `LICENSE` fil
|
|
|
200
207
|
moleditpy-installer
|
|
201
208
|
```
|
|
202
209
|
|
|
210
|
+
Open Babel 機能(代替的な3D構造生成など)を有効にする場合は、以下のコマンドで個別にインストールしてください。
|
|
211
|
+
**注意:** Open Babel は **GPL v2** ライセンスです。このパッケージをインストールすると、GPLの条項が適用される可能性があります。
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
pip install "moleditpy[openbabel]"
|
|
215
|
+
```
|
|
216
|
+
|
|
203
217
|
#### アプリケーションの起動
|
|
204
218
|
|
|
205
219
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 1.16.
|
|
3
|
+
Version: 1.16.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
|
Project-URL: Homepage, https://github.com/HiroYokoyama/python_molecular_editor
|
|
@@ -109,7 +109,14 @@ For detailed instructions, please refer to the project [Wiki](https://github.com
|
|
|
109
109
|
moleditpy-installer
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
To enable Open Babel features (e.g., alternative 3D structure generation), please install the package manually.
|
|
114
|
+
**Note:** Open Babel is licensed under **GPL v2**. Installing this package combines GPL code with this software.
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install "moleditpy[openbabel]"
|
|
119
|
+
```
|
|
113
120
|
|
|
114
121
|
#### Running the Application
|
|
115
122
|
|
|
@@ -225,6 +232,13 @@ This project is licensed under the **Apache-2.0 License**. See the `LICENSE` fil
|
|
|
225
232
|
moleditpy-installer
|
|
226
233
|
```
|
|
227
234
|
|
|
235
|
+
Open Babel 機能(代替的な3D構造生成など)を有効にする場合は、以下のコマンドで個別にインストールしてください。
|
|
236
|
+
**注意:** Open Babel は **GPL v2** ライセンスです。このパッケージをインストールすると、GPLの条項が適用される可能性があります。
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
pip install "moleditpy[openbabel]"
|
|
240
|
+
```
|
|
241
|
+
|
|
228
242
|
#### アプリケーションの起動
|
|
229
243
|
|
|
230
244
|
```bash
|
|
@@ -1579,6 +1579,9 @@ class MainWindowMainInit(object):
|
|
|
1579
1579
|
# Color overrides
|
|
1580
1580
|
'ball_stick_bond_color': '#7F7F7F',
|
|
1581
1581
|
'cpk_colors': {}, # symbol->hex overrides
|
|
1582
|
+
# Whether to kekulize aromatic systems for 3D display
|
|
1583
|
+
'display_kekule_3d': False,
|
|
1584
|
+
'always_ask_charge': False,
|
|
1582
1585
|
}
|
|
1583
1586
|
|
|
1584
1587
|
try:
|
|
@@ -557,92 +557,173 @@ class MainWindowMolecularParsers(object):
|
|
|
557
557
|
# Accept the candidate
|
|
558
558
|
return candidate_mol
|
|
559
559
|
|
|
560
|
-
#
|
|
560
|
+
# Decide whether to silently try charge=0 first, or prompt user first.
|
|
561
|
+
always_ask = bool(self.settings.get('always_ask_charge', False))
|
|
562
|
+
|
|
561
563
|
try:
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
564
|
+
if not always_ask:
|
|
565
|
+
# Silent first attempt (existing behavior)
|
|
566
|
+
try:
|
|
567
|
+
final_mol = _process_with_charge(0)
|
|
568
|
+
except RuntimeError:
|
|
569
|
+
# DetermineBonds explicitly failed for charge=0. In this
|
|
570
|
+
# situation, repeatedly prompt the user for charges until
|
|
571
|
+
# DetermineBonds succeeds or the user cancels.
|
|
572
|
+
while True:
|
|
573
|
+
charge_val, ok, skip_flag = prompt_for_charge()
|
|
574
|
+
if not ok:
|
|
575
|
+
# user cancelled the prompt -> abort
|
|
576
|
+
return None
|
|
577
|
+
if skip_flag:
|
|
578
|
+
# User selected Skip chemistry: attempt distance-based salvage
|
|
579
|
+
try:
|
|
580
|
+
self.estimate_bonds_from_distances(mol)
|
|
581
|
+
except Exception:
|
|
582
|
+
pass
|
|
583
|
+
salvaged = None
|
|
584
|
+
try:
|
|
585
|
+
salvaged = mol.GetMol()
|
|
586
|
+
except Exception:
|
|
587
|
+
salvaged = None
|
|
588
|
+
|
|
589
|
+
if salvaged is not None:
|
|
590
|
+
try:
|
|
591
|
+
salvaged.SetIntProp("_xyz_skip_checks", 1)
|
|
592
|
+
except Exception:
|
|
593
|
+
try:
|
|
594
|
+
salvaged._xyz_skip_checks = True
|
|
595
|
+
except Exception:
|
|
596
|
+
pass
|
|
597
|
+
final_mol = salvaged
|
|
598
|
+
break
|
|
599
|
+
else:
|
|
600
|
+
# Could not salvage; abort
|
|
601
|
+
try:
|
|
602
|
+
self.statusBar().showMessage("Skip chemistry selected but failed to create salvaged molecule.")
|
|
603
|
+
except Exception:
|
|
604
|
+
pass
|
|
605
|
+
return None
|
|
583
606
|
|
|
584
|
-
if salvaged is not None:
|
|
585
607
|
try:
|
|
586
|
-
|
|
587
|
-
|
|
608
|
+
final_mol = _process_with_charge(charge_val)
|
|
609
|
+
# success -> break out of prompt loop
|
|
610
|
+
break
|
|
611
|
+
except RuntimeError:
|
|
612
|
+
# DetermineBonds still failing for this charge -> loop again
|
|
588
613
|
try:
|
|
589
|
-
|
|
614
|
+
self.statusBar().showMessage("DetermineBonds failed for that charge; please try a different total charge or cancel.")
|
|
590
615
|
except Exception:
|
|
591
616
|
pass
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
617
|
+
continue
|
|
618
|
+
except Exception as e_prompt:
|
|
619
|
+
# Some other failure occurred after DetermineBonds or in
|
|
620
|
+
# finalization. If skip_chemistry_checks is enabled we
|
|
621
|
+
# try the salvaged mol once; otherwise prompt again.
|
|
622
|
+
try:
|
|
623
|
+
skip_checks = bool(self.settings.get('skip_chemistry_checks', False))
|
|
624
|
+
except Exception:
|
|
625
|
+
skip_checks = False
|
|
626
|
+
|
|
627
|
+
salvaged = None
|
|
628
|
+
try:
|
|
629
|
+
salvaged = mol.GetMol()
|
|
630
|
+
except Exception:
|
|
631
|
+
salvaged = None
|
|
632
|
+
|
|
633
|
+
if skip_checks and salvaged is not None:
|
|
634
|
+
final_mol = salvaged
|
|
635
|
+
# mark salvaged molecule as produced under skip_checks
|
|
636
|
+
try:
|
|
637
|
+
final_mol.SetIntProp("_xyz_skip_checks", 1)
|
|
638
|
+
except Exception:
|
|
639
|
+
try:
|
|
640
|
+
final_mol._xyz_skip_checks = True
|
|
641
|
+
except Exception:
|
|
642
|
+
pass
|
|
643
|
+
break
|
|
644
|
+
else:
|
|
645
|
+
try:
|
|
646
|
+
self.statusBar().showMessage(f"Retry failed: {e_prompt}")
|
|
647
|
+
except Exception:
|
|
648
|
+
pass
|
|
649
|
+
# Continue prompting
|
|
650
|
+
continue
|
|
651
|
+
else:
|
|
652
|
+
# User has requested to always be asked for charge — prompt before any silent try
|
|
653
|
+
while True:
|
|
654
|
+
charge_val, ok, skip_flag = prompt_for_charge()
|
|
655
|
+
if not ok:
|
|
656
|
+
# user cancelled the prompt -> abort
|
|
657
|
+
return None
|
|
658
|
+
if skip_flag:
|
|
659
|
+
# User selected Skip chemistry: attempt distance-based salvage
|
|
596
660
|
try:
|
|
597
|
-
self.
|
|
661
|
+
self.estimate_bonds_from_distances(mol)
|
|
598
662
|
except Exception:
|
|
599
663
|
pass
|
|
600
|
-
return None
|
|
601
|
-
|
|
602
|
-
try:
|
|
603
|
-
final_mol = _process_with_charge(charge_val)
|
|
604
|
-
# success -> break out of prompt loop
|
|
605
|
-
break
|
|
606
|
-
except RuntimeError:
|
|
607
|
-
# DetermineBonds still failing for this charge -> loop again
|
|
608
|
-
try:
|
|
609
|
-
self.statusBar().showMessage("DetermineBonds failed for that charge; please try a different total charge or cancel.")
|
|
610
|
-
except Exception:
|
|
611
|
-
pass
|
|
612
|
-
continue
|
|
613
|
-
except Exception as e_prompt:
|
|
614
|
-
# Some other failure occurred after DetermineBonds or in
|
|
615
|
-
# finalization. If skip_chemistry_checks is enabled we
|
|
616
|
-
# try the salvaged mol once; otherwise prompt again.
|
|
617
|
-
try:
|
|
618
|
-
skip_checks = bool(self.settings.get('skip_chemistry_checks', False))
|
|
619
|
-
except Exception:
|
|
620
|
-
skip_checks = False
|
|
621
|
-
|
|
622
|
-
salvaged = None
|
|
623
|
-
try:
|
|
624
|
-
salvaged = mol.GetMol()
|
|
625
|
-
except Exception:
|
|
626
664
|
salvaged = None
|
|
627
|
-
|
|
628
|
-
if skip_checks and salvaged is not None:
|
|
629
|
-
final_mol = salvaged
|
|
630
|
-
# mark salvaged molecule as produced under skip_checks
|
|
631
665
|
try:
|
|
632
|
-
|
|
666
|
+
salvaged = mol.GetMol()
|
|
633
667
|
except Exception:
|
|
668
|
+
salvaged = None
|
|
669
|
+
|
|
670
|
+
if salvaged is not None:
|
|
634
671
|
try:
|
|
635
|
-
|
|
672
|
+
salvaged.SetIntProp("_xyz_skip_checks", 1)
|
|
673
|
+
except Exception:
|
|
674
|
+
try:
|
|
675
|
+
salvaged._xyz_skip_checks = True
|
|
676
|
+
except Exception:
|
|
677
|
+
pass
|
|
678
|
+
final_mol = salvaged
|
|
679
|
+
break
|
|
680
|
+
else:
|
|
681
|
+
try:
|
|
682
|
+
self.statusBar().showMessage("Skip chemistry selected but failed to create salvaged molecule.")
|
|
636
683
|
except Exception:
|
|
637
684
|
pass
|
|
685
|
+
return None
|
|
686
|
+
|
|
687
|
+
try:
|
|
688
|
+
final_mol = _process_with_charge(charge_val)
|
|
689
|
+
# success -> break out of prompt loop
|
|
638
690
|
break
|
|
639
|
-
|
|
691
|
+
except RuntimeError:
|
|
692
|
+
# DetermineBonds still failing for this charge -> loop again
|
|
640
693
|
try:
|
|
641
|
-
self.statusBar().showMessage(
|
|
694
|
+
self.statusBar().showMessage("DetermineBonds failed for that charge; please try a different total charge or cancel.")
|
|
642
695
|
except Exception:
|
|
643
696
|
pass
|
|
644
|
-
# Continue prompting
|
|
645
697
|
continue
|
|
698
|
+
except Exception as e_prompt:
|
|
699
|
+
try:
|
|
700
|
+
skip_checks = bool(self.settings.get('skip_chemistry_checks', False))
|
|
701
|
+
except Exception:
|
|
702
|
+
skip_checks = False
|
|
703
|
+
|
|
704
|
+
salvaged = None
|
|
705
|
+
try:
|
|
706
|
+
salvaged = mol.GetMol()
|
|
707
|
+
except Exception:
|
|
708
|
+
salvaged = None
|
|
709
|
+
|
|
710
|
+
if skip_checks and salvaged is not None:
|
|
711
|
+
final_mol = salvaged
|
|
712
|
+
try:
|
|
713
|
+
final_mol.SetIntProp("_xyz_skip_checks", 1)
|
|
714
|
+
except Exception:
|
|
715
|
+
try:
|
|
716
|
+
final_mol._xyz_skip_checks = True
|
|
717
|
+
except Exception:
|
|
718
|
+
pass
|
|
719
|
+
break
|
|
720
|
+
else:
|
|
721
|
+
try:
|
|
722
|
+
self.statusBar().showMessage(f"Retry failed: {e_prompt}")
|
|
723
|
+
except Exception:
|
|
724
|
+
pass
|
|
725
|
+
continue
|
|
726
|
+
|
|
646
727
|
except Exception:
|
|
647
728
|
# If the silent attempt failed for reasons other than
|
|
648
729
|
# DetermineBonds failing (e.g., finalization errors), fall
|
|
@@ -156,11 +156,30 @@ class MainWindowView3d(object):
|
|
|
156
156
|
self.plotter.add_light(light)
|
|
157
157
|
|
|
158
158
|
# 5. 分子描画ロジック
|
|
159
|
+
# Optionally kekulize aromatic systems for 3D visualization.
|
|
160
|
+
mol_to_draw = mol
|
|
161
|
+
if self.settings.get('display_kekule_3d', False):
|
|
162
|
+
try:
|
|
163
|
+
# Operate on a copy to avoid mutating the original molecule
|
|
164
|
+
mol_to_draw = Chem.Mol(mol)
|
|
165
|
+
Chem.Kekulize(mol_to_draw, clearAromaticFlags=True)
|
|
166
|
+
except Exception as e:
|
|
167
|
+
# Kekulize failed; keep original and warn user
|
|
168
|
+
try:
|
|
169
|
+
self.statusBar().showMessage(f"Kekulize failed: {e}")
|
|
170
|
+
except Exception:
|
|
171
|
+
pass
|
|
172
|
+
mol_to_draw = mol
|
|
173
|
+
|
|
174
|
+
# Use the original molecule's conformer (positions) to ensure coordinates
|
|
175
|
+
# are preserved even when we create a kekulized copy for bond types.
|
|
159
176
|
conf = mol.GetConformer()
|
|
160
177
|
|
|
161
|
-
|
|
178
|
+
# Use the kekulized molecule's atom ordering for color/size decisions
|
|
179
|
+
self.atom_positions_3d = np.array([list(conf.GetAtomPosition(i)) for i in range(mol_to_draw.GetNumAtoms())])
|
|
162
180
|
|
|
163
|
-
|
|
181
|
+
# Use the possibly-kekulized molecule for symbol/bond types
|
|
182
|
+
sym = [a.GetSymbol() for a in mol_to_draw.GetAtoms()]
|
|
164
183
|
col = np.array([CPK_COLORS_PV.get(s, [0.5, 0.5, 0.5]) for s in sym])
|
|
165
184
|
|
|
166
185
|
# スタイルに応じて原子の半径を設定(設定から読み込み)
|
|
@@ -239,7 +258,7 @@ class MainWindowView3d(object):
|
|
|
239
258
|
except Exception:
|
|
240
259
|
bs_bond_rgb = [127, 127, 127]
|
|
241
260
|
|
|
242
|
-
for bond in
|
|
261
|
+
for bond in mol_to_draw.GetBonds():
|
|
243
262
|
begin_atom_idx = bond.GetBeginAtomIdx()
|
|
244
263
|
end_atom_idx = bond.GetEndAtomIdx()
|
|
245
264
|
sp = np.array(conf.GetAtomPosition(begin_atom_idx))
|
|
@@ -313,7 +332,7 @@ class MainWindowView3d(object):
|
|
|
313
332
|
if bt == Chem.rdchem.BondType.DOUBLE:
|
|
314
333
|
r = cyl_radius * double_radius_factor
|
|
315
334
|
# 二重結合の場合、結合している原子の他の結合を考慮してオフセット方向を決定
|
|
316
|
-
off_dir = self._calculate_double_bond_offset(
|
|
335
|
+
off_dir = self._calculate_double_bond_offset(mol_to_draw, bond, conf)
|
|
317
336
|
# 設定から二重結合のオフセットファクターを適用
|
|
318
337
|
s_double = cyl_radius * double_offset_factor
|
|
319
338
|
c1, c2 = c + off_dir * (s_double / 2), c - off_dir * (s_double / 2)
|
|
@@ -432,7 +451,10 @@ class MainWindowView3d(object):
|
|
|
432
451
|
# E/Zラベルも表示
|
|
433
452
|
if getattr(self, 'show_chiral_labels', False):
|
|
434
453
|
try:
|
|
435
|
-
|
|
454
|
+
# If we drew a kekulized molecule use it for E/Z detection so
|
|
455
|
+
# E/Z labels reflect Kekulé rendering; pass mol_to_draw as the
|
|
456
|
+
# molecule to scan for bond stereochemistry.
|
|
457
|
+
self.show_ez_labels_3d(mol, scan_mol=mol_to_draw)
|
|
436
458
|
except Exception as e:
|
|
437
459
|
self.statusBar().showMessage(f"3D E/Z label drawing error: {e}")
|
|
438
460
|
|
|
@@ -561,7 +583,7 @@ class MainWindowView3d(object):
|
|
|
561
583
|
|
|
562
584
|
|
|
563
585
|
|
|
564
|
-
def show_ez_labels_3d(self, mol):
|
|
586
|
+
def show_ez_labels_3d(self, mol, scan_mol=None):
|
|
565
587
|
"""3DビューでE/Zラベルを表示する(RDKitのステレオ化学判定を使用)"""
|
|
566
588
|
if not mol:
|
|
567
589
|
return
|
|
@@ -588,11 +610,19 @@ class MainWindowView3d(object):
|
|
|
588
610
|
pass
|
|
589
611
|
|
|
590
612
|
# 二重結合でRDKitが判定したE/Z立体化学を表示
|
|
591
|
-
for
|
|
613
|
+
# `scan_mol` is used for stereochemistry detection (bond types); default
|
|
614
|
+
# to the provided molecule if not supplied.
|
|
615
|
+
if scan_mol is None:
|
|
616
|
+
scan_mol = mol
|
|
617
|
+
|
|
618
|
+
for bond in scan_mol.GetBonds():
|
|
592
619
|
if bond.GetBondType() == Chem.BondType.DOUBLE:
|
|
593
620
|
stereo = bond.GetStereo()
|
|
594
621
|
if stereo in [Chem.BondStereo.STEREOE, Chem.BondStereo.STEREOZ]:
|
|
595
622
|
# 結合の中心座標を計算
|
|
623
|
+
# Use positions from the original molecule's conformer; `bond` may
|
|
624
|
+
# come from `scan_mol` which can be kekulized but position indices
|
|
625
|
+
# correspond to the original `mol`.
|
|
596
626
|
begin_pos = np.array(conf.GetAtomPosition(bond.GetBeginAtomIdx()))
|
|
597
627
|
end_pos = np.array(conf.GetAtomPosition(bond.GetEndAtomIdx()))
|
|
598
628
|
center_pos = (begin_pos + end_pos) / 2
|
|
@@ -1083,15 +1113,33 @@ class MainWindowView3d(object):
|
|
|
1083
1113
|
Only keys present in self.settings['cpk_colors'] are changed; other elements keep the defaults.
|
|
1084
1114
|
"""
|
|
1085
1115
|
try:
|
|
1116
|
+
# Overridden CPK settings are stored in self.settings['cpk_colors'].
|
|
1117
|
+
# To ensure that 2D modules (e.g., atom_item.py) which imported the
|
|
1118
|
+
# `CPK_COLORS` mapping from `modules.constants` at import time see
|
|
1119
|
+
# updates, mutate the mapping in-place on the constants module
|
|
1120
|
+
# instead of rebinding a new local variable here.
|
|
1086
1121
|
overrides = self.settings.get('cpk_colors', {}) or {}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1122
|
+
|
|
1123
|
+
# Import the constants module so we can update mappings directly
|
|
1124
|
+
try:
|
|
1125
|
+
from . import constants as constants_mod
|
|
1126
|
+
except Exception:
|
|
1127
|
+
import modules.constants as constants_mod
|
|
1128
|
+
|
|
1129
|
+
# Reset constants.CPK_COLORS to defaults but keep the same dict
|
|
1130
|
+
constants_mod.CPK_COLORS.clear()
|
|
1131
|
+
for k, v in DEFAULT_CPK_COLORS.items():
|
|
1132
|
+
constants_mod.CPK_COLORS[k] = QColor(v) if not isinstance(v, QColor) else v
|
|
1133
|
+
|
|
1134
|
+
# Apply overrides from settings
|
|
1090
1135
|
for k, hexv in overrides.items():
|
|
1091
1136
|
if isinstance(hexv, str) and hexv:
|
|
1092
|
-
CPK_COLORS[k] = QColor(hexv)
|
|
1093
|
-
|
|
1094
|
-
|
|
1137
|
+
constants_mod.CPK_COLORS[k] = QColor(hexv)
|
|
1138
|
+
|
|
1139
|
+
# Rebuild the PV representation in-place too
|
|
1140
|
+
constants_mod.CPK_COLORS_PV.clear()
|
|
1141
|
+
for k, c in constants_mod.CPK_COLORS.items():
|
|
1142
|
+
constants_mod.CPK_COLORS_PV[k] = [c.redF(), c.greenF(), c.blueF()]
|
|
1095
1143
|
except Exception as e:
|
|
1096
1144
|
print(f"Failed to update CPK colors from settings: {e}")
|
|
1097
1145
|
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/molecule_scene.py
RENAMED
|
@@ -727,61 +727,130 @@ class MoleculeScene(QGraphicsScene):
|
|
|
727
727
|
|
|
728
728
|
# --- フューズされた辺の数による条件分岐 ---
|
|
729
729
|
if len(existing_orders) >= 2:
|
|
730
|
-
|
|
731
|
-
# (この場合、新しい環を交互配置にするのは難しく、単に既存の構造を壊さないことを優先)
|
|
730
|
+
|
|
732
731
|
for rot in range(num_points):
|
|
733
|
-
|
|
734
|
-
|
|
732
|
+
match_double_count = 0
|
|
733
|
+
match_bonus = 0
|
|
734
|
+
mismatch_penalty = 0
|
|
735
|
+
|
|
736
|
+
# 【新規追加】接続部(Legs)の安全性チェック
|
|
737
|
+
# フューズ領域の両隣(テンプレート側)が「単結合(1)」であることを強く推奨する
|
|
738
|
+
# これにより、既存構造との接続点での原子価オーバー(手が5本になる)を防ぐ
|
|
739
|
+
safe_connection_score = 0
|
|
740
|
+
|
|
741
|
+
# フューズ領域の開始と終了を探す(インデックス集合から判定)
|
|
742
|
+
fused_indices = sorted(list(existing_orders.keys()))
|
|
743
|
+
# 連続領域と仮定して、端のインデックスを取得
|
|
744
|
+
# (0と5がつながっている環状のケースも考慮すべきだが、簡易的に最小/最大で判定し、
|
|
745
|
+
# もし飛び地なら不整合ペナルティで自然と落ちる)
|
|
746
|
+
|
|
747
|
+
# 簡易的な隣接チェック:
|
|
748
|
+
# フューズに使われる辺集合に含まれない「その隣」の辺を見る
|
|
749
|
+
for k in existing_orders:
|
|
750
|
+
# 左隣を見る
|
|
751
|
+
prev_idx = (k - 1 + rot) % num_points
|
|
752
|
+
# 右隣を見る
|
|
753
|
+
next_idx = (k + 1 + rot) % num_points
|
|
754
|
+
|
|
755
|
+
# もし隣がフューズ領域外(=接続部)なら、その次数をチェック
|
|
756
|
+
# 注意: existing_ordersのキーは「配置位置(k)」
|
|
757
|
+
# rotはテンプレートのズレ。
|
|
758
|
+
# テンプレート上の該当エッジの次数は orig_orders[(neighbor_k + rot)] ではなく
|
|
759
|
+
# orig_orders[neighbor_template_index]
|
|
760
|
+
|
|
761
|
+
# 正確なロジック:
|
|
762
|
+
# 今、配置位置 k にテンプレートの bond (k+rot) が来ている。
|
|
763
|
+
# 配置位置 k の「隣のボンド」ではなく、
|
|
764
|
+
# 「テンプレート上で」そのボンドの両隣にあるボンドが、今回のフューズに使われていないか確認する。
|
|
765
|
+
pass
|
|
766
|
+
|
|
767
|
+
# --- シンプルな実装: 全ての非フューズ辺(外周になる辺)をチェック ---
|
|
768
|
+
# 「フューズに使われていない辺」が単結合か二重結合かで加点
|
|
769
|
+
# ピレンの場合(3辺フューズ)、残り3辺が外周。
|
|
770
|
+
# ベンゼン(D-S-D-S-D-S)において、D-S-Dでフューズすると、残りはS-D-S。
|
|
771
|
+
# 接合部(Legs)にあたるのは、残りのS-D-Sの両端のS。これが重要。
|
|
772
|
+
|
|
773
|
+
# テンプレートの結合次数配列
|
|
774
|
+
current_template_orders = [orig_orders[(i + rot) % num_points] for i in range(num_points)]
|
|
775
|
+
|
|
776
|
+
# フューズ領域の両端を特定するために、
|
|
777
|
+
# 「フューズしているk」に対応するテンプレート側のインデックスを集める
|
|
778
|
+
used_template_indices = set((k + rot) % num_points for k in existing_orders)
|
|
779
|
+
|
|
780
|
+
# テンプレート上で「使われている領域」の両隣(接続部)が「1(単結合)」なら超高得点
|
|
781
|
+
for t_idx in used_template_indices:
|
|
782
|
+
# そのボンドのテンプレート上の左隣
|
|
783
|
+
adj_l = (t_idx - 1) % num_points
|
|
784
|
+
# そのボンドのテンプレート上の右隣
|
|
785
|
+
adj_r = (t_idx + 1) % num_points
|
|
786
|
+
|
|
787
|
+
# もし隣が「使われていない」なら、それは接続部である
|
|
788
|
+
if adj_l not in used_template_indices:
|
|
789
|
+
if orig_orders[adj_l] == 1: safe_connection_score += 5000
|
|
790
|
+
|
|
791
|
+
if adj_r not in used_template_indices:
|
|
792
|
+
if orig_orders[adj_r] == 1: safe_connection_score += 5000
|
|
793
|
+
|
|
794
|
+
# 既存のスコア計算
|
|
795
|
+
for k, exist_order in existing_orders.items():
|
|
796
|
+
template_ord = orig_orders[(k + rot) % num_points]
|
|
797
|
+
if template_ord == exist_order:
|
|
798
|
+
match_bonus += 100
|
|
799
|
+
if exist_order == 2: match_double_count += 1
|
|
800
|
+
else:
|
|
801
|
+
# 不一致でも、Legsが安全なら許容したいのでペナルティは控えめに、
|
|
802
|
+
# または safe_connection_score が圧倒的に勝つようにする
|
|
803
|
+
mismatch_penalty += 50
|
|
804
|
+
|
|
805
|
+
# 最終スコア: 接続部の安全性を最優先
|
|
806
|
+
current_score = safe_connection_score + (match_double_count * 1000) + match_bonus - mismatch_penalty
|
|
807
|
+
|
|
735
808
|
if current_score > max_score:
|
|
736
809
|
max_score = current_score
|
|
737
810
|
best_rot = rot
|
|
738
811
|
|
|
739
812
|
elif len(existing_orders) == 1:
|
|
740
|
-
# 1
|
|
741
|
-
|
|
742
|
-
# フューズされた辺のインデックスと次数を取得
|
|
813
|
+
# 1辺フューズ
|
|
743
814
|
k_fuse = next(iter(existing_orders.keys()))
|
|
744
815
|
exist_order = existing_orders[k_fuse]
|
|
745
816
|
|
|
746
|
-
# 目標: フューズされた辺の両隣(k-1とk+1)に来るテンプレートの次数が、既存の辺の次数と逆であること
|
|
747
|
-
# k_adj_1 -> (k_fuse - 1) % 6
|
|
748
|
-
# k_adj_2 -> (k_fuse + 1) % 6
|
|
749
|
-
|
|
750
817
|
for rot in range(num_points):
|
|
751
818
|
current_score = 0
|
|
752
819
|
rotated_template_order = orig_orders[(k_fuse + rot) % num_points]
|
|
753
820
|
|
|
754
|
-
# 1.
|
|
821
|
+
# 1. 接合部の次数マッチング
|
|
822
|
+
|
|
823
|
+
# パターンA: 交互配置(既存と逆)
|
|
755
824
|
if (exist_order == 1 and rotated_template_order == 2) or \
|
|
756
825
|
(exist_order == 2 and rotated_template_order == 1):
|
|
757
|
-
current_score += 100
|
|
826
|
+
current_score += 100
|
|
758
827
|
|
|
759
|
-
# 2
|
|
760
|
-
#
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
828
|
+
# 【追加変更点2】二重結合の重ね合わせ(共役維持)
|
|
829
|
+
# 既存が二重結合で、テンプレートも二重結合なら、ここで1つ消費される
|
|
830
|
+
elif (exist_order == 2 and rotated_template_order == 2):
|
|
831
|
+
current_score += 100
|
|
832
|
+
|
|
833
|
+
# 2. 両隣の辺の次数チェック(交互配置の維持を確認)
|
|
764
834
|
m_adj1 = (k_fuse - 1 + rot) % num_points
|
|
765
835
|
m_adj2 = (k_fuse + 1 + rot) % num_points
|
|
766
|
-
|
|
767
836
|
neighbor_order_1 = orig_orders[m_adj1]
|
|
768
837
|
neighbor_order_2 = orig_orders[m_adj2]
|
|
769
838
|
|
|
770
|
-
# 既存が単結合(1)の場合、両隣は二重結合(2)であってほしい
|
|
771
839
|
if exist_order == 1:
|
|
840
|
+
# 接合部が単なら、隣は二重であってほしい
|
|
772
841
|
if neighbor_order_1 == 2: current_score += 50
|
|
773
842
|
if neighbor_order_2 == 2: current_score += 50
|
|
774
843
|
|
|
775
|
-
# 既存が二重結合(2)の場合、両隣は単結合(1)であってほしい
|
|
776
844
|
elif exist_order == 2:
|
|
845
|
+
# 接合部が二重なら、隣は単であってほしい
|
|
777
846
|
if neighbor_order_1 == 1: current_score += 50
|
|
778
847
|
if neighbor_order_2 == 1: current_score += 50
|
|
779
848
|
|
|
780
|
-
# 3.
|
|
849
|
+
# 3. タイブレーク(他の接触しない辺との整合性など)
|
|
781
850
|
for k, e_order in existing_orders.items():
|
|
782
851
|
if k != k_fuse:
|
|
783
852
|
r_t_order = orig_orders[(k + rot) % num_points]
|
|
784
|
-
if r_t_order == e_order: current_score += 10
|
|
853
|
+
if r_t_order == e_order: current_score += 10
|
|
785
854
|
|
|
786
855
|
if current_score > max_score:
|
|
787
856
|
max_score = current_score
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/settings_dialog.py
RENAMED
|
@@ -62,11 +62,18 @@ class SettingsDialog(QDialog):
|
|
|
62
62
|
# element symbol recognition will be coerced where possible and Chem.SanitizeMol
|
|
63
63
|
# failures will be ignored so the 3D viewer can still display the structure.
|
|
64
64
|
'skip_chemistry_checks': False,
|
|
65
|
+
# When True, always prompt the user for molecular charge on XYZ import
|
|
66
|
+
# instead of silently trying charge=0 first. Default True to disable
|
|
67
|
+
# the silent 'charge=0' test.
|
|
68
|
+
'always_ask_charge': False,
|
|
65
69
|
# 3D conversion/optimization defaults
|
|
66
70
|
'3d_conversion_mode': 'fallback',
|
|
67
71
|
'optimization_method': 'MMFF_RDKIT',
|
|
68
72
|
'ball_stick_bond_color': '#7F7F7F',
|
|
69
73
|
'cpk_colors': {},
|
|
74
|
+
# If True, RDKit will attempt to kekulize aromatic systems for 3D display
|
|
75
|
+
# (shows alternating single/double bonds rather than aromatic circles)
|
|
76
|
+
'display_kekule_3d': False,
|
|
70
77
|
}
|
|
71
78
|
|
|
72
79
|
# --- 選択された色を管理する専用のインスタンス変数 ---
|
|
@@ -197,7 +204,7 @@ class SettingsDialog(QDialog):
|
|
|
197
204
|
|
|
198
205
|
# 化学チェックスキップオプション(otherタブに移動)
|
|
199
206
|
self.skip_chem_checks_checkbox = QCheckBox()
|
|
200
|
-
self.skip_chem_checks_checkbox.setToolTip("When enabled, file import will try to ignore chemical/sanitization errors and allow viewing malformed files.")
|
|
207
|
+
self.skip_chem_checks_checkbox.setToolTip("When enabled, XYZ file import will try to ignore chemical/sanitization errors and allow viewing malformed files.")
|
|
201
208
|
# Immediately persist change to settings when user toggles the checkbox
|
|
202
209
|
try:
|
|
203
210
|
self.skip_chem_checks_checkbox.stateChanged.connect(lambda s: self._on_skip_chem_checks_changed(s))
|
|
@@ -206,7 +213,27 @@ class SettingsDialog(QDialog):
|
|
|
206
213
|
|
|
207
214
|
# Add the checkbox to the other tab's form
|
|
208
215
|
try:
|
|
209
|
-
self.other_form_layout.addRow("Skip chemistry checks on import
|
|
216
|
+
self.other_form_layout.addRow("Skip chemistry checks on import XYZ file:", self.skip_chem_checks_checkbox)
|
|
217
|
+
except Exception:
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
# 3D Kekule display option (under Other) will be added below the
|
|
221
|
+
# 'Always ask molecular charge on import' option so ordering is clear
|
|
222
|
+
# in the UI.
|
|
223
|
+
self.kekule_3d_checkbox = QCheckBox()
|
|
224
|
+
self.kekule_3d_checkbox.setToolTip("When enabled, aromatic bonds will be kekulized in the 3D view (show alternating single/double bonds).")
|
|
225
|
+
# Don't persist kekule state immediately; Apply/OK should commit setting.
|
|
226
|
+
# Always ask charge on XYZ import (skip silent charge=0 test)
|
|
227
|
+
self.always_ask_charge_checkbox = QCheckBox()
|
|
228
|
+
self.always_ask_charge_checkbox.setToolTip("Prompt for overall molecular charge when importing XYZ files instead of silently trying charge=0 first.")
|
|
229
|
+
try:
|
|
230
|
+
self.other_form_layout.addRow("Always ask molecular charge on import XYZ file:", self.always_ask_charge_checkbox)
|
|
231
|
+
except Exception:
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
# Place the Kekulé option after the always-ask-charge option
|
|
235
|
+
try:
|
|
236
|
+
self.other_form_layout.addRow("Display Kekulé bonds in 3D:", self.kekule_3d_checkbox)
|
|
210
237
|
except Exception:
|
|
211
238
|
pass
|
|
212
239
|
|
|
@@ -578,6 +605,8 @@ class SettingsDialog(QDialog):
|
|
|
578
605
|
"Other": {
|
|
579
606
|
# other options
|
|
580
607
|
'skip_chemistry_checks': self.default_settings.get('skip_chemistry_checks', False),
|
|
608
|
+
'display_kekule_3d': self.default_settings.get('display_kekule_3d', False),
|
|
609
|
+
'always_ask_charge': self.default_settings.get('always_ask_charge', False),
|
|
581
610
|
},
|
|
582
611
|
"Ball & Stick": {
|
|
583
612
|
'ball_stick_atom_scale': self.default_settings['ball_stick_atom_scale'],
|
|
@@ -899,6 +928,10 @@ class SettingsDialog(QDialog):
|
|
|
899
928
|
self.projection_combo.setCurrentIndex(idx if idx != -1 else 0)
|
|
900
929
|
# skip chemistry checks
|
|
901
930
|
self.skip_chem_checks_checkbox.setChecked(settings_dict.get('skip_chemistry_checks', self.default_settings.get('skip_chemistry_checks', False)))
|
|
931
|
+
# kekule setting
|
|
932
|
+
self.kekule_3d_checkbox.setChecked(settings_dict.get('display_kekule_3d', self.default_settings.get('display_kekule_3d', False)))
|
|
933
|
+
# always ask for charge on XYZ imports
|
|
934
|
+
self.always_ask_charge_checkbox.setChecked(settings_dict.get('always_ask_charge', self.default_settings.get('always_ask_charge', False)))
|
|
902
935
|
|
|
903
936
|
def select_color(self):
|
|
904
937
|
"""カラーピッカーを開き、選択された色を内部変数とUIに反映させる"""
|
|
@@ -950,7 +983,9 @@ class SettingsDialog(QDialog):
|
|
|
950
983
|
'stick_triple_bond_offset_factor': self.stick_triple_offset_slider.value() / 100.0,
|
|
951
984
|
'stick_double_bond_radius_factor': self.stick_double_radius_slider.value() / 100.0,
|
|
952
985
|
'stick_triple_bond_radius_factor': self.stick_triple_radius_slider.value() / 100.0,
|
|
986
|
+
'display_kekule_3d': self.kekule_3d_checkbox.isChecked(),
|
|
953
987
|
'skip_chemistry_checks': self.skip_chem_checks_checkbox.isChecked(),
|
|
988
|
+
'always_ask_charge': self.always_ask_charge_checkbox.isChecked(),
|
|
954
989
|
# Ball & Stick bond color (3D grey/uniform color)
|
|
955
990
|
'ball_stick_bond_color': getattr(self, 'bs_bond_color', self.default_settings.get('ball_stick_bond_color', '#7F7F7F')),
|
|
956
991
|
}
|
|
@@ -1027,6 +1062,8 @@ class SettingsDialog(QDialog):
|
|
|
1027
1062
|
except Exception:
|
|
1028
1063
|
pass
|
|
1029
1064
|
|
|
1065
|
+
# Note: Kekule display is applied only when user clicks Apply/OK.
|
|
1066
|
+
|
|
1030
1067
|
def accept(self):
|
|
1031
1068
|
"""ダイアログの設定を適用してから閉じる"""
|
|
1032
1069
|
# apply_settingsを呼び出して設定を適用
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/requires.txt
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/MoleditPy_linux.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/about_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/alignment_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/analysis_window.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/angle_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.icns
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.ico
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/assets/icon.png
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/atom_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/bond_item.py
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
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/dihedral_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/main_window.py
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
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/mirror_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/molecular_data.py
RENAMED
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/move_group_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/planarize_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-1.16.1a3 → moleditpy_linux-1.16.3}/src/moleditpy_linux/modules/zoomable_view.py
RENAMED
|
File without changes
|