예제 #1
0
 def test_emits_column_changes_on_row_insert(self):
     inserted = []
     removed = []
     model = PyTableModel()
     model.columnsInserted.connect(inserted.append)
     model.columnsRemoved.connect(removed.append)
     inserted = QSignalSpy(model.columnsInserted)
     removed = QSignalSpy(model.columnsRemoved)
     model.append([2])
     self.assertEqual(list(inserted)[-1][1:], [0, 0])
     model.append([2, 3])
     self.assertEqual(list(inserted)[-1][1:], [1, 1])
     del model[:]
     self.assertEqual(list(removed)[0][1:], [0, 1])
     model.extend([[0, 1], [0, 2]])
     self.assertEqual(list(inserted)[-1][1:], [0, 1])
     model.clear()
     self.assertEqual(list(removed)[0][1:], [0, 1])
     model[:] = [[1], [2]]
     self.assertEqual(list(inserted)[-1][1:], [0, 0])
예제 #2
0
    def __init__(self):
        super().__init__()
        self.corpus = None              # corpus taken from distances
        self.linkage = None             # hierarchical clustering linkage as returned by Orange
        self.distances = None           # DistMatrix on input
        self.clustering_mask = None     # 1D array of clusters for self.corpus
        self.threshold = 0              # hierarchical clustering distance threshold
        self.threshold_spin = None

        # Info
        self.n_documents = ''
        self.n_unique = ''
        self.n_duplicates = ''
        info_box = gui.widgetBox(self.controlArea, box='Info')
        gui.label(info_box, self, 'Documents: %(n_documents)s')
        gui.label(info_box, self, '  ◦ unique: %(n_unique)s')
        gui.label(info_box, self, '  ◦ duplicates: %(n_duplicates)s')

        # Threshold Histogram & Cluster View
        self.histogram = Histogram(self)
        self.table_view = gui.TableView(selectionMode=QListView.SingleSelection)
        self.table_model = PyTableModel()
        self.table_model.setHorizontalHeaderLabels(['Cluster', 'Size'])
        self.table_view.setModel(self.table_model)
        self.table_view.selectionModel().selectionChanged.connect(self.send_duplicates)

        # Add to main area
        height = 300
        main_area = gui.hBox(self.mainArea)
        self.histogram.setMinimumWidth(500)
        self.histogram.setMinimumHeight(height)
        self.table_view.setFixedWidth(140)
        main_area.layout().addWidget(self.histogram)
        main_area.layout().addWidget(self.table_view)

        # Controls
        gui.comboBox(self.controlArea, self, 'linkage_method', items=self.LINKAGE, box='Linkage',
                     callback=self.recalculate_linkage, orientation=Qt.Horizontal)
        self.threshold_spin = gui.doubleSpin(self.controlArea, self, 'threshold',
                                             0, float('inf'), 0.01, decimals=2,
                                             label='Distance threshold', box='Distances',
                                             callback=self.threshold_changed,
                                             keyboardTracking=False, controlWidth=60)
        self.histogram.region.sigRegionChangeFinished.connect(self.threshold_from_histogram_region)
        self.threshold_spin.setEnabled(False)
        gui.rubber(self.controlArea)

        # Output
        gui.comboBox(self.controlArea, self, "cluster_role", box='Output',
                     label='Append Cluster IDs to:', callback=self.send_corpus,
                     items=self.CLUSTER_ROLES)
예제 #3
0
    def __init__(self):
        OWWidget.__init__(self)
        ConcurrentWidgetMixin.__init__(self)
        self.data = None
        self.selected_attributes = None
        box = gui.vBox(self.controlArea, "Granger Test")
        gui.hSlider(
            box,
            self,
            "confidence",
            minValue=90,
            maxValue=99,
            label="Confidence:",
            labelFormat=" %d%%",
            callback=self._setting_changed,
        )
        gui.spin(
            box,
            self,
            "max_lag",
            1,
            50,
            label="Max lag:",
            callback=self._setting_changed,
        )
        self.test_button = gui.button(box, self, "&Test", self._toggle_run)
        gui.rubber(self.controlArea)

        self.model = model = PyTableModel(parent=self)

        model.setHorizontalHeaderLabels(COLUMNS)
        self.causality_view = view = gui.TableView(self)
        view.setModel(model)
        bold = view.BoldFontDelegate(self)
        view.setItemDelegateForColumn(2, bold)
        view.setItemDelegateForColumn(4, bold)
        view.horizontalHeader().setStretchLastSection(False)
        view.horizontalHeader().sectionClicked.connect(self.header_click)
        view.selectionModel().selectionChanged.connect(self.on_select)
        view.sortByColumn(1, Qt.AscendingOrder)
        self.mainArea.layout().addWidget(view)
        self._set_modified(False)

        self.auto_commit_widget = gui.auto_commit(
            widget=self.controlArea,
            master=self,
            value="autocommit",
            label="Apply",
            commit=self.commit,
        )
예제 #4
0
    def _create_layout(self):
        self._new_webview()
        box = gui.widgetBox(self.controlArea, 'Info')
        self.topic_info = gui.label(box, self,
                                    '%(n_topic_words)d words in a topic')
        gui.label(box, self, '%(documents_info_str)s')

        box = gui.widgetBox(self.controlArea, 'Cloud preferences')
        gui.checkBox(box,
                     self,
                     'words_color',
                     'Color words',
                     callback=self.on_cloud_pref_change)
        TILT_VALUES = ('no', 'slight', 'more', 'full')
        gui.valueSlider(box,
                        self,
                        'words_tilt',
                        label='Words tilt:',
                        values=list(range(len(TILT_VALUES))),
                        callback=self.on_cloud_pref_change,
                        labelFormat=lambda x: TILT_VALUES[x])
        gui.button(box,
                   None,
                   'Regenerate word cloud',
                   callback=self.on_cloud_pref_change)

        box = gui.widgetBox(self.controlArea, 'Words && weights')

        class TableView(gui.TableView):
            def __init__(self, parent):
                super().__init__(parent)
                self._parent = parent

            def selectionChanged(self, selected, deselected):
                super().selectionChanged(selected, deselected)
                parent = self._parent
                for index in deselected.indexes():
                    data = parent.tablemodel[index.row()][1]
                    self._parent.selected_words.remove(data)
                for index in selected.indexes():
                    data = parent.tablemodel[index.row()][1]
                    self._parent.selected_words.add(data)
                parent.cloud_reselect()

        view = self.tableview = TableView(self)
        model = self.tablemodel = PyTableModel()
        model.setHorizontalHeaderLabels(['Weight', 'Word'])
        view.setModel(model)
        box.layout().addWidget(view)
예제 #5
0
class TestAbstractSortTableModel(TestCase):
    def setUp(self):
        assert issubclass(PyTableModel, AbstractSortTableModel)
        self.model = PyTableModel([[1, 4], [2, 3]])

    def test_sorting(self):
        self.model.sort(1, Qt.AscendingOrder)
        self.assertSequenceEqual(
            self.model.mapToSourceRows(...).tolist(), [1, 0])

        self.model.sort(1, Qt.DescendingOrder)
        self.assertSequenceEqual(
            self.model.mapToSourceRows(...).tolist(), [0, 1])
    def __init__(self):
        self.data = None
        self._models = OrderedDict()
        box = gui.vBox(self.controlArea, 'Evaluation Parameters')
        gui.spin(box, self, 'n_folds', 1, 100,
                 label='Number of folds:',
                 callback=self.on_changed)
        gui.spin(box, self, 'forecast_steps', 1, 100,
                 label='Forecast steps:',
                 callback=self.on_changed)
        gui.auto_commit(box, self, 'autocommit', '&Apply')
        gui.rubber(self.controlArea)

        self.model = model = PyTableModel(parent=self)
        view = gui.TableView(self)
        view.setModel(model)
        view.horizontalHeader().setStretchLastSection(False)
        view.verticalHeader().setVisible(True)
        self.mainArea.layout().addWidget(view)
    def __init__(self):
        self.data = None
        box = gui.vBox(self.controlArea, 'Granger Test')
        gui.hSlider(box, self, 'confidence',
                    minValue=90, maxValue=99,
                    label='Confidence:',
                    labelFormat=" %d%%",
                    callback=self.on_changed)
        gui.spin(box, self, 'max_lag', 1, 50,
                 label='Max lag:',
                 callback=self.on_changed)
        gui.auto_commit(box, self, 'autocommit', '&Test')
        gui.rubber(self.controlArea)

        self.model = model = PyTableModel(parent=self)
        model.setHorizontalHeaderLabels(['Min. lag', 'Series 1', '', 'Series 2'])
        view = gui.TableView(self)
        view.setModel(model)
        bold = view.BoldFontDelegate(self)
        view.setItemDelegateForColumn(1, bold)
        view.setItemDelegateForColumn(3, bold)
        view.horizontalHeader().setStretchLastSection(False)
        self.mainArea.layout().addWidget(view)
예제 #8
0
    def _setup_gui(self):
        # Control area
        box = gui.hBox(self.controlArea, "Filtering")
        gui.doubleSpin(box,
                       self,
                       "threshold",
                       0,
                       1,
                       0.01,
                       None,
                       label="Threshold: ",
                       orientation=Qt.Horizontal,
                       callback=self.__on_threshold_changed)

        box = gui.hBox(self.controlArea, "Display")
        gui.radioButtons(box,
                         self,
                         "display_index",
                         DisplayDocument.ITEMS,
                         callback=self.__on_display_changed)

        gui.rubber(self.controlArea)

        # Main area
        model = PyTableModel(parent=self)
        self._list_view = SemanticListView()
        self._list_view.setModel(model)
        self._list_view.selectionModel().selectionChanged.connect(
            self.__on_selection_changed)
        self._list_view.horizontalHeader().sectionClicked.connect(
            self.__on_horizontal_header_clicked)

        splitter = QSplitter()
        splitter.addWidget(self._list_view)
        self._web_view = gui.WebviewWidget(splitter, debug=False)
        splitter.setSizes([200, 300])
        self.mainArea.layout().addWidget(splitter)
예제 #9
0
    def test_sorting(self):
        assert issubclass(PyTableModel, AbstractSortTableModel)
        model = PyTableModel([[1, 4],
                              [2, 2],
                              [3, 3]])
        model.sort(1, Qt.AscendingOrder)
        # mapToSourceRows
        self.assertSequenceEqual(model.mapToSourceRows(...).tolist(), [1, 2, 0])
        self.assertEqual(model.mapToSourceRows(1).tolist(), 2)
        self.assertSequenceEqual(model.mapToSourceRows([1, 2]).tolist(), [2, 0])
        self.assertSequenceEqual(model.mapToSourceRows([]), [])
        self.assertSequenceEqual(model.mapToSourceRows(np.array([], dtype=int)).tolist(), [])
        self.assertRaises(IndexError, model.mapToSourceRows, np.r_[0.])

        # mapFromSourceRows
        self.assertSequenceEqual(model.mapFromSourceRows(...).tolist(), [2, 0, 1])
        self.assertEqual(model.mapFromSourceRows(1).tolist(), 0)
        self.assertSequenceEqual(model.mapFromSourceRows([1, 2]).tolist(), [0, 1])
        self.assertSequenceEqual(model.mapFromSourceRows([]), [])
        self.assertSequenceEqual(model.mapFromSourceRows(np.array([], dtype=int)).tolist(), [])
        self.assertRaises(IndexError, model.mapFromSourceRows, np.r_[0.])

        model.sort(1, Qt.DescendingOrder)
        self.assertSequenceEqual(model.mapToSourceRows(...).tolist(), [0, 2, 1])
        self.assertSequenceEqual(model.mapFromSourceRows(...).tolist(), [0, 2, 1])
예제 #10
0
class TestPyTableModel(TestCase):
    def setUp(self):
        self.model = PyTableModel([[1, 4], [2, 3]])

    def test_init(self):
        self.model = PyTableModel()
        self.assertEqual(self.model.rowCount(), 0)

    def test_rowCount(self):
        self.assertEqual(self.model.rowCount(), 2)
        self.assertEqual(len(self.model), 2)

    def test_columnCount(self):
        self.assertEqual(self.model.columnCount(), 2)

    def test_data(self):
        self.assertEqual(str(self.model.data(self.model.index(0, 0))), '1')

    def test_sort(self):
        self.model.sort(1)
        self.assertEqual(self.model[0][0], 2)

    def test_setHeaderLabels(self):
        self.model.setHorizontalHeaderLabels(['Col 1', 'Col 2'])
        self.assertEqual(self.model.headerData(1, Qt.Horizontal), 'Col 2')
        self.assertEqual(self.model.headerData(1, Qt.Vertical), '1')

    def test_removeRows(self):
        self.model.removeRows(0, 1)
        self.assertEqual(len(self.model), 1)
        self.assertEqual(self.model[0][1], 3)

    def test_removeColumns(self):
        self.model.removeColumns(0, 1)
        self.assertEqual(self.model.columnCount(), 1)
        self.assertEqual(self.model[1][0], 3)

    def test_insertRows(self):
        self.model.insertRows(0, 1)
        self.assertEqual(self.model[1][0], 1)

    def test_insertColumns(self):
        self.model.insertColumns(0, 1)
        self.assertEqual(self.model[0], ['', 1, 4])

    def test_wrap(self):
        self.model.wrap([[0]])
        self.assertEqual(self.model.rowCount(), 1)
        self.assertEqual(self.model.columnCount(), 1)

    def test_clear(self):
        self.model.clear()
        self.assertEqual(self.model.rowCount(), 0)

    def test_append(self):
        self.model.append([5, 6])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_extend(self):
        self.model.extend([[5, 6]])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_insert(self):
        self.model.insert(0, [5, 6])
        self.assertEqual(self.model[0][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_remove(self):
        self.model.remove([2, 3])
        self.assertEqual(self.model.rowCount(), 1)
예제 #11
0
    def test_sorting(self):
        assert issubclass(PyTableModel, AbstractSortTableModel)
        model = PyTableModel([[1, 4], [2, 2], [3, 3]])
        model.sort(1, Qt.AscendingOrder)
        # mapToSourceRows
        self.assertSequenceEqual(
            model.mapToSourceRows(...).tolist(), [1, 2, 0])
        self.assertEqual(model.mapToSourceRows(1).tolist(), 2)
        self.assertSequenceEqual(
            model.mapToSourceRows([1, 2]).tolist(), [2, 0])
        self.assertSequenceEqual(model.mapToSourceRows([]), [])
        self.assertSequenceEqual(
            model.mapToSourceRows(np.array([], dtype=int)).tolist(), [])
        self.assertRaises(IndexError, model.mapToSourceRows, np.r_[0.])

        # mapFromSourceRows
        self.assertSequenceEqual(
            model.mapFromSourceRows(...).tolist(), [2, 0, 1])
        self.assertEqual(model.mapFromSourceRows(1).tolist(), 0)
        self.assertSequenceEqual(
            model.mapFromSourceRows([1, 2]).tolist(), [0, 1])
        self.assertSequenceEqual(model.mapFromSourceRows([]), [])
        self.assertSequenceEqual(
            model.mapFromSourceRows(np.array([], dtype=int)).tolist(), [])
        self.assertRaises(IndexError, model.mapFromSourceRows, np.r_[0.])

        model.sort(1, Qt.DescendingOrder)
        self.assertSequenceEqual(
            model.mapToSourceRows(...).tolist(), [0, 2, 1])
        self.assertSequenceEqual(
            model.mapFromSourceRows(...).tolist(), [0, 2, 1])
예제 #12
0
class OWDuplicates(widget.OWWidget):
    name = 'Duplicate Detection'
    description = 'Detect & remove duplicates from a corpus.'
    icon = 'icons/Duplicates.svg'
    priority = 45

    inputs = [(IO.distances, DistMatrix, 'set_distances')]
    outputs = [
        (IO.corpus_without_duplicates, Corpus),
        (IO.duplicates, Corpus),
        (IO.corpus, Corpus),
    ]

    resizing_enabled = True

    class Error(OWWidget.Error):
        dist_matrix_invalid_shape = Msg('Duplicate detection only supports '
                                        'distances calculated between rows.')
        too_little_documents = Msg('More than one document is required.')

    LINKAGE = ['Single', 'Average', 'Complete', 'Weighted', 'Ward']
    linkage_method = settings.Setting(1)

    # Cluster variable domain role
    AttributeRole, ClassRole, MetaRole = 0, 1, 2
    CLUSTER_ROLES = ["Attributes", "Class", "Metas"]
    cluster_role = settings.Setting(2)

    def __init__(self):
        super().__init__()
        self.corpus = None              # corpus taken from distances
        self.linkage = None             # hierarchical clustering linkage as returned by Orange
        self.distances = None           # DistMatrix on input
        self.clustering_mask = None     # 1D array of clusters for self.corpus
        self.threshold = 0              # hierarchical clustering distance threshold
        self.threshold_spin = None

        # Info
        self.n_documents = ''
        self.n_unique = ''
        self.n_duplicates = ''
        info_box = gui.widgetBox(self.controlArea, box='Info')
        gui.label(info_box, self, 'Documents: %(n_documents)s')
        gui.label(info_box, self, '  ◦ unique: %(n_unique)s')
        gui.label(info_box, self, '  ◦ duplicates: %(n_duplicates)s')

        # Threshold Histogram & Cluster View
        self.histogram = Histogram(self)
        self.table_view = gui.TableView(selectionMode=QListView.SingleSelection)
        self.table_model = PyTableModel()
        self.table_model.setHorizontalHeaderLabels(['Cluster', 'Size'])
        self.table_view.setModel(self.table_model)
        self.table_view.selectionModel().selectionChanged.connect(self.send_duplicates)

        # Add to main area
        height = 300
        main_area = gui.hBox(self.mainArea)
        self.histogram.setMinimumWidth(500)
        self.histogram.setMinimumHeight(height)
        self.table_view.setFixedWidth(140)
        main_area.layout().addWidget(self.histogram)
        main_area.layout().addWidget(self.table_view)

        # Controls
        gui.comboBox(self.controlArea, self, 'linkage_method', items=self.LINKAGE, box='Linkage',
                     callback=self.recalculate_linkage, orientation=Qt.Horizontal)
        self.threshold_spin = gui.doubleSpin(self.controlArea, self, 'threshold',
                                             0, float('inf'), 0.01, decimals=2,
                                             label='Distance threshold', box='Distances',
                                             callback=self.threshold_changed,
                                             keyboardTracking=False, controlWidth=60)
        self.histogram.region.sigRegionChangeFinished.connect(self.threshold_from_histogram_region)
        self.threshold_spin.setEnabled(False)
        gui.rubber(self.controlArea)

        # Output
        gui.comboBox(self.controlArea, self, "cluster_role", box='Output',
                     label='Append Cluster IDs to:', callback=self.send_corpus,
                     items=self.CLUSTER_ROLES)

    def reset(self):
        self.corpus = None
        self.linkage = None
        self.distances = None
        self.clustering_mask = None
        self.n_documents = ''
        self.n_unique = ''
        self.n_duplicates = ''
        self.threshold = 0
        self.threshold_spin.setEnabled(False)
        self.table_model.clear()
        self.histogram.setValues([])

    def set_distances(self, distances):
        self.Error.clear()
        self.distances = distances
        if distances is None:
            self.reset()
            return

        self.corpus = self.distances.row_items
        self.n_documents = len(self.corpus)
        if self.n_documents < 2:
            self.Error.too_little_documents()
            self.reset()
            return
        if distances.shape != (self.n_documents, self.n_documents):
            self.Error.dist_matrix_invalid_shape()
            self.reset()
            return
        self.threshold_spin.setEnabled(True)
        self.recalculate_linkage()

    def threshold_from_histogram_region(self):
        _, self.threshold = self.histogram.getRegion()
        self.threshold_changed()

    def threshold_changed(self):
        self.threshold = np.clip(self.threshold, *self.histogram.boundary())
        self.histogram.setRegion(0, self.threshold)
        self.detect_duplicates()

    def recalculate_linkage(self):
        if self.distances is not None:
            self.linkage = dist_matrix_linkage(self.distances,
                                               self.LINKAGE[self.linkage_method].lower())

            # Magnitude of the spinbox's step is data-dependent
            vals = sorted(self.linkage[:, 2])
            low, up = vals[0], vals[-1]
            step = (up - low) / 20

            self.threshold_spin.setSingleStep(step)
            self.threshold = np.clip(self.threshold, low, up)
            self.histogram.setValues([])    # without this range breaks when changing linkages
            self.histogram.setValues(vals)
            self.histogram.setRegion(0, self.threshold)

            self.detect_duplicates()

    def detect_duplicates(self):
        if self.distances is not None:
            self.cluster_linkage()
            self.send_corpus()
            self.send_corpus_without_duplicates()
            self.fill_cluster_view()

    def cluster_linkage(self):
        # cluster documents
        n = int(self.n_documents)
        clusters = {j: [j] for j in range(n)}
        for i, (c1, c2, dist, size) in enumerate(self.linkage):
            if dist > self.threshold:
                break
            clusters[n + i] = clusters[c1] + clusters[c2]
            del clusters[c1]
            del clusters[c2]

        self.n_unique = len(clusters)
        self.n_duplicates = n - self.n_unique

        # create mask
        self.clustering_mask = np.empty(n, dtype=int)
        for i, c in enumerate(clusters.values()):
            self.clustering_mask[c] = i

    def fill_cluster_view(self):
        self.table_model.clear()
        c = Counter(self.clustering_mask)
        for id_, count in c.items():
            self.table_model.append([Cluster(id_), count])
        self.table_view.sortByColumn(1, Qt.DescendingOrder)
        self.table_view.selectRow(0)

    def send_corpus(self):
        if self.clustering_mask is not None:
            cluster_var = DiscreteVariable(
                'Duplicates Cluster',
                values=[str(Cluster(v)) for v in set(self.clustering_mask.flatten())]
            )
            corpus, domain = self.corpus, self.corpus.domain
            attrs = domain.attributes
            class_ = domain.class_vars
            metas = domain.metas

            if self.cluster_role == self.AttributeRole:
                attrs = attrs + (cluster_var,)
            elif self.cluster_role == self.ClassRole:
                class_ = class_ + (cluster_var,)
            elif self.cluster_role == self.MetaRole:
                metas = metas + (cluster_var,)

            domain = Domain(attrs, class_, metas)
            corpus = corpus.from_table(domain, corpus)
            corpus.get_column_view(cluster_var)[0][:] = self.clustering_mask
            self.send(IO.corpus, corpus)
        else:
            self.send(IO.corpus, None)

    def send_corpus_without_duplicates(self):
        if self.clustering_mask is not None:
            # TODO make this more general, currently we just take the first document
            mask = [np.where(self.clustering_mask == i)[0][0]
                    for i in set(self.clustering_mask)]
            c = self.corpus[mask]
            c.name = '{} (Without Duplicates)'.format(self.corpus.name)
            self.send(IO.corpus_without_duplicates, c)
        else:
            self.send(IO.corpus_without_duplicates, None)

    def send_duplicates(self):
        index = self.table_view.selectionModel().currentIndex().row()
        cluster = self.table_model[index][0]
        mask = np.flatnonzero(self.clustering_mask == cluster.id)
        c = self.corpus[mask]
        c.name = '{} {}'.format(IO.duplicates, cluster)
        self.send(IO.duplicates, c)

    def send_report(self):
        self.report_items([
            ('Linkage', self.LINKAGE[self.linkage_method]),
            ('Distance threshold', '{:.2f}'.format(self.threshold)),
            ('Documents', self.n_documents),
            ('Unique', self.n_unique),
            ('Duplicates', self.n_duplicates),
        ])
예제 #13
0
    def __init__(self):
        self.data = None
        box = gui.vBox(self.controlArea, 'Moving Transform')

        def _disable_fixed_wlen():
            fixed_wlen.setDisabled(not self.non_overlapping)
            self.view.repaint()
            self.on_changed()

        gui.checkBox(box, self, 'non_overlapping',
                     label=self._NON_OVERLAPPING_WINDOWS,
                     callback=_disable_fixed_wlen,
                     tooltip='If this is checked, instead of rolling windows '
                             'through the series, they are applied side-to-side, '
                             'so the resulting output series will be some '
                             'length-of-fixed-window-times shorter.')
        fixed_wlen = gui.spin(box, self, 'fixed_wlen', 2, 1000,
                              label='Fixed window width:',
                              callback=self.on_changed)
        fixed_wlen.setDisabled(not self.non_overlapping)
        # TODO: allow the user to choose left-aligned, right-aligned, or center-aligned window

        class TableView(gui.TableView):
            def __init__(self, parent):
                super().__init__(parent,
                                 editTriggers=(self.SelectedClicked |
                                               self.CurrentChanged |
                                               self.DoubleClicked |
                                               self.EditKeyPressed),
                                 )
                self.horizontalHeader().setStretchLastSection(False)
                agg_functions = ListModel(AGG_FUNCTIONS +
                                          [Cumulative_sum, Cumulative_product],
                                          parent=self)
                self.setItemDelegateForColumn(0, self.VariableDelegate(parent))
                self.setItemDelegateForColumn(1, self.SpinDelegate(parent))
                self.setItemDelegateForColumn(2, self.ComboDelegate(self, agg_functions))

            class _ItemDelegate(QStyledItemDelegate):
                def updateEditorGeometry(self, widget, option, _index):
                    widget.setGeometry(option.rect)

            class ComboDelegate(_ItemDelegate):
                def __init__(self, parent=None, combo_model=None):
                    super().__init__(parent)
                    self._parent = parent
                    if combo_model is not None:
                        self._combo_model = combo_model

                def createEditor(self, parent, _QStyleOptionViewItem, index):
                    combo = QComboBox(parent)
                    combo.setModel(self._combo_model)
                    return combo

                def setEditorData(self, combo, index):
                    var = index.model().data(index, Qt.EditRole)
                    combo.setCurrentIndex(self._combo_model.indexOf(var))

                def setModelData(self, combo, model, index):
                    var = self._combo_model[combo.currentIndex()]
                    model.setData(index, var, Qt.EditRole)

            class VariableDelegate(ComboDelegate):
                @property
                def _combo_model(self):
                    return self._parent.var_model

            class SpinDelegate(_ItemDelegate):
                def paint(self, painter, option, index):
                    # Don't paint window length if non-overlapping windows set
                    if not self.parent().non_overlapping:
                        super().paint(painter, option, index)

                def createEditor(self, parent, _QStyleOptionViewItem, _index):
                    # Don't edit window length if non-overlapping windows set
                    if self.parent().non_overlapping:
                        return None
                    spin = QSpinBox(parent, minimum=1, maximum=1000)
                    return spin

                def setEditorData(self, spin, index):
                    spin.setValue(index.model().data(index, Qt.EditRole))

                def setModelData(self, spin, model, index):
                    spin.interpretText()
                    model.setData(index, spin.value(), Qt.EditRole)

        self.var_model = VariableListModel(parent=self)

        self.table_model = model = PyTableModel(self.transformations,
                                                parent=self, editable=True)
        model.setHorizontalHeaderLabels(['Series', 'Window width', 'Aggregation function'])
        model.dataChanged.connect(self.on_changed)

        self.view = view = TableView(self)
        view.setModel(model)
        box.layout().addWidget(view)

        hbox = gui.hBox(box)
        from os.path import dirname, join
        self.add_button = button = gui.button(
            hbox, self, 'Add &Transform',
            callback=self.on_add_transform)
        button.setIcon(QIcon(join(dirname(__file__), 'icons', 'LineChart-plus.png')))

        self.del_button = button = gui.button(
            hbox, self, '&Delete Selected',
            callback=self.on_del_transform)
        QIcon.setThemeName('gnome')  # Works for me
        button.setIcon(QIcon.fromTheme('edit-delete'))

        gui.auto_commit(box, self, 'autocommit', '&Apply')
예제 #14
0
 def test_init(self):
     self.model = PyTableModel()
     self.assertEqual(self.model.rowCount(), 0)
예제 #15
0
class TestPyTableModel(TestCase):
    def setUp(self):
        self.model = PyTableModel([[1, 4],
                                   [2, 3]])

    def test_init(self):
        self.model = PyTableModel()
        self.assertEqual(self.model.rowCount(), 0)

    def test_rowCount(self):
        self.assertEqual(self.model.rowCount(), 2)
        self.assertEqual(len(self.model), 2)

    def test_columnCount(self):
        self.assertEqual(self.model.columnCount(), 2)

    def test_data(self):
        self.assertEqual(str(self.model.data(self.model.index(0, 0))), '1')

    def test_sort(self):
        self.model.sort(1)
        self.assertEqual(self.model[0][0], 2)

    def test_setHeaderLabels(self):
        self.model.setHorizontalHeaderLabels(['Col 1', 'Col 2'])
        self.assertEqual(self.model.headerData(1, Qt.Horizontal), 'Col 2')
        self.assertEqual(self.model.headerData(1, Qt.Vertical), '1')

    def test_removeRows(self):
        self.model.removeRows(0, 1)
        self.assertEqual(len(self.model), 1)
        self.assertEqual(self.model[0][1], 3)

    def test_removeColumns(self):
        self.model.removeColumns(0, 1)
        self.assertEqual(self.model.columnCount(), 1)
        self.assertEqual(self.model[1][0], 3)

    def test_insertRows(self):
        self.model.insertRows(0, 1)
        self.assertEqual(self.model[1][0], 1)

    def test_insertColumns(self):
        self.model.insertColumns(0, 1)
        self.assertEqual(self.model[0], ['', 1, 4])

    def test_wrap(self):
        self.model.wrap([[0]])
        self.assertEqual(self.model.rowCount(), 1)
        self.assertEqual(self.model.columnCount(), 1)

    def test_clear(self):
        self.model.clear()
        self.assertEqual(self.model.rowCount(), 0)

    def test_append(self):
        self.model.append([5, 6])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_extend(self):
        self.model.extend([[5, 6]])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_insert(self):
        self.model.insert(0, [5, 6])
        self.assertEqual(self.model[0][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_remove(self):
        self.model.remove([2, 3])
        self.assertEqual(self.model.rowCount(), 1)
    def __init__(self):
        OWWidget.__init__(self)
        ConcurrentWidgetMixin.__init__(self)

        self.data: Optional[Table] = None
        self.attr_name_to_variable: Optional[Table] = None
        self.covariates_from_worker_result = None
        self.time_var: Optional[str] = None
        self.event_var: Optional[str] = None

        gui.rubber(self.controlArea)

        sel_method_box = gui.vBox(self.buttonsArea, 'Select Attributes')
        grid = QGridLayout()
        grid.setContentsMargins(0, 0, 0, 0)
        grid.setSpacing(6)
        self.select_buttons = QButtonGroup()
        self.select_buttons.buttonClicked[int].connect(
            self.set_selection_method)

        def button(text, buttonid, toolTip=None):
            b = QRadioButton(text)
            self.select_buttons.addButton(b, buttonid)
            if toolTip is not None:
                b.setToolTip(toolTip)
            return b

        b1 = button(self.tr('None'), OWRankSurvivalFeatures.select_none)
        b2 = button(self.tr('Manual'), OWRankSurvivalFeatures.manual_selection)
        b3 = button(self.tr('Best ranked:'),
                    OWRankSurvivalFeatures.select_n_best)

        s = gui.spin(
            sel_method_box,
            self,
            'n_selected',
            1,
            999,
            callback=lambda: self.set_selection_method(OWRankSurvivalFeatures.
                                                       select_n_best),
            addToLayout=False,
        )

        grid.addWidget(b1, 0, 0)
        grid.addWidget(b2, 1, 0)
        grid.addWidget(b3, 2, 0)
        grid.addWidget(s, 2, 1)

        sel_method_box.layout().addLayout(grid)

        self.commit_button = gui.auto_commit(self.buttonsArea,
                                             self,
                                             'auto_commit',
                                             '&Commit',
                                             box=False)

        # Main area
        self.model = PyTableModel(parent=self)
        self.table_view = TableView(parent=self)
        self.table_view.setModel(self.model)
        self.model.setHorizontalHeaderLabels([
            'Log-Likelihood', 'Log-Likelihood Ratio', f'{"p".center(13)}',
            'FDR'
        ])
        self.table_view.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.table_view.selectionModel().selectionChanged.connect(
            self.on_select)

        def _set_select_manual():
            self.set_selection_method(OWRankSurvivalFeatures.manual_selection)

        self.table_view.manualSelection.connect(_set_select_manual)
        self.table_view.verticalHeader().sectionClicked.connect(
            _set_select_manual)

        self.mainArea.layout().addWidget(self.table_view)
예제 #17
0
    def test_report_table(self):
        rep = OWReport.get_instance()
        model = PyTableModel([['x', 1, 2], ['y', 2, 2]])
        model.setHorizontalHeaderLabels(['a', 'b', 'c'])

        model.setData(model.index(0, 0), Qt.AlignHCenter | Qt.AlignTop,
                      Qt.TextAlignmentRole)
        model.setData(model.index(1, 0), QFont('', -1, QFont.Bold),
                      Qt.FontRole)
        model.setData(model.index(1, 2), QBrush(Qt.red), Qt.BackgroundRole)

        view = gui.TableView()
        view.show()
        view.setModel(model)
        rep.report_table('Name', view)
        self.maxDiff = None
        self.assertEqual(
            rep.report_html, '<h2>Name</h2><table>\n'
            '<tr>'
            '<th style="color:black;border:0;background:transparent;'
            'text-align:left;vertical-align:middle;">a</th>'
            '<th style="color:black;border:0;background:transparent;'
            'text-align:left;vertical-align:middle;">b</th>'
            '<th style="color:black;border:0;background:transparent;'
            'text-align:left;vertical-align:middle;">c</th>'
            '</tr>'
            '<tr>'
            '<td style="color:black;border:0;background:transparent;'
            'text-align:center;vertical-align:top;">x</td>'
            '<td style="color:black;border:0;background:transparent;'
            'text-align:right;vertical-align:middle;">1</td>'
            '<td style="color:black;border:0;background:transparent;'
            'text-align:right;vertical-align:middle;">2</td>'
            '</tr>'
            '<tr>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight: bold;text-align:left;vertical-align:middle;">y</td>'
            '<td style="color:black;border:0;background:transparent;'
            'text-align:right;vertical-align:middle;">2</td>'
            '<td style="color:black;border:0;background:#ff0000;'
            'text-align:right;vertical-align:middle;">2</td>'
            '</tr></table>')
예제 #18
0
 def test_editable(self):
     editable_model = PyTableModel([[0]], editable=True)
     self.assertFalse(int(self.model.flags(self.model.index(0, 0)) & Qt.ItemIsEditable))
     self.assertTrue(int(editable_model.flags(editable_model.index(0, 0)) & Qt.ItemIsEditable))
class OWRankSurvivalFeatures(OWWidget, ConcurrentWidgetMixin):
    name = 'Rank Survival Features'
    # TODO: Add widget metadata
    description = ''
    icon = 'icons/owranksurvivalfeatures.svg'
    priority = 30
    keywords = []

    buttons_area_orientation = Qt.Vertical
    select_none, manual_selection, select_n_best = range(3)

    settingsHandler = DomainContextHandler()
    selected_attrs = ContextSetting([], schema_only=True)
    selection_method = Setting(select_n_best, schema_only=True)
    n_selected = Setting(20, schema_only=True)
    auto_commit: bool = Setting(False, schema_only=True)

    class Inputs:
        data = Input('Data', Table)

    class Outputs:
        reduced_data = Output('Reduced Data', Table, default=True)

    def __init__(self):
        OWWidget.__init__(self)
        ConcurrentWidgetMixin.__init__(self)

        self.data: Optional[Table] = None
        self.attr_name_to_variable: Optional[Table] = None
        self.covariates_from_worker_result = None
        self.time_var: Optional[str] = None
        self.event_var: Optional[str] = None

        gui.rubber(self.controlArea)

        sel_method_box = gui.vBox(self.buttonsArea, 'Select Attributes')
        grid = QGridLayout()
        grid.setContentsMargins(0, 0, 0, 0)
        grid.setSpacing(6)
        self.select_buttons = QButtonGroup()
        self.select_buttons.buttonClicked[int].connect(
            self.set_selection_method)

        def button(text, buttonid, toolTip=None):
            b = QRadioButton(text)
            self.select_buttons.addButton(b, buttonid)
            if toolTip is not None:
                b.setToolTip(toolTip)
            return b

        b1 = button(self.tr('None'), OWRankSurvivalFeatures.select_none)
        b2 = button(self.tr('Manual'), OWRankSurvivalFeatures.manual_selection)
        b3 = button(self.tr('Best ranked:'),
                    OWRankSurvivalFeatures.select_n_best)

        s = gui.spin(
            sel_method_box,
            self,
            'n_selected',
            1,
            999,
            callback=lambda: self.set_selection_method(OWRankSurvivalFeatures.
                                                       select_n_best),
            addToLayout=False,
        )

        grid.addWidget(b1, 0, 0)
        grid.addWidget(b2, 1, 0)
        grid.addWidget(b3, 2, 0)
        grid.addWidget(s, 2, 1)

        sel_method_box.layout().addLayout(grid)

        self.commit_button = gui.auto_commit(self.buttonsArea,
                                             self,
                                             'auto_commit',
                                             '&Commit',
                                             box=False)

        # Main area
        self.model = PyTableModel(parent=self)
        self.table_view = TableView(parent=self)
        self.table_view.setModel(self.model)
        self.model.setHorizontalHeaderLabels([
            'Log-Likelihood', 'Log-Likelihood Ratio', f'{"p".center(13)}',
            'FDR'
        ])
        self.table_view.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        self.table_view.selectionModel().selectionChanged.connect(
            self.on_select)

        def _set_select_manual():
            self.set_selection_method(OWRankSurvivalFeatures.manual_selection)

        self.table_view.manualSelection.connect(_set_select_manual)
        self.table_view.verticalHeader().sectionClicked.connect(
            _set_select_manual)

        self.mainArea.layout().addWidget(self.table_view)

    @property
    def covariates(self) -> Optional[List[str]]:
        if not self.data:
            return
        return [attr.name for attr in self.data.domain.attributes]

    @Inputs.data
    @check_survival_data
    def set_data(self, data: Table):
        self.closeContext()
        self.selected_attrs = []
        self.covariates_from_worker_result = []
        self.model.clear()
        self.model.resetSorting()

        if not data:
            return

        self.data = data
        self.attr_name_to_variable = {
            attr.name: attr
            for attr in self.data.domain.attributes
        }

        self.openContext(data)
        time_var, event_var = get_survival_endpoints(self.data.domain)
        self.time_var, self.event_var = time_var.name, event_var.name
        self.start(worker, self.data, self.covariates, self.time_var,
                   self.event_var)

    def commit(self):
        if not self.selected_attrs:
            self.Outputs.reduced_data.send(None)
        else:
            reduced_domain = Domain(self.selected_attrs,
                                    self.data.domain.class_vars,
                                    self.data.domain.metas)
            data = self.data.transform(reduced_domain)
            self.Outputs.reduced_data.send(data)

    def on_done(self, worker_result):
        covariate_names, results = worker_result

        # wrap everything except covariate names
        self.model.wrap(results.tolist())

        # this is temp solution because covariate orders gets mixed when using multiprocessing
        self.covariates_from_worker_result = covariate_names.tolist()

        # match covariate names to domain variables and set vertical header
        self.model.setVerticalHeaderLabels(
            [self.attr_name_to_variable[name] for name in covariate_names])
        self.table_view.resizeColumnsToContents()

        self.auto_select()

    def on_exception(self, ex):
        raise ex

    def on_partial_result(self, result: Any) -> None:
        pass

    def set_selection_method(self, method):
        self.selection_method = method
        self.select_buttons.button(method).setChecked(True)
        self.auto_select()

    def auto_select(self):
        selection_model = self.table_view.selectionModel()
        row_count = self.model.rowCount()
        column_count = self.model.columnCount()

        if self.selection_method == OWRankSurvivalFeatures.select_none:
            selection = QItemSelection()
        elif self.selection_method == OWRankSurvivalFeatures.select_n_best:
            n_selected = min(self.n_selected, row_count)
            selection = QItemSelection(
                self.model.index(0, 0),
                self.model.index(n_selected - 1, column_count - 1))
        else:
            selection = QItemSelection()
            if self.selected_attrs is not None:
                attr_indices = [
                    self.covariates_from_worker_result.index(var.name)
                    for var in self.selected_attrs
                ]
                for row in self.model.mapFromSourceRows(attr_indices):
                    selection.append(
                        QItemSelectionRange(
                            self.model.index(row, 0),
                            self.model.index(row, column_count - 1)))

        selection_model.select(selection, QItemSelectionModel.ClearAndSelect)

    def on_select(self):
        selected_rows = self.table_view.selectionModel().selectedRows(0)
        row_indices = [i.row() for i in selected_rows]
        attr_indices = self.model.mapToSourceRows(row_indices)
        self.selected_attrs = [
            self.model._headers[Qt.Vertical][row] for row in attr_indices
        ]
        self.commit()
예제 #20
0
    def __init__(self):
        super().__init__()
        self.corpus = None  # corpus taken from distances
        self.linkage = None  # hierarchical clustering linkage as returned by Orange
        self.distances = None  # DistMatrix on input
        self.clustering_mask = None  # 1D array of clusters for self.corpus
        self.threshold_spin = None

        # Info
        self.n_documents = ''
        self.n_unique = ''
        self.n_duplicates = ''
        info_box = gui.widgetBox(self.controlArea, box='Info')
        gui.label(info_box, self, 'Documents: %(n_documents)s')
        gui.label(info_box, self, '  ◦ unique: %(n_unique)s')
        gui.label(info_box, self, '  ◦ duplicates: %(n_duplicates)s')

        # Threshold Histogram & Cluster View
        self.histogram = Histogram(self)
        self.table_view = gui.TableView(
            selectionMode=QListView.SingleSelection)
        self.table_model = PyTableModel()
        self.table_model.setHorizontalHeaderLabels(['Cluster', 'Size'])
        self.table_view.setModel(self.table_model)
        self.table_view.selectionModel().selectionChanged.connect(
            self.send_duplicates)

        # Add to main area
        height = 300
        main_area = gui.hBox(self.mainArea)
        self.histogram.setMinimumWidth(500)
        self.histogram.setMinimumHeight(height)
        self.table_view.setFixedWidth(140)
        main_area.layout().addWidget(self.histogram)
        main_area.layout().addWidget(self.table_view)

        # Controls
        gui.comboBox(self.controlArea,
                     self,
                     'linkage_method',
                     items=self.LINKAGE,
                     box='Linkage',
                     callback=self.recalculate_linkage,
                     orientation=Qt.Horizontal)
        self.threshold_spin = gui.doubleSpin(self.controlArea,
                                             self,
                                             'threshold',
                                             0,
                                             float('inf'),
                                             0.01,
                                             decimals=2,
                                             label='Distance threshold',
                                             box='Distances',
                                             callback=self.threshold_changed,
                                             keyboardTracking=False,
                                             controlWidth=60)
        self.histogram.region.sigRegionChangeFinished.connect(
            self.threshold_from_histogram_region)
        self.threshold_spin.setEnabled(False)
        gui.rubber(self.controlArea)

        # Output
        gui.comboBox(self.controlArea,
                     self,
                     "cluster_role",
                     box='Output',
                     label='Append Cluster IDs to:',
                     callback=self.send_corpus,
                     items=self.CLUSTER_ROLES)
예제 #21
0
class TestPyTableModel(unittest.TestCase):
    def setUp(self):
        self.model = PyTableModel([[1, 4],
                                   [2, 3]])

    def test_init(self):
        self.model = PyTableModel()
        self.assertEqual(self.model.rowCount(), 0)

    def test_rowCount(self):
        self.assertEqual(self.model.rowCount(), 2)
        self.assertEqual(len(self.model), 2)

    def test_columnCount(self):
        self.assertEqual(self.model.columnCount(), 2)

    def test_data(self):
        mi = self.model.index(0, 0)
        self.assertEqual(self.model.data(mi), '1')
        self.assertEqual(self.model.data(mi, Qt.EditRole), 1)

    def test_editable(self):
        editable_model = PyTableModel([[0]], editable=True)
        self.assertFalse(int(self.model.flags(self.model.index(0, 0)) & Qt.ItemIsEditable))
        self.assertTrue(int(editable_model.flags(editable_model.index(0, 0)) & Qt.ItemIsEditable))

    def test_sort(self):
        self.model.sort(1)
        self.assertEqual(self.model.index(0, 0).data(Qt.EditRole), 2)

    def test_setHeaderLabels(self):
        self.model.setHorizontalHeaderLabels(['Col 1', 'Col 2'])
        self.assertEqual(self.model.headerData(1, Qt.Horizontal), 'Col 2')
        self.assertEqual(self.model.headerData(1, Qt.Vertical), 2)

    def test_removeRows(self):
        self.model.removeRows(0, 1)
        self.assertEqual(len(self.model), 1)
        self.assertEqual(self.model[0][1], 3)

    def test_removeColumns(self):
        self.model.removeColumns(0, 1)
        self.assertEqual(self.model.columnCount(), 1)
        self.assertEqual(self.model[1][0], 3)

    def test_insertRows(self):
        self.model.insertRows(0, 1)
        self.assertEqual(self.model[1][0], 1)

    def test_insertColumns(self):
        self.model.insertColumns(0, 1)
        self.assertEqual(self.model[0], ['', 1, 4])

    def test_wrap(self):
        self.model.wrap([[0]])
        self.assertEqual(self.model.rowCount(), 1)
        self.assertEqual(self.model.columnCount(), 1)

    def test_clear(self):
        self.model.clear()
        self.assertEqual(self.model.rowCount(), 0)

    def test_append(self):
        self.model.append([5, 6])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_extend(self):
        self.model.extend([[5, 6]])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_insert(self):
        self.model.insert(0, [5, 6])
        self.assertEqual(self.model[0][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_remove(self):
        self.model.remove([2, 3])
        self.assertEqual(self.model.rowCount(), 1)

    def test_other_roles(self):
        self.model.append([2, 3])
        self.model.setData(self.model.index(2, 0),
                           Qt.AlignCenter,
                           Qt.TextAlignmentRole)
        del self.model[1]
        self.assertTrue(Qt.AlignCenter &
                        self.model.data(self.model.index(1, 0),
                                        Qt.TextAlignmentRole))
예제 #22
0
 def setUp(self):
     self.model = PyTableModel([[1, 4],
                                [2, 3]])
예제 #23
0
class TestPyTableModel(unittest.TestCase):
    def setUp(self):
        self.model = PyTableModel([[1, 4], [2, 3]])

    def test_init(self):
        self.model = PyTableModel()
        self.assertEqual(self.model.rowCount(), 0)

    def test_rowCount(self):
        self.assertEqual(self.model.rowCount(), 2)
        self.assertEqual(len(self.model), 2)

    def test_columnCount(self):
        self.assertEqual(self.model.columnCount(), 2)

    def test_data(self):
        mi = self.model.index(0, 0)
        self.assertEqual(self.model.data(mi), '1')
        self.assertEqual(self.model.data(mi, Qt.EditRole), 1)

    def test_editable(self):
        editable_model = PyTableModel([[0]], editable=True)
        self.assertFalse(
            int(self.model.flags(self.model.index(0, 0)) & Qt.ItemIsEditable))
        self.assertTrue(
            int(
                editable_model.flags(editable_model.index(0, 0))
                & Qt.ItemIsEditable))

    def test_sort(self):
        self.model.sort(1)
        self.assertEqual(self.model.index(0, 0).data(Qt.EditRole), 2)

    def test_setHeaderLabels(self):
        self.model.setHorizontalHeaderLabels(['Col 1', 'Col 2'])
        self.assertEqual(self.model.headerData(1, Qt.Horizontal), 'Col 2')
        self.assertEqual(self.model.headerData(1, Qt.Vertical), 2)

    def test_removeRows(self):
        self.model.removeRows(0, 1)
        self.assertEqual(len(self.model), 1)
        self.assertEqual(self.model[0][1], 3)

    def test_removeColumns(self):
        self.model.removeColumns(0, 1)
        self.assertEqual(self.model.columnCount(), 1)
        self.assertEqual(self.model[1][0], 3)

    def test_insertRows(self):
        self.model.insertRows(0, 1)
        self.assertEqual(self.model[1][0], 1)

    def test_insertColumns(self):
        self.model.insertColumns(0, 1)
        self.assertEqual(self.model[0], ['', 1, 4])

    def test_wrap(self):
        self.model.wrap([[0]])
        self.assertEqual(self.model.rowCount(), 1)
        self.assertEqual(self.model.columnCount(), 1)

    def test_clear(self):
        self.model.clear()
        self.assertEqual(self.model.rowCount(), 0)

    def test_append(self):
        self.model.append([5, 6])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_extend(self):
        self.model.extend([[5, 6]])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_insert(self):
        self.model.insert(0, [5, 6])
        self.assertEqual(self.model[0][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_remove(self):
        self.model.remove([2, 3])
        self.assertEqual(self.model.rowCount(), 1)

    def test_other_roles(self):
        self.model.append([2, 3])
        self.model.setData(self.model.index(2, 0), Qt.AlignCenter,
                           Qt.TextAlignmentRole)
        del self.model[1]
        self.assertTrue(
            Qt.AlignCenter
            & self.model.data(self.model.index(1, 0), Qt.TextAlignmentRole))

    def test_set_iten_slice(self):
        self.model[:1] = [[10, 11], [12, 13], [14, 15]]
        self.assertEqual(list(self.model),
                         [[10, 11], [12, 13], [14, 15], [2, 3]])

        self.model[1:3] = []
        self.assertEqual(list(self.model), [[10, 11], [2, 3]])

        self.model[:] = [[20, 21]]
        self.assertEqual(list(self.model), [[20, 21]])

        self.model[1:] = [[10, 11], [2, 3]]
        self.assertEqual(list(self.model), [[20, 21], [10, 11], [2, 3]])

    def test_emits_column_changes_on_row_insert(self):
        inserted = []
        removed = []
        model = PyTableModel()
        model.columnsInserted.connect(inserted.append)
        model.columnsRemoved.connect(removed.append)
        inserted = QSignalSpy(model.columnsInserted)
        removed = QSignalSpy(model.columnsRemoved)
        model.append([2])
        self.assertEqual(list(inserted)[-1][1:], [0, 0])
        model.append([2, 3])
        self.assertEqual(list(inserted)[-1][1:], [1, 1])
        del model[:]
        self.assertEqual(list(removed)[0][1:], [0, 1])
        model.extend([[0, 1], [0, 2]])
        self.assertEqual(list(inserted)[-1][1:], [0, 1])
        model.clear()
        self.assertEqual(list(removed)[0][1:], [0, 1])
        model[:] = [[1], [2]]
        self.assertEqual(list(inserted)[-1][1:], [0, 0])
예제 #24
0
 def test_editable(self):
     editable_model = PyTableModel([[0]], editable=True)
     self.assertFalse(int(self.model.flags(self.model.index(0, 0)) & Qt.ItemIsEditable))
     self.assertTrue(int(editable_model.flags(editable_model.index(0, 0)) & Qt.ItemIsEditable))
예제 #25
0
    def __init__(self):
        self.data = None
        self.indices = []

        gui.comboBox(
            self.controlArea,
            self,
            'agg_interval',
            label='Aggregate by:',
            items=tuple(self.AGG_TIME.keys()),
            sendSelectedValue=True,
            orientation=Qt.Horizontal,
            callback=self.on_changed,
        )
        self.model = model = PyTableModel(parent=self, editable=[False, True])
        model.setHorizontalHeaderLabels(['Attribute', 'Aggregation function'])

        class TableView(gui.TableView):
            def __init__(self, parent):
                super().__init__(
                    parent,
                    editTriggers=(self.SelectedClicked | self.CurrentChanged
                                  | self.DoubleClicked | self.EditKeyPressed),
                )
                self.horizontalHeader().setStretchLastSection(False)
                self.setItemDelegateForColumn(1, self.ComboDelegate(self))

            class _ItemDelegate(QStyledItemDelegate):
                def updateEditorGeometry(self, widget, option, _index):
                    widget.setGeometry(option.rect)

            class ComboDelegate(_ItemDelegate):
                def __init__(self, parent):
                    super().__init__(parent)
                    self._parent = parent
                    self._combo_continuous_model = ListModel(AGG_FUNCTIONS,
                                                             parent=self)
                    self._combo_discrete_model = ListModel([Mode], parent=self)
                    self._combo_string_model = ListModel([Concatenate],
                                                         parent=self)

                def createEditor(self, parent, _QStyleOptionViewItem, index):
                    combo = QComboBox(parent)
                    attr = index.model()[index.row()][0]
                    combo.setModel(
                        self._combo_continuous_model if attr.
                        is_continuous else self._combo_discrete_model if attr.
                        is_discrete else self._combo_string_model)
                    return combo

                def setEditorData(self, combo, index):
                    var = index.model().data(index, Qt.EditRole)
                    combo.setCurrentIndex(combo.model().indexOf(var))

                def setModelData(self, combo, model, index):
                    func = combo.model()[combo.currentIndex()]
                    model.setData(index, func, Qt.EditRole)

        view = TableView(self)
        view.setModel(model)
        model.dataChanged.connect(self.on_changed)
        self.controlArea.layout().addWidget(view)
        gui.auto_commit(self.controlArea, self, 'autocommit', '&Apply')
예제 #26
0
    def __init__(self):
        super().__init__()
        self.data = None
        self.domainmodels = []
        self.unmatched = []

        top = self.controlArea

        def _radioChanged():
            self.mainArea.setVisible(self.is_decoding == 0
                                     and len(self.unmatched))
            self.commit()

        modes = gui.radioButtons(top,
                                 self,
                                 'is_decoding',
                                 callback=_radioChanged)

        gui.appendRadioButton(
            modes,
            '&Encode region names into geographical coordinates:',
            insertInto=top)
        box = gui.indentedBox(top)
        model = DomainModel(parent=self,
                            valid_types=(StringVariable, DiscreteVariable))
        self.domainmodels.append(model)

        combo = gui.comboBox(box,
                             self,
                             'str_attr',
                             label='Region identifier:',
                             orientation=Qt.Horizontal,
                             callback=self.region_attr_changed,
                             sendSelectedValue=True,
                             model=model)
        gui.comboBox(box,
                     self,
                     'str_type',
                     label='Identifier type:',
                     orientation=Qt.Horizontal,
                     items=tuple(self.ID_TYPE.keys()),
                     callback=lambda: self.commit(),
                     sendSelectedValue=True)

        # Select first mode if any of its combos are changed
        for combo in box.findChildren(QComboBox):
            combo.activated.connect(lambda: setattr(self, 'is_decoding', 0))

        gui.appendRadioButton(modes,
                              '&Decode latitude and longitude into regions:',
                              insertInto=top)
        box = gui.indentedBox(top)
        model = DomainModel(parent=self, valid_types=ContinuousVariable)
        self.domainmodels.append(model)
        combo = gui.comboBox(box,
                             self,
                             'lat_attr',
                             label='Latitude:',
                             orientation=Qt.Horizontal,
                             callback=lambda: self.commit(),
                             sendSelectedValue=True,
                             model=model)
        combo = gui.comboBox(box,
                             self,
                             'lon_attr',
                             label='Longitude:',
                             orientation=Qt.Horizontal,
                             callback=lambda: self.commit(),
                             sendSelectedValue=True,
                             model=model)
        gui.comboBox(
            box,
            self,
            'admin',
            label='Administrative level:',
            orientation=Qt.Horizontal,
            callback=lambda: self.commit(),
            items=
            ('Country',
             '1st-level subdivision (state, region, province, municipality, ...)',
             '2nd-level subdivisions (1st-level & US counties)'),
        )

        # Select second mode if any of its combos are changed
        for combo in box.findChildren(QComboBox):
            combo.activated.connect(lambda: setattr(self, 'is_decoding', 1))

        gui.checkBox(
            top,
            self,
            'append_features',
            label='E&xtend coded data with additional region properties',
            callback=lambda: self.commit(),
            toolTip='Extend coded data with region properties, such as'
            'ISO codes, continent, subregion, region type, '
            'economy type, FIPS/HASC codes, region capital etc. as available.')

        gui.auto_commit(self.controlArea, self, 'autocommit', '&Apply')
        gui.rubber(self.controlArea)

        model = self.replacementsModel = PyTableModel(self.replacements,
                                                      parent=self,
                                                      editable=[False, True])
        view = gui.TableView(self,
                             sortingEnabled=False,
                             selectionMode=gui.TableView.NoSelection,
                             editTriggers=gui.TableView.AllEditTriggers)
        view.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        view.verticalHeader().setSectionResizeMode(0)
        view.setModel(model)

        owwidget = self

        class TableItemDelegate(QItemDelegate):
            def createEditor(self, parent, options, index):
                nonlocal owwidget
                edit = QLineEdit(parent)
                wordlist = [''] + ToLatLon.valid_values(
                    owwidget.ID_TYPE[owwidget.str_type])
                edit.setCompleter(
                    QCompleter(wordlist,
                               edit,
                               caseSensitivity=Qt.CaseInsensitive,
                               filterMode=Qt.MatchContains))

                def save_and_commit():
                    if edit.text() and edit.text() in wordlist:
                        model = index.model()
                        pindex = QPersistentModelIndex(index)
                        if pindex.isValid():
                            new_index = pindex.sibling(pindex.row(),
                                                       pindex.column())
                            save = model.setData(new_index, edit.text(),
                                                 Qt.EditRole)
                            if save:
                                owwidget.commit()
                                return
                    edit.clear()

                edit.editingFinished.connect(save_and_commit)
                return edit

        view.setItemDelegate(TableItemDelegate())
        model.setHorizontalHeaderLabels(
            ['Unmatched Identifier', 'Custom Replacement'])
        box = gui.vBox(self.mainArea)
        self.info_str = ' /'
        gui.label(box, self, 'Unmatched identifiers: %(info_str)s')
        box.layout().addWidget(view)
        self.mainArea.setVisible(self.is_decoding == 0)
예제 #27
0
 def setUp(self):
     self.model = PyTableModel([[1, 4], [2, 3]])
예제 #28
0
    def __init__(self):
        super().__init__()
        self.data = None
        self.domainmodels = []

        top = self.controlArea

        def _radioChanged():
            self.mainArea.setVisible(self.is_decoding == 0)
            self.commit()

        modes = gui.radioButtons(top,
                                 self,
                                 'is_decoding',
                                 callback=_radioChanged)

        gui.appendRadioButton(
            modes,
            '&Encode region names into geographical coordinates:',
            insertInto=top)
        box = gui.indentedBox(top)
        model = DomainModel(parent=self,
                            valid_types=(StringVariable, DiscreteVariable))
        self.domainmodels.append(model)

        def _region_attr_changed():
            if self.data is None:
                return

            # Auto-detect the type of region in the attribute and set its combo
            values = self._get_data_values()
            func = ToLatLon.detect_input(values)
            str_type = next((k for k, v in self.ID_TYPE.items() if v == func),
                            None)
            if str_type is not None and str_type != self.str_type:
                self.str_type = str_type

            self.commit()

        combo = gui.comboBox(box,
                             self,
                             'str_attr',
                             label='Region identifier:',
                             orientation=Qt.Horizontal,
                             callback=_region_attr_changed,
                             sendSelectedValue=True)
        combo.setModel(model)
        gui.comboBox(box,
                     self,
                     'str_type',
                     label='Identifier type:',
                     orientation=Qt.Horizontal,
                     items=tuple(self.ID_TYPE.keys()),
                     callback=lambda: self.commit(),
                     sendSelectedValue=True)

        # Select first mode if any of its combos are changed
        for combo in box.findChildren(QComboBox):
            combo.currentIndexChanged.connect(
                lambda: setattr(self, 'is_decoding', 0))

        gui.appendRadioButton(modes,
                              '&Decode latitude and longitude into regions:',
                              insertInto=top)
        box = gui.indentedBox(top)
        model = DomainModel(parent=self, valid_types=ContinuousVariable)
        self.domainmodels.append(model)
        combo = gui.comboBox(box,
                             self,
                             'lat_attr',
                             label='Latitude:',
                             orientation=Qt.Horizontal,
                             callback=lambda: self.commit(),
                             sendSelectedValue=True)
        combo.setModel(model)
        combo = gui.comboBox(box,
                             self,
                             'lon_attr',
                             label='Longitude:',
                             orientation=Qt.Horizontal,
                             callback=lambda: self.commit(),
                             sendSelectedValue=True)
        combo.setModel(model)
        gui.comboBox(
            box,
            self,
            'admin',
            label='Administrative level:',
            orientation=Qt.Horizontal,
            callback=lambda: self.commit(),
            items=
            ('Country',
             '1st-level subdivision (state, region, province, municipality, ...)',
             '2nd-level subdivisions (1st-level & US counties)'),
        )

        # Select second mode if any of its combos are changed
        for combo in box.findChildren(QComboBox):
            combo.currentIndexChanged.connect(
                lambda: setattr(self, 'is_decoding', 1))

        gui.checkBox(
            top,
            self,
            'append_features',
            label='E&xtend coded data with additional region properties',
            callback=lambda: self.commit(),
            toolTip='Extend coded data with region properties, such as'
            'ISO codes, continent, subregion, region type, '
            'economy type, FIPS/HASC codes, region capital etc. as available.')

        gui.auto_commit(self.controlArea, self, 'autocommit', '&Apply')

        model = self.replacementsModel = PyTableModel(self.replacements,
                                                      parent=self,
                                                      editable=[False, True])
        view = gui.TableView(self,
                             sortingEnabled=False,
                             selectionMode=gui.TableView.NoSelection,
                             editTriggers=gui.TableView.AllEditTriggers)
        view.horizontalHeader().setSectionResizeMode(0)
        view.verticalHeader().setSectionResizeMode(0)
        view.setModel(model)

        owwidget = self

        class EditorFactory(QItemEditorFactory):
            def createEditor(self, p_int, parent):
                nonlocal owwidget
                edit = QLineEdit(parent)
                wordlist = [''] + ToLatLon.valid_values(
                    owwidget.ID_TYPE[owwidget.str_type])
                edit.setCompleter(
                    QCompleter(wordlist,
                               edit,
                               caseSensitivity=Qt.CaseInsensitive,
                               filterMode=Qt.MatchContains))
                return edit

        self.factory = EditorFactory()
        view.itemDelegate().setItemEditorFactory(self.factory)
        model.setHorizontalHeaderLabels(
            ['Unmatched Identifier', 'Custom Replacement'])
        box = gui.vBox(self.mainArea)
        self.info_str = ' /'
        gui.label(box, self, 'Unmatched identifiers: %(info_str)s')
        box.layout().addWidget(view)
        self.mainArea.setVisible(self.is_decoding == 0)
예제 #29
0
    def _create_layout(self):
        self.mainArea.layout().addWidget(self.graphview)
        info = gui.widgetBox(self.controlArea, 'Info')
        gui.label(info, self, '%(n_object_types)d object types')
        gui.label(info, self, '%(n_relations)d relations')
        # Table view of relation details
        info = gui.widgetBox(self.controlArea, 'Relations')

        class TableView(gui.TableView):
            def __init__(self, parent=None, **kwargs):
                super().__init__(parent, **kwargs)
                self._parent = parent
                self.bold_font = self.BoldFontDelegate(
                    self)  # member because PyQt sometimes unrefs too early
                self.setItemDelegateForColumn(2, self.bold_font)
                self.setItemDelegateForColumn(4, self.bold_font)
                self.horizontalHeader().setVisible(False)

            def selectionChanged(self, selected, deselected):
                super().selectionChanged(selected, deselected)
                if not selected:
                    assert len(deselected) > 0
                    relation = None
                else:
                    assert len(selected) == 1
                    data = self._parent.tablemodel[selected[0].top()][0]
                    relation = Relation(data)
                self._parent.send(Output.RELATION, relation)

        model = self.tablemodel = PyTableModel(parent=self)
        table = self.table = TableView(self,
                                       selectionMode=TableView.SingleSelection)
        table.setModel(model)
        info.layout().addWidget(self.table)

        gui.lineEdit(self.controlArea,
                     self,
                     'pref_algo_name',
                     'Fuser name:',
                     orientation='horizontal',
                     callback=self.checkcommit,
                     enterPlaceholder=True)
        gui.radioButtons(self.controlArea,
                         self,
                         'pref_algorithm', [i[0] for i in DECOMPOSITION_ALGO],
                         box='Decomposition algorithm',
                         callback=self.checkcommit)
        gui.radioButtons(self.controlArea,
                         self,
                         'pref_initialization',
                         INITIALIZATION_ALGO,
                         box='Initialization algorithm',
                         callback=self.checkcommit)
        slider = gui.hSlider(self.controlArea,
                             self,
                             'pref_n_iterations',
                             'Maximum number of iterations',
                             minValue=10,
                             maxValue=500,
                             createLabel=True,
                             callback=self.checkcommit)
        slider.setTracking(False)
        self.slider_rank = gui.hSlider(self.controlArea,
                                       self,
                                       'pref_rank',
                                       'Factorization rank',
                                       minValue=1,
                                       maxValue=100,
                                       createLabel=True,
                                       labelFormat=" %d%%",
                                       callback=self.checkcommit)
        self.slider_rank.setTracking(False)
        gui.auto_commit(self.controlArea,
                        self,
                        "autorun",
                        "Run",
                        checkbox_label="Run after any change  ")
예제 #30
0
    def _create_layout(self):
        self._new_webview()
        box = gui.widgetBox(self.controlArea, 'Info')
        self.topic_info = gui.label(box, self,
                                    '%(n_topic_words)d words in a topic')
        gui.label(box, self, '%(documents_info_str)s')

        box = gui.widgetBox(self.controlArea, 'Cloud preferences')
        gui.checkBox(box,
                     self,
                     'words_color',
                     'Color words',
                     callback=self.on_cloud_pref_change)
        TILT_VALUES = ('no', '30°', '45°', '60°')
        gui.valueSlider(box,
                        self,
                        'words_tilt',
                        label='Words tilt:',
                        values=list(range(len(TILT_VALUES))),
                        callback=self.on_cloud_pref_change,
                        labelFormat=lambda x: TILT_VALUES[x])
        gui.button(box,
                   None,
                   'Regenerate word cloud',
                   callback=self.on_cloud_pref_change)

        box = gui.widgetBox(self.controlArea, 'Words && weights')

        class TableView(gui.TableView):
            def __init__(self, parent):
                super().__init__(parent)
                self._parent = parent
                self.__nope = False

            def setModel(self, model):
                """Otherwise QTableView.setModel() calls
                QAbstractItemView.setSelectionModel() which resets selection,
                calling selectionChanged() and overwriting any selected_words
                setting that may have been saved."""
                self.__nope = True
                super().setModel(model)
                self.__nope = False

            def selectionChanged(self, selected, deselected):
                nonlocal model, proxymodel
                super().selectionChanged(selected, deselected)
                if not self.__nope:
                    words = {
                        model[proxymodel.mapToSource(index).row()][1]
                        for index in self.selectionModel().selectedIndexes()
                    }
                    self._parent.update_selection(words, self)

            def update_selection(self, words):
                nonlocal model, proxymodel
                selection = QItemSelection()
                for i, (_, word) in enumerate(model):
                    if word in words:
                        index = proxymodel.mapFromSource(model.index(i, 1))
                        selection.select(index, index)
                self.__nope = True
                self.clearSelection()
                self.selectionModel().select(
                    selection,
                    QItemSelectionModel.Select | QItemSelectionModel.Rows)
                self.__nope = False

        view = self.tableview = TableView(self)
        model = self.tablemodel = PyTableModel(parent=self)
        proxymodel = QSortFilterProxyModel(
            self,
            dynamicSortFilter=True,
            sortCaseSensitivity=Qt.CaseInsensitive,
            sortRole=Qt.EditRole)
        proxymodel.setSourceModel(model)
        model.setHorizontalHeaderLabels(['Weight', 'Word'])
        view.setModel(proxymodel)
        box.layout().addWidget(view)
예제 #31
0
 def setUp(self):
     assert issubclass(PyTableModel, AbstractSortTableModel)
     self.model = PyTableModel([[1, 4], [2, 3]])
예제 #32
0
class TestPyTableModel(TestCase):
    def setUp(self):
        self.model = PyTableModel([[1, 4], [2, 3]])

    def test_init(self):
        self.model = PyTableModel()
        self.assertEqual(self.model.rowCount(), 0)

    def test_rowCount(self):
        self.assertEqual(self.model.rowCount(), 2)
        self.assertEqual(len(self.model), 2)

    def test_columnCount(self):
        self.assertEqual(self.model.columnCount(), 2)

    def test_data(self):
        mi = self.model.index(0, 0)
        self.assertEqual(self.model.data(mi), '1')
        self.assertEqual(self.model.data(mi, Qt.EditRole), 1)

    def test_editable(self):
        editable_model = PyTableModel([[0]], editable=True)
        self.assertFalse(
            int(self.model.flags(self.model.index(0, 0)) & Qt.ItemIsEditable))
        self.assertTrue(
            int(
                editable_model.flags(editable_model.index(0, 0))
                & Qt.ItemIsEditable))

    def test_sort(self):
        self.model.sort(1)
        self.assertEqual(self.model[0][0], 2)

    def test_setHeaderLabels(self):
        self.model.setHorizontalHeaderLabels(['Col 1', 'Col 2'])
        self.assertEqual(self.model.headerData(1, Qt.Horizontal), 'Col 2')
        self.assertEqual(self.model.headerData(1, Qt.Vertical), '1')

    def test_removeRows(self):
        self.model.removeRows(0, 1)
        self.assertEqual(len(self.model), 1)
        self.assertEqual(self.model[0][1], 3)

    def test_removeColumns(self):
        self.model.removeColumns(0, 1)
        self.assertEqual(self.model.columnCount(), 1)
        self.assertEqual(self.model[1][0], 3)

    def test_insertRows(self):
        self.model.insertRows(0, 1)
        self.assertEqual(self.model[1][0], 1)

    def test_insertColumns(self):
        self.model.insertColumns(0, 1)
        self.assertEqual(self.model[0], ['', 1, 4])

    def test_wrap(self):
        self.model.wrap([[0]])
        self.assertEqual(self.model.rowCount(), 1)
        self.assertEqual(self.model.columnCount(), 1)

    def test_clear(self):
        self.model.clear()
        self.assertEqual(self.model.rowCount(), 0)

    def test_append(self):
        self.model.append([5, 6])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_extend(self):
        self.model.extend([[5, 6]])
        self.assertEqual(self.model[2][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_insert(self):
        self.model.insert(0, [5, 6])
        self.assertEqual(self.model[0][1], 6)
        self.assertEqual(self.model.rowCount(), 3)

    def test_remove(self):
        self.model.remove([2, 3])
        self.assertEqual(self.model.rowCount(), 1)

    def test_other_roles(self):
        self.model.append([2, 3])
        self.model.setData(self.model.index(2, 0), Qt.AlignCenter,
                           Qt.TextAlignmentRole)
        del self.model[1]
        self.assertTrue(
            Qt.AlignCenter
            & self.model.data(self.model.index(1, 0), Qt.TextAlignmentRole))
예제 #33
0
    def test_report_table(self):
        rep = OWReport.get_instance()
        model = PyTableModel([['x', 1, 2],
                              ['y', 2, 2]])
        model.setHorizontalHeaderLabels(['a', 'b', 'c'])

        model.setData(model.index(0, 0), Qt.AlignHCenter | Qt.AlignTop, Qt.TextAlignmentRole)
        model.setData(model.index(1, 0), QFont('', -1, QFont.Bold), Qt.FontRole)
        model.setData(model.index(1, 2), QBrush(Qt.red), Qt.BackgroundRole)

        view = gui.TableView()
        view.show()
        view.setModel(model)
        rep.report_table('Name', view)
        self.maxDiff = None
        self.assertEqual(
            rep.report_html,
            '<h2>Name</h2><table>\n'
            '<tr>'
            '<th style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:left;vertical-align:middle;">a</th>'
            '<th style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:left;vertical-align:middle;">b</th>'
            '<th style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:left;vertical-align:middle;">c</th>'
            '</tr>'
            '<tr>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:center;vertical-align:top;">x</td>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:right;vertical-align:middle;">1</td>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:right;vertical-align:middle;">2</td>'
            '</tr>'
            '<tr>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight:bold;text-align:left;vertical-align:middle;">y</td>'
            '<td style="color:black;border:0;background:transparent;'
            'font-weight:normal;text-align:right;vertical-align:middle;">2</td>'
            '<td style="color:black;border:0;background:#ff0000;'
            'font-weight:normal;text-align:right;vertical-align:middle;">2</td>'
            '</tr></table>')
예제 #34
0
 def test_init(self):
     self.model = PyTableModel()
     self.assertEqual(self.model.rowCount(), 0)
    def _create_layout(self):
        self.mainArea.layout().addWidget(self.graphview)
        info = gui.widgetBox(self.controlArea, 'Info')
        gui.label(info, self, '%(n_object_types)d object types')
        gui.label(info, self, '%(n_relations)d relations')

        class TableView(gui.TableView):
            def __init__(self, parent, bold_columns):
                super().__init__(parent,
                                 selectionMode=self.SingleSelection)
                self.horizontalHeader().setVisible(False)
                self.bold_font = self.BoldFontDelegate(self)  # member because PyQt sometimes unrefs too early
                for col in bold_columns:
                    self.setItemDelegateForColumn(col, self.bold_font)

        box = gui.widgetBox(self.controlArea, 'Recipe factors')
        table = self.table_factors = TableView(self, (2,))
        model = self.model_factors = PyTableModel(parent=self)
        table.setModel(model)
        box.layout().addWidget(table)

        box = gui.widgetBox(self.controlArea, 'Backbone factors')
        table = self.table_backbones = TableView(self, (2, 4))
        model = self.model_backbones = PyTableModel(parent=self)
        table.setModel(model)
        box.layout().addWidget(table)

        box = gui.widgetBox(self.controlArea, 'Completed relations')
        table = self.table_completions = TableView(self, (2, 4))
        model = self.model_completions = PyTableModel(parent=self)
        table.setModel(model)
        box.layout().addWidget(table)

        self.controlArea.layout().addStretch(1)

        def _on_selected_factor(item):
            self.table_completions.clearSelection()
            self.table_backbones.clearSelection()

        def _on_selected_backbone(item):
            self.table_completions.clearSelection()
            self.table_factors.clearSelection()

        def _on_selected_completion(item):
            self.table_factors.clearSelection()
            self.table_backbones.clearSelection()

        def on_selection_changed(table, model, itemChanged_handler):
            def _f(selected, deselected):
                gui.TableView.selectionChanged(table, selected, deselected)
                if not selected:
                    return self.commit(None)
                item = model[selected[0].top()][0]
                itemChanged_handler(item)
                self.commit(item)
            return _f

        self.table_factors.selectionChanged = on_selection_changed(
            self.table_factors, self.model_factors, _on_selected_factor)
        self.table_backbones.selectionChanged = on_selection_changed(
            self.table_backbones, self.model_backbones, _on_selected_backbone)
        self.table_completions.selectionChanged = on_selection_changed(
            self.table_completions, self.model_completions, _on_selected_completion)