Skip to content

Rendering UI files to SVG

Monday, 3 January 2011  |  rich

In response to a question on IRC yesterday, here's a quick example for the New Year - rendering designer's UI files to SVG using QSvgGenerator. As usual, the code is simple since Qt gives us everything we need.

The main program loads the UI file shows it, it also sets up our SVG capture. Loading the UI file is done using QUiLoader allowing us to load any file specified on the command line. We then figure out what to call the SVG file we're going to generate. Next we setup our Renderer object by telling it what to capture and the name of the file to write it to. In order to ensure the UI is ready, we use a single shot timer to trigger the capture one second after the application starts:

int main( int argc, char **argv )
{
    QApplication app( argc, argv );
QString filename = QString::fromLocal8Bit( argv[1] );
QUiLoader loader;
QFile f( filename );
if ( !f.open(QIODevice::ReadOnly) )
return 1;

QWidget *ui = loader.load( &f );
if ( !ui )
return 1;

QString svgFile = filename.remove(".ui");
svgFile = svgFile.append(".svg");

Renderer render;
render.setTarget(ui);
render.setSvgFile(svgFile);
QTimer::singleShot( 1000, &render, SLOT(start()));

ui->show();
app.exec();

}

The implementation of the actual capture is simple too, and is all handled by a single method 'renderToSvg()'. This method creates the generator and tells it the filename to use. Then it creates a QPainter and sets up drawing onto the QSvgGenerator - this is possible because QSvgGenerator is a QPaintDevice (like QWidget, QImage etc.). Finally we call the render() method of the widget we're capturing in order to perform the actual drawing.

bool Renderer::renderToSvg()
{
    if (svgFile.isEmpty()) {
        qDebug() << "No svg file set";
        return false;
    }

    QSvgGenerator svg;
    svg.setFileName(svgFile);
    QPainter p;
    p.begin(&svg);
    target->render(&p);
    p.end();
    
    return true;
}

The result of running this on a simple UI file can be seen at http://xmelegance.org/devel/networkrequests.svg. The code itself is available from my gitorious qt-examples repository as normal.

When I first wrote the above code, I tried to get the widget to render directly to the svg file, but this turned out to hit QTBUG-2278. The code that triggers the bug was:

    QSvgGenerator svg;
    svg.setFileName(svgFile);
    target->render(&svg);
So if I were you, I'd create the painter myself!