MoleditPy-linux 4.5.1__tar.gz → 4.5.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.
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/PKG-INFO +2 -2
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/pyproject.toml +2 -2
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/PKG-INFO +2 -2
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/requires.txt +1 -1
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/atom_item.py +31 -6
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/main_window_init.py +27 -17
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/system_utils.py +18 -2
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/LICENSE +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/README.md +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/setup.cfg +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/core/mol_geometry.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/core/molecular_data.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_manager.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/about_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/analysis_window.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/app_state.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/atom_picking.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/bond_item.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/compute_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/export_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/io_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/main_window.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/string_importers.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/ui_manager.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/constants.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/default_settings.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/suppress_log.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.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
|
|
@@ -697,7 +697,7 @@ Requires-Dist: numpy
|
|
|
697
697
|
Requires-Dist: pyqt6<6.10; python_version == "3.9"
|
|
698
698
|
Requires-Dist: pyqt6<6.12; python_version != "3.9"
|
|
699
699
|
Requires-Dist: pyvista<0.49
|
|
700
|
-
Requires-Dist: pyvistaqt<0.
|
|
700
|
+
Requires-Dist: pyvistaqt<0.13
|
|
701
701
|
Requires-Dist: rdkit<2026.4
|
|
702
702
|
Dynamic: license-file
|
|
703
703
|
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MoleditPy-linux"
|
|
7
7
|
|
|
8
|
-
version = "4.5.
|
|
8
|
+
version = "4.5.2"
|
|
9
9
|
|
|
10
10
|
license = {file = "LICENSE"}
|
|
11
11
|
|
|
@@ -37,7 +37,7 @@ dependencies = [
|
|
|
37
37
|
"pyqt6 < 6.10; python_version == '3.9'",
|
|
38
38
|
"pyqt6 < 6.12; python_version != '3.9'",
|
|
39
39
|
"pyvista < 0.49",
|
|
40
|
-
"pyvistaqt < 0.
|
|
40
|
+
"pyvistaqt < 0.13",
|
|
41
41
|
"rdkit < 2026.4",
|
|
42
42
|
]
|
|
43
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.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
|
|
@@ -697,7 +697,7 @@ Requires-Dist: numpy
|
|
|
697
697
|
Requires-Dist: pyqt6<6.10; python_version == "3.9"
|
|
698
698
|
Requires-Dist: pyqt6<6.12; python_version != "3.9"
|
|
699
699
|
Requires-Dist: pyvista<0.49
|
|
700
|
-
Requires-Dist: pyvistaqt<0.
|
|
700
|
+
Requires-Dist: pyvistaqt<0.13
|
|
701
701
|
Requires-Dist: rdkit<2026.4
|
|
702
702
|
Dynamic: license-file
|
|
703
703
|
|
|
@@ -43,6 +43,34 @@ from ..utils.sip_isdeleted_safe import sip_isdeleted_safe
|
|
|
43
43
|
if TYPE_CHECKING:
|
|
44
44
|
from .bond_item import BondItem
|
|
45
45
|
|
|
46
|
+
SUBSCRIPT_MAP = str.maketrans("0123456789", "₀₁₂₃₄₅₆₇₈₉")
|
|
47
|
+
|
|
48
|
+
# Every subscript digit, so one warm-up covers any implicit-H count.
|
|
49
|
+
_WARM_UP_TEXT = "CH" + "0123456789".translate(SUBSCRIPT_MAP)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def warm_font_cache(font: Optional[QFont] = None) -> None:
|
|
53
|
+
"""Pay Qt's one-off font costs up front instead of on the first heteroatom.
|
|
54
|
+
|
|
55
|
+
Two process-wide costs hide in QFontMetricsF: the first text shaping in a
|
|
56
|
+
family (~10-120 ms, worse on a cold Windows font cache) and the first
|
|
57
|
+
lookup of a subscript digit, which Arial lacks — Qt answers that by walking
|
|
58
|
+
the whole system font database (~200-330 ms, measured).
|
|
59
|
+
|
|
60
|
+
Drawing a carbon skeleton pays neither: a bonded neutral carbon is
|
|
61
|
+
invisible, so it renders no glyph at all. The first O or N a user places
|
|
62
|
+
gets "OH₂" and pays both at once, mid-click, as a visible freeze.
|
|
63
|
+
|
|
64
|
+
Call once on the GUI thread after the window is up. QFontMetricsF is not
|
|
65
|
+
usable off the GUI thread, so this cannot move to a worker.
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
QFontMetricsF(font or QFont(FONT_FAMILY, 20, FONT_WEIGHT_BOLD)).boundingRect(
|
|
69
|
+
_WARM_UP_TEXT
|
|
70
|
+
)
|
|
71
|
+
except (RuntimeError, TypeError, ValueError):
|
|
72
|
+
logging.debug("Font cache warm-up skipped", exc_info=True)
|
|
73
|
+
|
|
46
74
|
|
|
47
75
|
class AtomItem(QGraphicsItem):
|
|
48
76
|
"""2D scene item representing a single atom in the molecule editor."""
|
|
@@ -138,8 +166,7 @@ class AtomItem(QGraphicsItem):
|
|
|
138
166
|
if not is_skeletal_carbon:
|
|
139
167
|
hydrogen_part = "H"
|
|
140
168
|
if self.implicit_h_count > 1:
|
|
141
|
-
|
|
142
|
-
hydrogen_part += str(self.implicit_h_count).translate(subscript_map)
|
|
169
|
+
hydrogen_part += str(self.implicit_h_count).translate(SUBSCRIPT_MAP)
|
|
143
170
|
|
|
144
171
|
flip_text = False
|
|
145
172
|
if hydrogen_part and self.bonds:
|
|
@@ -261,8 +288,7 @@ class AtomItem(QGraphicsItem):
|
|
|
261
288
|
if not is_skeletal_carbon:
|
|
262
289
|
hydrogen_part = "H"
|
|
263
290
|
if self.implicit_h_count > 1:
|
|
264
|
-
|
|
265
|
-
hydrogen_part += str(self.implicit_h_count).translate(subscript_map)
|
|
291
|
+
hydrogen_part += str(self.implicit_h_count).translate(SUBSCRIPT_MAP)
|
|
266
292
|
|
|
267
293
|
flip_text = False
|
|
268
294
|
if hydrogen_part and self.bonds:
|
|
@@ -361,9 +387,8 @@ class AtomItem(QGraphicsItem):
|
|
|
361
387
|
if not is_skeletal_carbon:
|
|
362
388
|
hydrogen_part = "H"
|
|
363
389
|
if self.implicit_h_count > 1:
|
|
364
|
-
subscript_map = str.maketrans("0123456789", "₀₁₂₃₄₅₆₇₈₉")
|
|
365
390
|
hydrogen_part += str(self.implicit_h_count).translate(
|
|
366
|
-
|
|
391
|
+
SUBSCRIPT_MAP
|
|
367
392
|
)
|
|
368
393
|
|
|
369
394
|
# --- Determine if the text should be flipped ---
|
|
@@ -20,9 +20,6 @@ import os
|
|
|
20
20
|
import sys
|
|
21
21
|
from typing import Any, Dict, Optional
|
|
22
22
|
|
|
23
|
-
# RDKit imports (explicit to satisfy flake8 and used features)
|
|
24
|
-
from rdkit import Chem
|
|
25
|
-
|
|
26
23
|
# PyQt6 Modules
|
|
27
24
|
from PyQt6.QtCore import QLineF, QPointF, QRectF, Qt, QTimer, QUrl
|
|
28
25
|
from PyQt6.QtGui import (
|
|
@@ -65,7 +62,8 @@ except ImportError:
|
|
|
65
62
|
winreg = None # type: ignore[assignment]
|
|
66
63
|
|
|
67
64
|
|
|
68
|
-
from ..utils.constants import DEFAULT_CPK_COLORS, NUM_DASHES, VERSION
|
|
65
|
+
from ..utils.constants import DEFAULT_CPK_COLORS, FONT_FAMILY, NUM_DASHES, VERSION
|
|
66
|
+
from .atom_item import warm_font_cache
|
|
69
67
|
from .custom_qt_interactor import CustomQtInteractor
|
|
70
68
|
from ..core.molecular_data import MolecularData
|
|
71
69
|
from .molecule_scene import MoleculeScene
|
|
@@ -74,6 +72,10 @@ from .settings_dialog import SettingsDialog
|
|
|
74
72
|
from .zoomable_view import ZoomableView
|
|
75
73
|
|
|
76
74
|
|
|
75
|
+
# Distinct from None, which is a real answer meaning "OS preference unknown".
|
|
76
|
+
_UNQUERIED = object()
|
|
77
|
+
|
|
78
|
+
|
|
77
79
|
class MainInitManager:
|
|
78
80
|
"""Feature class separated from main_window.py"""
|
|
79
81
|
|
|
@@ -82,6 +84,7 @@ class MainInitManager:
|
|
|
82
84
|
) -> None:
|
|
83
85
|
self.host = host
|
|
84
86
|
# Explicit declarations for Mypy
|
|
87
|
+
self._os_dark_pref: Any = _UNQUERIED
|
|
85
88
|
self.scene: Any = None # MoleculeScene, created during init
|
|
86
89
|
self.data: Optional[MolecularData] = None
|
|
87
90
|
self.formula_label: Optional[QLabel] = None
|
|
@@ -179,18 +182,6 @@ class MainInitManager:
|
|
|
179
182
|
# Install event filter to capture window close events (handled in UIManager)
|
|
180
183
|
self.host.installEventFilter(self.host.ui_manager)
|
|
181
184
|
|
|
182
|
-
# RDKit Warm-up (initial execution cost)
|
|
183
|
-
try:
|
|
184
|
-
# Create a molecule with a variety of common atoms to ensure
|
|
185
|
-
# the valence/H-count machinery is fully initialized.
|
|
186
|
-
warmup_smiles = "OC(N)C(S)P"
|
|
187
|
-
warmup_mol = Chem.MolFromSmiles(warmup_smiles)
|
|
188
|
-
if warmup_mol:
|
|
189
|
-
for atom in warmup_mol.GetAtoms():
|
|
190
|
-
atom.GetNumImplicitHs()
|
|
191
|
-
except (AttributeError, RuntimeError, ValueError) as e:
|
|
192
|
-
logging.warning(f"RDKit warm-up failed: {e}")
|
|
193
|
-
|
|
194
185
|
self.host.state_manager.reset_undo_stack()
|
|
195
186
|
self.scene.selectionChanged.connect( # type: ignore[attr-defined]
|
|
196
187
|
self.host.edit_actions_manager.update_edit_menu_actions
|
|
@@ -206,6 +197,8 @@ class MainInitManager:
|
|
|
206
197
|
QTimer.singleShot(0, lambda: self.load_command_line_file(initial_file))
|
|
207
198
|
|
|
208
199
|
QTimer.singleShot(0, self.apply_initial_settings)
|
|
200
|
+
# After apply_initial_settings, so the user's own font family is warmed.
|
|
201
|
+
QTimer.singleShot(0, self._warm_font_cache)
|
|
209
202
|
# Camera initialization flag (permits reset only during the first draw)
|
|
210
203
|
self._camera_initialized = False
|
|
211
204
|
|
|
@@ -226,6 +219,19 @@ class MainInitManager:
|
|
|
226
219
|
f"Suppressed exception: {e}"
|
|
227
220
|
) # Suppress non-critical UI/menu initialization errors
|
|
228
221
|
|
|
222
|
+
def _warm_font_cache(self) -> None:
|
|
223
|
+
"""Resolve the atom-label font now, in the user's configured family."""
|
|
224
|
+
scene = getattr(self, "scene", None)
|
|
225
|
+
font = None
|
|
226
|
+
if scene is not None and hasattr(scene, "get_setting"):
|
|
227
|
+
family = scene.get_setting("atom_font_family_2d", FONT_FAMILY)
|
|
228
|
+
size = scene.get_setting("atom_font_size_2d", 20)
|
|
229
|
+
bold = scene.get_setting("atom_font_bold_2d", True)
|
|
230
|
+
font = QFont(
|
|
231
|
+
family, size, QFont.Weight.Bold if bold else QFont.Weight.Normal
|
|
232
|
+
)
|
|
233
|
+
warm_font_cache(font)
|
|
234
|
+
|
|
229
235
|
def init_ui(self) -> None:
|
|
230
236
|
"""Set the window icon and initialize main layout, toolbars, and menu bar."""
|
|
231
237
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
@@ -1076,7 +1082,11 @@ class MainInitManager:
|
|
|
1076
1082
|
return QColor(fg)
|
|
1077
1083
|
|
|
1078
1084
|
with suppress_log(Exception):
|
|
1079
|
-
|
|
1085
|
+
# Cached: this forks `defaults`/`gsettings` on macOS and Linux, and
|
|
1086
|
+
# icon painting asks once per icon (15+ during startup).
|
|
1087
|
+
if self._os_dark_pref is _UNQUERIED:
|
|
1088
|
+
self._os_dark_pref = detect_system_dark_mode()
|
|
1089
|
+
os_pref = self._os_dark_pref
|
|
1080
1090
|
if os_pref is not None:
|
|
1081
1091
|
return QColor("#FFFFFF") if os_pref else QColor("#000000")
|
|
1082
1092
|
|
|
@@ -21,6 +21,9 @@ try:
|
|
|
21
21
|
except ImportError:
|
|
22
22
|
winreg = None # type: ignore[assignment]
|
|
23
23
|
|
|
24
|
+
# A wedged `defaults`/`gsettings` must not take the app's startup with it.
|
|
25
|
+
_THEME_QUERY_TIMEOUT_S = 5.0
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
def detect_system_dark_mode() -> Optional[bool]:
|
|
26
29
|
"""Return True if the OS prefers dark app theme, False if light, or None if unknown."""
|
|
@@ -33,8 +36,18 @@ def detect_system_dark_mode() -> Optional[bool]:
|
|
|
33
36
|
|
|
34
37
|
|
|
35
38
|
def detect_system_theme() -> Optional[str]:
|
|
36
|
-
"""Return the OS's preferred theme setting as 'dark', 'light', or None.
|
|
37
|
-
|
|
39
|
+
"""Return the OS's preferred theme setting as 'dark', 'light', or None.
|
|
40
|
+
|
|
41
|
+
Forks a helper process on macOS and Linux, so callers that ask repeatedly
|
|
42
|
+
should hold on to the answer rather than re-querying.
|
|
43
|
+
"""
|
|
44
|
+
with suppress_log(
|
|
45
|
+
AttributeError,
|
|
46
|
+
RuntimeError,
|
|
47
|
+
OSError,
|
|
48
|
+
FileNotFoundError,
|
|
49
|
+
subprocess.SubprocessError,
|
|
50
|
+
):
|
|
38
51
|
# Windows
|
|
39
52
|
if platform.system() == "Windows" and winreg is not None:
|
|
40
53
|
with winreg.OpenKey(
|
|
@@ -50,6 +63,7 @@ def detect_system_theme() -> Optional[str]:
|
|
|
50
63
|
["defaults", "read", "-g", "AppleInterfaceStyle"],
|
|
51
64
|
capture_output=True,
|
|
52
65
|
text=True,
|
|
66
|
+
timeout=_THEME_QUERY_TIMEOUT_S,
|
|
53
67
|
)
|
|
54
68
|
if p.returncode == 0 and "dark" in p.stdout.strip().lower():
|
|
55
69
|
return "dark"
|
|
@@ -61,6 +75,7 @@ def detect_system_theme() -> Optional[str]:
|
|
|
61
75
|
["gsettings", "get", "org.gnome.desktop.interface", "color-scheme"],
|
|
62
76
|
capture_output=True,
|
|
63
77
|
text=True,
|
|
78
|
+
timeout=_THEME_QUERY_TIMEOUT_S,
|
|
64
79
|
)
|
|
65
80
|
if p.returncode == 0:
|
|
66
81
|
out = p.stdout.strip().strip("'\n ")
|
|
@@ -73,6 +88,7 @@ def detect_system_theme() -> Optional[str]:
|
|
|
73
88
|
["gsettings", "get", "org.gnome.desktop.interface", "gtk-theme"],
|
|
74
89
|
capture_output=True,
|
|
75
90
|
text=True,
|
|
91
|
+
timeout=_THEME_QUERY_TIMEOUT_S,
|
|
76
92
|
)
|
|
77
93
|
if p.returncode == 0 and "-dark" in p.stdout.lower():
|
|
78
94
|
return "dark"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/MoleditPy_linux.egg-info/entry_points.txt
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
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_manager.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/plugins/plugin_manager_window.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/align_plane_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/base_picking_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/bond_length_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/calculation_worker.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/color_settings_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/custom_interactor_style.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/custom_qt_interactor.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/edit_actions_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/geometry_base_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/molecular_scene_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/periodic_table_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/plugin_menu_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/template_preview_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/template_preview_view.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/translation_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/ui/user_template_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/default_settings.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.5.1 → moleditpy_linux-4.5.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|