How to create a QInputDialog in a new thread? - c++

Basically I'm calling a function from another thread using QtConcurrent.
Working as expected but once I create a QInputDialog within the called function, I'm getting an assertion exception telling me that I have to create the Dialog in the Main GUI Thread.
To be more specific this line:
password = QInputDialog::getText( this , tr( "Password" ) , tr( "Enter Password:" ) , QLineEdit::Password , selectedPassword , &ok );
Now the question would be how can I call the Dialog from a new thread without too much extra work.

You can't create widgets outside from main thread. You can emit signal from network thread and create dialog in main thread.
Or do something like this (pseudo-code):
class NotificationManager : public QObject
{
Q_OBJECT
//...
public slots:
void showMessage( const QString& text )
{
if ( QThread::currendThread() != this->thread() )
{
QMetaObject::invoke( this, "showMessage", Qt::QueuedConnection, Q_ARG( QString, text );
// Or use Qt::BlockingQueuedConnection to freeze caller thread, until dialog will be closed
return;
}
QMessageBox::information( nullptr, QString(), text );
}
};
class ThreadedWorker : public QRunnable
{
ThreadedWorker( NotificationManager *notifications )
: _notifications( notifications )
{}
void run() override
{
// Do some work;
notifications->showMessage( "Show this in GUI thread" );
}
private:
NotificationManager *_notifications;
}

Related

QProgressBar in new window don't work

I'm creating the new window with QProgressBar when i click on button of MainWindow but when new window is creating, QProgressBar don't appear while filling cycle is working. After then QProgressBar appear and it is filled.
Constructor:
ProgressWin::ProgressWin():QWidget()
{
this->resize(273,98);
this->move(670, 430);
bar1 = new QProgressBar(this);
bar1->setGeometry(20, 31, 251, 31);
bar1->setMinimum(0);
bar1->setMaximum(10000);
this->show();
unsigned long long secr, PQ;
unsigned long long rv;
unsigned long long decr;
for(int v = 0; v <= 100000; v++) {
bar1->setValue(v);
}
}
Code of button that call new window:
void RsaMainWindow::ButtClickCrypt()
{
FileName1 = ui->LineCrypt->text();
if(FileName1.isEmpty()) {
QMessageBox::information(0, "Information", "File for Crypt wasn't chosen");
return;
}
NewWin = new ProgressWin;
}
Class for new window:
class ProgressWin : public QWidget
{
QProgressBar *bar1;
public:
ProgressWin();
};
Class for MainWindow:
[namespace Ui {
class RsaMainWindow;
}
class RsaMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit RsaMainWindow(QWidget *parent = 0);
~RsaMainWindow();
private slots:
void ButtClickViewCryp();
void ButtClickViewDecr();
void ButtClickViewKeys();
void ButtClickCrypt();
void ButtClickDecr();
private:
Ui::RsaMainWindow *ui;
QString FileName1;
QString FileName2;
QString FileName3;
ProgressWin *NewWin;
};][1]
User interface usually work on the event-loop principle:
While (not closing the app)
Wait for some event
update app according event
endWhile
If you implement your heavy task in the GUI thread, when the user click on "Perform a heavy task", the code managing this click is called, and after it finish, a following event will trigger the drawing of the window. That mean your heavy task will freeze the user interface during the task.
To perform a heavy task correctly, you need to:
Create a background thread that perform the task. Each iteration, it update some shared-memory (or equivalent) status of the task. Some UI libraries, like QT allows to send queued messages, which help for those cases.
On the Main thread, on update of the status, set the progress bar to the new value and return.

Is it possible to move an object instance to different threads at different points of code in a QT project?

I am trying to determine if you can move one object instance to different threads at different points during run-time.
Below is some sample code to show you what I mean:
this->thread1 = new QThread( this );
this->thread2 = new QThread( this );
this->pObject->moveToThread( this->thread1 );
connect(this->thread1, SIGNAL(started()), this->pObject, SLOT(fnc1()));
connect(this->thread2, SIGNAL(started()), this->pObject, SLOT(fnc2()));
this->thread1->start();
//after thread1 has finished
this->pObject->moveToThread( this->thread2 );
this->thread2->start();
Is it possible to do this?
Edit: After Kuba's advice on not using a direct connection and him pointing out I must be interfering with the event loop somehow, I realised manually terminating the threads was not a good idea. I am adding my termination of the threads here to show where I am going wrong and to try and find a better way of achieving the same result.
connect(this->pObject, SIGNAL(finished()), this, SLOT(stopThread()));
void Class::stopThread( void )
{
if( this->thread1->isRunning() )
{
this->thread1->terminate();
return;
}
if( this->thread2->isRunning() )
{
this->thread2->terminate();
this->pObject->moveToThread( this->thread1 );
}
}
void Object::fnc1( void )
{
/*Does some work..*/
finished(); //Calls 'finished' to signal stopThread when done (not stopping on its own)
}
ADDITIONAL INFO
I have MainClass which holds the instances to both thread1, thread2 and pObject (pointer to the object I am trying to move from thread1 to thread2 and back again if necessary).
Main class constructor:
MainClass::MainClass( QWidget *parent ) : QMainWindow(parent)
{
this->ui.setupUi(this);
this->thread1 = new QThread( this );
this->thread2 = new QThread( this );
this->pObject->moveToThread( this->thread1 );
connect( this->pObject, SIGNAL(finished()), this, SLOT(stopThread()) );
connect( this->thread1, SIGNAL(started()), this->pObject, SLOT(fnc1()) );
connect( this->thread2, SIGNAL(started()), this->pObject, SLOT(fnc2()) );
}
Slot for when menu item is clicked:
void MainClass::on_action_call_fnc1_triggered( void )
{
if( this->thread1->isRunning() )
return;
/*EXECUTES SOME CLASSIFIED CODE THAT CANNOT BE SHOWN*/
this->thread1->start();//should trigger fnc1 execution
}
fnc1 held in Object class that is called when thread1 starts:
void Object::fnc1( void )
{
/*DOES SOME MORE SECRET PROCESSING THAT CANNOT BE SHOWN*/
this->finished(); // triggers MainClass::stopThread( void )
}
Slot for when menu item is clicked to start fnc2 executing:
void MainClass::on_action_call_fnc2_triggered( void )
{
if( this->thread1->isRunning() || this->thread2->isRunning() )
return;
this->pObject->moveToThread( this->thread2 );
this->thread2->start();//should trigger fnc2 execution
}
fnc2 held in Object:
void Object::fnc2( void )
{
/*DOES SOME MORE SECRET PROCESSING THAT CANNOT BE SHOWN*/
this->finished(); // triggers MainClass::stopThread( void )
}
stopThread function:
void MainClass::stopThread( void )
{
if( this->thread1->isRunning() )
{
/*this->thread1->quit();
this->thread1->exit();*/
this->thread1->terminate();
//this->thread1->wait( 0 ); //Trying different ways of stopping the thread
return;
}
if( this->thread2->isRunning() )
{
this->thread2->terminate();
//this->thread2->quit(); // Trying different ways of stopping the thread
//this->thread2->exit();
this->pObject->moveToThread( this->thread1 );
}
}
It will work, but you have to assert that the object's thread is indeed finished:
Q_ASSERT(pObject->thread() == nullptr);
pObject->moveToThread(thread2);
When thread1 is finished, the object's thread becomes null and only then you're allowed to move it to another thread from arbitrary thread. Otherwise, if object's thread is not finished yet, you could only move the object from its thread:
QTimer::singleShot(0, pObject, [this]{ pObject->moveToThread(thread2); }

client program crashes when connect to server after disconnect Qt

I am implementing client side of TCP-Ip server based on Qt but the program crashes when I closed connection and start again by hitting connect button.
Overview of project. I have Qwidget ( main application) with 2 lineEdit for user to input port number and server Ip address.
It also has 2 button that connect to server and disconnect. On hitting connect button , it will call constructor of client socket and call connectToHost.
Testing: Tried testing on same computer with server running on port 6000 and ip address 127.0.0.1.
Problem: When I launch Client application.And input port number and address and hit connect button it connects successfully. And I can write to server successfully. then I click disconnect button and it disconnects successfully but after that if I connect again by clicking connect button it crashes. I know problem is with tcpSocket but have no idea how to fix it.
clientAgent( QWidget appilciation ).h
namespace Ui {
class ClientAgent;
}
class ClientAgent : public QWidget
{
Q_OBJECT
public:
explicit ClientAgent(QWidget *parent = 0);
~ClientAgent();
private:
Ui::ClientAgent *ui;
ClientForTest *tcpSockForTest;
// Qwidget declartion
below
....
private slots:
void startClient();
void stopClient();
public slots:
void getCliReqTextChanged();
};
ClientAgent.cpp
ClientAgent::ClientAgent( QWidget *parent ) :
QWidget(parent),
ui( new Ui::ClientAgent )
{
// Widget declartion and initilisation
// Layout design etc
//define signals and slots for Client
// signals and slots
connect( btnStartClient, SIGNAL( clicked() ), this, SLOT( startClient() ) );
connect( btnStopClient, SIGNAL( clicked() ), this, SLOT( stopClient() ) );
// for write
connect( lEditCliReq, SIGNAL( textChanged(const QString& ) ), this, SLOT( getCliReqTextChanged() ) );
ui->setupUi( this );
}
ClientAgent::~ClientAgent()
{
delete ui;
}
void ClientAgent::startClient()
{
qDebug() << " we are in strt Clinet";
qDebug() << " connecting ";
// get server address and port number from GUI
QString testAddr = lEditAddr->text();
QString testPort = lEditPrt->text();
tcpSockForTest = new ClientForTest( testAddr, testPort.toInt(), this );
if( tcpSockForTest->connectToServer() == true )
{
lblCliStatus->setText(" connected ....");
}
else
{
lblCliStatus->setText(" failed to connect....");
}
}
void ClientAgent::stopClient()
{
qDebug() << " disconnecting ";
tcpSockForTest->disconnectToServer();
delete tcpSockForTest;
}
ClientForTest.h
class ClientForTest : public QObject
{
Q_OBJECT
public:
ClientForTest( QString hostAddr, quint16 portNum, QObject *parent );
bool connectToServer();
void disconnectToServer();
QString getStoreMsgFrmCliReq( ) const;
void writeToTest(const QString& stripCmd );
void executeSignals();
~ClientForTest();
signals:
void sigSendData();
public slots:
void connectedToTest();
void connectionClosedByServer();
void error();
private:
QTcpSocket *sockFortest;
QString hostName;
quint16 portNumber;
quint16 nextBlockSize;
QString storeLineEditMsg;// store message from lineEditCliReq;
};
ClientForTest.cpp
ClientForTest::ClientForTest( QString hostAddr, quint16 portNum, QObject *parent ) :
hostName( hostAddr ),
portNumber( portNum ),
QObject( parent )
{
connect( sockFortest, SIGNAL( connected() ), this, SLOT( connectedToTest() ) );
connect( sockFortest, SIGNAL( disconnected() ), this, SLOT( connectionClosedByServer() ) );
connect( sockFortest, SIGNAL( error( QAbstractSocket::SocketError ) ), this, SLOT( error() ) );
storeLineEditMsg = "";
}
void ClientForTest::executeSignals()
{
// actually I need toplace itin constructor will do later on
connect( this, SIGNAL( sigSendData() ), this, SLOT( connectedToTest() ) );
}
ClientForTest::~ClientForTest()
{
sockFortest->close();
delete sockFortest;
}
bool ClientForTest::connectToServer()
{
sockFortest = new QTcpSocket( this->parent() ); // COULD be Probelm here but how to fix it?
sockFortest->connectToHost( hostName, portNumber );
nextBlockSize = 0;
executeSignals();
return sockFortest->waitForConnected(1000);
}
void ClientForTest::disconnectToServer()
{
sockFortest->close();
//sockFortest.close();
qDebug() << "in disconnect for Test ";
emit updateLabelinParent( updateStatusDis );
}
void ClientForTest::connectionClosedByServer()
{
qDebug() << "connection closed by server ";
if( nextBlockSize != 0xFFFF )
{
disconnectToServer();
}
}
void ClientForTest::error()
{
qDebug() << "in error ";
disconnectToServer();
}
void ClientForTest::writeToTest( const QString& stripCmd )
{
storeLineEditMsg = stripCmd;
if( sockFortest->state() == QTcpSocket::UnconnectedState )
{
sockFortest->close();
delete sockFortest;
sockFortest = new QTcpSocket( this->parent() );
if( connectToServer() == true )
{
qDebug() << " YEEEE CONNECTED AGAIN finally ";
}
}
if( sockFortest->state() == QTcpSocket::ConnectedState )
{
qDebug() << " YEEEE CONNECTED";
sigSendData();
}
}
void ClientForTest::connectedToTest( )
{
QByteArray block;
QDataStream out( &block, QIODevice::WriteOnly );
out.setVersion( QDataStream::Qt_4_3 );
QString stripCmd = getStoreMsgFrmCliReq(); // received info for some other function I havnt shown that func here
out << quint16( 0 ) << stripCmd;
out.device()->seek( 0 );
out << quint16( block.size() - sizeof( quint16 ) );
qDebug()<<" yeeeee connected state...";
sockFortest->write( block );
//reset storeLineEditMessage
storeLineEditMsg.clear();
}
A few things, that could all together be responsible for your crash:
you connect the signals inside the ClientForTest constructor, but the socket itself is created later. That won't work. Move the line sockFortest = new QTcpSocket(this); to the constructor, before connecting
Same line, use this instead of this->parent()
And finally: There are multiple places you create/delete the socket. Don't do it. Create the socket inside the constructor with this as parent, and that's it. In your connectToServer, establish the connection, and in disconnectToServer, close it using disconnectFromHost. Same goes for the startClient and stopClient. Create the object once and just use the connect/disconnect functions, no deleting.
If code is required, I can add some.
Since it was requested, here is some more explanation:
Of course you can use parent, but in your case, the ClientForTest is an QObject, too. If you set the ClientForTest as as parent of the socket and the widget as the parent of ClientForTest, they will be both cleaned up properly. If you use this->parent(), both will be destroyed "at the same time". However, one comes first and somtimes Qt changes the order, so your socket could be destroyed before the ClientForTest. The destructor of ClientForTest would crash. That won't happen if the socket is a child of the ClientForTest
The main difference between close() and disconnectFromHost() is that the first actually closes the OS socket, while the second does not. The problem is, after a socket was closed, you cannot use it to create a new connection. Thus, if you want to reuse the socket, use disconnectFromHost() otherwise close()
And regarding 3. and 4.:
What you are doing is creating the ClientForTest when the user clicks connect, and delete it as soon as he clicks disconnect. But thats no good design (IMHO). Since tcpSockForTest already is a member of the class, create it (via new) inside the constructor, and delete it in the destructor (optionally, because if you pass the widget as parent, Qt will delete it for you).

how to modify values of dynamically created Widget from different class QT/C++

I know this question has been asked few times but all suggestions given there doesn't work for me.
Overview: I am implementing client server model and wants that as soon as msg arrived in server it should get displayed in main Qt widget. the widget , I choose to display msg is QLineEdit.
I have 3 files in project at the moment. Agent_A which is has all widget created dynamically. Then Server_test based on QTCPServer and sockClient for socket connection. I have received message on sockclient successfully from client but I don't know how to display it correctly on Agent_A .
I have added function in socketClient.cpp to update function in Agent_A but I guess when creating instance it always being NULL.
First a small snippet of my code and then what I have tried. may be you guys can input some valuable info.
Agent_A.h
class Agent_A : public QWidget
{
Q_OBJECT
public:
explicit Agent_A(QWidget *parent = 0);
void setLineEdit( const& modifyStr ); // function to change lineEditCmdString
~Agent_A();
private:
Ui::Agent_A *ui;
QPushButton *buttonStartServer;
QPushButton *buttonStopServer;
// some other widgets
QLabel *labelDisplay;
QLineEdit *lineEditCmdString;// I want to modify this value from sock client
ServerTest *server;
// few slots defined here
}
Agent_A.cpp
Agent_A::Agent_A( QWidget *parent ):
QWidget( parent ),
ui( new Ui::Agent_A )
{
//define push buttons
buttonStartServer = new QPushButton( tr( "&Start Server" ) );
buttonStopServer = new QPushButton( tr( "S&top" ));
// some properties of other widgets defined here which is not relevant to mention here
labelDisplay = new QLabel( tr("DisplayMessgae" ) );
lineEditCmdString = new QLineEdit;// I want to modify this value on sock client
labelDisplay->setBuddy( lineEditCmdString );
// define signals and slots for Server
connect( buttonStartServer, SIGNAL( clicked() ), this, SLOT( startServers() ) );
connect( buttonStopServer, SIGNAL( clicked() ), this, SLOT( stopServer() ) );
// some layout here which agian is not important to mention here.
ui->setupUi( this );
}
Agent_A::~Agent_A()
{
delete ui;
}
void Agent_A::setLineEdit( const Qstring& modifyStr )
{
lineEditCmdString->setText( modifyStr );
}
// now by socket client which creates socket
sockClient.h
class SockClient : public QObject
{
Q_OBJECT
public:
explicit SockClient( QObject *parent, QTcpSocket* socket= 0 );
~SockClient();
// I have added this function to update QLIneEdit in Agent_A
void updateTextinParent(const QString &changeText);
signals:
private slots:
void readClient();
private:
// some other functions
QTcpSocket *socketClient;
quint16 nextBlockSize;
public slots:
};
sockclient.cpp
// constructor for sockclient and some other functions
SockClient::SockClient( QObject *parent, QTcpSocket* socket ) : QObject( parent )
{
socketClient = socket ;
// create signals and slots
connect( socketClient, SIGNAL( readyRead() ), this, SLOT( readClient() ) );
connect( socketClient, SIGNAL( disconnected() ), this, SLOT( deleteLater() ) );
}
SockClient::~SockClient()
{
socketClient->close();
delete socketClient;
}
void SockClient::readClient()
{
QDataStream clientReadStream( socketClient );
clientReadStream.setVersion( QDataStream::Qt_4_3 );
QString strRecvFrm;
quint8 requestType;
clientReadStream >> nextBlockSize;
clientReadStream >> requestType;
if( requestType == 'S')
{
clientReadStream >> strRecvFrm;
}
qDebug() << " the string is " << strRecvFrm; // Has recieved correctly from client
updateTextinParent( strRecvFrmMops ); // Now trying to update widget
socketClient->close();
}
void SockClient::updateTextinParent( const QString& changeText )
{
if( this->parent() == 0 )
{
qDebug() << " Parent not assigned"; // This get printed ..
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( changeText );
}
}
// ServerTest.cpp where instance of sockClient is created
ServerTest::ServerTest(QObject *parent) : QObject(parent)
{
server = new QTcpServer( this );
}
void ServerTest::startServer()
{
connect( server, SIGNAL( newConnection() ), this, SLOT( incomingConnection() ) );
if( !server->listen( QHostAddress::Any, 9999) )
{
qDebug() << " Server failed to get started";
}
else
{
qDebug() << " Server started";
}
}
void ServerTest::stopServer()
{
server->close();
qDebug() << "Server closed";
}
ServerTest::~ServerTest()
{
server->close();
delete socketforClient;
delete server;
}
void ServerTest::incomingConnection()
{
socketforClient = new SockClient(this->parent(), server->nextPendingConnection() );
}
This is a very simple example:
qt.pro:
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
# Input
HEADERS += classes.h
SOURCES += main.cpp
classes.h:
#include <QObject>
#include <QDebug>
class Agent_A : public QObject
{
Q_OBJECT
public slots:
void updateText(const QString &changeText) {
qDebug() << "updateText: " << changeText;
};
};
class SockClient : public QObject
{
Q_OBJECT
signals:
void updateTextinParent(const QString &text);
public:
void incomingText(const QString &text) {
emit updateTextinParent(text);
};
};
main.cpp:
#include "classes.h"
int main(int argc, char **argv) {
Agent_A *agent = new Agent_A;
SockClient client;
QObject::connect(&client, SIGNAL(updateTextinParent(const QString &)),
agent, SLOT(updateText(const QString &)));
client.incomingText(QString("hello"));
return 0;
}
Agent_A *agent = qobject_cast< Agent_A* >( this->parent() ); // ?? is this is right way to do..?
if( agent != NULL )
{
qDebug() << " we are in updateTextin" << changeText; // it never get printed so I assume instance is always nULL
agent->setLineEdit( chnageText );
}
Could you please check first that parent is not NULL?
And could you please show code where you create instance of SockClient?
Of course, you can't modify text because of you set as parent to socketClient object this pointer in Server_test class, so parent to socketClient will be Server_test but no Agent_A.
So make parent Agent_A for socketClient object:
socketforClient = new SockClient(this->parent(), server->nextPendingConnection());
Or you can make some others workarounds.
One more note: you make connection to newConnection() signal at your startServer method, not constructor. So if i start server, then stop them and start again server will be connected twice to signal and slot incomingConnection() will be called twice too. So you need disconnect at from signal at stopServer() method or do connection at constructor of class or use Qt::UniqueConnection.

Qt progressBar getting Unhandled exception how detect when parent widget is done loading

im using Qt QProgressBar and place it in the statusBar on my main window
Like this in the constructor :
pb = new QProgressBar(statusBar());
pb->setTextVisible(false);
pb->hide();
statusBar()->addPermanentWidget(pb);
then im running procsses (web page loadding in this case )
and trying to show the progress with :
connect(ui.webView, SIGNAL(loadProgress(int)), SLOT(setProgress (int)));
void myMainWindow:: setProgress(int progress)
{
pb->show();
pb->setRange(0,100);
pb->setValue(progress);
}
But im getting Unhandled exception when it comes to pb->show()
I guess it has to do something with loading the parent main windows and then the progress bar
I was reading about the QAbstractEventDispatcher and processEvents but not understood how to implement it .
i did small test and put the pb->show() function call in button click signal/slut
that means im triggering the pb->show() after the web page and the mainwindows fully loaded and its working fine without the exception. that make me belive there is problem
with the event processing.
here is the class :
class MainWindowMainWindowContainer : public QMainWindow
{
Q_OBJECT
public:
MainWindowContainer(QWidget *parent = 0);
public slots:
void adjustLocation();
void changeLocation();
void adjustTitle();
void setProgress(int p);
void finishLoading(bool);
void finishedSlot(QNetworkReply* reply);
private:
Ui::OnLineBack_mainWindow ui;
int progress;
void createWebViewActions();
QProgressBar *pb;
void setprogressBar(int progress,bool show);
};
MainWindowContainer::MainWindowContainer(QWidget* parent) :
QMainWindow(parent),
{
ui.setupUi(this);
progress = 0;
createWebViewActions();
ui.webView->load(QUrl("www.cnnnn.com"));
ui.webView->show();
pb = new QProgressBar(statusBar());
pb->setTextVisible(false);
pb->hide();
statusBar()->addPermanentWidget(pb);
}
void MainWindowContainer::createWebViewActions()
{
connect(ui.webView, SIGNAL(loadFinished(bool)), SLOT(adjustLocation()));
connect(ui.webView, SIGNAL(titleChanged(QString)), SLOT(adjustTitle()));
connect(ui.webView, SIGNAL(loadProgress(int)), SLOT(setProgress(int)));
connect(ui.webView, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool)));
connect(ui.webView, SIGNAL(linkClicked(const QUrl&)),this, SLOT(linkClicked(const QUrl&)));
}
void MainWindowContainer::setProgress(int p)
{
progress = p;
adjustTitle();
}
void MainWindowContainer::adjustTitle()
{
qApp->processEvents();
pb->show();
if (progress <= 0 || progress >= 100)
{
QString titl = ui.webView->title();
statusBar()->showMessage(titl);
setprogressBar(-1,false);
}
else
{
statusBar()->showMessage(QString("%1 (%2%)").arg(ui.webView->title()).arg(progress));
setprogressBar(progress,true);
}
}
void MainWindowContainer::finishLoading(bool)
{
progress = 100;
adjustTitle();
}
void MainWindowContainer::setprogressBar(int progress,bool show)
{
if(show)
{
pb->show();
pb->setRange(0,100);
pb->setValue(progress);
}
else
{
pb->hide();
}
}
In your createWebViewActions() function you connect the signals to their respective slots. (One small remark, the connect for the titleChanged(QString) signal and adjustTitle() slot fails because they have different signatures)
Among others you are connecting the signal loadProgress(int) to slot setProgress(int). In this slot you call adjustTitle() where the instruction pb->show() is being executed.
Notice that you are calling the createWebViewActions() function before the call to QProgressBar constructor
(...)
createWebViewActions(); <------ here you establish the signal->slot connections
ui.webView->load(QUrl("www.cnnnn.com"));
ui.webView->show();
pb = new QProgressBar(statusBar()); <------ here you call the QProgressBar constructor
pb->setTextVisible(false);
pb->hide();
statusBar()->addPermanentWidget(pb);
(...)
I think that maybe this slot (setProgress()) is being called before the QProgressBar is constructed which triggers the Unhandled exception you are getting.
You could try and move the call to the QProgressBar constructor so that it is created before the slots connection.