C++ QT OSX Qt::META+Qt::Key_Tab shortcut bind - c++

I’m trying to bind Qt::META + Qt::Key_Tab shortcut in QTabWidget to switch tabs (like it works in chrome or many other applications).
I have tried every single solution found in google, but this shortcut combination is not working.
I have tried:
Combinations like Qt::Key_Control + Qt::Key_Tab, Qt::Key_Meta + Qt::Key_Tab, QKeySequence(Qt::Key_Meta, Qt::Key_Tab), QKeySequence(Qt::META, Qt::Key_Tab) etc.
QShortcut
QAction
capturing keys using virtual QWidget::event
capturing keys using virtual QWidget::eventFilter with installEventFilter
all relative like keyPressed and etc..
QWidget::event/QWidget::eventFilter catches Shift+Tab, Alt+Tab, but not Ctrl(META)+Tab. When I press Ctrl I see my qDebug output, when I press Ctrl + Tab nothing happens.
Can somebody explain me what is wrong and so special with this particular key combination in QT on OSX?
Doesn't matter what widget, I have created clean GUI project with no other widgets in it - still the same.
Some information:
OSX Mountain Lion 10.8.5
QT 5.2
BTW, In Qt Creator I’m not able to set Ctrl+Tab shortcut either, thats really ridiculous.
Note: It works great on Windows, it doesn't work on OSX!
I appreciate any help.
Simple code with QAction:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QAction *pAction = new QAction(this);
QKeySequence keySequence = Qt::META + Qt::Key_Tab; // Not working
// or
QKeySequence keySequence = Qt::ALT + Qt::Key_Tab; // Works Alt+Tab
// or
QKeySequence keySequence = QKeySequence(Qt::Key_Meta, Qt::Key_Tab); // Not working
// or
QKeySequence keySequence = QKeySequence(Qt::META, Qt::Key_Tab); // Not working
pAction->setShortcut(keySequence);
connect(pAction, SIGNAL(triggered()), this, SLOT(shortcut_NextTab()));
addAction(pAction);
}
And slot function:
void MainWindow::shortcut_NextTab()
{
qDebug() << "LOL";
}
Expecting to see LOL in Application output, when pressing Ctrl+Tab.

This seems to be a bug in Qt on Cocoa. See QTBUG-8596 and QTBUG-12232. The first bug report has a comment that says that it works if you add the QAction to the menu. I was experiencing the same problem as you, and that solution worked for me.

In this line:
QKeySequence keySequence = Qt::Key_Meta + Qt::Key_Tab;
You are just adding integers. Per QT documentation:
QKeySequence::QKeySequence ( int k1, int k2 = 0, int k3 = 0, int k4 = 0 )
Constructs a key sequence with up to 4 keys k1, k2, k3 and k4.
The key codes are listed in Qt::Key and can be combined with modifiers (see Qt::Modifier) such as Qt::SHIFT, Qt::CTRL, Qt::ALT, or Qt::META.
Meaning:
if you want a sequence, you need to use two-argument constructor to QKeySequence, not just add two integers together (which is what you are doing) and use one-argument constructor.
If you want a modifier - which I assume means holding a key down - use QT::Modifier, not Qt::Key_*.

Related

How can i disable or hide default cancel button in QFileDialog?

I'm trying to use QFileDialog as a widget, to use QFileDialog as a widget the final step for my is to disable the cancel button.
Have you an idea of how can i disable this button.
PS : I am using Qt 5.5.0
You should be able to access the various standard buttons via the QDialogButtonBox and, from there, do what you want with the Cancel button.
The following example code appears to works as expected...
QFileDialog fd;
/*
* Find the QDialogButtonBox.
*/
if (auto *button_box = fd.findChild<QDialogButtonBox *>()) {
/*
* Now find the `Cancel' button...
*/
if (auto *cancel_button = button_box->button(QDialogButtonBox::Cancel)) {
/*
* ...and remove it (or disable it if you prefer).
*/
button_box->removeButton(cancel_button);
}
}
fd.show();
The QFileDialog Class doesn't seem to have any option for this.
However, you could make your own file browser using QTreeModel and QTreeView (It's not too difficult).
There is a tutorial on how to do just that here.
It would take a while to type out all the code (sorry, I'm a slow typer), but this tutorial should allow you to have the flexibility you need to do what you want to do.
I understand that this answer isn't exactly what you asked, but I hope it is a good alternative.
EDIT: Accidentally pasted wrong link for QFileDialog Class

Change the Cut, Copy, Paste shortcut to the custom slots in Qt 5

Currently, I am working on an editor program. I want to assign three shortcut keys (QKeySequence::Cut), (QKeySequence::Copy) and (QKeySequence::Paste) to my customized functions. However, it does not work as my expectation.
For testing, I open the "Application Example" from QtCreator. Then, I try to disable all the shortcut keys as following:
//cutAct->setShortcuts(QKeySequence::Cut);
connect(cutAct, SIGNAL(triggered()), textEdit, SLOT(cut()));
copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
//copyAct->setShortcuts(QKeySequence::Copy);
connect(copyAct, SIGNAL(triggered()), textEdit, SLOT(copy()));
pasteAct = new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
//pasteAct->setShortcuts(QKeySequence::Paste);
Surprisingly, the shortcut keys still working as before.
Another test is that:
connect all the actions to customized slots.
assign all the key sequences to the actions which have already connected to my customized slots.
Then, my result is
Click Cut, Copy, Paste on toolbar go to my customized slots.
The shortcut key works independently with my customized slots.
Any advice are welcome.
Thank you very much.
I have found the way to override the default shortcut, thanks to the code of Sigil.
I use the following code:
Delacre a new action in header:
QShortcut &m_Paste1;
Then, in the constructor of class:
m_Paste1(*(new QShortcut(QKeySequence(QKeySequence::Paste), this, 0, 0, Qt::WidgetShortcut))),
Finally, connect it to your own slot
connect(&m_Paste1, SIGNAL(activated()), this, SLOT(paste()));

QLineEdit editingFinished signal twice when changing focus?

I've found a few similar questions on this but these appear to refer to cases where a message box is used in the slot handler. In my case I am a bit stuck as I am getting the editFinished signal twice even when my slot handler is doing nothing.
For a test, I have an array of QLineEdit which use a signalMapper to connect the editingFinished() signals to a single slot. The signalMapper passes the array index so I can see where the signal came from.
eg:
testenter::testenter(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::testenter)
{
// setup the UI according to the .h file
ui->setupUi(this);
signalMapper = new QSignalMapper(this);
// init the labels and edit boxes
for (int i = 0; i < 10; i++)
{
pm_label[i] = new QLabel(ui->scrollArea);
QString text = QString("Number %1").arg(i);
pm_label[i]->setText(text);
pm_label[i]->setGeometry(10,20+i*30, 50, 20);
pm_label[i]->show();
pm_editBox[i] = new QLineEdit(ui->scrollArea);
pm_editBox[i]->setGeometry(80,20+i*30, 50, 20);
pm_editBox[i]->show();
signalMapper->setMapping(pm_editBox[i], int(i));
connect(pm_editBox[i], SIGNAL(editingFinished()), signalMapper, SLOT(map()));
}
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(data_entry(int)));
}
void testenter::data_entry(int entry)
{
//dummy
}
When run in the debugger, if I enter data into one box then either hit return or select another box with the mouse (ie change focus) , then it calls data_entry twice, the first time with index of the box that is losing focus and the 2nd time with the box which gets the focus.
So my question: Am I missing something? Is this expected behaviour or a bug?
If a bug, anyone know a way round it as I wanted to use this signal to do custom validation on data when it is entered (by either return, tab or mouse click to change focus).
First off, no this isn't expected behavior, i.e. selecting a QLineEdit should not cause it's editingFinished signal to be emitted.
There are a couple of possible things that may cause this problem:
You've accidentally connected a signal twice to a slot
The slot map() is causing the newly selected box to lose focus
In the same vain, if you're debugging and using a break point to detect when the slots are getting called you may be causing the QLineEdit to lose focus when the active application changes from your QWidget to your debugger, again causing the signal to be sent again.
If you're having problems because of a doubly connected slot, which doesn't seem to be the case because you're specifically getting a signal from two different QLineEdits, you can make sure that this isn't happening by specifying the connection type, the connect method actually has an additional optional argument at the end which allows you to change the type from a DefaultConnection to a UniqueConnection.
That being said, data validation is something that Qt has an established mechanism for, and I suggest that you use it if possible, look into extending the QValidator abstract base class Ref Doc. You then tell each of your QLineEdit's to use the same validator.
I have run into the same issue. It really does emit the signal twice, which is a known bug: https://bugreports.qt.io/browse/QTBUG-40 which however has not been addressed for a very long time.
Finally I found that the best solution in my case is to change the signal from editingFinished to returnPressed. As a side effect this behaves much more predictably from the user perspective. See also here: http://www.qtforum.org/article/33631/qlineedit-the-signal-editingfinished-is-emitted-twice.html?s=35f85b5f8ea45c828c73b2619f5750ba9c686190#post109943
The OP "found a few similar questions on this but these appear to refer to cases where a message box is used in the slot handler." Well, that is my situation also, and here is where I ended up. So, at the risk of going off topic...
In my situation, when my slot receives the editingFinished signal sent from the QLineEdit, I launch a modal QMessageBox to ask the user something. The appearance of that message box is what triggers the QLineEdit to send the second, undesirable editingFinished signal.
A post in the bug report (https://bugreports.qt.io/browse/QTBUG-40) mentioned by #V.K. offers a workaround which helped me. The following is my implementation of the workaround. I let Qt magic mojo automatically connect the QLineEdit signal to my MainWindow slot.
void MainWindow::on_textbox_editingFinished( void )
{
QLineEdit * pTextbox = qobject_cast<QLineEdit *>( QObject::sender() );
if ( !pTextbox->isModified() )
{
// Ignore undesirable signals.
return;
}
pTextbox->setModified( false );
// Do something with the text.
doSomething( pTextbox->text() );
}
void MainWindow::doSomething( QString const & text )
{
QMessageBox box( this );
box.setStandardButtons( QMessageBox::Yes | QMessageBox::No );
box.setText( "Are you sure you want to change that text value?" );
if ( box.exec() == QMessageBox::Yes )
{
// Store the text.
m_text = text;
}
}

Fullscreen for QDialog from within MainWindow only working sometimes

(Testing with C++ on Qt 4.8 and Ubuntu 12.10 unity)
I've got a main window which displays a QDialog. When I put the Dialog window full-screen it does not seem to always work even though it seems to be a proper window.
Meaning, the window can appear full-screen, though only sometimes.
Anyone got an idea? I know Qt states it might not work for all X environments, but it can't be that bad, can it?
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QDialog* d = new QDialog();
d->setModal(false);
d->show();
qDebug() << d->isWindow();
// works most of the times, though not always:
// d->showFullScreen();
// sometimes works, sometimes it doesn't:
QTimer::singleShot(2000, d, SLOT(showFullScreen()));
}
DomTomCat here at stackoverflow showed a way to detect Ubuntu and the QDialog problem is related to a bug in Metacity (Ubuntu's default window manager).
Metacity doesn't manage the same way dialogs and main windows and it has to be tricked making it think that a QDialog is a normal window. In order to do so using QDialog class it's window flags have to be changed.
Instead of doing all the steps DomTomCat says, you can detect the session and then just
//example inside the QDialog
this->setWindowFlags(Qt::Window);
this->showFullScreen();
The bug was reported (and ignored) before but as far as I know this is the first simple workaround.
https://bugreports.qt.io/browse/QTBUG-16034
https://git.gnome.org/browse/metacity/tree/src/core/window.c#n6326
Ubuntu can also use compiz. This can be seen at:
grep DefaultProvider-windowmanager /usr/share/gnome-session/sessions/*
Best regards,
Iker De Echaniz.
I came to a method, which works. I don't know why it works compared to just calling showFullScreen(). I guess this is not the perfect and clean solution. This can surely be adapted to other environmental variables and X sessions.
QDialog* d = new QDialog();
d->setModal(false);
d->show();
const QString session = QString(getenv("DESKTOP_SESSION")).toLower();
QByteArray geometry;
if (session == "ubuntu") {
geometry = _d->saveGeometry();
d->setFixedSize(qApp->desktop()->size());
d->setWindowFlags(Qt::FramelessWindowHint);
d->setWindowState( d->windowState() | Qt::WindowFullScreen);
d->show();
d->activateWindow();
} else {
d->showFullScreen();
}
For restoring from the fullscreen state, this has worked
if (session == "ubuntu") {
d->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
d->setMinimumSize(0,0);
d->restoreGeometry(geometry);
d->setWindowFlags(Qt::Dialog);
d->show();
d->activateWindow();
} else {
d->showNormal();
}

setCentralWidget() causing the QMainWindow to crash.. Why?

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
this->setupUi(this);
this->setupActions();
this->setWindowTitle(tr("CuteEdit"));
label = new QLabel(tr("No Open Files"));
this->setCentralWidget(label);
label->setAlignment(Qt::AlignCenter);
}
By above code, I get a GUI like this(Its a screenshot of whole screen, Only observe the window displayed in middle of page of ebook). (I used QT Designer)
Now, i want user to select File->Open.. A Dialog appears and file gets selected.. Its contents are to be displayed in *textEdit widget..
Function for that is below..
void MainWindow::loadFile()
{
QString filename = QFileDialog::getOpenFileName(this);
QFile file(filename);
if (file.open(QIODevice::ReadOnly|QIODevice::Text))
{
label->hide();
textEdit->setPlainText(file.readAll());
mFilePath = filename;
QMainWindow::statusBar()->showMessage(tr("File successfully loaded."), 3000);
}
}
The window crashes at line:-
textEdit->setPlainText(file.readAll());
But if i comment the line:-
this->setCentralWidget(label);
i mean i remove label as being the central widget, the program runs as expected.. Why?
And also, I am not clear about the concept of CentralWidget. Pls guide.
JimDaniel is right in his last edit. Take a look at the source code of setCentralWidget():
void QMainWindow::setCentralWidget(QWidget *widget)
{
Q_D(QMainWindow);
if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
d->layout->centralWidget()->hide();
d->layout->centralWidget()->deleteLater();
}
d->layout->setCentralWidget(widget);
}
Do you see that if your MainWindow already had centralWidget() Qt schedules this object for deletion by deleteLater()?
And centralWidget() is the root widget for all layouts and other widgets in QMainWindow. Not the widget which is centered on window. So each QMainWindow produced by master in Qt Creator already has this root widget. (Take a look at your ui_mainwindow.h as JimDaniel proposed and you will see).
And you schedule this root widget for deletion in your window constructor! Nonsense! =)
I think for you it's a good idea to start new year by reading some book on Qt. =)
Happy New Year!
Are you sure it's not label->hide() that's crashing the app? Perhaps Qt doesn't like you hiding the central widget. I use Qt but I don't mess with QMainWindow that often.
EDIT: I compiled your code. I can help you a bit. Not sure what the ultimate reason is as I don't use the form generator, but you probably shouldn't be resetting the central widget to your label, as it's also set by the designer, if you open the ui_mainwindow.h file and look in setupGui() you can see that it has a widget called centralWidget that's already set. Since you have used the designer for your GUI, I would use it all the way and put the label widget in there as well. That will likely fix your problems. Maybe someone else can be of more help...
I'm not sure I understood your problem, neither what the guys above said (which I guess are valid information) and it seems to be an old topic.
However, I think I had a problem that looks like this and solved it, so I want to contribute my solution in case it helps anyone.
I was trying to "reset" central widget using QLabels. I had three different ones, switch from first to second, then to third and failed to switch back to the first one.
This is my solution that worked:
Header file
QLabel *imageLabel;
Constructor
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Reset
imageLabel = NULL;
imageLabel = new QLabel("<img src='/folder/etc.jpg' />");
this->setCentralWidget(imageLabel);
Hope that helps
Aris