MoleditPy-linux 2.3.2__py3-none-any.whl → 2.4.0__py3-none-any.whl
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/modules/atom_item.py +61 -14
- moleditpy_linux/modules/bond_item.py +78 -20
- moleditpy_linux/modules/constants.py +1 -1
- moleditpy_linux/modules/main_window.py +4 -0
- moleditpy_linux/modules/main_window_edit_actions.py +109 -2
- moleditpy_linux/modules/main_window_export.py +4 -7
- moleditpy_linux/modules/main_window_main_init.py +30 -3
- moleditpy_linux/modules/plugin_interface.py +10 -0
- moleditpy_linux/modules/plugin_manager.py +17 -0
- moleditpy_linux/modules/settings_dialog.py +361 -7
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/METADATA +1 -1
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/RECORD +16 -16
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/WHEEL +1 -1
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/entry_points.txt +0 -0
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/licenses/LICENSE +0 -0
- {moleditpy_linux-2.3.2.dist-info → moleditpy_linux-2.4.0.dist-info}/top_level.txt +0 -0
|
@@ -13,7 +13,7 @@ DOI: 10.5281/zenodo.17268532
|
|
|
13
13
|
from PyQt6.QtWidgets import QGraphicsItem
|
|
14
14
|
|
|
15
15
|
from PyQt6.QtGui import (
|
|
16
|
-
QPen, QBrush, QColor, QFont, QPainterPath, QFontMetricsF
|
|
16
|
+
QPen, QBrush, QColor, QFont, QPainterPath, QFontMetricsF, QPainter
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
from PyQt6.QtCore import (
|
|
@@ -45,14 +45,41 @@ class AtomItem(QGraphicsItem):
|
|
|
45
45
|
self.setPos(pos)
|
|
46
46
|
self.implicit_h_count = 0
|
|
47
47
|
self.setFlags(QGraphicsItem.GraphicsItemFlag.ItemIsMovable | QGraphicsItem.GraphicsItemFlag.ItemIsSelectable)
|
|
48
|
-
self.setZValue(1)
|
|
48
|
+
self.setZValue(1)
|
|
49
|
+
self.update_style()
|
|
49
50
|
self.setAcceptHoverEvents(True)
|
|
50
51
|
self.hovered = False
|
|
51
52
|
self.has_problem = False
|
|
52
53
|
|
|
54
|
+
|
|
55
|
+
def update_style(self):
|
|
56
|
+
# Allow updating font preference dynamically
|
|
57
|
+
font_size = 20
|
|
58
|
+
try:
|
|
59
|
+
if self.scene() and self.scene().views():
|
|
60
|
+
win = self.scene().views()[0].window()
|
|
61
|
+
if win and hasattr(win, 'settings'):
|
|
62
|
+
font_size = win.settings.get('atom_font_size_2d', 20)
|
|
63
|
+
except Exception:
|
|
64
|
+
pass
|
|
65
|
+
self.font = QFont(FONT_FAMILY, font_size, FONT_WEIGHT_BOLD)
|
|
66
|
+
self.prepareGeometryChange()
|
|
67
|
+
|
|
68
|
+
self.is_visible = not (self.symbol == 'C' and len(self.bonds) > 0 and self.charge == 0 and self.radical == 0)
|
|
69
|
+
self.update()
|
|
70
|
+
|
|
53
71
|
def boundingRect(self):
|
|
54
72
|
# --- paint()メソッドと完全に同じロジックでテキストの位置とサイズを計算 ---
|
|
55
|
-
|
|
73
|
+
# Get dynamic font size
|
|
74
|
+
font_size = 20
|
|
75
|
+
try:
|
|
76
|
+
if self.scene() and self.scene().views():
|
|
77
|
+
win = self.scene().views()[0].window()
|
|
78
|
+
if win and hasattr(win, 'settings'):
|
|
79
|
+
font_size = win.settings.get('atom_font_size_2d', 20)
|
|
80
|
+
except Exception:
|
|
81
|
+
pass
|
|
82
|
+
font = QFont(FONT_FAMILY, font_size, FONT_WEIGHT_BOLD)
|
|
56
83
|
fm = QFontMetricsF(font)
|
|
57
84
|
|
|
58
85
|
hydrogen_part = ""
|
|
@@ -164,9 +191,21 @@ class AtomItem(QGraphicsItem):
|
|
|
164
191
|
return path
|
|
165
192
|
|
|
166
193
|
def paint(self, painter, option, widget):
|
|
194
|
+
# Color logic: check if we should use bond color (uniform) or CPK (element-specific)
|
|
167
195
|
color = CPK_COLORS.get(self.symbol, CPK_COLORS['DEFAULT'])
|
|
196
|
+
try:
|
|
197
|
+
if self.scene() and self.scene().views():
|
|
198
|
+
win = self.scene().views()[0].window()
|
|
199
|
+
if win and hasattr(win, 'settings'):
|
|
200
|
+
if win.settings.get('atom_use_bond_color_2d', False):
|
|
201
|
+
bond_col = win.settings.get('bond_color_2d', '#222222')
|
|
202
|
+
color = QColor(bond_col)
|
|
203
|
+
except Exception:
|
|
204
|
+
pass
|
|
205
|
+
|
|
168
206
|
if self.is_visible:
|
|
169
207
|
# 1. 描画の準備
|
|
208
|
+
# Ensure correct font is used (self.font should be updated by update_style)
|
|
170
209
|
painter.setFont(self.font)
|
|
171
210
|
fm = painter.fontMetrics()
|
|
172
211
|
|
|
@@ -253,19 +292,29 @@ class AtomItem(QGraphicsItem):
|
|
|
253
292
|
offset_x = -symbol_rect.width() // 2
|
|
254
293
|
text_rect.moveTo(offset_x, -text_rect.height() // 2)
|
|
255
294
|
|
|
256
|
-
# 2.
|
|
295
|
+
# 2. 原子記号の背景を処理(白で塗りつぶす か 透明なら切り抜く)
|
|
257
296
|
if self.scene():
|
|
258
297
|
bg_brush = self.scene().backgroundBrush()
|
|
259
298
|
bg_rect = text_rect.adjusted(-5, -8, 5, 8)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
299
|
+
|
|
300
|
+
if bg_brush.style() == Qt.BrushStyle.NoBrush:
|
|
301
|
+
# 背景が透明の場合は、CompositionMode_Clearを使って
|
|
302
|
+
# 重なっている結合の線を「消しゴム」のように消す
|
|
303
|
+
painter.save()
|
|
304
|
+
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_Clear)
|
|
305
|
+
painter.setBrush(QColor(0, 0, 0, 255)) # 色は何でも良い(アルファが重要)
|
|
306
|
+
painter.setPen(Qt.PenStyle.NoPen)
|
|
307
|
+
painter.drawEllipse(bg_rect)
|
|
308
|
+
painter.restore()
|
|
309
|
+
else:
|
|
310
|
+
# 背景がある場合は、その背景色で塗りつぶす(従来通り)
|
|
311
|
+
painter.setBrush(bg_brush)
|
|
312
|
+
painter.setPen(Qt.PenStyle.NoPen)
|
|
313
|
+
painter.drawEllipse(bg_rect)
|
|
263
314
|
|
|
264
315
|
# 3. 原子記号自体を描画
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
else:
|
|
268
|
-
painter.setPen(QPen(color))
|
|
316
|
+
# Color is already determined above
|
|
317
|
+
painter.setPen(QPen(color))
|
|
269
318
|
painter.drawText(text_rect, int(alignment_flag), display_text)
|
|
270
319
|
|
|
271
320
|
# --- 電荷とラジカルの描画 ---
|
|
@@ -316,9 +365,7 @@ class AtomItem(QGraphicsItem):
|
|
|
316
365
|
painter.setPen(pen)
|
|
317
366
|
painter.drawRect(self.boundingRect())
|
|
318
367
|
|
|
319
|
-
|
|
320
|
-
self.is_visible = not (self.symbol == 'C' and len(self.bonds) > 0 and self.charge == 0 and self.radical == 0)
|
|
321
|
-
self.update()
|
|
368
|
+
|
|
322
369
|
|
|
323
370
|
|
|
324
371
|
# 約203行目 AtomItem クラス内
|
|
@@ -105,7 +105,21 @@ class BondItem(QGraphicsItem):
|
|
|
105
105
|
line = self.get_line_in_local_coords()
|
|
106
106
|
except Exception:
|
|
107
107
|
line = QLineF(0, 0, 0, 0)
|
|
108
|
-
|
|
108
|
+
|
|
109
|
+
# Get dynamic bond offset (spacing)
|
|
110
|
+
bond_offset = 3.5
|
|
111
|
+
try:
|
|
112
|
+
if self.scene() and hasattr(self.scene(), 'views') and self.scene().views():
|
|
113
|
+
win = self.scene().views()[0].window()
|
|
114
|
+
if win and hasattr(win, 'settings'):
|
|
115
|
+
# Use specific spacing based on bond order
|
|
116
|
+
if getattr(self, 'order', 1) == 3:
|
|
117
|
+
bond_offset = win.settings.get('bond_spacing_triple_2d', 3.5)
|
|
118
|
+
else:
|
|
119
|
+
bond_offset = win.settings.get('bond_spacing_double_2d', 3.5)
|
|
120
|
+
except Exception:
|
|
121
|
+
bond_offset = globals().get('BOND_OFFSET', 3.5)
|
|
122
|
+
|
|
109
123
|
extra = (getattr(self, 'order', 1) - 1) * bond_offset + 20
|
|
110
124
|
rect = QRectF(line.p1(), line.p2()).normalized().adjusted(-extra, -extra, extra, extra)
|
|
111
125
|
|
|
@@ -142,7 +156,18 @@ class BondItem(QGraphicsItem):
|
|
|
142
156
|
view = scene.views()[0]
|
|
143
157
|
scale = view.transform().m11()
|
|
144
158
|
|
|
145
|
-
|
|
159
|
+
# Dynamic bond width
|
|
160
|
+
width_2d = 2.0
|
|
161
|
+
try:
|
|
162
|
+
if view.window() and hasattr(view.window(), 'settings'):
|
|
163
|
+
width_2d = view.window().settings.get('bond_width_2d', 2.0)
|
|
164
|
+
except Exception:
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
# Hit area should be roughly closely matched or slightly larger than visual
|
|
168
|
+
# Ensure minimum hit width for usability
|
|
169
|
+
scene_width = max(DESIRED_BOND_PIXEL_WIDTH, width_2d * 10) / scale
|
|
170
|
+
|
|
146
171
|
|
|
147
172
|
stroker = QPainterPathStroker()
|
|
148
173
|
stroker.setWidth(scene_width)
|
|
@@ -160,24 +185,44 @@ class BondItem(QGraphicsItem):
|
|
|
160
185
|
line = self.get_line_in_local_coords()
|
|
161
186
|
if line.length() == 0: return
|
|
162
187
|
|
|
163
|
-
#
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
188
|
+
# Allow bond color override from app settings (2D color)
|
|
189
|
+
width_2d = 2.0
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
sc = self.scene()
|
|
193
|
+
if sc is not None and hasattr(sc, 'window') and sc.window is not None:
|
|
194
|
+
# Get settings
|
|
195
|
+
settings = sc.window.settings
|
|
196
|
+
|
|
197
|
+
# Width
|
|
198
|
+
width_2d = settings.get('bond_width_2d', 2.0)
|
|
199
|
+
|
|
200
|
+
# Cap Style logic
|
|
201
|
+
cap_style_str = settings.get('bond_cap_style_2d', 'Round')
|
|
202
|
+
cap_style = Qt.PenCapStyle.RoundCap # Default
|
|
203
|
+
|
|
204
|
+
if cap_style_str == 'Flat':
|
|
205
|
+
cap_style = Qt.PenCapStyle.FlatCap
|
|
206
|
+
elif cap_style_str == 'Square':
|
|
207
|
+
cap_style = Qt.PenCapStyle.SquareCap
|
|
208
|
+
|
|
209
|
+
# Color
|
|
210
|
+
if self.isSelected():
|
|
211
|
+
bond_color = QColor("blue") # Selection color
|
|
176
212
|
else:
|
|
177
|
-
|
|
178
|
-
|
|
213
|
+
bond_hex = settings.get('bond_color_2d', '#222222')
|
|
214
|
+
bond_color = QColor(bond_hex)
|
|
215
|
+
|
|
216
|
+
pen = QPen(bond_color, width_2d)
|
|
217
|
+
pen.setCapStyle(cap_style)
|
|
218
|
+
painter.setPen(pen)
|
|
219
|
+
|
|
220
|
+
else:
|
|
179
221
|
painter.setPen(self.pen)
|
|
180
|
-
|
|
222
|
+
except Exception:
|
|
223
|
+
painter.setPen(self.pen)
|
|
224
|
+
|
|
225
|
+
painter.setBrush(QBrush(Qt.GlobalColor.black))
|
|
181
226
|
|
|
182
227
|
# --- 立体化学 (Wedge/Dash) の描画 ---
|
|
183
228
|
if self.order == 1 and self.stereo in [1, 2]:
|
|
@@ -213,7 +258,19 @@ class BondItem(QGraphicsItem):
|
|
|
213
258
|
painter.drawLine(line)
|
|
214
259
|
else:
|
|
215
260
|
v = line.unitVector().normalVector()
|
|
216
|
-
|
|
261
|
+
# Use dynamic offset
|
|
262
|
+
bond_offset = 3.5
|
|
263
|
+
try:
|
|
264
|
+
sc = self.scene()
|
|
265
|
+
if sc and sc.views() and hasattr(sc.views()[0].window(), 'settings'):
|
|
266
|
+
if self.order == 3:
|
|
267
|
+
bond_offset = sc.views()[0].window().settings.get('bond_spacing_triple_2d', 3.5)
|
|
268
|
+
else:
|
|
269
|
+
bond_offset = sc.views()[0].window().settings.get('bond_spacing_double_2d', 3.5)
|
|
270
|
+
except Exception:
|
|
271
|
+
bond_offset = globals().get('BOND_OFFSET', 3.5)
|
|
272
|
+
|
|
273
|
+
offset = QPointF(v.dx(), v.dy()) * bond_offset
|
|
217
274
|
|
|
218
275
|
if self.order == 2:
|
|
219
276
|
# 環構造かどうかを判定し、描画方法を変更
|
|
@@ -274,7 +331,8 @@ class BondItem(QGraphicsItem):
|
|
|
274
331
|
is_in_ring = False
|
|
275
332
|
|
|
276
333
|
v = line.unitVector().normalVector()
|
|
277
|
-
offset
|
|
334
|
+
# Re-calculate offset in case loop variable scope issue, though strictly not needed if offset defined above works
|
|
335
|
+
offset = QPointF(v.dx(), v.dy()) * bond_offset
|
|
278
336
|
|
|
279
337
|
if is_in_ring and ring_center:
|
|
280
338
|
# 環構造: 1本の中心線(単結合位置) + 1本の短い内側線
|
|
@@ -524,6 +524,10 @@ class MainWindow(QMainWindow):
|
|
|
524
524
|
# --- MOVED TO main_window_edit_actions.py ---
|
|
525
525
|
return self.main_window_edit_actions.adjust_molecule_positions_to_avoid_collisions(mol, frags)
|
|
526
526
|
|
|
527
|
+
def open_rotate_2d_dialog(self):
|
|
528
|
+
# --- MOVED TO main_window_edit_actions.py ---
|
|
529
|
+
return self.main_window_edit_actions.open_rotate_2d_dialog()
|
|
530
|
+
|
|
527
531
|
def draw_molecule_3d(self, mol):
|
|
528
532
|
# --- MOVED TO main_window_view_3d.py ---
|
|
529
533
|
return self.main_window_view_3d.draw_molecule_3d(mol)
|
|
@@ -34,7 +34,7 @@ from rdkit.Chem import AllChem
|
|
|
34
34
|
|
|
35
35
|
# PyQt6 Modules
|
|
36
36
|
from PyQt6.QtWidgets import (
|
|
37
|
-
QApplication
|
|
37
|
+
QApplication, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QSpinBox, QSlider, QPushButton
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
from PyQt6.QtGui import (
|
|
@@ -43,9 +43,51 @@ from PyQt6.QtGui import (
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
from PyQt6.QtCore import (
|
|
46
|
-
QPointF, QLineF, QMimeData, QByteArray, QTimer
|
|
46
|
+
QPointF, QLineF, QMimeData, QByteArray, QTimer, Qt
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
+
class Rotate2DDialog(QDialog):
|
|
50
|
+
def __init__(self, parent=None):
|
|
51
|
+
super().__init__(parent)
|
|
52
|
+
self.setWindowTitle("Rotate 2D")
|
|
53
|
+
self.setFixedWidth(300)
|
|
54
|
+
|
|
55
|
+
layout = QVBoxLayout(self)
|
|
56
|
+
|
|
57
|
+
# Angle input
|
|
58
|
+
input_layout = QHBoxLayout()
|
|
59
|
+
input_layout.addWidget(QLabel("Angle (degrees):"))
|
|
60
|
+
self.angle_spin = QSpinBox()
|
|
61
|
+
self.angle_spin.setRange(-360, 360)
|
|
62
|
+
self.angle_spin.setValue(45)
|
|
63
|
+
input_layout.addWidget(self.angle_spin)
|
|
64
|
+
layout.addLayout(input_layout)
|
|
65
|
+
|
|
66
|
+
# Slider
|
|
67
|
+
self.slider = QSlider(Qt.Orientation.Horizontal)
|
|
68
|
+
self.slider.setRange(-180, 180)
|
|
69
|
+
self.slider.setValue(45)
|
|
70
|
+
self.slider.setTickPosition(QSlider.TickPosition.TicksBelow)
|
|
71
|
+
self.slider.setTickInterval(15)
|
|
72
|
+
layout.addWidget(self.slider)
|
|
73
|
+
|
|
74
|
+
# Sync slider and spinbox
|
|
75
|
+
self.angle_spin.valueChanged.connect(self.slider.setValue)
|
|
76
|
+
self.slider.valueChanged.connect(self.angle_spin.setValue)
|
|
77
|
+
|
|
78
|
+
# Buttons
|
|
79
|
+
btn_layout = QHBoxLayout()
|
|
80
|
+
ok_btn = QPushButton("Rotate")
|
|
81
|
+
ok_btn.clicked.connect(self.accept)
|
|
82
|
+
cancel_btn = QPushButton("Cancel")
|
|
83
|
+
cancel_btn.clicked.connect(self.reject)
|
|
84
|
+
btn_layout.addWidget(ok_btn)
|
|
85
|
+
btn_layout.addWidget(cancel_btn)
|
|
86
|
+
layout.addLayout(btn_layout)
|
|
87
|
+
|
|
88
|
+
def get_angle(self):
|
|
89
|
+
return self.angle_spin.value()
|
|
90
|
+
|
|
49
91
|
|
|
50
92
|
# Use centralized Open Babel availability from package-level __init__
|
|
51
93
|
# Use per-package modules availability (local __init__).
|
|
@@ -568,6 +610,67 @@ class MainWindowEditActions(object):
|
|
|
568
610
|
|
|
569
611
|
|
|
570
612
|
|
|
613
|
+
def open_rotate_2d_dialog(self):
|
|
614
|
+
"""2D回転ダイアログを開く"""
|
|
615
|
+
dialog = Rotate2DDialog(self)
|
|
616
|
+
if dialog.exec() == QDialog.DialogCode.Accepted:
|
|
617
|
+
angle = dialog.get_angle()
|
|
618
|
+
self.rotate_molecule_2d(angle)
|
|
619
|
+
|
|
620
|
+
def rotate_molecule_2d(self, angle_degrees):
|
|
621
|
+
"""2D分子を指定角度回転させる(選択範囲があればそれのみ、なければ全体)"""
|
|
622
|
+
try:
|
|
623
|
+
# Determine target atoms
|
|
624
|
+
selected_items = self.scene.selectedItems()
|
|
625
|
+
target_atoms = [item for item in selected_items if isinstance(item, AtomItem)]
|
|
626
|
+
|
|
627
|
+
# If no selection, rotate everything
|
|
628
|
+
if not target_atoms:
|
|
629
|
+
target_atoms = [data['item'] for data in self.data.atoms.values() if data.get('item') and not sip_isdeleted_safe(data['item'])]
|
|
630
|
+
|
|
631
|
+
if not target_atoms:
|
|
632
|
+
self.statusBar().showMessage("No atoms to rotate.")
|
|
633
|
+
return
|
|
634
|
+
|
|
635
|
+
# Calculate Center
|
|
636
|
+
xs = [atom.pos().x() for atom in target_atoms]
|
|
637
|
+
ys = [atom.pos().y() for atom in target_atoms]
|
|
638
|
+
if not xs: return
|
|
639
|
+
|
|
640
|
+
center_x = sum(xs) / len(xs)
|
|
641
|
+
center_y = sum(ys) / len(ys)
|
|
642
|
+
center = QPointF(center_x, center_y)
|
|
643
|
+
|
|
644
|
+
rad = math.radians(angle_degrees)
|
|
645
|
+
cos_a = math.cos(rad)
|
|
646
|
+
sin_a = math.sin(rad)
|
|
647
|
+
|
|
648
|
+
for atom in target_atoms:
|
|
649
|
+
# Relative pos
|
|
650
|
+
dx = atom.pos().x() - center_x
|
|
651
|
+
dy = atom.pos().y() - center_y
|
|
652
|
+
|
|
653
|
+
# Rotate
|
|
654
|
+
new_dx = dx * cos_a - dy * sin_a
|
|
655
|
+
new_dy = dx * sin_a + dy * cos_a
|
|
656
|
+
|
|
657
|
+
new_pos = QPointF(center_x + new_dx, center_y + new_dy)
|
|
658
|
+
atom.setPos(new_pos)
|
|
659
|
+
|
|
660
|
+
# Update bonds
|
|
661
|
+
self.scene.update_connected_bonds(target_atoms)
|
|
662
|
+
|
|
663
|
+
self.push_undo_state()
|
|
664
|
+
self.statusBar().showMessage(f"Rotated {len(target_atoms)} atoms by {angle_degrees} degrees.")
|
|
665
|
+
self.scene.update()
|
|
666
|
+
|
|
667
|
+
except Exception as e:
|
|
668
|
+
print(f"Error rotating molecule: {e}")
|
|
669
|
+
traceback.print_exc()
|
|
670
|
+
self.statusBar().showMessage(f"Error rotating: {e}")
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
|
|
571
674
|
|
|
572
675
|
def select_all(self):
|
|
573
676
|
for item in self.scene.items():
|
|
@@ -641,6 +744,10 @@ class MainWindowEditActions(object):
|
|
|
641
744
|
# アプリケーションのイベントループを強制的に処理し、画面の再描画を確実に行う
|
|
642
745
|
QApplication.processEvents()
|
|
643
746
|
|
|
747
|
+
# Call plugin document reset handlers
|
|
748
|
+
if hasattr(self, 'plugin_manager') and self.plugin_manager:
|
|
749
|
+
self.plugin_manager.invoke_document_reset_handlers()
|
|
750
|
+
|
|
644
751
|
self.statusBar().showMessage("Cleared all data.")
|
|
645
752
|
|
|
646
753
|
|
|
@@ -672,7 +672,7 @@ class MainWindowExport(object):
|
|
|
672
672
|
filePath += ".png"
|
|
673
673
|
|
|
674
674
|
reply = QMessageBox.question(self, 'Choose Background',
|
|
675
|
-
'Do you want a transparent background?\n(Choose "No"
|
|
675
|
+
'Do you want a transparent background?\n(Choose "No" to use the current background color)',
|
|
676
676
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No | QMessageBox.StandardButton.Cancel,
|
|
677
677
|
QMessageBox.StandardButton.Yes)
|
|
678
678
|
|
|
@@ -706,8 +706,7 @@ class MainWindowExport(object):
|
|
|
706
706
|
|
|
707
707
|
if is_transparent:
|
|
708
708
|
self.scene.setBackgroundBrush(QBrush(Qt.BrushStyle.NoBrush))
|
|
709
|
-
|
|
710
|
-
self.scene.setBackgroundBrush(QBrush(QColor("#FFFFFF")))
|
|
709
|
+
# Else: keep original_background (current 2D background)
|
|
711
710
|
|
|
712
711
|
rect_to_render = molecule_bounds.adjusted(-20, -20, 20, 20)
|
|
713
712
|
|
|
@@ -719,10 +718,8 @@ class MainWindowExport(object):
|
|
|
719
718
|
return
|
|
720
719
|
|
|
721
720
|
image = QImage(w, h, QImage.Format.Format_ARGB32_Premultiplied)
|
|
722
|
-
if
|
|
723
|
-
|
|
724
|
-
else:
|
|
725
|
-
image.fill(Qt.GlobalColor.white)
|
|
721
|
+
# Always fill with transparent; render will paint opaque background if present
|
|
722
|
+
image.fill(Qt.GlobalColor.transparent)
|
|
726
723
|
|
|
727
724
|
painter = QPainter()
|
|
728
725
|
ok = painter.begin(image)
|
|
@@ -372,7 +372,7 @@ class MainWindowMainInit(object):
|
|
|
372
372
|
|
|
373
373
|
# --- 左パネルのボタンレイアウト ---
|
|
374
374
|
left_buttons_layout = QHBoxLayout()
|
|
375
|
-
self.cleanup_button = QPushButton("
|
|
375
|
+
self.cleanup_button = QPushButton("Clean Up 2D")
|
|
376
376
|
self.cleanup_button.clicked.connect(self.clean_up_2d_structure)
|
|
377
377
|
left_buttons_layout.addWidget(self.cleanup_button)
|
|
378
378
|
|
|
@@ -987,7 +987,13 @@ class MainWindowMainInit(object):
|
|
|
987
987
|
|
|
988
988
|
edit_menu.addSeparator()
|
|
989
989
|
|
|
990
|
-
|
|
990
|
+
rotate_2d_action = QAction("Rotate 2D...", self)
|
|
991
|
+
rotate_2d_action.triggered.connect(self.open_rotate_2d_dialog)
|
|
992
|
+
edit_menu.addAction(rotate_2d_action)
|
|
993
|
+
|
|
994
|
+
edit_menu.addSeparator()
|
|
995
|
+
|
|
996
|
+
optimize_2d_action = QAction("Clean Up 2D", self)
|
|
991
997
|
optimize_2d_action.setShortcut(QKeySequence("Ctrl+J"))
|
|
992
998
|
optimize_2d_action.triggered.connect(self.clean_up_2d_structure)
|
|
993
999
|
edit_menu.addAction(optimize_2d_action)
|
|
@@ -1247,7 +1253,7 @@ class MainWindowMainInit(object):
|
|
|
1247
1253
|
|
|
1248
1254
|
settings_menu = menu_bar.addMenu("&Settings")
|
|
1249
1255
|
# 1) 3D View settings (existing)
|
|
1250
|
-
view_settings_action = QAction("
|
|
1256
|
+
view_settings_action = QAction("Settings...", self)
|
|
1251
1257
|
view_settings_action.triggered.connect(self.open_settings_dialog)
|
|
1252
1258
|
settings_menu.addAction(view_settings_action)
|
|
1253
1259
|
|
|
@@ -1495,6 +1501,10 @@ class MainWindowMainInit(object):
|
|
|
1495
1501
|
|
|
1496
1502
|
try:
|
|
1497
1503
|
if hasattr(self, 'scene') and self.scene:
|
|
1504
|
+
# Apply 2D background color
|
|
1505
|
+
bg_color_2d = self.settings.get('background_color_2d', '#FFFFFF')
|
|
1506
|
+
self.scene.setBackgroundBrush(QBrush(QColor(bg_color_2d)))
|
|
1507
|
+
|
|
1498
1508
|
for it in list(self.scene.items()):
|
|
1499
1509
|
if hasattr(it, 'update_style'):
|
|
1500
1510
|
it.update_style()
|
|
@@ -1674,6 +1684,18 @@ class MainWindowMainInit(object):
|
|
|
1674
1684
|
# Whether to kekulize aromatic systems for 3D display
|
|
1675
1685
|
'display_kekule_3d': False,
|
|
1676
1686
|
'always_ask_charge': False,
|
|
1687
|
+
'display_aromatic_circles_3d': False,
|
|
1688
|
+
'ball_stick_use_cpk_bond_color': False,
|
|
1689
|
+
|
|
1690
|
+
# --- 2D Settings Defaults ---
|
|
1691
|
+
'bond_width_2d': 2.0,
|
|
1692
|
+
'bond_spacing_double_2d': 3.5,
|
|
1693
|
+
'bond_spacing_triple_2d': 3.5,
|
|
1694
|
+
'atom_font_size_2d': 20,
|
|
1695
|
+
'background_color_2d': '#FFFFFF',
|
|
1696
|
+
'bond_color_2d': '#222222', # Almost black
|
|
1697
|
+
'atom_use_bond_color_2d': False,
|
|
1698
|
+
'bond_cap_style_2d': 'Round',
|
|
1677
1699
|
}
|
|
1678
1700
|
|
|
1679
1701
|
try:
|
|
@@ -1851,6 +1873,11 @@ class MainWindowMainInit(object):
|
|
|
1851
1873
|
action_text = text if text else parts[-1]
|
|
1852
1874
|
action = QAction(action_text, self)
|
|
1853
1875
|
action.triggered.connect(callback)
|
|
1876
|
+
|
|
1877
|
+
# Apply shortcut if provided
|
|
1878
|
+
if action_def.get('shortcut'):
|
|
1879
|
+
action.setShortcut(QKeySequence(action_def['shortcut']))
|
|
1880
|
+
|
|
1854
1881
|
action.setData(PLUGIN_ACTION_TAG) # TAG THE ACTION
|
|
1855
1882
|
current_menu.addAction(action)
|
|
1856
1883
|
|
|
@@ -168,6 +168,16 @@ class PluginContext:
|
|
|
168
168
|
"""
|
|
169
169
|
self._manager.register_3d_style(self._plugin_name, style_name, callback)
|
|
170
170
|
|
|
171
|
+
def register_document_reset_handler(self, callback: Callable[[], None]):
|
|
172
|
+
"""
|
|
173
|
+
Register a callback to be called when a new document is created (File→New).
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
callback: Function with no arguments that resets plugin state.
|
|
177
|
+
"""
|
|
178
|
+
self._manager.register_document_reset_handler(self._plugin_name, callback)
|
|
179
|
+
|
|
180
|
+
|
|
171
181
|
|
|
172
182
|
|
|
173
183
|
|
|
@@ -51,6 +51,7 @@ class PluginManager:
|
|
|
51
51
|
self.save_handlers = {}
|
|
52
52
|
self.load_handlers = {}
|
|
53
53
|
self.custom_3d_styles = {} # style_name -> {'plugin': name, 'callback': func}
|
|
54
|
+
self.document_reset_handlers = [] # List of callbacks to call on new document
|
|
54
55
|
|
|
55
56
|
def get_main_window(self):
|
|
56
57
|
return self.main_window
|
|
@@ -182,6 +183,7 @@ class PluginManager:
|
|
|
182
183
|
self.save_handlers = {}
|
|
183
184
|
self.load_handlers = {}
|
|
184
185
|
self.custom_3d_styles = {}
|
|
186
|
+
self.document_reset_handlers = []
|
|
185
187
|
|
|
186
188
|
if not os.path.exists(self.plugin_dir):
|
|
187
189
|
return []
|
|
@@ -378,6 +380,21 @@ class PluginManager:
|
|
|
378
380
|
self.custom_3d_styles[style_name] = {
|
|
379
381
|
'plugin': plugin_name, 'callback': callback
|
|
380
382
|
}
|
|
383
|
+
|
|
384
|
+
def register_document_reset_handler(self, plugin_name, callback):
|
|
385
|
+
"""Register callback to be invoked when a new document is created."""
|
|
386
|
+
self.document_reset_handlers.append({
|
|
387
|
+
'plugin': plugin_name,
|
|
388
|
+
'callback': callback
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
def invoke_document_reset_handlers(self):
|
|
392
|
+
"""Call all registered document reset handlers."""
|
|
393
|
+
for handler in self.document_reset_handlers:
|
|
394
|
+
try:
|
|
395
|
+
handler['callback']()
|
|
396
|
+
except Exception as e:
|
|
397
|
+
print(f"Error in document reset handler for {handler['plugin']}: {e}")
|
|
381
398
|
|
|
382
399
|
def get_plugin_info_safe(self, file_path):
|
|
383
400
|
"""Extracts plugin metadata using AST parsing (safe, no execution)."""
|
|
@@ -26,8 +26,8 @@ except Exception:
|
|
|
26
26
|
class SettingsDialog(QDialog):
|
|
27
27
|
def __init__(self, current_settings, parent=None):
|
|
28
28
|
super().__init__(parent)
|
|
29
|
-
self.setWindowTitle("
|
|
30
|
-
self.setMinimumSize(
|
|
29
|
+
self.setWindowTitle("Settings")
|
|
30
|
+
self.setMinimumSize(700, 800)
|
|
31
31
|
|
|
32
32
|
# 親ウィンドウの参照を保存(Apply機能のため)
|
|
33
33
|
self.parent_window = parent
|
|
@@ -89,6 +89,16 @@ class SettingsDialog(QDialog):
|
|
|
89
89
|
# (shows alternating single/double bonds rather than aromatic circles)
|
|
90
90
|
'display_kekule_3d': False,
|
|
91
91
|
'ball_stick_use_cpk_bond_color': False,
|
|
92
|
+
|
|
93
|
+
# --- 2D Settings Defaults ---
|
|
94
|
+
'bond_width_2d': 2.0,
|
|
95
|
+
'bond_spacing_double_2d': 3.5,
|
|
96
|
+
'bond_spacing_triple_2d': 3.5,
|
|
97
|
+
'atom_font_size_2d': 20,
|
|
98
|
+
'background_color_2d': '#FFFFFF',
|
|
99
|
+
'bond_color_2d': '#222222', # Almost black
|
|
100
|
+
'atom_use_bond_color_2d': False,
|
|
101
|
+
'bond_cap_style_2d': 'Round',
|
|
92
102
|
}
|
|
93
103
|
|
|
94
104
|
# --- 選択された色を管理する専用のインスタンス変数 ---
|
|
@@ -101,6 +111,9 @@ class SettingsDialog(QDialog):
|
|
|
101
111
|
self.tab_widget = QTabWidget()
|
|
102
112
|
layout.addWidget(self.tab_widget)
|
|
103
113
|
|
|
114
|
+
# 2D Settings Tab (First)
|
|
115
|
+
self.create_2d_settings_tab()
|
|
116
|
+
|
|
104
117
|
# Scene設定タブ
|
|
105
118
|
self.create_scene_tab()
|
|
106
119
|
|
|
@@ -129,6 +142,13 @@ class SettingsDialog(QDialog):
|
|
|
129
142
|
self.aromatic_torus_thickness_slider.setValue(int(thickness_factor * 100))
|
|
130
143
|
self.aromatic_torus_thickness_label.setText(f"{thickness_factor:.1f}")
|
|
131
144
|
|
|
145
|
+
# Initialize internal 2D colors
|
|
146
|
+
self.current_bg_color_2d = current_settings.get('background_color_2d', self.default_settings['background_color_2d'])
|
|
147
|
+
self.current_bond_color_2d = current_settings.get('bond_color_2d', self.default_settings['bond_color_2d'])
|
|
148
|
+
|
|
149
|
+
# Apply initial 2D button styles
|
|
150
|
+
self.update_2d_color_buttons()
|
|
151
|
+
|
|
132
152
|
# --- ボタンの配置 ---
|
|
133
153
|
buttons = QHBoxLayout()
|
|
134
154
|
|
|
@@ -160,6 +180,121 @@ class SettingsDialog(QDialog):
|
|
|
160
180
|
buttons.addWidget(ok_button)
|
|
161
181
|
buttons.addWidget(cancel_button)
|
|
162
182
|
layout.addLayout(buttons)
|
|
183
|
+
|
|
184
|
+
def create_2d_settings_tab(self):
|
|
185
|
+
"""2D Settings Tab"""
|
|
186
|
+
widget = QWidget()
|
|
187
|
+
form_layout = QFormLayout(widget)
|
|
188
|
+
|
|
189
|
+
# --- View Settings ---
|
|
190
|
+
form_layout.addRow(QLabel("<b>View Appearance</b>"))
|
|
191
|
+
|
|
192
|
+
# Background Color
|
|
193
|
+
self.bg_color_2d_button = QPushButton()
|
|
194
|
+
self.bg_color_2d_button.setFixedSize(60, 24)
|
|
195
|
+
self.bg_color_2d_button.clicked.connect(self.pick_bg_color_2d)
|
|
196
|
+
form_layout.addRow("Background Color:", self.bg_color_2d_button)
|
|
197
|
+
|
|
198
|
+
line = QFrame()
|
|
199
|
+
line.setFrameShape(QFrame.Shape.HLine)
|
|
200
|
+
line.setFrameShadow(QFrame.Shadow.Sunken)
|
|
201
|
+
form_layout.addRow(line)
|
|
202
|
+
|
|
203
|
+
# --- Bond Settings ---
|
|
204
|
+
form_layout.addRow(QLabel("<b>Bond Settings</b>"))
|
|
205
|
+
|
|
206
|
+
# Bond Color
|
|
207
|
+
self.bond_color_2d_button = QPushButton()
|
|
208
|
+
self.bond_color_2d_button.setFixedSize(60, 24)
|
|
209
|
+
self.bond_color_2d_button.clicked.connect(self.pick_bond_color_2d)
|
|
210
|
+
form_layout.addRow("Bond Color:", self.bond_color_2d_button)
|
|
211
|
+
|
|
212
|
+
# Bond Width
|
|
213
|
+
self.bond_width_2d_slider = QSlider(Qt.Orientation.Horizontal)
|
|
214
|
+
self.bond_width_2d_slider.setRange(10, 200) # 1.0 - 20.0
|
|
215
|
+
self.bond_width_2d_label = QLabel("2.0")
|
|
216
|
+
self.bond_width_2d_slider.valueChanged.connect(lambda v: self.bond_width_2d_label.setText(f"{v/10:.1f}"))
|
|
217
|
+
bw_layout = QHBoxLayout()
|
|
218
|
+
bw_layout.addWidget(self.bond_width_2d_slider)
|
|
219
|
+
bw_layout.addWidget(self.bond_width_2d_label)
|
|
220
|
+
form_layout.addRow("Bond Width:", bw_layout)
|
|
221
|
+
|
|
222
|
+
# Double Bond Spacing
|
|
223
|
+
self.bond_spacing_double_2d_slider = QSlider(Qt.Orientation.Horizontal)
|
|
224
|
+
self.bond_spacing_double_2d_slider.setRange(10, 200) # 1.0 - 20.0
|
|
225
|
+
self.bond_spacing_double_2d_label = QLabel("3.5")
|
|
226
|
+
self.bond_spacing_double_2d_slider.valueChanged.connect(lambda v: self.bond_spacing_double_2d_label.setText(f"{v/10:.1f}"))
|
|
227
|
+
bsd_layout = QHBoxLayout()
|
|
228
|
+
bsd_layout.addWidget(self.bond_spacing_double_2d_slider)
|
|
229
|
+
bsd_layout.addWidget(self.bond_spacing_double_2d_label)
|
|
230
|
+
form_layout.addRow("Double Bond Spacing:", bsd_layout)
|
|
231
|
+
|
|
232
|
+
# Triple Bond Spacing
|
|
233
|
+
self.bond_spacing_triple_2d_slider = QSlider(Qt.Orientation.Horizontal)
|
|
234
|
+
self.bond_spacing_triple_2d_slider.setRange(10, 200) # 1.0 - 20.0
|
|
235
|
+
self.bond_spacing_triple_2d_label = QLabel("3.5")
|
|
236
|
+
self.bond_spacing_triple_2d_slider.valueChanged.connect(lambda v: self.bond_spacing_triple_2d_label.setText(f"{v/10:.1f}"))
|
|
237
|
+
bst_layout = QHBoxLayout()
|
|
238
|
+
bst_layout.addWidget(self.bond_spacing_triple_2d_slider)
|
|
239
|
+
bst_layout.addWidget(self.bond_spacing_triple_2d_label)
|
|
240
|
+
form_layout.addRow("Triple Bond Spacing:", bst_layout)
|
|
241
|
+
|
|
242
|
+
# Bond Cap Style
|
|
243
|
+
self.bond_cap_style_2d_combo = QComboBox()
|
|
244
|
+
self.bond_cap_style_2d_combo.addItems(['Round', 'Flat', 'Square'])
|
|
245
|
+
form_layout.addRow("Bond Cap Style:", self.bond_cap_style_2d_combo)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
line2 = QFrame()
|
|
249
|
+
line2.setFrameShape(QFrame.Shape.HLine)
|
|
250
|
+
line2.setFrameShadow(QFrame.Shadow.Sunken)
|
|
251
|
+
form_layout.addRow(line2)
|
|
252
|
+
|
|
253
|
+
# --- Atom Settings ---
|
|
254
|
+
form_layout.addRow(QLabel("<b>Atom Settings</b>"))
|
|
255
|
+
|
|
256
|
+
# Font Size
|
|
257
|
+
self.atom_font_size_2d_slider = QSlider(Qt.Orientation.Horizontal)
|
|
258
|
+
self.atom_font_size_2d_slider.setRange(8, 72)
|
|
259
|
+
self.atom_font_size_2d_label = QLabel("20")
|
|
260
|
+
self.atom_font_size_2d_slider.valueChanged.connect(lambda v: self.atom_font_size_2d_label.setText(str(v)))
|
|
261
|
+
fs_layout = QHBoxLayout()
|
|
262
|
+
fs_layout.addWidget(self.atom_font_size_2d_slider)
|
|
263
|
+
fs_layout.addWidget(self.atom_font_size_2d_label)
|
|
264
|
+
form_layout.addRow("Atom Label Font Size:", fs_layout)
|
|
265
|
+
|
|
266
|
+
# Use Bond Color Checkbox
|
|
267
|
+
self.atom_use_bond_color_2d_checkbox = QCheckBox()
|
|
268
|
+
self.atom_use_bond_color_2d_checkbox.setToolTip("If checked, atoms will use the unified Bond Color instead of element-specific colors (CPK).")
|
|
269
|
+
form_layout.addRow("Use Bond Color for Atoms:", self.atom_use_bond_color_2d_checkbox)
|
|
270
|
+
|
|
271
|
+
self.tab_widget.addTab(widget, "2D Settings")
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# Initialize internal variable for combo updates
|
|
276
|
+
# (Usually done in update_ui_from_settings, but we add direct access here for simple binding if needed)
|
|
277
|
+
# We rely on update_ui_from_settings to set current selection.
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def pick_bg_color_2d(self):
|
|
281
|
+
color = QColorDialog.getColor(QColor(self.current_bg_color_2d), self, "Select 2D Background Color")
|
|
282
|
+
if color.isValid():
|
|
283
|
+
self.current_bg_color_2d = color.name()
|
|
284
|
+
self.update_2d_color_buttons()
|
|
285
|
+
|
|
286
|
+
def pick_bond_color_2d(self):
|
|
287
|
+
color = QColorDialog.getColor(QColor(self.current_bond_color_2d), self, "Select 2D Bond Color")
|
|
288
|
+
if color.isValid():
|
|
289
|
+
self.current_bond_color_2d = color.name()
|
|
290
|
+
self.update_2d_color_buttons()
|
|
291
|
+
|
|
292
|
+
def update_2d_color_buttons(self):
|
|
293
|
+
try:
|
|
294
|
+
self.bg_color_2d_button.setStyleSheet(f"background-color: {self.current_bg_color_2d}; border: 1px solid #888;")
|
|
295
|
+
self.bond_color_2d_button.setStyleSheet(f"background-color: {self.current_bond_color_2d}; border: 1px solid #888;")
|
|
296
|
+
except Exception:
|
|
297
|
+
pass
|
|
163
298
|
|
|
164
299
|
def create_scene_tab(self):
|
|
165
300
|
"""基本設定タブを作成"""
|
|
@@ -217,7 +352,7 @@ class SettingsDialog(QDialog):
|
|
|
217
352
|
self.projection_combo.setToolTip("Choose camera projection mode: Perspective (default) or Orthographic")
|
|
218
353
|
form_layout.addRow("Projection Mode:", self.projection_combo)
|
|
219
354
|
|
|
220
|
-
self.tab_widget.addTab(scene_widget, "Scene")
|
|
355
|
+
self.tab_widget.addTab(scene_widget, "3D Scene")
|
|
221
356
|
|
|
222
357
|
def create_other_tab(self):
|
|
223
358
|
"""other設定タブを作成"""
|
|
@@ -643,11 +778,22 @@ class SettingsDialog(QDialog):
|
|
|
643
778
|
tab_name = self.tab_widget.tabText(current_tab_index)
|
|
644
779
|
|
|
645
780
|
# 各タブの設定項目を定義
|
|
646
|
-
#
|
|
781
|
+
# Each tab settings
|
|
782
|
+
# Note: tab labels must match those added to the QTabWidget ("2D Settings", "Scene", "Ball & Stick", ...
|
|
647
783
|
# "CPK (Space-filling)", "Wireframe", "Stick", "Other"). Use the per-model
|
|
648
784
|
# multi-bond keys present in self.default_settings.
|
|
649
785
|
tab_settings = {
|
|
650
|
-
"
|
|
786
|
+
"2D Settings": {
|
|
787
|
+
'bond_width_2d': self.default_settings['bond_width_2d'],
|
|
788
|
+
'bond_spacing_double_2d': self.default_settings['bond_spacing_double_2d'],
|
|
789
|
+
'bond_spacing_triple_2d': self.default_settings['bond_spacing_triple_2d'],
|
|
790
|
+
'atom_font_size_2d': self.default_settings['atom_font_size_2d'],
|
|
791
|
+
'background_color_2d': self.default_settings['background_color_2d'],
|
|
792
|
+
'bond_color_2d': self.default_settings['bond_color_2d'],
|
|
793
|
+
'atom_use_bond_color_2d': self.default_settings['atom_use_bond_color_2d'],
|
|
794
|
+
'bond_cap_style_2d': self.default_settings['bond_cap_style_2d']
|
|
795
|
+
},
|
|
796
|
+
"3D Scene": {
|
|
651
797
|
'background_color': self.default_settings['background_color'],
|
|
652
798
|
'projection_mode': self.default_settings['projection_mode'],
|
|
653
799
|
'show_3d_axes': self.default_settings['show_3d_axes'],
|
|
@@ -711,6 +857,13 @@ class SettingsDialog(QDialog):
|
|
|
711
857
|
|
|
712
858
|
# UIを更新
|
|
713
859
|
self.update_ui_from_settings(updated_settings)
|
|
860
|
+
|
|
861
|
+
# If 2D settings were reset, update internal color variables too
|
|
862
|
+
if tab_name == "2D Settings":
|
|
863
|
+
self.current_bg_color_2d = updated_settings.get('background_color_2d', self.default_settings['background_color_2d'])
|
|
864
|
+
self.current_bond_color_2d = updated_settings.get('bond_color_2d', self.default_settings['bond_color_2d'])
|
|
865
|
+
self.update_2d_color_buttons()
|
|
866
|
+
|
|
714
867
|
# CPK tab: do not change parent/settings immediately; let Apply/OK persist any changes
|
|
715
868
|
|
|
716
869
|
# ユーザーへのフィードバック
|
|
@@ -748,7 +901,9 @@ class SettingsDialog(QDialog):
|
|
|
748
901
|
if 'cpk_colors' in self.parent_window.settings:
|
|
749
902
|
# Reset to defaults (empty override dict)
|
|
750
903
|
self.parent_window.settings['cpk_colors'] = {}
|
|
751
|
-
|
|
904
|
+
|
|
905
|
+
# Reset 2D Settings (colors need manual refresh in parent scene/view usually handled by apply)
|
|
906
|
+
|
|
752
907
|
# Reset 3D Ball & Stick uniform bond color to default
|
|
753
908
|
self.parent_window.settings['ball_stick_bond_color'] = self.default_settings.get('ball_stick_bond_color', '#7F7F7F')
|
|
754
909
|
# Update global CPK colors and reapply 3D settings immediately
|
|
@@ -1063,9 +1218,17 @@ class SettingsDialog(QDialog):
|
|
|
1063
1218
|
'aromatic_torus_thickness_factor': self.aromatic_torus_thickness_slider.value() / 100.0,
|
|
1064
1219
|
'skip_chemistry_checks': self.skip_chem_checks_checkbox.isChecked(),
|
|
1065
1220
|
'always_ask_charge': self.always_ask_charge_checkbox.isChecked(),
|
|
1066
|
-
# Ball & Stick bond color (3D grey/uniform color)
|
|
1067
1221
|
'ball_stick_bond_color': getattr(self, 'bs_bond_color', self.default_settings.get('ball_stick_bond_color', '#7F7F7F')),
|
|
1068
1222
|
'ball_stick_use_cpk_bond_color': self.bs_use_cpk_bond_checkbox.isChecked(),
|
|
1223
|
+
# 2D Settings
|
|
1224
|
+
'bond_width_2d': self.bond_width_2d_slider.value() / 10.0,
|
|
1225
|
+
'bond_spacing_double_2d': self.bond_spacing_double_2d_slider.value() / 10.0,
|
|
1226
|
+
'bond_spacing_triple_2d': self.bond_spacing_triple_2d_slider.value() / 10.0,
|
|
1227
|
+
'atom_font_size_2d': self.atom_font_size_2d_slider.value(),
|
|
1228
|
+
'background_color_2d': self.current_bg_color_2d,
|
|
1229
|
+
'bond_color_2d': self.current_bond_color_2d,
|
|
1230
|
+
'atom_use_bond_color_2d': self.atom_use_bond_color_2d_checkbox.isChecked(),
|
|
1231
|
+
'bond_cap_style_2d': self.bond_cap_style_2d_combo.currentText(),
|
|
1069
1232
|
}
|
|
1070
1233
|
|
|
1071
1234
|
def pick_bs_bond_color(self):
|
|
@@ -1119,6 +1282,27 @@ class SettingsDialog(QDialog):
|
|
|
1119
1282
|
# 現在の分子を再描画(設定変更を反映)
|
|
1120
1283
|
if hasattr(self.parent_window, 'current_mol') and self.parent_window.current_mol:
|
|
1121
1284
|
self.parent_window.draw_molecule_3d(self.parent_window.current_mol)
|
|
1285
|
+
|
|
1286
|
+
# 2Dビューの設定適用 (背景色、結合スタイルなど)
|
|
1287
|
+
# update_style() will read the new settings from parent_window.settings
|
|
1288
|
+
try:
|
|
1289
|
+
if hasattr(self.parent_window, 'scene') and self.parent_window.scene:
|
|
1290
|
+
# Update Background
|
|
1291
|
+
bg_col_2d = self.parent_window.settings.get('background_color_2d', '#FFFFFF')
|
|
1292
|
+
self.parent_window.scene.setBackgroundBrush(QColor(bg_col_2d))
|
|
1293
|
+
|
|
1294
|
+
# Update Items
|
|
1295
|
+
for item in self.parent_window.scene.items():
|
|
1296
|
+
if hasattr(item, 'update_style'):
|
|
1297
|
+
item.update_style()
|
|
1298
|
+
elif hasattr(item, 'update'):
|
|
1299
|
+
item.update()
|
|
1300
|
+
|
|
1301
|
+
if hasattr(self.parent_window.view_2d, 'viewport'):
|
|
1302
|
+
self.parent_window.view_2d.viewport().update()
|
|
1303
|
+
except Exception:
|
|
1304
|
+
pass
|
|
1305
|
+
|
|
1122
1306
|
# ステータスバーに適用完了を表示
|
|
1123
1307
|
self.parent_window.statusBar().showMessage("Settings applied successfully")
|
|
1124
1308
|
|
|
@@ -1147,3 +1331,173 @@ class SettingsDialog(QDialog):
|
|
|
1147
1331
|
# apply_settingsを呼び出して設定を適用
|
|
1148
1332
|
self.apply_settings()
|
|
1149
1333
|
super().accept()
|
|
1334
|
+
|
|
1335
|
+
def update_ui_from_settings(self, settings_dict):
|
|
1336
|
+
"""設定辞書に基づいてUIを更新"""
|
|
1337
|
+
# 1. Scene settings
|
|
1338
|
+
self.current_bg_color = settings_dict.get('background_color', self.default_settings['background_color'])
|
|
1339
|
+
self.update_color_button(self.current_bg_color)
|
|
1340
|
+
|
|
1341
|
+
self.axes_checkbox.setChecked(settings_dict.get('show_3d_axes', self.default_settings['show_3d_axes']))
|
|
1342
|
+
self.light_checkbox.setChecked(settings_dict.get('lighting_enabled', self.default_settings['lighting_enabled']))
|
|
1343
|
+
|
|
1344
|
+
intensity = settings_dict.get('light_intensity', self.default_settings['light_intensity'])
|
|
1345
|
+
self.intensity_slider.setValue(int(intensity * 100))
|
|
1346
|
+
self.intensity_label.setText(f"{intensity:.2f}")
|
|
1347
|
+
|
|
1348
|
+
specular = settings_dict.get('specular', self.default_settings['specular'])
|
|
1349
|
+
self.specular_slider.setValue(int(specular * 100))
|
|
1350
|
+
self.specular_label.setText(f"{specular:.2f}")
|
|
1351
|
+
|
|
1352
|
+
spec_power = settings_dict.get('specular_power', self.default_settings['specular_power'])
|
|
1353
|
+
self.spec_power_slider.setValue(int(spec_power))
|
|
1354
|
+
self.spec_power_label.setText(str(spec_power))
|
|
1355
|
+
|
|
1356
|
+
proj_mode = settings_dict.get('projection_mode', self.default_settings['projection_mode'])
|
|
1357
|
+
idx = self.projection_combo.findText(proj_mode)
|
|
1358
|
+
if idx >= 0:
|
|
1359
|
+
self.projection_combo.setCurrentIndex(idx)
|
|
1360
|
+
|
|
1361
|
+
# 2. Ball & Stick settings
|
|
1362
|
+
bs_atom_scale = settings_dict.get('ball_stick_atom_scale', self.default_settings['ball_stick_atom_scale'])
|
|
1363
|
+
self.bs_atom_scale_slider.setValue(int(bs_atom_scale * 100))
|
|
1364
|
+
self.bs_atom_scale_label.setText(f"{bs_atom_scale:.2f}")
|
|
1365
|
+
|
|
1366
|
+
bs_bond_radius = settings_dict.get('ball_stick_bond_radius', self.default_settings['ball_stick_bond_radius'])
|
|
1367
|
+
self.bs_bond_radius_slider.setValue(int(bs_bond_radius * 100))
|
|
1368
|
+
self.bs_bond_radius_label.setText(f"{bs_bond_radius:.2f}")
|
|
1369
|
+
|
|
1370
|
+
# Multi-bond offsets (Ball & Stick)
|
|
1371
|
+
bs_db_offset = settings_dict.get('ball_stick_double_bond_offset_factor', self.default_settings.get('ball_stick_double_bond_offset_factor', 2.0))
|
|
1372
|
+
self.bs_double_offset_slider.setValue(int(bs_db_offset * 100))
|
|
1373
|
+
self.bs_double_offset_label.setText(f"{bs_db_offset:.2f}")
|
|
1374
|
+
|
|
1375
|
+
bs_tr_offset = settings_dict.get('ball_stick_triple_bond_offset_factor', self.default_settings.get('ball_stick_triple_bond_offset_factor', 2.0))
|
|
1376
|
+
self.bs_triple_offset_slider.setValue(int(bs_tr_offset * 100))
|
|
1377
|
+
self.bs_triple_offset_label.setText(f"{bs_tr_offset:.2f}")
|
|
1378
|
+
|
|
1379
|
+
bs_db_rad = settings_dict.get('ball_stick_double_bond_radius_factor', self.default_settings.get('ball_stick_double_bond_radius_factor', 0.8))
|
|
1380
|
+
self.bs_double_radius_slider.setValue(int(bs_db_rad * 100))
|
|
1381
|
+
self.bs_double_radius_label.setText(f"{bs_db_rad:.2f}")
|
|
1382
|
+
|
|
1383
|
+
bs_tr_rad = settings_dict.get('ball_stick_triple_bond_radius_factor', self.default_settings.get('ball_stick_triple_bond_radius_factor', 0.75))
|
|
1384
|
+
self.bs_triple_radius_slider.setValue(int(bs_tr_rad * 100))
|
|
1385
|
+
self.bs_triple_radius_label.setText(f"{bs_tr_rad:.2f}")
|
|
1386
|
+
|
|
1387
|
+
bs_res = settings_dict.get('ball_stick_resolution', self.default_settings['ball_stick_resolution'])
|
|
1388
|
+
self.bs_resolution_slider.setValue(int(bs_res))
|
|
1389
|
+
self.bs_resolution_label.setText(str(bs_res))
|
|
1390
|
+
|
|
1391
|
+
# Ball & Stick bond color
|
|
1392
|
+
self.bs_bond_color = settings_dict.get('ball_stick_bond_color', self.default_settings.get('ball_stick_bond_color', '#7F7F7F'))
|
|
1393
|
+
try:
|
|
1394
|
+
self.bs_bond_color_button.setStyleSheet(f"background-color: {self.bs_bond_color}; border: 1px solid #888;")
|
|
1395
|
+
self.bs_bond_color_button.setToolTip(self.bs_bond_color)
|
|
1396
|
+
except Exception:
|
|
1397
|
+
pass
|
|
1398
|
+
|
|
1399
|
+
self.bs_use_cpk_bond_checkbox.setChecked(settings_dict.get('ball_stick_use_cpk_bond_color', self.default_settings.get('ball_stick_use_cpk_bond_color', False)))
|
|
1400
|
+
|
|
1401
|
+
# 3. CPK settings
|
|
1402
|
+
cpk_atom_scale = settings_dict.get('cpk_atom_scale', self.default_settings['cpk_atom_scale'])
|
|
1403
|
+
self.cpk_atom_scale_slider.setValue(int(cpk_atom_scale * 100))
|
|
1404
|
+
self.cpk_atom_scale_label.setText(f"{cpk_atom_scale:.2f}")
|
|
1405
|
+
|
|
1406
|
+
cpk_res = settings_dict.get('cpk_resolution', self.default_settings['cpk_resolution'])
|
|
1407
|
+
self.cpk_resolution_slider.setValue(int(cpk_res))
|
|
1408
|
+
self.cpk_resolution_label.setText(str(cpk_res))
|
|
1409
|
+
|
|
1410
|
+
# 4. Wireframe settings
|
|
1411
|
+
wf_bond_radius = settings_dict.get('wireframe_bond_radius', self.default_settings['wireframe_bond_radius'])
|
|
1412
|
+
self.wf_bond_radius_slider.setValue(int(wf_bond_radius * 100))
|
|
1413
|
+
self.wf_bond_radius_label.setText(f"{wf_bond_radius:.2f}")
|
|
1414
|
+
|
|
1415
|
+
wf_res = settings_dict.get('wireframe_resolution', self.default_settings['wireframe_resolution'])
|
|
1416
|
+
self.wf_resolution_slider.setValue(int(wf_res))
|
|
1417
|
+
self.wf_resolution_label.setText(str(wf_res))
|
|
1418
|
+
|
|
1419
|
+
# Multi-bond offsets (Wireframe)
|
|
1420
|
+
wf_db_offset = settings_dict.get('wireframe_double_bond_offset_factor', self.default_settings.get('wireframe_double_bond_offset_factor', 3.0))
|
|
1421
|
+
self.wf_double_offset_slider.setValue(int(wf_db_offset * 100))
|
|
1422
|
+
self.wf_double_offset_label.setText(f"{wf_db_offset:.2f}")
|
|
1423
|
+
|
|
1424
|
+
wf_tr_offset = settings_dict.get('wireframe_triple_bond_offset_factor', self.default_settings.get('wireframe_triple_bond_offset_factor', 3.0))
|
|
1425
|
+
self.wf_triple_offset_slider.setValue(int(wf_tr_offset * 100))
|
|
1426
|
+
self.wf_triple_offset_label.setText(f"{wf_tr_offset:.2f}")
|
|
1427
|
+
|
|
1428
|
+
wf_db_rad = settings_dict.get('wireframe_double_bond_radius_factor', self.default_settings.get('wireframe_double_bond_radius_factor', 0.8))
|
|
1429
|
+
self.wf_double_radius_slider.setValue(int(wf_db_rad * 100))
|
|
1430
|
+
self.wf_double_radius_label.setText(f"{wf_db_rad:.2f}")
|
|
1431
|
+
|
|
1432
|
+
wf_tr_rad = settings_dict.get('wireframe_triple_bond_radius_factor', self.default_settings.get('wireframe_triple_bond_radius_factor', 0.75))
|
|
1433
|
+
self.wf_triple_radius_slider.setValue(int(wf_tr_rad * 100))
|
|
1434
|
+
self.wf_triple_radius_label.setText(f"{wf_tr_rad:.2f}")
|
|
1435
|
+
|
|
1436
|
+
# 5. Stick settings
|
|
1437
|
+
stick_bond_radius = settings_dict.get('stick_bond_radius', self.default_settings['stick_bond_radius'])
|
|
1438
|
+
self.stick_bond_radius_slider.setValue(int(stick_bond_radius * 100))
|
|
1439
|
+
self.stick_bond_radius_label.setText(f"{stick_bond_radius:.2f}")
|
|
1440
|
+
|
|
1441
|
+
stick_res = settings_dict.get('stick_resolution', self.default_settings['stick_resolution'])
|
|
1442
|
+
self.stick_resolution_slider.setValue(int(stick_res))
|
|
1443
|
+
self.stick_resolution_label.setText(str(stick_res))
|
|
1444
|
+
|
|
1445
|
+
# Multi-bond offsets (Stick)
|
|
1446
|
+
stick_db_offset = settings_dict.get('stick_double_bond_offset_factor', self.default_settings.get('stick_double_bond_offset_factor', 1.5))
|
|
1447
|
+
self.stick_double_offset_slider.setValue(int(stick_db_offset * 100))
|
|
1448
|
+
self.stick_double_offset_label.setText(f"{stick_db_offset:.2f}")
|
|
1449
|
+
|
|
1450
|
+
stick_tr_offset = settings_dict.get('stick_triple_bond_offset_factor', self.default_settings.get('stick_triple_bond_offset_factor', 1.0))
|
|
1451
|
+
self.stick_triple_offset_slider.setValue(int(stick_tr_offset * 100))
|
|
1452
|
+
self.stick_triple_offset_label.setText(f"{stick_tr_offset:.2f}")
|
|
1453
|
+
|
|
1454
|
+
stick_db_rad = settings_dict.get('stick_double_bond_radius_factor', self.default_settings.get('stick_double_bond_radius_factor', 0.6))
|
|
1455
|
+
self.stick_double_radius_slider.setValue(int(stick_db_rad * 100))
|
|
1456
|
+
self.stick_double_radius_label.setText(f"{stick_db_rad:.2f}")
|
|
1457
|
+
|
|
1458
|
+
stick_tr_rad = settings_dict.get('stick_triple_bond_radius_factor', self.default_settings.get('stick_triple_bond_radius_factor', 0.4))
|
|
1459
|
+
self.stick_triple_radius_slider.setValue(int(stick_tr_rad * 100))
|
|
1460
|
+
self.stick_triple_radius_label.setText(f"{stick_tr_rad:.2f}")
|
|
1461
|
+
|
|
1462
|
+
# 6. Other settings
|
|
1463
|
+
self.skip_chem_checks_checkbox.setChecked(settings_dict.get('skip_chemistry_checks', self.default_settings.get('skip_chemistry_checks', False)))
|
|
1464
|
+
self.kekule_3d_checkbox.setChecked(settings_dict.get('display_kekule_3d', self.default_settings.get('display_kekule_3d', False)))
|
|
1465
|
+
# always ask for charge on XYZ imports
|
|
1466
|
+
self.always_ask_charge_checkbox.setChecked(settings_dict.get('always_ask_charge', self.default_settings.get('always_ask_charge', False)))
|
|
1467
|
+
# Aromatic ring circle display and torus thickness factor
|
|
1468
|
+
self.aromatic_circle_checkbox.setChecked(settings_dict.get('display_aromatic_circles_3d', self.default_settings.get('display_aromatic_circles_3d', False)))
|
|
1469
|
+
thickness_factor = float(settings_dict.get('aromatic_torus_thickness_factor', self.default_settings.get('aromatic_torus_thickness_factor', 0.6)))
|
|
1470
|
+
try:
|
|
1471
|
+
self.aromatic_torus_thickness_slider.setValue(int(thickness_factor * 100))
|
|
1472
|
+
self.aromatic_torus_thickness_label.setText(f"{thickness_factor:.1f}")
|
|
1473
|
+
except Exception:
|
|
1474
|
+
pass
|
|
1475
|
+
|
|
1476
|
+
# 7. 2D Settings
|
|
1477
|
+
bw_2d = settings_dict.get('bond_width_2d', self.default_settings['bond_width_2d'])
|
|
1478
|
+
self.bond_width_2d_slider.setValue(int(bw_2d * 10))
|
|
1479
|
+
self.bond_width_2d_label.setText(f"{bw_2d:.1f}")
|
|
1480
|
+
|
|
1481
|
+
bsd_2d = settings_dict.get('bond_spacing_double_2d', self.default_settings['bond_spacing_double_2d'])
|
|
1482
|
+
self.bond_spacing_double_2d_slider.setValue(int(bsd_2d * 10))
|
|
1483
|
+
self.bond_spacing_double_2d_label.setText(f"{bsd_2d:.1f}")
|
|
1484
|
+
|
|
1485
|
+
bst_2d = settings_dict.get('bond_spacing_triple_2d', self.default_settings['bond_spacing_triple_2d'])
|
|
1486
|
+
self.bond_spacing_triple_2d_slider.setValue(int(bst_2d * 10))
|
|
1487
|
+
self.bond_spacing_triple_2d_label.setText(f"{bst_2d:.1f}")
|
|
1488
|
+
|
|
1489
|
+
fs_2d = settings_dict.get('atom_font_size_2d', self.default_settings['atom_font_size_2d'])
|
|
1490
|
+
self.atom_font_size_2d_slider.setValue(int(fs_2d))
|
|
1491
|
+
self.atom_font_size_2d_label.setText(str(fs_2d))
|
|
1492
|
+
|
|
1493
|
+
self.atom_use_bond_color_2d_checkbox.setChecked(settings_dict.get('atom_use_bond_color_2d', self.default_settings.get('atom_use_bond_color_2d', False)))
|
|
1494
|
+
|
|
1495
|
+
self.current_bg_color_2d = settings_dict.get('background_color_2d', self.default_settings['background_color_2d'])
|
|
1496
|
+
|
|
1497
|
+
# Load Bond Cap Style
|
|
1498
|
+
cap_style = settings_dict.get('bond_cap_style_2d', self.default_settings.get('bond_cap_style_2d', 'Round'))
|
|
1499
|
+
index = self.bond_cap_style_2d_combo.findText(cap_style)
|
|
1500
|
+
if index >= 0:
|
|
1501
|
+
self.bond_cap_style_2d_combo.setCurrentIndex(index)
|
|
1502
|
+
self.current_bond_color_2d = settings_dict.get('bond_color_2d', self.default_settings['bond_color_2d'])
|
|
1503
|
+
self.update_2d_color_buttons()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
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
|
|
@@ -7,25 +7,25 @@ moleditpy_linux/modules/align_plane_dialog.py,sha256=SEC32l8z2x1W1Sf1Gu001OQEtin
|
|
|
7
7
|
moleditpy_linux/modules/alignment_dialog.py,sha256=CPubSJI52mNSXmWt7oKQ2un5lXnN8_K4Z-LMM7wWTxQ,11309
|
|
8
8
|
moleditpy_linux/modules/analysis_window.py,sha256=zjP5ipSTpKw8oLr1eKdoxW8Bk1SslGlPqsVucD-x_5w,9403
|
|
9
9
|
moleditpy_linux/modules/angle_dialog.py,sha256=uc2WbvSfRe892xoEirqpZ78pf2Smwzkinkso6zLWr0Y,17751
|
|
10
|
-
moleditpy_linux/modules/atom_item.py,sha256=
|
|
11
|
-
moleditpy_linux/modules/bond_item.py,sha256=
|
|
10
|
+
moleditpy_linux/modules/atom_item.py,sha256=zPV6AO0Je4rKgZekyYCGehucleKP21ALDsjVhGV8n-M,17738
|
|
11
|
+
moleditpy_linux/modules/bond_item.py,sha256=hOwga7DcxZf8zxwZr8F7viTNgEi_9wftKFgSpROUJs8,21602
|
|
12
12
|
moleditpy_linux/modules/bond_length_dialog.py,sha256=6bFPGssnqlgINuqpxLv-OhjMH3_hspnaH8QtorAyu2M,14782
|
|
13
13
|
moleditpy_linux/modules/calculation_worker.py,sha256=KiGQY7i-QCQofEoE0r65KoQgpEGFcbhmxWv6egfkUdc,42324
|
|
14
14
|
moleditpy_linux/modules/color_settings_dialog.py,sha256=Ow44BhCOLo0AFb6klO001k6B4drOgKX9DeNBQhZLp5o,15474
|
|
15
|
-
moleditpy_linux/modules/constants.py,sha256=
|
|
15
|
+
moleditpy_linux/modules/constants.py,sha256=hrpODQcypcLqXV8--0NiGgWRyWgEKcS6ju3Q-2RBY1w,4702
|
|
16
16
|
moleditpy_linux/modules/constrained_optimization_dialog.py,sha256=REsk4ePsqNmAGPMTS_jckeM7jexrU3krwun8sKqKUCs,30062
|
|
17
17
|
moleditpy_linux/modules/custom_interactor_style.py,sha256=LDNODMJoNHGe1AUSrvqv6PdeJm-hpPmSpWINppnJLt0,38942
|
|
18
18
|
moleditpy_linux/modules/custom_qt_interactor.py,sha256=vCZsDfRO-FtphD5cTP7Ps-5rpHZMIGloaoe6EaKzrsw,4139
|
|
19
19
|
moleditpy_linux/modules/dialog3_d_picking_mixin.py,sha256=z4udbkiX9PYmIGazPXsbftkk_oRRwZhcvlCqbyJzr24,6493
|
|
20
20
|
moleditpy_linux/modules/dihedral_dialog.py,sha256=bOTDO6-b74vEDn_z6OyuBr5cRz3RnRj83PiaEBUyWJA,18002
|
|
21
|
-
moleditpy_linux/modules/main_window.py,sha256=
|
|
21
|
+
moleditpy_linux/modules/main_window.py,sha256=s5O-9B2MDrRg1OrXtq7rVtnqaQ9arWItGZ4Wgbn87SQ,36504
|
|
22
22
|
moleditpy_linux/modules/main_window_app_state.py,sha256=8YDcGNCSpLTO1NGL9tEvNkXpUcS7JW-uK7TdUGvEqnk,35189
|
|
23
23
|
moleditpy_linux/modules/main_window_compute.py,sha256=ipIkhH_DONXDnPzh7xeym9X-Yfx8EhsvXYOdyxsAj4c,53347
|
|
24
24
|
moleditpy_linux/modules/main_window_dialog_manager.py,sha256=QR96LqHAPSOShXbc9cK-Ffq8a16JrXAoMKB0pHjESrQ,20072
|
|
25
25
|
moleditpy_linux/modules/main_window_edit_3d.py,sha256=CUArB5wcsgq1C7LygAEC6URlbnn4RhRYDa5n-Y-etWI,19731
|
|
26
|
-
moleditpy_linux/modules/main_window_edit_actions.py,sha256=
|
|
27
|
-
moleditpy_linux/modules/main_window_export.py,sha256=
|
|
28
|
-
moleditpy_linux/modules/main_window_main_init.py,sha256=
|
|
26
|
+
moleditpy_linux/modules/main_window_edit_actions.py,sha256=jjMBwCzwflEHHvf_zh_RBcup9ceR_H4dDEvdRrb6wno,69009
|
|
27
|
+
moleditpy_linux/modules/main_window_export.py,sha256=YVrcFaY9xffFJ6eEH6Omh8Zif8KIs6_VDW_EAzN97AA,38218
|
|
28
|
+
moleditpy_linux/modules/main_window_main_init.py,sha256=Qkpb2AvMADmQmdZ1190ufQ3OWwvcQTwu440riyBn9vg,94148
|
|
29
29
|
moleditpy_linux/modules/main_window_molecular_parsers.py,sha256=KR6vzuqc3nutOcorpYr0QOyX3MFBcxTwDhZX96VgJ9Q,48291
|
|
30
30
|
moleditpy_linux/modules/main_window_project_io.py,sha256=TWwtuKDuvgcvPZ9IGmW8r1EJJOrgxrIJRnxe_f4C1oM,17149
|
|
31
31
|
moleditpy_linux/modules/main_window_string_importers.py,sha256=v47wOd4RtjKYcF-aLP-mogGGdYTpTEo3dDyAu79_5MM,10782
|
|
@@ -38,10 +38,10 @@ moleditpy_linux/modules/molecule_scene.py,sha256=khdt7h9Mk_D1cMbYeHGtq7P9aFXo0xG
|
|
|
38
38
|
moleditpy_linux/modules/move_group_dialog.py,sha256=Fyuy3Uq1KsFsk9qR96r_FxPbAM_-zSfW2dsMQGv7btc,27276
|
|
39
39
|
moleditpy_linux/modules/periodic_table_dialog.py,sha256=ItEZUts1XCietz9paY-spvbzxh6SXak3GnikwqkHZCw,4006
|
|
40
40
|
moleditpy_linux/modules/planarize_dialog.py,sha256=eaqI1MpF35e-VUMpJATt-EtGG5FhcSUlbAenUaFGabY,8593
|
|
41
|
-
moleditpy_linux/modules/plugin_interface.py,sha256=
|
|
42
|
-
moleditpy_linux/modules/plugin_manager.py,sha256=
|
|
41
|
+
moleditpy_linux/modules/plugin_interface.py,sha256=JfobFdAOLp5OnyJp3BNsWnpmZNJYypWQHNVNT0fP1N8,8171
|
|
42
|
+
moleditpy_linux/modules/plugin_manager.py,sha256=ZFQz8VlCy1_IHX7DnMro7iRbouB_rxZQowfrKuZ76G8,21133
|
|
43
43
|
moleditpy_linux/modules/plugin_manager_window.py,sha256=b4kEv0DaWHZG76ZaFTOxn6CVtA62_0MpPYYr10ehCtA,12544
|
|
44
|
-
moleditpy_linux/modules/settings_dialog.py,sha256=
|
|
44
|
+
moleditpy_linux/modules/settings_dialog.py,sha256=kT1c4INl0EOlazDRv1WZbpg2AHEPfworyq8BO-6z79k,85511
|
|
45
45
|
moleditpy_linux/modules/template_preview_item.py,sha256=djdq3tz73d_fJGOvai3E-V9Hk9q9ZW7skx7BV59mooA,6556
|
|
46
46
|
moleditpy_linux/modules/template_preview_view.py,sha256=4OCHZDO51BvJpKdfrBWJ4_4WfLfFSKxsVIyf7I-Kj2E,3350
|
|
47
47
|
moleditpy_linux/modules/translation_dialog.py,sha256=x_GJsbVk-cj4aN2KgmYWDRUDInFlXezAoYoTvX-OT30,14553
|
|
@@ -51,9 +51,9 @@ moleditpy_linux/modules/assets/file_icon.ico,sha256=yyVj084A7HuMNbV073cE_Ag3Ne40
|
|
|
51
51
|
moleditpy_linux/modules/assets/icon.icns,sha256=wD5R6-Vw7K662tVKhu2E1ImN0oUuyAP4youesEQsn9c,139863
|
|
52
52
|
moleditpy_linux/modules/assets/icon.ico,sha256=RfgFcx7-dHY_2STdsOQCQziY5SNhDr3gPnjO6jzEDPI,147975
|
|
53
53
|
moleditpy_linux/modules/assets/icon.png,sha256=kCFN1WacYIdy0GN6SFEbNA00ef39pCczBnFdkkBI8Bs,147110
|
|
54
|
-
moleditpy_linux-2.
|
|
55
|
-
moleditpy_linux-2.
|
|
56
|
-
moleditpy_linux-2.
|
|
57
|
-
moleditpy_linux-2.
|
|
58
|
-
moleditpy_linux-2.
|
|
59
|
-
moleditpy_linux-2.
|
|
54
|
+
moleditpy_linux-2.4.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
55
|
+
moleditpy_linux-2.4.0.dist-info/METADATA,sha256=PQ4fwQhd4wuV-maVTsucTP_88GLk0EQhZi8UUhw_2P0,60708
|
|
56
|
+
moleditpy_linux-2.4.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
57
|
+
moleditpy_linux-2.4.0.dist-info/entry_points.txt,sha256=-OzipSi__yVwlimNtu3eiRP5t5UMg55Cs0udyhXYiyw,60
|
|
58
|
+
moleditpy_linux-2.4.0.dist-info/top_level.txt,sha256=qyqe-hDYL6CXyin9E5Me5rVl3PG84VqiOjf9bQvfJLs,16
|
|
59
|
+
moleditpy_linux-2.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|