source: orange/Orange/OrangeWidgets/Data/OWDataTable.py @ 11358:5e3605dae82f

Revision 11358:5e3605dae82f, 27.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 14 months ago (diff)

Updated old widget meta description icon.

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