Esempio n. 1
0
    def test_extend(self):
        model = PyListModel([])
        model.extend([1, 2, 3, 4])
        self.assertSequenceEqual(model, [1, 2, 3, 4])

        model.extend([5, 6])
        self.assertSequenceEqual(model, [1, 2, 3, 4, 5, 6])

        self.assertEqual(len(model), len(model._other_data))
Esempio n. 2
0
    def test_clear(self):
        model = PyListModel([1, 2, 3, 2, 4])
        model.clear()
        self.assertSequenceEqual(model, [])
        self.assertEqual(len(model), len(model._other_data))

        model.clear()
        self.assertSequenceEqual(model, [])
        self.assertEqual(len(model), len(model._other_data))
Esempio n. 3
0
    def test_append(self):
        model = PyListModel([])
        model.append(1)
        self.assertSequenceEqual(model, [1])

        model.append(2)
        self.assertSequenceEqual(model, [1, 2])

        self.assertEqual(len(model), len(model._other_data))
Esempio n. 4
0
    def test_insert_delete_rows(self):
        model = PyListModel([1, 2, 3, 4])
        success = model.insertRows(0, 3)

        self.assertIs(success, True)
        self.assertSequenceEqual(model, [None, None, None, 1, 2, 3, 4])

        success = model.removeRows(3, 4)
        self.assertIs(success, True)
        self.assertSequenceEqual(model, [None, None, None])
Esempio n. 5
0
    def test_insert_delete_rows(self):
        model = PyListModel([1, 2, 3, 4])
        success = model.insertRows(0, 3)

        self.assertIs(success, True)
        self.assertSequenceEqual(model, [None, None, None, 1, 2, 3, 4])

        success = model.removeRows(3, 4)
        self.assertIs(success, True)
        self.assertSequenceEqual(model, [None, None, None])
Esempio n. 6
0
    def test_wrap(self):
        model = PyListModel()
        s = [1, 2]
        model.wrap(s)
        self.assertSequenceEqual(model, [1, 2])
        model.append(3)
        self.assertEqual(s, [1, 2, 3])
        self.assertEqual(len(model._other_data), 3)

        s.append(5)
        self.assertRaises(RuntimeError, model._is_index_valid, 0)
Esempio n. 7
0
 def test_dropMimeData(self):
     model = PyListModel([1, 2])
     model.setData(model.index(0), "a", Qt.UserRole)
     mime = model.mimeData([model.index(0)])
     self.assertTrue(
         model.dropMimeData(mime, Qt.CopyAction, 2, -1, model.index(-1, -1))
     )
     self.assertEqual(len(model), 3)
     self.assertEqual(
         model.itemData(model.index(2)),
         {Qt.DisplayRole: 1, Qt.EditRole: 1, Qt.UserRole: "a"}
     )
Esempio n. 8
0
    def test_itemData(self):
        model = PyListModel([1, 2, 3, 4])
        mi = model.index(2)
        model.setItemData(mi, {Qt.ToolTipRole: "foo"})
        self.assertEqual(model.itemData(mi)[Qt.ToolTipRole], "foo")

        self.assertEqual(model.itemData(model.index(5)), {})
Esempio n. 9
0
 def __init__(self, parent, model_list, **kwargs):
     super().__init__(parent, **kwargs)
     self.setValidator(self.Validator())
     self.setModel(PyListModel(iterable=model_list,
                               flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable,
                               parent=self))
     self.view().setItemDelegate(self.TitleShowingPopupDelegate(self))
Esempio n. 10
0
 def test_construct_variables_discrete(self):
     data = Table("iris")
     name = "Discrete Variable"
     expression = ("iris_one if iris == 'Iris-setosa' else iris_two "
                   "if iris == 'Iris-versicolor' else iris_three")
     values = ("iris one", "iris two", "iris three")
     desc = PyListModel([
         DiscreteDescriptor(
             name=name,
             expression=expression,
             values=values,
             base_value=-1,
             ordered=False,
         )
     ])
     data = Table(
         Domain(
             list(data.domain.attributes) +
             construct_variables(desc, data.domain.variables),
             data.domain.class_vars,
             data.domain.metas,
         ),
         data,
     )
     self.assertTrue(isinstance(data.domain[name], DiscreteVariable))
     self.assertEqual(data.domain[name].values, list(values))
     for i in range(3):
         self.assertEqual(data[i * 50, name], values[i])
Esempio n. 11
0
    def __init__(self):
        OWWidget.__init__(self)
        ConcurrentWidgetMixin.__init__(self)
        self.__onto_handler = OntologyHandler()

        flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
        self.__model = PyListModel([], self, flags=flags)
        self.__input_model = QStandardItemModel()
        self.__library_view: QListView = None
        self.__input_view: ListViewSearch = None
        self.__ontology_view: EditableTreeView = None
        self.ontology_info = ""

        self._setup_gui()
        self._restore_state()
        self.settingsAboutToBePacked.connect(self._save_state)
Esempio n. 12
0
    def test_delitem(self):
        model = PyListModel([1, 2, 3, 4])
        del model[1]
        self.assertSequenceEqual(model, [1, 3, 4])

        model = PyListModel([1, 2, 3, 4])
        del model[1:3]

        self.assertSequenceEqual(model, [1, 4])
        model = PyListModel([1, 2, 3, 4])
        del model[:]
        self.assertSequenceEqual(model, [])

        model = PyListModel([1, 2, 3, 4])
        with self.assertRaises(IndexError):
            # non unit strides currently not supported
            del model[0:-1:2]
Esempio n. 13
0
    def test_itemData(self):
        model = PyListModel([1, 2, 3, 4])
        mi = model.index(2)
        model.setItemData(mi, {Qt.ToolTipRole: "foo"})
        self.assertEqual(model.itemData(mi)[Qt.ToolTipRole], "foo")

        self.assertEqual(model.itemData(model.index(5)), {})
Esempio n. 14
0
    def test_delitem(self):
        model = PyListModel([1, 2, 3, 4])
        model._other_data = list("abcd")
        del model[1]
        self.assertSequenceEqual(model, [1, 3, 4])
        self.assertSequenceEqual(model._other_data, "acd")

        model = PyListModel([1, 2, 3, 4])
        model._other_data = list("abcd")
        del model[1:3]

        self.assertSequenceEqual(model, [1, 4])
        self.assertSequenceEqual(model._other_data, "ad")

        model = PyListModel([1, 2, 3, 4])
        model._other_data = list("abcd")
        del model[:]
        self.assertSequenceEqual(model, [])
        self.assertEqual(len(model._other_data), 0)

        model = PyListModel([1, 2, 3, 4])
        with self.assertRaises(IndexError):
            # non unit strides currently not supported
            del model[0:-1:2]
        self.assertEqual(len(model), len(model._other_data))
Esempio n. 15
0
 def update(model: PyListModel, lib_words: List, in_words: List, rule: int):
     if rule == UpdateRules.INTERSECT:
         intersect = set(lib_words) & set(in_words)
         model.wrap(list({k: None for k in lib_words if k in intersect}))
     elif rule == UpdateRules.UNION:
         model.wrap(list({k: None for k in lib_words + in_words}))
     elif rule == UpdateRules.INPUT:
         model.wrap(list(in_words))
     elif rule == UpdateRules.LIBRARY:
         model.wrap(list(lib_words))
     else:
         raise NotImplementedError
Esempio n. 16
0
    def test_setitem(self):
        model = PyListModel([1, 2, 3, 4])
        model[1] = 42
        self.assertSequenceEqual(model, [1, 42, 3, 4])
        model[-1] = 42
        self.assertSequenceEqual(model, [1, 42, 3, 42])

        with self.assertRaises(IndexError):
            model[4]

        with self.assertRaises(IndexError):
            model[-5]

        model = PyListModel([1, 2, 3, 4])
        model[0:0] = [-1, 0]
        self.assertSequenceEqual(model, [-1, 0, 1, 2, 3, 4])

        model = PyListModel([1, 2, 3, 4])
        model[len(model):len(model)] = [5, 6]
        self.assertSequenceEqual(model, [1, 2, 3, 4, 5, 6])

        model = PyListModel([1, 2, 3, 4])
        model[0:2] = [-1, -2]
        self.assertSequenceEqual(model, [-1, -2, 3, 4])

        model = PyListModel([1, 2, 3, 4])
        model[-2:] = [-3, -4]
        self.assertSequenceEqual(model, [1, 2, -3, -4])

        model = PyListModel([1, 2, 3, 4])
        with self.assertRaises(IndexError):
            # non unit strides currently not supported
            model[0:-1:2] = [3, 3]
Esempio n. 17
0
 def test_construct_variables_string(self):
     data = Table("iris")
     name = 'String Variable'
     expression = "str(iris) + '_name'"
     desc = PyListModel(
         [StringDescriptor(name=name, expression=expression)])
     data = data.transform(
         Domain(data.domain.attributes, data.domain.class_vars,
                list(data.domain.metas) + construct_variables(desc, data)))
     self.assertTrue(isinstance(data.domain[name], StringVariable))
     for i in range(3):
         self.assertEqual(data[i * 50, name],
                          str(data[i * 50, "iris"]) + "_name")
Esempio n. 18
0
 def test_construct_numeric_names(self):
     data = Table("iris")
     data.domain.attributes[0].name = "0.1"
     data.domain.attributes[1].name = "1"
     desc = PyListModel([
         ContinuousDescriptor(name="S",
                              expression="_0_1 + _1",
                              number_of_decimals=3)
     ])
     nv = construct_variables(desc, data.domain)
     ndata = Table(Domain(nv, None), data)
     np.testing.assert_array_equal(ndata.X[:, 0], data.X[:, :2].sum(axis=1))
     ContinuousVariable._clear_all_caches()
Esempio n. 19
0
 def test_unicode_normalization():
     micro = "\u00b5"
     domain = Domain([ContinuousVariable(micro)])
     name = 'Micro Variable'
     expression = micro
     desc = PyListModel(
         [ContinuousDescriptor(name=name, expression=expression,
                               number_of_decimals=2)]
     )
     data = Table.from_numpy(domain, np.arange(5).reshape(5, 1))
     data = data.transform(Domain(data.domain.attributes,
                                  [],
                                  construct_variables(desc, data)))
     np.testing.assert_equal(data.X, data.metas)
Esempio n. 20
0
    def __init__(self):
        super().__init__(self)
        flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
        self.library_model = PyListModel([], self, flags=flags)
        self.words_model = PyListModel([], self, flags=flags, enable_dnd=True)

        self.library_view: QListView = None
        self.words_view: ListView = None

        self.__input_words_model = DomainModel(valid_types=(StringVariable, ))
        self.__input_words: Optional[Table] = None

        self.__library_box: QGroupBox = gui.vBox(None, "Library")
        self.__input_box: QGroupBox = gui.vBox(None, "Input")
        self.__words_box: QGroupBox = gui.vBox(None, box=True)
        self.__update_rule_rb: QRadioButton = None

        self.__add_word_action: QAction = None
        self.__remove_word_action: QAction = None

        self._setup_gui()
        self._restore_state()
        self.settingsAboutToBePacked.connect(self._save_state)
Esempio n. 21
0
 def test_construct_numeric_names():
     data = Table("iris")
     newdomain = Domain(
         (ContinuousVariable("0.1"), ContinuousVariable("1")) +
         data.domain.attributes[2:], data.domain.class_var)
     data = Table.from_numpy(newdomain, data.X, data.Y)
     desc = PyListModel([
         ContinuousDescriptor(name="S",
                              expression="_0_1 + _1",
                              number_of_decimals=3)
     ])
     nv = construct_variables(desc, data)
     ndata = Table(Domain(nv, None), data)
     np.testing.assert_array_equal(ndata.X[:, 0], data.X[:, :2].sum(axis=1))
Esempio n. 22
0
    def test_extend(self):
        model = PyListModel([])
        model.extend([1, 2, 3, 4])
        self.assertSequenceEqual(model, [1, 2, 3, 4])

        model.extend([5, 6])
        self.assertSequenceEqual(model, [1, 2, 3, 4, 5, 6])

        self.assertEqual(len(model), len(model._other_data))
Esempio n. 23
0
    def test_append(self):
        model = PyListModel([])
        model.append(1)
        self.assertSequenceEqual(model, [1])

        model.append(2)
        self.assertSequenceEqual(model, [1, 2])

        self.assertEqual(len(model), len(model._other_data))
Esempio n. 24
0
    def test_clear(self):
        model = PyListModel([1, 2, 3, 2, 4])
        model.clear()
        self.assertSequenceEqual(model, [])
        self.assertEqual(len(model), len(model._other_data))

        model.clear()
        self.assertSequenceEqual(model, [])
        self.assertEqual(len(model), len(model._other_data))
Esempio n. 25
0
    def test_list_specials(self):
        # Essentially tested in other tests, but let's do it explicitly, too
        # __len__
        self.assertEqual(len(self.model), 4)

        # __contains__
        self.assertTrue(2 in self.model)
        self.assertFalse(5 in self.model)

        # __iter__
        self.assertSequenceEqual(self.model, [1, 2, 3, 4])

        # __bool__
        self.assertTrue(bool(self.model))
        self.assertFalse(bool(PyListModel()))
Esempio n. 26
0
 def test_construct_variables_datetime(self):
     data = Table("housing")
     name = 'Date'
     expression = '"2019-07-{:02}".format(int(MEDV/3))'
     featuremodel = PyListModel(
         [DateTimeDescriptor(name=name, expression=expression)])
     data = Table(
         Domain(
             list(data.domain.attributes) +
             construct_variables(featuremodel, data),
             data.domain.class_vars, data.domain.metas), data)
     self.assertTrue(isinstance(data.domain[name], TimeVariable))
     for row in data:
         self.assertEqual("2019-07-{:02}".format(int(row["MEDV"] / 3)),
                          str(row["Date"])[:10])
Esempio n. 27
0
 def test_construct_variables_continuous(self):
     data = Table("iris")
     name = 'Continuous Variable'
     expression = "pow(sepal_length + sepal_width, 2)"
     featuremodel = PyListModel(
         [ContinuousDescriptor(name=name, expression=expression,
                               number_of_decimals=2)]
     )
     data = Table(Domain(list(data.domain.attributes) +
                         construct_variables(featuremodel, data.domain),
                         data.domain.class_vars,
                         data.domain.metas), data)
     self.assertTrue(isinstance(data.domain[name], ContinuousVariable))
     for i in range(3):
         self.assertEqual(data[i * 50, name],
                          pow(data[i * 50, 0] + data[i * 50, 1], 2))
Esempio n. 28
0
    def test_wrap(self):
        model = PyListModel()
        s = [1, 2]
        model.wrap(s)
        self.assertSequenceEqual(model, [1, 2])
        model.append(3)
        self.assertEqual(s, [1, 2, 3])
        self.assertEqual(len(model._other_data), 3)

        s.append(5)
        self.assertRaises(RuntimeError, model._is_index_valid, 0)
Esempio n. 29
0
 def test_construct_variables_discrete(self):
     data = Table("iris")
     name = 'Discrete Variable'
     expression = "iris_one if iris == 'Iris-setosa' else iris_two " \
                  "if iris == 'Iris-versicolor' else iris_three"
     values = ('iris one', 'iris two', 'iris three')
     desc = PyListModel(
         [DiscreteDescriptor(name=name, expression=expression,
                             values=values, ordered=False)]
     )
     data = data.transform(Domain(list(data.domain.attributes) +
                                  construct_variables(desc, data),
                                  data.domain.class_vars,
                                  data.domain.metas))
     self.assertTrue(isinstance(data.domain[name], DiscreteVariable))
     self.assertEqual(data.domain[name].values, values)
     for i in range(3):
         self.assertEqual(data[i * 50, name], values[i])
Esempio n. 30
0
    def setup_visible_image_controls(self):
        self.visbox = gui.widgetBox(self.controlArea, True)

        gui.checkBox(self.visbox,
                     self,
                     'show_visible_image',
                     label='Show visible image',
                     callback=lambda: (self.update_visible_image_interface(),
                                       self.update_visible_image()))

        self.visible_image_model = VisibleImageListModel()
        gui.comboBox(self.visbox,
                     self,
                     'visible_image',
                     model=self.visible_image_model,
                     callback=self.update_visible_image)

        self.visual_image_composition_modes = OrderedDict([
            ('Normal', QPainter.CompositionMode_Source),
            ('Overlay', QPainter.CompositionMode_Overlay),
            ('Multiply', QPainter.CompositionMode_Multiply),
            ('Difference', QPainter.CompositionMode_Difference)
        ])
        gui.comboBox(self.visbox,
                     self,
                     'visible_image_composition',
                     label='Composition mode:',
                     model=PyListModel(
                         self.visual_image_composition_modes.keys()),
                     callback=self.update_visible_image_composition_mode)

        gui.hSlider(self.visbox,
                    self,
                    'visible_image_opacity',
                    label='Opacity:',
                    minValue=0,
                    maxValue=255,
                    step=10,
                    createLabel=False,
                    callback=self.update_visible_image_opacity)

        self.update_visible_image_interface()
        self.update_visible_image_composition_mode()
        self.update_visible_image_opacity()
Esempio n. 31
0
 def test_construct_variables_discrete_no_values(self):
     data = Table("iris")
     name = 'Discrete Variable'
     expression = "str(iris)[-1]"  # last letter - a or r
     values = ()
     desc = PyListModel(
         [DiscreteDescriptor(name=name, expression=expression,
                             values=values, ordered=False)]
     )
     data = data.transform(Domain(list(data.domain.attributes) +
                                  construct_variables(desc, data),
                                  data.domain.class_vars,
                                  data.domain.metas))
     newvar = data.domain[name]
     self.assertTrue(isinstance(newvar, DiscreteVariable))
     self.assertEqual(set(data.domain[name].values), set("ar"))
     for i in range(3):
         inst = data[i * 50]
         self.assertEqual(str(inst[name]), str(inst["iris"])[-1])
    def test_token_list_completer(self):
        from Orange.widgets.utils.itemmodels import PyListModel

        completer = TokenListCompleter()
        completer.setTokenList(["foo", "bar", "baz"])
        completer.setCompletionPrefix("foo b")

        def completions(completer):
            current = completer.currentRow()
            items = []
            for i in range(completer.completionCount()):
                completer.setCurrentRow(i)
                items.append(completer.currentCompletion())
            completer.setCurrentRow(current)
            return items

        self.assertSequenceEqual(completions(completer),
                                 ["foo bar", "foo baz"])
        completer.setModel(None)
        self.assertSequenceEqual(completer.tokenList(), [])
        self.assertSequenceEqual(completions(completer), [])

        completer.setModel(QStringListModel(["a", "ab", "b"]))
        self.assertSequenceEqual(completer.tokenList(), ["a", "ab", "b"])
        completer.setCompletionPrefix("a a")
        self.assertSequenceEqual(completions(completer), ["a a", "a ab"])

        completer.setModel(PyListModel(["a", "aa", "ab", "ad"]))
        self.assertSequenceEqual(completer.tokenList(),
                                 ["a", "aa", "ab", "ad"])

        completer.model()[-1] = "z"
        self.assertSequenceEqual(completer.tokenList(), ["a", "aa", "ab", "z"])

        completer.model()[-2:] = ["ax", "az"]
        self.assertSequenceEqual(completer.tokenList(),
                                 ["a", "aa", "ax", "az"])

        completer.setSeparator(",")
        completer.setCompletionPrefix("a, a")
        self.assertSequenceEqual(completions(completer),
                                 ["a, a", "a, aa", "a, ax", "a, az"])
Esempio n. 33
0
    def __init__(self, *args, **kwargs):
        self.__pp_data: Optional[Table] = None
        self.__param_widget: ParametersWidget = None
        self.__expression_edit: QLineEdit = None
        self.__feature_combo: ComboBoxSearch = None
        self.__parameter_combo: ComboBoxSearch = None
        self.__function_combo: ComboBoxSearch = None

        self.__feature_model = DomainModel(
            order=DomainModel.ATTRIBUTES,
            placeholder=self.FEATURE_PLACEHOLDER,
            separators=False,
            valid_types=ContinuousVariable)
        self.__param_model = PyListModel([self.PARAM_PLACEHOLDER])

        self.__pending_parameters = self.parameters
        self.__pending_expression = self.expression

        super().__init__(*args, **kwargs)

        self.Warning.data_missing()
Esempio n. 34
0
    def test_set_data(self):
        model = PyListModel([1, 2, 3, 4])
        model.setData(model.index(0), None, Qt.EditRole)
        self.assertIs(model.data(model.index(0), Qt.EditRole), None)

        model.setData(model.index(1), "This is two", Qt.ToolTipRole)
        self.assertEqual(model.data(model.index(1), Qt.ToolTipRole),
                         "This is two",)

        self.assertFalse(model.setData(model.index(5), "foo"))
Esempio n. 35
0
    def __init__(self):
        super().__init__()
        self.domain = None
        self.data = None
        self.loaded_file = ""
        self._relocate_recent_files()

        vbox = gui.radioButtons(
            self.controlArea, self, "source", box=True, addSpace=True,
            callback=self.load_data)

        box = gui.widgetBox(vbox, orientation="horizontal")
        gui.appendRadioButton(vbox, "File", insertInto=box)
        self.file_combo = QtGui.QComboBox(
            box, sizeAdjustPolicy=QtGui.QComboBox.AdjustToContents)
        self.file_combo.setMinimumWidth(250)
        box.layout().addWidget(self.file_combo)
        self.file_combo.activated[int].connect(self.select_file)
        button = gui.button(
            box, self, '...', callback=self.browse_file, autoDefault=False)
        button.setIcon(self.style().standardIcon(QtGui.QStyle.SP_DirOpenIcon))
        button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        button = gui.button(
            box, self, "Reload", callback=self.reload, autoDefault=False)
        button.setIcon(
            self.style().standardIcon(QtGui.QStyle.SP_BrowserReload))
        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        box = gui.widgetBox(vbox, orientation="horizontal")
        gui.appendRadioButton(vbox, "URL", insertInto=box)
        self.le_url = le_url = QtGui.QLineEdit(self.url)
        l, t, r, b = le_url.getTextMargins()
        le_url.setTextMargins(l + 5, t, r, b)
        le_url.editingFinished.connect(self._url_set)
        box.layout().addWidget(le_url)

        self.completer_model = PyListModel()
        self.completer_model.wrap(self.recent_urls)
        completer = QtGui.QCompleter()
        completer.setModel(self.completer_model)
        completer.setCompletionMode(completer.PopupCompletion)
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        le_url.setCompleter(completer)

        box = gui.widgetBox(self.controlArea, "Info")
        self.info = gui.widgetLabel(box, 'No data loaded.')
        self.warnings = gui.widgetLabel(box, '')

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        gui.button(box, self, "Browse documentation data sets",
                   callback=lambda: self.browse_file(True), autoDefault=False)
        gui.rubber(box)
        box.layout().addWidget(self.report_button)
        self.report_button.setFixedWidth(170)

        # Set word wrap, so long warnings won't expand the widget
        self.warnings.setWordWrap(True)
        self.warnings.setSizePolicy(
            QSizePolicy.Ignored, QSizePolicy.MinimumExpanding)

        self.set_file_list()
        # Must not call open_file from within __init__. open_file
        # explicitly re-enters the event loop (by a progress bar)
        QtCore.QTimer.singleShot(0, self.load_data)
Esempio n. 36
0
    def test_moveRows(self):
        model = PyListModel([1, 2, 3, 4])
        for i in range(model.rowCount()):
            model.setData(model.index(i), str(i + 1), Qt.UserRole)

        def modeldata(role):
            return [model.index(i).data(role)
                    for i in range(model.rowCount())]

        def userdata():
            return modeldata(Qt.UserRole)

        def editdata():
            return modeldata(Qt.EditRole)

        r = model.moveRows(QModelIndex(), 1, 1, QModelIndex(), 0)
        self.assertIs(r, True)
        self.assertSequenceEqual(editdata(), [2, 1, 3, 4])
        self.assertSequenceEqual(userdata(), ["2", "1", "3", "4"])
        r = model.moveRows(QModelIndex(), 1, 2, QModelIndex(), 4)
        self.assertIs(r, True)
        self.assertSequenceEqual(editdata(), [2, 4, 1, 3])
        self.assertSequenceEqual(userdata(), ["2", "4", "1", "3"])
        r = model.moveRows(QModelIndex(), 3, 1, QModelIndex(), 0)
        self.assertIs(r, True)
        self.assertSequenceEqual(editdata(), [3, 2, 4, 1])
        self.assertSequenceEqual(userdata(), ["3", "2", "4", "1"])
        r = model.moveRows(QModelIndex(), 2, 1, QModelIndex(), 2)
        self.assertIs(r, False)
        model = PyListModel([])
        r = model.moveRows(QModelIndex(), 0, 0, QModelIndex(), 0)
        self.assertIs(r, False)
Esempio n. 37
0
    def test_set_data(self):
        model = PyListModel([1, 2, 3, 4])
        model.setData(model.index(0), None, Qt.EditRole)
        self.assertIs(model.data(model.index(0), Qt.EditRole), None)

        model.setData(model.index(1), "This is two", Qt.ToolTipRole)
        self.assertEqual(
            model.data(model.index(1), Qt.ToolTipRole),
            "This is two",
        )
Esempio n. 38
0
 def setUpClass(cls):
     cls.model = PyListModel([1, 2, 3, 4])
Esempio n. 39
0
 def test_sort(self):
     model = PyListModel([3, 1, 4, 2])
     model._other_data = list("abcd")
     model.sort()
     self.assertSequenceEqual(model, [1, 2, 3, 4])
     self.assertSequenceEqual(model._other_data, "bdac")
Esempio n. 40
0
 def test_mimeData(self):
     model = PyListModel([1, 2])
     model._other_data[:] = [{Qt.UserRole: "a"}, {}]
     mime = model.mimeData([model.index(0), model.index(1)])
     self.assertTrue(mime.hasFormat(PyListModel.MIME_TYPE))
Esempio n. 41
0
class OWFile(widget.OWWidget):
    name = "File"
    id = "orange.widgets.data.file"
    description = "Read a data from an input file or network" \
                  "and send the data table to the output."
    icon = "icons/File.svg"
    priority = 10
    category = "Data"
    keywords = ["data", "file", "load", "read"]
    outputs = [widget.OutputSignal(
        "Data", Table,
        doc="Attribute-valued data set read from the input file.")]

    want_main_area = False
    resizing_enabled = False

    LOCAL_FILE, URL = range(2)

    #: List[RecentPath]
    recent_paths = Setting([])
    recent_urls = Setting([])
    source = Setting(LOCAL_FILE)
    url = Setting("")

    dlg_formats = (
        "All readable files ({});;".format(
            '*' + ' *'.join(FileFormat.readers.keys())) +
        ";;".join("{} (*{})".format(f.DESCRIPTION, ' *'.join(f.EXTENSIONS))
                  for f in sorted(set(FileFormat.readers.values()),
                                  key=list(FileFormat.readers.values()).index)))

    def __init__(self):
        super().__init__()
        self.domain = None
        self.data = None
        self.loaded_file = ""
        self._relocate_recent_files()

        vbox = gui.radioButtons(
            self.controlArea, self, "source", box=True, addSpace=True,
            callback=self.load_data)

        box = gui.widgetBox(vbox, orientation="horizontal")
        gui.appendRadioButton(vbox, "File", insertInto=box)
        self.file_combo = QtGui.QComboBox(
            box, sizeAdjustPolicy=QtGui.QComboBox.AdjustToContents)
        self.file_combo.setMinimumWidth(250)
        box.layout().addWidget(self.file_combo)
        self.file_combo.activated[int].connect(self.select_file)
        button = gui.button(
            box, self, '...', callback=self.browse_file, autoDefault=False)
        button.setIcon(self.style().standardIcon(QtGui.QStyle.SP_DirOpenIcon))
        button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        button = gui.button(
            box, self, "Reload", callback=self.reload, autoDefault=False)
        button.setIcon(
            self.style().standardIcon(QtGui.QStyle.SP_BrowserReload))
        button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        box = gui.widgetBox(vbox, orientation="horizontal")
        gui.appendRadioButton(vbox, "URL", insertInto=box)
        self.le_url = le_url = QtGui.QLineEdit(self.url)
        l, t, r, b = le_url.getTextMargins()
        le_url.setTextMargins(l + 5, t, r, b)
        le_url.editingFinished.connect(self._url_set)
        box.layout().addWidget(le_url)

        self.completer_model = PyListModel()
        self.completer_model.wrap(self.recent_urls)
        completer = QtGui.QCompleter()
        completer.setModel(self.completer_model)
        completer.setCompletionMode(completer.PopupCompletion)
        completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
        le_url.setCompleter(completer)

        box = gui.widgetBox(self.controlArea, "Info")
        self.info = gui.widgetLabel(box, 'No data loaded.')
        self.warnings = gui.widgetLabel(box, '')

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        gui.button(box, self, "Browse documentation data sets",
                   callback=lambda: self.browse_file(True), autoDefault=False)
        gui.rubber(box)
        box.layout().addWidget(self.report_button)
        self.report_button.setFixedWidth(170)

        # Set word wrap, so long warnings won't expand the widget
        self.warnings.setWordWrap(True)
        self.warnings.setSizePolicy(
            QSizePolicy.Ignored, QSizePolicy.MinimumExpanding)

        self.set_file_list()
        # Must not call open_file from within __init__. open_file
        # explicitly re-enters the event loop (by a progress bar)
        QtCore.QTimer.singleShot(0, self.load_data)

    def _relocate_recent_files(self):
        paths = [("sample-datasets", get_sample_datasets_dir())]
        basedir = self.workflowEnv().get("basedir", None)
        if basedir is not None:
            paths.append(("basedir", basedir))

        rec = []
        for recent in self.recent_paths:
            resolved = recent.resolve(paths)
            if resolved is not None:
                rec.append(RecentPath.create(resolved.abspath, paths))
            elif recent.search(paths) is not None:
                rec.append(RecentPath.create(recent.search(paths), paths))
        self.recent_paths = rec

    def set_file_list(self):
        self.file_combo.clear()
        if not self.recent_paths:
            self.file_combo.addItem("(none)")
            self.file_combo.model().item(0).setEnabled(False)
        else:
            for i, recent in enumerate(self.recent_paths):
                self.file_combo.addItem(recent.value)
                self.file_combo.model().item(i).setToolTip(recent.abspath)

    def reload(self):
        if self.recent_paths:
            basename = self.file_combo.currentText()
            path = self.recent_paths[0]
            if basename in [path.relpath, path.value]:
                self.source = self.LOCAL_FILE
                return self.load_data()
        self.select_file(len(self.recent_paths) + 1)

    def select_file(self, n):
        if n < len(self.recent_paths):
            recent = self.recent_paths[n]
            del self.recent_paths[n]
            self.recent_paths.insert(0, recent)
        elif n:
            path = self.file_combo.currentText()
            if os.path.exists(path):
                self._add_path(path)
            else:
                self.info.setText('Data was not loaded:')
                self.warnings.setText("File {} does not exist".format(path))
                self.file_combo.removeItem(n)
                self.file_combo.lineEdit().setText(path)
                return

        if len(self.recent_paths) > 0:
            self.source = self.LOCAL_FILE
            self.load_data()
            self.set_file_list()

    def _url_set(self):
        self.source = self.URL
        self.load_data()

    def browse_file(self, in_demos=False):
        if in_demos:
            try:
                start_file = get_sample_datasets_dir()
            except AttributeError:
                start_file = ""
            if not start_file or not os.path.exists(start_file):
                widgets_dir = os.path.dirname(gui.__file__)
                orange_dir = os.path.dirname(widgets_dir)
                start_file = os.path.join(orange_dir, "doc", "datasets")
            if not start_file or not os.path.exists(start_file):
                d = os.getcwd()
                if os.path.basename(d) == "canvas":
                    d = os.path.dirname(d)
                start_file = os.path.join(os.path.dirname(d), "doc", "datasets")
            if not os.path.exists(start_file):
                QtGui.QMessageBox.information(
                    None, "File",
                    "Cannot find the directory with example data sets")
                return
        else:
            if self.recent_paths:
                start_file = self.recent_paths[0].abspath
            else:
                start_file = os.path.expanduser("~/")

        filename = QtGui.QFileDialog.getOpenFileName(
            self, 'Open Orange Data File', start_file, self.dlg_formats)
        if not filename:
            return

        self._add_path(filename)
        self.set_file_list()
        self.source = self.LOCAL_FILE
        self.load_data()

    def _add_path(self, filename):
        searchpaths = [("sample-datasets", get_sample_datasets_dir())]
        basedir = self.workflowEnv().get("basedir", None)
        if basedir is not None:
            searchpaths.append(("basedir", basedir))
        recent = RecentPath.create(filename, searchpaths)
        if recent in self.recent_paths:
            self.recent_paths.remove(recent)
        self.recent_paths.insert(0, recent)

    # Open a file, create data from it and send it over the data channel
    def load_data(self):
        def load(method, fn):
            with catch_warnings(record=True) as warnings:
                data = method(fn)
                self.warning(
                    33, warnings[-1].message.args[0] if warnings else '')
            return data, fn

        def load_from_file():
            fn = fn_original = self.recent_paths[0].abspath
            if fn == "(none)":
                return None, ""
            if not os.path.exists(fn):
                dir_name, basename = os.path.split(fn)
                if os.path.exists(os.path.join(".", basename)):
                    fn = os.path.join(".", basename)
                    self.information("Loading '{}' from the current directory."
                                     .format(basename))
            try:
                return load(Table.from_file, fn)
            except Exception as exc:
                self.warnings.setText(str(exc))
                ind = self.file_combo.currentIndex()
                self.file_combo.removeItem(ind)
                if ind < len(self.recent_paths) and \
                        self.recent_paths[ind].abspath == fn_original:
                    del self.recent_paths[ind]
                raise

        def load_from_network():
            def update_model():
                try:
                    self.completer_model.remove(url or self.url)
                except ValueError:
                    pass
                self.completer_model.insert(0, url)

            self.url = url = self.le_url.text()
            if url:
                QtCore.QTimer.singleShot(0, update_model)
            if not url:
                return None, ""
            elif "://" not in url:
                url = "http://" + url
            try:
                return load(Table.from_url, url)
            except:
                self.warnings.setText(
                    "URL '{}' does not contain valid data".format(url))
                # Don't remove from recent_urls:
                # resource may reappear, or the user mistyped it
                # and would like to retrieve it from history and fix it.
                raise

        self.warning()
        self.information()

        try:
            self.data, self.loaded_file = \
                [load_from_file, load_from_network][self.source]()
        except:
            self.info.setText("Data was not loaded:")
            self.data = None
            self.loaded_file = ""
            return
        else:
            self.warnings.setText("")

        data = self.data
        if data is None:
            self.send("Data", None)
            self.info.setText("No data loaded")
            return

        domain = data.domain
        text = "{} instance(s), {} feature(s), {} meta attribute(s)".format(
            len(data), len(domain.attributes), len(domain.metas))
        if domain.has_continuous_class:
            text += "\nRegression; numerical class."
        elif domain.has_discrete_class:
            text += "\nClassification; discrete class with {} values.".format(
                len(domain.class_var.values))
        elif data.domain.class_vars:
            text += "\nMulti-target; {} target variables.".format(
                len(data.domain.class_vars))
        else:
            text += "\nData has no target variable."
        if 'Timestamp' in data.domain:
            # Google Forms uses this header to timestamp responses
            text += '\n\nFirst entry: {}\nLast entry: {}'.format(
                data[0, 'Timestamp'], data[-1, 'Timestamp'])
        self.info.setText(text)

        add_origin(data, self.loaded_file)
        self.send("Data", data)

    def get_widget_name_extension(self):
        _, name = os.path.split(self.loaded_file)
        return os.path.splitext(name)[0]

    def send_report(self):
        def get_ext_name(filename):
            try:
                return FileFormat.names[os.path.splitext(filename)[1]]
            except KeyError:
                return "unknown"

        if self.data is None:
            self.report_paragraph("File", "No file.")
            return

        if self.source == self.LOCAL_FILE:
            home = os.path.expanduser("~")
            if self.loaded_file.startswith(home):
                # os.path.join does not like ~
                name = "~/" + \
                       self.loaded_file[len(home):].lstrip("/").lstrip("\\")
            else:
                name = self.loaded_file
            self.report_items("File", [("File name", name),
                                       ("Format", get_ext_name(name))])
        else:
            self.report_items("Data", [("URL", self.url),
                                       ("Format", get_ext_name(self.url))])

        self.report_data("Data", self.data)

    def workflowEnvChanged(self, key, value, oldvalue):
        if key == "basedir":
            self._relocate_recent_files()
            self.set_file_list()
Esempio n. 42
0
    def test_insert(self):
        model = PyListModel()
        model.insert(0, 1)
        self.assertSequenceEqual(model, [1])
        self.assertEqual(len(model._other_data), 1)
        model._other_data = ["a"]

        model.insert(0, 2)
        self.assertSequenceEqual(model, [2, 1])
        self.assertEqual(model._other_data[1], "a")
        self.assertNotEqual(model._other_data[0], "a")
        model._other_data[0] = "b"

        model.insert(1, 3)
        self.assertSequenceEqual(model, [2, 3, 1])
        self.assertEqual(model._other_data[0], "b")
        self.assertEqual(model._other_data[2], "a")
        self.assertNotEqual(model._other_data[1], "b")
        self.assertNotEqual(model._other_data[1], "a")
        model._other_data[1] = "c"

        model.insert(3, 4)
        self.assertSequenceEqual(model, [2, 3, 1, 4])
        self.assertSequenceEqual(model._other_data[:3], ["b", "c", "a"])
        model._other_data[3] = "d"

        model.insert(-1, 5)
        self.assertSequenceEqual(model, [2, 3, 1, 5, 4])
        self.assertSequenceEqual(model._other_data[:3], ["b", "c", "a"])
        self.assertEqual(model._other_data[4], "d")
        self.assertEqual(len(model), len(model._other_data))
Esempio n. 43
0
 def test_pop(self):
     model = PyListModel([1, 2, 3, 2, 4])
     model._other_data = list("abcde")
     model.pop(1)
     self.assertSequenceEqual(model, [1, 3, 2, 4])
     self.assertSequenceEqual(model._other_data, "acde")
Esempio n. 44
0
class OWWordList(OWWidget):
    name = "Word List"
    description = "Create a list of words."
    icon = "icons/WordList.svg"
    priority = 1000

    class Inputs:
        words = Input("Words", Table)

    class Outputs:
        selected_words = Output("Selected Words", Table)
        words = Output("Words", Table)

    class Warning(OWWidget.Warning):
        no_string_vars = Msg("Input needs at least one Text variable.")

    NONE, CACHED, LIBRARY = range(3)  # library list modification types

    want_main_area = False
    resizing_enabled = True

    settingsHandler = DomainContextHandler()
    word_list_library: List[Dict] = Setting([
        {
            "name": WordList.generate_word_list_name([]),
            "words": []
        },
    ])
    word_list_index: int = Setting(0)
    words_var: Optional[StringVariable] = ContextSetting(None)
    update_rule_index: int = Setting(UpdateRules.INTERSECT)
    words: List[str] = Setting(None, schema_only=True)
    selected_words: Set[str] = Setting(set(), schema_only=True)

    def __init__(self):
        super().__init__(self)
        flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable
        self.library_model = PyListModel([], self, flags=flags)
        self.words_model = PyListModel([], self, flags=flags, enable_dnd=True)

        self.library_view: QListView = None
        self.words_view: ListView = None

        self.__input_words_model = DomainModel(valid_types=(StringVariable, ))
        self.__input_words: Optional[Table] = None

        self.__library_box: QGroupBox = gui.vBox(None, "Library")
        self.__input_box: QGroupBox = gui.vBox(None, "Input")
        self.__words_box: QGroupBox = gui.vBox(None, box=True)
        self.__update_rule_rb: QRadioButton = None

        self.__add_word_action: QAction = None
        self.__remove_word_action: QAction = None

        self._setup_gui()
        self._restore_state()
        self.settingsAboutToBePacked.connect(self._save_state)

    def _setup_gui(self):
        layout = QGridLayout()
        gui.widgetBox(self.controlArea, orientation=layout)

        self._setup_library_box()
        self._setup_input_box()
        self._setup_words_box()

        layout.addWidget(self.__library_box, 0, 0)
        layout.addWidget(self.__input_box, 1, 0)
        layout.addWidget(self.__words_box, 0, 1, 0, 1)

    def _setup_library_box(self):
        self.library_view = QListView(
            editTriggers=QListView.DoubleClicked | QListView.EditKeyPressed,
            minimumWidth=200,
            sizePolicy=QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Expanding),
        )
        self.library_view.setItemDelegate(WordListItemDelegate(self))
        self.library_view.setModel(self.library_model)
        self.library_view.selectionModel().selectionChanged.connect(
            self.__on_library_selection_changed)

        self.__library_box.layout().setSpacing(1)
        self.__library_box.layout().addWidget(self.library_view)

        actions_widget = ModelActionsWidget()
        actions_widget.layout().setSpacing(1)

        action = QAction("+", self)
        action.setToolTip("Add a new word list to the library")
        action.triggered.connect(self.__on_add_word_list)
        actions_widget.addAction(action)

        action = QAction("\N{MINUS SIGN}", self)
        action.setToolTip("Remove word list from library")
        action.triggered.connect(self.__on_remove_word_list)
        actions_widget.addAction(action)

        action = QAction("Update", self)
        action.setToolTip("Save changes in the editor to library")
        action.setShortcut(QKeySequence(QKeySequence.Save))
        action.triggered.connect(self.__on_update_word_list)
        actions_widget.addAction(action)

        gui.rubber(actions_widget.layout())

        action = QAction("More", self, toolTip="More actions")

        new_from_file = QAction("Import Words from File", self)
        new_from_file.triggered.connect(self.__on_import_word_list)

        save_to_file = QAction("Save Words to File", self)
        save_to_file.setShortcut(QKeySequence(QKeySequence.SaveAs))
        save_to_file.triggered.connect(self.__on_save_word_list)

        menu = QMenu(actions_widget)
        menu.addAction(new_from_file)
        menu.addAction(save_to_file)
        action.setMenu(menu)
        button = actions_widget.addAction(action)
        button.setPopupMode(QToolButton.InstantPopup)
        self.__library_box.layout().addWidget(actions_widget)

    def __on_library_selection_changed(self, selected: QItemSelection, *_):
        index = [i.row() for i in selected.indexes()]
        if index:
            current = index[0]
            word_list: WordList = self.library_model[current]
            self.word_list_index = current
            self.selected_words = set()
            self.words_model.wrap(list(word_list.cached_words))
            self._apply_update_rule()

    def __on_add_word_list(self):
        taken = [l.name for l in self.library_model]
        name = WordList.generate_word_list_name(taken)
        word_list = WordList(name, self.words_model[:])
        self.library_model.append(word_list)
        self._set_selected_word_list(len(self.library_model) - 1)

    def __on_remove_word_list(self):
        index = self._get_selected_word_list_index()
        if index is not None:
            del self.library_model[index]
            self._set_selected_word_list(max(index - 1, 0))
            self._apply_update_rule()

    def __on_update_word_list(self):
        self._set_word_list_modified(mod_type=self.LIBRARY)

    def __on_import_word_list(self):
        filename, _ = QFileDialog.getOpenFileName(
            self, "Open Word List", os.path.expanduser("~/"),
            "Text files (*.txt)\nAll files(*.*)")
        if filename:
            name = os.path.basename(filename)
            with open(filename, encoding="utf-8") as f:
                words = [line.strip() for line in f.readlines()]
            self.library_model.append(WordList(name, words, filename=filename))
            self._set_selected_word_list(len(self.library_model) - 1)
            self._apply_update_rule()

    def __on_save_word_list(self):
        index = self._get_selected_word_list_index()
        if index is not None:
            word_list = self.library_model[index]
            filename = word_list.filename
        else:
            filename = os.path.expanduser("~/")

        filename, _ = QFileDialog.getSaveFileName(
            self, "Save Word List", filename,
            "Text files (*.txt)\nAll files(*.*)")
        if filename:
            head, tail = os.path.splitext(filename)
            if not tail:
                filename = head + ".txt"

            with open(filename, "w", encoding="utf-8") as f:
                for word in self.words_model:
                    f.write(f"{word}\n")

    def _setup_input_box(self):
        gui.comboBox(self.__input_box,
                     self,
                     "words_var",
                     label="Word variable:",
                     orientation=Qt.Vertical,
                     model=self.__input_words_model,
                     callback=self._apply_update_rule)
        gui.radioButtons(self.__input_box,
                         self,
                         "update_rule_index",
                         UpdateRules.ITEMS,
                         label="Update: ",
                         orientation=Qt.Vertical,
                         callback=self.__on_update_rule_changed)
        self.__input_box.setEnabled(False)

    def __on_update_rule_changed(self):
        self._enable_words_actions()
        self._apply_update_rule()

    def _setup_words_box(self):
        self.words_view = ListView()
        self.words_view.drop_finished.connect(self.__on_words_data_changed)
        self.words_view.setModel(self.words_model)
        self.words_view.selectionModel().selectionChanged.connect(
            self.__on_words_selection_changed)

        self.words_model.dataChanged.connect(self.__on_words_data_changed)

        self.__words_box.layout().setSpacing(1)
        self.__words_box.layout().addWidget(self.words_view)

        actions_widget = ModelActionsWidget()
        actions_widget.layout().setSpacing(1)

        action = QAction("+", self.words_view, toolTip="Add a new word")
        action.triggered.connect(self.__on_add_word)
        actions_widget.addAction(action)
        self.__add_word_action = action

        action = QAction("\N{MINUS SIGN}", self, toolTip="Remove word")
        action.triggered.connect(self.__on_remove_word)
        actions_widget.addAction(action)
        self.__remove_word_action = action

        gui.rubber(actions_widget)

        action = QAction("Sort", self)
        action.setToolTip("Sort words alphabetically")
        action.triggered.connect(self.__on_apply_sorting)
        actions_widget.addAction(action)

        self.__words_box.layout().addWidget(actions_widget)

    def __on_words_data_changed(self):
        self._set_word_list_modified(mod_type=self.CACHED)
        self.commit()

    def __on_words_selection_changed(self):
        self.commit()

    def __on_add_word(self):
        row = self.words_model.rowCount()
        if not self.words_model.insertRow(self.words_model.rowCount()):
            return
        with disconnected(self.words_view.selectionModel().selectionChanged,
                          self.__on_words_selection_changed):
            self._set_selected_words([0])
            index = self.words_model.index(row, 0)
            self.words_view.setCurrentIndex(index)
            self.words_model.setItemData(index, {Qt.EditRole: ""})
        self.words_view.edit(index)

    def __on_remove_word(self):
        rows = self.words_view.selectionModel().selectedRows(0)
        if not rows:
            return

        indices = sorted([row.row() for row in rows], reverse=True)
        with disconnected(self.words_view.selectionModel().selectionChanged,
                          self.__on_words_selection_changed):
            for index in indices:
                self.words_model.removeRow(index)
            if self.words_model:
                self._set_selected_words([max(0, indices[-1] - 1)])
        self.__on_words_data_changed()

    def __on_apply_sorting(self):
        if not self.words_model:
            return
        words = self.words_model[:]
        mask = np.zeros(len(words), dtype=bool)
        selection = self._get_selected_words_indices()
        if selection:
            mask[selection] = True

        indices = np.argsort(words)
        self.words_model.wrap([words[i] for i in indices])
        self._set_word_list_modified(mod_type=self.CACHED)
        if selection:
            self._set_selected_words(list(np.flatnonzero(mask[indices])))
        else:
            self.commit()

    @Inputs.words
    def set_words(self, words: Optional[Table]):
        self.closeContext()
        self.__input_words = words
        self._check_input_words()
        self._init_controls()
        self.openContext(self.__input_words)
        self._apply_update_rule()

    def _check_input_words(self):
        self.Warning.no_string_vars.clear()
        if self.__input_words:
            metas = self.__input_words.domain.metas
            if not any(isinstance(m, StringVariable) for m in metas):
                self.Warning.no_string_vars()
                self.__input_words = None

    def _init_controls(self):
        words = self.__input_words
        domain = words.domain if words is not None else None
        self.__input_words_model.set_domain(domain)
        if len(self.__input_words_model) > 0:
            self.words_var = self.__input_words_model[0]
        self.__input_box.setEnabled(bool(self.__input_words_model))
        self._enable_words_actions()

    def _enable_words_actions(self):
        if bool(self.__input_words_model) \
                and self.update_rule_index != UpdateRules.LIBRARY:
            self.words_view.setEditTriggers(QListView.NoEditTriggers)
            self.__add_word_action.setEnabled(False)
            self.__remove_word_action.setEnabled(False)
        else:
            self.words_view.setEditTriggers(QListView.DoubleClicked
                                            | QListView.EditKeyPressed)
            self.__add_word_action.setEnabled(True)
            self.__remove_word_action.setEnabled(True)

    def _apply_update_rule(self):
        lib_index = self._get_selected_word_list_index()
        lib_words, in_words, update_rule = [], [], UpdateRules.LIBRARY
        if lib_index is not None:
            lib_words = self.library_model[lib_index].cached_words
        else:
            lib_words = self.words_model[:]
        if self.__input_words is not None:
            in_words = self.__input_words.get_column_view(self.words_var)[0]
            in_words = list(in_words)
            update_rule = self.update_rule_index

        UpdateRules.update(self.words_model, lib_words, in_words, update_rule)
        if lib_index is not None:
            cached = self.library_model[lib_index].cached_words
            modified = WordList.NotModified if cached == self.words_model[:] \
                else WordList.Modified
            self.library_model[lib_index].update_rule_flag = modified
            self._set_word_list_modified(mod_type=self.NONE)
            self.library_view.repaint()

        # Apply selection. selection_changed invokes commit().
        # If there is no selection, call commit explicitly.
        if any(w in self.selected_words for w in self.words_model):
            self.set_selected_words()
            self.words_view.repaint()
        else:
            self.commit()

    def commit(self):
        selection = self._get_selected_words_indices()
        self.selected_words = set(np.array(self.words_model)[selection])

        words, selected_words = None, None
        if self.words_model:
            words_var = StringVariable("Words")
            words_var.attributes = {"type": "words"}
            domain = Domain([], metas=[words_var])
            _words = Table.from_list(domain, [[w] for w in self.words_model])
            _words.name = "Words"
            if selection:
                selected_words = _words[selection]
            words = create_annotated_table(_words, selection)
        self.Outputs.words.send(words)
        self.Outputs.selected_words.send(selected_words)

    def _set_word_list_modified(self, mod_type):
        index = self._get_selected_word_list_index()
        if index is not None:
            if mod_type == self.LIBRARY:
                self.library_model[index].words = self.words_model[:]
                self.library_model[index].cached_words = self.words_model[:]
                self.library_model[index].update_rule_flag \
                    = WordList.NotModified
            elif mod_type == self.CACHED:
                self.library_model[index].cached_words = self.words_model[:]
            elif mod_type == self.NONE:
                pass
            else:
                raise NotImplementedError
            self.library_model.emitDataChanged(index)
            self.library_view.repaint()

    def _set_selected_word_list(self, index: int):
        sel_model: QItemSelectionModel = self.library_view.selectionModel()
        sel_model.select(self.library_model.index(index, 0),
                         QItemSelectionModel.ClearAndSelect)

    def _get_selected_word_list_index(self) -> Optional[int]:
        rows = self.library_view.selectionModel().selectedRows()
        return rows[0].row() if rows else None

    def _set_selected_words(self, indices: List[int]):
        selection = QItemSelection()
        sel_model: QItemSelectionModel = self.words_view.selectionModel()
        for i in indices:
            selection.append(QItemSelectionRange(self.words_model.index(i, 0)))
        sel_model.select(selection, QItemSelectionModel.ClearAndSelect)

    def _get_selected_words_indices(self) -> List[int]:
        rows = self.words_view.selectionModel().selectedRows()
        return [row.row() for row in rows]

    def set_selected_words(self):
        if self.selected_words:
            indices = [
                i for i, w in enumerate(self.words_model)
                if w in self.selected_words
            ]
            self._set_selected_words(indices)

    def _restore_state(self):
        source = [WordList.from_dict(s) for s in self.word_list_library]
        self.library_model.wrap(source)
        # __on_library_selection_changed() (invoked by _set_selected_word_list)
        # clears self.selected_words
        selected_words = self.selected_words
        self._set_selected_word_list(self.word_list_index)

        if self.words is not None:
            self.words_model.wrap(list(self.words))
            self._set_word_list_modified(mod_type=self.CACHED)
            if selected_words:
                self.selected_words = selected_words
                self.set_selected_words()
            elif len(self.word_list_library) > self.word_list_index and \
                self.word_list_library[self.word_list_index] != self.words:
                self.commit()

    def _save_state(self):
        self.word_list_library = [s.as_dict() for s in self.library_model]
        self.words = self.words_model[:]

    def send_report(self):
        library = self.library_model[self.word_list_index].name \
            if self.library_model else "/"
        settings = [("Library", library)]
        if self.__input_words:
            self.report_data("Input Words", self.__input_words)
            settings.append(("Word variable", self.words_var))
            rule = UpdateRules.ITEMS[self.update_rule_index]
            settings.append(("Update", rule))
        self.report_items("Settings", settings)
        self.report_paragraph("Words", ", ".join(self.words_model[:]))
Esempio n. 45
0
 def test_reverse(self):
     model = PyListModel([1, 2, 3, 4])
     model._other_data = list("abcd")
     model.reverse()
     self.assertSequenceEqual(model, [4, 3, 2, 1])
     self.assertSequenceEqual(model._other_data, "dcba")
Esempio n. 46
0
 def data(self, index, role=Qt.DisplayRole):
     if self._is_index_valid(index):
         img = self[index.row()]
         if role == Qt.DisplayRole:
             return img["name"]
     return PyListModel.data(self, index, role)
Esempio n. 47
0
 def test_sort(self):
     model = PyListModel([3, 1, 4, 2])
     model._other_data = list("abcd")
     model.sort()
     self.assertSequenceEqual(model, [1, 2, 3, 4])
     self.assertSequenceEqual(model._other_data, "bdac")