[kde-edu]: [Repinging] Trying to fix - https://bugs.kde.org/show_bug.cgi?id=178572
ks.vladimir at gmail.com
Tue Feb 3 16:55:31 CET 2009
Hello Madhusudan !
On Tuesday 03 February 2009 08:56:05 Madhusudan C.S wrote:
> Hi Vladimir,
> I just went through the code as you suggested through gdb.
> On Mon, Feb 2, 2009 at 2:30 AM, Vladimir Kuznetsov
<ks.vladimir at gmail.com>wrote:
> > To check why it can be NULL, let's look at a point where the index is
> > created.
> > There are several functions in WorldModel which returns QModelIndex, but
> > all
> > of them uses WorldModel::solverIndex() function to obtain index for
> > solver which in turn calls StepCore::World::solver() function which just
> > returns _solver member of the World class.
> > Next we have to look at where that member (World::_solver) is
> > initialized. There is World::setSolver function that sets it and it is
> > called by WorldModel::swapSolver function which in turn is called by
> > CommandSetSolver class which is created in WorldModel::newSolver
> > function.
> > You could check using debugger whether WorldModel::newSolver receives a
> > correct solver class name as an argument and whether the solver is
> > created correctly. Then you could check whether it is correctly passed
> > passed to swapSolver function.
> These are the results I got. For convenience I am pasting the
> method here where the problem is occuring, please forgive :)
> StepCore::Solver* WorldModel::swapSolver(StepCore::Solver* solver)
> bool selected = selectionModel()->isSelected(solverIndex());
> bool current = selectionModel()->currentIndex() == solverIndex();
> beginRemoveRows(QModelIndex(), 1, 1);
> StepCore::Solver* oldSolver = _world->removeSolver();
> beginInsertRows(QModelIndex(), 1, 1);
> if(selected) selectionModel()->select(solverIndex(),
> if(current) selectionModel()->setCurrentIndex(solverIndex(),
> emitChanged(true, true);
> return oldSolver;
> Everything seems to be fine until first call goes to beginRemoveRows ()
> and then to _world->removeSolver(), but the program crashes when
> endRemoveRows() is called.
Hm, it seems that you are very close the the solution.
> Still not sure whats causing it. But I still did
> not understand why a new object QModelIndex() was created and passed
> to beginRemoveRows. Is that causing some kind of problem? The API
> asks to pass the parent index but we pass a newly created index.
> Is that all Ok?
This is OK, the QModelIndex is always a temporary object that just references
actual data in the model (i.e. if two QModelIndex instances have the same row,
column, parent and internalPointer then they are considered equal) so we can
always create new QModelIndex with the same data instead of passing existing
one. Here we use QModelIndex constructor that creates invalid index and
passing it as a parent means that we want to remove top-level item.
But you say that the program crashed on endInsertRows() which causes Qt to
reinspect our model by calling other methods of it. Crashing at this point
could indicate some inconsistency in the model state and as it happens after
removing the solver probably it has some connection to the solver. Indeed,
take a look at WorldModel::rowCount function. It always returns the same
number of top-level rows, moreover it asserts that the solver always exists !
Now we have two solution: either rewrite the model to allow removing the
solver, or just avoid removing the solver. Indeed, the function removes it and
immediately reinserts back which is just the same as simply changing it - we
can keep the fact that it was removed in secret from Qt :-)
Why have I added that that beginRemoveRows/... calls ? I can't remember,
probably that was just another stupid mistake that everyone sometimes makes :)
Thanks a lot for finding it !
Do you have KDE svn account ? If not, just send me a patch and I'll commit it
mentioning your name.
More information about the kde-edu