Addon Manager: Refactor to extract connection check GUI

This commit is contained in:
Chris Hennes
2022-11-10 15:09:15 -06:00
parent 818ab2b3ff
commit 103f8b77bf
3 changed files with 123 additions and 56 deletions

View File

@@ -54,7 +54,6 @@ from addonmanager_workers_installation import (
UpdateMetadataCacheWorker,
UpdateAllWorker,
)
from addonmanager_workers_utility import ConnectionChecker
import addonmanager_utilities as utils
import AddonManager_rc
from package_list import PackageList, PackageListItemModel
@@ -69,6 +68,7 @@ from manage_python_dependencies import (
)
from addonmanager_devmode import DeveloperMode
from addonmanager_firstrun import FirstRunDialog
from addonmanager_connection_checker import ConnectionCheckerGUI
import NetworkManager
@@ -111,7 +111,6 @@ class CommandAddonManager:
"""The main Addon Manager class and FreeCAD command"""
workers = [
"connection_checker",
"create_addon_list_worker",
"check_worker",
"show_worker",
@@ -164,6 +163,10 @@ class CommandAddonManager:
self.update_all_worker = None
self.developer_mode = None
# Set up the connection checker
self.connection_checker = ConnectionCheckerGUI()
self.connection_checker.connection_available.connect(self.launch)
# Give other parts of the AM access to the current instance
global INSTANCE
INSTANCE = self
@@ -184,61 +187,11 @@ class CommandAddonManager:
NetworkManager.InitializeNetworkManager()
firstRunDialog = FirstRunDialog()
readWarning = firstRunDialog.exec()
if not firstRunDialog.exec():
return
self.connection_checker.start()
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
dev_mode_active = pref.GetBool("developerMode", False)
if readWarning:
# Check the connection in a new thread, so FreeCAD stays responsive
self.connection_checker = ConnectionChecker()
self.connection_checker.success.connect(self.launch)
self.connection_checker.failure.connect(self.network_connection_failed)
self.connection_checker.start()
# If it takes longer than a half second to check the connection, show a message:
self.connection_message_timer = QtCore.QTimer.singleShot(
500, self.show_connection_check_message
)
def show_connection_check_message(self):
if not self.connection_checker.isFinished():
self.connection_check_message = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
translate("AddonsInstaller", "Checking connection"),
translate("AddonsInstaller", "Checking for connection to GitHub..."),
QtWidgets.QMessageBox.Cancel,
)
self.connection_check_message.buttonClicked.connect(
self.cancel_network_check
)
self.connection_check_message.show()
def cancel_network_check(self, _):
if not self.connection_checker.isFinished():
self.connection_checker.success.disconnect(self.launch)
self.connection_checker.failure.disconnect(self.network_connection_failed)
self.connection_checker.requestInterruption()
self.connection_checker.wait(500)
self.connection_check_message.close()
def network_connection_failed(self, message: str) -> None:
# This must run on the main GUI thread
if hasattr(self, "connection_check_message") and self.connection_check_message:
self.connection_check_message.close()
if NetworkManager.HAVE_QTNETWORK:
QtWidgets.QMessageBox.critical(
None, translate("AddonsInstaller", "Connection failed"), message
)
else:
QtWidgets.QMessageBox.critical(
None,
translate("AddonsInstaller", "Missing dependency"),
translate(
"AddonsInstaller",
"Could not import QtNetwork -- see Report View for details. Addon Manager unavailable.",
),
)
def launch(self) -> None:
"""Shows the Addon Manager UI"""

View File

@@ -7,6 +7,7 @@ SET(AddonManager_SRCS
Addon.py
AddonManager.py
AddonManager.ui
addonmanager_connection_checker.py
addonmanager_devmode.py
addonmanager_devmode_add_content.py
addonmanager_devmode_license_selector.py

View File

@@ -0,0 +1,113 @@
# ***************************************************************************
# * *
# * Copyright (c) 2022 FreeCAD Project Association *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD 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 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD 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 FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
""" System for checking the network connection status asynchronously. """
import FreeCAD
from PySide import QtCore, QtWidgets
import NetworkManager
from addonmanager_workers_utility import ConnectionChecker
translate = FreeCAD.Qt.translate
class ConnectionCheckerGUI(QtCore.QObject):
"""Determine whether there is an active network connection, showing a progress message if it
starts to take too long, and an error message if the network cannot be accessed."""
connection_available = QtCore.Signal()
check_complete = QtCore.Signal()
def __init__(self):
super().__init__()
# Check the connection in a new thread, so FreeCAD stays responsive
self.connection_checker = ConnectionChecker()
self.connection_checker.success.connect(self._check_succeeded)
self.connection_checker.failure.connect(self._network_connection_failed)
self.connection_message_timer = None
self.connection_check_message = None
def start(self):
"""Start the connection check"""
self.connection_checker.start()
# If it takes longer than a half second to check the connection, show a message:
self.connection_message_timer = QtCore.QTimer.singleShot(
500, self._show_connection_check_message
)
def _show_connection_check_message(self):
"""Display a message informing the user that the check is in process"""
if not self.connection_checker.isFinished():
self.connection_check_message = QtWidgets.QMessageBox(
QtWidgets.QMessageBox.Information,
translate("AddonsInstaller", "Checking connection"),
translate("AddonsInstaller", "Checking for connection to GitHub..."),
QtWidgets.QMessageBox.Cancel,
)
self.connection_check_message.buttonClicked.connect(
self.cancel_network_check
)
self.connection_check_message.show()
def cancel_network_check(self, _):
"""Cancel the check"""
if not self.connection_checker.isFinished():
self.connection_checker.success.disconnect(self.launch)
self.connection_checker.failure.disconnect(self.network_connection_failed)
self.connection_checker.requestInterruption()
self.connection_checker.wait(500)
self.connection_check_message.close()
self.check_complete.emit()
def _network_connection_failed(self, message: str) -> None:
"""Callback for failed connection check. Displays an error message, then emits the
check_complete signal (but not the connection available signal)."""
# This must run on the main GUI thread
if hasattr(self, "connection_check_message") and self.connection_check_message:
self.connection_check_message.close()
if NetworkManager.HAVE_QTNETWORK:
QtWidgets.QMessageBox.critical(
None, translate("AddonsInstaller", "Connection failed"), message
)
else:
#pylint: disable=line-too-long
QtWidgets.QMessageBox.critical(
None,
translate("AddonsInstaller", "Missing dependency"),
translate(
"AddonsInstaller",
"Could not import QtNetwork -- see Report View for details. Addon Manager unavailable.",
),
)
self.check_complete.emit()
def _check_succeeded(self):
"""Emit both the connection_available and the check_complete signals, in that order."""
self.connection_available.emit()
self.check_complete.emit()