PDA

View Full Version : Dynamic Menu



fruzzo
11th April 2012, 14:38
I am creating a Hierarchical Dynamic Menu, like for a menu bar.
It creates itself according to what is read from a configuration file.
So if for example in my configuration file i have this hierarchical structure:

Vehicles
--4Wheel
----Cars
--2Wheel
----Motorcycles
----Bicycle

My Menu should look like that structure:

Products
Vehicles
--4Wheel
----Cars
--2Wheel
----Motorcycles
----Bicycle

All menu items have to be checkable...

Any good idea how to develop this dynamic menu?

d_stranz
11th April 2012, 16:26
Since you don't know in advance what the menu items will be, then you can't define a unique slot that will get executed when the item is triggered.

In that case, I would make a new QAction instance for every item in the menu, and use the QAction::setData() method to store some kind of value that uniquely identifies each item in the menu tree. Connect all of the QMenu::triggered() signals to the same slot, and in the slot use the QAction pointer and the data value so you can identify which menu item was invoked.

You need to build the menu recursively (this is pseudo-code):



void MyWindow::buildProductMenu( QMenu * parentMenu, MyProductTreeItem * parentItem )
{
QAction * action = new QAction( parentItem->productName(), this );
action->setCheckable( true );
action->setChecked( false );
action->setData( parentItem->productCode() ); // Some unique identifier

parentMenu->addAction( action );
connect( parentMenu, SIGNAL( triggered( QAction * ) ), this, SLOT( productMenuActionTriggered( QAction * ) ) );

if ( parentItem->hasChildren() ) // create sub menus for each child
{
// pseudocode
for each child Item in parentItem
{
QMenu * childMenu = parentMenu->addMenu( childItem->productName() );
buildProductMenu( childMenu, childItem );
}
}
}

void MyWindow::productMenuActionTriggered( QAction * action )
{
QVariant productID = action->data();

// Convert QVariant to whatever it should really be, then use that to look up whatever
// product it refers to. Do something appropriate once you know.
}


Something like that; you'll need to try this and fix whatever I didn't get right. :) At the topmost level, you call buildProductMenu() with the QMenu pointer corresponding to "Products" and the pointer to the root item in your Products data tree.

If your product menu changes during the course of executing the program (that is, the product tree itself is dynamic), then you would need to destroy and rebuild the product menu tree whenever the product tree changes.

fruzzo
12th April 2012, 10:56
First of all...thanks for your aid...your solution seems to work fine, only some open questions:
as you can see from the attached snap, the menu tree has a QMenu and a QAction with the same name (e.g. Wheels_4 or Cars), how can I avoid this problem in order to have only one menu item with a unique name?
About the menu leaf, in your opinion how can I have only the associated QAction instead of the coupe QMenu and a QAction?

7582

Thanks.