MoleditPy-linux 3.0.4__tar.gz → 3.0.6__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-3.0.4 → moleditpy_linux-3.0.6}/PKG-INFO +1 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/pyproject.toml +1 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/__main__.py +1 -1
- moleditpy_linux-3.0.6/src/moleditpy_linux/main.py +149 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_manager.py +63 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_manager_window.py +2 -38
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/about_dialog.py +2 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -2
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/angle_dialog.py +0 -2
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -2
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +26 -3
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/dialog_logic.py +6 -6
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -2
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/main_window_init.py +9 -4
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/planarize_dialog.py +0 -1
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/translation_dialog.py +31 -8
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/constants.py +1 -1
- moleditpy_linux-3.0.4/src/moleditpy_linux/main.py +0 -78
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/LICENSE +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/README.md +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/setup.cfg +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/core/mol_geometry.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/core/molecular_data.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/analysis_window.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/app_state.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/atom_item.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/bond_item.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/compute_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/export_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/io_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/main_window.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/string_importers.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/ui_manager.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/default_settings.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/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: 3.0.
|
|
3
|
+
Version: 3.0.6
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.6
|
|
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
|
|
@@ -11,7 +11,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
print("-----------------------------------------------------")
|
|
14
|
-
print("MoleditPy
|
|
14
|
+
print("MoleditPy - A Python-based molecular editing software")
|
|
15
15
|
print("-----------------------------------------------------\n")
|
|
16
16
|
|
|
17
17
|
try:
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
MoleditPy — A Python-based molecular editing software
|
|
6
|
+
|
|
7
|
+
Author: Hiromichi Yokoyama
|
|
8
|
+
License: GPL-3.0 license
|
|
9
|
+
Repo: https://github.com/HiroYokoyama/python_molecular_editor
|
|
10
|
+
DOI: 10.5281/zenodo.17268532
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import ctypes
|
|
14
|
+
import sys
|
|
15
|
+
import argparse
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from .utils.constants import VERSION
|
|
21
|
+
except ImportError:
|
|
22
|
+
# Add the parent directory (src) to sys.path so 'moleditpy_linux.*' imports work
|
|
23
|
+
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
24
|
+
if src_dir not in sys.path:
|
|
25
|
+
sys.path.insert(0, src_dir)
|
|
26
|
+
from moleditpy_linux.utils.constants import VERSION
|
|
27
|
+
|
|
28
|
+
# VERSION is resolved above (before Qt) so --version works without launching the app.
|
|
29
|
+
|
|
30
|
+
from PyQt6.QtWidgets import QApplication
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
from .ui.main_window import MainWindow
|
|
34
|
+
except ImportError:
|
|
35
|
+
from moleditpy_linux.ui.main_window import MainWindow
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def setup_logging():
|
|
39
|
+
logging.basicConfig(
|
|
40
|
+
level=logging.INFO,
|
|
41
|
+
format="%(asctime)s [%(levelname)s] %(name)s (%(pathname)s:%(lineno)d): %(message)s",
|
|
42
|
+
stream=sys.stdout,
|
|
43
|
+
force=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
47
|
+
"""Log unhandled exceptions using the configured logging system."""
|
|
48
|
+
if issubclass(exc_type, KeyboardInterrupt):
|
|
49
|
+
# Allow keyboard interrupt to exit normally
|
|
50
|
+
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
logging.error(
|
|
54
|
+
"Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
sys.excepthook = handle_exception
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main():
|
|
61
|
+
# Setup logging as early as possible
|
|
62
|
+
setup_logging()
|
|
63
|
+
|
|
64
|
+
# --- Additional handling for Windows taskbar icon ---
|
|
65
|
+
if sys.platform == "win32":
|
|
66
|
+
myappid = "hyoko.moleditpy_linux.1.0" # Application-specific ID (arbitrary)
|
|
67
|
+
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
68
|
+
|
|
69
|
+
parser = argparse.ArgumentParser(
|
|
70
|
+
prog="moleditpy", description="MoleditPy molecular editor"
|
|
71
|
+
)
|
|
72
|
+
parser.add_argument("file", nargs="?", default=None, help="File to open on startup")
|
|
73
|
+
_variant = " (Linux)" if "moleditpy_linux" in (__file__ or "") else ""
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--version", action="version", version=f"MoleditPy{_variant} {VERSION}"
|
|
76
|
+
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"--safe",
|
|
79
|
+
action="store_true",
|
|
80
|
+
default=False,
|
|
81
|
+
help="Start in safe mode: skip loading all plugins",
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
"--install-plugin",
|
|
85
|
+
metavar="PATH",
|
|
86
|
+
help="Install a plugin from a .py file, .zip, or folder (Headless)",
|
|
87
|
+
)
|
|
88
|
+
# parse_known_args so Qt's own argv flags (e.g. -platform) are passed through
|
|
89
|
+
args, remaining = parser.parse_known_args()
|
|
90
|
+
|
|
91
|
+
# --- Headless Plugin Installation ---
|
|
92
|
+
if args.install_plugin:
|
|
93
|
+
plugin_path = os.path.abspath(args.install_plugin)
|
|
94
|
+
if not os.path.exists(plugin_path):
|
|
95
|
+
print(f"Error: Plugin path not found: {plugin_path}")
|
|
96
|
+
sys.exit(1)
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
from moleditpy_linux.plugins.plugin_manager import PluginManager
|
|
100
|
+
except ImportError:
|
|
101
|
+
from .plugins.plugin_manager import PluginManager
|
|
102
|
+
|
|
103
|
+
pm = PluginManager()
|
|
104
|
+
sha256 = pm._compute_sha256(plugin_path)
|
|
105
|
+
|
|
106
|
+
# Extract metadata
|
|
107
|
+
metadata_file = plugin_path
|
|
108
|
+
if os.path.isdir(plugin_path):
|
|
109
|
+
init_py = os.path.join(plugin_path, "__init__.py")
|
|
110
|
+
if os.path.exists(init_py):
|
|
111
|
+
metadata_file = init_py
|
|
112
|
+
|
|
113
|
+
info = (
|
|
114
|
+
pm.get_plugin_info_safe(metadata_file)
|
|
115
|
+
if metadata_file.endswith(".py")
|
|
116
|
+
else {}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
print("\n" + "=" * 40)
|
|
120
|
+
print(" PLUGIN INSTALLATION (HEADLESS)")
|
|
121
|
+
print("=" * 40)
|
|
122
|
+
print(f" Name: {info.get('name', os.path.basename(plugin_path))}")
|
|
123
|
+
print(f" Author: {info.get('author', 'Unknown')}")
|
|
124
|
+
print(f" Version: {info.get('version', 'Unknown')}")
|
|
125
|
+
print(f" Description: {info.get('description', 'No description')}")
|
|
126
|
+
print("-" * 40)
|
|
127
|
+
print(f" Path: {plugin_path}")
|
|
128
|
+
print(f" SHA-256: {sha256}")
|
|
129
|
+
print("=" * 40)
|
|
130
|
+
|
|
131
|
+
confirm = (
|
|
132
|
+
input("\nDo you want to proceed with installation? (y/N): ").strip().lower()
|
|
133
|
+
)
|
|
134
|
+
if confirm == "y":
|
|
135
|
+
success, msg = pm.install_plugin(plugin_path)
|
|
136
|
+
if success:
|
|
137
|
+
print(f"Success: {msg}")
|
|
138
|
+
sys.exit(0)
|
|
139
|
+
else:
|
|
140
|
+
print(f"Error: {msg}")
|
|
141
|
+
sys.exit(1)
|
|
142
|
+
else:
|
|
143
|
+
print("Installation aborted.")
|
|
144
|
+
sys.exit(0)
|
|
145
|
+
|
|
146
|
+
app = QApplication([sys.argv[0]] + remaining)
|
|
147
|
+
window = MainWindow(initial_file=args.file, safe_mode=args.safe)
|
|
148
|
+
window.show()
|
|
149
|
+
sys.exit(app.exec())
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_manager.py
RENAMED
|
@@ -12,6 +12,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
import ast
|
|
15
|
+
import hashlib
|
|
15
16
|
import importlib.util
|
|
16
17
|
import logging
|
|
17
18
|
import os
|
|
@@ -32,6 +33,46 @@ except ImportError:
|
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
class PluginManager:
|
|
36
|
+
def _compute_sha256(self, path: str) -> str:
|
|
37
|
+
"""Computes SHA-256 for a file or a directory (concatenated hashes of all files)."""
|
|
38
|
+
if os.path.isfile(path):
|
|
39
|
+
return self._sha256_for_file(path)
|
|
40
|
+
if os.path.isdir(path):
|
|
41
|
+
return self._sha256_for_directory(path)
|
|
42
|
+
return "N/A"
|
|
43
|
+
|
|
44
|
+
def _sha256_for_file(self, path: str) -> str:
|
|
45
|
+
"""Computes SHA-256 for a single file."""
|
|
46
|
+
hasher = hashlib.sha256()
|
|
47
|
+
try:
|
|
48
|
+
with open(path, "rb") as f:
|
|
49
|
+
for chunk in iter(lambda: f.read(8192), b""):
|
|
50
|
+
hasher.update(chunk)
|
|
51
|
+
return hasher.hexdigest()
|
|
52
|
+
except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
|
|
53
|
+
return "N/A"
|
|
54
|
+
|
|
55
|
+
def _sha256_for_directory(self, dir_path: str) -> str:
|
|
56
|
+
"""Computes SHA-256 for a directory by hashing all files in sorted order."""
|
|
57
|
+
hasher = hashlib.sha256()
|
|
58
|
+
try:
|
|
59
|
+
root = os.path.abspath(dir_path)
|
|
60
|
+
for current_root, _dirs, files in os.walk(root):
|
|
61
|
+
rel_root = os.path.relpath(current_root, root)
|
|
62
|
+
for filename in sorted(files):
|
|
63
|
+
file_path = os.path.join(current_root, filename)
|
|
64
|
+
rel_path = os.path.normpath(os.path.join(rel_root, filename))
|
|
65
|
+
# Hash the path to ensure directory structure is captured
|
|
66
|
+
hasher.update(rel_path.encode("utf-8", errors="replace"))
|
|
67
|
+
hasher.update(b"\0")
|
|
68
|
+
with open(file_path, "rb") as f:
|
|
69
|
+
for chunk in iter(lambda: f.read(8192), b""):
|
|
70
|
+
hasher.update(chunk)
|
|
71
|
+
hasher.update(b"\0")
|
|
72
|
+
return hasher.hexdigest()
|
|
73
|
+
except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
|
|
74
|
+
return "N/A"
|
|
75
|
+
|
|
35
76
|
def __init__(self, main_window: Any = None) -> None:
|
|
36
77
|
self.plugin_dir: str = os.path.join(
|
|
37
78
|
os.path.expanduser("~"), ".moleditpy", "plugins"
|
|
@@ -254,7 +295,28 @@ class PluginManager:
|
|
|
254
295
|
)
|
|
255
296
|
unique_module_name = unique_module_name.strip(".")
|
|
256
297
|
|
|
257
|
-
|
|
298
|
+
is_package = os.path.basename(filepath) == "__init__.py"
|
|
299
|
+
pkg_dir = os.path.dirname(filepath) if is_package else None
|
|
300
|
+
|
|
301
|
+
# For package plugins, register stub parent packages so that
|
|
302
|
+
# relative imports (e.g. "from . import parser") resolve correctly.
|
|
303
|
+
if is_package and "." in unique_module_name:
|
|
304
|
+
parts = unique_module_name.split(".")
|
|
305
|
+
for i in range(1, len(parts)):
|
|
306
|
+
parent_name = ".".join(parts[:i])
|
|
307
|
+
if parent_name not in sys.modules:
|
|
308
|
+
import types as _types
|
|
309
|
+
|
|
310
|
+
stub = _types.ModuleType(parent_name)
|
|
311
|
+
stub.__path__ = []
|
|
312
|
+
stub.__package__ = parent_name
|
|
313
|
+
sys.modules[parent_name] = stub
|
|
314
|
+
|
|
315
|
+
spec = importlib.util.spec_from_file_location(
|
|
316
|
+
unique_module_name,
|
|
317
|
+
filepath,
|
|
318
|
+
submodule_search_locations=([pkg_dir] if is_package else None),
|
|
319
|
+
)
|
|
258
320
|
if spec and spec.loader:
|
|
259
321
|
module = importlib.util.module_from_spec(spec)
|
|
260
322
|
sys.modules[spec.name] = module
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_manager_window.py
RENAMED
|
@@ -12,7 +12,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
12
12
|
|
|
13
13
|
import os
|
|
14
14
|
import shutil
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
|
|
17
17
|
from PyQt6.QtCore import Qt, QUrl
|
|
18
18
|
from PyQt6.QtGui import QDesktopServices, QDragEnterEvent, QDropEvent
|
|
@@ -259,7 +259,7 @@ class PluginManagerWindow(QDialog):
|
|
|
259
259
|
is_folder = True
|
|
260
260
|
|
|
261
261
|
if is_valid:
|
|
262
|
-
sha256_value = self._compute_sha256(file_path)
|
|
262
|
+
sha256_value = self.plugin_manager._compute_sha256(file_path)
|
|
263
263
|
# Extract info and confirm
|
|
264
264
|
info = {
|
|
265
265
|
"name": os.path.basename(file_path),
|
|
@@ -314,39 +314,3 @@ class PluginManagerWindow(QDialog):
|
|
|
314
314
|
summary += "Errors:\n" + "\n".join(errors)
|
|
315
315
|
|
|
316
316
|
QMessageBox.information(self, "Plugin Installation", summary)
|
|
317
|
-
|
|
318
|
-
def _compute_sha256(self, path):
|
|
319
|
-
if os.path.isfile(path):
|
|
320
|
-
return self._sha256_for_file(path)
|
|
321
|
-
if os.path.isdir(path):
|
|
322
|
-
return self._sha256_for_directory(path)
|
|
323
|
-
return "N/A"
|
|
324
|
-
|
|
325
|
-
def _sha256_for_file(self, path):
|
|
326
|
-
hasher = hashlib.sha256()
|
|
327
|
-
try:
|
|
328
|
-
with open(path, "rb") as f:
|
|
329
|
-
for chunk in iter(lambda: f.read(8192), b""):
|
|
330
|
-
hasher.update(chunk)
|
|
331
|
-
return hasher.hexdigest()
|
|
332
|
-
except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
|
|
333
|
-
return "N/A"
|
|
334
|
-
|
|
335
|
-
def _sha256_for_directory(self, dir_path):
|
|
336
|
-
hasher = hashlib.sha256()
|
|
337
|
-
try:
|
|
338
|
-
root = os.path.abspath(dir_path)
|
|
339
|
-
for current_root, _dirs, files in os.walk(root):
|
|
340
|
-
rel_root = os.path.relpath(current_root, root)
|
|
341
|
-
for filename in sorted(files):
|
|
342
|
-
file_path = os.path.join(current_root, filename)
|
|
343
|
-
rel_path = os.path.normpath(os.path.join(rel_root, filename))
|
|
344
|
-
hasher.update(rel_path.encode("utf-8", errors="replace"))
|
|
345
|
-
hasher.update(b"\0")
|
|
346
|
-
with open(file_path, "rb") as f:
|
|
347
|
-
for chunk in iter(lambda: f.read(8192), b""):
|
|
348
|
-
hasher.update(chunk)
|
|
349
|
-
hasher.update(b"\0")
|
|
350
|
-
return hasher.hexdigest()
|
|
351
|
-
except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
|
|
352
|
-
return "N/A"
|
|
@@ -72,7 +72,8 @@ class AboutDialog(QDialog):
|
|
|
72
72
|
layout.addWidget(self.image_label)
|
|
73
73
|
|
|
74
74
|
# Add text information
|
|
75
|
-
|
|
75
|
+
_variant = " (Linux)" if "moleditpy_linux" in (__file__ or "") else ""
|
|
76
|
+
info_text = f"MoleditPy{_variant} Ver. {VERSION}\nAuthor: Hiromichi Yokoyama\nLicense: GPL-3.0 license"
|
|
76
77
|
info_label = QLabel(info_text)
|
|
77
78
|
info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
78
79
|
layout.addWidget(info_label)
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py
RENAMED
|
@@ -192,9 +192,14 @@ class Dialog3DPickingMixin:
|
|
|
192
192
|
color : str, optional
|
|
193
193
|
Label colour (default ``'yellow'``).
|
|
194
194
|
"""
|
|
195
|
-
|
|
195
|
+
plotter = self.main_window.view_3d_manager.plotter
|
|
196
|
+
try:
|
|
197
|
+
cam = plotter.camera_position
|
|
198
|
+
except (AttributeError, RuntimeError, TypeError):
|
|
199
|
+
cam = None
|
|
196
200
|
|
|
197
|
-
|
|
201
|
+
pos = self.main_window.view_3d_manager.atom_positions_3d[atom_idx]
|
|
202
|
+
label_actor = plotter.add_point_labels(
|
|
198
203
|
[pos],
|
|
199
204
|
[label_text],
|
|
200
205
|
point_size=20,
|
|
@@ -204,6 +209,12 @@ class Dialog3DPickingMixin:
|
|
|
204
209
|
)
|
|
205
210
|
self.selection_labels.append(label_actor)
|
|
206
211
|
|
|
212
|
+
if cam is not None:
|
|
213
|
+
try:
|
|
214
|
+
plotter.camera_position = cam
|
|
215
|
+
except (AttributeError, RuntimeError, TypeError):
|
|
216
|
+
pass
|
|
217
|
+
|
|
207
218
|
def show_atom_labels_for(self, atoms_and_labels, color="yellow"):
|
|
208
219
|
"""Clear existing labels and add new ones for each *(idx, text)* pair.
|
|
209
220
|
|
|
@@ -214,11 +225,17 @@ class Dialog3DPickingMixin:
|
|
|
214
225
|
color : str, optional
|
|
215
226
|
Label colour (default ``'yellow'``).
|
|
216
227
|
"""
|
|
228
|
+
plotter = self.main_window.view_3d_manager.plotter
|
|
229
|
+
try:
|
|
230
|
+
cam = plotter.camera_position
|
|
231
|
+
except (AttributeError, RuntimeError, TypeError):
|
|
232
|
+
cam = None
|
|
233
|
+
|
|
217
234
|
self.clear_atom_labels()
|
|
218
235
|
|
|
219
236
|
for atom_idx, label_text in atoms_and_labels:
|
|
220
237
|
pos = self.main_window.view_3d_manager.atom_positions_3d[atom_idx]
|
|
221
|
-
label_actor =
|
|
238
|
+
label_actor = plotter.add_point_labels(
|
|
222
239
|
[pos],
|
|
223
240
|
[label_text],
|
|
224
241
|
point_size=20,
|
|
@@ -227,3 +244,9 @@ class Dialog3DPickingMixin:
|
|
|
227
244
|
always_visible=True,
|
|
228
245
|
)
|
|
229
246
|
self.selection_labels.append(label_actor)
|
|
247
|
+
|
|
248
|
+
if cam is not None:
|
|
249
|
+
try:
|
|
250
|
+
plotter.camera_position = cam
|
|
251
|
+
except (AttributeError, RuntimeError, TypeError):
|
|
252
|
+
pass
|
|
@@ -215,14 +215,14 @@ class DialogManager:
|
|
|
215
215
|
|
|
216
216
|
def open_translation_dialog(self):
|
|
217
217
|
"""Open the translation dialog"""
|
|
218
|
+
# Get preselected atoms
|
|
219
|
+
preselected_atoms = self._get_preselected_atoms_3d()
|
|
220
|
+
|
|
218
221
|
# Disable measurement mode
|
|
219
222
|
if self.host.edit_3d_manager.measurement_mode:
|
|
220
223
|
self.host.init_manager.measurement_action.setChecked(False)
|
|
221
224
|
self.host.edit_3d_manager.toggle_measurement_mode(False)
|
|
222
225
|
|
|
223
|
-
# Get preselected atoms
|
|
224
|
-
preselected_atoms = self._get_preselected_atoms_3d()
|
|
225
|
-
|
|
226
226
|
dialog = TranslationDialog(
|
|
227
227
|
self.host.view_3d_manager.current_mol,
|
|
228
228
|
self.host,
|
|
@@ -241,14 +241,14 @@ class DialogManager:
|
|
|
241
241
|
|
|
242
242
|
def open_move_group_dialog(self):
|
|
243
243
|
"""Open Move Group dialog"""
|
|
244
|
+
# Get preselected atoms
|
|
245
|
+
preselected_atoms = self._get_preselected_atoms_3d()
|
|
246
|
+
|
|
244
247
|
# Disable measurement mode
|
|
245
248
|
if self.host.edit_3d_manager.measurement_mode:
|
|
246
249
|
self.host.init_manager.measurement_action.setChecked(False)
|
|
247
250
|
self.host.edit_3d_manager.toggle_measurement_mode(False)
|
|
248
251
|
|
|
249
|
-
# Get preselected atoms
|
|
250
|
-
preselected_atoms = self._get_preselected_atoms_3d()
|
|
251
|
-
|
|
252
252
|
dialog = MoveGroupDialog(
|
|
253
253
|
self.host.view_3d_manager.current_mol,
|
|
254
254
|
self.host,
|
|
@@ -264,7 +264,10 @@ class MainInitManager:
|
|
|
264
264
|
file_ext = ext_with_dot.lstrip(".")
|
|
265
265
|
|
|
266
266
|
# 1. Custom Plugin Openers
|
|
267
|
-
if
|
|
267
|
+
if (
|
|
268
|
+
self.host.plugin_manager
|
|
269
|
+
and ext_with_dot in self.host.plugin_manager.file_openers
|
|
270
|
+
):
|
|
268
271
|
openers = self.host.plugin_manager.file_openers[ext_with_dot]
|
|
269
272
|
# Iterate through openers (already sorted by priority)
|
|
270
273
|
for opener_info in openers:
|
|
@@ -276,9 +279,11 @@ class MainInitManager:
|
|
|
276
279
|
self.host.init_manager.current_file_path = file_path
|
|
277
280
|
self.host.state_manager.update_window_title()
|
|
278
281
|
return # Success
|
|
279
|
-
except
|
|
280
|
-
|
|
281
|
-
|
|
282
|
+
except Exception as e:
|
|
283
|
+
logging.warning(
|
|
284
|
+
"Plugin opener failed for '%s': %s",
|
|
285
|
+
opener_info.get("plugin", "Unknown"),
|
|
286
|
+
e,
|
|
282
287
|
)
|
|
283
288
|
# If this opener fails, try the next one or fall through to default
|
|
284
289
|
continue
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/translation_dialog.py
RENAMED
|
@@ -40,11 +40,20 @@ class TranslationDialog(BasePickingDialog):
|
|
|
40
40
|
if preselected_atoms:
|
|
41
41
|
self.selected_atoms.update(preselected_atoms)
|
|
42
42
|
|
|
43
|
+
self._is_initializing = True
|
|
43
44
|
self.init_ui()
|
|
45
|
+
self._is_initializing = False
|
|
44
46
|
|
|
45
47
|
if self.selected_atoms:
|
|
46
|
-
self.
|
|
48
|
+
self.tabs.blockSignals(True)
|
|
49
|
+
if len(self.selected_atoms) == 1:
|
|
50
|
+
self.tabs.setCurrentIndex(_TAB_ABSOLUTE)
|
|
51
|
+
self._populate_abs_inputs_from_atom(next(iter(self.selected_atoms)))
|
|
52
|
+
else:
|
|
53
|
+
self.tabs.setCurrentIndex(_TAB_DELTA)
|
|
54
|
+
self.tabs.blockSignals(False)
|
|
47
55
|
self.update_display()
|
|
56
|
+
self.show_atom_labels()
|
|
48
57
|
|
|
49
58
|
# ------------------------------------------------------------------
|
|
50
59
|
# UI construction
|
|
@@ -169,6 +178,8 @@ class TranslationDialog(BasePickingDialog):
|
|
|
169
178
|
# ------------------------------------------------------------------
|
|
170
179
|
|
|
171
180
|
def _on_tab_changed(self, index):
|
|
181
|
+
if hasattr(self, "_is_initializing") and self._is_initializing:
|
|
182
|
+
return
|
|
172
183
|
self.selected_atoms.clear()
|
|
173
184
|
self.clear_atom_labels()
|
|
174
185
|
self.update_display()
|
|
@@ -187,23 +198,27 @@ class TranslationDialog(BasePickingDialog):
|
|
|
187
198
|
# Enforce single selection: replace previous atom
|
|
188
199
|
self.selected_atoms = {atom_idx}
|
|
189
200
|
self._populate_abs_inputs_from_atom(atom_idx)
|
|
190
|
-
self.show_atom_labels()
|
|
191
201
|
self.update_display()
|
|
202
|
+
self.show_atom_labels()
|
|
192
203
|
|
|
193
204
|
def _delta_on_atom_picked(self, atom_idx):
|
|
194
205
|
if atom_idx in self.selected_atoms:
|
|
195
206
|
self.selected_atoms.remove(atom_idx)
|
|
196
207
|
else:
|
|
197
208
|
self.selected_atoms.add(atom_idx)
|
|
198
|
-
self.show_atom_labels()
|
|
199
209
|
self.update_display()
|
|
210
|
+
self.show_atom_labels()
|
|
200
211
|
|
|
201
212
|
# ------------------------------------------------------------------
|
|
202
213
|
# Absolute tab helpers
|
|
203
214
|
# ------------------------------------------------------------------
|
|
204
215
|
|
|
205
216
|
def _populate_abs_inputs_from_atom(self, atom_idx):
|
|
206
|
-
pos =
|
|
217
|
+
pos = (
|
|
218
|
+
self.main_window.view_3d_manager.current_mol.GetConformer().GetPositions()[
|
|
219
|
+
atom_idx
|
|
220
|
+
]
|
|
221
|
+
)
|
|
207
222
|
self.abs_x_input.setText(f"{pos[0]:.4f}")
|
|
208
223
|
self.abs_y_input.setText(f"{pos[1]:.4f}")
|
|
209
224
|
self.abs_z_input.setText(f"{pos[2]:.4f}")
|
|
@@ -236,7 +251,9 @@ class TranslationDialog(BasePickingDialog):
|
|
|
236
251
|
ty = float(self.abs_y_input.text())
|
|
237
252
|
tz = float(self.abs_z_input.text())
|
|
238
253
|
except ValueError:
|
|
239
|
-
QMessageBox.warning(
|
|
254
|
+
QMessageBox.warning(
|
|
255
|
+
self, "Warning", "Please enter valid numbers for X, Y, Z."
|
|
256
|
+
)
|
|
240
257
|
return
|
|
241
258
|
|
|
242
259
|
atom_idx = next(iter(self.selected_atoms))
|
|
@@ -291,7 +308,9 @@ class TranslationDialog(BasePickingDialog):
|
|
|
291
308
|
dy = float(self.dy_input.text())
|
|
292
309
|
dz = float(self.dz_input.text())
|
|
293
310
|
except ValueError:
|
|
294
|
-
QMessageBox.warning(
|
|
311
|
+
QMessageBox.warning(
|
|
312
|
+
self, "Warning", "Please enter valid numbers for dx, dy, dz."
|
|
313
|
+
)
|
|
295
314
|
return
|
|
296
315
|
|
|
297
316
|
if dx == 0 and dy == 0 and dz == 0:
|
|
@@ -325,10 +344,14 @@ class TranslationDialog(BasePickingDialog):
|
|
|
325
344
|
self.abs_apply_btn.setEnabled(True)
|
|
326
345
|
else:
|
|
327
346
|
if count == 0:
|
|
328
|
-
self.delta_selection_label.setText(
|
|
347
|
+
self.delta_selection_label.setText(
|
|
348
|
+
"Click atoms to select (minimum 1 required)"
|
|
349
|
+
)
|
|
329
350
|
self.apply_button.setEnabled(False)
|
|
330
351
|
else:
|
|
331
|
-
self.delta_selection_label.setText(
|
|
352
|
+
self.delta_selection_label.setText(
|
|
353
|
+
f"Selected {count} atom{'s' if count != 1 else ''}"
|
|
354
|
+
)
|
|
332
355
|
self.apply_button.setEnabled(True)
|
|
333
356
|
|
|
334
357
|
def show_atom_labels(self):
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
MoleditPy — A Python-based molecular editing software
|
|
6
|
-
|
|
7
|
-
Author: Hiromichi Yokoyama
|
|
8
|
-
License: GPL-3.0 license
|
|
9
|
-
Repo: https://github.com/HiroYokoyama/python_molecular_editor
|
|
10
|
-
DOI: 10.5281/zenodo.17268532
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import ctypes
|
|
14
|
-
import sys
|
|
15
|
-
import argparse
|
|
16
|
-
import logging
|
|
17
|
-
import os
|
|
18
|
-
|
|
19
|
-
from PyQt6.QtWidgets import QApplication
|
|
20
|
-
|
|
21
|
-
try:
|
|
22
|
-
from .ui.main_window import MainWindow
|
|
23
|
-
except ImportError:
|
|
24
|
-
# Add the parent directory (src) to sys.path so 'moleditpy_linux.*' imports work
|
|
25
|
-
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
26
|
-
if src_dir not in sys.path:
|
|
27
|
-
sys.path.insert(0, src_dir)
|
|
28
|
-
from moleditpy_linux.ui.main_window import MainWindow
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def setup_logging():
|
|
32
|
-
logging.basicConfig(
|
|
33
|
-
level=logging.INFO,
|
|
34
|
-
format="%(asctime)s [%(levelname)s] %(name)s (%(pathname)s:%(lineno)d): %(message)s",
|
|
35
|
-
stream=sys.stdout,
|
|
36
|
-
force=True,
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
40
|
-
"""Log unhandled exceptions using the configured logging system."""
|
|
41
|
-
if issubclass(exc_type, KeyboardInterrupt):
|
|
42
|
-
# Allow keyboard interrupt to exit normally
|
|
43
|
-
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
|
44
|
-
return
|
|
45
|
-
|
|
46
|
-
logging.error(
|
|
47
|
-
"Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
sys.excepthook = handle_exception
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def main():
|
|
54
|
-
# Setup logging as early as possible
|
|
55
|
-
setup_logging()
|
|
56
|
-
|
|
57
|
-
# --- Additional handling for Windows taskbar icon ---
|
|
58
|
-
if sys.platform == "win32":
|
|
59
|
-
myappid = "hyoko.moleditpy_linux.1.0" # Application-specific ID (arbitrary)
|
|
60
|
-
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
61
|
-
|
|
62
|
-
parser = argparse.ArgumentParser(
|
|
63
|
-
prog="moleditpy", description="MoleditPy molecular editor"
|
|
64
|
-
)
|
|
65
|
-
parser.add_argument("file", nargs="?", default=None, help="File to open on startup")
|
|
66
|
-
parser.add_argument(
|
|
67
|
-
"--safe",
|
|
68
|
-
action="store_true",
|
|
69
|
-
default=False,
|
|
70
|
-
help="Start in safe mode: skip loading all plugins",
|
|
71
|
-
)
|
|
72
|
-
# parse_known_args so Qt's own argv flags (e.g. -platform) are passed through
|
|
73
|
-
args, remaining = parser.parse_known_args()
|
|
74
|
-
|
|
75
|
-
app = QApplication([sys.argv[0]] + remaining)
|
|
76
|
-
window = MainWindow(initial_file=args.file, safe_mode=args.safe)
|
|
77
|
-
window.show()
|
|
78
|
-
sys.exit(app.exec())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/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
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/base_picking_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/calculation_worker.py
RENAMED
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/color_settings_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/custom_interactor_style.py
RENAMED
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/custom_qt_interactor.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/edit_actions_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/geometry_base_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/molecular_scene_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/periodic_table_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/settings_tabs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/template_preview_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/template_preview_view.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/ui/user_template_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/default_settings.py
RENAMED
|
File without changes
|
{moleditpy_linux-3.0.4 → moleditpy_linux-3.0.6}/src/moleditpy_linux/utils/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|