Repository: biolab/orange3

Issue:
`available_font_families` crashes if default font is missing
<!--
If something's not right with Orange, fill out the bug report template at:
https://github.com/biolab/orange3/issues/new?assignees=&labels=bug+report&template=bug_report.md&title=

If you have an idea for a new feature, fill out the feature request template at:
https://github.com/biolab/orange3/issues/new?assignees=&labels=&template=feature_request.md&title=
-->
- [ ] **What's wrong?**
<!-- Be specific, clear, and concise. Include screenshots if relevant. -->
<!-- If you're getting an error message, copy it, and enclose it with three backticks (```). -->

![캡처](https://user-images.githubusercontent.com/42027890/96339589-a7d61800-10d0-11eb-99cc-355e3d774de1.PNG)


- [ ] **How can we reproduce the problem?** 
<!-- Upload a zip with the .ows file and data. -->
<!-- Describe the steps (open this widget, click there, then add this...) -->






- [ ] **Which version of Orange are you using? How did you install Orange?**
<!-- See "Help → About → Version" or `Orange.version.full_version` in code -->





- [ ] **What is your operating system?**







Discussion:
Traceback (most recent call last):
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\orangecanvas\scheme\widgetmanager.py", line 231, in __add_widget_for_node
    w = self.create_widget_for_node(node)
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\orangewidget\workflow\widgetsscheme.py", line 296, in create_widget_for_node
    widget = self.create_widget_instance(node)
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\orangewidget\workflow\widgetsscheme.py", line 409, in create_widget_instance
    widget.__init__()
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\owscatterplot.py", line 269, in __init__
    super().__init__()
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\utils\widget.py", line 405, in __init__
    self.setup_gui()
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\utils\widget.py", line 410, in setup_gui
    self._add_graph()
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\utils\widget.py", line 417, in _add_graph
    self.graph = self.GRAPH_CLASS(self, box)
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\owscatterplot.py", line 122, in __init__
    super().__init__(scatter_widget, parent)
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\owscatterplotgraph.py", line 591, in __init__
    self.parameter_setter = ScatterBaseParameterSetter(self)
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\owscatterplotgraph.py", line 369, in __init__
    super().__init__()
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\utils\customizableplot.py", line 266, in __init__
    Updater.FONT_FAMILY_LABEL: (available_font_families(), QFont().family()),
  File "C:\Users\user\Downloads\Orange3-3.27.0\Orange\lib\site-packages\Orange\widgets\visualize\utils\customizableplot.py", line 31, in available_font_families
    default = fonts.pop(fonts.index(default_font_family()))
ValueError: 'Gulim' is not in list

Resolving patch:
diff --git a/Orange/widgets/visualize/utils/customizableplot.py b/Orange/widgets/visualize/utils/customizableplot.py
--- a/Orange/widgets/visualize/utils/customizableplot.py
+++ b/Orange/widgets/visualize/utils/customizableplot.py
@@ -28,8 +28,11 @@ def available_font_families() -> List:
     if not QApplication.instance():
         _ = QApplication(sys.argv)
     fonts = QFontDatabase().families()
-    default = fonts.pop(fonts.index(default_font_family()))
+    default = default_font_family()
+
     defaults = [default]
+    if default in fonts:
+        fonts.remove(default)
 
     guessed_name = default.split()[0]
     i = 0
@@ -263,7 +266,7 @@ def update_axis(axis, **settings):
                 self.getAxis(axis), settings[self.TITLE_LABEL])
 
         self.FONT_FAMILY_SETTING: SettingsType = {  # pylint: disable=invalid-name
-            Updater.FONT_FAMILY_LABEL: (available_font_families(), QFont().family()),
+            Updater.FONT_FAMILY_LABEL: (available_font_families(), default_font_family()),
         }
 
         self.FONT_SETTING: SettingsType = {  # pylint: disable=invalid-name


Test patch:
diff --git a/Orange/widgets/visualize/utils/tests/test_customizableplot.py b/Orange/widgets/visualize/utils/tests/test_customizableplot.py
new file mode 100644
--- /dev/null
+++ b/Orange/widgets/visualize/utils/tests/test_customizableplot.py
@@ -0,0 +1,38 @@
+import unittest
+from unittest.mock import patch, Mock
+
+from Orange.widgets.visualize.utils import customizableplot
+
+
+class TestFonts(unittest.TestCase):
+    def test_available_font_families(self):
+        with patch.object(customizableplot, "QFont") as font, \
+                patch.object(customizableplot, "QFontDatabase") as db:
+            font.return_value = Mock()
+            font.return_value.family = Mock(return_value="mock regular")
+
+            db.return_value = Mock()
+            db.return_value.families = Mock(
+                return_value=["a", ".d", "e", ".b", "mock regular", "c"])
+            self.assertEqual(customizableplot.available_font_families(),
+                             ["mock regular", "", "a", ".b", "c", ".d", "e"])
+
+            db.return_value = Mock()
+            db.return_value.families = Mock(
+                return_value=["a", ".d", "e", ".b", "mock regular",
+                              "mock bold", "mock italic", "c", "mock semi"])
+            self.assertEqual(customizableplot.available_font_families(),
+                             ["mock regular", "mock bold", "mock italic",
+                              "mock semi", "",
+                              "a", ".b", "c", ".d", "e"])
+
+            # It seems it's possible that default font family does not exist
+            # (see gh-5036)
+            db.return_value.families.return_value = ["a", ".d", "e", ".b", "c"]
+            self.assertEqual(customizableplot.available_font_families(),
+                             ["mock regular", "", "a", ".b", "c", ".d", "e"])
+            self.assertIn(customizableplot.default_font_family(),
+                          customizableplot.available_font_families())
+
+if __name__ == "__main__":
+    unittest.main()