[Marble-devel] Review Request: Added addFeature and removeFeature support to GeoDataTreeModel
Javier Becerra Elcinto
javier at auva.es
Fri Sep 30 15:19:00 UTC 2011
-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
http://git.reviewboard.kde.org/r/102610/
-----------------------------------------------------------
(Updated Sept. 30, 2011, 3:18 p.m.)
Review request for Marble.
Changes
-------
Modified according to comments from Thibaut Gridel.
Declared the add/remove functions as slots.
Added signals added(GeoDataObject *) and removed(GeoDataObject *).
Description
-------
GeoDataTreeModel allows for insertion of a GeoDataDocument using the function addDocument(GeoDataDocument*). However it is not possible to modify an existing document (i.e. by adding or removing a feature) while keeping the model/view synchonised other than calling the GeoDataTreeModel::update() function, which updates the whole treemodel and demands a lot of ressources.
Adding new addFeature and removeFeature allows the modification of the tree while keeping the view automatically updated.
GeoDataTreeModel::addDocument and GeoDataTreeModel::removeDocument are modified to call addFeature and removeFeature, minimising the code modifying the treemodel.
This patch has been proved to work in single-threaded mode, however marblewidget crashes on KDescendantsProxyModel::mapFromSource(const QModelIndex &sourceIndex) when a new feature/document is added from a thread different from main. This behaviour is independent of this patch, as it can be reproduced in unpatched marblewidget calling GeoDataTreeModel::addDocument from another thread. The test code below can be used to test this bug uncommenting the last two lines of code of main.cpp.
Diffs (updated)
-----
src/lib/GeoDataTreeModel.h eda4c53
src/lib/GeoDataTreeModel.cpp 2c17cfa
Diff: http://git.reviewboard.kde.org/r/102610/diff/diff
Testing (updated)
-------
Files "PlacemarkInserter.h" and "main.cpp":
#ifndef PLACEMARKINSERTER_H
#define PLACEMARKINSERTER_H
//Marble
#include "GeoDataContainer.h"
#include "GeoDataPlacemark.h"
#include "MarbleWidget.h"
#include "MarbleModel.h"
#include "GeoDataTreeModel.h"
//Qt
#include <QtCore/QTimer>
#include <QtCore/QDebug>
class PlacemarkInserter:public QObject
{
Q_OBJECT
Marble::GeoDataContainer*folder;
Marble::MarbleWidget *marblewidget;
float lat;
float lon;
int index;
QString prefix;
QTimer timer;
bool removeprev;
Marble::GeoDataPlacemark *prev;
public:
PlacemarkInserter(float lon0, float lat0, int interval, QString pr, Marble::GeoDataContainer* f, Marble::MarbleWidget *mw=NULL ): lat(lat0), lon(lon0), prefix(pr), folder(f), marblewidget(mw), index(2), prev(NULL), removeprev(false)
{
timer.setInterval(interval);
timer.setSingleShot(false);
QObject::connect(&timer,SIGNAL(timeout()),this,SLOT(addNewPlacemark()));
}
public slots:
void setLatitude( float lat0 ) {lat=lat0;}
void setLongitude( float lon0 ) {lon=lon0;}
void setRemovePrevious( bool r ) {removeprev=r;}
void setInterval( int i ) {timer.setInterval(i);}
void start() { timer.start(); }
void stop() { timer.stop(); }
void addNewPlacemark()
{
qDebug()<<"Adding placemark "<<prefix<<index;
Marble::GeoDataPlacemark *myplacemark=new Marble::GeoDataPlacemark;
myplacemark->setName(QString("%1 %2").arg(prefix).arg(index++));
myplacemark->setCoordinate( lon+index*0.01, lat,0,Marble::GeoDataPoint::Degree);
if( marblewidget )
{
if( removeprev && prev )
{
marblewidget->model()->treeModel()->removeFeature( prev );
delete prev;
}
marblewidget->model()->treeModel()->addFeature( folder, myplacemark );
prev=myplacemark;
}
}
};
#include <QThread>
class PlacemarkInserterTh: public QThread
{
float lon;
float lat;
int interval;
Marble::GeoDataContainer *folder;
Marble::MarbleWidget *marblewidget;
QString prefix;
public:
PlacemarkInserterTh(float lon0, float lat0,int interval0, QString pr,Marble::GeoDataContainer *f, Marble::MarbleWidget *mw): lon(lon0),lat(lat0), interval(interval0),folder(f), marblewidget(mw), prefix(pr) {}
void run() { PlacemarkInserter inserter(lon,lat,interval,prefix, folder, marblewidget ); inserter.start(); this->exec();}
};
#endif // PLACEMARKINSERTER_H
//////////////////////////////////////////////7
//main.cpp
#include "PlacemarkInserter.h"
//Marble
#include "GeoDataDocument.h"
#include "GeoDataFolder.h"
#include "GeoDataPlacemark.h"
#include "MarbleWidget.h"
#include "FileViewWidget.h"
//Qt
#include <QtGui/QApplication>
#include <QDebug>
#include <QTextCodec>
int main(int argc, char** argv)
{
QApplication app(argc,argv);
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
//Creating a GeoDataDocument from scratch:
Marble::GeoDataDocument *mydoc=new Marble::GeoDataDocument();
mydoc->setFileName("mydocument.kml"); //Will identify the document internally, must be unique
mydoc->setName("My_GeoDataDocument"); //Name for visualisation in MarbleWidget
Marble::GeoDataFolder *myfolder=new Marble::GeoDataFolder;
myfolder->setName("My first folder"); //(setName from base class GeoDataFeature, inherited from GeoDataContainer)
mydoc->append(myfolder);
Marble::MarbleWidget marblewidget;
marblewidget.setMapThemeId("earth/openstreetmap/openstreetmap.dgml");
marblewidget.show();
Marble::FileViewWidget fileviewwidget;
fileviewwidget.setMarbleWidget(&marblewidget);
fileviewwidget.show();
//addDocument now issues a call to addFeature
int idx=marblewidget.model()->treeModel()->addDocument(mydoc);
qDebug()<<"Added document"<<idx;
PlacemarkInserter inserter0(-2.45,42.465278,250,"Test",myfolder, &marblewidget );
inserter0.setRemovePrevious(true); //tests new removeFeature functionality
inserter0.start();
PlacemarkInserter inserter1(-2.48, 42.465278 , 500 , "Test2" , mydoc , &marblewidget );
inserter1.setRemovePrevious(false);
inserter1.start();
//Uncomment next two lines if you want to see marblewidget crash when the treemodel is modified from
// a thread other than the main one. This bug was already present before the addFeature patch;
// calling addDocument from another thread also caused the application to crash.
//PlacemarkInserterTh crash_on_multithread(-2.55, 42.465278 , 500 , "Crash" , myfolder , &marblewidget );
//crash_on_multithread.start();
return app.exec();
}
Thanks,
Javier Becerra Elcinto
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/marble-devel/attachments/20110930/786e25af/attachment-0001.html>
More information about the Marble-devel
mailing list