Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeWidgets/Data/OWPaintData.py

    r11313 r11570  
    66<icon>icons/PaintData.svg</icon> 
    77""" 
    8  
    98import orange 
     9 
     10import copy 
     11 
     12from PyQt4 import QtCore 
    1013 
    1114from OWWidget import * 
     
    4043        self.updateGraph() 
    4144         
    42     def updateGraph(self, dataInterval = None): 
     45    def updateGraph(self, dataInterval=None): 
    4346        if dataInterval: 
    4447            start, end = dataInterval 
     
    4750            self.removeDrawingCurves() 
    4851            data = self.data 
     52 
    4953        clsValues, hasCls = (self.data.domain.classVar.values, True) if self.data.domain.classVar else ([0], False) 
    5054         
     
    9094        self.graph = graph 
    9195        if graph: 
    92             installed = getattr(graph,"_data_tool_event_filter", None) 
     96            installed = getattr(graph, "_data_tool_event_filter", None) 
    9397            if installed: 
    9498                self.graph.canvas().removeEventFilter(installed) 
     
    110114        """ Called when the tool is installed on a graph. 
    111115        """ 
     116        pass 
    112117         
    113118    def eventFilter(self, obj, event): 
     
    224229        else: 
    225230            self._moving_index, self._moving_pos, self._selection_region = index, pos, self.selection[index] 
    226             self.emit(SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), index, pos, self.toPath(self.selection[index]))   
     231            self.emit(SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), 
     232                      index, pos, self.toPath(self.selection[index])) 
    227233        self.emit(SIGNAL("selectionGeometryChanged()")) 
    228234     
     
    232238        if index == -1: 
    233239            self.selection[-1] = self.selection[-1][:-1] + (pos,) 
    234             self.emit(SIGNAL("selectionRegionUpdated(int, QPainterPath)"), len(self.selection) - 1 , self.toPath(self.selection[-1])) 
     240            self.emit(SIGNAL("selectionRegionUpdated(int, QPainterPath)"), len(self.selection) - 1, 
     241                      self.toPath(self.selection[-1])) 
    235242        else: 
    236243            diff = self._moving_pos - pos 
    237244            self.selection[index] = tuple([p - diff for p in self._selection_region]) 
    238             self.emit(SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), index, pos, self.toPath(self.selection[index])) 
     245            self.emit(SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), 
     246                      index, pos, self.toPath(self.selection[index])) 
    239247             
    240248        self.emit(SIGNAL("selectionGeometryChanged()")) 
     
    316324        self.pen.setJoinStyle(Qt.RoundJoin) 
    317325        self.pen.setCapStyle(Qt.RoundCap) 
    318         self.connect(self.selection, SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), self.onMoveStarted) 
    319         self.connect(self.selection, SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), self.onMove) 
    320         self.connect(self.selection, SIGNAL("selectionRegionMoveFinished(int, QPointF, QPainterPath)"), self.onMoveFinished) 
    321         self.connect(self.selection, SIGNAL("selectionRegionUpdated(int, QPainterPath)"), self.invalidateMoveSelection) 
     326        self.connect(self.selection, SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), 
     327                     self.onMoveStarted) 
     328        self.connect(self.selection, SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), 
     329                     self.onMove) 
     330        self.connect(self.selection, SIGNAL("selectionRegionMoveFinished(int, QPointF, QPainterPath)"), 
     331                     self.onMoveFinished) 
     332        self.connect(self.selection, SIGNAL("selectionRegionUpdated(int, QPainterPath)"), 
     333                     self.invalidateMoveSelection) 
    322334        self._validMoveSelection = False 
    323335        self._moving = None 
     
    416428            self.emit(SIGNAL("editing()")) 
    417429            self.emit(SIGNAL("editingFinished()")) 
    418          
     430 
     431 
    419432class GraphLassoSelections(GraphSelections): 
    420433    def start(self, event): 
     
    426439        else: 
    427440            self._moving_index, self._moving_pos, self._selection_region = index, pos, self.selection[index] 
    428             self.emit(SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), index, pos, self.toPath(self.selection[index]))   
     441            self.emit(SIGNAL("selectionRegionMoveStarted(int, QPointF, QPainterPath)"), 
     442                      index, pos, self.toPath(self.selection[index])) 
    429443        self.emit(SIGNAL("selectionGeometryChanged()")) 
    430444         
     
    434448        if index == -1: 
    435449            self.selection[-1].append(pos) 
    436             self.emit(SIGNAL("selectionRegionUpdated(int, QPainterPath)"), len(self.selection) - 1 , self.toPath(self.selection[-1])) 
     450            self.emit(SIGNAL("selectionRegionUpdated(int, QPainterPath)"), 
     451                      len(self.selection) - 1, self.toPath(self.selection[-1])) 
    437452        else: 
    438453            diff = self._moving_pos - pos 
    439454            self.selection[index] = [p - diff for p in self._selection_region] 
    440             self.emit(SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), index, pos, self.toPath(self.selection[index])) 
     455            self.emit(SIGNAL("selectionRegionMoved(int, QPointF, QPainterPath)"), 
     456                      index, pos, self.toPath(self.selection[index])) 
    441457             
    442458        self.emit(SIGNAL("selectionGeometryChanged()")) 
     
    636652            dx = -(x1 - x)/dist * attraction / max(distsq, rx) * advance 
    637653            dy = -(y1 - y)/dist * attraction / max(distsq, ry) * advance 
    638             ex[attr1] = x1 - random.normalvariate(0, dx) #*self.density) 
    639             ex[attr2] = y1 - random.normalvariate(0, dy) #*self.density) 
     654            ex[attr1] = x1 - random.normalvariate(0, dx)    # *self.density) 
     655            ex[attr2] = y1 - random.normalvariate(0, dy)    # *self.density) 
    640656        self.graph.updateGraph() 
    641657         
     
    702718        self.loadSettings() 
    703719         
    704         self.variablesModel = VariableListModel([orange.FloatVariable(name) for name in ["X", "Y"]], self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) 
    705  
    706          
     720        self.variablesModel = VariableListModel([orange.FloatVariable(name) for name in ["X", "Y"]], self, 
     721                                                flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsEditable) 
     722 
    707723        self.classVariable = orange.EnumVariable("Class label", values=["Class 1", "Class 2"], baseValue=0) 
    708          
     724 
     725        ur = OWGUI.widgetBox(self.controlArea, "Undo / Redo") 
     726        undo = QAction("Undo", self) 
     727        undo.pyqtConfigure(toolTip="Undo action") 
     728        self.connect(undo, SIGNAL("triggered()"), self.undoAction) 
     729 
     730        redo = QAction("Redo", self) 
     731        redo.pyqtConfigure(toolTip="Redo action") 
     732        self.connect(redo, SIGNAL("triggered()"), self.redoAction) 
     733 
     734        actionsWidget =  ModelActionsWidget([undo, redo], self) 
     735        actionsWidget.layout().addStretch(10) 
     736        actionsWidget.layout().setSpacing(1) 
     737 
     738        ur.layout().addWidget(actionsWidget) 
     739 
    709740        w = OWGUI.widgetBox(self.controlArea, "Class Label") 
    710741         
     
    712743        listView.setSelectionMode(QListView.SingleSelection) 
    713744         
    714         self.classValuesModel = EnumVariableModel(self.classVariable, self, flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled| Qt.ItemIsEditable) 
     745        self.classValuesModel = EnumVariableModel(self.classVariable, self, 
     746                                                  flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled| Qt.ItemIsEditable) 
    715747        self.classValuesModel.wrap(self.classVariable.values) 
    716748         
    717749        listView.setModel(self.classValuesModel) 
    718750        listView.selectionModel().select(self.classValuesModel.index(0), QItemSelectionModel.ClearAndSelect) 
    719         self.connect(listView.selectionModel(), SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), self.onClassLabelSelection) 
     751        self.connect(listView.selectionModel(), 
     752                     SIGNAL("selectionChanged(QItemSelection, QItemSelection)"), 
     753                     self.onClassLabelSelection) 
    720754        listView.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Maximum) 
    721755        w.layout().addWidget(listView) 
     
    777811        self.graph.setAttribute(Qt.WA_Hover, True) 
    778812        self.mainArea.layout().addWidget(self.graph) 
    779          
     813 
    780814        self.currentOptionsWidget = None 
    781815        self.data = [] 
     
    785819        self.onDomainChanged() 
    786820        self.toolActions.actions()[0].trigger() 
     821 
     822        self.dataHistory = [(orange.ExampleTable(self.domain), ["Class 1", "Class 2"])] 
     823        self.historyCounter = 0 
     824        self.updateHistoryBool = True 
    787825         
    788826        self.resize(800, 600) 
    789          
     827 
    790828    def addNewClassLabel(self): 
    791829        i = 1 
    792830        while True: 
    793             newlabel = "Class %i" %i 
     831            newlabel = "Class %i" % i 
    794832            if newlabel not in self.classValuesModel: 
    795833#                self.classValuesModel.append(newlabel) 
     
    813851         
    814852        self.removeClassLabel.setEnabled(len(self.classValuesModel) > 1) 
    815          
    816     def removeSelectedClassLabel(self): 
     853 
     854        self.updateHistory() 
     855         
     856    def removeSelectedClassLabel(self, label=None): 
    817857        index = self.selectedClassLabelIndex() 
    818858        if index is not None and len(self.classValuesModel) > 1: 
    819             label = self.classValuesModel[index] 
     859            if not label: 
     860                label = self.classValuesModel[index] 
    820861            examples = [ex for ex in self.graph.data if str(ex.getclass()) != label] 
    821862             
    822863            values = [val for val in self.classValuesModel if val != label] 
     864 
    823865            newclass = orange.EnumVariable("Class label", values=values) 
    824866            newdomain = orange.Domain(self.graph.data.domain.attributes, newclass) 
     
    826868            for ex in examples: 
    827869                if ex[self.classVariable] != label and ex[self.classVariable] in values: 
    828                     newdata.append(orange.Example(newdomain, [ex[a] for a in ex.domain.attributes] + [str(ex.getclass())])) 
    829                  
     870                    newdata.append(orange.Example(newdomain, [ex[a] for a in ex.domain.attributes] + 
     871                                                             [str(ex.getclass())])) 
     872 
    830873            self.classVariable = newclass 
    831874            self.classValuesModel.wrap(self.classVariable.values) 
     
    837880            self.classValuesView.selectionModel().select(newindex, QItemSelectionModel.ClearAndSelect) 
    838881             
    839             self.removeClassLabel.setEnabled(len(self.classValuesModel) > 1)  
     882            self.removeClassLabel.setEnabled(len(self.classValuesModel) > 1) 
     883 
     884            self.updateHistory() 
    840885         
    841886    def selectedClassLabelIndex(self): 
     
    863908            self.connect(newtool, SIGNAL("editing()"), self.onDataChanged) 
    864909            self.connect(newtool, SIGNAL("editingFinished()"), self.commitIf) 
     910            self.connect(newtool, SIGNAL("editingFinished()"), self.updateHistory) 
    865911            self.toolsStackCache[tool] = (newtool, option) 
    866912         
     
    868914        self.optionsLayout.setCurrentWidget(option) 
    869915        self.currentTool.setGraph(self.graph) 
    870          
     916 
     917    def updateHistory(self): 
     918        if not self.updateHistoryBool: 
     919            return 
     920        # if we start updating from previously undone actions, we cut off redos in our history 
     921        if not self.historyCounter == len(self.dataHistory)-1: 
     922            self.dataHistory = self.dataHistory[0:self.historyCounter+1] 
     923        # append an update of labels and data 
     924        labels = list(self.classValuesModel) 
     925        self.dataHistory.append((copy.deepcopy(self.graph.data), labels)) 
     926        # set the size of the data history stack and remove the oldest update if we go over the size 
     927        if len(self.dataHistory) > 100: 
     928            self.dataHistory.pop(0) 
     929            self.historyCounter -= 1 
     930        self.historyCounter += 1 
     931 
     932    def undoAction(self): 
     933        # check to see if we are at the end of the stack 
     934        if self.historyCounter > 0: 
     935            self.historyCounter -= 1 
     936            data, labels = self.dataHistory[self.historyCounter] 
     937            # we dont update history when undoing 
     938            self.updateHistoryBool = False 
     939            # check if we only need to update labels 
     940            if len(self.classValuesModel) > len(labels): 
     941                diff = set(self.classValuesModel) - set(labels) 
     942                self.removeSelectedClassLabel(label=diff.pop()) 
     943            elif len(self.classValuesModel) < len(labels): 
     944                self.addNewClassLabel() 
     945            # if not, update data 
     946            else: 
     947                self.graph.data = data 
     948                self.graph.updateGraph() 
     949            self.updateHistoryBool = True 
     950 
     951    def redoAction(self): 
     952        if self.historyCounter < len(self.dataHistory)-1: 
     953            self.historyCounter += 1 
     954            data, labels = self.dataHistory[self.historyCounter] 
     955            self.updateHistoryBool = False 
     956            if len(self.classValuesModel) > len(labels): 
     957                diff = set(self.classValuesModel) - set(labels) 
     958                self.removeSelectedClassLabel(label=diff.pop()) 
     959            elif len(self.classValuesModel) < len(labels): 
     960                self.addNewClassLabel() 
     961            else: 
     962                self.graph.data = data 
     963                self.graph.updateGraph() 
     964            self.updateHistoryBool = True 
     965 
    871966    def onDomainChanged(self, *args): 
    872967        if self.variablesModel: 
     
    880975    def onDataChanged(self): 
    881976        self.dataChangedFlag = True 
     977 
     978    def keyPressEvent(self, event): 
     979        if event.key() == QtCore.Qt.Key_Delete and isinstance(self.currentTool, SelectTool): 
     980            self.currentTool.deleteSelected() 
    882981     
    883982    def commitIf(self): 
     
    895994            data = orange.ExampleTable(domain, data) 
    896995        self.send("Data", data) 
    897          
    898          
     996 
    899997if __name__ == "__main__": 
    900998    app = QApplication(sys.argv) 
     
    9021000    w.show() 
    9031001    app.exec_() 
    904          
Note: See TracChangeset for help on using the changeset viewer.