Repository: spyder-ide/spyder

Issue:
Spyder crashes at startup after setting custom high DPI scaling at less than 1.0
### What steps reproduce the problem?

1. Spyder 4.0 crashes at startup after setting custom high DPI scaling at value less than 1.0
2. In Tools>Preferences>General>Interface set "Custom High DPI Scaling" at 0.8
3. Confirmation window "Spyder needs to restart to change the following setting" fails to list the new setting to be changed: shows only a blank bullet as opposed to when setting automatic high DPI scaling, which correctly shows the settings being changed.
4. When I hit yes to restart Spyder for the new setting to take effect, there is a floating point violation cum core dump.

### What is the expected output? What do you see instead?
When performing auto DPI scaling the resulting font size is way too small. Was playing around: scaling factors greater than one increase the default font size, less than one should make them smaller. Was looking for a scaling factor to better use the screen without it becoming illegible, used to do this in spyder 3.*

### ERROR MESSAGE in terminal:

(quant) cygnus_x1@BM-SurfaceBook-2:~$ spyder
[1:1:0100/000000.837530:ERROR:broker_posix.cc(41)] Invalid node channel message
[1:1:0100/000000.837621:ERROR:broker_posix.cc(41)] Invalid node channel message
Floating point exception (core dumped)

I am able to restart spyder after resetting (spyder --reset).

## Versions
* Spyder version: Spyder 4.0.0 
* Python version: Python 3.7.5 64-bit
* Qt version: Qt 5.9.6 
* PyQt version:  PyQt5 5.9.2
* Operating System name/version:  Linux 5.1.15-surface-linux-surface Ubuntu 18.04 LTS running on a Windows SurfaceBook 2 using the Linux jakeday kernel (https://github.com/jakeday/linux-surface)

### Dependencies
```
cloudpickle >=0.5.0          :  1.2.2 (OK)
pygments >=2.0               :  2.5.2 (OK)
qtconsole >=4.6.0            :  4.6.0 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
sphinx >=0.6.6               :  2.3.0 (OK)
pylint >=0.25                :  2.4.4 (OK)
psutil >=0.3                 :  5.6.7 (OK)
qtawesome >=0.5.7            :  0.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
zmq >=17                     :  18.1.0 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
numpydoc >=0.6.0             :  0.9.1 (OK)
spyder_kernels >=1.8.1;<2.0.0:  1.8.1 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
atomicwrites >=1.2.0         :  1.3.0 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
intervaltree                 :  None (OK)
watchdog                     :  None (OK)
keyring                      :  None (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pympler                      :  None (OK)
sympy >=0.7.3                :  None (NOK)
cython >=0.21                :  0.29.14 (OK)
IPython >=4.0                :  7.10.2 (OK)
matplotlib >=2.0.0           :  3.1.1 (OK)
pandas >=0.13.1              :  0.25.3 (OK)
numpy >=1.7                  :  1.17.4 (OK)
scipy >=0.17.0               :  1.3.2 (OK)
pyls >=0.31.2;<0.32.0        :  0.31.2 (OK)
xdg >=0.26                   :  0.26 (OK)
rtree >=0.8.3                :  0.8.3 (OK)
```



Discussion:
Reproduced the same error on another Ubuntu laptop running Linux 5.0.0-37-generic, so its not a problem with the jakeday kernel.
I can confirm this problem. It seems it's not possible to set a factor less than 1.0 by design.

@dalthviz, please take care of this one by adding a validation to the scaling factor so when users try to set a factor lesser than 1.0, we show a message saying that that's not possible and setting a value of 1.0 on it.
@Boris-Molina, you need to run

    spyder --reset

in a terminal to reset the previous setting and have a working Spyder again.

Resolving patch:
diff --git a/spyder/preferences/general.py b/spyder/preferences/general.py
--- a/spyder/preferences/general.py
+++ b/spyder/preferences/general.py
@@ -263,7 +263,7 @@ def set_open_file(state):
                                       "auto scaling does not work"),
                                 restart=True)
 
-        custom_scaling_edit = self.create_lineedit(
+        self.custom_scaling_edit = self.create_lineedit(
             "",
             'high_dpi_custom_scale_factors',
             tip=_("Enter values for different screens "
@@ -273,9 +273,10 @@ def set_open_file(state):
             regex=r"[0-9]+(?:\.[0-9]*)(;[0-9]+(?:\.[0-9]*))*",
             restart=True)
 
-        normal_radio.toggled.connect(custom_scaling_edit.setDisabled)
-        auto_scale_radio.toggled.connect(custom_scaling_edit.setDisabled)
-        custom_scaling_radio.toggled.connect(custom_scaling_edit.setEnabled)
+        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)
 
         # Layout Screen resolution
         screen_resolution_layout = QVBoxLayout()
@@ -285,7 +286,7 @@ def set_open_file(state):
         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(custom_scaling_edit, 2, 1)
+        screen_resolution_inner_layout.addWidget(self.custom_scaling_edit, 2, 1)
 
         screen_resolution_layout.addLayout(screen_resolution_inner_layout)
         screen_resolution_group.setLayout(screen_resolution_layout)
@@ -306,6 +307,27 @@ def set_open_file(state):
         self.setLayout(vlayout)
 
     def apply_settings(self, options):
+        if 'high_dpi_custom_scale_factors' in options:
+            scale_factors = self.get_option(
+                'high_dpi_custom_scale_factors').split(';')
+            change_min_scale_factor = False
+            for idx, scale_factor in enumerate(scale_factors[:]):
+                scale_factor = float(scale_factor)
+                if scale_factor < 1.0:
+                    change_min_scale_factor = True
+                    scale_factors[idx] = "1.0"
+            if change_min_scale_factor:
+                scale_factors_text = ";".join(scale_factors)
+                QMessageBox.critical(
+                    self, _("Error"),
+                    _("We're sorry but setting a scale factor bellow 1.0 "
+                      "isn't possible. Any scale factor bellow 1.0 will "
+                      "be set to 1.0"),
+                    QMessageBox.Ok)
+                self.custom_scaling_edit.textbox.setText(scale_factors_text)
+                self.set_option(
+                    'high_dpi_custom_scale_factors', scale_factors_text)
+                self.changed_options.add('high_dpi_custom_scale_factors')
         self.main.apply_settings()
 
     def _save_lang(self):


Test patch: