<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 2008 Torsten Rahn <tackat@kde.org>
// Copyright 2009 Jens-Michael Hoffmann <jensmh@gmx.de>
//

// Own
#include "PluginManager.h"

// Qt
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>

// Local dir
#include "MarbleDirs.h"
#include "MarbleDebug.h"
#include "RenderPlugin.h"
#include "NetworkPlugin.h"
#include "PositionProviderPlugin.h"
#include "AbstractFloatItem.h"
#include "RunnerPlugin.h"

namespace Marble
{

class PluginManagerPrivate
{
 public:
    PluginManagerPrivate()
            : m_pluginsLoaded(false)
    {
    }

    ~PluginManagerPrivate();

    void loadPlugins();

    bool m_pluginsLoaded;
    QMap<QPluginLoader*, RenderPlugin *> m_renderPluginTemplates;
    QMap<QPluginLoader*, NetworkPlugin *> m_networkPluginTemplates;
    QMap<QPluginLoader*, PositionProviderPlugin *> m_positionProviderPluginTemplates;
    QMap<QPluginLoader*, RunnerPlugin *> m_runnerPlugins;

private:
    bool cleanup( const QList<QPluginLoader*> loaders );
};

PluginManagerPrivate::~PluginManagerPrivate()
{
    QMap<QPluginLoader*, RunnerPlugin *>::const_iterator i = m_runnerPlugins.constBegin();
    bool allUnloaded = cleanup( m_renderPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_networkPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_positionProviderPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_runnerPlugins.keys() );

    if ( allUnloaded ) {
        mDebug() << "All plugins unloaded. Plugin instances still alive will crash now.";
    }
}

bool PluginManagerPrivate::cleanup( const QList<QPluginLoader*> loaders )
{
    bool allUnloaded = true;
    foreach( QPluginLoader* loader, loaders ) {
        allUnloaded = allUnloaded && loader->unload();
        delete loader;
    }

    return allUnloaded;
}

PluginManager::PluginManager( QObject *parent )
    : QObject(parent),
      d( new PluginManagerPrivate() )
{
}

PluginManager::~PluginManager()
{
    delete d;
}

QList<AbstractFloatItem *> PluginManager::createFloatItems() const
{
    QList<AbstractFloatItem *> floatItemList;

    d->loadPlugins();

    QMap<QPluginLoader*, RenderPlugin *>::const_iterator i = d->m_renderPluginTemplates.constBegin();
    QMap<QPluginLoader*, RenderPlugin *>::const_iterator const end = d->m_renderPluginTemplates.constEnd();
    for (; i != end; ++i) {
        AbstractFloatItem * const floatItem = qobject_cast<AbstractFloatItem *>(*i);
        if ( floatItem ) {
            floatItemList.append( qobject_cast<AbstractFloatItem *>( floatItem->
                                                                     newInstance() ));
        }
    }

    return floatItemList;
}

template<class T>
QList<T*> createPlugins( PluginManagerPrivate* d, const QMap<QPluginLoader*, T*> &loaders )
{
    QList<T*> result;
    d->loadPlugins();
    typename QMap<QPluginLoader*, T*>::const_iterator i = loaders.constBegin();
    typename QMap<QPluginLoader*, T*>::const_iterator const end = loaders.constEnd();
    for (; i != end; ++i) {
        result.append( (*i)->newInstance() );
    }
    return result;
}

QList<RenderPlugin *> PluginManager::createRenderPlugins() const
{
    return createPlugins( d, d->m_renderPluginTemplates );
}

QList<NetworkPlugin *> PluginManager::createNetworkPlugins() const
{
    return createPlugins( d, d->m_networkPluginTemplates );
}

QList<PositionProviderPlugin *> PluginManager::createPositionProviderPlugins() const
{
    return createPlugins( d, d->m_positionProviderPluginTemplates );
}

QList<RunnerPlugin *> PluginManager::runnerPlugins() const
{
    d->loadPlugins();
    return d->m_runnerPlugins.values();
}

/** Append obj to the given plugins list if it inherits both T and U */
template<class T, class U>
bool appendPlugin( QObject * obj, QPluginLoader* &loader, QMap<QPluginLoader*,T*> &plugins )
{
    if ( qobject_cast<T*>( obj ) && qobject_cast<U*>( obj ) ) {
        Q_ASSERT( obj->metaObject()->superClass() ); // all our plugins have a super class
        mDebug() <<  obj->metaObject()->superClass()->className()
                << "plugin loaded from" << loader->fileName();
        T* plugin = qobject_cast<T*>( obj );
        Q_ASSERT( plugin ); // checked above
        plugins[loader] = plugin;
        return true;
    }

    return false;
}

void PluginManagerPrivate::loadPlugins()
{
    if (m_pluginsLoaded)
    {
        return;
    }

    QTime t;
    t.start();
    mDebug() << "Starting to load Plugins.";

    QStringList pluginFileNameList = MarbleDirs::pluginEntryList( "", QDir::Files );

    MarbleDirs::debug();

    qDeleteAll( m_renderPluginTemplates );
    m_renderPluginTemplates.clear();

    qDeleteAll( m_networkPluginTemplates );
    m_networkPluginTemplates.clear();

    qDeleteAll( m_positionProviderPluginTemplates );
    m_positionProviderPluginTemplates.clear();

    // No need to delete runner plugins

    foreach( const QString &fileName, pluginFileNameList ) {
        // mDebug() << fileName << " - " << MarbleDirs::pluginPath( fileName );
        QString const path = MarbleDirs::pluginPath( fileName );
        QPluginLoader* loader = new QPluginLoader( path );

        QObject * obj = loader->instance();

        if ( obj ) {
            bool isPlugin = appendPlugin<RenderPlugin, RenderPluginInterface>
                       ( obj, loader, m_renderPluginTemplates );
            isPlugin = isPlugin || appendPlugin<NetworkPlugin, NetworkPluginInterface>
                       ( obj, loader, m_networkPluginTemplates );
            isPlugin = isPlugin || appendPlugin<PositionProviderPlugin, PositionProviderPluginInterface>
                       ( obj, loader, m_positionProviderPluginTemplates );
            isPlugin = isPlugin || appendPlugin<RunnerPlugin, RunnerPlugin>
                       ( obj, loader, m_runnerPlugins ); // intentionally T==U
            if ( !isPlugin ) {
                mDebug() << "Plugin failure:" << fileName << "is a plugin, but it does not implement the "
                        << "right interfaces or it was compiled against an old version of Marble. Ignoring it.";
                delete loader;
            }
        } else {
            mDebug() << "Plugin failure:" << fileName << "is not a valid Marble Plugin:"
                     << loader->errorString();
        }
    }

    m_pluginsLoaded = true;
    qDebug("Time elapsed: %d ms", t.elapsed());
}

}

#include "PluginManager.moc"
<commit_msg>remove set but unused variable (reported by GCC)<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 2008 Torsten Rahn <tackat@kde.org>
// Copyright 2009 Jens-Michael Hoffmann <jensmh@gmx.de>
//

// Own
#include "PluginManager.h"

// Qt
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>

// Local dir
#include "MarbleDirs.h"
#include "MarbleDebug.h"
#include "RenderPlugin.h"
#include "NetworkPlugin.h"
#include "PositionProviderPlugin.h"
#include "AbstractFloatItem.h"
#include "RunnerPlugin.h"

namespace Marble
{

class PluginManagerPrivate
{
 public:
    PluginManagerPrivate()
            : m_pluginsLoaded(false)
    {
    }

    ~PluginManagerPrivate();

    void loadPlugins();

    bool m_pluginsLoaded;
    QMap<QPluginLoader*, RenderPlugin *> m_renderPluginTemplates;
    QMap<QPluginLoader*, NetworkPlugin *> m_networkPluginTemplates;
    QMap<QPluginLoader*, PositionProviderPlugin *> m_positionProviderPluginTemplates;
    QMap<QPluginLoader*, RunnerPlugin *> m_runnerPlugins;

private:
    bool cleanup( const QList<QPluginLoader*> loaders );
};

PluginManagerPrivate::~PluginManagerPrivate()
{
    bool allUnloaded = cleanup( m_renderPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_networkPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_positionProviderPluginTemplates.keys() );
    allUnloaded = allUnloaded && cleanup( m_runnerPlugins.keys() );

    if ( allUnloaded ) {
        mDebug() << "All plugins unloaded. Plugin instances still alive will crash now.";
    }
}

bool PluginManagerPrivate::cleanup( const QList<QPluginLoader*> loaders )
{
    bool allUnloaded = true;
    foreach( QPluginLoader* loader, loaders ) {
        allUnloaded = allUnloaded && loader->unload();
        delete loader;
    }

    return allUnloaded;
}

PluginManager::PluginManager( QObject *parent )
    : QObject(parent),
      d( new PluginManagerPrivate() )
{
}

PluginManager::~PluginManager()
{
    delete d;
}

QList<AbstractFloatItem *> PluginManager::createFloatItems() const
{
    QList<AbstractFloatItem *> floatItemList;

    d->loadPlugins();

    QMap<QPluginLoader*, RenderPlugin *>::const_iterator i = d->m_renderPluginTemplates.constBegin();
    QMap<QPluginLoader*, RenderPlugin *>::const_iterator const end = d->m_renderPluginTemplates.constEnd();
    for (; i != end; ++i) {
        AbstractFloatItem * const floatItem = qobject_cast<AbstractFloatItem *>(*i);
        if ( floatItem ) {
            floatItemList.append( qobject_cast<AbstractFloatItem *>( floatItem->
                                                                     newInstance() ));
        }
    }

    return floatItemList;
}

template<class T>
QList<T*> createPlugins( PluginManagerPrivate* d, const QMap<QPluginLoader*, T*> &loaders )
{
    QList<T*> result;
    d->loadPlugins();
    typename QMap<QPluginLoader*, T*>::const_iterator i = loaders.constBegin();
    typename QMap<QPluginLoader*, T*>::const_iterator const end = loaders.constEnd();
    for (; i != end; ++i) {
        result.append( (*i)->newInstance() );
    }
    return result;
}

QList<RenderPlugin *> PluginManager::createRenderPlugins() const
{
    return createPlugins( d, d->m_renderPluginTemplates );
}

QList<NetworkPlugin *> PluginManager::createNetworkPlugins() const
{
    return createPlugins( d, d->m_networkPluginTemplates );
}

QList<PositionProviderPlugin *> PluginManager::createPositionProviderPlugins() const
{
    return createPlugins( d, d->m_positionProviderPluginTemplates );
}

QList<RunnerPlugin *> PluginManager::runnerPlugins() const
{
    d->loadPlugins();
    return d->m_runnerPlugins.values();
}

/** Append obj to the given plugins list if it inherits both T and U */
template<class T, class U>
bool appendPlugin( QObject * obj, QPluginLoader* &loader, QMap<QPluginLoader*,T*> &plugins )
{
    if ( qobject_cast<T*>( obj ) && qobject_cast<U*>( obj ) ) {
        Q_ASSERT( obj->metaObject()->superClass() ); // all our plugins have a super class
        mDebug() <<  obj->metaObject()->superClass()->className()
                << "plugin loaded from" << loader->fileName();
        T* plugin = qobject_cast<T*>( obj );
        Q_ASSERT( plugin ); // checked above
        plugins[loader] = plugin;
        return true;
    }

    return false;
}

void PluginManagerPrivate::loadPlugins()
{
    if (m_pluginsLoaded)
    {
        return;
    }

    QTime t;
    t.start();
    mDebug() << "Starting to load Plugins.";

    QStringList pluginFileNameList = MarbleDirs::pluginEntryList( "", QDir::Files );

    MarbleDirs::debug();

    qDeleteAll( m_renderPluginTemplates );
    m_renderPluginTemplates.clear();

    qDeleteAll( m_networkPluginTemplates );
    m_networkPluginTemplates.clear();

    qDeleteAll( m_positionProviderPluginTemplates );
    m_positionProviderPluginTemplates.clear();

    // No need to delete runner plugins

    foreach( const QString &fileName, pluginFileNameList ) {
        // mDebug() << fileName << " - " << MarbleDirs::pluginPath( fileName );
        QString const path = MarbleDirs::pluginPath( fileName );
        QPluginLoader* loader = new QPluginLoader( path );

        QObject * obj = loader->instance();

        if ( obj ) {
            bool isPlugin = appendPlugin<RenderPlugin, RenderPluginInterface>
                       ( obj, loader, m_renderPluginTemplates );
            isPlugin = isPlugin || appendPlugin<NetworkPlugin, NetworkPluginInterface>
                       ( obj, loader, m_networkPluginTemplates );
            isPlugin = isPlugin || appendPlugin<PositionProviderPlugin, PositionProviderPluginInterface>
                       ( obj, loader, m_positionProviderPluginTemplates );
            isPlugin = isPlugin || appendPlugin<RunnerPlugin, RunnerPlugin>
                       ( obj, loader, m_runnerPlugins ); // intentionally T==U
            if ( !isPlugin ) {
                mDebug() << "Plugin failure:" << fileName << "is a plugin, but it does not implement the "
                        << "right interfaces or it was compiled against an old version of Marble. Ignoring it.";
                delete loader;
            }
        } else {
            mDebug() << "Plugin failure:" << fileName << "is not a valid Marble Plugin:"
                     << loader->errorString();
        }
    }

    m_pluginsLoaded = true;
    qDebug("Time elapsed: %d ms", t.elapsed());
}

}

#include "PluginManager.moc"
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop 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 2008 Torsten Rahn <tackat@kde.org>"
//

// Own
#include "PluginManager.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>

// Local dir
#include "MarbleDirs.h"
#include "MarbleRenderPlugin.h"
#include "MarbleAbstractFloatItem.h"

namespace Marble
{

class PluginManagerPrivate
{
 public:
    PluginManagerPrivate()
    {
    }

    QList<MarbleRenderPlugin *> m_renderPlugins;
};

PluginManager::PluginManager( QObject *parent )
    : QObject(parent),
      d( new PluginManagerPrivate() )
{
    // For testing:
    QTime t;
    t.start();
    loadPlugins();
    qDebug("Time elapsed: %d ms", t.elapsed());
}

PluginManager::~PluginManager()
{
    qDeleteAll( d->m_renderPlugins );
    d->m_renderPlugins.clear();
    delete d;
}

QList<MarbleAbstractFloatItem *> PluginManager::floatItems() const
{
    QList<MarbleAbstractFloatItem *> floatItemList;

    QList<MarbleRenderPlugin *>::const_iterator i = d->m_renderPlugins.constBegin();
    for (; i != d->m_renderPlugins.constEnd(); ++i)
    {
        MarbleAbstractFloatItem *floatItem = qobject_cast<MarbleAbstractFloatItem *>(*i);
        if ( floatItem )
        {
            floatItemList.append( floatItem );
        }
    }

    return floatItemList;
}

QList<MarbleRenderPlugin *> PluginManager::renderPlugins() const
{
    return d->m_renderPlugins;
}

void PluginManager::loadPlugins()
{
    qDebug() << "Starting to load Plugins.";
    QStringList pluginFileNameList;

    pluginFileNameList = MarbleDirs::pluginEntryList( "", QDir::Files );

    MarbleDirs::debug();

    qDeleteAll( d->m_renderPlugins );
    d->m_renderPlugins.clear();

    foreach( const QString &fileName, pluginFileNameList ) {
        qDebug() << fileName << " - " << MarbleDirs::pluginPath( fileName );
        QPluginLoader loader( MarbleDirs::pluginPath( fileName ) );

        QObject * obj = loader.instance();

        MarbleRenderPlugin * layerPlugin;
        if ( obj ) {
            layerPlugin = qobject_cast<MarbleRenderPlugin *>(obj)->pluginInstance();
        }

        if( obj && layerPlugin ) {
            d->m_renderPlugins.append( layerPlugin );
        }
        else {
            qDebug() << "Plugin Failure: " << fileName << " is not a valid Marble Plugin:";
            qDebug() << loader.errorString();
        }
    }
}

}

#include "PluginManager.moc"
<commit_msg>Coding style: brackets.<commit_after>//
// This file is part of the Marble Desktop 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 2008 Torsten Rahn <tackat@kde.org>"
//

// Own
#include "PluginManager.h"

// Qt
#include <QtCore/QDebug>
#include <QtCore/QList>
#include <QtCore/QPluginLoader>
#include <QtCore/QTime>

// Local dir
#include "MarbleDirs.h"
#include "MarbleRenderPlugin.h"
#include "MarbleAbstractFloatItem.h"

namespace Marble
{

class PluginManagerPrivate
{
 public:
    PluginManagerPrivate()
    {
    }

    QList<MarbleRenderPlugin *> m_renderPlugins;
};

PluginManager::PluginManager( QObject *parent )
    : QObject(parent),
      d( new PluginManagerPrivate() )
{
    // For testing:
    QTime t;
    t.start();
    loadPlugins();
    qDebug("Time elapsed: %d ms", t.elapsed());
}

PluginManager::~PluginManager()
{
    qDeleteAll( d->m_renderPlugins );
    d->m_renderPlugins.clear();
    delete d;
}

QList<MarbleAbstractFloatItem *> PluginManager::floatItems() const
{
    QList<MarbleAbstractFloatItem *> floatItemList;

    QList<MarbleRenderPlugin *>::const_iterator i = d->m_renderPlugins.constBegin();
    for (; i != d->m_renderPlugins.constEnd(); ++i) {
        MarbleAbstractFloatItem *floatItem = qobject_cast<MarbleAbstractFloatItem *>(*i);
        if ( floatItem ) {
            floatItemList.append( floatItem );
        }
    }

    return floatItemList;
}

QList<MarbleRenderPlugin *> PluginManager::renderPlugins() const
{
    return d->m_renderPlugins;
}

void PluginManager::loadPlugins()
{
    qDebug() << "Starting to load Plugins.";
    QStringList pluginFileNameList;

    pluginFileNameList = MarbleDirs::pluginEntryList( "", QDir::Files );

    MarbleDirs::debug();

    qDeleteAll( d->m_renderPlugins );
    d->m_renderPlugins.clear();

    foreach( const QString &fileName, pluginFileNameList ) {
        qDebug() << fileName << " - " << MarbleDirs::pluginPath( fileName );
        QPluginLoader loader( MarbleDirs::pluginPath( fileName ) );

        QObject * obj = loader.instance();

        MarbleRenderPlugin * layerPlugin;
        if ( obj ) {
            layerPlugin = qobject_cast<MarbleRenderPlugin *>(obj)->pluginInstance();
        }

        if( obj && layerPlugin ) {
            d->m_renderPlugins.append( layerPlugin );
        }
        else {
            qDebug() << "Plugin Failure: " << fileName << " is not a valid Marble Plugin:";
            qDebug() << loader.errorString();
        }
    }
}

}

#include "PluginManager.moc"
<|endoftext|>


<commit_before>#pragma once

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "chunk.hpp"
#include "common.hpp"
#include "types.hpp"

namespace opossum {
// A table is partitioned horizontally into a number of chunks
class Table {
 public:
  // creates a table
  // the parameter specifies the maximum chunk size, i.e., partition size
  // default (0) is an unlimited size. A table holds always at least one chunk
  explicit Table(const size_t chunk_size = 0, const bool auto_compress = false);

  // copying a table is not allowed
  Table(Table const &) = delete;
  Table &operator=(const Table &) = delete;

  // we need to explicitly set the move constructor to default when
  // we overwrite the copy constructor
  Table(Table &&) = default;
  Table &operator=(Table &&) = default;

  // returns the number of columns
  size_t col_count() const;

  // returns the number of rows
  size_t row_count() const;

  // returns the number of chunks
  size_t chunk_count() const;

  // returns the chunk with the given id
  Chunk &get_chunk(ChunkID chunk_id);
  const Chunk &get_chunk(ChunkID chunk_id) const;

  // adds a chunk to the table
  void add_chunk(Chunk chunk);

  // returns the column name of the nth column
  const std::string &column_name(size_t column_id) const;

  // returns the column type of the nth column
  const std::string &column_type(size_t column_id) const;

  // returns the column with the given name
  size_t column_id_by_name(const std::string &column_name) const;

  // return the maximum chunk size
  size_t chunk_size() const;

  // adds a column to the end, i.e., right, of the table
  void add_column(const std::string &name, const std::string &type, bool create_value_column = true);

  // inserts a row at the end of the table
  void append(std::vector<AllTypeVariant> values);

  // returns the number of the chunk and the position in the chunk for a given row
  // TODO(md): this would be a nice place to use structured bindings once they are supported by the compilers
  inline std::pair<ChunkID, ChunkOffset> locate_row(RowID row) const { return {row.chunk_id, row.chunk_offset}; }

  // calculates the row id from a given chunk and the chunk offset
  inline RowID calculate_row_id(ChunkID chunk, ChunkOffset offset) const { return RowID{chunk, offset}; }

  // enforces dictionary compression on a certain chunk
  void compress_chunk(ChunkID chunk_id);

 protected:
  // 0 means that the chunk has an unlimited size.
  const size_t _chunk_size;
  const bool _auto_compress;
  std::vector<Chunk> _chunks;

  // these should be const strings, but having a vector of const values is a C++17 feature
  // that is not yet completely implemented in all compilers
  std::vector<std::string> _column_names;
  std::vector<std::string> _column_types;
};
}  // namespace opossum
<commit_msg>Removes unused inline<commit_after>#pragma once

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "chunk.hpp"
#include "common.hpp"
#include "types.hpp"

namespace opossum {
// A table is partitioned horizontally into a number of chunks
class Table {
 public:
  // creates a table
  // the parameter specifies the maximum chunk size, i.e., partition size
  // default (0) is an unlimited size. A table holds always at least one chunk
  explicit Table(const size_t chunk_size = 0, const bool auto_compress = false);

  // copying a table is not allowed
  Table(Table const &) = delete;
  Table &operator=(const Table &) = delete;

  // we need to explicitly set the move constructor to default when
  // we overwrite the copy constructor
  Table(Table &&) = default;
  Table &operator=(Table &&) = default;

  // returns the number of columns
  size_t col_count() const;

  // returns the number of rows
  size_t row_count() const;

  // returns the number of chunks
  size_t chunk_count() const;

  // returns the chunk with the given id
  Chunk &get_chunk(ChunkID chunk_id);
  const Chunk &get_chunk(ChunkID chunk_id) const;

  // adds a chunk to the table
  void add_chunk(Chunk chunk);

  // returns the column name of the nth column
  const std::string &column_name(size_t column_id) const;

  // returns the column type of the nth column
  const std::string &column_type(size_t column_id) const;

  // returns the column with the given name
  size_t column_id_by_name(const std::string &column_name) const;

  // return the maximum chunk size
  size_t chunk_size() const;

  // adds a column to the end, i.e., right, of the table
  void add_column(const std::string &name, const std::string &type, bool create_value_column = true);

  // inserts a row at the end of the table
  void append(std::vector<AllTypeVariant> values);

  // returns the number of the chunk and the position in the chunk for a given row
  // TODO(md): this would be a nice place to use structured bindings once they are supported by the compilers
  std::pair<ChunkID, ChunkOffset> locate_row(RowID row) const { return {row.chunk_id, row.chunk_offset}; }

  // calculates the row id from a given chunk and the chunk offset
  RowID calculate_row_id(ChunkID chunk, ChunkOffset offset) const { return RowID{chunk, offset}; }

  // enforces dictionary compression on a certain chunk
  void compress_chunk(ChunkID chunk_id);

 protected:
  // 0 means that the chunk has an unlimited size.
  const size_t _chunk_size;
  const bool _auto_compress;
  std::vector<Chunk> _chunks;

  // these should be const strings, but having a vector of const values is a C++17 feature
  // that is not yet completely implemented in all compilers
  std::vector<std::string> _column_names;
  std::vector<std::string> _column_types;
};
}  // namespace opossum
<|endoftext|>


<commit_before>#include "channel.h"
#include "timing/timingfactory.h"

class Channel::Private
{
public:
    Private()
    : id(0)
    {
    }

    int id;
    QString target;
    QString certificate;
    TimingPtr timing;
};

Channel::Channel()
: d(new Private)
{
}

Channel::Channel(const int &id, const QString &target, const QString &certificate, const TimingPtr &timing)
: d(new Private)
{
    d->id = id;
    d->target = target;
    d->certificate = certificate;
    d->timing = timing;
}

Channel::~Channel()
{
    delete d;
}

ChannelPtr Channel::fromVariant(const QVariant &variant)
{
    QVariantMap hash = variant.toMap();

    return ChannelPtr(new Channel(hash.value("id").toInt(),
                                  hash.value("target").toString(),
                                  hash.value("certificate").toString(),
                                  TimingFactory::timingFromVariant(hash.value("timing"))));
}

QVariant Channel::toVariant() const
{
    QVariantMap hash;
    hash.insert("id", d->id);
    hash.insert("target", d->target);
    hash.insert("certificate", d->certificate);
    hash.insert("timing", d->timing->toVariant());
    return hash;
}

void Channel::setTarget(const QString &target)
{
    d->target = target;
}

QString Channel::target() const
{
    return d->target;
}

TimingPtr Channel::timing() const
{
    return d->timing;
}
<commit_msg>Fix bug when timing is not set inc hannel<commit_after>#include "channel.h"
#include "timing/timingfactory.h"

class Channel::Private
{
public:
    Private()
    : id(0)
    {
    }

    int id;
    QString target;
    QString certificate;
    TimingPtr timing;
};

Channel::Channel()
: d(new Private)
{
}

Channel::Channel(const int &id, const QString &target, const QString &certificate, const TimingPtr &timing)
: d(new Private)
{
    d->id = id;
    d->target = target;
    d->certificate = certificate;
    d->timing = timing;
}

Channel::~Channel()
{
    delete d;
}

ChannelPtr Channel::fromVariant(const QVariant &variant)
{
    QVariantMap hash = variant.toMap();

    return ChannelPtr(new Channel(hash.value("id").toInt(),
                                  hash.value("target").toString(),
                                  hash.value("certificate").toString(),
                                  TimingFactory::timingFromVariant(hash.value("timing"))));
}

QVariant Channel::toVariant() const
{
    QVariantMap hash;
    hash.insert("id", d->id);
    hash.insert("target", d->target);
    hash.insert("certificate", d->certificate);
    if(d->timing)
    {
        hash.insert("timing", d->timing->toVariant());
    }
    return hash;
}

void Channel::setTarget(const QString &target)
{
    d->target = target;
}

QString Channel::target() const
{
    return d->target;
}

TimingPtr Channel::timing() const
{
    return d->timing;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "core/dom/ClientRect.h"
#include "core/dom/ClientRectList.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/page/EventHandler.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/testing/URLTestHelpers.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "public/platform/Platform.h"
#include "public/platform/WebUnitTestSupport.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFrame.h"
#include "public/web/WebHitTestResult.h"
#include "public/web/WebInputEvent.h"
#include "public/web/WebTouchAction.h"
#include "public/web/WebView.h"
#include "public/web/WebViewClient.h"
#include "public/web/WebWidgetClient.h"
#include "web/WebViewImpl.h"
#include "web/tests/FrameTestHelpers.h"

#include <gtest/gtest.h>

using namespace blink;
using blink::FrameTestHelpers::runPendingTasks;

namespace {

class TouchActionTrackingWebViewClient : public FrameTestHelpers::TestWebViewClient {
public:
    TouchActionTrackingWebViewClient() :
        m_actionSetCount(0),
        m_action(WebTouchActionAuto)
    {
    }

    // WebWidgetClient methods
    virtual void setTouchAction(WebTouchAction touchAction)
    {
        m_actionSetCount++;
        m_action = touchAction;
    }

    // Local methods
    void reset()
    {
        m_actionSetCount = 0;
        m_action = WebTouchActionAuto;
    }

    int touchActionSetCount()
    {
        return m_actionSetCount;
    }

    WebTouchAction lastTouchAction()
    {
        return m_action;
    }

private:
    int m_actionSetCount;
    WebTouchAction m_action;
};

const int kfakeTouchId = 7;

class TouchActionTest : public testing::Test {
public:
    TouchActionTest()
        : m_baseURL("http://www.test.com/")
    {
        URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), "touch-action-tests.css");
        URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), "touch-action-tests.js");
    }

    virtual void TearDown()
    {
        Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
    }

protected:
    void runTouchActionTest(std::string file);
    void runShadowDOMTest(std::string file);
    void sendTouchEvent(WebView*, WebInputEvent::Type, blink::IntPoint clientPoint);
    WebView* setupTest(std::string file, TouchActionTrackingWebViewClient&);
    void runTestOnTree(blink::ContainerNode* root, WebView*, TouchActionTrackingWebViewClient&);

    std::string m_baseURL;
    FrameTestHelpers::WebViewHelper m_webViewHelper;
};

void TouchActionTest::runTouchActionTest(std::string file)
{
    TouchActionTrackingWebViewClient client;

    // runTouchActionTest() loads a document in a frame, setting up a
    // nested message loop. Should any Oilpan GC happen while it is in
    // effect, the implicit assumption that we're outside any event
    // loop (=> there being no pointers on the stack needing scanning)
    // when that GC strikes will no longer hold.
    //
    // To ensure that the references on the stack are also traced, we
    // turn them into persistent, stack allocated references. This
    // workaround is sufficient to handle this artificial test
    // scenario.
    WebView* webView = setupTest(file, client);

    RefPtrWillBePersistent<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    runTestOnTree(document.get(), webView, client);

    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
}

void TouchActionTest::runShadowDOMTest(std::string file)
{
    TouchActionTrackingWebViewClient client;

    WebView* webView = setupTest(file, client);

    blink::TrackExceptionState es;

    // Oilpan: see runTouchActionTest() comment why these are persistent references.
    RefPtrWillBePersistent<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    RefPtrWillBePersistent<blink::StaticElementList> hostNodes = document->querySelectorAll("[shadow-host]", es);
    ASSERT_FALSE(es.hadException());
    ASSERT_GE(hostNodes->length(), 1u);

    for (unsigned index = 0; index < hostNodes->length(); index++) {
        blink::ShadowRoot* shadowRoot = hostNodes->item(index)->shadowRoot();
        runTestOnTree(shadowRoot, webView, client);
    }

    // Projections show up in the main document.
    runTestOnTree(document.get(), webView, client);

    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
}

WebView* TouchActionTest::setupTest(std::string file, TouchActionTrackingWebViewClient& client)
{
    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), WebString::fromUTF8(file));
    // Note that JavaScript must be enabled for shadow DOM tests.
    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + file, true, 0, &client);

    // Lock page scale factor to avoid zooming out to contents size.
    m_webViewHelper.webView()->setPageScaleFactorLimits(1, 1);

    // Set size to enable hit testing, and avoid line wrapping for consistency with browser.
    webView->resize(WebSize(800, 1200));

    // Scroll to verify the code properly transforms windows to client co-ords.
    const int kScrollOffset = 100;
    RefPtrWillBeRawPtr<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    document->frame()->view()->setScrollOffset(blink::IntPoint(0, kScrollOffset));

    return webView;
}

void TouchActionTest::runTestOnTree(blink::ContainerNode* root, WebView* webView, TouchActionTrackingWebViewClient& client)
{
    // Find all elements to test the touch-action of in the document.
    blink::TrackExceptionState es;

    // Oilpan: see runTouchActionTest() comment why these are persistent references.
    RefPtrWillBePersistent<blink::StaticElementList> elements = root->querySelectorAll("[expected-action]", es);
    ASSERT_FALSE(es.hadException());

    for (unsigned index = 0; index < elements->length(); index++) {
        Element* element = elements->item(index);
        element->scrollIntoViewIfNeeded();

        std::string failureContext("Test case: ");
        if (element->hasID()) {
            failureContext.append(element->getIdAttribute().ascii().data());
        } else if (element->firstChild()) {
            failureContext.append("\"");
            failureContext.append(element->firstChild()->textContent(false).stripWhiteSpace().ascii().data());
            failureContext.append("\"");
        } else {
            failureContext += "<missing ID>";
        }

        // Run each test three times at different positions in the element.
        // Note that we don't want the bounding box because our tests sometimes have elements with
        // multiple border boxes with other elements in between. Use the first border box (which
        // we can easily visualize in a browser for debugging).
        RefPtrWillBePersistent<blink::ClientRectList> rects = element->getClientRects();
        ASSERT_GE(rects->length(), 0u) << failureContext;
        RefPtrWillBePersistent<blink::ClientRect> r = rects->item(0);
        blink::FloatRect clientFloatRect = blink::FloatRect(r->left(), r->top(), r->width(), r->height());
        blink::IntRect clientRect =  enclosedIntRect(clientFloatRect);
        for (int locIdx = 0; locIdx < 3; locIdx++) {
            blink::IntPoint clientPoint;
            std::stringstream contextStream;
            contextStream << failureContext << " (";
            switch (locIdx) {
            case 0:
                clientPoint = clientRect.center();
                contextStream << "center";
                break;
            case 1:
                clientPoint = clientRect.location();
                contextStream << "top-left";
                break;
            case 2:
                clientPoint = clientRect.maxXMaxYCorner();
                clientPoint.move(-1, -1);
                contextStream << "bottom-right";
                break;
            default:
                FAIL() << "Invalid location index.";
            }
            contextStream << "=" << clientPoint.x() << "," << clientPoint.y() << ").";
            std::string failureContextPos = contextStream.str();

            blink::LocalFrame* frame = root->document().frame();
            blink::FrameView* frameView = frame->view();
            blink::IntRect visibleRect = frameView->windowClipRect();
            ASSERT_TRUE(visibleRect.contains(clientPoint)) << failureContextPos
                << " Test point not contained in visible area: " << visibleRect.x() << "," << visibleRect.y()
                << "-" << visibleRect.maxX() << "," << visibleRect.maxY();

            // First validate that a hit test at this point will really hit the element
            // we intended. This is the easiest way for a test to be broken, but has nothing really
            // to do with touch action.
            // Note that we can't use WebView's hit test API because it doesn't look into shadow DOM.
            blink::IntPoint docPoint(frameView->windowToContents(clientPoint));
            blink::HitTestResult result = frame->eventHandler().hitTestResultAtPoint(docPoint, blink::HitTestRequest::ReadOnly | blink::HitTestRequest::Active);
            ASSERT_EQ(element, result.innerElement()) << "Unexpected hit test result " << failureContextPos
                << "  Got element: \"" << result.innerElement()->outerHTML().stripWhiteSpace().left(80).ascii().data() << "\""
                << std::endl << "Document render tree:" << std::endl << externalRepresentation(root->document().frame()).utf8().data();

            // Now send the touch event and check any touch action result.
            sendTouchEvent(webView, WebInputEvent::TouchStart, clientPoint);

            AtomicString expectedAction = element->getAttribute("expected-action");
            if (expectedAction == "auto") {
                // Auto is the default - no action set.
                EXPECT_EQ(0, client.touchActionSetCount()) << failureContextPos;
                EXPECT_EQ(WebTouchActionAuto, client.lastTouchAction()) << failureContextPos;
            } else {
                // Should have received exactly one touch action.
                EXPECT_EQ(1, client.touchActionSetCount()) << failureContextPos;
                if (client.touchActionSetCount()) {
                    if (expectedAction == "none") {
                        EXPECT_EQ(WebTouchActionNone, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-x") {
                        EXPECT_EQ(WebTouchActionPanX, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-y") {
                        EXPECT_EQ(WebTouchActionPanY, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-x-y") {
                        EXPECT_EQ((WebTouchActionPanX | WebTouchActionPanY), client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "manipulation") {
                        EXPECT_EQ((WebTouchActionPanX | WebTouchActionPanY | WebTouchActionPinchZoom), client.lastTouchAction()) << failureContextPos;
                    } else {
                        FAIL() << "Unrecognized expected-action \"" << expectedAction.ascii().data()
                            << "\" " << failureContextPos;
                    }
                }
            }

            // Reset webview touch state.
            client.reset();
            sendTouchEvent(webView, WebInputEvent::TouchCancel, clientPoint);
            EXPECT_EQ(0, client.touchActionSetCount());
        }
    }
}
void TouchActionTest::sendTouchEvent(WebView* webView, WebInputEvent::Type type, blink::IntPoint clientPoint)
{
    ASSERT_TRUE(type == WebInputEvent::TouchStart || type == WebInputEvent::TouchCancel);

    WebTouchEvent webTouchEvent;
    webTouchEvent.type = type;
    if (type == WebInputEvent::TouchCancel)
        webTouchEvent.cancelable = false;
    webTouchEvent.touchesLength = 1;
    webTouchEvent.touches[0].state = (type == WebInputEvent::TouchStart ?
        WebTouchPoint::StatePressed :
        WebTouchPoint::StateCancelled);
    webTouchEvent.touches[0].id = kfakeTouchId;
    webTouchEvent.touches[0].screenPosition.x = clientPoint.x();
    webTouchEvent.touches[0].screenPosition.y = clientPoint.y();
    webTouchEvent.touches[0].position.x = clientPoint.x();
    webTouchEvent.touches[0].position.y = clientPoint.y();
    webTouchEvent.touches[0].radiusX = 10;
    webTouchEvent.touches[0].radiusY = 10;

    webView->handleInputEvent(webTouchEvent);
    runPendingTasks();
}

TEST_F(TouchActionTest, Simple)
{
    runTouchActionTest("touch-action-simple.html");
}

TEST_F(TouchActionTest, Overflow)
{
    runTouchActionTest("touch-action-overflow.html");
}

TEST_F(TouchActionTest, ShadowDOM)
{
    runShadowDOMTest("touch-action-shadow-dom.html");
}

TEST_F(TouchActionTest, Pan)
{
    runTouchActionTest("touch-action-pan.html");
}

}
<commit_msg>Disable webkit_unit_tests TouchActionTest.Simple<commit_after>/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include "core/dom/ClientRect.h"
#include "core/dom/ClientRectList.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/page/EventHandler.h"
#include "core/rendering/HitTestResult.h"
#include "core/rendering/RenderTreeAsText.h"
#include "core/testing/URLTestHelpers.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "public/platform/Platform.h"
#include "public/platform/WebUnitTestSupport.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFrame.h"
#include "public/web/WebHitTestResult.h"
#include "public/web/WebInputEvent.h"
#include "public/web/WebTouchAction.h"
#include "public/web/WebView.h"
#include "public/web/WebViewClient.h"
#include "public/web/WebWidgetClient.h"
#include "web/WebViewImpl.h"
#include "web/tests/FrameTestHelpers.h"

#include <gtest/gtest.h>

using namespace blink;
using blink::FrameTestHelpers::runPendingTasks;

namespace {

class TouchActionTrackingWebViewClient : public FrameTestHelpers::TestWebViewClient {
public:
    TouchActionTrackingWebViewClient() :
        m_actionSetCount(0),
        m_action(WebTouchActionAuto)
    {
    }

    // WebWidgetClient methods
    virtual void setTouchAction(WebTouchAction touchAction)
    {
        m_actionSetCount++;
        m_action = touchAction;
    }

    // Local methods
    void reset()
    {
        m_actionSetCount = 0;
        m_action = WebTouchActionAuto;
    }

    int touchActionSetCount()
    {
        return m_actionSetCount;
    }

    WebTouchAction lastTouchAction()
    {
        return m_action;
    }

private:
    int m_actionSetCount;
    WebTouchAction m_action;
};

const int kfakeTouchId = 7;

class TouchActionTest : public testing::Test {
public:
    TouchActionTest()
        : m_baseURL("http://www.test.com/")
    {
        URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), "touch-action-tests.css");
        URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), "touch-action-tests.js");
    }

    virtual void TearDown()
    {
        Platform::current()->unitTestSupport()->unregisterAllMockedURLs();
    }

protected:
    void runTouchActionTest(std::string file);
    void runShadowDOMTest(std::string file);
    void sendTouchEvent(WebView*, WebInputEvent::Type, blink::IntPoint clientPoint);
    WebView* setupTest(std::string file, TouchActionTrackingWebViewClient&);
    void runTestOnTree(blink::ContainerNode* root, WebView*, TouchActionTrackingWebViewClient&);

    std::string m_baseURL;
    FrameTestHelpers::WebViewHelper m_webViewHelper;
};

void TouchActionTest::runTouchActionTest(std::string file)
{
    TouchActionTrackingWebViewClient client;

    // runTouchActionTest() loads a document in a frame, setting up a
    // nested message loop. Should any Oilpan GC happen while it is in
    // effect, the implicit assumption that we're outside any event
    // loop (=> there being no pointers on the stack needing scanning)
    // when that GC strikes will no longer hold.
    //
    // To ensure that the references on the stack are also traced, we
    // turn them into persistent, stack allocated references. This
    // workaround is sufficient to handle this artificial test
    // scenario.
    WebView* webView = setupTest(file, client);

    RefPtrWillBePersistent<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    runTestOnTree(document.get(), webView, client);

    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
}

void TouchActionTest::runShadowDOMTest(std::string file)
{
    TouchActionTrackingWebViewClient client;

    WebView* webView = setupTest(file, client);

    blink::TrackExceptionState es;

    // Oilpan: see runTouchActionTest() comment why these are persistent references.
    RefPtrWillBePersistent<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    RefPtrWillBePersistent<blink::StaticElementList> hostNodes = document->querySelectorAll("[shadow-host]", es);
    ASSERT_FALSE(es.hadException());
    ASSERT_GE(hostNodes->length(), 1u);

    for (unsigned index = 0; index < hostNodes->length(); index++) {
        blink::ShadowRoot* shadowRoot = hostNodes->item(index)->shadowRoot();
        runTestOnTree(shadowRoot, webView, client);
    }

    // Projections show up in the main document.
    runTestOnTree(document.get(), webView, client);

    m_webViewHelper.reset(); // Explicitly reset to break dependency on locally scoped client.
}

WebView* TouchActionTest::setupTest(std::string file, TouchActionTrackingWebViewClient& client)
{
    URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL), WebString::fromUTF8(file));
    // Note that JavaScript must be enabled for shadow DOM tests.
    WebView* webView = m_webViewHelper.initializeAndLoad(m_baseURL + file, true, 0, &client);

    // Lock page scale factor to avoid zooming out to contents size.
    m_webViewHelper.webView()->setPageScaleFactorLimits(1, 1);

    // Set size to enable hit testing, and avoid line wrapping for consistency with browser.
    webView->resize(WebSize(800, 1200));

    // Scroll to verify the code properly transforms windows to client co-ords.
    const int kScrollOffset = 100;
    RefPtrWillBeRawPtr<blink::Document> document = static_cast<PassRefPtrWillBeRawPtr<blink::Document> >(webView->mainFrame()->document());
    document->frame()->view()->setScrollOffset(blink::IntPoint(0, kScrollOffset));

    return webView;
}

void TouchActionTest::runTestOnTree(blink::ContainerNode* root, WebView* webView, TouchActionTrackingWebViewClient& client)
{
    // Find all elements to test the touch-action of in the document.
    blink::TrackExceptionState es;

    // Oilpan: see runTouchActionTest() comment why these are persistent references.
    RefPtrWillBePersistent<blink::StaticElementList> elements = root->querySelectorAll("[expected-action]", es);
    ASSERT_FALSE(es.hadException());

    for (unsigned index = 0; index < elements->length(); index++) {
        Element* element = elements->item(index);
        element->scrollIntoViewIfNeeded();

        std::string failureContext("Test case: ");
        if (element->hasID()) {
            failureContext.append(element->getIdAttribute().ascii().data());
        } else if (element->firstChild()) {
            failureContext.append("\"");
            failureContext.append(element->firstChild()->textContent(false).stripWhiteSpace().ascii().data());
            failureContext.append("\"");
        } else {
            failureContext += "<missing ID>";
        }

        // Run each test three times at different positions in the element.
        // Note that we don't want the bounding box because our tests sometimes have elements with
        // multiple border boxes with other elements in between. Use the first border box (which
        // we can easily visualize in a browser for debugging).
        RefPtrWillBePersistent<blink::ClientRectList> rects = element->getClientRects();
        ASSERT_GE(rects->length(), 0u) << failureContext;
        RefPtrWillBePersistent<blink::ClientRect> r = rects->item(0);
        blink::FloatRect clientFloatRect = blink::FloatRect(r->left(), r->top(), r->width(), r->height());
        blink::IntRect clientRect =  enclosedIntRect(clientFloatRect);
        for (int locIdx = 0; locIdx < 3; locIdx++) {
            blink::IntPoint clientPoint;
            std::stringstream contextStream;
            contextStream << failureContext << " (";
            switch (locIdx) {
            case 0:
                clientPoint = clientRect.center();
                contextStream << "center";
                break;
            case 1:
                clientPoint = clientRect.location();
                contextStream << "top-left";
                break;
            case 2:
                clientPoint = clientRect.maxXMaxYCorner();
                clientPoint.move(-1, -1);
                contextStream << "bottom-right";
                break;
            default:
                FAIL() << "Invalid location index.";
            }
            contextStream << "=" << clientPoint.x() << "," << clientPoint.y() << ").";
            std::string failureContextPos = contextStream.str();

            blink::LocalFrame* frame = root->document().frame();
            blink::FrameView* frameView = frame->view();
            blink::IntRect visibleRect = frameView->windowClipRect();
            ASSERT_TRUE(visibleRect.contains(clientPoint)) << failureContextPos
                << " Test point not contained in visible area: " << visibleRect.x() << "," << visibleRect.y()
                << "-" << visibleRect.maxX() << "," << visibleRect.maxY();

            // First validate that a hit test at this point will really hit the element
            // we intended. This is the easiest way for a test to be broken, but has nothing really
            // to do with touch action.
            // Note that we can't use WebView's hit test API because it doesn't look into shadow DOM.
            blink::IntPoint docPoint(frameView->windowToContents(clientPoint));
            blink::HitTestResult result = frame->eventHandler().hitTestResultAtPoint(docPoint, blink::HitTestRequest::ReadOnly | blink::HitTestRequest::Active);
            ASSERT_EQ(element, result.innerElement()) << "Unexpected hit test result " << failureContextPos
                << "  Got element: \"" << result.innerElement()->outerHTML().stripWhiteSpace().left(80).ascii().data() << "\""
                << std::endl << "Document render tree:" << std::endl << externalRepresentation(root->document().frame()).utf8().data();

            // Now send the touch event and check any touch action result.
            sendTouchEvent(webView, WebInputEvent::TouchStart, clientPoint);

            AtomicString expectedAction = element->getAttribute("expected-action");
            if (expectedAction == "auto") {
                // Auto is the default - no action set.
                EXPECT_EQ(0, client.touchActionSetCount()) << failureContextPos;
                EXPECT_EQ(WebTouchActionAuto, client.lastTouchAction()) << failureContextPos;
            } else {
                // Should have received exactly one touch action.
                EXPECT_EQ(1, client.touchActionSetCount()) << failureContextPos;
                if (client.touchActionSetCount()) {
                    if (expectedAction == "none") {
                        EXPECT_EQ(WebTouchActionNone, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-x") {
                        EXPECT_EQ(WebTouchActionPanX, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-y") {
                        EXPECT_EQ(WebTouchActionPanY, client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "pan-x-y") {
                        EXPECT_EQ((WebTouchActionPanX | WebTouchActionPanY), client.lastTouchAction()) << failureContextPos;
                    } else if (expectedAction == "manipulation") {
                        EXPECT_EQ((WebTouchActionPanX | WebTouchActionPanY | WebTouchActionPinchZoom), client.lastTouchAction()) << failureContextPos;
                    } else {
                        FAIL() << "Unrecognized expected-action \"" << expectedAction.ascii().data()
                            << "\" " << failureContextPos;
                    }
                }
            }

            // Reset webview touch state.
            client.reset();
            sendTouchEvent(webView, WebInputEvent::TouchCancel, clientPoint);
            EXPECT_EQ(0, client.touchActionSetCount());
        }
    }
}
void TouchActionTest::sendTouchEvent(WebView* webView, WebInputEvent::Type type, blink::IntPoint clientPoint)
{
    ASSERT_TRUE(type == WebInputEvent::TouchStart || type == WebInputEvent::TouchCancel);

    WebTouchEvent webTouchEvent;
    webTouchEvent.type = type;
    if (type == WebInputEvent::TouchCancel)
        webTouchEvent.cancelable = false;
    webTouchEvent.touchesLength = 1;
    webTouchEvent.touches[0].state = (type == WebInputEvent::TouchStart ?
        WebTouchPoint::StatePressed :
        WebTouchPoint::StateCancelled);
    webTouchEvent.touches[0].id = kfakeTouchId;
    webTouchEvent.touches[0].screenPosition.x = clientPoint.x();
    webTouchEvent.touches[0].screenPosition.y = clientPoint.y();
    webTouchEvent.touches[0].position.x = clientPoint.x();
    webTouchEvent.touches[0].position.y = clientPoint.y();
    webTouchEvent.touches[0].radiusX = 10;
    webTouchEvent.touches[0].radiusY = 10;

    webView->handleInputEvent(webTouchEvent);
    runPendingTasks();
}

// crbug.com/411038
TEST_F(TouchActionTest, DISABLED_Simple)
{
    runTouchActionTest("touch-action-simple.html");
}

TEST_F(TouchActionTest, Overflow)
{
    runTouchActionTest("touch-action-overflow.html");
}

TEST_F(TouchActionTest, ShadowDOM)
{
    runShadowDOMTest("touch-action-shadow-dom.html");
}

TEST_F(TouchActionTest, Pan)
{
    runTouchActionTest("touch-action-pan.html");
}

}
<|endoftext|>


<commit_before>#include "scrollwidget.h"

#include <Tempest/Layout>

using namespace Tempest;

struct ScrollWidget::BoxLayout: public Tempest::LinearLayout {
  BoxLayout( ScrollWidget* owner,
             Tempest::Orientation ori ):LinearLayout(ori), sc(owner){}

  void applyLayout(){
    if(widgets().size()==0)
      return;

    const Margin& m = margin();
    Size sz = Size{0,0};
    Widget* helper = owner()->owner();
    if(helper){
      sz.w = std::max(helper->w(),sz.w);
      sz.h = std::max(helper->h(),sz.h);
      }

    int sw = 0, sh = 0;

    const Widget* first = widgets().size()>0 ? widgets()[0] : nullptr;
    for(const Widget* w : widgets())
      if(w->isVisible()){
        Size s = sizeHint(w);
        if(orientation()==Horizontal){
          sw += s.w;
          if(w!=first)
            sw+=spacing();
          sh = std::max(sh,s.h);
          } else {
          sw = std::max(sw,s.w);
          sh += s.h;
          if(w!=first)
            sh+=spacing();
          }
        }

    sw += m.xMargin();
    sh += m.yMargin();

    sz.w = std::max(sz.w,sw);
    sz.h = std::max(sz.h,sh);
    owner()->resize(sz);

    sc->updateScrolls();
    LinearLayout::applyLayout();
    }

  ScrollWidget* sc;
  };

struct ScrollWidget::HelperLayout: public Tempest::Layout {
  void applyLayout(){
    Size ow = owner()->size();

    for(Widget* w : widgets()){
      const SizePolicy& sp = w->sizePolicy();
      Size sz = w->size();

      if(sp.typeH==FixedMin)
        sz.w = sp.minSize.w;
      if(sp.typeH==FixedMax)
        sz.w = sp.maxSize.w;
      if(sp.typeH==Preferred || sp.typeH==Expanding)
        sz.w = ow.w;

      if(sp.typeV==FixedMin)
        sz.h = sp.minSize.h;
      if(sp.typeV==FixedMax)
        sz.h = sp.maxSize.h;
      if(sp.typeV==Preferred || sp.typeV==Expanding)
        sz.h = ow.h;

      w->resize(sz);
      }
    }
  };

ScrollWidget::ScrollWidget()
  : sbH(nullptr), sbV(nullptr), vert(AsNeed), hor(AsNeed) {
  helper.setLayout(new HelperLayout());
  helper.onResize.bind(this,&ScrollWidget::resizeEv);

  layout().add(&helper);

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);

  setScrollBars( createScrollBar(Horizontal),
                 createScrollBar(Vertical  ),
                 false );

#ifdef __MOBILE_PLATFORM__
  hideScrollBars();
#endif
  }

ScrollWidget::ScrollWidget(bool noUi)
  : sbH(nullptr), sbV(nullptr), vert(AsNeed), hor(AsNeed) {
  helper.setLayout(new HelperLayout());
  helper.onResize.bind(this,&ScrollWidget::resizeEv);

  layout().add(&helper);

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);

  if(!noUi)
    setScrollBars( createScrollBar(Horizontal),
                   createScrollBar(Vertical  ),
                   false );

#ifdef __MOBILE_PLATFORM__
  hideScrollBars();
#endif
  }

void ScrollWidget::setScrollBars( Tempest::ScrollBar* hor,
                                  Tempest::ScrollBar* vert,
                                  bool deleteOld ) {
  if(sbH!=nullptr)
    sbH->onValueChanged.ubind(this, &ScrollWidget::scrollH);
  if(sbV!=nullptr)
    sbV->onValueChanged.ubind(this, &ScrollWidget::scrollV);

  if(deleteOld){
    delete sbH;
    delete sbV;
    }

  sbH           = hor;
  sbV           = vert;
  layout().add(sbH);
  layout().add(sbV);

  if(sbH!=nullptr)
    sbH->onValueChanged.bind(this, &ScrollWidget::scrollH);
  if(sbV!=nullptr)
    sbV->onValueChanged.bind(this, &ScrollWidget::scrollV);

  setHscrollViewMode(this->hor);
  setVscrollViewMode(this->vert);

  updateScrolls();
  }

void ScrollWidget::initializeList() {
  if(list!=nullptr)
    return;

  delete cen;
  list = new ListView(orient);
  cen  = list;
  helper.layout().add(cen);
  list->onItemListChanged.bind(this,&ScrollWidget::updateScrolls);
  }

void ScrollWidget::updateScrolls() {
  using std::max;
  using std::min;

  const std::vector<Widget*>& wx = cen->layout().widgets();
  const Widget* first = wx.size()>0 ? wx[0]     : nullptr;
  const Widget* last  = wx.size()>0 ? wx.back() : nullptr;

  bool hasScH = (hor ==AlwaysOn || cen->w()>w());
  bool hasScV = (vert==AlwaysOn || cen->h()>h());

  for(bool recalc=true;recalc;){
    recalc = false;
    if(hasScH){
      if(!hasScV && cen->h()>(h()-sbH->h()) && vert==AsNeed){
        hasScV = true;
        recalc = true;
        }
      }

    if(hasScV){
      if(!hasScH && cen->w()>(w()-sbV->w()) && hor==AsNeed){
        hasScH = true;
        recalc = true;
        }
      }
    }

  const Margin& m = margin();
  const int cenW = w()-m.xMargin()-(hasScV ? sbV->w() : 0);
  const int cenH = h()-m.yMargin()-(hasScH ? sbH->h() : 0);

  const int sw = sbV==nullptr ? 0 : sbV->minSize().w;
  const int sh = sbH==nullptr ? 0 : sbH->minSize().h;

  const int dx = max(cen->w()-helper.w(),0);
  const int dy = max(cen->h()-helper.h(),0);
  if(sbH!=nullptr){
    Layout::placeIn(sbH,
                    m.left, m.top+h()-sh-m.yMargin(),
                    w()-m.xMargin()-(hasScV ? sh : 0), sh);
    sbH->setVisible(hasScH && dx>0);
    if(hor==AsNeed && dx<=0)
      sbH->setValue(0);

    int maxSc = dx, minSc=0;
    if(scAfterEndH && last!=nullptr)
      maxSc = max(cen->w()-min(last->w(),helper.w()),0);
    if(scBeforeBeginH && first!=nullptr)
      minSc = max(cen->w()-min(first->w(),helper.w()),0);
    if(cen && cen->w()>0)
      sbH->setCentralButtonSize((sbH->centralAreaSize()*helper.w())/std::max(1,maxSc-minSc));
    sbH->setRange( minSc,maxSc );
    }

  if(sbV!=nullptr){
    Layout::placeIn(sbV,
                    m.left+w()-sw-m.xMargin(), m.top,
                    sw, h()-m.yMargin()-(hasScH ? sw : 0));
    sbV->setVisible(hasScV && dy>0);
    if(vert==AsNeed && dy<=0)
      sbV->setValue(0);

    int maxSc = dy, minSc = 0;
    if(scAfterEndV && last!=nullptr)
      maxSc = max(cen->h()-min(last->h(),helper.h()),0);
    if(scBeforeBeginV && first!=nullptr)
      minSc = max(cen->h()-min(first->h(),helper.h()),0);
    if(cen && cen->h()>0)
      sbV->setCentralButtonSize((sbV->centralAreaSize()*helper.h())/std::max(1,maxSc-minSc));
    sbV->setRange( minSc, maxSc );
    }

  Layout::placeIn(&helper, m.left, m.top, cenW, cenH);
  }

ScrollWidget::~ScrollWidget() {
  if(list!=nullptr)
    list->onItemListChanged.ubind(this,&ScrollWidget::updateScrolls);
  helper.onResize.removeBinds();
  }

Tempest::Widget &ScrollWidget::centralWidget() {
  return *cen;
  }

bool ScrollWidget::isListBased() const {
  return list!=nullptr;
  }

ListView *ScrollWidget::asListView() {
  return list;
  }

const ListView *ScrollWidget::asListView() const {
  return list;
  }

void ScrollWidget::removeList() {
  if(list==nullptr)
    return;

  delete list;
  list = nullptr;

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);
  }

void ScrollWidget::setLayout(Orientation ori) {
  orient = ori;

  if(list!=nullptr)
    list->setOrientation(orient); else
    cen->setLayout(new BoxLayout(this,ori));
  }

void ScrollWidget::hideScrollBars() {
  setScrollBarsVisible(0,0);
  }

void ScrollWidget::setScrollBarsVisible(bool vh, bool vv) {
  if( sbH==nullptr || sbV==nullptr )
    return;

  if( vh==sbH->isVisible() && vv==sbV->isVisible() )
    return;

  sbH->setVisible(vh);
  sbV->setVisible(vv);
  resizeEv( w(), h() );
  }

void ScrollWidget::setVscrollViewMode(scrollViewMode mode) {
  if(sbH==nullptr)
    return;

  vert = mode;
  switch(mode){
    case AsNeed:    resizeEv(cen->w(), cen->h()); break;
    case AlwaysOff: sbV->setVisible(false);     break;
    case AlwaysOn:  sbV->setVisible(true);      break;
    }
  }

void ScrollWidget::setHscrollViewMode(scrollViewMode mode) {
  if(sbH==nullptr)
    return;

  hor = mode;
  switch(mode){
    case AsNeed:    resizeEv(cen->w(), cen->h()); break;
    case AlwaysOff: sbH->setVisible(false);     break;
    case AlwaysOn:  sbH->setVisible(true);      break;
    }
  }

void ScrollWidget::scrollAfterEndH(bool s) {
  scAfterEndH = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollAfterEndH() const {
  return scAfterEndH;
  }

void ScrollWidget::scrollBeforeBeginH(bool s) {
  scBeforeBeginH = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollBeforeBeginH() const {
  return scBeforeBeginH;
  }

void ScrollWidget::scrollAfterEndV(bool s) {
  scAfterEndV = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollAfterEndV() const {
  return scAfterEndV;
  }

void ScrollWidget::scrollBeforeBeginV(bool s) {
  scBeforeBeginV = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollBeforeBeginV() const {
  return scBeforeBeginV;
  }

void ScrollWidget::mouseWheelEvent(Tempest::MouseEvent &e) {
  if(sbV==nullptr)
    return;

  if( !rect().contains(e.x+x(), e.y+y()) || !sbV->isVisible() ){
    e.ignore();
    return;
    }

  if(e.delta>0)
    sbV->setValue(sbV->value() - sbV->largeStep()); else
  if(e.delta<0)
    sbV->setValue(sbV->value() + sbV->largeStep());
  }

void ScrollWidget::mouseMoveEvent(Tempest::MouseEvent &e) {
  e.ignore();
  }

void ScrollWidget::gestureEvent(Tempest::AbstractGestureEvent &e) {
  e.ignore();

  if( e.gestureType()==Tempest::AbstractGestureEvent::gtDragGesture ){
    Tempest::DragGesture &d = (Tempest::DragGesture&)(e);
    if(sbH!=nullptr && sbH->range()>w() && !sbH->isVisible()){
      int v = sbH->value();
      int dpos = d.dpos.x;

      sbH->setValue(sbH->value() - dpos );
      if( v!=sbH->value() )
        e.accept();
      }
    if(sbV!=nullptr && sbV->range()>h() && !sbV->isVisible()){
      int v = sbV->value();
      int dpos = d.dpos.y;

      sbV->setValue(sbV->value() - dpos );
      if( v!=sbV->value() )
        e.accept();
      }
    }
  }

void ScrollWidget::resizeEvent(SizeEvent &) {
  resizeEv(helper.w(), helper.h());
  }

ScrollBar *ScrollWidget::createScrollBar(Orientation ori) {
  return new ScrollBar(ori);
  }

void ScrollWidget::scrollH( int v ) {
  if(sbH!=nullptr){
    sbH->setValue( v );
    cen->setPosition(-sbH->value(), cen->y());
    } else
    cen->setPosition(cen->x(), -v);
  }

void ScrollWidget::scrollV(int v) {
  if(sbV!=nullptr){
    sbV->setValue( v );
    cen->setPosition(cen->x(), -sbV->value());
    } else
    cen->setPosition(cen->x(), -v);
  }

void ScrollWidget::resizeEv(int,int) {
  updateScrolls();
  }

Tempest::Size ScrollWidget::sizeHint(const Tempest::Widget *wid) {
  int w = wid->sizePolicy().minSize.w,
      h = wid->sizePolicy().minSize.h;

  if( wid->sizePolicy().typeH==Tempest::FixedMax )
    w = wid->sizePolicy().maxSize.w;
  if( wid->sizePolicy().typeV==Tempest::FixedMax )
    h = wid->sizePolicy().maxSize.h;

  return Tempest::Size(w,h);
  }
<commit_msg>scroll widget fixed<commit_after>#include "scrollwidget.h"

#include <Tempest/Layout>

using namespace Tempest;

struct ScrollWidget::BoxLayout: public Tempest::LinearLayout {
  BoxLayout( ScrollWidget* owner,
             Tempest::Orientation ori ):LinearLayout(ori), sc(owner){}

  void applyLayout(){
    if(widgets().size()==0)
      return;

    const Margin& m = margin();
    Size sz = Size{0,0};
    Widget* helper = owner()->owner();
    if(helper){
      sz.w = std::max(helper->w(),sz.w);
      sz.h = std::max(helper->h(),sz.h);
      }

    int sw = 0, sh = 0;

    const Widget* first = widgets().size()>0 ? widgets()[0] : nullptr;
    for(const Widget* w : widgets())
      if(w->isVisible()){
        Size s = sizeHint(w);
        if(orientation()==Horizontal){
          sw += s.w;
          if(w!=first)
            sw+=spacing();
          sh = std::max(sh,s.h);
          } else {
          sw = std::max(sw,s.w);
          sh += s.h;
          if(w!=first)
            sh+=spacing();
          }
        }

    sw += m.xMargin();
    sh += m.yMargin();

    sz.w = std::max(sz.w,sw);
    sz.h = std::max(sz.h,sh);
    owner()->resize(sz);

    sc->updateScrolls();
    LinearLayout::applyLayout();
    }

  ScrollWidget* sc;
  };

struct ScrollWidget::HelperLayout: public Tempest::Layout {
  void applyLayout(){
    Size ow = owner()->size();

    for(Widget* w : widgets()){
      const SizePolicy& sp = w->sizePolicy();
      Size sz = w->size();

      if(sp.typeH==FixedMin)
        sz.w = sp.minSize.w;
      if(sp.typeH==FixedMax)
        sz.w = sp.maxSize.w;
      if(sp.typeH==Preferred || sp.typeH==Expanding)
        sz.w = ow.w;

      if(sp.typeV==FixedMin)
        sz.h = sp.minSize.h;
      if(sp.typeV==FixedMax)
        sz.h = sp.maxSize.h;
      if(sp.typeV==Preferred || sp.typeV==Expanding)
        sz.h = ow.h;

      w->resize(sz);
      }
    }
  };

ScrollWidget::ScrollWidget()
  : sbH(nullptr), sbV(nullptr), vert(AsNeed), hor(AsNeed) {
  helper.setLayout(new HelperLayout());
  helper.onResize.bind(this,&ScrollWidget::resizeEv);

  layout().add(&helper);

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);

  setScrollBars( createScrollBar(Horizontal),
                 createScrollBar(Vertical  ),
                 false );

#ifdef __MOBILE_PLATFORM__
  hideScrollBars();
#endif
  }

ScrollWidget::ScrollWidget(bool noUi)
  : sbH(nullptr), sbV(nullptr), vert(AsNeed), hor(AsNeed) {
  helper.setLayout(new HelperLayout());
  helper.onResize.bind(this,&ScrollWidget::resizeEv);

  layout().add(&helper);

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);

  if(!noUi)
    setScrollBars( createScrollBar(Horizontal),
                   createScrollBar(Vertical  ),
                   false );

#ifdef __MOBILE_PLATFORM__
  hideScrollBars();
#endif
  }

void ScrollWidget::setScrollBars( Tempest::ScrollBar* hor,
                                  Tempest::ScrollBar* vert,
                                  bool deleteOld ) {
  if(sbH!=nullptr)
    sbH->onValueChanged.ubind(this, &ScrollWidget::scrollH);
  if(sbV!=nullptr)
    sbV->onValueChanged.ubind(this, &ScrollWidget::scrollV);

  if(deleteOld){
    delete sbH;
    delete sbV;
    }

  sbH           = hor;
  sbV           = vert;
  layout().add(sbH);
  layout().add(sbV);

  if(sbH!=nullptr)
    sbH->onValueChanged.bind(this, &ScrollWidget::scrollH);
  if(sbV!=nullptr)
    sbV->onValueChanged.bind(this, &ScrollWidget::scrollV);

  setHscrollViewMode(this->hor);
  setVscrollViewMode(this->vert);

  updateScrolls();
  }

void ScrollWidget::initializeList() {
  if(list!=nullptr)
    return;

  delete cen;
  list = new ListView(orient);
  cen  = list;
  helper.layout().add(cen);
  list->onItemListChanged.bind(this,&ScrollWidget::updateScrolls);
  }

void ScrollWidget::updateScrolls() {
  using std::max;
  using std::min;

  const std::vector<Widget*>& wx = cen->layout().widgets();
  const Widget* first = wx.size()>0 ? wx[0]     : nullptr;
  const Widget* last  = wx.size()>0 ? wx.back() : nullptr;

  bool hasScH = (hor ==AlwaysOn || cen->w()>w());
  bool hasScV = (vert==AlwaysOn || cen->h()>h());

  for(bool recalc=true;recalc;){
    recalc = false;
    if(hasScH){
      if(!hasScV && cen->h()>(h()-sbH->h()) && vert==AsNeed){
        hasScV = true;
        recalc = true;
        }
      }

    if(hasScV){
      if(!hasScH && cen->w()>(w()-sbV->w()) && hor==AsNeed){
        hasScH = true;
        recalc = true;
        }
      }
    }

  const Margin& m = margin();
  const int cenW = w()-m.xMargin()-(hasScV ? sbV->w() : 0);
  const int cenH = h()-m.yMargin()-(hasScH ? sbH->h() : 0);

  const int sw = sbV==nullptr ? 0 : sbV->minSize().w;
  const int sh = sbH==nullptr ? 0 : sbH->minSize().h;

  const int dx = max(cen->w()-helper.w(),0);
  const int dy = max(cen->h()-helper.h(),0);
  if(sbH!=nullptr){
    Layout::placeIn(sbH,
                    m.left, m.top+h()-sh-m.yMargin(),
                    w()-m.xMargin()-(hasScV ? sh : 0), sh);
    sbH->setVisible(hasScH && dx>0);
    if(hor==AsNeed && dx<=0)
      sbH->setValue(0);

    int maxSc = dx, minSc=0;
    if(scAfterEndH && last!=nullptr)
      maxSc = max(cen->w()-min(last->w(),helper.w()),0);
    if(scBeforeBeginH && first!=nullptr)
      minSc = max(cen->w()-min(first->w(),helper.w()),0);
    if(cen && cen->w()>0){
      const int rgn = std::max(1,cen->w());
      sbH->setCentralButtonSize((sbV->centralAreaSize()*cenW)/rgn);
      }
    sbH->setRange( minSc,maxSc );
    }

  if(sbV!=nullptr){
    Layout::placeIn(sbV,
                    m.left+w()-sw-m.xMargin(), m.top,
                    sw, h()-m.yMargin()-(hasScH ? sw : 0));
    sbV->setVisible(hasScV && dy>0);
    if(vert==AsNeed && dy<=0)
      sbV->setValue(0);

    int maxSc = dy, minSc = 0;
    if(scAfterEndV && last!=nullptr)
      maxSc = max(cen->h()-min(last->h(),helper.h()),0);
    if(scBeforeBeginV && first!=nullptr)
      minSc = max(cen->h()-min(first->h(),helper.h()),0);
    if(cen && cen->h()>0){
      const int rgn = std::max(1,cen->h());
      sbV->setCentralButtonSize((sbV->centralAreaSize()*cenH)/rgn);
      }
    sbV->setRange( minSc, maxSc );
    }

  Layout::placeIn(&helper, m.left, m.top, cenW, cenH);
  }

ScrollWidget::~ScrollWidget() {
  if(list!=nullptr)
    list->onItemListChanged.ubind(this,&ScrollWidget::updateScrolls);
  helper.onResize.removeBinds();
  }

Tempest::Widget &ScrollWidget::centralWidget() {
  return *cen;
  }

bool ScrollWidget::isListBased() const {
  return list!=nullptr;
  }

ListView *ScrollWidget::asListView() {
  return list;
  }

const ListView *ScrollWidget::asListView() const {
  return list;
  }

void ScrollWidget::removeList() {
  if(list==nullptr)
    return;

  delete list;
  list = nullptr;

  cen = new Widget();
  cen->setLayout(new BoxLayout(this,orient));
  helper.layout().add(cen);
  }

void ScrollWidget::setLayout(Orientation ori) {
  orient = ori;

  if(list!=nullptr)
    list->setOrientation(orient); else
    cen->setLayout(new BoxLayout(this,ori));
  }

void ScrollWidget::hideScrollBars() {
  setScrollBarsVisible(0,0);
  }

void ScrollWidget::setScrollBarsVisible(bool vh, bool vv) {
  if( sbH==nullptr || sbV==nullptr )
    return;

  if( vh==sbH->isVisible() && vv==sbV->isVisible() )
    return;

  sbH->setVisible(vh);
  sbV->setVisible(vv);
  resizeEv( w(), h() );
  }

void ScrollWidget::setVscrollViewMode(scrollViewMode mode) {
  if(sbH==nullptr)
    return;

  vert = mode;
  switch(mode){
    case AsNeed:    resizeEv(cen->w(), cen->h()); break;
    case AlwaysOff: sbV->setVisible(false);     break;
    case AlwaysOn:  sbV->setVisible(true);      break;
    }
  }

void ScrollWidget::setHscrollViewMode(scrollViewMode mode) {
  if(sbH==nullptr)
    return;

  hor = mode;
  switch(mode){
    case AsNeed:    resizeEv(cen->w(), cen->h()); break;
    case AlwaysOff: sbH->setVisible(false);     break;
    case AlwaysOn:  sbH->setVisible(true);      break;
    }
  }

void ScrollWidget::scrollAfterEndH(bool s) {
  scAfterEndH = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollAfterEndH() const {
  return scAfterEndH;
  }

void ScrollWidget::scrollBeforeBeginH(bool s) {
  scBeforeBeginH = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollBeforeBeginH() const {
  return scBeforeBeginH;
  }

void ScrollWidget::scrollAfterEndV(bool s) {
  scAfterEndV = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollAfterEndV() const {
  return scAfterEndV;
  }

void ScrollWidget::scrollBeforeBeginV(bool s) {
  scBeforeBeginV = s;
  updateScrolls();
  }

bool ScrollWidget::hasScrollBeforeBeginV() const {
  return scBeforeBeginV;
  }

void ScrollWidget::mouseWheelEvent(Tempest::MouseEvent &e) {
  if(sbV==nullptr)
    return;

  if( !rect().contains(e.x+x(), e.y+y()) || !sbV->isVisible() ){
    e.ignore();
    return;
    }

  if(e.delta>0)
    sbV->setValue(sbV->value() - sbV->largeStep()); else
  if(e.delta<0)
    sbV->setValue(sbV->value() + sbV->largeStep());
  }

void ScrollWidget::mouseMoveEvent(Tempest::MouseEvent &e) {
  e.ignore();
  }

void ScrollWidget::gestureEvent(Tempest::AbstractGestureEvent &e) {
  e.ignore();

  if( e.gestureType()==Tempest::AbstractGestureEvent::gtDragGesture ){
    Tempest::DragGesture &d = (Tempest::DragGesture&)(e);
    if(sbH!=nullptr && sbH->range()>w() && !sbH->isVisible()){
      int v = sbH->value();
      int dpos = d.dpos.x;

      sbH->setValue(sbH->value() - dpos );
      if( v!=sbH->value() )
        e.accept();
      }
    if(sbV!=nullptr && sbV->range()>h() && !sbV->isVisible()){
      int v = sbV->value();
      int dpos = d.dpos.y;

      sbV->setValue(sbV->value() - dpos );
      if( v!=sbV->value() )
        e.accept();
      }
    }
  }

void ScrollWidget::resizeEvent(SizeEvent &) {
  resizeEv(helper.w(), helper.h());
  }

ScrollBar *ScrollWidget::createScrollBar(Orientation ori) {
  return new ScrollBar(ori);
  }

void ScrollWidget::scrollH( int v ) {
  if(sbH!=nullptr){
    sbH->setValue( v );
    cen->setPosition(-sbH->value(), cen->y());
    } else
    cen->setPosition(cen->x(), -v);
  }

void ScrollWidget::scrollV(int v) {
  if(sbV!=nullptr){
    sbV->setValue( v );
    cen->setPosition(cen->x(), -sbV->value());
    } else
    cen->setPosition(cen->x(), -v);
  }

void ScrollWidget::resizeEv(int,int) {
  updateScrolls();
  }

Tempest::Size ScrollWidget::sizeHint(const Tempest::Widget *wid) {
  int w = wid->sizePolicy().minSize.w,
      h = wid->sizePolicy().minSize.h;

  if( wid->sizePolicy().typeH==Tempest::FixedMax )
    w = wid->sizePolicy().maxSize.w;
  if( wid->sizePolicy().typeV==Tempest::FixedMax )
    h = wid->sizePolicy().maxSize.h;

  return Tempest::Size(w,h);
  }
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/StringUtil.h"

#include <cctype>
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <cstring>

namespace seasocks {

char* skipWhitespace(char* str) {
    while (isspace(*str))
        ++str;
    return str;
}

char* skipNonWhitespace(char* str) {
    while (*str && !isspace(*str)) {
        ++str;
    }
    return str;
}

char* shift(char*& str) {
    if (str == nullptr) {
        return nullptr;
    }
    char* startOfWord = skipWhitespace(str);
    if (*startOfWord == 0) {
        str = startOfWord;
        return nullptr;
    }
    char* endOfWord = skipNonWhitespace(startOfWord);
    if (*endOfWord != 0) {
        *endOfWord++ = 0;
    }
    str = endOfWord;
    return startOfWord;
}

std::string trimWhitespace(const std::string& str) {
    auto* start = str.c_str();
    while (isspace(*start))
        ++start;
    auto* end = &str.back();
    while (end >= start && isspace(*end))
        --end;
    return std::string(start, end - start + 1);
}

std::string getLastError() {
    char errbuf[1024];
    strerror_r(errno, errbuf, sizeof(errbuf));
    return errbuf;
}

std::string formatAddress(const sockaddr_in& address) {
    char ipBuffer[24];
    sprintf(ipBuffer,
            "%d.%d.%d.%d:%d",
            (address.sin_addr.s_addr >> 0) & 0xff,
            (address.sin_addr.s_addr >> 8) & 0xff,
            (address.sin_addr.s_addr >> 16) & 0xff,
            (address.sin_addr.s_addr >> 24) & 0xff,
            htons(address.sin_port));
    return ipBuffer;
}

std::vector<std::string> split(const std::string& input, char splitChar) {
    if (input.empty())
        return std::vector<std::string>();
    std::vector<std::string> result;
    size_t pos = 0;
    size_t newPos;
    while ((newPos = input.find(splitChar, pos)) != std::string::npos) {
        result.push_back(input.substr(pos, newPos - pos));
        pos = newPos + 1;
    }
    result.push_back(input.substr(pos));
    return result;
}

void replace(std::string& string, const std::string& find,
             const std::string& replace) {
    size_t pos = 0;
    const size_t findLen = find.length();
    const size_t replaceLen = replace.length();
    while ((pos = string.find(find, pos)) != std::string::npos) {
        string = string.substr(0, pos) + replace + string.substr(pos + findLen);
        pos += replaceLen;
    }
}

bool caseInsensitiveSame(const std::string& lhs, const std::string& rhs) {
    return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
}

std::string webtime(time_t time) {
    struct tm tm;
    gmtime_r(&time, &tm);
    char buf[1024];
    // Wed, 20 Apr 2011 17:31:28 GMT
    strftime(buf, sizeof(buf) - 1, "%a, %d %b %Y %H:%M:%S %Z", &tm);
    return buf;
}

std::string now() {
    return webtime(time(nullptr));
}

}
<commit_msg>Resolved ignoring return value error<commit_after>// Copyright (c) 2013-2017, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "seasocks/StringUtil.h"

#include <cctype>
#include <cerrno>
#include <cstddef>
#include <cstdio>
#include <cstring>

namespace seasocks {

char* skipWhitespace(char* str) {
    while (isspace(*str))
        ++str;
    return str;
}

char* skipNonWhitespace(char* str) {
    while (*str && !isspace(*str)) {
        ++str;
    }
    return str;
}

char* shift(char*& str) {
    if (str == nullptr) {
        return nullptr;
    }
    char* startOfWord = skipWhitespace(str);
    if (*startOfWord == 0) {
        str = startOfWord;
        return nullptr;
    }
    char* endOfWord = skipNonWhitespace(startOfWord);
    if (*endOfWord != 0) {
        *endOfWord++ = 0;
    }
    str = endOfWord;
    return startOfWord;
}

std::string trimWhitespace(const std::string& str) {
    auto* start = str.c_str();
    while (isspace(*start))
        ++start;
    auto* end = &str.back();
    while (end >= start && isspace(*end))
        --end;
    return std::string(start, end - start + 1);
}

std::string getLastError() {
    char errbuf[1024];
    return strerror_r(errno, errbuf, sizeof(errbuf));
}

std::string formatAddress(const sockaddr_in& address) {
    char ipBuffer[24];
    sprintf(ipBuffer,
            "%d.%d.%d.%d:%d",
            (address.sin_addr.s_addr >> 0) & 0xff,
            (address.sin_addr.s_addr >> 8) & 0xff,
            (address.sin_addr.s_addr >> 16) & 0xff,
            (address.sin_addr.s_addr >> 24) & 0xff,
            htons(address.sin_port));
    return ipBuffer;
}

std::vector<std::string> split(const std::string& input, char splitChar) {
    if (input.empty())
        return std::vector<std::string>();
    std::vector<std::string> result;
    size_t pos = 0;
    size_t newPos;
    while ((newPos = input.find(splitChar, pos)) != std::string::npos) {
        result.push_back(input.substr(pos, newPos - pos));
        pos = newPos + 1;
    }
    result.push_back(input.substr(pos));
    return result;
}

void replace(std::string& string, const std::string& find,
             const std::string& replace) {
    size_t pos = 0;
    const size_t findLen = find.length();
    const size_t replaceLen = replace.length();
    while ((pos = string.find(find, pos)) != std::string::npos) {
        string = string.substr(0, pos) + replace + string.substr(pos + findLen);
        pos += replaceLen;
    }
}

bool caseInsensitiveSame(const std::string& lhs, const std::string& rhs) {
    return strcasecmp(lhs.c_str(), rhs.c_str()) == 0;
}

std::string webtime(time_t time) {
    struct tm tm;
    gmtime_r(&time, &tm);
    char buf[1024];
    // Wed, 20 Apr 2011 17:31:28 GMT
    strftime(buf, sizeof(buf) - 1, "%a, %d %b %Y %H:%M:%S %Z", &tm);
    return buf;
}

std::string now() {
    return webtime(time(nullptr));
}

}
<|endoftext|>


<commit_before>#pragma once

namespace math
{
        ///
        /// \brief common parameters for stochastic optimization
        ///
        template
        <
                typename tproblem                       ///< optimization problem
        >
        struct stoch_params_t
        {
                using tstate = typename tproblem::tstate;
                using tscalar = typename tproblem::tscalar;
                using tvector = typename tproblem::tvector;
                using topulog = typename tproblem::topulog;

                ///
                /// \brief constructor
                ///
                stoch_params_t( const std::size_t epochs,
                                const std::size_t epoch_size,
                                const topulog& ulog = topulog())
                        :       m_epochs(epochs),
                                m_epoch_size(epoch_size),
                                m_ulog(ulog)
                {
                }

                ///
                /// \brief construct the associated set of parameters suitable for tuning
                ///
                stoch_params_t tunable() const
                {
                        return { std::size_t(1), m_epoch_size, nullptr };
                }

                ///
                /// \brief log the current optimization state
                ///
                bool ulog(const tstate& state) const
                {
                        return m_ulog ? m_ulog(state) : true;
                }

                // attributes
                std::size_t             m_epochs;       ///< number of epochs
                std::size_t             m_epoch_size;   ///< epoch size in number of iterations
                topulog                 m_ulog;         ///< update log: (the current_state_after_each_epoch)
        };
}
<commit_msg>fix include<commit_after>#pragma once

#include <cstddef>

namespace math
{
        ///
        /// \brief common parameters for stochastic optimization
        ///
        template
        <
                typename tproblem                       ///< optimization problem
        >
        struct stoch_params_t
        {
                using tstate = typename tproblem::tstate;
                using tscalar = typename tproblem::tscalar;
                using tvector = typename tproblem::tvector;
                using topulog = typename tproblem::topulog;

                ///
                /// \brief constructor
                ///
                stoch_params_t( const std::size_t epochs,
                                const std::size_t epoch_size,
                                const topulog& ulog = topulog())
                        :       m_epochs(epochs),
                                m_epoch_size(epoch_size),
                                m_ulog(ulog)
                {
                }

                ///
                /// \brief construct the associated set of parameters suitable for tuning
                ///
                stoch_params_t tunable() const
                {
                        return { std::size_t(1), m_epoch_size, nullptr };
                }

                ///
                /// \brief log the current optimization state
                ///
                bool ulog(const tstate& state) const
                {
                        return m_ulog ? m_ulog(state) : true;
                }

                // attributes
                std::size_t             m_epochs;       ///< number of epochs
                std::size_t             m_epoch_size;   ///< epoch size in number of iterations
                topulog                 m_ulog;         ///< update log: (the current_state_after_each_epoch)
        };
}
<|endoftext|>