#include <qapplication.h>
#include <qsqldatabase.h>
#include <qprogressdialog.h>
#include <qsql_psql.h>
#include <libpq-fe.h>

void noticeProcessor(void * arg, const char * message)
{
    const QString SET_PROGRESS_STEPS("set_progress_steps: ");
    const QString SET_PROGRESS_TEXT("set_progress_text: ");
    const QString SET_PROGRESS("set_progress: ");

    static QProgressDialog* progress = NULL;
    if (progress == NULL)
    {
        progress = new QProgressDialog(qApp->mainWidget(), "progress", TRUE);
        progress->setMinimumDuration(0);
        progress->setAutoReset(TRUE);
        progress->setAutoClose(TRUE);
    }

    QString msg = QString::fromUtf8(message);
    int pos;

    if ((pos = msg.find(SET_PROGRESS_STEPS)) >= 0)
    {
        progress->reset();
        progress->setTotalSteps(msg.mid(pos + SET_PROGRESS_STEPS.length()).toInt());
    }
    else if ((pos = msg.find(SET_PROGRESS_TEXT)) >= 0)
    {
        progress->setLabelText(msg.mid(pos + SET_PROGRESS_TEXT.length()));
        progress->repaint();
    }
    else if ((pos = msg.find(SET_PROGRESS)) >= 0)
    {
        progress->setProgress(msg.mid(pos + SET_PROGRESS.length()).toInt());
        if (progress->wasCanceled())
        {
            QPSQLDriver* drv = (QPSQLDriver*)(QSqlDatabase::database()->driver());
            PQrequestCancel(drv->connection());
            progress->reset();
        }
    }
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    if (argc < 5)
    {
        qWarning("Usage: %s <username> <password> <database> <hostname>", argv[0]);
        return 1;
    }

    QSqlDatabase* db = QSqlDatabase::addDatabase("QPSQL7");
    db->setUserName(argv[1]);
    db->setPassword(argv[2]);
    db->setDatabaseName(argv[3]);
    db->setHostName(argv[4]);
    if (!db->open())
    {
        qWarning("Could not open database:\n%s", db->lastError().text().latin1());
        return 1;
    }

    // tricky part -- set notice processor for Qt database connection
    QPSQLDriver* drv = (QPSQLDriver*)(QSqlDatabase::database()->driver());
    PQsetNoticeProcessor(drv->connection(), noticeProcessor, NULL);

    QSqlQuery qry;
    if (!qry.exec("select progresstest()"))
    {
        qWarning("Could not execute query (possible cancel?):\n%s", qry.lastError().text().latin1());
        return 1;
    }

    return 0;
}
