Addon Manager: Improve display of install details

As suggested in the forums, this adds display of the installation date and
installed version to the expanded display and detail view.
This commit is contained in:
Chris Hennes
2021-12-17 10:01:29 -06:00
parent 52da213a3c
commit ef09c0af16
6 changed files with 201 additions and 111 deletions

View File

@@ -78,6 +78,7 @@ class CommandAddonManager:
"update_metadata_cache_worker", "update_all_worker"]
lock = threading.Lock()
restart_required = False
def __init__(self):
FreeCADGui.addPreferencePage(os.path.join(os.path.dirname(__file__),
@@ -201,6 +202,7 @@ class CommandAddonManager:
self.packageDetails.uninstall.connect(self.remove)
self.packageDetails.update.connect(self.update)
self.packageDetails.back.connect(self.on_buttonBack_clicked)
self.packageDetails.update_status.connect(self.status_updated)
# center the dialog over the FreeCAD window
mw = FreeCADGui.getMainWindow()
@@ -276,8 +278,7 @@ class CommandAddonManager:
# all threads have finished
if oktoclose:
if ((hasattr(self, "install_worker") and self.install_worker) or
(hasattr(self, "addon_removed") and self.addon_removed)):
if self.restart_required:
# display restart dialog
m = QtWidgets.QMessageBox()
m.setWindowTitle(translate("AddonsInstaller", "Addon manager"))
@@ -478,9 +479,9 @@ class CommandAddonManager:
self.check_worker.start()
self.enable_updates(len(self.packages_with_updates))
def status_updated(self, repo:str, status:AddonManagerRepo.UpdateStatus) -> None:
self.item_model.update_item_status(repo.name, status)
if status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
def status_updated(self, repo:AddonManagerRepo) -> None:
self.item_model.reload_item(repo)
if repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
self.packages_with_updates.append(repo)
self.enable_updates(len(self.packages_with_updates))
@@ -578,6 +579,7 @@ class CommandAddonManager:
return
if repo.repo_type == AddonManagerRepo.RepoType.WORKBENCH or repo.repo_type == AddonManagerRepo.RepoType.PACKAGE:
self.show_progress_widgets()
self.install_worker = InstallWorkbenchWorker(repo)
self.install_worker.status_message.connect(self.show_information)
self.current_progress_region = 1
@@ -610,7 +612,7 @@ class CommandAddonManager:
"now available from the Macros dialog.")
self.on_package_installed (repo, message)
else:
message = translate("AddonsInstaller", "Installation of macro failed" + ":")
message = translate("AddonsInstaller", "Installation of macro failed") + ":"
for error in errors:
message += "\n * "
message += error
@@ -629,6 +631,7 @@ class CommandAddonManager:
self.subupdates_succeeded = []
self.subupdates_failed = []
self.show_progress_widgets()
self.current_progress_region = 1
self.number_of_progress_regions = 1
self.update_all_worker = UpdateAllWorker(self.packages_with_updates)
@@ -640,7 +643,7 @@ class CommandAddonManager:
self.update_all_worker.start()
def on_update_all_completed(self) -> None:
#self.show_progress_bar(False)
self.hide_progress_widgets()
if not self.subupdates_failed:
message = translate ("AddonsInstaller", "All packages were successfully updated. Packages:") + "\n"
message += ''.join([repo.name + "\n" for repo in self.subupdates_succeeded])
@@ -654,6 +657,9 @@ class CommandAddonManager:
message += ''.join([repo.name + "\n" for repo in self.subupdates_failed])
for installed_repo in self.subupdates_succeeded:
self.restart_required = True
installed_repo.update_status = AddonManagerRepo.UpdateStatus.PENDING_RESTART
self.item_model.reload_item(installed_repo)
for requested_repo in self.packages_with_updates:
if installed_repo.name == requested_repo.name:
self.packages_with_updates.remove(installed_repo)
@@ -704,22 +710,22 @@ class CommandAddonManager:
self.hide_progress_widgets()
def on_package_installed(self, repo:AddonManagerRepo, message:str) -> None:
self.hide_progress_widgets()
QtWidgets.QMessageBox.information(None,
translate("AddonsInstaller", "Installation succeeded"),
message,
QtWidgets.QMessageBox.Close)
if repo.contains_workbench():
self.item_model.update_item_status(repo.name, AddonManagerRepo.UpdateStatus.PENDING_RESTART)
else:
self.item_model.update_item_status(repo.name, AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE)
self.packageDetails.show_repo(repo, reload=True)
repo.update_status = AddonManagerRepo.UpdateStatus.PENDING_RESTART
self.item_model.reload_item(repo)
self.packageDetails.show_repo(repo)
self.restart_required = True
def on_installation_failed(self, _:AddonManagerRepo, message:str) -> None:
self.hide_progress_widgets()
QtWidgets.QMessageBox.warning(None,
translate("AddonsInstaller", "Installation failed"),
message,
QtWidgets.QMessageBox.Close)
self.dialog.progressBar.hide()
def executemacro(self, repo:AddonManagerRepo) -> None:
"""executes a selected macro"""
@@ -732,7 +738,7 @@ class CommandAddonManager:
macro_path = os.path.join(self.macro_repo_dir,macro.filename)
FreeCADGui.open(str(macro_path))
self.dialog.hide()
FreeCADGui.SendMsgToActiveView("Run")
FreeCADGui.SendMsgToActiveView("Run")
else:
with tempfile.TemporaryDirectory() as dir:
temp_install_succeeded = macro.install(dir)
@@ -764,7 +770,8 @@ class CommandAddonManager:
shutil.rmtree(clonedir, onerror=self.remove_readonly)
self.item_model.update_item_status(repo.name, AddonManagerRepo.UpdateStatus.NOT_INSTALLED)
self.addon_removed = True # A value to trigger the restart message on dialog close
self.packageDetails.show_repo(repo, reload=True)
self.packageDetails.show_repo(repo)
self.restart_required = True
else:
self.dialog.textBrowserReadMe.setText(translate("AddonsInstaller", "Unable to remove this addon with the Addon Manager."))
@@ -772,7 +779,7 @@ class CommandAddonManager:
macro = repo.macro
if macro.remove():
self.item_model.update_item_status(repo.name, AddonManagerRepo.UpdateStatus.NOT_INSTALLED)
self.packageDetails.show_repo(repo, reload=True)
self.packageDetails.show_repo(repo)
else:
self.dialog.textBrowserReadMe.setText(translate("AddonsInstaller", "Macro could not be removed."))

View File

@@ -82,6 +82,8 @@ class AddonManagerRepo:
self.icon = None
self.cached_icon_filename = ""
self.macro = None # Bridge to Gaël Écorchard's macro management class
self.updated_timestamp = None
self.installed_version = None
def __str__ (self) -> str:
result = f"FreeCAD {self.repo_type}\n"

View File

@@ -30,6 +30,7 @@ import tempfile
import hashlib
import threading
import queue
from datetime import datetime
from typing import Union, List
from PySide2 import QtCore, QtGui, QtNetwork
@@ -39,11 +40,11 @@ if FreeCAD.GuiUp:
import FreeCADGui
import addonmanager_utilities as utils
from addonmanager_utilities import translate # this needs to be as is for pylupdate
from addonmanager_macro import Macro
from addonmanager_metadata import MetadataDownloadWorker
from AddonManagerRepo import AddonManagerRepo
translate = FreeCAD.Qt.translate
have_git = False
try:
@@ -240,9 +241,7 @@ class LoadMacrosFromCacheWorker(QtCore.QThread):
class CheckWorkbenchesForUpdatesWorker(QtCore.QThread):
"""This worker checks for available updates for all workbenches"""
# Emitting an Enum fails on Ubuntu 20.04, so use an int instead
#update_status = QtCore.Signal(AddonManagerRepo, AddonManagerRepo.UpdateStatus)
update_status = QtCore.Signal(AddonManagerRepo, int)
update_status = QtCore.Signal(AddonManagerRepo)
progress_made = QtCore.Signal(int, int)
done = QtCore.Signal()
@@ -307,31 +306,47 @@ class CheckWorkbenchesForUpdatesWorker(QtCore.QThread):
try:
gitrepo.fetch()
except Exception:
FreeCAD.Console.PrintWarning("AddonManager: Unable to fetch git updates for workbench " + wb.name)
FreeCAD.Console.PrintWarning("AddonManager: " + translate("AddonsInstaller","Unable to fetch git updates for workbench") + " " + wb.name)
else:
try:
if "git pull" in gitrepo.status():
self.update_status.emit(wb, AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE)
wb.update_status = AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
else:
self.update_status.emit(wb, AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE)
except stderr:
wb.update_status = AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE
self.update_status.emit(wb)
except Exception:
FreeCAD.Console.PrintWarning("AddonManager - " + wb.name + " git status"
" fatal: this operation must be run in a work tree \n")
def check_package(self, package):
def check_package(self, package:AddonManagerRepo) -> None:
clonedir = self.moddir + os.sep + package.name
if os.path.exists(clonedir):
installed_metadata_file = os.path.join(clonedir, "package.xml")
installed_metadata = FreeCAD.Metadata(installed_metadata_file)
# Packages are considered up-to-date if the metadata version matches. Authors should update
# their version string when they want the addon manager to alert users of a new version.
if package.metadata.Version > installed_metadata.Version:
self.update_status.emit(package, AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE)
if not os.path.isfile(installed_metadata_file):
# If there is no package.xml file, then it's because the package author added it after the last time
# the local installation was updated. By definition, then, there is an update available, if only to
# download the new XML file.
package.update_status = AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
package.installed_version = None
self.update_status.emit(package)
return
else:
self.update_status.emit(package, AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE)
package.updated_timestamp = os.path.getmtime(installed_metadata_file)
try:
installed_metadata = FreeCAD.Metadata(installed_metadata_file)
package.installed_version = installed_metadata.Version
# Packages are considered up-to-date if the metadata version matches. Authors should update
# their version string when they want the addon manager to alert users of a new version.
if package.metadata.Version != installed_metadata.Version:
package.update_status = AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
else:
package.update_status = AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE
self.update_status.emit(package)
except Exception as e:
FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Failed to read metadata from") + f" {installed_metadata_file}")
def check_macro(self, macro_wrapper):
def check_macro(self, macro_wrapper:AddonManagerRepo) -> None:
# Make sure this macro has its code downloaded:
try:
if not macro_wrapper.macro.parsed and macro_wrapper.macro.on_git:
@@ -365,9 +380,10 @@ class CheckWorkbenchesForUpdatesWorker(QtCore.QThread):
else:
return
if new_sha1 == old_sha1:
self.update_status.emit(macro_wrapper, AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE)
macro_wrapper.update_status = AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE
else:
self.update_status.emit(macro_wrapper, AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE)
macro_wrapper.update_status = AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
self.update_status.emit(macro_wrapper)
class FillMacroListWorker(QtCore.QThread):
@@ -489,7 +505,7 @@ class ShowWorker(QtCore.QThread):
status_message = QtCore.Signal(str)
readme_updated = QtCore.Signal(str)
addon_repos = QtCore.Signal(object)
update_status = QtCore.Signal(AddonManagerRepo)
done = QtCore.Signal()
def __init__(self, repo, cache_path):
@@ -570,9 +586,9 @@ class ShowWorker(QtCore.QThread):
self.repo.description = desc
if QtCore.QThread.currentThread().isInterruptionRequested():
return
self.addon_repos.emit(self.repo)
# Addon is installed so lets check if it has an update
if self.repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
message = desc
if self.repo.update_status == AddonManagerRepo.UpdateStatus.UNCHECKED:
# Addon is installed but we haven't checked it yet, so lets check if it has an update
upd = False
# checking for updates
if not NOGIT and have_git:
@@ -598,72 +614,14 @@ class ShowWorker(QtCore.QThread):
gitrepo.fetch()
if "git pull" in gitrepo.status():
upd = True
# If there is an update pending, lets user know via the UI
if upd:
message = """
<div style="width: 100%;text-align: center;background: #75AFFD;">
<br/>
<strong style="background: #397FF7;color: #FFFFFF;">
"""
message += translate("AddonsInstaller", "An update is available for this addon.")
message += "</strong><br/></div><hr/>" + desc + '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + "</a>"
self.repo.update_status = AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE
# If there isn't, indicate that this addon is already installed
else:
message = """
<div style="width: 100%;text-align: center;background: #C1FEB2;">
<br/>
<strong style="background: #00B629;color: #FFFFFF;">
"""
message += translate("AddonsInstaller", "This addon is already installed.")
message += "</strong><br/></div><hr/>" + desc
message += '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + "</a>"
self.repo.update_status = AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE
# Let the user know the install path for this addon
message += "<br/>" + translate("AddonsInstaller", "Installed location") + ": "
message += FreeCAD.getUserAppDataDir() + os.sep + "Mod" + os.sep + self.repo.name
self.update_status.emit(self.repo)
if QtCore.QThread.currentThread().isInterruptionRequested():
return
self.addon_repos.emit(self.repo)
elif self.repo.update_status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
message = """
<div style="width: 100%;text-align: center;background: #C1FEB2;">
<br/>
<strong style="background: #00B629;color: #FFFFFF;">
"""
message += translate("AddonsInstaller", "This addon has been updated, a restart is now required before it can be used.")
message += "</strong><br/></div><hr/>" + desc + '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + "</a>"
message += "<br/>" + translate("AddonsInstaller", "Installed location") + ": "
message += FreeCAD.getUserAppDataDir() + os.sep + "Mod" + os.sep + self.repo.name
elif self.repo.update_status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
message = """
<div style="width: 100%;text-align: center;background: #C1FEB2;">
<br/>
<strong style="background: #00B629;color: #FFFFFF;">
"""
message += translate("AddonsInstaller", "This addon is already installed.")
message += "</strong><br></div><hr/>" + desc
message += '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + "</a>"
message += "<br/>" + translate("AddonsInstaller", "Installed location") + ": "
message += FreeCAD.getUserAppDataDir() + os.sep + "Mod" + os.sep + self.repo.name
elif self.repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
message = """
<div style="width: 100%;text-align: center;background: #75AFFD;">
<br/>
<strong style="background: #397FF7;color: #FFFFFF;">
"""
message += translate("AddonsInstaller", "An update is available for this addon.")
message += "</strong><br/></div><hr/>" + desc + '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + "</a>"
message += "<br/>" + translate("AddonsInstaller", "Installed location") + ": "
message += FreeCAD.getUserAppDataDir() + os.sep + "Mod" + os.sep + self.repo.name
else:
message = desc + '<br/><br/>Addon repository: <a href="'
message += self.repo.url + '">' + self.repo.url + '</a>'
# If the Addon is obsolete, let the user know through the Addon UI
if self.repo.name in obsolete:
@@ -905,6 +863,7 @@ class InstallWorkbenchWorker(QtCore.QThread):
self.status_message.emit("Updating submodules...")
for submodule in repo_sms.submodules:
submodule.update(init=True, recursive=True)
self.update_metadata()
self.success.emit(self.repo, answer)
def run_git_clone(self, clonedir:str) -> None:
@@ -946,6 +905,7 @@ class InstallWorkbenchWorker(QtCore.QThread):
"A macro has been installed and is available "
"under Macro -> Macros menu")
answer += ":\n<b>" + f + "</b>"
self.update_metadata()
self.success.emit(self.repo, answer)
def check_python_dependencies(self, baseurl:str) -> Union[bool,str]:
@@ -960,7 +920,7 @@ class InstallWorkbenchWorker(QtCore.QThread):
try:
mu = utils.urlopen(depsurl)
except Exception:
return True,"No metadata.txt found"
return True, translate("AddonsInstaller", "No metadata.txt found, cannot evaluate Python dependencies")
if mu:
# metadata.txt found
depsfile = mu.read()
@@ -1003,7 +963,7 @@ class InstallWorkbenchWorker(QtCore.QThread):
"Missing optional python module (doesn't prevent installing)")
message += ": " + pl + ", "
if message and (not ok):
message = translate("AddonsInstaller", "Some errors were found that prevent to install this workbench")
message = translate("AddonsInstaller", "Some errors were found that prevent installation of this workbench")
message += ": <b>" + message + "</b>. "
message += translate("AddonsInstaller", "Please install the missing components first.")
return ok, message
@@ -1067,8 +1027,17 @@ class InstallWorkbenchWorker(QtCore.QThread):
os.rmdir(zipdir + os.sep + master)
if bakdir:
shutil.rmtree(bakdir)
self.update_metadata()
self.success.emit(self.repo, translate("AddonsInstaller", "Successfully installed") + " " + zipurl)
def update_metadata(self):
basedir = FreeCAD.getUserAppDataDir()
package_xml = os.path.join(basedir,"Mod",self.repo.name,"package.xml")
if os.path.isfile(package_xml):
self.repo.metadata = FreeCAD.Metadata(package_xml)
self.repo.installed_version = self.repo.metadata.Version
self.repo.updated_timestamp = datetime.now().timestamp()
class CheckSingleWorker(QtCore.QThread):
"""Worker to check for updates for a single addon"""

View File

@@ -44,6 +44,7 @@ class PackageDetails(QWidget):
uninstall = Signal(AddonManagerRepo)
update = Signal(AddonManagerRepo)
execute = Signal(AddonManagerRepo)
update_status = Signal(AddonManagerRepo)
def __init__(self, parent=None):
super().__init__(parent)
@@ -86,6 +87,45 @@ class PackageDetails(QWidget):
self.show_package(repo)
self.ui.buttonExecute.hide()
if repo.update_status != AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
installed_version_string = ""
if repo.installed_version:
installed_version_string = translate("AddonsInstaller", "Version") + " "
installed_version_string += repo.installed_version
else:
installed_version_string = translate("AddonsInstaller", "Unknown version (no package.xml file found)") + " "
if repo.updated_timestamp:
installed_version_string += " " + translate("AddonsInstaller", "installed on") + " "
installed_version_string += QDateTime.fromTime_t(repo.updated_timestamp).date().toString(Qt.SystemLocaleShortDate)
installed_version_string += ". "
else:
installed_version_string += translate("AddonsInstaller", "installed") + ". "
if repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
if repo.metadata:
installed_version_string += "<b>" + translate("AddonsInstaller", "Update available to version") + " "
installed_version_string += repo.metadata.Version
installed_version_string += ".</b>"
else:
installed_version_string += "<b>" + translate("AddonsInstaller", "Update available to unknown version (no package.xml file found)") + ".</b>"
elif repo.update_status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
installed_version_string += translate("AddonsInstaller", "This is the latest version available") + "."
elif repo.update_status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
installed_version_string += translate("AddonsInstaller", "Updated, please restart FreeCAD to use") + "."
elif repo.update_status == AddonManagerRepo.UpdateStatus.UNCHECKED:
installed_version_string += translate("AddonsInstaller", "Update check in progress") + "."
basedir = FreeCAD.getUserAppDataDir()
moddir = os.path.join(basedir , "Mod", repo.name)
installed_version_string += "<br/>" + translate("AddonsInstaller", "Installation location") + ": " + moddir
self.ui.labelPackageDetails.setText(installed_version_string)
self.ui.labelPackageDetails.show()
else:
self.ui.labelPackageDetails.hide()
if repo.update_status == AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
self.ui.buttonInstall.show()
self.ui.buttonUninstall.hide()
@@ -160,6 +200,8 @@ class PackageDetails(QWidget):
self.worker = ShowWorker(repo, PackageDetails.cache_path(repo))
self.worker.readme_updated.connect(lambda desc: self.cache_readme(repo, desc))
self.worker.readme_updated.connect(lambda desc: self.ui.textBrowserReadMe.setText(desc))
self.worker.update_status.connect(self.update_status.emit)
self.worker.update_status.connect(self.show)
self.worker.start()
def show_package(self, repo:AddonManagerRepo) -> None:
@@ -170,6 +212,8 @@ class PackageDetails(QWidget):
self.worker = ShowWorker(repo,PackageDetails.cache_path(repo))
self.worker.readme_updated.connect(lambda desc: self.cache_readme(repo, desc))
self.worker.readme_updated.connect(lambda desc: self.ui.textBrowserReadMe.setText(desc))
self.worker.update_status.connect(self.update_status.emit)
self.worker.update_status.connect(self.show)
self.worker.start()
def show_macro(self, repo:AddonManagerRepo) -> None:
@@ -232,9 +276,13 @@ class Ui_PackageDetails(object):
self.layoutDetailsBackButton.addWidget(self.buttonExecute)
self.verticalLayout_2.addLayout(self.layoutDetailsBackButton)
self.labelPackageDetails = QLabel(PackageDetails)
self.labelPackageDetails.hide()
self.verticalLayout_2.addWidget(self.labelPackageDetails)
self.textBrowserReadMe = QTextBrowser(PackageDetails)
self.textBrowserReadMe.setObjectName(u"textBrowserReadMe")
self.textBrowserReadMe.setOpenExternalLinks(True)

View File

@@ -76,6 +76,19 @@
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelInstallationDetails">
<property name="text">
<string notr="true">Installation details go here</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QTextBrowser" name="textBrowserReadMe"/>
</item>

View File

@@ -28,6 +28,7 @@ from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import datetime
from typing import Dict, Union
from enum import IntEnum
import threading
@@ -291,18 +292,68 @@ class PackageListItemDelegate(QStyledItemDelegate):
self.widget.ui.labelMaintainer.setText("")
# Update status
if repo.update_status == AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
self.widget.ui.labelStatus.setText("")
elif repo.update_status == AddonManagerRepo.UpdateStatus.UNCHECKED:
self.widget.ui.labelStatus.setText(translate("AddonsInstaller","Installed"))
elif repo.update_status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
self.widget.ui.labelStatus.setText(translate("AddonsInstaller","Up-to-date"))
elif repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
self.widget.ui.labelStatus.setText(translate("AddonsInstaller","Update available"))
elif repo.update_status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
self.widget.ui.labelStatus.setText(translate("AddonsInstaller","Pending restart"))
if self.displayStyle == ListDisplayStyle.EXPANDED:
self.widget.ui.labelStatus.setText(self.get_expanded_update_string(repo))
else:
self.widget.ui.labelStatus.setText(self.get_compact_update_string(repo))
self.widget.adjustSize()
def get_compact_update_string(self, repo:AddonManagerRepo) -> str:
""" Get a single-line string listing details about the installed version and date """
result = ""
if repo.update_status == AddonManagerRepo.UpdateStatus.UNCHECKED:
result = translate("AddonsInstaller","Installed")
elif repo.update_status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
result = translate("AddonsInstaller","Up-to-date")
elif repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
result = translate("AddonsInstaller","Update available")
elif repo.update_status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
result = translate("AddonsInstaller","Pending restart")
return result
def get_expanded_update_string(self, repo:AddonManagerRepo) -> str:
""" Get a multi-line string listing details about the installed version and date """
result = ""
installed_version_string = ""
if repo.update_status != AddonManagerRepo.UpdateStatus.NOT_INSTALLED:
if repo.installed_version:
installed_version_string = "\n" + translate("AddonsInstaller", "Installed version") + ": "
installed_version_string += repo.installed_version
else:
installed_version_string = "\n" + translate("AddonsInstaller", "Unknown version")
installed_date_string = ""
if repo.updated_timestamp:
installed_date_string = "\n" + translate("AddonsInstaller", "Installed on") + ": "
installed_date_string += QDateTime.fromTime_t(repo.updated_timestamp).date().toString(Qt.SystemLocaleShortDate)
available_version_string = ""
if repo.metadata:
available_version_string = "\n" + translate("AddonsInstaller", "Available version") + ": "
available_version_string += repo.metadata.Version
if repo.update_status == AddonManagerRepo.UpdateStatus.UNCHECKED:
result = translate("AddonsInstaller","Installed")
result += installed_version_string
result += installed_date_string
elif repo.update_status == AddonManagerRepo.UpdateStatus.NO_UPDATE_AVAILABLE:
result = translate("AddonsInstaller","Up-to-date")
result += installed_version_string
result += installed_date_string
elif repo.update_status == AddonManagerRepo.UpdateStatus.UPDATE_AVAILABLE:
result = translate("AddonsInstaller","Update available")
result += installed_version_string
result += installed_date_string
result += available_version_string
elif repo.update_status == AddonManagerRepo.UpdateStatus.PENDING_RESTART:
result = translate("AddonsInstaller","Pending restart")
return result
def paint(self, painter:QPainter, option:QStyleOptionViewItem, index:QModelIndex):
painter.save()
self.widget.resize(option.rect.size())