📄 qmenu.cpp
字号:
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); 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; else newOffset = (q->height() - botScroll) - saccum; 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+topScroll; 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 = QApplication::desktop()->availableGeometry(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 geom.setHeight(geom.height()-(newOffset-scroll->scrollOffset)); } else if(scroll->scrollFlags & newScrollFlags & QMenuScroller::ScrollDown) { geom.setTop(geom.top() + (newOffset-scroll->scrollOffset)); if (geom != q->geometry()) { 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..}//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) { for(int i = 0, saccum = 0; i < actionList.count(); i++) { QAction *act = actionList.at(i); const int iHeight = actionRects.value(act).height(); 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) { scrollMenu(act, page ? QMenuScroller::ScrollTop : QMenuScroller::ScrollBottom, active); break; } } break; } saccum -= iHeight; } }}/* This is poor-mans eventfilters. This avoids the use of eventFilter (which can be nasty for users of QMenuBar's). */bool QMenuPrivate::mouseEventTaken(QMouseEvent *e){ Q_Q(QMenu); QPoint pos = q->mapFromGlobal(e->globalPos()); if (scroll && !activeMenu) { //let the scroller "steal" the event bool isScroll = false; if (pos.x() >= 0 && pos.x() < q->width()) { const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); for(int dir = QMenuScroller::ScrollUp; dir <= QMenuScroller::ScrollDown; dir = dir << 1) { if (scroll->scrollFlags & dir) { if (dir == QMenuScroller::ScrollUp) isScroll = (pos.y() <= scrollerHeight); else if (dir == QMenuScroller::ScrollDown) isScroll = (pos.y() >= q->height()-scrollerHeight); if (isScroll) { scroll->scrollDirection = dir; break; } } } } if (isScroll) { if (!scroll->scrollTimer) scroll->scrollTimer = new QBasicTimer; scroll->scrollTimer->start(50, q); return true; } else if (scroll->scrollTimer && scroll->scrollTimer->isActive()) { scroll->scrollTimer->stop(); } } if (tearoff) { //let the tear off thingie "steal" the event.. QRect tearRect(0, 0, q->width(), q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q)); if (scroll && scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) tearRect.translate(0, q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q)); q->update(tearRect); if (tearRect.contains(pos)) { setCurrentAction(0); tearoffHighlighted = 1; if (e->type() == QEvent::MouseButtonRelease) { if (tornPopup) { tornPopup->close(); } else { tornPopup = new QTornOffMenu(q); tornPopup->setGeometry(q->geometry()); tornPopup->show(); } hideUpToMenuBar(); } return true; } tearoffHighlighted = 0; } if (q->frameGeometry().contains(e->globalPos())) //otherwise if the event is in our rect we want it.. return false; for(QWidget *caused = causedPopup.widget; caused;) { bool passOnEvent = false; QWidget *next_widget = 0; QPoint cpos = caused->mapFromGlobal(e->globalPos());#ifndef QT_NO_MENUBAR if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) { passOnEvent = mb->rect().contains(cpos); } else#endif if (QMenu *m = qobject_cast<QMenu*>(caused)) { passOnEvent = m->d_func()->actionAt(cpos); next_widget = m->d_func()->causedPopup.widget; } if (passOnEvent) { QMouseEvent new_e(e->type(), cpos, e->button(), e->buttons(), e->modifiers()); QApplication::sendEvent(caused, &new_e); return true; } if (!next_widget) break; caused = next_widget; } return false;}void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e){ Q_Q(QMenu);#ifndef QT_NO_WHATSTHIS bool inWhatsThisMode = QWhatsThis::inWhatsThisMode();#endif if (!action || !q->isEnabled() || (action_e == QAction::Trigger#ifndef QT_NO_WHATSTHIS && !inWhatsThisMode#endif && (action->isSeparator() ||!action->isEnabled()))) return; /* I have to save the caused stack here because it will be undone after popup execution (ie in the hide). Then I iterate over the list to actually send the events. --Sam */ QList<QPointer<QWidget> > causedStack; for(QWidget *widget = causedPopup.widget; widget; ) { causedStack.append(widget); if (QMenu *qmenu = ::qobject_cast<QMenu*>(widget)) widget = qmenu->d_func()->causedPopup.widget; else break; } if (action_e == QAction::Trigger) { hideUpToMenuBar();#ifndef QT_NO_WHATSTHIS if (inWhatsThisMode) { QString s = action->whatsThis(); if (s.isEmpty()) s = whatsThis; QWhatsThis::showText(q->mapToGlobal(actionRect(action).center()), s, q); return; }#endif } action->activate(action_e); for(int i = 0; i < causedStack.size(); ++i) { QPointer<QWidget> widget = causedStack.at(i); if (!widget) continue; //fire if (QMenu *qmenu = ::qobject_cast<QMenu*>(widget)) { widget = qmenu->d_func()->causedPopup.widget; if (action_e == QAction::Trigger) { emit qmenu->triggered(action);#ifdef QT3_SUPPORT emit qmenu->activated(qmenu->findIdForAction(action));#endif } else if (action_e == QAction::Hover) { emit qmenu->hovered(action);#ifdef QT3_SUPPORT emit qmenu->highlighted(qmenu->findIdForAction(action));#endif }#ifndef QT_NO_MENUBAR } else if (QMenuBar *qmenubar = ::qobject_cast<QMenuBar*>(widget)) { if (action_e == QAction::Trigger) { emit qmenubar->triggered(action);#ifdef QT3_SUPPORT emit qmenubar->activated(qmenubar->findIdForAction(action));#endif } else if (action_e == QAction::Hover) { emit qmenubar->hovered(action);#ifdef QT3_SUPPORT emit qmenubar->highlighted(qmenubar->findIdForAction(action));#endif } break; //nothing more..#endif } } if (action_e == QAction::Hover) {#ifndef QT_NO_ACCESSIBILITY int actionID = indexOf(action); QAccessible::updateAccessibility(q, actionID, QAccessible::Focus); QAccessible::updateAccessibility(q, actionID, QAccessible::Selection);#endif QWidget *w = causedPopup.widget; while (QMenu *m = qobject_cast<QMenu*>(w)) w = m->d_func()->causedPopup.widget; action->showStatusText(w); }}void QMenuPrivate::_q_actionTriggered(){ Q_Q(QMenu); if (QAction *action = qobject_cast<QAction *>(q->sender())) { emit q->triggered(action);#ifdef QT3_SUPPORT emit q->activated(q->findIdForAction(action));#endif }}void QMenuPrivate::_q_actionHovered(){ Q_Q(QMenu); if (QAction *action = qobject_cast<QAction *>(q->sender())) { emit q->hovered(action);#ifdef QT3_SUPPORT emit q->highlighted(q->findIdForAction(action));#endif }}QStyleOptionMenuItem QMenuPrivate::getStyleOption(const QAction *action) const{ Q_Q(const QMenu); QStyleOptionMenuItem opt; opt.initFrom(q); opt.palette = q->palette(); opt.state = QStyle::State_None; if (q->window()->isActiveWindow()) opt.state |= QStyle::State_Active; if (q->isEnabled() && action->isEnabled() && (!action->menu() || action->menu()->isEnabled())) opt.state |= QStyle::State_Enabled; else opt.palette.setCurrentColorGroup(QPalette::Disabled); opt.font = action->font(); if (currentAction && currentAction == action && !currentAction->isSeparator()) { opt.state |= QStyle::State_Selected | (mouseDown ? QStyle::State_Sunken : QStyle::State_None); } opt.menuHasCheckableItems = hasCheckableItems; if (!action->isCheckable()) { opt.checkType = QStyleOptionMenuItem::NotCheckable; } else { opt.checkType = (action->actionGroup() && action->actionGroup()->isExclusive()) ? QStyleOptionMenuItem::Exclusive : QStyleOptionMenuItem::NonExclusive; opt.checked = action->isChecked(); } if (action->menu()) opt.menuItemType = QStyleOptionMenuItem::SubMenu; else if (action->isSeparator()) opt.menuItemType = QStyleOptionMenuItem::Separator; else if (defaultAction == action) opt.menuItemType = QStyleOptionMenuItem::DefaultItem; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -