Changeset 11491:d8183bc8cf38 in orange


Ignore:
Timestamp:
05/07/13 16:35:51 (11 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Changed the tab widget in a quick menu.

The tab widget is now displayed vertically beside the menu items
and changes the current tab on hover.

Location:
Orange/OrangeCanvas
Files:
1 added
2 edited

Legend:

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

    r11489 r11491  
    2121    QStandardItemModel, QSortFilterProxyModel, QStyleOptionToolButton, 
    2222    QStylePainter, QStyle, QApplication, QStyledItemDelegate, 
    23     QStyleOptionViewItemV4, QSizeGrip, QKeySequence 
     23    QStyleOptionViewItemV4, QSizeGrip 
    2424) 
    2525 
     
    3535from ..gui.lineedit import LineEdit 
    3636from ..gui.tooltree import ToolTree, FlattenedTreeItemModel 
     37from ..gui.toolgrid import ToolButtonEventListener 
     38from ..gui.toolbox import create_tab_gradient 
    3739from ..gui.utils import StyledWidget_paintEvent 
    3840 
     
    4244 
    4345log = logging.getLogger(__name__) 
     46 
     47 
     48class _MenuItemDelegate(QStyledItemDelegate): 
     49    def __init__(self, parent=None): 
     50        QStyledItemDelegate.__init__(self, parent) 
     51 
     52    def sizeHint(self, option, index): 
     53        option = QStyleOptionViewItemV4(option) 
     54        self.initStyleOption(option, index) 
     55        size = QStyledItemDelegate.sizeHint(self, option, index) 
     56 
     57        # TODO: get the default QMenu item height from the current style. 
     58        size.setHeight(max(size.height(), 25)) 
     59        return size 
    4460 
    4561 
     
    6379        self.__icon = icon 
    6480 
     81        self.view().setItemDelegate(_MenuItemDelegate(self.view())) 
    6582        # Make sure the initial model is wrapped in a ItemDisableFilter. 
    6683        self.setModel(self.model()) 
     
    341358 
    342359    def paintEvent(self, event): 
     360        opt = QStyleOptionToolButton() 
     361        self.initStyleOption(opt) 
     362        opt.features |= QStyleOptionToolButton.HasMenu 
    343363        if self.__flat: 
    344364            # Use default widget background/border styling. 
    345365            StyledWidget_paintEvent(self, event) 
    346366 
    347             opt = QStyleOptionToolButton() 
    348             self.initStyleOption(opt) 
    349367            p = QStylePainter(self) 
    350368            p.drawControl(QStyle.CE_ToolButtonLabel, opt) 
    351369        else: 
    352             QToolButton.paintEvent(self, event) 
    353  
     370            p = QStylePainter(self) 
     371            p.drawComplexControl(QStyle.CC_ToolButton, opt) 
     372 
     373    def sizeHint(self): 
     374        opt = QStyleOptionToolButton() 
     375        self.initStyleOption(opt) 
     376        opt.features |= QStyleOptionToolButton.HasMenu 
     377        style = self.style() 
     378 
     379        hint = style.sizeFromContents(QStyle.CT_ToolButton, opt, 
     380                                      opt.iconSize, self) 
     381        return hint 
    354382 
    355383_Tab = \ 
     
    364392 
    365393 
    366 # TODO: ..application.canvastooldock.QuickCategoryToolbar is very similar, 
    367 #       to TobBarWidget. Maybe common functionality could factored our. 
    368  
    369394class TabBarWidget(QWidget): 
    370395    """ 
     
    377402    def __init__(self, parent=None, **kwargs): 
    378403        QWidget.__init__(self, parent, **kwargs) 
    379         layout = QHBoxLayout() 
     404        layout = QVBoxLayout() 
    380405        layout.setContentsMargins(0, 0, 0, 0) 
    381406        layout.setSpacing(0) 
    382407        self.setLayout(layout) 
    383408 
    384         self.setSizePolicy(QSizePolicy.Expanding, 
    385                            QSizePolicy.Fixed) 
     409        self.setSizePolicy(QSizePolicy.Fixed, 
     410                           QSizePolicy.Expanding) 
    386411        self.__tabs = [] 
     412 
    387413        self.__currentIndex = -1 
     414        self.__changeOnHover = False 
     415 
     416        self.__iconSize = QSize(26, 26) 
     417 
    388418        self.__group = QButtonGroup(self, exclusive=True) 
    389419        self.__group.buttonPressed[QAbstractButton].connect( 
     
    391421        ) 
    392422 
     423        self.__hoverListener = ToolButtonEventListener(self) 
     424 
     425    def setChangeOnHover(self, changeOnHover): 
     426        """ 
     427        If set to ``True`` the tab widget will change the current index when 
     428        the mouse hovers over a tab button. 
     429 
     430        """ 
     431        if self.__changeOnHover != changeOnHover: 
     432            self.__changeOnHover = changeOnHover 
     433 
     434            if changeOnHover: 
     435                self.__hoverListener.buttonEnter.connect( 
     436                    self.__onButtonEnter 
     437                ) 
     438            else: 
     439                self.__hoverListener.buttonEnter.disconnect( 
     440                    self.__onButtonEnter 
     441                ) 
     442 
     443    def changeOnHover(self): 
     444        """ 
     445        Does the current tab index follow the mouse cursor. 
     446        """ 
     447        return self.__changeOnHover 
     448 
    393449    def count(self): 
    394450        """ 
     
    410466        button.setSizePolicy(QSizePolicy.Expanding, 
    411467                             QSizePolicy.Expanding) 
     468        button.setIconSize(self.__iconSize) 
    412469 
    413470        self.__group.addButton(button) 
     471 
     472        button.installEventFilter(self.__hoverListener) 
     473 
    414474        tab = _Tab(text, icon, toolTip, button, None, None) 
    415475        self.layout().insertWidget(index, button) 
     
    430490            tab = self.__tabs.pop(index) 
    431491            self.__group.removeButton(tab.button) 
     492 
     493            tab.button.removeEventFilter(self.__hoverListener) 
     494 
    432495            tab.button.deleteLater() 
    433496 
     
    490553        return self.__tabs[index].button 
    491554 
     555    def setIconSize(self, size): 
     556        if self.__iconSize != size: 
     557            self.__iconSize = size 
     558            for tab in self.__tabs: 
     559                tab.button.setIconSize(self.__iconSize) 
     560 
    492561    def __updateTab(self, index): 
    493562        """ 
     
    515584                break 
    516585 
     586    def __onButtonEnter(self, button): 
     587        if self.__changeOnHover: 
     588            button.click() 
     589 
    517590 
    518591class PagedMenu(QWidget): 
     
    531604        self.__currentIndex = -1 
    532605 
    533         layout = QVBoxLayout() 
     606        layout = QHBoxLayout() 
    534607        layout.setContentsMargins(0, 0, 0, 0) 
    535608        layout.setSpacing(0) 
    536609 
    537610        self.__tab = TabBarWidget(self) 
    538         self.__tab.setFixedHeight(25) 
    539611        self.__tab.currentChanged.connect(self.setCurrentIndex) 
     612        self.__tab.setChangeOnHover(True) 
    540613 
    541614        self.__stack = MenuStackWidget(self) 
    542615 
    543         layout.addWidget(self.__tab) 
     616        layout.addWidget(self.__tab, alignment=Qt.AlignTop) 
    544617        layout.addWidget(self.__stack) 
    545618 
     
    659732        self.layout().setContentsMargins(6, 6, 6, 6) 
    660733 
     734        self.__search = SearchWidget(self, objectName="search-line") 
     735 
     736        self.__search.setPlaceholderText( 
     737            self.tr("Search for widget or select from the list.") 
     738        ) 
     739 
     740        self.layout().addWidget(self.__search) 
     741 
    661742        self.__frame = QFrame(self, objectName="menu-frame") 
    662743        layout = QVBoxLayout() 
    663         layout.setContentsMargins(1, 1, 1, 1) 
     744        layout.setContentsMargins(0, 0, 0, 0) 
    664745        layout.setSpacing(2) 
    665746        self.__frame.setLayout(layout) 
     
    674755        self.__frame.layout().addWidget(self.__pages) 
    675756 
    676         self.__search = SearchWidget(self, objectName="search-line") 
    677  
    678         self.__search.setPlaceholderText( 
    679             self.tr("Search for widget or select from the list.") 
    680         ) 
    681  
    682         self.layout().addWidget(self.__search) 
    683757        self.setSizePolicy(QSizePolicy.Fixed, 
    684758                           QSizePolicy.Expanding) 
     
    691765            view = self.__suggestPage.view() 
    692766            view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) 
    693             # Don't show the focus frame because it expands into the tab 
    694             # bar at the top. 
     767            # Don't show the focus frame because it expands into the tab bar. 
    695768            view.setAttribute(Qt.WA_MacShowFocusRect, False) 
    696769 
    697         self.addPage(self.tr("Quick Search"), self.__suggestPage) 
     770        i = self.addPage(self.tr("Quick Search"), self.__suggestPage) 
     771        button = self.__pages.tabButton(i) 
     772        button.setObjectName("search-tab-button") 
     773        button.setStyleSheet( 
     774            "TabButton {\n" 
     775            "    qproperty-flat_: false;\n" 
     776            "    border: none;" 
     777            "}\n") 
    698778 
    699779        self.__search.textEdited.connect(self.__on_textEdited) 
     
    756836        """ 
    757837        page = MenuPage(self) 
    758         view = page.view() 
    759         delegate = WidgetItemDelegate(view) 
    760         view.setItemDelegate(delegate) 
    761838 
    762839        page.setModel(index.model()) 
     
    797874            if brush.isValid(): 
    798875                brush = brush.toPyObject() 
     876                base_color = brush.color() 
    799877                button = self.__pages.tabButton(i) 
    800                 palette = button.palette() 
    801878                button.setStyleSheet( 
    802879                    "TabButton {\n" 
    803880                    "    qproperty-flat_: false;\n" 
    804                     "    background-color: %s;\n" 
     881                    "    background: %s;\n" 
    805882                    "    border: none;\n" 
     883                    "    border-bottom: 1px solid palette(dark);\n" 
    806884                    "}\n" 
    807885                    "TabButton:checked {\n" 
    808                     "    border: 1px solid %s;\n" 
    809                     "}" % (brush.color().name(), 
    810                            palette.color(palette.Mid).name()) 
     886                    "    background: %s\n" 
     887                    "}" % (create_css_gradient(base_color), 
     888                           create_css_gradient(base_color.darker(110))) 
    811889                ) 
    812890 
     
    9761054 
    9771055        return FramelessWindow.eventFilter(self, obj, event) 
    978  
    979  
    980 class WidgetItemDelegate(QStyledItemDelegate): 
    981     def __init__(self, parent=None): 
    982         QStyledItemDelegate.__init__(self, parent) 
    983  
    984     def sizeHint(self, option, index): 
    985         option = QStyleOptionViewItemV4(option) 
    986         self.initStyleOption(option, index) 
    987         size = QStyledItemDelegate.sizeHint(self, option, index) 
    988         size.setHeight(max(size.height(), 25)) 
    989         return size 
    9901056 
    9911057 
     
    11541220 
    11551221        self.move(x, y) 
     1222 
     1223 
     1224def create_css_gradient(base_color): 
     1225    """ 
     1226    Create a Qt css linear gradient fragment based on the `base_color`. 
     1227    """ 
     1228    grad = create_tab_gradient(base_color) 
     1229    stops = grad.stops() 
     1230    stops = "\n".join("    stop: {0:f} {1}".format(stop, color.name()) 
     1231                      for stop, color in stops) 
     1232    return ("qlineargradient(\n" 
     1233            "    x1: 0, y1: 0, x2: 0, y2: 1,\n" 
     1234            "{0})").format(stops) 
  • Orange/OrangeCanvas/styles/orange.qss

    r11412 r11491  
    359359 
    360360QuickMenu ToolTree QTreeView::item { 
    361     height: 25px; 
    362     border-top: 1px solid #e9eff2; 
    363     border-bottom: 1px solid #e9eff2; 
     361    height: 25px; 
     362    border-bottom: 1px solid #e9eff2; 
    364363} 
    365364 
    366365QuickMenu QTreeView::item:hover { 
    367     background-color: lightblue; 
    368     color: white; 
     366    background: qlineargradient( 
     367        x1: 0, y1: 0, x2: 0, y2: 1, 
     368        stop: 0 #688EF6, 
     369        stop: 0.5 #4047f4, 
     370        stop: 1.0 #2D68F3 
     371    ); 
     372    color: white; 
    369373} 
    370374 
    371375QuickMenu QTreeView::item:selected { 
    372     background-color: blue; 
    373     color: white; 
    374 } 
    375  
    376 /* Quick Menu search line edit  
     376    background-color: blue; 
     377    color: white; 
     378} 
     379 
     380QuickMenu TabBarWidget QToolButton { 
     381    width: 33px; 
     382    height: 25px; 
     383    border-bottom: 1px solid palette(dark); 
     384    padding-right: 5px; 
     385} 
     386 
     387QuickMenu TabBarWidget QToolButton#search-tab-button { 
     388    background-color: #9CACB4; 
     389} 
     390 
     391QuickMenu TabBarWidget QToolButton:menu-indicator { 
     392    image: url(canvas_icons:/arrow-right.svg); 
     393    subcontrol-position: center right; 
     394    height: 8px; 
     395    width: 8px; 
     396} 
     397 
     398/* Quick Menu search line edit 
    377399 */ 
    378400 
Note: See TracChangeset for help on using the changeset viewer.