Changeset 3619:9e624cbea6a3 in orange


Ignore:
Timestamp:
04/30/07 17:46:51 (7 years ago)
Author:
janezd <janez.demsar@…>
Branch:
default
Convert:
b0a03fc183049c90e9de40699eb1e66f99c0dec1
Message:
  • reorganized the widget a bit
  • added context settings
File:
1 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/Data/OWSelectData.py

    r3481 r3619  
    1414 
    1515class OWSelectData(OWWidget): 
    16  
    17     # loadedConditions and loadedVarNames saved the last conditions, but they failed to show 
    18     # in the table when they are reloaded! 
    19     # I removed them; we shall have the context settings doing that some day 
    20     settingsList = ["updateOnChange", "purgeAttributes", "purgeClasses"]#, "loadedConditions", "loadedVarNames"] 
     16    settingsList = ["updateOnChange", "purgeAttributes", "purgeClasses"] 
     17    contextHandlers = {"": PerfectDomainContextHandler(fields = ["Conditions"], matchValues=2)} 
    2118 
    2219    def __init__(self, parent = None, signalManager = None, name = "Select data"): 
    2320        OWWidget.__init__(self, parent, signalManager, name)  #initialize base class 
    2421 
    25         # set channels 
    2622        self.inputs = [("Examples", ExampleTable, self.setData)] 
    2723        self.outputs = [("Matching Examples", ExampleTable, Default), ("Non-Matching Examples", ExampleTable)] 
    2824 
    29         # manually set member variables 
    3025        self.name2var = {}   # key: variable name, item: orange.Variable 
    3126        self.Conditions = [] 
    3227 
    33         # handled member variables 
    3428        self.currentVar = None 
    3529        self.NegateCondition = False 
    36         self.currentOperatorDict = {orange.VarTypes.Continuous:Operator(Operator.operatorsC[0], orange.VarTypes.Continuous), 
    37                                     orange.VarTypes.Discrete:Operator(Operator.operatorsD[0],orange.VarTypes.Discrete), 
    38                                     orange.VarTypes.String:Operator(Operator.operatorsS[0], orange.VarTypes.String)} 
     30        self.currentOperatorDict = {orange.VarTypes.Continuous: Operator(Operator.operatorsC[0], orange.VarTypes.Continuous), 
     31                                    orange.VarTypes.Discrete: Operator(Operator.operatorsD[0],orange.VarTypes.Discrete), 
     32                                    orange.VarTypes.String: Operator(Operator.operatorsS[0], orange.VarTypes.String)} 
    3933        self.Num1 = 0.0 
    4034        self.Num2 = 0.0 
     
    4842        self.oldPurgeClasses = True 
    4943 
    50         # load settings 
    5144        self.loadedVarNames = [] 
    5245        self.loadedConditions = [] 
    5346        self.loadSettings() 
    5447 
    55         # GUI 
    5648        self.mainArea.setFixedWidth(0) 
    5749        ca=QFrame(self.controlArea) 
     
    5951        gl=QGridLayout(ca,4,3,5) 
    6052 
    61         # attribute condition box 
    6253        boxAttrCond = QVGroupBox('Attribute Condition', ca) 
    6354        gl.addMultiCellWidget(boxAttrCond, 0,0,0,2) 
     
    6960        glac.setColStretch(2,2) 
    7061 
    71         # attributes 
    7262        boxAttr = QVGroupBox(frmAttrCond) 
    7363        glac.addWidget(boxAttr,0,0) 
     
    8171        self.connect(self.leSelect, SIGNAL('textChanged(const QString &)'), self.setLbAttr) 
    8272 
    83         # operators 
    8473        boxOper = QVGroupBox('Operator', frmAttrCond) 
    8574        # operators 0: empty 
     
    10796                                orange.VarTypes.Discrete: self.lbOperatorsD, 
    10897                                orange.VarTypes.String: self.lbOperatorsS} 
    109         # NOT checkbox 
     98 
    11099        glac.addWidget(boxOper,0,1) 
    111100        self.cbNot = OWGUI.checkBox(boxOper, self, "NegateCondition", "NOT") 
    112101 
    113         # values 
     102 
    114103        self.valuesStack = QWidgetStack(frmAttrCond) 
    115104        glac.addWidget(self.valuesStack,0,2) 
     
    141130        self.cbCaseSensitive = OWGUI.checkBox(boxVal, self, "CaseSensitive", "Case sensitive") 
    142131 
    143         # buttons Add, Update, Remove, Disjunction, Up, Down 
    144132        self.boxButtons = QHBox(ca) 
    145133        gl.addMultiCellWidget(self.boxButtons, 1,1,0,2) 
     
    155143        self.btnMoveDown.setEnabled(False) 
    156144 
    157         # data selection criteria 
     145 
    158146        boxCriteria = QVGroupBox(ca) 
    159147        boxCriteria.setTitle('Data Selection Criteria') 
     
    173161        self.criteriaTable.setColumnWidth(1, 360) 
    174162 
    175         # data in 
    176163        boxDataIn = QVGroupBox(ca) 
    177164        boxDataIn.setTitle('Data In') 
     
    180167        self.dataInAttributesLabel = OWGUI.widgetLabel(boxDataIn, "num attributes") 
    181168 
    182         # data out 
    183169        boxDataOut = QVGroupBox(ca) 
    184170        boxDataOut.setTitle('Data Out') 
     
    187173        self.dataOutAttributesLabel = OWGUI.widgetLabel(boxDataOut, "num attributes") 
    188174 
    189         # update 
    190175        boxSettings = QVGroupBox(ca) 
    191176        boxSettings.setTitle('Update') 
     
    196181        btnUpdate = OWGUI.button(boxSettings, self, "Update", self.setOutput) 
    197182 
    198         # icons 
    199183        self.icons = self.createAttributeIconDict() 
    200184        self.setData(None) 
     
    205189 
    206190 
    207     ############################################################################################################################################################ 
    208     ## Data input and output management ######################################################################################################################## 
    209     ############################################################################################################################################################ 
    210  
    211191    def setData(self, data): 
    212         """Loads stored conditions (if we have a similar domain), updates list boxes and data in info, sends out data. 
    213         """ 
     192        self.closeContext("") 
    214193        self.data = data 
    215194        self.bas = orange.DomainBasicAttrStat(data) 
     195        self.name2var = {} 
     196        self.Conditions = [] 
     197 
    216198        if self.data: 
    217             # set self.name2var 
    218199            optmetas = self.data.domain.getmetas(True).values() 
    219200            optmetas.sort(lambda x,y: cmp(x.name, y.name)) 
    220201            self.varList = self.data.domain.variables.native() + self.data.domain.getmetas(False).values() + optmetas 
    221             varNames = [] 
    222202            for v in self.varList: 
    223203                self.name2var[v.name] = v 
    224                 varNames.append(v.name) 
    225             if varNames == self.loadedVarNames: 
    226                 if self.Conditions == []: 
    227                     self.Conditions = self.loadedConditions 
    228             else: 
    229                 self.loadedVarNames = varNames 
    230  
    231                 # clear conditions and criteria table 
    232                 self.Conditions = [] 
    233                 for row in range(self.criteriaTable.numRows()-1,-1,-1): 
    234                     self.criteriaTable.clearCellWidget(row,0) 
    235                     self.criteriaTable.clearCell(row,1) 
    236                     self.criteriaTable.hideRow(row) 
    237                 self.criteriaTable.setNumRows(0) 
    238  
    239204            self.setLbAttr() 
    240  
    241             self.criteriaTable.setCurrentCell(-1,1) 
    242205            self.boxButtons.setEnabled(True) 
    243  
    244         else: 
    245             self.name2var = {} 
     206        else: 
    246207            self.varList = [] 
    247             self.Conditions = [] 
     208            self.currentVar = None 
     209             
    248210            self.lbAttr.clear() 
    249211            self.leSelect.clear() 
    250             self.currentVar = None 
    251             for row in range(self.criteriaTable.numRows()-1,-1,-1): 
    252                 self.criteriaTable.clearCellWidget(row,0) 
    253                 self.criteriaTable.clearCell(row,1) 
    254                 self.criteriaTable.hideRow(row) 
    255             self.criteriaTable.setNumRows(0) 
    256             self.criteriaTable.setCurrentCell(-1,1) 
    257212            self.boxButtons.setEnabled(False) 
    258         # update operators, values and info, and send out data 
     213 
     214        self.openContext("", data) 
     215        self.synchronizeTable() 
     216        self.criteriaTable.setCurrentCell(-1,1) 
     217         
    259218        self.updateOperatorStack() 
    260219        self.updateValuesStack() 
     
    262221        self.setOutput() 
    263222 
     223 
    264224    def setLbAttr(self, filter=None): 
    265         # update attribute listbox 
    266225        self.lbAttr.clear() 
    267226        if not filter: 
     
    280239 
    281240 
     241    def setOutputIf(self): 
     242        if self.updateOnChange: 
     243            self.setOutput() 
     244 
    282245    def setOutput(self): 
    283         """Sends out data, updates data out info. 
    284         """ 
    285246        matchingOutput = self.data 
    286247        nonMatchingOutput = None 
     
    325286            elif cond.enabled or not enabledOnly: 
    326287                fdList[-1].append(cond.operator.getFilter(domain, cond.varName, cond.val1, cond.val2, cond.negated, cond.caseSensitive)) 
    327 ##        # remove the first list if empty 
    328 ##        if len(fdList) > 1 and len(fdList[0]) == 0: 
    329 ##            fdList.pop(0) 
    330288        return fdList 
    331289 
    332290 
    333     ############################################################################################################################################################ 
    334     ## Callback handlers ################################################################################################################################### 
    335     ############################################################################################################################################################ 
    336  
    337291    def lbAttrChange(self): 
    338         """Updates operator listBox and value stack, only if necesarry. 
    339         """ 
    340292        text = str(self.lbAttr.currentText()) 
    341293        prevVar = self.currentVar 
     
    364316        if self.currentVar: 
    365317            varType = self.currentVar.varType 
    366             self.currentOperatorDict[varType] = Operator(self.lbOperatorsDict[varType].currentText(), varType) 
     318            self.currentOperatorDict[varType] = Operator(str(self.lbOperatorsDict[varType].currentText()), varType) 
    367319            self.updateValuesStack() 
    368320 
     
    375327            if self.lbVals.isSelected(i): 
    376328                self.currentVals.append(str(self.lbVals.text(i))) 
    377  
    378  
    379     def OnNewCondition(self): 
    380         """Updates conditions and condition table, sends out new data. 
    381         """ 
    382         # update self.Conditions 
    383         row = self.criteriaTable.currentRow() 
    384         if row == self.criteriaTable.numRows(): 
    385             row -= 1 
    386         cond = self.getCondtionFromSelection() 
    387         if not cond: 
    388             return 
    389         self.Conditions.insert(row+1, cond) 
    390         # update self.criteriaTable 
    391         self.insertCriteriaTableRow(cond, row+1) 
    392         self.updateFilteredDataLens() 
    393         # enable Update/Remove buttons 
    394         self.btnUpdate.setEnabled(True) 
    395         self.btnRemove.setEnabled(True) 
    396         # send out new data 
    397         if self.updateOnChange: 
    398             self.setOutput() 
    399         self.leSelect.clear() 
    400329 
    401330 
     
    414343            self.setOutput() 
    415344 
     345 
     346    def OnNewCondition(self): 
     347        cond = self.getConditionFromSelection() 
     348        if not cond: 
     349            return 
     350 
     351        where = min(self.criteriaTable.currentRow() + 1, self.criteriaTable.numRows()) 
     352        self.Conditions.insert(where, cond) 
     353        self.synchronizeTable() 
     354        self.criteriaTable.setCurrentCell(where, 1) 
     355        self.setOutputIf() 
     356        self.leSelect.clear() 
     357 
     358 
    416359    def OnUpdateCondition(self): 
    417         """Calls remove and insert. 
    418         TODO: sends out data twice - fix that! 
    419         """ 
    420         # update self.Conditions 
    421360        row = self.criteriaTable.currentRow() 
    422361        if row < 0: 
    423362            return 
    424         cond = self.getCondtionFromSelection() 
     363        cond = self.getConditionFromSelection() 
    425364        if not cond: 
    426365            return 
    427366        self.Conditions[row] = cond 
    428         # update self.criteriaTable 
    429         self.criteriaTable.clearCellWidget(row, 0) 
    430         self.criteriaTable.clearCell(row, 1) 
    431         self.putContitionToTable(row, cond) 
    432         self.updateFilteredDataLens() 
    433         # send out new data 
    434         if self.updateOnChange: 
    435             self.setOutput() 
     367        self.synchronizeTable() 
     368        self.setOutputIf() 
    436369        self.leSelect.clear() 
    437370 
     
    445378            return 
    446379        self.Conditions.pop(currRow) 
    447         # update self.criteriaTable 
    448         numRows = self.criteriaTable.numRows() 
    449         for r in range(currRow, numRows - 1): 
    450             self.criteriaTable.swapRows(r+1,r) 
    451             self.criteriaTable.updateCell(r, 0) 
    452             self.criteriaTable.updateCell(r, 1) 
    453         for c in range(2): 
    454             self.criteriaTable.clearCellWidget(numRows-1, 0) 
    455             self.criteriaTable.clearCell(numRows-1, 1) 
    456         self.criteriaTable.hideRow(numRows - 1) 
    457         self.criteriaTable.setNumRows(numRows - 1) 
    458         if currRow == numRows - 1: 
    459             self.criteriaTable.setCurrentCell(currRow-1,1) 
    460         else: 
    461             self.criteriaTable.setCurrentCell(currRow,1) 
    462         self.updateFilteredDataLens() 
    463         # disable Update/Remove buttons 
    464         if len(self.Conditions) == 0: 
    465             self.btnUpdate.setEnabled(False) 
    466             self.btnRemove.setEnabled(False) 
    467         # send out new data 
    468         if self.updateOnChange: 
    469             self.setOutput() 
     380        self.synchronizeTable() 
     381        self.criteriaTable.setCurrentCell(min(currRow, self.criteriaTable.numRows()-1), 1) 
     382        self.setOutputIf() 
    470383 
    471384 
     
    474387        """ 
    475388        # update self.Conditions 
    476         row = self.criteriaTable.currentRow() 
    477         if row == self.criteriaTable.numRows(): 
    478             row -= 1 
    479         cond = Condition(True, "OR") 
    480         self.Conditions.insert(row+1, cond) 
    481         # update self.criteriaTable 
    482         self.insertCriteriaTableRow(cond, row+1) 
    483         self.updateFilteredDataLens() 
    484         # enable Update/Remove buttons 
    485         self.btnUpdate.setEnabled(True) 
    486         self.btnRemove.setEnabled(True) 
    487         # send out new data 
    488         if self.updateOnChange: 
    489             self.setOutput() 
     389        where = min(self.criteriaTable.currentRow() + 1, self.criteriaTable.numRows()) 
     390        self.Conditions.insert(where, Condition(True, "OR")) 
     391        self.criteriaTable.setCurrentCell(where, 1) 
     392        self.synchronizeTable() 
     393        self.setOutputIf() 
    490394 
    491395 
     
    498402            return 
    499403        self.Conditions = self.Conditions[:currRow-1] + [self.Conditions[currRow], self.Conditions[currRow-1]] + self.Conditions[currRow+1:] 
    500         self.criteriaTable.swapRows(currRow, currRow-1) 
    501         self.criteriaTable.setCurrentCell(currRow-1,1) 
    502         self.criteriaTable.updateCell(currRow, 0) 
    503         self.criteriaTable.updateCell(currRow, 1) 
    504         self.criteriaTable.updateCell(currRow-1, 0) 
    505         self.criteriaTable.updateCell(currRow-1, 1) 
    506         self.updateFilteredDataLens() 
    507         self.updateMoveButtons() 
    508         # send out new data 
    509         if self.updateOnChange: 
    510             self.setOutput() 
     404        self.synchronizeTable() 
     405        self.setOutputIf() 
    511406 
    512407 
     
    519414            return 
    520415        self.Conditions = self.Conditions[:currRow] + [self.Conditions[currRow+1], self.Conditions[currRow]] + self.Conditions[currRow+2:] 
    521         self.criteriaTable.swapRows(currRow, currRow+1) 
    522         self.criteriaTable.setCurrentCell(currRow+1,1) 
    523         self.criteriaTable.updateCell(currRow, 0) 
    524         self.criteriaTable.updateCell(currRow, 1) 
    525         self.criteriaTable.updateCell(currRow+1, 0) 
    526         self.criteriaTable.updateCell(currRow+1, 1) 
    527         self.updateFilteredDataLens() 
    528         self.updateMoveButtons() 
    529         # send out new data 
    530         if self.updateOnChange: 
    531             self.setOutput() 
     416        self.synchronizeTable() 
     417        self.setOutputIf() 
    532418 
    533419 
     
    705591 
    706592 
    707     def insertCriteriaTableRow(self, cond, row): 
    708         """Inserts condition at the given row. 
    709         """ 
    710         numRows = self.criteriaTable.numRows() 
    711         self.criteriaTable.setNumRows(numRows + 1) 
    712         for r in range(numRows, row, -1): 
    713             self.criteriaTable.swapRows(r-1,r) 
    714             self.criteriaTable.updateCell(r, 0) 
    715             self.criteriaTable.updateCell(r, 1) 
    716         self.putContitionToTable(row, cond) 
    717         self.criteriaTable.setCurrentCell(row,1) 
    718  
    719  
    720     def getCondtionFromSelection(self): 
     593    def getConditionFromSelection(self): 
    721594        """Returns a condition according to the currently selected attribute / operator / values. 
    722595        """ 
     
    737610 
    738611 
    739     def putContitionToTable(self, row, cond): 
    740         """Writes out the condition to the given row in a criteria table. 
    741         """ 
    742         # column 0 getFilter(self, domain, variable, value1, value2, negate, caseSensitive) 
    743         if cond.type == "OR": 
    744             cw = QLabel("", self) 
    745         else: 
    746             cw = QCheckBox(str(len(cond.operator.getFilter(self.data.domain, cond.varName, cond.val1, cond.val2, cond.negated, cond.caseSensitive)(self.data))), self) 
    747             cw.setChecked(cond.enabled) 
    748             self.connect(cw, SIGNAL("toggled(bool)"), lambda val: self.criteriaActiveChange(cond, val)) 
    749         self.criteriaTable.setCellWidget(row, 0, cw) 
    750         # column 1 
    751         if cond.type == "OR": 
    752             txt = "OR" 
    753         else: 
    754             txt = "" 
    755             if cond.negated: 
    756                 txt += "NOT " 
    757             txt += cond.varName + " " + str(cond.operator) + " " 
    758             if cond.operator != Operator.operatorDef: 
    759                 if cond.operator.varType == orange.VarTypes.Discrete: 
    760                     if cond.operator.isInterval: 
    761                         if len(cond.val1) > 0: 
    762                             txt += "[" 
    763                             for name in cond.val1: 
    764                                 txt += "%s, " % name 
    765                             txt = txt[0:-2] + "]" 
     612    def synchronizeTable(self): 
     613        for row in range(len(self.Conditions), self.criteriaTable.numRows()): 
     614            self.criteriaTable.clearCellWidget(row,0) 
     615            self.criteriaTable.clearCell(row,1) 
     616             
     617        self.criteriaTable.setNumRows(len(self.Conditions)) 
     618 
     619        for row, cond in enumerate(self.Conditions): 
     620            if cond.type == "OR": 
     621                cw = QLabel("", self) 
     622            else: 
     623                cw = QCheckBox(str(len(cond.operator.getFilter(self.data.domain, cond.varName, cond.val1, cond.val2, cond.negated, cond.caseSensitive)(self.data))), self) 
     624                cw.setChecked(cond.enabled) 
     625                self.connect(cw, SIGNAL("toggled(bool)"), lambda val: self.criteriaActiveChange(cond, val)) 
     626 
     627            self.criteriaTable.setCellWidget(row, 0, cw) 
     628 
     629            # column 1 
     630            if cond.type == "OR": 
     631                txt = "OR" 
     632            else: 
     633                txt = "" 
     634                if cond.negated: 
     635                    txt += "NOT " 
     636                txt += cond.varName + " " + str(cond.operator) + " " 
     637                if cond.operator != Operator.operatorDef: 
     638                    if cond.operator.varType == orange.VarTypes.Discrete: 
     639                        if cond.operator.isInterval: 
     640                            if len(cond.val1) > 0: 
     641                                txt += "[" 
     642                                for name in cond.val1: 
     643                                    txt += "%s, " % name 
     644                                txt = txt[0:-2] + "]" 
     645                            else: 
     646                                txt += "[]" 
    766647                        else: 
    767                             txt += "[]" 
    768                     else: 
    769                         txt += cond.val1[0] 
    770                 elif cond.operator.varType == orange.VarTypes.String: 
    771                     if cond.caseSensitive: 
    772                         cs = " (C)" 
    773                     else: 
    774                         cs = "" 
    775                     if cond.operator.isInterval: 
    776                         txt += "'%s'%s and '%s'%s" % (cond.val1, cs, cond.val2, cs) 
    777                     else: 
    778                         txt += "'%s'%s" % (cond.val1, cs) 
    779                 elif cond.operator.varType == orange.VarTypes.Continuous: 
    780                     if cond.operator.isInterval: 
    781                         txt += str(cond.val1) + " and " + str(cond.val2) 
    782                     else: 
    783                         txt += str(cond.val1) 
    784         OWGUI.tableItem(self.criteriaTable, row, 1, txt , editType=QTableItem.Never) 
     648                            txt += cond.val1[0] 
     649                    elif cond.operator.varType == orange.VarTypes.String: 
     650                        if cond.caseSensitive: 
     651                            cs = " (C)" 
     652                        else: 
     653                            cs = "" 
     654                        if cond.operator.isInterval: 
     655                            txt += "'%s'%s and '%s'%s" % (cond.val1, cs, cond.val2, cs) 
     656                        else: 
     657                            txt += "'%s'%s" % (cond.val1, cs) 
     658                    elif cond.operator.varType == orange.VarTypes.Continuous: 
     659                        if cond.operator.isInterval: 
     660                            txt += str(cond.val1) + " and " + str(cond.val2) 
     661                        else: 
     662                            txt += str(cond.val1) 
     663                             
     664            OWGUI.tableItem(self.criteriaTable, row, 1, txt , editType=QTableItem.Never) 
     665         
     666        self.updateFilteredDataLens() 
     667 
     668        en = len(self.Conditions) 
     669        self.btnUpdate.setEnabled(en) 
     670        self.btnRemove.setEnabled(en) 
     671        self.updateMoveButtons() 
    785672 
    786673 
     
    811698            # update the clicked row 
    812699            self.criteriaTable.cellWidget(condIdx,0).setText(str(len(fdListAll[0][condIdx-idx1](self.data)))) 
     700             
    813701        elif len(self.Conditions) > 0: 
    814702            # update all "OR" rows 
Note: See TracChangeset for help on using the changeset viewer.