We want to present you another C++ example of Marble Runnable usage, here on KDE TechBase. It's about the cars. Imagine that there are two flying cars in the air. They are driving around ukranian city Kiev (EURO-2012). They are driving circles around it with set radius and speed. At the end of tutorial you will have an application with smth like:

Then each CarWorker creates a QTimer with interval x. On timeout() it calls the CarWorker::iterate() - function to calculate new position of placemark and notify Window (another thread) about it.

Everything is going on until the application finishes.

The code with comments:

//// This file is part of the Marble Virtual Globe.//// This program is free software licensed under the GNU LGPL. You can// find a copy of this license in LICENSE.txt in the top directory of// the source code.//// Copyright 2012 Illya Kovalevskyy <illya.kovalevskyy@gmail.com>// Copyright 2012 Torsten Rahn <tackat@kde.org>//#include <QtGui/QApplication>#include <QtCore/QThread>#include <QtCore/QTimer>#include <QtCore/QHash>#include <QtCore/qmath.h>#include <QtCore/QDebug>#include <QtGui/QVBoxLayout>#include <marble/MarbleWidget.h>#include <marble/MarbleGlobal.h>#include <marble/GeoDataDocument.h>#include <marble/GeoDataPlacemark.h>#include <marble/GeoDataLineString.h>#include <marble/GeoDataTreeModel.h>#include <marble/MarbleModel.h>usingnamespaceMarble;// CarWorker ClassclassCarWorker:publicQObject{Q_OBJECTpublic:CarWorker(constGeoDataCoordinates&city,qrealradius,qrealspeed);signals:/// This signal will be emitted when we need to/// move the placemark.voidcoordinatesChanged(GeoDataCoordinatescoord);publicslots:voidstartWork();voidfinishWork();privateslots:voiditerate();private:QTimer*m_timer;GeoDataCoordinatesm_city;qrealm_radius;qrealm_speed;qrealm_alpha;};CarWorker::CarWorker(constGeoDataCoordinates&city,qrealradius,qrealspeed):QObject(),m_timer(newQTimer(this)),m_city(city),m_radius(radius),m_speed(speed),m_alpha(0.0){}voidCarWorker::startWork(){m_timer->setInterval(0);connect(m_timer,SIGNAL(timeout()),this,SLOT(iterate()));m_timer->start();}/// Single timer loop iteration:/// Calculates new coordinates for the carvoidCarWorker::iterate(){/// A bit of mathqreallon=m_city.longitude(GeoDataCoordinates::Degree)+m_radius*qCos(m_alpha*DEG2RAD);qreallat=m_city.latitude(GeoDataCoordinates::Degree)+m_radius*qSin(m_alpha*DEG2RAD);GeoDataCoordinatescoord(lon,lat,0.0,GeoDataCoordinates::Degree);emitcoordinatesChanged(coord);/// Iteration is finished. We need to increase anglem_alpha+=m_speed;}voidCarWorker::finishWork(){m_timer->stop();}// Window ClassclassWindow:publicQWidget{Q_OBJECTpublic:Window(QWidget*parent=0);voidstartCars();publicslots:voidsetCarCoordinates(constGeoDataCoordinates&coord);private:MarbleWidget*m_marbleWidget;CarWorker*m_firstWorker;CarWorker*m_secondWorker;GeoDataPlacemark*m_carFirst;GeoDataPlacemark*m_carSecond;QThread*m_threadFirst;QThread*m_threadSecond;};Window::Window(QWidget*parent):QWidget(parent),m_marbleWidget(newMarbleWidget){QVBoxLayout*layout=newQVBoxLayout(this);layout->addWidget(m_marbleWidget);setLayout(layout);// Load the OpenStreetMap mapm_marbleWidget->setMapThemeId("earth/openstreetmap/openstreetmap.dgml");m_marbleWidget->setProjection(Mercator);setGeometry(80,60,1000,800);GeoDataCoordinatesKiev(30.523333,50.45,0.0,GeoDataCoordinates::Degree);m_marbleWidget->centerOn(Kiev);m_marbleWidget->setZoom(2300);m_carFirst=newGeoDataPlacemark("Bus");m_carSecond=newGeoDataPlacemark("Car");GeoDataDocument*document=newGeoDataDocument;document->append(m_carFirst);document->append(m_carSecond);m_marbleWidget->model()->treeModel()->addDocument(document);show();}voidWindow::startCars(){GeoDataCoordinatesKiev(30.523333,50.45,0.0,GeoDataCoordinates::Degree);m_threadFirst=newQThread;m_firstWorker=newCarWorker(Kiev,(qreal)0.1,(qreal)0.7);m_firstWorker->moveToThread(m_threadFirst);connect(m_firstWorker,SIGNAL(coordinatesChanged(GeoDataCoordinates)),this,SLOT(setCarCoordinates(GeoDataCoordinates)),Qt::BlockingQueuedConnection);m_threadSecond=newQThread;m_secondWorker=newCarWorker(Kiev,(qreal)0.2,(qreal)-0.5);m_secondWorker->moveToThread(m_threadSecond);connect(m_secondWorker,SIGNAL(coordinatesChanged(GeoDataCoordinates)),this,SLOT(setCarCoordinates(GeoDataCoordinates)),Qt::BlockingQueuedConnection);connect(m_threadFirst,SIGNAL(started()),m_firstWorker,SLOT(startWork()));connect(m_threadFirst,SIGNAL(finished()),m_firstWorker,SLOT(finishWork()));connect(m_threadSecond,SIGNAL(started()),m_secondWorker,SLOT(startWork()));connect(m_threadSecond,SIGNAL(finished()),m_secondWorker,SLOT(finishWork()));m_threadFirst->start();m_threadSecond->start();}voidWindow::setCarCoordinates(constGeoDataCoordinates&coord){CarWorker*worker=qobject_cast<CarWorker*>(sender());if(worker==m_firstWorker){m_carFirst->setCoordinate(coord);m_marbleWidget->model()->treeModel()->updateFeature(m_carFirst);}elseif(worker==m_secondWorker){m_carSecond->setCoordinate(coord);m_marbleWidget->model()->treeModel()->updateFeature(m_carSecond);}}// Mainintmain(intargc,char**argv){QApplicationapp(argc,argv);Windowwindow;window.startCars();returnapp.exec();}#include "vehicletracking.moc"