Thiago Macieira
Qt
KDE
Qt Jambi
Contributors
QtCreator
QtMobility
Posted by Thiago Macieira
 in Qt, KDE, Qt Jambi, Contributors, QtCreator, QtMobility
 on Tuesday, October 27, 2009 @ 10:05

For those of you who don’t read the new Qt blog website, where Qt Marketing and Product Management talk about “corporatey” stuff (affectionately called the “PHB blog” by our developers), we’ve just announced that our brand, new bugtracker is public: see http://bugreports.qt.nokia.com.

So, I won’t repeat everything that is in the other blog (it is, after all, written by Marketing, so it should be better written than this thrown-together “reblogging”). I’d just like to highlight one important point that Adam made in his blog:

The Qt Bug Tracker isn´t simply a read-only view into the bug tracking system used by Qt developers, it is the bug tracking tracking system used by Qt developers.

The previous solution was an in-house system we had built over the years. It started as a distribution list for the Qt developers back in the day, then got an automatic tool to reply to the emails received and assign numbers, a robot to collect incoming emails and add to the database. Internally, we’ve had a rich-client to access that database and manipulate our own bugs. But communicating with the reporters was always very difficult.

This new tool is different. Everything is on the web. And you get to vote on issues, even watch if they change.

This is another step in our opening up of our development model. Enjoy!

Eskil Abrahamsen Blomfeldt
Qt Jambi
Bindings Generator
 in Qt Jambi, Bindings Generator
 on Friday, October 02, 2009 @ 18:01

Ever since Nokia announced that the official support for Qt Jambi would end after the 4.5 series, I’ve had a few people ask me how they can help adapt the Qt 4.6 changes to Qt Jambi. I thought this blog would be a good place to offer my experiences on the subject, so here’s a short guide. I will use the current state of the Qt 4.6 branch as an example and try to focus on the different steps and considerations you will need to take to get a functioning Qt Jambi 4.6.0.

Please note that I won’t actually make all the modifications necessary, but I’ll try to outline what you need to do in order to get there yourself.

Prerequisites
In order to be able to do this work, you should be confident with both Java programming and C++ programming. You should also read up on JNI (no magic there, but it will help if you recognize the function calls.) Knowing a little bit of Qt Jambi and Qt, so that you understand the design principles behind the APIs, is also very useful. And you should read up on the Qt Jambi type system, and try to get familiar with the binding code generated by the Qt Jambi Generator.

There is a lot of complexity to manage in the binding code, so try to keep a cool head. Even if you don’t understand each detail in the generated code, it is helpful to understand how a function declaration in C++ ends up as a functioning Java method once you have run the Qt Jambi Generator. Please read the article on the Generator in Qt Quarterly issue 29 [pdf]. This contains an overview of the bindings-layer in Qt Jambi and some reasoning behind the complexities within.

Getting the sources
First of all, you need to get the sources for both Qt and Qt Jambi, and you need to be able to build them. This is also covered elsewhere, so I won’t spend much time on it here, but just link you in the right direction. What you need to do is:

  1. Make a local clone of the Qt repository. The command to do this is listed in the header of the repository home page.
  2. Build Qt (should be well-documented elsewhere.)
  3. Make a clone of Qt Jambi in Gitorious so that you have somewhere to upload your work. This is done by making a user in Gitorious and hitting the “Clone this repository” link on the Qt Jambi repository.
  4. Make a local clone of the repository you just made on your hard drive. The command to do this is listed on your repository’s home page.
  5. Build Qt Jambi. There are helpful instructions in the project wiki.

I myself have made a clone of the Qt Jambi repository called “eskils-clone” which contains all the changes made in the course of this blog.

Getting started
The first thing I always do when porting a new version of Qt to Java, is to run the Qt Jambi generator. This is part of the top level ant build, but sometimes it helps to run it manually so you can properly see all its output.

Example on Windows (assuming %JAMBIDIR% contains the location of your Qt Jambi clone):

cd %JAMBIDIR%\generator
release\generator --output-directory=..

NOTE: Two handy command line arguments for the Qt Jambi Generator are --dummy and --diff. The former will run a dummy run, meaning that it will take all steps related to generating the files, except for actually writing the files to the disk. That way you can test the impact of your changes without actually committing anything to the generated files. The --diff argument causes the Generator to show you a detailed listing of the changes which will be made to each generated file.

The final output from the Generator is the number of files generated during the run. The number in parentheses is the number of files which were actually overwritten (because they had been modified since the previous run.)

In the current state, you will see lots and lots of warnings. Most of these are due to missing declarations in the type system for new APIs. The very minimal work we have to do when porting new API to Qt Jambi, is to go through all new types and identifying them in the type system. To help us in this work, the Qt Jambi Generator outputs a set of .log-files which contain potential issues.

  1. mjb_rejected_classes.log: Lists all (implicitly or explicitly) rejected classes.
  2. mjb_rejected_enums.log: Lists all rejected enum types.
  3. mjb_nativepointer_api.log: Lists all functions that use QNativePointer as argument type or return type.
  4. mjb_object_type_usage.log: Lists functions that are in danger of passing an object from C++ into Java that has limited life time.
  5. mjb_reference_count_candidates.log: Lists functions that (based on their name and signature pattern) may retain references to objects owned by Java.

I’ll look at each of them in order. It is useful to follow the order from the list above, as modifications made to fix some issues might create more entries in other .log-files. For instance, if a class has no type system entry, its functions will not be checked for e.g. native pointer API. Thus, when the class is added to the type system, you can get several more issues in the nativepointer API log.

Rejected classes
As a first step, we go through the “mjb_rejected_classes.log” file. This contains a list of “rejected classes”. The rejected classes are the classes which were defined in the Qt headers, but which for some reason did not make it into the generated Java API. In the beginning of the file, there is a section called “Not in type system”. This section contains the names of all classes which were rejected because they had no type system entry, the ones which were implicitly rejected. These are the ones we will focus our attention to, as all the other entries in the list have been rejected on purpose.

For each of the entries in the list, we need to identify two things: Which module it belongs to, and whether it is an object type, a value type or an interface type. Most of the time, this is easy, but tedious work. We go through the list of classes one-by-one, and make entries for them in the correct type system.

Each type system consists of three files: typesystem_<module>-common.xml, typesystem_<module>-java.xml and typesystem_<module>-java.java. When running the ant task, the first two will be merged into a single file called typesystem_<module>.xml. Make sure you edit the correct files, because if you edit the merged file, your changes will be overwritten the next time you run the ant build.

The reason the type system is split up this way, is that the “common” file should contain data which is not specific to any particular target language, and could thus be used for generating e.g. QtScript or Python bindings. Anything which is particular to Java and the JNI binding layer (like Java code injections etc.) needs to go into the Java-specific XML-file.The typesystem_<module>-java.java file contains snippets of Java code which are injected into the generated classes in Qt Jambi. It has been formatted to be viewable in a Java editor and get correct highlighting. This is simply a convenience to make maintaining the code snippets easier, as you can also put the code directly into the XML files.

  1. The first class we see in the mjb_rejected_classes.log file is “QAbstractAnimation”.
  2. Looking at the documentation, we can tell that this class belongs to the “QtCore” module. It should thus be declared in the typesystem_core-common.xml file. We put all type declarations in the common file, since this information is useful to any language bindings.
  3. Looking further at the documentation, we see that this class inherits QObject. That means it’s definitely an object type, since our design principles do not allow value types to inherit from object types, and since QObjects cannot be interfaces in Qt.

Based on this reasoning, we make an entry in typesystem_core-common.xml as follows:

<object -type name="QAbstractAnimation" />

Merging the XML files and running the Qt Jambi Generator again, we’ll see that the QAbstractAnimation entry is missing from the new mjb_rejected_classes.log file:

cd %JAMBIDIR%
ant generator.xmlmerge
cd generator
release\generator --output-directory=..

Remember to run the “generator.xmlmerge” ant task first, otherwise your changes will have no effect when running the Qt Jambi Generator. All types in QtKinetic and the QtStateMachine framework are object types, so I tagged them all as such.

To identify the meta type of a given class, it’s useful to look at its contents and how it’s used.

  • If it has virtual functions, either by inheritance or declared in the class, it is either an object type or an interface type.
  • If it is usually passed by pointer, it is probably an object type.
  • If it is usually passed by const-reference, it is probably a value type.
  • If it has a copy constructor, it is probably a value type.
  • The most precise way to make the distinction, however, is to understand what the class does and how it is used. If it represents a value, and not a specific, unique instance of a class, it is a value type. For instance: Does sameness of the contents of two objects of the class imply sameness of the objects themselves? For an object type, the object can only be identical to itself, while value types can be identical to any object representing the same value.
  • Identifying interface types is a little bit more complicated. Any object type which does not inherit QObject can potentially be an interface type. If the type is used for multiple inheritance in Qt, it is a candidate for an interface type. All but one class used in multiple inheritance must be declared as interface types.
  • Usually we identify interface types as part of fixes for compilation errors unless it’s obvious when going through the list of rejected classes.
  • Lets do one more. In the list of rejected classes, we find the class “QByteArrayMatcher::Data”. Looking at the documentation, we see that this class is not documented. This usually implies that the class is internal and should not be mapped to Qt Jambi. Since documentation is not always up-to-date prior to release, however, we can check the source code to be sure. In this case, the class is declared as private to QByteArrayMatcher, so we won’t be able to access it from the binding layer, even if we wanted. In cases like these, we will explicitly reject the class:

    <rejection class="QByteArrayMatcher::Data" />

    In my clone I’ve added the type declarations for all new classes in the modules we currently support in Qt 4.6. For new modules (such as QtMultimedia) you would need to set up a type system for the module first, mimicking the approach taken in the other type systems.

    Rejected enum types
    The next step when all classes have been mapped, is to look at the mjb_rejected_enums.log file. The relevant section is “Not in type system” in this log file as well.

    In the case of enum types, you will need to consider three things:

    1. What module the type belongs to
    2. Whether you want to map the type
    3. Whether the type is a regular enum type or a flags type.

    In the last case, the enum type will have an accompanying QFlags declaration, which needs to be specified as the flags type of the enum type.

    Take for instance the QAbstractAnimation::DeletionPolicy enum type:

    <enum -type name="QAbstractAnimation::DeletionPolicy" />

    This is a regular enumeration and is not used as a flag type, so we simply declare it in the type system. A enum type such as QGraphicsEffect::ChangeFlag, however, is clearly a flags type, and must be declared as such:

    <enum -type name="QGraphicsEffect::ChangeFlag" flags="QGraphicsEffect::ChangeFlags" />

    I’ve done this for all new enum types.

    Looking at the warnings
    Reading the warnings produced by the Qt Jambi Generator can often give you useful hints about why the generated code might not compile. Therefore it’s handy to go through all the warnings one-by-one, and either fix them or at least understand why they are happening before we move on. Some warnings alert you that a Java version of a given function has not been generated because either a return type or argument type was not recognized. This is e.g. the case with “skipping function ‘QByteArray::QByteArray’, unmatched parameter type ‘Qt::Initialization’”. The argument type “Qt::Initialization” is an internal enum type and was rejected when the enum types were mapped in the type system. Thus, the constructor expecting such an argument must also be internal, and should be rejected. We thus want to ignore this warning, and, indeed, all warnings regarding the type Qt::Initialization, so we add the following to the type system:

    <suppress -warning text="WARNING(MetaJavaBuilder) :: skipping * unmatched *type 'Qt::Initialization'"/>

    This will remove any warning regarding a function or field which has been skipped because it uses the internal type. The other warnings of the same type need to be considered individually.

    Another warning which occurs alerts us of “private virtual functions”. This is a sign of either a bug in the original API, or a hack in the original API which cannot be mapped into Java, where a virtual function is overridden as private in a subclass to avoid it being called from the outside in the cases where the object has been typed to the subclass. There is usually nothing you can do in such a case unless you can change the original API, so such warnings should usually be suppressed as well.

    I’ve suppressed all warnings that we do not intend or need to fix.

    A third warning which we can also suppress is regarding classes with equals operators but not qHash() functions related to them. These classes will be slow when used as key types for a hash table. If we think it makes sense to provide this functionality, we can implement a qHash() function for the classes (e.g. in “%JAMBIDIR%\qtjambi_core\qtjambi_core_qhashes.h“). Otherwise we can suppress the warnings.

    There is one warning concerning an “unsupported default value”. This is a non-critical warning, as the only result is that the function in question will not have a default value for its argument in the Java version. It should be fixed when cleaning up the rest of the API, using the replace-default-expression tag, but we can leave it for now.

    The remaining warnings are more severe. Lets look at them one-by-one.

    Shadowing: QObject::children() const and QGraphicsObject::children() const; Java code will not compile
    This warning informs us that the class QGraphicsObject uses function shadowing in C++, something which is not allowed in Java. In order for the code to compile, we either need to rename the Java version of the function to something which does not collide with function names in the superclasses, or we need to reject the function.

    In this case, we can see from the code that the function declaration is an implementation detail to select the correct instance of a function in the multiple inheritance graph. Since we don’t have this problem in Qt Jambi (QGraphicsItem::children() is already rejected by the type system since it is deprecated), we simply reject the function:

    <object -type name="QGraphicsObject">
    <modify -function signature="children()const" remove="all" />
    </object>

    namespace ‘com.trolltech.qt.core.QXmlStreamReader’ for enum ‘ReadElementTextBehaviour’ is not declared
    This warning message tells us that we have wrongfully placed the enum type “ReadElementTextBehavior” in the type system for QtCore, rather than QtXml where it belongs. Even though the QXmlStreamReader currently resides in QtCore in C++, it resides in the XML module in Qt Jambi. The reason for this is that the class was originally defined in QtXml in C++, but moved at a later time. This change was binary compatible in C++, but not in Java, so we could not move the class in Qt Jambi.

    Therefore, we need to remember to place declarations directly related to this class in the XML type system instead. Fixing this error is simply a case of moving the enum-type declaration.

    Duplicate enum values
    In Qt Jambi, it is not possible for several enums to share a single value. When this happens, we have to reject all but one of the offending enums.

    Sometimes the cause of the error is that an enum has been renamed in C++. Since there are no restrictions on the number of enums that can share the same integer value in C++, renaming will sometimes happen by introducing a new identifier and deprecating the old. This is the case e.g. for QWebSettings::WebAttribute, where the “LocalStorageDatabaseEnabled” enum has been renamed to “LocalStorageEnabled”. In these cases, we must prefer the old identifier in Java to maintain binary compatibility. In such cases, the C++ and Java APIs will necessarily diverge:

    <enum -type name="QWebSettings::WebAttribute">
    <reject -enum-value name="LocalStorageEnabled" />
    </enum>

    Other times, several enums have intentionally been given the same value in C++ as part of the API. For instance, QWebHistory::HistoryStateVersion has a “DefaultHistoryVersion” which points to the current default among the other enums. In this case, we have to reject the DefaultHistoryVersion enum, and lose that part of the API.

    A final problem is in the case of Qt::Modifier. In this case the Generator reports that all enums are set to zero. Looking at the code, we see that the enums in C++ are assigned to values in another enum type, and this is not currently supported by the Qt Jambi Generator. Until the Generator can be adapted to support this syntax, we have to reject the enum type Qt::Modifier from the type system. This will undoubtedly cause problems down the line, when new API begins using the enum type, but for now, we ignore it.

    Class inherits from polymorphic class, but has no polymorphic id set
    This will be the case when e.g. new events or style options are added to Qt. In the type system, we need to address how the binding layer can differentiate between different subclasses of a polymorphic type which is not a QObject. The expression that is generated for QEvent in particular, is given in the declaration in the type system:

    <object -type name="QEvent" polymorphic-base="yes" polymorphic-id-expression="%1-&gt;type() == QEvent::None"/>

    This declaration tells us that QEvent is the base class of a polymorphic hierarchy of classes. The “%1″ token is replaced by the object name in the generated code, and the given expression is evaluated at runtime to decide whether the object is of the given type. In this case, the object is an object of QEvent (and not a subclass) when the type() function returns QEvent::None.

    We need to add similar expressions for the declarations of the new events. For instance, we add the following to the declaration of QTouchEvent:

    <object -type name="QTouchEvent" polymorphic-id-expression="%1-&gt;type() == QEvent::TouchBegin || %1-&gt;type() == QEvent::TouchUpdate || %1-&gt;type() == QEvent::TouchEnd" />

    In either of these three cases, a QEvent object should be cast to QTouchEvent.

    Signature for function modification not found
    This seems to be a bug in the Qt Jambi Generator, but it will have to be studied more closely. For the time being, we can ignore the warning.

    Try compiling it
    Then the time has come to try to compile Qt Jambi 4.6. At this point, we should have a pretty good start, since we’ve gone through all warnings and fixed the ones that would hinder compilation. However, there will most certainly be minor issues left that we need to fix before we are done.

    The only way to find out, is to run the ant build and wait for the results. Then we need to go through each compile error and see what we can do to fix them. I’ll list the errors I get here, and the solution I find for them.

    Cannot open include file: ‘foobar.h’: No such file or directory
    The compiler reports that it’s unable to locate certain include files required by the generated code. This is because the classes have wrongfully been declared in the QtCore module in the type system, but are actually declared in QtGui in the C++ headers. Since the QtGui headers are not available when compiling the QtCore module, compilation fails. The fix is to move the declarations in question into the GUI type system.

    cannot convert from ‘QEasingCurve::EasingFunction’ to ‘double’
    The compiler reports a couple of errors regarding conversion between QEasingCurve::EasingFunction and double. Looking at the documentation for the former, we see that it is a typedef for a function pointer. Since we do not support function pointer APIs in Qt Jambi, the Generator is confused, and we need to reject the functions that use this type in the type system.

    <value -type name="QEasingCurve">
    <modify -function signature="customType()const" remove="all" />
    <modify -function signature="setCustomType(double)" remove="all" />
    </value>

    Using QEasingCurve::EasingFunction in place of double, you would get a warning telling you the correct syntax of the signature in the eyes of the Qt Jambi Generator. Since it does not understand the function pointer type, it has assumed that EasingFunction is a typedef for “double”, and thus we must use this in our signatures (unless we actually declare QEasingCurve::EasingType as a primitive type in the type system.)

    In order to match the API in C++ as well as possible, we have to make sure we adapt a similar, hand-written API in Qt Jambi. This will be left for later. Until then, custom easing curves will not be supported by Qt Jambi.

    Compile errors for QGenericMatrix
    When compiling the QtGui module in the bindings, we see errors related to QGenericMatrix. Looking at the documentation for this, we see that it’s a template class, and thus cannot be mapped to Java.

    Rejecting it, however, will also reject all functions that depend on the class. For the time being, we accept the occlusion of this API from Qt Jambi. Later on, however, someone needs to make sure this API is properly mapped, e.g. by mapping the different specializations of QGenericMatrix to Qt Jambi instead, or perhaps by handwriting some of the functions.

    function ‘fooBar’ already has a body
    When compiling the QtGui module, we get several similar errors concerning functions that “already have bodies”, i.e. they have been defined twice in the library. The problem in these cases is usually that the there is a const overload in the C++ API which otherwise has an identical signature. In Java, there is no such thing as a const specifier that alters the signature of a function, so we need to reject one of the overloads.

    Another common cause of this error is that the function has overloads which take different types in C++, but which have been mapped to a common type in Qt Jambi. This can be the case, for instance, when two types both map into QNativePointer. An example of this problem is the pair of functions QPixmapCache::find(const QString &amp;, QPixmap &amp;) and QPixmapCache::find(const QString &, QPixmap *). QPixmap is a value type, so both signatures become QPixmapCache.find(String, QNativePointer) in Java. Since the latter overload provides no additional convenience in Qt Jambi, we reject it in the type system.

    setAttributeArray(com.trolltech.qt.QNativePointer,com.trolltech.qt.QNativePointer) is already defined
    Since the C++ code now compiles, we move on to the Java compilation. We see several errors indicating problems in QShaderProgram. Looking at the documentation, we see that the class has several overloads which take char* name as the first argument. At some point, each of these should be handled especially, using a java.lang.String for the name argument instead. However, for the moment, we only want to make the code compile, so we focus on the ones that break compilation.

    Since the disambiguating argument in each of the overloads is a pointer to a value type, they have all got the ambiguous setAttributeArray(QNativePointer, QNativePointer, int) method. For now, we rename them all, with a comment saying that the API needs to be cleaned up.

    Another similar error message in the same class is caused by the fact that Java does not support unsigned integer types (with the notable exception of char.) Therefore, both int and unsigned int will map to int in the Java code, which can cause ambiguities in overloads. In the case of QShaderProgram, we reject the unsigned integer version of the function.

    <object -type name="QGLShaderProgram">

    <modify -function signature="setAttributeArray(int, const QVector2D *, int)" rename="setAttributeArray_QVector2D" />
    <modify -function signature="setAttributeArray(int, const QVector3D *, int)" rename="setAttributeArray_QVector3D" />
    <modify -function signature="setAttributeArray(int, const QVector4D *, int)" rename="setAttributeArray_QVector4D" />
    <modify -function signature="setAttributeArray(const char *, const QVector2D *, int)" rename="setAttributeArray_QVector2D" />
    <modify -function signature="setAttributeArray(const char *, const QVector3D *, int)" rename="setAttributeArray_QVector3D" />
    <modify -function signature="setAttributeArray(const char *, const QVector4D *, int)" rename="setAttributeArray_QVector4D" />
    <modify -function signature="setUniformValueArray(int, const GLint *, int)" rename="setUniformValueArray_int" />
    <modify -function signature="setUniformValueArray(int, const GLuint *, int)" rename="setUniformValueArray_uint" />
    <modify -function signature="setUniformValueArray(int, const QVector2D *, int)" rename="setUniformValueArray_QVector2D" />
    <modify -function signature="setUniformValueArray(int, const QVector3D *, int)" rename="setUniformValueArray_QVector3D" />
    <modify -function signature="setUniformValueArray(int, const QVector4D *, int)" rename="setUniformValueArray_QVector4D" />

    <modify -function signature="setUniformValueArray(const char*, const GLint *, int)" rename="setUniformValueArray_int" />
    <modify -function signature="setUniformValueArray(const char*, const GLuint *, int)" remove="all" />
    <modify -function signature="setUniformValueArray(const char*, const QVector2D *, int)" rename="setUniformValueArray_QVector2D" />
    <modify -function signature="setUniformValueArray(const char*, const QVector3D *, int)" rename="setUniformValueArray_QVector3D" />
    <modify -function signature="setUniformValueArray(const char*, const QVector4D *, int)" rename="setUniformValueArray_QVector4D" />
    <modify -function signature="setUniformValue(int, GLuint)" remove="all" />
    <modify -function signature="setUniformValue(const char*, GLuint)" remove="all" />
    </object>

    We also reject a couple of overloads with two-dimensional arrays with a fixed size in the signature, since the Java does not support that. The result is that API is still usable, but not convenient, so it should be fixed before the API can be considered ready for use.

    clone() is already defined in com.trolltech.qt.webkit.QWebElement
    The final Java compile error is due to a bug in the Qt Jambi Generator. For classes where it’s possible, Qt Jambi will automatically generate a clone() method to implement the Cloneable interface. If the class already has a function called “clone” with no arguments, this will of course cause problems. I’ve made a tiny fix to the Generator in this case, causing it to skip creating the clone() when one already exists. If the existing clone method does not have the correct signature, compilation will still fail, so the fix is not complete, but it will fix the problem for the time being.

    Cannot find symbol : variable DefaultHistoryVersion
    From earlier, we remember rejecting the enum “DefaultHistoryVersion”. Apparently, this is used as a default value for an argument in a function, which causes the code to fail compiling. We need to remove the default value for now. A better solution for later might be to manually add DefaultHistoryVersion as a variable in the class, and have it point to the latest version. However, this would also require that we maintain the manually written code for each release to make sure the DefaultHistoryVersion is updated, so it might not be worth the trouble.

    <object -type name="QWebHistory">
    <modify -function signature="saveState(QWebHistory::HistoryStateVersion)const">
    </modify><modify -argument index="1"><remove -default-expression /></modify>

    </object>

    Tweaking the APIs
    So Qt Jambi 4.6 finally compiles, but there is still much to be done. I’ve noted along the way that much of the convenience of the original API has been thrown away because of missing support in the Generator, or because of fundamental differences in the language. In many of these cases, we will have to try to adapt the intention of the API, and write code by hand to do so.

    When this is done, it is also necessary to go through the remaining three log files. The native pointer API log gives us a list of methods which are currently difficult to use for users of our API, but probably functional. In these cases we need to take measures to introduce a more readable API. Some entries in this list are intentionally left unhandled, as they are instances of low-level API which needs the functionality of QNativePointer. Most of the API should be ported to use more easily approachable types, however.

    The last two log files both give us the names of functions that the Generator thinks will potentially cause crashes with the current state of the type system. We need to look through these, read the code of the functions, and make decisions based on our best assumptions.

    The API cannot be considered ready until all this has been taken care of, and there are no more warnings and no more entries in the log files which have not been intentionally left unhandled after close consideration.

    The road ahead
    I’ve already done a lot of the work necessary to make Qt Jambi 4.6 work and compile, but there is still a lot to be done. I haven’t yet tested compilation on any platform other than Windows, and I haven’t addressed any of the deficiencies in the automatically ported API as mentioned in the previous section.

    In addition to this, several of the new examples and demos should be ported in order to test the new bindings and usability of the new API, and there’s the question of the modules which have not yet been ported to Java.

    UPDATE: If you wish to contribute to the port of Qt Jambi to 4.6, there is a repository dedicated to this. It contains the changes discussed in this blog. Send me a message on Gitorious if you want to be added to the qt-jambi-community group and have write access to the repository.

    Good luck with Qt Jambi 4.6!

    Eskil Abrahamsen Blomfeldt
    Qt
    Qt Jambi
    News
    Contributors
    Git
     in Qt, Qt Jambi, News, Contributors, Git
     on Monday, May 11, 2009 @ 12:06

    It’s taken a little longer than expected, but the nice and polished Qt Jambi 4.5.0_01 packages are finally ready for download on Qt Software’s server. As usual, there are both source and binary packages available, but to match the new licensing of Qt, the GPL packages have been replaced by LGPL packages this time around. Read the press release.

    As has been announced earlier, this will be the final feature release of Qt Jambi from Qt Software. Patch releases and support will continue for the next year, but when Qt 4.6 comes out, Qt Software will not be releasing an official Java version. Part of me is sad about this, sure, but part of me is excited as well, because with the new licensing terms, I think there is a real chance that Qt Jambi can become a success in the wild and continue to grow, maybe even at a quicker rate, in both stability and popularity and excellence, after the official support for it has ended.

    This success relies on one thing in particular: Our ability to establish a community of volunteers who want to maintain and use Qt Jambi when its official life as a Qt Software product ends. Having this community is vital. It’s what will make or break Qt Jambi in the future, so we want to do what we can to get that going.

    The first step is of course to license the product under the LGPL. This means that both open and closed source users can continue to use the product.

    The second step we are taking is to host a public git repository for Qt Jambi. People who wish to contribute to Qt Jambi can clone the repository and request merges to master when they feel their changes are ready for it. We will maintain the public repository for the coming year, and integrate changes that are deemed safe/tested and that pass whatever legal criteria might be required (I don’t have details on this yet, so lets call everything subject to change.)

    As a third measure, we have made sure that the repository is complete, meaning that it contains the revision history from the very moment we took Qt Jambi out of research and made a product branch of it. The inner workings of Qt Jambi are complex, so being able to do a “git blame” and find the change description that explains exactly why, for instance, a particular function requires a recursion guard or a mutex lock, is a requirement when new maintainers take over control.

    Fourth: As many of you know, we have always tried to keep a direct line of communication with users. So far this has been using the Qt Jambi Interest mailing list, and that will continue unless the community takes its discussion elsewhere. In addition, I want to make available as much information as possible on the processes we have established and experience we have gained while working on Qt Jambi for the past years. My current thinking is to put this here on labs in the form of blogs, but as the amount of information grows, a wiki might also be in order.

    Finally, if you are interested in contributing to Qt Jambi, and you have any questions/ideas on how we can make it a success as a community project, please sign up to the mailing list and let us know. Also, clone the repository at http://gitorious.org/qt-jambi and start hacking! :-)

    Tor Arne Vestbø
    Qt
    KDE
    Qt Jambi
    Labs
    News
    QtCreator
     in Qt, KDE, Qt Jambi, Labs, News, QtCreator
     on Monday, May 11, 2009 @ 12:00

    With the announcement back in January of Qt going LGPL there was a small piece of information that slipped though the cracks of the wider news reporting, namely the fact that we were planing on opening up our repositories and development model. The first major phase of this work is now complete, and we are proud to present the results:


    Launching a public repository is a big milestone for us in Qt Software, as it allows us to work closer with contributors, strengthens the the link to the community, and gives that warm and fuzzy feeling of working with open source. Granted, our releases have been open source, but our development model has not. Although you could always send us patches by mail or through our bug tracker it was a cumbersome process, requiring a faxed copy of a copyright-assignment form from the contributor, as well as a lot of manual labor on our part.

    Our goal with the new site is to make this process as simple and welcoming as possible, and that’s why we will no longer ask for copyright assignment. Instead we ask contributors to grant Qt Software a non-exclusive right to re-use and incorporate the code as a part of Qt, handled by a one-time online click-through the first time you submit code for inclusion in Qt.

    Maintaining your patches to Qt and working in parallel with our development is also very easy thanks to the features of Git and Gitorious. Just clone the official Qt repository, push you changes to your newly created clone, and submit a merge request for our reviewers. Everything happens on the site. (For more information on how to contribute see the Qt project wiki).

    Choosing Gitorious as the basis for our public repository hosting was the result of both chance and strategy. As previously blogged about we switched to Git for our development almost a year ago, and as part of the move we installed Gitorious on one of our servers to manage our many projects and repositories. We soon started hacking on the code to add various features and tweaks, and quickly fell in love with the codebase. Fast forward a couple of months to the LGPL and public repository planning, we started playing with the idea of using Gitorious for hosting the public site too. At that point we realized that the author and maintainer of Gitorious, Johan Sørensen, was actually living in Oslo, so we invited him to our offices for a chat. One thing lead to another, and we ended up funding Johan and one of his colleagues to work on Gitorious for the past four months. The new Gitorious site is the result of that work. All of our changes have been pushed upstream, and we will continue to invest in further development of the site.

    So what are the features of the new site? Johan has already enumerated these in full on his blog, but a few highlights are in order:

    • Team support (easier to manage committers and project ownership)
    • Asynchronous task processing (no more lag when pushing)
    • Visual tweaks (including breadcrumbs and pretty URLs)

    We are also looking at improving the whole review process, for example by adding line-based commenting to merge requests, bug-tracker integration, and automated testing of contributions, but these are ideas still in research. Stay tuned for updates on this.

    So, what are you waiting for? Create an account on Gitorious, start cloning, and join the exciting development of Qt! :)

    Good luck!

    Eskil Abrahamsen Blomfeldt
    Qt Jambi
     in Qt Jambi
     on Wednesday, July 23, 2008 @ 14:11

    A while back we announced the research project Qt Jambi AWT Bridge which allows you to mix AWT/Swing components and Qt widgets in the same window on Windows and Linux.

    There were a few issues with the original version. The main problems were the fact that your window would be deactivated by the window manager when you clicked inside an embedded widget, some issues with unnecessary whitespace around the embedded components when you embedded AWT inside of Qt, and some people experienced a race condition which caused the embedded widgets to sometimes disappear.

    The project has now largely been rewritten to be more robust, and both the window activation issues and whitespace issues have been resolved. If you sync the latest version from Subversion, you should be able to see major improvements. There are still some issues with keyboard focus (tabbing between the application widgets and the embedded widgets) which we are trying to resolve.

    The sequence of commands to build has also changed. Please follow the following steps in order to build the project from source (for users of a binary package of Qt Jambi, we will try to get binaries for the bridge up at some point.) The following steps will only work if you have also built Qt Jambi from source.

    Windows (Replace “nmake” with the “make”-application of your choice.)
    set JAMBIDIR=\path\to\jambi\source\package
    set JAVADIR=\path\to\java\sdk
    .\generatorstep.bat
    qmake
    nmake

    Linux
    export JAMBIDIR=/path/to/jambi/source/package
    export JAVADIR=/path/java/sdk
    ./generatorstep.sh
    qmake
    make

    That should take care of building the native binaries. Then put Qt Jambi in your class path and compile all the .java files:

    javac com/trolltech/research/qtjambiawtbridge/generated/*.java
    javac com/trolltech/research/qtjambiawtbridge/*.java
    javac com/trolltech/research/qtjambiawtbridge/examples/*.java

    There are two examples in the com.trolltech.research.qtjambiawtbridge.examples package: QtInAwt and AwtInQt. These are the same as before, and show, respectively, how to integrate a Qt widget in an AWT frame, and how to integrate an AWT component in a Qt widget. Here’s a screen shot of QtInAwt:

    awtbridgescreenshot.png

    The window here is handled by AWT, the two input fields and labels for the name are Swing components, and the entire bottom part is a layout created in Qt Jambi.

    Please go to the project homepage for more information.

    Comments Off
    gunnar
    Uncategorized
    Qt
    Qt Jambi
    WebKit
    Qt Concurrent
    Graphics View
    Patternist
    Posted by gunnar
     in Uncategorized, Qt, Qt Jambi, WebKit, Qt Concurrent, Graphics View, Patternist
     on Tuesday, June 10, 2008 @ 09:13

    So the time is finally here. Qt 4.4.0 was released a few weeks ago and as promised Qt Jambi is right behind. A lot of effort has gone into this one, in addition to supporting all the new Qt features, like Phonon, Webkit, Widgets in Graphics View, XQuery and Qt Concurrent, we also have a seriously improved deployment system, JDBC support and a compile-time checked signal-slot approach for the paranoid. Its a good time to be a Java developer I tell yah! We already mentioned all the featuers in the Qt Jambi 4.4.0 Preview Blog so we won’t repeat ourselves here… (There is a danger in linking to eskils blog, as it links to others again, which again links to others, which in the end proves to be a fairly complex graph, but then again… we are engineers and like that kind of stuff)

    Under the cover we’ve also done quite some work. We also did an overhaul of the garbage collection and memory management subsystem and hopefully ironed out all the bumps and dents. We’ve also done some work on the build system, so that our users that build from source have a bit more substantial buildsystem to work with. Previously it was a complex install document, which has been replaced by a simple ant command which just does it all… I was very happy to see that the deployment system & ANT build scripts works well enough for the webstart to look like a plain, normal webstart app:

    <resources>
    <j2se version="1.5+"/>
    <jar href="qtjambi-examples-4.4.0_01.jar"/>
    <jar href="qtjambi-4.4.0_01.jar"/>
    </resources>

    <resources os="Windows" arch="x86">
    <j2se version="1.5+"/>
    <jar href="qtjambi-win32-msvc2005-4.4.0_01.jar"/>
    </resources>

    No magic nativejar or anything like that, just the qtjambi-win32-msvc2005-4.4.0_01.jar in the classpath and that is enough to load it, jpeg and svg plugins and all. The good thing is that the files included in the webstart are produced directly by the ant script with all dependencies etc set up properly… (well… almost properly, it took us an evening last week to get it really working, but now it works properly). Because of the fixes to memory management and deployment Eskil and I got these offical diplomas:

    Absolutely last load issue fixed and Last memory managment bug

    So, what more is there to say… Try the webstart with its new demos, download the packages and start hacking!

    -
    The Qt Jambi Team

    Eskil Abrahamsen Blomfeldt
    Qt
    Qt Jambi
     in Qt, Qt Jambi
     on Wednesday, March 12, 2008 @ 13:03

    The Qt 4.4 beta was released on February 26th, and, true to form, the corresponding Qt Jambi release comes a couple of weeks later.

    In honor of the 4.4 release, we’d like to go through some of the new features you should look out for.

    WebKit integration
    WebKit is an open source web browser engine which is the basis of, among other things, the Safari web browser on Mac OS X. The engine has been integrated in Qt, and is available to Qt Jambi programmers in the package com.trolltech.qt.webkit. This means that you can easily integrate web content in your applications, and jump on the whole acronym-bandwagon by using AJAX methodology in your code. Håvard did a whole blog teasing this feature a while back, so instead of rewriting all that, we’ll just point you in the right direction. Benjamin wrote a blog a few days ago that goes into more detail, so take a look at that as well if you’re interested. On the WebKit Integration announcement page you’ll find lots more information, and some very cool videos that illustrate some of its awesome powers.

    Multimedia framework
    Qt and Qt Jambi 4.4 gets full-blown multimedia support through the Phonon framework adopted from KDE. This gives easy access to playing and manipulating movies and music in all the nice file formats for which the underlying media framework has codecs. The framework defaults to using Gstreamer (Linux), Microsoft DirectShow (Windows) and Quicktime (Mac OS X). There’s also this teaser blog about Qt Jambi and Phonon with an example for those interested.

    New deployment system (Qt Jambi specific)
    While we’ve always been recommending a .jar based deployment method, we’ve required people to build their own .jar files containing the necessary native libraries, and a meta-info approach to specifying which dependencies exists in a given project. This system has proven not only to be easy to misunderstand, but to have some fundemental flaws that could cause crashes and general discomfort if you did it wrong. In fact, in order to deploy previous versions on Mac, it was required that you were either Eskil, Gunnar, or someone with direct e-mail contact with either of us. In Qt Jambi 4.4 we’ve hopefully fixed this once and for all, by defining a default .jar based deployment system which avoids problems with mixing libraries and in which deploying to a different platform is as easy as replacing a single platform specific .jar file. In fact, if size is irrelevant, it’s possible to ship a single distribution of your application which will run on all platforms, as long as the platform .jar file for the given platform is in the class path when running the application.

    If you are building from source and require extra libraries to be included, this can be achieved simply by editing the ant script.

    JDBC support (Qt Jambi specific)
    A drawback in our SQL framework in previous versions of Qt Jambi has been that you needed to have access to a Qt/C++ source distribution in order to use it. The reason was that we could not provide binaries that were compatible with all the different database drivers out there. In Qt Jambi 4.4 we support the Java DataBase Connectivity API which is the industry standard for database access in Java. This has been available on Trolltech Labs for a while, but now it has finally been integrated in Qt Jambi and is available in the com.trolltech.qt.sql package. Gunnar wrote a blog about it back when it was put up on labs.

    XML patterns
    XML support has been greatly improved in Qt and Qt Jambi 4.4. An example for this is the added support for XQuery 1.0 and XPath 2.0. In Qt Jambi, it is available in the package com.trolltech.qt.xmlpatterns. For more information, see Frans’s blogs about the C++ version of the API.

    Qt Concurrent
    One of the greater challenges in terms of mapping C++ to Java was the Qt Concurrent framework. This is a set of classes and functions that will help you parallelize tasks (e.g. to optimize for multicore cpus) without having to worry about many of issues the ordinarily related to multithreaded programming. In C++ it uses a lot of very language specific constructs, like templates and function pointers, making it hard to automatically map the API to Java. Indeed, we had to write part of the bindings layer by hand, replacing the use of function pointers with interfaces instead. We also implemented support in the Qt Jambi Generator for mapping C++ template classes to Java’s generic classes (under certain conditions) in order to get the correct API for classes such as QFuture. The underlying, generated code for binding this class uses a general, reference counting wrapper for java.lang.Object where the Java API (and the original C++ API) uses a generic parameter. Since generics in Java is a static, syntactic mechanism, there is no need to worry about it in the JNI code.

    Other stuff
    There are many more changes in Qt Jambi 4.4, bug fixes and new features. In order to get an overview of them all, you should see both the change logs for Qt Jambi 4.4 and Qt 4.4 (which will be out when the release is final.) From the top of our heads, we can mention an enhanced network API, QMetaObject introspection for Java objects, and numerous improvements to Designer.


    Gunnar and Eskil

    Eskil Abrahamsen Blomfeldt
    Qt Jambi
     in Qt Jambi
     on Tuesday, March 04, 2008 @ 09:12

    The Qt Jambi team has, as have all devs in Trolltech, been busy preparing two separate releases the past few weeks slash months (Qt Jambi 4.3.4_01 and Qt Jambi 4.4.0_01.)

    In the midst of this, someone reminded me that I promised I’d post a blog when we added prebuilt Windows binaries to the repository for QtJambiAwtBridge. This has now been done (Gunnar actually added it a while ago), so it should be possible to use the bridge without having a Qt source package ready. It’s in QtJambiAwtBridge lab in the directory “prebuilt”. For maximum compatibility, please use the binary together with a Qt Jambi binary package.

    As far as the code goes, not much has happened to the QtJambiAwtBridge, and there probably won’t be much time to work on it until the two upcoming releases are ready and out the door. At that point, I will sit down and see what I can do about the outstanding issues (mainly regarding focus handling and window activation as far as I know, please post a report if you find other problems.)

    Since I’m already posting this, I might as well add that Qt Jambi JDBC has been target of a few bug fixes lately: The standard Java SQL types are now automatically displayable and editable in views of the database models, a bug has been fixed where the contents of cells in a view looking at a JDBC-based model would sometimes rearrange or blank out, and finally: We’ve added a few changes that greatly increase the number of JDBC drivers with which we are compatible. We previously required that the underlying driver supported returning autogenerated keys, which is optional in the JDBC specs, and there was also a bug with certain unforgiving drivers when trying to do random access on the result sets. One of the drivers for which these bug fixes adds compatibility is the pgsql one.

    As far as Qt Jambi JDBC goes, the driver will be integrated into Qt Jambi 4.4 and become permanent part of the Qt Jambi library.

    gunnar
    Qt
    Qt Jambi
    Posted by gunnar
     in Qt, Qt Jambi
     on Tuesday, February 05, 2008 @ 08:39

    I planned on writing a blog about some of the work we’ve done on deployment for Qt Jambi 4.4, but I realized when writing that the memory of “Why the !”#!%!§ doesn’t it work on that linux box!” was still to fresh in memory and I was simply to upset to write anything about it. Some time has passed and a Finnish company came along, putting things into perspective, so now I can calmly share some thoughts on deployment with you…

    Deploying C++ software across multiple platforms can be rather painful, partially because Qt doesn’t really provide any tools to help out. We do provide deployment guides for the various systems, but our users still have to learn and understand all the details. It doesn’t “just work”. Why? you may ask…

    On windows life used to be pretty simple, you ship your .exe and .dll’s together in the same directory together with the right runtime libraries and you’re set, alternatively build with Visual Studio 6.0 and almost don’t worry about it at all. This was until a certain company introduced manifests as a way of describing dependencies between libraries and executables. It does sound great on paper, but in practice it really doesn’t work, especially if the executable (java.exe in this case) is built without manifest. As a direct effect, you are now required to either preinstall the runtime libraries in the WinSxS folder (via installer) or duplicate the runtime libraries in all directories that contain executable code, such as /lib, /bin and /plugins/…, meaning that each plugin directory needs to have its own duplicate copy of the MS runtime libraries. Should you choose to not follow these rules, the application won’t run…

    On Linux we have the problem that the various systems are vastly different. Some boxes didn’t have Xinerama installed, some have libstdc++ version 5, some have version 6. Some have Qt installed with debug symbols and some have Qt 3 installed. Basically there are a lot of variables and the only way to go about this is for our users to ship a complete bundle containing all dependencies. In Qt 4.4 we changed Qt in some places to support dynamic resolving and loading a few X libs which reduced the dependency table a bit. In Qt 4.3 our binaries were built without Xinerama for instance, to make them run on certain systems. Since Qt 4.4 we support Xinerama if its available on the deployment machine out of the box.

    On Mac OS X, things are immediately rather bright, save for this minor issue of install_name… Install names describes, among other things, the location of dependent binaries. When build Qt libraries in the default way, the dependencies will be absolute file names to things like ~/qt/lib/libQtCore which doesn’t work on a target machine. In Qt 4.3, we patched our prebuilt binaries to contain relative paths to where they were loaded from, but our users who built Qt Jambi themselves would have to do this too, which is a rather messy process. Why not simply use frameworks or bundles, and the reason is simply that we want to have a means of deployment that feels java-like and works identically across all platforms, so our users can understand this, and not care anymore about deployment on any target system. Frameworks and bundles are pretty far from that…

    In addition to these platform spesific problems, we have the issue that in Java, you normally relate to .jar files which are portable while native libraries, such as the Qt C++ libraries, have to be available on the file system for the application to load them. These native libraries need to be available through the java.library.path, which equals the environment variables PATH on windows, LD_LIBRARY_PATH on Linux / UNIX and DYLD_LIBRARY_PATH on OS X. In Qt Jambi 4.3 we did provide some magic to automatically find the libraries without the environment variables, but ideally you want to relate to just .jar files, right? Well… With Qt Jambi 4.4 you can!

    What we ended up doing is that we created some ant tasks to help us and our users out. The way it works is that we have build tasks for running qmake, make and juic and a task for bundling. The bundle task will make sure the binaries have the right install name in place on Mac OS X and on windows it will copy the manifests and runtimes into the right subdirectories. The result of this is a .jar file, for instance qtjambi-win64-msvc2005-4.4.0_01.jar which contains the correct native binaries for Windows 64bit and when its in the classpath, it will just work. Similarly it will create a qtjambi-linux32-gcc-4.4.0_01.jar for linux, and if you put both the two in the classpath, it will pick the right one.

    This makes it extremly easy for the people that deploy a plain Qt Jambi application, as they simply include a .jar file in their classpath and it works. The slightly more complex scenario is where you generate some code using the Qt Jambi Generator and want to deploy that. The process is rather similar, you simply add your binaries to the bundle task and you get a .jar file containing Qt Jambi native libraries and you own native libraries and once again you are set. We still support loading binaries from the environment variables listed above, which is handy for development and for starting Qt Jambi from a C++ app, like Qt Designer, so hopefully, we covered most scenarios.

    We hope to have the Qt Jambi 4.4.0_01 Beta out by the end of february, so I’m looking forward to getting your feedback on this…

    lars
    Qt
    Qtopia
    KDE
    Qt Jambi
    News
    Posted by lars
     in Qt, Qtopia, KDE, Qt Jambi, News
     on Monday, January 28, 2008 @ 07:59

    As you might have seen, Nokia has announced to acquire Trolltech. An open letter to the open-source community can be found here.

    This is exciting news for everyone. As you can see in the letter, our commitment to the community will not be affected by this. Qt development will continue in the same way as we’ve always done it.



    © 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
    All other trademarks are property of their respective owners.