MoleditPy-linux 4.10.0__tar.gz → 4.10.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/PKG-INFO +1 -1
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/pyproject.toml +1 -1
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_manager_window.py +180 -56
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/LICENSE +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/README.md +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/setup.cfg +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/mol_geometry.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/molecular_data.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_manager.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/about_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/analysis_window.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/app_state.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/atom_item.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/atom_picking.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_item.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/chain_mixin.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/compute_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/export_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/io_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window_init.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/preview_molecule.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_cleanup_tab.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/string_importers.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/ui_manager.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/constants.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/default_settings.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/hit_radius.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/suppress_log.py +0 -0
- {moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/system_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.10.
|
|
3
|
+
Version: 4.10.2
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MoleditPy-linux
|
|
3
|
-
Version: 4.10.
|
|
3
|
+
Version: 4.10.2
|
|
4
4
|
Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
|
|
5
5
|
Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -13,17 +13,19 @@ DOI: 10.5281/zenodo.17268532
|
|
|
13
13
|
import logging
|
|
14
14
|
import os
|
|
15
15
|
import shutil
|
|
16
|
-
from typing import Any, Optional
|
|
16
|
+
from typing import Any, Optional, cast
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
from PyQt6.QtCore import Qt, QUrl
|
|
20
20
|
from PyQt6.QtGui import QDesktopServices, QDragEnterEvent, QDropEvent
|
|
21
21
|
from PyQt6.QtWidgets import (
|
|
22
22
|
QAbstractItemView,
|
|
23
|
+
QCheckBox,
|
|
23
24
|
QDialog,
|
|
24
25
|
QHBoxLayout,
|
|
25
26
|
QHeaderView,
|
|
26
27
|
QLabel,
|
|
28
|
+
QLineEdit,
|
|
27
29
|
QMessageBox,
|
|
28
30
|
QPushButton,
|
|
29
31
|
QTableWidget,
|
|
@@ -41,39 +43,68 @@ class PluginManagerWindow(QDialog):
|
|
|
41
43
|
super().__init__(parent)
|
|
42
44
|
self.btn_remove: Any = None
|
|
43
45
|
self.table: Any = None
|
|
46
|
+
self.search_input: Any = None
|
|
44
47
|
self.plugin_manager = plugin_manager
|
|
45
48
|
self._preferences_applied = False
|
|
46
49
|
self.setWindowTitle("Plugin Manager")
|
|
47
|
-
self.resize(
|
|
50
|
+
self.resize(850, 520)
|
|
48
51
|
self.setAcceptDrops(True) # Enable drag & drop for the whole window
|
|
49
52
|
|
|
50
53
|
self.init_ui()
|
|
51
54
|
self.refresh_plugin_list()
|
|
52
55
|
|
|
53
56
|
def init_ui(self) -> None:
|
|
54
|
-
"""Build
|
|
57
|
+
"""Build plugin manager UI with table, buttons, search box, and drop support."""
|
|
55
58
|
layout = QVBoxLayout(self)
|
|
56
59
|
|
|
57
|
-
lbl_info = QLabel(
|
|
60
|
+
lbl_info = QLabel(
|
|
61
|
+
"Drag & Drop .py or .zip files to install plugins. Use checkboxes to enable/disable."
|
|
62
|
+
)
|
|
58
63
|
lbl_info.setStyleSheet("color: gray; font-style: italic;")
|
|
59
64
|
layout.addWidget(lbl_info)
|
|
60
65
|
|
|
66
|
+
# Search Box
|
|
67
|
+
search_layout = QHBoxLayout()
|
|
68
|
+
search_label = QLabel("Search:")
|
|
69
|
+
self.search_input = QLineEdit()
|
|
70
|
+
self.search_input.setPlaceholderText(
|
|
71
|
+
"Search plugins by name, author, location, or description..."
|
|
72
|
+
)
|
|
73
|
+
self.search_input.setClearButtonEnabled(True)
|
|
74
|
+
self.search_input.textChanged.connect(self.filter_plugins)
|
|
75
|
+
search_layout.addWidget(search_label)
|
|
76
|
+
search_layout.addWidget(self.search_input)
|
|
77
|
+
layout.addLayout(search_layout)
|
|
78
|
+
|
|
61
79
|
# Plugin Table
|
|
62
80
|
self.table = QTableWidget()
|
|
63
|
-
self.table.setColumnCount(
|
|
81
|
+
self.table.setColumnCount(7)
|
|
64
82
|
self.table.setHorizontalHeaderLabels(
|
|
65
|
-
[
|
|
83
|
+
[
|
|
84
|
+
"Enabled",
|
|
85
|
+
"Status",
|
|
86
|
+
"Name",
|
|
87
|
+
"Version",
|
|
88
|
+
"Author",
|
|
89
|
+
"Location",
|
|
90
|
+
"Description",
|
|
91
|
+
]
|
|
66
92
|
)
|
|
67
93
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
68
94
|
QHeaderView.ResizeMode.Interactive
|
|
69
95
|
)
|
|
70
96
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
71
|
-
|
|
97
|
+
0, QHeaderView.ResizeMode.ResizeToContents
|
|
72
98
|
)
|
|
73
99
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
74
|
-
5, QHeaderView.ResizeMode.
|
|
100
|
+
5, QHeaderView.ResizeMode.Interactive
|
|
101
|
+
)
|
|
102
|
+
self.table.horizontalHeader().setSectionResizeMode(
|
|
103
|
+
6, QHeaderView.ResizeMode.Stretch
|
|
75
104
|
) # Description stretches
|
|
76
|
-
self.table.setColumnWidth(
|
|
105
|
+
self.table.setColumnWidth(0, 70) # Enabled checkbox
|
|
106
|
+
self.table.setColumnWidth(1, 100) # Status
|
|
107
|
+
self.table.setColumnWidth(2, 180) # Name
|
|
77
108
|
self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
|
78
109
|
self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
|
79
110
|
self.table.itemSelectionChanged.connect(self.update_button_state)
|
|
@@ -111,6 +142,20 @@ class PluginManagerWindow(QDialog):
|
|
|
111
142
|
|
|
112
143
|
layout.addLayout(btn_layout)
|
|
113
144
|
|
|
145
|
+
def _create_checkbox_container(
|
|
146
|
+
self, checked: bool, tooltip: str = "Enable or disable this plugin"
|
|
147
|
+
) -> tuple[QWidget, QCheckBox]:
|
|
148
|
+
"""Create a centered QCheckBox container widget without custom stylesheets."""
|
|
149
|
+
container = QWidget()
|
|
150
|
+
box_layout = QHBoxLayout(container)
|
|
151
|
+
box_layout.setContentsMargins(0, 0, 0, 0)
|
|
152
|
+
box_layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
153
|
+
checkbox = QCheckBox()
|
|
154
|
+
checkbox.setChecked(checked)
|
|
155
|
+
checkbox.setToolTip(tooltip)
|
|
156
|
+
box_layout.addWidget(checkbox)
|
|
157
|
+
return container, checkbox
|
|
158
|
+
|
|
114
159
|
def refresh_plugin_list(self) -> None:
|
|
115
160
|
"""Repopulate the plugin table from the current plugin registry."""
|
|
116
161
|
self.table.setRowCount(0)
|
|
@@ -118,20 +163,36 @@ class PluginManagerWindow(QDialog):
|
|
|
118
163
|
|
|
119
164
|
self.table.setRowCount(len(plugins))
|
|
120
165
|
for row, p in enumerate(plugins):
|
|
121
|
-
|
|
166
|
+
# Column 0: Enabled Checkbox (Clean native check, centered)
|
|
167
|
+
is_enabled = not p.get("disabled", False)
|
|
168
|
+
container, _ = self._create_checkbox_container(is_enabled)
|
|
169
|
+
self.table.setCellWidget(row, 0, container)
|
|
170
|
+
|
|
171
|
+
# Store the plugin index in the item's UserRole for stable reference during filtering
|
|
172
|
+
enabled_item = QTableWidgetItem()
|
|
173
|
+
enabled_item.setData(Qt.ItemDataRole.UserRole, row)
|
|
174
|
+
self.table.setItem(row, 0, enabled_item)
|
|
175
|
+
|
|
176
|
+
# Column 1: Status (colored text)
|
|
177
|
+
status = str(p.get("status", "Unknown"))
|
|
178
|
+
status_item = QTableWidgetItem(status)
|
|
122
179
|
status_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
self.table.setItem(row,
|
|
130
|
-
self.table.setItem(row, 1, QTableWidgetItem(str(p.get("name", "Unknown"))))
|
|
131
|
-
self.table.setItem(row, 2, QTableWidgetItem(str(p.get("version", ""))))
|
|
132
|
-
self.table.setItem(row, 3, QTableWidgetItem(str(p.get("author", ""))))
|
|
180
|
+
if status.startswith("Error"):
|
|
181
|
+
status_item.setForeground(Qt.GlobalColor.red)
|
|
182
|
+
elif status == "Loaded":
|
|
183
|
+
status_item.setForeground(Qt.GlobalColor.darkGreen)
|
|
184
|
+
elif status in ("No Entry Point", "Disabled"):
|
|
185
|
+
status_item.setForeground(Qt.GlobalColor.gray)
|
|
186
|
+
self.table.setItem(row, 1, status_item)
|
|
133
187
|
|
|
134
|
-
#
|
|
188
|
+
# Column 2: Name
|
|
189
|
+
self.table.setItem(row, 2, QTableWidgetItem(str(p.get("name", "Unknown"))))
|
|
190
|
+
# Column 3: Version
|
|
191
|
+
self.table.setItem(row, 3, QTableWidgetItem(str(p.get("version", ""))))
|
|
192
|
+
# Column 4: Author
|
|
193
|
+
self.table.setItem(row, 4, QTableWidgetItem(str(p.get("author", ""))))
|
|
194
|
+
|
|
195
|
+
# Column 5: Location (Relative Path)
|
|
135
196
|
full_path = p.get("filepath", "")
|
|
136
197
|
rel_path = ""
|
|
137
198
|
if full_path:
|
|
@@ -141,35 +202,85 @@ class PluginManagerWindow(QDialog):
|
|
|
141
202
|
)
|
|
142
203
|
except (AttributeError, RuntimeError, ValueError, TypeError):
|
|
143
204
|
rel_path = os.path.basename(full_path)
|
|
144
|
-
self.table.setItem(row,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
205
|
+
self.table.setItem(row, 5, QTableWidgetItem(str(rel_path)))
|
|
206
|
+
|
|
207
|
+
# Column 6: Description
|
|
208
|
+
self.table.setItem(row, 6, QTableWidgetItem(str(p.get("description", ""))))
|
|
209
|
+
|
|
210
|
+
if self.search_input and self.search_input.text():
|
|
211
|
+
self.filter_plugins(self.search_input.text())
|
|
212
|
+
|
|
213
|
+
def filter_plugins(self, text: str) -> None:
|
|
214
|
+
"""Filter table rows based on search text."""
|
|
215
|
+
query = text.strip().lower()
|
|
216
|
+
for row in range(self.table.rowCount()):
|
|
217
|
+
if not query:
|
|
218
|
+
self.table.setRowHidden(row, False)
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
# Check status, name, author, location, and description
|
|
222
|
+
status = (
|
|
223
|
+
self.table.item(row, 1).text().lower()
|
|
224
|
+
if self.table.item(row, 1)
|
|
225
|
+
else ""
|
|
226
|
+
)
|
|
227
|
+
name = (
|
|
228
|
+
self.table.item(row, 2).text().lower()
|
|
229
|
+
if self.table.item(row, 2)
|
|
230
|
+
else ""
|
|
231
|
+
)
|
|
232
|
+
author = (
|
|
233
|
+
self.table.item(row, 4).text().lower()
|
|
234
|
+
if self.table.item(row, 4)
|
|
235
|
+
else ""
|
|
236
|
+
)
|
|
237
|
+
location = (
|
|
238
|
+
self.table.item(row, 5).text().lower()
|
|
239
|
+
if self.table.item(row, 5)
|
|
240
|
+
else ""
|
|
241
|
+
)
|
|
242
|
+
description = (
|
|
243
|
+
self.table.item(row, 6).text().lower()
|
|
244
|
+
if self.table.item(row, 6)
|
|
245
|
+
else ""
|
|
246
|
+
)
|
|
157
247
|
|
|
158
|
-
|
|
159
|
-
|
|
248
|
+
match = (
|
|
249
|
+
query in name
|
|
250
|
+
or query in author
|
|
251
|
+
or query in location
|
|
252
|
+
or query in description
|
|
253
|
+
or query in status
|
|
254
|
+
)
|
|
255
|
+
self.table.setRowHidden(row, not match)
|
|
256
|
+
|
|
257
|
+
def _status_checkbox(self, row: int) -> Optional[QCheckBox]:
|
|
258
|
+
"""Return the visible status checkbox for a plugin table row."""
|
|
259
|
+
container = self.table.cellWidget(row, 0)
|
|
260
|
+
if isinstance(container, QCheckBox):
|
|
261
|
+
return container
|
|
262
|
+
if isinstance(container, QWidget):
|
|
263
|
+
checkbox = container.findChild(QCheckBox)
|
|
264
|
+
return checkbox
|
|
265
|
+
return None
|
|
160
266
|
|
|
161
267
|
def _save_checkbox_preferences(self) -> set[str]:
|
|
162
268
|
"""Collect and persist checkbox choices."""
|
|
163
269
|
disabled_paths = set()
|
|
164
|
-
for row
|
|
165
|
-
|
|
166
|
-
if
|
|
167
|
-
|
|
168
|
-
|
|
270
|
+
for row in range(self.table.rowCount()):
|
|
271
|
+
item = self.table.item(row, 0)
|
|
272
|
+
plugin_idx = item.data(Qt.ItemDataRole.UserRole) if item else row
|
|
273
|
+
if plugin_idx is not None and 0 <= plugin_idx < len(
|
|
274
|
+
self.plugin_manager.plugins
|
|
169
275
|
):
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
276
|
+
plugin = self.plugin_manager.plugins[plugin_idx]
|
|
277
|
+
status_checkbox = self._status_checkbox(row)
|
|
278
|
+
if status_checkbox is not None and not status_checkbox.isChecked():
|
|
279
|
+
filepath = plugin.get("filepath")
|
|
280
|
+
if filepath:
|
|
281
|
+
disabled_paths.add(
|
|
282
|
+
self.plugin_manager.plugin_path_key(filepath)
|
|
283
|
+
)
|
|
173
284
|
|
|
174
285
|
self.plugin_manager.save_disabled_plugins(disabled_paths)
|
|
175
286
|
return disabled_paths
|
|
@@ -212,6 +323,19 @@ class PluginManagerWindow(QDialog):
|
|
|
212
323
|
self.plugin_manager.discover_plugins()
|
|
213
324
|
self.refresh_plugin_list()
|
|
214
325
|
|
|
326
|
+
def _plugin_for_row(self, row: int) -> Optional[dict[str, Any]]:
|
|
327
|
+
"""Retrieve plugin dict for a table row, accounting for search filtering."""
|
|
328
|
+
if row < 0 or row >= self.table.rowCount():
|
|
329
|
+
return None
|
|
330
|
+
item = self.table.item(row, 0)
|
|
331
|
+
idx = item.data(Qt.ItemDataRole.UserRole) if item else row
|
|
332
|
+
if idx is not None and 0 <= idx < len(self.plugin_manager.plugins):
|
|
333
|
+
plugin: dict[str, Any] = cast(
|
|
334
|
+
dict[str, Any], self.plugin_manager.plugins[idx]
|
|
335
|
+
)
|
|
336
|
+
return plugin
|
|
337
|
+
return None
|
|
338
|
+
|
|
215
339
|
def on_remove_plugin(self) -> None:
|
|
216
340
|
"""Delete the selected plugin file or folder and reload."""
|
|
217
341
|
row = self.table.currentRow()
|
|
@@ -219,9 +343,8 @@ class PluginManagerWindow(QDialog):
|
|
|
219
343
|
QMessageBox.warning(self, "Warning", "Please select a plugin to remove.")
|
|
220
344
|
return
|
|
221
345
|
|
|
222
|
-
|
|
223
|
-
if
|
|
224
|
-
plugin = self.plugin_manager.plugins[row]
|
|
346
|
+
plugin = self._plugin_for_row(row)
|
|
347
|
+
if plugin is not None:
|
|
225
348
|
filepath = plugin.get("filepath")
|
|
226
349
|
|
|
227
350
|
if filepath and os.path.exists(filepath):
|
|
@@ -266,15 +389,15 @@ class PluginManagerWindow(QDialog):
|
|
|
266
389
|
def show_plugin_details(self, item: QTableWidgetItem) -> None:
|
|
267
390
|
"""Show a message box with full metadata for the double-clicked plugin."""
|
|
268
391
|
row = item.row()
|
|
269
|
-
|
|
270
|
-
|
|
392
|
+
plugin = self._plugin_for_row(row)
|
|
393
|
+
if plugin is not None:
|
|
271
394
|
msg = (
|
|
272
|
-
f"Name: {
|
|
273
|
-
f"Version: {
|
|
274
|
-
f"Author: {
|
|
275
|
-
f"Status: {
|
|
276
|
-
f"Location: {
|
|
277
|
-
f"Description:\n{
|
|
395
|
+
f"Name: {plugin.get('name', 'Unknown')}\n"
|
|
396
|
+
f"Version: {plugin.get('version', 'Unknown')}\n"
|
|
397
|
+
f"Author: {plugin.get('author', 'Unknown')}\n"
|
|
398
|
+
f"Status: {plugin.get('status', 'Unknown')}\n"
|
|
399
|
+
f"Location: {plugin.get('filepath', 'Unknown')}\n\n"
|
|
400
|
+
f"Description:\n{plugin.get('description', 'No description available.')}"
|
|
278
401
|
)
|
|
279
402
|
QMessageBox.information(self, "Plugin Details", msg)
|
|
280
403
|
|
|
@@ -302,7 +425,8 @@ class PluginManagerWindow(QDialog):
|
|
|
302
425
|
is_folder = False
|
|
303
426
|
|
|
304
427
|
if os.path.isfile(file_path):
|
|
305
|
-
# Special handling: If user drops __init__.py,
|
|
428
|
+
# Special handling: If user drops __init__.py,
|
|
429
|
+
# assume they want to install the package (folder)
|
|
306
430
|
if os.path.basename(file_path) == "__init__.py":
|
|
307
431
|
file_path = os.path.dirname(file_path)
|
|
308
432
|
is_valid = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/top_level.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
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/molecular_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/align_plane_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/alignment_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/base_picking_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_length_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/calculation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/color_settings_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_interactor_style.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_qt_interactor.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_actions_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/geometry_base_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window_init.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecular_scene_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_group_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/periodic_table_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/planarize_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/plugin_menu_manager.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/preview_molecule.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/string_importers.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_view.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/translation_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/user_template_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/default_settings.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.0 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|