Click here to Skip to main content
15,901,283 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
I writing a QT gui app. My App has a window with a combo box with the id of records that a user can pick to edit. I have code in the MainWindow class that executes a sql query to populate the combo box. I have code to check for sql errors. After informing the user that there was an error I want to shutdown the whole app. I googled this for hours. I've tried close, QCoreApplication::exit() in the MainWindow class and that doesn't work. Please help.
Posted

I found a solution. Any place I get a sql error, I simply close the form not abort the app. Also using this link I found a nice way of showing my login dialog so it doesn't show the MainWindow before a successful login.

http://stackoverflow.com/questions/5527908/qt-how-to-open-qdialog-when-main-application-done-fully-to-load-all-widgets[^]



I made this change to the suggested code. You need to design the login gui dialog yourself.


void MainWindow::showDialog()
{
    this->hide();
    TryAgain=true;
    while (TryAgain==true)
    {
        mLogin =new LoginDialog(this);

        mLogin->exec();

    }

   

    mLogin->close();
    if (Abort==true)
    {
       
        qApp->closeAllWindows();

    }
    else this->show();
}


Here is the code in my login dialog

#include "logindialog.h"
#include "ui_logindialog.h"
#include <mainwindow.h>
#include <menu.h>
#include <QApplication>
#include <QDebug>
#include <QString>
#include <QtSql/QSql>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlError>
#include <QMessageBox>
#include "Globals.h"




 LoginDialog::LoginDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::LoginDialog)
{
    ui->setupUi(this);
    ui->txtUser->setText("root");
    ui->txtPwd->setText("moonpie");



}

LoginDialog::~LoginDialog()
{
    delete ui;
}



void LoginDialog::on_btnCancel_clicked()
{
    TryAgain=false;
    close();
}

void LoginDialog::on_btnLogin_clicked()
{
    QString user,pwd;
    QSqlDatabase db;
    user=ui->txtUser->text();
    pwd=ui->txtPwd->text();
    bool loggedIn=false;

    qDebug() << "inside createConnection";
    db = QSqlDatabase::addDatabase("QMYSQL");
    QString connection;
    connection = db.connectionName();
    db.setHostName("localhost");
    db.setDatabaseName("mydb");
    db.setUserName(user);
    db.setPassword(pwd);



      TryAgain=false;


    if (!db.open()) {

        if (QMessageBox::question(this, "Login Failed",
        "Login Failed Retry?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
        {
            loggedIn=false;
            TryAgain=true;
            Abort=false;

        }
        else
        {
            loggedIn=false;
            TryAgain=false;
            Abort=true;
            qDebug() << "LoginDialog Abort==true";

        }

    }
    else
    {
     loggedIn= true;
     Abort = false;
    }



    if (loggedIn==false)
    {

        this->close();
    }
    else
    {
        TryAgain=false;
        this->close();





    }

qDebug() << "LoginDialog End of Login doialog";
if (TryAgain==true)
    qDebug() << "LoginDialog TryAgain==true";
else
    qDebug() << "LoginDialog TryAgain==false";

if (Abort==true)
qDebug() << "LoginDialog Abort==true";
else
    qDebug() << "LoginDialog Abort==false";
}



Here is the Globals.h

C++
#ifndef GLOBALS_H
#define GLOBALS_H

#endif // GLOBALS_H
extern bool TryAgain;
extern bool Abort;



Here is the Globals.cpp

#include "Globals.h"
bool TryAgain=false;
bool Abort=false;
 
Share this answer
 
Comments
Jochen Arndt 8-Dec-15 3:34am    
This is a bad solution because it uses global variables instead of dialog return values.

In your LoginDialog call accept(), reject(), or done(int r) according to the result like (these will also close the dialog):
accept() or done (QDialog::Accept): Logged in
reject() or done (QDialog::Reject): Not logged, no abort
done(100): Not logged in, abort

In your main window check the value returned by m_Login->exec(). It is QDialog::Accepted, QDialog::Rejected, or 100.
I'm sorry, I'm not sure what you mean by calling accept(), reject(), or done(int r) can you elaborate? Also what does the 100 returned from m_Login->exec() mean? did you mean QDialog::Done ?
 
Share this answer
 
Comments
CHill60 15-Dec-15 16:53pm    
If you want to respond to a post then use the "Have a Question or Comment?" link next to it so that the poster is notified. Do not post comments as solutions
JohnnyG62 15-Dec-15 23:38pm    
Okay. thanks for the tip !

I'm sorry, I'm not sure what you mean by calling accept(), reject(), or done(int r) can you elaborate? Also what does the 100 returned from m_Login->exec() mean? did you mean QDialog::Done ?
This is not a solution for the initial question but a better approach then provided by solution 1 and explains what I said in my comment to that solution:
Quote:
This is a bad solution because it uses global variables instead of dialog return values.

In your LoginDialog call accept(), reject(), or done(int r) according to the result like (these will also close the dialog):
accept() or done (QDialog::Accepted): Logged in
reject() or done (QDialog::Rejected): Not logged, no abort
done(100): Not logged in, abort

In your main window check the value returned by m_Login->exec(). It is QDialog::Accepted, QDialog::Rejected, or 100.

The '100' return code is just an example. In the below code I use QDialogQMessageBox::Retry instead.

The login dialog:
// This may be removed when using the default handling (connecting Cancel button to reject())
void LoginDialog::on_btnCancel_clicked()
{
    reject();
}
 
void LoginDialog::on_btnLogin_clicked()
{
    // trying to open database
    if (!db.open()) {
         if (QMessageBox::question(this, "Login Failed",
        "Login Failed Retry?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
        {
            done(QMessageBox::Retry);
        }
        else
        {
            reject(); // same as done(QDialog::Rejected)
        }
    }
    else
    {
        accept(); // same as done(QDialog::Accepted)
    }
 }


The MainWindow function:
void MainWindow::showDialog()
{
    this->hide();
    int result = QMessageBox::Retry;
    while (result == QMessageBox::Retry)
    {
        LoginDialog *login = new LoginDialog(this);
        result = login->exec();
    // EDIT: Delete dialog here if it has not been created with  Qt::WA_DeleteOnClose
        delete login;
    }
    if (result == QDialog::Rejected)
        qApp->closeAllWindows();
    else 
        this->show();
}


[UPDATE]
An even better solution would be to handle retry inside the login dialog:
void LoginDialog::on_btnLogin_clicked()
{
    // trying to open database
    if (!db.open()) {
         if (QMessageBox::question(this, "Login Failed",
        "Login Failed Retry?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
        {
            // Retry: Let the dialog stay open.
            // Optionally clear the input fields here.
            return;
        }
        // Let exec() return with QDialog::Rejected
        reject();
    }
    else
    {
        // Let exec() return with QDialog::Accepted
        accept();
    }
}

The corresponding MainWindow function:
void MainWindow::showDialog()
{
    this->hide();
    LoginDialog *login = new LoginDialog(this);
    int result = login->exec();
    // Delete dialog here if it has not been created with  Qt::WA_DeleteOnClose
    delete login;
    if (result == QDialog::Rejected)
        qApp->closeAllWindows();
    else 
        this->show();
}
 
Share this answer
 
v4
Comments
JohnnyG62 16-Dec-15 16:20pm    
I'm sorry if I didn't respond correctly. I'm using the "Have Question or Comment" link. I didn't see a reply button next to the posters name. Anyway. I tied your suggestion but got the folloing compile errors.

The login dialog:
error: 'Retry' is not a member of 'QDialog'
done(QDialog::Retry);
^

error: 'StandardButton' is not a member of 'QDialog'
QDialog::StandardButton result = QDialog::Retry;
^

error: 'Retry' is not a member of 'QDialog'
while (result == QDialog::Retry)
^
error: 'Cancel' is not a member of 'QDialog'
if (result == QDialog::Cancel)
Jochen Arndt 16-Dec-15 16:57pm    
The Reply button is for comments (right of the poster's name).
The "Have Question or Comment" link is for questions and solutions (at the bottom).

Sorry, I was too fast when posting. The dialog exec return values for accept() and reject() are QDialog::Accepted (1) and QDialog::Rejected (0). The return value for done() is the passed value which can be any except 0 and 1 when not wanting similar benaviour as accept() and reject().

I will update my answer.
An example would be using QPushButton::Retry.
JohnnyG62 16-Dec-15 21:05pm    
Getting very close. I understand your code and like the design. One issue, When I click on the retry button, the result passed back to MainWindow is zero not QMessageBox::Retry = 524288. Here is the output of some debug staments

Inside MainWindow
QMessageBox::Retry = 524288

Inside LoginDialog
done(QMessageBox::Retry) = 524288
back in MainWindow
result from login->exec() = 0
I really appreciate your help thus far :-)
Jochen Arndt 17-Dec-15 3:16am    
This should work (I'm using done() to close dialogs and return values).
Form the Qt documentation:

void QDialog::done(int r)
Closes the dialog and sets its result code to r. If this dialog is shown with exec(), done() causes the local event loop to finish, and exec() to return r.

But there is no 'Retry' button. There should be only a 'Yes' button. And then the call to question should be:
QMessageBox::question(this, "Login Failed",
"Login Failed Retry?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No)

While investigating this I think I found the initial problem that prevents your app from closing. It may be sourced by not deleting the login dialog (however, it will be deleted when the parent window is deleted). I have updated the code example.
JohnnyG62 17-Dec-15 13:04pm    
Well that didn't work. I have a cognitive issue (brain injury), so It's probably me. I may be overlooking something. Below is the revised code based on your suggestions. Perhaps I made a mistake? If you don't have time to waste on this anymore, I understand. Thanks for all your help
-----------------------------------------------------
void LoginDialog::on_btnLogin_clicked()
{
if (!db.open()) {


if (QMessageBox::question(this, "Login Failed",
"Login Failed Retry?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
{

done(QMessageBox::Retry);
}
else
{
delete con;

reject(); // same as done(QDialog::Rejected)
}
}
else
{

accept(); // same as done(QDialog::Accepted)
}
}
-----------------------------------------------------
void MainWindow::showDialog()
{
this->hide();
int result = QMessageBox::Retry;

while (result == QMessageBox::Retry)
{
LoginDialogNew *login = new LoginDialogNew(this);
result = login->exec();
delete login;
}



if (result == QDialog::Rejected)
qApp->closeAllWindows();
else{

this->show();


}
}

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900