Changeset 11498:373539640304 in orange


Ignore:
Timestamp:
05/09/13 15:30:02 (12 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Implemented 'sloppy submenus' like handling of hover tab changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeCanvas/document/quickmenu.py

    r11494 r11498  
    2121    QStandardItemModel, QSortFilterProxyModel, QStyleOptionToolButton, 
    2222    QStylePainter, QStyle, QApplication, QStyledItemDelegate, 
    23     QStyleOptionViewItemV4, QSizeGrip 
     23    QStyleOptionViewItemV4, QSizeGrip, QCursor, QPolygon, QRegion 
    2424) 
    2525 
     
    2828 
    2929from PyQt4.QtCore import ( 
    30     Qt, QObject, QPoint, QSize, QRect, QEventLoop, QEvent, QModelIndex 
     30    Qt, QObject, QPoint, QSize, QRect, QEventLoop, QEvent, QModelIndex, 
     31    QTimer 
    3132) 
    3233 
     
    434435            self.__onButtonPressed 
    435436        ) 
    436  
    437         self.__hoverListener = ToolButtonEventListener(self) 
     437        self.setMouseTracking(True) 
     438 
     439        self.__sloppyButton = None 
     440        self.__sloppyRegion = QRegion() 
     441        self.__sloppyTimer = QTimer(self, singleShot=True) 
     442        self.__sloppyTimer.timeout.connect(self.__onSloppyTimeout) 
    438443 
    439444    def setChangeOnHover(self, changeOnHover): 
     
    445450        if self.__changeOnHover != changeOnHover: 
    446451            self.__changeOnHover = changeOnHover 
    447  
    448             if changeOnHover: 
    449                 self.__hoverListener.buttonEnter.connect( 
    450                     self.__onButtonEnter 
    451                 ) 
    452             else: 
    453                 self.__hoverListener.buttonEnter.disconnect( 
    454                     self.__onButtonEnter 
    455                 ) 
    456452 
    457453    def changeOnHover(self): 
     
    481477                             QSizePolicy.Expanding) 
    482478        button.setIconSize(self.__iconSize) 
     479        button.setMouseTracking(True) 
    483480 
    484481        self.__group.addButton(button) 
    485482 
    486         button.installEventFilter(self.__hoverListener) 
     483        button.installEventFilter(self) 
    487484 
    488485        tab = _Tab(text, icon, toolTip, button, None, None) 
     
    505502            self.__group.removeButton(tab.button) 
    506503 
    507             tab.button.removeEventFilter(self.__hoverListener) 
     504            tab.button.removeEventFilter(self) 
     505 
     506            if tab.button is self.__sloppyButton: 
     507                self.__sloppyButton = None 
     508                self.__sloppyRegion = QRegion() 
    508509 
    509510            tab.button.deleteLater() 
     
    550551            self.__currentIndex = index 
    551552 
     553            self.__sloppyRegion = QRegion() 
     554            self.__sloppyButton = None 
     555 
    552556            if index != -1: 
    553557                self.__tabs[index].button.setChecked(True) 
     
    586590            b.setIcon(tab.icon) 
    587591 
    588         if tab.toolTip: 
    589             b.setToolTip(tab.toolTip) 
    590  
    591592        if tab.palette: 
    592593            b.setPalette(tab.palette) 
     
    598599                break 
    599600 
    600     def __onButtonEnter(self, button): 
    601         if self.__changeOnHover: 
    602             button.click() 
     601    def __calcSloppyRegion(self, current): 
     602        """ 
     603        Given a current mouse cursor position return a region of the widget 
     604        where hover/move events should change the current tab only on a 
     605        timeout. 
     606 
     607        """ 
     608        p1 = current + QPoint(0, 2) 
     609        p2 = current + QPoint(0, -2) 
     610        p3 = self.pos() + QPoint(self.width(), 0) 
     611        p4 = self.pos() + QPoint(self.width(), self.height()) 
     612        return QRegion(QPolygon([p1, p2, p3, p4])) 
     613 
     614    def __setSloppyButton(self, button): 
     615        """ 
     616        Set the current sloppy button (a tab button inside sloppy region) 
     617        and reset the sloppy timeout. 
     618 
     619        """ 
     620        self.__sloppyButton = button 
     621        delay = self.style().styleHint(QStyle.SH_Menu_SubMenuPopupDelay, None) 
     622        # The delay timeout is the same as used by Qt in the QMenu. 
     623        self.__sloppyTimer.start(delay * 6) 
     624 
     625    def __onSloppyTimeout(self): 
     626        if self.__sloppyButton is not None: 
     627            button = self.__sloppyButton 
     628            self.__sloppyButton = None 
     629            if not button.isChecked(): 
     630                button.setChecked(True) 
     631 
     632                # Update the sloppy region from the current cursor position. 
     633                current = self.mapFromGlobal(QCursor.pos()) 
     634                if self.contentsRect().contains(current): 
     635                    self.__sloppyRegion = self.__calcSloppyRegion(current) 
     636 
     637    def eventFilter(self, receiver, event): 
     638        if event.type() == QEvent.MouseMove and \ 
     639                isinstance(receiver, TabButton): 
     640            pos = receiver.mapTo(self, event.pos()) 
     641            if self.__sloppyRegion.contains(pos): 
     642                self.__setSloppyButton(receiver) 
     643            else: 
     644                if not receiver.isChecked(): 
     645                    index = [tab.button for tab in self.__tabs].index(receiver) 
     646                    self.setCurrentIndex(index) 
     647                    self.__sloppyRegion = self.__calcSloppyRegion(pos) 
     648 
     649        return QWidget.eventFilter(self, receiver, event) 
     650 
     651    def leaveEvent(self, event): 
     652        self.__sloppyButton = None 
     653        self.__sloppyRegion = QRegion() 
     654 
     655        return QWidget.leaveEvent(self, event) 
    603656 
    604657 
Note: See TracChangeset for help on using the changeset viewer.