Qt - Why add '&' to the string? - c++

QPushButton *quitButton = new QPushButton("&Quit");
Why add a & to the Quit? Removing & and it seems the code behaves the same.

The ampersand makes the button respond to a particular key-combination. In your case, if you press ALT + Q it will force the button to be pushed.
From Qt
The QPushButton widget provides a command button.
The push button, or command button, is perhaps the most commonly used widget in any graphical user interface. Push (click) a button to command the computer to perform some action, or to answer a question. Typical buttons are OK, Apply, Cancel, Close, Yes, No and Help.
A command button is rectangular and typically displays a text label describing its action. A shortcut key can be specified by preceding the preferred character with an ampersand in the text. For example:
QPushButton *button = new QPushButton("&Download", this);
In this example the shortcut is Alt+D. See the QShortcut documentation for details (to display an actual ampersand, use '&&').

The ampersand means that the letter 'Q' next to it will be used as a keyboard shortcut.

Related

Qt: How to shift the cursor focus to a field in a Find dialog box/tool once it's shown?

I'm working on a text editor project, and the Find tool currently looks like this when launched:
I'm wondering how I could shift the application/text cursor focus so it goes within the "Find what" field automatically as soon as I show the dialog box (which is of type QDialog).
Currently, as you can see, the text cursor remains within the document, so the user has to manually click on the Find tool to start searching, which is a bit iconvenient. I tried messing around with the setFocus method of my dialog box, but that doesn't seem to help.
To activate the focus in the QDialog do the following:
void MainWindow::on_actionFind_triggered()
{
if(findDialog->isHidden())
{
findDialog->show();
findDialog->activateWindow();
findDialog->raise();
findDialog->setFocus();
}
}
But by default the one that will take the focus will be the QPushButton, so to change that behavior it must be established as a QDialog proxy to the QLineEdit.
lineEdit = new QLineEdit();
setFocusProxy(lineEdit); // <---

Change between Qt4 and Qt5 with conflicting access keys and Shortcut keys

There is a change between QT4 and QT5 when handling Menubar menus access keys and QActions shortcuts that have conflicting key combinations.
In Qt4 when a MenuBar contains a menu with an ampersand like &File it can be opened by tapping on Alt and then tapping F. If a QAction is created using the same hotkey combination like Alt+F then the QAction ‘s signal will be fired if Alt and F are pushed simultaneously or alt is held down and F is pushed.
This is similar functionality to Visual Studios and other MS programs.
In Qt5.4 and Qt5.5 when a MenuBar contains a menu with an ampersand like &File it can be opened by tapping on Alt and then tapping F. If a QAction is created using the same hotkey combination like Alt+F then the QAction ‘s signal will be NOT fired. Instead nothing happens and a warning message is sent to the application output.
QAction::eventFilter: Ambiguous shortcut overload: Alt+F
This issue can be duplicated using a QTcreator example like menus and changing the setshortcut for newAct to Alt+F or another shortkey that is the same as a menubar.
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAct);
void MainWindow::createActions()
{
newAct = new QAction(tr("&New"), this);
newAct->setShortcut(tr("Alt+F")); // This will work in QT4 but not in QT5 and will send a message QAction::eventFilter: Ambiguous shortcut overload: Alt+F
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
My question is what is the correct functionality for windows QT4 or Qt5. If QT5 is correct is there a way to setup Qt so it acts like QT4 instead.
TL;DR: Don't hate your users. Don't do that.
Application-global key shortcuts must be unambiguous. Qt5's behavior is correct. Qt4 failed to detect this, and would let you horribly mislead the user. When a user sees an underline keyboard shortcut for the menu or a menu item, they have every right to believe that the shortcut is application global and won't depend on the context. What you observed in Qt 4 was "allowed", but very bad from usability perspective and had no place in polished, professional applications.
To get the behavior you're after, you must make the action unambiguous: you must remove the shortcut from the menu action. That will work correctly: the menu loses the shortcut, and your application-global shortcut takes over that key sequence.
Alas, I'm very much doubtful that it is a good idea to take over a very common menu shortcut - one that is present in most Windows applications that have menus. If I was your user, I would not like you for taking over Alt-F.

How to prevent closing QMessageBox after clicking a button

I have 3 buttons on QMessageBox added by QMessageBox::addButton() method. Is it possible to prevent closing the message box if a button has been clicked? By default every button closes the window, but I don't want to do it for one button.
One interesting way to approach it that worked for me is to completely disconnect the signals for the target button created, and then re-add the intended functionality. This won't work for everyone, especially if the button isn't created this way and/or you still want to close the dialog correctly. (There might be a way to add it back and/or simulate the behavior with QDialog::accept, QDialog::reject, QDialog::done - haven't tried yet.)
Example:
QMessageBox *msgBox = new QMessageBox(this);
QAbstractButton *doNotCloseButton = msgBox->addButton(tr("This button will not close anything"), QMessageBox::ActionRole);
// Disconnect all events - this will prevent the button from closing the dialog
doNotCloseButton->disconnect();
connect(doNotCloseButton, &QAbstractButton::clicked, this, [=](){ doNotCloseButton->setText("See? Still open!"); });
If you can get a pointer to the QMessageBox widget, you can try to install a QObject::eventFilter on it which filters the QEvent::Close.
Just had the same problem but I wanted to add a checkbox and it kept closing the dialog on clicked even with the ButtonRole set to QMessageBox::ActionRole (tried others too). For this scenario I just called blockSignals(true) on the QCheckBox and now it allows check/uncheck behaviour without closing the dialog. Luckily QCheckBox works fine without signals but assume you want a signal from your button.
They should likely add a new role that doesn't close the dialog as it's a pain to derive a class for simple customizations.
I looked through the addButton() functions overloads, but there is no custom behavior for the buttons you add with this method. They will behave like the standard buttons on a messagebox should.
However if you want to create a fully customizable dialog, then your best option is to extend the QDialog class and use whatever controlls you like on it.
Thanks to #Albert's Answer, I found that this also possible in python:
messagebox = QMessageBox()
button = QPushButton("This button will not close anything")
messagebox.addButton(button, QMessageBox.ButtonRole.NoRole)
button.disconnect()

How to change the default QPushButton in a QDialogBox

My goal is to have two buttons, "Cancel" and "Connect", and to have Cancel be the default button when the user presses ENTER. I also want the user to be able to TAB to the next button ("Connect") and press ENTER and have "Connect" get pushed. Here's my code:
QPushButton * cancelButton = new QPushButton(tr("&Cancel"));
cancelButton->setAutoDefault(true);
cancelButton->setDefault(true);
cancelButton->setFocus();
QPushButton * continueButton = new QPushButton(tr("Co&nnect"));
continueButton->setAutoDefault(true);
continueButton->setDefault(false);
ui->buttonBox->addButton(cancelButton, QDialogButtonBox::RejectRole);
ui->buttonBox->addButton(continueButton, QDialogButtonBox::AcceptRole);
Setting the Cancel button to the the default button doesn't actually seem to work.
Setting the autoDefault property on all the butons seems to be necessary in allow the buttons to get pushed after pressing TAB and ENTER for example. This seems to jive with the documentation for autoDefault. However, the documentation for the default property seems to indicate that the default button will get pushed only if there are no buttons that have the autoDefault property set. Otherwise, the button that gets pushed when ENTER is pressed will be the currently selected autoDefault button. So it seems like what I need to do is to make the cancelButton have focus by default, but I can't seem to figure out how to do this.
You have to call cancelButton->setFocus(); after adding the buttons to the QDialogButtonBox, not before.
Try adding below line before you call dialog->show
button->isEnabled(true)

QMessageBox addButton() using standard icon/display

I'm trying to make our popup messages boxes have more appropriate text, rather than the generic "Ok", "Cancel", etc. However, I don't see an easy way to get the standard icons on the buttons.
For example, normally the QMessageBox::Save button has an icon with it. Instead I want the text to be "Save Part", but since this is still essentially a save operation it'd be nice to have the same icon.
I'd be happy to have this tied to the Role, as all my custom test buttons map to one of the standard roles. Is there any easy way to get the standard icons onto the custom buttons?
If you just want to change the text on the StandardButton but keep the standard icon you can do the following:
QMessageBox *box = new QMessageBox("title", "text", QMessageBox::NoIcon, QMessageBox::Save, QMessageBox::Close, QMessageBox::Open);
box->button(QMessageBox::Save)->setText("Save part");
box->show();
This will result in following:
And the button will keep the same role
Add a button with QMessageBox::addButton to QMessageBox, then call the Button's setIcon with the icon returned by the QStyle::standardIcon you want.