Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Move check for possible updates after the main window is visible (Application) #15988

Merged
merged 5 commits into from
Jul 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions spyder/plugins/application/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@
import sys

# Third party imports
from qtpy.QtCore import Qt, QThread, Slot
from qtpy.QtWidgets import QMessageBox, QAction
from qtpy.QtCore import Qt, QThread, QTimer, Slot
from qtpy.QtWidgets import QAction, QMessageBox

# Local imports
from spyder import (
__docs_url__, __forum_url__, __project_url__, __trouble_url__)
from spyder import dependencies
from spyder.api.translations import get_translation
from spyder.api.widgets.main_container import PluginMainContainer
from spyder.config.base import DEV
from spyder.config.utils import is_anaconda
from spyder.utils.qthelpers import start_file, DialogManager
from spyder.widgets.about import AboutDialog
Expand Down Expand Up @@ -64,7 +63,11 @@ class ApplicationActions:


class ApplicationContainer(PluginMainContainer):

def setup(self):
# Compute dependencies in a thread to not block the interface.
self.dependencies_thread = QThread()

# Attributes
self.dialog_manager = DialogManager()
self.give_updates_feedback = False
Expand Down Expand Up @@ -142,11 +145,6 @@ def setup(self):
shortcut_context="_",
register_shortcut=True)

# Initialize
if DEV is None and self.get_conf('check_updates_on_startup'):
self.give_updates_feedback = False
self.check_updates(startup=True)

def update_actions(self):
pass

Expand Down Expand Up @@ -174,6 +172,7 @@ def _check_updates_ready(self):
box = MessageCheckBox(icon=QMessageBox.Information,
parent=self)
box.setWindowTitle(_("New Spyder version"))
box.setAttribute(Qt.WA_ShowWithoutActivating)
box.set_checkbox_text(_("Check for updates at startup"))
box.setStandardButtons(QMessageBox.Ok)
box.setDefaultButton(QMessageBox.Ok)
Expand Down Expand Up @@ -216,7 +215,7 @@ def _check_updates_ready(self):
msg = header + content + footer
box.setText(msg)
box.set_check_visible(True)
box.exec_()
box.show()
check_updates = box.is_checked()
elif feedback:
msg = _("Spyder is up to date.")
Expand Down Expand Up @@ -249,7 +248,15 @@ def check_updates(self, startup=False):
self.worker_updates.sig_ready.connect(self.thread_updates.quit)
self.worker_updates.moveToThread(self.thread_updates)
self.thread_updates.started.connect(self.worker_updates.start)
self.thread_updates.start()

# Delay starting this check to avoid blocking the main window
# while loading.
# Fixes spyder-ide/spyder#15839
updates_timer = QTimer(self)
updates_timer.setInterval(3000)
updates_timer.setSingleShot(True)
updates_timer.timeout.connect(self.thread_updates.start)
updates_timer.start()

@Slot()
def show_dependencies(self):
Expand All @@ -271,7 +278,16 @@ def show_windows_env_variables(self):

def compute_dependencies(self):
"""Compute dependencies"""
dependencies.declare_dependencies()
self.dependencies_thread.run = dependencies.declare_dependencies
self.dependencies_thread.finished.connect(
self.report_missing_dependencies)

# This avoids computing missing deps before the window is fully up
dependencies_timer = QTimer(self)
dependencies_timer.setInterval(10000)
dependencies_timer.setSingleShot(True)
dependencies_timer.timeout.connect(self.dependencies_thread.start)
dependencies_timer.start()

@Slot()
def report_missing_dependencies(self):
Expand Down Expand Up @@ -304,6 +320,7 @@ def report_missing_dependencies(self):
message_box = QMessageBox(self)
message_box.setIcon(QMessageBox.Critical)
message_box.setAttribute(Qt.WA_DeleteOnClose)
message_box.setAttribute(Qt.WA_ShowWithoutActivating)
message_box.setStandardButtons(QMessageBox.Ok)
message_box.setWindowModality(Qt.NonModal)
message_box.setWindowTitle(_('Error'))
Expand Down
34 changes: 12 additions & 22 deletions spyder/plugins/application/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import sys

# Third party imports
from qtpy.QtCore import Qt, QThread, QTimer, Slot
from qtpy.QtCore import Slot
from qtpy.QtWidgets import QMenu

# Local imports
Expand Down Expand Up @@ -43,12 +43,6 @@ class Application(SpyderPluginV2):
CONF_FILE = False
CONF_WIDGET_CLASS = ApplicationConfigPage

def __init__(self, parent, configuration=None):
super().__init__(parent, configuration)

# Compute dependencies in a thread to not block the interface.
self.dependencies_thread = QThread()

def get_name(self):
return _('Application')

Expand Down Expand Up @@ -92,23 +86,19 @@ def on_close(self):

def on_mainwindow_visible(self):
"""Actions after the mainwindow in visible."""
container = self.get_container()

# Show dialog with missing dependencies
if not running_under_pytest():
container = self.get_container()
self.dependencies_thread.run = container.compute_dependencies
self.dependencies_thread.finished.connect(
container.report_missing_dependencies)

# This avoids computing missing deps before the window is fully up
dependencies_timer = QTimer(self)
dependencies_timer.setInterval(10000)
dependencies_timer.setSingleShot(True)
dependencies_timer.timeout.connect(self.dependencies_thread.start)
dependencies_timer.start()

# --- Private methods
# ------------------------------------------------------------------------
container.compute_dependencies()

# Check for updates
if DEV is None and self.get_conf('check_updates_on_startup'):
container.give_updates_feedback = False
container.check_updates(startup=True)

# ---- Private methods
# ------------------------------------------------------------------------
def _populate_file_menu(self):
mainmenu = self.get_plugin(Plugins.MainMenu)
if mainmenu:
Expand Down Expand Up @@ -172,7 +162,7 @@ def _populate_help_menu_about_section(self, mainmenu):
menu_id=ApplicationMenus.Help,
section=HelpMenuSections.About)

# --- Public API
# ---- Public API
# ------------------------------------------------------------------------
def get_application_context_menu(self, parent=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion spyder/plugins/ipythonconsole/widgets/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ def reset_namespace(self, warning=False, message=False):
box.set_check_visible(True)
box.setText(warn_str)

answer = box.exec_()
answer = box.show()

# Update checkbox based on user interaction
self.set_conf(
Expand Down
3 changes: 2 additions & 1 deletion spyder/widgets/helperwidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class MessageCheckBox(QMessageBox):
def __init__(self, *args, **kwargs):
super(MessageCheckBox, self).__init__(*args, **kwargs)

self._checkbox = QCheckBox()
self.setWindowModality(Qt.NonModal)
self._checkbox = QCheckBox(self)

# Set layout to include checkbox
size = 9
Expand Down