⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmenu.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 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://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** 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 "qmenu.h"#ifndef QT_NO_MENU#include "qstyle.h"#include "qevent.h"#include "qtimer.h"#include "qlayout.h"#include "qpainter.h"#include "qapplication.h"#include "qdesktopwidget.h"#ifndef QT_NO_ACCESSIBILITY# include "qaccessible.h"#endif#ifndef QT_NO_EFFECTS# include <private/qeffects_p.h>#endif#ifndef QT_NO_WHATSTHIS# include <qwhatsthis.h>#endif#include "qmenu_p.h"#include "qmenubar_p.h"#include "qdebug.h"#include <private/qaction_p.h>#ifdef QT3_SUPPORT#include <qmenudata.h>#endif // QT3_SUPPORTQBasicTimer QMenuPrivate::menuDelayTimer;QBasicTimer QMenuPrivate::sloppyDelayTimer;/* QMenu code */// internal class used for the torn off popupclass QTornOffMenu : public QMenu{    Q_OBJECTpublic:    QTornOffMenu(QMenu *p) : QMenu(0)    {        d_func()->tornoff = 1;        d_func()->causedPopup.widget = ((QTornOffMenu*)p)->d_func()->causedPopup.widget;        d_func()->causedPopup.action = ((QTornOffMenu*)p)->d_func()->causedPopup.action;        setParent(p, Qt::Window | Qt::Tool);	setAttribute(Qt::WA_DeleteOnClose, true);        setWindowTitle(p->windowTitle());        setEnabled(p->isEnabled());        QObject::connect(this, SIGNAL(activated(int)), p, SIGNAL(activated(int)));        QObject::connect(this, SIGNAL(highlighted(int)), p, SIGNAL(highlighted(int)));        QList<QAction*> items = p->actions();        for(int i = 0; i < items.count(); i++)            addAction(items.at(i));    }    void syncWithMenu(QMenu *, QActionEvent *act)    {        if (act->type() == QEvent::ActionAdded) {            insertAction(act->before(), act->action());        } else if (act->type() == QEvent::ActionRemoved)            removeAction(act->action());    }    void actionEvent(QActionEvent *e)    {        QMenu::actionEvent(e);        resize(sizeHint());    }};#include "qmenu.moc"void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const{    Q_Q(const QMenu);    if (!itemsDirty) {        actionRects = this->actionRects;        actionList = this->actionList;        return;    }    actionRects.clear();    actionList.clear();    QList<QAction*> items = q->actions();    int max_column_width = 0, dh = QApplication::desktop()->availableGeometry(q).height(), ncols = 1, y = 0;    const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuHMargin, 0, q),              vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q),              icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);    //for compatability now - will have to refactor this away..    tabWidth = 0;    maxIconWidth = 0;    hasCheckableItems = false;    for(int i = 0; i < items.count(); i++) {        QAction *action = items.at(i);        if (!action->isVisible())            continue;        hasCheckableItems |= action->isCheckable();        QIcon is = action->icon();        if (!is.isNull()) {            uint miw = maxIconWidth;            maxIconWidth = qMax<uint>(miw, icone + 4);        }    }    //calculate size    QFontMetrics qfm = q->fontMetrics();    for(int i = 0; i < items.count(); i++) {        QAction *action = items.at(i);        if (!action->isVisible())            continue;        QFontMetrics fm(action->font().resolve(q->font()));        QSize sz;        //calc what I think the size is..        if (action->isSeparator()) {            sz = QSize(2, 2);        } else {            QString s = action->text();            int t = s.indexOf('\t');            if (t != -1) {                tabWidth = qMax(int(tabWidth), qfm.width(s.mid(t+1)));                s = s.left(t);#ifndef QT_NO_SHORTCUT            } else {                QKeySequence seq = action->shortcut();                if (!seq.isEmpty())                    tabWidth = qMax(int(tabWidth), qfm.width(seq));#endif            }            int w = fm.width(s);            w -= s.count('&') * fm.width('&');            w += s.count("&&") * fm.width('&');            sz.setWidth(w);            sz.setHeight(qMax(fm.height(), qfm.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());            }        }        //let the style modify the above size..        QStyleOptionMenuItem opt = getStyleOption(action);        opt.rect = q->rect();        sz = q->style()->sizeFromContents(QStyle::CT_MenuItem, &opt, sz, q);        if (!sz.isEmpty()) {            max_column_width = qMax(max_column_width, sz.width());            //wrapping            if (!scroll &&               y+sz.height()+vmargin > dh - (q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) {                ncols++;                y = vmargin;            }            y += sz.height();            //append item            actionRects.insert(action, QRect(0, 0, sz.width(), sz.height()));            actionList.append(action);        }    }    if (tabWidth)        max_column_width += tabWidth; //finally add in the tab width    //calculate position    int x = hmargin;    y = vmargin;    for(int i = 0; i < actionList.count(); i++) {        QAction *action = actionList.at(i);        QRect &rect = actionRects[action];        if (!scroll &&           y+rect.height() > dh - (q->style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) {            ncols--;            if (ncols < 0)                qWarning("QMenu: Column mismatch calculation. %d", ncols);            x += max_column_width + hmargin;            y = vmargin;        }        rect.translate(x, y);                        //move        rect.setWidth(max_column_width); //uniform width        y += rect.height();    }}void QMenuPrivate::updateActions(){    Q_Q(const QMenu);    if (!itemsDirty)        return;    sloppyAction = 0;    calcActionRects(actionRects, actionList);    ncols = 1;    int last_left = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q);    if (!scroll) {        for(int i = 0; i < actionList.count(); i++) {            int left = actionRects.value(actionList.at(i)).left();            if (left > last_left) {                last_left = left;                ncols++;            }        }    }    itemsDirty = 0;}QRect QMenuPrivate::actionRect(QAction *act) const{    Q_Q(const QMenu);    QRect ret = actionRects.value(act);    if (scroll)        ret.translate(0, scroll->scrollOffset);    if (tearoff)        ret.translate(0, q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q));    const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q);    ret.translate(fw+leftmargin, fw+topmargin);    return ret;}void QMenuPrivate::hideUpToMenuBar(){    Q_Q(QMenu);    if (!tornoff) {        QWidget *caused = causedPopup.widget;        q->hide(); //hide after getting causedPopup        while(caused) {#ifndef QT_NO_MENUBAR            if (QMenuBar *mb = qobject_cast<QMenuBar*>(caused)) {                mb->d_func()->setCurrentAction(0);                caused = 0;            } else#endif            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 {                qWarning("not possible..");                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();    }}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, 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, false);        }        return;    }    if (currentAction)        q->update(actionRect(currentAction));    sloppyAction = 0;    if (!sloppyRegion.isEmpty())        sloppyRegion = QRegion();    QMenu *hideActiveMenu = activeMenu;    QAction *previousAction = currentAction;    currentAction = action;    if (action && !action->isSeparator()) {        activateAction(action, QAction::Hover);        if (popup != -1) {            hideActiveMenu = 0; //will be done "later"            popupAction(currentAction, popup, activateFirst);        }        q->update(actionRect(action));    }  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);        }    }    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;}/*!    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){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -