📄 qmenu.cpp
字号:
if (QMenu *m = qobject_cast<QMenu*>(caused)) { caused = m->d_func()->causedPopup.widget; if (!m->d_func()->tornoff) m->hide(); m->d_func()->setCurrentAction(0); } else {#ifndef QT_NO_TOOLBUTTON if (qobject_cast<QToolButton*>(caused) == 0)#endif qWarning("QMenu: Internal error"); caused = 0; } } } setCurrentAction(0);}void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst){ Q_Q(QMenu); if (action && action->isEnabled()) { if (!delay) q->internalDelayedPopup(); else QMenuPrivate::menuDelayTimer.start(delay, q); if (activateFirst && action->menu()) action->menu()->d_func()->setFirstActionActive(); } else if (QMenu *menu = activeMenu) { //hide the current item activeMenu = 0; menu->hide(); }}void QMenuPrivate::setSyncAction(){ Q_Q(QMenu); QAction *current = currentAction; if(current && (!current->isEnabled() || current->menu() || current->isSeparator())) current = 0; for(QWidget *caused = q; caused;) { if (QMenu *m = qobject_cast<QMenu*>(caused)) { caused = m->d_func()->causedPopup.widget; if (m->d_func()->eventLoop) m->d_func()->syncAction = current; // synchronous operation } else { break; } }}void QMenuPrivate::setFirstActionActive(){ Q_Q(QMenu); const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); for(int i = 0, saccum = 0; i < actionList.count(); i++) { QAction *act = actionList[i]; if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) { saccum -= actionRects.value(act).height(); if (saccum > scroll->scrollOffset-scrollerHeight) continue; } if (!act->isSeparator() && (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) || act->isEnabled())) { setCurrentAction(act); break; } }}// popup == -1 means do not popup, 0 means immediately, others mean use a timervoid QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason reason, bool activateFirst){ Q_Q(QMenu); tearoffHighlighted = 0; if (action == currentAction && !(action && action->menu() && action->menu() != activeMenu)) { if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) { if(causedPopup.action && menu->d_func()->activeMenu == q) menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false); } return; } if (currentAction) q->update(actionRect(currentAction)); sloppyAction = 0; if (!sloppyRegion.isEmpty()) sloppyRegion = QRegion(); QMenu *hideActiveMenu = activeMenu;#ifndef QT_NO_STATUSTIP QAction *previousAction = currentAction;#endif currentAction = action; if (action) { if (!action->isSeparator()) { activateAction(action, QAction::Hover); if (popup != -1) { hideActiveMenu = 0; //will be done "later" popupAction(currentAction, popup, activateFirst); } q->update(actionRect(action)); QWidget *widget = widgetItems.value(action); if (reason == SelectedFromKeyboard) { if (widget) { if (widget->focusPolicy() != Qt::NoFocus) widget->setFocus(Qt::TabFocusReason); } else { //when the action has no QWidget, the QMenu itself should // get the focus // Since the menu is a pop-up, it uses the popup reason. q->setFocus(Qt::PopupFocusReason); } } } else { //action is a separator if (popup != -1) hideActiveMenu = 0; //will be done "later" }#ifndef QT_NO_STATUSTIP } else if (previousAction) { QWidget *w = causedPopup.widget; while (QMenu *m = qobject_cast<QMenu*>(w)) w = m->d_func()->causedPopup.widget; if (w) { QString empty; QStatusTipEvent tip(empty); QApplication::sendEvent(w, &tip); }#endif } if (hideActiveMenu) { activeMenu = 0;#ifndef QT_NO_EFFECTS // kill any running effect qFadeEffect(0); qScrollEffect(0);#endif hideActiveMenu->hide(); }}QAction *QMenuPrivate::actionAt(QPoint p) const{ if (!q_func()->rect().contains(p)) //sanity check return 0; for(int i = 0; i < actionList.count(); i++) { QAction *act = actionList[i]; if (actionRect(act).contains(p)) return act; } return 0;}void QMenuPrivate::setOverrideMenuAction(QAction *a){ Q_Q(QMenu); QObject::disconnect(menuAction, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed())); if (a) { menuAction = a; QObject::connect(a, SIGNAL(destroyed()), q, SLOT(_q_overrideMenuActionDestroyed())); } else { //we revert back to the default action created by the QMenu itself menuAction = defaultMenuAction; }}void QMenuPrivate::_q_overrideMenuActionDestroyed(){ menuAction=defaultMenuAction;}/*! Returns the action associated with this menu.*/QAction *QMenu::menuAction() const{ return d_func()->menuAction;}/*! \property QMenu::title \brief The title of the menu This is equivalent to the QAction::text property of the menuAction().*/QString QMenu::title() const{ return d_func()->menuAction->text();}void QMenu::setTitle(const QString &text){ d_func()->menuAction->setText(text);}/*! \property QMenu::icon \brief The icon of the menu This is equivalent to the QAction::icon property of the menuAction().*/QIcon QMenu::icon() const{ return d_func()->menuAction->icon();}void QMenu::setIcon(const QIcon &icon){ d_func()->menuAction->setIcon(icon);}//actually performs the scrollingvoid QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active){ Q_Q(QMenu); if (!scroll || !scroll->scrollFlags) return; int newOffset = 0; const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0; const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q); if (location == QMenuScroller::ScrollTop) { for(int i = 0, saccum = 0; i < actionList.count(); i++) { QAction *act = actionList.at(i); if (act == action) { newOffset = topScroll - saccum; break; } saccum += actionRects.value(act).height(); } } else { for(int i = 0, saccum = 0; i < actionList.count(); i++) { QAction *act = actionList.at(i); saccum += actionRects.value(act).height(); if (act == action) { if (location == QMenuScroller::ScrollCenter) newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll); else newOffset = (q->height() - botScroll) - (saccum - topScroll); break; } } if(newOffset) newOffset -= vmargin*2; } //figure out which scroll flags uint newScrollFlags = QMenuScroller::ScrollNone; if (newOffset < 0) //easy and cheap one newScrollFlags |= QMenuScroller::ScrollUp; for(int i = 0, saccum=newOffset; i < actionList.count(); i++) { saccum += actionRects.value(actionList.at(i)).height(); if (saccum > q->height()) { newScrollFlags |= QMenuScroller::ScrollDown; break; } } if (location == QMenuScroller::ScrollTop && ((newScrollFlags & QMenuScroller::ScrollUp) || !(scroll->scrollFlags & QMenuScroller::ScrollUp))) newOffset += scrollHeight; else if (location == QMenuScroller::ScrollBottom && ((newScrollFlags & QMenuScroller::ScrollDown) || !(scroll->scrollFlags & QMenuScroller::ScrollDown))) newOffset -= scrollHeight; QRect screen = popupGeometry(QApplication::desktop()->screenNumber(q)); const int desktopFrame = q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q); if (q->height() < screen.height()-(desktopFrame*2)-1) { QRect geom = q->geometry(); if (newOffset > scroll->scrollOffset && (scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollUp)) { //scroll up const int newHeight = geom.height()-(newOffset-scroll->scrollOffset); if(newHeight > geom.height()) geom.setHeight(newHeight); } else if(scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) { int newTop = geom.top() + (newOffset-scroll->scrollOffset); if (newTop < desktopFrame+screen.top()) newTop = desktopFrame+screen.top(); if (newTop < geom.top()) { geom.setTop(newTop); newOffset = 0; newScrollFlags &= ~QMenuScroller::ScrollUp; } } if (geom.bottom() > screen.bottom() - desktopFrame) geom.setBottom(screen.bottom() - desktopFrame); if (geom.top() < desktopFrame+screen.top()) geom.setTop(desktopFrame+screen.top()); if (geom != q->geometry()) {#if 0 if (newScrollFlags & QMenuScroller::ScrollDown && q->geometry().top() - geom.top() >= -newOffset) newScrollFlags &= ~QMenuScroller::ScrollDown;#endif q->setGeometry(geom); } } //actually update flags scroll->scrollOffset = newOffset; if (scroll->scrollOffset > 0) scroll->scrollOffset = 0; scroll->scrollFlags = newScrollFlags; if (active) setCurrentAction(action); q->update(); //issue an update so we see all the new state..}void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool active){ Q_Q(QMenu); if(location == QMenuScroller::ScrollBottom) { for(int i = actionList.size()-1; i >= 0; --i) { QAction *act = actionList.at(i); if (!act->isSeparator() && (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) || act->isEnabled())) { if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown) scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollBottom, active); else if(active) setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard); break; } } } else if(location == QMenuScroller::ScrollTop) { for(int i = 0; i < actionList.size(); ++i) { QAction *act = actionList.at(i); if (!act->isSeparator() && (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) || act->isEnabled())) { if(scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollTop, active); else if(active) setCurrentAction(act, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard); break; } } }}//only directionalvoid QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool page, bool active){ Q_Q(QMenu); if (!scroll || !(scroll->scrollFlags & direction)) //not really possible... return; const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0; if (direction == QMenuScroller::ScrollUp) { for(int i = 0, saccum = 0; i < actionList.count(); i++) { QAction *act = actionList.at(i); const int iHeight = actionRects.value(act).height(); saccum -= iHeight; if (saccum <= scroll->scrollOffset-topScroll) { scrollMenu(act, page ? QMenuScroller::ScrollBottom : QMenuScroller::ScrollTop, active); break; } } } else if (direction == QMenuScroller::ScrollDown) { bool scrolled = false; for(int i = 0, saccum = topScroll; i < actionList.count(); i++) { // saccum = topScroll QAction *act = actionList.at(i); const int iHeight = actionRects.value(act).height(); saccum -= iHeight; if (saccum <= scroll->scrollOffset-topScroll) { const int scrollerArea = q->height() - botScroll; int visible = -(((scroll->scrollOffset-topScroll) - saccum) - iHeight); for(i++ ; i < actionList.count(); i++) { act = actionList.at(i); const int iHeight = actionRects.value(act).height(); visible += iHeight; if (visible > scrollerArea-topScroll) { scrolled = true; scrollMenu(act, page ? QMenuScroller::ScrollTop : QMenuScroller::ScrollBottom, active); break; } } break; } } if(!scrolled) { scroll->scrollFlags &= ~QMenuScroller::ScrollDown; q->update(); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -