Document Completed Signal inside qt using QAxWidget - c++

I'm Using qt Built-in Examples in /examples/activeqt/webbrowser, and i'm trying to use DocumentComplete SIGNAL.
my purpose is using embedded Internet explorer inside QAxWidget and popup a message (with contetnt from the website) after DocumentComplete. NavigateComplete Signal is not good enough for me use...
the code can be seen here : qt Web browser Example
class MainWindow : public QMainWindow, public Ui::MainWindow
{
Q_OBJECT
public:
MainWindow();
public slots:
void on_WebBrowser_TitleChange(const QString &title);
void on_WebBrowser_ProgressChange(int a, int b);
void on_WebBrowser_CommandStateChange(int cmd, bool on);
void on_WebBrowser_BeforeNavigate();
void on_WebBrowser_NavigateComplete(const QString &address);
void on_WebBrowser_DocumentComplete(IDispatch*,QVariant&)
void on_actionGo_triggered();
void on_actionNewWindow_triggered();
void on_actionAddBookmark_triggered();
void on_actionAbout_triggered();
void on_actionAboutQt_triggered();
void on_actionFileClose_triggered();
private:
QProgressBar *m_progressBar;
};
MainWindow::MainWindow()
{
setupUi(this);
connect(m_addressEdit, SIGNAL(returnPressed()), actionGo, SLOT(trigger()));
connect(actionBack, SIGNAL(triggered()), WebBrowser, SLOT(GoBack()));
connect(actionForward, SIGNAL(triggered()), WebBrowser, SLOT(GoForward()));
connect(actionStop, SIGNAL(triggered()), WebBrowser, SLOT(Stop()));
connect(actionRefresh, SIGNAL(triggered()), WebBrowser, SLOT(Refresh()));
connect(actionHome, SIGNAL(triggered()), WebBrowser, SLOT(GoHome()));
connect(actionSearch, SIGNAL(triggered()), WebBrowser, SLOT(GoSearch()));
connect(WebBrowser,SIGNAL(DocumentComplete(IDispatch*,QVariant&), this, SLOT(on_WebBrowser_DocumentComplete(IDispatch*,QVariant&)))
}
void MainWindow::on_WebBrowser_DocumentComplete(IDispatch*,QVariant&)
{
QMessangeBox x;
x.setText("pop-up");
x.exec();
}
the dubbuger says: No such slot MainWindow::on_WebBrowser_DocumentComplete(IDispatch*,QVaria‌​nt&)

As long as the workaround needs more than comment:
MyWidgetUsesActiveX::MyWidgetUsesActiveX()
{
///
connect(m_pActiveX, SIGNAL(signal(const QString&, int, void*)),
this, SLOT(activexEventHandler(const QString&, int, void*)));
}
void MyWidgetUsesActiveX::activexEventHandler(
const QString &name, int argc, void *argv)
{
VARIANTARG *params = (VARIANTARG*)argv;
// See what events fired
qDebug() << "Event:" << name << "argc:" << argc;
// some concrete example
if (name == "OnRemoteWindowDisplayed")
{
// Extract parameters
_variant_t varValue = params[argc-1];
bool bDisplayed = (bool)varValue;
// hwnd
varValue = params[argc-2];
int iResult = (int)varValue;
varValue = params[argc-3];
int windowAttribute = (int) varValue;
// CALL that stubborn slot we cannot have called otherwise
onRemoteWindowDisplayed(bDisplayed, iResult, windowAttribute);
}
else if (name == "OnSomethingElse")
{
// extract concrete parameters and call the handler from here
// onSomethingElse(param1, param2, param3);
}
else
{
// Log it?
}
}

i solved the issue by regenerating the .moc file. under build configuration the folder location of qmake was wrong. by correcting it to project location fixed my problem. the slot is now recognized. thank all for you help.
Qt Build Configuration

Related

QtWebEngine - synchronously execute JavaScript to read function result

I have the following method in one of my C++ classes (using QtWebEngine):
QString get()
{
QString result;
view->page()->runJavaScript("test();", [this](const QVariant &v)
{
result = v.toString();
});
return result;
}
It is to execute test() JS function and return the result of this invocation.
Unfortunately, the callback is asynchronous and the program crashes. How can I make it work?
The callback is asynchronous because the JavaScript execution occurs not only in another thread but in another process. So there is no way to make it fully synchronous.
The best possible solution would be to migrate your C++ code to work asynchronously. If you can't do that, the only feasible solution is to use QEventLoop, somewhat like this:
void ranJavaScript()
{
emit notifyRanJavaScript();
}
QString get()
{
QString result;
QEventLoop loop;
QObject::connect(this, SIGNAL(notifyRanJavaScript()), &loop, SLOT(quit()));
view->page()->runJavaScript("test();", [this](const QVariant &v)
{
result = v.toString();
this.ranJavaScript();
});
loop.exec();
return result;
}
However, note that this example is oversimplified for a real-world usage: you need to ensure the JavaScript was not ran before the event loop is started. The most proper way to do that would involve implementing a proper slot instead of a lambda + factoring out the call to view->page()->runJavaScript() into another slot which would be called asynchronously after starting the event loop. It is a lot of glue code for such a seemingly simple task but that's what it takes. Here's an example:
MainWindow.h
#ifndef TMP_MAIN_WINDOW_H
#define TMP_MAIN_WINDOW_H
#include <QMainWindow>
#include <QVariant>
class QWebEngineView;
class QPushButton;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget * parent = 0);
QString get();
void onScriptEnded(const QVariant & data);
Q_SIGNALS:
void notifyRanJavaScript();
private Q_SLOTS:
void onButtonPressed();
void startScript();
private:
QWebEngineView * m_view;
QPushButton * m_button;
QString m_scriptResult;
};
#endif // TMP_MAIN_WINDOW_H
MainWindow.cpp
#include "MainWindow.h"
#include <QWebEngineView>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QEventLoop>
#include <QDebug>
#include <QTimer>
MainWindow::MainWindow(QWidget * parent) :
QMainWindow(parent)
{
m_view = new QWebEngineView;
QWebEnginePage * page = new QWebEnginePage(m_view);
m_view->setPage(page);
QString html = QStringLiteral("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
"\"http://www.w3.org/TR/html4/strict.dtd\"><html>"
"<head><h3>head</h3>\n</head>"
"<script type=\"text/javascript\">function test() { return \"A!\"; }</script>"
"<body>text\n</body></html>");
m_view->page()->setHtml(html);
m_button = new QPushButton;
m_button->setMinimumWidth(35);
m_button->setText(QStringLiteral("Test"));
QObject::connect(m_button, SIGNAL(pressed()), this, SLOT(onButtonPressed()));
QHBoxLayout * buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(m_button);
buttonLayout->addStretch();
QVBoxLayout * viewLayout = new QVBoxLayout;
viewLayout->addLayout(buttonLayout);
viewLayout->addWidget(m_view);
QWidget * widget = new QWidget(this);
widget->setLayout(viewLayout);
setCentralWidget(widget);
}
QString MainWindow::get()
{
QEventLoop loop;
QObject::connect(this, SIGNAL(notifyRanJavaScript()), &loop, SLOT(quit()));
// Schedule the slot to run in 0 seconds but not right now
QTimer::singleShot(0, this, SLOT(startScript()));
// The event loop would block until onScriptEnded slot is executed
loop.exec();
// If we got here, the script has been executed and the result was saved in m_scriptResult
return m_scriptResult;
}
void MainWindow::onScriptEnded(const QVariant & data)
{
qDebug() << QStringLiteral("Script ended: ") << data;
m_scriptResult = data.toString();
emit notifyRanJavaScript();
}
void MainWindow::onButtonPressed()
{
QString str = get();
QMessageBox::information(this, QStringLiteral("Script result"), str,
QMessageBox::StandardButton::Ok);
}
struct Functor
{
Functor(MainWindow & window) : m_window(window) {}
void operator()(const QVariant & data)
{
m_window.onScriptEnded(data);
}
MainWindow & m_window;
};
void MainWindow::startScript()
{
qDebug() << QStringLiteral("Start script");
m_view->page()->runJavaScript(QStringLiteral("test();"), Functor(*this));
}
Dmitry's solution only works partially, unfortunately. In his example the code is invoked upon pressing a button. However, if the same code is moved to execute while the window is loading, the slot for the finished script (onScriptEnded) is never called. To fix this, I had to wrap the call to the evaluation of JS itself (called evaluateJavaScript in my project) in another QTimer::singleShot:
QTimer::singleShot(0, this, [&] { evaluateJavaScript(); });
Unfortunately, in my real project I have many calls, often one evaluation waiting for another before it to finish. It's practically impossible to use this every single time so I still look for a solution.
In the kchmviewer project, I found a very easy way to wait for the result of the runJavaScript function. The following code is part of the ViewWindow class which inherits from QWebEngineView.
int ViewWindow::getScrollbarPosition()
{
QAtomicInt value = -1;
page()->runJavaScript("document.body.scrollTop", [&value](const QVariant &v)
{
qDebug( "value retrieved: %d\n", v.toInt());
value = v.toInt();
});
while (value == -1)
{
QApplication::processEvents();
}
qDebug( "scroll value %d", value.load() );
return value;
}

Qt5/C++ release mouse during mousePressEvent

I've a QGridLayout where each cell contains my custom widget QFrameExtended defined as follow:
In .h:
#ifndef QFRAMEEXTENDED_H
#define QFRAMEEXTENDED_H
#include <QObject>
#include <QFrame>
class QFrameExtended : public QFrame
{
Q_OBJECT
private:
public:
int id;
explicit QFrameExtended(QWidget *parent = 0);
signals:
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void pressed(QFrameExtended *);
void released(QFrameExtended *);
public slots:
void on_mouse_press();
void on_mouse_release();
};
#endif // QFRAMEEXTENDED_H
In .cpp:
#include "qframe_extended.h"
QFrameExtended::QFrameExtended(QWidget *parent) : QFrame(parent)
{
this->id = /* Imagine here there is a function to generate an id */ ;
connect( this, SIGNAL( mousePressEvent(QMouseEvent*) ), this, SLOT( on_mouse_press() ) );
connect( this, SIGNAL( mouseReleaseEvent(QMouseEvent*) ), this, SLOT( on_mouse_release() ) );
}
void QFrameExtended::on_mouse_press() {
emit pressed(this);
}
void QFrameExtended::on_mouse_release() {
emit released(this);
}
My form creates the QGridLayout with the QFrameExtended widgets and for each of them defines an event handler:
/* ... */
/* This snippet of code is inside a loop that is creating frame objects */
connect(frame, &QFrameExtended::pressed, this, &MyForm::on_mouse_press);
connect(frame, &QFrameExtended::released, this, &MyForm::on_mouse_release);
/* ... */
and finally these are the event handlers:
void MyForm::on_mouse_press(QFrameExtended *frame) {
qDebug() << "Pressed here: " << frame->id << endl;
}
void MyForm::on_mouse_release(QFrameExtended *frame) {
qDebug() << "Released here: " << frame->id << endl;
}
When I click on a cell (i.e. a QFrameExtended widget) without release the button, I would see printed on the console the id of the cell. After I moved the mouse over another cell, when I release the button I would see printed the second id.
An example is an output like this:
Pressed here: 1
Released here: 3
but the reality is that when I press the mouse button over a QFrameExtended, he starting to grab all mouse events until I release the button. This is the expected behaviour:
Qt automatically grabs the mouse when a mouse button is pressed inside a widget; the widget will continue to receive mouse events until the last mouse button is released.
From: http://doc.qt.io/qt-4.8/qmouseevent.html
How can I change this behaviour? I'll really appreciate if you can give me also an example
Ok, I resolved following the tip of peppe. I tried to extend the QGridLayout but layouts don't support mouse events, because don't inherit from QWidget. So, I extended the QWidget that contains the layout.
In .h:
#ifndef QWIDGETEXTENDED_H
#define QWIDGETEXTENDED_H
#include <QWidget>
#include <QString>
#include <QMouseEvent>
#include "qframe_extended.h"
class QWidgetExtended : public QWidget
{
Q_OBJECT
public:
explicit QWidgetExtended(QWidget *parent = 0);
protected:
virtual void mousePressEvent(QMouseEvent *);
virtual void mouseReleaseEvent(QMouseEvent *);
signals:
void pressed(QFrameExtended *);
void released(QFrameExtended *);
};
#endif
In .cpp:
#include "qwidget_extended.h"
#include "qframe_extended.h"
QWidgetExtended::QWidgetExtended(QWidget *parent) : QWidget(parent)
{
}
void QWidgetExtended::mousePressEvent(QMouseEvent *event) {
QFrameExtended frame;
QWidget *widget = this->childAt(event->pos());
if (widget != NULL) {
QString widgetClassName(widget->metaObject()->className());
//I don't use explicitly the string because if one day someone changes the name of the class, the compiler will output an error
QString className(frame.metaObject()->className());
if (widgetClassName == className) {
emit pressed(dynamic_cast<QFrameExtended*> (widget));
}
}
}
void QWidgetExtended::mouseReleaseEvent(QMouseEvent *event) {
QFrameExtended frame;
QWidget *widget = this->childAt(event->pos());
if (widget != NULL) {
QString widgetClassName(widget->metaObject()->className());
//I don't use explicitly the string because if one day someone changes the name of the class, the compiler will output an error
QString className(frame.metaObject()->className());
if (widgetClassName == className) {
emit released(dynamic_cast<QFrameExtended*> (widget));
}
}
}

Qt: Context menu / connect with parameters

I have a problem connecting context menu actions in Qt. I know there are plenty of similar questions around, nevertheless I couldn't find a solution yet.
I have a series of plots built using QCustomplot.
What I want to do is to create a context menu when right-clicking on the background of each plot listing all the signal present in the graph. By clicking an entry of this menu, the corresponding signal should be hidden (if currently visible) or made visible (if hidden).
Now, I've defined a class called PlotHandler of which I paste the relevant parts here below:
plotHandler.cpp
#include "plothandler.h"
PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
QWidget(parent), scrolling(false), refreshing(true)
{
pPlot = new QCustomPlot(this);
pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}
void PlotHandler::contextMenuRequest(QPoint pos)
{
int i;
QMenu *menu = new QMenu(this);
for(i=0; i<pGroup->getDataLength(); i++)
{
QAction *menuEntry;
menuEntry = new QAction(pPlot->graph(i)->name(), this);
menuEntry->setProperty("graphIdx", i);
menu->addAction(menuEntry);
connect(menuEntry, SIGNAL(triggered()), this, SLOT(addRemoveGraph()));
}
menu->popup(pPlot->mapToGlobal(pos));
}
void PlotHandler::addRemoveGraph()
{
QAction *selectedSignal = qobject_cast<QAction *>(sender());
int tmp = selectedSignal->property("graphIdx").toInt();
if (pPlot->graph(tmp)->visible())
{
pPlot->graph(tmp)->setVisible(false);
}
else
{
pPlot->graph(tmp)->setVisible(true);
}
}
plotHandler.h
class PlotHandler : public QWidget
{
Q_OBJECT
public:
explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
QString groupRequested();
private:
QCustomPlot *pPlot;
public slots:
void contextMenuRequest(QPoint pos);
void addRemoveGraph();
}
The menu is correctly showed with the right entries and when I click on an action addRemoveGraph is called. In debug it gives back the following message:
The inferior stopped because it triggered an exception. Stopped in
thread 0 by: Exception at 0x5d6c2f9a, code: 0xc0000005: read access
violation at: 0x0, flags=0x0.
trying to execute
int tmp = selectedSignal->property("graphIdx").toInt();
Could anyone point me towards the right direction?
Thanks in advance
You use QObject::setProperty but QAction doesn't have a property named "graphIdx". When you attempt to read the "graphIdx" property from QAction you will always get an invalid QVariant.
int tmp = selectedSignal->property("graphIdx").toInt();
// tmp always is 0;
You can use QAction::setData if you need to store only one property. Otherwise, use QObject::setProperty to set a custom property on any QObject. QAction is a QObject.
Here below the solution that solved the issue.
plotHandler.cpp
#include "plothandler.h"
PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
QWidget(parent), scrolling(false), refreshing(true)
{
pPlot = new QCustomPlot(this);
pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}
void PlotHandler::contextMenuRequest(QPoint pos)
{
int i;
QMenu *menu = new QMenu(this);
for(i=0; i<pGroup->getDataLength(); i++)
{
QAction *menuEntry;
menuEntry = new QAction(pPlot->graph(i)->name(), this);
menuEntry->setData(i);
menu->addAction(menuEntry);
}
connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(addRemoveGraph(QAction*)));
menu->popup(pPlot->mapToGlobal(pos));
}
void PlotHandler::addRemoveGraph(QAction *selectedSignal)
{
int tmp = selectedSignal->property("graphIdx").toInt();
if (pPlot->graph(tmp)->visible())
{
pPlot->graph(tmp)->setVisible(false);
}
else
{
pPlot->graph(tmp)->setVisible(true);
}
pPlot->replot();
}
plotHandler.h
class PlotHandler : public QWidget
{
Q_OBJECT
public:
explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
QString groupRequested();
private:
QCustomPlot *pPlot;
public slots:
void contextMenuRequest(QPoint pos);
void addRemoveGraph();
}
Thanks everyone for your help.

Unable to display QDialog/QProgressbar

I have design an app is C++/Qt to transfer file between my Mac to Android Device.
to do this, I have created a class QDialog as shown below:
dialog.cpp
Dialog::Dialog(QWidget *parent)
: QWidget(parent)
{
}
void Dialog::CreateProgressBar() {
ProgressDialog = new QWidget(this);
ProgressDialog->setWindowTitle("Progress");
ProgressLayout = new QVBoxLayout(this);
ProgressIndicator = new QProgressBar();
ProgressIndicator->resize(200,25);
ProgressIndicator->setValue(0);
ProgressIndicator->setOrientation(Qt::Horizontal);
//connect(this,SIGNAL(ProgressBar(const uint64_t, const uint64_t, void const * const)),ProgressIndicator,SLOT(setValue(int)));
CancelButton = new QPushButton();
CancelButton->setFixedSize(25,25);
CancelButton->setText("Cancel");
CancelButton->setFlat(true);
CancelButton->setAutoFillBackground(true);
CancelButton->setStyleSheet("QPushButton { background-color : white;}");
connect(CancelButton, SIGNAL(clicked()), this, SLOT(onCancelButtonAction()));
ProgressLayout->addWidget(ProgressIndicator);
ProgressLayout->addWidget(CancelButton);
ProgressDialog->setLayout(ProgressLayout);
ProgressDialog->show();
}
void Dialog::setValue(const uint64_t value) {
ProgressIndicator->setValue(value);
}
void Dialog::DestroyProgressBar() {
ProgressDialog->close();
}
dialog.h
class Dialog : public QWidget
{
Q_OBJECT
public:
Dialog(QWidget *parent = 0);
/* ProgressIndicator */
//int ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data);
void CreateProgressBar();
void DestroyProgressBar();
int createOverwriteDialogBox(char* filename);
void setValue(const uint64_t value);
void WaitBoxDialog();
void DestroyWaitBoxDialog();
private:
QWidget *ProgressDialog;
QProgressBar *ProgressIndicator;
QVBoxLayout *ProgressLayout;
QPushButton *CancelButton;
To display it, I'm currently having a source code called wrapper.cpp which is in charge on managing the copy.
When managing the Copy, and before colling the API LIBMTP_Send_File_to_File, I start the method instantiation.
Dialog *MyProgress = new Dialog();
MyProgress->CreateProgressBar();
genfile = LIBMTP_new_file_t();
LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, NULL, NULL);//ProgressBar, MyProgress);
LIBMTP_destroy_file_t(genfile);
MyProgress->DestroyProgressBar();
//delete MyProgress;
}
I'm still don't understand why I couldn't see the dialog.
I think you need two threads, one to do your processing and the other one to keep the GUI running. Something like this:
#include <QFutureWatcher>
#include <QMetaObject>
#include <QtConcurrent/QtConcurrentRun>
void sendFile()
{
LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, NULL, NULL);
QMetaObject::invokeMethod(MyProgress, "setValue", Q_ARG(int, 50));
LIBMTP_destroy_file_t(genfile);
}
MyProgress->CreateProgressBar();
QFutureWatcher<void> futureWatcher;
connect(futureWatcher, SIGNAL(finished()), MyProgress, SLOT(DestroyProgressBar()));
futureWatcher.setFuture(QtConcurrent::run(sendFile));
You'll need to make setValue and DestroyProgressBar public slots, of course.

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.