Bug 317719 - Marble can't show several DataLayers in QML applidation
Summary: Marble can't show several DataLayers in QML applidation
Status: RESOLVED FIXED
Alias: None
Product: marble
Classification: Applications
Component: general (show other bugs)
Version: 1.4 (KDE 4.9)
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Dennis Nienhüser
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-04-02 09:53 UTC by Oleg Lyubimov
Modified: 2013-04-07 07:44 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In: KDE-4.10.3/Marble-1.5.3


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oleg Lyubimov 2013-04-02 09:53:29 UTC
When you write QML application using MarbleDeclarativeWidget and declare several (at least two) DataLayers with different list models, Marble shows only the last dataLayer and doesn't show other layers. 

Reproducible: Always

Steps to Reproduce:
1. Create QML application with 2 dataLayers (see code examples below)
2. Run the application and see only the second layer at the map.
#----------------- QML files---------------------------------------------------------
//#### Layer.qml #######################################
import QtQuick 1.1
import org.kde.edu.marble 0.11

MarbleWidget {
    id: widget
    width: 800;
    height: 600
    dataLayers: [

        DataLayer{
            id: la1
            // The model defines the data that will appear. The lon and lat
            // property of its items define their position
            // See SevenWondersOfTheAncientWorld.qml for details
            model: Model1 {}
            delegate: Rectangle {
                width: 100;
                height: 20;
                border.color: "darkgray"; border.width: 2
                radius: 4; smooth: true
                Column {
                    id: column; x: 4; y: 4; spacing: 4
                    Text {
                        id: label
                        // "name" is a property defined by items in the model
                        text: "Delegate#2"
                        width: 92
                        wrapMode: Text.Wrap
                        font.bold: true
                    }
                }
            }
        }
       ,

    DataLayer{
        id: la2
        model: Model2{}
        delegate: Rectangle {
            width: 100;
            height: 20;
            color: "blue"
            Text {
                anchors.centerIn: parent
                font.bold: true
                text: "Delegate#1"
            }
        }
    }
   ]
}
//########### Model1.qml #########################
import QtQuick 1.1

ListModel {
    ListElement{
        lon: 44.4275; lat: 32.5355
    }
    ListElement{
        lon: 28.227778; lat: 36.451111
    }
    ListElement{
        lon: 31.134358; lat: 29.979175
    }
}
############## Model2.qml ####################
import QtQuick 1.1

ListModel {

    ListElement{
        lon: 70.424056; lat: 47.037944
    }
    ListElement{
        lon: 75.363889; lat: 47.949722
    }
    ListElement{
        lon: 80.63; lat: 47.637861
    }
}
//######### End ###########
Actual Results:  
You see only the last dataLayer on the map.

Expected Results:  
You should see all dataLayers on the map.

I have spend some time to investigate this bug. and make following conclusions:
    1) function void LayerManager::Private::addPlugins() looks in the variable m_renderPlugins, and if it is not contain element with current name add this element to m_renderPlugins.
 In my test application addPlugins() adds the first plugin with dataLayer - "DeclarativeDataPlugin_1" 
when addPlugins() is called to add the second plugin with dataLayer - "DeclarativeDataPlugin_2", but the m_renderPlugins contains the element with name "DeclarativeDataPlugin_2" (instead of  "DeclarativeDataPlugin_1"). "DeclarativeDataPlugin_2 in m_renderPlugins has the same address with  "DeclarativeDataPlugin_1" . Something change this elent and I don't understand what is that.
--- So, we need to go deeper---------
   2)  We should look at function "Marble::RenderPlugin *DeclarativeDataPlugin::newInstance(const Marble::MarbleModel *marbleModel) const"
if you add qDebug to the start and to the end of this function 
( qDebug() << "Instance NameID Before" << d->m_nameId;
qDebug() << "Instance After NameID" << instance->nameId();)
you see, that the name ID is different.  I have add this "dog-nail" 

Marble::RenderPlugin *DeclarativeDataPlugin::newInstance(const Marble::MarbleModel *marbleModel) const
{
    QString name_Id_tmp = nameId();
      .
      .
    d->m_modelInstances << dataModel;
     instance->setNameId(name_Id_tmp);
    qDebug() << "Instance After NameID" << instance->nameId();
    return instance;
}

and the becomes not reproducible (I see all dataLayers on the map).
I can't find the reason, why nameId is changed in this function, but this fix works. 
Dear Marble Developers, could you tell me your mine about this bug. Where I should look to find the real reason of this bug?
Comment 1 Dennis Nienhüser 2013-04-03 20:48:49 UTC
Good catch, thanks for reporting and tracking it down. The cause is the wrong use of the shared (static) m_counter variable for nameId() in case it has not been assigned a unique string id (i.e. in .qml you're not setting some unique nameId like "myFirstLayer" for each DataLayer). Instead it must use its own (not shared) counter which is only synced with the global counter in the ctor.

I'll commit a fix shortly and backport it to 1.5 as well. If you can't / don't want to wait for the fix, you can also specify the nameId property in each DataLayer in QML as a workaround. I checked that this workaround works as well with your example above. E.g. 

DataLayer{
  id: la1
  nameId: "layer1"
  ...

DataLayer{
  id: la2
  nameId: "layer2"
  ...
Comment 2 Dennis Nienhüser 2013-04-03 20:50:07 UTC
Git commit 801e4c7dab0ec0d832c1bb4c3311236583f65f25 by Dennis Nienhüser.
Committed on 03/04/2013 at 22:39.
Pushed by nienhueser into branch 'master'.

Use shared counter only for initialization.

Fixes equality comparison for anonymous QML data layers (where nameId
is unspecified) needed to have more than one QML data layer displayed
at once.

M  +5    -4    src/plugins/declarative/DeclarativeDataPlugin.cpp

http://commits.kde.org/marble/801e4c7dab0ec0d832c1bb4c3311236583f65f25
Comment 3 Dennis Nienhüser 2013-04-03 20:55:42 UTC
Git commit b7d4c01c6ea639a173974fc16beb7dc7600c09f6 by Dennis Nienhüser.
Committed on 03/04/2013 at 22:39.
Pushed by nienhueser into branch 'KDE/4.10'.

Use shared counter only for initialization.

Fixes equality comparison for anonymous QML data layers (where nameId
is unspecified) needed to have more than one QML data layer displayed
at once.
FIXED-IN: KDE-4.10.3/Marble-1.5.3
(cherry picked from commit 801e4c7dab0ec0d832c1bb4c3311236583f65f25)

M  +5    -4    src/plugins/declarative/DeclarativeDataPlugin.cpp

http://commits.kde.org/marble/b7d4c01c6ea639a173974fc16beb7dc7600c09f6