source: orange/Orange/OrangeWidgets/Data/OWDataTable.py @ 10703:5521edca468f

Revision 10703:5521edca468f, 27.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 2 years ago (diff)

Added copy (Control + C) support to Data Table widget.

Line 
1"""
2<name>Data Table</name>
3<description>Shows data in a spreadsheet.</description>
4<icon>icons/DataTable.png</icon>
5<priority>100</priority>
6<contact>Peter Juvan (peter.juvan@fri.uni-lj.si)</contact>
7"""
8
9# OWDataTable.py
10#
11# wishes:
12# ignore attributes, filter examples by attribute values, do
13# all sorts of preprocessing (including discretization) on the table,
14# output a new table and export it in variety of formats.
15
16from OWWidget import *
17import OWGUI
18import math
19from orngDataCaching import *
20import OWColorPalette
21
22##############################################################################
23
24def safe_call(func):
25    from functools import wraps
26    @wraps(func)
27    def wrapper(*args, **kwargs):
28        try:
29            return func(*args, **kwargs)
30        except Exception, ex:
31            print >> sys.stderr, func.__name__, "call error", ex
32            return QVariant()
33    return wrapper
34   
35
36class ExampleTableModel(QAbstractItemModel):
37    def __init__(self, examples, dist, *args):
38        QAbstractItemModel.__init__(self, *args)
39        self.examples = examples
40        self.dist = dist
41        self.attributes = list(self.examples.domain.attributes)
42        self.class_var = self.examples.domain.classVar
43        self.metas = self.examples.domain.getmetas().values()
44        self.all_attrs = self.attributes + ([self.class_var] if self.class_var else []) + self.metas
45        self.cls_color = QColor(160,160,160)
46        self.meta_color = QColor(220,220,200)
47        self.sorted_map = range(len(self.examples))
48       
49        self.attr_labels = sorted(reduce(set.union, [attr.attributes for attr in self.all_attrs], set()))
50        self._show_attr_labels = False
51        self._other_data = {}
52       
53    def get_show_attr_labels(self):
54        return self._show_attr_labels
55   
56    def set_show_attr_labels(self, val):
57        self.emit(SIGNAL("layoutAboutToBeChanged()"))
58        self._show_attr_labels = val
59        self.emit(SIGNAL("headerDataChanged(Qt::Orientation, int, int)"),
60                  Qt.Horizontal, 
61                  0, 
62                  len(self.all_attrs) - 1
63                  )
64        self.emit(SIGNAL("layoutChanged()"))
65        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), 
66                  self.index(0,0),
67                  self.index(len(self.examples) - 1, len(self.all_attrs) - 1)
68                  )
69       
70    show_attr_labels = pyqtProperty("bool", 
71                                   fget=get_show_attr_labels,
72                                   fset=set_show_attr_labels,
73                                   )
74   
75    @safe_call
76    def data(self, index, role):
77        row, col = self.sorted_map[index.row()], index.column()
78        example, attr = self.examples[row], self.all_attrs[col]
79        val = example[attr]
80        domain = self.examples.domain
81        if role == Qt.DisplayRole:
82                return QVariant(str(val))
83        elif role == Qt.BackgroundRole:
84            #check if attr is actual class or a duplication in the meta attributes
85            if attr == self.class_var and col == len(domain.attributes) and domain.classVar:
86                return QVariant(self.cls_color)
87            elif attr in self.metas:
88                return QVariant(self.meta_color)
89        elif role == OWGUI.TableBarItem.BarRole and val.varType == orange.VarTypes.Continuous \
90                    and not val.isSpecial() and attr not in self.metas:
91            dist = self.dist[col]
92            return QVariant((float(val) - dist.min) / (dist.max - dist.min or 1))
93        elif role == OWGUI.TableValueRole:
94            # The actual value
95            return QVariant(val)
96        elif role == OWGUI.TableClassValueRole: 
97            # The class value for the row's example
98            return QVariant(example.get_class())
99        elif role == OWGUI.TableVariable: 
100            # The variable descriptor for column
101            return QVariant(val.variable)
102       
103        return self._other_data.get((index.row(), index.column(), role), QVariant())
104       
105    def setData(self, index, variant, role):
106        self._other_data[index.row(), index.column(), role] = variant
107        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), index, index)
108       
109    def index(self, row, col, parent=QModelIndex()):
110        return self.createIndex(row, col, 0)
111   
112    def parent(self, index):
113        return QModelIndex()
114   
115    def rowCount(self, parent=QModelIndex()):
116        if parent.isValid():
117            return 0
118        else:
119            return max([len(self.examples)] + [row for row, _, _ in self._other_data.keys()])
120       
121    def columnCount(self, index=QModelIndex()):
122        return max([len(self.all_attrs)] + [col for _, col, _ in self._other_data.keys()])
123   
124    @safe_call
125    def headerData(self, section, orientation, role):
126        if orientation == Qt.Horizontal:
127            attr = self.all_attrs[section]
128            if role ==Qt.DisplayRole:
129                values = [attr.name] + ([str(attr.attributes.get(label, "")) for label in self.attr_labels] if self.show_attr_labels else [])
130                return QVariant("\n".join(values))
131            if role == Qt.ToolTipRole:
132                pairs = [(key, str(attr.attributes[key])) for key in self.attr_labels if key in attr.attributes]
133                tip = "<b>%s</b>" % attr.name
134                tip = "<br>".join([tip] + ["%s = %s" % pair for pair in pairs])
135                return QVariant(tip) 
136        else:
137            if role == Qt.DisplayRole:
138                return QVariant(section + 1)
139        return QVariant()
140   
141    def sort(self, column, order=Qt.AscendingOrder):
142        self.emit(SIGNAL("layoutAboutToBeChanged()"))
143        attr = self.all_attrs[column] 
144        values = [(ex[attr], i) for i, ex in enumerate(self.examples)]
145        values = sorted(values, key=lambda t: t[0] if not t[0].isSpecial() else sys.maxint, reverse=(order!=Qt.AscendingOrder))
146        self.sorted_map = [v[1] for v in values]
147        self.emit(SIGNAL("layoutChanged()"))
148        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"),
149                  self.index(0,0),
150                  self.index(len(self.examples) - 1, len(self.all_attrs) - 1)
151                  )
152
153
154class TableViewWithCopy(QTableView):
155    def keyPressEvent(self, event):
156        if event == QKeySequence.Copy:
157            sel_model = self.selectionModel()
158            try:
159                self.copy_selection_to_clipboard(sel_model)
160            except Exception:
161                import traceback
162                traceback.print_exc(file=sys.stderr)
163        else:
164            return QTableView.keyPressEvent(self, event)
165           
166    def copy_selection_to_clipboard(self, selection_model):
167        """Copy table selection to the clipboard.
168        """
169        # TODO: html/rtf table
170        import csv
171        from StringIO import StringIO
172        rows = selection_model.selectedRows(0)
173        lines = []
174        csv_str = StringIO()
175        csv_writer = csv.writer(csv_str, dialect="excel")
176        tsv_str = StringIO()
177        tsv_writer = csv.writer(tsv_str, dialect="excel-tab")
178        for row in rows:
179            line = []
180            for i in range(self.model().columnCount()):
181                index = self.model().index(row.row(), i)
182                val = index.data(Qt.DisplayRole)
183                line.append(unicode(val.toString()))
184
185            csv_writer.writerow(line)
186            tsv_writer.writerow(line)
187
188        csv_lines = csv_str.getvalue()
189        tsv_lines = tsv_str.getvalue()
190
191        mime = QMimeData()
192        mime.setData("text/csv", QByteArray(csv_lines))
193        mime.setData("text/tab-separated-values", QByteArray(tsv_lines))
194        mime.setData("text/plain", QByteArray(tsv_lines))
195        QApplication.clipboard().setMimeData(mime, QClipboard.Clipboard)
196
197
198class OWDataTable(OWWidget):
199    settingsList = ["showDistributions", "showMeta", "distColorRgb", "showAttributeLabels", "autoCommit", "selectedSchemaIndex", "colorByClass"]
200
201    def __init__(self, parent=None, signalManager = None):
202        OWWidget.__init__(self, parent, signalManager, "Data Table")
203
204        self.inputs = [("Data", ExampleTable, self.dataset, Multiple + Default)]
205        self.outputs = [("Selected Data", ExampleTable, Default), ("Other Data", ExampleTable)]
206
207        self.data = {}          # key: id, value: ExampleTable
208        self.showMetas = {}     # key: id, value: (True/False, columnList)
209        self.showMeta = 1
210        self.showAttributeLabels = 1
211        self.showDistributions = 1
212        self.distColorRgb = (220,220,220, 255)
213        self.distColor = QColor(*self.distColorRgb)
214        self.locale = QLocale()
215        self.autoCommit = False
216        self.colorSettings = None
217        self.selectedSchemaIndex = 0
218        self.colorByClass = True
219       
220        self.loadSettings()
221
222        # info box
223        infoBox = OWGUI.widgetBox(self.controlArea, "Info")
224        self.infoEx = OWGUI.widgetLabel(infoBox, 'No data on input.')
225        self.infoMiss = OWGUI.widgetLabel(infoBox, ' ')
226        OWGUI.widgetLabel(infoBox, ' ')
227        self.infoAttr = OWGUI.widgetLabel(infoBox, ' ')
228        self.infoMeta = OWGUI.widgetLabel(infoBox, ' ')
229        OWGUI.widgetLabel(infoBox, ' ')
230        self.infoClass = OWGUI.widgetLabel(infoBox, ' ')
231        infoBox.setMinimumWidth(200)
232        OWGUI.separator(self.controlArea)
233
234        # settings box
235        boxSettings = OWGUI.widgetBox(self.controlArea, "Settings", addSpace=True)
236        self.cbShowMeta = OWGUI.checkBox(boxSettings, self, "showMeta", 'Show meta attributes', callback = self.cbShowMetaClicked)
237        self.cbShowMeta.setEnabled(False)
238        self.cbShowAttLbls = OWGUI.checkBox(boxSettings, self, "showAttributeLabels", 'Show attribute labels (if any)', callback = self.cbShowAttLabelsClicked)
239        self.cbShowAttLbls.setEnabled(True)
240
241        box = OWGUI.widgetBox(self.controlArea, "Colors")
242        OWGUI.checkBox(box, self, "showDistributions", 'Visualize continuous values', callback = self.cbShowDistributions)
243        OWGUI.checkBox(box, self, "colorByClass", 'Color by class value', callback = self.cbShowDistributions)
244        OWGUI.button(box, self, "Set colors", self.setColors, tooltip = "Set the canvas background color and color palette for coloring continuous variables", debuggingEnabled = 0)
245
246        resizeColsBox = OWGUI.widgetBox(boxSettings, 0, "horizontal", 0)
247        OWGUI.label(resizeColsBox, self, "Resize columns: ")
248        OWGUI.toolButton(resizeColsBox, self, "+", self.increaseColWidth, tooltip = "Increase the width of the columns", width=20, height=20)
249        OWGUI.toolButton(resizeColsBox, self, "-", self.decreaseColWidth, tooltip = "Decrease the width of the columns", width=20, height=20)
250        OWGUI.rubber(resizeColsBox)
251
252        self.btnResetSort = OWGUI.button(boxSettings, self, "Restore Order of Examples", callback = self.btnResetSortClicked, tooltip = "Show examples in the same order as they appear in the file")
253       
254        OWGUI.separator(self.controlArea)
255        selectionBox = OWGUI.widgetBox(self.controlArea, "Selection")
256        self.sendButton = OWGUI.button(selectionBox, self, "Send selections", self.commit, default=True)
257        cb = OWGUI.checkBox(selectionBox, self, "autoCommit", "Commit on any change", callback=self.commitIf)
258        OWGUI.setStopper(self, self.sendButton, cb, "selectionChangedFlag", self.commit)
259
260        OWGUI.rubber(self.controlArea)
261
262        dlg = self.createColorDialog()
263        self.discPalette = dlg.getDiscretePalette("discPalette")
264
265        # GUI with tabs
266        self.tabs = OWGUI.tabWidget(self.mainArea)
267        self.id2table = {}  # key: widget id, value: table
268        self.table2id = {}  # key: table, value: widget id
269        self.connect(self.tabs, SIGNAL("currentChanged(QWidget*)"), self.tabClicked)
270       
271        self.selectionChangedFlag = False
272       
273
274    def createColorDialog(self):
275        c = OWColorPalette.ColorPaletteDlg(self, "Color Palette")
276        c.createDiscretePalette("discPalette", "Discrete Palette")
277        box = c.createBox("otherColors", "Other Colors")
278        c.createColorButton(box, "Default", "Default color", QColor(Qt.white))
279        c.setColorSchemas(self.colorSettings, self.selectedSchemaIndex)
280        return c
281
282    def setColors(self):
283        dlg = self.createColorDialog()
284        if dlg.exec_():
285            self.colorSettings = dlg.getColorSchemas()
286            self.selectedSchemaIndex = dlg.selectedSchemaIndex
287            self.discPalette = dlg.getDiscretePalette("discPalette")
288            self.distColorRgb = dlg.getColor("Default")
289
290    def increaseColWidth(self):
291        table = self.tabs.currentWidget()
292        if table:
293            for col in range(table.model().columnCount(QModelIndex())):
294                w = table.columnWidth(col)
295                table.setColumnWidth(col, w + 10)
296
297    def decreaseColWidth(self):
298        table = self.tabs.currentWidget()
299        if table:
300            for col in range(table.model().columnCount(QModelIndex())):
301                w = table.columnWidth(col)
302                minW = table.sizeHintForColumn(col)
303                table.setColumnWidth(col, max(w - 10, minW))
304
305
306    def dataset(self, data, id=None):
307        """Generates a new table and adds it to a new tab when new data arrives;
308        or hides the table and removes a tab when data==None;
309        or replaces the table when new data arrives together with already existing id."""
310        if data != None:  # can be an empty table!
311            if self.data.has_key(id):
312                # remove existing table
313                self.data.pop(id)
314                self.showMetas.pop(id)
315                self.id2table[id].hide()
316                self.tabs.removeTab(self.tabs.indexOf(self.id2table[id]))
317                self.table2id.pop(self.id2table.pop(id))
318            self.data[id] = data
319            self.showMetas[id] = (True, [])
320
321            table = TableViewWithCopy() #QTableView()
322            table.setSelectionBehavior(QAbstractItemView.SelectRows)
323            table.setSortingEnabled(True)
324            table.setHorizontalScrollMode(QTableWidget.ScrollPerPixel)
325            table.horizontalHeader().setMovable(True)
326            table.horizontalHeader().setClickable(True)
327            table.horizontalHeader().setSortIndicatorShown(False)
328           
329            option = table.viewOptions()
330            size = table.style().sizeFromContents(QStyle.CT_ItemViewItem, option, QSize(20, 20), table) #QSize(20, QFontMetrics(option.font).lineSpacing()), table)
331           
332            table.verticalHeader().setDefaultSectionSize(size.height() + 2) #int(size.height() * 1.25) + 2)
333
334            self.id2table[id] = table
335            self.table2id[table] = id
336            if data.name:
337                tabName = "%s " % data.name
338            else:
339                tabName = ""
340            tabName += "(" + str(id[1]) + ")"
341            if id[2] != None:
342                tabName += " [" + str(id[2]) + "]"
343            self.tabs.addTab(table, tabName)
344
345            self.progressBarInit()
346            self.setTable(table, data)
347            self.progressBarFinished()
348            self.tabs.setCurrentIndex(self.tabs.indexOf(table))
349            self.setInfo(data)
350            self.sendButton.setEnabled(not self.autoCommit)
351
352        elif self.data.has_key(id):
353            table = self.id2table[id]
354            self.data.pop(id)
355            self.showMetas.pop(id)
356            table.hide()
357            self.tabs.removeTab(self.tabs.indexOf(table))
358            self.table2id.pop(self.id2table.pop(id))
359            self.setInfo(self.data.get(self.table2id.get(self.tabs.currentWidget(),None),None))
360
361        if len(self.data) == 0:
362            self.sendButton.setEnabled(False)
363
364        self.setCbShowMeta()
365
366    def setCbShowMeta(self):
367        for ti in range(self.tabs.count()):
368            if len(self.tabs.widget(ti).model().metas)>0:
369                self.cbShowMeta.setEnabled(True)
370                break
371        else:
372            self.cbShowMeta.setEnabled(False)
373           
374    def sendReport(self):
375        qTableInstance = self.tabs.currentWidget()
376        id = self.table2id.get(qTableInstance, None)
377        data = self.data.get(id, None)
378        self.reportData(data)
379        table = self.id2table[id]
380        import OWReport
381        self.reportRaw(OWReport.reportTable(table))
382       
383       
384    # Writes data into table, adjusts the column width.
385    def setTable(self, table, data):
386        if data==None:
387            return
388        qApp.setOverrideCursor(Qt.WaitCursor)
389        vars = data.domain.variables
390        m = data.domain.getmetas(False)
391        ml = [(k, m[k]) for k in m]
392        ml.sort(lambda x,y: cmp(y[0], x[0]))
393        metas = [x[1] for x in ml]
394        metaKeys = [x[0] for x in ml]
395
396        mo = data.domain.getmetas(True).items()
397        if mo:
398            mo.sort(lambda x,y: cmp(x[1].name.lower(),y[1].name.lower()))
399            metas.append(None)
400            metaKeys.append(None)
401
402        varsMetas = vars + metas
403
404        numVars = len(data.domain.variables)
405        numMetas = len(metas)
406        numVarsMetas = numVars + numMetas
407        numEx = len(data)
408        numSpaces = int(math.log(max(numEx,1), 10))+1
409
410#        table.clear()
411        table.oldSortingIndex = -1
412        table.oldSortingOrder = 1
413#        table.setColumnCount(numVarsMetas)
414#        table.setRowCount(numEx)
415
416        dist = getCached(data, orange.DomainBasicAttrStat, (data,))
417       
418        datamodel = ExampleTableModel(data, dist, self)
419       
420#        proxy = QSortFilterProxyModel(self)
421#        proxy.setSourceModel(datamodel)
422       
423        color_schema = self.discPalette if self.colorByClass else None
424        table.setItemDelegate(OWGUI.TableBarItem(self, color=self.distColor, color_schema=color_schema) \
425                              if self.showDistributions else QStyledItemDelegate(self)) #TableItemDelegate(self, table))
426       
427        table.setModel(datamodel)
428        def p():
429            try:
430                table.updateGeometries()
431                table.viewport().update()
432            except RuntimeError:
433                pass
434       
435        size = table.verticalHeader().sectionSizeHint(0)
436        table.verticalHeader().setDefaultSectionSize(size)
437       
438        self.connect(datamodel, SIGNAL("layoutChanged()"), lambda *args: QTimer.singleShot(50, p))
439       
440        id = self.table2id.get(table, None)
441
442        # set the header (attribute names)
443
444        self.drawAttributeLabels(table)
445
446        self.showMetas[id][1].extend([i for i, attr in enumerate(table.model().all_attrs) if attr in table.model().metas])
447        self.connect(table.horizontalHeader(), SIGNAL("sectionClicked(int)"), self.sortByColumn)
448        self.connect(table.selectionModel(), SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), self.updateSelection)
449        #table.verticalHeader().setMovable(False)
450
451        qApp.restoreOverrideCursor() 
452
453    def setCornerText(self, table, text):
454        """
455        Set table corner text. As this is an ugly hack, do everything in
456        try - except blocks, as it may stop working in newer Qt.
457        """
458
459        if not hasattr(table, "btn") and not hasattr(table, "btnfailed"):
460            try:
461                btn = table.findChild(QAbstractButton)
462
463                class efc(QObject):
464                    def eventFilter(self, o, e):
465                        if (e.type() == QEvent.Paint):
466                            if isinstance(o, QAbstractButton):
467                                btn = o
468                                #paint by hand (borrowed from QTableCornerButton)
469                                opt = QStyleOptionHeader()
470                                opt.init(btn)
471                                state = QStyle.State_None;
472                                if (btn.isEnabled()):
473                                    state |= QStyle.State_Enabled;
474                                if (btn.isActiveWindow()):
475                                    state |= QStyle.State_Active;
476                                if (btn.isDown()):
477                                    state |= QStyle.State_Sunken;
478                                opt.state = state;
479                                opt.rect = btn.rect();
480                                opt.text = btn.text();
481                                opt.position = QStyleOptionHeader.OnlyOneSection;
482                                painter = QStylePainter(btn);
483                                painter.drawControl(QStyle.CE_Header, opt);
484                                return True # eat evebt
485                        return False
486               
487                table.efc = efc()
488                btn.installEventFilter(table.efc)
489                table.btn = btn
490            except:
491                table.btnfailed = True
492
493        if hasattr(table, "btn"):
494            try:
495                btn = table.btn
496                btn.setText(text)
497                opt = QStyleOptionHeader()
498                opt.text = btn.text()
499                s = btn.style().sizeFromContents(QStyle.CT_HeaderSection, opt, QSize(), btn).expandedTo(QApplication.globalStrut())
500                if s.isValid():
501                    table.verticalHeader().setMinimumWidth(s.width())
502                   
503            except:
504                pass
505
506    def sortByColumn(self, index):
507        table = self.tabs.currentWidget()
508        table.horizontalHeader().setSortIndicatorShown(1)
509        header = table.horizontalHeader()
510        if index == table.oldSortingIndex:
511            order = table.oldSortingOrder == Qt.AscendingOrder and Qt.DescendingOrder or Qt.AscendingOrder
512        else:
513            order = Qt.AscendingOrder
514        table.sortByColumn(index, order)
515        table.oldSortingIndex = index
516        table.oldSortingOrder = order
517        #header.setSortIndicator(index, order)
518
519    def tabClicked(self, qTableInstance):
520        """Updates the info box and showMetas checkbox when a tab is clicked.
521        """
522        id = self.table2id.get(qTableInstance,None)
523        self.setInfo(self.data.get(id,None))
524        show_col = self.showMetas.get(id,None)
525        if show_col:
526            self.cbShowMeta.setChecked(show_col[0])
527            self.cbShowMeta.setEnabled(len(show_col[1])>0)
528        self.updateSelection()
529
530    def cbShowMetaClicked(self):
531        table = self.tabs.currentWidget()
532        id = self.table2id.get(table, None)
533        if self.showMetas.has_key(id):
534            show,col = self.showMetas[id]
535            self.showMetas[id] = (not show,col)
536        if show:
537            for c in col:
538                table.hideColumn(c)
539        else:
540            for c in col:
541                table.showColumn(c)
542                table.resizeColumnToContents(c)
543
544    def drawAttributeLabels(self, table):
545#        table.setHorizontalHeaderLabels(table.variableNames)
546        table.model().show_attr_labels = bool(self.showAttributeLabels)
547        if self.showAttributeLabels:
548            labelnames = set()
549            for a in table.model().examples.domain:
550                labelnames.update(a.attributes.keys())
551            labelnames = sorted(list(labelnames))
552#            if len(labelnames):
553#                table.setHorizontalHeaderLabels([table.variableNames[i] + "\n" + "\n".join(["%s" % a.attributes.get(lab, "") for lab in labelnames]) for (i, a) in enumerate(table.data.domain.attributes)])
554            self.setCornerText(table, "\n".join([""] + labelnames))
555        else:
556            self.setCornerText(table, "")
557        table.repaint()
558
559    def cbShowAttLabelsClicked(self):
560        for table in self.table2id.keys():
561            self.drawAttributeLabels(table)
562
563    def cbShowDistributions(self):
564        for ti in range(self.tabs.count()):
565            color_schema = self.discPalette if self.colorByClass else None
566            delegate = OWGUI.TableBarItem(self, color=self.distColor,
567                                          color_schema=color_schema) \
568                       if self.showDistributions else QStyledItemDelegate(self)
569            self.tabs.widget(ti).setItemDelegate(delegate)
570        tab = self.tabs.currentWidget()
571        if tab:
572            tab.reset()
573
574    # show data in the default order
575    def btnResetSortClicked(self):
576        table = self.tabs.currentWidget()
577        if table:
578            id = self.table2id[table]
579            data = self.data[id]
580            table.horizontalHeader().setSortIndicatorShown(False)
581            self.progressBarInit()
582            self.setTable(table, data)
583            self.progressBarFinished()
584
585    def setInfo(self, data):
586        """Updates data info.
587        """
588        def sp(l, capitalize=False):
589            n = len(l)
590            if n == 0:
591                if capitalize:
592                    return "No", "s"
593                else:
594                    return "no", "s"
595            elif n == 1:
596                return str(n), ''
597            else:
598                return str(n), 's'
599
600        if data == None:
601            self.infoEx.setText('No data on input.')
602            self.infoMiss.setText('')
603            self.infoAttr.setText('')
604            self.infoMeta.setText('')
605            self.infoClass.setText('')
606        else:
607            self.infoEx.setText("%s example%s," % sp(data))
608            missData = orange.Preprocessor_takeMissing(data)
609            self.infoMiss.setText('%s (%.1f%s) with missing values.' % (len(missData), len(data) and 100.*len(missData)/len(data), "%"))
610            self.infoAttr.setText("%s attribute%s," % sp(data.domain.attributes,True))
611            self.infoMeta.setText("%s meta attribute%s." % sp(data.domain.getmetas()))
612            if data.domain.classVar:
613                if data.domain.classVar.varType == orange.VarTypes.Discrete:
614                    self.infoClass.setText('Discrete class with %s value%s.' % sp(data.domain.classVar.values))
615                elif data.domain.classVar.varType == orange.VarTypes.Continuous:
616                    self.infoClass.setText('Continuous class.')
617                else:
618                    self.infoClass.setText("Class is neither discrete nor continuous.")
619            else:
620                self.infoClass.setText('Classless domain.')
621
622    def updateSelection(self, *args):
623        self.sendButton.setEnabled(bool(self.getCurrentSelection()) and not self.autoCommit)
624        self.commitIf()
625           
626    def getCurrentSelection(self):
627        table = self.tabs.currentWidget()
628        if table and table.model():
629            model = table.model()
630            new = table.selectionModel().selectedIndexes()
631            return sorted(set([model.sorted_map[ind.row()] for ind in new]))
632       
633    def commitIf(self):
634        if self.autoCommit:
635            self.commit()
636        else:
637            self.selectionChangedFlag = True
638           
639    def commit(self):
640        table = self.tabs.currentWidget()
641        if table and table.model():
642            model = table.model()
643            selected = self.getCurrentSelection()
644            selection = [1 if i in selected else 0 for i in range(len(model.examples))]
645            data = model.examples.select(selection)
646            self.send("Selected Data", data if len(data) > 0 else None)
647            data = model.examples.select(selection, 0)
648            self.send("Other Data", data if len(data) > 0 else None)
649        else:
650            self.send("Selected Data", None)
651            self.send("Other Data", None)
652           
653        self.selectionChangedFlag = False
654           
655       
656
657if __name__=="__main__":
658    a = QApplication(sys.argv)
659    ow = OWDataTable()
660
661    #d1 = orange.ExampleTable(r'..\..\doc\datasets\auto-mpg')
662    #d2 = orange.ExampleTable('test-labels')
663    #d3 = orange.ExampleTable(r'..\..\doc\datasets\sponge.tab')
664    #d4 = orange.ExampleTable(r'..\..\doc\datasets\wpbc.csv')
665    d5 = orange.ExampleTable('../../doc/datasets/adult_sample.tab')
666    #d5 = orange.ExampleTable(r"E:\Development\Orange Datasets\UCI\wine.tab")
667#    d5 = orange.ExampleTable("adult_sample")
668#    d5 = orange.ExampleTable("/home/marko/tdw")
669    #d5 = orange.ExampleTable(r"e:\Development\Orange Datasets\Cancer\SRBCT.tab")
670    ow.show()
671    #ow.dataset(d1,"auto-mpg")
672    #ow.dataset(d2,"voting")
673    #ow.dataset(d4,"wpbc")
674    ow.dataset(d5,"adult_sample")
675    a.exec_()
676    ow.saveSettings()
Note: See TracBrowser for help on using the repository browser.