Addon Manager: Worker refactor (round 1)
This commit is contained in:
@@ -44,13 +44,15 @@ translate = FreeCAD.Qt.translate
|
||||
|
||||
|
||||
class ListDisplayStyle(IntEnum):
|
||||
""" The display mode of the list """
|
||||
"""The display mode of the list"""
|
||||
|
||||
COMPACT = 0
|
||||
EXPANDED = 1
|
||||
|
||||
|
||||
class StatusFilter(IntEnum):
|
||||
""" Predefined filers """
|
||||
"""Predefined filers"""
|
||||
|
||||
ANY = 0
|
||||
INSTALLED = 1
|
||||
NOT_INSTALLED = 2
|
||||
@@ -97,7 +99,7 @@ class PackageList(QWidget):
|
||||
self.item_model = None
|
||||
|
||||
def setModel(self, model):
|
||||
""" This is a model-view-controller widget: set its model. """
|
||||
"""This is a model-view-controller widget: set its model."""
|
||||
self.item_model = model
|
||||
self.item_filter.setSourceModel(self.item_model)
|
||||
self.item_filter.sort(0)
|
||||
@@ -117,8 +119,8 @@ class PackageList(QWidget):
|
||||
)
|
||||
|
||||
def on_listPackages_clicked(self, index: QModelIndex):
|
||||
""" Determine what addon was selected and emit the itemSelected signal with it as
|
||||
an argument. """
|
||||
"""Determine what addon was selected and emit the itemSelected signal with it as
|
||||
an argument."""
|
||||
source_selection = self.item_filter.mapToSource(index)
|
||||
selected_repo = self.item_model.repos[source_selection.row()]
|
||||
self.itemSelected.emit(selected_repo)
|
||||
@@ -176,7 +178,7 @@ class PackageList(QWidget):
|
||||
self.item_filter.setFilterRegExp(text_filter)
|
||||
|
||||
def set_view_style(self, style: ListDisplayStyle) -> None:
|
||||
""" Set the style (compact or expanded) of the list """
|
||||
"""Set the style (compact or expanded) of the list"""
|
||||
self.item_model.layoutAboutToBeChanged.emit()
|
||||
self.item_delegate.set_view(style)
|
||||
if style == ListDisplayStyle.COMPACT:
|
||||
@@ -190,7 +192,7 @@ class PackageList(QWidget):
|
||||
|
||||
|
||||
class PackageListItemModel(QAbstractListModel):
|
||||
""" The model for use with the PackageList class. """
|
||||
"""The model for use with the PackageList class."""
|
||||
|
||||
repos = []
|
||||
write_lock = threading.Lock()
|
||||
@@ -200,19 +202,19 @@ class PackageListItemModel(QAbstractListModel):
|
||||
IconUpdateRole = Qt.UserRole + 2
|
||||
|
||||
def rowCount(self, parent: QModelIndex = QModelIndex()) -> int:
|
||||
""" The number of rows """
|
||||
"""The number of rows"""
|
||||
if parent.isValid():
|
||||
return 0
|
||||
return len(self.repos)
|
||||
|
||||
def columnCount(self, parent: QModelIndex = QModelIndex()) -> int:
|
||||
""" Only one column, always returns 1. """
|
||||
"""Only one column, always returns 1."""
|
||||
if parent.isValid():
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def data(self, index: QModelIndex, role: int = Qt.DisplayRole):
|
||||
""" Get the data for a given index and role. """
|
||||
"""Get the data for a given index and role."""
|
||||
if not index.isValid():
|
||||
return None
|
||||
row = index.row()
|
||||
@@ -235,7 +237,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
return self.repos[row]
|
||||
|
||||
def headerData(self, _unused1, _unused2, _role=Qt.DisplayRole):
|
||||
""" No header in this implementation: always returns None. """
|
||||
"""No header in this implementation: always returns None."""
|
||||
return None
|
||||
|
||||
def setData(self, index: QModelIndex, value, role=Qt.EditRole) -> None:
|
||||
@@ -259,7 +261,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
)
|
||||
|
||||
def append_item(self, repo: Addon) -> None:
|
||||
""" Adds this addon to the end of the model. Thread safe. """
|
||||
"""Adds this addon to the end of the model. Thread safe."""
|
||||
if repo in self.repos:
|
||||
# Cowardly refuse to insert the same repo a second time
|
||||
return
|
||||
@@ -269,7 +271,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
self.endInsertRows()
|
||||
|
||||
def clear(self) -> None:
|
||||
""" Clear the model, removing all rows. Thread safe. """
|
||||
"""Clear the model, removing all rows. Thread safe."""
|
||||
if self.rowCount() > 0:
|
||||
with self.write_lock:
|
||||
self.beginRemoveRows(QModelIndex(), 0, self.rowCount() - 1)
|
||||
@@ -277,7 +279,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
self.endRemoveRows()
|
||||
|
||||
def update_item_status(self, name: str, status: Addon.Status) -> None:
|
||||
""" Set the status of addon with name to status. """
|
||||
"""Set the status of addon with name to status."""
|
||||
for row, item in enumerate(self.repos):
|
||||
if item.name == name:
|
||||
self.setData(
|
||||
@@ -286,7 +288,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
return
|
||||
|
||||
def update_item_icon(self, name: str, icon: QIcon) -> None:
|
||||
""" Set the icon for Addon with name to icon """
|
||||
"""Set the icon for Addon with name to icon"""
|
||||
for row, item in enumerate(self.repos):
|
||||
if item.name == name:
|
||||
self.setData(
|
||||
@@ -295,7 +297,7 @@ class PackageListItemModel(QAbstractListModel):
|
||||
return
|
||||
|
||||
def reload_item(self, repo: Addon) -> None:
|
||||
""" Sets the addon data for the given addon (based on its name) """
|
||||
"""Sets the addon data for the given addon (based on its name)"""
|
||||
for index, item in enumerate(self.repos):
|
||||
if item.name == repo.name:
|
||||
with self.write_lock:
|
||||
@@ -336,17 +338,17 @@ class PackageListItemDelegate(QStyledItemDelegate):
|
||||
self.widget = self.expanded
|
||||
|
||||
def set_view(self, style: ListDisplayStyle) -> None:
|
||||
""" Set the view of to style """
|
||||
"""Set the view of to style"""
|
||||
if not self.displayStyle == style:
|
||||
self.displayStyle = style
|
||||
|
||||
def sizeHint(self, _option, index):
|
||||
""" Attempt to figure out the correct height for the widget based on its current contents. """
|
||||
"""Attempt to figure out the correct height for the widget based on its current contents."""
|
||||
self.update_content(index)
|
||||
return self.widget.sizeHint()
|
||||
|
||||
def update_content(self, index):
|
||||
""" Creates the display of the content for a given index. """
|
||||
"""Creates the display of the content for a given index."""
|
||||
repo = index.data(PackageListItemModel.DataAccessRole)
|
||||
if self.displayStyle == ListDisplayStyle.EXPANDED:
|
||||
self.widget = self.expanded
|
||||
@@ -381,8 +383,8 @@ class PackageListItemDelegate(QStyledItemDelegate):
|
||||
|
||||
self.widget.adjustSize()
|
||||
|
||||
def _setup_expanded_package (self, repo:Addon):
|
||||
""" Set up the display for a package in expanded view """
|
||||
def _setup_expanded_package(self, repo: Addon):
|
||||
"""Set up the display for a package in expanded view"""
|
||||
maintainers = repo.metadata.Maintainer
|
||||
maintainers_string = ""
|
||||
if len(maintainers) == 1:
|
||||
@@ -392,23 +394,17 @@ class PackageListItemDelegate(QStyledItemDelegate):
|
||||
)
|
||||
elif len(maintainers) > 1:
|
||||
n = len(maintainers)
|
||||
maintainers_string = translate(
|
||||
"AddonsInstaller", "Maintainers:", "", n
|
||||
)
|
||||
maintainers_string = translate("AddonsInstaller", "Maintainers:", "", n)
|
||||
for maintainer in maintainers:
|
||||
maintainers_string += (
|
||||
f"\n{maintainer['name']} <{maintainer['email']}>"
|
||||
)
|
||||
maintainers_string += f"\n{maintainer['name']} <{maintainer['email']}>"
|
||||
self.widget.ui.labelMaintainer.setText(maintainers_string)
|
||||
if repo.tags:
|
||||
self.widget.ui.labelTags.setText(
|
||||
translate("AddonsInstaller", "Tags")
|
||||
+ ": "
|
||||
+ ", ".join(repo.tags)
|
||||
translate("AddonsInstaller", "Tags") + ": " + ", ".join(repo.tags)
|
||||
)
|
||||
|
||||
def _setup_macro(self, repo:Addon):
|
||||
""" Set up the display for a macro """
|
||||
def _setup_macro(self, repo: Addon):
|
||||
"""Set up the display for a macro"""
|
||||
self.widget.ui.labelDescription.setText(repo.macro.comment)
|
||||
version_string = ""
|
||||
if repo.macro.version:
|
||||
@@ -526,8 +522,8 @@ class PackageListItemDelegate(QStyledItemDelegate):
|
||||
return result
|
||||
|
||||
def paint(self, painter: QPainter, option: QStyleOptionViewItem, _: QModelIndex):
|
||||
""" Main paint function: renders this widget into a given rectangle, successively drawing
|
||||
all of its children. """
|
||||
"""Main paint function: renders this widget into a given rectangle, successively drawing
|
||||
all of its children."""
|
||||
painter.save()
|
||||
self.widget.resize(option.rect.size())
|
||||
painter.translate(option.rect.topLeft())
|
||||
@@ -550,42 +546,42 @@ class PackageListFilter(QSortFilterProxyModel):
|
||||
def setPackageFilter(
|
||||
self, package_type: int
|
||||
) -> None: # 0=All, 1=Workbenches, 2=Macros, 3=Preference Packs
|
||||
""" Set the package filter to package_type and refreshes. """
|
||||
"""Set the package filter to package_type and refreshes."""
|
||||
self.package_type = package_type
|
||||
self.invalidateFilter()
|
||||
|
||||
def setStatusFilter(
|
||||
self, status: int
|
||||
) -> None: # 0=Any, 1=Installed, 2=Not installed, 3=Update available
|
||||
""" Sets the status filter to status and refreshes. """
|
||||
"""Sets the status filter to status and refreshes."""
|
||||
self.status = status
|
||||
self.invalidateFilter()
|
||||
|
||||
def setHidePy2(self, hide_py2: bool) -> None:
|
||||
""" Sets whether or not to hide Python 2-only Addons """
|
||||
"""Sets whether or not to hide Python 2-only Addons"""
|
||||
self.hide_py2 = hide_py2
|
||||
self.invalidateFilter()
|
||||
|
||||
def setHideObsolete(self, hide_obsolete: bool) -> None:
|
||||
""" Sets whether or not to hide Addons marked obsolete """
|
||||
"""Sets whether or not to hide Addons marked obsolete"""
|
||||
self.hide_obsolete = hide_obsolete
|
||||
self.invalidateFilter()
|
||||
|
||||
def setHideNewerFreeCADRequired(self, hide_nfr: bool) -> None:
|
||||
""" Sets whether or not to hide packages that have indicated they need a newer version
|
||||
of FreeCAD than the one currently running. """
|
||||
"""Sets whether or not to hide packages that have indicated they need a newer version
|
||||
of FreeCAD than the one currently running."""
|
||||
self.hide_newer_freecad_required = hide_nfr
|
||||
self.invalidateFilter()
|
||||
|
||||
def lessThan(self, left, right) -> bool:
|
||||
""" Enable sorting of display name (not case sensitive). """
|
||||
"""Enable sorting of display name (not case sensitive)."""
|
||||
l = self.sourceModel().data(left, PackageListItemModel.DataAccessRole)
|
||||
r = self.sourceModel().data(right, PackageListItemModel.DataAccessRole)
|
||||
|
||||
return l.display_name.lower() < r.display_name.lower()
|
||||
|
||||
def filterAcceptsRow(self, row, parent=QModelIndex()):
|
||||
""" Do the actual filtering (called automatically by Qt when drawing the list) """
|
||||
"""Do the actual filtering (called automatically by Qt when drawing the list)"""
|
||||
index = self.sourceModel().createIndex(row, 0)
|
||||
data = self.sourceModel().data(index, PackageListItemModel.DataAccessRole)
|
||||
if self.package_type == 1:
|
||||
|
||||
Reference in New Issue
Block a user