Simple ribbon: how to use QActions within QTabBar? - qt

I'm trying to implement simple tabbed interface with Qt5. I use QTabWidget with QToolBars placed inside its tabs and I add QActions to the QToolBars.
That works but causes the following issue: any action remains accessible only while its parent tab is active. If I try to use keyboard shortcut for currently "invisible" action, I will have no success. Since there's no menu etc, the tabs are the only place, where the actions are placed.
Here's how I add the elements to the toolbar:
QTabWidget *ribbon = new QTabWidget(window);
QToolBar *tool_bar_game = new QToolBar(tab_game);
QAction *action_go_to_next_level = new QAction(window);
action_go_to_next_level->setText(QApplication::translate("Window", "&Next", 0));
action_go_to_next_level->setIcon(QIcon::fromTheme("go-last"));
action_go_to_next_level->setShortcut(QApplication::translate("Window", "PgDown", 0));
ribbon->addTab(tool_bar_game, tr("Game"));
tool_bar_game->addAction(action_go_to_next_level);
and a screenshot:
How can I make the action accessible with shortcuts, even when the action's parent tab is not currently opened?

I'm not surprised that this doesn't work, effectively you try to use a shortcut on a hidden widget. It would be very confusing if this worked.
The obvious workaround for this is to add the shortcut instead of to the QAction to a widget that is always active. Personally, I suggest the window.
Without having tested the code, I believe this should work:
QTabWidget *ribbon = new QTabWidget(window);
QToolBar *tool_bar_game = new QToolBar(tab_game);
QAction *action_go_to_next_level = new QAction(window);
action_go_to_next_level->setText(QApplication::translate("Window", "&Next", 0));
action_go_to_next_level->setIcon(QIcon::fromTheme("go-last"));
QShortcut *page_down = new QShortcut(QKeySequence("PgDown"), window);
// trigger the action when the shortcut is activated
QObject::connect(page_down, &QShortcut::activated,
action_go_to_next_level, &QAction::trigger);
ribbon->addTab(tool_bar_game, tr("Game"));
tool_bar_game->addAction(action_go_to_next_level);

Related

Assigning actions to QMenu items

I have created a Qt project in which I'm using a widget and it does not support any menu in the designer's class, so it should be done programmatically. I succeeded in creating the menu and adding the items but I'm struggling in assigning any action for the menu items...
That's what I've done so far:
QMenuBar* menuBar = new QMenuBar();
QMenu *fileMenu = new QMenu("File");
menuBar->addMenu(fileMenu);
fileMenu->addAction("Save");
fileMenu->addAction("Exit");
QAction* newAct = new QAction(tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Exit"));
connect(newAct, &QAction::triggered, this, &MainWindow::on_action_triggered);
this->layout()->setMenuBar(menuBar);
But no action is triggered when I press The Exit item
addAction creates QAction and returns pointer to it, you dont need to create it explicitly, but when you do you must add item to menu with addAction, setting parent is not enough fileMenu->addAction(newAct);.

QMenu - shortcut is not triggered

What is correct way to use QAction shortcuts? I have QTableView with custom context menu where beside other actions I want to have action Refresh F5:
// Popup
QAction *a;
a = mPopup.addAction(IconsManager::icon(fa::refresh), "Refresh", this, &UserPlaylistsSubWidget::refreshList, QKeySequence(Qt::Key_F5));
a->setShortcutVisibleInContextMenu(true);
First, I had to set setShortcutVisibleInContextMenu to make it visible in context menu but action is still not triggered when press F5 (QTableView is active and focused widget). Tried also different values for QAction::setShortcutContext but still no result.
Qt 5.12. Linux (KDE Neon)
Edit: Here is code which rise popup
connect(ui->list, &QWidget::customContextMenuRequested, this, &UserPlaylistsSubWidget::popUp);
void UserPlaylistsSubWidget::popUp(const QPoint &pos)
{
mPopup.popup(ui->list->viewport()->mapToGlobal(pos));
}
Figured it out. Didn't know that QTableView has own actions list and can show it in own popup with setContextMenuPolicy(Qt::ActionsContextMenu). So here is correct solution and F5 shortcut works as expected:
QAction *a = new QAction(IconsManager::icon(fa::refresh), "Refresh", ui->list);
a->setShortcut(QKeySequence(Qt::Key_F5));
a->setShortcutVisibleInContextMenu(true);
connect(a, &QAction::triggered, this, &UserPlaylistsSubWidget::refreshList);
ui->list->addAction(a);

QAction doesn't show QMenu

I'm creating my UI from Qt Designer and it generares this code:
toolBar = new QToolBar(MainWindow);
QIcon icon;
icon.addFile(QStringLiteral(":/main"), QSize(), QIcon::Normal, QIcon::Off);
MainWindow->addToolBar(Qt::TopToolBarArea, toolBar);
actionConvert = new QAction(MainWindow);
actionConvert->setObjectName(QStringLiteral("actionConvert"));
actionConvert->setIcon(icon);
toolBar->addAction(actionConvert);
Now, back in my frame code:
QMenu *menuAdd = new QMenu (this);
menuAdd->addAction (tr("&Files..."));
menuAdd->addAction (tr("&Directory..."));
ui->actionConvert->setMenu (menuAdd);
When I run the application I can see the qaction in the toolbar even the arrow pointing down, which indicates that there is a menu, but when I click it, the menu doesn't appear...any ideas?
There does not seem to be anything wrong with your example code.
It's possible that the reason you aren't seeing the menu is that you need to press and hold the button for a few seconds in order for the menu to appear. A single click will just execute the button's normal action.
See: QToolButton::ToolButtonPopupMode.
You should add menu with menuBar() method as in my case:
void MainWindow::ueInitMenu()
{
this->ueSetCodeRegisterPlacesAction(new QAction(tr("Places"),
this));
this->ueCodeRegisterPlacesAction()->setShortcut(tr("Ctrl+P"));
this->ueCodeRegisterPlacesAction()->setStatusTip(tr("Shows places code register"));
connect(this->ueCodeRegisterPlacesAction(),
SIGNAL(triggered()),
this,
SLOT(ueSlotShowPlacesView()));
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
this->ueCodeRegisterMenu()->addAction(this->ueCodeRegisterPlacesAction());
} // ueInitMenu
especialy the line:
this->ueSetCodeRegisterMenu(this->menuBar()->addMenu(tr("Code register")));
so in your case:
this->menuBar()->addMenu(tr("System menu");
and then add actions. Also take a look at Menus Example.

Qt - Symbian Mobile - Soft key menus not displaying correctly

I create and show a QWebView with soft key options at the bottom. When I click "Options", a menu shows up, but it's tiny, black, and in the upper left hand corner (it should look like the standard blue soft keys and be directly above them). I followed this example.
//create webview
webView = new QWebView;
webView->setUrl(QString(":html/internal.html"));
//create menu
QAction *option1 = new QAction(tr("Back"), webView);
option1->setSoftKeyRole(QAction::PositiveSoftKey);
connect(option1, SIGNAL(triggered()), this, SLOT(deleteView()));
//create right softkey action to launch the "options" menu
QAction *option2 = new QAction(tr("Options"), webView);
option2->setSoftKeyRole(QAction::NegativeSoftKey);
connect(option2, SIGNAL(triggered(), this, SLOT(showMenu()));
QMenu *menuOptions = new QMenu(webView);
menuOptions->addAction(tr("Sub Menu 1"), this, SLOT(aboutView()));
menuOptions->addAction(tr("Sub Menu 2"), this, SLOT(aboutView()));
option2->setMenu(menuOptions);
//add softkey menus
QList < QAction* > softKeys;
softKeys.append(option1);
softKeys.append(option2);
webView->addActions(softKeys);
webView->show();
This example works well on simulator and also in phone. It is included in the QTDIR/examples/widgets folder since Qt 4.6.x

On Qt widgets like DoubleSpinBox or ComboBox, how do i have custom right click menu

I have a few combo-boxes and double spin boxes on my Qt Dialog. Now I need a "ResetToDefault" item on a menu that comes up when you right click on the widget (spin box or combo box).
How do i get it. Is there some way I can have a custom menu that comes up on right click or Is there a way i can add items to the menu that comes on right click.
First, for Qt4, the simplest way is to create an action to reset the data, and add it the the widget using the addAction method (or use the designer). Then, set the contextMenuPolicy attribute to Qt::ActionsContextMenu. The context menu will appear and the action will be triggered.
Code example:
QAction *reset_act = new QAction("Reset to default");
mywidget->addAction(reset_act);
mywidget->setContextMenuPolicy(Qt::ActionsContextMenu);
// here connect the 'triggered' signal to some slot
For Qt3, you might have to intercept the context menu event, and thus inherit the QSpinBox and others. Or maybe you can intercept the context menu event from the main window, detect if it occurred above the widget supposed to have a context menu (using the QWidget::childAt method) and show it there. But you'll have to test.
For Qt4, you can do this for an editable QComboBox by using your own QLineEdit. Create a derived QLineEdit class which implements the contextMenuEvent
class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
MyLineEdit(QWidget* parent = 0) : QLineEdit(parent){}
void contextMenuEvent(QContextMenuEvent *event)
{
QPointer<QMenu> menu = createStandardContextMenu();
//add your actions here
menu->exec(event->globalPos());
delete menu;
}
};
Then, use the setLineEdit function of QComboBox to set the line edit
MyLineEdit* edit = new MyLineEdit();
comboBox->setLineEdit(edit);
The combo box will now use your line edit class. The createStandardContextMenu function creates the normal context menu and you can add any new actions to it that you like in the contextMenuEvent handler before it is shown.
If the QComboBox is not editable then it doesn't have a default context menu so using the Qt::ActionsContextMenu method is much simpler.
QAbstractSpinBox also has a setLineEdit function so you can use a similar technique. Although, for some reason the setLineEdit function is protected on QAbstractSpinBox but public on QLineEdit.

Resources