[Marble-devel] Help with Placemarks on MarbleWidget

Javier Becerra - AUVA javier at auva.es
Wed Sep 14 08:09:32 UTC 2011


Hi,

I think that you need to update the data model so that the new placemark
appears on the mapwidget. A call to
"marblewidget->model()->treeModel()->update()" (working with the latest
code on git) should do it, but it maybe slow if you need to add many
placemarks.

I am working on adding a function "addFeature" to GeoDataTreeModel which
will work the same way as addDocument, updating only the data you
replaced, which should work better if you have a large number of
placemarks to add. It works fine in single-threaded mode (see attached
file for a patch). 

If you want to give it a try, you will have to create your kml tree,
something like:

   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)

    Marble::GeoDataPlacemark *myplacemark=new Marble::GeoDataPlacemark;
    myplacemark->setName("A placemark in a folder");

    marblewidget->model()->treeModel()->addDocument(mydoc);
    marblewidget->model()->treeModel()->addFeature(mydoc, myfolder);
    marblewidget->model()->treeModel()->addFeature(myfolder,
myplacemark);

You can also retrieve an existing element GeoData... structure from its
QModelIndex (for instance, if you loaded an existing document with a
call to MarbleWidget::addDocument(QString) ):
GeoDataObject* geoobject =
static_cast<GeoDataObject*>( modelindex.internalPointer() 


I have added GeoDataTreeModel::index(GeoDataFeature*) function to
recover the QModelIndex of a feature already present in the treemodel, I
am not sure if there is an easier way to get the model (I go through up
the tree upto top-level node m_rootDocument, and then build the index
downwards, any ideas?).

The attached code is work in progress. My plan is to include:
+Implement a removeFeature function
+Reimplement calls to addDocument and removeDocument with calls to new
functions addFeature and removeFeature (so that all the code to do the
update is centered in a single function).
+Add protection for multithreaded operation. With code on svn (and my
patch as it is) a single call to addDocument from a thread different of
the main thread causes the application to crash. 

I am having some trouble with multithreading, I will send a message to
the list asking for help on this later.

I will be glad to hear any feedback you may have on the patch, I will
submit it to reviewboard when it is complete.

Hth
Javier


El mar, 13-09-2011 a las 22:51 -0400, Shannon Mackey escribió:
> It was suggested, on the KDE Libraries & APIs Forums that I try this list for 
> assistance.
> 
> 
> I believe I've got the correct function to put Placemarks on my MarbleWidget:
> 
> @void  addGeoDataString (const QString &data, const QString &key="data")@
> 
> to put the Point indicated in this kml string onto my MarbleWidget
> 
> @<?xml version="1.0" encoding="UTF-8"?>
> <kml xmlns="http://www.opengis.net/kml/2.2">
> <Document>
> <Placemark>
>   <name>Houlton International Airport</name>
>   <description>Weather Station</description>
>   <Point>
>     <coordinates>-67.8,46.12,150</coordinates>
>   </Point>
> </Placemark>
> </Document>
> </kml>@
> 
> but I'm getting nothing to appear.
> 
> 
> Is my kml correct?
> 
> Do I need to call another function on MarbleWidget to display the newly added 
> Points in the model?
> 
> I've left the second parameter empty, as it has a default, and frankly (from 
> the "documentation":http://api.kde.org/4.6-api/kdeedu-
> apidocs/marble/html/classMarble_1_1MarbleWidget.html#a429644198835fbfc15982e552c41cc62)
> @Parameters:
> data-  the string containing the Placemarks.
> key-  the string needed to identify the data@
> 
> I don't know what "data" is supposed to indicate. 
> I've gone back in MarbleWidget source code, where the parameters flip-flopped 
> places enough times to tangle me up.
> 
> Mostly, I think this is probably a simple thing, and that I'm overlooking 
> something obvious.
> Anyone have a clue for me?
> 
> -solareclectic
> _______________________________________________
> Marble-devel mailing list
> Marble-devel at kde.org
> https://mail.kde.org/mailman/listinfo/marble-devel

-------------- next part --------------
diff --git a/src/lib/GeoDataTreeModel.cpp b/src/lib/GeoDataTreeModel.cpp
index 2c17cfa..6f973d4 100644
--- a/src/lib/GeoDataTreeModel.cpp
+++ b/src/lib/GeoDataTreeModel.cpp
@@ -15,8 +15,10 @@
 // Qt
 #include <QtCore/QModelIndex>
 #include <QtCore/QFile>
+#include <QtCore/QList>
 #include <QtGui/QPixmap>
 
+
 // Marble
 #include "GeoDataDocument.h"
 #include "GeoDataContainer.h"
@@ -428,6 +430,67 @@ Qt::ItemFlags GeoDataTreeModel::flags ( const QModelIndex & index ) const
 }
 
 
+
+QModelIndex GeoDataTreeModel::index(GeoDataFeature *feature)
+{
+    QModelIndex itdown;
+    if( feature && ( feature != d->m_rootDocument ) )
+    {
+        QList< GeoDataFeature*> ancestors;
+
+        GeoDataFeature* itup=feature; //Iterator to reach the top of the GeoDataDocument (bottom-up)
+
+        while(itup && (itup != d->m_rootDocument))
+        {
+
+            ancestors.append(itup);
+            itup=dynamic_cast<GeoDataFeature*> (itup->parent());
+        }
+
+        QModelIndex itdown=index( d->m_rootDocument->childPosition( ancestors.last() ),0,QModelIndex());//Iterator to go top down
+
+        GeoDataContainer *parent;
+
+        while( ( ancestors.size()>1 ) )
+        {
+            parent=dynamic_cast<GeoDataContainer*>(ancestors.last());
+
+            if(parent)
+            {
+                ancestors.removeLast();
+                itdown=index( parent->childPosition(ancestors.last()) , 0, itdown );
+            }
+            else
+            {   //We should not reach this point if the tree has not changed
+                itdown=QModelIndex();
+                break;
+            }
+        }
+    }
+    return itdown ;
+}
+
+void GeoDataTreeModel::addFeature( GeoDataContainer* parent, GeoDataFeature* feature )
+{
+    if( parent && feature )
+    {
+        QModelIndex ind=index( parent );
+        if( ind.isValid() )
+        {
+            beginInsertRows(ind , parent->size() , parent->size());
+            parent->append(feature);
+            endInsertRows();
+        }
+        else
+            mDebug()<<"Container "<<parent->name()<<" is not part of this GeoDataTreeModel instance.";
+        emit treeChanged();
+    }
+    else
+        mDebug()<<"Null pointer in call to GeoDataTreeModel::addGeoDataFeature (parent "<<parent<<" - feature"<<feature<<")";
+
+}
+
+
 int GeoDataTreeModel::addDocument( GeoDataDocument *document )
 {
     beginInsertRows( QModelIndex(), d->m_rootDocument->size(), d->m_rootDocument->size() );
diff --git a/src/lib/GeoDataTreeModel.h b/src/lib/GeoDataTreeModel.h
index eda4c53..937d80d 100644
--- a/src/lib/GeoDataTreeModel.h
+++ b/src/lib/GeoDataTreeModel.h
@@ -17,6 +17,8 @@
 namespace Marble
 {
 class GeoDataDocument;
+class GeoDataFeature;
+class GeoDataContainer;
 
 /**
  * @short The representation of GeoData in a model
@@ -55,6 +57,8 @@ class GeoDataTreeModel : public QAbstractItemModel
     QModelIndex index( int row, int column,
                        const QModelIndex &parent = QModelIndex() ) const;
 
+    QModelIndex index( GeoDataFeature* obj);
+
     QModelIndex parent( const QModelIndex &index ) const;
 
     int columnCount( const QModelIndex &parent = QModelIndex() ) const;
@@ -73,6 +77,10 @@ class GeoDataTreeModel : public QAbstractItemModel
     void setRootDocument( GeoDataDocument* document );
     GeoDataDocument *rootDocument();
 
+    void addFeature( GeoDataContainer *parent, GeoDataFeature *feature );
+
+    void removeFeature( GeoDataFeature *feature );
+
     int addDocument( GeoDataDocument* document );
 
     void removeDocument( int index );


More information about the Marble-devel mailing list