Source code for spinetoolbox.widgets.plugin_manager_widgets

######################################################################################################################
# Copyright (C) 2017-2021 Spine project consortium
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
# any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################

"""
Contains PluginManager dialogs and widgets.

:author: M. Marin (KTH)
:date:   21.2.2021
"""
from PySide2.QtCore import Qt, Slot, Signal, QSortFilterProxyModel, QTimer, QSize
from PySide2.QtWidgets import QDialog, QVBoxLayout, QLineEdit, QListView, QDialogButtonBox
from PySide2.QtGui import QStandardItemModel, QStandardItem
from .custom_qwidgets import ToolBarWidget


[docs]class _InstallPluginModel(QStandardItemModel):
[docs] def data(self, index, role=None): if role == Qt.SizeHintRole: return QSize(0, 40) return super().data(index, role)
[docs]class _ManagePluginsModel(_InstallPluginModel):
[docs] def flags(self, index): return super().flags(index) & ~Qt.ItemIsSelectable
[docs]class InstallPluginDialog(QDialog):
[docs] item_selected = Signal(str)
def __init__(self, parent): """Initialize class""" super().__init__(parent) self.setWindowTitle('Install plugin') QVBoxLayout(self) self._line_edit = QLineEdit(self) self._line_edit.setPlaceholderText("Search registry...") self._list_view = QListView(self) self._model = QSortFilterProxyModel(self) self._source_model = _InstallPluginModel(self) self._model.setSourceModel(self._source_model) self._model.setFilterCaseSensitivity(Qt.CaseInsensitive) self._list_view.setModel(self._model) self._timer = QTimer(self) self._timer.setInterval(200) self._button_box = QDialogButtonBox(self) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.layout().addWidget(self._line_edit) self.layout().addWidget(self._list_view) self.layout().addWidget(self._button_box) self.setAttribute(Qt.WA_DeleteOnClose) self.setMinimumWidth(400) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect(self.close) self._button_box.button(QDialogButtonBox.Ok).clicked.connect(self._handle_ok_clicked) self._list_view.doubleClicked.connect(self._emit_item_selected) self._list_view.selectionModel().selectionChanged.connect(self._update_ok_button_enabled) self._line_edit.textEdited.connect(self._handle_search_text_changed) self._timer.timeout.connect(self._filter_model)
[docs] def populate_list(self, names): for name in names: self._source_model.appendRow(QStandardItem(name))
@Slot(str)
[docs] def _handle_search_text_changed(self, _text): self._timer.start()
[docs] def _filter_model(self): self._model.setFilterRegExp(self._line_edit.text())
@Slot(bool)
[docs] def _handle_ok_clicked(self, _=False): index = self._list_view.currentIndex() self._emit_item_selected(index)
@Slot("QModelIndex")
[docs] def _emit_item_selected(self, index): if not index.isValid(): return self.item_selected.emit(index.data(Qt.DisplayRole)) self.close()
@Slot("QItemSelection", "QItemSelection")
[docs] def _update_ok_button_enabled(self, _selected, _deselected): on = self._list_view.selectionModel().hasSelection() self._button_box.button(QDialogButtonBox.Ok).setEnabled(on)
[docs]class ManagePluginsDialog(QDialog):
[docs] item_removed = Signal(str)
[docs] item_updated = Signal(str)
def __init__(self, parent): """Initialize class""" super().__init__(parent) self.setWindowTitle('Manage plugins') QVBoxLayout(self) self._list_view = QListView(self) self._model = _ManagePluginsModel(self) self._list_view.setModel(self._model) self._button_box = QDialogButtonBox(self) self._button_box.setStandardButtons(QDialogButtonBox.Close) self.layout().addWidget(self._list_view) self.layout().addWidget(self._button_box) self.setAttribute(Qt.WA_DeleteOnClose) self.setMinimumWidth(400) self._button_box.button(QDialogButtonBox.Close).clicked.connect(self.close)
[docs] def populate_list(self, names): for name, can_update in names: item = QStandardItem(name) self._model.appendRow(item) widget = self._create_plugin_widget(name, can_update) index = self._model.indexFromItem(item) self._list_view.setIndexWidget(index, widget)
[docs] def _create_plugin_widget(self, plugin_name, can_update): widget = ToolBarWidget(plugin_name, self) widget.tool_bar.addAction("Remove", lambda _=False, n=plugin_name: self._emit_item_removed(n)) update = widget.tool_bar.addAction("Update", lambda _=False, n=plugin_name: self._emit_item_updated(n)) update.setEnabled(can_update) update.triggered.connect(lambda _=False: update.setEnabled(False)) return widget
[docs] def _emit_item_removed(self, plugin_name): for row in range(self._model.rowCount()): if self._model.index(row, 0).data(Qt.DisplayRole) == plugin_name: self._model.removeRow(row) break self.item_removed.emit(plugin_name)
[docs] def _emit_item_updated(self, plugin_name): self.item_updated.emit(plugin_name)