Changeset 3794:bfea6ec66355 in orange


Ignore:
Timestamp:
07/20/07 17:20:06 (7 years ago)
Author:
Gregor <Gregor@…>
Branch:
default
Convert:
b87c2bddea4218bb96bab8fa5d27811f4ef06427
Message:

* empty log message *

Location:
orange
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • orange/OrangeWidgets/OWBaseWidget.py

    r3775 r3794  
    44# A General Orange Widget, from which all the Orange Widgets are derived 
    55# 
     6import orngOrangeFoldersQt4 
    67from OWTools import * 
    78from OWContexts import * 
     
    1011from string import * 
    1112from orngSignalManager import * 
     13import OWGUI 
     14 
     15ERROR = 0 
     16WARNING = 1 
    1217 
    1318def unisetattr(self, name, value, grandparent): 
     
    6671 
    6772 
    68  
    6973################## 
    7074# this definitions are needed only to define ExampleTable as subclass of ExampleTableWithClass 
     
    7276    pass 
    7377 
    74 #class ExampleTableWithClass(ExampleTable): 
    75 #    pass 
     78class ExampleTableWithClass(ExampleTable): 
     79    pass 
    7680 
    7781class AttributeList(list): 
     
    97101            self.settingsList = getattr(self, "settingsList", []) + ["widgetWidth", "widgetHeight", "widgetXPosition", "widgetYPosition", "widgetShown"] 
    98102 
    99         self.title = title.replace("&","") 
    100  
    101         QDialog.__init__(self, parent, self.title, modal, Qt.WStyle_Customize + Qt.WStyle_NormalBorder + Qt.WStyle_Title + Qt.WStyle_SysMenu + Qt.WStyle_Minimize + Qt.WStyle_Maximize) 
     103        #  , self.captionTitle, modal, Qt.WStyle_Customize + Qt.WStyle_NormalBorder + Qt.WStyle_Title + Qt.WStyle_SysMenu + Qt.WStyle_Minimize + Qt.WStyle_Maximize 
     104        QDialog.__init__(self, parent) 
    102105 
    103106        # directories are better defined this way, otherwise .ini files get written in many places 
    104         self.widgetDir = os.path.dirname(__file__) + "/" 
    105  
    106         # create output directory for widget settings 
    107         home = user.home 
    108         if home[-1] == ":": 
    109             home += "\\" 
    110         if os.name == "nt": 
    111             if not os.path.exists(os.path.join(home, "Application Data")): 
    112                 os.mkdir(os.path.join(home, "Application Data")) 
    113             self.outputDir = os.path.join(os.path.join(home, "Application Data"), "Orange")                  # directory for saving settings and stuff 
    114         elif sys.platform == "darwin": 
    115             self.outputDir = os.path.join(home, "Library") 
    116             self.outputDir = os.path.join(self.outputDir, "Application Support") 
    117             self.outputDir = os.path.join(self.outputDir, "Orange") 
    118         else: 
    119             self.outputDir = os.path.join(home, "Orange")                  # directory for saving settings and stuff 
    120  
    121         if not os.path.exists(self.outputDir): 
    122             try: os.mkdir(self.outputDir)            # Vista has roaming profiles that will say that this folder does not exist and will then fail to create it, because it exists... 
    123             except: pass 
    124              
    125         self.outputDir = os.path.join(self.outputDir, "widgetSettings") 
    126         if not os.path.exists(self.outputDir): 
    127             try: os.mkdir(self.outputDir)            # Vista has roaming profiles that will say that this folder does not exist and will then fail to create it, because it exists... 
    128             except: pass 
    129  
     107        self.__dict__.update(orngOrangeFoldersQt4.directoryNames) 
     108 
     109        title = title.replace("&","") 
     110        self.setCaption(title) # used for widget caption 
    130111        self.loadContextSettings() 
    131  
    132         self.captionTitle = title.replace("&","")     # used for widget caption 
    133  
    134         # if we want the widget to show the title then the title must start with "Qt" 
    135         if (int(qVersion()[0]) < 3) and self.captionTitle[:2].upper() != "QT": 
    136             self.captionTitle = "Qt " + self.captionTitle 
    137112 
    138113        # number of control signals, that are currently being processed 
     
    159134        self.widgetState = {"Info":{}, "Warning":{}, "Error":{}} 
    160135 
    161         #the title 
    162         self.setCaption(self.captionTitle) 
    163  
    164136        if hasattr(self, "contextHandlers"): 
    165137            for contextHandler in self.contextHandlers.values(): 
    166138                contextHandler.initLocalContext(self) 
    167139 
     140 
    168141    # uncomment this when you need to see which events occured 
    169142    """ 
    170143    def event(self, e): 
    171         eventDict = dict([(0, 'None'), (1, 'Timer'), (2, 'MouseButtonPress'), (3, 'MouseButtonRelease'), (4, 'MouseButtonDblClick'), (5, 'MouseMove'), (6, 'KeyPress'), (7, 'KeyRelease'), (8, 'FocusIn'), (9, 'FocusOut'), (10, 'Enter'), (11, 'Leave'), (12, 'Paint'), (13, 'Move'), (14, 'Resize'), (15, 'Create'), (16, 'Destroy'), (17, 'Show'), (18, 'Hide'), (19, 'Close'), (20, 'Quit'), (21, 'Reparent'), (22, 'ShowMinimized'), (23, 'ShowNormal'), (24, 'WindowActivate'), (25, 'WindowDeactivate'), (26, 'ShowToParent'), (27, 'HideToParent'), (28, 'ShowMaximized'), (30, 'Accel'), (31, 'Wheel'), (32, 'AccelAvailable'), (33, 'CaptionChange'), (34, 'IconChange'), (35, 'ParentFontChange'), (36, 'ApplicationFontChange'), (37, 'ParentPaletteChange'), (38, 'ApplicationPaletteChange'), (40, 'Clipboard'), (42, 'Speech'), (50, 'SockAct'), (51, 'AccelOverride'), (60, 'DragEnter'), (61, 'DragMove'), (62, 'DragLeave'), (63, 'Drop'), (64, 'DragResponse'), (70, 'ChildInserted'), (71, 'ChildRemoved'), (72, 'LayoutHint'), (73, 'ShowWindowRequest'), (80, 'ActivateControl'), (81, 'DeactivateControl'), (1000, 'User')]) 
    172         print self, eventDict[e.type()] 
     144        #eventDict = dict([(0, 'None'), (1, 'Timer'), (2, 'MouseButtonPress'), (3, 'MouseButtonRelease'), (4, 'MouseButtonDblClick'), (5, 'MouseMove'), (6, 'KeyPress'), (7, 'KeyRelease'), (8, 'FocusIn'), (9, 'FocusOut'), (10, 'Enter'), (11, 'Leave'), (12, 'Paint'), (13, 'Move'), (14, 'Resize'), (15, 'Create'), (16, 'Destroy'), (17, 'Show'), (18, 'Hide'), (19, 'Close'), (20, 'Quit'), (21, 'Reparent'), (22, 'ShowMinimized'), (23, 'ShowNormal'), (24, 'WindowActivate'), (25, 'WindowDeactivate'), (26, 'ShowToParent'), (27, 'HideToParent'), (28, 'ShowMaximized'), (30, 'Accel'), (31, 'Wheel'), (32, 'AccelAvailable'), (33, 'CaptionChange'), (34, 'IconChange'), (35, 'ParentFontChange'), (36, 'ApplicationFontChange'), (37, 'ParentPaletteChange'), (38, 'ApplicationPaletteChange'), (40, 'Clipboard'), (42, 'Speech'), (50, 'SockAct'), (51, 'AccelOverride'), (60, 'DragEnter'), (61, 'DragMove'), (62, 'DragLeave'), (63, 'Drop'), (64, 'DragResponse'), (70, 'ChildInserted'), (71, 'ChildRemoved'), (72, 'LayoutHint'), (73, 'ShowWindowRequest'), (80, 'ActivateControl'), (81, 'DeactivateControl'), (1000, 'User')]) 
     145        eventDict = dict([(0, "None"), (130, "AccessibilityDescription"), (119, "AccessibilityHelp"), (86, "AccessibilityPrepare"), (114, "ActionAdded"), (113, "ActionChanged"), (115, "ActionRemoved"), (99, "ActivationChange"), (121, "ApplicationActivated"), (122, "ApplicationDeactivated"), (36, "ApplicationFontChange"), (37, "ApplicationLayoutDirectionChange"), (38, "ApplicationPaletteChange"), (35, "ApplicationWindowIconChange"), (68, "ChildAdded"), (69, "ChildPolished"), (71, "ChildRemoved"), (40, "Clipboard"), (19, "Close"), (82, "ContextMenu"), (52, "DeferredDelete"), (60, "DragEnter"), (62, "DragLeave"), (61, "DragMove"), (63, "Drop"), (98, "EnabledChange"), (10, "Enter"), (150, "EnterEditFocus"), (124, "EnterWhatsThisMode"), (116, "FileOpen"), (8, "FocusIn"), (9, "FocusOut"), (97, "FontChange"), (159, "GraphicsSceneContextMenu"), (164, "GraphicsSceneDragEnter"), (166, "GraphicsSceneDragLeave"), (165, "GraphicsSceneDragMove"), (167, "GraphicsSceneDrop"), (163, "GraphicsSceneHelp"), (160, "GraphicsSceneHoverEnter"), (162, "GraphicsSceneHoverLeave"), (161, "GraphicsSceneHoverMove"), (158, "GraphicsSceneMouseDoubleClick"), (155, "GraphicsSceneMouseMove"), (156, "GraphicsSceneMousePress"), (157, "GraphicsSceneMouseRelease"), (168, "GraphicsSceneWheel"), (18, "Hide"), (27, "HideToParent"), (127, "HoverEnter"), (128, "HoverLeave"), (129, "HoverMove"), (96, "IconDrag"), (101, "IconTextChange"), (83, "InputMethod"), (6, "KeyPress"), (7, "KeyRelease"), (89, "LanguageChange"), (90, "LayoutDirectionChange"), (76, "LayoutRequest"), (11, "Leave"), (151, "LeaveEditFocus"), (125, "LeaveWhatsThisMode"), (88, "LocaleChange"), (153, "MenubarUpdated"), (43, "MetaCall"), (102, "ModifiedChange"), (4, "MouseButtonDblClick"), (2, "MouseButtonPress"), (3, "MouseButtonRelease"), (5, "MouseMove"), (109, "MouseTrackingChange"), (13, "Move"), (12, "Paint"), (39, "PaletteChange"), (131, "ParentAboutToChange"), (21, "ParentChange"), (75, "Polish"), (74, "PolishRequest"), (123, "QueryWhatsThis"), (14, "Resize"), (117, "Shortcut"), (51, "ShortcutOverride"), (17, "Show"), (26, "ShowToParent"), (50, "SockAct"), (112, "StatusTip"), (100, "StyleChange"), (87, "TabletMove"), (92, "TabletPress"), (93, "TabletRelease"), (171, "TabletEnterProximity"), (172, "TabletLeaveProximity"), (1, "Timer"), (120, "ToolBarChange"), (110, "ToolTip"), (78, "UpdateLater"), (77, "UpdateRequest"), (111, "WhatsThis"), (118, "WhatsThisClicked"), (31, "Wheel"), (132, "WinEventAct"), (24, "WindowActivate"), (103, "WindowBlocked"), (25, "WindowDeactivate"), (34, "WindowIconChange"), (105, "WindowStateChange"), (33, "WindowTitleChange"), (104, "WindowUnblocked"), (126, "ZOrderChange"), (169, "KeyboardLayoutChange"), (170, "DynamicPropertyChange")]) 
     146        if eventDict.has_key(e.type()): 
     147            print str(self.windowTitle()), eventDict[e.type()] 
    173148        return QDialog.event(self, e) 
    174149    """ 
     
    176151    def setWidgetIcon(self, iconName): 
    177152        if os.path.exists(iconName): 
    178             QDialog.setIcon(self, QPixmap(iconName)) 
     153            self.setWindowIcon(QIcon(iconName)) 
    179154        elif os.path.exists(self.widgetDir + iconName): 
    180             QDialog.setIcon(self, QPixmap(self.widgetDir + iconName)) 
     155            self.setWindowIcon(QIcon(self.widgetDir + iconName)) 
    181156        elif os.path.exists(self.widgetDir + "icons/" + iconName): 
    182             QDialog.setIcon(self, QPixmap(self.widgetDir + "icons/" + iconName)) 
     157            self.setWindowIcon(QIon(self.widgetDir + "icons/" + iconName)) 
    183158        elif os.path.exists(self.widgetDir + "icons/Unknown.png"): 
    184             QDialog.setIcon(self, QPixmap(self.widgetDir + "icons/Unknown.png")) 
     159            self.setWindowIcon(QIcon(self.widgetDir + "icons/Unknown.png")) 
    185160 
    186161    # ############################################## 
    187162    def createAttributeIconDict(self): 
    188         import OWGUI 
    189163        return OWGUI.getAttributeIcons() 
    190164 
     
    216190        if self.savePosition: 
    217191            if getattr(self, "widgetXPosition", None) != None and getattr(self, "widgetYPosition", None) != None: 
    218 ##                print self.title, "restoring position", self.widgetXPosition, self.widgetYPosition 
     192                #print self.captionTitle, "restoring position", self.widgetXPosition, self.widgetYPosition 
    219193                self.move(self.widgetXPosition, self.widgetYPosition) 
    220             if getattr(self, "widgetWidth", None) != None and getattr(self, "widgetHeight", None) != None: 
     194            if getattr(self,"widgetWidth", None) != None and getattr(self,"widgetHeight", None) != None: 
    221195                self.resize(self.widgetWidth, self.widgetHeight) 
    222196 
     
    233207            self.widgetWidth = self.width() 
    234208            self.widgetHeight = self.height() 
    235 ##            print self.title, "saving resize", self.widgetWidth, self.widgetHeight 
    236209 
    237210 
     
    243216            self.widgetXPosition = ev.pos().x() 
    244217            self.widgetYPosition = ev.pos().y() 
    245 ##            print self.title, "saving position", self.widgetXPosition, self.widgetYPosition 
     218            #print self.captionTitle, "saving position", self.widgetXPosition, self.widgetYPosition 
    246219 
    247220    # set widget state to hidden 
     
    258231 
    259232    def setCaption(self, caption): 
    260         if self.parent != None and isinstance(self.parent, QTabWidget): self.parent.changeTab(self, caption) 
    261         else: QDialog.setCaption(self, caption) 
    262  
    263     def setCaptionTitle(self, caption): 
    264         self.captionTitle = caption     # we have to save caption title in case progressbar will change it 
    265         self.setCaption(caption) 
     233        if self.parent != None and isinstance(self.parent, QTabWidget): 
     234            self.parent.setTabText(self.parent.indexOf(self), caption) 
     235        else: 
     236            if (int(qVersion()[0]) < 3) and caption[:2].upper() != "QT":      # if we want the widget to show the title then the title must start with "Qt" 
     237                caption = "Qt " + caption 
     238            self.captionTitle = caption     # we have to save caption title in case progressbar will change it 
     239            self.setWindowTitle(caption) 
    266240 
    267241    # put this widget on top of all windows 
     
    272246    def send(self, signalName, value, id = None): 
    273247        if not self.hasOutputName(signalName): 
    274             print "Warning! Signal '%s' is not a valid signal name for the '%s' widget. Please fix the signal name." % (signalName, self.title) 
     248            print "Warning! Signal '%s' is not a valid signal name for the '%s' widget. Please fix the signal name." % (signalName, self.captionTitle) 
    275249 
    276250        if self.linksOut.has_key(signalName): 
     
    284258    def getdeepattr(self, attr, **argkw): 
    285259        try: 
    286             return reduce(lambda o, n: getattr(o, n),  attr.split("."), self) 
     260            return reduce(lambda o, n: getattr(o, n, None),  attr.split("."), self) 
    287261        except: 
    288262            if argkw.has_key("default"): 
     
    308282                    settings[name] =  self.getdeepattr(name) 
    309283                except: 
    310                     #print "Attribute %s not found in %s widget. Remove it from the settings list." % (name, self.title) 
     284                    #print "Attribute %s not found in %s widget. Remove it from the settings list." % (name, self.captionTitle) 
    311285                    pass 
    312286        return settings 
     
    315289    def getSettingsFile(self, file): 
    316290        if file==None: 
    317             if os.path.exists(os.path.join(self.outputDir, self.title + ".ini")): 
    318                 file = os.path.join(self.outputDir, self.title + ".ini") 
     291            if os.path.exists(os.path.join(self.widgetSettingsDir, self.captionTitle + ".ini")): 
     292                file = os.path.join(self.widgetSettingsDir, self.captionTitle + ".ini") 
    319293            else: 
    320294                return 
     
    351325 
    352326 
     327 
     328 
    353329    def loadContextSettings(self, file = None): 
    354330        if not hasattr(self.__class__, "savedContextSettings"): 
     
    379355        if settings: 
    380356            if file==None: 
    381                 file = os.path.join(self.outputDir, self.title + ".ini") 
     357                file = os.path.join(self.widgetSettingsDir, self.captionTitle + ".ini") 
    382358            if type(file) == str: 
    383359                file = open(file, "w") 
     
    496472        return None 
    497473 
     474    def handleNewSignals(self): 
     475        pass 
     476 
    498477    # signal manager calls this function when all input signals have updated the data 
    499478    def processSignals(self): 
     
    501480 
    502481        # we define only a way to handle signals that have defined a handler function 
    503         for signal in self.inputs:        # we go from the first to the last defined input 
    504             key = signal[0] 
    505             if self.linksIn.has_key(key): 
    506                 for i in range(len(self.linksIn[key])): 
    507                     (dirty, widgetFrom, handler, signalData) = self.linksIn[key][i] 
    508                     if not (handler and dirty): continue 
    509  
    510                     qApp.setOverrideCursor(QWidget.waitCursor) 
    511                     try: 
    512                         for (value, id, nameFrom) in signalData: 
    513                             if self.signalIsOnlySingleConnection(key): 
    514                                 self.printEvent("ProcessSignals: Calling %s with %s" % (handler, value), eventVerbosity = 2) 
    515                                 handler(value) 
    516                             else: 
    517                                 self.printEvent("ProcessSignals: Calling %s with %s (%s, %s)" % (handler, value, nameFrom, id), eventVerbosity = 2) 
    518                                 handler(value, (widgetFrom, nameFrom, id)) 
    519                     except: 
    520                         type, val, traceback = sys.exc_info() 
    521                         sys.excepthook(type, val, traceback)  # we pretend that we handled the exception, so that we don't crash other widgets 
    522  
    523                     qApp.restoreOverrideCursor() 
    524                     self.linksIn[key][i] = (0, widgetFrom, handler, []) # clear the dirty flag 
    525  
    526         if hasattr(self, "handleNewSignals"): 
    527             self.handleNewSignals() 
     482        for key in self.linksIn.keys(): 
     483            for i in range(len(self.linksIn[key])): 
     484                (dirty, widgetFrom, handler, signalData) = self.linksIn[key][i] 
     485                if not (handler and dirty): continue 
     486 
     487                qApp.setOverrideCursor(Qt.WaitCursor) 
     488                try: 
     489                    for (value, id, nameFrom) in signalData: 
     490                        if self.signalIsOnlySingleConnection(key): 
     491                            self.printEvent("ProcessSignals: Calling %s with %s" % (handler, value), eventVerbosity = 2) 
     492                            handler(value) 
     493                        else: 
     494                            self.printEvent("ProcessSignals: Calling %s with %s (%s, %s)" % (handler, value, nameFrom, id), eventVerbosity = 2) 
     495                            handler(value, (widgetFrom, nameFrom, id)) 
     496                except: 
     497                    type, val, traceback = sys.exc_info() 
     498                    sys.excepthook(type, val, traceback)  # we pretend that we handled the exception, so that we don't crash other widgets 
     499 
     500                qApp.restoreOverrideCursor() 
     501                self.linksIn[key][i] = (0, widgetFrom, handler, []) # clear the dirty flag 
     502 
     503        self.handleNewSignals() 
    528504 
    529505        if self.processingHandler: 
     
    556532        self.progressBarValue = 0 
    557533        self.startTime = time.time() 
    558         self.setCaption(self.captionTitle + " (0% complete)") 
     534        self.setWindowTitle(self.captionTitle + " (0% complete)") 
    559535        if self.progressBarHandler: 
    560536            self.progressBarHandler(self, -1) 
     
    573549            else: 
    574550                text = "%(min)d min, %(sec)d sec" % vars() 
    575             self.setCaption(self.captionTitle + " (%(value).2f%% complete, remaining time: %(text)s)" % vars()) 
     551            self.setWindowTitle(self.captionTitle + " (%(value).2f%% complete, remaining time: %(text)s)" % vars()) 
    576552        else: 
    577             self.setCaption(self.captionTitle + " (0% complete)" ) 
     553            self.setWindowTitle(self.captionTitle + " (0% complete)" ) 
    578554        if self.progressBarHandler: self.progressBarHandler(self, value) 
    579555        qApp.processEvents() 
     
    583559 
    584560    def progressBarFinished(self): 
    585         self.setCaption(self.captionTitle) 
     561        self.setWindowTitle(self.captionTitle) 
    586562        if self.progressBarHandler: self.progressBarHandler(self, 101) 
    587563 
     
    598574    def setWidgetStateHandler(self, handler): 
    599575        self.widgetStateHandler = handler 
     576 
    600577 
    601578    # if we are in debug mode print the event into the file 
     
    721698        return unisetattr(self, name, value, QDialog) 
    722699 
     700    
     701    # ################################################################## 
     702    # a function for randomly changing settings in the widget - used in automatic widget debugging 
    723703    def randomlyChangeSettings(self, verboseMode = 0): 
    724704        if len(self._guiElements) == 0: return 
     
    743723                if widget.isToggleButton(): 
    744724                    newValue = "Clicking button %s. State is %d" % (str(widget.text()).strip(), not widget.isOn()) 
    745                     widget.setOn(not widget.isOn()) 
     725                    widget.setOn(not widget.isChecked()) 
    746726                else: 
    747727                    newValue = "Pressed button %s" % (str(widget.text()).strip()) 
     
    750730                if widget.count(): 
    751731                    itemIndex = random.randint(0, widget.count()-1) 
    752                     newValue = "Listbox %s. Changed selection of item %d to %s" % (value, itemIndex, not widget.isSelected(itemIndex)) 
    753                     widget.setSelected(itemIndex, not widget.isSelected(itemIndex)) 
     732                    newValue = "Listbox %s. Changed selection of item %d to %s" % (value, itemIndex, not widget.item(itemIndex).isSelected()) 
     733                    widget.item(itemIndex).setSelected(not widget.item(itemIndex).isSelected()) 
    754734                else: 
    755735                    callback = None 
     
    777757                if widget.count(): 
    778758                    pos = random.randint(0, widget.count()-1) 
    779                     newValue = "Changed value of combo %s to %s" % (value, str(widget.text(pos))) 
     759                    newValue = "Changed value of combo %s to %s" % (value, str(widget.itemText(pos))) 
    780760                    if sendSelectedValue: 
    781                         setattr(self, value, valueType(str(widget.text(pos)))) 
     761                        setattr(self, value, valueType(str(widget.itemText(pos)))) 
    782762                    else: 
    783763                        setattr(self, value, pos) 
     
    806786    a=QApplication(sys.argv) 
    807787    oww=OWBaseWidget() 
    808     a.setMainWidget(oww) 
    809788    oww.show() 
    810     a.exec_loop() 
     789    a.exec_() 
    811790    oww.saveSettings() 
  • orange/OrangeWidgets/OWClusterOptimization.py

    r3567 r3794  
    9898        self.attributeCountIndex = 1 
    9999        self.argumentationType = BEST_GROUPS 
    100          
     100 
    101101        self.argumentationClassValue = 0 
    102102        self.distributionScale = 1 
     
    112112        self.canUseMoreArguments = 0 
    113113        self.moreArgumentsIndex = 4 
    114          
     114 
    115115        self.loadSettings() 
    116116 
    117117        self.tabs = QTabWidget(self, 'tabWidget') 
    118118        self.controlArea.addWidget(self.tabs) 
    119          
     119 
    120120        self.MainTab = QVGroupBox(self) 
    121121        self.SettingsTab = QVGroupBox(self) 
     
    123123        self.ClassificationTab = QVGroupBox(self) 
    124124        self.ManageTab = QVGroupBox(self) 
    125          
     125 
    126126        self.tabs.insertTab(self.MainTab, "Main") 
    127127        self.tabs.insertTab(self.SettingsTab, "Settings") 
     
    129129        self.tabs.insertTab(self.ClassificationTab, "Classification") 
    130130        self.tabs.insertTab(self.ManageTab, "Manage & Save") 
    131          
    132          
     131 
     132 
    133133        # ########################### 
    134134        # MAIN TAB 
     
    150150        self.stopOptimizationButton.hide() 
    151151 
    152         self.resultList = QListBox(self.resultsBox) 
    153         #self.resultList.setSelectionMode(QListBox.Extended)   # this would be nice if could be enabled, but it has a bug - currentItem doesn't return the correct value if this is on 
     152        self.resultList = OWGUI.listBox(self.resultsBox, self) 
     153        #self.resultList.setSelectionMode(QListWidget.ExtendedSelection)   # this would be nice if could be enabled, but it has a bug - currentItem doesn't return the correct value if this is on 
    154154        self.resultList.setMinimumSize(200,200) 
    155155 
     
    176176        OWGUI.comboBox(self.heuristicsSettingsBox, self, "attrCont", box = "Ordering of Continuous Attributes", items = [val for (val, m) in contMeasures]) 
    177177        OWGUI.comboBox(self.heuristicsSettingsBox, self, "attrDisc", box = "Ordering of Discrete Attributes", items = [val for (val, m) in discMeasures]) 
    178          
     178 
    179179        self.resultListCombo = OWGUI.comboBoxWithCaption(self.miscSettingsBox, self, "resultListLen", "Maximum length of projection list:   ", tooltip = "Maximum length of the list of interesting projections. This is also the number of projections that will be saved if you click Save button.", items = self.resultsListLenNums, callback = self.updateShownProjections, sendSelectedValue = 1, valueType = int) 
    180180        self.minTableLenEdit = OWGUI.lineEdit(self.miscSettingsBox, self, "minExamples", "Minimum examples in data set:        ", orientation = "horizontal", tooltip = "Due to missing values, different subsets of attributes can have different number of examples. Projections with less than this number of examples will be ignored.", valueType = int) 
    181181 
    182182        # ########################## 
    183         # ARGUMENTATION tab         
     183        # ARGUMENTATION tab 
    184184        self.argumentationStartBox = OWGUI.widgetBox(self.ArgumentationTab, "Arguments") 
    185185        self.findArgumentsButton = OWGUI.button(self.argumentationStartBox, self, "Find arguments", callback = self.findArguments) 
     
    190190        self.classValueList = OWGUI.comboBox(self.ArgumentationTab, self, "argumentationClassValue", box = "Arguments for class:", tooltip = "Select the class value that you wish to see arguments for", callback = self.argumentationClassChanged) 
    191191        self.argumentBox = OWGUI.widgetBox(self.ArgumentationTab, "Arguments for the selected class value") 
    192         self.argumentList = QListBox(self.argumentBox) 
     192        self.argumentList = OWGUI.listBox(self.argumentBox, self) 
    193193        self.argumentList.setMinimumSize(200,200) 
    194194        self.connect(self.argumentList, SIGNAL("selectionChanged()"),self.argumentSelected) 
     
    212212        self.manageResultsBox = OWGUI.widgetBox(self.ManageTab, "Number of concurrently visualized attributes") 
    213213        self.manageBox = OWGUI.widgetBox(self.ManageTab, "Manage projections") 
    214          
    215         self.classesList = QListBox(self.classesBox) 
    216         self.classesList.setSelectionMode(QListBox.Multi) 
     214 
     215        self.classesList = OWGUI.listBox(self.classesBox, selectionMode = QListWidget.MultiSelection, callback = self.updateShownProjections) 
    217216        self.classesList.setMinimumSize(60,60) 
    218         self.connect(self.classesList, SIGNAL("selectionChanged()"), self.updateShownProjections) 
    219217 
    220218        self.buttonBox6 = OWGUI.widgetBox(self.manageBox, orientation = "horizontal") 
     
    225223        #OWGUI.button(self.buttonBox7, self, "Graph projections", self.graphProjectionQuality) 
    226224        #OWGUI.button(self.buttonBox7, self, "Interaction Analysis", self.interactionAnalysis) 
    227          
     225 
    228226        self.buttonBox3 = OWGUI.widgetBox(self.manageBox, orientation = "horizontal") 
    229227        self.clusterStabilityButton = OWGUI.button(self.buttonBox3, self, 'Show cluster stability', self.evaluatePointsInClusters) 
    230         self.clusterStabilityButton.setToggleButton(1) 
     228        self.clusterStabilityButton.setCheckable(1) 
    231229        #self.saveProjectionButton = OWGUI.button(self.buttonBox3, self, 'Save projection') 
    232230        OWGUI.button(self.buttonBox3, self, "Save best graphs", self.exportMultipleGraphs) 
     
    234232        OWGUI.button(self.manageBox, self, "Clear results", self.clearResults) 
    235233 
    236         self.attrLenList = QListBox(self.manageResultsBox) 
    237         self.attrLenList.setSelectionMode(QListBox.Multi) 
     234        self.attrLenList = OWGUI.listBox(self.manageResultsBox, self, selectionMode = QListWidget.MultiSelection, callback = self.attrLenListChanged) 
    238235        self.attrLenList.setMinimumSize(60,60) 
    239         self.connect(self.attrLenList, SIGNAL("selectionChanged()"), self.attrLenListChanged) 
    240          
     236 
    241237        self.resize(375,550) 
    242238        self.setMinimumWidth(375) 
     
    254250                self.clusterLearner = clusterLearner(self, self.parentWidget) 
    255251                self.parentWidget.send("Cluster learner", self.clusterLearner) 
    256                  
    257                  
     252 
     253 
    258254    # ############################################################## 
    259255    # EVENTS 
     
    274270    # user clicked in the listbox that shows possible number of attributes of result list 
    275271    # result list must be updated accordingly 
    276     def attrLenListChanged(self): 
     272    def attrLenListChanged(self, *args): 
    277273        # check which attribute lengths do we want to show 
    278274        self.attrLenDict = {} 
    279275        for i in range(self.attrLenList.count()): 
    280             intVal = int(str(self.attrLenList.text(i))) 
    281             selected = self.attrLenList.isSelected(i) 
     276            intVal = int(str(self.attrLenList.item(i).text())) 
     277            selected = self.attrLenList.item(i).isSelected() 
    282278            self.attrLenDict[intVal] = selected 
    283279        self.updateShownProjections() 
     
    298294        selectedClasses = [] 
    299295        for i in range(self.classesList.count()-1): 
    300             if self.classesList.isSelected(i): selectedClasses.append(i) 
    301         if self.classesList.isSelected(self.classesList.count()-1): 
     296            if self.classesList.item(i).isSelected(): selectedClasses.append(i) 
     297        if self.classesList.item(self.classesList.count()-1).isSelected(): 
    302298            selectedClasses.append(-1)      # "all clusters" is represented by -1 in the selectedClasses array 
    303299        return selectedClasses 
     
    313309        removeSingleLines(graph, None, None, None, 0, -1) 
    314310        edgesDict, clusterDict, verticesDict, count = enumerateClusters(graph, 0) 
    315          
     311 
    316312        closureDict = computeClosure(graph, edgesDict, 1, 1, 1, -3, -4)   # find points that define the edge of a cluster with one class value. these points used when we search for nearest points of a specific cluster 
    317313        #bigPolygonVerticesDict = copy(verticesDict)  # compute which points lie in which cluster 
     
    338334        closureDict = computeClosure(graph, edgesDict, 1, 1, 2, -3, -2) 
    339335        polygonVerticesDict = verticesDict  # compute which points lie in which cluster 
    340          
     336 
    341337        aveDistDict = computeAverageDistance(graph, edgesDict) 
    342          
     338 
    343339        # compute areas of all found clusters 
    344340        #areaDict = computeAreas(graph, edgesDict, clusterDict, verticesDict, closureDict, 2) 
     
    351347        for i in range(len(allOtherClass)-1)[::-1]: 
    352348            if allOtherClass[i] == allOtherClass[i+1]: allOtherClass.remove(allOtherClass[i]) 
    353          
     349 
    354350        valueDict = {} 
    355351        otherDict = {} 
     
    396392            value = points 
    397393            if self.considerDistance: value *= dist 
    398              
     394 
    399395            valueDict[key] = value 
    400396            #enlargedClosureDict[key] = enlargeClosure(graph, closureDict[key], aveDistDict[key]) 
     
    404400            #otherDict[key] = (graph.objects[polygonVerticesDict[key][0]].getclass().value, value, points, dist, aveDistDict[key]) 
    405401            otherDict[key] = (int(graph.objects[polygonVerticesDict[key][0]].getclass()), value, points, dist, (xAve, yAve), aveDistDict[key]) 
    406          
     402 
    407403        del edgesDict, clusterDict, verticesDict, allOtherClass 
    408404        for key in closureDict.keys(): 
     
    417413    # for each point then return a float between 0 and 1 
    418414    def evaluatePointsInClusters(self): 
    419         if self.clusterStabilityButton.isOn(): 
     415        if self.clusterStabilityButton.isChecked(): 
    420416            self.pointStability = numpy.zeros(len(self.rawdata), numpy.float) 
    421417            self.pointStabilityCount = [0 for i in range(len(self.rawdata.domain.classVar.values))]       # for each class value create a counter that will count the number of clusters for it 
    422              
     418 
    423419            if (int(qVersion()[0]) >= 3): 
    424420                (text, ok) = QInputDialog.getText('Projection count', 'How many of the best projections do you want to consider?') 
     
    426422                (text, ok) = QInputDialog.getText('Qt Projection count', 'How many of the best projections do you want to consider?') 
    427423            if not ok: return 
    428             nrOfProjections = int(str(text))  
     424            nrOfProjections = int(str(text)) 
    429425 
    430426            considered = 0 
     
    445441                for j in range(len(clusterClasses)):        # some projections may contain more clusters of the same class. we make sure we don't process this wrong 
    446442                    self.pointStabilityCount[j] += clusterClasses[j] 
    447          
     443 
    448444            for i in range(len(self.rawdata)): 
    449445                if self.pointStabilityCount[int(self.rawdata[i].getclass())] != 0: 
     
    453449        if self.parentWidget: self.parentWidget.showSelectedCluster() 
    454450 
    455              
     451 
    456452    def updateShownProjections(self, *args): 
    457453        self.resultList.clear() 
     
    471467            if self.allResults[i][STR_LIST] != "": string += self.allResults[i][STR_LIST] 
    472468            else: string += self.buildAttrString(self.allResults[i][ATTR_LIST]) 
    473              
     469 
    474470            self.resultList.insertItem(string) 
    475471            self.shownResults.append(self.allResults[i]) 
    476472            i+=1 
    477         if self.resultList.count() > 0: self.resultList.setCurrentItem(0)         
     473        if self.resultList.count() > 0: self.resultList.setCurrentItem(0) 
    478474 
    479475 
     
    488484        if not sameDomain: self.clearResults() 
    489485 
    490         if not data or not (data.domain.classVar and data.domain.classVar.varType == orange.VarTypes.Discrete):         
     486        if not data or not (data.domain.classVar and data.domain.classVar.varType == orange.VarTypes.Discrete): 
    491487            self.selectedClasses = [] 
    492488            self.classesList.clear() 
     
    504500                self.classValueList.insertItem(data.domain.classVar.values[i]) 
    505501            self.classesList.insertItem("All clusters") 
    506             self.classesList.selectAll(1) 
     502            self.classesList.selectAll() 
    507503            if len(data.domain.classVar.values) > 0: self.classValueList.setCurrentItem(0) 
    508504 
     
    511507        self.subsetdata = subsetdata 
    512508        self.clearArguments() 
    513      
    514                  
     509 
     510 
    515511    # given a dataset return a list of (val, attrName) where val is attribute "importance" and attrName is name of the attribute 
    516512    def getEvaluatedAttributes(self, data): 
     
    519515        self.setStatusBarText("") 
    520516        return attrs 
    521      
     517 
    522518    def addResult(self, value, closure, vertices, attrList, classValue, enlargedClosure, other, strList = ""): 
    523519        self.insertItem(self.findTargetIndex(value), value, closure, vertices, attrList, classValue, enlargedClosure, other, strList) 
     
    536532        if max(value, self.allResults[top][VALUE]) == value: 
    537533            return top 
    538         else:  
     534        else: 
    539535            return bottom 
    540536 
     
    553549            else: string += self.buildAttrString(attrList) 
    554550 
    555             self.resultList.insertItem(string, index) 
     551            self.resultList.insertItem(index, string) 
    556552            self.shownResults.insert(index, (value, closure, vertices, attrList, classValue, enlargedClosure, other, strList)) 
    557553 
    558554        # remove worst projection if list is too long 
    559555        if self.resultList.count() > self.resultListLen: 
    560             self.resultList.removeItem(self.resultList.count()-1) 
     556            self.resultList.takeItem(self.resultList.count()-1) 
    561557            self.shownResults.pop() 
    562      
     558 
    563559    def finishedAddingResults(self): 
    564560        self.cancelOptimization = 0 
    565          
     561 
    566562        self.attrLenList.clear() 
    567563        self.attrLenDict = {} 
     
    576572            self.attrLenList.insertItem(str(val)) 
    577573            self.attrLenDict[val] = 1 
    578         self.attrLenList.selectAll(1) 
     574        self.attrLenList.selectAll() 
    579575        self.resultList.setCurrentItem(0) 
    580576 
    581      
     577 
    582578    # ############################################################## 
    583579    # Loading and saving projection files 
     
    628624            QMessageBox.critical(None,'Load','There is no data. First load a data set and then load a cluster file',QMessageBox.Ok) 
    629625            return 
    630                  
     626 
    631627        name = QFileDialog.getOpenFileName( self.lastSaveDirName, "Interesting clusters (*.clu)", self, "", "Open Clusters") 
    632628        if name.isEmpty(): return 
     
    648644        selectedClasses = eval(file.readline()[:-1]) 
    649645        for i in range(len(self.rawdata.domain.classVar.values)): 
    650             self.classesList.setSelected(i, i in selectedClasses) 
    651         if -1 in selectedClasses: self.classesList.setSelected(self.classesList.count()-1, 1) 
     646            self.classesList.item(i).setSelected(i in selectedClasses) 
     647        if -1 in selectedClasses: self.classesList.item(self.classesList.count()-1).setSelected(1) 
    652648        checksum = eval(file.readline()[:-1]) 
    653649        if self.rawdata and self.rawdata.checksum() != checksum: 
     
    679675        self.ClassificationTab.setEnabled(0) 
    680676 
    681     def enableControls(self):     
     677    def enableControls(self): 
    682678        self.optimizationTypeCombo.setEnabled(1) 
    683679        self.attributeCountCombo.setEnabled(1) 
     
    710706        (fil,ext) = os.path.splitext(fileName) 
    711707        ext = ext.replace(".","") 
    712         if ext == "":    
     708        if ext == "": 
    713709            ext = "PNG"     # if no format was specified, we choose png 
    714710            fileName = fileName + ".png" 
     
    718714        size = self.sizeDlg.getSize() 
    719715        for i in range(1, min(self.resultList.count(), self.bestGraphsCount+1)): 
    720             self.resultList.setSelected(i-1, 1) 
     716            self.resultList.item(i-1).setSelected(1) 
    721717            self.graph.replot() 
    722718            name = fil + " (%02d)" % i + extension 
     
    738734    """ 
    739735 
    740      
     736 
    741737 
    742738    # ###################################################### 
     
    745741    def getOptimizationType(self): 
    746742        return self.optimizationType 
    747     
     743 
    748744    # from a list of attributes build a nice string with attribute names 
    749745    def buildAttrString(self, attrList): 
     
    789785        self.clearArguments() 
    790786        self.arguments = [[] for i in range(self.classValueList.count())] 
    791          
     787 
    792788        if self.subsetdata == None: 
    793789            QMessageBox.information( None, "Cluster Dialog Argumentation", 'To find arguments you first have to provide a new example that you wish to classify. \nYou can do this by sending the example to the visualization widget through the "Example Subset" signal.', QMessageBox.Ok + QMessageBox.Default) 
     
    828824                        if inside == 0 or (inside == 1 and self.conditionForArgument == MUST_BE_INSIDE): continue 
    829825                        vals[classValue] += 1 
    830                          
     826 
    831827                        self.arguments[classValue].append((None, value, attrList, startingIndex+index)) 
    832828                        if classValue == self.classValueList.currentItem(): 
    833829                            self.argumentList.insertItem("%.2f - %s" %(value, attrList)) 
    834830                    if classIndices[cls] == startingIndex: classIndices[cls] = len(self.allResults)+1 
    835                      
     831 
    836832                foundArguments += 1 
    837833                if min(classIndices) >= len(self.allResults): canFinish = 1  # out of possible arguments 
    838                  
     834 
    839835                if sum(vals) > 0 and foundArguments >= argumentCount: 
    840836                    if not self.canUseMoreArguments or (max(vals)*100.0)/float(sum(vals)) > self.moreArgumentsNums[self.moreArgumentsIndex]: 
     
    848844                # we also stop if we are not allowed to search for more than argumentCount arguments or we are allowed and we have a reliable prediction or we have used a 100 additional arguments 
    849845                if foundArguments >= argumentCount and (not self.canUseMoreArguments or (max(vals)*100.0 / sum(vals) > self.moreArgumentsNums[self.moreArgumentsIndex]) or foundArguments >= argumentCount + 100): break 
    850                  
     846 
    851847                (value, closure, vertices, attrList, classValue, enlargedClosure, other, strList) = self.allResults[index] 
    852848                if type(classValue) == dict: continue       # the projection contains several clusters 
     
    856852                if self.conditionForArgument == MUST_BE_INSIDE and inside != 2: continue 
    857853                elif inside == 0: continue 
    858                  
     854 
    859855                foundArguments += 1  # increase argument count 
    860                  
     856 
    861857                if self.useProjectionValue: vals[classValue] += value 
    862858                else: vals[classValue] += 1 
     
    885881            QMessageBox.information(None, "Classification results", s, QMessageBox.Ok + QMessageBox.Default) 
    886882        return classValue, dist 
    887          
     883 
    888884    # is the example described with scaledExampleVals inside closure that contains points in vertices in projection of attrList attributes 
    889885    def isExampleInsideCluster(self, attrList, scaledExampleVals, closure, vertices, averageEdgeDistance): 
     
    895891            return 0 
    896892        short = numpy.transpose(numpy.take(array, vertices)) 
    897          
     893 
    898894        [xTest, yTest] = self.graph.getProjectedPointPosition(attrList, testExampleAttrVals) 
    899895 
     
    914910                val = 1 
    915911                break 
    916             
     912 
    917913        return val 
    918914 
     
    930926        if max(value, arguments[top][1]) == value: 
    931927            return top 
    932         else:  
     928        else: 
    933929            return bottom 
    934          
     930 
    935931    def stopArgumentationClick(self): 
    936932        self.cancelArgumentation = 1 
    937      
     933 
    938934    def argumentationClassChanged(self): 
    939935        self.argumentList.clear() 
     
    950946        clusterClosure = (self.allResults[self.arguments[classInd][ind][3]][CLOSURE], self.allResults[self.arguments[classInd][ind][3]][ENL_CLOSURE], self.allResults[self.arguments[classInd][ind][3]][CLASS]) 
    951947        self.parentWidget.updateGraph(self.arguments[classInd][ind][2], clusterClosure = clusterClosure) 
    952          
     948 
    953949 
    954950class clusterClassifier(orange.Classifier): 
     
    966962        else: computeProjections = 1 
    967963 
    968         self.visualizationWidget.setData(data, clearResults = computeProjections)         
     964        self.visualizationWidget.setData(data, clearResults = computeProjections) 
    969965        if computeProjections == 1:     # run cluster detection 
    970966            self.evaluating = 1 
     
    980976        if self.evaluating: 
    981977            self.clusterOptimizationDlg.stopOptimizationClick() 
    982              
     978 
    983979 
    984980    # for a given example run argumentation and find out to which class it most often falls 
     
    10151011                        break 
    10161012                    if classIndices[cls] == startingIndex: classIndices[cls] = len(self.clusterOptimizationDlg.allResults)+1 
    1017                      
     1013 
    10181014                argumentCount += 1 
    10191015                if min(classIndices) >= len(self.clusterOptimizationDlg.allResults): canFinish = 1  # out of possible arguments 
    1020                  
     1016 
    10211017                if sum(classProjectionVals) > 0 and argumentCount >= allowedArguments: 
    10221018                    if not self.clusterOptimizationDlg.canUseMoreArguments or (max(classProjectionVals)*100.0)/float(sum(classProjectionVals)) > self.clusterOptimizationDlg.moreArgumentsNums[self.clusterOptimizationDlg.moreArgumentsIndex]: 
     
    10391035                s += "<nobr>Note: To get the current prediction, <b>%d</b> arguments had to be used (instead of %d)<br>" % (argumentCount, allowedArguments) 
    10401036            print s[:-4] 
    1041              
     1037 
    10421038            return (classValue, dist) 
    10431039        else: 
     
    10611057 
    10621058                # find 10 more arguments than it is necessary - this is because with a different fold of data the clusters can be differently evaluated 
    1063                 if argumentCount >= self.clusterOptimizationDlg.argumentCounts[self.clusterOptimizationDlg.argumentCountIndex]:  
     1059                if argumentCount >= self.clusterOptimizationDlg.argumentCounts[self.clusterOptimizationDlg.argumentCountIndex]: 
    10641060                    argumentValues.sort(); argumentValues.reverse() 
    10651061                    vals = [0.0 for i in range(len(self.clusterOptimizationDlg.rawdata.domain.classVar.values))] 
     
    10871083                            s += "<nobr>Note: To get the current prediction, <b>%d</b> arguments had to be used (instead of %d)<br>" % (consideredArguments, neededArguments) 
    10881084                        print s[:-4] 
    1089                          
     1085 
    10901086                        return (classValue, dist) 
    10911087 
     
    10961092                if self.clusterOptimizationDlg.useProjectionValue:  vals[c] += val 
    10971093                else:                                               vals[c] += 1 
    1098                  
     1094 
    10991095            if max(vals) == 0.0: 
    11001096                print "there are no arguments for this example in the current projection list." 
     
    11211117        self.name = self.clusterOptimizationDlg.parentWidget.clusterClassifierName 
    11221118        self.firstTime = 1 
    1123          
     1119 
    11241120    def __call__(self, examples, weightID = 0): 
    11251121        classifier = clusterClassifier(self.clusterOptimizationDlg, self.visualizationWidget, examples, self.firstTime) 
    11261122        self.firstTime = 0 
    11271123        return classifier 
    1128          
     1124 
    11291125 
    11301126# ############################################################################################################################################ 
     
    11481144        if list1_dict.has_key(e): int_dict[e] = 1 
    11491145    return int_dict.keys() 
    1150      
     1146 
    11511147# on which side of the line through (x1,y1), (x2,y2) lies the point (xTest, yTest) 
    11521148def getPosition(x1, y1, x2, y2, xTest, yTest): 
     
    12491245        edges = closureDict[key] 
    12501246        vertices = union([i for (i,j) in edges], [j for (i,j) in edges]) 
    1251          
     1247 
    12521248        for vertex in vertices: 
    12531249            correctClass = int(graph.objects[vertex].getclass()) 
     
    12581254 
    12591255            # if the distance to the correct class value is greater than to the incorrect class -> remove the point from the 
    1260             if correct == [] or (len(incorrect) > 0 and min(correct) > min(incorrect)):      
     1256            if correct == [] or (len(incorrect) > 0 and min(correct) > min(incorrect)): 
    12611257                # if closure will degenerate into a line -> remove the remaining vertices 
    12621258                correctClassNeighbors = [] 
     
    12791275                # remove the vertex from the closure 
    12801276                for n in graph.getNeighbours(vertex): 
    1281                     if int(graph.objects[n].getclass()) != correctClass or graph[vertex,n][CLUSTER] == -1: continue  
     1277                    if int(graph.objects[n].getclass()) != correctClass or graph[vertex,n][CLUSTER] == -1: continue 
    12821278                    if newVal == None:  graph[vertex,n] = None 
    12831279                    else:               graph[vertex,n][VALUE] = newVal 
     
    13311327# produce a dictionary with edges, clusters and vertices. clusters are enumerated from 1 up. Each cluster has a different value. 
    13321328# minimumValidValue - edges that have smaller value than this will be ignored and will represent boundary between different clusters 
    1333 def enumerateClusters(graph, minimumValidValue):     
     1329def enumerateClusters(graph, minimumValidValue): 
    13341330    clusterIndex = 1 
    13351331    verticesDict = {} 
     
    13381334    for (i,j) in graph.getEdges(): graph[i,j][CLUSTER] = -1   # initialize class cluster 
    13391335    for i in range(graph.nVertices): clusterDict[i] = -1 
    1340      
     1336 
    13411337    for i in range(graph.nVertices): 
    13421338        if graph.getNeighbours(i) == [] or clusterDict[i] != -1: continue 
     
    13671363            continue 
    13681364 
    1369         # remove edges that are of lenghts average + alphaShapesValue * standard deviation         
     1365        # remove edges that are of lenghts average + alphaShapesValue * standard deviation 
    13701366        lengths = [graph[i,j][DISTANCE] for (i,j) in edges] 
    13711367        ave = sum(lengths) / len(lengths) 
     
    13741370        for index in range(len(lengths)): 
    13751371            if lengths[index] > allowedDistance: graph[edges[index][0], edges[index][1]][VALUE] = removedEdgeValue 
    1376          
     1372 
    13771373 
    13781374# alphashapes removed some edges. if after clustering two poins of the edge still belong to the same cluster, restore the deleted edges 
     
    13871383                if deleteValue == None: graph[i,j] = None 
    13881384                else:                   graph[i,j][VALUE] = deleteValue 
    1389          
     1385 
    13901386 
    13911387# compute the area of the polygons that are not necessarily convex 
     
    13931389def computeAreas(graph, edgesDict, clusterDict, verticesDict, closureDict, outerEdgeValue): 
    13941390    areaDict = {} 
    1395      
     1391 
    13961392    for key in closureDict.keys(): 
    13971393        # first check if the closure is really a closure, by checking if it is connected into a circle 
     
    14091405            continue 
    14101406 
    1411         # then compute its area size         
     1407        # then compute its area size 
    14121408        currArea = 0.0 
    14131409        edges = closureDict[key] # select outer edges 
     
    14761472        if data[p1][0] == xTest and data[p1][1] == yTest: return 1 
    14771473        if data[p2][0] == xTest and data[p2][1] == yTest: return 1 
    1478          
     1474 
    14791475    count = 0 
    14801476    for (p2, p3) in closure: 
     
    14841480            x = (x1 * y2 - x2 * y1) / (y2 - y1) 
    14851481            if x > 0: count += 1 
    1486     return count % 2  
    1487          
     1482    return count % 2 
     1483 
    14881484 
    14891485# compute average distance between points inside each cluster 
     
    16371633    a.setMainWidget(ow) 
    16381634    ow.show() 
    1639     a.exec_loop()         
     1635    a.exec_loop() 
  • orange/OrangeWidgets/OWDlgs.py

    r3700 r3794  
    22from OWBaseWidget import * 
    33import OWGUI, OWGraphTools, OWTools 
    4 try: 
    5    from qwt import QwtPlot 
    6 except: 
    7    from Qwt4 import QwtPlot 
    8  
    9 from qtcanvas import QCanvas 
     4from PyQt4.Qwt5 import * 
    105from ColorPalette import * 
    116 
     
    2621 
    2722        self.space = OWGUI.widgetBox(self) 
    28         self.layout = QVBoxLayout(self, 8) 
    29         self.layout.addWidget(self.space) 
    30  
    31         box = QVButtonGroup("Image Size", self.space) 
     23        self.setLayout(QVBoxLayout(self)) 
     24        self.layout().setMargin(8) 
     25        self.layout().addWidget(self.space) 
     26 
     27        #box = QVButtonGroup(" Image Size ", self.space) 
     28        box = OWGUI.widgetBox(self.space, "Image Size") 
    3229        if isinstance(graph, QwtPlot): 
    3330            size = OWGUI.radioButtonsInBox(box, self, "selectedSize", ["Current size", "400 x 400", "600 x 600", "800 x 800", "Custom:"], callback = self.updateGUI) 
    34  
    35             ind1 = OWGUI.indentedBox(box) 
    36             ind2 = OWGUI.indentedBox(box) 
    37             self.customXEdit = OWGUI.lineEdit(ind1, self, "customX", "Width:", orientation = "horizontal", valueType = int) 
    38             self.customYEdit = OWGUI.lineEdit(ind2, self, "customY", "Height:", orientation = "horizontal", valueType = int) 
    39  
    40             OWGUI.comboBoxWithCaption(self.space, self, "penWidthFactor", label = 'Factor:', box = "Pen width multiplication factor",  tooltip = "Set the pen width factor for all curves in the plot\n(Useful for example when the lines in the plot look to thin)\nDefault: 1", sendSelectedValue = 1, valueType = int, items = range(1,20)) 
    41  
    42         elif isinstance(graph, QCanvas): 
     31            self.customXEdit = OWGUI.lineEdit(OWGUI.indentedBox(box), self, "customX", "Width:", orientation = "horizontal", valueType = int) 
     32            self.customYEdit = OWGUI.lineEdit(OWGUI.indentedBox(box), self, "customY", "Height:", orientation = "horizontal", valueType = int) 
     33            OWGUI.comboBoxWithCaption(self.space, self, "penWidthFactor", label = 'Factor:   ', box = " Pen width multiplication factor ",  tooltip = "Set the pen width factor for all curves in the plot\n(Useful for example when the lines in the plot look to thin)\nDefault: 1", sendSelectedValue = 1, valueType = int, items = range(1,20)) 
     34        elif isinstance(graph, QGraphicsScene): 
    4335            OWGUI.widgetLabel(box, "Image size will be set automatically.") 
    4436 
    45         self.printButton =          OWGUI.button(self.space, self, "Print", callback = self.printPic) 
    46         self.saveImageButton =      OWGUI.button(self.space, self, "Save Image", callback = self.saveImage) 
     37        #self.printButton =     OWGUI.button(self.space, self, "Print", callback = self.printPic) 
     38        self.saveImageButton = OWGUI.button(self.space, self, "Save Image", callback = self.saveImage) 
    4739        self.saveMatplotlibButton = OWGUI.button(self.space, self, "Save Graph As matplotlib Script", callback = self.saveToMatplotlib) 
    4840        for (text, funct) in extraButtons: 
     
    5446        self.updateGUI() 
    5547 
    56  
    5748    def saveImage(self, filename = None, size = None, closeDialog = 1): 
    5849        if not filename: 
     
    7364        else:              buffer = QPixmap(size) 
    7465        painter.begin(buffer) 
    75         painter.fillRect(buffer.rect(), QBrush(Qt.white)) # make background same color as the widget's background 
     66        painter.fillRect(buffer.rect(), QBrush(QColor(Qt.white))) # make background same color as the widget's background 
    7667        self.fillPainter(painter, buffer.rect()) 
    7768        painter.flush() 
     
    118109                        color = tuple([item.color().red()/255., item.color().green()/255., item.color().blue()/255.]) 
    119110                        weight = item.font().bold() and "bold" or "normal" 
    120                         f.write("text(%f, %f, '%s'%s%s, color = %s, name = '%s', weight = '%s')\n" % (item.x(), maxy-item.y(), str(item.text()), vertAlign, horAlign, color, str(item.font().family()), weight)) 
     111                        f.write("text(%f, %f, '%s'%s%s, color = %s, name = '%s', weight = '%s')\n" % (item.x(), maxy-item.y(), str(item.label().text()), vertAlign, horAlign, color, str(item.font().family()), weight)) 
    121112 
    122113                f.write("# disable grid\ngrid(False)\n\n") 
     
    133124 
    134125 
    135     def printPic(self): 
    136         printer = QPrinter() 
    137         size = self.getSize() 
    138  
    139         if printer.setup(): 
    140             painter = QPainter(printer) 
    141             metrics = QPaintDeviceMetrics(printer) 
    142             height = metrics.height() - 2*printer.margins().height() 
    143             width = metrics.width() - 2*printer.margins().width() 
    144  
    145             factor = 1.0 
    146             if isinstance(self.graph, QCanvas): 
    147                 minx,maxx,miny,maxy = self.getQCanvasBoundaries() 
    148                 factor = min(float(width)/(maxx-minx), float(height)/(maxy-miny)) 
    149  
    150             if height == 0: 
    151                 print "Error. Height is zero. Preventing division by zero." 
    152                 return 
    153             pageKvoc = width / float(height) 
    154             sizeKvoc = size.width() / float(size.height()) 
    155             if pageKvoc < sizeKvoc:     rect = QRect(printer.margins().width(), printer.margins().height(), width, height) 
    156             else:                       rect = QRect(printer.margins().width(), printer.margins().height(), width, height) 
    157  
    158             self.fillPainter(painter, rect, factor) 
    159             painter.end() 
    160         self.saveSettings() 
    161         QDialog.accept(self) 
     126#    def printPic(self): 
     127#        printer = QPrinter() 
     128#        size = self.getSize() 
     129# 
     130#        if printer.setup(): 
     131#            painter = QPainter(printer) 
     132#            metrics = QPaintDeviceMetrics(printer) 
     133#            height = metrics.height() - 2*printer.margins().height() 
     134#            width = metrics.width() - 2*printer.margins().width() 
     135# 
     136#            factor = 1.0 
     137#            if isinstance(self.graph, QCanvas): 
     138#                minx,maxx,miny,maxy = self.getQCanvasBoundaries() 
     139#                factor = min(float(width)/(maxx-minx), float(height)/(maxy-miny)) 
     140# 
     141#            if height == 0: 
     142#                print "Error. Height is zero. Preventing division by zero." 
     143#                return 
     144#            pageKvoc = width / float(height) 
     145#            sizeKvoc = size.width() / float(size.height()) 
     146#            if pageKvoc < sizeKvoc:     rect = QRect(printer.margins().width(), printer.margins().height(), width, height) 
     147#            else:                       rect = QRect(printer.margins().width(), printer.margins().height(), width, height) 
     148# 
     149#            self.fillPainter(painter, rect, factor) 
     150#            painter.end() 
     151#        self.saveSettings() 
     152#        QDialog.accept(self) 
    162153 
    163154 
     
    174165                    pen = self.graph.curve(key).pen(); pen.setWidth(pen.width()/self.penWidthFactor); self.graph.curve(key).setPen(pen) 
    175166 
    176         elif isinstance(self.graph, QCanvas): 
     167        elif isinstance(self.graph, QGraphicsScene): 
    177168            # draw background 
    178169            self.graph.drawBackground(painter, rect) 
     
    191182                        painter.setFont(item.font()) 
    192183                        painter.setPen(item.color()) 
    193                         painter.drawText(x,y,w,h,item.textFlags(), item.text()) 
     184                        painter.drawText(x,y,w,h,item.textFlags(), item.label().text()) 
    194185                        #painter.drawText(int(scale*item.x()), int(scale*item.y()), str(item.text())) 
    195186                    else: 
     
    211202    # EXTRA FUNCTIONS ############################################ 
    212203    def getQCanvasBoundaries(self): 
    213         minx,maxx,miny,maxy = 10000000,0,10000000,0 
    214         for item in self.graph.allItems(): 
    215             if not item.visible(): continue 
    216             br = item.boundingRect() 
    217             minx = min(br.left(), minx) 
    218             maxx = max(maxx, br.right()) 
    219             miny = min(br.top(), miny) 
    220             maxy = max(maxy, br.bottom()) 
    221         return minx-10, maxx+10, miny-10, maxy+10 
     204        rect = self.graph.itemsBoundingRect() 
     205        rect = rect.adjusted(-10, -10, 10, 10) 
     206        return rect.left()-10, rect.right()+10, rect.bottom()-10, rect.top()+10 
    222207 
    223208 
    224209    def getFileName(self, defaultName, mask, extension): 
    225         fileName = str(QFileDialog.getSaveFileName(self.lastSaveDirName + defaultName, mask, None, "Save to..", "Save to..")) 
     210        fileName = str(QFileDialog.getSaveFileName(self, "Save to..", self.lastSaveDirName + defaultName, mask)) 
    226211        if not fileName: return None 
    227212        if not os.path.splitext(fileName)[1][1:]: fileName = fileName + extension 
     
    236221 
    237222    def getSize(self): 
    238         if isinstance(self.graph, QCanvas): 
     223        if isinstance(self.graph, QGraphicsScene): 
    239224            minx,maxx,miny,maxy = self.getQCanvasBoundaries() 
    240225            size = QSize(maxx-minx, maxy-miny) 
     
    261246    def __init__(self,parent, caption = "Color Palette", callback = None, modal  = TRUE): 
    262247        OWBaseWidget.__init__(self, None, None, caption, modal = modal) 
    263         self.layout = QVBoxLayout(self, 4) 
     248        self.setLayout(QVBoxLayout(self)) 
     249        self.layout().setMargin(4) 
    264250 
    265251        self.callback = callback 
     
    271257        self.selectedSchemaIndex = 0 
    272258 
    273         self.mainArea = OWGUI.widgetBox(self, box = None) 
    274         self.layout.addWidget(self.mainArea) 
    275         self.mainArea.setSpacing(4) 
     259        self.mainArea = OWGUI.widgetBox(self, spacing = 4) 
     260        self.layout().addWidget(self.mainArea) 
    276261        self.schemaCombo = OWGUI.comboBox(self.mainArea, self, "selectedSchemaIndex", box = "Saved Profiles", callback = self.paletteSelected) 
    277262 
    278263        self.hbox = OWGUI.widgetBox(self, orientation = "horizontal") 
    279         self.layout.addWidget(self.hbox) 
    280  
    281264        self.okButton = OWGUI.button(self.hbox, self, "OK", self.acceptChanges) 
    282265        self.cancelButton = OWGUI.button(self.hbox, self, "Cancel", self.reject) 
     
    309292 
    310293    def createColorButton(self, box, buttonName, buttonCaption, initialColor = Qt.black): 
    311         newbox = QHBox(box) 
    312         self.__dict__["buttonBox"+str(self.counter)] = newbox 
    313         newbox.setSpacing(5) 
    314         self.__dict__[buttonName] = ColorButton(self, newbox) 
    315         self.__dict__["buttonLabel"+str(self.counter)] = OWGUI.widgetLabel(newbox, buttonCaption) 
    316         self.__dict__[buttonName].setColor(initialColor) 
     294        self.__dict__[buttonName] = ColorButton(self, box, buttonCaption) 
     295        self.__dict__[buttonName].setColor(QColor(initialColor)) 
    317296        self.colorButtonNames.append(buttonName) 
    318         self.__dict__["buttonBoxSpacing"+str(self.counter)] = QHBox(newbox) 
    319  
    320         self.__dict__[buttonName].setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed )) 
    321         self.__dict__["buttonLabel"+str(self.counter)].setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed )) 
    322  
    323297        self.counter += 1 
    324298 
    325299 
    326     def createContinuousPalette(self, paletteName, boxCaption, passThroughBlack = 0, initialColor1 = Qt.white, initialColor2 = Qt.black): 
     300    def createContinuousPalette(self, paletteName, boxCaption, passThroughBlack = 0, initialColor1 = QColor(Qt.white), initialColor2 = Qt.black): 
    327301        self.__dict__["buttonBox"+str(self.counter)] = OWGUI.widgetBox(self.mainArea, boxCaption) 
    328302 
    329303        self.__dict__["paletteBox"+str(self.counter)] = OWGUI.widgetBox(self.__dict__["buttonBox"+str(self.counter)], orientation = "horizontal") 
    330         self.__dict__[paletteName+"Left"]  = ColorButton(self, self.__dict__["paletteBox"+str(self.counter)]) 
    331         self.__dict__[paletteName+"Left"].master = self 
     304        self.__dict__[paletteName+"Left"]  = ColorButton(self, self.__dict__["paletteBox"+str(self.counter)], color = QColor(initialColor1)) 
     305        #self.__dict__[paletteName+"Left"].master = self 
    332306        self.__dict__[paletteName+ "View"] = InterpolationView(self.__dict__["paletteBox"+str(self.counter)]) 
    333         self.__dict__[paletteName+"Right"] = ColorButton(self, self.__dict__["paletteBox"+str(self.counter)]) 
    334         self.__dict__[paletteName+"Right"].master = self 
    335  
    336         self.__dict__[paletteName+"Left"].setColor(initialColor1) 
    337         self.__dict__[paletteName+"Right"].setColor(initialColor2) 
    338         self.__dict__["buttonBox"+str(self.counter)].addSpace(6) 
     307        self.__dict__[paletteName+"Right"] = ColorButton(self, self.__dict__["paletteBox"+str(self.counter)], color = QColor(initialColor2)) 
     308        #self.__dict__[paletteName+"Right"].master = self 
    339309 
    340310        self.__dict__[paletteName+"passThroughBlack"] = passThroughBlack 
     
    347317    # ##################################################### 
    348318    def createDiscretePalette(self, boxCaption, colorPalette = OWGraphTools.defaultRGBColors): 
    349         box = OWGUI.widgetBox(self.mainArea, boxCaption) 
    350         hbox = OWGUI.widgetBox(box, orientation = 'horizontal') 
    351  
    352         self.discListbox = QListBox(hbox) 
    353  
     319        hbox = OWGUI.widgetBox(self.mainArea, boxCaption, orientation = 'horizontal') 
     320        self.discListbox = OWGUI.listBox(hbox, self) 
    354321        vbox = OWGUI.widgetBox(hbox, orientation = 'vertical') 
    355         self.buttLoad       = OWGUI.button(vbox, self, "D", callback = self.showPopup, tooltip="Load a predefined set of colors") 
    356         self.buttLoad.setMaximumWidth(20) 
    357         self.buttLoad.setMaximumHeight(20) 
     322        #self.buttLoad       = OWGUI.button(vbox, self, "D", callback = self.showPopup, tooltip="Load a predefined set of colors") 
     323        self.buttLoad       = OWGUI.button(vbox, self, "D", tooltip="Load a predefined set of colors", callback = self.showPopup) 
     324        self.buttLoad.setFixedSize(20, 20) 
    358325        buttonUPAttr   = OWGUI.button(vbox, self, "", callback = self.moveAttrUP, tooltip="Move selected attributes up") 
    359326        buttonDOWNAttr = OWGUI.button(vbox, self, "", callback = self.moveAttrDOWN, tooltip="Move selected attributes down") 
    360         buttonUPAttr.setPixmap(QPixmap(os.path.join(self.widgetDir, r"icons\Dlg_up1.png"))) 
     327        buttonUPAttr.setIcon(QIcon(os.path.join(self.widgetDir, r"icons\Dlg_up1.png"))) 
    361328        buttonUPAttr.setSizePolicy(QSizePolicy(QSizePolicy.Fixed , QSizePolicy.Expanding)) 
    362329        buttonUPAttr.setMaximumWidth(20) 
    363         buttonDOWNAttr.setPixmap(QPixmap(os.path.join(self.widgetDir, r"icons\Dlg_down1.png"))) 
     330        buttonDOWNAttr.setIcon(QIcon(os.path.join(self.widgetDir, r"icons\Dlg_down1.png"))) 
    364331        buttonDOWNAttr.setSizePolicy(QSizePolicy(QSizePolicy.Fixed , QSizePolicy.Expanding)) 
    365332        buttonDOWNAttr.setMaximumWidth(20) 
    366         buttonUPAttr.setMaximumWidth(20) 
    367         self.connect(self.discListbox, SIGNAL("doubleClicked ( QListBoxItem * )"), self.changeDiscreteColor) 
    368  
    369         self.popupMenu = QPopupMenu(self) 
    370         self.popupMenu.insertItem("Load default RGB palette", self.loadRGBPalette) 
    371         self.popupMenu.insertItem("Load Color Brewer palette", self.loadCBPalette) 
     333        self.connect(self.discListbox, SIGNAL("itemDoubleClicked ( QListWidgetItem *)"), self.changeDiscreteColor) 
     334 
     335        self.popupMenu = QMenu(self) 
     336        self.popupMenu.addAction("Load default RGB palette", self.loadRGBPalette) 
     337        self.popupMenu.addAction("Load Color Brewer palette", self.loadCBPalette) 
     338        #self.buttLoad.setMenu(self.popupMenu) 
    372339 
    373340        self.discreteColors = [QColor(r,g,b) for (r,g,b) in colorPalette] 
    374341        for ind in range(len(self.discreteColors)): 
    375             self.discListbox.insertItem(OWTools.ColorPixmap(self.discreteColors[ind], 15), "Color %d" % (ind)) 
     342            self.discListbox.addItem(QListWidgetItem(OWTools.ColorPixmap(self.discreteColors[ind], 14), "Color %d" % (ind))) 
    376343 
    377344    def changeDiscreteColor(self, item): 
    378         ind = self.discListbox.index(item) 
     345        ind = self.discListbox.indexFromItem(item).row() 
    379346        color = QColorDialog.getColor(self.discreteColors[ind], self) 
    380347        if color.isValid(): 
    381             self.discListbox.changeItem(OWTools.ColorPixmap(color, 15), "Color %d" % (ind), ind) 
     348            self.discListBox.item(ind).setIcon(OWTools.ColorPixmap(color, 14)) 
    382349            self.discreteColors[ind] = color 
    383350 
     
    386353        self.discreteColors = [QColor(r,g,b) for (r,g,b) in OWGraphTools.defaultRGBColors] 
    387354        for ind in range(len(self.discreteColors)): 
    388             self.discListbox.insertItem(OWTools.ColorPixmap(self.discreteColors[ind], 15), "Color %d" % (ind)) 
     355            self.discListbox.addItem(QListWidgetItem(OWTools.ColorPixmap(self.discreteColors[ind], 14), "Color %d" % (ind))) 
    389356 
    390357    def loadCBPalette(self): 
     
    392359        self.discreteColors = [QColor(r,g,b) for (r,g,b) in OWGraphTools.ColorBrewerColors] 
    393360        for ind in range(len(self.discreteColors)): 
    394             self.discListbox.insertItem(OWTools.ColorPixmap(self.discreteColors[ind], 15), "Color %d" % (ind)) 
     361            self.discListbox.addItem(QListWidgetItem(OWTools.ColorPixmap(self.discreteColors[ind], 14), "Color %d" % (ind))) 
    395362 
    396363    def showPopup(self): 
    397364        point = self.buttLoad.mapToGlobal(QPoint(0, self.buttLoad.height())) 
    398         self.popupMenu.popup(point, 0) 
     365        self.popupMenu.popup(point) 
    399366 
    400367    # move selected attribute in "Attribute Order" list one place up 
    401368    def moveAttrUP(self): 
    402         for i in range(1, self.discListbox.count()): 
    403             if self.discListbox.isSelected(i): 
    404                 pixI, textI = self.discListbox.pixmap(i-1), self.discListbox.text(i) 
    405                 pixII, textII = self.discListbox.pixmap(i), self.discListbox.text(i-1) 
    406                 self.discListbox.insertItem(pixI, textI, i-1) 
    407                 self.discListbox.insertItem(pixII, textII, i-1) 
    408                 self.discListbox.removeItem(i+1) 
    409                 self.discListbox.removeItem(i+1) 
    410                 self.discListbox.setSelected(i-1, TRUE) 
    411                 self.discreteColors.insert(i-1, self.discreteColors.pop(i)) 
     369        if len(self.discListbox.selectedIndexes()) == 0: return 
     370        ind = self.discListbox.selectedIndexes()[0].row() 
     371        if ind == 0: return 
     372        iconI = self.discListbox.item(ind-1).icon() 
     373        iconII = self.discListbox.item(ind).icon() 
     374        self.discListbox.item(ind-1).setIcon(iconII) 
     375        self.discListbox.item(ind).setIcon(iconI) 
     376        self.discListbox.setCurrentRow(ind-1) 
     377        self.discreteColors.insert(ind-1, self.discreteColors.pop(ind)) 
    412378 
    413379 
    414380    # move selected attribute in "Attribute Order" list one place down 
    415381    def moveAttrDOWN(self): 
    416         count = self.discListbox.count() 
    417         for i in range(count-2,-1,-1): 
    418             if self.discListbox.isSelected(i): 
    419                 pixI, textI = self.discListbox.pixmap(i+1), self.discListbox.text(i) 
    420                 pixII, textII = self.discListbox.pixmap(i), self.discListbox.text(i+1) 
    421                 self.discListbox.insertItem(pixI, textI, i) 
    422                 self.discListbox.insertItem(pixII, textII, i+1) 
    423                 self.discListbox.removeItem(i+2) 
    424                 self.discListbox.removeItem(i+2) 
    425                 self.discListbox.setSelected(i+1, TRUE) 
    426                 self.discreteColors.insert(i+1, self.discreteColors.pop(i)) 
     382        if len(self.discListbox.selectedIndexes()) == 0: return 
     383        ind = self.discListbox.selectedIndexes()[0].row() 
     384        if ind == self.discListbox.count()-1: return 
     385        iconI = self.discListbox.item(ind+1).icon() 
     386        iconII = self.discListbox.item(ind).icon() 
     387        self.discListbox.item(ind+1).setIcon(iconII) 
     388        self.discListbox.item(ind).setIcon(iconI) 
     389        self.discListbox.setCurrentRow(ind+1) 
     390        self.discreteColors.insert(ind+1, self.discreteColors.pop(ind)) 
    427391 
    428392 
     
    461425 
    462426        self.colorSchemas = schemas 
    463         for (name, sch) in schemas: 
    464             self.schemaCombo.insertItem(name) 
    465  
    466         self.schemaCombo.insertItem("Save current palette as...") 
     427        self.schemaCombo.insertItems(0, [s[0] for s in schemas]) 
     428 
     429        self.schemaCombo.addItem("Save current palette as...") 
    467430        self.selectedSchemaIndex = selectedSchemaIndex 
    468431        self.paletteSelected() 
     
    477440            self.__dict__[name+"passThroughBlack"] = chk 
    478441            self.__dict__[name+"passThroughBlackCheckbox"].setChecked(chk) 
    479             palette = self.createPalette(self.rgbToQColor(l), self.rgbToQColor(r), chk) + 5*[Qt.white.rgb()] 
     442            palette = self.createPalette(self.rgbToQColor(l), self.rgbToQColor(r), chk) + 5*[QColor(Qt.white).rgb()] 
    480443            self.__dict__[name+"View"].setPalette1(palette) 
    481444 
     
    484447            self.discListbox.clear() 
    485448            for ind in range(len(self.discreteColors)): 
    486                 self.discListbox.insertItem(OWTools.ColorPixmap(self.discreteColors[ind], 15), "Color %d" % (ind)) 
     449                self.discListbox.addItem(QListWidgetItem(OWTools.ColorPixmap(self.discreteColors[ind], 14), "Color %d" % (ind))) 
    487450 
    488451    def paletteSelected(self): 
     
    493456            message = "Please enter a new name for the current color schema:" 
    494457            ok = FALSE 
    495             while (not ok): 
    496                 s = QInputDialog.getText("New Schema Name", message, QLineEdit.Normal) 
    497                 ok = TRUE 
    498                 if (s[1]==TRUE): 
    499                     newName = str(s[0]) 
    500                     oldNames = [str(self.schemaCombo.text(i)).lower() for i in range(self.schemaCombo.count()-1)] 
     458            while not ok: 
     459                text, ok = QInputDialog.getText(self, "New Schema Name", message) 
     460                if (ok): 
     461                    newName = str(text) 
     462                    oldNames = [str(self.schemaCombo.itemText(i)).lower() for i in range(self.schemaCombo.count()-1)] 
    501463                    if newName.lower() == "default": 
    502464                        ok = FALSE 
     
    506468                        self.colorSchemas.pop(index) 
    507469 
    508                     if (ok): 
     470                    if ok: 
    509471                        self.colorSchemas.insert(0, (newName, self.getCurrentState())) 
    510                         self.schemaCombo.insertItem(newName, 0) 
     472                        self.schemaCombo.insertItem(0, newName) 
    511473                        #self.schemaCombo.setCurrentItem(0) 
    512474                        self.selectedSchemaIndex = 0 
     
    524486        # we could also use QColor(positiveColor(rgb), 0xFFFFFFFF) but there is probably a reason 
    525487        # why this was not used before so I am leaving it as it is 
    526          
     488 
    527489        return QColor(qRed(positiveColor(rgb)), qGreen(positiveColor(rgb)), qBlue(positiveColor(rgb))) # on Mac color cannot be negative number in this case so we convert it manually 
    528490 
     
    567529    a = QApplication(sys.argv) 
    568530 
    569 ##    c = ColorPalette(None, modal = FALSE) 
    570 ##    c.createContinuousPalette("continuousPalette", "Continuous Palette") 
    571 ##    c.createDiscretePalette("Discrete Palette") 
    572 ##    box = c.createBox("otherColors", "Colors") 
    573 ##    c.createColorButton(box, "Canvas", "Canvas") 
    574 ##    box.addSpace(5) 
    575 ##    c.createColorButton(box, "Grid", "Grid") 
    576 ##    box.addSpace(5) 
    577 ##    c.createColorButton(box, "test", "ttest") 
    578 ##    box.addSpace(5) 
    579 ##    box.adjustSize() 
    580 ##    c.setColorSchemas() 
    581 ##    a.setMainWidget(c) 
    582 ##    c.show() 
    583 ##    a.exec_loop() 
    584  
    585     c = OWChooseImageSizeDlg(None) 
     531    c = ColorPalette(None, modal = FALSE) 
     532    c.createContinuousPalette("continuousPalette", "Continuous Palette") 
     533    c.createDiscretePalette("Discrete Palette") 
     534    box = c.createBox("otherColors", "Colors") 
     535    c.createColorButton(box, "Canvas", "Canvas") 
     536    box.addSpace(5) 
     537    c.createColorButton(box, "Grid", "Grid") 
     538    box.addSpace(5) 
     539    c.createColorButton(box, "test", "ttest") 
     540    box.addSpace(5) 
     541    box.adjustSize() 
     542    c.setColorSchemas() 
    586543    a.setMainWidget(c) 
    587544    c.show() 
    588545    a.exec_loop() 
     546    """ 
     547    c = OWChooseImageSizeDlg(None) 
     548    c.show() 
     549    a.exec_loop() 
     550    """ 
  • orange/OrangeWidgets/OWFreeVizOptimization.py

    r3788 r3794  
    4343        self.loadSettings() 
    4444 
    45         self.tabs = QTabWidget(self, 'tabWidget') 
    46         self.controlArea.addWidget(self.tabs) 
    47  
    48         self.MainTab = QVGroupBox(self) 
    49         self.S2NHeuristicTab = QVGroupBox(self) 
    50  
    51         self.tabs.insertTab(self.MainTab, "Main") 
    52         self.tabs.insertTab(self.S2NHeuristicTab, "S2N Heuristic") 
     45        self.tabs = OWGUI.tabWidget(self) 
     46        self.MainTab = OWGUI.createTabPage(self.tabs, "Main") 
     47        self.S2NHeuristicTab = OWGUI.createTabPage(self.tabs, "S2N Heuristic") 
    5348 
    5449        if parentName.lower() != "radviz": 
    55             self.LinearTransformationTab = QVGroupBox(self) 
    56             self.tabs.insertTab(self.LinearTransformationTab, "Dimensionality Reduction") 
     50            self.LinearTransformationTab = OWGUI.createTabPage(self.tabs, "Dimensionality Reduction") 
    5751 
    5852        # ########################### 
     
    7670        OWGUI.button(hbox1, self, "Random", callback = self.randomAnchors) 
    7771        self.manualPositioningButton = OWGUI.button(hbox1, self, "Manual", callback = self.setManualPosition) 
    78         self.manualPositioningButton.setToggleButton(1) 
     72        self.manualPositioningButton.setCheckable(1) 
    7973        OWGUI.comboBox(vbox, self, "restrain", label="Restrain anchors:", orientation = "horizontal", items = ["Unrestrained", "Fixed length", "Fixed angle"], callback = self.setRestraints) 
    8074 
     
    8377        self.cbLaw = OWGUI.comboBox(box2, self, "law", label="Law", labelWidth = 40, orientation="horizontal", items=["Linear", "Square", "Gaussian", "KNN", "Variance"], callback = self.forceLawChanged) 
    8478 
    85         hbox2 = QHBox(box2); OWGUI.separator(hbox2, 20, 0); vbox2 = QVBox(hbox2) 
     79        hbox2 = OWGUI.widgetBox(box2, orientation = "horizontal") 
     80        hbox2.layout().addSpacing(10) 
    8681 
    8782        validSigma = QDoubleValidator(self); validSigma.setBottom(0.01) 
    88         self.spinSigma = OWGUI.lineEdit(vbox2, self, "forceSigma", label = "Kernel width (sigma) ", labelWidth = 110, orientation = "horizontal", valueType = float) 
     83        self.spinSigma = OWGUI.lineEdit(hbox2, self, "forceSigma", label = "Kernel width (sigma) ", labelWidth = 110, orientation = "horizontal", valueType = float) 
    8984        self.spinSigma.setFixedSize(60, self.spinSigma.sizeHint().height()) 
    9085        self.spinSigma.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)) 
    9186 
    92         OWGUI.separator(box2, 20) 
     87        box2.layout().addSpacing(20) 
    9388 
    9489        self.cbforcerel = OWGUI.comboBox(box2, self, "forceRelation", label= "Attractive : Repulsive  ",orientation = "horizontal", items=self.forceRelValues, callback = self.updateForces) 
    9590        self.cbforcebal = OWGUI.checkBox(box2, self, "forceBalancing", "Dynamic force balancing", tooltip="If set, the forces are normalized so that the total sums of the\nrepulsive and attractive are in the above proportion.") 
    9691 
    97         OWGUI.separator(box2, 20) 
     92        box2.layout().addSpacing(20) 
    9893 
    9994        self.cbDisableAttractive = OWGUI.checkBox(box2, self, "disableAttractive", "Disable attractive forces", callback = self.setDisableAttractive) 
     
    134129            plsBox = OWGUI.widgetBox(self.LinearTransformationTab, "Partial Least Squares") 
    135130            OWGUI.button(plsBox, self, "Partial least squares", callback = self.findPLSProjection) 
    136              
    137131 
    138132        # ########################### 
    139133        self.statusBar = QStatusBar(self) 
    140134        self.controlArea.addWidget(self.statusBar) 
    141         self.controlArea.activate() 
     135        #self.controlArea.activate() 
    142136 
    143137        self.resize(310,650) 
     
    159153    # ############################################################## 
    160154    def setManualPosition(self): 
    161         self.parentWidget.graph.manualPositioning = self.manualPositioningButton.isOn() 
     155        self.parentWidget.graph.manualPositioning = self.manualPositioningButton.isChecked() 
    162156 
    163157    def setData(self, data): 
     
    187181 
    188182    def forceLawChanged(self): 
    189         self.spinSigma.setDisabled(self.cbLaw.currentItem() not in [2, 3]) 
     183        self.spinSigma.setDisabled(self.cbLaw.currentIndex() not in [2, 3]) 
    190184 
    191185    def setRestraints(self): 
  • orange/OrangeWidgets/OWGUI.py

    r3788 r3794  
    1 from qt import * 
    2 from qttable import * 
     1from PyQt4.QtCore import * 
     2from PyQt4.QtGui import * 
    33import math 
    4 import OWBaseWidget 
    54import orange 
    6 import sys, traceback 
    7  
     5#import sys, traceback 
    86 
    97YesNo = NoYes = ("No", "Yes") 
     8groupBoxMargin = 6 
    109 
    1110import os.path 
    1211 
    1312enter_icon = None 
     13 
     14def getdeepattr(obj, attr, **argkw): 
     15    try: 
     16        return reduce(lambda o, n: getattr(o, n, None),  attr.split("."), obj) 
     17    except: 
     18        if argkw.has_key("default"): 
     19            return argkw[default] 
     20        else: 
     21            raise AttributeError, "'%s' has no attribute '%s'" % (obj, attr) 
     22 
    1423 
    1524def getEnterIcon(): 
    1625    global enter_icon 
    1726    if not enter_icon: 
    18         enter_icon = QPixmap(os.path.dirname(__file__) + "/icons/Dlg_enter.png") 
     27        enter_icon = QIcon(os.path.dirname(__file__) + "/icons/Dlg_enter.png") 
    1928    return enter_icon 
    2029 
    2130 
    2231# constructs a box (frame) if not none, and returns the right master widget 
    23 def widgetBox(widget, box=None, orientation='vertical', addSpace=False): 
     32def widgetBox(widget, box=None, orientation='vertical', addSpace=False, sizePolicy = None, margin = -1, spacing = -1, flat = 0, addToLayout = 1): 
    2433    if box: 
    25         if orientation == 'horizontal' or not orientation: 
    26             b = QHGroupBox(widget) 
    27         else: 
    28             b = QVGroupBox(widget) 
     34        b = QGroupBox(widget) 
    2935        if type(box) in (str, unicode): # if you pass 1 for box, there will be a box, but no text 
    3036            b.setTitle(" "+box.strip()+" ") 
    31     else: 
    32         if orientation == 'horizontal' or not orientation: 
    33             b = QHBox(widget) 
    34         else: 
    35             b = QVBox(widget) 
     37        if margin == -1: margin = groupBoxMargin 
     38        b.setFlat(flat) 
     39    else: 
     40        b = QWidget(widget) 
     41        if margin == -1: margin = 0 
     42    if addToLayout and widget.layout(): 
     43        widget.layout().addWidget(b) 
     44 
     45    if isinstance(orientation, QLayout): 
     46        b.setLayout(orientation) 
     47    elif orientation == 'horizontal' or not orientation: 
     48        b.setLayout(QHBoxLayout()) 
     49##        b.setSizePolicy(sizePolicy or QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)) 
     50    else: 
     51        b.setLayout(QVBoxLayout()) 
     52##        b.setSizePolicy(sizePolicy or QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)) 
     53    if sizePolicy: 
     54        b.setSizePolicy(sizePolicy) 
     55 
     56    if spacing == -1: spacing = 4 
     57    b.layout().setSpacing(spacing) 
     58    b.layout().setMargin(margin) 
     59 
    3660    if type(addSpace) == int: 
    3761        separator(widget, 0, addSpace) 
     
    5175        if labelWidth: 
    5276            lbl.setFixedSize(labelWidth, lbl.sizeHint().height()) 
     77        if widget.layout(): widget.layout().addWidget(lbl) 
    5378    else: 
    5479        lbl = None 
     
    6186def label(widget, master, label, labelWidth = None): 
    6287    lbl = QLabel("", widget) 
     88    if widget.layout(): widget.layout().addWidget(lbl) 
    6389 
    6490    reprint = CallFront_Label(lbl, label, master) 
    65     for mo in __re_frmt.finditer(label): 
     91    for mo in __re_frmt.finditer(label) and hasattr(master, "controlledAttributes"): 
    6692        master.controlledAttributes[mo.group("value")] = reprint 
    6793    reprint() 
     
    75101class SpinBoxWFocusOut(QSpinBox): 
    76102    def __init__(self, min, max, step, bi): 
    77         QSpinBox.__init__(self, min, max, step, bi) 
     103        QSpinBox.__init__(self, bi) 
     104        self.setRange(min, max) 
     105        self.setSingleStep(step) 
    78106        self.inSetValue = False 
    79107        self.enterButton = None 
     
    137165 
    138166    wa = bi.control = SpinBoxWFocusOut(min, max, step, bi) 
     167    if bi.layout(): bi.layout().addWidget(wa) 
    139168    # must be defined because of the setText below 
    140169    if controlWidth: 
    141170        wa.setFixedWidth(controlWidth) 
    142171    if tooltip: 
    143         QToolTip.add(wa, tooltip) 
     172        wa.setToolTip(tooltip) 
    144173    if value: 
    145         wa.setValue(master.getdeepattr(value)) 
     174        wa.setValue(getdeepattr(master, value)) 
    146175 
    147176    cfront, wa.cback, wa.cfunc = connectControl(wa, master, value, callback, not (callback and callbackOnReturn) and "valueChanged(int)", CallFront_spin(wa)) 
     
    160189 
    161190    if posttext: 
    162         QLabel(posttext, bi) 
     191        widgetLabel(bi, posttext) 
    163192 
    164193    if debuggingEnabled: 
     
    176205 
    177206    wa = b.control = DoubleSpinBox(min, max, step, value, master, b) 
    178     wa.setValue(master.getdeepattr(value)) 
     207    wa.setValue(getdeepattr(master, value)) 
     208    if b.layout(): b.layout().addWidget(wa) 
    179209 
    180210    if controlWidth: 
     
    182212 
    183213    if tooltip: 
    184         QToolTip.add(wa, tooltip) 
     214        wa.setToolTip(tooltip) 
    185215 
    186216    connectControl(wa, master, value, callback, "valueChanged(int)", CallFront_doubleSpin(wa), fvcb=wa.clamp) 
     
    188218 
    189219 
    190 def checkBox(widget, master, value, label, box=None, tooltip=None, callback=None, getwidget=None, id=None, disabled=0, labelWidth=None, disables = [], debuggingEnabled = 1): 
    191     if box or label: 
    192         b = widgetBox(widget, box, orientation=None) 
    193         wa = QCheckBox(label, b) 
    194         wa.box = b 
    195     else: 
    196         wa = QCheckBox(widget) 
    197         wa.box = None 
     220def checkBox(widget, master, value, label, box=None, tooltip=None, callback=None, getwidget=None, id=None, disabled=0, labelWidth=None, disables = [], addToLayout = 1, debuggingEnabled = 1): 
     221    b = widgetBox(widget, box, orientation=None) 
     222    wa = QCheckBox(label, b) 
     223    if addToLayout and b.layout(): b.layout().addWidget(wa) 
    198224 
    199225    if labelWidth: 
    200226        wa.setFixedSize(labelWidth, wa.sizeHint().height()) 
    201  
    202     wa.setChecked(master.getdeepattr(value)) 
     227    wa.setChecked(getdeepattr(master, value)) 
    203228    if disabled: 
    204229        wa.setDisabled(1) 
    205230    if tooltip: 
    206         QToolTip.add(wa, tooltip) 
     231        wa.setToolTip(tooltip) 
    207232 
    208233    cfront, cback, cfunc = connectControl(wa, master, value, None, "toggled(bool)", CallFront_checkBox(wa), 
    209234                                          cfunc = callback and FunctionCallback(master, callback, widget=wa, getwidget=getwidget, id=id)) 
    210  
    211     wa.disables = disables or [] 
     235    wa.disables = disables or [] # need to create a new instance of list (in case someone would want to append...) 
    212236    wa.makeConsistent = Disabler(wa, master, value) 
    213237    master.connect(wa, SIGNAL("toggled(bool)"), wa.makeConsistent) 
    214238    wa.makeConsistent.__call__(value) 
    215  
    216239    if debuggingEnabled: 
    217240        master._guiElements = getattr(master, "_guiElements", []) + [("checkBox", wa, value, callback)] 
    218  
    219241    return wa 
    220242 
    221243 
    222244def enterButton(parent, height, placeholder = True): 
    223         button = QPushButton(parent) 
    224         button.setFixedSize(height, height) 
    225         button.setPixmap(getEnterIcon()) 
    226         if not placeholder: 
    227             return button 
    228  
    229         button.hide() 
    230         holder = QWidget(parent) 
    231         holder.setFixedSize(height, height) 
    232         return button, holder 
     245    button = QPushButton(parent) 
     246    button.setFixedSize(height, height) 
     247    button.setIcon(getEnterIcon()) 
     248    if parent.layout(): parent.layout().addWidget(button) 
     249    if not placeholder: 
     250        return button 
     251 
     252    button.hide() 
     253    holder = QWidget(parent) 
     254    holder.setFixedSize(height, height) 
     255    return button, holder 
    233256 
    234257 
     
    294317        wa.enterButton = None 
    295318 
     319    if b.layout(): b.layout().addWidget(wa) 
    296320    if value: 
    297         wa.setText(unicode(master.getdeepattr(value))) 
     321        wa.setText(unicode(getdeepattr(master, value))) 
    298322 
    299323    if controlWidth: 
     
    301325 
    302326    if tooltip: 
    303         QToolTip.add(wa, tooltip) 
     327        wa.setToolTip(tooltip) 
    304328    if validator: 
    305329        wa.setValidator(validator) 
    306330 
    307     wa.cback = connectControl(wa, master, value, callbackOnType and callback, "textChanged(const QString &)", CallFront_lineEdit(wa), fvcb = value and valueType)[1] 
     331    wa.cback = connectControl(wa, master, value, callback and callbackOnType, "textChanged(const QString &)", CallFront_lineEdit(wa), fvcb = value and valueType)[1] 
    308332 
    309333    wa.box = b 
     
    311335 
    312336 
    313 def button(widget, master, label, callback = None, disabled=0, tooltip=None, debuggingEnabled = 1, width = None, toggleButton = False,value = ""): 
     337def button(widget, master, label, callback = None, disabled=0, tooltip=None, debuggingEnabled = 1, width = None, toggleButton = False, value = "", addToLayout = 1): 
    314338    btn = QPushButton(label, widget) 
     339    if addToLayout and widget.layout(): widget.layout().addWidget(btn) 
     340 
    315341    if width: 
    316342        btn.setFixedWidth(width) 
    317343    btn.setDisabled(disabled) 
    318344    if tooltip: 
    319         QToolTip.add(btn, tooltip) 
    320  
     345        btn.setToolTip(tooltip) 
    321346    if toggleButton: 
    322         btn.setToggleButton(True) 
    323  
    324  
    325     if value: 
    326         cfront, cback, cfunc = connectControl(btn, master, value, None, "toggled(bool)", CallFront_toggleButton(btn), 
    327                                               cfunc = callback and FunctionCallback(master, callback, widget=btn)) 
    328     else: 
    329         if callback: 
    330             master.connect(btn, SIGNAL("clicked()"), callback) 
    331  
     347        btn.setCheckable(True) 
     348 
     349    if callback: 
     350        master.connect(btn, SIGNAL("clicked()"), callback) 
    332351    if debuggingEnabled: 
    333352        master._guiElements = getattr(master, "_guiElements", []) + [("button", btn, callback)] 
     
    337356def separator(widget, width=0, height=8): 
    338357    sep = QWidget(widget) 
     358    if widget.layout(): widget.layout().addWidget(sep) 
    339359    sep.setFixedSize(width, height) 
    340360    return sep 
    341361 
    342362def rubber(widget, orientation="vertical"): 
    343     sep = QWidget(widget) 
    344     sep.setMinimumSize(1, 1) 
    345     if orientation=="horizontal" or not orientation: 
    346         sep.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)) 
    347     else: 
    348         sep.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)) 
    349     return sep 
     363#    sep = QWidget(widget) 
     364#    if widget.layout(): widget.layout().addWidget(sep) 
     365#    sep.setMinimumSize(1, 1) 
     366#    if orientation=="horizontal" or not orientation: 
     367#        sep.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)) 
     368#    else: 
     369#        sep.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)) 
     370#    return sep 
     371    widget.layout().addStretch(100) 
    350372 
    351373def createAttributePixmap(char, color = Qt.black): 
    352     pixmap = QPixmap() 
    353     pixmap.resize(13, 13) 
     374    pixmap = QPixmap(13,13) 
    354375    painter = QPainter() 
    355376    painter.begin(pixmap) 
    356     painter.setPen(color); 
    357     painter.setBrush(color); 
    358     painter.drawRect(0, 0, 13, 13); 
    359     painter.setPen(Qt.white) 
     377    painter.setPen( color ); 
     378    painter.setBrush( color ); 
     379    painter.drawRect( 0, 0, 13, 13 ); 
     380    painter.setPen( QColor(Qt.white)) 
    360381    painter.drawText(3, 11, char) 
    361382    painter.end() 
    362     return pixmap 
     383    return QIcon(pixmap) 
    363384 
    364385 
     
    368389    global attributeIconDict 
    369390    if not attributeIconDict: 
    370         attributeIconDict = {orange.VarTypes.Continuous: createAttributePixmap("C", QColor(202, 0, 32)), 
    371                      orange.VarTypes.Discrete: createAttributePixmap("D", QColor(26, 150, 65)), 
     391        attributeIconDict = {orange.VarTypes.Continuous: createAttributePixmap("C", QColor(202,0,32)), 
     392                     orange.VarTypes.Discrete: createAttributePixmap("D", QColor(26,150,65)), 
    372393                     orange.VarTypes.String: createAttributePixmap("S", Qt.black), 
    373394                     -1: createAttributePixmap("?", QColor(128, 128, 128))} 
    374395    return attributeIconDict 
    375396 
    376  
    377 def listBox(widget, master, value, labels, box = None, tooltip = None, callback = None, selectionMode = QListBox.Single, debuggingEnabled = 1, addSpace = False): 
    378     bg = box and QHButtonGroup(box, widget) or widget 
    379  
    380     lb = QListBox(bg) 
     397class OrangeListBox(QListWidget): 
     398    def sizeHint(self): 
     399        return QSize(150, 100) 
     400 
     401def listBox(widget, master, value = None, labels = None, box = None, tooltip = None, callback = None, selectionMode = QListWidget.SingleSelection, debuggingEnabled = 1): 
     402    bg = box and widgetBox(widget, box, orientation = "horizontal") or widget 
     403    lb = OrangeListBox(bg) 
    381404    lb.setSelectionMode(selectionMode) 
    382  
    383     if addSpace: 
    384         separator(widget) 
    385  
    386     clist = master.getdeepattr(value) 
    387     if type(clist) >= ControlledList: 
    388         clist = ControlledList(clist, lb) 
    389         master.__setattr__(value, clist) 
     405    if bg.layout(): bg.layout().addWidget(lb) 
     406 
     407    if value != None: 
     408        clist = getdeepattr(master, value) 
     409        if type(clist) >= ControlledList: 
     410            clist = ControlledList(clist, lb) 
     411            master.__setattr__(value, clist) 
    390412 
    391413    lb.ogValue = value 
     
    393415    lb.ogMaster = master 
    394416    if tooltip: 
    395         QToolTip.add(lb, tooltip) 
    396  
    397     connectControl(lb, master, value, callback, "selectionChanged()", CallFront_ListBox(lb), ListBoxCallback(lb, master, value)) 
    398     master.controlledAttributes[labels] = CallFront_ListBoxLabels(lb) 
    399     setattr(master, labels, getattr(master, labels)) 
    400     setattr(master, value, getattr(master, value)) 
     417        lb.setToolTip(tooltip) 
     418 
     419    connectControl(lb, master, value, callback, "itemSelectionChanged()", CallFront_ListBox(lb), ListBoxCallback(lb, master)) 
     420    if value != None: 
     421        setattr(master, value, getattr(master, value)) 
     422    if hasattr(master, "controlledAttributes") and labels != None: 
     423        master.controlledAttributes[labels] = CallFront_ListBoxLabels(lb) 
     424    if labels != None: 
     425        setattr(master, labels, getattr(master, labels)) 
    401426    if debuggingEnabled: 
    402427        master._guiElements = getattr(master, "_guiElements", []) + [("listBox", lb, value, callback)] 
     
    407432def radioButtonsInBox(widget, master, value, btnLabels, box=None, tooltips=None, callback=None, debuggingEnabled = 1, addSpace = False, orientation = 'vertical'): 
    408433    if box: 
    409         bb = (orientation == 'horizontal' or not orientation) and QHButtonGroup or QVButtonGroup 
    410         if type(box) in [str, unicode]: 
    411             bg = bb(box, widget) 
    412         else: 
    413             bg = bb(widget) 
     434        bg = widgetBox(widget, box, orientation) 
    414435    else: 
    415436        bg = widget 
     
    418439        separator(widget) 
    419440 
    420     bg.setRadioButtonExclusive(1) 
    421441    bg.buttons = [] 
    422442    for i in range(len(btnLabels)): 
     
    431451def appendRadioButton(bg, master, value, label, tooltip = None, insertInto = None): 
    432452    i = len(bg.buttons) 
     453    dest = insertInto or bg 
    433454    if type(label) in (str, unicode): 
    434         w = QRadioButton(label, insertInto or bg) 
    435     else: 
    436         w = QRadioButton(unicode(i), insertInto or bg) 
    437         w.setPixmap(label) 
    438     if insertInto: 
    439         bg.insert(w) 
    440     w.setOn(master.getdeepattr(value) == i) 
     455        w = QRadioButton(label, dest) 
     456    else: 
     457        w = QRadioButton(unicode(i), dest) 
     458        w.setIcon(QIcon(label)) 
     459    if dest.layout(): dest.layout().addWidget(w) 
     460 
     461    w.setChecked(getdeepattr(master, value) == i) 
    441462    bg.buttons.append(w) 
    442463    if tooltip: 
    443         QToolTip.add(w, tooltip) 
    444  
     464        w.setToolTip(tooltip) 
     465    return w 
    445466 
    446467def radioButton(widget, master, value, label, box = None, tooltip = None, callback = None, debuggingEnabled = 1): 
    447468    if box: 
    448         bg = QHButtonGroup(box, widget) 
     469        bg = widgetBox(widget, box, orientation="horizontal") 
    449470    else: 
    450471        bg = widget 
     
    455476        w = QRadioButton("X") 
    456477        w.setPixmap(label) 
    457     w.setOn(master.getdeepattr(value)) 
     478    if bg.layout(): bg.layout().addWidget(w) 
     479 
     480    w.setChecked(getdeepattr(master, value)) 
    458481    if tooltip: 
    459         QToolTip.add(w, tooltip) 
     482        w.setToolTip(tooltip) 
    460483 
    461484    connectControl(w, master, value, callback, "stateChanged(int)", CallFront_checkBox(w)) 
     
    466489 
    467490def hSlider(widget, master, value, box=None, minValue=0, maxValue=10, step=1, callback=None, labelFormat=" %d", ticks=0, divideFactor = 1.0, debuggingEnabled = 1, vertical = False, createLabel = 1): 
    468     if box: 
    469         sliderBox = QHButtonGroup(box, widget) 
    470     else: 
    471         sliderBox = QHBox(widget) 
     491    sliderBox = widgetBox(widget, box, orientation = "horizontal") 
    472492 
    473493    if vertical: 
    474         sliderOrient = QSlider.Vertical 
    475     else: 
    476         sliderOrient = QSlider.Horizontal 
    477  
    478     slider = QSlider(minValue, maxValue, step, master.getdeepattr(value), sliderOrient, sliderBox) 
     494        sliderOrient = Qt.Vertical 
     495    else: 
     496        sliderOrient = Qt.Horizontal 
     497 
     498    slider = QSlider(sliderOrient, sliderBox) 
     499    slider.setRange(minValue, maxValue) 
     500    slider.setSingleStep(step) 
     501    slider.setTickInterval(step) 
     502    slider.setValue(getdeepattr(master, value)) 
     503 
     504    if sliderBox.layout(): sliderBox.layout().addWidget(slider) 
     505 
    479506    if ticks: 
    480         slider.setTickmarks(QSlider.Below) 
     507        slider.setTickPosition(QSlider.TicksBelow) 
    481508        slider.setTickInterval(ticks) 
    482509 
    483510    if createLabel: 
    484511        label = QLabel(sliderBox) 
     512        if sliderBox.layout(): sliderBox.layout().addWidget(label) 
    485513        label.setText(labelFormat % minValue) 
    486514        width1 = label.sizeHint().width() 
     
    488516        width2 = label.sizeHint().width() 
    489517        label.setFixedSize(max(width1, width2), label.sizeHint().height()) 
    490         txt = labelFormat % (master.getdeepattr(value)/divideFactor) 
     518        txt = labelFormat % (getdeepattr(master, value)/divideFactor) 
    491519        label.setText(txt) 
    492520        label.setLbl = lambda x, l=label, f=labelFormat: l.setText(f % (x/divideFactor)) 
     
    494522 
    495523    connectControl(slider, master, value, callback, "valueChanged(int)", CallFront_hSlider(slider)) 
    496      
     524 
    497525    if debuggingEnabled: 
    498526        master._guiElements = getattr(master, "_guiElements", []) + [("hSlider", slider, value, minValue, maxValue, step, callback)] 
     
    500528 
    501529 
    502 def qwtHSlider(widget, master, value, box=None, label=None, labelWidth=None, minValue=1, maxValue=10, step=0.1, precision=1, callback=None, logarithmic=0, ticks=0, maxWidth=80, tooltip = None, debuggingEnabled = 1): 
    503     try: 
    504         import qwt 
    505     except: 
    506         import Qwt4 as qwt 
    507     init = master.getdeepattr(value) 
     530def qwtHSlider(widget, master, value, box=None, label=None, labelWidth=None, minValue=1, maxValue=10, step=0.1, precision=1, callback=None, logarithmic=0, ticks=0, maxWidth=80, tooltip = None, showValueLabel = 1, debuggingEnabled = 1): 
     531    import PyQt4.Qwt5 as qwt 
     532 
     533    init = getdeepattr(master, value) 
    508534    if box: 
    509         sliderBox = QHButtonGroup(box, widget) 
     535        sliderBox = widgetBox(widget, box, orientation = "horizontal") 
    510536    else: 
    511537        sliderBox = widget 
    512538 
    513     hb = QHBox(sliderBox) 
     539    hb = widgetBox(sliderBox, orientation = "horizontal") 
    514540    if label: 
    515         lbl = QLabel(label, hb) 
    516         if labelWidth: 
    517             lbl.setFixedSize(labelWidth, lbl.sizeHint().height()) 
     541        lbl = widgetLabel(hb, label, labelWidth) 
     542 
    518543    if ticks: 
    519         slider = qwt.QwtSlider(hb, "", Qt.Horizontal, qwt.QwtSlider.Bottom, qwt.QwtSlider.BgSlot) 
    520     else: 
    521         slider = qwt.QwtSlider(hb, "", Qt.Horizontal, qwt.QwtSlider.None, qwt.QwtSlider.BgSlot) 
     544        slider = qwt.QwtSlider(hb, Qt.Horizontal, qwt.QwtSlider.Bottom, qwt.QwtSlider.BgSlot) 
     545    else: 
     546        slider = qwt.QwtSlider(hb, Qt.Horizontal, qwt.QwtSlider.NoScale, qwt.QwtSlider.BgSlot) 
     547    hb.layout().addWidget(slider) 
     548 
    522549    slider.setScale(minValue, maxValue, logarithmic) # the third parameter for logaritmic scale 
    523550    slider.setScaleMaxMinor(10) 
     
    525552    slider.setThumbLength(12) 
    526553    if maxWidth: 
    527         slider.setMaximumSize(maxWidth, 40) 
     554        slider.setMaximumSize(maxWidth,40) 
    528555    if logarithmic: 
    529556        slider.setRange(math.log10(minValue), math.log10(maxValue), step) 
     
    533560        slider.setValue(init) 
    534561    if tooltip: 
    535         QToolTip.add(hb, tooltip) 
     562        hb.setToolTip(tooltip) 
    536563 
    537564##    format = "%s%d.%df" % ("%", precision+3, precision) 
    538565    format = " %s.%df" % ("%", precision) 
    539566 
    540     lbl = QLabel(hb) 
    541     lbl.setText(format % minValue) 
    542     width1 = lbl.sizeHint().width() 
    543     lbl.setText(format % maxValue) 
    544     width2 = lbl.sizeHint().width() 
    545     lbl.setFixedSize(max(width1, width2), lbl.sizeHint().height()) 
    546     lbl.setText(format % init) 
     567    if showValueLabel: 
     568        lbl = widgetLabel(hb, format % minValue) 
     569        width1 = lbl.sizeHint().width() 
     570        lbl.setText(format % maxValue) 
     571        width2 = lbl.sizeHint().width() 
     572        lbl.setFixedSize(max(width1, width2), lbl.sizeHint().height()) 
     573        lbl.setText(format % init) 
    547574 
    548575    if logarithmic: 
    549576        cfront = CallFront_logSlider(slider) 
    550577        cback = ValueCallback(master, value, f=lambda x: 10**x) 
    551         master.connect(slider, SIGNAL("valueChanged(double)"), SetLabelCallback(master, lbl, format=format, f=lambda x: 10**x)) 
     578        if showValueLabel: master.connect(slider, SIGNAL("valueChanged(double)"), SetLabelCallback(master, lbl, format=format, f=lambda x: 10**x)) 
    552579    else: 
    553580        cfront = CallFront_hSlider(slider) 
    554581        cback = ValueCallback(master, value) 
    555         master.connect(slider, SIGNAL("valueChanged(double)"), SetLabelCallback(master, lbl, format=format)) 
     582        if showValueLabel: master.connect(slider, SIGNAL("valueChanged(double)"), SetLabelCallback(master, lbl, format=format)) 
    556583    connectControl(slider, master, value, callback, "valueChanged(double)", cfront, cback) 
    557584    slider.box = hb 
     
    562589 
    563590 
    564  
    565 class SearchLineEdit(QLineEdit): 
    566     def __init__(self, t, searcher): 
    567         QLineEdit.__init__(self, t) 
    568         self.searcher = searcher 
    569          
    570     def keyPressEvent(self, e): 
    571         k = e.key() 
    572         if k == Qt.Key_Down: 
    573             curItem = self.searcher.lb.currentItem() 
    574             if curItem+1 < self.searcher.lb.count(): 
    575                 self.searcher.lb.setCurrentItem(curItem+1) 
    576         elif k == Qt.Key_Up: 
    577             curItem = self.searcher.lb.currentItem() 
    578             if curItem: 
    579                 self.searcher.lb.setCurrentItem(curItem-1) 
    580         elif k == Qt.Key_Escape: 
    581             self.searcher.window.hide() 
    582         else: 
    583             return QLineEdit.keyPressEvent(self, e) 
    584          
    585 class Searcher: 
    586     def __init__(self, control, master): 
    587         self.control = control 
    588         self.master = master 
    589          
    590     def __call__(self): 
    591         self.window = t = QFrame(self.master, "", QStyle.WStyle_Dialog + QStyle.WStyle_Tool + QStyle.WStyle_Customize + QStyle.WStyle_NormalBorder) 
    592         la = QVBoxLayout(t).setAutoAdd(1) 
    593         gs = self.master.mapToGlobal(QPoint(0, 0)) 
    594         gl = self.control.mapToGlobal(QPoint(0, 0)) 
    595         t.move(gl.x()-gs.x(), gl.y()-gs.y()) 
    596         self.allItems = [str(self.control.text(i)) for i in range(self.control.count())] 
    597         le = SearchLineEdit(t, self) 
    598         self.lb = QListBox(t) 
    599         for i in self.allItems: 
    600             self.lb.insertItem(i) 
    601         t.setFixedSize(self.control.width(), 200) 
    602         t.show() 
    603         le.setFocus() 
    604          
    605         self.master.connect(le, SIGNAL("textChanged(const QString &)"), self.textChanged) 
    606         self.master.connect(le, SIGNAL("returnPressed()"), self.returnPressed) 
    607         self.master.connect(self.lb, SIGNAL("clicked(QListBoxItem *)"), self.mouseClicked) 
    608          
    609     def textChanged(self, s): 
    610         s = str(s) 
    611         self.lb.clear() 
    612         for i in self.allItems: 
    613             if s.lower() in i.lower(): 
    614                 self.lb.insertItem(i) 
    615                 
    616     def returnPressed(self):  
    617         if self.lb.count(): 
    618             self.conclude(self.lb.text(max(0, self.lb.currentItem()))) 
    619         else: 
    620             self.window.hide() 
    621         
    622     def mouseClicked(self, item): 
    623         self.conclude(item.text()) 
    624         
    625     def conclude(self, valueQStr): 
    626         value = str(valueQStr) 
    627         index = self.allItems.index(value) 
    628         self.control.setCurrentItem(index) 
    629         if self.control.cback: 
    630             if self.control.sendSelectedValue: 
    631                 self.control.cback(value) 
    632             else: 
    633                 self.control.cback(index) 
    634         if self.control.cfunc: 
    635             self.control.cfunc() 
    636                  
    637         self.window.hide() 
    638  
    639  
    640 def comboBox(widget, master, value, box=None, label=None, labelWidth=None, orientation='vertical', items=None, tooltip=None, callback=None, sendSelectedValue = 0, valueType = unicode, control2attributeDict = {}, emptyString = None, debuggingEnabled = 1, searchAttr = False, addSpace = False): 
    641     horizontalBox = False 
    642     if box or label: 
    643         hb = widgetBox(widget, box, orientation) 
    644         widgetLabel(hb, label, labelWidth) 
    645         horizontalBox = orientation == 'horizontal' or not orientation 
    646     else: 
    647         hb = widget 
    648  
     591def comboBox(widget, master, value, box=None, label=None, labelWidth=None, orientation='vertical', items=None, tooltip=None, callback=None, sendSelectedValue = 0, valueType = unicode, control2attributeDict = {}, emptyString = None, editable = 0, debuggingEnabled = 1): 
     592    hb = widgetBox(widget, box, orientation) 
     593    widgetLabel(hb, label, labelWidth) 
    649594    if tooltip: 
    650         QToolTip.add(hb, tooltip) 
    651  
    652     if searchAttr and not horizontalBox: 
    653         hb2 = widgetBox(hb, "", 0) 
    654     else: 
    655         hb2 = hb 
    656     combo = QComboBox(hb2) 
    657     if searchAttr: 
    658         searchButton = enterButton(hb2, combo.sizeHint().height(), False) 
    659         master.connect(searchButton, SIGNAL("clicked()"), Searcher(combo, master)) 
    660  
     595        hb.setToolTip(tooltip) 
     596    combo = QComboBox(hb) 
     597    combo.setEditable(editable) 
    661598    combo.box = hb 
    662  
    663     if addSpace: 
    664         separator(widget) 
     599    if hb.layout(): hb.layout().addWidget(combo) 
    665600 
    666601    if items: 
    667         for i in items: 
    668             combo.insertItem(unicode(i)) 
    669         if len(items)>0: 
    670                 if sendSelectedValue and master.getdeepattr(value) in items: combo.setCurrentItem(items.index(master.getdeepattr(value))) 
    671                 elif not sendSelectedValue: combo.setCurrentItem(master.getdeepattr(value)) 
     602        combo.insertItems(combo.count(), [unicode(i) for i in items]) 
     603        if len(items)>0 and value != None: 
     604            if sendSelectedValue and getdeepattr(master, value) in items: combo.setCurrentIndex(items.index(getdeepattr(master, value))) 
     605            elif not sendSelectedValue: 
     606                combo.setCurrentIndex(getdeepattr(master, value)) 
    672607        else: 
    673608            combo.setDisabled(True) 
    674609 
    675     combo.sendSelectedValue = sendSelectedValue 
    676     if sendSelectedValue: 
    677         control2attributeDict = dict(control2attributeDict) 
    678         if emptyString: 
    679             control2attributeDict[emptyString] = "" 
    680         combo.cfront, combo.cback, combo.cfunc = connectControl(combo, master, value, callback, "activated( const QString & )", 
    681                        CallFront_comboBox(combo, valueType, control2attributeDict), 
    682                        ValueCallbackCombo(master, value, valueType, control2attributeDict)) 
    683     else: 
    684         combo.cfront, combo.cback, combo.cfunc = connectControl(combo, master, value, callback, "activated(int)", CallFront_comboBox(combo, None, control2attributeDict)) 
    685          
     610    if value != None: 
     611        if sendSelectedValue: 
     612            control2attributeDict = dict(control2attributeDict) 
     613            if emptyString: 
     614                control2attributeDict[emptyString] = "" 
     615            connectControl(combo, master, value, callback, "activated( const QString & )", 
     616                           CallFront_comboBox(combo, valueType, control2attributeDict), 
     617                           ValueCallbackCombo(master, value, valueType, control2attributeDict)) 
     618        else: 
     619            connectControl(combo, master, value, callback, "activated(int)", CallFront_comboBox(combo, None, control2attributeDict)) 
     620 
    686621    if debuggingEnabled: 
    687622        master._guiElements = getattr(master, "_guiElements", []) + [("comboBox", combo, value, sendSelectedValue, valueType, callback)] 
     
    696631 
    697632# creates a widget box with a button in the top right edge, that allows you to hide all the widgets in the box and collapse the box to its minimum height 
    698 class collapsableWidgetBox(QVGroupBox): 
    699     def __init__(self, widget, box = "", master = None, value = "", callback = None): 
    700         QVGroupBox.__init__(self, widget) 
     633class collapsableWidgetBox(QGroupBox): 
     634    def __init__(self, widget, box = "", master = None, value = "", orientation = "vertical", callback = None): 
     635        QGroupBox.__init__(self, widget) 
     636        if orientation == 'vertical': self.setLayout(QVBoxLayout()) 
     637        else:                         self.setLayout(QHBoxLayout()) 
     638 
     639        if widget.layout(): 
     640            widget.layout().addWidget(self) 
    701641        if type(box) in (str, unicode): # if you pass 1 for box, there will be a box, but no text 
    702642            self.setTitle(" " + box.strip() + " ") 
    703643 
    704         self.pixEdgeOffset = 10 
     644        #self.pixEdgeOffset = 10 
     645        self.setCheckable(1) 
    705646 
    706647        self.master = master 
    707648        self.value = value 
    708649        self.callback = callback 
    709         self.xPixCoord = 0 
    710         self.shownPixSize = (0, 0) 
     650        widget.connect(self, SIGNAL("clicked()"), self.toggled) 
     651#        self.xPixCoord = 0 
     652#        self.shownPixSize = (0,0) 
    711653        self.childWidgetVisibility = {} 
    712         self.pixmaps = [] 
    713  
    714         import os 
    715         iconDir = os.path.join(os.path.dirname(__file__), "icons") 
    716         icon1 = os.path.join(iconDir, "arrow_down.png") 
    717         icon2 = os.path.join(iconDir, "arrow_up.png") 
    718  
    719         if os.path.exists(icon1) and os.path.exists(icon2): 
    720             self.pixmaps = [QPixmap(icon1), QPixmap(icon2)] 
    721         else: 
    722             self.setBackgroundColor(Qt.black) 
     654#        self.pixmaps = [] 
     655 
     656#        import os 
     657#        iconDir = os.path.join(os.path.dirname(__file__), "icons") 
     658#        icon1 = os.path.join(iconDir, "arrow_down.png") 
     659#        icon2 = os.path.join(iconDir, "arrow_up.png") 
     660# 
     661#        if os.path.exists(icon1) and os.path.exists(icon2): 
     662#            self.pixmaps = [QPixmap(icon1), QPixmap(icon2)] 
     663#        else: 
     664#            self.setBackgroundColor(Qt.black) 
    723665        #self.updateControls()      # not needed yet, since no widgets are in it 
    724666 
    725  
    726     def mousePressEvent(self, ev): 
    727         QVGroupBox.mousePressEvent(self, ev) 
    728  
    729         # did we click on the pixmap? 
    730         if ev.x() > self.xPixCoord and ev.x() < self.xPixCoord + self.shownPixSize[0] and ev.y() < self.shownPixSize[1]: 
    731             if self.value: 
    732                 self.master.__setattr__(self.value, not self.master.getdeepattr(self.value)) 
    733             self.updateControls() 
    734             self.repaint() 
     667    def toggled(self, val = 0): 
     668        if self.value: 
     669            self.master.__setattr__(self.value, self.isChecked()) 
     670        self.updateControls() 
    735671        if self.callback != None: 
    736672            self.callback() 
     673 
     674#    def mousePressEvent(self, ev): 
     675#        QGroupBox.mousePressEvent(self, ev) 
     676# 
     677#        # did we click on the pixmap? 
     678#        if ev.x() > self.xPixCoord and ev.x() < self.xPixCoord + self.shownPixSize[0] and ev.y() < self.shownPixSize[1]: 
     679#            if self.value: 
     680#                self.master.__setattr__(self.value, not getdeepattr(self.master, self.value)) 
     681#            self.updateControls() 
     682#            #self.repaint() 
     683#        if self.callback != None: 
     684#            self.callback() 
    737685 
    738686    # call when all widgets are added into the widget box to update the correct state (shown or hidden) 
     
    744692 
    745693    def updateControls(self): 
    746         val = self.master.getdeepattr(self.value) 
     694        self.setFlat(not self.isChecked()) 
     695        self.layout().setMargin(self.isChecked()*groupBoxMargin) 
    747696 
    748697        for c in self.children(): 
    749698            if isinstance(c, QLayout): continue 
    750             if val: 
     699            if self.isChecked(): 
    751700                if self.childWidgetVisibility.get(str(c), 1): c.show() 
    752701            else: 
    753702                self.childWidgetVisibility[str(c)] = not c.isHidden()      # before hiding, save its visibility so that we'll know to show it or not later 
    754703                c.hide() 
    755  
    756     def paintEvent(self, ev): 
    757         QVGroupBox.paintEvent(self, ev) 
    758  
    759         if self.pixmaps != []: 
    760             pix = self.pixmaps[self.master.getdeepattr(self.value)] 
    761             painter = QPainter(self) 
    762             painter.drawPixmap(self.width() - pix.width() - self.pixEdgeOffset, 0, pix) 
    763             self.xPixCoord = self.width() - pix.width() - self.pixEdgeOffset 
    764             self.shownPixSize = (pix.width(), pix.height()) 
     704        self.repaint() 
     705 
     706#    def paintEvent(self, ev): 
     707#        QGroupBox.paintEvent(self, ev) 
     708# 
     709#        if self.pixmaps != []: 
     710#            pix = self.pixmaps[getdeepattr(self.master, self.value)] 
     711#            painter = QPainter(self) 
     712#            painter.drawPixmap(self.width() - pix.width() - self.pixEdgeOffset, 0, pix) 
     713#            self.xPixCoord = self.width() - pix.width() - self.pixEdgeOffset 
     714#            self.shownPixSize = (pix.width(), pix.height()) 
    765715 
    766716 
     
    768718# creates an icon that allows you to show/hide the widgets in the widgets list 
    769719class widgetHider(QWidget): 
    770     def __init__(self, widget, master, value, size = (19, 19), widgets = [], tooltip = None): 
     720    def __init__(self, widget, master, value, size = (19,19), widgets = [], tooltip = None): 
    771721        QWidget.__init__(self, widget) 
     722        if widget.layout(): 
     723            widget.layout().addWidget(self) 
    772724        self.value = value 
    773725        self.master = master 
    774726 
    775727        if tooltip: 
    776             QToolTip.add(self, tooltip) 
     728            self.setToolTip(tooltip) 
    777729 
    778730        import os 
     
    784736        if os.path.exists(icon1) and os.path.exists(icon2): 
    785737            self.pixmaps = [QPixmap(icon1), QPixmap(icon2)] 
    786             w = self.pixmaps[0].width(); h = self.pixmaps[0].height()+1 
     738            self.setFixedSize(self.pixmaps[0].size()) 
    787739        else: 
    788740            self.setBackgroundColor(Qt.black) 
    789             w, h = size 
    790         self.setMaximumWidth(w) 
    791         self.setMaximumHeight(h) 
    792         self.setMinimumSize(w, h) 
     741            self.setFixedSize(size[0], size[1]) 
    793742 
    794743        self.disables = widgets or [] # need to create a new instance of list (in case someone would want to append...) 
    795744        self.makeConsistent = Disabler(self, master, value, type = HIDER) 
    796         if self.pixmaps != []: 
    797             # a little compatibility for QT 3.3 (on Mac at least) 
    798             if hasattr(self, "setPaletteBackgroundPixmap"): 
    799                 self.setPaletteBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
    800             else: 
    801                 self.setBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
    802  
    803745        if widgets != []: 
    804746            self.setWidgets(widgets) 
    805747 
    806748    def mousePressEvent(self, ev): 
    807         self.master.__setattr__(self.value, not self.master.getdeepattr(self.value)) 
    808         if self.pixmaps != []: 
    809             # a little compatibility for QT 3.3 (on Mac at least) 
    810             if hasattr(self, "setPaletteBackgroundPixmap"): 
    811                 self.setPaletteBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
    812             else: 
    813                 self.setBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
     749        self.master.__setattr__(self.value, not getdeepattr(self.master, self.value)) 
    814750        self.makeConsistent.__call__() 
    815751 
     
    817753    def setWidgets(self, widgets): 
    818754        self.disables = widgets or [] 
     755        self.makeConsistent.__call__() 
     756 
     757    def paintEvent(self, ev): 
     758        QWidget.paintEvent(self, ev) 
     759 
    819760        if self.pixmaps != []: 
    820             # a little compatibility for QT 3.3 (on Mac at least) 
    821             if hasattr(self, "setPaletteBackgroundPixmap"): 
    822                 self.setPaletteBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
    823             else: 
    824                 self.setBackgroundPixmap(self.pixmaps[self.master.getdeepattr(self.value)]) 
    825         self.makeConsistent.__call__() 
    826  
    827  
     761            pix = self.pixmaps[getdeepattr(self.master, self.value)] 
     762            painter = QPainter(self) 
     763            painter.drawPixmap(0, 0, pix) 
    828764 
    829765 
     
    856792 
    857793    def __setitem__(self, index, item): 
    858         self.listBox.setSelected(list.__getitem__(self, index), 0) 
    859         self.listBox.setSelected(item, 1) 
     794        self.listBox.item(list.__getitem__(self, index)).setSelected(0) 
     795        item.setSelected(1) 
    860796        list.__setitem__(self, index, item) 
    861797 
    862798    def __delitem__(self, index): 
    863         self.listBox.setSelected(__getitem__(self, index), 0) 
     799        self.listBox.item(__getitem__(self, index)).setSelected(0) 
    864800        list.__delitem__(self, index) 
    865801 
    866802    def __setslice__(self, start, end, slice): 
    867803        for i in list.__getslice__(self, start, end): 
    868             self.listBox.setSelected(i, 0) 
     804            self.listBox.item(i).setSelected(0) 
    869805        for i in slice: 
    870             self.listBox.setSelected(i, 1) 
     806            self.listBox.item(i).setSelected(1) 
    871807        list.__setslice__(self, start, end, slice) 
    872808 
     
    874810        if not start and end==len(self): 
    875811            for i in range(self.listBox.count()): 
    876                 self.listBox.setSelected(i, 0) 
     812                self.listBox.item(i).setSelected(0) 
    877813        else: 
    878814            for i in list.__getslice__(self, start, end): 
    879                 self.listBox.setSelected(i, 0) 
     815                self.listBox.item(i).setSelected(0) 
    880816        list.__delslice__(self, start, end) 
    881817 
    882818    def append(self, item): 
    883819        list.append(self, item) 
    884         self.listBox.setSelected(item, 1) 
     820        item.setSelected(1) 
    885821 
    886822    def extend(self, slice): 
    887823        list.extend(self, slice) 
    888824        for i in slice: 
    889             self.listBox.setSelected(i, 1) 
     825            self.listBox.item(i).setSelected(1) 
    890826 
    891827    def insert(self, index, item): 
    892         self.listBox.setSelected(item, 1) 
     828        item.setSelected(1) 
    893829        list.insert(self, index, item) 
    894830 
    895831    def pop(self, index=-1): 
    896         self.listBox.setSelected(list.__getitem__(self, index), 0) 
     832        self.listBox.item(list.__getitem__(self, index)).setSelected(0) 
    897833        list.pop(self, index) 
    898834 
    899835    def remove(self, item): 
    900         self.listBox.setSelected(item, 0) 
     836        item.setSelected(0) 
    901837        list.remove(self, item) 
    902838 
     
    1037973 
    1038974class ListBoxCallback: 
    1039     def __init__(self, control, widget, attribute): 
     975    def __init__(self, control, widget): 
    1040976        self.control = control 
    1041977        self.widget = widget 
    1042978        self.disabled = False 
    1043979 
    1044     def __call__(self): # triggered by selectionChange() 
    1045         if not self.disabled: 
    1046             clist = self.widget.getdeepattr(self.control.ogValue) 
     980    def __call__(self, *args): # triggered by selectionChange() 
     981        if not self.disabled and self.control.ogValue != None: 
     982            clist = getdeepattr(self.widget, self.control.ogValue) 
    1047983            list.__delslice__(clist, 0, len(clist)) 
    1048984            control = self.control 
    1049985            for i in range(control.count()): 
    1050                 if control.isSelected(i): 
     986                if control.item(i).isSelected(): 
    1051987                    list.append(clist, i) 
    1052  
    1053988            self.widget.__setattr__(self.control.ogValue, clist) 
     989 
    1054990 
    1055991 
     
    10931029    def action(self, value): 
    10941030        if value != None: 
    1095             self.control.setChecked(value) 
    1096  
    1097  
    1098 class CallFront_toggleButton(ControlledCallFront): 
    1099     def action(self, value): 
    1100         if value != None: 
    1101             self.control.setOn(value) 
     1031            values = [Qt.Unchecked, Qt.Checked, Qt.PartiallyChecked] 
     1032            self.control.setCheckState(values[value]) 
    11021033 
    11031034 
     
    11131044            if self.valType: 
    11141045                for i in range(self.control.count()): 
    1115                     if self.valType(str(self.control.text(i))) == value: 
    1116                         self.control.setCurrentItem(i) 
     1046                    if self.valType(str(self.control.itemText(i))) == value: 
     1047                        self.control.setCurrentIndex(i) 
    11171048                        return 
    11181049                values = "" 
    11191050                for i in range(self.control.count()): 
    1120                     values += str(self.control.text(i)) + (i < self.control.count()-1 and ", " or ".") 
     1051                    values += str(self.control.itemText(i)) + (i < self.control.count()-1 and ", " or ".") 
    11211052                print "unable to set %s to value '%s'. Possible values are %s" % (self.control, value, values) 
    11221053            else: 
    1123                 self.control.setCurrentItem(value) 
     1054                self.control.setCurrentIndex(value) 
    11241055 
    11251056 
     
    11481079        if value < 0 or value >= len(self.control.buttons): 
    11491080            value = 0 
    1150         self.control.buttons[value].setOn(1) 
     1081        self.control.buttons[value].setChecked(1) 
    11511082 
    11521083 
    11531084class CallFront_ListBox(ControlledCallFront): 
    11541085    def action(self, value): 
    1155         if value != None: 
     1086        if value != None and self.control.ogValue != None: 
    11561087            if not type(value) <= ControlledList: 
    11571088                setattr(self.control.ogMaster, self.control.ogValue, ControlledList(value, self.control)) 
    1158             for i in range(self.control.count()): 
    1159                 self.control.setSelected(i, 0) 
     1089            self.control.clearSelection() 
    11601090            for i in value: 
    1161                 self.control.setSelected(i, 1) 
     1091                self.control.item(i).setSelected(1) 
    11621092 
    11631093 
     
    11701100                if type(i) == tuple: 
    11711101                    if type(i[1]) == int: 
    1172                         self.control.insertItem(icons.get(i[1], icons[-1]), i[0]) 
     1102                        self.control.addItem(QListWidgetItem(icons.get(i[1], icons[-1]), i[0])) 
    11731103                    else: 
    1174                         self.control.insertItem(i[1], i[0]) 
     1104                        self.control.addItem( QListWidgetItem(i[0],i[1]) ) 
    11751105                else: 
    1176                     self.control.insertItem(i) 
     1106                    self.control.addItem(i) 
    11771107 
    11781108 
     
    12141144                disabled = not value[0] 
    12151145            else: 
    1216                 disabled = not self.master.getdeepattr(self.valueName) 
     1146                disabled = not getdeepattr(self.master, self.valueName) 
    12171147        else: 
    12181148            disabled = 1 
     
    12441174# some table related widgets 
    12451175 
    1246 class tableItem(QTableItem): 
    1247     def __init__(self, table, x, y, text, editType=QTableItem.WhenCurrent, background=Qt.white, sortingKey=None, wordWrap=False, pixmap=None): 
     1176class tableItem(QTableWidgetItem): 
     1177    def __init__(self, table, x, y, text, editType = Qt.ItemIsEditable, background=QColor(Qt.white), sortingKey=None, wordWrap=False, pixmap=None): 
    12481178        self.background = background 
    12491179        if pixmap: 
    1250             QTableItem.__init__(self, table, editType, text, pixmap) 
     1180            QTableWidgetItem.__init__(self, QIcon(pixmap), text) 
    12511181        else: 
    1252             QTableItem.__init__(self, table, editType, text) 
     1182            QTableWidgetItem.__init__(self, None, text) 
     1183        self.setFlags(self.flags() + editType) 
    12531184        table.setItem(x, y, self) 
    12541185        self.sortingKey = sortingKey 
     
    12851216# float 
    12861217class DoubleSpinBox(QSpinBox): 
    1287     def __init__(self, min, max, step, value, master, *args): 
     1218    def __init__(self,min,max,step,value,master, *args): 
     1219        QSpinBox.__init__(self) 
     1220        self.validator = QDoubleValidator(self) 
    12881221        self.min=min 
    12891222        self.max=max 
     
    12921225        self.master=master 
    12931226        self.value=value 
    1294         apply(QSpinBox.__init__, (self, 0, self.steps, 1)+args) 
    1295         self.setValidator(QDoubleValidator(self)) 
    1296  
    1297     def mapValueToText(self, i): 
     1227        self.setRange(min, max) 
     1228        self.setSingleStep(self.steps) 
     1229 
     1230    def mapValueToText(self,i): 
    12981231        return str(self.min+i*self.stepSize) 
    12991232 
     
    13051238    def expand(self, val): 
    13061239        return int(math.floor((val-self.min)/self.stepSize)) 
    1307  
    1308  
     1240    def validate(self, text, pos): 
     1241        return self.validator.validate(text, pos) 
     1242 
     1243def tabWidget(widget): 
     1244    w = QTabWidget(widget) 
     1245    if widget.layout(): 
     1246        widget.layout().addWidget(w) 
     1247    return w 
     1248 
     1249def createTabPage(widget, name): 
     1250    w = widgetBox(widget, addToLayout = 0, margin = 1) 
     1251    widget.addTab(w, name) 
     1252    return w 
     1253 
     1254def table(widget, rows = 0, columns = 0, selectionMode = -1, addToLayout = 1): 
     1255    w = QTableWidget(rows, columns, widget) 
     1256    if widget and addToLayout and widget.layout(): 
     1257        widget.layout().addWidget(w) 
     1258    if selectionMode != -1: 
     1259        w.setSelectionMode(selectionMode) 
     1260    return w 
  • orange/OrangeWidgets/OWGraph.py

    r3789 r3794  
    44# the base for all graphs 
    55 
    6 from qt import * 
    76from OWTools import * 
    8 try: 
    9     from qwt import * 
    10 except: 
    11     from Qwt4 import * 
    12 import qtcanvas, orange, math 
     7from PyQt4.Qwt5 import * 
    138from OWGraphTools import *      # color palletes, user defined curves, ... 
    149from OWDlgs import OWChooseImageSizeDlg 
    15 from OWBaseWidget import unisetattr, OWBaseWidget 
     10import orange, math 
     11from OWBaseWidget import unisetattr 
    1612 
    1713NOTHING = 0 
     
    2521    def __init__(self, parent = None, name = "None"): 
    2622        "Constructs the graph" 
    27         QwtPlot.__init__(self, parent, name) 
     23        QwtPlot.__init__(self, parent) 
    2824        self.parentName = name 
    29         self.setWFlags(Qt.WResizeNoErase) #this works like magic.. no flicker during repaint! 
    30  
    31         self.setAutoReplot(FALSE) 
    32         self.setAutoLegend(FALSE) 
    33         self.setAxisAutoScale(QwtPlot.xBottom) 
    34         self.setAxisAutoScale(QwtPlot.xTop) 
    35         self.setAxisAutoScale(QwtPlot.yLeft) 
    36         self.setAxisAutoScale(QwtPlot.yRight) 
    37  
    38         newFont = QFont('Helvetica', 10, QFont.Bold) 
    39         self.setTitleFont(newFont) 
    40         self.setAxisTitleFont(QwtPlot.xBottom, newFont) 
    41         self.setAxisTitleFont(QwtPlot.xTop, newFont) 
    42         self.setAxisTitleFont(QwtPlot.yLeft, newFont) 
    43         self.setAxisTitleFont(QwtPlot.yRight, newFont) 
    44  
    45         newFont = QFont('Helvetica', 9) 
    46         self.setAxisFont(QwtPlot.xBottom, newFont) 
    47         self.setAxisFont(QwtPlot.xTop, newFont) 
    48         self.setAxisFont(QwtPlot.yLeft, newFont) 
    49         self.setAxisFont(QwtPlot.yRight, newFont) 
    50         self.setLegendFont(newFont) 
     25        #self.setWindowFlags(Qt.WResizeNoErase) #this works like magic.. no flicker during repaint! 
     26 
     27        #self.setAxisAutoScale(QwtPlot.xBottom) 
     28        #self.setAxisAutoScale(QwtPlot.xTop) 
     29        #self.setAxisAutoScale(QwtPlot.yLeft) 
     30        #self.setAxisAutoScale(QwtPlot.yRight) 
     31 
     32        self.axisTitleFont = QFont('Helvetica', 10, QFont.Bold) 
     33        text = QwtText("") 
     34        text.setFont(self.axisTitleFont) 
     35        self.setAxisTitle(QwtPlot.xBottom, text) 
     36        self.setAxisTitle(QwtPlot.xTop, text) 
     37        self.setAxisTitle(QwtPlot.yLeft, text) 
     38        self.setAxisTitle(QwtPlot.yRight, text) 
     39 
     40        ticksFont = QFont('Helvetica', 9) 
     41        self.setAxisFont(QwtPlot.xBottom, ticksFont) 
     42        self.setAxisFont(QwtPlot.xTop, ticksFont) 
     43        self.setAxisFont(QwtPlot.yLeft, ticksFont) 
     44        self.setAxisFont(QwtPlot.yRight, ticksFont) 
     45        #self.setLegendFont(ticksFont) 
    5146 
    5247        self.tipLeft = None 
     
    5550 
    5651        self.showAxisScale = 1 
    57         self.showMainTitle = FALSE 
    58         self.mainTitle = "" 
    59         self.showXaxisTitle = FALSE 
    60         self.XaxisTitle = "" 
    61         self.showYLaxisTitle = FALSE 
    62         self.YLaxisTitle = "" 
    63         self.showYRaxisTitle = FALSE 
    64         self.YRaxisTitle = "" 
     52        self.showMainTitle = 0 
     53        self.showXaxisTitle = 0 
     54        self.showYLaxisTitle = 0 
     55        self.showYRaxisTitle = 0 
     56        self.mainTitle = None 
     57        self.XaxisTitle = None 
     58        self.YLaxisTitle = None 
     59        self.YRaxisTitle = None 
    6560 
    6661        self.state = ZOOMING 
    67         self.tooltip = MyQToolTip(self) 
    68         self.zoomKey = None 
     62        self.zoomCurve = None 
    6963        self.tempSelectionCurve = None 
    70         self.selectionCurveKeyList = [] 
    71         self.selectionChangedCallback = None   # callback function to call when we add new selection polygon or rectangle 
    72         self.legendCurveKeys = [] 
    73  
    74         self.enableGridX(FALSE) 
    75         self.enableGridY(FALSE) 
     64        self.selectionCurveList = [] 
     65        self.autoSendSelectionCallback = None   # callback function to call when we add new selection polygon or rectangle 
     66        self.insertLegend(QwtLegend(), QwtPlot.BottomLegend) 
     67 
     68        self.gridCurve = QwtPlotGrid() 
     69        #self.gridCurve.attach(self) 
    7670 
    7771        self.mouseCurrentlyPressed = 0 
     
    8074        self.blankClick = 0 
    8175        self.noneSymbol = QwtSymbol() 
    82         self.noneSymbol.setStyle(QwtSymbol.None) 
     76        self.noneSymbol.setStyle(QwtSymbol.NoSymbol) 
    8377        self.tips = TooltipManager(self) 
    8478        self.statusBar = None 
    8579        self.canvas().setMouseTracking(1) 
    86         self.connect(self, SIGNAL("plotMouseMoved(const QMouseEvent &)"), self.onMouseMoved) 
     80        self.setMouseTracking(1) 
    8781        self.zoomStack = [] 
    8882        self.panPosition = None 
    89         self.connect(self, SIGNAL('plotMousePressed(const QMouseEvent&)'), self.onMousePressed) 
    90         self.connect(self, SIGNAL('plotMouseReleased(const QMouseEvent&)'),self.onMouseReleased) 
    9183        self.optimizedDrawing = 1 
    92         self.pointWidth = 7 
     84        self.pointWidth = 5 
    9385        self.showFilledSymbols = 1 
    9486        self.showLegend = 1 
    9587        self.scaleFactor = 1.0              # used in some visualizations to "stretch" the data - see radviz, polviz 
    96         self.setCanvasColor(QColor(Qt.white.name())) 
     88        self.setCanvasColor(QColor(Qt.white)) 
    9789        self.xpos = 0   # we have to initialize values, since we might get onMouseRelease event before onMousePress 
    9890        self.ypos = 0 
     
    10698        self.contPalette = ColorPaletteGenerator(numberOfColors = -1) 
    10799        self.discPalette = ColorPaletteGenerator() 
    108 ##        self.currentScale = {} 
    109  
    110         if parent: 
    111             if type(parent) > OWBaseWidget: 
    112                 parent._guiElements = getattr(parent, "_guiElements", []) + [("qwtPlot", self)] 
    113             elif type(parent.parent()) >= OWBaseWidget: 
    114                 parent.parent()._guiElements = getattr(parent.parent(), "_guiElements", []) + [("qwtPlot", self)] 
     100        self.currentScale = {} 
     101 
     102        #self.updateLayout() 
    115103 
    116104 
     
    124112    def saveToFile(self, extraButtons = []): 
    125113        sizeDlg = OWChooseImageSizeDlg(self, extraButtons) 
    126         sizeDlg.exec_loop() 
     114        sizeDlg.exec_() 
    127115 
    128116    def saveToFileDirect(self, fileName, size = None): 
     
    130118        sizeDlg.saveImage(fileName, size) 
    131119 
    132 ##    def setAxisScale(self, axis, min, max, step = 0): 
    133 ##        current = self.currentScale.get(axis, None) 
    134 ##        if current and current == (min, max, step): return 
    135 ##        QwtPlot.setAxisScale(self, axis, min, max, step) 
    136 ##        self.currentScale[axis] = (min, max, step) 
    137  
    138     def setLabels(self, labels, axis): 
    139         if not self.showAxisScale: 
    140             self.setAxisScaleDraw(axis, HiddenScaleDraw()) 
    141             self.axisScaleDraw(axis).setTickLength(0, 0, 0) 
    142             self.axisScaleDraw(axis).setOptions(0) 
    143         else: 
    144             self.axisScaleDraw(axis).setTickLength(1, 1, 3) 
    145             self.axisScaleDraw(axis).setOptions(1) 
    146  
    147             if (labels <> None): 
    148                 self.setAxisScaleDraw(axis, DiscreteAxisScaleDraw(labels)) 
    149                 self.setAxisScale(axis, 0, len(labels) - 1, 1) 
    150                 self.setAxisMaxMinor(axis, 0) 
    151                 self.setAxisMaxMajor(axis, len(labels)) 
    152             else: 
    153                 self.setAxisScaleDraw(axis, QwtScaleDraw()) 
    154                 self.setAxisAutoScale(axis) 
    155                 self.setAxisMaxMinor(axis, 10) 
    156                 self.setAxisMaxMajor(axis, 10) 
    157             self.updateToolTips() 
     120    def setAxisScale(self, axis, min, max, step = 0): 
     121        current = self.currentScale.get(axis, None) 
     122        if current and current == (min, max, step): return 
     123        QwtPlot.setAxisScale(self, axis, min, max, step) 
     124        self.currentScale[axis] = (min, max, step) 
     125 
     126    def setTickLength(self, axis, minor, medium, major): 
     127        self.axisScaleDraw(axis).setTickLength(QwtScaleDiv.MinorTick, minor) 
     128        self.axisScaleDraw(axis).setTickLength(QwtScaleDiv.MediumTick, medium) 
     129        self.axisScaleDraw(axis).setTickLength(QwtScaleDiv.MajorTick, major) 
     130 
    158131 
    159132    def setYLlabels(self, labels): 
    160133        "Sets the Y-axis labels on the left." 
    161         self.setLabels(labels, QwtPlot.yLeft) 
     134        self.axisScaleDraw(QwtPlot.yLeft).enableComponent(QwtScaleDraw.Backbone, self.showAxisScale) 
     135        self.axisScaleDraw(QwtPlot.yLeft).enableComponent(QwtScaleDraw.Ticks, self.showAxisScale) 
     136        self.axisScaleDraw(QwtPlot.yLeft).enableComponent(QwtScaleDraw.Labels, self.showAxisScale) 
     137        if not self.showAxisScale: 
     138            return 
     139 
     140        #self.setTickLength(QwtPlot.yLeft, 1, 1, 3) 
     141 
     142        if (labels <> None): 
     143            self.setAxisScaleDraw(QwtPlot.yLeft, DiscreteAxisScaleDraw(labels)) 
     144            self.setAxisScale(QwtPlot.yLeft, 0, len(labels) - 1, 1) 
     145            self.setAxisMaxMinor(QwtPlot.yLeft, 0) 
     146            self.setAxisMaxMajor(QwtPlot.yLeft, len(labels)) 
     147        else: 
     148            self.setAxisScaleDraw(QwtPlot.yLeft, QwtScaleDraw()) 
     149            self.setAxisAutoScale(QwtPlot.yLeft) 
     150            self.setAxisMaxMinor(QwtPlot.yLeft, 10) 
     151            self.setAxisMaxMajor(QwtPlot.yLeft, 10) 
     152        self.updateToolTips() 
    162153 
    163154    def setYRlabels(self, labels): 
    164155        "Sets the Y-axis labels on the right." 
    165         self.setLabels(labels, QwtPlot.yRight) 
     156        self.axisScaleDraw(QwtPlot.yRight).enableComponent(QwtScaleDraw.Backbone, self.showAxisScale) 
     157        self.axisScaleDraw(QwtPlot.yRight).enableComponent(QwtScaleDraw.Ticks, self.showAxisScale) 
     158        self.axisScaleDraw(QwtPlot.yRight).enableComponent(QwtScaleDraw.Labels, self.showAxisScale) 
     159        if not self.showAxisScale: 
     160            return 
     161 
     162        if (labels <> None): 
     163            self.setAxisScaleDraw(QwtPlot.yRight, DiscreteAxisScaleDraw(labels)) 
     164            self.setAxisScale(QwtPlot.yRight, 0, len(labels) - 1, 1) 
     165            self.setAxisMaxMinor(QwtPlot.yRight, 0) 
     166            self.setAxisMaxMajor(QwtPlot.yRight, len(labels)) 
     167        else: 
     168            self.setAxisScaleDraw(QwtPlot.yRight, QwtScaleDraw()) 
     169            self.setAxisAutoScale(QwtPlot.yRight) 
     170            self.setAxisMaxMinor(QwtPlot.yRight, 10) 
     171            self.setAxisMaxMajor(QwtPlot.yRight, 10) 
     172        self.updateToolTips() 
    166173 
    167174    def setXlabels(self, labels): 
    168175        "Sets the x-axis labels if x-axis discrete." 
    169176        "Or leave up to QwtPlot (MaxMajor, MaxMinor) if x-axis continuous." 
    170         self.setLabels(labels, QwtPlot.xBottom) 
     177        self.axisScaleDraw(QwtPlot.xBottom).enableComponent(QwtScaleDraw.Backbone, self.showAxisScale) 
     178        self.axisScaleDraw(QwtPlot.xBottom).enableComponent(QwtScaleDraw.Ticks, self.showAxisScale) 
     179        self.axisScaleDraw(QwtPlot.xBottom).enableComponent(QwtScaleDraw.Labels, self.showAxisScale) 
     180        if not self.showAxisScale: 
     181            return 
     182 
     183        if (labels <> None): 
     184            self.setAxisScaleDraw(QwtPlot.xBottom, DiscreteAxisScaleDraw(labels)) 
     185            self.setAxisScale(QwtPlot.xBottom, 0, len(labels) - 1, 1) 
     186            self.setAxisMaxMinor(QwtPlot.xBottom, 0) 
     187            self.setAxisMaxMajor(QwtPlot.xBottom, len(labels)) 
     188        else: 
     189            self.setAxisScaleDraw(QwtPlot.xBottom, QwtScaleDraw()) 
     190            self.setAxisAutoScale(QwtPlot.xBottom) 
     191            self.setAxisMaxMinor(QwtPlot.xBottom, 10) 
     192            self.setAxisMaxMajor(QwtPlot.xBottom, 10) 
     193        self.updateToolTips() 
    171194 
    172195    def enableXaxis(self, enable): 
     
    204227        self.updateToolTips() 
    205228        self.updateLayout() 
     229        QwtPlot.resizeEvent(self, event) 
    206230 
    207231    def paintEvent(self, qpe): 
    208         """ 
    209         Paints the graph. 
    210         Called whenever repaint is needed by the system 
    211         or user explicitly calls repaint() 
    212         """ 
    213         for key in self.selectionCurveKeyList:     # the selection curves must set new point array 
    214             self.curve(key).pointArrayValid = 0    # at any change in the graphics otherwise the right examples will not be selected 
     232        for curve in self.selectionCurveList:     # the selection curves must set new point array 
     233            curve.pointArrayValid = 0    # at any change in the graphics otherwise the right examples will not be selected 
    215234 
    216235        QwtPlot.paintEvent(self, qpe) #let the ancestor do its job 
    217         self.replot() 
     236        #self.replot() 
    218237 
    219238    def setShowMainTitle(self, b): 
     
    222241            self.setTitle(self.mainTitle) 
    223242        else: 
    224             self.setTitle("") 
    225         self.updateLayout() 
     243            self.setTitle(None) 
     244        #self.updateLayout() 
    226245        self.repaint() 
    227246 
     
    231250            self.setTitle(self.mainTitle) 
    232251        else: 
    233             self.setTitle("") 
    234         self.updateLayout() 
    235         self.repaint() 
    236  
    237     # show or hide axis title. if b = -1 then only update currently set status of the title 
     252            self.setTitle(None) 
     253        #self.updateLayout() 
     254        self.repaint() 
     255 
    238256    def setShowXaxisTitle(self, b = -1): 
    239257        if b == self.showXaxisTitle: return 
    240258        if b != -1: 
    241259            self.showXaxisTitle = b 
    242         if self.showXaxisTitle: 
     260        if (self.showXaxisTitle <> 0): 
    243261            self.setAxisTitle(QwtPlot.xBottom, self.XaxisTitle) 
    244262        else: 
    245             self.setAxisTitle(QwtPlot.xBottom, "") 
    246         self.updateLayout() 
     263            self.setAxisTitle(QwtPlot.xBottom, QwtText()) 
     264        #self.updateLayout() 
    247265        self.repaint() 
    248266 
     
    250268        if title == self.XaxisTitle: return 
    251269        self.XaxisTitle = title 
    252         if self.showXaxisTitle == 0: return 
    253         self.setAxisTitle(QwtPlot.xBottom, self.XaxisTitle) 
    254         self.updateLayout() 
    255         self.repaint() 
    256  
    257     # show or hide axis title. if b = -1 then only update currently set status of the title 
     270        if (self.showXaxisTitle <> 0): 
     271            self.setAxisTitle(QwtPlot.xBottom, self.XaxisTitle) 
     272        else: 
     273            self.setAxisTitle(QwtPlot.xBottom, QwtText()) 
     274        #self.updateLayout() 
     275        self.repaint() 
     276 
    258277    def setShowYLaxisTitle(self, b = -1): 
    259278        if b == self.showYLaxisTitle: return 
    260279        if b != -1: 
    261280            self.showYLaxisTitle = b 
    262         if self.showYLaxisTitle: 
     281        if (self.showYLaxisTitle <> 0): 
    263282            self.setAxisTitle(QwtPlot.yLeft, self.YLaxisTitle) 
    264283        else: 
    265             self.setAxisTitle(QwtPlot.yLeft, "") 
    266         self.updateLayout() 
     284            self.setAxisTitle(QwtPlot.yLeft, QwtText()) 
     285        #self.updateLayout() 
    267286        self.repaint() 
    268287 
     
    270289        if title == self.YLaxisTitle: return 
    271290        self.YLaxisTitle = title 
    272         if self.showYLaxisTitle == 0: return 
    273         self.setAxisTitle(QwtPlot.yLeft, self.YLaxisTitle) 
    274         self.updateLayout() 
    275         self.repaint() 
    276  
    277     # show or hide axis title. if b = -1 then only update currently set status of the title 
     291        if (self.showYLaxisTitle <> 0): 
     292            self.setAxisTitle(QwtPlot.yLeft, self.YLaxisTitle) 
     293        else: 
     294            self.setAxisTitle(QwtPlot.yLeft, QwtText()) 
     295        #self.updateLayout() 
     296        self.repaint() 
     297 
    278298    def setShowYRaxisTitle(self, b = -1): 
    279299        if b == self.showYRaxisTitle: return 
    280300        if b != -1: 
    281301            self.showYRaxisTitle = b 
    282         if self.showYRaxisTitle: 
     302        if (self.showYRaxisTitle <> 0): 
    283303            self.setAxisTitle(QwtPlot.yRight, self.YRaxisTitle) 
    284304        else: 
    285             self.setAxisTitle(QwtPlot.yRight, "") 
    286         self.updateLayout() 
     305            self.setAxisTitle(QwtPlot.yRight, QwtText()) 
     306        #self.updateLayout() 
    287307        self.repaint() 
    288308 
     
    290310        if title == self.YRaxisTitle: return 
    291311        self.YRaxisTitle = title 
    292         if self.showYRaxisTitle == 0: return 
    293         self.setAxisTitle(QwtPlot.yRight, self.YRaxisTitle) 
    294         self.updateLayout() 
     312        if (self.showYRaxisTitle <> 0): 
     313            self.setAxisTitle(QwtPlot.yRight, self.YRaxisTitle) 
     314        else: 
     315            self.setAxisTitle(QwtPlot.yRight, QwtText()) 
     316        #self.updateLayout() 
    295317        self.repaint() 
    296318 
    297319    def enableGridXB(self, b): 
    298         self.setGridXAxis(QwtPlot.xBottom) 
    299         self.enableGridX(b) 
    300         self.repaint() 
    301  
    302     def enableGridXT(self, b): 
    303         self.setGridXAxis(QwtPlot.xTop) 
    304         self.enableGridX(b) 
    305         self.repaint() 
    306  
    307     def enableGridYR(self, b): 
    308         self.setGridYAxis(QwtPlot.yRight) 
    309         self.enableGridY(b) 
    310         self.repaint() 
     320        self.gridCurve.enableX(b) 
     321        self.replot() 
    311322 
    312323    def enableGridYL(self, b): 
    313         self.setGridYAxis(QwtPlot.yLeft) 
    314         self.enableGridY(b) 
    315         self.repaint() 
    316  
    317     def enableGraphLegend(self, b): 
    318         self.enableLegend(b) 
    319         self.setAutoLegend(b) 
    320         self.repaint() 
     324        self.gridCurve.enableY(b) 
     325        self.replot() 
    321326 
    322327    def setGridColor(self, c): 
    323         self.setGridPen(QPen(c)) 
    324         self.repaint() 
     328        self.gridCurve.setPen(QPen(c)) 
     329        self.replot() 
    325330 
    326331    def setCanvasColor(self, c): 
     
    333338    def setData(self, data): 
    334339        # clear all curves, markers, tips 
     340        self.clear() 
    335341        self.removeAllSelections(0)  # clear all selections 
    336         self.removeCurves() 
    337         self.legendCurveKeys = [] 
    338         if hasattr(self, "oldLegendKeys"): 
    339             self.oldLegendKeys = {} 
    340         self.removeMarkers() 
    341342        self.tips.removeAll() 
    342343        self.zoomStack = [] 
    343  
    344344 
    345345    # #################################################################### 
     
    353353            else:                          text += "&nbsp;"*4 + "%s = %s<br>" % (data.domain[index].name, str(example[index])) 
    354354 
     355 
    355356        if data.domain.classVar: 
     357            text = text[:-4] 
    356358            text += "<hr><b>Class:</b><br>" 
    357359            if example.getclass().isSpecial(): text += "&nbsp;"*4 + "%s = ?<br>" % (data.domain.classVar.name) 
     
    359361 
    360362        if len(self.rawdata.domain.getmetas()) != 0: 
     363            text = text[:-4] 
    361364            text += "<hr><b>Meta attributes:</b><br>" 
    362365            # show values of meta attributes 
     
    367370        return text[:-4]        # remove the last <br> 
    368371 
    369     def addCurve(self, name, brushColor, penColor, size, style = QwtCurve.NoCurve, symbol = QwtSymbol.Ellipse, enableLegend = 0, xData = [], yData = [], showFilledSymbols = None, lineWidth = 1, pen = None): 
    370         newCurveKey = self.insertCurve(name) 
     372    def addCurve(self, name, brushColor = Qt.black, penColor = Qt.black, size = 5, style = QwtPlotCurve.NoCurve, symbol = QwtSymbol.Ellipse, enableLegend = 0, xData = [], yData = [], showFilledSymbols = None, lineWidth = 1, pen = None, autoScale = 0, antiAlias = 1): 
     373        curve = QwtPlotCurve(name) 
     374        if antiAlias: 
     375            curve.setRenderHint(QwtPlotItem.RenderAntialiased) 
     376        curve.setItemAttribute(QwtPlotItem.Legend, enableLegend) 
     377        curve.setItemAttribute(QwtPlotItem.AutoScale, enableLegend) 
     378 
    371379        if showFilledSymbols or (showFilledSymbols == None and self.showFilledSymbols): 
    372380            newSymbol = QwtSymbol(symbol, QBrush(brushColor), QPen(penColor), QSize(size, size)) 
    373381        else: 
    374382            newSymbol = QwtSymbol(symbol, QBrush(), QPen(penColor), QSize(size, size)) 
    375         self.setCurveSymbol(newCurveKey, newSymbol) 
    376         self.setCurveStyle(newCurveKey, style) 
     383        curve.setSymbol(newSymbol) 
     384        curve.setStyle(style) 
    377385        if not pen: 
    378             self.setCurvePen(newCurveKey, QPen(penColor, lineWidth)) 
    379         else: 
    380             self.setCurvePen(newCurveKey, pen) 
    381         self.enableLegend(enableLegend, newCurveKey) 
     386            curve.setPen(QPen(penColor, lineWidth)) 
     387        else: 
     388            curve.setPen(pen) 
    382389        if xData != [] and yData != []: 
    383             self.setCurveData(newCurveKey, xData, yData) 
    384  
    385         return newCurveKey 
    386  
    387     def addMarker(self, name, x, y, alignment = -1, bold = 0, color = None, size=None): 
    388         mkey = self.insertMarker(name) 
    389         self.marker(mkey).setXValue(x) 
    390         self.marker(mkey).setYValue(y) 
    391         if alignment != -1: 
    392             self.marker(mkey).setLabelAlignment(alignment) 
    393         if bold or size: 
    394             font = self.marker(mkey).font() 
    395             if bold: 
    396                 font.setBold(1) 
    397             if size: 
    398                 font.setPixelSize(size) 
    399             self.marker(mkey).setFont(font) 
    400 ##        if color: 
    401 ##            self.marker(mkey).setLabelColor(color) 
    402         return mkey 
     390            curve.setData(xData, yData) 
     391        curve.attach(self) 
     392        return curve 
     393 
     394    def addMarker(self, name, x, y, alignment = -1, bold = 0, color = None, brushColor = None, size=None): 
     395        text = QwtText(name, QwtText.PlainText) 
     396        if color != None: 
     397            text.setColor(color) 
     398            text.setPaintAttribute(QwtText.PaintUsingTextColor, 1) 
     399        if brushColor != None: 
     400            text.setBackgroundBrush(QBrush(brushColor)) 
     401        font = text.font() 
     402        if bold:  font.setBold(1) 
     403        if size:  font.setPixelSize(size) 
     404        text.setFont(font) 
     405        text.setPaintAttribute(QwtText.PaintUsingTextFont, 1) 
     406        if alignment != -1:  text.setRenderFlags(alignment) 
     407 
     408        marker = QwtPlotMarker() 
     409        marker.setLabel(text) 
     410        marker.setValue(x,y) 
     411        #if alignment != -1: 
     412        #    marker.setLabelAlignment(alignment) 
     413        marker.attach(self) 
     414        return marker 
    403415 
    404416    # show a tooltip at x,y with text. if the mouse will move for more than 2 pixels it will be removed 
    405417    def showTip(self, x, y, text): 
    406         MyQToolTip.tip(self.tooltip, QRect(x+self.canvas().frameGeometry().x()-3, y+self.canvas().frameGeometry().y()-3, 6, 6), text) 
     418        QToolTip.showText(self.mapToGlobal(QPoint(x, y)), text, self.canvas(), QRect(x-3,y-3,6,6)) 
    407419 
    408420    # mouse was only pressed and released on the same spot. visualization methods might want to process this event 
     
    425437        self.state = PANNING 
    426438        if self.tempSelectionCurve: self.removeLastSelection() 
    427          
     439 
    428440    def activateSelection(self): 
    429441        self.state = SELECT 
    430442 
     443 
    431444    def removeDrawingCurves(self, removeLegendItems = 1): 
    432         for key in self.curveKeys(): 
    433             if isinstance(self.curve(key), SelectionCurve): 
     445        for curve in self.itemList(): 
     446            if not removeLegendItems and curve.testItemAttribute(QwtPlotItem.Legend): 
    434447                continue 
    435             if removeLegendItems == 0 and key in self.legendCurveKeys: 
    436                 continue 
    437             self.removeCurve(key) 
     448            if not isinstance(curve, SelectionCurve) and not isinstance(curve, QwtPlotMarker): 
     449                curve.detach() 
     450        self.gridCurve.attach(self)        # we also removed the grid curve 
     451 
     452    def removeMarkers(self): 
     453        self.detachItems(QwtPlotItem.Rtti_PlotMarker) 
    438454 
    439455    def removeLastSelection(self): 
    440         if self.selectionCurveKeyList != []: 
    441             lastCurve = self.selectionCurveKeyList.pop() 
    442             self.removeCurve(lastCurve) 
     456        removed = 0 
     457        if self.selectionCurveList != []: 
     458            lastCurve = self.selectionCurveList.pop() 
     459            lastCurve.detach() 
    443460            self.tempSelectionCurve = None 
    444             self.replot() 
    445             if self.selectionChangedCallback: 
    446                 self.selectionChangedCallback() # do we want to send new selection 
    447             return 1 
    448         else: 
    449             return 0 
     461            removed = 1 
     462        self.replot() 
     463        if self.autoSendSelectionCallback: 
     464            self.autoSendSelectionCallback() # do we want to send new selection 
     465        return removed 
    450466 
    451467    def removeAllSelections(self, send = 1): 
    452         for key in self.selectionCurveKeyList: 
    453             self.removeCurve(key) 
    454         self.selectionCurveKeyList = [] 
     468        self.detachItems(SelectionCurveRtti) 
     469        self.selectionCurveList = [] 
    455470        self.replot() 
    456         if send and self.selectionChangedCallback: 
    457             self.selectionChangedCallback() 
     471        if send and self.autoSendSelectionCallback: 
     472            self.autoSendSelectionCallback() # do we want to send new selection 
    458473 
    459474    def zoomOut(self): 
    460475        if len(self.zoomStack): 
    461             newXMin, newXMax, newYMin, newYMax = self.zoomStack.pop() 
    462             self.setNewZoom(self.axisScale(QwtPlot.xBottom).lBound(), self.axisScale(QwtPlot.xBottom).hBound(), self.axisScale(QwtPlot.yLeft).lBound(), self.axisScale(QwtPlot.yLeft).hBound(), newXMin, newXMax, newYMin, newYMax) 
     476            (xmin, xmax, ymin, ymax) = self.zoomStack.pop() 
     477            self.setAxisScale(QwtPlot.xBottom, xmin, xmax) 
     478            self.setAxisScale(QwtPlot.yLeft, ymin, ymax) 
     479            self.replot() 
    463480            return 1 
    464481        return 0 
    465482 
    466     def setNewZoom(self, oldXMin, oldXMax, oldYMin, oldYMax, newXMin, newXMax, newYMin, newYMax): 
    467         #zoomOutCurveKey = self.insertCurve(RectangleCurve(self, brush = None, xData = [oldXMin, oldXMax, oldXMax, oldXMin], yData = [oldYMin, oldYMin, oldYMax, oldYMax])) 
    468         if len(self.curveKeys()) > 2000:    # if too many curves then don't be smooth 
    469             steps = 1 
    470         else: 
    471             steps = 10 
    472         for i in range(1, steps+1): 
    473             midXMin = oldXMin * (steps-i)/float(steps) + newXMin * i/float(steps) 
    474             midXMax = oldXMax * (steps-i)/float(steps) + newXMax * i/float(steps) 
    475             midYMin = oldYMin * (steps-i)/float(steps) + newYMin * i/float(steps) 
    476             midYMax = oldYMax * (steps-i)/float(steps) + newYMax * i/float(steps) 
    477             self.setAxisScale(QwtPlot.yLeft, midYMax, midYMin) 
    478             self.setAxisScale(QwtPlot.xBottom, midXMin, midXMax) 
    479  
    480             #if i == steps: 
    481             #    self.removeCurve(zoomOutCurveKey) 
    482             self.replot() 
     483    def closestMarker(self, intX, intY): 
     484        point = QPoint(intX, intY) 
     485        marker = None 
     486        dist = 1000000000 
     487        for curve in self.itemList(): 
     488            if isinstance(curve, QwtPlotMarker): 
     489                curvePoint = QPoint(self.transform(QwtPlot.xBottom, curve.xValue()), self.transform(QwtPlot.yLeft, curve.yValue())) 
     490                d = (point - curvePoint).manhattanLength() 
     491                if d < dist: 
     492                    dist = d 
     493                    marker = curve 
     494        return marker, dist 
     495 
     496 
     497    def closestCurve(self, intX, intY): 
     498        point = QPoint(intX, intY) 
     499        nearestCurve = None 
     500        dist = 10000000000 
     501        index = -1 
     502        for curve in self.itemList(): 
     503            if isinstance(curve, QwtPlotCurve) and curve.dataSize() > 0: 
     504                ind, d = curve.closestPoint(point) 
     505                if d < dist: 
     506                    nearestCurve, dist, index = curve, d, ind 
     507        if nearestCurve == None: 
     508            return None, 0, 0, 0, 0 
     509        else: 
     510            return nearestCurve, dist, nearestCurve.x(index), nearestCurve.y(index), index 
    483511 
    484512 
     
    486514    # HANDLING MOUSE EVENTS 
    487515    # ############################################### 
    488     def onMousePressed(self, e): 
     516    def mousePressEvent(self, e): 
     517        QwtPlot.mousePressEvent(self, e) 
    489518        self.mouseCurrentlyPressed = 1 
    490519        self.mouseCurrentButton = e.button() 
    491         self.xpos = e.x() 
    492         self.ypos = e.y() 
    493  
    494          
    495         xs = self.axisScale(QwtPlot.xBottom) 
     520        canvasPos = self.canvas().mapFrom(self, e.pos()) 
     521        self.xpos = canvasPos.x() 
     522        self.ypos = canvasPos.y() 
     523 
     524        xs = self.axisScaleDiv(QwtPlot.xBottom) 
    496525        x = self.invTransform(QwtPlot.xBottom, e.x()) 
    497526        print "omp", xs.lBound(), xs.hBound(), x 
     
    500529        # ZOOM 
    501530        if e.button() == Qt.LeftButton and self.state == ZOOMING: 
    502             self.tempSelectionCurve = SelectionCurve(self, pen = Qt.DashLine) 
    503             self.zoomKey = self.insertCurve(self.tempSelectionCurve) 
     531            self.tempSelectionCurve = SelectionCurve(pen = Qt.DashLine) 
     532            self.tempSelectionCurve.attach(self) 
     533            self.zoomCurve = self.tempSelectionCurve 
    504534 
    505535        # #### 
    506536        # PANNING 
    507         if e.button() == Qt.LeftButton and self.state == PANNING: 
     537        elif e.button() == Qt.LeftButton and self.state == PANNING: 
    508538            self.panPosition = e.globalX(), e.globalY() 
    509             self.paniniX = self.axisScale(QwtPlot.xBottom).lBound(), self.axisScale(QwtPlot.xBottom).hBound() 
    510             self.paniniY = self.axisScale(QwtPlot.yLeft).lBound(), self.axisScale(QwtPlot.yLeft).hBound() 
     539            self.paniniX = self.axisScaleDiv(QwtPlot.xBottom).lBound(), self.axisScaleDiv(QwtPlot.xBottom).hBound() 
     540            self.paniniY = self.axisScaleDiv(QwtPlot.yLeft).lBound(), self.axisScaleDiv(QwtPlot.yLeft).hBound() 
    511541 
    512542        # #### 
    513543        # SELECT RECTANGLE 
    514544        elif e.button() == Qt.LeftButton and self.state == SELECT_RECTANGLE: 
    515             self.tempSelectionCurve = SelectionCurve(self) 
    516             key = self.insertCurve(self.tempSelectionCurve) 
    517             self.selectionCurveKeyList.append(key) 
     545            self.tempSelectionCurve = SelectionCurve() 
     546            self.tempSelectionCurve.attach(self) 
     547            self.selectionCurveList.append(self.tempSelectionCurve) 
    518548 
    519549        # #### 
     
    521551        elif e.button() == Qt.LeftButton and self.state == SELECT_POLYGON: 
    522552            if self.tempSelectionCurve == None: 
    523                 self.tempSelectionCurve = SelectionCurve(self) 
    524                 key = self.insertCurve(self.tempSelectionCurve) 
    525                 self.selectionCurveKeyList.append(key) 
    526                 self.tempSelectionCurve.addPoint(self.invTransform(QwtPlot.xBottom, self.xpos), self.invTransform(QwtPlot.yLeft, self.ypos)) 
     553                self.tempSelectionCurve = SelectionCurve() 
     554                self.tempSelectionCurve.attach(self) 
     555                self.selectionCurveList.append(self.tempSelectionCurve) 
    527556            self.tempSelectionCurve.addPoint(self.invTransform(QwtPlot.xBottom, self.xpos), self.invTransform(QwtPlot.yLeft, self.ypos)) 
    528557 
     
    530559                self.tempSelectionCurve = None 
    531560                self.replot() 
    532                 if self.selectionChangedCallback: 
    533                     self.selectionChangedCallback() # do we want to send new selection 
    534  
    535         # fake a mouse move to show the cursor position 
    536         self.onMouseMoved(e) 
    537         self.event(e) 
     561                if self.autoSendSelectionCallback: self.autoSendSelectionCallback() # do we want to send new selection 
     562 
    538563 
    539564    # only needed to show the message in statusbar 
    540     def onMouseMoved(self, e): 
    541         xFloat = self.invTransform(QwtPlot.xBottom, e.x()) 
    542         yFloat = self.invTransform(QwtPlot.yLeft, e.y()) 
     565    def mouseMoveEvent(self, e): 
     566        QwtPlot.mouseMoveEvent(self, e) 
     567        canvasPos = self.canvas().mapFrom(self, e.pos()) 
     568        xFloat = self.invTransform(QwtPlot.xBottom, canvasPos.x()) 
     569        yFloat = self.invTransform(QwtPlot.yLeft, canvasPos.y()) 
    543570 
    544571        text = "" 
     
    548575 
    549576        if self.statusBar != None: 
    550             self.statusBar.message(text) 
     577            self.statusBar.showMessage(text) 
    551578        if text != "": 
    552579            self.showTip(self.transform(QwtPlot.xBottom, x), self.transform(QwtPlot.yLeft, y), text) 
     
    560587        elif self.state == SELECT_POLYGON and self.tempSelectionCurve != None: 
    561588            self.tempSelectionCurve.replaceLastPoint(xFloat,yFloat) 
    562             self.repaint() 
     589            self.replot() 
    563590 
    564591        elif self.state == PANNING and self.panPosition: 
    565592            dx = self.invTransform(QwtPlot.xBottom, e.globalX()) - self.invTransform(QwtPlot.xBottom, self.panPosition[0]) 
    566593            dy = self.invTransform(QwtPlot.yLeft, e.globalY()) - self.invTransform(QwtPlot.yLeft, self.panPosition[1]) 
    567             self.setAxisScale(QwtPlot.xBottom, self.paniniX[0] - dx, self.paniniX[1] - dx) 
    568             self.setAxisScale(QwtPlot.yLeft, self.paniniY[0] - dy, self.paniniY[1] - dy) 
     594            self.setaxisScaleDiv(QwtPlot.xBottom, self.paniniX[0] - dx, self.paniniX[1] - dx) 
     595            self.setaxisScaleDiv(QwtPlot.yLeft, self.paniniY[0] - dy, self.paniniY[1] - dy) 
    569596            self.replot() 
    570              
    571         self.event(e) 
    572  
    573  
    574     def onMouseReleased(self, e): 
     597 
     598 
     599    def mouseReleaseEvent(self, e): 
     600        QwtPlot.mouseReleaseEvent(self, e) 
    575601        if not self.mouseCurrentlyPressed: return   # this might happen if we double clicked the widget titlebar 
    576602        self.mouseCurrentlyPressed = 0 
    577603        self.mouseCurrentButton = 0 
     604        self.panPosition = None 
    578605        staticClick = 0 
    579         self.panPosition = None 
     606        canvasPos = self.canvas().mapFrom(self, e.pos()) 
    580607 
    581608        if e.button() != Qt.RightButton: 
    582             if self.xpos == e.x() and self.ypos == e.y(): 
     609            if self.xpos == canvasPos.x() and self.ypos == canvasPos.y(): 
    583610                self.staticMouseClick(e) 
    584611                staticClick = 1 
     
    586613        if e.button() == Qt.LeftButton: 
    587614            if self.state == ZOOMING: 
    588                 xmin = min(self.xpos, e.x());  xmax = max(self.xpos, e.x()) 
    589                 ymin = min(self.ypos, e.y());  ymax = max(self.ypos, e.y()) 
    590  
    591                 if self.zoomKey: self.removeCurve(self.zoomKey) 
    592                 self.zoomKey = None 
     615                xmin = min(self.xpos, canvasPos.x());  xmax = max(self.xpos, canvasPos.x()) 
     616                ymin = min(self.ypos, canvasPos.y());  ymax = max(self.ypos, canvasPos.y()) 
     617 
     618                if self.zoomCurve: self.zoomCurve.detach() 
     619                self.zoomCurve = None 
    593620                self.tempSelectionCurve = None 
    594621 
    595                 if staticClick or (xmax-xmin)+(ymax-ymin) < 4: 
    596                     return 
     622                if staticClick or (xmax-xmin)+(ymax-ymin) < 4: return 
    597623 
    598624                xmin = self.invTransform(QwtPlot.xBottom, xmin);  xmax = self.invTransform(QwtPlot.xBottom, xmax) 
     
    600626 
    601627                self.blankClick = 0 
    602                 self.zoomStack.append((self.axisScale(QwtPlot.xBottom).lBound(), self.axisScale(QwtPlot.xBottom).hBound(), self.axisScale(QwtPlot.yLeft).lBound(), self.axisScale(QwtPlot.yLeft).hBound())) 
    603                 self.setNewZoom(self.axisScale(QwtPlot.xBottom).lBound(), self.axisScale(QwtPlot.xBottom).hBound(), self.axisScale(QwtPlot.yLeft).lBound(), self.axisScale(QwtPlot.yLeft).hBound(), xmin, xmax, ymax, ymin) 
     628                self.zoomStack.append((self.axisScaleDiv(QwtPlot.xBottom).lBound(), self.axisScaleDiv(QwtPlot.xBottom).hBound(), self.axisScaleDiv(QwtPlot.yLeft).lBound(), self.axisScaleDiv(QwtPlot.yLeft).hBound())) 
     629                self.setAxisScale(QwtPlot.xBottom, xmin, xmax) 
     630                self.setAxisScale(QwtPlot.yLeft, ymax, ymin) 
     631                self.replot() 
    604632 
    605633            elif self.state == SELECT_RECTANGLE: 
    606634                if self.tempSelectionCurve: 
    607635                    self.tempSelectionCurve = None 
    608                 if self.selectionChangedCallback: 
    609                     self.selectionChangedCallback() # do we want to send new selection 
     636                if self.autoSendSelectionCallback: self.autoSendSelectionCallback() # do we want to send new selection 
    610637 
    611638        elif e.button() == Qt.RightButton: 
     
    628655                        self.removeLastSelection() 
    629656                    else:   # set new last point 
    630                         self.tempSelectionCurve.replaceLastPoint(self.invTransform(QwtPlot.xBottom, e.x()), self.invTransform(QwtPlot.yLeft, e.y())) 
     657                        self.tempSelectionCurve.replaceLastPoint(self.invTransform(QwtPlot.xBottom, canvasPos.x()), self.invTransform(QwtPlot.yLeft, canvasPos.y())) 
    631658                    self.replot() 
    632659                else: 
    633660                    ok = self.removeLastSelection() 
    634661                    if not ok: self.zoomOut() 
    635  
    636662        #self.replot() 
    637         self.event(e) 
    638  
    639              
     663 
    640664    def wheelEvent(self, e): 
    641665        if not self.enableWheelZoom: 
    642666            return 
    643          
     667 
    644668        d = -e.delta()/120. 
    645669 
     
    648672            yoff = d * (ys.hBound() - ys.lBound()) / 100. 
    649673            self.setAxisScale(QwtPlot.yLeft, ys.lBound() + yoff, ys.hBound() + yoff) 
    650          
     674 
    651675        elif getattr(self, "altPressed", False): 
    652676            xs = self.axisScale(QwtPlot.xBottom) 
    653677            xoff = d * (xs.hBound() - xs.lBound()) / 100. 
    654678            self.setAxisScale(QwtPlot.xBottom, xs.lBound() - xoff, xs.hBound() - xoff) 
    655          
     679 
    656680        else: 
    657681            ro, rn = .9**d, 1-.9**d 
    658              
     682 
    659683            pos = self.mapFromGlobal(e.pos()) 
    660684            ex, ey = pos.x(), pos.y() 
    661      
    662             xs = self.axisScale(QwtPlot.xBottom) 
     685 
     686            xs = self.axisScaleDiv(QwtPlot.xBottom) 
    663687            x = self.invTransform(QwtPlot.xBottom, ex) 
    664     #        print xs.lBound(), xs.hBound(), x 
    665688            self.setAxisScale(QwtPlot.xBottom, ro*xs.lBound() + rn*x, ro*xs.hBound() + rn*x) 
    666              
    667             ys = self.axisScale(QwtPlot.yLeft) 
     689 
     690            ys = self.axisScaleDiv(QwtPlot.yLeft) 
    668691            y = self.invTransform(QwtPlot.yLeft, ey) 
    669692            self.setAxisScale(QwtPlot.yLeft, ro*ys.lBound() + rn*y, ro*ys.hBound() + rn*y) 
    670          
     693 
    671694        self.replot() 
    672695 
    673          
     696 
    674697    # does a point (x,y) lie inside one of the selection rectangles (polygons) 
    675698    def isPointSelected(self, x,y): 
    676         for curveKey in self.selectionCurveKeyList: 
    677             if self.curve(curveKey).isInside(x,y): return 1 
     699        for curve in self.selectionCurveList: 
     700            if curve.isInside(x,y): return 1 
    678701        return 0 
    679702 
     
    682705        import numpy 
    683706        total = numpy.zeros(len(xData)) 
    684         for curveKey in self.selectionCurveKeyList: 
    685             total += self.curve(curveKey).getSelectedPoints(xData, yData, validData) 
     707        for curve in self.selectionCurveList: 
     708            total += curve.getSelectedPoints(xData, yData, validData) 
    686709        unselected = numpy.equal(total, 0) 
    687710        selected = 1 - unselected 
    688711        return selected.tolist(), unselected.tolist() 
    689712 
    690     # set selections 
    691     def setSelections(self, selections): 
    692         for (xs, ys) in selections: 
    693             curve = SelectionCurve(self) 
    694             curve.setData(xs, ys) 
    695             key = self.insertCurve(curve) 
    696             self.selectionCurveKeyList.append(key) 
    697  
    698     # get current selections in the form [([xs1, ys1]), (xs2, ys2)] 
    699     def getSelections(self): 
    700         data = [] 
    701         for key in self.selectionCurveKeyList: 
    702             curve = self.curve(key) 
    703             data.append(([curve.x(i) for i in range(curve.dataSize())], [curve.y(i) for i in range(curve.dataSize())])) 
    704         return data 
    705  
    706     def randomChange(self): 
    707         import random 
    708         if random.randint(0,1) and self.selectionCurveKeyList != []: 
    709             self.removeLastSelection() 
    710         else: 
    711             curve = SelectionCurve(self) 
    712             key = self.insertCurve(curve) 
    713             self.selectionCurveKeyList.append(key) 
    714  
    715             xMin = self.axisScale(QwtPlot.xBottom).lBound(); xMax = self.axisScale(QwtPlot.xBottom).hBound() 
    716             yMin = self.axisScale(QwtPlot.yLeft).lBound();   yMax = self.axisScale(QwtPlot.yLeft).hBound() 
    717             x1 = xMin + random.random()* (xMax-xMin); x2 = xMin + random.random()* (xMax-xMin) 
    718             y1 = yMin + random.random()* (yMax-yMin); y2 = yMin + random.random()* (yMax-yMin) 
    719  
    720             curve.setData([x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1]) 
    721  
    722  
    723713    # save graph in matplotlib python file 
    724714    def saveToMatplotlib(self, fileName, size = QSize(400,400)): 
    725715        f = open(fileName, "wt") 
    726716 
    727         x1 = self.axisScale(QwtPlot.xBottom).lBound(); x2 = self.axisScale(QwtPlot.xBottom).hBound() 
    728         y1 = self.axisScale(QwtPlot.yLeft).lBound();   y2 = self.axisScale(QwtPlot.yLeft).hBound() 
     717        x1 = self.axisScaleDiv(QwtPlot.xBottom).lBound(); x2 = self.axisScaleDiv(QwtPlot.xBottom).hBound() 
     718        y1 = self.axisScaleDiv(QwtPlot.yLeft).lBound();   y2 = self.axisScaleDiv(QwtPlot.yLeft).hBound() 
    729719 
    730720        if self.showAxisScale == 0: edgeOffset = 0.01 
     
    733723        f.write("from pylab import *\nfrom matplotlib import font_manager\n\n#possible changes in how the plot looks\n#rcParams['xtick.major.size'] = 0\n#rcParams['ytick.major.size'] = 0\n\n#constants\nx1 = %f; x2 = %f\ny1 = %f; y2 = %f\ndpi = 80\nxsize = %d\nysize = %d\nedgeOffset = %f\n\nfigure(facecolor = 'w', figsize = (xsize/float(dpi), ysize/float(dpi)), dpi = dpi)\nhold(True)\n" % (x1,x2,y1,y2,size.width(), size.height(), edgeOffset)) 
    734724 
    735         linestyles = ['None', "-", "-.", "--", ":", "-", "-"]      # qwt line styles: NoCurve, Lines, Sticks, Steps, Dots, Spline, UserCurve 
     725        linestyles = ["o", "-", "-.", "--", ":", "-", "-"]      # qwt line styles: NoCurve, Lines, Sticks, Steps, Dots, Spline, UserCurve 
    736726        markers = ["None", "o", "s", "^", "d", "v", "^", "<", ">", "x", "+"]    # curveSymbols = [None, Ellipse, Rect, Triangle, Diamond, DTriangle, UTriangle, LTriangle, RTriangle, XCross, Cross] 
    737727 
    738728        f.write("#add curves\n") 
    739         for key in self.curveKeys(): 
    740             c = self.curve(key) 
     729        for c in self.itemList(): 
     730            if not isinstance(c, QwtPlotCurve): continue 
    741731            xData = [c.x(i) for i in range(c.dataSize())] 
    742732            yData = [c.y(i) for i in range(c.dataSize())] 
     
    749739            colorB = self._getColorFromObject(c.brush()) 
    750740            linewidth = c.pen().width() 
    751             if isinstance(c, PolygonCurve): 
     741            if c.__class__ == PolygonCurve and len(xData) == 4: 
    752742                x0 = min(xData); x1 = max(xData); diffX = x1-x0 
    753743                y0 = min(yData); y1 = max(yData); diffY = y1-y0 
    754744                f.write("gca().add_patch(Rectangle((%f, %f), %f, %f, edgecolor=%s, facecolor = %s, linewidth = %d, fill = 1))\n" % (x0,y0,diffX, diffY, color, colorB, linewidth)) 
    755             elif isinstance(c, RectangleCurve):        # rectangle curve can contain multiple rects, each has 5 points (the last one is the same as the first) 
    756                 for i in range(len(xData))[::5]: 
    757                     x0 = min(xData[i:i+5]); x1 = max(xData[i:i+5]); diffX = x1-x0 
    758                     y0 = min(yData[i:i+5]); y1 = max(yData[i:i+5]); diffY = y1-y0 
    759                     f.write("gca().add_patch(Rectangle((%f, %f), %f, %f, edgecolor=%s, facecolor = %s, linewidth = %d, fill = 1))\n" % (x0,y0,diffX, diffY, color, colorB, linewidth)) 
    760             elif c.__class__ == UnconnectedLinesCurve: 
    761                 for i in range(len(xData))[::2]:        # multiple unconnected lines 
    762                     f.write("plot(%s, %s, marker = 'None', linestyle = '-', color = %s, linewidth = %d)\n" % (xData[i:i+2], yData[i:i+2], color, linewidth)) 
    763745            elif c.style() < len(linestyles): 
    764746                linestyle = linestyles[c.style()] 
     
    766748 
    767749        f.write("\n# add markers\n") 
    768         for key in self.markerKeys(): 
    769             marker = self.marker(key) 
     750        for marker in self.itemList(): 
     751            if not isinstance(marker, QwtPlotMarker): continue 
    770752            x = marker.xValue() 
    771753            y = marker.yValue() 
     
    802784        f.write("\n# possible settings to change\n#axes().set_frame_on(0) #hide the frame\n#axis('off') #hide the axes and labels on them\n\n") 
    803785 
     786 
    804787        if self.legend().itemCount() > 0: 
    805788            legendItems = [] 
    806789            for item in self.legend().contentsWidget().children(): 
    807                 if isinstance(item, QwtLegendButton): 
    808                     text = str(item.title()).replace("<b>", "").replace("</b>", "") 
    809                     if not item.symbol(): 
    810                         legendItems.append((text, None, None, None)) 
    811                     else: 
    812                         legendItems.append((text, markers[item.symbol().style()], self._getColorFromObject(item.symbol().pen()) , self._getColorFromObject(item.symbol().brush()))) 
     790                if type(item) != QwtLegendButton: continue 
     791                text = str(item.title()).replace("<b>", "").replace("</b>", "") 
     792                if not item.symbol(): 
     793                    legendItems.append((text, None, None, None)) 
     794                else: 
     795                    legendItems.append((text, markers[item.symbol().style()], self._getColorFromObject(item.symbol().pen()) , self._getColorFromObject(item.symbol().brush()))) 
    813796            f.write(""" 
    814797#functions to show legend below the figure 
     
    843826        col = tuple([v/float(255) for v in col]) 
    844827        return col 
    845  
    846 class MyQToolTip(QToolTip): 
    847     def __init__(self, parent): 
    848         QToolTip.__init__(self, parent) 
    849         self.rect = None 
    850         self.text = None 
    851  
    852     def setRect(self, rect, text): 
    853         self.rect = rect 
    854         self.text = text 
    855  
    856     def maybeTip(self, p): 
    857         if self.rect and self.text: 
    858             if self.rect.contains(p): 
    859                 self.tip(self.rect, self.text) 
    860828 
    861829 
  • orange/OrangeWidgets/OWGraphTools.py

    r3723 r3794  
    1 from qt import * 
    2 try: 
    3     from qwt import * 
    4 except: 
    5     from Qwt4 import * 
     1from PyQt4.QtCore import * 
     2from PyQt4.QtGui import * 
     3from PyQt4.Qwt5 import * 
    64 
    75#from Numeric import * 
     
    2018#ColorBrewer color set - bad when there are small points but great when you have to color areas 
    2119ColorBrewerColors = [(0, 140, 255), (228, 26, 28), (77, 175, 74), (255, 127, 0), (255, 255, 51), (152, 78, 163), (166, 86, 40), (247, 129, 191), (153, 153, 153)] 
     20 
     21SelectionCurveRtti = QwtPlotCurve.Rtti_PlotUserItem + 123 
     22LegendCurveRtti = QwtPlotCurve.Rtti_PlotUserItem + 124 
    2223 
    2324class ColorPaletteGenerator: 
     
    129130        list.insert(len(list), (val, ind)) 
    130131 
     132 
     133#A dynamic tool tip class 
     134class TooltipManager: 
     135    # Creates a new dynamic tool tip. 
     136    def __init__(self, qwtplot): 
     137        self.qwtplot = qwtplot 
     138        self.positions=[] 
     139        self.texts=[] 
     140 
     141    # Adds a tool tip. If a tooltip with the same name already exists, it updates it instead of adding a new one. 
     142    def addToolTip(self,x, y,text, customX = 0, customY = 0): 
     143        self.positions.append((x,y, customX, customY)) 
     144        self.texts.append(text) 
     145 
     146    #Decides whether to pop up a tool tip and which text to pop up 
     147    def maybeTip(self, x, y): 
     148        if len(self.positions) == 0: return ("", -1, -1) 
     149        dists = [abs(x-position[0]) + abs(y-position[1]) for position in self.positions] 
     150        nearestIndex = dists.index(min(dists)) 
     151 
     152        intX = abs(self.qwtplot.transform(self.qwtplot.xBottom, x) - self.qwtplot.transform(self.qwtplot.xBottom, self.positions[nearestIndex][0])) 
     153        intY = abs(self.qwtplot.transform(self.qwtplot.yLeft, y) - self.qwtplot.transform(self.qwtplot.yLeft, self.positions[nearestIndex][1])) 
     154        if self.positions[nearestIndex][2] == 0 and self.positions[nearestIndex][3] == 0:   # if we specified no custom range then assume 6 pixels 
     155            if intX + intY < 6:  return (self.texts[nearestIndex], self.positions[nearestIndex][0], self.positions[nearestIndex][1]) 
     156            else:                return ("", None, None) 
     157        else: 
     158            if abs(self.positions[nearestIndex][0] - x) <= self.positions[nearestIndex][2] and abs(self.positions[nearestIndex][1] - y) <= self.positions[nearestIndex][3]: 
     159                return (self.texts[nearestIndex], x, y) 
     160            else: 
     161                return ("", None, None) 
     162 
     163    def removeAll(self): 
     164        self.positions = [] 
     165        self.texts = [] 
     166 
     167 
    131168# #################################################################### 
    132169# used in widgets that enable to draw a rectangle or a polygon to select a subset of data points 
    133170class SelectionCurve(QwtPlotCurve): 
    134     def __init__(self, parent, name = "", pen = Qt.SolidLine ): 
    135         QwtPlotCurve.__init__(self, parent, name) 
     171    def __init__(self, name = "", pen = Qt.SolidLine ): 
     172        QwtPlotCurve.__init__(self, name) 
    136173        self.pointArrayValid = 0 
    137         self.setStyle(QwtCurve.Lines) 
     174        self.setStyle(QwtPlotCurve.Lines) 
    138175        self.setPen(QPen(QColor(128,128,128), 1, pen)) 
     176        self.setItemAttribute(QwtPlotItem.Legend, 0) 
     177 
     178    def rtti(self): 
     179        return SelectionCurveRtti 
    139180 
    140181    def addPoint(self, xPoint, yPoint): 
     
    260301# the second two points as the second line, etc. 
    261302class UnconnectedLinesCurve(QwtPlotCurve): 
    262     def __init__(self, parent, pen = QPen(Qt.black), xData = None, yData = None): 
    263         QwtPlotCurve.__init__(self, parent) 
     303    def __init__(self, name, pen = QPen(Qt.black), xData = None, yData = None): 
     304        QwtPlotCurve.__init__(self, name) 
    264305        if pen.width() == 0: 
    265306            pen.setWidth(1) 
    266307        self.setPen(pen) 
    267308        self.Pen = pen 
    268         self.setStyle(QwtCurve.Lines) 
     309        self.setStyle(QwtPlotCurve.Lines) 
     310        self.setItemAttribute(QwtPlotItem.Legend, 0) 
    269311        if xData != None and yData != None: 
    270312            self.setData(xData, yData) 
     
    279321 
    280322class RectangleCurve(QwtPlotCurve): 
    281     def __init__(self, parent, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None): 
    282         QwtPlotCurve.__init__(self, parent) 
     323    def __init__(self, name, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None): 
     324        QwtPlotCurve.__init__(self, name) 
    283325        if pen: 
    284326            self.setPen(pen) 
     
    287329        self.Pen = pen 
    288330        self.Brush = brush 
    289         self.setStyle(QwtCurve.Lines) 
     331        self.setStyle(QwtPlotCurve.Lines) 
     332        self.setItemAttribute(QwtPlotItem.Legend, 0) 
    290333        if xData != None and yData != None: 
    291334            self.setData(xData, yData) 
     335 
    292336 
    293337    # To show a rectangle, we have to create a closed polygon. 
     
    311355# brush and pen can also be set by calls to setPen and setBrush functions 
    312356class PolygonCurve(QwtPlotCurve): 
    313     def __init__(self, parent, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None): 
    314         QwtPlotCurve.__init__(self, parent) 
     357    def __init__(self, name, pen = QPen(Qt.black), brush = QBrush(Qt.white), xData = None, yData = None): 
     358        QwtPlotCurve.__init__(self, name) 
    315359        if pen: 
    316360            self.setPen(pen) 
     
    319363        self.Pen = pen 
    320364        self.Brush = brush 
    321         self.setStyle(QwtCurve.Lines) 
     365        self.setStyle(QwtPlotCurve.Lines) 
     366        self.setItemAttribute(QwtPlotItem.Legend, 0) 
    322367        if xData != None and yData != None: 
    323368            self.setData(xData, yData) 
     
    345390# 
    346391class errorBarQwtPlotCurve(QwtPlotCurve): 
    347     def __init__(self, parent = None, text = None, connectPoints = 0, tickXw = 0.1, tickYw = 0.1, showVerticalErrorBar = 1, showHorizontalErrorBar = 0): 
    348         QwtPlotCurve.__init__(self, parent, text) 
     392    def __init__(self, text = "", connectPoints = 0, tickXw = 0.1, tickYw = 0.1, showVerticalErrorBar = 1, showHorizontalErrorBar = 0): 
     393        QwtPlotCurve.__init__(self, text) 
    349394        self.connectPoints = connectPoints 
    350395        self.tickXw = tickXw 
     
    352397        self.showVerticalErrorBar = showVerticalErrorBar 
    353398        self.showHorizontalErrorBar = showHorizontalErrorBar 
     399        self.setItemAttribute(QwtPlotItem.Legend, 0) 
    354400 
    355401    def draw(self, p, xMap, yMap, f, t): 
     
    359405        self.setPen( self.symbol().pen() ) 
    360406        p.setPen( self.symbol().pen() ) 
    361         if self.style() == QwtCurve.UserCurve: 
     407        if self.style() == QwtPlotCurve.UserCurve: 
    362408            back = p.backgroundMode() 
    363409 
     
    422468    def label(self, value): 
    423469        index = int(round(value)) 
    424         if index != value: return ""    # if value not an integer value return "" 
    425         if index >= len(self.labels) or index < 0: return '' 
    426         return QString(str(self.labels[index])) 
     470        if index != value: return QwtText("")    # if value not an integer value return "" 
     471        if index >= len(self.labels) or index < 0: return QwtText("") 
     472        return QwtText(str(self.labels[index])) 
    427473 
    428474# #################################################################### 
     
    433479 
    434480    def label(self, value): 
    435         return QString.null 
     481        return QwtText() 
  • orange/OrangeWidgets/OWMosaicOptimization.py

    r3725 r3794  
    1919allExamplesText = "<All examples>" 
    2020 
    21 class OWMosaicOptimization(OWBaseWidget, orngMosaic): 
     21class OWMosaicOptimization(OWWidget, orngMosaic): 
    2222    resultsListLenNums = [ 100 ,  250 ,  500 ,  1000 ,  5000 ,  10000, 20000, 50000, 100000] 
    2323    resultsListLenList = [str(x) for x in resultsListLenNums] 
     
    3131 
    3232    def __init__(self, mosaicWidget = None, signalManager = None): 
    33         OWBaseWidget.__init__(self, None, signalManager, "Mosaic Evaluation Dialog", savePosition = True) 
     33        OWWidget.__init__(self, None, signalManager, "Mosaic Evaluation Dialog", savePosition = True, wantMainArea = 0, wantStatusBar = 1) 
    3434        orngMosaic.__init__(self) 
    3535 
     
    4040        else: 
    4141            self.setCaption("Qt Mosaic Evaluation Dialog") 
    42         self.controlArea = QVBoxLayout(self) 
    4342 
    4443        # loaded variables 
     
    6564 
    6665        self.loadSettings() 
    67  
    68         self.tabs = QTabWidget(self, 'tabWidget') 
    69         self.controlArea.addWidget(self.tabs) 
    70  
    71         self.MainTab = QVGroupBox(self) 
    72         self.SettingsTab = QVGroupBox(self) 
    73         self.TreeTab = QVGroupBox(self) 
    74         self.ManageTab = QVGroupBox(self) 
    75         self.ArgumentationTab = QVGroupBox(self) 
    76         self.ClassificationTab = QVGroupBox(self) 
    77  
    78         self.tabs.insertTab(self.MainTab, "Main") 
    79         self.tabs.insertTab(self.SettingsTab, "Settings") 
    80         self.tabs.insertTab(self.ArgumentationTab, "Argumentation") 
    81         self.tabs.insertTab(self.ClassificationTab, "Classification") 
    82         self.tabs.insertTab(self.TreeTab, "Tree") 
    83         self.tabs.insertTab(self.ManageTab, "Manage") 
     66        self.layout().setMargin(0) 
     67        self.tabs = OWGUI.tabWidget(self.controlArea) 
     68        self.MainTab = OWGUI.createTabPage(self.tabs, "Main") 
     69        self.SettingsTab = OWGUI.createTabPage(self.tabs, "Settings") 
     70        self.ArgumentationTab = OWGUI.createTabPage(self.tabs, "Argumentation") 
     71        self.ClassificationTab = OWGUI.createTabPage(self.tabs, "Classification") 
     72        self.TreeTab = OWGUI.createTabPage(self.tabs, "Tree") 
     73        self.ManageTab = OWGUI.createTabPage(self.tabs, "Manage") 
    8474 
    8575        # ########################### 
     
    9282        self.buttonsBox = OWGUI.widgetBox(self.MainTab, box = 1) 
    9383 
    94         self.label1 = QLabel('Projections with ', self.buttonBox) 
     84        self.label1 = OWGUI.widgetLabel(self.buttonBox, 'Projections with ') 
    9585        self.optimizationTypeCombo = OWGUI.comboBox(self.buttonBox, self, "optimizationType", items = ["    exactly    ", "  maximum  "] ) 
    9686        self.attributeCountCombo = OWGUI.comboBox(self.buttonBox, self, "attributeCount", items = range(1, 5), tooltip = "Evaluate only projections with exactly (or maximum) this number of attributes", sendSelectedValue = 1, valueType = int) 
    97         self.attributeLabel = QLabel(' attributes', self.buttonBox) 
     87        self.attributeLabel = OWGUI.widgetLabel(self.buttonBox, ' attributes') 
    9888 
    9989        self.startOptimizationButton = OWGUI.button(self.optimizationBox, self, "Start Evaluating Projections", callback = self.evaluateProjections) 
     
    10393        self.stopOptimizationButton.hide() 
    10494 
    105         self.resultList = QListBox(self.resultsBox) 
    106         self.resultList.setMinimumSize(200,200) 
    107         self.connect(self.resultList, SIGNAL("selectionChanged()"), self.showSelectedAttributes) 
    108  
    109         OWGUI.checkBox(self.optimizeOrderSubBox, self, "optimizeAttributeOrder", "Optimize order of attributes", callback = self.optimizeCurrentAttributeOrder, tooltip = "Order the visualized attributes so that it will enhance class separation") 
    110         OWGUI.checkBox(self.optimizeOrderSubBox, self, "optimizeAttributeValueOrder", "Optimize order of attribute values", callback = self.optimizeCurrentAttributeOrder, tooltip = "Order also the values of visualized attributes so that it will enhance class separation.\nWARNING: This can take a lot of time when visualizing attributes with many values.") 
     95        self.resultList = OWGUI.listBox(self.resultsBox, self, callback = self.showSelectedAttributes) 
     96        self.resultList.setMinimumHeight(200) 
     97 
     98        OWGUI.checkBox(self.optimizeOrderSubBox, self, "optimizeAttributeOrder", "Optimize attributes", callback = self.optimizeCurrentAttributeOrder, tooltip = "Order the visualized attributes so that it will enhance class separation") 
     99        OWGUI.checkBox(self.optimizeOrderSubBox, self, "optimizeAttributeValueOrder", "Optimize attribute values", callback = self.optimizeCurrentAttributeOrder, tooltip = "Order also the values of visualized attributes so that it will enhance class separation.\nWARNING: This can take a lot of time when visualizing attributes with many values.") 
    111100 
    112101        self.optimizeOrderButton = OWGUI.button(self.buttonsBox, self, "Optimize Current Attribute Order", callback = self.optimizeCurrentAttributeOrder, tooltip = "Optimize the order of currently visualized attributes", debuggingEnabled=0) 
    113  
    114102 
    115103        # ########################## 
     
    127115 
    128116        self.testingCombo2 = OWGUI.comboBox(self.SettingsTab, self, "attributeOrderTestingMethod", box = "Testing Method Used for Optimizing Attribute Orders", items = ["10 fold cross validation", "Learn and test on learn data"], tooltip = "Method used when evaluating different attribute orders.") 
     117        self.SettingsTab.layout().addStretch(100) 
    129118 
    130119        # ########################## 
     
    138127 
    139128        self.argumentsClassBox = OWGUI.widgetBox(self.ArgumentationTab, "Show Arguments For Class:", orientation = "horizontal") 
    140         self.classValueList = OWGUI.comboBox(self.argumentsClassBox, self, "argumentationClassValue", tooltip = "Select the class value that you wish to see arguments for", callback = self.updateShownArguments) 
     129        self.classValueCombo = OWGUI.comboBox(self.argumentsClassBox, self, "argumentationClassValue", tooltip = "Select the class value that you wish to see arguments for", callback = self.updateShownArguments) 
    141130        self.logitLabel = OWGUI.widgetLabel(self.argumentsClassBox, " ", labelWidth = 100) 
    142131 
    143132        self.argumentBox = OWGUI.widgetBox(self.ArgumentationTab, "Arguments/Odds Ratios For The Selected Class Value") 
    144         self.argumentList = QListBox(self.argumentBox) 
    145         self.argumentList.setMinimumSize(200,200) 
    146         self.connect(self.argumentList, SIGNAL("selectionChanged()"),self.argumentSelected) 
     133        self.argumentList = OWGUI.listBox(self.argumentBox, self, callback = self.argumentSelected) 
     134        self.argumentList.setMinimumHeight(200) 
    147135        self.resultsDetailsBox = OWGUI.widgetBox(self.ArgumentationTab, "Shown Details in Arguments List" , orientation = "horizontal") 
    148136        self.showConfidenceCheck = OWGUI.checkBox(self.resultsDetailsBox, self, 'showConfidence', '95% Confidence Interval', callback = self.updateShownArguments, tooltip = "Show confidence interval of the argument.") 
     
    154142        #self.argumentValueFormulaIndex = OWGUI.comboBox(self.ClassificationTab, self, "argumentValueFormula", box="Argument Value is Computed As ...", items=["1.0 x Projection Value", "0.5 x Projection Value + 0.5 x Predicted Example Probability", "1.0 x Predicted Example Probability"], tooltip=None) 
    155143        probBox = OWGUI.widgetBox(self.ClassificationTab, box = "Probability Estimation") 
    156         self.probCombo = OWGUI.comboBox(probBox, self, "probabilityEstimation", items = ["Relative Frequency", "Laplace", "m-Estimate"], callback = self.updateMestimateComboState) 
    157  
    158         mValid = QDoubleValidator(self) 
    159         mValid.setRange(0,10000,1) 
    160         self.mEditBox = OWGUI.lineEdit(probBox, self, 'mValue', label='              Parameter for m-estimate:   ', orientation='horizontal', valueType = float, validator = mValid) 
    161  
    162         b = OWGUI.widgetBox(self.ClassificationTab, "Evaluating Time") 
     144        self.probCombo = OWGUI.comboBox(probBox, self, "probabilityEstimation", items = ["Relative Frequency", "Laplace", "m-Estimate"], callback = self.updateMEstimateComboState) 
     145 
     146        self.mEditBox = OWGUI.lineEdit(probBox, self, 'mValue', label='              Parameter for m-estimate:   ', orientation='horizontal', valueType = float, validator = QDoubleValidator(0,10000,1, self)) 
     147 
     148        b = OWGUI.widgetBox(self.ClassificationTab, "Evaluating Time", orientation = "horizontal") 
    163149        OWGUI.checkWithSpin(b, self, "Use time limit:    ", 1, 1000, "useTimeLimit", "timeLimit", "(minutes)", debuggingEnabled = 0)      # disable debugging. we always set this to 1 minute 
    164150        classBox = OWGUI.widgetBox(self.ClassificationTab, "For Classification Use...") 
     
    179165 
    180166        OWGUI.button(self.ClassificationTab, self, "Resend Learner", callback = self.resendLearner, tooltip = "Resend learner with new settings. You need to press this \nonly when you are sending mosaic learner signal to other widgets.") 
     167        self.ClassificationTab.layout().addStretch(100) 
    181168 
    182169        # ########################## 
    183170        # TREE TAB 
    184171        subsetBox = OWGUI.widgetBox(self.TreeTab, "Example Subset Analysis") 
    185         self.splitter = QSplitter(Qt.Vertical, subsetBox, "main") 
    186         self.subsetTree = QListView(self.splitter) 
    187         self.subsetTree.setRootIsDecorated(1) 
    188         self.subsetTree.setAllColumnsShowFocus(1) 
    189         self.subsetTree.addColumn('Visualized Attributes') 
    190         self.subsetTree.addColumn('# inst.') 
    191         self.subsetTree.setColumnWidth(0, 300) 
    192         self.subsetTree.setColumnWidthMode(0, QListView.Maximum) 
    193         self.subsetTree.setColumnAlignment(0, QListView.AlignLeft) 
    194         self.subsetTree.setColumnWidth(1, 50) 
    195         self.subsetTree.setColumnWidthMode(1, QListView.Manual) 
    196         self.subsetTree.setColumnAlignment(1, QListView.AlignRight) 
    197         self.connect(self.subsetTree, SIGNAL("selectionChanged(QListViewItem *)"), self.mtSelectedTreeItemChanged) 
    198         self.connect(self.subsetTree, SIGNAL("rightButtonPressed(QListViewItem *, const QPoint &, int )"), self.mtSubsetTreeRemoveItemPopup) 
    199  
    200         self.selectionsList = QListBox(self.splitter) 
    201         self.connect(self.selectionsList, SIGNAL("selectionChanged()"), self.mtSelectedListItemChanged) 
    202         self.connect(self.selectionsList, SIGNAL('doubleClicked(QListBoxItem *)'), self.mtSelectedListItemDoubleClicked) 
     172        self.splitter = QSplitter(Qt.Vertical, subsetBox) 
     173        subsetBox.layout().addWidget(self.splitter) 
     174        self.subsetTree = QTreeWidget(self.splitter) 
     175        self.splitter.addWidget(self.subsetTree) 
     176        self.subsetTree.setColumnCount(2) 
     177        self.subsetTree.setHeaderLabels(['Visualized Attributes', '# inst.']) 
     178        #self.subsetTree.setAllColumnsShowFocus(1) 
     179        self.subsetTree.header().setStretchLastSection(True) 
     180        self.subsetTree.header().setClickable(0) 
     181        self.subsetTree.header().setSortIndicatorShown(0) 
     182        self.subsetTree.header().setResizeMode(0, QHeaderView.Stretch) 
     183 
     184#        self.subsetTree.addColumn() 
     185#        self.subsetTree.addColumn() 
     186#        self.subsetTree.setColumnWidth(0, 300) 
     187#        self.subsetTree.setColumnWidthMode(0, QListView.Maximum) 
     188#        self.subsetTree.setColumnAlignment(0, QListView.AlignLeft) 
     189#        self.subsetTree.setColumnWidth(1, 50) 
     190#        self.subsetTree.setColumnWidthMode(1, QListView.Manual) 
     191#        self.subsetTree.setColumnAlignment(1, QListView.AlignRight) 
     192 
     193        self.connect(self.subsetTree, SIGNAL("itemSelectionChanged()"), self.mtSelectedTreeItemChanged) 
     194        #self.connect(self.subsetTree, SIGNAL("rightButtonPressed(QListViewItem *, const QPoint &, int )"), self.mtSubsetTreeRemoveItemPopup) 
     195 
     196        self.selectionsList = OWGUI.listBox(self.splitter, self, callback = self.mtSelectedListItemChanged) 
     197        self.connect(self.selectionsList, SIGNAL('itemDoubleClicked(QListWidgetItem *)'), self.mtSelectedListItemDoubleClicked) 
    203198 
    204199        self.subsetItems = {} 
     
    221216        OWGUI.button(loadSaveBox, self, "Save", callback = self.mtSaveTree, tooltip = "Save tree to a file", debuggingEnabled = 0) 
    222217 
    223         self.subsetPopupMenu = QPopupMenu(self) 
    224         self.subsetPopupMenu.insertItem("Explore currently selected examples", self.mtEploreCurrentSelection) 
    225         self.subsetPopupMenu.insertItem("Find interesting projection", self.evaluateProjections) 
    226         self.subsetPopupMenu.insertSeparator() 
    227         self.subsetPopupMenu.insertItem("Remove node", self.mtRemoveSelectedItem) 
    228         self.subsetPopupMenu.insertItem("Clear tree", self.mtInitSubsetTree) 
    229  
    230  
     218        self.subsetPopupMenu = QMenu(self) 
     219        self.subsetPopupMenu.addAction("Explore currently selected examples", self.mtEploreCurrentSelection) 
     220        self.subsetPopupMenu.addAction("Find interesting projection", self.evaluateProjections) 
     221        self.subsetPopupMenu.addSeparator() 
     222        self.subsetPopupMenu.addAction("Remove node", self.mtRemoveSelectedItem) 
     223        self.subsetPopupMenu.addAction("Clear tree", self.mtInitSubsetTree) 
    231224 
    232225        # ########################## 
     
    236229        self.manageResultsBox = OWGUI.widgetBox(self.ManageTab, "Manage Projections") 
    237230 
    238         self.attrLenList = QListBox(self.visualizedAttributesBox) 
    239         self.attrLenList.setSelectionMode(QListBox.Multi) 
    240         self.attrLenList.setMinimumSize(60,60) 
    241         self.connect(self.attrLenList, SIGNAL("selectionChanged()"), self.attrLenListChanged) 
     231        self.attrLenList = OWGUI.listBox(self.visualizedAttributesBox, self, selectionMode = QListWidget.MultiSelection, callback = self.attrLenListChanged) 
     232        self.attrLenList.setMinimumHeight(60) 
    242233 
    243234        self.buttonBox7 = OWGUI.widgetBox(self.dialogsBox, orientation = "horizontal") 
     
    257248 
    258249        # ########################### 
    259         self.statusBar = QStatusBar(self) 
    260         self.controlArea.addWidget(self.statusBar) 
    261         self.controlArea.activate() 
    262  
    263         self.updateMestimateComboState() 
     250        self.updateMEstimateComboState() 
    264251        self.updateClassMethodsCombo() 
    265252        self.updateGUI() 
     
    318305        else:   self.testingBox.hide() 
    319306 
    320     def updateMestimateComboState(self): 
     307    def updateMEstimateComboState(self): 
    321308        self.mEditBox.setEnabled(self.probabilityEstimation == M_ESTIMATE) 
    322309 
     
    348335        self.attrLenDict = {} 
    349336        for i in range(self.attrLenList.count()): 
    350             self.attrLenDict[int(str(self.attrLenList.text(i)))] = self.attrLenList.isSelected(i) 
     337            self.attrLenDict[int(str(self.attrLenList.item(i).text()))] = self.attrLenList.item(i).isSelected() 
    351338        self.updateShownProjections() 
    352339 
     
    367354        for i in range(len(self.results)): 
    368355            if self.attrLenDict.has_key(len(self.results[i][ATTR_LIST])) and self.attrLenDict[len(self.results[i][ATTR_LIST])] == 1: 
    369                 self.resultList.insertItem("%.3f : %s" % (self.results[i][SCORE], self.buildAttrString(self.results[i][ATTR_LIST]))) 
     356                self.resultList.addItem("%.3f : %s" % (self.results[i][SCORE], self.buildAttrString(self.results[i][ATTR_LIST]))) 
    370357                self.resultListIndices.append(i) 
    371358                self.shownResults.append(self.results[i]) 
    372359        qApp.processEvents() 
    373360 
    374         if self.resultList.count() > 0: self.resultList.setCurrentItem(0) 
     361        if self.resultList.count() > 0: 
     362            self.resultList.setCurrentItem(self.resultList.item(0)) 
    375363 
    376364    def setData(self, data, removeUnusedValues = 0): 
     
    378366 
    379367        self.setStatusBarText("") 
    380         self.classValueList.clear() 
     368        self.classValueCombo.clear() 
    381369        self.argumentList.clear() 
    382370        self.selectedClasses = [] 
     
    395383 
    396384        # add class values 
    397         for val in getVariableValuesSorted(self.data, self.data.domain.classVar.name): 
    398             self.classValueList.insertItem(val) 
     385        self.classValueCombo.addItems(getVariableValuesSorted(self.data, self.data.domain.classVar.name)) 
    399386        self.updateShownArguments() 
    400387 
    401388        if len(self.data.domain.classVar.values) > 0: 
    402             self.classValueList.setCurrentItem(0) 
     389            self.classValueCombo.setCurrentIndex(0) 
    403390        return self.data 
    404391 
     
    410397 
    411398        self.argumentList.clear() 
    412         self.arguments = [[] for i in range(self.classValueList.count())] 
     399        self.arguments = [[] for i in range(self.classValueCombo.count())] 
    413400 
    414401        if not example and not self.mosaicWidget.subsetData: 
     
    436423        self.argumentationClassValue = values.index(classValue)     # activate the class that has the highest probability 
    437424        self.updateShownArguments() 
    438         if self.argumentList.count() > 0 and selectBest: self.argumentList.setCurrentItem(0) 
     425        if self.argumentList.count() > 0 and selectBest: self.argumentList.setCurrentIndex(0) 
    439426 
    440427        if showClassification: 
     
    455442        for i in range(1,5): 
    456443            if self.attrLenDict.has_key(i): 
    457                 self.attrLenList.insertItem(str(i)) 
    458  
    459         self.attrLenList.selectAll(1) 
     444                self.attrLenList.addItem(str(i)) 
     445 
     446        self.attrLenList.selectAll() 
    460447        delattr(self, "skipUpdate") 
    461448        self.updateShownProjections() 
    462         self.resultList.setCurrentItem(0) 
     449        self.resultList.setCurrentItem(self.resultList.item(0)) 
    463450 
    464451 
     
    475462            else: 
    476463                filename = "%s" % (self.parentName) 
    477             qname = QFileDialog.getSaveFileName( os.path.join(self.lastSaveDirName, filename), "Interesting mosaic visualizations (*.mproj)", self, "", "Save List of Visualizations") 
     464            qname = QFileDialog.getSaveFileName(self, "Save List of Visualizations",  os.path.join(self.lastSaveDirName, filename), "Interesting mosaic visualizations (*.mproj)") 
    478465            if qname.isEmpty(): return 
    479466            name = str(qname) 
     
    502489 
    503490        if name == None: 
    504             name = QFileDialog.getOpenFileName( self.lastSaveDirName, "Interesting mosaic visualizations (*.mproj)", self, "", "Open List of Visualizations") 
     491            name = QFileDialog.getOpenFileName(self, "Open List of Visualizations", self.lastSaveDirName, "Interesting mosaic visualizations (*.mproj)") 
    505492            if name.isEmpty(): return 
    506493            name = str(name) 
     
    532519    def attrsToString(self, attrList): 
    533520        return ", ".join(attrList) 
     521 
     522    def insertItem(self, score, attrList, index, tryIndex, extraInfo = []): 
     523        orngMosaic.insertItem(self, score, attrList, index, tryIndex, extraInfo) 
     524        self.resultList.insertItem(index, "%.3f : %s" % (score, self.buildAttrString(attrList))) 
     525        self.resultListIndices.insert(index, index) 
     526 
    534527 
    535528    # ###################################################### 
     
    542535        self.selectionsList.clear() 
    543536        self.treeRoot = None 
    544         self.subsetTree.setColumnWidth(0, self.subsetTree.width() - self.subsetTree.columnWidth(1)-4) 
     537        #self.subsetTree.setColumnWidth(0, self.subsetTree.width() - self.subsetTree.columnWidth(1)-4) 
    545538 
    546539        if self.wholeDataSet: 
    547             root = QListViewItem(self.subsetTree, allExamplesText, str(len(self.wholeDataSet))) 
     540            root = QTreeWidgetItem(self.subsetTree, [allExamplesText, str(len(self.wholeDataSet))]) 
    548541            root.details = {"data": self.wholeDataSet, "exampleCount": len(self.wholeDataSet)} 
    549542            root.selections = {} 
    550543            self.treeRoot = root 
    551             root.setOpen(1) 
    552             self.subsetTree.insertItem(root) 
     544            root.setExpanded(1) 
    553545            self.processingSubsetData = 1 
    554             self.subsetTree.setSelected(root, 1) 
     546            root.setSelected(1) 
    555547            self.processingSubsetData = 0 
    556548 
     
    580572        selectedData = self.mosaicWidget.data.selectref(selectedIndices) 
    581573        unselectedData = self.mosaicWidget.data.selectref(selectedIndices, negate = 1) 
    582         selectedTreeItem = self.subsetTree.selectedItem()     # current selection 
     574        selectedTreeItem = self.subsetTree.selectedItems()[0]     # current selection 
    583575 
    584576        # add a new item into the list box 
    585         newListItem = QListBoxText(self.selectionsList, self.mtSelectionsToString(selectionDict)) 
     577        newListItem = QListWidgetItem(self.mtSelectionsToString(selectionDict), self.selectionsList) 
    586578        newListItem.selections = selectionDict 
    587         self.selectionsList.setSelected(newListItem, 1) 
     579        newListItem.setSelected(1) 
    588580 
    589581        # add a child into the tree view 
    590582        attrListStr = self.attrsToString(attrList) 
    591         newTreeItem = QListViewItem(selectedTreeItem, attrListStr) 
     583        newTreeItem = QTreeWidgetItem(selectedTreeItem, [attrListStr, str(len(selectedData))]) 
    592584        newTreeItem.details = {"attrs": list(attrList), "exampleCount": len(selectedData)} 
    593585        newTreeItem.selections = selectionDict 
    594         newTreeItem.setText(1, str(len(selectedData))) 
    595         newTreeItem.setOpen(1) 
     586        newTreeItem.setExpanded(1) 
    596587 
    597588 
     
    600591        if not self.wholeDataSet: return 
    601592        if self.processingSubsetData: return 
    602  
    603         selectedTreeItem = self.subsetTree.selectedItem() 
    604         selectedListItem = self.selectionsList.currentItem() != -1 and self.selectionsList.item(self.selectionsList.currentItem()) or None 
     593        if self.subsetTree.selectedItems() == []: return 
     594 
     595        selectedTreeItem = self.subsetTree.selectedItems()[0] 
     596        selectedListItem = self.selectionsList.currentItem() 
    605597        attrList, selectionIndices, projDict, selectionDict = self.mtGetProjectionState(getSelectionIndices = 0) 
    606598        if not selectedTreeItem: return 
    607599 
    608600        # if this is the last element in the tree, then update the element's values 
    609         if selectedTreeItem.firstChild() == None: 
     601        if selectedTreeItem.child(0) == None: 
    610602            selectedTreeItem.setText(0, self.attrsToString(attrList)) 
    611603            selectedTreeItem.details.update(projDict) 
     
    617609            # did we change the visualized attributes. If yes then we have to add a new node into the tree 
    618610            if 0 in [selectedTreeItem.details[key] == projDict[key] for key in projDict.keys()]: 
    619                 newTreeItem = QListViewItem(selectedTreeItem.parent() or self.subsetTree, self.attrsToString(attrList), str(selectedTreeItem.text(1))) 
    620                 newTreeItem.setOpen(1) 
     611                newTreeItem = QTreeWidgetItem(selectedTreeItem.parent() or self.subsetTree, [self.attrsToString(attrList), str(selectedTreeItem.text(1))]) 
     612                newTreeItem.setExpanded (1) 
    621613                newTreeItem.details = projDict 
    622614                newTreeItem.selections = {} 
    623                 self.subsetTree.setSelected(newTreeItem, 1) 
     615                self.mtClearTreeSelections() 
     616                newTreeItem.setSelected(1) 
    624617                self.selectionsList.clear() 
    625618 
    626619 
    627620    # we selected a different item in the tree 
    628     def mtSelectedTreeItemChanged(self, newSelection): 
     621    def mtSelectedTreeItemChanged(self, newSelection = None): 
    629622        if self.processingSubsetData: 
    630623            return 
     624        if newSelection == None: 
     625            items = self.subsetTree.selectedItems() 
     626            if len(items) == 0: return 
     627            newSelection = items[0] 
     628 
    631629        self.processingSubsetData = 1 
    632630 
     
    651649 
    652650        self.selectionsList.clear() 
    653         child = newSelection.firstChild() 
    654         while child: 
     651        for i in range(newSelection.childCount()): 
     652            child = newSelection.child(i) 
    655653            selectionDict = child.selections 
    656             newListItem = QListBoxText(self.selectionsList, self.mtSelectionsToString(selectionDict)) 
     654            newListItem = QListWidgetItem(self.mtSelectionsToString(selectionDict), self.selectionsList) 
    657655            newListItem.selections = selectionDict 
    658             child = child.nextSibling() 
    659656 
    660657        self.mosaicWidget.setShownAttributes(newSelection.details.get("attrs", None)) 
     
    664661    # a new selection was selected in the selection list. update the graph 
    665662    def mtSelectedListItemChanged(self): 
    666         selectedListItem = self.selectionsList.currentItem() != -1 and self.selectionsList.item(self.selectionsList.currentItem()) 
     663        selectedListItem = self.selectionsList.currentItem() 
    667664        if not selectedListItem: 
    668665            return 
     
    674671 
    675672    def mtSelectedListItemDoubleClicked(self, item): 
    676         pos = self.selectionsList.currentItem() 
    677         treeItem = self.subsetTree.selectedItem().firstChild() 
    678         for i in range(pos): 
    679             treeItem = treeItem.nextSibling() 
    680         self.subsetTree.setSelected(treeItem, 1) 
     673        pos = self.selectionsList.currentRow() 
     674        treeItem = self.subsetTree.selectedItems()[0].child(pos) 
     675        self.mtClearTreeSelections() 
     676        treeItem.setSelected(1) 
    681677        self.mtSelectedTreeItemChanged(treeItem) 
     678 
     679    def mtClearTreeSelections(self, item = None): 
     680        if item == None: 
     681            item  = self.subsetTree.invisibleRootItem() 
     682        item.setSelected(0) 
     683        for i in range(item.childCount()): 
     684            self.mtClearTreeSelections(item.child(i)) 
    682685 
    683686    def mtGetItemIndices(self, item): 
     
    700703    # popup menu items 
    701704    def mtRemoveSelectedItem(self): 
    702         item = self.subsetTree.selectedItem() 
    703         if not item: 
    704             return 
    705         parent = item.parent() 
     705        items = self.subsetTree.selectedItems() 
     706        if not items: return 
     707 
     708        parent = items[0].parent() 
    706709        if parent == None: 
    707710            self.mtInitSubsetTree() 
    708711        else: 
    709712            self.mtRemoveTreeItem(item) 
    710             self.subsetTree.setSelected(parent, 1) 
     713            self.mtClearTreeSelections() 
     714            parent.setSelected(1) 
    711715            self.mtSelectedTreeItemChanged(parent) 
    712716 
     
    716720    def resizeEvent(self, ev): 
    717721        OWBaseWidget.resizeEvent(self, ev) 
    718         self.subsetTree.setColumnWidth(0, self.subsetTree.width()-self.subsetTree.columnWidth(1)-4 - 20) 
    719  
     722        #self.subsetTree.setColumnWidth(0, self.subsetTree.width()-self.subsetTree.columnWidth(1)-4 - 20) 
     723 
     724    def getTreeItemSibling(self, item): 
     725        parent = item.parent() 
     726        if not parent: 
     727            parent = self.subsetTree.invisibleRootItem() 
     728        ind = parent.indexOfChild(item) 
     729        return parent.child(ind+1) 
    720730 
    721731    def mtSelectionsToString(self, settings): 
     
    727737    def mtStrToItem(self, strItem, currItem = -1): 
    728738        if currItem == -1: 
    729             currItem = self.treeRoot 
     739            currItem = self.subsetTree.invisibleRootItem() 
    730740        if currItem == None: 
    731741            return None 
    732         if str(currItem) == strItem: 
     742        if currItem.text(0) == strItem: 
    733743            return currItem 
    734         child = currItem.firstChild() 
    735         if child: 
    736             item = self.mtStrToItem(strItem, child) 
     744        i = 0 
     745        for i in range(currItem.childCount()): 
     746            item = self.mtStrToItem(strItem, currItem.child(i)) 
    737747            if item: 
    738748                return item 
    739         return self.mtStrToItem(strItem, currItem.nextSibling()) 
     749        return self.mtStrToItem(strItem, self.getTreeItemSibling(currItem)) 
    740750 
    741751 
     
    743753    def mtSaveTree(self, name = None): 
    744754        if name == None: 
    745             qname = QFileDialog.getSaveFileName( os.path.join(self.lastSaveDirName, "explorer tree.tree"), "Explorer tree (*.tree)", self, "", "Save tree") 
     755            qname = QFileDialog.getSaveFileName(self, "Save tree", os.path.join(self.lastSaveDirName, "explorer tree.tree"), "Explorer tree (*.tree)") 
    746756            if qname.isEmpty(): 
    747757                return 
     
    763773 
    764774        if name == None: 
    765             name = QFileDialog.getOpenFileName( self.lastSaveDirName, "Explorer tree (*.tree)", self, "", "Load tree") 
     775            name = QFileDialog.getOpenFileName(self, "Load tree", self.lastSaveDirName, "Explorer tree (*.tree)") 
    766776            if name.isEmpty(): return 
    767777            name = str(name) 
     
    772782        tree = cPickle.load(f) 
    773783        self.mtDictToTree(tree, "None", self.subsetTree) 
    774         root = self.subsetTree.firstChild() 
     784        root = self.subsetTree.invisibleRootItem().child(0) 
    775785        if root: 
    776786            self.treeRoot = root 
    777             self.subsetTree.setSelected(root, 1) 
    778             self.selectedTreeItemChanged(root) 
     787            root.setSelected(1) 
     788            self.mtSelectedTreeItemChanged(root) 
    779789 
    780790    # generate a dictionary from the tree that can be pickled 
     
    782792        if not node: return 
    783793 
    784         child = node.firstChild() 
     794        child = node.child(0) 
    785795        if child: 
    786796            self.mtTreeToDict(child, tree) 
    787797 
    788798        tree[str(node.parent())] = tree.get(str(node.parent()), []) + [(str(node), node.details, node.selections)] 
    789         self.mtTreeToDict(node.nextSibling(), tree) 
     799        self.mtTreeToDict(self.getTreeItemSibling(node), tree) 
    790800 
    791801    # create a tree from a dictionary 
     
    796806                strAttrs = self.attrsToString(details["attrs"]) 
    797807                exampleCount = details["exampleCount"] 
    798                 item = QListViewItem(parentItem, strAttrs, str(exampleCount)) 
     808                item = QTreeWidgetItem(parentItem, [strAttrs, str(exampleCount)]) 
    799809                item.details = details 
    800810                item.selections = selections 
    801                 item.setOpen(1) 
     811                item.setExpanded(1) 
    802812                self.mtDictToTree(tree, strChildNode, item) 
    803813 
     
    816826 
    817827                examples = self.mosaicWidget.data 
    818                 selectedItem = self.subsetTree.selectedItem() 
     828                #selectedItems = self.subsetTree.selectedItems() 
     829                selectedItem = self.subsetTree.currentItem() 
     830 
    819831                if selectedItem and selectedItem.parent() != None: 
    820                     res = QMessageBox.information(self, "Tree Building", "Currently you are visualizing only a subset of examples. Do you want to build the tree\nonly for these examples or for all examples?", "Only for these", "For all examples", None, 0, 1) 
    821                     if res == 1: 
     832                    box = QMessageBox() 
     833                    box.setIcon(QMessageBox.Question) 
     834                    box.setWindowTitle("Tree Building") 
     835                    box.setText("Currently you are visualizing only a subset of examples. Do you want to build the tree only for these examples or for all examples?") 
     836                    onlyTheseButton = box.addButton("Only for these", QMessageBox.YesRole) 
     837                    allExamplesButton = box.addButton("For all examples", QMessageBox.NoRole) 
     838                    box.exec_() 
     839                    if box.clickedButton() == allExamplesButton: 
    822840                        examples = self.wholeDataSet 
    823841                        parent = self.subsetTree 
     
    826844                else: 
    827845                    parent = self.subsetTree 
    828                     selections = selectedItem and selectedItem.selections or {} 
     846                selections = selectedItem and selectedItem.selections or {} 
    829847 
    830848                 #create a mosaic and use a classifier to generate a mosaic tree so that we don't set data to the main mosaic (which would mean that we would have to prevent the user from clicking the current tree) 
     
    841859                    if not selectedItem: 
    842860                        self.subsetTree.clear() 
    843                     elif selectedItem.firstChild() == None: 
     861                    elif selectedItem.child(0) == None: 
    844862                        self.mtRemoveTreeItem(selectedItem) 
    845863 
    846                     item = QListViewItem(parent, self.attrsToString(root.attrs), str(len(root.branchSelector.data))) 
     864                    item = QTreeWidgetItem(parent, [self.attrsToString(root.attrs), str(len(root.branchSelector.data))]) 
    847865                    item.details = {"attrs": root.attrs, "exampleCount": len(root.branchSelector.data)} 
    848866                    item.selections = selections 
    849                     item.setOpen(1) 
     867                    item.setExpanded(1) 
    850868                    if parent == self.subsetTree: 
    851869                        self.treeRoot = item 
     
    863881            selections = treeNode.branchSelector.values[key] 
    864882            exampleCount = len(branch.branchSelector.data) 
    865             item = QListViewItem(parentTreeItem, strAttrs, str(exampleCount)) 
     883            item = QTreeWidgetItem(parentTreeItem, [strAttrs, str(exampleCount)]) 
    866884            item.details = {"attrs": branch.attrs, "exampleCount": exampleCount} 
    867885            item.selections = {'selectionConditions': selections, 'selectionConditionsHistorically': [selections], "selectedIndices": self.mosaicWidget.getSelectedExamples(asExampleTable = 0, selectionConditions = selections, data = treeNode.branchSelector.data, attrs = treeNode.attrs)} 
    868             item.setOpen(1) 
     886            item.setExpanded(1) 
    869887            self.mtGenerateTreeFromClassifier(branch, item) 
    870888 
     
    874892        if parent == None: 
    875893            parent = self.subsetTree 
    876         parent.takeItem(item) 
     894        print parent 
     895        ind = parent.indexOfChild(item) 
     896        parent.takeChild(ind) 
    877897 
    878898    def mtVisualizeMosaicTree(self): 
    879899        tree = {} 
    880900        self.mtTreeToDict(self.treeRoot, tree) 
    881         #dialog = MosaicTreeDialog(self, self.mosaicWidget, self.signalManager) 
    882         #dialog.visualizeTree(tree) 
    883         #dialog.show() 
    884901        treeDialog = OWBaseWidget(self, self.signalManager, "Mosaic Tree") 
    885         treeDialog.canvasLayout = QVBoxLayout(treeDialog) 
    886         treeDialog.canvasWidget = QWidget(treeDialog) 
    887  
    888         treeDialog.canvas = QCanvas(10000, 10000) 
    889         treeDialog.canvasView = QCanvasView(treeDialog.canvas, treeDialog) 
    890         treeDialog.canvasLayout.addWidget(treeDialog.canvasView) 
    891         treeDialog.canvasLayout.activate() 
    892         treeDialog.canvasView.show() 
     902        treeDialog.setLayout(QVBoxLayout()) 
     903        treeDialog.layout().setMargin(2) 
     904 
     905        treeDialog.canvas = QGraphicsScene() 
     906        treeDialog.canvasView = QGraphicsView(treeDialog.canvas, treeDialog) 
     907        treeDialog.canvasView.setAlignment(Qt.AlignLeft | Qt.AlignTop) 
     908        treeDialog.layout().addWidget(treeDialog.canvasView) 
     909        #treeDialog.canvasView.show() 
    893910        treeDialog.resize(800, 800) 
    894911        treeDialog.move(0,0) 
     
    9921009                        OWQCanvasFuncts.OWCanvasLine(treeDialog.canvas, parentXPos, yPos - 30, node["currXPos"] + xMosaicSize/2, yPos - 10, penWidth = 4, penColor = colors[nodeIndex]) 
    9931010 
    994         treeDialog.canvas.resize(maxX + self.mosaicSize + 200, maxY) 
     1011        #treeDialog.canvas.resize(maxX + self.mosaicSize + 200, maxY) 
     1012        treeDialog.canvasView.setSceneRect(0,0,maxX + self.mosaicSize + 200, maxY) 
    9951013 
    9961014        # restore the original canvas and canvas view 
     
    10221040 
    10231041    def getSelectedProjection(self): 
    1024         currentItem = self.resultList.currentItem() 
    1025         if self.resultList.count() == 0 or currentItem == -1: 
    1026             return None 
    1027         return self.results[self.resultListIndices[currentItem]]      # we have to look into resultListIndices, since perhaps not all projections from the self.results are shown 
     1042        if self.resultList.selectedItems() == []: return None 
     1043        return self.results[self.resultListIndices[self.resultList.row(self.resultList.selectedItems()[0])]]  # we have to look into resultListIndices, since perhaps not all projections from the self.results are shown 
    10281044 
    10291045    def stopEvaluationClick(self): 
     
    10361052    def destroy(self, dw = 1, dsw = 1): 
    10371053        self.saveSettings() 
    1038  
    1039     def setStatusBarText(self, text): 
    1040         self.statusBar.message(text) 
    1041         qApp.processEvents() 
    10421054 
    10431055    def insertArgument(self, argScore, error, attrList, index): 
     
    10451057        if self.showConfidence and type(error) != tuple: s += "+-%.2f " % error 
    10461058        s += "- " + self.buildAttrString(attrList) 
    1047         self.argumentList.insertItem(s, index) 
     1059        self.argumentList.insertItem(index, s) 
    10481060 
    10491061    def updateShownArguments(self): 
    10501062        self.argumentList.clear() 
    10511063        if len(self.arguments) == 0: return 
    1052         classVal = str(self.classValueList.currentText()) 
     1064        classVal = str(self.classValueCombo.currentText()) 
    10531065        self.logitLabel.setText("log odds = %.2f" % self.logits.get(classVal, -1)) 
    10541066 
     
    10661078    def argumentSelected(self): 
    10671079        ind = self.argumentList.currentItem() 
    1068         classVal = str(self.classValueList.currentText()) 
     1080        classVal = str(self.classValueCombo.currentText()) 
    10691081        self.showSelectedAttributes(self.arguments[classVal][ind][2]) 
    10701082 
     
    11021114        dialog.setData(self.results, self.data, OWkNNOptimization.VIZRANK_MOSAIC) 
    11031115        dialog.show() 
    1104  
    11051116 
    11061117#test widget appearance 
  • orange/OrangeWidgets/OWQCanvasFuncts.py

    r2557 r3794  
    1 from qt import * 
    2 from qtcanvas import * 
     1from PyQt4.QtCore import * 
     2from PyQt4.QtGui import * 
    33 
    4 def OWCanvasText(canvas, text, x  = 0, y = 0, alignment = Qt.AlignLeft + Qt.AlignVCenter, bold = 0, font = None, z = 0, show = 1): 
    5     text = QCanvasText(text, canvas) 
    6     text.setTextFlags(alignment) 
     4class OWCanvasText(QGraphicsTextItem): 
     5    def __init__(self, canvas, text, x  = 0, y = 0, alignment = 0, bold = 0, font = None, z = 0, tooltip = None, show = 1): 
     6        QGraphicsTextItem.__init__(self, text, None, canvas) 
    77 
    8     if font: 
    9         text.setFont(font) 
    10     if bold: 
    11         font = text.font(); font.setBold(bold); text.setFont(font) 
    12     text.move(x, y) 
    13     text.setZ(z) 
     8        if font: 
     9            self.setFont(font) 
     10        if bold: 
     11            font = self.font(); font.setBold(bold); self.setFont(font) 
    1412 
    15     if show: text.show() 
    16     else: text.hide() 
    17     return text 
     13        self.alignment = alignment 
    1814 
    19 def OWCanvasRectangle(canvas, x, y, width, height, penColor = Qt.black, brushColor = None, penWidth = 1, z = 0, penStyle = Qt.SolidLine, show = 1): 
    20     rect = QCanvasRectangle(x, y, width, height, canvas) 
     15        self.setPos(x, y) 
     16        self.setZValue(z) 
     17        if tooltip: self.setToolTip(tooltip) 
     18 
     19        if show: self.show() 
     20        else: self.hide() 
     21 
     22    def setPos(self, x, y): 
     23        rect = self.boundingRect() 
     24        if self.alignment & Qt.AlignRight:     x -= rect.width() 
     25        elif self.alignment & Qt.AlignHCenter: x-= rect.width()/2. 
     26        if self.alignment & Qt.AlignBottom:    y-= rect.height() 
     27        elif self.alignment & Qt.AlignVCenter: y-= rect.height()/2. 
     28        QGraphicsTextItem.setPos(self, x, y) 
     29 
     30 
     31def OWCanvasRectangle(canvas, x, y, width, height, penColor = Qt.black, brushColor = None, penWidth = 1, z = 0, penStyle = Qt.SolidLine, pen = None, tooltip = None, show = 1): 
     32    rect = QGraphicsRectItem(x, y, width, height, None, canvas) 
    2133    if brushColor: rect.setBrush(QBrush(brushColor)) 
    22     rect.setPen(QPen(penColor, penWidth, penStyle)) 
    23     rect.setZ(z) 
     34    if pen: rect.setPen(pen) 
     35    else:   rect.setPen(QPen(penColor, penWidth, penStyle)) 
     36    rect.setZValue(z) 
     37    if tooltip: rect.setToolTip(tooltip) 
    2438    if show: rect.show() 
    2539    return rect 
    2640 
    2741 
    28 def OWCanvasLine(canvas, x1, y1, x2, y2, penWidth = 1, penColor = Qt.black, z = 0, show = 1): 
    29     r = QCanvasLine(canvas) 
    30     r.setPoints(x1, y1, x2, y2) 
     42def OWCanvasLine(canvas, x1, y1, x2, y2, penWidth = 1, penColor = Qt.black, z = 0, tooltip = None, show = 1): 
     43    r = QGraphicsLineItem(x1, y1, x2, y2, None, canvas) 
    3144    r.setPen(QPen(penColor, penWidth)) 
    32     r.setZ(z) 
     45    r.setZValue(z) 
     46    if tooltip: r.setToolTip(tooltip) 
    3347    if show: r.show() 
    3448    return r 
    3549 
    36 def OWCanvasEllipse(canvas, x, y, width, height, penWidth = 1, startAngle = 0, angles = 360, penColor = Qt.black, brushColor = None, z = 0, penStyle = Qt.SolidLine, show = 1): 
    37     if penColor != None and brushColor == None: 
    38         # if we dont want to fill the ellipse then we have to draw it with a series of lines - QCanvasEllipse always draws with NoPen 
    39         p = QPointArray() 
    40         p.makeArc(x, y, width, height, startAngle, angles*16) 
    41         lines = [] 
    42         for i in range(0,p.size(),2): 
    43             l = OWCanvasLine(canvas, p.point(i)[0], p.point(i)[1], p.point((i+2)%p.size())[0], p.point((i+2)%p.size())[1], penWidth, penColor, z, show) 
    44             lines.append(l) 
    45         return lines 
    46     else:         
    47         e = QCanvasEllipse(width, height, canvas) 
    48         e.setX(x) 
    49         e.setY(y) 
    50         e.setZ(z) 
     50def OWCanvasEllipse(canvas, x, y, width, height, penWidth = 1, startAngle = 0, angles = 360, penColor = Qt.black, brushColor = None, z = 0, penStyle = Qt.SolidLine, tooltip = None, show = 1): 
     51    e = QGraphicsEllipseItem(x, y, width, height, None, canvas) 
     52    e.setZValue(z) 
     53    if brushColor != None: 
    5154        e.setBrush(QBrush(brushColor)) 
    52         e.setAngles(startAngle, angles*16) 
    53         if show: e.show() 
    54         return e 
    55      
     55    e.setPen(QPen(penColor)) 
     56    e.setStartAngle(startAngle) 
     57    e.setSpanAngle(angles*16) 
     58    if tooltip: e.setToolTip(tooltip) 
     59    if show: e.show() 
     60    return e 
     61 
     62#    if penColor != None and brushColor == None: 
     63#        # if we dont want to fill the ellipse then we have to draw it with a series of lines - QCanvasEllipse always draws with NoPen 
     64#        p = QPointArray() 
     65#        p.makeArc(x, y, width, height, startAngle, angles*16) 
     66#        lines = [] 
     67#        for i in range(0,p.size(),2): 
     68#            l = OWCanvasLine(canvas, p.point(i)[0], p.point(i)[1], p.point((i+2)%p.size())[0], p.point((i+2)%p.size())[1], penWidth, penColor, z, show) 
     69#            lines.append(l) 
     70#        return lines 
     71#    else: 
     72#        e = QCanvasEllipse(width, height, canvas) 
     73#        e.setX(x) 
     74#        e.setY(y) 
     75#        e.setZValue(z) 
     76#        e.setBrush(QBrush(brushColor)) 
     77#        e.setAngles(startAngle, angles*16) 
     78#        if show: e.show() 
     79#        return e 
  • orange/OrangeWidgets/OWToolbars.py

    r3781 r3794  
    1 from qt import * 
     1from PyQt4.QtCore import * 
     2from PyQt4.QtGui import * 
    23import os.path 
    34 
    45dir = os.path.dirname(__file__) + "/icons/" 
    56dlg_zoom = dir + "Dlg_zoom.png" 
    6 dlg_pan = dir + "Dlg_zoom.png" 
    7 dlg_select = dir + "Dlg_zoom.png" 
    87dlg_rect = dir + "Dlg_rect.png" 
    98dlg_poly = dir + "Dlg_poly.png" 
     
    1716def createButton(parent, text, action = None, icon = None, toggle = 0): 
    1817    btn = QToolButton(parent) 
    19     btn.setToggleButton(toggle) 
    20     btn.cback = action   # otherwise garbage collection kills it 
    21     if action: parent.connect(btn, SIGNAL("clicked()"), action) 
    22     if icon:   btn.setPixmap(icon) 
    23     QToolTip.add(btn, text) 
     18    if parent.layout(): 
     19        parent.layout().addWidget(btn) 
     20    btn.setCheckable(toggle) 
     21    if action: 
     22        parent.connect(btn, SIGNAL("clicked()"), action) 
     23    if icon: 
     24        btn.setIcon(icon) 
     25    btn.setToolTip(text) 
    2426    return btn 
    25      
    26 class ZoomSelectToolbar(QHButtonGroup): 
    27 #                (tooltip, attribute containing the button, callback function, button icon, button cursor, toggle) 
    28     builtinFunctions = (None, 
    29                  ("Zooming", "buttonZoom", "activateZooming", QPixmap(dlg_zoom), Qt.sizeAllCursor, 1),  
    30                  ("Panning", "buttonPan", "activatePanning", QPixmap(dlg_pan), Qt.pointingHandCursor, 1),  
    31                  ("Selection", "buttonSelect", "activateSelection", QPixmap(dlg_select), Qt.arrowCursor, 1),  
    32                  ("Rectangle selection", "buttonSelectRect", "activateRectangleSelection", QPixmap(dlg_rect), Qt.arrowCursor, 1),  
    33                  ("Polygon selection", "buttonSelectPoly", "activatePolygonSelection", QPixmap(dlg_poly), Qt.arrowCursor, 1),  
    34                  ("Remove last selection", "buttonRemoveLastSelection", "removeLastSelection", QPixmap(dlg_undo), None, 0),  
    35                  ("Remove all selections", "buttonRemoveAllSelections", "removeAllSelections", QPixmap(dlg_clear), None, 0),  
    36                  ("Send selections", "buttonSendSelections", "", QPixmap(dlg_send), None, 0) 
    37                 ) 
    38                   
    39     IconSpace, IconZoom, IconPan, IconSelect, IconRectangle, IconPolygon, IconRemoveLast, IconRemoveAll, IconSendSelection = range(9) 
    4027 
    41     def __init__(self, widget, parent, graph, autoSend = 0, buttons = (1, 4, 5, 0, 6, 7, 8)): 
    42         QHButtonGroup.__init__(self, "Zoom / Select", parent) 
    43          
     28 
     29class ZoomSelectToolbar(QGroupBox): 
     30    def __init__(self, widget, parent, graph, autoSend = 0): 
     31        QGroupBox.__init__(self, "Zoom / Select", parent) 
     32        self.setLayout(QHBoxLayout()) 
     33        self.layout().setMargin(6) 
     34        if parent.layout(): 
     35            parent.layout().addWidget(self) 
     36 
    4437        self.graph = graph # save graph. used to send signals 
    4538        self.widget = None 
    46          
    47         self.functions = [type(f) == int and self.builtinFunctions[f] or f for f in buttons] 
    48         for b, f in enumerate(self.functions): 
    49             if not f: 
    50                 self.addSpace(10) 
    51             else: 
    52                 button = createButton(self, f[0], lambda x=b: self.action(x), f[3], toggle = f[5]) 
    53                 setattr(self, f[1], button) 
    54                 if f[0] == "Send selections": 
    55                     button.setEnabled(not autoSend) 
    5639 
    57         self.action(0) 
     40        self.buttonZoom = createButton(self, "Zooming", self.actionZooming, QIcon(dlg_zoom), toggle = 1) 
     41        self.buttonSelectRect = createButton(self, "Rectangle selection", self.actionRectangleSelection, QIcon(dlg_rect), toggle = 1) 
     42        self.buttonSelectPoly = createButton(self, "Polygon selection", self.actionPolygonSelection, QIcon(dlg_poly), toggle = 1) 
     43 
     44        self.layout().addSpacing(10) 
     45 
     46        self.buttonRemoveLastSelection = createButton(self, 'Remove last selection', self.actionRemoveLastSelection, QIcon(dlg_undo), toggle = 0) 
     47        self.buttonRemoveAllSelections = createButton(self, 'Remove all selections', self.actionRemoveAllSelections, QIcon(dlg_clear), toggle = 0) 
     48        self.buttonSendSelections = createButton(self, 'Send selections', icon = QIcon(dlg_send), toggle = 0) 
     49        self.buttonSendSelections.setEnabled(not autoSend) 
     50 
     51        self.actionZooming()    # activate zooming 
    5852        self.widget = widget    # we set widget here so that it doesn't affect the value of self.widget.toolbarSelection 
    5953 
    60     def action(self, b): 
    61         f = self.functions[b] 
    62         if f[5]: 
    63             if hasattr(self.widget, "toolbarSelection"): 
    64                 self.widget.toolbarSelection = b 
    65             for fi, ff in enumerate(self.functions): 
    66                 if ff and ff[5]: 
    67                     getattr(self, ff[1]).setOn(fi == b) 
    68         getattr(self.graph, f[2])() 
    69          
    70         # why doesn't this work? 
    71         cursor = f[4] 
    72         if not cursor is None: 
    73             self.graph.canvas().setCursor(cursor) 
    74             print self.graph.canvas().cursor().shape() 
    75             if self.widget: 
    76                 self.widget.setCursor(cursor) 
    77              
    78          
    79     # for backward compatibility with a previous version of this class 
    80     def actionZooming(self): self.action(0) 
    81     def actionRectangleSelection(self): self.action(3) 
    82     def actionPolygonSelection(self): self.action(4) 
    83      
     54    def actionZooming(self): 
     55        if self.widget and "toolbarSelection" in self.widget.__dict__.keys(): self.widget.toolbarSelection = 0 
     56        self.buttonZoom.setChecked(1) 
     57        self.buttonSelectRect.setChecked(0) 
     58        self.buttonSelectPoly.setChecked(0) 
     59        self.graph.activateZooming() 
     60 
     61    def actionRectangleSelection(self): 
     62        if self.widget and "toolbarSelection" in self.widget.__dict__.keys(): self.widget.toolbarSelection = 1 
     63        self.buttonZoom.setChecked(0) 
     64        self.buttonSelectRect.setChecked(1) 
     65        self.buttonSelectPoly.setChecked(0) 
     66        self.graph.activateRectangleSelection() 
     67 
     68    def actionPolygonSelection(self): 
     69        if self.widget and "toolbarSelection" in self.widget.__dict__.keys(): self.widget.toolbarSelection = 2 
     70        self.buttonZoom.setChecked(0) 
     71        self.buttonSelectRect.setChecked(0) 
     72        self.buttonSelectPoly.setChecked(1) 
     73        self.graph.activatePolygonSelection() 
     74 
     75    def actionRemoveLastSelection(self): 
     76        self.graph.removeLastSelection() 
     77 
     78    def actionRemoveAllSelections(self): 
     79        self.graph.removeAllSelections() 
     80 
  • orange/OrangeWidgets/OWTools.py

    r2833 r3794  
    1 #  
     1# 
    22# OWTools.py 
    33# tools for Visual Orange 
     
    77FALSE=0 
    88 
    9 from qt import * 
     9from PyQt4.QtCore import * 
     10from PyQt4.QtGui import * 
    1011from random import * 
    1112 
     
    3132 
    3233#A 10X10 single color pixmap 
    33 class ColorPixmap (QPixmap): 
    34     def __init__(self,color=Qt.white, size = 10): 
     34class ColorPixmap (QIcon): 
     35    def __init__(self,color=QColor(Qt.white), size = 10): 
    3536        "Creates a single-color pixmap" 
    36         QPixmap.__init__(self,size,size) 
     37        p = QPixmap(size,size) 
     38        p.fill(color) 
    3739        self.color = color 
    38         self.fill(color) 
     40        QIcon.__init__(self, p) 
    3941 
    40    
    41 class QPointFloat: 
    42     def __init__(self, x, y): 
    43         self.x = x 
    44         self.y = y 
    4542 
    46 class QRectFloat: 
    47     def __init__(self, x, y, width, height): 
    48         self.x = x 
    49         self.y = y 
    50         self.width = width 
    51         self.height = height 
    52          
    5343 
    54 #A dynamic tool tip class       
    55 class TooltipManager: 
    56     # Creates a new dynamic tool tip. 
    57     def __init__(self, qwtplot): 
    58         self.qwtplot = qwtplot 
    59         self.positions=[] 
    60         self.texts=[] 
    61  
    62     # Adds a tool tip. If a tooltip with the same name already exists, it updates it instead of adding a new one. 
    63     def addToolTip(self,x, y,text, customX = 0, customY = 0): 
    64         self.positions.append((x,y, customX, customY)) 
    65         self.texts.append(text) 
    66  
    67     #Decides whether to pop up a tool tip and which text to pop up 
    68     def maybeTip(self, x, y): 
    69         if len(self.positions) == 0: return ("", -1, -1) 
    70         dists = [abs(x-position[0]) + abs(y-position[1]) for position in self.positions] 
    71         nearestIndex = dists.index(min(dists)) 
    72  
    73         intX = abs(self.qwtplot.transform(self.qwtplot.xBottom, x) - self.qwtplot.transform(self.qwtplot.xBottom, self.positions[nearestIndex][0])) 
    74         intY = abs(self.qwtplot.transform(self.qwtplot.yLeft, y) - self.qwtplot.transform(self.qwtplot.yLeft, self.positions[nearestIndex][1])) 
    75         if self.positions[nearestIndex][2] == 0 and self.positions[nearestIndex][3] == 0:   # if we specified no custom range then assume 6 pixels 
    76             if intX + intY < 6:  return (self.texts[nearestIndex], self.positions[nearestIndex][0], self.positions[nearestIndex][1]) 
    77             else:                return ("", None, None) 
    78       &nb