<html>
<body>
<div style="font-family: Verdana, Arial, Helvetica, Sans-Serif;">
<table bgcolor="#f9f3c9" width="100%" cellpadding="8" style="border: 1px #c9c399 solid;">
<tr>
<td>
This is an automatically generated e-mail. To reply, visit:
<a href="http://git.reviewboard.kde.org/r/102610/">http://git.reviewboard.kde.org/r/102610/</a>
</td>
</tr>
</table>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Very nice patch!
I haven't applied nor tried the code yet, only provided some nitpicks from the coding style and intent category.
It is the way to go for sure.</pre>
</blockquote>
</blockquote>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Thanks for your feedback!
See my comments below</pre>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="http://git.reviewboard.kde.org/r/102610/diff/1/?file=36119#file36119line60" style="color: black; font-weight: bold; text-decoration: underline;">src/lib/GeoDataTreeModel.h</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">class GeoDataTreeModel : public QAbstractItemModel</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">60</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "> <span class="n">QModelIndex</span> <span class="n">index</span><span class="p">(</span> <span class="n">GeoDataFeature</span><span class="o">*</span> <span class="n">feat</span> <span class="p">);</span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Your methods assume a GeoDataFeature is the base class that could ever be manipulated by the tree.
Historically I had gone even in Geometries in case of MultiGeometries (see for example parent() code), so If we still want to go there we should use a GeoDataObject i fear.
Maybe addFeature and removeFeature are enough to manipulate placemarks though.
As a todo for another time, appending a geometry in a multigeo would need handling from the model too.</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">I chose to limit the function to GeoDataFeature as a matter of efficiency; features are restricted to be children of containers and containers have a "childPosition" function (required to build the tree top-down). GeoDataObjects do not keep track of their children (iirc), and you would need to treat some (many?) classes derived from GeoDataObject individually.
A Feature seemed atomic enough to update a model with minimum impact.
If we could build a QModelIndex without going up and down the tree that would also ease the task.</pre>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="http://git.reviewboard.kde.org/r/102610/diff/1/?file=36120#file36120line431" style="color: black; font-weight: bold; text-decoration: underline;">src/lib/GeoDataTreeModel.cpp</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">Qt::ItemFlags GeoDataTreeModel::flags ( const QModelIndex & index ) const</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">431</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="n">QModelIndex</span> <span class="n">GeoDataTreeModel</span><span class="o">::</span><span class="n">index</span><span class="p">(</span> <span class="n">GeoDataFeature</span> <span class="o">*</span><span class="n">feat</span> <span class="p">)</span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Small style nitpick, please use full names for variables instead of abbreviations, even through the rest of the code</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Sorry for that one, I thought I had corrected it.</pre>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="http://git.reviewboard.kde.org/r/102610/diff/1/?file=36120#file36120line433" style="color: black; font-weight: bold; text-decoration: underline;">src/lib/GeoDataTreeModel.cpp</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">Qt::ItemFlags GeoDataTreeModel::flags ( const QModelIndex & index ) const</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">433</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "> <span class="c1">//This function recovers the QModelIndex of a given feature in the geodatatree structure.</span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">The first comment may go in the header above the method name, doxygen style, so that documentation will pick it.
The other comments for internal details are fine here.</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">OK</pre>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="http://git.reviewboard.kde.org/r/102610/diff/1/?file=36120#file36120line445" style="color: black; font-weight: bold; text-decoration: underline;">src/lib/GeoDataTreeModel.cpp</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="4"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">Qt::ItemFlags GeoDataTreeModel::flags ( const QModelIndex & index ) const</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">445</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "> <span class="n">itup</span><span class="o">=</span><span class="k">dynamic_cast</span><span class="o"><</span><span class="n">GeoDataFeature</span><span class="o">*></span> <span class="p">(</span><span class="n">itup</span><span class="o">-></span><span class="n">parent</span><span class="p">());</span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">argh, dynamic cast has proven very bad performance wise in this perfo intensive class. Could you replace with other cast or even use the nodeType() testing?
Mimetism has it that even if the code is not perfo sensitive, someone will copy the dynamic_cast idea somewhere bad...</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Ok, I tend to double-check security rather than performance, but you are right that it is a sensitive piece of code in that sense.
I don't like the nodeType testing that much but it seems to be working ok (I read someone suggesting to change it to an enum, seems like a good idea).</pre>
<br />
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<p style="margin-top: 0;">On September 14th, 2011, 6:52 p.m., <b>Thibaut Gridel</b> wrote:</p>
<blockquote style="margin-left: 1em; border-left: 2px solid #d0d0d0; padding-left: 10px;">
<table width="100%" border="0" bgcolor="white" style="border: 1px solid #C0C0C0; border-collapse: collapse; margin: 2px padding: 2px;">
<thead>
<tr>
<th colspan="4" bgcolor="#F0F0F0" style="border-bottom: 1px solid #C0C0C0; font-size: 9pt; padding: 4px 8px; text-align: left;">
<a href="http://git.reviewboard.kde.org/r/102610/diff/1/?file=36120#file36120line475" style="color: black; font-weight: bold; text-decoration: underline;">src/lib/GeoDataTreeModel.cpp</a>
<span style="font-weight: normal;">
(Diff revision 1)
</span>
</th>
</tr>
</thead>
<tbody style="background-color: #e4d9cb; padding: 4px 8px; text-align: center;">
<tr>
<td colspan="2"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<td colspan="2"><pre style="font-size: 8pt; line-height: 140%; margin: 0; ">int GeoDataTreeModel::addFeature( GeoDataContainer* parent, GeoDataFeature* feature )</pre></td>
</tr>
</tbody>
<tbody>
<tr>
<th bgcolor="#b1ebb0" style="border-right: 1px solid #C0C0C0;" align="right"><font size="2"></font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "></pre></td>
<th bgcolor="#b1ebb0" style="border-left: 1px solid #C0C0C0; border-right: 1px solid #C0C0C0;" align="right"><font size="2">475</font></th>
<td bgcolor="#c5ffc4" width="50%"><pre style="font-size: 8pt; line-height: 140%; margin: 0; "><span class="p">{</span><span class="ew"> </span></pre></td>
</tr>
</tbody>
</table>
<pre style="white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">uho, tab got introduced here... we try to stay eol clean (my editor does it for me actually)</pre>
</blockquote>
</blockquote>
<pre style="margin-left: 1em; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Sorry, I thought the editor of QtCreator handled that automatically. I will double check next time.</pre>
<br />
<p>- Javier</p>
<br />
<p>On September 14th, 2011, 10:57 a.m., Javier Becerra Elcinto wrote:</p>
<table bgcolor="#fefadf" width="100%" cellspacing="0" cellpadding="8" style="background-image: url('http://git.reviewboard.kde.org/media/rb/images/review_request_box_top_bg.png'); background-position: left top; background-repeat: repeat-x; border: 1px black solid;">
<tr>
<td>
<div>Review request for Marble.</div>
<div>By Javier Becerra Elcinto.</div>
<p style="color: grey;"><i>Updated Sept. 14, 2011, 10:57 a.m.</i></p>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Description </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
<tr>
<td>
<pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">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.</pre>
</td>
</tr>
</table>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Testing </h1>
<table width="100%" bgcolor="#ffffff" cellspacing="0" cellpadding="10" style="border: 1px solid #b8b5a0">
<tr>
<td>
<pre style="margin: 0; padding: 0; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">Files "PlacemarkInserte.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();
}
</pre>
</td>
</tr>
</table>
<h1 style="color: #575012; font-size: 10pt; margin-top: 1.5em;">Diffs</b> </h1>
<ul style="margin-left: 3em; padding-left: 0;">
<li>src/lib/GeoDataTreeModel.h <span style="color: grey">(eda4c53)</span></li>
<li>src/lib/GeoDataTreeModel.cpp <span style="color: grey">(2c17cfa)</span></li>
</ul>
<p><a href="http://git.reviewboard.kde.org/r/102610/diff/" style="margin-left: 3em;">View Diff</a></p>
</td>
</tr>
</table>
</div>
</body>
</html>