MoleditPy-linux 4.10.1__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.1 → moleditpy_linux-4.10.2}/PKG-INFO +1 -1
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/pyproject.toml +1 -1
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/PKG-INFO +1 -1
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_manager_window.py +177 -67
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/LICENSE +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/README.md +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/setup.cfg +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/__main__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/file_icon.ico +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.icns +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.ico +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/assets/icon.png +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/mol_geometry.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/core/molecular_data.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/main.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_interface.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_manager.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/about_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/analysis_window.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/app_state.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/atom_item.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/atom_picking.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/base_picking_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_item.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/calculation_worker.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/chain_mixin.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/compute_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_interactor_style.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_qt_interactor.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_actions_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/export_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/io_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window_init.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecular_scene_handler.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecule_scene.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_group_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/planarize_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/plugin_menu_manager.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/preview_molecule.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_cleanup_tab.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/string_importers.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_item.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/translation_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/ui_manager.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/view_3d_logic.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/__init__.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/constants.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/default_settings.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/hit_radius.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
- {moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/suppress_log.py +0 -0
- {moleditpy_linux-4.10.1 → 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,7 +13,7 @@ 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
|
|
@@ -25,6 +25,7 @@ from PyQt6.QtWidgets import (
|
|
|
25
25
|
QHBoxLayout,
|
|
26
26
|
QHeaderView,
|
|
27
27
|
QLabel,
|
|
28
|
+
QLineEdit,
|
|
28
29
|
QMessageBox,
|
|
29
30
|
QPushButton,
|
|
30
31
|
QTableWidget,
|
|
@@ -42,42 +43,68 @@ class PluginManagerWindow(QDialog):
|
|
|
42
43
|
super().__init__(parent)
|
|
43
44
|
self.btn_remove: Any = None
|
|
44
45
|
self.table: Any = None
|
|
46
|
+
self.search_input: Any = None
|
|
45
47
|
self.plugin_manager = plugin_manager
|
|
46
48
|
self._preferences_applied = False
|
|
47
49
|
self.setWindowTitle("Plugin Manager")
|
|
48
|
-
self.resize(
|
|
50
|
+
self.resize(850, 520)
|
|
49
51
|
self.setAcceptDrops(True) # Enable drag & drop for the whole window
|
|
50
52
|
|
|
51
53
|
self.init_ui()
|
|
52
54
|
self.refresh_plugin_list()
|
|
53
55
|
|
|
54
56
|
def init_ui(self) -> None:
|
|
55
|
-
"""Build
|
|
57
|
+
"""Build plugin manager UI with table, buttons, search box, and drop support."""
|
|
56
58
|
layout = QVBoxLayout(self)
|
|
57
59
|
|
|
58
60
|
lbl_info = QLabel(
|
|
59
|
-
"Drag & Drop .py or .zip files
|
|
61
|
+
"Drag & Drop .py or .zip files to install plugins. Use checkboxes to enable/disable."
|
|
60
62
|
)
|
|
61
63
|
lbl_info.setStyleSheet("color: gray; font-style: italic;")
|
|
62
64
|
layout.addWidget(lbl_info)
|
|
63
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
|
+
|
|
64
79
|
# Plugin Table
|
|
65
80
|
self.table = QTableWidget()
|
|
66
|
-
self.table.setColumnCount(
|
|
81
|
+
self.table.setColumnCount(7)
|
|
67
82
|
self.table.setHorizontalHeaderLabels(
|
|
68
|
-
[
|
|
83
|
+
[
|
|
84
|
+
"Enabled",
|
|
85
|
+
"Status",
|
|
86
|
+
"Name",
|
|
87
|
+
"Version",
|
|
88
|
+
"Author",
|
|
89
|
+
"Location",
|
|
90
|
+
"Description",
|
|
91
|
+
]
|
|
69
92
|
)
|
|
70
93
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
71
94
|
QHeaderView.ResizeMode.Interactive
|
|
72
95
|
)
|
|
73
96
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
74
|
-
|
|
97
|
+
0, QHeaderView.ResizeMode.ResizeToContents
|
|
98
|
+
)
|
|
99
|
+
self.table.horizontalHeader().setSectionResizeMode(
|
|
100
|
+
5, QHeaderView.ResizeMode.Interactive
|
|
75
101
|
)
|
|
76
102
|
self.table.horizontalHeader().setSectionResizeMode(
|
|
77
|
-
|
|
103
|
+
6, QHeaderView.ResizeMode.Stretch
|
|
78
104
|
) # Description stretches
|
|
79
|
-
self.table.setColumnWidth(
|
|
80
|
-
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
|
|
81
108
|
self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
|
82
109
|
self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
|
83
110
|
self.table.itemSelectionChanged.connect(self.update_button_state)
|
|
@@ -115,6 +142,20 @@ class PluginManagerWindow(QDialog):
|
|
|
115
142
|
|
|
116
143
|
layout.addLayout(btn_layout)
|
|
117
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
|
+
|
|
118
159
|
def refresh_plugin_list(self) -> None:
|
|
119
160
|
"""Repopulate the plugin table from the current plugin registry."""
|
|
120
161
|
self.table.setRowCount(0)
|
|
@@ -122,22 +163,36 @@ class PluginManagerWindow(QDialog):
|
|
|
122
163
|
|
|
123
164
|
self.table.setRowCount(len(plugins))
|
|
124
165
|
for row, p in enumerate(plugins):
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
self.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
#
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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)
|
|
179
|
+
status_item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
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)
|
|
187
|
+
|
|
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)
|
|
141
196
|
full_path = p.get("filepath", "")
|
|
142
197
|
rel_path = ""
|
|
143
198
|
if full_path:
|
|
@@ -147,43 +202,85 @@ class PluginManagerWindow(QDialog):
|
|
|
147
202
|
)
|
|
148
203
|
except (AttributeError, RuntimeError, ValueError, TypeError):
|
|
149
204
|
rel_path = os.path.basename(full_path)
|
|
150
|
-
self.table.setItem(row,
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
+
)
|
|
167
247
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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)
|
|
172
256
|
|
|
173
257
|
def _status_checkbox(self, row: int) -> Optional[QCheckBox]:
|
|
174
258
|
"""Return the visible status checkbox for a plugin table row."""
|
|
175
|
-
|
|
176
|
-
|
|
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
|
|
177
266
|
|
|
178
267
|
def _save_checkbox_preferences(self) -> set[str]:
|
|
179
268
|
"""Collect and persist checkbox choices."""
|
|
180
269
|
disabled_paths = set()
|
|
181
|
-
for row
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
|
275
|
+
):
|
|
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
|
+
)
|
|
187
284
|
|
|
188
285
|
self.plugin_manager.save_disabled_plugins(disabled_paths)
|
|
189
286
|
return disabled_paths
|
|
@@ -226,6 +323,19 @@ class PluginManagerWindow(QDialog):
|
|
|
226
323
|
self.plugin_manager.discover_plugins()
|
|
227
324
|
self.refresh_plugin_list()
|
|
228
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
|
+
|
|
229
339
|
def on_remove_plugin(self) -> None:
|
|
230
340
|
"""Delete the selected plugin file or folder and reload."""
|
|
231
341
|
row = self.table.currentRow()
|
|
@@ -233,9 +343,8 @@ class PluginManagerWindow(QDialog):
|
|
|
233
343
|
QMessageBox.warning(self, "Warning", "Please select a plugin to remove.")
|
|
234
344
|
return
|
|
235
345
|
|
|
236
|
-
|
|
237
|
-
if
|
|
238
|
-
plugin = self.plugin_manager.plugins[row]
|
|
346
|
+
plugin = self._plugin_for_row(row)
|
|
347
|
+
if plugin is not None:
|
|
239
348
|
filepath = plugin.get("filepath")
|
|
240
349
|
|
|
241
350
|
if filepath and os.path.exists(filepath):
|
|
@@ -280,15 +389,15 @@ class PluginManagerWindow(QDialog):
|
|
|
280
389
|
def show_plugin_details(self, item: QTableWidgetItem) -> None:
|
|
281
390
|
"""Show a message box with full metadata for the double-clicked plugin."""
|
|
282
391
|
row = item.row()
|
|
283
|
-
|
|
284
|
-
|
|
392
|
+
plugin = self._plugin_for_row(row)
|
|
393
|
+
if plugin is not None:
|
|
285
394
|
msg = (
|
|
286
|
-
f"Name: {
|
|
287
|
-
f"Version: {
|
|
288
|
-
f"Author: {
|
|
289
|
-
f"Status: {
|
|
290
|
-
f"Location: {
|
|
291
|
-
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.')}"
|
|
292
401
|
)
|
|
293
402
|
QMessageBox.information(self, "Plugin Details", msg)
|
|
294
403
|
|
|
@@ -316,7 +425,8 @@ class PluginManagerWindow(QDialog):
|
|
|
316
425
|
is_folder = False
|
|
317
426
|
|
|
318
427
|
if os.path.isfile(file_path):
|
|
319
|
-
# Special handling: If user drops __init__.py,
|
|
428
|
+
# Special handling: If user drops __init__.py,
|
|
429
|
+
# assume they want to install the package (folder)
|
|
320
430
|
if os.path.basename(file_path) == "__init__.py":
|
|
321
431
|
file_path = os.path.dirname(file_path)
|
|
322
432
|
is_valid = True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/MoleditPy_linux.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/plugins/plugin_interface.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/align_plane_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/base_picking_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/bond_length_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/calculation_worker.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_interactor_style.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/custom_qt_interactor.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/edit_actions_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/main_window_init.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/molecular_scene_handler.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/move_group_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/periodic_table_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/planarize_dialog.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/plugin_menu_manager.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/preview_molecule.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/string_importers.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_item.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/template_preview_view.py
RENAMED
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/ui/translation_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → 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.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/default_settings.py
RENAMED
|
File without changes
|
|
File without changes
|
{moleditpy_linux-4.10.1 → moleditpy_linux-4.10.2}/src/moleditpy_linux/utils/sip_isdeleted_safe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|