Ignore:
Location:
Orange/OrangeCanvas
Files:
1 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • Orange/OrangeCanvas/application/canvasmain.py

    r11496 r11479  
    1616    QMainWindow, QWidget, QAction, QActionGroup, QMenu, QMenuBar, QDialog, 
    1717    QFileDialog, QMessageBox, QVBoxLayout, QSizePolicy, QColor, QKeySequence, 
    18     QIcon, QToolBar, QToolButton, QDockWidget, QDesktopServices, QApplication, 
    19     QCursor 
     18    QIcon, QToolBar, QToolButton, QDockWidget, QDesktopServices, QApplication 
    2019) 
    2120 
     
    4140from ..help import HelpManager 
    4241 
    43 from .canvastooldock import CanvasToolDock, QuickCategoryToolbar, \ 
    44                             CategoryPopupMenu 
     42from .canvastooldock import CanvasToolDock, QuickCategoryToolbar 
    4543from .aboutdialog import AboutDialog 
    4644from .schemeinfo import SchemeInfoDialog 
     
    771769        """ 
    772770        category = action.text() 
    773         if self.use_popover: 
    774             # Show a popup menu with the widgets in the category 
    775             m = CategoryPopupMenu(self.quick_category) 
    776             reg = self.widget_registry.model() 
    777             i = index(self.widget_registry.categories(), category, 
    778                       predicate=lambda name, cat: cat.name == name) 
    779             if i != -1: 
    780                 m.setCategoryItem(reg.item(i)) 
    781                 action = m.exec_(QCursor.pos()) 
    782                 if action is not None: 
    783                     self.on_tool_box_widget_activated(action) 
    784  
    785         else: 
    786             for i in range(self.widgets_tool_box.count()): 
    787                 cat_act = self.widgets_tool_box.tabAction(i) 
    788                 cat_act.setChecked(cat_act.text() == category) 
    789  
    790             self.dock_widget.expand() 
     771        for i in range(self.widgets_tool_box.count()): 
     772            cat_act = self.widgets_tool_box.tabAction(i) 
     773            if cat_act.text() == category: 
     774                if not cat_act.isChecked(): 
     775                    # Trigger the action to expand the tool grid contained 
     776                    # within. 
     777                    cat_act.trigger() 
     778 
     779            else: 
     780                if cat_act.isChecked(): 
     781                    # Trigger the action to hide the tool grid contained 
     782                    # within. 
     783                    cat_act.trigger() 
     784 
     785        self.dock_widget.expand() 
    791786 
    792787    def set_scheme_margins_enabled(self, enabled): 
     
    969964        scheme_doc.setScheme(new_scheme) 
    970965 
    971         # Send a close event to the Scheme, it is responsible for 
    972         # closing/clearing all resources (widgets). 
    973         QApplication.sendEvent(old_scheme, QEvent(QEvent.Close)) 
    974  
     966        old_scheme.save_widget_settings() 
     967        old_scheme.close_all_open_widgets() 
     968        old_scheme.signal_manager.stop() 
    975969        old_scheme.deleteLater() 
    976970 
     
    15401534                return 
    15411535 
    1542         old_scheme = document.scheme() 
    1543  
    15441536        # Set an empty scheme to clear the document 
    15451537        document.setScheme(widgetsscheme.WidgetsScheme()) 
    15461538 
    1547         QApplication.sendEvent(old_scheme, QEvent(QEvent.Close)) 
    1548  
    1549         old_scheme.deleteLater() 
     1539        scheme = document.scheme() 
     1540        scheme.save_widget_settings() 
     1541        scheme.close_all_open_widgets() 
     1542        scheme.signal_manager.stop() 
     1543        scheme.deleteLater() 
    15501544 
    15511545        config.save_config() 
     
    17151709            triggers |= SchemeEditWidget.DoubleClicked 
    17161710 
    1717         right_click = settings.value("trigger-on-right-click", 
     1711        left_click = settings.value("trigger-on-left-click", 
    17181712                                    defaultValue=False, 
    17191713                                    type=bool) 
    1720         if right_click: 
    1721             triggers |= SchemeEditWidget.RightClicked 
     1714        if left_click: 
     1715            triggers |= SchemeEditWidget.Clicked 
    17221716 
    17231717        space_press = settings.value("trigger-on-space-key", 
     
    17831777        self.open_in_external_browser = \ 
    17841778            settings.value("open-in-external-browser", defaultValue=False, 
    1785                            type=bool) 
    1786  
    1787         self.use_popover = \ 
    1788             settings.value("toolbox-dock-use-popover-menu", defaultValue=True, 
    17891779                           type=bool) 
    17901780 
  • Orange/OrangeCanvas/application/canvastooldock.py

    r11495 r11243  
    33 
    44""" 
    5 import sys 
    6  
    75from PyQt4.QtGui import ( 
    86    QWidget, QSplitter, QVBoxLayout, QTextEdit, QAction, QPalette, 
    9     QSizePolicy, QApplication, QDrag 
     7    QSizePolicy 
    108) 
    119 
    12 from PyQt4.QtCore import ( 
    13     Qt, QSize, QObject, QPropertyAnimation, QEvent, QRect, 
    14     QModelIndex, QPersistentModelIndex, QEventLoop, QMimeData 
    15 ) 
    16  
    17 from PyQt4.QtCore import pyqtProperty as Property, pyqtSignal as Signal 
     10from PyQt4.QtCore import Qt, QSize, QObject, QPropertyAnimation, QEvent 
     11from PyQt4.QtCore import pyqtProperty as Property 
    1812 
    1913from ..gui.toolgrid import ToolGrid 
    2014from ..gui.toolbar import DynamicResizeToolBar 
    2115from ..gui.quickhelp import QuickHelp 
    22 from ..gui.framelesswindow import FramelessWindow 
    23 from ..document.quickmenu import MenuPage 
    2416from .widgettoolbox import WidgetToolBox, iter_item 
    2517 
    2618from ..registry.qt import QtWidgetRegistry 
    27 from ..utils.qtcompat import toPyObject 
    2819 
    2920 
     
    346337                action = self._gridSlots[index].action 
    347338                self.removeAction(action) 
    348  
    349  
    350 class CategoryPopupMenu(FramelessWindow): 
    351     triggered = Signal(QAction) 
    352     hovered = Signal(QAction) 
    353  
    354     def __init__(self, parent=None, **kwargs): 
    355         FramelessWindow.__init__(self, parent, **kwargs) 
    356         self.setWindowFlags(self.windowFlags() | Qt.Popup) 
    357  
    358         layout = QVBoxLayout() 
    359         layout.setContentsMargins(6, 6, 6, 6) 
    360  
    361         self.__menu = MenuPage() 
    362         self.__menu.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) 
    363  
    364         if sys.platform == "darwin": 
    365             self.__menu.view().setAttribute(Qt.WA_MacShowFocusRect, False) 
    366  
    367         self.__menu.triggered.connect(self.__onTriggered) 
    368         self.__menu.hovered.connect(self.hovered) 
    369  
    370         self.__dragListener = ItemViewDragStartEventListener(self) 
    371         self.__dragListener.dragStarted.connect(self.__onDragStarted) 
    372  
    373         self.__menu.view().viewport().installEventFilter(self.__dragListener) 
    374  
    375         layout.addWidget(self.__menu) 
    376  
    377         self.setLayout(layout) 
    378  
    379         self.__action = None 
    380         self.__loop = None 
    381         self.__item = None 
    382  
    383     def setCategoryItem(self, item): 
    384         """ 
    385         Set the category root item (:class:`QStandardItem`). 
    386         """ 
    387         self.__item = item 
    388         model = item.model() 
    389         self.__menu.setModel(model) 
    390         self.__menu.setRootIndex(item.index()) 
    391  
    392     def popup(self, pos=None): 
    393         if pos is None: 
    394             pos = self.pos() 
    395         geom = widget_popup_geometry(pos, self) 
    396         self.setGeometry(geom) 
    397         self.show() 
    398  
    399     def exec_(self, pos=None): 
    400         self.popup(pos) 
    401         self.__loop = QEventLoop() 
    402  
    403         self.__action = None 
    404         self.__loop.exec_() 
    405         self.__loop = None 
    406  
    407         if self.__action is not None: 
    408             action = self.__action 
    409         else: 
    410             action = None 
    411         return action 
    412  
    413     def hideEvent(self, event): 
    414         if self.__loop is not None: 
    415             self.__loop.exit(0) 
    416  
    417         return FramelessWindow.hideEvent(self, event) 
    418  
    419     def __onTriggered(self, action): 
    420         self.__action = action 
    421         self.triggered.emit(action) 
    422         self.hide() 
    423  
    424         if self.__loop: 
    425             self.__loop.exit(0) 
    426  
    427     def __onDragStarted(self, index): 
    428         desc = toPyObject(index.data(QtWidgetRegistry.WIDGET_DESC_ROLE)) 
    429         icon = toPyObject(index.data(Qt.DecorationRole)) 
    430  
    431         drag_data = QMimeData() 
    432         drag_data.setData( 
    433             "application/vnv.orange-canvas.registry.qualified-name", 
    434             desc.qualified_name 
    435         ) 
    436         drag = QDrag(self) 
    437         drag.setPixmap(icon.pixmap(38)) 
    438         drag.setMimeData(drag_data) 
    439  
    440         # TODO: Should animate (accept) hide. 
    441         self.hide() 
    442  
    443         # When a drag is started and the menu hidden the item's tool tip 
    444         # can still show for a short time UNDER the cursor preventing a 
    445         # drop. 
    446         viewport = self.__menu.view().viewport() 
    447         filter = ToolTipEventFilter() 
    448         viewport.installEventFilter(filter) 
    449  
    450         drag.exec_(Qt.CopyAction) 
    451  
    452         viewport.removeEventFilter(filter) 
    453  
    454  
    455 class ItemViewDragStartEventListener(QObject): 
    456     dragStarted = Signal(QModelIndex) 
    457  
    458     def __init__(self, parent=None): 
    459         QObject.__init__(self, parent) 
    460         self._pos = None 
    461         self._index = None 
    462  
    463     def eventFilter(self, viewport, event): 
    464         view = viewport.parent() 
    465  
    466         if event.type() == QEvent.MouseButtonPress and \ 
    467                 event.button() == Qt.LeftButton: 
    468  
    469             index = view.indexAt(event.pos()) 
    470  
    471             if index is not None: 
    472                 self._pos = event.pos() 
    473                 self._index = QPersistentModelIndex(index) 
    474  
    475         elif event.type() == QEvent.MouseMove and self._pos is not None and \ 
    476                 ((self._pos - event.pos()).manhattanLength() >= 
    477                  QApplication.startDragDistance()): 
    478  
    479             if self._index.isValid(): 
    480                 # Map to a QModelIndex in the model. 
    481                 index = self._index 
    482                 index = index.model().index(index.row(), index.column(), 
    483                                             index.parent()) 
    484                 self._pos = None 
    485                 self._index = None 
    486  
    487                 self.dragStarted.emit(index) 
    488  
    489         return QObject.eventFilter(self, view, event) 
    490  
    491  
    492 class ToolTipEventFilter(QObject): 
    493     def eventFilter(self, receiver, event): 
    494         if event.type() == QEvent.ToolTip: 
    495             return True 
    496  
    497         return QObject.eventFilter(self, receiver, event) 
    498  
    499  
    500 def widget_popup_geometry(pos, widget): 
    501     widget.ensurePolished() 
    502  
    503     if widget.testAttribute(Qt.WA_Resized): 
    504         size = widget.size() 
    505     else: 
    506         size = widget.sizeHint() 
    507  
    508     desktop = QApplication.desktop() 
    509     screen_geom = desktop.availableGeometry(pos) 
    510  
    511     # Adjust the size to fit inside the screen. 
    512     if size.height() > screen_geom.height(): 
    513         size.setHeight(screen_geom.height()) 
    514     if size.width() > screen_geom.width(): 
    515         size.setWidth(screen_geom.width()) 
    516  
    517     geom = QRect(pos, size) 
    518  
    519     if geom.top() < screen_geom.top(): 
    520         geom.setTop(screen_geom.top()) 
    521  
    522     if geom.left() < screen_geom.left(): 
    523         geom.setLeft(screen_geom.left()) 
    524  
    525     bottom_margin = screen_geom.bottom() - geom.bottom() 
    526     right_margin = screen_geom.right() - geom.right() 
    527     if bottom_margin < 0: 
    528         # Falls over the bottom of the screen, move it up. 
    529         geom.translate(0, bottom_margin) 
    530  
    531     # TODO: right to left locale 
    532     if right_margin < 0: 
    533         # Falls over the right screen edge, move the menu to the 
    534         # other side of pos. 
    535         geom.translate(-size.width(), 0) 
    536  
    537     return geom 
  • Orange/OrangeCanvas/application/settings.py

    r11488 r11416  
    274274                                        "on an empty spot in the canvas")) 
    275275 
    276         cb2 = QCheckBox(self.tr("On right click"), 
    277                         toolTip=self.tr("Open quick menu on a right click " 
     276        cb2 = QCheckBox(self.tr("On left click"), 
     277                        toolTip=self.tr("Open quick menu on a left click " 
    278278                                        "on an empty spot in the canvas")) 
    279279 
     
    287287 
    288288        self.bind(cb1, "checked", "quickmenu/trigger-on-double-click") 
    289         self.bind(cb2, "checked", "quickmenu/trigger-on-right-click") 
     289        self.bind(cb2, "checked", "quickmenu/trigger-on-left-click") 
    290290        self.bind(cb3, "checked", "quickmenu/trigger-on-space-key") 
    291291        self.bind(cb4, "checked", "quickmenu/trigger-on-any-key") 
  • Orange/OrangeCanvas/config.py

    r11496 r11476  
    7171      "Is the canvas toolbox movable (between left and right edge)"), 
    7272 
    73      ("mainwindow/toolbox-dock-use-popover-menu", bool, True, 
    74       "Use a popover menu to select a widget when clicking on a category " 
    75       "button"), 
    76  
    7773     ("mainwindow/number-of-recent-schemes", int, 7, 
    7874      "Number of recent schemes to keep in history"), 
     
    9389      "Show quick menu on double click."), 
    9490 
    95      ("quickmenu/trigger-on-right-click", bool, True, 
    96       "Show quick menu on right click."), 
     91     ("quickmenu/trigger-on-left-click", bool, False, 
     92      "Show quick menu on left click."), 
    9793 
    9894     ("quickmenu/trigger-on-space-key", bool, True, 
  • Orange/OrangeCanvas/document/interactions.py

    r11490 r11450  
    760760            self.end() 
    761761 
    762     def create_new(self, pos, search_text=""): 
     762    def create_new(self, pos): 
    763763        """ 
    764764        Create a new widget with a `QuickMenu` at `pos` (in screen 
     
    769769        menu.setFilterFunc(None) 
    770770 
    771         action = menu.exec_(pos, search_text) 
     771        action = menu.exec_(pos) 
    772772        if action: 
    773773            item = action.property("item").toPyObject() 
  • Orange/OrangeCanvas/document/quickmenu.py

    r11494 r11462  
    2121    QStandardItemModel, QSortFilterProxyModel, QStyleOptionToolButton, 
    2222    QStylePainter, QStyle, QApplication, QStyledItemDelegate, 
    23     QStyleOptionViewItemV4, QSizeGrip 
     23    QStyleOptionViewItemV4, QSizeGrip, QKeySequence 
    2424) 
    2525 
     
    3535from ..gui.lineedit import LineEdit 
    3636from ..gui.tooltree import ToolTree, FlattenedTreeItemModel 
    37 from ..gui.toolgrid import ToolButtonEventListener 
    38 from ..gui.toolbox import create_tab_gradient 
    3937from ..gui.utils import StyledWidget_paintEvent 
    4038 
     
    4442 
    4543log = logging.getLogger(__name__) 
    46  
    47  
    48 class _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 
    6044 
    6145 
     
    7963        self.__icon = icon 
    8064 
    81         self.view().setItemDelegate(_MenuItemDelegate(self.view())) 
    8265        # Make sure the initial model is wrapped in a ItemDisableFilter. 
    8366        self.setModel(self.model()) 
     
    150133        proxyModel = self.view().model() 
    151134        return proxyModel.mapToSource(ToolTree.rootIndex(self)) 
    152  
    153     def sizeHint(self): 
    154         view = self.view() 
    155         hint = view.sizeHint() 
    156         model = view.model() 
    157  
    158         # This will not work for nested items (tree). 
    159         count = model.rowCount(view.rootIndex()) 
    160  
    161         width = view.sizeHintForColumn(0) 
    162  
    163         if count: 
    164             height = view.sizeHintForRow(0) 
    165             height = height * count 
    166         else: 
    167             height = hint.height() 
    168         return QSize(max(width, hint.width()), max(height, hint.height())) 
    169135 
    170136 
     
    327293        widget_hints = [default_size] 
    328294        for i in range(self.count()): 
    329             hint = self.widget(i).sizeHint() 
     295            w = self.widget(i) 
     296            if isinstance(w, ToolTree): 
     297                hint = self.__sizeHintForTreeView(w.view()) 
     298            else: 
     299                hint = w.sizeHint() 
    330300            widget_hints.append(hint) 
    331  
    332301        width = max([s.width() for s in widget_hints]) 
    333302        # Take the median for the height 
     
    372341 
    373342    def paintEvent(self, event): 
    374         opt = QStyleOptionToolButton() 
    375         self.initStyleOption(opt) 
    376         opt.features |= QStyleOptionToolButton.HasMenu 
    377343        if self.__flat: 
    378344            # Use default widget background/border styling. 
    379345            StyledWidget_paintEvent(self, event) 
    380346 
     347            opt = QStyleOptionToolButton() 
     348            self.initStyleOption(opt) 
    381349            p = QStylePainter(self) 
    382350            p.drawControl(QStyle.CE_ToolButtonLabel, opt) 
    383351        else: 
    384             p = QStylePainter(self) 
    385             p.drawComplexControl(QStyle.CC_ToolButton, opt) 
    386  
    387     def sizeHint(self): 
    388         opt = QStyleOptionToolButton() 
    389         self.initStyleOption(opt) 
    390         opt.features |= QStyleOptionToolButton.HasMenu 
    391         style = self.style() 
    392  
    393         hint = style.sizeFromContents(QStyle.CT_ToolButton, opt, 
    394                                       opt.iconSize, self) 
    395         return hint 
     352            QToolButton.paintEvent(self, event) 
     353 
    396354 
    397355_Tab = \ 
     
    406364 
    407365 
     366# TODO: ..application.canvastooldock.QuickCategoryToolbar is very similar, 
     367#       to TobBarWidget. Maybe common functionality could factored our. 
     368 
    408369class TabBarWidget(QWidget): 
    409370    """ 
     
    416377    def __init__(self, parent=None, **kwargs): 
    417378        QWidget.__init__(self, parent, **kwargs) 
    418         layout = QVBoxLayout() 
     379        layout = QHBoxLayout() 
    419380        layout.setContentsMargins(0, 0, 0, 0) 
    420381        layout.setSpacing(0) 
    421382        self.setLayout(layout) 
    422383 
    423         self.setSizePolicy(QSizePolicy.Fixed, 
    424                            QSizePolicy.Expanding) 
     384        self.setSizePolicy(QSizePolicy.Expanding, 
     385                           QSizePolicy.Fixed) 
    425386        self.__tabs = [] 
    426  
    427387        self.__currentIndex = -1 
    428         self.__changeOnHover = False 
    429  
    430         self.__iconSize = QSize(26, 26) 
    431  
    432388        self.__group = QButtonGroup(self, exclusive=True) 
    433389        self.__group.buttonPressed[QAbstractButton].connect( 
     
    435391        ) 
    436392 
    437         self.__hoverListener = ToolButtonEventListener(self) 
    438  
    439     def setChangeOnHover(self, changeOnHover): 
    440         """ 
    441         If set to ``True`` the tab widget will change the current index when 
    442         the mouse hovers over a tab button. 
    443  
    444         """ 
    445         if self.__changeOnHover != changeOnHover: 
    446             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                 ) 
    456  
    457     def changeOnHover(self): 
    458         """ 
    459         Does the current tab index follow the mouse cursor. 
    460         """ 
    461         return self.__changeOnHover 
    462  
    463393    def count(self): 
    464394        """ 
     
    480410        button.setSizePolicy(QSizePolicy.Expanding, 
    481411                             QSizePolicy.Expanding) 
    482         button.setIconSize(self.__iconSize) 
    483412 
    484413        self.__group.addButton(button) 
    485  
    486         button.installEventFilter(self.__hoverListener) 
    487  
    488414        tab = _Tab(text, icon, toolTip, button, None, None) 
    489415        self.layout().insertWidget(index, button) 
     
    504430            tab = self.__tabs.pop(index) 
    505431            self.__group.removeButton(tab.button) 
    506  
    507             tab.button.removeEventFilter(self.__hoverListener) 
    508  
    509432            tab.button.deleteLater() 
    510433 
     
    567490        return self.__tabs[index].button 
    568491 
    569     def setIconSize(self, size): 
    570         if self.__iconSize != size: 
    571             self.__iconSize = size 
    572             for tab in self.__tabs: 
    573                 tab.button.setIconSize(self.__iconSize) 
    574  
    575492    def __updateTab(self, index): 
    576493        """ 
     
    598515                break 
    599516 
    600     def __onButtonEnter(self, button): 
    601         if self.__changeOnHover: 
    602             button.click() 
    603  
    604517 
    605518class PagedMenu(QWidget): 
     
    618531        self.__currentIndex = -1 
    619532 
    620         layout = QHBoxLayout() 
     533        layout = QVBoxLayout() 
    621534        layout.setContentsMargins(0, 0, 0, 0) 
    622535        layout.setSpacing(0) 
    623536 
    624537        self.__tab = TabBarWidget(self) 
     538        self.__tab.setFixedHeight(25) 
    625539        self.__tab.currentChanged.connect(self.setCurrentIndex) 
    626         self.__tab.setChangeOnHover(True) 
    627540 
    628541        self.__stack = MenuStackWidget(self) 
    629542 
    630         layout.addWidget(self.__tab, alignment=Qt.AlignTop) 
     543        layout.addWidget(self.__tab) 
    631544        layout.addWidget(self.__stack) 
    632545 
     
    746659        self.layout().setContentsMargins(6, 6, 6, 6) 
    747660 
    748         self.__search = SearchWidget(self, objectName="search-line") 
    749  
    750         self.__search.setPlaceholderText( 
    751             self.tr("Search for widget or select from the list.") 
    752         ) 
    753  
    754         self.layout().addWidget(self.__search) 
    755  
    756661        self.__frame = QFrame(self, objectName="menu-frame") 
    757662        layout = QVBoxLayout() 
    758         layout.setContentsMargins(0, 0, 0, 0) 
     663        layout.setContentsMargins(1, 1, 1, 1) 
    759664        layout.setSpacing(2) 
    760665        self.__frame.setLayout(layout) 
     
    769674        self.__frame.layout().addWidget(self.__pages) 
    770675 
     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) 
    771683        self.setSizePolicy(QSizePolicy.Fixed, 
    772684                           QSizePolicy.Expanding) 
     
    779691            view = self.__suggestPage.view() 
    780692            view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) 
    781             # Don't show the focus frame because it expands into the tab bar. 
     693            # Don't show the focus frame because it expands into the tab 
     694            # bar at the top. 
    782695            view.setAttribute(Qt.WA_MacShowFocusRect, False) 
    783696 
    784         i = self.addPage(self.tr("Quick Search"), self.__suggestPage) 
    785         button = self.__pages.tabButton(i) 
    786         button.setObjectName("search-tab-button") 
    787         button.setStyleSheet( 
    788             "TabButton {\n" 
    789             "    qproperty-flat_: false;\n" 
    790             "    border: none;" 
    791             "}\n") 
     697        self.addPage(self.tr("Quick Search"), self.__suggestPage) 
    792698 
    793699        self.__search.textEdited.connect(self.__on_textEdited) 
     
    850756        """ 
    851757        page = MenuPage(self) 
     758        view = page.view() 
     759        delegate = WidgetItemDelegate(view) 
     760        view.setItemDelegate(delegate) 
    852761 
    853762        page.setModel(index.model()) 
     
    888797            if brush.isValid(): 
    889798                brush = brush.toPyObject() 
    890                 base_color = brush.color() 
    891799                button = self.__pages.tabButton(i) 
     800                palette = button.palette() 
    892801                button.setStyleSheet( 
    893802                    "TabButton {\n" 
    894803                    "    qproperty-flat_: false;\n" 
    895                     "    background: %s;\n" 
     804                    "    background-color: %s;\n" 
    896805                    "    border: none;\n" 
    897                     "    border-bottom: 1px solid palette(dark);\n" 
    898806                    "}\n" 
    899807                    "TabButton:checked {\n" 
    900                     "    background: %s\n" 
    901                     "}" % (create_css_gradient(base_color), 
    902                            create_css_gradient(base_color.darker(110))) 
     808                    "    border: 1px solid %s;\n" 
     809                    "}" % (brush.color().name(), 
     810                           palette.color(palette.Mid).name()) 
    903811                ) 
    904812 
     
    915823                self.__pages.page(i).setFilterFunc(func) 
    916824 
    917     def popup(self, pos=None, searchText=""): 
    918         """ 
    919         Popup the menu at `pos` (in screen coordinates). 'Search' text field 
    920         is initialized with `searchText` if provided. 
     825    def popup(self, pos=None): 
     826        """ 
     827        Popup the menu at `pos` (in screen coordinates). 
    921828        """ 
    922829        if pos is None: 
    923830            pos = QPoint() 
    924831 
    925         self.__search.setText(searchText) 
    926         self.__suggestPage.setFilterFixedString(searchText) 
     832        self.__search.setText("") 
     833        self.__suggestPage.setFilterFixedString("") 
    927834 
    928835        self.ensurePolished() 
     
    966873        self.show() 
    967874 
    968         if searchText: 
    969             self.setFocusProxy(self.__search) 
    970         else: 
    971             self.setFocusProxy(None) 
    972  
    973     def exec_(self, pos=None, searchText=""): 
     875    def exec_(self, pos=None): 
    974876        """ 
    975877        Execute the menu at position `pos` (in global screen coordinates). 
    976878        Return the triggered :class:`QAction` or `None` if no action was 
    977         triggered. 'Search' text field is initialized with `searchText` if 
    978         provided. 
    979  
    980         """ 
    981         self.popup(pos, searchText) 
     879        triggered. 
     880 
     881        """ 
     882        self.popup(pos) 
    982883        self.setFocus(Qt.PopupFocusReason) 
    983884 
     
    1068969 
    1069970        return FramelessWindow.eventFilter(self, obj, event) 
     971 
     972 
     973class WidgetItemDelegate(QStyledItemDelegate): 
     974    def __init__(self, parent=None): 
     975        QStyledItemDelegate.__init__(self, parent) 
     976 
     977    def sizeHint(self, option, index): 
     978        option = QStyleOptionViewItemV4(option) 
     979        self.initStyleOption(option, index) 
     980        size = QStyledItemDelegate.sizeHint(self, option, index) 
     981        size.setHeight(max(size.height(), 25)) 
     982        return size 
    1070983 
    1071984 
     
    12341147 
    12351148        self.move(x, y) 
    1236  
    1237  
    1238 def create_css_gradient(base_color): 
    1239     """ 
    1240     Create a Qt css linear gradient fragment based on the `base_color`. 
    1241     """ 
    1242     grad = create_tab_gradient(base_color) 
    1243     stops = grad.stops() 
    1244     stops = "\n".join("    stop: {0:f} {1}".format(stop, color.name()) 
    1245                       for stop, color in stops) 
    1246     return ("qlineargradient(\n" 
    1247             "    x1: 0, y1: 0, x2: 0, y2: 1,\n" 
    1248             "{0})").format(stops) 
  • Orange/OrangeCanvas/document/schemeedit.py

    r11492 r11471  
    1010import logging 
    1111import itertools 
    12 import unicodedata 
    1312 
    1413from operator import attrgetter 
     
    101100    # Quick Menu triggers 
    102101    (NoTriggers, 
    103      RightClicked, 
     102     Clicked, 
    104103     DoubleClicked, 
    105104     SpaceKey, 
     
    345344 
    346345        scene = CanvasScene() 
    347         self.__setupScene(scene) 
     346        scene.set_channel_names_visible(self.__channelNamesVisible) 
     347        scene.set_node_animation_enabled(self.__nodeAnimationEnabled) 
     348        scene.setFont(self.font()) 
    348349 
    349350        view = CanvasView(scene) 
     
    358359        self.__scene = scene 
    359360 
     361        self.__focusListener = GraphicsSceneFocusEventListener() 
     362        self.__focusListener.itemFocusedIn.connect(self.__onItemFocusedIn) 
     363        self.__focusListener.itemFocusedOut.connect(self.__onItemFocusedOut) 
     364        self.__scene.addItem(self.__focusListener) 
     365 
     366        self.__scene.selectionChanged.connect( 
     367            self.__onSelectionChanged 
     368        ) 
     369 
    360370        layout.addWidget(view) 
    361371        self.setLayout(layout) 
    362  
    363     def __setupScene(self, scene): 
    364         """ 
    365         Set up a :class:`CanvasScene` instance for use by the editor. 
    366  
    367         .. note:: If an existing scene is in use it must be teared down using 
    368             __teardownScene 
    369  
    370         """ 
    371         scene.set_channel_names_visible(self.__channelNamesVisible) 
    372         scene.set_node_animation_enabled( 
    373             self.__nodeAnimationEnabled 
    374         ) 
    375  
    376         scene.setFont(self.font()) 
    377  
    378         scene.installEventFilter(self) 
    379  
    380         scene.set_registry(self.__registry) 
    381  
    382         # Focus listener 
    383         self.__focusListener = GraphicsSceneFocusEventListener() 
    384         self.__focusListener.itemFocusedIn.connect( 
    385             self.__onItemFocusedIn 
    386         ) 
    387         self.__focusListener.itemFocusedOut.connect( 
    388             self.__onItemFocusedOut 
    389         ) 
    390         scene.addItem(self.__focusListener) 
    391  
    392         scene.selectionChanged.connect( 
    393             self.__onSelectionChanged 
    394         ) 
    395  
    396         scene.node_item_activated.connect( 
    397             self.__onNodeActivate 
    398         ) 
    399  
    400         scene.annotation_added.connect( 
    401             self.__onAnnotationAdded 
    402         ) 
    403  
    404         scene.annotation_removed.connect( 
    405             self.__onAnnotationRemoved 
    406         ) 
    407  
    408         self.__annotationGeomChanged = QSignalMapper(self) 
    409  
    410     def __teardownScene(self, scene): 
    411         """ 
    412         Tear down an instance of :class:`CanvasScene` that was used by the 
    413         editor. 
    414  
    415         """ 
    416         # Clear the current item selection in the scene so edit action 
    417         # states are updated accordingly. 
    418         scene.clearSelection() 
    419  
    420         # Clear focus from any item. 
    421         scene.setFocusItem(None) 
    422  
    423         # Clear the annotation mapper 
    424         self.__annotationGeomChanged.deleteLater() 
    425         self.__annotationGeomChanged = None 
    426  
    427         self.__focusListener.itemFocusedIn.disconnect( 
    428             self.__onItemFocusedIn 
    429         ) 
    430         self.__focusListener.itemFocusedOut.disconnect( 
    431             self.__onItemFocusedOut 
    432         ) 
    433  
    434         scene.selectionChanged.disconnect( 
    435             self.__onSelectionChanged 
    436         ) 
    437  
    438         scene.removeEventFilter(self) 
    439  
    440         # Clear all items from the scene 
    441         scene.blockSignals(True) 
    442         scene.clear_scene() 
    443372 
    444373    def toolbarActions(self): 
     
    511440 
    512441            - `SchemeEditWidget.NoTrigeres` 
    513             - `SchemeEditWidget.RightClicked` 
     442            - `SchemeEditWidget.Clicked` 
    514443            - `SchemeEditWidget.DoubleClicked` 
    515444            - `SchemeEditWidget.SpaceKey` 
     
    605534                self.__cleanSettings = [] 
    606535 
    607             self.__teardownScene(self.__scene) 
     536            # Clear the current item selection in the scene so edit action 
     537            # states are updated accordingly. 
     538            self.__scene.clearSelection() 
     539 
     540            self.__annotationGeomChanged.deleteLater() 
     541            self.__annotationGeomChanged = QSignalMapper(self) 
     542 
     543            self.__undoStack.clear() 
     544 
     545            self.__focusListener.itemFocusedIn.disconnect( 
     546                self.__onItemFocusedIn 
     547            ) 
     548            self.__focusListener.itemFocusedOut.disconnect( 
     549                self.__onItemFocusedOut 
     550            ) 
     551 
     552            self.__scene.selectionChanged.disconnect( 
     553                self.__onSelectionChanged 
     554            ) 
     555 
     556            self.__scene.removeEventFilter(self) 
     557 
     558            # Clear all items from the scene 
     559            self.__scene.blockSignals(True) 
     560            self.__scene.clear_scene() 
     561 
    608562            self.__scene.deleteLater() 
    609563 
    610             self.__undoStack.clear() 
    611  
    612564            self.__scene = CanvasScene() 
    613             self.__setupScene(self.__scene) 
    614  
    615565            self.__view.setScene(self.__scene) 
     566            self.__scene.set_channel_names_visible(self.__channelNamesVisible) 
     567            self.__scene.set_node_animation_enabled( 
     568                self.__nodeAnimationEnabled 
     569            ) 
     570 
     571            self.__scene.setFont(self.font()) 
     572 
     573            self.__scene.installEventFilter(self) 
     574 
     575            self.__scene.set_registry(self.__registry) 
     576 
     577            # Focus listener 
     578            self.__focusListener = GraphicsSceneFocusEventListener() 
     579            self.__focusListener.itemFocusedIn.connect( 
     580                self.__onItemFocusedIn 
     581            ) 
     582            self.__focusListener.itemFocusedOut.connect( 
     583                self.__onItemFocusedOut 
     584            ) 
     585            self.__scene.addItem(self.__focusListener) 
     586 
     587            self.__scene.selectionChanged.connect( 
     588                self.__onSelectionChanged 
     589            ) 
     590 
     591            self.__scene.node_item_activated.connect( 
     592                self.__onNodeActivate 
     593            ) 
     594 
     595            self.__scene.annotation_added.connect( 
     596                self.__onAnnotationAdded 
     597            ) 
     598 
     599            self.__scene.annotation_removed.connect( 
     600                self.__onAnnotationRemoved 
     601            ) 
    616602 
    617603            self.__scene.set_scheme(scheme) 
     
    988974 
    989975        any_item = scene.item_at(pos) 
    990         if not any_item: 
    991             self.__emptyClickButtons |= event.button() 
    992  
    993976        if not any_item and event.button() == Qt.LeftButton: 
     977            self.__emptyClickButtons |= Qt.LeftButton 
    994978            # Create a RectangleSelectionAction but do not set in on the scene 
    995979            # just yet (instead wait for the mouse move event). 
     
    10261010            handler = self.__possibleSelectionHandler 
    10271011            self._setUserInteractionHandler(handler) 
    1028             self.__possibleSelectionHandler = None 
    10291012            return handler.mouseMoveEvent(event) 
    10301013 
     
    10321015 
    10331016    def sceneMouseReleaseEvent(self, event): 
    1034         scene = self.__scene 
    1035         if scene.user_interaction_handler: 
    1036             return False 
    1037  
    10381017        if event.button() == Qt.LeftButton and self.__possibleMouseItemsMove: 
    10391018            self.__possibleMouseItemsMove = False 
     
    10681047                self.__itemsMoving.clear() 
    10691048                return True 
    1070         elif event.button() == Qt.LeftButton: 
    1071             self.__possibleSelectionHandler = None 
     1049 
     1050        if self.__emptyClickButtons & Qt.LeftButton and \ 
     1051                event.button() & Qt.LeftButton: 
     1052            self.__emptyClickButtons &= ~Qt.LeftButton 
     1053 
     1054            if self.__quickMenuTriggers & SchemeEditWidget.Clicked and \ 
     1055                    mouse_drag_distance(event, Qt.LeftButton) < 1: 
     1056                action = interactions.NewNodeAction(self) 
     1057 
     1058                with nested(disabled(self.__undoAction), 
     1059                            disabled(self.__redoAction)): 
     1060                    action.create_new(event.screenPos()) 
     1061 
     1062                event.accept() 
     1063                return True 
    10721064 
    10731065        return False 
     
    11211113 
    11221114        handler = None 
    1123         searchText = "" 
    11241115        if (event.key() == Qt.Key_Space and \ 
    11251116                self.__quickMenuTriggers & SchemeEditWidget.SpaceKey): 
     
    11271118 
    11281119        elif len(event.text()) and \ 
    1129                 self.__quickMenuTriggers & SchemeEditWidget.AnyKey and \ 
    1130                 is_printable(unicode(event.text())[0]): 
     1120                self.__quickMenuTriggers & SchemeEditWidget.AnyKey: 
    11311121            handler = interactions.NewNodeAction(self) 
    1132             searchText = unicode(event.text()) 
    1133  
    11341122            # TODO: set the search text to event.text() and set focus on the 
    11351123            # search line 
     
    11441132                        disabled(self.__undoAction), 
    11451133                        disabled(self.__redoAction)): 
    1146                 handler.create_new(QCursor.pos(), searchText) 
     1134                handler.create_new(QCursor.pos()) 
    11471135 
    11481136            event.accept() 
     
    14261414            return 
    14271415 
    1428         item = self.scene().item_at(scenePos) 
    1429         if not item and \ 
    1430                 self.__quickMenuTriggers & SchemeEditWidget.RightClicked: 
    1431             action = interactions.NewNodeAction(self) 
    1432  
    1433             with nested(disabled(self.__undoAction), 
    1434                         disabled(self.__redoAction)): 
    1435                 action.create_new(globalPos) 
    1436             return 
    1437  
    14381416    def __onRenameAction(self): 
    14391417        """ 
     
    15751553    for obj in objects: 
    15761554        obj.setEnabled(enable) 
    1577  
    1578  
    1579 # All control character categories. 
    1580 _control = set(["Cc", "Cf", "Cs", "Co", "Cn"]) 
    1581  
    1582  
    1583 def is_printable(unichar): 
    1584     """ 
    1585     Return True if the unicode character `unichar` is a printable character. 
    1586     """ 
    1587     return unicodedata.category(unichar) not in _control 
  • Orange/OrangeCanvas/gui/tooltree.py

    r11493 r11370  
    5656 
    5757        view.activated.connect(self.__onActivated) 
    58         view.clicked.connect(self.__onActivated) 
     58        view.pressed.connect(self.__onPressed) 
    5959        view.entered.connect(self.__onEntered) 
    6060 
     
    144144                action.trigger() 
    145145                self.triggered.emit(action) 
     146 
     147    def __onPressed(self, index): 
     148        self.__onActivated(index) 
    146149 
    147150    def __onEntered(self, index): 
  • Orange/OrangeCanvas/scheme/widgetsscheme.py

    r11487 r11470  
    8484 
    8585        # Save settings to user global settings. 
    86         if not widget._settingsFromSchema: 
    87             widget.saveSettings() 
     86        widget.saveSettings() 
    8887 
    8988        # Notify the widget it will be deleted. 
     
    151150        return widget 
    152151 
     152    def close_all_open_widgets(self): 
     153        for widget in self.widget_for_node.values(): 
     154            widget.close() 
     155 
    153156    def widget_settings(self): 
    154157        """Return a list of dictionaries with widget settings. 
     
    156159        return [self.widget_for_node[node].getSettings(alsoContexts=False) 
    157160                for node in self.nodes] 
     161 
     162    def save_widget_settings(self): 
     163        """Save all widget settings to their global settings file. 
     164        """ 
     165        for node in self.nodes: 
     166            widget = self.widget_for_node[node] 
     167            widget.saveSettings() 
    158168 
    159169    def sync_node_properties(self): 
     
    179189        self.sync_node_properties() 
    180190        Scheme.save_to(self, stream, pretty, pickle_fallback) 
    181  
    182     def event(self, event): 
    183         """ 
    184         Reimplemented from `QObject.event`. 
    185  
    186         Responds to QEvent.Close event by stopping signal processing and 
    187         closing all widgets. 
    188  
    189         """ 
    190         if event.type() == QEvent.Close: 
    191             self.signal_manager.stop() 
    192  
    193             # Notify the widget instances. 
    194             for widget in self.widget_for_node.values(): 
    195                 if not widget._settingsFromSchema: 
    196                     # First save global settings if necessary. 
    197                     widget.saveSettings() 
    198  
    199                 widget.close() 
    200                 widget.onDeleteWidget() 
    201  
    202             event.accept() 
    203             return True 
    204         else: 
    205             return Scheme.event(self, event) 
    206191 
    207192    def __on_help_request(self): 
  • Orange/OrangeCanvas/styles/orange.qss

    r11495 r11412  
    103103 
    104104 
    105 /* QuickCategoryToolbar popup menus */ 
    106  
    107 CategoryPopupMenu { 
    108     background-color: #E9EFF2; 
    109 } 
    110  
    111 CategoryPopupMenu ToolTree QTreeView::item { 
    112     height: 25px; 
    113     border-bottom: 1px solid #e9eff2; 
    114 } 
    115  
    116 CategoryPopupMenu QTreeView::item:hover { 
    117     background: qlineargradient( 
    118         x1: 0, y1: 0, x2: 0, y2: 1, 
    119         stop: 0 #688EF6, 
    120         stop: 0.5 #4047f4, 
    121         stop: 1.0 #2D68F3 
    122     ); 
    123     color: white; 
    124 } 
    125  
    126 CategoryPopupMenu QTreeView::item:selected { 
    127     background-color: blue; 
    128     color: white; 
    129 } 
     105 
     106/* 
     107 *QuickCategoryToolbar _QuickCategoryButton { 
     108 *    qproperty-nativeStyling_: "true"; 
     109 *    background-color: palette(button); 
     110 *    border: none; 
     111 *    border-bottom: 1px solid palette(dark); 
     112 *} 
     113 */ 
    130114 
    131115 
     
    375359 
    376360QuickMenu ToolTree QTreeView::item { 
    377     height: 25px; 
    378     border-bottom: 1px solid #e9eff2; 
     361    height: 25px; 
     362    border-top: 1px solid #e9eff2; 
     363    border-bottom: 1px solid #e9eff2; 
    379364} 
    380365 
    381366QuickMenu QTreeView::item:hover { 
    382     background: qlineargradient( 
    383         x1: 0, y1: 0, x2: 0, y2: 1, 
    384         stop: 0 #688EF6, 
    385         stop: 0.5 #4047f4, 
    386         stop: 1.0 #2D68F3 
    387     ); 
    388     color: white; 
     367    background-color: lightblue; 
     368    color: white; 
    389369} 
    390370 
    391371QuickMenu QTreeView::item:selected { 
    392     background-color: blue; 
    393     color: white; 
    394 } 
    395  
    396 QuickMenu TabBarWidget QToolButton { 
    397     width: 33px; 
    398     height: 25px; 
    399     border-bottom: 1px solid palette(dark); 
    400     padding-right: 5px; 
    401 } 
    402  
    403 QuickMenu TabBarWidget QToolButton#search-tab-button { 
    404     background-color: #9CACB4; 
    405 } 
    406  
    407 QuickMenu TabBarWidget QToolButton:menu-indicator { 
    408     image: url(canvas_icons:/arrow-right.svg); 
    409     subcontrol-position: center right; 
    410     height: 8px; 
    411     width: 8px; 
    412 } 
    413  
    414 /* Quick Menu search line edit 
     372    background-color: blue; 
     373    color: white; 
     374} 
     375 
     376/* Quick Menu search line edit  
    415377 */ 
    416378 
Note: See TracChangeset for help on using the changeset viewer.