<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 <NAME> <<EMAIL>>
// Copyright 2007      <NAME>  <<EMAIL>>
// Copyright 2008, 2009, 2010 <NAME> <<EMAIL>>
// Copyright 2010-2012 <NAME> <<EMAIL>>//

#include "TextureLayer.h"

#include <QtCore/qmath.h>
#include <QtCore/QTimer>
#include <QtCore/QList>
#include <QtGui/QSortFilterProxyModel>

#include "SphericalScanlineTextureMapper.h"
#include "EquirectScanlineTextureMapper.h"
#include "MercatorScanlineTextureMapper.h"
#include "TileScalingTextureMapper.h"
#include "GeoDataGroundOverlay.h"
#include "GeoPainter.h"
#include "GeoSceneGroup.h"
#include "GeoSceneTypes.h"
#include "MergedLayerDecorator.h"
#include "MarbleDebug.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "StackedTile.h"
#include "StackedTileLoader.h"
#include "SunLocator.h"
#include "TextureColorizer.h"
#include "TileLoader.h"
#include "VectorComposer.h"
#include "ViewportParams.h"

namespace Marble
{

const int REPAINT_SCHEDULING_INTERVAL = 1000;

class TextureLayer::Private
{
public:
    Private( HttpDownloadManager *downloadManager,
             const SunLocator *sunLocator,
             VectorComposer *veccomposer,
             const PluginManager *pluginManager,
             QAbstractItemModel *groundOverlayModel,
             TextureLayer *parent );

    void requestDelayedRepaint();
    void updateTextureLayers();
    void updateTile( const TileId &tileId, const QImage &tileImage );

    void addGroundOverlays( QModelIndex parent, int first, int last );
    void removeGroundOverlays( QModelIndex parent, int first, int last );
    void resetGroundOverlaysCache();

    static bool drawOrderLessThan( const GeoDataGroundOverlay* o1, const GeoDataGroundOverlay* o2 );

public:
    TextureLayer  *const m_parent;
    const SunLocator *const m_sunLocator;
    VectorComposer *const m_veccomposer;
    TileLoader m_loader;
    MergedLayerDecorator m_layerDecorator;
    StackedTileLoader    m_tileLoader;
    GeoDataCoordinates m_centerCoordinates;
    int m_tileZoomLevel;
    TextureMapperInterface *m_texmapper;
    TextureColorizer *m_texcolorizer;
    QVector<const GeoSceneTextureTile *> m_textures;
    const GeoSceneGroup *m_textureLayerSettings;
    QString m_runtimeTrace;
    QSortFilterProxyModel m_groundOverlayModel;
    QList<const GeoDataGroundOverlay *> m_groundOverlayCache;
    // For scheduling repaints
    QTimer           m_repaintTimer;
};

TextureLayer::Private::Private( HttpDownloadManager *downloadManager,
                                const SunLocator *sunLocator,
                                VectorComposer *veccomposer,
                                const PluginManager *pluginManager,
                                QAbstractItemModel *groundOverlayModel,
                                TextureLayer *parent )
    : m_parent( parent )
    , m_sunLocator( sunLocator )
    , m_veccomposer( veccomposer )
    , m_loader( downloadManager, pluginManager )
    , m_layerDecorator( &m_loader, sunLocator )
    , m_tileLoader( &m_layerDecorator )
    , m_centerCoordinates()
    , m_tileZoomLevel( -1 )
    , m_texmapper( 0 )
    , m_texcolorizer( 0 )
    , m_textureLayerSettings( 0 )
    , m_repaintTimer()
{
    m_groundOverlayModel.setSourceModel( groundOverlayModel );
    m_groundOverlayModel.setDynamicSortFilter( true );
    m_groundOverlayModel.setSortRole ( MarblePlacemarkModel::PopularityIndexRole );
    m_groundOverlayModel.sort (0, Qt::AscendingOrder );

    connect( &m_groundOverlayModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
             m_parent,              SLOT(addGroundOverlays(QModelIndex,int,int)) );

    connect( &m_groundOverlayModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
             m_parent,              SLOT(removeGroundOverlays(QModelIndex,int,int)) );

    connect( &m_groundOverlayModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
             m_parent,              SLOT(resetGroundOverlaysCache()) );

    connect( &m_groundOverlayModel, SIGNAL(modelReset()),
             m_parent,              SLOT(resetGroundOverlaysCache()) );

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );
}

void TextureLayer::Private::requestDelayedRepaint()
{
    if ( m_texmapper ) {
        m_texmapper->setRepaintNeeded();
    }

    if ( !m_repaintTimer.isActive() ) {
        m_repaintTimer.start();
    }
}

void TextureLayer::Private::updateTextureLayers()
{
    QVector<GeoSceneTextureTile const *> result;

    foreach ( const GeoSceneTextureTile *candidate, m_textures ) {
        bool enabled = true;
        if ( m_textureLayerSettings ) {
            const bool propertyExists = m_textureLayerSettings->propertyValue( candidate->name(), enabled );
            enabled |= !propertyExists; // if property doesn't exist, enable texture nevertheless
        }
        if ( enabled ) {
            result.append( candidate );
            mDebug() << "enabling texture" << candidate->name();
        } else {
            mDebug() << "disabling texture" << candidate->name();
        }
    }

    m_layerDecorator.setTextureLayers( result );
    m_tileLoader.clear();

    m_parent->setNeedsUpdate();
}

void TextureLayer::Private::updateTile( const TileId &tileId, const QImage &tileImage )
{
    if ( tileImage.isNull() )
        return; // keep tiles in cache to improve performance

    m_tileLoader.updateTile( tileId, tileImage );

    requestDelayedRepaint();
}

bool TextureLayer::Private::drawOrderLessThan( const GeoDataGroundOverlay* o1, const GeoDataGroundOverlay* o2 )
{
    return o1->drawOrder() < o2->drawOrder();
}

void TextureLayer::Private::addGroundOverlays( QModelIndex parent, int first, int last )
{
    for ( int i = first; i <= last; ++i ) {
        QModelIndex index = m_groundOverlayModel.index( i, 0, parent );
        const GeoDataGroundOverlay *overlay = qvariant_cast<GeoDataGroundOverlay *>( index.data( MarblePlacemarkModel::ObjectPointerRole ) );

        int pos = qLowerBound( m_groundOverlayCache.begin(), m_groundOverlayCache.end(), overlay, drawOrderLessThan) - m_groundOverlayCache.begin();
        m_groundOverlayCache.insert( pos, overlay );
    }

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();
}

void TextureLayer::Private::removeGroundOverlays( QModelIndex parent, int first, int last )
{
    for ( int i = first; i <= last; ++i ) {
        QModelIndex index = m_groundOverlayModel.index( i, 0, parent );
        const GeoDataGroundOverlay *overlay = qvariant_cast<GeoDataGroundOverlay *>( index.data( MarblePlacemarkModel::ObjectPointerRole ) );

        int pos = qLowerBound( m_groundOverlayCache.begin(), m_groundOverlayCache.end(), overlay, drawOrderLessThan) - m_groundOverlayCache.begin();
        if (pos >= 0 && pos < m_groundOverlayCache.size() ) {
            m_groundOverlayCache.removeAt( pos );
        }
    }

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();
}

void TextureLayer::Private::resetGroundOverlaysCache()
{
    m_groundOverlayCache.clear();

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();<commit_msg>Restores double casting for GroundOverlays retrieved from the GeoDataTreeModel<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2006-2007 <NAME> <<EMAIL>>
// Copyright 2007      <NAME>  <<EMAIL>>
// Copyright 2008, 2009, 2010 <NAME> <<EMAIL>>
// Copyright 2010-2012 <NAME> <<EMAIL>>//

#include "TextureLayer.h"

#include <QtCore/qmath.h>
#include <QtCore/QTimer>
#include <QtCore/QList>
#include <QtGui/QSortFilterProxyModel>

#include "SphericalScanlineTextureMapper.h"
#include "EquirectScanlineTextureMapper.h"
#include "MercatorScanlineTextureMapper.h"
#include "TileScalingTextureMapper.h"
#include "GeoDataGroundOverlay.h"
#include "GeoPainter.h"
#include "GeoSceneGroup.h"
#include "GeoSceneTypes.h"
#include "MergedLayerDecorator.h"
#include "MarbleDebug.h"
#include "MarbleDirs.h"
#include "MarblePlacemarkModel.h"
#include "StackedTile.h"
#include "StackedTileLoader.h"
#include "SunLocator.h"
#include "TextureColorizer.h"
#include "TileLoader.h"
#include "VectorComposer.h"
#include "ViewportParams.h"

namespace Marble
{

const int REPAINT_SCHEDULING_INTERVAL = 1000;

class TextureLayer::Private
{
public:
    Private( HttpDownloadManager *downloadManager,
             const SunLocator *sunLocator,
             VectorComposer *veccomposer,
             const PluginManager *pluginManager,
             QAbstractItemModel *groundOverlayModel,
             TextureLayer *parent );

    void requestDelayedRepaint();
    void updateTextureLayers();
    void updateTile( const TileId &tileId, const QImage &tileImage );

    void addGroundOverlays( QModelIndex parent, int first, int last );
    void removeGroundOverlays( QModelIndex parent, int first, int last );
    void resetGroundOverlaysCache();

    static bool drawOrderLessThan( const GeoDataGroundOverlay* o1, const GeoDataGroundOverlay* o2 );

public:
    TextureLayer  *const m_parent;
    const SunLocator *const m_sunLocator;
    VectorComposer *const m_veccomposer;
    TileLoader m_loader;
    MergedLayerDecorator m_layerDecorator;
    StackedTileLoader    m_tileLoader;
    GeoDataCoordinates m_centerCoordinates;
    int m_tileZoomLevel;
    TextureMapperInterface *m_texmapper;
    TextureColorizer *m_texcolorizer;
    QVector<const GeoSceneTextureTile *> m_textures;
    const GeoSceneGroup *m_textureLayerSettings;
    QString m_runtimeTrace;
    QSortFilterProxyModel m_groundOverlayModel;
    QList<const GeoDataGroundOverlay *> m_groundOverlayCache;
    // For scheduling repaints
    QTimer           m_repaintTimer;
};

TextureLayer::Private::Private( HttpDownloadManager *downloadManager,
                                const SunLocator *sunLocator,
                                VectorComposer *veccomposer,
                                const PluginManager *pluginManager,
                                QAbstractItemModel *groundOverlayModel,
                                TextureLayer *parent )
    : m_parent( parent )
    , m_sunLocator( sunLocator )
    , m_veccomposer( veccomposer )
    , m_loader( downloadManager, pluginManager )
    , m_layerDecorator( &m_loader, sunLocator )
    , m_tileLoader( &m_layerDecorator )
    , m_centerCoordinates()
    , m_tileZoomLevel( -1 )
    , m_texmapper( 0 )
    , m_texcolorizer( 0 )
    , m_textureLayerSettings( 0 )
    , m_repaintTimer()
{
    m_groundOverlayModel.setSourceModel( groundOverlayModel );
    m_groundOverlayModel.setDynamicSortFilter( true );
    m_groundOverlayModel.setSortRole ( MarblePlacemarkModel::PopularityIndexRole );
    m_groundOverlayModel.sort (0, Qt::AscendingOrder );

    connect( &m_groundOverlayModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
             m_parent,              SLOT(addGroundOverlays(QModelIndex,int,int)) );

    connect( &m_groundOverlayModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
             m_parent,              SLOT(removeGroundOverlays(QModelIndex,int,int)) );

    connect( &m_groundOverlayModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
             m_parent,              SLOT(resetGroundOverlaysCache()) );

    connect( &m_groundOverlayModel, SIGNAL(modelReset()),
             m_parent,              SLOT(resetGroundOverlaysCache()) );

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );
}

void TextureLayer::Private::requestDelayedRepaint()
{
    if ( m_texmapper ) {
        m_texmapper->setRepaintNeeded();
    }

    if ( !m_repaintTimer.isActive() ) {
        m_repaintTimer.start();
    }
}

void TextureLayer::Private::updateTextureLayers()
{
    QVector<GeoSceneTextureTile const *> result;

    foreach ( const GeoSceneTextureTile *candidate, m_textures ) {
        bool enabled = true;
        if ( m_textureLayerSettings ) {
            const bool propertyExists = m_textureLayerSettings->propertyValue( candidate->name(), enabled );
            enabled |= !propertyExists; // if property doesn't exist, enable texture nevertheless
        }
        if ( enabled ) {
            result.append( candidate );
            mDebug() << "enabling texture" << candidate->name();
        } else {
            mDebug() << "disabling texture" << candidate->name();
        }
    }

    m_layerDecorator.setTextureLayers( result );
    m_tileLoader.clear();

    m_parent->setNeedsUpdate();
}

void TextureLayer::Private::updateTile( const TileId &tileId, const QImage &tileImage )
{
    if ( tileImage.isNull() )
        return; // keep tiles in cache to improve performance

    m_tileLoader.updateTile( tileId, tileImage );

    requestDelayedRepaint();
}

bool TextureLayer::Private::drawOrderLessThan( const GeoDataGroundOverlay* o1, const GeoDataGroundOverlay* o2 )
{
    return o1->drawOrder() < o2->drawOrder();
}

void TextureLayer::Private::addGroundOverlays( QModelIndex parent, int first, int last )
{
    for ( int i = first; i <= last; ++i ) {
        QModelIndex index = m_groundOverlayModel.index( i, 0, parent );
        const GeoDataGroundOverlay *overlay = static_cast<GeoDataGroundOverlay *>( qvariant_cast<GeoDataObject *>( index.data( MarblePlacemarkModel::ObjectPointerRole ) ) );

        int pos = qLowerBound( m_groundOverlayCache.begin(), m_groundOverlayCache.end(), overlay, drawOrderLessThan ) - m_groundOverlayCache.begin();
        m_groundOverlayCache.insert( pos, overlay );
    }

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();
}

void TextureLayer::Private::removeGroundOverlays( QModelIndex parent, int first, int last )
{
    for ( int i = first; i <= last; ++i ) {
        QModelIndex index = m_groundOverlayModel.index( i, 0, parent );
        const GeoDataGroundOverlay *overlay = static_cast<GeoDataGroundOverlay *>( qvariant_cast<GeoDataObject *>( index.data( MarblePlacemarkModel::ObjectPointerRole ) ) );

        int pos = qLowerBound( m_groundOverlayCache.begin(), m_groundOverlayCache.end(), overlay, drawOrderLessThan ) - m_groundOverlayCache.begin();
        if (pos >= 0 && pos < m_groundOverlayCache.size() ) {
            m_groundOverlayCache.removeAt( pos );
        }
    }

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();
}

void TextureLayer::Private::resetGroundOverlaysCache()
{
    m_groundOverlayCache.clear();

    m_layerDecorator.setGroundOverlays( m_groundOverlayCache );

    m_parent->reset();
{'fraction_non_alphanumeric': 0.10019527304558616, 'fraction_numerical': 0.006733553296074338, 'mean_word_length': 3.6138552345448898, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4800535', 'n_tokens_mistral': 4680, 'n_tokens_neox': 4569, 'n_words': 929}