Aurélien Gâteau wrote:
Hello,

Cobranding work is going well, the configuration part is done, you can now define your own default configuration values by editing the system 'config.xml' file instead of editing config.cpp.

I am now working on loading images from the file system instead of bundling them in the binary, using resource files defined in .qrc files.

A .qrc file contains a list of files, it is processed by the resource compiler ('rcc') to produce a C++ file containing the content of all the files. This C++ file is then compiled and linked in the binary. My initial proposal to load images from the file system was to introduce an ImageLoader class which would centralize all image loading code, and replace all occurrence of:
        QPixmap(":/pics/some/image.png")
with:
        ImageLoader::loadPixmap("some/image.png")

It was going well, until I hit the .ui wall: To assign images to widgets in Designer, one need to choose a .qrc file, then select images from this .qrc file to use in widgets. The .ui compiler ('uic') will generate code for this .ui, loading images in the QPixmap(":/pics/some/image.png") way.

One solution is to give up defining images from Designer and do it from the code, but it means lots of empty widgets in the .ui file, so I think it would be quite of a regression.

Another solution, which I am submitting to you for your opinion, is to trick Qt into loading images from the file system. To load resource files Qt implements a resource file engine by inheriting from QAbstractFileEngine [1]. Qt resource file engine handles all file names beginning with a ':'. What I did is to register another file engine which handle file names beginning with a ':' *before* the Qt resource file engine.

Implementation is really simple, it's not even a custom file engine, it just reuses the QFSFileEngine class:

---
#include <QtCore/QFSFileEngine>
class FSResourceFileEngineHandler : public QAbstractFileEngineHandler {
public:
        FSResourceFileEngineHandler(const QString& baseDir)
        : _baseDir(baseDir) {}

        QAbstractFileEngine* create(const QString& path_) const {
                QString path = path_;
                if (path.size() > 0 && path.startsWith(QLatin1Char(':'))) {
                        path = _baseDir + path.mid(1);
                        if (QFile::exists(path)) {
                                QFSFileEngine* engine = new QFSFileEngine;
                                engine->setFileName(path);
                                return engine;
                        }
                }
                return 0;
        }

private:
        QString _baseDir;
};
---

To use it, declare the handler in the main() function, like this:

---
int main() {
        FSResourceFileEngineHandler handler("/path/to/resources/");
        ...
}
---

Now, make sure "/path/to/resources" contains the files defined in your .qrc file and you're done. This code:
        QPixmap pix(":/pics/image.png");
Will make Qt load the pixmap from /path/to/resources/pics/image.png

The nice thing about this is that if there is no file matching the requested filename in the file system, FSResourceFileEngineHandler::create() returns 0, and Qt fallbacks to its own resource file engine.

From within Designer you can still use .qrc files, and select images as before, but the .qrc file does not need to be compiled anymore.

It's a bit tricky because one must declare the handler *after* Qt resource handler. In this case it works because Qt resource handler is defined as a static global variable, so it's initialized before entering the main() function.

Another advantage of this solution is that it requires very little changes, compared to the ImageLoader solution.

What do you think about this idea?

Aurélien

[1]: http://doc.trolltech.com/4.1/qfsfileengine.html
_______________________________________________
Wengophone-devel mailing list
Wengophone-devel@lists.openwengo.com
http://dev.openwengo.com/mailman/listinfo/wengophone-devel


It is pretty clever tric,
But did you consider, adding small sed script into build sequence replacing QPixmap() with

ImageLoader::loadPixmap("some/image.png")

or
with OWQPixmap?


Thanks
Vadim

_______________________________________________
Wengophone-devel mailing list
Wengophone-devel@lists.openwengo.com
http://dev.openwengo.com/mailman/listinfo/wengophone-devel

Reply via email to