How do i connect messageBox when it is clicked, to a slot? - qt

I want to create a messagebox asking question whether a user want to play again or not. When user clicks either a button , it performs a task. The task is defined in a slot. How can i connect the button click to that slot??
QMessageBox::StandardButton reply=QMessageBox::question(this,"GAME Over-Do you want to play again?");
connect(QMessageBox,SIGNAL(buttonClicked()),this,SLOT(box());
it shows QMessageBox is a class, and is unable to connect it to that slot. I want to connect to that slot.

There is different ways to use QMessageBox. You could use blocking static functions of QMessageBox and check response like that:
QMessageBox::StandardButton reply = QMessageBox::question(this,"Title", "GAME Over-Do you want to play again?");
if(reply == QMessageBox::Yes)
{
//call your slot
//box();
qDebug() << " Yes clicked";
}
else
{
//Game over
qDebug() << "game over";
}
but this will block execution of your code until user clicks some button in message box.
If you need your code run forward without waiting for user response you could use QMessageBox in non-blocking way:
QMessageBox * msg = new QMessageBox(QMessageBox::Question, "Title", "GAME Over-Do you want to play again?", QMessageBox::Yes| QMessageBox::No, this);
connect(msg,SIGNAL(accepted()),this,SLOT(box()));
connect(msg,SIGNAL(rejected()),this,SLOT(gameover()));
msg->show();
qDebug() << "Not blocked";

Related

Accessibility notification in Qt

I am trying to push notification to Jaws or NVDA when certain events occur.
These events can occur any time and any application widget can have the focus. They are not linked to user actions but to the controller events.
This is my try:
void announceNewMessageIfNeeded(){
if(QAccessible::isActive()){
QWidget* focusWidget = QApplication::focusWidget();
if(focusWidget != nullptr){
auto* accessibleInterface = QAccessible::queryAccessibleInterface(focusWidget);
accessibleInterface->setText(QAccessible::Name, "New Message");
auto *ev = new QAccessibleEvent(accessibleInterface, QAccessible::Alert);
QAccessible::updateAccessibility(ev);
}
}
}
I tried the above code with various little changes but I either do not have accesibility update or undesired access to nullpointers.
With debug logs, I know for sure that the focusWidget is correct (it points to the item having the currentFocus) and that announceNewMessageIfNeeded is called.
Any idea?
solution that seems to work:
if(QAccessible::isActive()){
QWidget* focusedWidget = QApplication::focusWidget();
if(focusedWidget != nullptr){
auto *ev = new QAccessibleValueChangeEvent(focusedWidget, "New Message");
QAccessible::updateAccessibility(ev);
}
}

QGuiApplication::commitDataRequest: QML window is not painted

I'm trying to add quit confirmation message at OS shutdown according to this example:
https://doc.qt.io/qt-5/qsessionmanager.html#allowsInteraction
I interact with the user via QML interface. It is asynchronous, so I use slots/signals. And I use additional QEventLoop to stay inside of QGuiApplication::commitDataRequest call while interacting with the user.
The trouble is that after I shutdown OS (Windows 10) - my app prevents OS to shutdown and it's good, but its screen is just white, or contains old state without the confirmation dialog. I need to hide/restore window or change its size, or do some mouse clicks inside of it to force it repaint. When it repaint all is OK and my confirmation dialog is there.
Is this a bug? Is there a workaround?
This is the code I use:
void AppQuitConfirmationAtOsShutdownManager::onCommitDataRequest(
QSessionManager &m)
{
if (!m_ui->isConfirmationRequired())
return;
if (!m.allowsInteraction())
return;
bool isConfirmed = true;
QEventLoop loop;
qtconnect(m_ui.data(), &AppQuitConfirmationUiManager::confirmationResult,
&loop, [&](bool confirmed)
{
isConfirmed = confirmed;
loop.quit();
},
Qt::QueuedConnection);
m_ui->requestConfirmation();
loop.exec();
m.release();
if (!isConfirmed)
m.cancel();
}

Properly using Qt QProcess

I'm considering to use QProcess to call a command line app (gpio) multiple times. Every time user clicks a button then a command is issued.
And the app output will be monitored and redirected to screeen. The code looks like the following.
void Gpio::command(QString argument)
{
// if(process)
// delete process;
process = new QProcess(this);
connect(process, SIGNAL(started()), this, SLOT(onStart()));
connect(process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(onFinish(int,QProcess::ExitStatus)));
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readGpio()));
QString program("gpio");
QStringList list = argument.split(" ");
process->start(program, list);
}
Question: Should I delete process? Doing so I got:
QProcess: Destroyed while process is still running.
Monitoring exitCode and exitStatus I see they are always 0.
This question concerns more about the proper use of QProcess while "QProcess and shell : Destroyed while process is still running" focus on the specific error.
as you don't want to run multiple processes concurrently (as per the comments), you don't need to create / delete the QProcess multiple times.
gpio.h
QProcess* m_gpioProcess;
gpio.cpp file
Gpio::Gpio(.....),
.....(),
m_gpioProcess(new QProcess(this))
{
m_gpioProcess->setProgram("gpio");
connect(m_gpioProcess, SIGNAL(started()), this, SLOT(onStart()));
connect(m_gpioProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(onFinish(int,QProcess::ExitStatus)));
connect(m_gpioProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readGpio()));
}
void Gpio::command(const QString& args)
{
if (m_gpioProcess->state() != QProcess::NotRunning) {
qDebug() << "Process already running, ignoring the request";
return;
}
m_gpioProcess->setArguments(args.split(" "));
m_gpioProcess->start();
if (m_gpioProcess->waitForStarted()) {
qDebug() << "Process started with arguments:" << m_gpioProcess->arguments();
}
}
if you want to prevent user clicking the button multiple times, consider enabling / disabling the button as per m_gpioProcess state.
for Qt 4.8, just remove this line
m_gpioProcess->setProgram("gpio");
and this line
m_gpioProcess->setArguments(args.split(" "));
and change this line
m_gpioProcess->start();
to
m_gpioProcess->start("gpio", args.split(" "));
Well, It seems I was forgetting process->waitForFinished(); after the call to start. This seems to solve the problem.
add following code maybe helpful:
process->close();

Basic Qt tcp-server application only show selected clients messages

I am developing a simple tcp server with qt. There is no problem with that. But the problem is, i have listed every connected client in a listbox and i want to see the incoming data only from the selected client from the listbox but i can only see the last connected client's messages.
here is the code,
this is the constructor part
server = new QTcpServer();
client = new QTcpSocket();
connect(server, SIGNAL(newConnection()),this, SLOT(acceptConnection()));
server->listen(QHostAddress::Any, ui->txtPort->text().toInt(bool(),10));
if(server->isListening())
{
ui->statusBar->showMessage("Server Started..");
}
else
{
ui->statusBar->showMessage("Server Not Started..");
}
connect(client,SIGNAL(disconnected()),this,SLOT(client_disconnected()));
connect(ui->listWidget,SIGNAL(clicked(QModelIndex)),this,SLOT(selected_client()));
here is acceptConnection() part
client = server->nextPendingConnection();
ui->listWidget->insertItem(client_count,client->peerAddress().toString());
client_count++;
and this is the listWidget item's selected item event
ui->txtRead->clear();
selected_client_index = ui->listWidget->currentIndex().row();
connect(client, SIGNAL(readyRead()),this, SLOT(startRead()));
and lastly the startRead() part
char buffer[1024] = {0};
client->read(buffer, client->bytesAvailable());
qDebug() << buffer;
ui->txtRead->insertPlainText(buffer);
How can i select the specific client and show its messages ?
Thanks in advance.
You should not use client in startRead, but some selectedClient, that You remembers in selected_client() SLOT.
As for now, when You use client = server->nextPendingConnection(), You are losing any previous clients. You should save them into some QList<QTcpSocket*>.

QDialog::accept quits Main Application

I have a ClientSocket Class which is a TcpSocket in a certain state of conversation I need to ask the user to enter a Communication password. So I've created a Dialog DG::ChallangeDialog . in DG::ChallangeDialogs ctor I've
ui->setupUi(this);
QPushButton* okButton = ui->buttonBox->button(QDialogButtonBox::Ok);
if(okButton != 0x0){
okButton->setText("Challange");
}
QObject::connect(this, SIGNAL(accepted()), this, SLOT(acceptedSlot()));
acceptedSlot again emits a signal challanged(QString)
void ChallangeDialog::acceptedSlot(){
QString text = ui->passBox->text();
emit challanged(text);
}
in ClientSocket I do
case Hallo:{
if(m->message().startsWith("welcome")){
DG::ChallangeDialog* dlg = new DG::ChallangeDialog;
dlg->setModal(true);
connect(dlg, SIGNAL(challanged(QString)), this, SLOT(challanged(QString)));
dlg->exec();
/*
DG::MessagePacket* res = new DG::MessagePacket((int)Hallo);
res->setMessage("challange");
send(res);
state = Challange;
*/
}
}break;
In ClientSocket::challange slot I send a Message challange (text) over the socket and store the password.
and I expect the Dialog to hide there and the normal socket conversation to continue. and after the Dialog is accepted or rejected the main application quits (It quits it doesn't crash). Why ?
My Application has no Other Widgets. I just works like an QCoreApplication. But still I've used QApplication cause I've some GUI Needs.
Is this the only window that is shown at this time? If so, I would guess that your QApplication instance is set to quit when the last window is closed. It is true by default.
If this is the case, you should explicitly set this to false before showing any windows.

Resources