Can I decide where a Qaction is added to a Qmenubar - qt

I need to add a QAction directly into a QMenuBar (not an QAction inside a QMenu but a QAction directly in the QMenuBar) I am able to do this with the following command.
ui->menuBar->addAction("VFTP",this, SLOT(VFTPmenuTrigger()) );
My only problem is that when I add it, it is appended to the end of the menu bar that I have built in Qt designer. I would like to be able to put it somewhere in the middle. Seems the only way I could do this is if I generate the menu bar by coding it only. Is there a way to build most of my menuBar in Qt Designer and then add that Qaction in the menu bar where I want? I hope I am clear and I added the QAction programmatically because it is not possible to do so with Qt (I know it sounds countintuitive to put a QAction directly in the menu bar but this is what the customer wants)

If you look at QMenuBar code you'll that it does this:
QAction *QMenuBar::addAction(const QString &text, const QObject *receiver, const char* member)
{
QAction *ret = new QAction(text, this);
QObject::connect(ret, SIGNAL(triggered(bool)), receiver, member);
addAction(ret);
return ret;
}
which basically uses QWidget::addAction(). So it stands to reason that you can use QWidget::insertAction() yourself to do the same thing. insertAction() lets you specify before what QAction you want to add.

Related

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);

How to programmatically close QMenu

I have pretty specific situation. I want to place a QAction into QToolbar and reach following behaviour:
Checkable QAction with icon.
Classic arrow on the right side which is used for showing menu
By pressing this arrow my QDialog should appears on screen instead of QMenu-like one
Now I'm a bit confused with implementing all this things together.
For now I've created QAction added it to toolbar and also created an empty QMenubecause I didn't get the idea of how to add the "dropdown" arrow another way.
So, I also connected my slot to QMenu aboutToShow() signal and now, I can create my dialog and exec() it just before QMenu shows. But here's the main problem appears: after I did everything with my dialog an click OK button QMenu trying to appear, but as it is empty it shows nothing and further actions become available only after I left-click somwhere to "close" this menu.
Is there any way to force QMenu not to show or can inherit from QMenu and reimplemnt its behaviour (I've tried to do such trick with exec() show() popup() methods of QMenu after subclassing from it, but none of them are being called when menu appears on the screen) ?
Here's the solution, which worked for me.
class QCustomMenu : public QMenu
{
Q_OBJECT
public:
QCustomMenu(QObject *parent = 0):QMenu(parent){};
};
In code:
QAction* myActionWithMenu = new QAction ( "ActionText", toolbar);
QCustomMenu* myMenu = new QCustomMenu(toolbar);
connect(myMenu, SIGNAL(aboutToShow()), this, SLOT(execMyMenu()));
execMyMenu() implementation:
void execMyMenu(){
m_activeMenu = (QCustomMenu*)sender(); // m_activeMenu -- private member of your head class, needs to point to active custom menu
QMyDialog* dlg = new QMyDialog();
// setup your dialog with needed information
dlg->exec();
// handle return information
m_myTimer = startTimer(10); // m_myTimer -- private member of your head(MainWindow or smth like that) class
}
Now we have to handle timerEvent and close our menu:
void MyHeadClass::timerEvent(QTimerEvent *event)
{
// Check if it is our "empty"-menu timer
if ( event->timerId()==m_myTimer )
{
m_activeMenu->close(); // closing empty menu
killTimer(m_myTimer); // deactivating timer
m_myTimer = 0; // seting timer identifier to zero
m_activeMenu = NULL; // as well as active menu pointer to NULL
}
}
It works great on every platform and does what I wanted.
Hope, this would help someone. I've spent week trying to find this solution.

QMenu exec to return on a QMenu click (instead of QAction)

I am building a menu and I would like to be able to click both on QAction and QMenu items.
When running exec, nothing happens if I click on a QMenu.
Even if I added an action to the QMenu.
Is there a way to do this?
Here is what I tried:
QMenu* menu = new QMenu( "xxx", topMenu );
QAction* action = menu->menuAction();
topMenu->addAction( action );
EDIT:
I do not know why exec() makes it different, but to walk-around it you can create subclass of QMenu to be your topMenu so that it handles mouse release event manually like this:
void CustomMenu::mouseReleaseEvent(QMouseEvent *event) {
QAction *const actionAtEvent = actionAt(event->pos());
if (actionAtEvent)
actionAtEvent->trigger();
QMenu::mouseReleaseEvent(event);
}
Original, not helpfull answer:
It might help you to use QMenu::menuAction() to get associated QAction and connect it's signals.

How to put pushbutton inside the QMenu or QAction control?

I need to put a QPushButton inside a QMenu. Is it possible and, if so, then how?
I want to achieve something like this:
QWidgetAction is what you are looking for. This is what is on qt docs
The QWidgetAction class extends QAction by an interface for inserting custom widgets into action based containers
So basically it gives a custom UI to QAction according to what QWidget you pass to it.
I have used QWidgetAction to show checkbox as QMenu items.
QCheckBox *chkBox = new QCheckBox(menu);
chkBox ->setText("MyCheckBox");
QWidgetAction *chkBoxAction= new QWidgetAction(menu);
chkBoxAction->setDefaultWidget(chkBox);
menu->addAction(chkBoxAction);
You can then handle signals from checkbox accordingly.
If you only want a menu item to have a state, you may use Checkable property of QAction:
rotateAct = new QAction(QIcon(":/images/Mouse/Rotate.png"), tr("&Rotate"), this);
rotateAct->setCheckable(true);

How can I add another tab that looks exactly like the first one (like in a browser)?

I have a browser made in Qt and a I have a tabwidget with one tab (which has a label, lineedit and a webview). I want to add others that look like the first one (have label, lineedit and webview).
How can I do this?
I don't know of any way to "clone" or duplicate an existing tab or widget, so I believe you'll need to code the tab contents yourself (i.e. not through the designer).
If all you need are a QLabel, a QLineEdit and a QWebView, that's not very complex. The idea would be to:
create a custom widget (inheriting from QWidget directly, or from QFrame)
lay out the contained widgets in the fashion you want in its constructor
add as many tabs as you want, when you want them, via the QTabWidget.addTab function.
The Tab Dialog example has everything you need - it's actually more complex than what you need because it uses different widgets for each tab. You can get away with a single widget.
If you wonder how to do the layout, and you're satisfied with what you got from the designer, you can inspect the generated (.moc) files. You'll see what layouts it uses, and you can replicate that in your own code.
Skeleton widget:
class BrowserTab : public QWidet
{
Q_OBJECT
public:
BrowserTab(QUrl const& home, QWidget *parent = 0);
void setUrl(QUrl const& url);
private:
QWebView *web;
QLabel *title;
QLineEdit *urlEdit;
};
BrowserTab::BrowserTab(QUrl const& home, QWidget *parent)
: QWidget(parent)
{
urlEdit = new QLineEdit(this);
title = new QLabel(this);
web = new QWebView(this);
QVBoxLayout *vl = new QVBoxLayout;
vl->addLayout(title);
vl->addLayout(urlEdit);
vl->addLayout(web);
setLayout(vl);
setUrl(home);
}
void BrowserTab::setUrl(QUrl const& url)
{
web->load(url);
// update label & urlEdit here
}
You'll need to do a bit more to make it a proper browser (setUrl should probably be a slot too), but this should get you started.

Resources