Exposing QObjects to Qt Webkit

From Qt Wiki
Jump to navigation Jump to search

Template:Abstract.

Template:ArticleMetaData

Code[edit | edit source]

sampleqobject.h[edit | edit source]

Naturally we need a QObject to expose. When exposing QObjects to the Qt Webkit to be used from JavaScript, remember that only signals and slots will be available.

  1. ifndef SAMPLEQOBJECT_H
  2. define SAMPLEQOBJECT_H
  1. include <QtCore/QObject>
  2. include <QtCore/QMap>
  3. include <QtCore/QString>
  4. include <QtCore/QVariant>

class SampleQObject : public QObject {

   Q_OBJECT

public:

   explicit SampleQObject(QObject *parent = 0);

signals:

   void signal(QMap<QString, QVariant> object);

public slots:

   QMap<QString, QVariant> slotThatReturns(const QMap<QString, 
                                           QVariant>& object);
   void slotThatEmitsSignal();

private:

   int m_signalEmited;
   QMap<QString, QVariant> m_returnObject;
   QMap<QString, QVariant> m_emitSignal;

};

  1. endif // SAMPLEQOBJECT_H

sampleobject.cpp[edit | edit source]

Here are the implementations for signals and slots.

  1. include "sampleqobject.h"
  1. include <QtCore/QDebug>

SampleQObject::SampleQObject(QObject *parent) :

   QObject(parent)

{

   m_signalEmited = 0;

}

QMap<QString, QVariant> SampleQObject::slotThatReturns(const QMap<QString, QVariant>& object) {

   qDebug() << "SampleQObject::slotThatReturns";
   this->m_returnObject.clear();
   this->m_returnObject.unite(object);
   QString addedBonus = QString::number(object["intValue"].toInt(), 
                                        10).append(" added bonus.");
   this->m_returnObject["stringValue"] = QVariant(addedBonus);
   qDebug() << "SampleQObject::slotThatReturns" << this->m_returnObject;
   return this->m_returnObject;

}

void SampleQObject::slotThatEmitsSignal() {

   qDebug() << "SampleQObject::slotThatEmitsSignal";
   this->m_signalEmited++;
   this->m_emitSignal.clear();
   this->m_emitSignal["signalsEmited"] = QVariant(this->m_signalEmited);
   this->m_emitSignal["sender"] = QVariant("SampleQObject::slotThatEmitsSignal");
   qDebug() << "SampleQObject::slotThatEmitsSignal" << this->m_emitSignal;
   emit signal(this->m_emitSignal);

}

mainwindow.ui[edit | edit source]

This is the UI file for the snippet. It references the QWebView which will be used to expose the QObjects.

<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0">

<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
 <property name="geometry">
  <rect>
   <x>0</x>
   <y>0</y>
   <width>600</width>
   <height>400</height>
  </rect>
 </property>
 <property name="windowTitle">
  <string>MainWindow</string>
 </property>
 <widget class="QWidget" name="centralWidget">
  <layout class="QVBoxLayout" name="verticalLayout">
   <property name="spacing">
    <number>0</number>
   </property>
   <property name="margin">
    <number>0</number>
   </property>
   <item>
    <widget class="QWebView" name="webView">
     <property name="url">
      <url>
       <string>qrc:/view.html</string>
      </url>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
 <customwidget>
  <class>QWebView</class>
  <extends>QWidget</extends>
  <header>QtWebKit/QWebView</header>
 </customwidget>
</customwidgets>
<resources/>
<connections/>

</ui>

mainwindow.h[edit | edit source]

Next, we need to tie these all together in a QMainWindow descendant.

  1. ifndef MAINWINDOW_H
  2. define MAINWINDOW_H
  1. include <QMainWindow>
  2. include "sampleqobject.h"

namespace Ui {

   class MainWindow;

}

class MainWindow : public QMainWindow {

   Q_OBJECT

public:

   MainWindow(QWidget* parent = 0);
   ~MainWindow();

private slots:

   void addJavaScriptObject();

protected:

   void changeEvent(QEvent *e);

private:

   Ui::MainWindow* ui;
   SampleQObject* m_sampleQObject;

};

  1. endif // MAINWINDOW_H

mainwindow.cpp[edit | edit source]

  1. include "mainwindow.h"
  2. include "ui_mainwindow.h"
  1. include <QtWebKit/QWebPage>
  2. include <QtWebKit/QWebFrame>

MainWindow::MainWindow(QWidget *parent) :

   QMainWindow(parent),
   ui(new Ui::MainWindow)

{

   ui->setupUi(this);
   /**
     * This is the interesting part, here we create the QObject
     * and connect the QWebViews pages main frames 
     * javaScriptWindowObjectCleared signal to our addJavaScriptObject slot
     * which then exposes the QObject to the WebKit.
     *
     * QWebFrame::javaScriptWindowObjectCleared signal is emitted whenever
     * the global window object of the JavaScript environment is cleared,
     * e.g., before starting a new load.
     * If you intend to add QObjects to a QWebFrame using 
     * addToJavaScriptWindowObject(), you should add them in a slot connected 
     * to this signal. This ensures that your objects remain accessible when 
     * loading new URLs.
     * http://doc.qt.nokia.com/4.7/qwebframe.html#javaScriptWindowObjectCleared
     */
   m_sampleQObject = new SampleQObject(this);
   connect(ui->webView->page()->mainFrame(), 
           SIGNAL(javaScriptWindowObjectCleared()),
           this, 
           SLOT(addJavaScriptObject()));

}

MainWindow::~MainWindow() {

   delete ui;
   delete m_sampleQObject;

}

void MainWindow::changeEvent(QEvent *e) {

   QMainWindow::changeEvent(e);
   switch (e->type()) {
   case QEvent::LanguageChange:
       ui->retranslateUi(this);
       break;
   default:
       break;
   }

}

void MainWindow::addJavaScriptObject() {

   /**
     * This code calls another interesting method 
     * QWebFrame::addJavaScriptObject
     * which can expose any QObject to the JavaScript context with the 
     * name given as the first parameter.
     */
   this->ui->webView->page()
                    ->mainFrame()
                    ->addToJavaScriptWindowObject("sampleQObject", 
                                                  this->m_sampleQObject);

}

Postconditions[edit | edit source]

You've successfully exposed the QObject to the Qt WebKit's web context.

See also[edit | edit source]

Code Snippets for calling slots and connecting signals to JavaScript slots: