diff options
Diffstat (limited to 'muse2/muse/widgets/popupmenu.cpp')
-rw-r--r-- | muse2/muse/widgets/popupmenu.cpp | 243 |
1 files changed, 238 insertions, 5 deletions
diff --git a/muse2/muse/widgets/popupmenu.cpp b/muse2/muse/widgets/popupmenu.cpp index 862bda91..263c8475 100644 --- a/muse2/muse/widgets/popupmenu.cpp +++ b/muse2/muse/widgets/popupmenu.cpp @@ -6,25 +6,49 @@ // (C) Copyright 1999-2010 Werner Schweer (ws@seh.de) // // PopupMenu sub-class of QMenu created by Tim. +// (C) Copyright 2010-2011 Tim E. Real (terminator356 A T sourceforge D O T net) //========================================================= //#include <stdio.h> #include <QMouseEvent> +#include <QHoverEvent> #include <QAction> +#include <QPoint> +#include <QDesktopWidget> +#include <QApplication> +//#include <QTimer> + #include <stdio.h> //#include <QStandardItemModel> #include "popupmenu.h" + //====================== // PopupMenu //====================== -PopupMenu::PopupMenu(QWidget* parent) - : QMenu(parent) +//PopupMenu::PopupMenu() +//{ +// init(); +//} + +PopupMenu::PopupMenu(bool stayOpen) + : _stayOpen(stayOpen) { - // Menus will trigger! Set to make sure our trigger handlers ignore menus. - menuAction()->setData(-1); + init(); +} + +PopupMenu::PopupMenu(QWidget* parent, bool stayOpen) + : QMenu(parent), _stayOpen(stayOpen) +{ + init(); +} + +PopupMenu::PopupMenu(const QString& title, QWidget* parent, bool stayOpen) + : QMenu(title, parent), _stayOpen(stayOpen) +{ + init(); } PopupMenu::~PopupMenu() @@ -32,6 +56,23 @@ PopupMenu::~PopupMenu() //printf("PopupMenu::~PopupMenu\n"); } +void PopupMenu::init() +{ + // Menus will trigger! Set to make sure our trigger handlers ignore menus. + menuAction()->setData(-1); + + //_stayOpen = false; + moveDelta = 0; + + #ifndef POPUP_MENU_DISABLE_AUTO_SCROLL + timer = new QTimer(this); + timer->setInterval(100); + timer->setSingleShot(false); + connect(this, SIGNAL(hovered(QAction*)), SLOT(popHovered(QAction*))); + connect(timer, SIGNAL(timeout()), SLOT(timerHandler())); + #endif // POPUP_MENU_DISABLE_AUTO_SCROLL +} + void PopupMenu::clear() { QList<QAction*> list = actions(); @@ -49,9 +90,14 @@ void PopupMenu::clear() // Now let QT remove and delete this menu's actions. QMenu::clear(); + + #ifndef POPUP_MENU_DISABLE_AUTO_SCROLL + connect(this, SIGNAL(hovered(QAction*)), SLOT(popHovered(QAction*))); + connect(timer, SIGNAL(timeout()), SLOT(timerHandler())); + #endif // POPUP_MENU_DISABLE_AUTO_SCROLL } -QAction* PopupMenu::findActionFromData(QVariant v) +QAction* PopupMenu::findActionFromData(QVariant v) const { QList<QAction*> list = actions(); for(int i = 0; i < list.size(); ++i) @@ -69,8 +115,194 @@ QAction* PopupMenu::findActionFromData(QVariant v) return 0; } +bool PopupMenu::event(QEvent* event) +{ + //printf("PopupMenu::event type:%d\n", event->type()); // REMOVE Tim. + + switch(event->type()) + { + #ifndef POPUP_MENU_DISABLE_STAY_OPEN + case QEvent::MouseButtonDblClick: + { + if(_stayOpen) + { + QMouseEvent* e = static_cast<QMouseEvent*>(event); + if(e->modifiers() == Qt::NoModifier) + { + event->accept(); + // Convert into a return press, which selects the item and closes the menu. + // Note that with double click, it's a press followed by release followed by double click. + // That would toggle our item twice eg on->off->on, which is hopefully OK. + QKeyEvent ke(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); + //ke.ignore(); // Pass it on + return QMenu::event(&ke); + } + } + } + break; + case QEvent::KeyPress: + { + if(_stayOpen) + { + QKeyEvent* e = static_cast<QKeyEvent*>(event); + if(e->modifiers() == Qt::NoModifier && e->key() == Qt::Key_Space) + { + QAction* act = activeAction(); + if(act) + { + act->trigger(); + event->accept(); + return true; // We handled it. + } + } + } + } + break; + #endif // POPUP_MENU_DISABLE_STAY_OPEN + + #ifndef POPUP_MENU_DISABLE_AUTO_SCROLL + case QEvent::MouseMove: + { + QMouseEvent* e = static_cast<QMouseEvent*>(event); + QPoint globPos = e->globalPos(); + //QPoint pos = e->pos(); + int dw = QApplication::desktop()->width(); // We want the whole thing if multiple monitors. + + //printf("PopupMenu::event MouseMove: pos x:%d y:%d globPos x:%d y:%d\n", + // pos.x(), pos.y(), globPos.x(), globPos.y()); // REMOVE Tim. + + /* + //QAction* action = actionAt(globPos); + QAction* action = actionAt(pos); + if(action) + { + QRect r = actionGeometry(action); + //printf(" act x:%d y:%d w:%d h:%d popup px:%d py:%d pw:%d ph:%d\n", + // r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height()); // REMOVE Tim. + + //action->hover(); + } + */ + + if(x() < 0 && globPos.x() <= 0) // If on the very first pixel (or beyond) + { + moveDelta = 32; + if(!timer->isActive()) + timer->start(); + event->accept(); + return true; + } + else + if(x() + width() >= dw && globPos.x() >= (dw -1)) // If on the very last pixel (or beyond) + { + moveDelta = -32; + if(!timer->isActive()) + timer->start(); + event->accept(); + return true; + } + + if(timer->isActive()) + timer->stop(); + + //event->accept(); + //return true; + + event->ignore(); // Pass it on + //return QMenu::event(event); + } + break; + #endif // POPUP_MENU_DISABLE_AUTO_SCROLL + + default: + break; + } + + return QMenu::event(event); +} + +#ifndef POPUP_MENU_DISABLE_AUTO_SCROLL +void PopupMenu::timerHandler() +{ + // printf("PopupMenu::timerHandler\n"); // REMOVE Tim. + + //if(!isVisible() || !hasFocus()) + if(!isVisible()) + { + timer->stop(); + return; + } + + int dw = QApplication::desktop()->width(); // We want the whole thing if multiple monitors. + int nx = x() + moveDelta; + if(moveDelta < 0 && nx + width() < dw) + { + timer->stop(); + nx = dw - width(); + } + else + if(moveDelta > 0 && nx > 0) + { + timer->stop(); + nx = 0; + } + + move(nx, y()); +} + +void PopupMenu::popHovered(QAction* action) +{ + //timer->stop(); + + //moveDelta = 0; + if(action) + { + int dw = QApplication::desktop()->width(); // We want the whole thing if multiple monitors. + + QRect r = actionGeometry(action); + //printf("PopupMenu::popHovered x:%d y:%d w:%d h:%d px:%d py:%d pw:%d ph:%d\n", + // r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height()); // REMOVE Tim. + //printf("PopupMenu::popHovered x:%d y:%d w:%d h:%d px:%d py:%d pw:%d ph:%d dtw:%d\n", + // r.x(), r.y(), r.width(), r.height(), x(), y(), width(), height(), dw); // REMOVE Tim. + //int x = r.x() + ctrlSubPop->x(); + if(x() + r.x() < 0) + //setGeometry(0, y(), width(), height()); + //scroll(-x, 0); + //move(-r.x() + 32, y()); // Allow some of left column to show so that mouse can move over it. + //move(-r.x() + r.width(), y()); // Allow some of left column to show so that mouse can move over it. + //moveDelta = x() - r.x() + 32; + move(-r.x(), y()); + else + if(r.x() + r.width() + x() > dw) + //setGeometry(1200 - r.x() - r.width(), y(), width(), height()); + //scroll(-x + 1200, 0); + //move(dw - r.x() - r.width() - 32, y()); // Allow some of right column to show so that mouse can move over it. + //move(dw - r.x(), y()); // Allow some of right column to show so that mouse can move over it. + //moveDelta = x() + dw - r.x() - r.width() - 32; + move(dw - r.x() - r.width(), y()); + } + + //if(moveDelta == 0) + // timer->stop(); + +} +#endif // POPUP_MENU_DISABLE_AUTO_SCROLL + void PopupMenu::mouseReleaseEvent(QMouseEvent *e) { + #ifdef POPUP_MENU_DISABLE_STAY_OPEN + QMenu::mouseReleaseEvent(e); + return; + + #else + if(!_stayOpen) + { + QMenu::mouseReleaseEvent(e); + return; + } + + //printf("PopupMenu::mouseReleaseEvent\n"); // REMOVE Tim. + //Q_D(QMenu); //if (d->mouseEventTaken(e)) // return; @@ -106,6 +338,7 @@ void PopupMenu::mouseReleaseEvent(QMouseEvent *e) // d->hideUpToMenuBar(); // } QMenu::mouseReleaseEvent(e); + #endif // POPUP_MENU_DISABLE_STAY_OPEN } /* |