summaryrefslogtreecommitdiff
path: root/muse2
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2010-11-06 08:04:38 +0000
committerTim E. Real <termtech@rogers.com>2010-11-06 08:04:38 +0000
commit3a459a08c7bac364ab4454adb5bcfded8d79c6a8 (patch)
tree1543f065052bf4101d3f01c48c6e333ed27e9f14 /muse2
parent2428f541f4a60ade9dc402ac6bec1bb362b768b4 (diff)
The return of the 'stay open' popup menu! (WIP)
Diffstat (limited to 'muse2')
-rw-r--r--muse2/ChangeLog6
-rw-r--r--muse2/muse/app.cpp554
-rw-r--r--muse2/muse/app.h6
-rw-r--r--muse2/muse/arranger/arranger.h6
-rw-r--r--muse2/muse/arranger/trackinfo.cpp41
-rw-r--r--muse2/muse/synth.cpp3
-rw-r--r--muse2/muse/widgets/popupmenu.cpp2811
-rw-r--r--muse2/muse/widgets/popupmenu.h298
8 files changed, 547 insertions, 3178 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 331294e3..47859942 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,9 @@
+06.11.2010
+ - Yipee! De retour aux les popup menus 'stay-open'. (Tim)
+ - Fixed PopupMenu class.
+ Work in progress. Currently midi trackinfo 'iR' button routing is complete.
+ TODO: Strip routing popups. Also, try to eliminate global routing menu map (gRoutingMenuMap)
+ and directly store the routes as QVariant action user data. Someone started this already...
04.11.2010
- Fixed LADSPA plugin dialog. TODO: fix sorting order. (Tim)
- Fixed MenuTitleItem class. Fixed some usages of it (Jack popup routes, midi cfg routes). (Tim)
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index f9087051..6ce85950 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -36,6 +36,7 @@
#include <QStyle>
#include <QSplashScreen>
#include <QObject>
+#include <QAction>
//Added by qt3to4:
#include <QTimerEvent>
#include <Q3CString>
@@ -845,6 +846,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
watchdogThread = 0;
editInstrument = 0;
routingPopupMenu = 0;
+ routingPopupView = 0;
appName = QString("MusE");
@@ -1913,6 +1915,13 @@ void MusE::closeEvent(QCloseEvent*)
// Make sure to clear the menu, which deletes any sub menus.
if(routingPopupMenu)
routingPopupMenu->clear();
+ #if 0
+ if(routingPopupView)
+ {
+ routingPopupView->clear();
+ delete routingPopupView;
+ }
+ #endif
// Changed by Tim. p3.3.14
//SynthIList* sl = song->syntis();
@@ -2038,53 +2047,33 @@ PopupMenu* MusE::getRoutingPopupMenu()
// updateRouteMenus
//---------------------------------------------------------
-//void MusE::updateRouteMenus(Track* track)
-void MusE::updateRouteMenus(Track* track, QObject* master) // p3.3.50
+void MusE::updateRouteMenus(Track* track, QObject* master)
{
+ // NOTE: The puropse of this routine is to make sure the items actually reflect
+ // the routing status. And with MusE-1 QT3, it was also required to actually
+ // check the items since QT3 didn't do it for us.
+ // But now with MusE-2 and QT4, QT4 checks an item when it is clicked.
+ // So this routine is less important now, since 99% of the time, the items
+ // will be in the right checked state.
+ // But we still need this in case for some reason a route could not be
+ // added (or removed). Then the item will be properly un-checked (or checked) here.
+
//if(!track || track != gRoutingPopupMenuMaster || track->type() == Track::AUDIO_AUX)
//if(!track || track->type() == Track::AUDIO_AUX)
if(!track || gRoutingPopupMenuMaster != master) // p3.3.50
return;
- //QPopupMenu* pup = muse->getORoutesPopup();
PopupMenu* pup = getRoutingPopupMenu();
- if(pup->count() == 0)
+ if(pup->actions().size() == 0)
return;
- // p4.0.1 Protection since reverting to regular (self-extinguishing) menu behaviour here in muse2.
if(!pup->isVisible())
- {
- //printf("MusE::updateRouteMenus menu is not visible\n");
return;
- }
//AudioTrack* t = (AudioTrack*)track;
RouteList* rl = gIsOutRoutingPopupMenu ? track->outRoutes() : track->inRoutes();
- /*
- iRoute iorl = orl->begin();
- for(; iorl != orl->end(); ++iorl)
- {
- iRouteMenuMap imm = ormm->begin();
- for(; imm != ormm->end(); ++imm)
- {
- if(*iorl == imm->second)
- {
- orpup->setItemChecked(imm->first, true);
- break;
- }
- }
- //if(imm == ormm->end())
- //{
- //}
-
- }
- //if (iorl == orl->end())
- //{
- //}
- */
-
iRouteMenuMap imm = gRoutingMenuMap.begin();
for(; imm != gRoutingMenuMap.end(); ++imm)
{
@@ -2114,11 +2103,14 @@ void MusE::updateRouteMenus(Track* track, QObject* master) // p3.3.50
}
}
//pup->setItemChecked(imm->first, found);
- pup->setItemChecked(imm->first, irl != rl->end());
+ //printf("MusE::updateRouteMenus setItemChecked\n");
+ // TODO: MusE-2: Convert this, fastest way is to change the routing map, otherwise this requires a lookup.
+ //if(pup->isItemChecked(imm->first) != (irl != rl->end()))
+ // pup->setItemChecked(imm->first, irl != rl->end());
+ QAction* act = pup->findActionFromData(imm->first);
+ if(act && act->isChecked() != (irl != rl->end()))
+ act->setChecked(irl != rl->end());
}
-
-
- return;
}
//---------------------------------------------------------
@@ -2135,128 +2127,66 @@ void MusE::routingPopupMenuActivated(Track* track, int n)
{
PopupMenu* pup = getRoutingPopupMenu();
- //printf("MusE::routingPopupMenuActivated midi n:%d count:%d\n", n, pup->count());
-
- if(pup->count() == 0)
+ if(pup->actions().size() == 0)
return;
//MidiTrack* t = (MidiTrack*)track;
RouteList* rl = gIsOutRoutingPopupMenu ? track->outRoutes() : track->inRoutes();
if(n == -1)
- {
- //printf("MusE::routingPopupMenuActivated midi n = -1\n");
- ///delete pup;
- ///pup = 0;
return;
- }
- else
- {
- //int mdidx = n / MIDI_CHANNELS;
- //int ch = n % MIDI_CHANNELS;
- //int chbit = 1 << ch; // p3.3.50
- //int chmask = 0;
-
- //if(n >= MIDI_PORTS * MIDI_CHANNELS) // p3.3.50 Toggle channels.
- //{
- //for (int i = 0; i < MIDI_CHANNELS; i++)
- //muse->routingPopupMenuActivated(selected, i + MIDI_CHANNELS * (n-1000));
- //muse->routingPopupMenuActivated(selected, i + MIDI_CHANNELS * (n - MIDI_PORTS * MIDI_CHANNELS)); // p3.3.50
- // chbit = (1 << MIDI_CHANNELS) - 1;
- //}
- //if(debugMsg)
- //printf("MusE::routingPopupMenuActivated mdidx:%d ch:%d\n", mdidx, ch);
-
- // p3.3.50
- iRouteMenuMap imm = gRoutingMenuMap.find(n);
- if(imm == gRoutingMenuMap.end())
- return;
- if(imm->second.type != Route::MIDI_PORT_ROUTE)
- return;
- Route &aRoute = imm->second;
- int chbit = aRoute.channel;
- Route bRoute(track, chbit);
- int mdidx = aRoute.midiPort;
-
- MidiPort* mp = &midiPorts[mdidx];
- MidiDevice* md = mp->device();
- if(!md)
- {
- ///delete pup;
- return;
- }
-
- //if(!(md->rwFlags() & 2))
- if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2)))
- {
- ///delete pup;
- return;
- }
-
- //QString s(pup->text(n));
- //QT_TR_NOOP(md->name())
-
- //Route srcRoute(s, false, -1);
-
- //Route aRoute(md, ch);
- //Route aRoute(mdidx, ch); // p3.3.49
- //Route aRoute(mdidx, chbit); // p3.3.50 In accordance with new channel mask, use the bit position.
-
- //Route srcRoute(md, -1);
- //Route dstRoute(track, -1);
- //Route bRoute(track, ch);
- //Route bRoute(track, chbit); // p3.3.50
+
+ iRouteMenuMap imm = gRoutingMenuMap.find(n);
+ if(imm == gRoutingMenuMap.end())
+ return;
+ if(imm->second.type != Route::MIDI_PORT_ROUTE)
+ return;
+ Route &aRoute = imm->second;
+ int chbit = aRoute.channel;
+ Route bRoute(track, chbit);
+ int mdidx = aRoute.midiPort;
- //if (track->type() == Track::AUDIO_INPUT)
- // srcRoute.channel = dstRoute.channel = n & 0xf;
-
- int chmask = 0;
- iRoute iir = rl->begin();
- for (; iir != rl->end(); ++iir)
- {
- //if(*iir == (dst ? bRoute : aRoute))
- //if(*iir == aRoute)
- if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == mdidx) // p3.3.50 Is there already a route to this port?
- {
- chmask = iir->channel; // p3.3.50 Grab the channel mask.
- break;
- }
- }
- //if (iir != rl->end())
- if ((chmask & chbit) == chbit) // p3.3.50 Is the channel's bit(s) set?
- {
- // disconnect
- if(gIsOutRoutingPopupMenu)
- {
- //printf("MusE::routingPopupMenuActivated removing route src track name: %s dst device name: %s\n", track->name().latin1(), md->name().latin1());
- audio->msgRemoveRoute(bRoute, aRoute);
- }
- else
- {
- //printf("MusE::routingPopupMenuActivated removing route src device name: %s dst track name: %s\n", md->name().latin1(), track->name().latin1());
- audio->msgRemoveRoute(aRoute, bRoute);
- }
- }
- else
+ MidiPort* mp = &midiPorts[mdidx];
+ MidiDevice* md = mp->device();
+ if(!md)
+ return;
+
+ //if(!(md->rwFlags() & 2))
+ if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2)))
+ return;
+
+ int chmask = 0;
+ iRoute iir = rl->begin();
+ for (; iir != rl->end(); ++iir)
+ {
+ //if(*iir == (dst ? bRoute : aRoute))
+ //if(*iir == aRoute)
+ if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == mdidx) // p3.3.50 Is there already a route to this port?
{
- // connect
- if(gIsOutRoutingPopupMenu)
- {
- //printf("MusE::routingPopupMenuActivated adding route src track name: %s dst device name: %s\n", track->name().latin1(), md->name().latin1());
- audio->msgAddRoute(bRoute, aRoute);
- }
- else
- {
- //printf("MusE::routingPopupMenuActivated adding route src device name: %s dst track name: %s\n", md->name().latin1(), track->name().latin1());
- audio->msgAddRoute(aRoute, bRoute);
- }
- }
-
- //printf("MusE::routingPopupMenuActivated calling msgUpdateSoloStates\n");
- audio->msgUpdateSoloStates();
- //printf("MusE::routingPopupMenuActivated calling song->update\n");
- song->update(SC_ROUTE);
+ chmask = iir->channel; // p3.3.50 Grab the channel mask.
+ break;
+ }
}
+ //if (iir != rl->end())
+ if ((chmask & chbit) == chbit) // p3.3.50 Is the channel's bit(s) set?
+ {
+ // disconnect
+ if(gIsOutRoutingPopupMenu)
+ audio->msgRemoveRoute(bRoute, aRoute);
+ else
+ audio->msgRemoveRoute(aRoute, bRoute);
+ }
+ else
+ {
+ // connect
+ if(gIsOutRoutingPopupMenu)
+ audio->msgAddRoute(bRoute, aRoute);
+ else
+ audio->msgAddRoute(aRoute, bRoute);
+ }
+
+ audio->msgUpdateSoloStates();
+ song->update(SC_ROUTE);
}
else
{
@@ -2485,9 +2415,6 @@ void MusE::routingPopupMenuActivated(Track* track, int n)
//else
//{
//}
-
- ///delete pup;
- //oR->setDown(false);
}
//---------------------------------------------------------
@@ -2496,23 +2423,13 @@ void MusE::routingPopupMenuActivated(Track* track, int n)
void MusE::routingPopupMenuAboutToHide()
{
- // p3.3.47
- //printf("MusE::routingPopupMenuAboutToHide\n");
- //if(track)
- // printf("%s", track->name().latin1());
- //printf("\n");
-
// Hmm, can't do this? Sub-menus stay open with this. Re-arranged, testing... Nope.
//PopupMenu* pup = muse->getRoutingPopupMenu();
//pup->disconnect();
//pup->clear();
- // p4.0.1 Removed. IIRC These lines were not strictly necessary in muse-1,
- // and here in muse-2 we reverted back to regular Q3PopupMenu behaviour for now,
- // which is self-extinguishing, so these lines cannot be enabled -
- // gRoutingPopupMenuMaster and gRoutingMenuMap are required for routingPopupMenuActivated().
- //gRoutingMenuMap.clear();
- //gRoutingPopupMenuMaster = 0;
+ gRoutingMenuMap.clear();
+ gRoutingPopupMenuMaster = 0;
}
//---------------------------------------------------------
@@ -2541,14 +2458,295 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
RouteList* rl = dst ? track->outRoutes() : track->inRoutes();
//Route dst(track, -1);
- ///QPopupMenu* pup = new QPopupMenu(parent);
-
PopupMenu* pup = getRoutingPopupMenu();
pup->disconnect();
//connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int)));
//connect(pup, SIGNAL(aboutToHide()), SLOT(routingPopupMenuAboutToHide()));
+ int gid = 0;
+ //int n;
+ QAction* act = 0;
+
+ // Routes can't be re-read until the message sent from msgAddRoute1()
+ // has had time to be sent and actually affected the routes.
+ ///_redisplay:
+
+ pup->clear();
+ gRoutingMenuMap.clear();
+ gid = 0;
+
+ //MidiInPortList* tl = song->midiInPorts();
+ //for(iMidiInPort i = tl->begin();i != tl->end(); ++i)
+ for(int i = 0; i < MIDI_PORTS; ++i)
+ {
+ //MidiInPort* track = *i;
+ // NOTE: Could possibly list all devices, bypassing ports, but no, let's stick with ports.
+ MidiPort* mp = &midiPorts[i];
+ MidiDevice* md = mp->device();
+ if(!md)
+ continue;
+
+ if(!(md->rwFlags() & (dst ? 1 : 2)))
+ continue;
+
+ //printf("MusE::prepareRoutingPopupMenu adding submenu portnum:%d\n", i);
+
+ //QMenu* m = menu->addMenu(track->name());
+ //QPopupMenu* subp = new QPopupMenu(parent);
+ //PopupMenu* subp = new PopupMenu(this);
+ //PopupMenu* subp = new PopupMenu();
+ PopupMenu* subp = new PopupMenu(pup);
+ subp->setTitle(md->name());
+
+ // MusE-2: Check this - needed with QMenu? Help says no. No - verified, it actually causes double triggers!
+ //connect(subp, SIGNAL(triggered(QAction*)), pup, SIGNAL(triggered(QAction*)));
+ //connect(subp, SIGNAL(aboutToHide()), pup, SIGNAL(aboutToHide()));
+
+ int chanmask = 0;
+ // p3.3.50 To reduce number of routes required, from one per channel to just one containing a channel mask.
+ // Look for the first route to this midi port. There should always be only a single route for each midi port, now.
+ for(iRoute ir = rl->begin(); ir != rl->end(); ++ir)
+ {
+ if(ir->type == Route::MIDI_PORT_ROUTE && ir->midiPort == i)
+ {
+ // We have a route to the midi port. Grab the channel mask.
+ chanmask = ir->channel;
+ break;
+ }
+ }
+
+ for(int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ {
+ //QAction* a = m->addAction(QString("Channel %1").arg(ch+1));
+ //subp->insertItem(QT_TR_NOOP(QString("Channel %1").arg(ch+1)), i * MIDI_CHANNELS + ch);
+ gid = i * MIDI_CHANNELS + ch;
+
+ //printf("MusE::prepareRoutingPopupMenu inserting gid:%d\n", gid);
+
+ act = subp->addAction(QString("Channel %1").arg(ch+1));
+ act->setCheckable(true);
+ act->setData(gid);
+ //a->setCheckable(true);
+ //Route src(track, ch, RouteNode::TRACK);
+ //Route src(md, ch);
+ //Route r = Route(src, dst);
+ //a->setData(QVariant::fromValue(r));
+ //a->setChecked(rl->indexOf(r) != -1);
+
+ //Route srcRoute(md, ch);
+ //Route srcRoute(i, ch); // p3.3.49 New: Midi port route.
+ int chbit = 1 << ch;
+ Route srcRoute(i, chbit); // p3.3.50 In accordance with new channel mask, use the bit position.
+
+ gRoutingMenuMap.insert( pRouteMenuMap(gid, srcRoute) );
+
+ //for(iRoute ir = rl->begin(); ir != rl->end(); ++ir) // p3.3.50 Removed.
+ //{
+ //if(*ir == dst)
+ // if(*ir == srcRoute)
+ // {
+ // subp->setItemChecked(id, true);
+ // break;
+ // }
+ //}
+ if(chanmask & chbit) // p3.3.50 Is the channel already set? Show item check mark.
+ act->setChecked(true);
+ }
+ //subp->insertItem(QString("Toggle all"), 1000+i);
+ // p3.3.50 One route with all channel bits set.
+ gid = MIDI_PORTS * MIDI_CHANNELS + i; // Make sure each 'toggle' item gets a unique id.
+ act = subp->addAction(QString("Toggle all"));
+ //act->setCheckable(true);
+ act->setData(gid);
+ Route togRoute(i, (1 << MIDI_CHANNELS) - 1); // Set all channel bits.
+ gRoutingMenuMap.insert( pRouteMenuMap(gid, togRoute) );
+
+ pup->addMenu(subp);
+ }
+
+ /*
+ QPopupMenu* pup = new QPopupMenu(iR);
pup->setCheckable(true);
+ //MidiTrack* t = (MidiTrack*)track;
+ RouteList* irl = track->inRoutes();
+
+ MidiTrack* t = (MidiTrack*)track;
+ int gid = 0;
+ for (int i = 0; i < channel; ++i)
+ {
+ char buffer[128];
+ snprintf(buffer, 128, "%s %d", tr("Channel").latin1(), i+1);
+ MenuTitleItem* titel = new MenuTitleItem(QString(buffer));
+ pup->insertItem(titel);
+
+ if (!checkAudioDevice()) return;
+ std::list<QString> ol = audioDevice->outputPorts();
+ for (std::list<QString>::iterator ip = ol.begin(); ip != ol.end(); ++ip) {
+ int id = pup->insertItem(*ip, (gid * 16) + i);
+ Route dst(*ip, true, i);
+ ++gid;
+ for (iRoute ir = irl->begin(); ir != irl->end(); ++ir) {
+ if (*ir == dst) {
+ pup->setItemChecked(id, true);
+ break;
+ }
+ }
+ }
+ if (i+1 != channel)
+ pup->insertSeparator();
+ }
+ */
+
+ if(pup->actions().size() == 0)
+ {
+ gRoutingPopupMenuMaster = 0;
+ //pup->clear();
+ //pup->disconnect();
+ gRoutingMenuMap.clear();
+ //oR->setDown(false);
+ return 0;
+ }
+
+ gIsOutRoutingPopupMenu = dst;
+ return pup;
+ }
+
+ return 0;
+}
+
+#if 0
+//---------------------------------------------------------
+// getRoutingPopupView
+//---------------------------------------------------------
+
+PopupView* MusE::getRoutingPopupView()
+{
+ if(!routingPopupView)
+ //routingPopupView = new PopupView(this);
+ routingPopupView = new PopupView();
+ return routingPopupView;
+}
+
+//---------------------------------------------------------
+// routingPopupViewActivated
+//---------------------------------------------------------
+
+void MusE::routingPopupViewActivated(Track* track, int n)
+{
+ //if(!track || (track != gRoutingPopupMenuMaster))
+ if(!track)
+ return;
+
+ if(track->isMidiTrack())
+ {
+ PopupView* pup = getRoutingPopupView();
+
+ //printf("MusE::routingPopupMenuActivated midi n:%d count:%d\n", n, pup->count());
+
+ if(pup->model()->rowCount() == 0)
+ return;
+
+ //MidiTrack* t = (MidiTrack*)track;
+ RouteList* rl = gIsOutRoutingPopupMenu ? track->outRoutes() : track->inRoutes();
+
+ if(n == -1)
+ return;
+
+ iRouteMenuMap imm = gRoutingMenuMap.find(n);
+ if(imm == gRoutingMenuMap.end())
+ return;
+ if(imm->second.type != Route::MIDI_PORT_ROUTE)
+ return;
+ Route &aRoute = imm->second;
+ int chbit = aRoute.channel;
+ Route bRoute(track, chbit);
+ int mdidx = aRoute.midiPort;
+
+ MidiPort* mp = &midiPorts[mdidx];
+ MidiDevice* md = mp->device();
+ if(!md)
+ return;
+
+ //if(!(md->rwFlags() & 2))
+ if(!(md->rwFlags() & (gIsOutRoutingPopupMenu ? 1 : 2)))
+ return;
+
+ int chmask = 0;
+ iRoute iir = rl->begin();
+ for (; iir != rl->end(); ++iir)
+ {
+ //if(*iir == (dst ? bRoute : aRoute))
+ //if(*iir == aRoute)
+ if(iir->type == Route::MIDI_PORT_ROUTE && iir->midiPort == mdidx) // p3.3.50 Is there already a route to this port?
+ {
+ chmask = iir->channel; // p3.3.50 Grab the channel mask.
+ break;
+ }
+ }
+ //if (iir != rl->end())
+ if ((chmask & chbit) == chbit) // p3.3.50 Is the channel's bit(s) set?
+ {
+ // disconnect
+ if(gIsOutRoutingPopupMenu)
+ audio->msgRemoveRoute(bRoute, aRoute);
+ else
+ audio->msgRemoveRoute(aRoute, bRoute);
+ }
+ else
+ {
+ // connect
+ if(gIsOutRoutingPopupMenu)
+ audio->msgAddRoute(bRoute, aRoute);
+ else
+ audio->msgAddRoute(aRoute, bRoute);
+ }
+
+ audio->msgUpdateSoloStates();
+ song->update(SC_ROUTE);
+ }
+ else
+ {
+ // TODO: Try to move code from AudioStrip::routingPopupMenuActivated into here.
+ }
+ //else
+ //{
+ //}
+}
+
+//---------------------------------------------------------
+// prepareRoutingPopupView
+//---------------------------------------------------------
+
+PopupView* MusE::prepareRoutingPopupView(Track* track, bool dst)
+{
+ if(!track)
+ return 0;
+
+ //QPoint ppt = QCursor::pos();
+
+ if(track->isMidiTrack())
+ {
+
+ //QPoint ppt = parent->rect().bottomLeft();
+
+ //if(dst)
+ //{
+ // TODO
+
+ //}
+ //else
+ //{
+ RouteList* rl = dst ? track->outRoutes() : track->inRoutes();
+ //Route dst(track, -1);
+
+ ///QPopupMenu* pup = new QPopupMenu(parent);
+
+ PopupView* pup = getRoutingPopupView();
+ pup->disconnect();
+ //connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int)));
+ //connect(pup, SIGNAL(aboutToHide()), SLOT(routingPopupMenuAboutToHide()));
+
+ ///pup->setCheckable(true);
int gid = 0;
//int n;
@@ -2580,8 +2778,8 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
//QMenu* m = menu->addMenu(track->name());
//QPopupMenu* subp = new QPopupMenu(parent);
//PopupMenu* subp = new PopupMenu(this);
- PopupMenu* subp = new PopupMenu();
- connect(subp, SIGNAL(activated(int)), pup, SIGNAL(activated(int)));
+ QStandardItem* subp = new QStandardItem(QT_TR_NOOP(md->name()));
+/// connect(subp, SIGNAL(activated(int)), pup, SIGNAL(activated(int)));
//connect(subp, SIGNAL(aboutToHide()), pup, SIGNAL(aboutToHide()));
int chanmask = 0;
@@ -2605,7 +2803,12 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
//printf("MusE::prepareRoutingPopupMenu inserting gid:%d\n", gid);
- subp->insertItem(QString("Channel %1").arg(ch+1), gid);
+/// subp->insertItem(QString("Channel %1").arg(ch+1), gid);
+ QStandardItem* sti = new QStandardItem(QString("Channel %1").arg(ch+1));
+ sti->setCheckable(true);
+ sti->setData(gid);
+ subp->appendRow(sti);
+
//a->setCheckable(true);
//Route src(track, ch, RouteNode::TRACK);
//Route src(md, ch);
@@ -2630,16 +2833,23 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
// }
//}
if(chanmask & chbit) // p3.3.50 Is the channel already set? Show item check mark.
- subp->setItemChecked(gid, true);
+/// subp->setItemChecked(gid, true);
+ sti->setCheckState(Qt::Checked);
}
//subp->insertItem(QString("Toggle all"), 1000+i);
// p3.3.50 One route with all channel bits set.
gid = MIDI_PORTS * MIDI_CHANNELS + i; // Make sure each 'toggle' item gets a unique id.
- subp->insertItem(QString("Toggle all"), gid);
+/// subp->insertItem(QString("Toggle all"), gid);
+ QStandardItem* sti = new QStandardItem(QString("Toggle all"));
+ sti->setData(gid);
+ subp->appendRow(sti);
+
Route togRoute(i, (1 << MIDI_CHANNELS) - 1); // Set all channel bits.
gRoutingMenuMap.insert( pRouteMenuMap(gid, togRoute) );
- pup->insertItem(QT_TR_NOOP(md->name()), subp);
+/// pup->insertItem(QT_TR_NOOP(md->name()), subp);
+ pup->model()->appendRow(subp);
+ pup->updateView();
}
/*
@@ -2675,7 +2885,8 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
}
*/
- if(pup->count() == 0)
+/// if(pup->count() == 0)
+ if(pup->model()->rowCount() == 0)
{
///delete pup;
gRoutingPopupMenuMaster = 0;
@@ -2692,6 +2903,7 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst)
return 0;
}
+#endif
//---------------------------------------------------------
// saveAs
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 4728f74f..b13c38a3 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -37,6 +37,7 @@ class Q3ListViewItem;
class QPoint;
class QToolButton;
class PopupMenu;
+class PopupView;
class Track;
class PrinterConfig;
class MidiSyncConfig;
@@ -116,6 +117,7 @@ class MusE : public QMainWindow
// Special 'stay-open' menu for routes.
PopupMenu* routingPopupMenu;
+ PopupView* routingPopupView;
int aid1a, aid1b, aid2, aid3, autoId;
int tr_id, bt_id, mr_id;
@@ -318,6 +320,10 @@ class MusE : public QMainWindow
PopupMenu* prepareRoutingPopupMenu(Track* /*track*/, bool /*dst*/);
void routingPopupMenuActivated(Track* /*track*/, int /*id*/);
void updateRouteMenus(Track* /*track*/, QObject* /*master*/);
+ // Testing...
+ //PopupView* getRoutingPopupView();
+ //PopupView* prepareRoutingPopupView(Track* /*track*/, bool /*dst*/);
+ //void routingPopupViewActivated(Track* /*track*/, int /*id*/);
#ifdef HAVE_LASH
void lash_idle_cb ();
diff --git a/muse2/muse/arranger/arranger.h b/muse2/muse/arranger/arranger.h
index 37b4c55e..34aa5c68 100644
--- a/muse2/muse/arranger/arranger.h
+++ b/muse2/muse/arranger/arranger.h
@@ -41,6 +41,9 @@ class TLLayout;
class WidgetStack;
class AudioStrip;
class SpinBox;
+class QAction;
+//class QModelIndex;
+
//---------------------------------------------------------
// TWhatsThis
//---------------------------------------------------------
@@ -172,7 +175,8 @@ class Arranger : public QWidget {
void verticalScrollSetYpos(unsigned);
void inRoutesPressed();
void outRoutesPressed();
- void routingPopupMenuActivated(int /*id*/);
+ void routingPopupMenuActivated(QAction*);
+ //void routingPopupViewActivated(const QModelIndex&);
signals:
void redirectWheelEvent(QWheelEvent*);
diff --git a/muse2/muse/arranger/trackinfo.cpp b/muse2/muse/arranger/trackinfo.cpp
index 382ef1e0..b23cead8 100644
--- a/muse2/muse/arranger/trackinfo.cpp
+++ b/muse2/muse/arranger/trackinfo.cpp
@@ -9,7 +9,7 @@
#include <qcombobox.h>
#include <qtoolbutton.h>
#include <qlabel.h>
-#include <q3popupmenu.h>
+#include <QMenu>
#include <qmessagebox.h>
//#include <q3hbox.h>
#include <qcheckbox.h>
@@ -17,6 +17,7 @@
//#include <q3widgetstack.h>
#include <qlineedit.h>
#include <qtimer.h>
+#include <QModelIndex>
//Added by qt3to4:
#include <QPixmap>
#include <math.h>
@@ -573,7 +574,8 @@ void Arranger::iInputPortChanged(const QString& s)
// routingPopupMenuActivated
//---------------------------------------------------------
-void Arranger::routingPopupMenuActivated(int n)
+//void Arranger::routingPopupMenuActivated(int n)
+void Arranger::routingPopupMenuActivated(QAction* act)
{
//if(gRoutingPopupMenuMaster != this || !track || !track->isMidiTrack())
if(!midiTrackInfo || gRoutingPopupMenuMaster != midiTrackInfo || !selected || !selected->isMidiTrack())
@@ -585,10 +587,34 @@ void Arranger::routingPopupMenuActivated(int n)
// muse->routingPopupMenuActivated(selected, i + MIDI_CHANNELS * (n - MIDI_PORTS * MIDI_CHANNELS)); // p3.3.50
//}
//else {
- muse->routingPopupMenuActivated(selected, n);
+ ///muse->routingPopupMenuActivated(selected, n);
+ muse->routingPopupMenuActivated(selected, act->data().toInt());
//}
}
+#if 0
+//---------------------------------------------------------
+// routingPopupViewActivated
+//---------------------------------------------------------
+
+void Arranger::routingPopupViewActivated(const QModelIndex& mdi)
+{
+ //if(gRoutingPopupMenuMaster != this || !track || !track->isMidiTrack())
+ if(!midiTrackInfo || gRoutingPopupMenuMaster != midiTrackInfo || !selected || !selected->isMidiTrack())
+ return;
+ //if (n > 999) {
+ //if (n >= MIDI_PORTS * MIDI_CHANNELS) { // p3.3.50
+ // for (int i = 0; i < MIDI_CHANNELS; i++)
+ //muse->routingPopupMenuActivated(selected, i + MIDI_CHANNELS * (n-1000));
+ // muse->routingPopupMenuActivated(selected, i + MIDI_CHANNELS * (n - MIDI_PORTS * MIDI_CHANNELS)); // p3.3.50
+ //}
+ //else {
+/// muse->routingPopupMenuActivated(selected, n);
+ muse->routingPopupMenuActivated(selected, mdi.data().toInt());
+ //}
+}
+#endif
+
//---------------------------------------------------------
// inRoutesPressed
//---------------------------------------------------------
@@ -605,16 +631,21 @@ void Arranger::inRoutesPressed()
//song->chooseMidiRoutes(iR, (MidiTrack*)track, false);
PopupMenu* pup = muse->prepareRoutingPopupMenu(selected, false);
+ //PopupView* pup = muse->prepareRoutingPopupView(selected, false);
if(!pup)
return;
//pup->disconnect();
//gRoutingPopupMenuMaster = this;
gRoutingPopupMenuMaster = midiTrackInfo;
- connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int)));
+ //connect(pup, SIGNAL(activated(int)), SLOT(routingPopupMenuActivated(int)));
+ connect(pup, SIGNAL(triggered(QAction*)), SLOT(routingPopupMenuActivated(QAction*)));
+ //connect(pup, SIGNAL(activated(const QModelIndex&)), SLOT(routingPopupViewActivated(const QModelIndex&)));
// Nope, can't clear menu and mm list in there, sub-menus stay open. Never mind for now...
connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupMenuAboutToHide()));
- pup->popup(QCursor::pos(), 0);
+ //connect(pup, SIGNAL(aboutToHide()), muse, SLOT(routingPopupViewAboutToHide()));
+ pup->popup(QCursor::pos());
+ //pup->setVisible(true);
midiTrackInfo->iRButton->setDown(false);
return;
}
diff --git a/muse2/muse/synth.cpp b/muse2/muse/synth.cpp
index a9685706..b6e06e65 100644
--- a/muse2/muse/synth.cpp
+++ b/muse2/muse/synth.cpp
@@ -36,9 +36,6 @@
#include "midictrl.h"
//#include "stringparam.h"
-// REMOVE Tim.
-#include "plugin.h"
-
std::vector<Synth*> synthis; // array of available synthis
extern void connectNodes(AudioTrack*, AudioTrack*);
diff --git a/muse2/muse/widgets/popupmenu.cpp b/muse2/muse/widgets/popupmenu.cpp
index 59951375..e2344d32 100644
--- a/muse2/muse/widgets/popupmenu.cpp
+++ b/muse2/muse/widgets/popupmenu.cpp
@@ -5,2774 +5,131 @@
//
// (C) Copyright 1999-2010 Werner Schweer (ws@seh.de)
//
-// PopupMenu sub-class of QPopupMenu created by Tim.
+// PopupMenu sub-class of QMenu created by Tim.
//=========================================================
-
-
-//=========================================================
-//
-// NOTICE: This sub-class of QPopupMenu *automatically* deletes
-// and *clears* any sub popup menus, when clear() is called.
-// Therefore a parent widget is *not* necessary when
-// creating sub popup menus to add to the popup.
-//
-//=========================================================
-
-
-
-// MusE: want no menu bar here. Can't use, not needed for now anyway.
-#define QT_NO_MENUBAR
-#define QT_NO_WHATSTHIS
-
-#include <qapplication.h>
-//#include <qtimer.h>
-#include <qpointer.h>
-//Added by qt3to4:
-#include <Q3Signal>
#include <QMouseEvent>
-#include <Q3PopupMenu>
-//#include <qmenubar.h>
-//#include <qstyle.h>
-//#include <qdatetime.h>
+#include <QAction>
+//#include <QStandardItemModel>
#include "popupmenu.h"
-
-// used to provide ONE single-shot timer
-//static QTimer * singleSingleShot = 0;
-//static bool preventAnimation = FALSE;
-// Used to detect motion prior to mouse-release
-static int motion;
-static PopupMenu* active_popup_menu = 0;
-
-/*
-static void cleanup()
-{
- delete singleSingleShot;
- singleSingleShot = 0;
-}
-
-static void popupSubMenuLater( int msec, QPopupMenu * receiver ) {
-//static void popupSubMenuLater( int msec, PopupMenu * receiver ) {
- if ( !singleSingleShot ) {
- singleSingleShot = new QTimer( qApp, "popup submenu timer" );
- qAddPostRoutine( cleanup );
- }
-
- singleSingleShot->disconnect( SIGNAL(timeout()) );
- QObject::connect( singleSingleShot, SIGNAL(timeout()),
- receiver, SLOT(subMenuTimer()) );
- singleSingleShot->start( msec, TRUE );
-}
-*/
-
-/*
-//======================
-// MenuDataData
-//======================
-
-class QMenuDataData {
-public:
- QMenuDataData();
- QGuardedPtr<QWidget> aWidget;
- int aInt;
-};
-
-//======================
-// QPopupMenuPrivate
-//======================
-
-class QPopupMenuPrivate {
-public:
- struct Scroll {
- enum { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
- uint scrollable : 2;
- uint direction : 1;
- int topScrollableIndex, scrollableSize;
- QTime lastScroll;
- QTimer *scrolltimer;
- } scroll;
- QSize calcSize;
- QRegion mouseMoveBuffer;
-};
-*/
-
//======================
// PopupMenu
//======================
-PopupMenu::PopupMenu(QWidget* parent, const char* name)
- : Q3PopupMenu(parent, name)
+PopupMenu::PopupMenu(QWidget* parent)
+ : QMenu(parent)
{
- // It's too bad QPopupMenu::d is private.
- // It will be redundant and this will be our own private member.
- //d = new QPopupMenuPrivate;
- //d->scroll.scrollableSize = d->scroll.topScrollableIndex = 0;
- //d->scroll.scrollable = QPopupMenuPrivate::Scroll::ScrollNone;
- //d->scroll.scrolltimer = 0;
+ // Menus will trigger! Set to make sure our trigger handlers ignore menus.
+ menuAction()->setData(-1);
}
PopupMenu::~PopupMenu()
{
- //if(d->scroll.scrolltimer)
- // delete d->scroll.scrolltimer;
-
- //preventAnimation = FALSE;
- //delete d;
-
- // Make sure to clear the popup so that any child popups are also deleted !
- //popup->clear();
+ printf("PopupMenu::~PopupMenu\n"); // REMOVE Tim.
}
-
-
-#if 0 // p4.0.1
-
-void PopupMenu::menuDelPopup(Q3PopupMenu *popup)
+void PopupMenu::clear()
{
- //printf("PopupMenu::menuDelPopup deleting popup...\n");
-
- // Make sure to clear the popup so that any child popups are also deleted !
- // Tested OK. All the popups are deleted.
- popup->clear();
-
- popup->disconnect( SIGNAL(activatedRedirect(int)) );
- popup->disconnect( SIGNAL(highlightedRedirect(int)) );
- disconnect( popup, SIGNAL(destroyed(QObject*)),
- this, SLOT(popupDestroyed(QObject*)) );
- delete popup;
-}
-
-/*
-void PopupMenu::setFirstItemActive()
-{
- QMenuItemListIt it(*QPopupMenu::mitems);
- register QMenuItem *mi;
- int ai = 0;
- //if(d->scroll.scrollable)
- // ai = d->scroll.topScrollableIndex;
- while ( (mi=it.current()) )
+ QList<QAction*> list = actions();
+ for(int i = 0; i < list.size(); ++i)
+ {
+ QAction* act = list[i];
+ QMenu* menu = act->menu();
+ if(menu)
{
- ++it;
- if(!mi->isSeparator() && mi->id() != QMenuData::d->aInt &&
- (style().styleHint(QStyle::SH_PopupMenu_AllowActiveAndDisabled, this) || mi->isEnabledAndVisible()))
- {
- setActiveItem( ai );
- return;
- }
- ai++;
- }
- QPopupMenu::actItem = -1;
-}
-*/
-
-/*
-void PopupMenu::hideAllPopups()
-{
- //register QMenuData *top = this; // find top level popup
- register MenuData *top = this; // find top level popup
- if ( !preventAnimation )
- QTimer::singleShot( 10, this, SLOT(allowAnimation()) );
- preventAnimation = TRUE;
-
- if ( !isPopup() )
- return; // nothing to do
-
- //while ( top->parentMenu && top->parentMenu->isPopupMenu
- while ( top->parentMenu && ((MenuData*)top->parentMenu)->isPopupMenu
- //&& ((QPopupMenu*)top->parentMenu)->isPopup() )
- && ((PopupMenu*)((MenuData*)top->parentMenu))->isPopup() )
- //top = top->parentMenu;
- top = (MenuData*)top->parentMenu;
- //((QPopupMenu*)top)->hide(); // cascade from top level
- ((PopupMenu*)top)->hide(); // cascade from top level
-
-#ifndef QT_NO_WHATSTHIS
- if (whatsThisItem) {
- qWhatsThisBDH();
- whatsThisItem = 0;
- }
-#endif
-
-}
-*/
-
-/*
-void PopupMenu::hidePopups()
-{
- if ( !preventAnimation )
- QTimer::singleShot( 10, this, SLOT(allowAnimation()) );
- preventAnimation = TRUE;
-
- //QMenuItemListIt it(*mitems);
- QMenuItemListIt it(*MenuData::mitems);
- register QMenuItem *mi;
- while ( (mi=it.current()) ) {
- ++it;
- if ( mi->popup() && mi->popup()->parentMenu == this ) //avoid circularity
- mi->popup()->hide();
+ menu->clear();
+ act->setMenu(0); // CHECK: Is this OK?
+ delete menu;
}
- popupActive = -1; // no active sub menu
- if(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this))
- d->mouseMoveBuffer = QRegion();
-
- QRect mfrect = itemGeometry( actItem );
- setMicroFocusHint( mfrect.x(), mfrect.y(), mfrect.width(), mfrect.height(), FALSE );
-}
-*/
-
-bool PopupMenu::tryMenuBar( QMouseEvent *e )
-{
-#if 0 // ddskrjo
- register QMenuData *top = this; // find top level
- //register PopupMenu *top = this; // find top level
- //while ( top->parentMenu )
- while ( ((PopupMenu*)top)->parentMenu )
- //top = top->parentMenu;
- //top = (MenuData*)top->parentMenu;
- top = ((PopupMenu*)top)->parentMenu;
-#ifndef QT_NO_MENUBAR
- return top->isMenuBar ?
- ((QMenuBar *)top)->tryMouseEvent( this, e ) :
- ((Q3PopupMenu*)top)->tryMouseEvent(this, e );
-#else
- //return ((QPopupMenu*)top)->tryMouseEvent(this, e );
- return ((PopupMenu*)top)->tryMouseEvent(this, e );
-#endif
-
-#endif
- return false; // ddskrjo
-}
-
-//bool PopupMenu::tryMouseEvent( QPopupMenu *p, QMouseEvent * e)
-bool PopupMenu::tryMouseEvent( PopupMenu *p, QMouseEvent * e)
-{
- if ( p == this )
- return FALSE;
- QPoint pos = mapFromGlobal( e->globalPos() );
- if ( !rect().contains( pos ) ) // outside
- return FALSE;
- QMouseEvent ee( e->type(), pos, e->globalPos(), e->button(), e->state() );
- event( &ee );
- return TRUE;
-}
-
-/*
-void PopupMenu::byeMenuBar()
-{
-#ifndef QT_NO_MENUBAR
- //register QMenuData *top = this; // find top level
- register MenuData *top = this; // find top level
- while ( top->parentMenu )
- top = top->parentMenu;
-#endif
- hideAllPopups();
-#ifndef QT_NO_MENUBAR
- if ( top->isMenuBar )
- ((QMenuBar *)top)->goodbye();
-#endif
+ }
+
+ // Now let QT remove and delete this menu's actions.
+ QMenu::clear();
}
-*/
-void PopupMenu::actSig(int id, bool inwhatsthis)
+QAction* PopupMenu::findActionFromData(QVariant v)
{
- if(!inwhatsthis)
+ QList<QAction*> list = actions();
+ for(int i = 0; i < list.size(); ++i)
+ {
+ QAction* act = list[i];
+ PopupMenu* menu = (PopupMenu*)act->menu();
+ if(menu)
{
- emit activated( id );
-#if defined(QT_ACCESSIBILITY_SUPPORT)
- if(!fromAccel)
- QAccessible::updateAccessibility(this, indexOf(id)+1, QAccessible::MenuCommand);
-#endif
- }
- else
- {
-#ifndef QT_NO_WHATSTHIS
- QRect r(itemGeometry(indexOf(id)));
- QPoint p(r.center().x(), r.bottom());
- QString whatsThis = findItem(id)->whatsThis();
- if(whatsThis.isNull())
- whatsThis = Q3WhatsThis::textFor(this, p);
- Q3WhatsThis::leaveWhatsThisMode(whatsThis, mapToGlobal(p), this);
-#endif
+ if(QAction* actm = menu->findActionFromData(v))
+ return actm;
}
-
- //emit activatedRedirect(id); ddskrjo
+ if(act->data() == v)
+ return act;
+ }
+ return 0;
}
-
-/*
-void PopupMenu::mousePressEvent(QMouseEvent *e)
-{
- printf("PopupMenu::mousePressEvent\n");
-
- //int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- //if (rect().contains(e->pos()) &&
- // ((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && e->pos().y() <= sh) || //up
- // (d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- // e->pos().y() >= contentsRect().height() - sh))) //down
+void PopupMenu::mouseReleaseEvent(QMouseEvent *e)
+{
+ //Q_D(QMenu);
+ //if (d->mouseEventTaken(e))
// return;
-
- mouseBtDn = TRUE; // mouse button down
- int item = itemAtPos( e->pos() );
- if ( item == -1 ) {
- //if ( !rect().contains(e->pos()) && !tryMenuBar(e) ) {
- // byeMenuBar();
- //}
- return;
- }
- register QMenuItem *mi = mitems->at(item);
- ///if ( item != actItem ) // new item activated
- /// setActiveItem( item );
- QPopupMenu *popup = mi->popup();
- if(popup)
- {
- if(popup->isVisible()) // sub menu already open
- {
- //int pactItem = popup->actItem;
- //popup->actItem = -1;
- //popup->hidePopups();
- //popup->updateRow( pactItem );
- }
- else // open sub menu
- {
- //hidePopups();
- popupSubMenuLater( 20, this );
- }
- }
- else
+ //d->mouseDown = false;
+ //QAction *action = d->actionAt(e->pos());
+ QAction *action = actionAt(e->pos());
+
+ //for(QWidget *caused = this; caused;) {
+ // if (QMenu *m = qobject_cast<QMenu*>(caused)) {
+ // QAction *currentAction = d->currentAction;
+ // if(currentAction && (!currentAction->isEnabled() || currentAction->menu() || currentAction->isSeparator()))
+ // currentAction = 0;
+ // caused = m->d_func()->causedPopup.widget;
+ // if (m->d_func()->eventLoop)
+ // m->d_func()->syncAction = currentAction; // synchronous operation
+ // } else {
+ // break;
+ // }
+ //}
+
+ //if (action && action == d->currentAction) {
+ if (action && action == activeAction() && !action->isSeparator() && action->isEnabled())
{
- //hidePopups();
+ //if (action->menu())
+ // action->menu()->d_func()->setFirstActionActive();
+ //else
+ //d->activateAction(action, QAction::Trigger);
+ action->activate(QAction::Trigger);
}
-}
-*/
-
-void PopupMenu::mouseReleaseEvent(QMouseEvent *e)
-{
-#if 0 // ddskrjo
- // do not hide a standalone context menu on press-release, unless
- // the user moved the mouse significantly
- //if(!parentMenu && !mouseBtDn && actItem < 0 && motion < 6)
- // return;
-
- //mouseBtDn = FALSE;
- //MenuData::mouseBtDn = FALSE;
- Q3PopupMenu::mouseBtDn = FALSE;
-
- // if the user released the mouse outside the menu, pass control
- // to the menubar or our parent menu
- //int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if(!rect().contains(e->pos()) && tryMenuBar(e))
- return;
- //else
- //if((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && e->pos().y() <= sh) || //up
- // (d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- // e->pos().y() >= contentsRect().height() - sh)) //down
- // return;
-
- if(Q3PopupMenu::actItem < 0)
- {
- // we do not have an active item
- // if the release is inside without motion (happens with
- // oversized popup menus on small screens), ignore it
- if(rect().contains(e->pos()) && motion < 6)
- return;
- ///else
- /// byeMenuBar();
- }
else
- {
- // selected menu item!
- register QMenuItem *mi = Q3PopupMenu::mitems->at(Q3PopupMenu::actItem);
- if(mi->widget())
- {
- QWidget* widgetAt = QApplication::widgetAt(e->globalPos(), TRUE);
- if(widgetAt && widgetAt != this)
- {
- QMouseEvent me(e->type(), widgetAt->mapFromGlobal(e->globalPos()),
- e->globalPos(), e->button(), e->state());
- QApplication::sendEvent( widgetAt, &me );
- }
- }
- //QPopupMenu *popup = mi->popup();
- PopupMenu *popup = (PopupMenu*)mi->popup();
-#ifndef QT_NO_WHATSTHIS
- bool b = Q3WhatsThis::inWhatsThisMode();
-#else
- const bool b = FALSE;
-#endif
- if(!mi->isEnabledAndVisible())
- {
-#ifndef QT_NO_WHATSTHIS
- if(b)
- {
- actItem = -1;
- updateItem(mi->id());
- byeMenuBar();
- actSig(mi->id(), b);
- }
-#endif
- }
- else
- if(popup)
- {
- //popup->setFirstItemActive();
- }
- else
- {
- // normal menu item
- ///byeMenuBar(); // deactivate menu bar
- if(mi->isEnabledAndVisible())
- {
- ///QPopupMenu::actItem = -1;
- Q3PopupMenu::updateItem(mi->id());
- active_popup_menu = this;
- QPointer<Q3Signal> signal = mi->signal();
- actSig(mi->id(), b);
- if(signal && !b)
- signal->activate();
- active_popup_menu = 0;
- }
- }
- }
-#endif
+ //if (d->motions > 6) {
+ // d->hideUpToMenuBar();
+ // }
+ QMenu::mouseReleaseEvent(e);
}
-
-
-#endif // p4.0.1
-
-
-
-
-/****************************************************************************
-**
-** Implementation of QPopupMenu class
-**
-** Created : 941128
-**
-** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
-**
-** This file is part of the widgets module of the Qt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free Qt Foundation.
-**
-** 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.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.QPL
-** included in the packaging of this file. Licensees holding valid Qt
-** Commercial licenses may use this file in accordance with the Qt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
-
/*
-#include "popupmenu.h"
-#ifndef QT_NO_POPUPMENU
-#include <qmenubar.h>
-#include <qaccel.h>
-#include <qpainter.h>
-#include <qdrawutil.h>
-#include <qapplication.h>
-#include <qpixmap.h>
-#include <qpixmapcache.h>
-#include <qtimer.h>
-#include <qwhatsthis.h>
-#include <qobjectlist.h>
-#include <qguardedptr.h>
-//#include <qeffects_p.h>
-#include <qcursor.h>
-#include <qstyle.h>
-#include <qtimer.h>
-#include <qdatetime.h>
-#if defined(QT_ACCESSIBILITY_SUPPORT)
-#include <qaccessible.h>
-#endif
-
-//#define ANIMATED_POPUP
-//#define BLEND_POPUP
-
-// Motif style parameters
-
-static const int motifArrowHMargin = 6; // arrow horizontal margin
-static const int motifArrowVMargin = 2; // arrow vertical margin
-
-#if 0
-# define DEBUG_SLOPPY_SUBMENU
-#endif
-
-// used for internal communication
-static PopupMenu * syncMenu = 0;
-static int syncMenuId = 0;
-
-// Used to detect motion prior to mouse-release
-static int motion;
-
-// used to provide ONE single-shot timer
-static QTimer * singleSingleShot = 0;
-
-static bool supressAboutToShow = FALSE;
-
-static void cleanup()
-{
- delete singleSingleShot;
- singleSingleShot = 0;
-}
-
-static void popupSubMenuLater( int msec, PopupMenu * receiver ) {
- if ( !singleSingleShot ) {
- singleSingleShot = new QTimer( qApp, "popup submenu timer" );
- qAddPostRoutine( cleanup );
- }
-
- singleSingleShot->disconnect( SIGNAL(timeout()) );
- QObject::connect( singleSingleShot, SIGNAL(timeout()),
- receiver, SLOT(subMenuTimer()) );
- singleSingleShot->start( msec, TRUE );
-}
-
-static bool preventAnimation = FALSE;
-
-#ifndef QT_NO_WHATSTHIS
-extern void qWhatsThisBDH();
-static QMenuItem* whatsThisItem = 0;
-#endif
-
-class QMenuDataData {
- // attention: also defined in qmenudata.cpp
-public:
- QMenuDataData();
- QGuardedPtr<QWidget> aWidget;
- int aInt;
-};
-
-class QPopupMenuPrivate {
-public:
- struct Scroll {
- enum { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
- uint scrollable : 2;
- uint direction : 1;
- int topScrollableIndex, scrollableSize;
- QTime lastScroll;
- QTimer *scrolltimer;
- } scroll;
- QSize calcSize;
- QRegion mouseMoveBuffer;
-};
-
-static PopupMenu* active_popup_menu = 0;
-
-PopupMenu::PopupMenu( QWidget *parent, const char *name )
- : QFrame( parent, name, WType_Popup | WNoAutoErase )
-{
- d = new QPopupMenuPrivate;
- d->scroll.scrollableSize = d->scroll.topScrollableIndex = 0;
- d->scroll.scrollable = QPopupMenuPrivate::Scroll::ScrollNone;
- d->scroll.scrolltimer = 0;
- isPopupMenu = TRUE;
-#ifndef QT_NO_ACCEL
- autoaccel = 0;
- accelDisabled = FALSE;
-#endif
- popupActive = -1;
- snapToMouse = TRUE;
- tab = 0;
- checkable = 0;
- tornOff = 0;
- pendingDelayedContentsChanges = 0;
- pendingDelayedStateChanges = 0;
- maxPMWidth = 0;
-
- tab = 0;
- ncols = 1;
- setFrameStyle( QFrame::PopupPanel | QFrame::Raised );
- setMouseTracking(style().styleHint(QStyle::SH_PopupMenu_MouseTracking, this));
- //style().polishPopupMenu( this );
- style().polishPopupMenu( (QPopupMenu*)this );
- setBackgroundMode( PaletteButton );
- connectModalRecursionSafety = 0;
-
- setFocusPolicy( StrongFocus );
-}
-
-PopupMenu::~PopupMenu()
-{
- if ( syncMenu == this && qApp ) {
- qApp->exit_loop();
- syncMenu = 0;
- }
-
- if(d->scroll.scrolltimer)
- delete d->scroll.scrolltimer;
-
- if ( isVisible() ) {
- parentMenu = 0;
- hidePopups();
- }
-
- delete (QWidget*) QMenuData::d->aWidget; // tear-off menu
-
- preventAnimation = FALSE;
- delete d;
-}
-
-
-void PopupMenu::updateItem( int id ) // update popup menu item
-{
- updateRow( indexOf(id) );
-}
-
-
-void PopupMenu::setCheckable( bool enable )
-{
- if ( isCheckable() != enable ) {
- checkable = enable;
- badSize = TRUE;
- if ( QMenuData::d->aWidget )
- ( (PopupMenu*)(QWidget*)QMenuData::d->aWidget)->setCheckable( enable );
- }
-}
-
-bool PopupMenu::isCheckable() const
-{
- return checkable;
-}
-
-void PopupMenu::menuContentsChanged()
-{
- // here the part that can't be delayed
- QMenuData::menuContentsChanged();
- badSize = TRUE; // might change the size
-#if defined(Q_WS_MAC) && !defined(QMAC_QMENUBAR_NO_NATIVE)
- mac_dirty_popup = 1;
-#endif
- if( pendingDelayedContentsChanges )
- return;
- pendingDelayedContentsChanges = 1;
- if( !pendingDelayedStateChanges ) // if the timer hasn't been started yet
- QTimer::singleShot( 0, this, SLOT(performDelayedChanges()));
-}
-
-void PopupMenu::performDelayedContentsChanged()
-{
- pendingDelayedContentsChanges = 0;
- // here the part the can be delayed
-#ifndef QT_NO_ACCEL
- // if performDelayedStateChanged() will be called too,
- // it will call updateAccel() too, no need to do it twice
- if( !pendingDelayedStateChanges )
- updateAccel( 0 );
-#endif
- if ( isVisible() ) {
- if ( tornOff )
- return;
- updateSize(TRUE);
- update();
- }
- PopupMenu* p = (PopupMenu*)(QWidget*)QMenuData::d->aWidget;
- if ( p && p->isVisible() ) {
- p->updateSize(TRUE);
- p->update();
- }
-#if defined(Q_WS_MAC) && !defined(QMAC_QMENUBAR_NO_NATIVE)
- mac_dirty_popup = 1;
-#endif
-}
-
-
-void PopupMenu::menuStateChanged()
-{
- // here the part that can't be delayed
- if( pendingDelayedStateChanges )
- return;
- pendingDelayedStateChanges = 1;
- if( !pendingDelayedContentsChanges ) // if the timer hasn't been started yet
- QTimer::singleShot( 0, this, SLOT(performDelayedChanges()));
-}
-
-void PopupMenu::performDelayedStateChanged()
-{
- pendingDelayedStateChanges = 0;
- // here the part that can be delayed
-#ifndef QT_NO_ACCEL
- updateAccel( 0 ); // ### when we have a good solution for the accel vs. focus widget problem, remove that. That is only a workaround
- // if you remove this, see performDelayedContentsChanged()
-#endif
- update();
- if ( QMenuData::d->aWidget )
- QMenuData::d->aWidget->update();
-}
-
-void PopupMenu::performDelayedChanges()
-{
- if( pendingDelayedContentsChanges )
- performDelayedContentsChanged();
- if( pendingDelayedStateChanges )
- performDelayedStateChanged();
-}
-
-void PopupMenu::menuInsPopup( PopupMenu *popup )
-{
- connect( popup, SIGNAL(activatedRedirect(int)),
- SLOT(subActivated(int)) );
- connect( popup, SIGNAL(highlightedRedirect(int)),
- SLOT(subHighlighted(int)) );
- connect( popup, SIGNAL(destroyed(QObject*)),
- this, SLOT(popupDestroyed(QObject*)) );
-}
-
-void PopupMenu::menuDelPopup( PopupMenu *popup )
-{
- popup->disconnect( SIGNAL(activatedRedirect(int)) );
- popup->disconnect( SIGNAL(highlightedRedirect(int)) );
- disconnect( popup, SIGNAL(destroyed(QObject*)),
- this, SLOT(popupDestroyed(QObject*)) );
-}
-
-
-void PopupMenu::frameChanged()
-{
- menuContentsChanged();
-}
-
-void PopupMenu::popup( const QPoint &pos, int indexAtPoint )
-{
- if ( !isPopup() && isVisible() )
- hide();
-
- //avoid circularity
- if ( isVisible() || !isEnabled() )
- return;
-
-#if defined(Q_WS_MAC) && !defined(QMAC_QMENUBAR_NO_NATIVE)
- if( macPopupMenu(pos, indexAtPoint ))
- return;
-#endif
-
-#if (QT_VERSION-0 >= 0x040000)
-#error "Fix this now"
- // #### should move to QWidget - anything might need this functionality,
- // #### since anything can have WType_Popup window flag.
- // #### This includes stuff in QPushButton and some stuff for setting
- // #### the geometry of QDialog.
- // QPopupMenu
- // ::exec()
- // ::popup()
- // QPushButton (shouldn't require QMenuPopup)
- // ::popupPressed
- // Some stuff in qwidget.cpp for dialogs... can't remember exactly.
- // Also the code here indicatets the parameter should be a rect, not a
- // point.
-#endif
-
- if(d->scroll.scrollable) {
- d->scroll.scrollable = QPopupMenuPrivate::Scroll::ScrollNone;
- d->scroll.topScrollableIndex = d->scroll.scrollableSize = 0;
- badSize = TRUE;
- }
- updateSize();
-
- QPoint mouse = QCursor::pos();
- snapToMouse = pos == mouse;
-
- // have to emit here as a menu might be setup in a slot connected
- // to aboutToShow which will change the size of the menu
- bool s = supressAboutToShow;
- supressAboutToShow = TRUE;
- if ( !s) {
- emit aboutToShow();
- updateSize(TRUE);
- }
-
- int screen_num;
- if (QApplication::desktop()->isVirtualDesktop())
- screen_num =
- QApplication::desktop()->screenNumber( QApplication::reverseLayout() ?
- pos+QPoint(width(),0) : pos );
- else
- screen_num = QApplication::desktop()->screenNumber( this );
-#ifdef Q_WS_MAC
- QRect screen = QApplication::desktop()->availableGeometry( screen_num );
-#else
- QRect screen = QApplication::desktop()->screenGeometry( screen_num );
-#endif
- int sw = screen.width(); // screen width
- int sh = screen.height(); // screen height
- int sx = screen.x(); // screen pos
- int sy = screen.y();
- int x = pos.x();
- int y = pos.y();
- if ( indexAtPoint >= 0 ) // don't subtract when < 0
- y -= itemGeometry( indexAtPoint ).y(); // (would subtract 2 pixels!)
- int w = width();
- int h = height();
-
- if ( snapToMouse ) {
- if ( qApp->reverseLayout() )
- x -= w;
- if ( x+w > sx+sw )
- x = mouse.x()-w;
- if ( y+h > sy+sh )
- y = mouse.y()-h;
- if ( x < sx )
- x = mouse.x();
- if ( y < sy )
- y = sy;
- }
-
- if ( x+w > sx+sw ) // the complete widget must
- x = sx+sw - w; // be visible
- if ( y+h > sy+sh )
- y = sy+sh - h;
- if ( x < sx )
- x = sx;
- if ( y < sy )
- y = sy;
-
- if(style().styleHint(QStyle::SH_PopupMenu_Scrollable, this)) {
- int off_top = 0, off_bottom = 0;
- if(y+h > sy+sh)
- off_bottom = (y+h) - (sy+sh);
- if(y < sy)
- off_top = sy - y;
- if(off_bottom || off_top) {
- int ch = updateSize().height(); //store the old height, before setting scrollable --Sam
- const int vextra = style().pixelMetric(QStyle::PM_PopupMenuFrameVerticalExtra, this);
- d->scroll.scrollableSize = h - off_top - off_bottom - 2*vextra;
- if(off_top) {
- move( x, y = sy );
- d->scroll.scrollable = d->scroll.scrollable | QPopupMenuPrivate::Scroll::ScrollUp;
- }
- if( off_bottom )
- d->scroll.scrollable = d->scroll.scrollable | QPopupMenuPrivate::Scroll::ScrollDown;
- if( off_top != off_bottom && indexAtPoint >= 0 ) {
- ch -= (vextra * 2);
- if(ch > sh) //no bigger than the screen!
- ch = sh;
- if( ch > d->scroll.scrollableSize )
- d->scroll.scrollableSize = ch;
- }
-
- updateSize(TRUE); //now set the size using the scrollable/scrollableSize as above
- w = width();
- h = height();
- if(indexAtPoint >= 0) {
- if(off_top) { //scroll to it
- register QMenuItem *mi = NULL;
- QMenuItemListIt it(*mitems);
- for(int tmp_y = 0; tmp_y < off_top && (mi=it.current()); ) {
- QSize sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemHeight( mi )),
- QStyleOption(mi,maxPMWidth,0));
- tmp_y += sz.height();
- d->scroll.topScrollableIndex++;
- }
- }
- }
- }
- }
- move( x, y );
- motion=0;
- actItem = -1;
-
-#ifndef QT_NO_EFFECTS
- int hGuess = qApp->reverseLayout() ? QEffects::LeftScroll : QEffects::RightScroll;
- int vGuess = QEffects::DownScroll;
- if ( qApp->reverseLayout() ) {
- if ( snapToMouse && ( x + w/2 > mouse.x() ) ||
- ( parentMenu && parentMenu->isPopupMenu &&
- ( x + w/2 > ((PopupMenu*)parentMenu)->x() ) ) )
- hGuess = QEffects::RightScroll;
- } else {
- if ( snapToMouse && ( x + w/2 < mouse.x() ) ||
- ( parentMenu && parentMenu->isPopupMenu &&
- ( x + w/2 < ((PopupMenu*)parentMenu)->x() ) ) )
- hGuess = QEffects::LeftScroll;
- }
-
-#ifndef QT_NO_MENUBAR
- if ( snapToMouse && ( y + h/2 < mouse.y() ) ||
- ( parentMenu && parentMenu->isMenuBar &&
- ( y + h/2 < ((QMenuBar*)parentMenu)->mapToGlobal( ((QMenuBar*)parentMenu)->pos() ).y() ) ) )
- vGuess = QEffects::UpScroll;
-#endif
-
- if ( QApplication::isEffectEnabled( UI_AnimateMenu ) &&
- preventAnimation == FALSE ) {
- if ( QApplication::isEffectEnabled( UI_FadeMenu ) )
- qFadeEffect( this );
- else if ( parentMenu )
- qScrollEffect( this, parentMenu->isPopupMenu ? hGuess : vGuess );
- else
- qScrollEffect( this, hGuess | vGuess );
- } else
-#endif
- {
- show();
- }
-#if defined(QT_ACCESSIBILITY_SUPPORT)
- QAccessible::updateAccessibility( this, 0, QAccessible::PopupMenuStart );
-#endif
-}
-
-void PopupMenu::subActivated( int id )
-{
- emit activatedRedirect( id );
-}
-
-void PopupMenu::subHighlighted( int id )
-{
- emit highlightedRedirect( id );
-}
-
-static bool fromAccel = FALSE;
-
-#ifndef QT_NO_ACCEL
-void PopupMenu::accelActivated( int id )
-{
- QMenuItem *mi = findItem( id );
- if ( mi && mi->isEnabledAndVisible() ) {
- QGuardedPtr<QSignal> signal = mi->signal();
- fromAccel = TRUE;
- actSig( mi->id() );
- fromAccel = FALSE;
- if ( signal )
- signal->activate();
- }
-}
-
-void PopupMenu::accelDestroyed() // accel about to be deleted
-{
- autoaccel = 0; // don't delete it twice!
-}
-#endif //QT_NO_ACCEL
-
-void PopupMenu::popupDestroyed( QObject *o )
-{
- removePopup( (PopupMenu*)o );
-}
-
-void PopupMenu::actSig( int id, bool inwhatsthis )
-{
- if ( !inwhatsthis ) {
- emit activated( id );
-#if defined(QT_ACCESSIBILITY_SUPPORT)
- if ( !fromAccel )
- QAccessible::updateAccessibility( this, indexOf(id)+1, QAccessible::MenuCommand );
-#endif
- } else {
-#ifndef QT_NO_WHATSTHIS
- QRect r( itemGeometry( indexOf( id ) ) );
- QPoint p( r.center().x(), r.bottom() );
- QString whatsThis = findItem( id )->whatsThis();
- if ( whatsThis.isNull() )
- whatsThis = QWhatsThis::textFor( this, p );
- QWhatsThis::leaveWhatsThisMode( whatsThis, mapToGlobal( p ), this );
-#endif
- }
-
- emit activatedRedirect( id );
-}
-
-void PopupMenu::hilitSig( int id )
-{
- emit highlighted( id );
- emit highlightedRedirect( id );
-
-#if defined(QT_ACCESSIBILITY_SUPPORT)
- QAccessible::updateAccessibility( this, indexOf(id)+1, QAccessible::Focus );
- QAccessible::updateAccessibility( this, indexOf(id)+1, QAccessible::Selection );
-#endif
-}
-
-void PopupMenu::setFirstItemActive()
-{
- QMenuItemListIt it(*mitems);
- register QMenuItem *mi;
- int ai = 0;
- if(d->scroll.scrollable)
- ai = d->scroll.topScrollableIndex;
- while ( (mi=it.current()) ) {
- ++it;
- if ( !mi->isSeparator() && mi->id() != QMenuData::d->aInt &&
- ( style().styleHint( QStyle::SH_PopupMenu_AllowActiveAndDisabled, this ) || mi->isEnabledAndVisible() )) {
- setActiveItem( ai );
- return;
- }
- ai++;
- }
- actItem = -1;
-}
-
-void PopupMenu::hideAllPopups()
-{
- register QMenuData *top = this; // find top level popup
- if ( !preventAnimation )
- QTimer::singleShot( 10, this, SLOT(allowAnimation()) );
- preventAnimation = TRUE;
-
- if ( !isPopup() )
- return; // nothing to do
-
- while ( top->parentMenu && top->parentMenu->isPopupMenu
- && ((PopupMenu*)top->parentMenu)->isPopup() )
- top = top->parentMenu;
- ((PopupMenu*)top)->hide(); // cascade from top level
-
-#ifndef QT_NO_WHATSTHIS
- if (whatsThisItem) {
- qWhatsThisBDH();
- whatsThisItem = 0;
- }
-#endif
-
-}
-
-void PopupMenu::hidePopups()
-{
- if ( !preventAnimation )
- QTimer::singleShot( 10, this, SLOT(allowAnimation()) );
- preventAnimation = TRUE;
-
- QMenuItemListIt it(*mitems);
- register QMenuItem *mi;
- while ( (mi=it.current()) ) {
- ++it;
- if ( mi->popup() && mi->popup()->parentMenu == this ) //avoid circularity
- mi->popup()->hide();
- }
- popupActive = -1; // no active sub menu
- if(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this))
- d->mouseMoveBuffer = QRegion();
-
- QRect mfrect = itemGeometry( actItem );
- setMicroFocusHint( mfrect.x(), mfrect.y(), mfrect.width(), mfrect.height(), FALSE );
-}
-
-bool PopupMenu::tryMenuBar( QMouseEvent *e )
-{
- register QMenuData *top = this; // find top level
- while ( top->parentMenu )
- top = top->parentMenu;
-#ifndef QT_NO_MENUBAR
- return top->isMenuBar ?
- ((QMenuBar *)top)->tryMouseEvent( this, e ) :
- ((PopupMenu*)top)->tryMouseEvent(this, e );
-#else
- return ((PopupMenu*)top)->tryMouseEvent(this, e );
-#endif
-}
-
-bool PopupMenu::tryMouseEvent( PopupMenu *p, QMouseEvent * e)
-{
- if ( p == this )
- return FALSE;
- QPoint pos = mapFromGlobal( e->globalPos() );
- if ( !rect().contains( pos ) ) // outside
- return FALSE;
- QMouseEvent ee( e->type(), pos, e->globalPos(), e->button(), e->state() );
- event( &ee );
- return TRUE;
-}
-
-void PopupMenu::byeMenuBar()
-{
-#ifndef QT_NO_MENUBAR
- register QMenuData *top = this; // find top level
- while ( top->parentMenu )
- top = top->parentMenu;
-#endif
- hideAllPopups();
-#ifndef QT_NO_MENUBAR
- if ( top->isMenuBar )
- ((QMenuBar *)top)->goodbye();
-#endif
-}
-
-int PopupMenu::itemAtPos( const QPoint &pos, bool ignoreSeparator ) const
-{
- if ( !contentsRect().contains(pos) )
- return -1;
-
- int row = 0;
- int x = contentsRect().x();
- int y = contentsRect().y();
- QMenuItem *mi;
- QMenuItemListIt it( *mitems );
- if(d->scroll.scrollable) {
- if(d->scroll.topScrollableIndex) {
- for( ; (mi = it.current()) && row < d->scroll.topScrollableIndex; row++)
- ++it;
- if(!mi) {
- row = 0;
- it.toFirst();
- }
- y += style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- }
- }
- int itemw = contentsRect().width() / ncols;
- QSize sz;
- while ( (mi=it.current()) ) {
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- y >= contentsRect().height() - style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this))
- return -1;
- ++it;
- if ( !mi->isVisible() ) {
- ++row;
- continue;
- }
- int itemh = itemHeight( mi );
-
- sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemh),
- QStyleOption(mi,maxPMWidth));
- sz = sz.expandedTo(QSize(itemw, sz.height()));
- itemw = sz.width();
- itemh = sz.height();
-
- if ( ncols > 1 && y + itemh > contentsRect().bottom() ) {
- y = contentsRect().y();
- x +=itemw;
- }
- if ( QRect( x, y, itemw, itemh ).contains( pos ) )
- break;
- y += itemh;
- ++row;
- }
-
- if ( mi && ( !ignoreSeparator || !mi->isSeparator() ) )
- return row;
- return -1;
-}
-
-QRect PopupMenu::itemGeometry( int index )
-{
- QMenuItem *mi;
- QSize sz;
- int row = 0, scrollh = 0;
- int x = contentsRect().x();
- int y = contentsRect().y();
- QMenuItemListIt it( *mitems );
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp) {
- scrollh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- y += scrollh;
- if(d->scroll.topScrollableIndex) {
- for( ; (mi = it.current()) && row < d->scroll.topScrollableIndex; row++)
- ++it;
- if(!mi) {
- row = 0;
- it.toFirst();
- }
- }
- }
- int itemw = contentsRect().width() / ncols;
- while ( (mi=it.current()) ) {
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- y >= contentsRect().height() - scrollh)
- break;
- ++it;
- if ( !mi->isVisible() ) {
- ++row;
- continue;
- }
- int itemh = itemHeight( mi );
-
- sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemh),
- QStyleOption(mi,maxPMWidth));
- sz = sz.expandedTo(QSize(itemw, sz.height()));
- itemw = sz.width();
- itemh = sz.height();
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- (y + itemh > contentsRect().height() - scrollh))
- itemh -= (y + itemh) - (contentsRect().height() - scrollh);
- if ( ncols > 1 && y + itemh > contentsRect().bottom() ) {
- y = contentsRect().y();
- x +=itemw;
- }
- if ( row == index )
- return QRect( x,y,itemw,itemh );
- y += itemh;
- ++row;
- }
-
- return QRect(0,0,0,0);
-}
-
-QSize PopupMenu::updateSize(bool force_update, bool do_resize)
-{
- polish();
- if ( count() == 0 ) {
- QSize ret = QSize( 50, 8 );
- if(do_resize)
- setFixedSize( ret );
- badSize = TRUE;
- return ret;
- }
-
- int scrheight = 0;
- if(d->scroll.scrollableSize) {
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp)
- scrheight += style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown)
- scrheight += style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- }
-
- if(badSize || force_update) {
-#ifndef QT_NO_ACCEL
- updateAccel( 0 );
-#endif
- int height = 0;
- int max_width = 0, max_height = 0;
- QFontMetrics fm = fontMetrics();
- register QMenuItem *mi;
- maxPMWidth = 0;
- int maxWidgetWidth = 0;
- tab = 0;
-
- for ( QMenuItemListIt it( *mitems ); it.current(); ++it ) {
- mi = it.current();
- QWidget *miw = mi->widget();
- if (miw) {
- if ( miw->parentWidget() != this )
- miw->reparent( this, QPoint(0,0), TRUE );
- // widget items musn't propgate mouse events
- ((PopupMenu*)miw)->setWFlags(WNoMousePropagation);
- }
- if ( mi->custom() )
- mi->custom()->setFont( font() );
- if ( mi->iconSet() != 0)
- maxPMWidth = QMAX( maxPMWidth,
- mi->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4 );
- }
-
- int dh = QApplication::desktop()->height();
- ncols = 1;
-
- for ( QMenuItemListIt it2( *mitems ); it2.current(); ++it2 ) {
- mi = it2.current();
- if ( !mi->isVisible() )
- continue;
- int w = 0;
- int itemHeight = PopupMenu::itemHeight( mi );
-
- if ( mi->widget() ) {
- QSize s( mi->widget()->sizeHint() );
- s = s.expandedTo( mi->widget()->minimumSize() );
- mi->widget()->resize( s );
- if ( s.width() > maxWidgetWidth )
- maxWidgetWidth = s.width();
- itemHeight = s.height();
- } else {
- if( ! mi->isSeparator() ) {
- if ( mi->custom() ) {
- if ( mi->custom()->fullSpan() ) {
- maxWidgetWidth = QMAX( maxWidgetWidth,
- mi->custom()->sizeHint().width() );
- } else {
- QSize s ( mi->custom()->sizeHint() );
- w += s.width();
- }
- }
-
- w += maxPMWidth;
-
- if (! mi->text().isNull()) {
- QString s = mi->text();
- int t;
- if ( (t = s.find('\t')) >= 0 ) { // string contains tab
- w += fm.width( s, t );
- w -= s.contains('&') * fm.width('&');
- w += s.contains("&&") * fm.width('&');
- int tw = fm.width( s.mid(t + 1) );
- if ( tw > tab)
- tab = tw;
- } else {
- w += fm.width( s );
- w -= s.contains('&') * fm.width('&');
- w += s.contains("&&") * fm.width('&');
- }
- } else if (mi->pixmap())
- w += mi->pixmap()->width();
- } else {
- if ( mi->custom() ) {
- QSize s ( mi->custom()->sizeHint() );
- w += s.width();
- } else {
- w = itemHeight = 2;
- }
- }
-
- QSize sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(w, itemHeight),
- QStyleOption(mi,maxPMWidth));
-
- w = sz.width();
- itemHeight = sz.height();
-
-#if defined(QT_CHECK_NULL)
- if ( mi->text().isNull() && !mi->pixmap() && !mi->iconSet() &&
- !mi->isSeparator() && !mi->widget() && !mi->custom() )
- qWarning( "PopupMenu: (%s) Popup has invalid menu item",
- name( "unnamed" ) );
-#endif
- }
- height += itemHeight;
- if(style().styleHint(QStyle::SH_PopupMenu_Scrollable, this)) {
- if(scrheight && height >= d->scroll.scrollableSize - scrheight) {
- height = d->scroll.scrollableSize - scrheight;
- break;
- }
- } else if( height + 2*frameWidth() >= dh ) {
- ncols++;
- max_height = QMAX(max_height, height - itemHeight);
- height = itemHeight;
- }
- if ( w > max_width )
- max_width = w;
- }
- if( ncols == 1 && !max_height )
- max_height = height;
-
- if(style().styleHint(QStyle::SH_PopupMenu_Scrollable, this)) {
- height += scrheight;
- setMouseTracking(TRUE);
- }
-
- if ( tab )
- tab -= fontMetrics().minRightBearing();
- else
- max_width -= fontMetrics().minRightBearing();
-
- if ( max_width + tab < maxWidgetWidth )
- max_width = maxWidgetWidth - tab;
-
- const int fw = frameWidth();
- int extra_width = (fw+style().pixelMetric(QStyle::PM_PopupMenuFrameHorizontalExtra, this)) * 2,
- extra_height = (fw+style().pixelMetric(QStyle::PM_PopupMenuFrameVerticalExtra, this)) * 2;
- if ( ncols == 1 )
- d->calcSize = QSize( QMAX( minimumWidth(), max_width + tab + extra_width ),
- QMAX( minimumHeight() , height + extra_height ) );
- else
- d->calcSize = QSize( QMAX( minimumWidth(), (ncols*(max_width + tab)) + extra_width ),
- QMAX( minimumHeight(), QMIN( max_height + extra_height + 1, dh ) ) );
- badSize = FALSE;
- }
-
- {
- // Position the widget items. It could be done in drawContents
- // but this way we get less flicker.
- QSize sz;
- int x = contentsRect().x();
- int y = contentsRect().y();
- int itemw = contentsRect().width() / ncols;
- for(QMenuItemListIt it(*mitems); it.current(); ++it) {
- QMenuItem *mi = it.current();
- if ( !mi->isVisible() )
- continue;
-
- int itemh = itemHeight( mi );
-
- sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemh), QStyleOption(mi,maxPMWidth));
- sz = sz.expandedTo(QSize(itemw, sz.height()));
- itemw = sz.width();
- itemh = sz.height();
-
- if ( ncols > 1 && y + itemh > contentsRect().bottom() ) {
- y = contentsRect().y();
- x +=itemw;
- }
- if ( mi->widget() )
- mi->widget()->setGeometry( x, y, itemw, mi->widget()->height() );
- y += itemh;
- }
- }
-
- if( do_resize && size() != d->calcSize ) {
- setMaximumSize( d->calcSize );
- d->calcSize = maximumSize(); //let the max size adjust it (virtual)
- resize( d->calcSize );
- }
- return d->calcSize;
-}
-
-#ifndef QT_NO_ACCEL
-void PopupMenu::updateAccel( QWidget *parent )
-{
- QMenuItemListIt it(*mitems);
- register QMenuItem *mi;
-
- if ( parent ) {
- delete autoaccel;
- autoaccel = 0;
- } else if ( !autoaccel ) {
- // we have no parent. Rather than ignoring any accelerators we try to find this popup's main window
- if ( tornOff ) {
- parent = this;
- } else {
- QWidget *w = (QWidget *) this;
- parent = w->parentWidget();
- while ( (!w->testWFlags(WType_TopLevel) || !w->testWFlags(WType_Popup)) && parent ) {
- w = parent;
- parent = parent->parentWidget();
- }
- }
- }
-
- if ( parent == 0 && autoaccel == 0 )
- return;
-
- if ( autoaccel ) // build it from scratch
- autoaccel->clear();
- else {
- // create an autoaccel in any case, even if we might not use
- // it immediately. Maybe the user needs it later.
- autoaccel = new QAccel( parent, this );
- connect( autoaccel, SIGNAL(activated(int)),
- SLOT(accelActivated(int)) );
- connect( autoaccel, SIGNAL(activatedAmbiguously(int)),
- SLOT(accelActivated(int)) );
- connect( autoaccel, SIGNAL(destroyed()),
- SLOT(accelDestroyed()) );
- if ( accelDisabled )
- autoaccel->setEnabled( FALSE );
- }
- while ( (mi=it.current()) ) {
- ++it;
- QKeySequence k = mi->key();
- if ( (int)k ) {
- int id = autoaccel->insertItem( k, mi->id() );
-#ifndef QT_NO_WHATSTHIS
- autoaccel->setWhatsThis( id, mi->whatsThis() );
-#endif
- }
- if ( !mi->text().isNull() || mi->custom() ) {
- QString s = mi->text();
- int i = s.find('\t');
-
- // Note: Only looking at the first key in the sequence!
- if ( (int)k && (int)k != Key_unknown ) {
- QString t = (QString)mi->key();
- if ( i >= 0 )
- s.replace( i+1, s.length()-i, t );
- else {
- s += '\t';
- s += t;
- }
- } else if ( !k ) {
- if ( i >= 0 )
- s.truncate( i );
- }
- if ( s != mi->text() ) {
- mi->setText( s );
- badSize = TRUE;
- }
- }
- if ( mi->popup() && parent ) { // call recursively
- // reuse
- PopupMenu* popup = mi->popup();
- if (!popup->avoid_circularity) {
- popup->avoid_circularity = 1;
- popup->updateAccel( parent );
- popup->avoid_circularity = 0;
- }
- }
- }
-}
-
-void PopupMenu::enableAccel( bool enable )
-{
- if ( autoaccel )
- autoaccel->setEnabled( enable );
- accelDisabled = !enable; // rememeber when updateAccel
- QMenuItemListIt it(*mitems);
- register QMenuItem *mi;
- while ( (mi=it.current()) ) { // do the same for sub popups
- ++it;
- if ( mi->popup() ) // call recursively
- mi->popup()->enableAccel( enable );
- }
-}
-#endif
-
-void PopupMenu::setFont( const QFont &font )
-{
- QWidget::setFont( font );
- badSize = TRUE;
- if ( isVisible() ) {
- updateSize();
- update();
- }
-}
-
-void PopupMenu::show()
-{
- if ( !isPopup() && isVisible() )
- hide();
-
- if ( isVisible() ) {
- supressAboutToShow = FALSE;
- QWidget::show();
- return;
- }
- if (!supressAboutToShow)
- emit aboutToShow();
- else
- supressAboutToShow = FALSE;
- performDelayedChanges();
- updateSize(TRUE);
- QWidget::show();
- popupActive = -1;
- if(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this))
- d->mouseMoveBuffer = QRegion();
-}
-
-void PopupMenu::hide()
-{
- if ( syncMenu == this && qApp ) {
- qApp->exit_loop();
- syncMenu = 0;
- }
-
- if ( !isVisible() ) {
- QWidget::hide();
- return;
- }
- emit aboutToHide();
-
- actItem = popupActive = -1;
- if(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this))
- d->mouseMoveBuffer = QRegion();
- mouseBtDn = FALSE; // mouse button up
-#if defined(QT_ACCESSIBILITY_SUPPORT)
- QAccessible::updateAccessibility( this, 0, QAccessible::PopupMenuEnd );
-#endif
- parentMenu = 0;
- hidePopups();
- QWidget::hide();
-}
-
-int PopupMenu::itemHeight( int row ) const
-{
- return itemHeight( mitems->at( row ) );
-}
-
-int PopupMenu::itemHeight( QMenuItem *mi ) const
-{
- if ( mi->widget() )
- return mi->widget()->height();
- if ( mi->custom() && mi->custom()->fullSpan() )
- return mi->custom()->sizeHint().height();
-
- QFontMetrics fm(fontMetrics());
- int h = 0;
- if ( mi->isSeparator() ) // separator height
- h = 2;
- else if ( mi->pixmap() ) // pixmap height
- h = mi->pixmap()->height();
- else // text height
- h = fm.height();
-
- if ( !mi->isSeparator() && mi->iconSet() != 0 )
- h = QMAX(h, mi->iconSet()->pixmap( QIconSet::Small,
- QIconSet::Normal ).height());
- if ( mi->custom() )
- h = QMAX(h, mi->custom()->sizeHint().height());
-
- return h;
-}
-
-void PopupMenu::drawItem( QPainter* p, int tab_, QMenuItem* mi,
- bool act, int x, int y, int w, int h)
-{
- QStyle::SFlags flags = QStyle::Style_Default;
- if (isEnabled() && mi->isEnabledAndVisible() && (!mi->popup() || mi->popup()->isEnabled()) )
- flags |= QStyle::Style_Enabled;
- if (act)
- flags |= QStyle::Style_Active;
- if (mouseBtDn)
- flags |= QStyle::Style_Down;
-
- const QColorGroup &cg = ((flags&QStyle::Style_Enabled) ? colorGroup() : palette().disabled() );
-
- if ( mi->custom() && mi->custom()->fullSpan() ) {
- QMenuItem dummy;
- style().drawControl(QStyle::CE_PopupMenuItem, p, this, QRect(x, y, w, h), cg,
- flags, QStyleOption(&dummy,maxPMWidth,tab_));
- mi->custom()->paint( p, cg, act, flags&QStyle::Style_Enabled, x, y, w, h );
- } else
- style().drawControl(QStyle::CE_PopupMenuItem, p, this, QRect(x, y, w, h), cg,
- flags, QStyleOption(mi,maxPMWidth,tab_));
-}
-
-void PopupMenu::drawContents( QPainter* p )
-{
- QMenuItemListIt it(*mitems);
- QMenuItem *mi = 0;
- int row = 0;
- int x = contentsRect().x();
- int y = contentsRect().y();
- if(d->scroll.scrollable) {
- if(d->scroll.topScrollableIndex) {
- for( ; (mi = it.current()) && row < d->scroll.topScrollableIndex; row++)
- ++it;
- if(!mi)
- it.toFirst();
- }
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp) {
- QRect rect(x, y, contentsRect().width(),
- style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this));
- if(!p->hasClipping() || p->clipRegion().contains(rect)) {
- QStyle::SFlags flags = QStyle::Style_Up;
- if (isEnabled())
- flags |= QStyle::Style_Enabled;
- style().drawControl(QStyle::CE_PopupMenuScroller, p, this, rect,
- colorGroup(), flags, QStyleOption(maxPMWidth));
- }
- y += rect.height();
- }
- }
-
- int itemw = contentsRect().width() / ncols;
- QSize sz;
- QStyle::SFlags flags;
- while ( (mi=it.current()) ) {
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- y >= contentsRect().height() - style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this))
- break;
- ++it;
- if ( !mi->isVisible() ) {
- ++row;
- continue;
- }
- int itemh = itemHeight( mi );
- sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemh),
- QStyleOption(mi,maxPMWidth,0)
- );
- sz = sz.expandedTo(QSize(itemw, sz.height()));
- itemw = sz.width();
- itemh = sz.height();
-
- if ( ncols > 1 && y + itemh > contentsRect().bottom() ) {
- if ( y < contentsRect().bottom() ) {
- QRect rect(x, y, itemw, contentsRect().bottom() - y);
- if(!p->hasClipping() || p->clipRegion().contains(rect)) {
- flags = QStyle::Style_Default;
- if (isEnabled() && mi->isEnabledAndVisible())
- flags |= QStyle::Style_Enabled;
- style().drawControl(QStyle::CE_PopupMenuItem, p, this, rect,
- colorGroup(), flags, QStyleOption((QMenuItem*)0,maxPMWidth));
- }
- }
- y = contentsRect().y();
- x +=itemw;
- }
- if (!mi->widget() && (!p->hasClipping() || p->clipRegion().contains(QRect(x, y, itemw, itemh))))
- drawItem( p, tab, mi, row == actItem, x, y, itemw, itemh );
- y += itemh;
- ++row;
- }
- if ( y < contentsRect().bottom() ) {
- QRect rect(x, y, itemw, contentsRect().bottom() - y);
- if(!p->hasClipping() || p->clipRegion().contains(rect)) {
- flags = QStyle::Style_Default;
- if ( isEnabled() )
- flags |= QStyle::Style_Enabled;
- style().drawControl(QStyle::CE_PopupMenuItem, p, this, rect,
- colorGroup(), flags, QStyleOption((QMenuItem*)0,maxPMWidth));
- }
- }
- if( d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown ) {
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- QRect rect(x, contentsRect().height() - sh, contentsRect().width(), sh);
- if(!p->hasClipping() || p->clipRegion().contains(rect)) {
- QStyle::SFlags flags = QStyle::Style_Down;
- if (isEnabled())
- flags |= QStyle::Style_Enabled;
- style().drawControl(QStyle::CE_PopupMenuScroller, p, this, rect,
- colorGroup(), flags, QStyleOption(maxPMWidth));
- }
- }
-#if defined( DEBUG_SLOPPY_SUBMENU )
- if ( style().styleHint(QStyle::SH_PopupMenu_SloppySubMenus, this )) {
- p->setClipRegion( d->mouseMoveBuffer );
- p->fillRect( d->mouseMoveBuffer.boundingRect(), colorGroup().brush( QColorGroup::Highlight ) );
- }
-#endif
-}
-
-void PopupMenu::paintEvent( QPaintEvent *e )
-{
- QFrame::paintEvent( e );
-}
-
-void PopupMenu::closeEvent( QCloseEvent * e) {
- e->accept();
- byeMenuBar();
-}
-
-void PopupMenu::mousePressEvent( QMouseEvent *e )
-{
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if (rect().contains(e->pos()) &&
- ((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && e->pos().y() <= sh) || //up
- (d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- e->pos().y() >= contentsRect().height() - sh))) //down
- return;
-
- mouseBtDn = TRUE; // mouse button down
- int item = itemAtPos( e->pos() );
- if ( item == -1 ) {
- if ( !rect().contains(e->pos()) && !tryMenuBar(e) ) {
- byeMenuBar();
- }
- return;
- }
- register QMenuItem *mi = mitems->at(item);
- if ( item != actItem ) // new item activated
- setActiveItem( item );
-
- PopupMenu *popup = mi->popup();
- if ( popup ) {
- if ( popup->isVisible() ) { // sub menu already open
- int pactItem = popup->actItem;
- popup->actItem = -1;
- popup->hidePopups();
- popup->updateRow( pactItem );
- } else { // open sub menu
- hidePopups();
- popupSubMenuLater( 20, this );
- }
- } else {
- hidePopups();
- }
-}
-
-void PopupMenu::mouseReleaseEvent( QMouseEvent *e )
-{
- // do not hide a standalone context menu on press-release, unless
- // the user moved the mouse significantly
- if ( !parentMenu && !mouseBtDn && actItem < 0 && motion < 6 )
- return;
-
- mouseBtDn = FALSE;
-
- // if the user released the mouse outside the menu, pass control
- // to the menubar or our parent menu
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if ( !rect().contains( e->pos() ) && tryMenuBar(e) )
- return;
- else if((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && e->pos().y() <= sh) || //up
- (d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- e->pos().y() >= contentsRect().height() - sh)) //down
- return;
-
- if ( actItem < 0 ) { // we do not have an active item
- // if the release is inside without motion (happens with
- // oversized popup menus on small screens), ignore it
- if ( rect().contains( e->pos() ) && motion < 6 )
- return;
- else
- byeMenuBar();
- } else { // selected menu item!
- register QMenuItem *mi = mitems->at(actItem);
- if ( mi ->widget() ) {
- QWidget* widgetAt = QApplication::widgetAt( e->globalPos(), TRUE );
- if ( widgetAt && widgetAt != this ) {
- QMouseEvent me( e->type(), widgetAt->mapFromGlobal( e->globalPos() ),
- e->globalPos(), e->button(), e->state() );
- QApplication::sendEvent( widgetAt, &me );
- }
- }
- PopupMenu *popup = mi->popup();
-#ifndef QT_NO_WHATSTHIS
- bool b = QWhatsThis::inWhatsThisMode();
-#else
- const bool b = FALSE;
-#endif
- if ( !mi->isEnabledAndVisible() ) {
-#ifndef QT_NO_WHATSTHIS
- if ( b ) {
- actItem = -1;
- updateItem( mi->id() );
- byeMenuBar();
- actSig( mi->id(), b);
- }
-#endif
- } else if ( popup ) {
- popup->setFirstItemActive();
- } else { // normal menu item
- byeMenuBar(); // deactivate menu bar
- if ( mi->isEnabledAndVisible() ) {
- actItem = -1;
- updateItem( mi->id() );
- active_popup_menu = this;
- QGuardedPtr<QSignal> signal = mi->signal();
- actSig( mi->id(), b );
- if ( signal && !b )
- signal->activate();
- active_popup_menu = 0;
- }
- }
- }
-}
-
-void PopupMenu::mouseMoveEvent( QMouseEvent *e )
-{
- motion++;
-
- if ( parentMenu && parentMenu->isPopupMenu ) {
- PopupMenu* p = (PopupMenu*)parentMenu;
- int myIndex;
-
- p->findPopup( this, &myIndex );
- QPoint pPos = p->mapFromParent( e->globalPos() );
- if ( p->actItem != myIndex && !p->rect().contains( pPos ) )
- p->setActiveItem( myIndex );
-
- if ( style().styleHint(QStyle::SH_PopupMenu_SloppySubMenus, this )) {
- p->d->mouseMoveBuffer = QRegion();
-#ifdef DEBUG_SLOPPY_SUBMENU
- p->repaint();
-#endif
- }
- }
-
- if ( (e->state() & Qt::MouseButtonMask) == 0 &&
- !hasMouseTracking() )
- return;
-
- if(d->scroll.scrollable && e->pos().x() >= rect().x() && e->pos().x() <= rect().width()) {
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && e->pos().y() <= sh) ||
- (d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown && e->pos().y() >= height()-sh)) {
- if(!d->scroll.scrolltimer) {
- d->scroll.scrolltimer = new QTimer(this, "popup scroll timer");
- QObject::connect( d->scroll.scrolltimer, SIGNAL(timeout()),
- this, SLOT(subScrollTimer()) );
- }
- if(!d->scroll.scrolltimer->isActive())
- d->scroll.scrolltimer->start(40);
- return;
- }
- }
-
- int item = itemAtPos( e->pos() );
- if ( item == -1 ) { // no valid item
- int lastActItem = actItem;
- actItem = -1;
- if ( lastActItem >= 0 )
- updateRow( lastActItem );
- if ( lastActItem > 0 ||
- ( !rect().contains( e->pos() ) && !tryMenuBar( e ) ) ) {
- popupSubMenuLater(style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay,
- this), this);
- }
- } else { // mouse on valid item
- // but did not register mouse press
- if ( (e->state() & Qt::MouseButtonMask) && !mouseBtDn )
- mouseBtDn = TRUE; // so mouseReleaseEvent will pop down
-
- register QMenuItem *mi = mitems->at( item );
-
- if ( mi->widget() ) {
- QWidget* widgetAt = QApplication::widgetAt( e->globalPos(), TRUE );
- if ( widgetAt && widgetAt != this ) {
- QMouseEvent me( e->type(), widgetAt->mapFromGlobal( e->globalPos() ),
- e->globalPos(), e->button(), e->state() );
- QApplication::sendEvent( widgetAt, &me );
- }
- }
-
- if ( actItem == item )
- return;
-
- if ( style().styleHint(QStyle::SH_PopupMenu_SloppySubMenus, this) &&
- d->mouseMoveBuffer.contains( e->pos() ) ) {
- actItem = item;
- popupSubMenuLater( style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this) * 6,
- this );
- return;
- }
-
- if ( mi->popup() || ( popupActive >= 0 && popupActive != item ))
- popupSubMenuLater( style().styleHint(QStyle::SH_PopupMenu_SubMenuPopupDelay, this),
- this );
- else if ( singleSingleShot )
- singleSingleShot->stop();
-
- if ( item != actItem )
- setActiveItem( item );
- }
-}
-
-void PopupMenu::keyPressEvent( QKeyEvent *e )
-{
- QMenuItem *mi = 0;
- PopupMenu *popup;
- int dy = 0;
- bool ok_key = TRUE;
-
- int key = e->key();
- if ( QApplication::reverseLayout() ) {
- // in reverse mode opening and closing keys for submenues are reversed
- if ( key == Key_Left )
- key = Key_Right;
- else if ( key == Key_Right )
- key = Key_Left;
- }
-
- switch ( key ) {
- case Key_Tab:
- // ignore tab, otherwise it will be passed to the menubar
- break;
-
- case Key_Up:
- dy = -1;
- break;
-
- case Key_Down:
- dy = 1;
- break;
-
- case Key_Alt:
- if ( style().styleHint(QStyle::SH_MenuBar_AltKeyNavigation, this) )
- byeMenuBar();
- break;
-
- case Key_Escape:
- if ( tornOff ) {
- close();
- return;
- }
- // just hide one
- {
- QMenuData* p = parentMenu;
- hide();
-#ifndef QT_NO_MENUBAR
- if ( p && p->isMenuBar )
- ((QMenuBar*) p)->goodbye( TRUE );
-#endif
- }
- break;
-
- case Key_Left:
- if ( ncols > 1 && actItem >= 0 ) {
- QRect r( itemGeometry( actItem ) );
- int newActItem = itemAtPos( QPoint( r.left() - 1, r.center().y() ) );
- if ( newActItem >= 0 ) {
- setActiveItem( newActItem );
- break;
- }
- }
- if ( parentMenu && parentMenu->isPopupMenu ) {
- ((PopupMenu *)parentMenu)->hidePopups();
- if ( singleSingleShot )
- singleSingleShot->stop();
- break;
- }
-
- ok_key = FALSE;
- break;
-
- case Key_Right:
- if ( actItem >= 0 && ( mi=mitems->at(actItem) )->isEnabledAndVisible() && (popup=mi->popup()) ) {
- hidePopups();
- if ( singleSingleShot )
- singleSingleShot->stop();
- // ### The next two lines were switched to fix the problem with the first item of the
- // submenu not being highlighted...any reason why they should have been the other way??
- subMenuTimer();
- popup->setFirstItemActive();
- break;
- } else if ( actItem == -1 && ( parentMenu && !parentMenu->isMenuBar )) {
- dy = 1;
- break;
- }
- if ( ncols > 1 && actItem >= 0 ) {
- QRect r( itemGeometry( actItem ) );
- int newActItem = itemAtPos( QPoint( r.right() + 1, r.center().y() ) );
- if ( newActItem >= 0 ) {
- setActiveItem( newActItem );
- break;
- }
- }
- ok_key = FALSE;
- break;
-
- case Key_Space:
- if (! style().styleHint(QStyle::SH_PopupMenu_SpaceActivatesItem, this))
- break;
- // for motif, fall through
-
- case Key_Return:
- case Key_Enter:
- {
- if ( actItem < 0 )
- break;
-#ifndef QT_NO_WHATSTHIS
- bool b = QWhatsThis::inWhatsThisMode();
-#else
- const bool b = FALSE;
-#endif
- mi = mitems->at( actItem );
- if ( !mi->isEnabled() && !b )
- break;
- popup = mi->popup();
- if ( popup ) {
- hidePopups();
- popupSubMenuLater( 20, this );
- popup->setFirstItemActive();
- } else {
- actItem = -1;
- updateItem( mi->id() );
- byeMenuBar();
- if ( mi->isEnabledAndVisible() || b ) {
- active_popup_menu = this;
- QGuardedPtr<QSignal> signal = mi->signal();
- actSig( mi->id(), b );
- if ( signal && !b )
- signal->activate();
- active_popup_menu = 0;
- }
- }
- }
- break;
-#ifndef QT_NO_WHATSTHIS
- case Key_F1:
- if ( actItem < 0 || e->state() != ShiftButton)
- break;
- mi = mitems->at( actItem );
- if ( !mi->whatsThis().isNull() ){
- if ( !QWhatsThis::inWhatsThisMode() )
- QWhatsThis::enterWhatsThisMode();
- QRect r( itemGeometry( actItem) );
- QWhatsThis::leaveWhatsThisMode( mi->whatsThis(), mapToGlobal( r.bottomLeft()) );
- }
- //fall-through!
-#endif
- default:
- ok_key = FALSE;
-
- }
- if ( !ok_key &&
- ( !e->state() || e->state() == AltButton || e->state() == ShiftButton ) &&
- e->text().length()==1 ) {
- QChar c = e->text()[0].upper();
-
- QMenuItemListIt it(*mitems);
- QMenuItem* first = 0;
- QMenuItem* currentSelected = 0;
- QMenuItem* firstAfterCurrent = 0;
-
- register QMenuItem *m;
- mi = 0;
- int indx = 0;
- int clashCount = 0;
- while ( (m=it.current()) ) {
- ++it;
- QString s = m->text();
- if ( !s.isEmpty() ) {
- int i = s.find( '&' );
- while ( i >= 0 && i < (int)s.length() - 1 ) {
- if ( s[i+1].upper() == c ) {
- ok_key = TRUE;
- clashCount++;
- if ( !first )
- first = m;
- if ( indx == actItem )
- currentSelected = m;
- else if ( !firstAfterCurrent && currentSelected )
- firstAfterCurrent = m;
- break;
- } else if ( s[i+1] == '&' ) {
- i = s.find( '&', i+2 );
- } else {
- break;
- }
- }
- }
- if ( mi )
- break;
- indx++;
- }
-
- if ( 1 == clashCount ) { // No clashes, continue with selection
- mi = first;
- popup = mi->popup();
- if ( popup ) {
- setActiveItem( indexOf(mi->id()) );
- hidePopups();
- popupSubMenuLater( 20, this );
- popup->setFirstItemActive();
- } else {
- byeMenuBar();
-#ifndef QT_NO_WHATSTHIS
- bool b = QWhatsThis::inWhatsThisMode();
-#else
- const bool b = FALSE;
-#endif
- if ( mi->isEnabledAndVisible() || b ) {
- active_popup_menu = this;
- QGuardedPtr<QSignal> signal = mi->signal();
- actSig( mi->id(), b );
- if ( signal && !b )
- signal->activate();
- active_popup_menu = 0;
- }
- }
- } else if ( clashCount > 1 ) { // Clashes, highlight next...
- // If there's clashes and no one is selected, use first one
- // or if there is no clashes _after_ current, use first one
- if ( !currentSelected || (currentSelected && !firstAfterCurrent))
- dy = indexOf( first->id() ) - actItem;
- else
- dy = indexOf( firstAfterCurrent->id() ) - actItem;
- }
- }
-#ifndef QT_NO_MENUBAR
- if ( !ok_key ) { // send to menu bar
- register QMenuData *top = this; // find top level
- while ( top->parentMenu )
- top = top->parentMenu;
- if ( top->isMenuBar ) {
- int beforeId = top->actItem;
- ((QMenuBar*)top)->tryKeyEvent( this, e );
- if ( beforeId != top->actItem )
- ok_key = TRUE;
- }
- }
-#endif
- if ( actItem < 0 ) {
- if ( dy > 0 ) {
- setFirstItemActive();
- } else if ( dy < 0 ) {
- QMenuItemListIt it(*mitems);
- it.toLast();
- register QMenuItem *mi;
- int ai = count() - 1;
- while ( (mi=it.current()) ) {
- --it;
- if ( !mi->isSeparator() && mi->id() != QMenuData::d->aInt ) {
- setActiveItem( ai );
- return;
- }
- ai--;
- }
- actItem = -1;
- }
- return;
- }
-
- if ( dy ) { // highlight next/prev
- register int i = actItem;
- int c = mitems->count();
- for(int n = c; n; n--) {
- i = i + dy;
- if(d->scroll.scrollable) {
- if(d->scroll.scrolltimer)
- d->scroll.scrolltimer->stop();
- if(i < 0)
- i = 0;
- else if(i >= c)
- i = c - 1;
- } else {
- if ( i == c )
- i = 0;
- else if ( i < 0 )
- i = c - 1;
- }
- mi = mitems->at( i );
- if ( !mi || !mi->isVisible() )
- continue;
-
- if ( !mi->isSeparator() &&
- ( style().styleHint(QStyle::SH_PopupMenu_AllowActiveAndDisabled, this)
- || mi->isEnabledAndVisible() ) )
- break;
- }
- if ( i != actItem )
- setActiveItem( i );
- if(d->scroll.scrollable) { //need to scroll to make it visible?
- QRect r = itemGeometry(actItem);
- if(r.isNull() || r.height() < itemHeight(mitems->at(actItem))) {
- bool refresh = FALSE;
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && dy == -1) { //up
- if(d->scroll.topScrollableIndex >= 0) {
- d->scroll.topScrollableIndex--;
- refresh = TRUE;
- }
- } else if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown) { //down
- QMenuItemListIt it(*mitems);
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- for(int i = 0, y = ((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp) ? sh : 0); it.current(); i++, ++it) {
- if(i >= d->scroll.topScrollableIndex) {
- int itemh = itemHeight(it.current());
- QSize sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemh),
- QStyleOption(it.current(),maxPMWidth,0));
- y += sz.height();
- if(y > (contentsRect().height()-sh)) {
- if(sz.height() > sh || !it.atLast())
- d->scroll.topScrollableIndex++;
- refresh = TRUE;
- break;
- }
- }
- }
- }
- if(refresh) {
- updateScrollerState();
- update();
- }
- }
- }
- }
-
-#ifdef Q_OS_WIN32
- if ( !ok_key &&
- !( e->key() == Key_Control || e->key() == Key_Shift || e->key() == Key_Meta ) )
- qApp->beep();
-#endif // Q_OS_WIN32
-}
-
-void PopupMenu::timerEvent( QTimerEvent *e )
-{
- QFrame::timerEvent( e );
-}
-
-void PopupMenu::leaveEvent( QEvent * )
-{
- if ( testWFlags( WStyle_Tool ) && style().styleHint(QStyle::SH_PopupMenu_MouseTracking, this) ) {
- int lastActItem = actItem;
- actItem = -1;
- if ( lastActItem >= 0 )
- updateRow( lastActItem );
- }
-}
-
-void PopupMenu::styleChange( QStyle& old )
-{
- QFrame::styleChange( old );
- setMouseTracking(style().styleHint(QStyle::SH_PopupMenu_MouseTracking, this));
- style().polishPopupMenu( this );
- updateSize(TRUE);
-}
-
-void PopupMenu::enabledChange( bool )
-{
- if ( QMenuData::d->aWidget ) // torn-off menu
- QMenuData::d->aWidget->setEnabled( isEnabled() );
-}
-
-int PopupMenu::columns() const
-{
- return ncols;
-}
-
-// This private slot handles the scrolling popupmenu
-void PopupMenu::subScrollTimer() {
- QPoint pos = QCursor::pos();
- if(!d->scroll.scrollable || !isVisible()) {
- if(d->scroll.scrolltimer)
- d->scroll.scrolltimer->stop();
- return;
- } else if(pos.x() > x() + width() || pos.x() < x()) {
- return;
- }
- int sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if(!d->scroll.lastScroll.isValid()) {
- d->scroll.lastScroll = QTime::currentTime();
- } else {
- int factor=0;
- if(pos.y() < y())
- factor = y() - pos.y();
- else if(pos.y() > y() + height())
- factor = pos.y() - (y() + height());
- int msecs = 250 - ((factor / 10) * 40);
- if(d->scroll.lastScroll.msecsTo(QTime::currentTime()) < QMAX(0, msecs))
- return;
- d->scroll.lastScroll = QTime::currentTime();
- }
- if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp && pos.y() <= y() + sh) { //up
- if(d->scroll.topScrollableIndex > 0) {
- d->scroll.topScrollableIndex--;
- updateScrollerState();
- update(contentsRect());
- }
- } else if(d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollDown &&
- pos.y() >= (y() + contentsRect().height()) - sh) { //down
- QMenuItemListIt it(*mitems);
- for(int i = 0, y = contentsRect().y() + sh; it.current(); i++, ++it) {
- if(i >= d->scroll.topScrollableIndex) {
- int itemh = itemHeight(it.current());
- QSize sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this, QSize(0, itemh),
- QStyleOption(it.current(),maxPMWidth,0));
- y += sz.height();
- if(y > contentsRect().height() - sh) {
- d->scroll.topScrollableIndex++;
- updateScrollerState();
- update(contentsRect());
- break;
- }
- }
- }
- }
-}
-
-// This private slot handles the delayed submenu effects
-
-void PopupMenu::subMenuTimer() {
-
- if ( !isVisible() || (actItem < 0 && popupActive < 0) || actItem == popupActive )
- return;
-
- if ( popupActive >= 0 ) {
- hidePopups();
- popupActive = -1;
- }
-
- // hidePopups() may change actItem etc.
- if ( !isVisible() || actItem < 0 || actItem == popupActive )
- return;
-
- QMenuItem *mi = mitems->at(actItem);
- if ( !mi || !mi->isEnabledAndVisible() )
- return;
-
- PopupMenu *popup = mi->popup();
- if ( !popup || !popup->isEnabled() )
- return;
-
- //avoid circularity
- if ( popup->isVisible() )
- return;
-
- Q_ASSERT( popup->parentMenu == 0 );
- popup->parentMenu = this; // set parent menu
-
- emit popup->aboutToShow();
- supressAboutToShow = TRUE;
-
-
- QRect r( itemGeometry( actItem ) );
- QPoint p;
- QSize ps = popup->sizeHint();
- if( QApplication::reverseLayout() ) {
- p = QPoint( r.left() + motifArrowHMargin - ps.width(), r.top() + motifArrowVMargin );
- p = mapToGlobal( p );
-
- bool right = FALSE;
- if ( ( parentMenu && parentMenu->isPopupMenu &&
- ((PopupMenu*)parentMenu)->geometry().x() < geometry().x() ) ||
- p.x() < 0 )
- right = TRUE;
- if ( right && (ps.width() > QApplication::desktop()->width() - mapToGlobal( r.topRight() ).x() ) )
- right = FALSE;
- if ( right )
- p.setX( mapToGlobal( r.topRight() ).x() );
- } else {
- p = QPoint( r.right() - motifArrowHMargin, r.top() + motifArrowVMargin );
- p = mapToGlobal( p );
-
- bool left = FALSE;
- if ( ( parentMenu && parentMenu->isPopupMenu &&
- ((PopupMenu*)parentMenu)->geometry().x() > geometry().x() ) ||
- p.x() + ps.width() > QApplication::desktop()->width() )
- left = TRUE;
- if ( left && (ps.width() > mapToGlobal( r.topLeft() ).x() ) )
- left = FALSE;
- if ( left )
- p.setX( mapToGlobal( r.topLeft() ).x() - ps.width() );
- }
- QRect pr = popup->itemGeometry(popup->count() - 1);
- if (p.y() + ps.height() > QApplication::desktop()->height() &&
- p.y() - ps.height() + (QCOORD) pr.height() >= 0)
- p.setY( p.y() - ps.height() + (QCOORD) pr.height());
-
- if ( style().styleHint(QStyle::SH_PopupMenu_SloppySubMenus, this )) {
- QPoint cur = QCursor::pos();
- if ( r.contains( mapFromGlobal( cur ) ) ) {
- QPoint pts[4];
- pts[0] = QPoint( cur.x(), cur.y() - 2 );
- pts[3] = QPoint( cur.x(), cur.y() + 2 );
- if ( p.x() >= cur.x() ) {
- pts[1] = QPoint( geometry().right(), p.y() );
- pts[2] = QPoint( geometry().right(), p.y() + ps.height() );
- } else {
- pts[1] = QPoint( p.x() + ps.width(), p.y() );
- pts[2] = QPoint( p.x() + ps.width(), p.y() + ps.height() );
- }
- QPointArray points( 4 );
- for( int i = 0; i < 4; i++ )
- points.setPoint( i, mapFromGlobal( pts[i] ) );
- d->mouseMoveBuffer = QRegion( points );
- repaint();
- }
- }
-
- popupActive = actItem;
- popup->popup( p );
-}
-
-void PopupMenu::allowAnimation()
-{
- preventAnimation = FALSE;
-}
-
-void PopupMenu::updateRow( int row )
-{
- if ( !isVisible() )
- return;
-
- if ( badSize ) {
- updateSize();
- update();
- return;
- }
- updateSize();
- QRect r = itemGeometry( row );
- if ( !r.isNull() ) // can happen via the scroller
- repaint( r );
-}
-
-int PopupMenu::exec( const QPoint & pos, int indexAtPoint )
-{
- snapToMouse = TRUE;
- if ( !qApp )
- return -1;
-
- PopupMenu* priorSyncMenu = syncMenu;
-
- syncMenu = this;
- syncMenuId = -1;
-
- QGuardedPtr<PopupMenu> that = this;
- connectModal( that, TRUE );
- popup( pos, indexAtPoint );
- qApp->enter_loop();
- connectModal( that, FALSE );
-
- syncMenu = priorSyncMenu;
- return syncMenuId;
-}
-
-
-
-// Connect the popup and all its submenus to modalActivation() if
-// \a doConnect is true, otherwise disconnect.
-void PopupMenu::connectModal( PopupMenu* receiver, bool doConnect )
-{
- if ( !receiver )
- return;
-
- connectModalRecursionSafety = doConnect;
-
- if ( doConnect )
- connect( this, SIGNAL(activated(int)),
- receiver, SLOT(modalActivation(int)) );
- else
- disconnect( this, SIGNAL(activated(int)),
- receiver, SLOT(modalActivation(int)) );
-
- QMenuItemListIt it(*mitems);
- register QMenuItem *mi;
- while ( (mi=it.current()) ) {
- ++it;
- if ( mi->popup() && mi->popup() != receiver
- && (bool)(mi->popup()->connectModalRecursionSafety) != doConnect )
- mi->popup()->connectModal( receiver, doConnect ); //avoid circular
- }
-}
-
-int PopupMenu::exec()
-{
- return exec(mapToGlobal(QPoint(0,0)));
-}
-
-
-// Internal slot used for exec().
-
-void PopupMenu::modalActivation( int id )
-{
- syncMenuId = id;
-}
-
-void PopupMenu::setActiveItem( int i )
-{
- int lastActItem = actItem;
- actItem = i;
- if ( lastActItem >= 0 )
- updateRow( lastActItem );
- if ( i >= 0 && i != lastActItem )
- updateRow( i );
- QMenuItem *mi = mitems->at( actItem );
- if ( !mi )
- return;
-
- if ( mi->widget() && mi->widget()->isFocusEnabled() ) {
- mi->widget()->setFocus();
- } else {
- setFocus();
- QRect mfrect = itemGeometry( actItem );
- setMicroFocusHint( mfrect.x(), mfrect.y(), mfrect.width(), mfrect.height(), FALSE );
- }
- if ( mi->id() != -1 )
- hilitSig( mi->id() );
-#ifndef QT_NO_WHATSTHIS
- if (whatsThisItem && whatsThisItem != mi) {
- qWhatsThisBDH();
- }
- whatsThisItem = mi;
-#endif
-}
-
-QSize PopupMenu::sizeHint() const
-{
- constPolish();
- PopupMenu* that = (PopupMenu*) this;
- //We do not need a resize here, just the sizeHint..
- return that->updateSize(FALSE, FALSE).expandedTo( QApplication::globalStrut() );
-}
-
-int PopupMenu::idAt( const QPoint& pos ) const
-{
- return idAt( itemAtPos( pos ) );
-}
-
-bool PopupMenu::customWhatsThis() const
-{
- return TRUE;
-}
-
-bool PopupMenu::focusNextPrevChild( bool next )
-{
- register QMenuItem *mi;
- int dy = next? 1 : -1;
- if ( dy && actItem < 0 ) {
- setFirstItemActive();
- } else if ( dy ) { // highlight next/prev
- register int i = actItem;
- int c = mitems->count();
- int n = c;
- while ( n-- ) {
- i = i + dy;
- if ( i == c )
- i = 0;
- else if ( i < 0 )
- i = c - 1;
- mi = mitems->at( i );
- if ( mi && !mi->isSeparator() &&
- ( ( style().styleHint(QStyle::SH_PopupMenu_AllowActiveAndDisabled, this)
- && mi->isVisible() )
- || mi->isEnabledAndVisible() ) )
- break;
- }
- if ( i != actItem )
- setActiveItem( i );
- }
- return TRUE;
-}
-
-void PopupMenu::focusInEvent( QFocusEvent * )
-{
-}
-
-void PopupMenu::focusOutEvent( QFocusEvent * )
-{
-}
-
-class QTearOffMenuItem : public QCustomMenuItem
-{
-public:
- QTearOffMenuItem()
- {
- }
- ~QTearOffMenuItem()
- {
- }
- void paint( QPainter* p, const QColorGroup& cg, bool,
- bool, int x, int y, int w, int h )
- {
- p->setPen( QPen( cg.dark(), 1, DashLine ) );
- p->drawLine( x+2, y+h/2-1, x+w-4, y+h/2-1 );
- p->setPen( QPen( cg.light(), 1, DashLine ) );
- p->drawLine( x+2, y+h/2, x+w-4, y+h/2 );
- }
- bool fullSpan() const
- {
- return TRUE;
- }
-
- QSize sizeHint()
- {
- return QSize( 20, 6 );
- }
-};
-
-int PopupMenu::insertTearOffHandle( int id, int index )
-{
- int myid = insertItem( new QTearOffMenuItem, id, index );
- connectItem( myid, this, SLOT( toggleTearOff() ) );
- QMenuData::d->aInt = myid;
- return myid;
-}
+//======================
+// PopupView
+//======================
-void PopupMenu::toggleTearOff()
+PopupView::PopupView(QWidget* parent)
+ : QColumnView(parent)
{
- if ( active_popup_menu && active_popup_menu->tornOff ) {
- active_popup_menu->close();
- } else if (QMenuData::d->aWidget ) {
- delete (QWidget*) QMenuData::d->aWidget; // delete the old one
- } else {
- // create a tear off menu
- PopupMenu* p = new PopupMenu( parentWidget(), "tear off menu" );
- connect( p, SIGNAL( activated(int) ), this, SIGNAL( activated(int) ) );
- connect( p, SIGNAL( highlighted(int) ), this, SIGNAL( highlighted(int) ) );
-#ifndef QT_NO_WIDGET_TOPEXTRA
- p->setCaption( caption() );
-#endif
- p->setCheckable( isCheckable() );
- p->reparent( parentWidget(), WType_TopLevel | WStyle_Tool |
- WNoAutoErase | WDestructiveClose,
- geometry().topLeft(), FALSE );
- p->mitems->setAutoDelete( FALSE );
- p->tornOff = TRUE;
- for ( QMenuItemListIt it( *mitems ); it.current(); ++it ) {
- if ( it.current()->id() != QMenuData::d->aInt && !it.current()->widget() )
- p->mitems->append( it.current() );
- }
- p->show();
- QMenuData::d->aWidget = p;
- }
+ _model= new QStandardItemModel(this);
+ // FIXME: After clearing, then re-filling, no items seen.
+ // But if setModel is called FOR THE FIRST TIME after clearing the model,
+ // then it works. Calling setModel any time after that does not work.
+ setModel(_model);
}
-void PopupMenu::activateItemAt( int index )
+PopupView::~PopupView()
{
- if ( index >= 0 && index < (int) mitems->count() ) {
- QMenuItem *mi = mitems->at( index );
- if ( index != actItem ) // new item activated
- setActiveItem( index );
- PopupMenu *popup = mi->popup();
- if ( popup ) {
- if ( popup->isVisible() ) { // sub menu already open
- int pactItem = popup->actItem;
- popup->actItem = -1;
- popup->hidePopups();
- popup->updateRow( pactItem );
- } else { // open sub menu
- hidePopups();
- actItem = index;
- subMenuTimer();
- popup->setFirstItemActive();
- }
- } else {
- byeMenuBar(); // deactivate menu bar
-
-#ifndef QT_NO_WHATSTHIS
- bool b = QWhatsThis::inWhatsThisMode();
-#else
- const bool b = FALSE;
-#endif
- if ( !mi->isEnabledAndVisible() ) {
-#ifndef QT_NO_WHATSTHIS
- if ( b ) {
- actItem = -1;
- updateItem( mi->id() );
- byeMenuBar();
- actSig( mi->id(), b);
- }
-#endif
- } else {
- byeMenuBar(); // deactivate menu bar
- if ( mi->isEnabledAndVisible() ) {
- actItem = -1;
- updateItem( mi->id() );
- active_popup_menu = this;
- QGuardedPtr<QSignal> signal = mi->signal();
- actSig( mi->id(), b );
- if ( signal && !b )
- signal->activate();
- active_popup_menu = 0;
- }
- }
- }
- } else {
- if ( tornOff ) {
- close();
- } else {
- QMenuData* p = parentMenu;
- hide();
-#ifndef QT_NO_MENUBAR
- if ( p && p->isMenuBar )
- ((QMenuBar*) p)->goodbye( TRUE );
-#endif
- }
- }
-
+ // Make sure to clear the popup so that any child popups are also deleted !
+ //popup->clear();
}
-void
-PopupMenu::updateScrollerState()
+void PopupView::clear()
{
- uint old_scrollable = d->scroll.scrollable;
- d->scroll.scrollable = QPopupMenuPrivate::Scroll::ScrollNone;
- if(!style().styleHint(QStyle::SH_PopupMenu_Scrollable, this))
- return;
-
- QMenuItem *mi;
- QMenuItemListIt it( *mitems );
- if(d->scroll.topScrollableIndex) {
- for(int row = 0; (mi = it.current()) && row < d->scroll.topScrollableIndex; row++)
- ++it;
- if(!mi)
- it.toFirst();
- }
- int y = 0, sh = style().pixelMetric(QStyle::PM_PopupMenuScrollerHeight, this);
- if(!it.atFirst()) {
- // can't use |= because of a bug/feature in IBM xlC 5.0.2
- d->scroll.scrollable = d->scroll.scrollable | QPopupMenuPrivate::Scroll::ScrollUp;
- y += sh;
- }
- while ( (mi=it.current()) ) {
- ++it;
- int myheight = contentsRect().height();
- QSize sz = style().sizeFromContents(QStyle::CT_PopupMenuItem, this,
- QSize(0, itemHeight( mi )),
- QStyleOption(mi,maxPMWidth));
- if(y + sz.height() >= myheight) {
- d->scroll.scrollable = d->scroll.scrollable | QPopupMenuPrivate::Scroll::ScrollDown;
- break;
- }
- y += sz.height();
- }
- if((d->scroll.scrollable & QPopupMenuPrivate::Scroll::ScrollUp) &&
- !(old_scrollable & QPopupMenuPrivate::Scroll::ScrollUp))
- d->scroll.topScrollableIndex++;
+ _model->clear();
}
-
-#endif // QT_NO_POPUPMENU
-
-*/
+*/
+
diff --git a/muse2/muse/widgets/popupmenu.h b/muse2/muse/widgets/popupmenu.h
index bea30f1d..c06d51f4 100644
--- a/muse2/muse/widgets/popupmenu.h
+++ b/muse2/muse/widgets/popupmenu.h
@@ -5,299 +5,55 @@
//
// (C) Copyright 1999-2010 Werner Schweer (ws@seh.de)
//
-// PopupMenu sub-class of QPopupMenu created by Tim.
+// PopupMenu sub-class of QMenu created by Tim.
//=========================================================
-
-
-//=========================================================
-//
-// NOTICE: This sub-class of QPopupMenu *automatically* deletes
-// and *clears* any sub popup menus, when clear() is called.
-// Therefore a parent widget is *not* necessary when
-// creating sub popup menus to add to the popup.
-//
-//=========================================================
-
-
-
#ifndef __POPUPMENU_H__
#define __POPUPMENU_H__
-#include <q3popupmenu.h>
-//Added by qt3to4:
-#include <QMouseEvent>
-//#include <qmenudata.h>
+#include <QMenu>
+//#include <QMouseEvent>
+//#include <QColumnView>
class QWidget;
class QMouseEvent;
+class QVariant;
+class QAction;
+//class QStandardItemModel;
-//class MenuData : public QMenuData
-//{
- //friend class QMenuBar;
-// friend class QPopupMenu;
-// friend class PopupMenu;
-
-// Q_OBJECT
- //private:
-//};
-
-/*
-// Internal class to get access to protected QMenuData members.
-class MenuData : public QMenuData
+class PopupMenu : public QMenu
{
- friend class QPopupMenu;
- friend class QMenuData;
- friend class PopupMenu;
-
-private:
-
-public:
- MenuData() : QMenuData() { }
- virtual ~MenuData() { }
-};
-*/
-
-//class Q_EXPORT PopupMenu : public QPopupMenu
-class PopupMenu : public Q3PopupMenu
-//class PopupMenu : public QPopupMenu, public MenuData
-{
- friend class QMenuData;
- //friend class QMenuBar;
- friend class Q3PopupMenu;
- friend class QMenuBar;
- //friend class MenuData;
-
Q_OBJECT
- private:
- // QPopupMenu::d is private, so this is our own private.
- //QPopupMenuPrivate *d;
-
- //virtual void setFirstItemActive();
- //void hideAllPopups();
- //void hidePopups();
-/// bool tryMenuBar(QMouseEvent *);
- //bool tryMouseEvent(QPopupMenu *, QMouseEvent *);
-/// bool tryMouseEvent(PopupMenu *, QMouseEvent *);
- //void byeMenuBar();
-/// void actSig(int, bool = FALSE);
-/// virtual void menuDelPopup(Q3PopupMenu *);
protected:
- //int actItem;
-
- //void mousePressEvent(QMouseEvent *);
-/// void mouseReleaseEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
public:
- PopupMenu(QWidget* parent=0, const char* name=0);
+ PopupMenu(QWidget* parent=0);
~PopupMenu();
+ void clear();
+ QAction* findActionFromData(QVariant);
};
-#endif
-
-
-
-
-/****************************************************************************
-**
-** Definition of QPopupMenu class
-**
-** Created : 941128
-**
-** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
-**
-** This file is part of the widgets module of the Qt GUI Toolkit.
-**
-** This file may be used under the terms of the GNU General
-** Public License versions 2.0 or 3.0 as published by the Free
-** Software Foundation and appearing in the files LICENSE.GPL2
-** and LICENSE.GPL3 included in the packaging of this file.
-** Alternatively you may (at your option) use any later version
-** of the GNU General Public License if such license has been
-** publicly approved by Trolltech ASA (or its successors, if any)
-** and the KDE Free Qt Foundation.
-**
-** 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.
-**
-** This file may be used under the terms of the Q Public License as
-** defined by Trolltech ASA and appearing in the file LICENSE.QPL
-** included in the packaging of this file. Licensees holding valid Qt
-** Commercial licenses may use this file in accordance with the Qt
-** Commercial License Agreement provided with the Software.
-**
-** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
-** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
-** herein.
-**
-**********************************************************************/
/*
-#ifndef __POPUPMENU_H__
-#define __POPUPMENU_H__
-
-#ifndef QT_H
-#include <qframe.h>
-#include <qmenudata.h>
-#endif // QT_H
-
-#ifndef QT_NO_POPUPMENU
-class QPopupMenuPrivate;
-
-class Q_EXPORT PopupMenu : public QFrame, public QMenuData
+class PopupView : public QColumnView
{
- Q_OBJECT
- Q_PROPERTY( bool checkable READ isCheckable WRITE setCheckable )
-public:
- PopupMenu( QWidget* parent=0, const char* name=0 );
- ~PopupMenu();
-
- void popup( const QPoint & pos, int indexAtPoint = -1 ); // open
- void updateItem( int id );
-
- virtual void setCheckable( bool );
- bool isCheckable() const;
-
- void setFont( const QFont & );
- void show();
- void hide();
-
- int exec();
- int exec( const QPoint & pos, int indexAtPoint = 0 ); // modal
-
- virtual void setActiveItem( int );
- QSize sizeHint() const;
-
- int idAt( int index ) const { return QMenuData::idAt( index ); }
- int idAt( const QPoint& pos ) const;
-
- bool customWhatsThis() const;
-
- int insertTearOffHandle( int id=-1, int index=-1 );
-
- void activateItemAt( int index );
- QRect itemGeometry( int index );
-
-
-signals:
- void activated( int itemId );
- void highlighted( int itemId );
- void activatedRedirect( int itemId ); // to parent menu
- void highlightedRedirect( int itemId );
- void aboutToShow();
- void aboutToHide();
-
-protected:
- int itemHeight( int ) const;
- int itemHeight( QMenuItem* mi ) const;
- void drawItem( QPainter* p, int tab, QMenuItem* mi,
- bool act, int x, int y, int w, int h);
-
- void drawContents( QPainter * );
-
- void closeEvent( QCloseEvent *e );
- void paintEvent( QPaintEvent * );
- void mousePressEvent( QMouseEvent * );
- void mouseReleaseEvent( QMouseEvent * );
- void mouseMoveEvent( QMouseEvent * );
- void keyPressEvent( QKeyEvent * );
- void focusInEvent( QFocusEvent * );
- void focusOutEvent( QFocusEvent * );
- void timerEvent( QTimerEvent * );
- void leaveEvent( QEvent * );
- void styleChange( QStyle& );
- void enabledChange( bool );
- int columns() const;
-
- bool focusNextPrevChild( bool next );
-
- int itemAtPos( const QPoint &, bool ignoreSeparator = TRUE ) const;
-
-private slots:
- void subActivated( int itemId );
- void subHighlighted( int itemId );
-#ifndef QT_NO_ACCEL
- void accelActivated( int itemId );
- void accelDestroyed();
-#endif
- void popupDestroyed( QObject* );
- void modalActivation( int );
-
- void subMenuTimer();
- void subScrollTimer();
- void allowAnimation();
- void toggleTearOff();
-
- void performDelayedChanges();
-
-private:
- void updateScrollerState();
- void menuContentsChanged();
- void menuStateChanged();
- void performDelayedContentsChanged();
- void performDelayedStateChanged();
- void menuInsPopup( PopupMenu * );
- void menuDelPopup( PopupMenu * );
- void frameChanged();
-
- void actSig( int, bool = FALSE );
- void hilitSig( int );
- virtual void setFirstItemActive();
- void hideAllPopups();
- void hidePopups();
- bool tryMenuBar( QMouseEvent * );
- void byeMenuBar();
-
- QSize updateSize(bool force_recalc=FALSE, bool do_resize=TRUE);
- void updateRow( int row );
-#ifndef QT_NO_ACCEL
- void updateAccel( QWidget * );
- void enableAccel( bool );
-#endif
- QPopupMenuPrivate *d;
-#ifndef QT_NO_ACCEL
- QAccel *autoaccel;
-#endif
-
-#if defined(Q_WS_MAC) && !defined(QMAC_QMENUBAR_NO_NATIVE)
- bool macPopupMenu(const QPoint &, int);
- uint mac_dirty_popup : 1;
-#endif
-
- int popupActive;
- int tab;
- uint accelDisabled : 1;
- uint checkable : 1;
- uint connectModalRecursionSafety : 1;
- uint tornOff : 1;
- uint pendingDelayedContentsChanges : 1;
- uint pendingDelayedStateChanges : 1;
- int maxPMWidth;
- int ncols;
- bool snapToMouse;
- bool tryMouseEvent( PopupMenu *, QMouseEvent * );
-
- friend class QMenuData;
- friend class QMenuBar;
-
- void connectModal(PopupMenu* receiver, bool doConnect);
-
-private: // Disabled copy constructor and operator=
-#if defined(Q_DISABLE_COPY)
- PopupMenu( const PopupMenu & );
- PopupMenu &operator=( const PopupMenu & );
-#endif
+ Q_OBJECT
+ private:
+ QStandardItemModel* _model;
+
+ protected:
+
+ public:
+ PopupView(QWidget* parent=0);
+ ~PopupView();
+
+ void clear();
+ QStandardItemModel* model() { return _model; }
};
+*/
-#endif // QT_NO_POPUPMENU
+#endif
-#endif // QPOPUPMENU_H
-*/ \ No newline at end of file