######################################################################################################################
# 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]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 _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)