wizard no longer crashes if selection menu reloaded

wizard now caches icons so no duplication of requests
enforcement of dependencies partially implemented
allowed redirection of all network requests
This commit is contained in:
Brennen Raimer
2019-04-30 12:55:41 -04:00
parent 1f426ea6ae
commit 2571e097e2

View File

@@ -34,6 +34,7 @@ class InstallerWizard(QtWidgets.QWizard):
self.selection_page.initializePage = self._load_tools
self.intro.anchorClicked.connect(self._link_clicked)
self.license.anchorClicked.connect(self._link_clicked)
self.selection_menu.itemClicked.connect(self._enforce_dependencies)
self.install_location.setValidator(Location_Validator(parent=self))
self.location_page.registerField("Location*", self.install_location)
self.browse_button.clicked.connect(self._select_location)
@@ -95,6 +96,7 @@ class InstallerWizard(QtWidgets.QWizard):
if self._network_manager.networkAccessible():
request = QtNetwork.QNetworkRequest(QtCore.QUrl("https://www.gnu.org/licenses/gpl-3.0-standalone.html"))
request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, QtNetwork.QNetworkRequest.AlwaysNetwork)
request.setAttribute(QtNetwork.QNetworkRequest.FollowRedirectsAttribute, True)
reply = self._network_manager.get(request)
reply.downloadProgress.connect(lambda received, total: process_dialog.setMaximum(total))
reply.downloadProgress.connect(lambda received, total: process_dialog.setValue(received))
@@ -147,8 +149,15 @@ class InstallerWizard(QtWidgets.QWizard):
process_dialog.setAutoClose(True)
process_dialog.setAutoReset(True)
process_dialog.setCancelButton(None)
try: #clear data from this page before reloading
self.__tools__ = None
self._icon_cache = {item.text(0):item.icon(0) for item in list(MenuIterator(self.selection_menu, QtWidgets.QTreeWidgetItemIterator.NoChildren))}
self.selection_menu.clear()
except NameError:
pass
request = QtNetwork.QNetworkRequest(QtCore.QUrl("https://raw.githubusercontent.com/norweeg/portable-computing-toolkit-installer/initial_dev/portable_computing_toolkit_installer/resources/supported_tools.json"))
request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, QtNetwork.QNetworkRequest.AlwaysNetwork)
request.setAttribute(QtNetwork.QNetworkRequest.FollowRedirectsAttribute, True)
reply = self._network_manager.get(request)
reply.downloadProgress.connect(lambda received, total: process_dialog.setMaximum(total))
reply.downloadProgress.connect(lambda received, total: process_dialog.setValue(received))
@@ -163,7 +172,6 @@ class InstallerWizard(QtWidgets.QWizard):
self._display_error(f"Unable to decode {request.url.toString()}", e).accepted.connect(self.back)
else:
self._populate_menu()
self.selection_menu.itemSelectionChanged.connect(self._enforce_dependencies)
else:
self._display_error(f"Encountered an error while loading supported tools from {request.url().toString()}", reply.errorString()).finished.connect(lambda x: self.back())
@@ -202,9 +210,12 @@ class InstallerWizard(QtWidgets.QWizard):
new_item.setData(1, QtCore.Qt.DecorationRole, QtGui.QIcon(str(Path(__file__).parent.parent/"resources/icons/internet-web-browser-4.png")))
new_item.setData(1, QtCore.Qt.ToolTipRole, tool["homepage"])
try:
self._get_icon(new_item, tool["icon url"])
except KeyError:
self._get_icon(new_item)
new_item.setIcon(0, self._icon_cache[new_item.text(0)])
except (AttributeError, KeyError):
try:
self._get_icon(new_item, tool["icon url"])
except KeyError:
self._get_icon(new_item)
try:
if tool["depends on"] == current_level: #tool depends on itself makes it mandatory
new_item.setFlags(new_item.flags()^QtCore.Qt.ItemIsUserCheckable)
@@ -244,20 +255,24 @@ class InstallerWizard(QtWidgets.QWizard):
"""
if not icon_url:
icon_url = QtCore.QUrl(f"http://www.google.com/s2/favicons?domain={QtCore.QUrl(tree_item.data(1, QtCore.Qt.ToolTipRole)).toString()}")
icon_request = self._network_manager.get(QtNetwork.QNetworkRequest(QtCore.QUrl(icon_url)))
icon_request = QtNetwork.QNetworkRequest(QtCore.QUrl(icon_url))
icon_request.setAttribute(QtNetwork.QNetworkRequest.CacheLoadControlAttribute, QtNetwork.QNetworkRequest.AlwaysNetwork)
icon_request.setAttribute(QtNetwork.QNetworkRequest.FollowRedirectsAttribute, True)
icon_reply = self._network_manager.get(icon_request)
#when download is complete, validates request returned without error and sets icon
icon_request.finished.connect(partial(self._set_icon, tree_item, icon_request))
icon_reply.finished.connect(partial(self._set_icon, tree_item, icon_reply))
icon_reply.error.connect(lambda error: self._display_error(QtCore.QMetaEnum.valueToKey(error)))
def _set_icon(self, tree_item, request):
def _set_icon(self, tree_item, reply):
"""Validates a network request and sets its result as the icon of a QTreeWidgetItem.
Arguments:
tree_item {QTreeWidgetItem} -- A tree widget item to set the icon of
request {QNetworkReply} -- The results of the HTTP GET request whose data will be used as the icon for tree_item
"""
if not request.error():
if not reply.error():
pixmap = QtGui.QPixmap()
pixmap.loadFromData(request.readAll())
pixmap.loadFromData(reply.readAll())
tree_item.setIcon(0, QtGui.QIcon(pixmap))
def _get_selections(self):
@@ -265,15 +280,17 @@ class InstallerWizard(QtWidgets.QWizard):
"""
return list(MenuIterator(self.selection_menu, QtWidgets.QTreeWidgetItemIterator.Checked|QtWidgets.QTreeWidgetItemIterator.NoChildren))
@QtCore.pyqtSlot()
def _enforce_dependencies(self):
for tool in self._get_selections():
@QtCore.pyqtSlot("QTreeWidgetItem*","int")
def _enforce_dependencies(self, item, column):
#if item is checked, look for dependent items and check them too
if item.checkState(0) == QtCore.Qt.Checked:
tools_by_name = {tool["name"]:tool for tool in self.__tools__}
try:
dependencies = tool["depends on"].split(",")
dependencies = tools_by_name[item.text(0)]["depends on"].split(",")
except KeyError:
continue
pass
else:
for dependency in [self.selection_menu.findItems(item, QtCore.Qt.MatchFixedString|QtCore.Qt.MatchCaseSensitive|QtCore.Qt.MatchRecursive) for item in dependencies]:
dependency.setSelected(True)
dependency.setHidden(False)
for dependency in dependencies:
for dependant_item in self.selection_menu.findItems(dependency, QtCore.Qt.MatchFixedString|QtCore.Qt.MatchCaseSensitive|QtCore.Qt.MatchRecursive):
dependant_item.setCheckState(0, QtCore.Qt.Checked)