📄 qmenubar.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <qmenubar.h>#include <qstyle.h>#include <qlayout.h>#include <qapplication.h>#include <qdesktopwidget.h>#ifndef QT_NO_ACCESSIBILITY# include <qaccessible.h>#endif#include <qpainter.h>#include <qevent.h>#include <qmainwindow.h>#include <qtoolbar.h>#include <qtoolbutton.h>#include <qwhatsthis.h>#ifndef QT_NO_MENUBAR#ifdef QT3_SUPPORT#include <private/qaction_p.h>#include <qmenudata.h>#endif#include "qmenu_p.h"#include "qmenubar_p.h"#include "qdebug.h"class QMenuBarExtension : public QToolButton{public: explicit QMenuBarExtension(QWidget *parent); QSize sizeHint() const;};QMenuBarExtension::QMenuBarExtension(QWidget *parent) : QToolButton(parent){ setObjectName(QLatin1String("qt_menubar_ext_button")); setAutoRaise(true);#ifndef QT_NO_MENU setPopupMode(QToolButton::InstantPopup);#endif setIcon(style()->standardIcon(QStyle::SP_ToolBarHorizontalExtensionButton));}QSize QMenuBarExtension::sizeHint() const{ int ext = style()->pixelMetric(QStyle::PM_ToolBarExtensionExtent); return QSize(ext, ext);}QAction *QMenuBarPrivate::actionAt(QPoint p) const{ Q_Q(const QMenuBar); QList<QAction*> items = q->actions(); for(int i = 0; i < items.size(); ++i) { if(actionRect(items.at(i)).contains(p)) return items.at(i); } return 0;}QRect QMenuBarPrivate::menuRect(bool extVisible) const{ Q_Q(const QMenuBar); int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q); QRect result = q->rect(); result.adjust(hmargin, 0, -hmargin, 0); if (extVisible) { if (q->layoutDirection() == Qt::RightToLeft) result.setLeft(result.left() + extension->sizeHint().width()); else result.setWidth(result.width() - extension->sizeHint().width()); } if (leftWidget && leftWidget->isVisible()) { QSize sz = leftWidget->sizeHint(); if (q->layoutDirection() == Qt::RightToLeft) result.setRight(result.right() - sz.width()); else result.setLeft(result.left() + sz.width()); } if (rightWidget && rightWidget->isVisible()) { QSize sz = rightWidget->sizeHint(); if (q->layoutDirection() == Qt::RightToLeft) result.setLeft(result.left() + sz.width()); else result.setRight(result.right() - sz.width()); } return result;}bool QMenuBarPrivate::isVisible(QAction *action){ return !hiddenActions.contains(action);}void QMenuBarPrivate::updateGeometries(){ Q_Q(QMenuBar); if(!itemsDirty) return; int q_width = q->width()-(q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q)*2); int q_start = -1; if(leftWidget || rightWidget) { int vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q) + q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q); int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q) + q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q); if (leftWidget && leftWidget->isVisible()) { QSize sz = leftWidget->sizeHint(); q_width -= sz.width(); q_start = sz.width(); QPoint pos(hmargin, (q->height() - leftWidget->height()) / 2); QRect vRect = QStyle::visualRect(q->layoutDirection(), q->rect(), QRect(pos, sz)); leftWidget->setGeometry(vRect); } if (rightWidget && rightWidget->isVisible()) { QSize sz = rightWidget->sizeHint(); q_width -= sz.width(); QPoint pos(q->width() - sz.width() - hmargin, vmargin); QRect vRect = QStyle::visualRect(q->layoutDirection(), q->rect(), QRect(pos, sz)); rightWidget->setGeometry(vRect); } }#ifdef Q_WS_MAC if(mac_menubar) {//nothing to see here folks, move along.. itemsDirty = false; return; }#endif calcActionRects(q_width, q_start, actionRects, actionList); itemsWidth = q_width; itemsStart = q_start; currentAction = 0;#ifndef QT_NO_SHORTCUT if(itemsDirty) { for(int j = 0; j < shortcutIndexMap.size(); ++j) q->releaseShortcut(shortcutIndexMap.value(j)); shortcutIndexMap.resize(0); // faster than clear for(int i = 0; i < actionList.count(); i++) shortcutIndexMap.append(q->grabShortcut(QKeySequence::mnemonic(actionList.at(i)->text()))); }#endif itemsDirty = false; hiddenActions.clear(); //this is the menu rectangle without any extension QRect menuRect = this->menuRect(false); //we try to see if the actions will fit there bool hasHiddenActions = false; foreach(QAction *action, actionList) { if (!menuRect.contains(actionRect(action))) { hasHiddenActions = true; break; } } //...and if not, determine the ones that fit on the menu with the extension visible if (hasHiddenActions) { menuRect = this->menuRect(true); foreach(QAction *action, actionList) { if (!menuRect.contains(actionRect(action))) { hiddenActions.append(action); } } } if (hiddenActions.count() > 0) { QMenu *pop = extension->menu(); if (!pop) { pop = new QMenu(q); extension->setMenu(pop); } pop->clear(); pop->addActions(hiddenActions); int vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q); int x = q->layoutDirection() == Qt::RightToLeft ? menuRect.left() - extension->sizeHint().width() + 1 : menuRect.right(); extension->setGeometry(x, vmargin, extension->sizeHint().width(), menuRect.height() - vmargin*2); extension->show(); } else { extension->hide(); } q->updateGeometry();#ifdef QT3_SUPPORT if (q->parentWidget() != 0) { QMenubarUpdatedEvent menubarUpdated(q); QApplication::sendEvent(q->parentWidget(), &menubarUpdated); }#endif}QRect QMenuBarPrivate::actionRect(QAction *act) const{ Q_Q(const QMenuBar); QRect ret = actionRects.value(act); const int fw = q->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, q); ret.translate(fw, fw); return QStyle::visualRect(q->layoutDirection(), q->rect(), ret);}void QMenuBarPrivate::setKeyboardMode(bool b){ Q_Q(QMenuBar); if (b && !q->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation, 0, q)) { setCurrentAction(0); return; } keyboardState = b; if(b) { QWidget *fw = qApp->focusWidget(); if (fw != q) keyboardFocusWidget = qApp->focusWidget(); if(!currentAction && !actionList.isEmpty()) setCurrentAction(actionList.first()); q->setFocus(); } else { if(!popupState) setCurrentAction(0); if(keyboardFocusWidget) { keyboardFocusWidget->setFocus(); keyboardFocusWidget = 0; } } q->update();}void QMenuBarPrivate::popupAction(QAction *action, bool activateFirst){ Q_Q(QMenuBar); if(!action || !action->menu() || closePopupMode) return; popupState = true; if (action->isEnabled() && action->menu()->isEnabled()) { closePopupMode = 0; activeMenu = action->menu(); activeMenu->d_func()->causedPopup.widget = q; activeMenu->d_func()->causedPopup.action = action; QRect adjustedActionRect = actionRect(action); QPoint pos(q->mapToGlobal(QPoint(adjustedActionRect.left(), adjustedActionRect.bottom() + 1))); QSize popup_size = activeMenu->sizeHint(); QRect screenRect = QApplication::desktop()->screenGeometry(pos); const bool fitUp = (q->mapToGlobal(adjustedActionRect.topLeft()).y() >= popup_size.height()); const bool fitDown = (pos.y() + popup_size.height() <= screenRect.bottom()); const int actionWidth = adjustedActionRect.width(); if (!fitUp && !fitDown) { //we should shift the menu bool shouldShiftToRight = !q->isRightToLeft(); if (q->isRightToLeft() && popup_size.width() > pos.x()) shouldShiftToRight = true; else if (actionWidth + popup_size.width() + pos.x() > screenRect.right()) shouldShiftToRight = false; if (shouldShiftToRight) pos.rx() += actionWidth; else pos.rx() -= popup_size.width(); } else if (q->isRightToLeft()) { pos.setX(pos.x()-(popup_size.width() - actionWidth)); } if(pos.x() < screenRect.x()) { pos.setX(screenRect.x()); } else { const int off = pos.x()+popup_size.width() - screenRect.right(); if(off > 0) pos.setX(qMax(screenRect.x(), pos.x()-off)); } if(!defaultPopDown || (fitUp && !fitDown)) pos.setY(qMax(screenRect.y(), q->mapToGlobal(QPoint(0, adjustedActionRect.top()-popup_size.height())).y())); activeMenu->popup(pos); if(activateFirst) activeMenu->d_func()->setFirstActionActive(); } q->update(actionRect(action));}bool QMenuBarPrivate::closeActiveMenu(){ if(activeMenu) { QMenu *menu = activeMenu; activeMenu = 0; menu->hide(); return true; } return false;}void QMenuBarPrivate::setCurrentAction(QAction *action, bool popup, bool activateFirst){ if(currentAction == action && popup == popupState) return; doChildEffects = (popup && !activeMenu); Q_Q(QMenuBar); QWidget *fw = 0; if(closeActiveMenu() && popup) { fw = q->window()->focusWidget(); q->setFocus(Qt::NoFocusReason); } if(currentAction) q->update(actionRect(currentAction)); popupState = popup;#ifndef QT_NO_STATUSTIP QAction *previousAction = currentAction;#endif currentAction = action; if (fw) fw->setFocus(Qt::NoFocusReason); if (action) { activateAction(action, QAction::Hover); if(popup) popupAction(action, activateFirst); q->update(actionRect(action));#ifndef QT_NO_STATUSTIP } else if (previousAction) { QString empty; QStatusTipEvent tip(empty); QApplication::sendEvent(q, &tip);#endif }}void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const{ Q_Q(const QMenuBar); if(!itemsDirty && itemsWidth == max_width && itemsStart == start) { actionRects = actionRects; actionList = actionList; return; } actionRects.clear(); actionList.clear(); const int itemSpacing = q->style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q); int max_item_height = 0, separator = -1, separator_start = 0, separator_len = 0; QList<QAction*> items = q->actions(); //calculate size const QFontMetrics fm = q->fontMetrics(); const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q), vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q), icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q); for(int i = 0; i < items.count(); i++) { QAction *action = items.at(i); if(!action->isVisible()) continue; QSize sz; //calc what I think the size is.. if(action->isSeparator()) { if (q->style()->styleHint(QStyle::SH_DrawMenuBarSeparator, 0, q)) separator = actionRects.count(); continue; //we don't really position these! } else { QString s = action->text(); if(!s.isEmpty()) { int w = fm.width(s); w -= s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&')); w += s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&')); sz = QSize(w, fm.height()); } QIcon is = action->icon(); if (!is.isNull()) { QSize is_sz = QSize(icone, icone); if (is_sz.height() > sz.height()) sz.setHeight(is_sz.height()); if (is_sz.width() > sz.width()) sz.setWidth(is_sz.width()); } } //let the style modify the above size.. QStyleOptionMenuItem opt; q->initStyleOption(&opt, action); sz = q->style()->sizeFromContents(QStyle::CT_MenuBarItem, &opt, sz, q); if(!sz.isEmpty()) { { //update the separator state int iWidth = sz.width(); iWidth += itemSpacing; if(separator == -1) separator_start += iWidth; else separator_len += iWidth; } //maximum height
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -