24 #include <QtCore/QMetaMethod>
25 #include <QtCore/QObject>
26 #include <QtCore/QPointer>
27 #include <QtCore/QTimer>
28 #include <QtGui/QApplication>
29 #include <QtGui/QCursor>
30 #include <QtGui/QFontMetrics>
31 #include <QtGui/QHBoxLayout>
32 #include <QtGui/QKeyEvent>
33 #include <QtGui/QMenuItem>
34 #include <QtGui/QLabel>
35 #include <QtGui/QPainter>
36 #include <QtGui/QStyle>
37 #include <QtGui/QToolButton>
38 #include <QtGui/QWidgetAction>
47 class KMenu::KMenuPrivate
51 KMenuPrivate (
KMenu *_parent);
54 void resetKeyboardVars(
bool noMatches =
false);
55 void actionHovered(
QAction* action);
56 void showCtxMenu(
const QPoint &pos);
57 void skipTitles(QKeyEvent *event);
69 bool eventFilter(
QObject *
object, QEvent *event)
73 if (event->type() == QEvent::Paint ||
74 event->type() == QEvent::KeyPress ||
75 event->type() == QEvent::KeyRelease) {
102 QPointer<QAction> highlightedAction;
106 KMenu::KMenuPrivate::KMenuPrivate (
KMenu *_parent)
112 , lastHoveredAction(0L)
113 , mouseButtons(Qt::NoButton)
114 , keyboardModifiers(Qt::NoModifier)
116 , highlightedAction(0)
122 KMenu::KMenuPrivate::~KMenuPrivate ()
135 KMenuContext(
const KMenuContext& o);
136 KMenuContext(QPointer<KMenu> menu,QPointer<QAction> action);
138 inline QPointer<KMenu> menu()
const {
return m_menu; }
139 inline QPointer<QAction> action()
const {
return m_action; }
142 QPointer<KMenu> m_menu;
143 QPointer<QAction> m_action;
147 Q_DECLARE_METATYPE(KMenuContext)
153 , d(new KMenuPrivate(this))
155 connect(&(d->clearTimer), SIGNAL(
timeout()), SLOT(resetKeyboardVars()));
159 :
QMenu(title, parent)
160 , d(new KMenuPrivate(this))
162 connect(&(d->clearTimer), SIGNAL(
timeout()), SLOT(resetKeyboardVars()));
172 return addTitle(QIcon(), text, before);
178 QFont font = buttonAction->font();
180 buttonAction->setFont(font);
181 buttonAction->setText(text);
182 buttonAction->setIcon(icon);
187 titleButton->installEventFilter(d);
188 titleButton->setDefaultAction(buttonAction);
189 titleButton->setDown(
true);
190 titleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
191 action->setDefaultWidget(titleButton);
193 insertAction(before, action);
203 d->resetKeyboardVars();
204 QMenu::closeEvent(e);
209 return d->mouseButtons;
214 return d->keyboardModifiers;
219 d->mouseButtons = Qt::NoButton;
220 d->keyboardModifiers = Qt::NoModifier;
223 d->keyboardModifiers = e->modifiers();
224 QMenu::keyPressEvent(e);
226 if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) {
234 bool firstpass =
true;
239 if (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter
240 || key == Qt::Key_Up || key == Qt::Key_Down || key == Qt::Key_Left
241 || key == Qt::Key_Right || key == Qt::Key_F1 || key == Qt::Key_PageUp
242 || key == Qt::Key_PageDown || key == Qt::Key_Back || key == Qt::Key_Select) {
244 d->resetKeyboardVars();
247 d->keyboardModifiers = e->modifiers();
248 QMenu::keyPressEvent(e);
250 if (key == Qt::Key_Up || key == Qt::Key_Down) {
254 }
else if ( key == Qt::Key_Shift || key == Qt::Key_Control || key == Qt::Key_Alt || key == Qt::Key_Meta )
255 return QMenu::keyPressEvent(e);
259 if (!d->keySeq.isNull()) {
260 if (key == Qt::Key_Backspace) {
262 if (d->keySeq.length() == 1) {
263 d->resetKeyboardVars();
268 keyString = d->keySeq.left(d->keySeq.length() - 1);
271 d->resetKeyboardVars();
273 }
else if (key == Qt::Key_Delete) {
274 d->resetKeyboardVars();
280 }
else if (d->noMatches) {
282 d->resetKeyboardVars();
290 a = d->lastHitAction;
293 }
else if (key == Qt::Key_Backspace && menuAction()) {
296 d->resetKeyboardVars();
300 d->keySeq += keyString;
301 const int seqLen = d->keySeq.length();
303 foreach (a, actions()) {
312 if (a == d->lastHitAction)
313 thisText = d->originalText;
315 thisText = a->text();
321 thisText = thisText.left(seqLen);
324 if (!thisText.indexOf(d->keySeq, 0, Qt::CaseInsensitive)) {
331 if (d->lastHitAction && d->lastHitAction != a)
333 d->lastHitAction->setText(d->originalText);
336 if (d->lastHitAction != a || d->lastHitAction == 0L)
337 d->originalText = a->text();
340 a->setText(underlineText(d->originalText, d->keySeq.length()));
343 d->lastHitAction = a;
346 d->clearTimer.setSingleShot(
true);
347 d->clearTimer.start(5000);
363 d->lastHitAction->activate(QAction::Trigger);
364 d->resetKeyboardVars();
366 }
else if (d->lastHitAction && d->lastHitAction->menu()) {
368 d->lastHitAction->activate(QAction::Trigger);
369 d->resetKeyboardVars();
376 d->resetKeyboardVars(
true);
378 QMenu::keyPressEvent(e);
383 d->resetKeyboardVars();
384 return QMenu::focusNextPrevChild( next );
390 for (uint i = 0; i < length; i++) {
392 ret.insert(2*i,
'&');
397 void KMenu::KMenuPrivate::resetKeyboardVars(
bool _noMatches)
401 lastHitAction->setText(originalText);
409 noMatches = _noMatches;
414 d->shortcuts = enable;
419 d->autoExec = enable;
431 if (d->ctxMenu && d->ctxMenu->isVisible())
437 if( e->button() == Qt::MidButton)
440 QMenu::mousePressEvent(e);
446 d->keyboardModifiers = e->modifiers();
447 d->mouseButtons = e->buttons();
449 if ( e->button() == Qt::MidButton) {
450 if(activeAction() ) {
451 const QMetaObject *metaObject = activeAction()->metaObject();
452 const int index = metaObject->indexOfMethod(
"triggered(Qt::MouseButtons,Qt::KeyboardModifiers)");
454 const QMetaMethod method = metaObject->method(index);
455 method.invoke(activeAction(), Qt::DirectConnection,
456 Q_ARG(Qt::MouseButtons, e->button()),
457 Q_ARG(Qt::KeyboardModifiers, QApplication::keyboardModifiers() ));
463 if ( !d->ctxMenu || !d->ctxMenu->isVisible() )
464 QMenu::mouseReleaseEvent(e);
471 d->ctxMenu =
new QMenu(
this);
472 connect(
this, SIGNAL(hovered(
QAction*)), SLOT(actionHovered(
QAction*)));
485 if (!d->ctxMenu || !d->ctxMenu->isVisible())
493 void KMenu::KMenuPrivate::actionHovered(
QAction* action)
495 lastHoveredAction = action;
496 parent->hideContextMenu();
502 v.setValue(KMenuContext(contextedMenu,contextedAction));
503 for(
int i=0;i<actions.count();i++) {
504 actions[i]->setData(v);
508 void KMenu::KMenuPrivate::showCtxMenu(
const QPoint &pos)
510 highlightedAction = parent->activeAction();
512 if (!highlightedAction)
518 emit parent->aboutToShowContextMenu(parent, highlightedAction, ctxMenu);
522 if (
QMenu* subMenu = highlightedAction->menu())
524 QTimer::singleShot(100, subMenu, SLOT(hide()));
528 ctxMenu->popup(parent->mapToGlobal(pos));
531 void KMenu::KMenuPrivate::skipTitles(QKeyEvent *event)
535 while (action && action->objectName() ==
KMENU_TITLE)
537 parent->keyPressEvent(event);
538 action = qobject_cast<
QWidgetAction*>(parent->activeAction());
539 if (firstAction == action) {
540 parent->setActiveAction(0);
548 return qobject_cast<
KMenu*>(QApplication::activePopupWidget());
553 if (
KMenu* menu = qobject_cast<KMenu*>(QApplication::activePopupWidget())) {
554 if (!menu->d->lastHoveredAction) {
557 QVariant var = menu->d->lastHoveredAction->data();
558 KMenuContext ctx = var.value<KMenuContext>();
559 Q_ASSERT(ctx.menu() == menu);
570 if (e->reason() == QContextMenuEvent::Mouse)
572 d->showCtxMenu(e->pos());
574 else if (activeAction())
576 d->showCtxMenu(actionGeometry(activeAction()).center());
583 QMenu::contextMenuEvent(e);
588 if (d->ctxMenu && d->ctxMenu->isVisible())
598 bool blocked = blockSignals(
true);
600 blockSignals(blocked);
612 KMenuContext::KMenuContext( )
618 KMenuContext::KMenuContext(
const KMenuContext & o )
620 , m_action(o.m_action)
624 KMenuContext::KMenuContext(QPointer<KMenu> menu,QPointer<QAction> action)
KAction * next(const QObject *recvr, const char *slot, QObject *parent)
Scroll down one page.
QString removeAcceleratorMarker(const QString &label) const
static void manage(QWidget *widget, bool programmers_mode=false)
Manages the accelerators of a widget.