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

📄 contextmenu.cpp

📁 Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3.10平台上编译为嵌入式图形界面操作系统。
💻 CPP
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define INCLUDE_MENUITEM_DEF#define QTOPIA_INTERNAL_LANGLIST#include <qpopupmenu.h>#include <qvaluelist.h>#include <qtimer.h>#include <qfile.h>#include <qaction.h>#include <qgfx_qws.h>#include <qtopia/qpeapplication.h>#include <qtopia/global.h>#include <qtopia/resource.h>#include <qtopia/contextbar.h>#include "contextmenu.h"#ifdef QTOPIA_PHONEextern bool mousePreferred; // can't call Global::mousePreferred in libqtopia2 from libqtopia#endifextern const QArray<int> qpe_systemButtons();QIconSet qtopia_internal_loadIconSet( const QString &pix );class ContextMenuData{public:    ContextMenuData()    {	adjustHeight = FALSE;	shown = FALSE;	focusWidget = 0;	helpexists = FALSE;	cancelId = -1;	helpId = -1;	helpEnabled = TRUE;        hasHelp = FALSE;	sepId = -1;    }        ~ContextMenuData()    {    }    bool adjustHeight;    QWidget *focusWidget;    bool shown;    QString helpFile;    bool helpexists;    int cancelId;    int helpId;    bool helpEnabled;    bool hasHelp;    int sepId;    QMap<QWidget*, QWidget*> focusWidgetMap;};static QMap<QWidget*, ContextMenu *> *modalMenuMap=0;static QMap<QWidget*, ContextMenu *> *nonModalMenuMap=0;/*!  \class ContextMenu  \brief The ContextMenu class provides a QPopupMenu that is bound to a  context button.  The Context Bar will be updated when the ContextMenu is available.  Pressing  the context button will popup the ContextMenu.  Note that the rules for context button assignment are identical as  those for ContextBar, i.e. if the current focus widget does not claim  the context key or have a context menu, then the context menu or label of  an ancestor will be active.  ContextMenu is only available in the Qtopia Phone Edition.  \sa ContextBar  \ingroup qtopiaphone*//*!  Constructs a ContextMenu which will popup when Key_Menu is pressed and  widget \a parent has focus and is in modal editing state \a state.    The \a parent and \a name parameters are the standard Qt parent parameters.  \sa ContextBar*/ContextMenu::ContextMenu(QWidget *parent, const char *name, int state)    : QPopupMenu(parent, name){    d = new ContextMenuData();    init();    if (parent)	addTo(parent, state);}void ContextMenu::init(){    if (!modalMenuMap) {	modalMenuMap = new QMap<QWidget*, ContextMenu*>;	nonModalMenuMap = new QMap<QWidget*, ContextMenu*>;    }    hide();    ContextBar::setLabel(this, key(), ContextBar::Options, ContextBar::ModalAndNonModal);}/*!    Destructs the ContextMenu*/ContextMenu::~ContextMenu(){    QMap<QWidget*, QWidget*>::Iterator it = d->focusWidgetMap.begin();    while (it != d->focusWidgetMap.end()) {	QWidget *w = *it;	++it;	removeFrom(w);    }    delete d;}/*!  Sets whether help is enabled in the context menu.*/void ContextMenu::setEnableHelp(bool b){    d->helpEnabled = b;    // if already shown?    if (d->helpId != -1) {	setItemEnabled(d->helpId, b);    }}/*!  Adds this ContextMenu to widget \a w for modal editing state \a state.  \sa removeFrom()*/void ContextMenu::addTo(QWidget *w, int state){    if (!w)	return;    if (!state)	state = Modal | NonModal;    QWidget *fw = w;    while (fw->focusProxy())	fw = fw->focusProxy();    if (!d->focusWidgetMap.contains(fw)) {	fw->installEventFilter(this);	d->focusWidgetMap[fw] = w;    }    ContextBar::setLabel(fw, key(), ContextBar::Options, (ContextBar::EditingState)state);    if (state & Modal)	modalMenuMap->insert(w, this);    if (state & NonModal)	nonModalMenuMap->insert(w, this);    connect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));}/*!  Removes this ContextMenu from widget \a w for modal editing state \a state.  \sa addTo()*/void ContextMenu::removeFrom(QWidget *w, int state){    if (!state)	state = Modal | NonModal;    QWidget *fw = w;    while (fw->focusProxy())	fw = fw->focusProxy();    bool haveModal = internalMenuFor(w, Modal) == this;    bool haveNonModal = internalMenuFor(w, NonModal) == this;    if (state & Modal && haveModal) {	ContextBar::clearLabel(fw, key(), ContextBar::Modal);	modalMenuMap->remove(w);	haveModal = FALSE;    }    if (state & NonModal && haveNonModal) {	ContextBar::clearLabel(fw, key(), ContextBar::NonModal);	nonModalMenuMap->remove(w);	haveNonModal = FALSE;    }    if (!haveModal && !haveNonModal) {	fw->removeEventFilter(fw);	d->focusWidgetMap.remove(fw);    }    disconnect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));}/*!  Inserts action \a a at position \a idx in the menu.  \sa addAction()*/void ContextMenu::insertAction(QAction *a, int idx){    if (!a)	return;    int curCount = (int)count();    a->addTo( this );    if (idx >= 0 && idx < curCount-1 && (int)count() > curCount) {	// a could be an action group. need to insert the group at idx	// have to add all of them using addTo, then move them to the	// desired position 	// can't copy from a separate list because ids need to be preserved	while( curCount < (int)count() )	{	    QMenuItem *mi = mitems->take( curCount );	    if( !mi )	    {		qDebug("BUG : ContextMenu::insertAction can't take null item");		return;	    }	    mitems->insert(idx++, mi);	    // Make sure menuContentsChanged() is called	    int acc = accel(mi->id());	    setAccel(acc, mi->id());	    ++curCount;	}    }}/*!  Adds action \a a to the end of the menu.  \sa insertAction()*/void ContextMenu::addAction(QAction *a){    if (a)	a->addTo(this);}/*!  Returns the ContextMenu assigned to widget \a w in modal editing  state \a state.  If a ContextMenu does not yet exist for the widget,  an empty menu will be created.*/ContextMenu *ContextMenu::menuFor(QWidget *w, int state){    if (!state)	state = Modal | NonModal;    ContextMenu *m = internalMenuFor(w, state);    if (!m && (w->inherits("QLineEdit") || w->inherits("QMultiLineEdit"))) {	m = createEditMenu(w, state);    } else if (!m) {	m = new ContextMenu(w, 0, state);    }    return m;}ContextMenu *ContextMenu::createEditMenu(QWidget *w, int state){    ContextMenu *editMenu = new ContextMenu(w, "EditMenu", state);     editMenu->insertItem(qtopia_internal_loadIconSet("copy"), tr("Copy"),1);    editMenu->insertItem(qtopia_internal_loadIconSet("paste"), tr("Paste"),2);    connect(editMenu, SIGNAL(activated(int)),	    editMenu, SLOT(editMenuActivated(int)));    return editMenu;}void ContextMenu::editMenuActivated(int i){    int ascii=0;    int scan=0;    switch (i) {	case 0:		    ascii='x'; scan=Key_X; // Cut	    break;	case 1:	    ascii='c'; scan=Key_C; // Copy	    break;	case 2:	    ascii='v'; scan=Key_V; // Paste    }    if (scan && qApp->focusWidget()) {	QKeyEvent *ke = new QKeyEvent(QEvent::KeyPress, scan, ascii, ControlButton);	QApplication::postEvent(qApp->focusWidget(), ke);	ke = new QKeyEvent(QEvent::KeyRelease, scan, ascii, ControlButton);	QApplication::postEvent(qApp->focusWidget(), ke);    }}/*!  Returns the context menu key.*/int ContextMenu::key(){    static int k = -1;    if (k < 0) {	if (!qpe_systemButtons().contains(Key_Menu)) {	    if (qpe_systemButtons().contains(Key_Context1))		k = Key_Context1;	    else		qWarning("Cannot map key to ContextMenu");	} else {	    k = Key_Menu;	}    }    return k;}extern QRect qt_maxWindowRect;#include <qfileinfo.h>static QString findHelp(const QWidget* w){    // seems like we sometimes start an app with just the name and sometimes with a full path.    // So make sure we only use the basename here    QFileInfo fi( QString(qApp->argv()[0]) );    QString hf = fi.baseName();    if ( w ) {        hf += "-";        hf += w->name();    }    hf += ".html";    QStringList helpPath = Global::helpPath();    for (QStringList::ConstIterator it=helpPath.begin(); it!=helpPath.end(); ++it) {        if ( QFile::exists( *it + "/" + hf ) ) {//            qDebug(">>> Using help \"%s\" <<<",hf.latin1());            return hf;            break;        }    }    if ( w && QString(w->name()) == "unnamed" ) {        QString parents;        parents = QString("(%1)").arg(w->className());        QObject *p = w->parent();        while (p) {            parents = QString("(%1)%2").arg(p->className()).arg(parents);            p = p->parent();        }        qDebug(QString(">>> No help for \"%1 %2\" <<<").arg(hf).arg(parents));    } else {        qDebug(">>> No help for \"%s\" <<<",hf.latin1());    }    return "";}/*!  Returns whether help exists for the parent widget.*/bool ContextMenu::helpExists() const{    if ( d->helpFile.isNull() ) {        QString hf = findHelp(0);        bool he = !hf.isEmpty();        d->helpFile = hf;        d->helpexists = he;        return he;    }    if (!d->helpexists) {        qDebug(">>> NO help exists for \"%s\" <<<",d->helpFile.latin1());    }    return d->helpexists;}/*!  Invokes end-user help for the parent widget.  This slot is automatically connected to a 'Help' item  if helpExists().*/void ContextMenu::help(){    QWidget* w = d->focusWidget;    if ( !w )        w = qApp->activeWindow();    if ( !w )        return;    w = w->topLevelWidget();    if ( helpExists() ) {        QString hf = findHelp(w);        if ( hf.isEmpty() ) {            hf = d->helpFile;        }        qDebug(">>> Using help \"%s\" <<<",hf.latin1());        Global::execute( "helpbrowser", hf );    }}/*!  Opens the popup menu in a standard position.*/void ContextMenu::popup(){    QRect r = qt_maxWindowRect;    d->adjustHeight = TRUE;    popup( r.bottomLeft() );    d->adjustHeight = FALSE;}/*!  Opens the popup menu at \a pos.*/void ContextMenu::popup(const QPoint &pos){    if( !d->shown ) {        d->hasHelp = helpExists();        d->shown = TRUE;    }        if( d->sepId != -1 ) {        removeItem( d->sepId );        d->sepId = -1;    }        if( d->helpId != -1 ) {        removeItem( d->helpId );        d->helpId = -1;    }        if( d->cancelId != -1 ) {        removeItem( d->cancelId );        d->cancelId = -1;    }       if( count() ) d->sepId = insertSeparator();        if( d->helpEnabled && d->hasHelp )        d->helpId = insertItem( qtopia_internal_loadIconSet( "help_icon" ),            tr( "Help" ), this, SLOT( help() ) );                // qwizard check first?    if ( d->focusWidget ) {	QWidget* tlw = d->focusWidget->topLevelWidget();	if ( tlw->inherits("QDialog")		&& !qpe_systemButtons().contains(Key_No))	{	    if (!QPEApplication::isMenuLike((QDialog*)tlw))		d->cancelId = insertItem(qtopia_internal_loadIconSet("close"), tr("Cancel"), tlw, SLOT(reject()));	}    }        if( d->helpId == -1 && d->cancelId == -1 && d->sepId != -1 ) {        removeItem( d->sepId );        d->sepId = -1;    }    if (count()) {	if (d->adjustHeight)	    QPopupMenu::popup( QPoint(pos.x(), pos.y() - sizeHint().height() + 1) );	else	    QPopupMenu::popup(pos);	focusNextPrevChild(TRUE); // ie. setFirstItemActive();    }}/*!  \reimp*/bool ContextMenu::eventFilter(QObject *o, QEvent *e){    if (!o || !e || e->type() != QEvent::KeyPress )	return FALSE;    if (!o->isWidgetType())	return FALSE;    QKeyEvent *k = (QKeyEvent *) e;    if (k->key() != key())	return FALSE;    d->focusWidget = (QWidget*)o;    if( e->type() == QEvent::KeyPress ) {	QMap<QWidget*, QWidget*>::ConstIterator it;	it = d->focusWidgetMap.find(d->focusWidget);	if (it != d->focusWidgetMap.end()) {	    QWidget *w = *it;	    if (((mousePreferred || w->isModalEditing()) && 		    internalMenuFor(w, Modal) == this)		|| ((mousePreferred || !w->isModalEditing()) && 		    internalMenuFor(w, NonModal) == this)) {		popup();		return TRUE;	    }	}    }     return FALSE;}/*!  \reimp*/void ContextMenu::keyPressEvent(QKeyEvent *e){    if (e->key() == key())	close();    else	QPopupMenu::keyPressEvent(e);}/*!  \reimp*/void ContextMenu::keyReleaseEvent(QKeyEvent *e){    QPopupMenu::keyReleaseEvent(e);}/*!  \reimp  */void ContextMenu::mouseReleaseEvent(QMouseEvent *e){    int item = idAt( e->pos() );    if (item == -1) {	if (!rect().contains(e->pos()))	    return;    }    QPopupMenu::mouseReleaseEvent(e);}ContextMenu *ContextMenu::internalMenuFor(QWidget *w, int state){    QMap<QWidget*, ContextMenu*>::ConstIterator it;    if (state & Modal && modalMenuMap) {	it = modalMenuMap->find(w);	if (it != modalMenuMap->end())	    return *it;    }    if (state & NonModal && modalMenuMap) {	it = nonModalMenuMap->find(w);	if (it != nonModalMenuMap->end())	    return *it;    }    return 0;}void ContextMenu::widgetDestroyed(){    QWidget *w = (QWidget*)sender();    removeFrom(w);}

⌨️ 快捷键说明

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