def __init__(self, *args, **kwargs): title = kwargs.get('title', args[0] if len(args) > 0 else '') parent_win = kwargs.get('parent_win', None) win_flag = kwargs.get('win_flag', None) if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog QFrame.__init__(self) if parent_win is None else QFrame.__init__( self, parent_win, win_flag) # self.setObjectName(self.__class__.__name__) layout = QVBoxLayout() self.setLayout(layout) if AnyQt.USED_API == 'pyqt5': layout.setContentsMargins(0, 0, 0, 0) else: layout.setMargin(0) self.title = title self.has_progress = False self._mainmenu = [] self._splitters = [] self._tabs = [] self._formset = None self._formLoaded = False self.uid = id(self) self.setAccessibleName('BaseWidget')
def __init__(self, parent): QFrame.__init__(self, parent) self.setContentsMargins(0, 0, 0, 0) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(1) self._setNameLineEdit = QLineEdit(self) layout.addWidget(self._setNameLineEdit) self._setListView = QListView(self) self._listModel = QStandardItemModel(self) self._proxyModel = QSortFilterProxyModel(self) self._proxyModel.setSourceModel(self._listModel) self._setListView.setModel(self._proxyModel) self._setListView.setItemDelegate(ListItemDelegate(self)) self._setNameLineEdit.textChanged.connect( self._proxyModel.setFilterFixedString) self._completer = QCompleter(self._listModel, self) self._setNameLineEdit.setCompleter(self._completer) self._listModel.itemChanged.connect(self._onSetNameChange) layout.addWidget(self._setListView) buttonLayout = QHBoxLayout() self._addAction = QAction( "+", self, toolTip="Add a new sort key") self._updateAction = QAction( "Update", self, toolTip="Update/save current selection") self._removeAction = QAction( "\u2212", self, toolTip="Remove selected sort key.") self._addToolButton = QToolButton(self) self._updateToolButton = QToolButton(self) self._removeToolButton = QToolButton(self) self._updateToolButton.setSizePolicy( QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) self._addToolButton.setDefaultAction(self._addAction) self._updateToolButton.setDefaultAction(self._updateAction) self._removeToolButton.setDefaultAction(self._removeAction) buttonLayout.addWidget(self._addToolButton) buttonLayout.addWidget(self._updateToolButton) buttonLayout.addWidget(self._removeToolButton) layout.addLayout(buttonLayout) self.setLayout(layout) self._addAction.triggered.connect(self.addCurrentSelection) self._updateAction.triggered.connect(self.updateSelectedSelection) self._removeAction.triggered.connect(self.removeSelectedSelection) self._setListView.selectionModel().selectionChanged.connect( self._onListViewSelectionChanged) self.selectionModel = None self._selections = []
def __init__(self, parent=None, animationEnabled=True): QFrame.__init__(self, parent) self.__animationEnabled = animationEnabled layout = StackLayout() self.__fadeWidget = CrossFadePixmapWidget(self) self.transitionAnimation = \ QPropertyAnimation(self.__fadeWidget, b"blendingFactor_", self) self.transitionAnimation.setStartValue(0.0) self.transitionAnimation.setEndValue(1.0) self.transitionAnimation.setDuration(100 if animationEnabled else 0) self.transitionAnimation.finished.connect( self.__onTransitionFinished ) layout.addWidget(self.__fadeWidget) layout.currentChanged.connect(self.__onLayoutCurrentChanged) self.setLayout(layout) self.__widgets = [] self.__currentIndex = -1 self.__nextCurrentIndex = -1
def __init__(self, parent=None, columns=4, buttonSize=None, iconSize=None, toolButtonStyle=Qt.ToolButtonTextUnderIcon): QFrame.__init__(self, parent) if buttonSize is not None: buttonSize = QSize(buttonSize) if iconSize is not None: iconSize = QSize(iconSize) self.__columns = columns self.__buttonSize = buttonSize or QSize(50, 50) self.__iconSize = iconSize or QSize(26, 26) self.__toolButtonStyle = toolButtonStyle self.__gridSlots = [] self.__buttonListener = ToolButtonEventListener(self) self.__buttonListener.buttonRightClicked.connect( self.__onButtonRightClick) self.__buttonListener.buttonEnter.connect( self.__onButtonEnter) self.__mapper = QSignalMapper() self.__mapper.mapped[QObject].connect(self.__onClicked) self.__setupUi()
def __init__(self, parent=None, columns=4, buttonSize=None, iconSize=None, toolButtonStyle=Qt.ToolButtonTextUnderIcon): QFrame.__init__(self, parent) if buttonSize is not None: buttonSize = QSize(buttonSize) if iconSize is not None: iconSize = QSize(iconSize) self.__columns = columns self.__buttonSize = buttonSize or QSize(50, 50) self.__iconSize = iconSize or QSize(26, 26) self.__toolButtonStyle = toolButtonStyle self.__gridSlots = [] self.__buttonListener = ToolButtonEventListener(self) self.__buttonListener.buttonRightClicked.connect( self.__onButtonRightClick) self.__buttonListener.buttonEnter.connect(self.__onButtonEnter) self.__mapper = QSignalMapper() self.__mapper.mapped[QObject].connect(self.__onClicked) self.__setupUi()
def __init__(self, tree, dataset, master, parent=None): QFrame.__init__(self, parent) Control.__init__(self, tree, dataset, master) self.setLayout(QVBoxLayout()) self.outFormats = getattr(tree, "outFormats", "tsv") if tree: self.setPage(tree)
def __init__(self, *args): QFrame.__init__(self) ControlBase.__init__(self, *args) self._speed = 1 self.logger = logging.getLogger('pyforms') self._updateVideoFrame = True
def __init__(self, parent=None, **kwargs): QFrame.__init__(self, parent, **kwargs) self.__pages = [] self.__tabButtonHeight = -1 self.__tabIconSize = QSize() self.__exclusive = False self.__setupUi()
def __init__(self, *args, **kwargs): QFrame.__init__(self) ControlBase.__init__(self, *args, **kwargs) self.process_frame_event = kwargs.get('process_frame_event', self.process_frame_event) self._speed = 1 self.logger = logging.getLogger('pyforms') self._updateVideoFrame = True
def actionEvent(self, event): QFrame.actionEvent(self, event) if event.type() == QEvent.ActionAdded: # Note: the action is already in the self.actions() list. actions = list(self.actions()) index = actions.index(event.action()) self.__insertActionButton(index, event.action()) elif event.type() == QEvent.ActionRemoved: self.__removeActionButton(event.action())
def __init__(self, parent=None): super().__init__(parent) self.corpus = None self.initial_ngram_range = None # initial range of input corpus — used for inplace self.preprocessor = preprocess.Preprocessor() # -- INFO -- info_box = gui.widgetBox(self.controlArea, 'Info') info_box.setFixedWidth(self.control_area_width) self.controlArea.layout().addStretch() self.info_label = gui.label(info_box, self, '') self.update_info() # -- PIPELINE -- frame = QFrame() frame.setContentsMargins(0, 0, 0, 0) frame.setFrameStyle(QFrame.Box) frame.setStyleSheet('.QFrame { border: 1px solid #B3B3B3; }') frame_layout = QVBoxLayout() frame_layout.setContentsMargins(0, 0, 0, 0) frame_layout.setSpacing(0) frame.setLayout(frame_layout) self.stages = [] for stage in self.preprocessors: widget = stage(self) self.stages.append(widget) setattr(self, stage.attribute, widget) frame_layout.addWidget(widget) widget.change_signal.connect(self.settings_invalidated) frame_layout.addStretch() self.scroll = QScrollArea() self.scroll.setWidget(frame) self.scroll.setWidgetResizable(True) self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll.resize(frame_layout.sizeHint()) self.scroll.setMinimumHeight(500) self.set_minimal_width() self.mainArea.layout().sizeHint() self.mainArea.layout().addWidget(self.scroll) # Buttons area self.report_button.setFixedWidth(self.control_area_width) commit_button = gui.auto_commit(self.buttonsArea, self, 'autocommit', 'Commit', box=False) commit_button.setFixedWidth(self.control_area_width) self.buttonsArea.layout().addWidget(commit_button)
def __setupUi(self): self.setLayout(QVBoxLayout(self)) self.layout().setContentsMargins(6, 6, 6, 6) self.__search = SearchWidget(self, objectName="search-line") self.__search.setPlaceholderText( self.tr("Search for widget or select from the list.")) self.layout().addWidget(self.__search) self.__frame = QFrame(self, objectName="menu-frame") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) self.__frame.setLayout(layout) self.layout().addWidget(self.__frame) self.__pages = PagedMenu(self, objectName="paged-menu") self.__pages.currentChanged.connect(self.setCurrentIndex) self.__pages.triggered.connect(self.triggered) self.__pages.hovered.connect(self.hovered) self.__frame.layout().addWidget(self.__pages) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__suggestPage = SuggestMenuPage(self, objectName="suggest-page") self.__suggestPage.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) self.__suggestPage.setIcon(icon_loader().get("icons/Search.svg")) if sys.platform == "darwin": view = self.__suggestPage.view() view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab bar. view.setAttribute(Qt.WA_MacShowFocusRect, False) i = self.addPage(self.tr("Quick Search"), self.__suggestPage) button = self.__pages.tabButton(i) button.setObjectName("search-tab-button") button.setStyleSheet("TabButton {\n" " qproperty-flat_: false;\n" " border: none;" "}\n") self.__search.textEdited.connect(self.__on_textEdited) self.__navigator = ItemViewKeyNavigator(self) self.__navigator.setView(self.__suggestPage.view()) self.__search.installEventFilter(self.__navigator) self.__grip = WindowSizeGrip(self) self.__grip.raise_()
def __add_aggregation_controls(self): def new_inbox(): nonlocal row, col, inbox inbox = QWidget() layout = QGridLayout() inbox.setLayout(layout) layout.setContentsMargins(0, 0, 0, 0) box.layout().addWidget(inbox) row = col = 0 box = gui.vBox(self.controlArea, "Aggregations") row = col = 0 inbox = None new_inbox() self.aggregation_checkboxes = [] # for test purposes for agg in self.AGGREGATIONS: if agg is None: line = QFrame() line.setFrameShape(QFrame.HLine) line.setLineWidth(1) line.setFrameShadow(QFrame.Sunken) box.layout().addWidget(line) new_inbox() continue elif agg == 2: col += 1 row = 0 continue check_box = QCheckBox(str(agg), inbox) check_box.setChecked(agg in self.sel_agg_functions) check_box.clicked.connect( lambda *args, a=agg: self.__aggregation_cb_clicked(a, args[0])) inbox.layout().addWidget(check_box, row, col) self.aggregation_checkboxes.append(check_box) row += 1
def __setup(self): # Setup the subwidgets/groups/layout smax = max((numpy.max(g.scores) for g in self.__groups if g.scores.size), default=1) smin = min((numpy.min(g.scores) for g in self.__groups if g.scores.size), default=-1) smin = min(smin, 0) font = self.font() font.setPixelSize(self.__barHeight) axispen = QPen(Qt.black) ax = pg.AxisItem(parent=self, orientation="top", maxTickLength=7, pen=axispen) ax.setRange(smin, smax) self.layout().addItem(ax, 0, 2) for i, group in enumerate(self.__groups): silhouettegroup = BarPlotItem(parent=self) silhouettegroup.setBrush(QBrush(QColor(*group.color))) silhouettegroup.setPen(self.__pen) silhouettegroup.setDataRange(smin, smax) silhouettegroup.setPlotData(group.scores) silhouettegroup.setPreferredBarSize(self.__barHeight) silhouettegroup.setData(0, group.indices) self.layout().addItem(silhouettegroup, i + 1, 2) if group.label: line = QFrame(frameShape=QFrame.VLine) proxy = QGraphicsProxyWidget(self) proxy.setWidget(line) self.layout().addItem(proxy, i + 1, 1) label = QGraphicsSimpleTextItem(self) label.setText("{} ({})".format(escape(group.label), len(group.scores))) item = WrapperLayoutItem(label, Qt.Vertical, parent=self) self.layout().addItem(item, i + 1, 0, Qt.AlignCenter) textlist = TextListWidget(self, font=font) sp = textlist.sizePolicy() sp.setVerticalPolicy(QSizePolicy.Ignored) textlist.setSizePolicy(sp) textlist.setParent(self) if group.rownames is not None: textlist.setItems(group.items) textlist.setVisible(self.__rowNamesVisible) else: textlist.setVisible(False) self.layout().addItem(textlist, i + 1, 3) ax = pg.AxisItem(parent=self, orientation="bottom", maxTickLength=7, pen=axispen) ax.setRange(smin, smax) self.layout().addItem(ax, len(self.__groups) + 1, 2)
def __init__(self, parent=None): super().__init__(parent) self.corpus = None self.initial_ngram_range = None # initial range of input corpus — used for inplace self.preprocessor = preprocess.Preprocessor() # -- INFO -- info_box = gui.widgetBox(self.controlArea, 'Info') info_box.setFixedWidth(self.control_area_width) self.controlArea.layout().addStretch() self.info_label = gui.label(info_box, self, '') self.update_info() # -- PIPELINE -- frame = QFrame() frame.setContentsMargins(0, 0, 0, 0) frame.setFrameStyle(QFrame.Box) frame.setStyleSheet('.QFrame { border: 1px solid #B3B3B3; }') frame_layout = QVBoxLayout() frame_layout.setContentsMargins(0, 0, 0, 0) frame_layout.setSpacing(0) frame.setLayout(frame_layout) self.stages = [] for stage in self.preprocessors: widget = stage(self) self.stages.append(widget) setattr(self, stage.attribute, widget) frame_layout.addWidget(widget) widget.change_signal.connect(self.settings_invalidated) frame_layout.addStretch() self.scroll = QScrollArea() self.scroll.setWidget(frame) self.scroll.setWidgetResizable(True) self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scroll.resize(frame_layout.sizeHint()) self.scroll.setMinimumHeight(500) self.set_minimal_width() self.mainArea.layout().addWidget(self.scroll) # Buttons area self.report_button.setFixedWidth(self.control_area_width) commit_button = gui.auto_commit(self.buttonsArea, self, 'autocommit', 'Commit', box=False) commit_button.setFixedWidth(self.control_area_width - 5) self.buttonsArea.layout().addWidget(commit_button)
def __setupUi(self): self.setLayout(QVBoxLayout(self)) self.layout().setContentsMargins(6, 6, 6, 6) self.__search = SearchWidget(self, objectName="search-line") self.__search.setPlaceholderText( self.tr("Search for widget or select from the list.") ) self.layout().addWidget(self.__search) self.__frame = QFrame(self, objectName="menu-frame") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) self.__frame.setLayout(layout) self.layout().addWidget(self.__frame) self.__pages = PagedMenu(self, objectName="paged-menu") self.__pages.currentChanged.connect(self.setCurrentIndex) self.__pages.triggered.connect(self.triggered) self.__pages.hovered.connect(self.hovered) self.__frame.layout().addWidget(self.__pages) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__suggestPage = SuggestMenuPage(self, objectName="suggest-page") self.__suggestPage.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) self.__suggestPage.setIcon(icon_loader().get("icons/Search.svg")) if sys.platform == "darwin": view = self.__suggestPage.view() view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab bar. view.setAttribute(Qt.WA_MacShowFocusRect, False) i = self.addPage(self.tr("Quick Search"), self.__suggestPage) button = self.__pages.tabButton(i) button.setObjectName("search-tab-button") button.setStyleSheet( "TabButton {\n" " qproperty-flat_: false;\n" " border: none;" "}\n") self.__search.textEdited.connect(self.__on_textEdited) self.__navigator = ItemViewKeyNavigator(self) self.__navigator.setView(self.__suggestPage.view()) self.__search.installEventFilter(self.__navigator) self.__grip = WindowSizeGrip(self) self.__grip.raise_()
def __init__(self, *args, **kwargs): self._video_widget = None # GL widget QFrame.__init__(self) ControlBase.__init__(self, *args, **kwargs) self._multiple_files = kwargs.get('multiple_files', False) self._current_frame = None # current frame image self._current_frame_index = None # current frame index self.process_frame_event = kwargs.get('process_frame_event', self.process_frame_event) self._speed = 1 self.logger = logging.getLogger('pyforms') self._update_video_frame = True # if true update the spinbox with the current frame self._update_video_slider = True # if true update the slider with the current frame
def eventFilter(self, obj, event): etype = event.type() if etype == QEvent.KeyPress and obj.hasFocus(): key = event.key() if key in [Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right]: if self.__focusMove(obj, key): event.accept() return True return QFrame.eventFilter(self, obj, event)
def add_line(parent): frame = QFrame() frame.setFrameShape(QFrame.HLine) frame.setFrameShadow(QFrame.Sunken) parent.layout().addSpacing(6) parent.layout().addWidget(frame) parent.layout().addSpacing(6)
def __init__(self, *args, **kwargs): title = kwargs.get('title', args[0] if len(args) > 0 else '') parent_win = kwargs.get('parent_win', kwargs.get('parent_widget', None)) win_flag = kwargs.get('win_flag', None) self._parent_widget = parent_win if parent_win is not None and win_flag is None: win_flag = QtCore.Qt.Dialog QFrame.__init__(self) if parent_win is None else QFrame.__init__( self, parent_win, win_flag) layout = QVBoxLayout() self.setLayout(layout) if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0, 0, 0, 0) elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) self.title = title self.title = title self.has_progress = False self.toolbar = [] self._mainmenu = [] self._splitters = [] self.vlayouts = [] self.hlayouts = [] self._tabs = [] self._formset = None self._formLoaded = False self.uid = id(self) self.setAccessibleName('BaseWidget')
def __add_aggregation_controls(self): box = gui.vBox(self.controlArea, "Aggregations") for agg in self.AGGREGATIONS: if agg is None: gui.separator(box, height=1) line = QFrame() line.setFrameShape(QFrame.HLine) line.setLineWidth(1) line.setFrameShadow(QFrame.Sunken) box.layout().addWidget(line) continue check_box = QCheckBox(str(agg), box) check_box.setChecked(agg in self.sel_agg_functions) check_box.clicked.connect( lambda *args, a=agg: self.__aggregation_cb_clicked(a, args[0])) box.layout().addWidget(check_box)
def __init__(self, master=None, parent=None, label=None, color=None): QWidget.__init__(self, master) self.parent = parent self.master = master if self.parent and self.parent.layout() is not None: self.parent.layout().addWidget(self) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.icon = QFrame(self) self.icon.setFixedSize(ColorButtonSize, ColorButtonSize) self.icon.setAutoFillBackground(1) self.icon.setFrameStyle(QFrame.StyledPanel + QFrame.Sunken) self.layout().addWidget(self.icon) if label != None: self.label = gui.widgetLabel(self, label) self.layout().addWidget(self.label) if color != None: self.setColor(color)
def __add_aggregation_controls(self): box = gui.vBox(self.controlArea, "聚合") chinese_aggs = [ "计数(Count)", "计数已定义项(Count_defined)", None, "总和(Sum)", "平均(Mean)", "样式(Mode)", "最小(Min)", "最大(Max)", "中位数(Median)", "变量(Var)", None, "大多数(Majority)" ] for agg, chinese_agg in zip(self.AGGREGATIONS, chinese_aggs): if agg is None: gui.separator(box, height=1) line = QFrame() line.setFrameShape(QFrame.HLine) line.setLineWidth(1) line.setFrameShadow(QFrame.Sunken) box.layout().addWidget(line) continue check_box = QCheckBox(str(chinese_agg), box) check_box.setChecked(agg in self.sel_agg_functions) check_box.clicked.connect( lambda *args, a=agg: self.__aggregation_cb_clicked(a, args[0])) box.layout().addWidget(check_box)
class ColorButton(QWidget): def __init__(self, master=None, parent=None, label=None, color=None): QWidget.__init__(self, master) self.parent = parent self.master = master if self.parent and self.parent.layout() is not None: self.parent.layout().addWidget(self) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.icon = QFrame(self) self.icon.setFixedSize(ColorButtonSize, ColorButtonSize) self.icon.setAutoFillBackground(1) self.icon.setFrameStyle(QFrame.StyledPanel + QFrame.Sunken) self.layout().addWidget(self.icon) if label != None: self.label = gui.widgetLabel(self, label) self.layout().addWidget(self.label) if color != None: self.setColor(color) def setColor(self, color): self.color = color palette = QPalette() palette.setBrush(QPalette.Background, color) self.icon.setPalette(palette) def getColor(self): return self.color def mousePressEvent(self, ev): color = QColorDialog.getColor(self.color) if color.isValid(): self.setColor(color) if self.master and hasattr(self.master, "colorSchemaChange"): self.master.colorSchemaChange()
def insertAction(self, before, action): """ Insert a new action at the position currently occupied by `before` (can also be an index). Parameters ---------- before : :class:`QAction` or int Position where the `action` should be inserted. action : :class:`QAction` Action to insert """ if isinstance(before, int): actions = list(self.actions()) if len(actions) == 0 or before >= len(actions): # Insert as the first action or the last action. return self.addAction(action) before = actions[before] return QFrame.insertAction(self, before, action)
def __init__(self): super().__init__() self.output_corpus = None self.pubmed_api = None self.progress = None self.email_is_valid = False self.record_count = 0 self.download_running = False # To hold all the controls. Makes access easier. self.pubmed_controls = [] h_box = gui.hBox(self.controlArea) label = gui.label(h_box, self, 'Email:') label.setMaximumSize(label.sizeHint()) # Drop-down for recent emails. self.email_combo = QComboBox(h_box) self.email_combo.setMinimumWidth(150) self.email_combo.setEditable(True) self.email_combo.lineEdit().textChanged.connect(self.sync_email) h_box.layout().addWidget(self.email_combo) self.email_combo.activated[int].connect(self.select_email) # RECORD SEARCH self.search_tabs = gui.tabWidget(self.controlArea) # --- Regular search --- regular_search_box = gui.widgetBox(self.controlArea, addSpace=True) # Author self.author_input = gui.lineEdit(regular_search_box, self, 'author', 'Author:', orientation=Qt.Horizontal) self.pubmed_controls.append(self.author_input) h_box = gui.hBox(regular_search_box) year_box = gui.widgetBox(h_box, orientation=Qt.Horizontal) min_date = QDate.fromString( self.MIN_DATE.strftime(self.PY_DATE_FORMAT), self.QT_DATE_FORMAT ) if not self.pub_date_from: self.pub_date_from = self.MIN_DATE.strftime(self.PY_DATE_FORMAT) if not self.pub_date_to: self.pub_date_to = date.today().strftime(self.PY_DATE_FORMAT) self.date_from = QDateEdit( QDate.fromString(self.pub_date_from, self.QT_DATE_FORMAT), displayFormat=self.QT_DATE_FORMAT, minimumDate=min_date, calendarPopup=True ) self.date_to = QDateEdit( QDate.fromString(self.pub_date_to, self.QT_DATE_FORMAT), displayFormat=self.QT_DATE_FORMAT, minimumDate=min_date, calendarPopup=True ) self.date_from.dateChanged.connect( lambda date: setattr(self, 'pub_date_from', date.toString(self.QT_DATE_FORMAT))) self.date_to.dateChanged.connect( lambda date: setattr(self, 'pub_date_to', date.toString(self.QT_DATE_FORMAT))) self.pubmed_controls.append(self.date_from) self.pubmed_controls.append(self.date_to) gui.label(year_box, self, 'From:') year_box.layout().addWidget(self.date_from) gui.label(year_box, self, 'to:') year_box.layout().addWidget(self.date_to) # Keywords. h_box = gui.hBox(regular_search_box) label = gui.label(h_box, self, 'Query:') label.setMaximumSize(label.sizeHint()) self.keyword_combo = QComboBox(h_box) self.keyword_combo.setMinimumWidth(150) self.keyword_combo.setEditable(True) h_box.layout().addWidget(self.keyword_combo) self.keyword_combo.activated[int].connect(self.select_keywords) self.pubmed_controls.append(self.keyword_combo) tab_height = regular_search_box.sizeHint() regular_search_box.setMaximumSize(tab_height) # --- Advanced search --- advanced_search_box = gui.widgetBox(self.controlArea, addSpace=True) # Advanced search query. h_box = gui.hBox(advanced_search_box) self.advanced_query_input = QTextEdit(h_box) h_box.layout().addWidget(self.advanced_query_input) self.advanced_query_input.setMaximumSize(tab_height) self.pubmed_controls.append(self.advanced_query_input) gui.createTabPage(self.search_tabs, 'Regular search', regular_search_box) gui.createTabPage(self.search_tabs, 'Advanced search', advanced_search_box) # Search info label. self.search_info_label = gui.label( self.controlArea, self, 'Number of records found: /') # Search for records button. self.run_search_button = gui.button( self.controlArea, self, 'Find records', callback=self.run_search, tooltip='Performs a search for articles that fit the ' 'specified parameters.') self.pubmed_controls.append(self.run_search_button) h_line = QFrame() h_line.setFrameShape(QFrame.HLine) h_line.setFrameShadow(QFrame.Sunken) self.controlArea.layout().addWidget(h_line) # RECORD RETRIEVAL # Text includes box. text_includes_box = gui.widgetBox(self.controlArea, 'Text includes', addSpace=True) self.authors_checkbox = gui.checkBox(text_includes_box, self, 'includes_authors', 'Authors') self.title_checkbox = gui.checkBox(text_includes_box, self, 'includes_title', 'Article title') self.mesh_checkbox = gui.checkBox(text_includes_box, self, 'includes_mesh', 'Mesh headings') self.abstract_checkbox = gui.checkBox(text_includes_box, self, 'includes_abstract', 'Abstract') self.url_checkbox = gui.checkBox(text_includes_box, self, 'includes_url', 'URL') self.pubmed_controls.append(self.authors_checkbox) self.pubmed_controls.append(self.title_checkbox) self.pubmed_controls.append(self.mesh_checkbox) self.pubmed_controls.append(self.abstract_checkbox) self.pubmed_controls.append(self.url_checkbox) # Num. records. h_box = gui.hBox(self.controlArea) label = gui.label(h_box, self, 'Retrieve') label.setMaximumSize(label.sizeHint()) self.num_records_input = gui.spin(h_box, self, 'num_records', minv=1, maxv=100000) self.max_records_label = gui.label(h_box, self, 'records from /.') self.max_records_label.setMaximumSize(self.max_records_label .sizeHint()) self.pubmed_controls.append(self.num_records_input) # Download articles. # Search for records button. self.retrieve_records_button = gui.button( self.controlArea, self, 'Retrieve records', callback=self.retrieve_records, tooltip='Retrieves the specified documents.') self.pubmed_controls.append(self.retrieve_records_button) # Num. retrieved records info label. self.retrieval_info_label = gui.label( self.controlArea, self, 'Number of records retrieved: /') # Load the most recent emails. self.set_email_list() # Load the most recent queries. self.set_keyword_list() # Check the email and enable controls accordingly. if self.recent_emails: email = self.recent_emails[0] self.email_is_valid = validate_email(email) self.enable_controls()
class QuickMenu(FramelessWindow): """ A quick menu popup for the widgets. The widgets are set using :func:`QuickMenu.setModel` which must be a model as returned by :func:`QtWidgetRegistry.model` """ #: An action has been triggered in the menu. triggered = Signal(QAction) #: An action has been hovered in the menu hovered = Signal(QAction) def __init__(self, parent=None, **kwargs): FramelessWindow.__init__(self, parent, **kwargs) self.setWindowFlags(Qt.Popup) self.__filterFunc = None self.__sortingFunc = None self.__setupUi() self.__loop = None self.__model = QStandardItemModel() self.__triggeredAction = None def __setupUi(self): self.setLayout(QVBoxLayout(self)) self.layout().setContentsMargins(6, 6, 6, 6) self.__search = SearchWidget(self, objectName="search-line") self.__search.setPlaceholderText( self.tr("Search for widget or select from the list.") ) self.layout().addWidget(self.__search) self.__frame = QFrame(self, objectName="menu-frame") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) self.__frame.setLayout(layout) self.layout().addWidget(self.__frame) self.__pages = PagedMenu(self, objectName="paged-menu") self.__pages.currentChanged.connect(self.setCurrentIndex) self.__pages.triggered.connect(self.triggered) self.__pages.hovered.connect(self.hovered) self.__frame.layout().addWidget(self.__pages) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__suggestPage = SuggestMenuPage(self, objectName="suggest-page") self.__suggestPage.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) self.__suggestPage.setIcon(icon_loader().get("icons/Search.svg")) if sys.platform == "darwin": view = self.__suggestPage.view() view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab bar. view.setAttribute(Qt.WA_MacShowFocusRect, False) i = self.addPage(self.tr("Quick Search"), self.__suggestPage) button = self.__pages.tabButton(i) button.setObjectName("search-tab-button") button.setStyleSheet( "TabButton {\n" " qproperty-flat_: false;\n" " border: none;" "}\n") self.__search.textEdited.connect(self.__on_textEdited) self.__navigator = ItemViewKeyNavigator(self) self.__navigator.setView(self.__suggestPage.view()) self.__search.installEventFilter(self.__navigator) self.__grip = WindowSizeGrip(self) self.__grip.raise_() def setSizeGripEnabled(self, enabled): """ Enable the resizing of the menu with a size grip in a bottom right corner (enabled by default). """ if bool(enabled) != bool(self.__grip): if self.__grip: self.__grip.deleteLater() self.__grip = None else: self.__grip = WindowSizeGrip(self) self.__grip.raise_() def sizeGripEnabled(self): """ Is the size grip enabled. """ return bool(self.__grip) def addPage(self, name, page): """ Add the `page` (:class:`MenuPage`) with `name` and return it's index. The `page.icon()` will be used as the icon in the tab bar. """ icon = page.icon() tip = name if page.toolTip(): tip = page.toolTip() index = self.__pages.addPage(page, name, icon, tip) # Route the page's signals page.triggered.connect(self.__onTriggered) page.hovered.connect(self.hovered) # Install event filter to intercept key presses. page.view().installEventFilter(self) return index def createPage(self, index): """ Create a new page based on the contents of an index (:class:`QModeIndex`) item. """ page = MenuPage(self) page.setModel(index.model()) page.setRootIndex(index) view = page.view() if sys.platform == "darwin": view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab # bar at the top. view.setAttribute(Qt.WA_MacShowFocusRect, False) name = str(index.data(Qt.DisplayRole)) page.setTitle(name) icon = index.data(Qt.DecorationRole) if isinstance(icon, QIcon): page.setIcon(icon) page.setToolTip(index.data(Qt.ToolTipRole)) return page def setModel(self, model): """ Set the model containing the actions. """ root = model.invisibleRootItem() for i in range(root.rowCount()): item = root.child(i) index = item.index() page = self.createPage(index) page.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) i = self.addPage(page.title(), page) brush = index.data(QtWidgetRegistry.BACKGROUND_ROLE) if isinstance(brush, QBrush): base_color = brush.color() button = self.__pages.tabButton(i) button.setStyleSheet( TAB_BUTTON_STYLE_TEMPLATE % (create_css_gradient(base_color), create_css_gradient(base_color.darker(120))) ) self.__model = model self.__suggestPage.setModel(model) def setSortingFunc(self, func): """ Set a sorting function in the suggest (search) menu. """ if self.__sortingFunc != func: self.__sortingFunc = func for i in range(0, self.__pages.count()): if isinstance(self.__pages.page(i), SuggestMenuPage): self.__pages.page(i).setSortingFunc(func) def setFilterFunc(self, func): """ Set a filter function. """ if func != self.__filterFunc: self.__filterFunc = func for i in range(0, self.__pages.count()): self.__pages.page(i).setFilterFunc(func) def popup(self, pos=None, searchText=""): """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp("(^|\W)"+searchText) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) UsageStatistics.set_last_search_query(searchText) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() self.setFocusProxy(self.__search) def exec_(self, pos=None, searchText=""): """ Execute the menu at position `pos` (in global screen coordinates). Return the triggered :class:`QAction` or `None` if no action was triggered. 'Search' text field is initialized with `searchText` if provided. """ self.popup(pos, searchText) self.setFocus(Qt.PopupFocusReason) self.__triggeredAction = None self.__loop = QEventLoop() self.__loop.exec_() self.__loop.deleteLater() self.__loop = None action = self.__triggeredAction self.__triggeredAction = None return action def hideEvent(self, event): """ Reimplemented from :class:`QWidget` """ FramelessWindow.hideEvent(self, event) if self.__loop: self.__loop.exit() def setCurrentPage(self, page): """ Set the current shown page to `page`. """ self.__pages.setCurrentPage(page) def setCurrentIndex(self, index): """ Set the current page index. """ self.__pages.setCurrentIndex(index) def __clearCurrentItems(self): """ Clear any selected (or current) items in all the menus. """ for i in range(self.__pages.count()): self.__pages.page(i).view().selectionModel().clear() def __onTriggered(self, action): """ Re-emit the action from the page. """ self.__triggeredAction = action # Hide and exit the event loop if necessary. self.hide() self.triggered.emit(action) def __on_textEdited(self, text): patt = QRegExp("(^|\W)" + text) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) self.__pages.setCurrentPage(self.__suggestPage) self.__selectFirstIndex() UsageStatistics.set_last_search_query(text) def __selectFirstIndex(self): view = self.__pages.currentPage().view() model = view.model() index = model.index(0, 0) view.setCurrentIndex(index) def triggerSearch(self): """ Trigger action search. This changes to current page to the 'Suggest' page and sets the keyboard focus to the search line edit. """ self.__pages.setCurrentPage(self.__suggestPage) self.__search.setFocus(Qt.ShortcutFocusReason) # Make sure that the first enabled item is set current. self.__suggestPage.ensureCurrent() def keyPressEvent(self, event): if event.text(): # Ignore modifiers, ... self.__search.setFocus(Qt.ShortcutFocusReason) self.setCurrentIndex(0) self.__search.keyPressEvent(event) FramelessWindow.keyPressEvent(self, event) event.accept() def event(self, event): if event.type() == QEvent.ShortcutOverride: log.debug("Overriding shortcuts") event.accept() return True return FramelessWindow.event(self, event) def eventFilter(self, obj, event): if isinstance(obj, QTreeView): etype = event.type() if etype == QEvent.KeyPress: # ignore modifiers non printable characters, Enter, ... if event.text() and event.key() not in \ [Qt.Key_Enter, Qt.Key_Return]: self.__search.setFocus(Qt.ShortcutFocusReason) self.setCurrentIndex(0) self.__search.keyPressEvent(event) return True return FramelessWindow.eventFilter(self, obj, event)
def __init__(self): super().__init__() self.output_corpus = None self.pubmed_api = None self.progress = None self.email_is_valid = False self.record_count = 0 self.download_running = False # To hold all the controls. Makes access easier. self.pubmed_controls = [] h_box = gui.hBox(self.controlArea) label = gui.label(h_box, self, 'Email:') label.setMaximumSize(label.sizeHint()) # Drop-down for recent emails. self.email_combo = QComboBox(h_box) self.email_combo.setMinimumWidth(150) self.email_combo.setEditable(True) self.email_combo.lineEdit().textChanged.connect(self.sync_email) h_box.layout().addWidget(self.email_combo) self.email_combo.activated[int].connect(self.select_email) # RECORD SEARCH self.search_tabs = gui.tabWidget(self.controlArea) # --- Regular search --- regular_search_box = gui.widgetBox(self.controlArea, addSpace=True) # Author self.author_input = gui.lineEdit(regular_search_box, self, 'author', 'Author:', orientation=Qt.Horizontal) self.pubmed_controls.append(self.author_input) h_box = gui.hBox(regular_search_box) year_box = gui.widgetBox(h_box, orientation=Qt.Horizontal) min_date = QDate.fromString( self.MIN_DATE.strftime(self.PY_DATE_FORMAT), self.QT_DATE_FORMAT) if not self.pub_date_from: self.pub_date_from = self.MIN_DATE.strftime(self.PY_DATE_FORMAT) if not self.pub_date_to: self.pub_date_to = date.today().strftime(self.PY_DATE_FORMAT) self.date_from = QDateEdit(QDate.fromString(self.pub_date_from, self.QT_DATE_FORMAT), displayFormat=self.QT_DATE_FORMAT, minimumDate=min_date, calendarPopup=True) self.date_to = QDateEdit(QDate.fromString(self.pub_date_to, self.QT_DATE_FORMAT), displayFormat=self.QT_DATE_FORMAT, minimumDate=min_date, calendarPopup=True) self.date_from.dateChanged.connect(lambda date: setattr( self, 'pub_date_from', date.toString(self.QT_DATE_FORMAT))) self.date_to.dateChanged.connect(lambda date: setattr( self, 'pub_date_to', date.toString(self.QT_DATE_FORMAT))) self.pubmed_controls.append(self.date_from) self.pubmed_controls.append(self.date_to) gui.label(year_box, self, 'From:') year_box.layout().addWidget(self.date_from) gui.label(year_box, self, 'to:') year_box.layout().addWidget(self.date_to) # Keywords. h_box = gui.hBox(regular_search_box) label = gui.label(h_box, self, 'Query:') label.setMaximumSize(label.sizeHint()) self.keyword_combo = QComboBox(h_box) self.keyword_combo.setMinimumWidth(150) self.keyword_combo.setEditable(True) h_box.layout().addWidget(self.keyword_combo) self.keyword_combo.activated[int].connect(self.select_keywords) self.pubmed_controls.append(self.keyword_combo) tab_height = regular_search_box.sizeHint() regular_search_box.setMaximumSize(tab_height) # --- Advanced search --- advanced_search_box = gui.widgetBox(self.controlArea, addSpace=True) # Advanced search query. h_box = gui.hBox(advanced_search_box) self.advanced_query_input = QTextEdit(h_box) h_box.layout().addWidget(self.advanced_query_input) self.advanced_query_input.setMaximumSize(tab_height) self.pubmed_controls.append(self.advanced_query_input) gui.createTabPage(self.search_tabs, 'Regular search', regular_search_box) gui.createTabPage(self.search_tabs, 'Advanced search', advanced_search_box) # Search info label. self.search_info_label = gui.label(self.controlArea, self, 'Number of records found: /') # Search for records button. self.run_search_button = gui.button( self.controlArea, self, 'Find records', callback=self.run_search, tooltip='Performs a search for articles that fit the ' 'specified parameters.') self.pubmed_controls.append(self.run_search_button) h_line = QFrame() h_line.setFrameShape(QFrame.HLine) h_line.setFrameShadow(QFrame.Sunken) self.controlArea.layout().addWidget(h_line) # RECORD RETRIEVAL # Text includes box. text_includes_box = gui.widgetBox(self.controlArea, 'Text includes', addSpace=True) self.authors_checkbox = gui.checkBox(text_includes_box, self, 'includes_authors', 'Authors') self.title_checkbox = gui.checkBox(text_includes_box, self, 'includes_title', 'Article title') self.mesh_checkbox = gui.checkBox(text_includes_box, self, 'includes_mesh', 'Mesh headings') self.abstract_checkbox = gui.checkBox(text_includes_box, self, 'includes_abstract', 'Abstract') self.url_checkbox = gui.checkBox(text_includes_box, self, 'includes_url', 'URL') self.pubmed_controls.append(self.authors_checkbox) self.pubmed_controls.append(self.title_checkbox) self.pubmed_controls.append(self.mesh_checkbox) self.pubmed_controls.append(self.abstract_checkbox) self.pubmed_controls.append(self.url_checkbox) # Num. records. h_box = gui.hBox(self.controlArea) label = gui.label(h_box, self, 'Retrieve') label.setMaximumSize(label.sizeHint()) self.num_records_input = gui.spin(h_box, self, 'num_records', minv=1, maxv=10000) self.max_records_label = gui.label(h_box, self, 'records from /.') self.max_records_label.setMaximumSize( self.max_records_label.sizeHint()) self.pubmed_controls.append(self.num_records_input) # Download articles. # Search for records button. self.retrieve_records_button = gui.button( self.controlArea, self, 'Retrieve records', callback=self.retrieve_records, tooltip='Retrieves the specified documents.') self.pubmed_controls.append(self.retrieve_records_button) # Num. retrieved records info label. self.retrieval_info_label = gui.label( self.controlArea, self, 'Number of records retrieved: /') # Load the most recent emails. self.set_email_list() # Load the most recent queries. self.set_keyword_list() # Check the email and enable controls accordingly. if self.recent_emails: email = self.recent_emails[0] self.email_is_valid = validate_email(email) self.enable_controls()
def __init__(self, parent=None, **kwargs): # type: (Optional[QWidget], Any) -> None super().__init__(parent, **kwargs) self.setWindowFlags(Qt.Popup) self.__filterFunc = None # type: Optional[FilterFunc] self.__sortingFunc = None # type: Optional[Callable[[Any, Any], bool]] self.setLayout(QVBoxLayout(self)) self.layout().setContentsMargins(6, 6, 6, 6) self.__search = SearchWidget(self, objectName="search-line") self.__search.setPlaceholderText( self.tr("Search for widget or select from the list.")) self.layout().addWidget(self.__search) self.__frame = QFrame(self, objectName="menu-frame") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) self.__frame.setLayout(layout) self.layout().addWidget(self.__frame) self.__pages = PagedMenu(self, objectName="paged-menu") self.__pages.currentChanged.connect(self.setCurrentIndex) self.__pages.triggered.connect(self.triggered) self.__pages.hovered.connect(self.hovered) self.__frame.layout().addWidget(self.__pages) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__suggestPage = SuggestMenuPage(self, objectName="suggest-page") self.__suggestPage.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) self.__suggestPage.setIcon(icon_loader().get("icons/Search.svg")) if sys.platform == "darwin": view = self.__suggestPage.view() view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab bar. view.setAttribute(Qt.WA_MacShowFocusRect, False) i = self.addPage(self.tr("Quick Search"), self.__suggestPage) button = self.__pages.tabButton(i) button.setObjectName("search-tab-button") button.setStyleSheet("TabButton {\n" " qproperty-flat_: false;\n" " border: none;" "}\n") self.__search.textEdited.connect(self.__on_textEdited) self.__navigator = ItemViewKeyNavigator(self) self.__navigator.setView(self.__suggestPage.view()) self.__search.installEventFilter(self.__navigator) self.__grip = WindowSizeGrip(self) # type: Optional[WindowSizeGrip] self.__grip.raise_() self.__loop = None # type: Optional[QEventLoop] self.__model = None # type: Optional[QAbstractItemModel] self.setModel(QStandardItemModel()) self.__triggeredAction = None # type: Optional[QAction]
class QuickMenu(FramelessWindow): """ A quick menu popup for the widgets. The widgets are set using :func:`QuickMenu.setModel` which must be a model as returned by :func:`QtWidgetRegistry.model` """ #: An action has been triggered in the menu. triggered = Signal(QAction) #: An action has been hovered in the menu hovered = Signal(QAction) def __init__(self, parent=None, **kwargs): # type: (Optional[QWidget], Any) -> None super().__init__(parent, **kwargs) self.setWindowFlags(Qt.Popup) self.__filterFunc = None # type: Optional[FilterFunc] self.__sortingFunc = None # type: Optional[Callable[[Any, Any], bool]] self.setLayout(QVBoxLayout(self)) self.layout().setContentsMargins(6, 6, 6, 6) self.__search = SearchWidget(self, objectName="search-line") self.__search.setPlaceholderText( self.tr("Search for widget or select from the list.")) self.layout().addWidget(self.__search) self.__frame = QFrame(self, objectName="menu-frame") layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(2) self.__frame.setLayout(layout) self.layout().addWidget(self.__frame) self.__pages = PagedMenu(self, objectName="paged-menu") self.__pages.currentChanged.connect(self.setCurrentIndex) self.__pages.triggered.connect(self.triggered) self.__pages.hovered.connect(self.hovered) self.__frame.layout().addWidget(self.__pages) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding) self.__suggestPage = SuggestMenuPage(self, objectName="suggest-page") self.__suggestPage.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) self.__suggestPage.setIcon(icon_loader().get("icons/Search.svg")) if sys.platform == "darwin": view = self.__suggestPage.view() view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab bar. view.setAttribute(Qt.WA_MacShowFocusRect, False) i = self.addPage(self.tr("Quick Search"), self.__suggestPage) button = self.__pages.tabButton(i) button.setObjectName("search-tab-button") button.setStyleSheet("TabButton {\n" " qproperty-flat_: false;\n" " border: none;" "}\n") self.__search.textEdited.connect(self.__on_textEdited) self.__navigator = ItemViewKeyNavigator(self) self.__navigator.setView(self.__suggestPage.view()) self.__search.installEventFilter(self.__navigator) self.__grip = WindowSizeGrip(self) # type: Optional[WindowSizeGrip] self.__grip.raise_() self.__loop = None # type: Optional[QEventLoop] self.__model = None # type: Optional[QAbstractItemModel] self.setModel(QStandardItemModel()) self.__triggeredAction = None # type: Optional[QAction] def setSizeGripEnabled(self, enabled): # type: (bool) -> None """ Enable the resizing of the menu with a size grip in a bottom right corner (enabled by default). """ if bool(enabled) != bool(self.__grip): if self.__grip: self.__grip.deleteLater() self.__grip = None else: self.__grip = WindowSizeGrip(self) self.__grip.raise_() def sizeGripEnabled(self): # type: () -> bool """ Is the size grip enabled. """ return bool(self.__grip) def addPage(self, name, page): # type: (str, MenuPage) -> int """ Add the `page` (:class:`MenuPage`) with `name` and return it's index. The `page.icon()` will be used as the icon in the tab bar. """ return self.insertPage(self.__pages.count(), name, page) def insertPage(self, index, name, page): # type: (int, str, MenuPage) -> int icon = page.icon() tip = name if page.toolTip(): tip = page.toolTip() index = self.__pages.insertPage(index, page, name, icon, tip) # Route the page's signals page.triggered.connect(self.__onTriggered) page.hovered.connect(self.hovered) # Install event filter to intercept key presses. page.view().installEventFilter(self) return index def createPage(self, index): # type: (QModelIndex) -> MenuPage """ Create a new page based on the contents of an index (:class:`QModeIndex`) item. """ page = MenuPage(self) page.setModel(index.model()) page.setRootIndex(index) view = page.view() if sys.platform == "darwin": view.verticalScrollBar().setAttribute(Qt.WA_MacMiniSize, True) # Don't show the focus frame because it expands into the tab # bar at the top. view.setAttribute(Qt.WA_MacShowFocusRect, False) name = str(index.data(Qt.DisplayRole)) page.setTitle(name) icon = index.data(Qt.DecorationRole) if isinstance(icon, QIcon): page.setIcon(icon) page.setToolTip(index.data(Qt.ToolTipRole)) return page def __clear(self): # type: () -> None for i in range(self.__pages.count() - 1, 0, -1): self.__pages.removePage(i) def setModel(self, model): # type: (QAbstractItemModel) -> None """ Set the model containing the actions. """ if self.__model is not None: self.__model.dataChanged.disconnect(self.__on_dataChanged) self.__model.rowsInserted.disconnect(self.__on_rowsInserted) self.__model.rowsRemoved.disconnect(self.__on_rowsRemoved) self.__clear() for i in range(model.rowCount()): index = model.index(i, 0) self.__insertPage(i + 1, index) self.__model = model self.__suggestPage.setModel(model) if model is not None: model.dataChanged.connect(self.__on_dataChanged) model.rowsInserted.connect(self.__on_rowsInserted) model.rowsRemoved.connect(self.__on_rowsRemoved) def __on_dataChanged(self, topLeft, bottomRight): # type: (QModelIndex, QModelIndex) -> None parent = topLeft.parent() # Only handle top level item (categories). if not parent.isValid(): for row in range(topLeft.row(), bottomRight.row() + 1): index = topLeft.sibling(row, 0) # Note: the tab buttons are offest by 1 (to accommodate # the Suggest Page). button = self.__pages.tabButton(row + 1) brush = as_qbrush(index.data(QtWidgetRegistry.BACKGROUND_ROLE)) if brush is not None: base_color = brush.color() button.setStyleSheet( TAB_BUTTON_STYLE_TEMPLATE % (create_css_gradient(base_color), create_css_gradient(base_color.darker(120)))) def __on_rowsInserted(self, parent, start, end): # type: (QModelIndex, int, int) -> None # Only handle top level item (categories). assert self.__model is not None if not parent.isValid(): for row in range(start, end + 1): index = self.__model.index(row, 0) self.__insertPage(row + 1, index) def __on_rowsRemoved(self, parent, start, end): # type: (QModelIndex, int, int) -> None # Only handle top level item (categories). if not parent.isValid(): for row in range(end, start - 1, -1): self.__removePage(row + 1) def __insertPage(self, row, index): # type: (int, QModelIndex) -> None page = self.createPage(index) page.setActionRole(QtWidgetRegistry.WIDGET_ACTION_ROLE) i = self.insertPage(row, page.title(), page) brush = as_qbrush(index.data(QtWidgetRegistry.BACKGROUND_ROLE)) if brush is not None: base_color = brush.color() button = self.__pages.tabButton(i) button.setStyleSheet(TAB_BUTTON_STYLE_TEMPLATE % (create_css_gradient(base_color), create_css_gradient(base_color.darker(120)))) def __removePage(self, row): # type: (int) -> None page = self.__pages.page(row) page.triggered.disconnect(self.__onTriggered) page.hovered.disconnect(self.hovered) page.view().removeEventFilter(self) self.__pages.removePage(row) def setSortingFunc(self, func): # type: (Callable[[Any, Any], bool]) -> None """ Set a sorting function in the suggest (search) menu. """ if self.__sortingFunc != func: self.__sortingFunc = func for i in range(0, self.__pages.count()): page = self.__pages.page(i) if isinstance(page, SuggestMenuPage): page.setSortingFunc(func) def setFilterFunc(self, func): # type: (Optional[FilterFunc]) -> None """ Set a filter function. """ if func != self.__filterFunc: self.__filterFunc = func for i in range(0, self.__pages.count()): self.__pages.page(i).setFilterFunc(func) def popup(self, pos=None, searchText=""): # type: (Optional[QPoint], str) -> None """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp(r"(^|\W)" + searchText) patt.setCaseSensitivity(Qt.CaseInsensitive) self.__suggestPage.setFilterRegExp(patt) UsageStatistics.set_last_search_query(searchText) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() self.setFocusProxy(self.__search) def exec_(self, pos=None, searchText=""): # type: (Optional[QPoint], str) -> Optional[QAction] """ Execute the menu at position `pos` (in global screen coordinates). Return the triggered :class:`QAction` or `None` if no action was triggered. 'Search' text field is initialized with `searchText` if provided. """ self.popup(pos, searchText) self.setFocus(Qt.PopupFocusReason) self.__triggeredAction = None self.__loop = QEventLoop() self.__loop.exec_() self.__loop.deleteLater() self.__loop = None action = self.__triggeredAction self.__triggeredAction = None return action def hideEvent(self, event): """ Reimplemented from :class:`QWidget` """ super().hideEvent(event) if self.__loop: self.__loop.exit() def setCurrentPage(self, page): # type: (MenuPage) -> None """ Set the current shown page to `page`. """ self.__pages.setCurrentPage(page) def setCurrentIndex(self, index): # type: (int) -> None """ Set the current page index. """ self.__pages.setCurrentIndex(index) def __clearCurrentItems(self): # type: () -> None """ Clear any selected (or current) items in all the menus. """ for i in range(self.__pages.count()): self.__pages.page(i).view().selectionModel().clear() def __onTriggered(self, action): # type: (QAction) -> None """ Re-emit the action from the page. """ self.__triggeredAction = action # Hide and exit the event loop if necessary. self.hide() self.triggered.emit(action) def __on_textEdited(self, text): # type: (str) -> None patt = QRegExp(r"(^|\W)" + text) patt.setCaseSensitivity(Qt.CaseInsensitive) self.__suggestPage.setFilterRegExp(patt) self.__pages.setCurrentPage(self.__suggestPage) self.__selectFirstIndex() UsageStatistics.set_last_search_query(text) def __selectFirstIndex(self): # type: () -> None view = self.__pages.currentPage().view() model = view.model() index = model.index(0, 0) view.setCurrentIndex(index) def triggerSearch(self): # type: () -> None """ Trigger action search. This changes to current page to the 'Suggest' page and sets the keyboard focus to the search line edit. """ self.__pages.setCurrentPage(self.__suggestPage) self.__search.setFocus(Qt.ShortcutFocusReason) # Make sure that the first enabled item is set current. self.__suggestPage.ensureCurrent() def keyPressEvent(self, event): if event.text(): # Ignore modifiers, ... self.__search.setFocus(Qt.ShortcutFocusReason) self.setCurrentIndex(0) self.__search.keyPressEvent(event) super().keyPressEvent(event) event.accept() def event(self, event): if event.type() == QEvent.ShortcutOverride: log.debug("Overriding shortcuts") event.accept() return True return super().event(event) def eventFilter(self, obj, event): if isinstance(obj, QTreeView): etype = event.type() if etype == QEvent.KeyPress: # ignore modifiers non printable characters, Enter, ... if event.text() and event.key() not in \ [Qt.Key_Enter, Qt.Key_Return]: self.__search.setFocus(Qt.ShortcutFocusReason) self.setCurrentIndex(0) self.__search.keyPressEvent(event) return True return super().eventFilter(obj, event)
def sizeHint(self): size = QFrame.sizeHint(self) return QSize(size.width(), 150)
def show(self): QFrame.show(self)
def hide(self): QFrame.hide(self)
def hide(self): QFrame.hide(self) def show(self): QFrame.show(self)
def generate_panel(self, formset): """ Generate a panel for the module form with all the controls formset format example: [('_video', '_arenas', '_run'), {"Player":['_threshold', "_player", "=", "_results", "_query"], "Background image":[(' ', '_selectBackground', '_paintBackground'), '_image']}, "_progress"] tuple: will display the controls in the same horizontal line list: will display the controls in the same vertical line dict: will display the controls in a tab widget '||': will plit the controls in a horizontal line '=': will plit the controls in a vertical line @param formset: Form configuration @type formset: list """ control = None if '=' in formset or isinstance(formset, hsplitter): control = QSplitter(QtCore.Qt.Vertical) index = list(formset).index('=') first_panel = self.generate_panel(formset[0:index]) second_panel = self.generate_panel(formset[index + 1:]) control.addWidget(first_panel) control.addWidget(second_panel) self._splitters.append(control) return control elif '||' in formset or isinstance(formset, vsplitter): control = QSplitter(QtCore.Qt.Horizontal) index = list(formset).index('||') first_panel = self.generate_panel(formset[0:index]) second_panel = self.generate_panel(formset[index + 1:]) control.addWidget(first_panel) control.addWidget(second_panel) if isinstance(formset, vsplitter): sizes = [formset.left_width, formset.right_width] control.setSizes(sizes) self._splitters.append(control) return control control = QFrame(self) layout = None if type(formset) is tuple: layout = QHBoxLayout() for row in formset: if isinstance(row, (list, tuple, vsplitter, hsplitter)): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout.addItem(spacer) elif type(row) is dict: c = self.generate_tabs(row) layout.addWidget(c) self._tabs.append(c) else: param = self.controls.get(row, None) if param is None: label = QLabel() label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) # layout.addWidget( label ) if row.startswith('info:'): label.setText(row[5:]) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('info') elif row.startswith('h1:'): label.setText(row[3:]) font = QFont() font.setPointSize(17) font.setBold(True) label.setFont(font) label.setAccessibleName('h1') elif row.startswith('h2:'): label.setText(row[3:]) font = QFont() font.setPointSize(16) font.setBold(True) label.setFont(font) label.setAccessibleName('h2') elif row.startswith('h3:'): label.setText(row[3:]) font = QFont() font.setPointSize(15) font.setBold(True) label.setFont(font) label.setAccessibleName('h3') elif row.startswith('h4:'): label.setText(row[3:]) font = QFont() font.setPointSize(14) font.setBold(True) label.setFont(font) label.setAccessibleName('h4') elif row.startswith('h5:'): label.setText(row[3:]) font = QFont() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAccessibleName('h5') else: label.setText(row) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('msg') label.setToolTip(label.text()) layout.addWidget(label) else: param.parent = self param.name = row layout.addWidget(param.form) elif type(formset) is list: layout = QVBoxLayout() for row in formset: if isinstance(row, (list, tuple, vsplitter, hsplitter)): panel = self.generate_panel(row) layout.addWidget(panel) elif row == " ": spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) layout.addItem(spacer) elif type(row) is dict: c = self.generate_tabs(row) layout.addWidget(c) self._tabs.append(c) else: param = self.controls.get(row, None) if param is None: label = QLabel() label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) label.resize(30, 30) # layout.addWidget( label ) if row.startswith('info:'): label.setText(row[5:]) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('info') elif row.startswith('h1:'): label.setText(row[3:]) font = QFont() font.setPointSize(17) font.setBold(True) label.setFont(font) label.setAccessibleName('h1') elif row.startswith('h2:'): label.setText(row[3:]) font = QFont() font.setPointSize(16) font.setBold(True) label.setFont(font) label.setAccessibleName('h2') elif row.startswith('h3:'): label.setText(row[3:]) font = QFont() font.setPointSize(15) font.setBold(True) label.setFont(font) label.setAccessibleName('h3') elif row.startswith('h4:'): label.setText(row[3:]) font = QFont() font.setPointSize(14) font.setBold(True) label.setFont(font) label.setAccessibleName('h4') elif row.startswith('h5:'): label.setText(row[3:]) font = QFont() font.setPointSize(12) font.setBold(True) label.setFont(font) label.setAccessibleName('h5') else: label.setText(row) font = QFont() font.setPointSize(10) label.setFont(font) label.setAccessibleName('msg') label.setToolTip(label.text()) layout.addWidget(label) else: param.parent = self param.name = row layout.addWidget(param.form) if _api.USED_API == _api.QT_API_PYQT5: layout.setContentsMargins(0, 0, 0, 0) elif _api.USED_API == _api.QT_API_PYQT4: layout.setMargin(0) control.setLayout(layout) return control
def show(self): QFrame.show(self) def refresh(self):
def sizeHint(self): hint = QFrame.sizeHint(self) if hint.isEmpty(): hint = QSize(0, 0) return hint