Håvard Frøiland
Qt
KDE
Qt Jambi
WebKit
 in Qt, KDE, Qt Jambi, WebKit
 on Friday, January 11, 2008 @ 11:58

There is almost always room for a browser in a desktop application. You might need to show some help pages, documents, formated source code, xml or what not. And then you need a browser.

Up to now these browsers have often been limited to show some simple html. But with Qt 4.4 and Qt Jambi 4.4 we will have a proper WebKit integration and voila.. you have a full fledged web browser at your fingertips.

Let’s have a quick look at what it can do!

browser1.pngbrowser21.png

Oi, that looks promising.. Let’s have a look at the source code to this example that has been written using Qt Jambi.

import com.trolltech.qt.core.*;
import com.trolltech.qt.gui.*;
import com.trolltech.qt.webkit.*;       

class HelloWebKit extends QWidget {       

    private QWebView browser;
    private QLineEdit field;       

    public HelloWebKit() {
        field = new QLineEdit();
        browser = new QWebView();       

        QVBoxLayout layout = new QVBoxLayout(this);
        layout.addWidget(field);
        layout.addWidget(browser);       

        field.returnPressed.connect(this, "open()");
    }       

    public void open() {
        String text = field.text();       

        if (text.indexOf("://") < 0)
            text = "http://" + text;       

        browser.load(new QUrl(text));
    }       

    public static void main(String args[]) {
        QApplication.initialize(args);       

        HelloWebKit widget = new HelloWebKit();
        widget.show();       

        QApplication.exec();
    }
}

That wasn’t difficult was it :-) But can this actually render some normal webpages.. yes it can. So here goes another screenshot :-)

browser3.png

Håvard Frøiland
Qt
Qt Jambi
 in Qt, Qt Jambi
 on Friday, June 08, 2007 @ 09:09

Qt Jambi is a new product that will let Java programmer harvest the power of Qt. Now it turns out that it’s not only Java addicts that should get excited. There are a bunch of languages that compiles to byte code, and are using the existing JVM as it’s runtime. I set out to investigate the possibilities, and it is looking good :-)

Let’s start by looking at Kawa . Kawa is an implementation of Scheme, which is in the Lisp family of programming languages. So let’s try to open a file dialog, and connect it’s signal currentChanged to println. To run the code below, just make sure kawa is in your path, and that the the qtjambi.jar is in the classpath.

#!/usr/bin/env kawa.sh

(invoke-static <com.trolltech.qt.gui.QApplication> 'initialize (<java.lang.String[]>))

(set! fileDialog (make <com.trolltech.qt.gui.QFileDialog>))
(*:show fileDialog)

(*:connect (*:.currentChanged fileDialog)
	   (<java.lang.System>:.out) "println(String)")

(invoke-static <com.trolltech.qt.gui.QApplication> 'exec )

Hey, that worked just perfect. It opened a file dialog, and printed out the name of the selected file to the console.

Ok, let’s have a look at Groovy. We will try to do something a bit more complicated this time. Let’s make an interactive graph plotter.

groovy-1.png

import com.trolltech.qt.core.*
import com.trolltech.qt.gui.*

class FunctionPlotter extends QWidget {
    FunctionPlotter(parent) {
        super(parent)
    }

    def function 

    def protected void paintEvent(QPaintEvent e) {
        QPainter painter = new QPainter(this);
        painter.translate((int)(width()/2), (int)(height()/2))
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        painter.setPen(QColor.blue)
        painter.drawLine((int)(-width()/2), 0, (int)(width()/2), 0)
	painter.drawLine(0, (int)(-height()/2), 0, (int)(height()/2))
	painter.setPen(QColor.black)

        double y;
	double x = -width()/2;
	while (x < width()/2) {

	    try {
                y = function(x)
                painter.drawPoint((int)x, (int)-y)
	    }
            catch(exeption){}

            x++;
        }
	painter.end()
    }

    def public void eval(String s) {
        System.out.println("Eval: " + s);
	def shell = new GroovyShell()
	try{
	    function = shell.evaluate("{x -> " + s + "}")
	    update()
	}
	catch(e){}
    }

    def protected QSize sizeHint() {
	new QSize(500, 400)
    }
}

class Fun extends QWidget {

    def input = new QLineEdit(this)
    def plotter = new FunctionPlotter(this)

    Fun(parent) {
        super(parent)
        def QVBoxLayout layout = new QVBoxLayout()
	layout.addWidget(input)
	input.setText("Math.cos(x / 50) * 300")
        plotter.eval(input.text())
	layout.addWidget(plotter)
	setLayout(layout)
	input.textEdited.connect(plotter, "eval(String)")
    }
}

QApplication.initialize( this.args )

def fun = new Fun(null)
fun.show();

QApplication.exec();

That was fun :-), so what did we do. We created a widget (Fun) with a QLineEdit and a custom FunctionPlotter widget. Then we connected the QLineEdit’s input to the FunctionPlotters eval function. The FunctionPlotters eval function would try to evaluate the expression, and assign the resulting function to the function variable. Each time the widget needs to paint the graph, it will call this function for each x value that fit’s on the plot, and plot a dot for the result.

This approach is of course fairly unsafe, since you could write a function that formated your harddrive, but it also shows some of the power of a scriptable language.

Good luck with exploring the possibilities, and post a comment when you have tried some other languages.