From 8861408d57bbdf13ebf9631760cc7b78a29db111 Mon Sep 17 00:00:00 2001 From: jsbautista <42411448+jsbautista@users.noreply.github.com> Date: Tue, 18 Jul 2023 17:37:14 -0500 Subject: [PATCH] PR: Add help info widget to show tooltips in Preferences (UX/UI) (#20926) Co-authored-by: dalthviz Co-authored-by: Carlos Cordoba --- spyder/app/tests/test_mainwindow.py | 4 +- spyder/plugins/appearance/confpage.py | 7 +- spyder/plugins/application/confpage.py | 35 ++++-- spyder/plugins/completion/confpage.py | 9 +- .../languageserver/conftabs/advanced.py | 25 ++-- .../languageserver/conftabs/docstring.py | 2 +- .../languageserver/conftabs/formatting.py | 3 +- .../languageserver/conftabs/introspection.py | 3 +- .../languageserver/conftabs/linting.py | 2 +- spyder/plugins/editor/confpage.py | 10 +- spyder/plugins/ipythonconsole/confpage.py | 10 +- spyder/plugins/maininterpreter/confpage.py | 6 +- spyder/plugins/preferences/api.py | 109 ++++++++++++------ spyder/plugins/statusbar/confpage.py | 16 +-- spyder/plugins/variableexplorer/confpage.py | 10 +- spyder/plugins/workingdirectory/confpage.py | 10 +- spyder/utils/icon_manager.py | 1 + 17 files changed, 169 insertions(+), 93 deletions(-) diff --git a/spyder/app/tests/test_mainwindow.py b/spyder/app/tests/test_mainwindow.py index 9ed53465dd9..4f5fcd52c9a 100644 --- a/spyder/app/tests/test_mainwindow.py +++ b/spyder/app/tests/test_mainwindow.py @@ -3033,7 +3033,7 @@ def test_preferences_checkboxes_not_checked_regression(main_window, qtbot): check_name = tab_widgets[tabname] check = getattr(tab, check_name) page.tabs.setCurrentIndex(idx) - check.animateClick() + check.checkbox.animateClick() qtbot.wait(500) dlg.ok_btn.animateClick() @@ -3222,7 +3222,7 @@ def test_preferences_change_interpreter(qtbot, main_window): # Change main interpreter on preferences dlg, index, page = preferences_dialog_helper(qtbot, main_window, 'main_interpreter') - page.cus_exec_radio.setChecked(True) + page.cus_exec_radio.radiobutton.setChecked(True) page.cus_exec_combo.combobox.setCurrentText(sys.executable) mi_container = main_window.main_interpreter.get_container() diff --git a/spyder/plugins/appearance/confpage.py b/spyder/plugins/appearance/confpage.py index bc072c7fb41..4c3943ddf99 100644 --- a/spyder/plugins/appearance/confpage.py +++ b/spyder/plugins/appearance/confpage.py @@ -181,7 +181,8 @@ def setup_page(self): self.delete_button.clicked.connect(self.delete_scheme) self.schemes_combobox.currentIndexChanged.connect(self.update_preview) self.schemes_combobox.currentIndexChanged.connect(self.update_buttons) - system_font_checkbox.stateChanged.connect(self.update_app_font_group) + system_font_checkbox.checkbox.stateChanged.connect( + self.update_app_font_group) # Setup for name in names: @@ -191,8 +192,8 @@ def setup_page(self): self.scheme_editor_dialog.add_color_scheme_stack(name, custom=True) if sys.platform == 'darwin': - system_font_checkbox.setEnabled(False) - self.update_app_font_group(system_font_checkbox.isChecked()) + system_font_checkbox.checkbox.setEnabled(False) + self.update_app_font_group(system_font_checkbox.checkbox.isChecked()) self.update_combobox() self.update_preview() diff --git a/spyder/plugins/application/confpage.py b/spyder/plugins/application/confpage.py index 38df265a0b4..67ab45f22f9 100644 --- a/spyder/plugins/application/confpage.py +++ b/spyder/plugins/application/confpage.py @@ -102,8 +102,8 @@ def setup_page(self): 'use_custom_margin') margin_spin = self.create_spinbox("", _("pixels"), 'custom_margin', default=0, min_=0, max_=30) - margin_box.toggled.connect(margin_spin.spinbox.setEnabled) - margin_box.toggled.connect(margin_spin.slabel.setEnabled) + margin_box.checkbox.toggled.connect(margin_spin.spinbox.setEnabled) + margin_box.checkbox.toggled.connect(margin_spin.slabel.setEnabled) margin_spin.spinbox.setEnabled(self.get_option('use_custom_margin')) margin_spin.slabel.setEnabled(self.get_option('use_custom_margin')) @@ -114,8 +114,8 @@ def setup_page(self): 'custom_cursor_blinking', default=QApplication.cursorFlashTime(), min_=0, max_=5000, step=100) - cursor_box.toggled.connect(cursor_spin.spinbox.setEnabled) - cursor_box.toggled.connect(cursor_spin.slabel.setEnabled) + cursor_box.checkbox.toggled.connect(cursor_spin.spinbox.setEnabled) + cursor_box.checkbox.toggled.connect(cursor_spin.slabel.setEnabled) cursor_spin.spinbox.setEnabled( self.get_option('use_custom_cursor_blinking')) cursor_spin.slabel.setEnabled( @@ -153,7 +153,7 @@ def set_open_file(state): _("Open files from Finder with Spyder"), 'mac_open_file', tip=_("Register Spyder with the Launch Services")) - mac_open_file_box.toggled.connect(set_open_file) + mac_open_file_box.checkbox.toggled.connect(set_open_file) macOS_layout = QVBoxLayout() macOS_layout.addWidget(mac_open_file_box) if als.get_bundle_identifier() is None: @@ -207,10 +207,12 @@ def set_open_file(state): regex=r"[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*", restart=True) - normal_radio.toggled.connect(self.custom_scaling_edit.setDisabled) - auto_scale_radio.toggled.connect(self.custom_scaling_edit.setDisabled) - custom_scaling_radio.toggled.connect( - self.custom_scaling_edit.setEnabled) + normal_radio.radiobutton.toggled.connect( + self.custom_scaling_edit.textbox.setDisabled) + auto_scale_radio.radiobutton.toggled.connect( + self.custom_scaling_edit.textbox.setDisabled) + custom_scaling_radio.radiobutton.toggled.connect( + self.custom_scaling_edit.textbox.setEnabled) # Layout Screen resolution screen_resolution_layout = QVBoxLayout() @@ -218,10 +220,19 @@ def set_open_file(state): screen_resolution_inner_layout = QGridLayout() screen_resolution_inner_layout.addWidget(normal_radio, 0, 0) - screen_resolution_inner_layout.addWidget(auto_scale_radio, 1, 0) - screen_resolution_inner_layout.addWidget(custom_scaling_radio, 2, 0) screen_resolution_inner_layout.addWidget( - self.custom_scaling_edit, 2, 1) + auto_scale_radio.radiobutton, 1, 0) + screen_resolution_inner_layout.addWidget( + auto_scale_radio.radiobutton.help_label, 1, 1) + screen_resolution_inner_layout.addWidget( + custom_scaling_radio.radiobutton, 2, 0) + screen_resolution_inner_layout.addWidget( + custom_scaling_radio.radiobutton.help_label, 2, 1) + screen_resolution_inner_layout.addWidget( + self.custom_scaling_edit.textbox, 2, 2) + screen_resolution_inner_layout.addWidget( + self.custom_scaling_edit.help_label, 2, 3) + screen_resolution_inner_layout.setColumnStretch(2, 1) screen_resolution_layout.addLayout(screen_resolution_inner_layout) screen_resolution_group.setLayout(screen_resolution_layout) diff --git a/spyder/plugins/completion/confpage.py b/spyder/plugins/completion/confpage.py index dd30007314e..1ff6ff239c2 100644 --- a/spyder/plugins/completion/confpage.py +++ b/spyder/plugins/completion/confpage.py @@ -67,18 +67,23 @@ def setup_page(self): completions_layout.addWidget(completions_after_characters.plabel, 3, 0) completions_layout.addWidget( completions_after_characters.spinbox, 3, 1) + completions_layout.addWidget( + completions_after_characters.help_label, 3, 2) completions_layout.addWidget(completions_hint_after_idle.plabel, 5, 0) completions_layout.addWidget(completions_hint_after_idle.spinbox, 5, 1) + completions_layout.addWidget( + completions_hint_after_idle.help_label, 5, 2) completions_layout.addWidget(completions_wait_for_ms.plabel, 6, 0) completions_layout.addWidget(completions_wait_for_ms.spinbox, 6, 1) - completions_layout.setColumnStretch(2, 6) + completions_layout.addWidget(completions_wait_for_ms.help_label, 6, 2) + completions_layout.setColumnStretch(3, 6) self.completions_group.setLayout(completions_layout) def disable_completion_after_characters(state): completions_after_characters.plabel.setEnabled(state) completions_after_characters.spinbox.setEnabled(state) - automatic_completion_box.toggled.connect( + automatic_completion_box.checkbox.toggled.connect( disable_completion_after_characters) layout = QVBoxLayout() diff --git a/spyder/plugins/completion/providers/languageserver/conftabs/advanced.py b/spyder/plugins/completion/providers/languageserver/conftabs/advanced.py index 8b5c59b1d55..5bbee615779 100644 --- a/spyder/plugins/completion/providers/languageserver/conftabs/advanced.py +++ b/spyder/plugins/completion/providers/languageserver/conftabs/advanced.py @@ -59,8 +59,8 @@ def __init__(self, parent): self.use_stdio = self.create_checkbox( _("Use stdio pipes to communicate with server"), 'advanced/stdio') - self.use_stdio.stateChanged.connect(self.disable_tcp) - self.external_server.stateChanged.connect(self.disable_stdio) + self.use_stdio.checkbox.stateChanged.connect(self.disable_tcp) + self.external_server.checkbox.stateChanged.connect(self.disable_stdio) # Advanced layout advanced_g_layout = QGridLayout() @@ -87,9 +87,9 @@ def __init__(self, parent): advanced_options_widget = QWidget() advanced_options_widget.setLayout(advanced_options_layout) advanced_options_widget.setEnabled(self.get_option('advanced/enabled')) - self.advanced_options_check.toggled.connect( + self.advanced_options_check.checkbox.toggled.connect( advanced_options_widget.setEnabled) - self.advanced_options_check.toggled.connect( + self.advanced_options_check.checkbox.toggled.connect( self.show_advanced_warning) # Advanced options layout @@ -108,15 +108,16 @@ def disable_tcp(self, state): if state == Qt.Checked: self.advanced_host.textbox.setEnabled(False) self.advanced_port.spinbox.setEnabled(False) - self.external_server.stateChanged.disconnect() - self.external_server.setChecked(False) - self.external_server.setEnabled(False) + self.external_server.checkbox.stateChanged.disconnect() + self.external_server.checkbox.setChecked(False) + self.external_server.checkbox.setEnabled(False) else: self.advanced_host.textbox.setEnabled(True) self.advanced_port.spinbox.setEnabled(True) - self.external_server.setChecked(False) - self.external_server.setEnabled(True) - self.external_server.stateChanged.connect(self.disable_stdio) + self.external_server.checkbox.setChecked(False) + self.external_server.checkbox.setEnabled(True) + self.external_server.checkbox.stateChanged.connect( + self.disable_stdio) def disable_stdio(self, state): if state == Qt.Checked: @@ -167,10 +168,10 @@ def is_valid(self): # and we need to automatically check the corresponding # option if host not in ['127.0.0.1', 'localhost']: - self.external_server.setChecked(True) + self.external_server.checkbox.setChecked(True) # Checks for external PyLS - if self.external_server.isChecked(): + if self.external_server.checkbox.isChecked(): port = int(self.advanced_port.spinbox.text()) # Check that host and port of the current server are diff --git a/spyder/plugins/completion/providers/languageserver/conftabs/docstring.py b/spyder/plugins/completion/providers/languageserver/conftabs/docstring.py index e38d50ad0a8..f6d91093d7a 100644 --- a/spyder/plugins/completion/providers/languageserver/conftabs/docstring.py +++ b/spyder/plugins/completion/providers/languageserver/conftabs/docstring.py @@ -108,7 +108,7 @@ def __init__(self, parent): docstring_style_g_widget = QWidget() docstring_style_g_widget.setLayout(docstring_style_g_layout) docstring_style_g_widget.setEnabled(self.get_option('pydocstyle')) - self.docstring_style_check.toggled.connect( + self.docstring_style_check.checkbox.toggled.connect( docstring_style_g_widget.setEnabled) # Docstring style layout diff --git a/spyder/plugins/completion/providers/languageserver/conftabs/formatting.py b/spyder/plugins/completion/providers/languageserver/conftabs/formatting.py index 874ee394958..42e90472cd4 100644 --- a/spyder/plugins/completion/providers/languageserver/conftabs/formatting.py +++ b/spyder/plugins/completion/providers/languageserver/conftabs/formatting.py @@ -92,7 +92,8 @@ def __init__(self, parent): code_style_g_widget = QWidget() code_style_g_widget.setLayout(code_style_g_layout) code_style_g_widget.setEnabled(self.get_option('pycodestyle')) - self.code_style_check.toggled.connect(code_style_g_widget.setEnabled) + self.code_style_check.checkbox.toggled.connect( + code_style_g_widget.setEnabled) # Code style layout code_style_group = QGroupBox(_("Code style")) diff --git a/spyder/plugins/completion/providers/languageserver/conftabs/introspection.py b/spyder/plugins/completion/providers/languageserver/conftabs/introspection.py index ec4405e1aa8..e43afb84c0d 100644 --- a/spyder/plugins/completion/providers/languageserver/conftabs/introspection.py +++ b/spyder/plugins/completion/providers/languageserver/conftabs/introspection.py @@ -54,7 +54,8 @@ def __init__(self, parent): introspection_layout.addWidget(enable_hover_hints_box) introspection_group.setLayout(introspection_layout) - goto_definition_box.toggled.connect(follow_imports_box.setEnabled) + goto_definition_box.checkbox.toggled.connect( + follow_imports_box.setEnabled) # Advanced group advanced_group = QGroupBox(_("Advanced")) diff --git a/spyder/plugins/completion/providers/languageserver/conftabs/linting.py b/spyder/plugins/completion/providers/languageserver/conftabs/linting.py index 68e4780472c..dac11a1b817 100644 --- a/spyder/plugins/completion/providers/languageserver/conftabs/linting.py +++ b/spyder/plugins/completion/providers/languageserver/conftabs/linting.py @@ -48,4 +48,4 @@ def __init__(self, parent): linting_layout.addWidget(underline_errors_box) linting_layout.addWidget(linting_complexity_box) self.setLayout(linting_layout) - linting_check.toggled.connect(underline_errors_box.setEnabled) + linting_check.checkbox.toggled.connect(underline_errors_box.setEnabled) diff --git a/spyder/plugins/editor/confpage.py b/spyder/plugins/editor/confpage.py index 7464cff5cbe..5f3ac1d0feb 100644 --- a/spyder/plugins/editor/confpage.py +++ b/spyder/plugins/editor/confpage.py @@ -65,8 +65,10 @@ def setup_page(self): "", _(" ms"), 'occurrence_highlighting/timeout', min_=100, max_=1000000, step=100) - occurrence_box.toggled.connect(occurrence_spin.spinbox.setEnabled) - occurrence_box.toggled.connect(occurrence_spin.slabel.setEnabled) + occurrence_box.checkbox.toggled.connect( + occurrence_spin.spinbox.setEnabled) + occurrence_box.checkbox.toggled.connect( + occurrence_spin.slabel.setEnabled) occurrence_spin.spinbox.setEnabled( self.get_option('occurrence_highlighting')) occurrence_spin.slabel.setEnabled( @@ -220,7 +222,7 @@ def enable_tabwidth_spin(index): _('seconds'), 'autosave_interval', min_=1, max_=3600) - autosave_checkbox.toggled.connect(autosave_spinbox.setEnabled) + autosave_checkbox.checkbox.toggled.connect(autosave_spinbox.setEnabled) autosave_layout = QVBoxLayout() autosave_layout.addWidget(autosave_checkbox) @@ -297,7 +299,7 @@ def enable_tabwidth_spin(index): eol_combo_choices, 'convert_eol_on_save_to', ) - convert_eol_on_save_box.toggled.connect( + convert_eol_on_save_box.checkbox.toggled.connect( convert_eol_on_save_combo.setEnabled) convert_eol_on_save_combo.setEnabled( self.get_option('convert_eol_on_save')) diff --git a/spyder/plugins/ipythonconsole/confpage.py b/spyder/plugins/ipythonconsole/confpage.py index 22d3defa639..19f37b029e3 100644 --- a/spyder/plugins/ipythonconsole/confpage.py +++ b/spyder/plugins/ipythonconsole/confpage.py @@ -94,7 +94,7 @@ def setup_page(self): "plotting libraries different to Matplotlib or to develop\n" "GUIs with Spyder.")) autoload_pylab_box.setEnabled(self.get_option('pylab')) - pylab_box.toggled.connect(autoload_pylab_box.setEnabled) + pylab_box.checkbox.toggled.connect(autoload_pylab_box.setEnabled) pylab_layout = QVBoxLayout() pylab_layout.addWidget(pylab_box) @@ -131,7 +131,7 @@ def setup_page(self): backend_layout.addWidget(backend_box) backend_group.setLayout(backend_layout) backend_group.setEnabled(self.get_option('pylab')) - pylab_box.toggled.connect(backend_group.setEnabled) + pylab_box.checkbox.toggled.connect(backend_group.setEnabled) # Inline backend Group inline_group = QGroupBox(_("Inline backend")) @@ -186,7 +186,7 @@ def setup_page(self): inline_v_layout.addLayout(inline_h_layout) inline_group.setLayout(inline_v_layout) inline_group.setEnabled(self.get_option('pylab')) - pylab_box.toggled.connect(inline_group.setEnabled) + pylab_box.checkbox.toggled.connect(inline_group.setEnabled) # --- Startup --- # Run lines Group @@ -215,7 +215,7 @@ def setup_page(self): 'startup/use_run_file', False) run_file_browser = self.create_browsefile('', 'startup/run_file', '') run_file_browser.setEnabled(False) - file_radio.toggled.connect(run_file_browser.setEnabled) + file_radio.checkbox.toggled.connect(run_file_browser.setEnabled) run_file_layout = QVBoxLayout() run_file_layout.addWidget(run_file_label) @@ -338,8 +338,10 @@ def setup_page(self): prompts_g_layout = QGridLayout() prompts_g_layout.addWidget(in_prompt_edit.label, 0, 0) prompts_g_layout.addWidget(in_prompt_edit.textbox, 0, 1) + prompts_g_layout.addWidget(in_prompt_edit.help_label, 0, 2) prompts_g_layout.addWidget(out_prompt_edit.label, 1, 0) prompts_g_layout.addWidget(out_prompt_edit.textbox, 1, 1) + prompts_g_layout.addWidget(out_prompt_edit.help_label, 1, 2) prompts_layout.addLayout(prompts_g_layout) prompts_group.setLayout(prompts_layout) diff --git a/spyder/plugins/maininterpreter/confpage.py b/spyder/plugins/maininterpreter/confpage.py index 368a4bc58ae..b568edcef44 100644 --- a/spyder/plugins/maininterpreter/confpage.py +++ b/spyder/plugins/maininterpreter/confpage.py @@ -99,8 +99,10 @@ def setup_page(self): adjust_to_contents=True, validate_callback=programs.is_python_interpreter, ) - self.def_exec_radio.toggled.connect(self.cus_exec_combo.setDisabled) - self.cus_exec_radio.toggled.connect(self.cus_exec_combo.setEnabled) + self.def_exec_radio.radiobutton.toggled.connect( + self.cus_exec_combo.setDisabled) + self.cus_exec_radio.radiobutton.toggled.connect( + self.cus_exec_combo.setEnabled) pyexec_layout.addWidget(self.cus_exec_combo) pyexec_group.setLayout(pyexec_layout) diff --git a/spyder/plugins/preferences/api.py b/spyder/plugins/preferences/api.py index 3b7efcebe67..f0626125476 100644 --- a/spyder/plugins/preferences/api.py +++ b/spyder/plugins/preferences/api.py @@ -16,13 +16,13 @@ from qtpy import API from qtpy.compat import (getexistingdirectory, getopenfilename, from_qvariant, to_qvariant) -from qtpy.QtCore import Qt, Signal, Slot, QRegExp -from qtpy.QtGui import QColor, QRegExpValidator, QTextOption +from qtpy.QtCore import Qt, Signal, Slot, QRegExp, QSize +from qtpy.QtGui import QColor, QRegExpValidator, QTextOption, QPixmap from qtpy.QtWidgets import (QButtonGroup, QCheckBox, QComboBox, QDoubleSpinBox, QFileDialog, QFontComboBox, QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QMessageBox, QPlainTextEdit, QPushButton, QRadioButton, - QSpinBox, QTabWidget, QVBoxLayout, QWidget) + QSpinBox, QTabWidget, QVBoxLayout, QWidget, QSizePolicy) # Local imports from spyder.config.base import _ @@ -30,6 +30,7 @@ from spyder.config.user import NoDefault from spyder.py3compat import to_text_string from spyder.utils.icon_manager import ima +from spyder.utils.image_path_manager import get_image_path from spyder.utils.misc import getcwd_or_home from spyder.widgets.colors import ColorLayout from spyder.widgets.comboboxes import FileComboBox @@ -440,15 +441,29 @@ def has_been_modified(self, section, option): else: self.changed_options.add((section, option)) + def add_help_info_label(self, layout, tip_text): + help_label = QLabel() + image = ima.icon('help_gray').pixmap(QSize(20, 20)) + help_label.setPixmap(image) + help_label.setFixedWidth(23) + help_label.setFixedHeight(23) + help_label.setToolTip(tip_text) + layout.addWidget(help_label) + layout.addStretch(100) + + return layout, help_label + def create_checkbox(self, text, option, default=NoDefault, tip=None, msg_warning=None, msg_info=None, msg_if_enabled=False, section=None, restart=False): + layout = QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) checkbox = QCheckBox(text) + layout.addWidget(checkbox) + self.checkboxes[checkbox] = (section, option, default) if section is not None and section != self.CONF_SECTION: self.cross_section_options[option] = section - if tip is not None: - checkbox.setToolTip(tip) if msg_warning is not None or msg_info is not None: def show_message(is_checked=False): if is_checked or not msg_if_enabled: @@ -460,13 +475,24 @@ def show_message(is_checked=False): msg_info, QMessageBox.Ok) checkbox.clicked.connect(show_message) checkbox.restart_required = restart - return checkbox + + widget = QWidget(self) + widget.checkbox = checkbox + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label + widget.setLayout(layout) + return widget def create_radiobutton(self, text, option, default=NoDefault, tip=None, msg_warning=None, msg_info=None, msg_if_enabled=False, button_group=None, restart=False, section=None): + layout = QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) radiobutton = QRadioButton(text) + layout.addWidget(radiobutton) + if section is not None and section != self.CONF_SECTION: self.cross_section_options[option] = section if button_group is None: @@ -474,8 +500,6 @@ def create_radiobutton(self, text, option, default=NoDefault, self.default_button_group = QButtonGroup(self) button_group = self.default_button_group button_group.addButton(radiobutton) - if tip is not None: - radiobutton.setToolTip(tip) self.radiobuttons[radiobutton] = (section, option, default) if msg_warning is not None or msg_info is not None: def show_message(is_checked): @@ -489,7 +513,14 @@ def show_message(is_checked): radiobutton.toggled.connect(show_message) radiobutton.restart_required = restart radiobutton.label_text = text - return radiobutton + + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + radiobutton.help_label = help_label + widget = QWidget(self) + widget.radiobutton = radiobutton + widget.setLayout(layout) + return widget def create_lineedit(self, text, option, default=NoDefault, tip=None, alignment=Qt.Vertical, regex=None, @@ -505,16 +536,18 @@ def create_lineedit(self, text, option, default=NoDefault, layout.addWidget(label) layout.addWidget(edit) layout.setContentsMargins(0, 0, 0, 0) - if tip: - edit.setToolTip(tip) if regex: edit.setValidator(QRegExpValidator(QRegExp(regex))) if placeholder: edit.setPlaceholderText(placeholder) self.lineedits[edit] = (section, option, default) + widget = QWidget(self) widget.label = label widget.textbox = edit + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label widget.setLayout(layout) edit.restart_required = restart edit.label_text = text @@ -534,12 +567,14 @@ def create_textedit(self, text, option, default=NoDefault, layout.addWidget(label) layout.addWidget(edit) layout.setContentsMargins(0, 0, 0, 0) - if tip: - edit.setToolTip(tip) self.textedits[edit] = (section, option, default) + widget = QWidget(self) widget.label = label widget.textbox = edit + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label widget.setLayout(layout) edit.restart_required = restart edit.label_text = text @@ -561,6 +596,8 @@ def create_browsedir(self, text, option, default=NoDefault, tip=None, layout.addWidget(widget) layout.addWidget(browse_btn) layout.setContentsMargins(0, 0, 0, 0) + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) browsedir = QWidget(self) browsedir.setLayout(layout) return browsedir @@ -591,6 +628,8 @@ def create_browsefile(self, text, option, default=NoDefault, tip=None, layout.addWidget(widget) layout.addWidget(browse_btn) layout.setContentsMargins(0, 0, 0, 0) + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) browsedir = QWidget(self) browsedir.setLayout(layout) return browsedir @@ -636,9 +675,7 @@ def create_spinbox(self, prefix, suffix, option, default=NoDefault, if min_ is not None: spinbox.setMinimum(min_) if max_ is not None: - spinbox.setMaximum(max_) - if tip is not None: - spinbox.setToolTip(tip) + spinbox.setMaximum(max_) self.spinboxes[spinbox] = (section, option, default) layout = QHBoxLayout() for subwidget in (plabel, spinbox, slabel): @@ -647,6 +684,9 @@ def create_spinbox(self, prefix, suffix, option, default=NoDefault, layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) widget.spinbox = spinbox + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label widget.setLayout(layout) return widget @@ -657,8 +697,6 @@ def create_coloredit(self, text, option, default=NoDefault, tip=None, label = QLabel(text) clayout = ColorLayout(QColor(Qt.black), self) clayout.lineedit.setMaximumWidth(80) - if tip is not None: - clayout.setToolTip(tip) self.coloredits[clayout] = (section, option, default) if without_layout: return label, clayout @@ -667,6 +705,9 @@ def create_coloredit(self, text, option, default=NoDefault, tip=None, layout.addLayout(clayout) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget = QWidget(self) widget.setLayout(layout) return widget @@ -678,8 +719,6 @@ def create_scedit(self, text, option, default=NoDefault, tip=None, label = QLabel(text) clayout = ColorLayout(QColor(Qt.black), self) clayout.lineedit.setMaximumWidth(80) - if tip is not None: - clayout.setToolTip(tip) cb_bold = QCheckBox() cb_bold.setIcon(ima.icon('bold')) cb_bold.setToolTip(_("Bold")) @@ -698,6 +737,8 @@ def create_scedit(self, text, option, default=NoDefault, tip=None, layout.addWidget(cb_italic) layout.addStretch(1) layout.setContentsMargins(0, 0, 0, 0) + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) widget = QWidget(self) widget.setLayout(layout) return widget @@ -709,8 +750,6 @@ def create_combobox(self, text, choices, option, default=NoDefault, self.cross_section_options[option] = section label = QLabel(text) combobox = QComboBox() - if tip is not None: - combobox.setToolTip(tip) for name, key in choices: if not (name is None and key is None): combobox.addItem(name, to_qvariant(key)) @@ -730,6 +769,9 @@ def create_combobox(self, text, choices, option, default=NoDefault, widget = QWidget(self) widget.label = label widget.combobox = combobox + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label widget.setLayout(layout) combobox.restart_required = restart combobox.label_text = text @@ -751,9 +793,6 @@ def create_file_combobox(self, text, choices, option, default=NoDefault, edit.label_text = text edit.restart_required = restart self.lineedits[edit] = (section, option, default) - - if tip is not None: - combobox.setToolTip(tip) combobox.addItems(choices) combobox.choices = choices @@ -771,9 +810,13 @@ def create_file_combobox(self, text, choices, option, default=NoDefault, layout.addWidget(combobox, 0, 0, 0, 9) layout.addWidget(browse_btn, 0, 10) layout.setContentsMargins(0, 0, 0, 0) + widget = QWidget(self) widget.combobox = combobox widget.browse_btn = browse_btn + if tip is not None: + layout, help_label = self.add_help_info_label(layout, tip) + widget.help_label = help_label widget.setLayout(layout) return widget @@ -808,13 +851,6 @@ def create_fontgroup(self, option=None, text=None, title=None, layout.addWidget(subwidget) layout.addStretch(1) - widget = QWidget(self) - widget.fontlabel = fontlabel - widget.sizelabel = sizelabel - widget.fontbox = fontbox - widget.sizebox = sizebox - widget.setLayout(layout) - if not without_group: if text is None: text = _("Font style") @@ -823,10 +859,17 @@ def create_fontgroup(self, option=None, text=None, title=None, group.setLayout(layout) if tip is not None: - group.setToolTip(tip) + layout, help_label = self.add_help_info_label(layout, tip) return group else: + widget = QWidget(self) + widget.fontlabel = fontlabel + widget.sizelabel = sizelabel + widget.fontbox = fontbox + widget.sizebox = sizebox + widget.setLayout(layout) + return widget def create_button(self, text, callback): diff --git a/spyder/plugins/statusbar/confpage.py b/spyder/plugins/statusbar/confpage.py index 3119a1d0cc8..9c7fdc3e14c 100644 --- a/spyder/plugins/statusbar/confpage.py +++ b/spyder/plugins/statusbar/confpage.py @@ -22,18 +22,18 @@ def setup_page(self): # --- Status bar sbar_group = QGroupBox(_("Display")) - memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable', - tip=self.plugin.mem_status.toolTip()) + memory_box = newcb(_("Show memory usage every"), 'memory_usage/enable') memory_spin = self.create_spinbox("", _(" ms"), 'memory_usage/timeout', - min_=100, max_=1000000, step=100) - memory_box.toggled.connect(memory_spin.setEnabled) + min_=100, max_=1000000, step=100, + tip=self.plugin.mem_status.toolTip()) + memory_box.checkbox.toggled.connect(memory_spin.setEnabled) memory_spin.setEnabled(self.get_option('memory_usage/enable')) - cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable', - tip=self.plugin.cpu_status.toolTip()) + cpu_box = newcb(_("Show CPU usage every"), 'cpu_usage/enable') cpu_spin = self.create_spinbox("", _(" ms"), 'cpu_usage/timeout', - min_=100, max_=1000000, step=100) - cpu_box.toggled.connect(cpu_spin.setEnabled) + min_=100, max_=1000000, step=100, + tip=self.plugin.cpu_status.toolTip()) + cpu_box.checkbox.toggled.connect(cpu_spin.setEnabled) cpu_spin.setEnabled(self.get_option('cpu_usage/enable')) clock_box = newcb(_("Show clock"), 'clock/enable') diff --git a/spyder/plugins/variableexplorer/confpage.py b/spyder/plugins/variableexplorer/confpage.py index bd3ae283cdd..e07a5d9008b 100644 --- a/spyder/plugins/variableexplorer/confpage.py +++ b/spyder/plugins/variableexplorer/confpage.py @@ -30,8 +30,14 @@ def setup_page(self): ('exclude_callables_and_modules', _("Exclude callables and modules")) ] - filter_boxes = [self.create_checkbox(text, option) - for option, text in filter_data] + filter_boxes = [ + self.create_checkbox( + text, + option, + tip='Excludes variables that fit the description' + ) + for option, text in filter_data + ] display_group = QGroupBox(_("Display")) display_data = [('minmax', _("Show arrays min/max"), '')] diff --git a/spyder/plugins/workingdirectory/confpage.py b/spyder/plugins/workingdirectory/confpage.py index 66133682a00..0112345ce9d 100644 --- a/spyder/plugins/workingdirectory/confpage.py +++ b/spyder/plugins/workingdirectory/confpage.py @@ -57,8 +57,8 @@ def setup_page(self): 'startup/fixed_directory', getcwd_or_home() ) - thisdir_radio.toggled.connect(thisdir_bd.setEnabled) - lastdir_radio.toggled.connect(thisdir_bd.setDisabled) + thisdir_radio.radiobutton.toggled.connect(thisdir_bd.setEnabled) + lastdir_radio.radiobutton.toggled.connect(thisdir_bd.setDisabled) thisdir_layout = QHBoxLayout() thisdir_layout.addWidget(thisdir_radio) thisdir_layout.addWidget(thisdir_bd) @@ -100,9 +100,9 @@ def setup_page(self): 'console/fixed_directory', getcwd_or_home() ) - console_dir_radio.toggled.connect(console_dir_bd.setEnabled) - console_project_radio.toggled.connect(console_dir_bd.setDisabled) - console_cwd_radio.toggled.connect(console_dir_bd.setDisabled) + console_dir_radio.radiobutton.toggled.connect(console_dir_bd.setEnabled) + console_project_radio.radiobutton.toggled.connect(console_dir_bd.setDisabled) + console_cwd_radio.radiobutton.toggled.connect(console_dir_bd.setDisabled) console_dir_layout = QHBoxLayout() console_dir_layout.addWidget(console_dir_radio) console_dir_layout.addWidget(console_dir_bd) diff --git a/spyder/utils/icon_manager.py b/spyder/utils/icon_manager.py index cc21dface1a..8ef8eeaa4b1 100644 --- a/spyder/utils/icon_manager.py +++ b/spyder/utils/icon_manager.py @@ -167,6 +167,7 @@ def __init__(self): 'pythonpath': [('spyder.python-logo-up', 'spyder.python-logo-down'), {'options': [{'color': SpyderPalette.PYTHON_LOGO_UP}, {'color': SpyderPalette.PYTHON_LOGO_DOWN}]}], 'findf': [('mdi.file-find',), {'color': self.MAIN_FG_COLOR}], 'history': [('mdi.history',), {'color': self.MAIN_FG_COLOR}], + 'help_gray': [('mdi.help-circle-outline',), {'color': SpyderPalette.COLOR_OCCURRENCE_4}], 'help': [('mdi.help-circle',), {'color': self.MAIN_FG_COLOR}], 'lock': [('mdi.lock',), {'color': self.MAIN_FG_COLOR}], 'lock_open': [('mdi.lock-open',), {'color': self.MAIN_FG_COLOR}],