<commit_before>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <ghoul/opengl/shaderobject.h>

#include <ghoul/logging/log.h>
#include <ghoul/filesystem/filesystem>

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstring>
#include <fstream>
#include <functional>
#include <regex>

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif

namespace {
const std::string _loggerCat = "ShaderObject";
}

namespace ghoul {
namespace opengl {

ShaderObject::ShaderObject(ShaderType shaderType, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName("")
    , _shaderName("")
	, _loggerCat("ShaderObject")
	, _onChangeCallback(changeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
}

ShaderObject::ShaderObject(ShaderType shaderType, std::string filename, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName(std::move(filename))
    , _shaderName("")
	, _loggerCat("ShaderObject")
	, _onChangeCallback(changeCallback)
{
#ifdef DEBUG
    if (filename == "")
        LWARNING("Filename is empty");
#endif

    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
    setShaderFilename(_fileName);
}

ShaderObject::ShaderObject(ShaderType shaderType, std::string filename,
						   std::string name, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName(std::move(filename))
    , _shaderName(std::move(name))
	, _loggerCat("ShaderObject('" + _shaderName + "')")
	, _onChangeCallback(changeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
                      _shaderName.c_str());
#endif
    setShaderFilename(_fileName);
}

ShaderObject::ShaderObject(const ShaderObject& cpy)
    : _id(0)
    , _type(cpy._type)
    , _fileName(cpy._fileName)
	, _shaderName(cpy._shaderName)
	, _loggerCat(cpy._loggerCat)
	, _onChangeCallback(cpy._onChangeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
                      _shaderName.c_str());
#endif
    setShaderFilename(_fileName);
}

ShaderObject::~ShaderObject() {
    glDeleteShader(_id);
    _id = 0;
}

ShaderObject::operator GLuint() const {
    return _id;
}

ShaderObject& ShaderObject::operator=(const ShaderObject& rhs) {
    if (this != &rhs) {
        _type = rhs._type;
        _fileName = rhs._fileName;
        _shaderName = rhs._shaderName;
		_loggerCat = rhs._loggerCat;
		_onChangeCallback = rhs._onChangeCallback;

        glDeleteShader(_id);
        _id = glCreateShader(_type);
        if (_id == 0)
            LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
        if (glObjectLabel)
            glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1)
                          , _shaderName.c_str());
#endif
        setShaderFilename(_fileName);
    }
    return *this;
}

void ShaderObject::setName(std::string name) {
    _shaderName = std::move(name);
    _loggerCat = "ShaderObject['" + _shaderName + "']";
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
_shaderName.c_str());
#endif
}

const std::string& ShaderObject::name() const {
    return _shaderName;
}

bool ShaderObject::hasName() const {
    return !_shaderName.empty();
}

std::string ShaderObject::filename() {
	return _fileName;
}

bool ShaderObject::setShaderFilename(std::string filename) {
	_fileName = std::move(filename);
    if (_fileName == "") {
        deleteShader();
        return true;
    }

	// Clear tracked files, this might have changed since last time
	for (auto f : _trackedFiles)
		delete f.second;
	_trackedFiles.erase(_trackedFiles.begin(), _trackedFiles.end());

	std::string contents;
	contents.reserve(8192);
	if (!readFile(_fileName, contents))
		return false;

	// TODO: Some other solution for outputting the source as human readable for debugging
	std::ofstream os(_fileName + ".OpenSpaceGenerated.glsl");
	os.close();

    const char* contentPtr =  contents.c_str();
    glShaderSource(_id, 1, &contentPtr, NULL);

    LINFO("Loaded " + typeAsString() + ": '" + _fileName + "'");
    return true;
}

void ShaderObject::deleteShader() {
    glDeleteShader(_id);
    _id = 0;
}

bool ShaderObject::rebuildFromFile() {
    return setShaderFilename(_fileName);
}

bool ShaderObject::compile() {
    glCompileShader(_id);

    GLint compilationStatus;
    glGetShaderiv(_id, GL_COMPILE_STATUS, &compilationStatus);
    if (compilationStatus == GL_FALSE) {
        GLint logLength;
        glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength);

        if (logLength == 0) {
            LERROR(typeAsString() + " compile error: Unknown error");
            return false;
        }

        GLchar* log = new GLchar[logLength];
        glGetShaderInfoLog(_id, logLength, NULL, log);
        LERROR(typeAsString() + " compile error:\n" + log);
        delete[] log;

        return false;
    }
    return compilationStatus == GL_TRUE;
}

std::string ShaderObject::typeAsString() const {
    return ShaderObject::stringForShaderType(_type);
}

std::string ShaderObject::stringForShaderType(ShaderType type) {
    switch (type) {
    case ShaderTypeVertex:
        return "Vertex shader";
    case ShaderTypeTesselationControl:
        return "Tesselation Control shader";
    case ShaderTypeTesselationEvaluation:
        return "Tesselation Evaluation shader";
    case ShaderTypeGeometry:
        return "Geometry shader";
    case ShaderTypeFragment:
        return "Fragment shader";
#ifdef GL_VERSION_4_3
    case ShaderTypeCompute:
        return "Compute shader";
#endif
    default:
        assert(false);
        return "";
    }
}

bool ShaderObject::readFile(const std::string& filename, std::string& content) {
	// check that the file exists
	if (!FileSys.fileExists(filename)) {
		LWARNING("Shader '" << _shaderName << "' could not find '" << filename << "'");
		return false;
	}

	// Check that the file is currently not in _trackedFiles
	auto s = _trackedFiles.find(filename);
	if (s != _trackedFiles.end()) {
		LWARNING("Shader '" << _shaderName << "' already including '" << filename << "'");
		return false;
	}

	// Check that file can be opened
	std::ifstream f(filename, std::ifstream::in);
	if (!f.is_open()) {
		LWARNING("Shader '" << _shaderName << "' could not open '" << filename << "'");
		return false;
	}

	// Construct a file object
	using namespace ghoul::filesystem;

	// CODE FOR DEBUG PURPOSE
	//filesystem::File::FileChangedCallback c = nullptr;
	//c = [ this](const filesystem::File&){
	//	LDEBUG("Update fired from " << name());
	//	if (_onChangeCallback)
	//		_onChangeCallback;
	//};

	File* fileObject = new File(filename, false, _onChangeCallback);
	_trackedFiles[filename] = fileObject;

	// Ready to start parsing
	std::string line;
	std::regex e1(R"(^\s*#include \"(.+)\"\s*)");	// Regex to match relative paths
	std::regex e2(R"(^\s*#include <(.+)>\s*)");		// Regex to match ghoul absPath
	while (std::getline(f, line)) {
		std::smatch m;
		if (std::regex_search(line, m, e1)) {
			std::string includeFilename = fileObject->directoryName() + FileSystem::PathSeparator + std::string(m[1]);
			content += "// Including '" + includeFilename + "'\n";
			if (!readFile(includeFilename, content))
				content += "// Warning, unsuccessful loading of '" + includeFilename + "'\n";
		}
		else if (std::regex_search(line, m, e2)) {
			std::string includeFilename = absPath(m[1]);
			content += "// Including '" + includeFilename + "'\n";
			if (!readFile(includeFilename, content))
				content += "// Warning, unsuccessful loading of '" + includeFilename + "'\n";
		}
		else {
			content += line + "\n";
		}
	}

	f.close();
	return true;
}

} // namespace opengl
} // namespace ghoul

#ifdef _MSC_VER
#pragma warning(pop)
#endif
<commit_msg>Fix that outputs the shader source even if it fails<commit_after>/*****************************************************************************************
 *                                                                                *
 * GHOUL                                                                                *
 * General Helpful Open Utility Library                                                  *
 *                                                                                *
 * Copyright (c) 2012-2014                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include <ghoul/opengl/shaderobject.h>

#include <ghoul/logging/log.h>
#include <ghoul/filesystem/filesystem>

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstring>
#include <fstream>
#include <functional>
#include <regex>

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996)
#endif

namespace {
const std::string _loggerCat = "ShaderObject";
}

namespace ghoul {
namespace opengl {

ShaderObject::ShaderObject(ShaderType shaderType, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName("")
    , _shaderName("")
	, _loggerCat("ShaderObject")
	, _onChangeCallback(changeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
}

ShaderObject::ShaderObject(ShaderType shaderType, std::string filename, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName(std::move(filename))
    , _shaderName("")
	, _loggerCat("ShaderObject")
	, _onChangeCallback(changeCallback)
{
#ifdef DEBUG
    if (filename == "")
        LWARNING("Filename is empty");
#endif

    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
    setShaderFilename(_fileName);
}

ShaderObject::ShaderObject(ShaderType shaderType, std::string filename,
						   std::string name, ShaderObjectCallback changeCallback)
    : _id(0)
    , _type(shaderType)
    , _fileName(std::move(filename))
    , _shaderName(std::move(name))
	, _loggerCat("ShaderObject('" + _shaderName + "')")
	, _onChangeCallback(changeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
                      _shaderName.c_str());
#endif
    setShaderFilename(_fileName);
}

ShaderObject::ShaderObject(const ShaderObject& cpy)
    : _id(0)
    , _type(cpy._type)
    , _fileName(cpy._fileName)
	, _shaderName(cpy._shaderName)
	, _loggerCat(cpy._loggerCat)
	, _onChangeCallback(cpy._onChangeCallback)
{
    _id = glCreateShader(_type);
    if (_id == 0)
        LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
                      _shaderName.c_str());
#endif
    setShaderFilename(_fileName);
}

ShaderObject::~ShaderObject() {
    glDeleteShader(_id);
    _id = 0;
}

ShaderObject::operator GLuint() const {
    return _id;
}

ShaderObject& ShaderObject::operator=(const ShaderObject& rhs) {
    if (this != &rhs) {
        _type = rhs._type;
        _fileName = rhs._fileName;
        _shaderName = rhs._shaderName;
		_loggerCat = rhs._loggerCat;
		_onChangeCallback = rhs._onChangeCallback;

        glDeleteShader(_id);
        _id = glCreateShader(_type);
        if (_id == 0)
            LERROR("glCreateShader returned 0");
#ifdef GL_VERSION_4_3
        if (glObjectLabel)
            glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1)
                          , _shaderName.c_str());
#endif
        setShaderFilename(_fileName);
    }
    return *this;
}

void ShaderObject::setName(std::string name) {
    _shaderName = std::move(name);
    _loggerCat = "ShaderObject['" + _shaderName + "']";
#ifdef GL_VERSION_4_3
    if (glObjectLabel)
        glObjectLabel(GL_SHADER, _id, GLsizei(_shaderName.length() + 1),
_shaderName.c_str());
#endif
}

const std::string& ShaderObject::name() const {
    return _shaderName;
}

bool ShaderObject::hasName() const {
    return !_shaderName.empty();
}

std::string ShaderObject::filename() {
	return _fileName;
}

bool ShaderObject::setShaderFilename(std::string filename) {
	_fileName = std::move(filename);
    if (_fileName == "") {
        deleteShader();
        return true;
    }

	// Clear tracked files, this might have changed since last time
	for (auto f : _trackedFiles)
		delete f.second;
	_trackedFiles.erase(_trackedFiles.begin(), _trackedFiles.end());

	std::string contents;
	contents.reserve(8192);

	bool success = readFile(_fileName, contents);
	// TODO: Some other solution for outputting the source as human readable for debugging
	std::ofstream os(_fileName + ".OpenSpaceGenerated.glsl");
	os << contents;
	os.close();

	if (!success)
		return false;

    const char* contentPtr =  contents.c_str();
    glShaderSource(_id, 1, &contentPtr, NULL);

    LINFO("Loaded " + typeAsString() + ": '" + _fileName + "'");
    return true;
}

void ShaderObject::deleteShader() {
    glDeleteShader(_id);
    _id = 0;
}

bool ShaderObject::rebuildFromFile() {
    return setShaderFilename(_fileName);
}

bool ShaderObject::compile() {
    glCompileShader(_id);

    GLint compilationStatus;
    glGetShaderiv(_id, GL_COMPILE_STATUS, &compilationStatus);
    if (compilationStatus == GL_FALSE) {
        GLint logLength;
        glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength);

        if (logLength == 0) {
            LERROR(typeAsString() + " compile error: Unknown error");
            return false;
        }

        GLchar* log = new GLchar[logLength];
        glGetShaderInfoLog(_id, logLength, NULL, log);
        LERROR(typeAsString() + " compile error:\n" + log);
        delete[] log;

        return false;
    }
    return compilationStatus == GL_TRUE;
}

std::string ShaderObject::typeAsString() const {
    return ShaderObject::stringForShaderType(_type);
}

std::string ShaderObject::stringForShaderType(ShaderType type) {
    switch (type) {
    case ShaderTypeVertex:
        return "Vertex shader";
    case ShaderTypeTesselationControl:
        return "Tesselation Control shader";
    case ShaderTypeTesselationEvaluation:
        return "Tesselation Evaluation shader";
    case ShaderTypeGeometry:
        return "Geometry shader";
    case ShaderTypeFragment:
        return "Fragment shader";
#ifdef GL_VERSION_4_3
    case ShaderTypeCompute:
        return "Compute shader";
#endif
    default:
        assert(false);
        return "";
    }
}

bool ShaderObject::readFile(const std::string& filename, std::string& content) {
	// check that the file exists
	if (!FileSys.fileExists(filename)) {
		LWARNING("Shader '" << _shaderName << "' could not find '" << filename << "'");
		return false;
	}

	// Check that the file is currently not in _trackedFiles
	auto s = _trackedFiles.find(filename);
	if (s != _trackedFiles.end()) {
		LWARNING("Shader '" << _shaderName << "' already including '" << filename << "'");
		return false;
	}

	// Check that file can be opened
	std::ifstream f(filename, std::ifstream::in);
	if (!f.is_open()) {
		LWARNING("Shader '" << _shaderName << "' could not open '" << filename << "'");
		return false;
	}

	// Construct a file object
	using namespace ghoul::filesystem;

	// CODE FOR DEBUG PURPOSE
	//filesystem::File::FileChangedCallback c = nullptr;
	//c = [ this](const filesystem::File&){
	//	LDEBUG("Update fired from " << name());
	//	if (_onChangeCallback)
	//		_onChangeCallback;
	//};

	File* fileObject = new File(filename, false, _onChangeCallback);
	_trackedFiles[filename] = fileObject;

	// Ready to start parsing
	std::string line;
	std::regex e1(R"(^\s*#include \"(.+)\"\s*)");	// Regex to match relative paths
	std::regex e2(R"(^\s*#include <(.+)>\s*)");		// Regex to match ghoul absPath
	while (std::getline(f, line)) {
		std::smatch m;
		if (std::regex_search(line, m, e1)) {
			std::string includeFilename = fileObject->directoryName() + FileSystem::PathSeparator + std::string(m[1]);
			content += "// Including '" + includeFilename + "'\n";
			if (!readFile(includeFilename, content))
				content += "// Warning, unsuccessful loading of '" + includeFilename + "'\n";
		}
		else if (std::regex_search(line, m, e2)) {
			std::string includeFilename = absPath(m[1]);
			content += "// Including '" + includeFilename + "'\n";
			if (!readFile(includeFilename, content))
				content += "// Warning, unsuccessful loading of '" + includeFilename + "'\n";
		}
		else {
			content += line + "\n";
		}
	}

	f.close();
	return true;
}

} // namespace opengl
} // namespace ghoul

#ifdef _MSC_VER
#pragma warning(pop)
#endif
<|endoftext|>


<commit_before>/*
 * LCALIFLateralConn.cpp
 *
 *  Created on: Oct 3, 2012
 *      Author: pschultz
 */

#include "LCALIFLateralConn.hpp"

namespace PV {

LCALIFLateralConn::LCALIFLateralConn()
{
   initialize_base();
}

LCALIFLateralConn::LCALIFLateralConn(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights *weightInit) {
   initialize_base();
   initialize(name, hc, pre, post, filename, weightInit);
}

LCALIFLateralConn::~LCALIFLateralConn()
{
   free(integratedSpikeCount); integratedSpikeCount = NULL;
}

int LCALIFLateralConn::initialize_base() {
   integratedSpikeCount = NULL;
   return PV_SUCCESS;
}

int LCALIFLateralConn::initialize(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights * weightInit) {
   int status = HyPerConn::initialize(name, hc, pre, post, filename, weightInit);
   LCALIFLayer * lcapre = dynamic_cast<LCALIFLayer * >(pre);
   LCALIFLayer * lcapost = dynamic_cast<LCALIFLayer *>(post);
   if (lcapre == NULL || lcapost == NULL) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralConn \"%s\": Presynaptic layer \"%s\" and postsynaptic layer \"%s\" must both be LCALIFLayers.\n", name, pre->getName(), post->getName());
      }
      abort();
   }
   const PVLayerLoc * preloc = pre->getLayerLoc();
   const PVLayerLoc * postloc = post->getLayerLoc();
   int nxpre = preloc->nx; int nxpost = postloc->nx;
   int nypre = preloc->ny; int nypost = postloc->ny;
   int nfpre = preloc->nf; int nfpost = postloc->nf;
   int nbpre = preloc->nb; int nbpost = postloc->nb;
   if (nxpre!=nxpost || nypre!=nypost || nfpre!=nfpost || nbpre!=nbpost) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralConn: pre- and post-synaptic layers must have the same geometry (including margin width)\n");
         fprintf(stderr, "  Pre:  nx=%d, ny=%d, nf=%d, nb=%d\n", nxpre, nypre, nfpre, nbpre);
         fprintf(stderr, "  Post: nx=%d, ny=%d, nf=%d, nb=%d\n", nxpost, nypost, nfpost, nbpost);
      }
      abort();
   }
   integratedSpikeCount = (float *) calloc(pre->getNumExtended(), sizeof(float)); // Spike counts initialized to 0
   return status;
}

int LCALIFLateralConn::setParams(PVParams * params) {
   int status = HyPerConn::setParams(params);
   integrationTimeConstant = readIntegrationTimeConstant();
   inhibitionTimeConstant = readInhibitionTimeConstant();
   return status;
}

int LCALIFLateralConn::calc_dW(int axonId) {
   assert(axonId>=0 && axonId < numberOfAxonalArborLists());
   updateIntegratedSpikeCount();
   pvdata_t * gSyn_buffer_start = post->getChannel(channel);
   LCALIFLayer * lcapre = dynamic_cast<LCALIFLayer *>(pre);
   assert(lcapre != NULL);
   pvdata_t targetRate = lcapre->getTargetRate() / 1000; // Convert to kHz (DMP)
   pvdata_t target_rate_sq = targetRate * targetRate;
   float dt_inh = parent->getDeltaTime()/inhibitionTimeConstant;
   const PVPatchStrides * strides  = getPostNonextStrides();
   const int sx = strides->sx;
   const int sy = strides->sy;
   const int sf = strides->sf;
   const PVLayerLoc * postloc = post->getLayerLoc();
   const int nxpost = postloc->nx;
   const int nypost = postloc->ny;
   const int nfpost = postloc->nf;
   const int nbpost = postloc->nb;

//   int nxPre = preSynapticLayer()->getLayerLoc()->nx;
//   int nyPre = preSynapticLayer()->getLayerLoc()->ny;
//   int nfPre = preSynapticLayer()->getLayerLoc()->nf;
//   int nbPre = preSynapticLayer()->getLayerLoc()->nb;
   for (int kPre=0; kPre<getNumWeightPatches(); kPre++) {
      // The weight p(x,y,f) connects a presynaptic neuron in extended space to a postsynaptic neuron in restricted space.
      // We need to get the indices.  The presynaptic index is k.  To get the postsynaptic index, find
      // The memory location this weight is mapped to and subtract it from the start of the postsynaptic GSyn buffer.
      pvdata_t * gSyn_patch_start = getGSynPatchStart(kPre, axonId);
      int patch_start_index = gSyn_patch_start - gSyn_buffer_start;
      const PVPatch * p = getWeights(kPre, axonId);
      pvdata_t * dw_data = get_dwData(axonId,kPre);
      int nx = p->nx;
      int ny = p->ny;
      for (int y=0; y<ny; y++) {
         for (int x=0; x<nx; x++) {
            for (int f=0; f<nfp; f++) {
               int postindex = patch_start_index + sy*y + sx*x + sf*f;
               int postindexext = kIndexExtended(postindex, nxpost, nypost, nfpost, nbpost);
               pvdata_t delta_weight = (dt_inh/target_rate_sq) * ((integratedSpikeCount[kPre]/integrationTimeConstant) * (integratedSpikeCount[postindexext]/integrationTimeConstant) - target_rate_sq);
               dw_data[sxp*x + syp*y + sfp*f] = delta_weight;
//               int xpre = kxPos(kPre, nxPre+2*nbPre, nyPre+2*nbPre, nfPre)-nbPre;
//               int ypre = kyPos(kPre, nxPre+2*nbPre, nyPre+2*nbPre, nfPre)-nbPre;
//               int fpre = featureIndex(kPre, nxPre+2*nbPre, nyPre+2*nbPre, nfPre);
//               int xpost = kxPos(postindex, postloc->nx, postloc->ny, postloc->nf);
//               int ypost = kyPos(postindex, postloc->nx, postloc->ny, postloc->nf);
//               int fpost = featureIndex(postindex, postloc->nx, postloc->ny, postloc->nf);
//               int xpostext = kxPos(postindexext, postloc->nx+2*postloc->nb, postloc->ny+2*postloc->ny, postloc->nf)-postloc->nb;
//               int ypostext = kyPos(postindexext, postloc->nx+2*postloc->nb, postloc->ny+2*postloc->ny, postloc->nf)-postloc->nb;
//               int fpostext = featureIndex(postindexext, postloc->nx+2*postloc->nb, postloc->ny+2*postloc->ny, postloc->nf);
//               printf("Patch %d, presynaptic coordinates x=%d, y=%d, f=%d: patch coordinates x=%d, y=%d, f=%d, postindex=%d, coordinates x=%d, y=%d, f=%d, extended post index %d, coordinates x=%d, y=%d, f=%d\n",
//                      kPre, xpre, ypre, fpre, x, y, f, postindex, xpost, ypost, fpost, postindexext, xpostext, ypostext, fpostext);
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::updateWeights(int axonId) {
   if (plasticityFlag) {
      for (int kPre=0; kPre<getNumWeightPatches(); kPre++) {
         const PVPatch * p = getWeights(kPre, axonId);
         pvdata_t * dw_data = get_dwData(axonId,kPre);
         pvdata_t * w_data = get_wData(axonId,kPre);
         int nx = p->nx;
         int ny = p->ny;
         for (int y=0; y<ny; y++) {
            for (int x=0; x<nx; x++) {
               for (int f=0; f<nfp; f++) {
                  int idx = sxp*x + syp*y + sfp*f;
                  pvdata_t w = w_data[idx] + dw_data[idx];
                  if (w<0) w=0;
                  w_data[idx] = w;
               }
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::updateIntegratedSpikeCount() {
   float exp_dt_tau = exp(-parent->getDeltaTime()/integrationTimeConstant);
   pvdata_t * activity = pre->getActivity();
   for (int kext=0; kext<getNumWeightPatches(); kext++) {
      integratedSpikeCount[kext] = exp_dt_tau * (integratedSpikeCount[kext]+activity[kext]);
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::checkpointWrite(const char * cpDir) {
   int status = HyPerConn::checkpointWrite(cpDir);
   // This is kind of hacky, but we save the extended buffer integratedSpikeCount as if it were a nonextended buffer of size (nx+2*nb)-by-(ny+2*nb)
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   PVLayerLoc loc;
   memcpy(&loc, pre->getLayerLoc(), sizeof(PVLayerLoc));
   loc.nx += 2*loc.nb;
   loc.ny += 2*loc.nb;
   loc.nxGlobal = loc.nx * parent->icCommunicator()->numCommColumns();
   loc.nyGlobal = loc.ny * parent->icCommunicator()->numCommRows();
   loc.nb = 0;
   write_pvdata(filename, parent->icCommunicator(), (double) parent->simulationTime(), integratedSpikeCount, &loc, PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   return status;
}

int LCALIFLateralConn::checkpointRead(const char * cpDir, float* timef) {
   int status = HyPerConn::checkpointRead(cpDir, timef);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   double timed;
   PVLayerLoc loc;
   memcpy(&loc, pre->getLayerLoc(), sizeof(PVLayerLoc));
   loc.nx += 2*loc.nb;
   loc.ny += 2*loc.nb;
   loc.nxGlobal = loc.nx * parent->icCommunicator()->numCommColumns();
   loc.nyGlobal = loc.ny * parent->icCommunicator()->numCommRows();
   loc.nb = 0;
   read_pvdata(filename, parent->icCommunicator(), &timed, integratedSpikeCount, &loc, PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   if( (float) timed != *timef && parent->icCommunicator()->commRank() == 0 ) {
      fprintf(stderr, "Warning: %s and %s_A.pvp have different timestamps: %f versus %f\n", filename, name, (float) timed, *timef);
   }

   return status;
}

} /* namespace PV */
<commit_msg>No self-inhibition for LCALIFLateralConn<commit_after>/*
 * LCALIFLateralConn.cpp
 *
 *  Created on: Oct 3, 2012
 *      Author: pschultz
 */

#include "LCALIFLateralConn.hpp"

namespace PV {

LCALIFLateralConn::LCALIFLateralConn()
{
   initialize_base();
}

LCALIFLateralConn::LCALIFLateralConn(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights *weightInit) {
   initialize_base();
   initialize(name, hc, pre, post, filename, weightInit);
}

LCALIFLateralConn::~LCALIFLateralConn()
{
   free(integratedSpikeCount); integratedSpikeCount = NULL;
}

int LCALIFLateralConn::initialize_base() {
   integratedSpikeCount = NULL;
   return PV_SUCCESS;
}

int LCALIFLateralConn::initialize(const char * name, HyPerCol * hc, HyPerLayer * pre, HyPerLayer * post,
      const char * filename, InitWeights * weightInit) {
   int status = HyPerConn::initialize(name, hc, pre, post, filename, weightInit);
   LCALIFLayer * lcapre = dynamic_cast<LCALIFLayer * >(pre);
   LCALIFLayer * lcapost = dynamic_cast<LCALIFLayer *>(post);
   if (lcapre == NULL || lcapost == NULL) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralConn \"%s\": Presynaptic layer \"%s\" and postsynaptic layer \"%s\" must both be LCALIFLayers.\n", name, pre->getName(), post->getName());
      }
      abort();
   }
   const PVLayerLoc * preloc = pre->getLayerLoc();
   const PVLayerLoc * postloc = post->getLayerLoc();
   int nxpre = preloc->nx; int nxpost = postloc->nx;
   int nypre = preloc->ny; int nypost = postloc->ny;
   int nfpre = preloc->nf; int nfpost = postloc->nf;
   int nbpre = preloc->nb; int nbpost = postloc->nb;
   if (nxpre!=nxpost || nypre!=nypost || nfpre!=nfpost || nbpre!=nbpost) {
      if (parent->columnId()==0) {
         fprintf(stderr, "LCALIFLateralConn: pre- and post-synaptic layers must have the same geometry (including margin width)\n");
         fprintf(stderr, "  Pre:  nx=%d, ny=%d, nf=%d, nb=%d\n", nxpre, nypre, nfpre, nbpre);
         fprintf(stderr, "  Post: nx=%d, ny=%d, nf=%d, nb=%d\n", nxpost, nypost, nfpost, nbpost);
      }
      abort();
   }
   integratedSpikeCount = (float *) calloc(pre->getNumExtended(), sizeof(float)); // Spike counts initialized to 0
   return status;
}

int LCALIFLateralConn::setParams(PVParams * params) {
   int status = HyPerConn::setParams(params);
   integrationTimeConstant = readIntegrationTimeConstant();
   inhibitionTimeConstant = readInhibitionTimeConstant();
   return status;
}

int LCALIFLateralConn::calc_dW(int axonId) {
   assert(axonId>=0 && axonId < numberOfAxonalArborLists());
   updateIntegratedSpikeCount();
   pvdata_t * gSyn_buffer_start = post->getChannel(channel);
   LCALIFLayer * lcapre = dynamic_cast<LCALIFLayer *>(pre);
   assert(lcapre != NULL);
   pvdata_t targetRate = lcapre->getTargetRate() / 1000; // Convert to kHz (DMP)
   pvdata_t target_rate_sq = targetRate * targetRate;
   float dt_inh = parent->getDeltaTime()/inhibitionTimeConstant;
   const PVPatchStrides * strides  = getPostNonextStrides();
   const int sx = strides->sx;
   const int sy = strides->sy;
   const int sf = strides->sf;
   const PVLayerLoc * postloc = post->getLayerLoc();
   const int nxpost = postloc->nx;
   const int nypost = postloc->ny;
   const int nfpost = postloc->nf;
   const int nbpost = postloc->nb;

   for (int kPre=0; kPre<getNumWeightPatches(); kPre++) {
      // The weight p(x,y,f) connects a presynaptic neuron in extended space to a postsynaptic neuron in restricted space.
      // We need to get the indices.  The presynaptic index is k.  To get the postsynaptic index, find
      // The memory location this weight is mapped to and subtract it from the start of the postsynaptic GSyn buffer.
      pvdata_t * gSyn_patch_start = getGSynPatchStart(kPre, axonId);
      int patch_start_index = gSyn_patch_start - gSyn_buffer_start;
      const PVPatch * p = getWeights(kPre, axonId);
      pvdata_t * dw_data = get_dwData(axonId,kPre);
      int nx = p->nx;
      int ny = p->ny;
      for (int y=0; y<ny; y++) {
         for (int x=0; x<nx; x++) {
            for (int f=0; f<nfp; f++) {
               int postindex = patch_start_index + sy*y + sx*x + sf*f;
               int postindexext = kIndexExtended(postindex, nxpost, nypost, nfpost, nbpost);
               if (postindexext != kPre) {
                  pvdata_t delta_weight = (dt_inh/target_rate_sq) * ((integratedSpikeCount[kPre]/integrationTimeConstant) * (integratedSpikeCount[postindexext]/integrationTimeConstant) - target_rate_sq);
                  dw_data[sxp*x + syp*y + sfp*f] = delta_weight;
               }
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::updateWeights(int axonId) {
   if (plasticityFlag) {
      for (int kPre=0; kPre<getNumWeightPatches(); kPre++) {
         const PVPatch * p = getWeights(kPre, axonId);
         pvdata_t * dw_data = get_dwData(axonId,kPre);
         pvdata_t * w_data = get_wData(axonId,kPre);
         int nx = p->nx;
         int ny = p->ny;
         for (int y=0; y<ny; y++) {
            for (int x=0; x<nx; x++) {
               for (int f=0; f<nfp; f++) {
                  int idx = sxp*x + syp*y + sfp*f;
                  pvdata_t w = w_data[idx] + dw_data[idx];
                  if (w<0) w=0;
                  w_data[idx] = w;
               }
            }
         }
      }
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::updateIntegratedSpikeCount() {
   float exp_dt_tau = exp(-parent->getDeltaTime()/integrationTimeConstant);
   pvdata_t * activity = pre->getActivity();
   for (int kext=0; kext<getNumWeightPatches(); kext++) {
      integratedSpikeCount[kext] = exp_dt_tau * (integratedSpikeCount[kext]+activity[kext]);
   }
   return PV_SUCCESS;
}

int LCALIFLateralConn::checkpointWrite(const char * cpDir) {
   int status = HyPerConn::checkpointWrite(cpDir);
   // This is kind of hacky, but we save the extended buffer integratedSpikeCount as if it were a nonextended buffer of size (nx+2*nb)-by-(ny+2*nb)
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   PVLayerLoc loc;
   memcpy(&loc, pre->getLayerLoc(), sizeof(PVLayerLoc));
   loc.nx += 2*loc.nb;
   loc.ny += 2*loc.nb;
   loc.nxGlobal = loc.nx * parent->icCommunicator()->numCommColumns();
   loc.nyGlobal = loc.ny * parent->icCommunicator()->numCommRows();
   loc.nb = 0;
   write_pvdata(filename, parent->icCommunicator(), (double) parent->simulationTime(), integratedSpikeCount, &loc, PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   return status;
}

int LCALIFLateralConn::checkpointRead(const char * cpDir, float* timef) {
   int status = HyPerConn::checkpointRead(cpDir, timef);
   char filename[PV_PATH_MAX];
   int chars_needed = snprintf(filename, PV_PATH_MAX, "%s/%s_integratedSpikeCount.pvp", cpDir, name);
   if (chars_needed >= PV_PATH_MAX) {
      fprintf(stderr, "LCALIFLateralConn::checkpointWrite error.  Path \"%s/%s_integratedSpikeCount.pvp\" is too long.\n", cpDir, name);
      abort();
   }
   double timed;
   PVLayerLoc loc;
   memcpy(&loc, pre->getLayerLoc(), sizeof(PVLayerLoc));
   loc.nx += 2*loc.nb;
   loc.ny += 2*loc.nb;
   loc.nxGlobal = loc.nx * parent->icCommunicator()->numCommColumns();
   loc.nyGlobal = loc.ny * parent->icCommunicator()->numCommRows();
   loc.nb = 0;
   read_pvdata(filename, parent->icCommunicator(), &timed, integratedSpikeCount, &loc, PV_FLOAT_TYPE, /*extended*/ false, /*contiguous*/ false);
   if( (float) timed != *timef && parent->icCommunicator()->commRank() == 0 ) {
      fprintf(stderr, "Warning: %s and %s_A.pvp have different timestamps: %f versus %f\n", filename, name, (float) timed, *timef);
   }

   return status;
}

} /* namespace PV */
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <QAction>
# include <QToolBar>
# include <QToolButton>
#endif

#include "ToolBarManager.h"
#include "MainWindow.h"
#include "Application.h"
#include "Command.h"

using namespace Gui;

ToolBarItem::ToolBarItem()
{
}

ToolBarItem::ToolBarItem(ToolBarItem* item)
{
    if ( item )
        item->appendItem(this);
}

ToolBarItem::~ToolBarItem()
{
    clear();
}

void ToolBarItem::setCommand(const std::string& name)
{
    _name = name;
}

std::string ToolBarItem::command() const
{
    return _name;
}

bool ToolBarItem::hasItems() const
{
    return _items.count() > 0;
}

ToolBarItem* ToolBarItem::findItem(const std::string& name)
{
    if ( _name == name ) {
        return this;
    } else {
        for ( QList<ToolBarItem*>::ConstIterator it = _items.begin(); it != _items.end(); ++it ) {
            if ( (*it)->_name == name ) {
                return *it;
            }
        }
    }

    return 0;
}

ToolBarItem* ToolBarItem::copy() const
{
    ToolBarItem* root = new ToolBarItem;
    root->setCommand( command() );

    QList<ToolBarItem*> items = getItems();
    for ( QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it ) {
        root->appendItem( (*it)->copy() );
    }

    return root;
}

uint ToolBarItem::count() const
{
    return _items.count();
}

void ToolBarItem::appendItem(ToolBarItem* item)
{
    _items.push_back( item );
}

bool ToolBarItem::insertItem( ToolBarItem* before, ToolBarItem* item)
{
    int pos = _items.indexOf(before);
    if (pos != -1) {
        _items.insert(pos, item);
        return true;
    } else
        return false;
}

void ToolBarItem::removeItem(ToolBarItem* item)
{
    int pos = _items.indexOf(item);
    if (pos != -1)
        _items.removeAt(pos);
}

void ToolBarItem::clear()
{
    for ( QList<ToolBarItem*>::Iterator it = _items.begin(); it != _items.end(); ++it ) {
        delete *it;
    }

    _items.clear();
}

ToolBarItem& ToolBarItem::operator << (ToolBarItem* item)
{
    appendItem(item);
    return *this;
}

ToolBarItem& ToolBarItem::operator << (const std::string& command)
{
    ToolBarItem* item = new ToolBarItem(this);
    item->setCommand(command);
    return *this;
}

QList<ToolBarItem*> ToolBarItem::getItems() const
{
    return _items;
}

// -----------------------------------------------------------

ToolBarManager* ToolBarManager::_instance=0;

ToolBarManager* ToolBarManager::getInstance()
{
    if ( !_instance )
        _instance = new ToolBarManager;
    return _instance;
}

void ToolBarManager::destruct()
{
    delete _instance;
    _instance = 0;
}

ToolBarManager::ToolBarManager()
{
}

ToolBarManager::~ToolBarManager()
{
}

void ToolBarManager::setup(ToolBarItem* toolBarItems)
{
    if (!toolBarItems)
        return; // empty menu bar

    saveState();
    this->toolbarNames.clear();

    int max_width = getMainWindow()->width();
    int top_width = 0;

    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");
    QList<ToolBarItem*> items = toolBarItems->getItems();
    QList<QToolBar*> toolbars = toolBars();
    for (QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) {
        // search for the toolbar
        this->toolbarNames << QString::fromUtf8((*it)->command().c_str());
        QToolBar* toolbar = findToolBar(toolbars, QString::fromAscii((*it)->command().c_str()));
        std::string toolbarName = (*it)->command();
        bool visible = hPref->GetBool(toolbarName.c_str(), true);
        bool toolbar_added = false;

        if (!toolbar) {
            toolbar = getMainWindow()->addToolBar(
                QApplication::translate("Workbench",
                                        toolbarName.c_str(),
                                        0, QApplication::UnicodeUTF8)); // i18n
            toolbar->setObjectName(QString::fromAscii((*it)->command().c_str()));
            toolbar->setVisible(visible);
            toolbar_added = true;
        }
        else {
            toolbar->setVisible(visible);
            toolbar->toggleViewAction()->setVisible(true);
            int index = toolbars.indexOf(toolbar);
            toolbars.removeAt(index);
        }

        // setup the toolbar
        setup(*it, toolbar);

        // try to add some breaks to avoid to have all toolbars in one line
        if (toolbar_added) {
            if (top_width > 0 && getMainWindow()->toolBarBreak(toolbar))
                top_width = 0;
            // the width() of a toolbar doesn't return useful results so we estimate
            // its size by the number of buttons and the icon size
            QList<QToolButton*> btns = toolbar->findChildren<QToolButton*>();
            top_width += (btns.size() * toolbar->iconSize().width());
            if (top_width > max_width) {
                top_width = 0;
                getMainWindow()->insertToolBarBreak(toolbar);
            }
        }
    }

    // hide all unneeded toolbars
    for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        // ignore toolbars which do not belong to the previously active workbench
        QByteArray toolbarName = (*it)->objectName().toUtf8();
        if (!(*it)->toggleViewAction()->isVisible())
            continue;
        hPref->SetBool(toolbarName.constData(), (*it)->isVisible());
        (*it)->hide();
        (*it)->toggleViewAction()->setVisible(false);
    }
}

void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const
{
    CommandManager& mgr = Application::Instance->commandManager();
    QList<ToolBarItem*> items = item->getItems();
    QList<QAction*> actions = toolbar->actions();
    for (QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) {
        // search for the action item
        QAction* action = findAction(actions, QString::fromAscii((*it)->command().c_str()));
        if (!action) {
            if ((*it)->command() == "Separator") {
                action = toolbar->addSeparator();
            } else {
                // Check if action was added successfully
                if (mgr.addTo((*it)->command().c_str(), toolbar))
                    action = toolbar->actions().last();
            }

            // set the tool button user data
            if (action) action->setData(QString::fromAscii((*it)->command().c_str()));
        } else {
            // Note: For toolbars we do not remove and readd the actions
            // because this causes flicker effects. So, it could happen that the order of
            // buttons doesn't match with the order of commands in the workbench.
            int index = actions.indexOf(action);
            actions.removeAt(index);
        }
    }

    // remove all tool buttons which we don't need for the moment
    for (QList<QAction*>::Iterator it = actions.begin(); it != actions.end(); ++it) {
        toolbar->removeAction(*it);
    }
}

void ToolBarManager::saveState() const
{
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");

    QList<QToolBar*> toolbars = toolBars();
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
        QToolBar* toolbar = findToolBar(toolbars, *it);
        if (toolbar) {
            QByteArray toolbarName = toolbar->objectName().toUtf8();
            hPref->SetBool(toolbarName.constData(), toolbar->isVisible());
        }
    }
}

void ToolBarManager::restoreState() const
{
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");

    QList<QToolBar*> toolbars = toolBars();
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
        QToolBar* toolbar = findToolBar(toolbars, *it);
        if (toolbar) {
            QByteArray toolbarName = toolbar->objectName().toUtf8();
            toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible()));
        }
    }
}

void ToolBarManager::retranslate() const
{
    QList<QToolBar*> toolbars = toolBars();
    for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        QByteArray toolbarName = (*it)->objectName().toUtf8();
        (*it)->setWindowTitle(
            QApplication::translate("Workbench",
                                    (const char*)toolbarName,
                                    0, QApplication::UnicodeUTF8));
    }
}

QToolBar* ToolBarManager::findToolBar(const QList<QToolBar*>& toolbars, const QString& item) const
{
    for (QList<QToolBar*>::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        if ((*it)->objectName() == item)
            return *it;
    }

    return 0; // no item with the user data found
}

QAction* ToolBarManager::findAction(const QList<QAction*>& acts, const QString& item) const
{
    for (QList<QAction*>::ConstIterator it = acts.begin(); it != acts.end(); ++it) {
        if ((*it)->data().toString() == item)
            return *it;
    }

    return 0; // no item with the user data found
}

QList<QToolBar*> ToolBarManager::toolBars() const
{
    QWidget* mw = getMainWindow();
    QList<QToolBar*> tb;
    QList<QToolBar*> bars = getMainWindow()->findChildren<QToolBar*>();
    for (QList<QToolBar*>::ConstIterator it = bars.begin(); it != bars.end(); ++it) {
        if ((*it)->parentWidget() == mw)
            tb.push_back(*it);
    }

    return tb;
}
<commit_msg>+ fix changing 3d view when switching from Complete workbench to any other workbench<commit_after>/***************************************************************************
 *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <QAction>
# include <QToolBar>
# include <QToolButton>
#endif

#include "ToolBarManager.h"
#include "MainWindow.h"
#include "Application.h"
#include "Command.h"

using namespace Gui;

ToolBarItem::ToolBarItem()
{
}

ToolBarItem::ToolBarItem(ToolBarItem* item)
{
    if ( item )
        item->appendItem(this);
}

ToolBarItem::~ToolBarItem()
{
    clear();
}

void ToolBarItem::setCommand(const std::string& name)
{
    _name = name;
}

std::string ToolBarItem::command() const
{
    return _name;
}

bool ToolBarItem::hasItems() const
{
    return _items.count() > 0;
}

ToolBarItem* ToolBarItem::findItem(const std::string& name)
{
    if ( _name == name ) {
        return this;
    } else {
        for ( QList<ToolBarItem*>::ConstIterator it = _items.begin(); it != _items.end(); ++it ) {
            if ( (*it)->_name == name ) {
                return *it;
            }
        }
    }

    return 0;
}

ToolBarItem* ToolBarItem::copy() const
{
    ToolBarItem* root = new ToolBarItem;
    root->setCommand( command() );

    QList<ToolBarItem*> items = getItems();
    for ( QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it ) {
        root->appendItem( (*it)->copy() );
    }

    return root;
}

uint ToolBarItem::count() const
{
    return _items.count();
}

void ToolBarItem::appendItem(ToolBarItem* item)
{
    _items.push_back( item );
}

bool ToolBarItem::insertItem( ToolBarItem* before, ToolBarItem* item)
{
    int pos = _items.indexOf(before);
    if (pos != -1) {
        _items.insert(pos, item);
        return true;
    } else
        return false;
}

void ToolBarItem::removeItem(ToolBarItem* item)
{
    int pos = _items.indexOf(item);
    if (pos != -1)
        _items.removeAt(pos);
}

void ToolBarItem::clear()
{
    for ( QList<ToolBarItem*>::Iterator it = _items.begin(); it != _items.end(); ++it ) {
        delete *it;
    }

    _items.clear();
}

ToolBarItem& ToolBarItem::operator << (ToolBarItem* item)
{
    appendItem(item);
    return *this;
}

ToolBarItem& ToolBarItem::operator << (const std::string& command)
{
    ToolBarItem* item = new ToolBarItem(this);
    item->setCommand(command);
    return *this;
}

QList<ToolBarItem*> ToolBarItem::getItems() const
{
    return _items;
}

// -----------------------------------------------------------

ToolBarManager* ToolBarManager::_instance=0;

ToolBarManager* ToolBarManager::getInstance()
{
    if ( !_instance )
        _instance = new ToolBarManager;
    return _instance;
}

void ToolBarManager::destruct()
{
    delete _instance;
    _instance = 0;
}

ToolBarManager::ToolBarManager()
{
}

ToolBarManager::~ToolBarManager()
{
}

void ToolBarManager::setup(ToolBarItem* toolBarItems)
{
    if (!toolBarItems)
        return; // empty menu bar

    saveState();
    this->toolbarNames.clear();

    int max_width = getMainWindow()->width();
    int top_width = 0;

    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");
    QList<ToolBarItem*> items = toolBarItems->getItems();
    QList<QToolBar*> toolbars = toolBars();
    for (QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) {
        // search for the toolbar
        this->toolbarNames << QString::fromUtf8((*it)->command().c_str());
        QToolBar* toolbar = findToolBar(toolbars, QString::fromAscii((*it)->command().c_str()));
        std::string toolbarName = (*it)->command();
        bool visible = hPref->GetBool(toolbarName.c_str(), true);
        bool toolbar_added = false;

        if (!toolbar) {
            toolbar = getMainWindow()->addToolBar(
                QApplication::translate("Workbench",
                                        toolbarName.c_str(),
                                        0, QApplication::UnicodeUTF8)); // i18n
            toolbar->setObjectName(QString::fromAscii((*it)->command().c_str()));
            toolbar->setVisible(visible);
            toolbar_added = true;
        }
        else {
            toolbar->setVisible(visible);
            toolbar->toggleViewAction()->setVisible(true);
            int index = toolbars.indexOf(toolbar);
            toolbars.removeAt(index);
        }

        // setup the toolbar
        setup(*it, toolbar);

        // try to add some breaks to avoid to have all toolbars in one line
        if (toolbar_added) {
            if (top_width > 0 && getMainWindow()->toolBarBreak(toolbar))
                top_width = 0;
            // the width() of a toolbar doesn't return useful results so we estimate
            // its size by the number of buttons and the icon size
            QList<QToolButton*> btns = toolbar->findChildren<QToolButton*>();
            top_width += (btns.size() * toolbar->iconSize().width());
            if (top_width > max_width) {
                top_width = 0;
                getMainWindow()->insertToolBarBreak(toolbar);
            }
        }
    }

    // hide all unneeded toolbars
    for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        // make sure that the main window has the focus when hiding the toolbar with
        // the combo box inside
        QWidget *fw = QApplication::focusWidget();
        while (fw &&  !fw->isWindow()) {
            if (fw == *it) {
                getMainWindow()->setFocus();
                break;
            }
            fw = fw->parentWidget();
        }
        // ignore toolbars which do not belong to the previously active workbench
        QByteArray toolbarName = (*it)->objectName().toUtf8();
        if (!(*it)->toggleViewAction()->isVisible())
            continue;
        hPref->SetBool(toolbarName.constData(), (*it)->isVisible());
        (*it)->hide();
        (*it)->toggleViewAction()->setVisible(false);
    }
}

void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const
{
    CommandManager& mgr = Application::Instance->commandManager();
    QList<ToolBarItem*> items = item->getItems();
    QList<QAction*> actions = toolbar->actions();
    for (QList<ToolBarItem*>::ConstIterator it = items.begin(); it != items.end(); ++it) {
        // search for the action item
        QAction* action = findAction(actions, QString::fromAscii((*it)->command().c_str()));
        if (!action) {
            if ((*it)->command() == "Separator") {
                action = toolbar->addSeparator();
            } else {
                // Check if action was added successfully
                if (mgr.addTo((*it)->command().c_str(), toolbar))
                    action = toolbar->actions().last();
            }

            // set the tool button user data
            if (action) action->setData(QString::fromAscii((*it)->command().c_str()));
        } else {
            // Note: For toolbars we do not remove and readd the actions
            // because this causes flicker effects. So, it could happen that the order of
            // buttons doesn't match with the order of commands in the workbench.
            int index = actions.indexOf(action);
            actions.removeAt(index);
        }
    }

    // remove all tool buttons which we don't need for the moment
    for (QList<QAction*>::Iterator it = actions.begin(); it != actions.end(); ++it) {
        toolbar->removeAction(*it);
    }
}

void ToolBarManager::saveState() const
{
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");

    QList<QToolBar*> toolbars = toolBars();
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
        QToolBar* toolbar = findToolBar(toolbars, *it);
        if (toolbar) {
            QByteArray toolbarName = toolbar->objectName().toUtf8();
            hPref->SetBool(toolbarName.constData(), toolbar->isVisible());
        }
    }
}

void ToolBarManager::restoreState() const
{
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");

    QList<QToolBar*> toolbars = toolBars();
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
        QToolBar* toolbar = findToolBar(toolbars, *it);
        if (toolbar) {
            QByteArray toolbarName = toolbar->objectName().toUtf8();
            toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible()));
        }
    }
}

void ToolBarManager::retranslate() const
{
    QList<QToolBar*> toolbars = toolBars();
    for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        QByteArray toolbarName = (*it)->objectName().toUtf8();
        (*it)->setWindowTitle(
            QApplication::translate("Workbench",
                                    (const char*)toolbarName,
                                    0, QApplication::UnicodeUTF8));
    }
}

QToolBar* ToolBarManager::findToolBar(const QList<QToolBar*>& toolbars, const QString& item) const
{
    for (QList<QToolBar*>::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) {
        if ((*it)->objectName() == item)
            return *it;
    }

    return 0; // no item with the user data found
}

QAction* ToolBarManager::findAction(const QList<QAction*>& acts, const QString& item) const
{
    for (QList<QAction*>::ConstIterator it = acts.begin(); it != acts.end(); ++it) {
        if ((*it)->data().toString() == item)
            return *it;
    }

    return 0; // no item with the user data found
}

QList<QToolBar*> ToolBarManager::toolBars() const
{
    QWidget* mw = getMainWindow();
    QList<QToolBar*> tb;
    QList<QToolBar*> bars = getMainWindow()->findChildren<QToolBar*>();
    for (QList<QToolBar*>::ConstIterator it = bars.begin(); it != bars.end(); ++it) {
        if ((*it)->parentWidget() == mw)
            tb.push_back(*it);
    }

    return tb;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdint.h>
#include <chrono>

typedef unsigned char byte;

struct args
{
    byte *plain_ptr;
    uint64_t plain_num_bytes;
    byte *auth_ptr;
    uint64_t auth_num_bytes;
    byte *iv_ptr;
    byte *expanded_key_ptr;
    byte *out_ptr;
    byte *tag_ptr;
};

extern "C" void aes128_key_expansion(byte *key_ptr, byte *key_expansion_ptr);
extern "C" void gcm128_encrypt(args *a);
extern "C" int gcm128_decrypt(args *a);

byte key[16] =
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
byte key_expansion[11 * 16];

byte plain[32] =
    { 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
      216, 217, 218, 99,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
    };
byte auth[1]; // actually size 0
byte iv[16] =
    { 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0 };
byte out[32];
byte tag[16];

void printbytes(char *label, byte *b, int len)
{
    printf("%s:", label);
    for (int i = 0; i < len; i++) printf(" %2x", unsigned(b[i]));
    printf("\n");
}

int main()
{
    printf("hello\n");

    args a;
    a.plain_ptr = plain;
    a.plain_num_bytes = 19;
    a.auth_ptr = auth;
    a.auth_num_bytes = 0;
    a.iv_ptr = iv;
    a.expanded_key_ptr = key_expansion;
    a.out_ptr = out;
    a.tag_ptr = tag;
    printbytes("key", key, 16);
    aes128_key_expansion(key, key_expansion);
    printbytes("key_expansion", key_expansion, 11 * 16);
    gcm128_encrypt(&a);
    printbytes("cipher", out, 19);
    printbytes("tag", tag, 16);

    a.out_ptr = plain;
    a.plain_ptr = out;
    int ret = gcm128_decrypt(&a);
    printf("gcm_decrypt returned %d\n", ret);
    printbytes("plaintext", plain, 19);

    int nblocks = 256;
    byte *plain2 = new byte[nblocks * 16];
    byte *out2 = new byte[nblocks * 16];
    for (int i = 0; i < nblocks * 16; i++)
    {
        plain2[i] = i % 256;
    }
    a.plain_ptr = plain2;
    a.plain_num_bytes = nblocks * 16;
    a.out_ptr = out2;
    for (int i = 0; i < 10; i++)
    {
        auto time1 = std::chrono::high_resolution_clock::now();
        int n = 10000;
        for (int j = 0; j < n; j++)
        {
            gcm128_encrypt(&a);
        }
        auto time2 = std::chrono::high_resolution_clock::now();
        int dt = std::chrono::duration_cast<std::chrono::microseconds>(time2 - time1).count();
        printf("time = %d microseconds for %d iterations (%lf MB/s)\n", dt, n, double(n) * (nblocks * 16) / dt);
    }
    printbytes("cipher", out2, 16);
    printbytes("tag", tag, 16);

    printf("goodbye\n");
    return 0;
}
<commit_msg>Generalize the test harness a bit, so it exercises both 128-bit and 256-bit code<commit_after>#include <stdio.h>
#include <stdint.h>
#include <chrono>

typedef unsigned char byte;

struct args
{
    byte *plain_ptr;
    uint64_t plain_num_bytes;
    byte *auth_ptr;
    uint64_t auth_num_bytes;
    byte *iv_ptr;
    byte *expanded_key_ptr;
    byte *out_ptr;
    byte *tag_ptr;
};

extern "C" void aes128_key_expansion(byte *key_ptr, byte *key_expansion_ptr);
extern "C" void gcm128_encrypt(args *a);
extern "C" int gcm128_decrypt(args *a);

extern "C" void aes256_key_expansion(byte *key_ptr, byte *key_expansion_ptr);
extern "C" void gcm256_encrypt(args *a);
extern "C" int gcm256_decrypt(args *a);

byte key[32] =
    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
     16,17,18,19,20,21,22,23,24,25, 26, 27, 28, 29, 30, 31 };
byte key_expansion[15 * (128/8)];

byte plain[32] =
    { 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
      216, 217, 218, 99,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
    };
byte auth[1]; // actually size 0
byte iv[16] =
    { 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 0, 0, 0, 0 };
byte out[32];
byte tag[16];

void printbytes(char *label, byte *b, int len)
{
    printf("%s:", label);
    for (int i = 0; i < len; i++) printf(" %2x", unsigned(b[i]));
    printf("\n");
}

void test(void (*aes_key_expansion) (byte*, byte*),
          void (*gcm_encrypt) (args*),
          int  (*gcm_decrypt) (args*),
          int num_rounds)
{
    args a;
    a.plain_ptr = plain;
    a.plain_num_bytes = 19;
    a.auth_ptr = auth;
    a.auth_num_bytes = 0;
    a.iv_ptr = iv;
    a.expanded_key_ptr = key_expansion;
    a.out_ptr = out;
    a.tag_ptr = tag;
    printbytes("key", key, 16);
    aes_key_expansion(key, key_expansion);
    printbytes("key_expansion", key_expansion, (num_rounds + 1) * 16);
    gcm_encrypt(&a);
    printbytes("cipher", out, 19);
    printbytes("tag", tag, 16);

    a.out_ptr = plain;
    a.plain_ptr = out;
    int ret = gcm_decrypt(&a);
    printf("gcm_decrypt returned %d\n", ret);
    printbytes("plaintext", plain, 19);

    int nblocks = 256;
    byte *plain2 = new byte[nblocks * 16];
    byte *out2 = new byte[nblocks * 16];
    for (int i = 0; i < nblocks * 16; i++)
    {
        plain2[i] = i % 256;
    }
    a.plain_ptr = plain2;
    a.plain_num_bytes = nblocks * 16;
    a.out_ptr = out2;
    for (int i = 0; i < 10; i++)
    {
        auto time1 = std::chrono::high_resolution_clock::now();
        int n = 10000;
        for (int j = 0; j < n; j++)
        {
            gcm_encrypt(&a);
        }
        auto time2 = std::chrono::high_resolution_clock::now();
        int dt = std::chrono::duration_cast<std::chrono::microseconds>(time2 - time1).count();
        printf("time = %d microseconds for %d iterations (%lf MB/s)\n", dt, n, double(n) * (nblocks * 16) / dt);
    }
    printbytes("cipher", out2, 16);
    printbytes("tag", tag, 16);
}

int main()
{
    printf("hello\n");

    printf("\nBeginning 128-bit test...\n");
    test(aes128_key_expansion,
         gcm128_encrypt,
         gcm128_decrypt,
         10);

    printf("\nBeginning 256-bit test...\n");
    test(aes256_key_expansion,
         gcm256_encrypt,
         gcm256_decrypt,
         14);

    printf("goodbye\n");
    return 0;
}
<|endoftext|>


<commit_before>#include "backuplistwidgetitem.h"

WARNINGS_DISABLE
#include <QAction>
#include <QDesktopServices>
#include <QDir>
#include <QEvent>
#include <QFileInfo>
#include <QKeySequence>
#include <QLabel>
#include <QMovie>
#include <QPixmap>
#include <QSize>
#include <QWidget>

#include "ui_backuplistwidgetitem.h"
WARNINGS_ENABLE

#include "TElidedLabel.h"

#include "basetask.h"
#include "dirinfotask.h"
#include "elidedclickablelabel.h"
#include "utils.h"

#define BUSY_MOVIE_FILENAME ":/lib/loading.gif"

BackupListWidgetItem::BackupListWidgetItem()
    : _ui(new Ui::BackupListWidgetItem),
      _widget(new QWidget),
      _count(0),
      _size(0),
      _dirInfoTask(nullptr)
{
    _ui->setupUi(_widget);
    // Send translation events to the widget.
    _widget->installEventFilter(this);
    updateUi();
    // Set a sensible size.
    setSizeHint(QSize(_widget->minimumWidth(), _widget->minimumHeight()));

    // Set up actions.
    _widget->addAction(_ui->actionOpen);
    _widget->addAction(_ui->actionRemove);
    _ui->browseButton->setDefaultAction(_ui->actionOpen);
    _ui->removeButton->setDefaultAction(_ui->actionRemove);
    // Set up action connections.
    connect(_ui->actionRemove, &QAction::triggered, this,
            &BackupListWidgetItem::requestDelete);
    connect(_ui->actionOpen, &QAction::triggered, this,
            &BackupListWidgetItem::browseUrl);

    // Set up the "busy" animation.
    _busyMovie = new QMovie(BUSY_MOVIE_FILENAME);
}

BackupListWidgetItem::~BackupListWidgetItem()
{
    // We don't need the task fo finish if we're deleting this item.
    if(_dirInfoTask != nullptr)
        emit cancelTaskRequested(_dirInfoTask, _dirInfoTaskUuid);

    _busyMovie->stop();
    _ui->detailLabel->setMovie(nullptr);
    delete _busyMovie;
    delete _ui;
}

QWidget *BackupListWidgetItem::widget()
{
    return _widget;
}

QUrl BackupListWidgetItem::url() const
{
    return _url;
}

void BackupListWidgetItem::setUrl(const QUrl &url)
{
    _url = url;

    if(!_url.isEmpty())
    {
        QString fileUrl = _url.toLocalFile();
        if(fileUrl.isEmpty())
            return;
        QFileInfo file(fileUrl);
        if(!file.exists())
            return;
        // Display path in the widget.  pathLabel is an TElidedLabel, so
        // the text might be cut short.  Therefore we display the path
        // as a tooltip as well, which will always be displayed in full.
        _ui->pathLabel->setText(fileUrl);
        _ui->pathLabel->setToolTip(fileUrl);

        if(file.isDir())
        {
            QPixmap icon(":/icons/folder.png");
            _ui->iconLabel->setPixmap(icon);
            // Load info about this directory in a separate thread.
            startDirInfoTask();
        }
        else if(file.isFile())
        {
            QPixmap icon(":/icons/file.png");
            _ui->iconLabel->setPixmap(icon);
            _count = 1;
            _size  = static_cast<quint64>(file.size());
            _ui->detailLabel->setText(Utils::humanBytes(_size));
        }
        else
        {
            // Could be a device file, fifo, or whatever; thus ignore.
            return;
        }
    }
}

void BackupListWidgetItem::browseUrl()
{
    QDesktopServices::openUrl(_url);
}

void BackupListWidgetItem::updateDirDetail(quint64 size, quint64 count)
{
    // The task has finished.
    _dirInfoTask = nullptr;
    _busyMovie->stop();
    _ui->detailLabel->setMovie(nullptr);

    _size  = size;
    _count = count;
    _ui->detailLabel->setText(QString::number(_count) + tr(" items, ")
                              + Utils::humanBytes(_size));
    emit requestUpdate();
}

void BackupListWidgetItem::cancelDirDetail()
{
    // The task has finished.
    _dirInfoTask = nullptr;

    _ui->detailLabel->setText("canceled");
    _ui->detailLabel->setToolTip(
        "Calculation canceled by user; click to restart");
    connect(_ui->detailLabel, &ElidedClickableLabel::clicked, this,
            &BackupListWidgetItem::startDirInfoTask);
}

void BackupListWidgetItem::startDirInfoTask()
{
    // Cancel the clickable label.
    disconnect(_ui->detailLabel, &ElidedClickableLabel::clicked, this,
               &BackupListWidgetItem::startDirInfoTask);

    // Bail if we're already working on this.
    if(_dirInfoTask != nullptr)
        return;

    // Get the directory name, or bail.
    QString fileUrl = _url.toLocalFile();
    if(fileUrl.isEmpty())
        return;
    QFileInfo file(fileUrl);
    if(!file.exists())
        return;
    if(!file.isDir())
        return;

    // Prepare the task.
    QDir dir(file.absoluteFilePath());
    _dirInfoTask     = new DirInfoTask(dir);
    _dirInfoTaskUuid = _dirInfoTask->uuid();
    connect(_dirInfoTask, &DirInfoTask::result, this,
            &BackupListWidgetItem::updateDirDetail, QUEUED);
    connect(_dirInfoTask, &DirInfoTask::canceled, this,
            &BackupListWidgetItem::cancelDirDetail, QUEUED);

    // Display "waiting"
    _ui->detailLabel->setText("");
    _ui->detailLabel->setToolTip("");
    _ui->detailLabel->setMovie(_busyMovie);
    _busyMovie->start();

    // Send the task to the TaskManager.
    emit taskRequested(_dirInfoTask);
}

bool BackupListWidgetItem::eventFilter(QObject *obj, QEvent *event)
{
    if((obj == _widget) && (event->type() == QEvent::LanguageChange))
    {
        _ui->retranslateUi(_widget);
        updateUi();
        return true;
    }
    return false;
}

quint64 BackupListWidgetItem::size() const
{
    return _size;
}

quint64 BackupListWidgetItem::count() const
{
    return _count;
}

void BackupListWidgetItem::updateUi()
{
    // Display tooltip using a platform-specific string.
    _ui->actionRemove->setToolTip(_ui->actionRemove->toolTip().arg(
        _ui->actionRemove->shortcut().toString(QKeySequence::NativeText)));
}
<commit_msg>BackupListWidgetItem: early bail<commit_after>#include "backuplistwidgetitem.h"

WARNINGS_DISABLE
#include <QAction>
#include <QDesktopServices>
#include <QDir>
#include <QEvent>
#include <QFileInfo>
#include <QKeySequence>
#include <QLabel>
#include <QMovie>
#include <QPixmap>
#include <QSize>
#include <QWidget>

#include "ui_backuplistwidgetitem.h"
WARNINGS_ENABLE

#include "TElidedLabel.h"

#include "basetask.h"
#include "dirinfotask.h"
#include "elidedclickablelabel.h"
#include "utils.h"

#define BUSY_MOVIE_FILENAME ":/lib/loading.gif"

BackupListWidgetItem::BackupListWidgetItem()
    : _ui(new Ui::BackupListWidgetItem),
      _widget(new QWidget),
      _count(0),
      _size(0),
      _dirInfoTask(nullptr)
{
    _ui->setupUi(_widget);
    // Send translation events to the widget.
    _widget->installEventFilter(this);
    updateUi();
    // Set a sensible size.
    setSizeHint(QSize(_widget->minimumWidth(), _widget->minimumHeight()));

    // Set up actions.
    _widget->addAction(_ui->actionOpen);
    _widget->addAction(_ui->actionRemove);
    _ui->browseButton->setDefaultAction(_ui->actionOpen);
    _ui->removeButton->setDefaultAction(_ui->actionRemove);
    // Set up action connections.
    connect(_ui->actionRemove, &QAction::triggered, this,
            &BackupListWidgetItem::requestDelete);
    connect(_ui->actionOpen, &QAction::triggered, this,
            &BackupListWidgetItem::browseUrl);

    // Set up the "busy" animation.
    _busyMovie = new QMovie(BUSY_MOVIE_FILENAME);
}

BackupListWidgetItem::~BackupListWidgetItem()
{
    // We don't need the task fo finish if we're deleting this item.
    if(_dirInfoTask != nullptr)
        emit cancelTaskRequested(_dirInfoTask, _dirInfoTaskUuid);

    _busyMovie->stop();
    _ui->detailLabel->setMovie(nullptr);
    delete _busyMovie;
    delete _ui;
}

QWidget *BackupListWidgetItem::widget()
{
    return _widget;
}

QUrl BackupListWidgetItem::url() const
{
    return _url;
}

void BackupListWidgetItem::setUrl(const QUrl &url)
{
    _url = url;

    // Bail (if applicable).
    if(url.isEmpty())
        return;

    {
        QString fileUrl = _url.toLocalFile();
        if(fileUrl.isEmpty())
            return;
        QFileInfo file(fileUrl);
        if(!file.exists())
            return;
        // Display path in the widget.  pathLabel is an TElidedLabel, so
        // the text might be cut short.  Therefore we display the path
        // as a tooltip as well, which will always be displayed in full.
        _ui->pathLabel->setText(fileUrl);
        _ui->pathLabel->setToolTip(fileUrl);

        if(file.isDir())
        {
            QPixmap icon(":/icons/folder.png");
            _ui->iconLabel->setPixmap(icon);
            // Load info about this directory in a separate thread.
            startDirInfoTask();
        }
        else if(file.isFile())
        {
            QPixmap icon(":/icons/file.png");
            _ui->iconLabel->setPixmap(icon);
            _count = 1;
            _size  = static_cast<quint64>(file.size());
            _ui->detailLabel->setText(Utils::humanBytes(_size));
        }
        else
        {
            // Could be a device file, fifo, or whatever; thus ignore.
            return;
        }
    }
}

void BackupListWidgetItem::browseUrl()
{
    QDesktopServices::openUrl(_url);
}

void BackupListWidgetItem::updateDirDetail(quint64 size, quint64 count)
{
    // The task has finished.
    _dirInfoTask = nullptr;
    _busyMovie->stop();
    _ui->detailLabel->setMovie(nullptr);

    _size  = size;
    _count = count;
    _ui->detailLabel->setText(QString::number(_count) + tr(" items, ")
                              + Utils::humanBytes(_size));
    emit requestUpdate();
}

void BackupListWidgetItem::cancelDirDetail()
{
    // The task has finished.
    _dirInfoTask = nullptr;

    _ui->detailLabel->setText("canceled");
    _ui->detailLabel->setToolTip(
        "Calculation canceled by user; click to restart");
    connect(_ui->detailLabel, &ElidedClickableLabel::clicked, this,
            &BackupListWidgetItem::startDirInfoTask);
}

void BackupListWidgetItem::startDirInfoTask()
{
    // Cancel the clickable label.
    disconnect(_ui->detailLabel, &ElidedClickableLabel::clicked, this,
               &BackupListWidgetItem::startDirInfoTask);

    // Bail if we're already working on this.
    if(_dirInfoTask != nullptr)
        return;

    // Get the directory name, or bail.
    QString fileUrl = _url.toLocalFile();
    if(fileUrl.isEmpty())
        return;
    QFileInfo file(fileUrl);
    if(!file.exists())
        return;
    if(!file.isDir())
        return;

    // Prepare the task.
    QDir dir(file.absoluteFilePath());
    _dirInfoTask     = new DirInfoTask(dir);
    _dirInfoTaskUuid = _dirInfoTask->uuid();
    connect(_dirInfoTask, &DirInfoTask::result, this,
            &BackupListWidgetItem::updateDirDetail, QUEUED);
    connect(_dirInfoTask, &DirInfoTask::canceled, this,
            &BackupListWidgetItem::cancelDirDetail, QUEUED);

    // Display "waiting"
    _ui->detailLabel->setText("");
    _ui->detailLabel->setToolTip("");
    _ui->detailLabel->setMovie(_busyMovie);
    _busyMovie->start();

    // Send the task to the TaskManager.
    emit taskRequested(_dirInfoTask);
}

bool BackupListWidgetItem::eventFilter(QObject *obj, QEvent *event)
{
    if((obj == _widget) && (event->type() == QEvent::LanguageChange))
    {
        _ui->retranslateUi(_widget);
        updateUi();
        return true;
    }
    return false;
}

quint64 BackupListWidgetItem::size() const
{
    return _size;
}

quint64 BackupListWidgetItem::count() const
{
    return _count;
}

void BackupListWidgetItem::updateUi()
{
    // Display tooltip using a platform-specific string.
    _ui->actionRemove->setToolTip(_ui->actionRemove->toolTip().arg(
        _ui->actionRemove->shortcut().toString(QKeySequence::NativeText)));
}
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "plugin_manager.h"

#include "seeks_proxy.h"
#include "proxy_configuration.h"
#include "errlog.h"

#include "plugin.h"
#include "interceptor_plugin.h"
#include "action_plugin.h"
#include "filter_plugin.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>  // linux, TODO: windows.

#include <list>
#include <iostream>

#include <assert.h>

using sp::proxy_configuration;

namespace sp
{
   // variables.
   std::vector<plugin*> plugin_manager::_plugins = std::vector<plugin*>();
   std::vector<interceptor_plugin*> plugin_manager::_ref_interceptor_plugins
     = std::vector<interceptor_plugin*>();
   std::vector<action_plugin*> plugin_manager::_ref_action_plugins
     = std::vector<action_plugin*>();
   std::vector<filter_plugin*> plugin_manager::_ref_filter_plugins
     = std::vector<filter_plugin*>();

   hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr> plugin_manager::_cgi_dispatchers
     = hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>();

   std::string plugin_manager::_plugin_repository = "";

   std::map<std::string,maker_ptr*,std::less<std::string> > plugin_manager::_factory
     = std::map<std::string,maker_ptr*,std::less<std::string> >();

   std::list<void*> plugin_manager::_dl_list = std::list<void*>();

   std::map<std::string,configuration_spec*,std::less<std::string> > plugin_manager::_configurations
     = std::map<std::string,configuration_spec*,std::less<std::string> >();

   std::string plugin_manager::_config_html_template = "templates/pm_config.html";

   int plugin_manager::load_all_plugins()
     {
	/**
	 * Defaults the plugin repository to the base directory, only if the repository has not been set
	 * through the command line, or in the configuration file, in that order.
	 */
	if (plugin_manager::_plugin_repository.empty() && seeks_proxy::_config->_plugindir)
	  {
	     plugin_manager::_plugin_repository = std::string(seeks_proxy::_config->_plugindir);
	  }
	else if (plugin_manager::_plugin_repository.empty())
	  {
	     // basedir.
	     assert(seeks_proxy::_basedir);
	     plugin_manager::_plugin_repository = std::string(seeks_proxy::_basedir)
#ifdef unix
	       + "/plugins/"
#endif
	       ;
#if defined(_WIN32)
	     + "\plugins\\";
#endif
	  }

	unsigned int BUF_SIZE = 1024;

	// TODO: win32...

	std::string command_str = "find " + plugin_manager::_plugin_repository
#if defined(ON_OPENBSD)
	  + " -name *.so*";
#elsif defined (ON_OSX)
	+ " -name *plugin.dylib";
#else
	+ " -name *.so";
#endif
	FILE *dl = popen(command_str.c_str(), "r"); // reading directory.
	if (!dl)
	  {
	     perror("popen");
	     exit(-1);
	  }

	void *dlib;
	char name[1024];
	char in_buf[BUF_SIZE]; // input buffer for lib names.
	while(fgets(in_buf, BUF_SIZE, dl))
	  {
	     char *ws = strpbrk(in_buf, " \t\n"); // remove spaces.
	     if (ws) *ws = '\0';

	     sprintf(name, "%s", in_buf); // append './' to lib name.
	     dlib = dlopen(name, RTLD_NOW);  // NOW imposes resolving all symbols
	                                     // required for auto-registration.
	     if (dlib == NULL)
	       {
		  errlog::log_error(LOG_LEVEL_ERROR, "%s", dlerror());
		  //exit(-1);
	       }

	     plugin_manager::_dl_list.insert(plugin_manager::_dl_list.end(),dlib); // add lib handle to the list.

#if defined(ON_OPENBSD) || defined(ON_OSX)
	     maker_ptr *pl_fct = (maker_ptr*)dlsym(dlib,"maker");
	     if (!pl_fct)
	       continue;

	     plugin *pl = (*pl_fct)();
	     if (pl)
	       plugin_manager::_factory[pl->get_name()] = pl_fct;
#endif
	  }

	pclose(dl);

	//debug
	std::map<std::string,maker_ptr*,std::less<std::string> >::const_iterator mit
	  = plugin_manager::_factory.begin();
	while(mit!=plugin_manager::_factory.end())
	  {
	     errlog::log_error(LOG_LEVEL_INFO,"loaded plugin \t%s", (*mit).first.c_str());
	     mit++;
	  }
	//debug

	return 1;
     }

   int plugin_manager::close_all_plugins()
     {
	// destroy all plugins that have been created.
	std::vector<plugin*>::iterator vit = plugin_manager::_plugins.begin();
	while(vit!=plugin_manager::_plugins.end())
	  {
	     delete *vit;
	     ++vit;
	  }
	plugin_manager::_plugins.clear();

	// close all the opened dynamic libs.
	std::list<void*>::iterator lit = plugin_manager::_dl_list.begin();
	while(lit!=plugin_manager::_dl_list.end())
	  {
	     dlclose((*lit));
	     ++lit;
	  }

	return 1;
     }

   int plugin_manager::instanciate_plugins()
     {
	std::map<std::string,maker_ptr*,std::less<std::string> >::const_iterator mit
	  = plugin_manager::_factory.begin();
	while(mit!=plugin_manager::_factory.end())
	  {
	     plugin *p = (*mit).second(); // call to a maker function.

	     // register the plugin object and its functions, if activated.
	     if (seeks_proxy::_config->is_plugin_activated(p->get_name_cstr()))
		 {
		    plugin_manager::register_plugin(p);

		    // register the plugin elements.
		    if (p->_interceptor_plugin)
		      plugin_manager::_ref_interceptor_plugins.push_back(p->_interceptor_plugin);
		    if (p->_action_plugin)
		      plugin_manager::_ref_action_plugins.push_back(p->_action_plugin);
		    if (p->_filter_plugin)
		      plugin_manager::_ref_filter_plugins.push_back(p->_filter_plugin);

		    // run start() on plugin.
		    p->start();
		 }

	     ++mit;
	  }
	return 0;
     }

   //TODO: deinstanciate plugin = deregister + stop().

   void plugin_manager::register_plugin(plugin *p)
     {
	plugin_manager::_plugins.push_back(p);

	errlog::log_error(LOG_LEVEL_INFO,"Registering plugin %s, and %d CGI dispatchers",
			  p->get_name_cstr(), p->_cgi_dispatchers.size());

	std::vector<cgi_dispatcher*>::const_iterator vit = p->_cgi_dispatchers.begin();
	while(vit != p->_cgi_dispatchers.end())
	  {
	     cgi_dispatcher *cgid = (*vit);

	     hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>::iterator hit;
	     if ((hit = plugin_manager::_cgi_dispatchers.find(cgid->_name)) != plugin_manager::_cgi_dispatchers.end())
	       {
		  errlog::log_error(LOG_LEVEL_CGI, "CGI function %s of plugin %s, has already been registered by another plugin.",
				    cgid->_name, p->get_name_cstr());
	       }
	     else
	       {
		  errlog::log_error(LOG_LEVEL_INFO, "registering CGI dispatcher %s", cgid->_name);

		  plugin_manager::_cgi_dispatchers.insert(std::pair<const char*,cgi_dispatcher*>(cgid->_name,
												 cgid));
	       }

	     ++vit;
	  }
     }

   cgi_dispatcher* plugin_manager::find_plugin_cgi_dispatcher(const char *path)
     {
	hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>::const_iterator hit;
	if((hit = plugin_manager::_cgi_dispatchers.find(path)) != plugin_manager::_cgi_dispatchers.end())
	  return (*hit).second;
	else
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "Can't find any plugin dispatcher in %s", path);
	     return NULL;
	  }
     }

   void plugin_manager::get_url_plugins(client_state *csp, http_request *http)
     {
	std::vector<interceptor_plugin*>::const_iterator lit1
	  = plugin_manager::_ref_interceptor_plugins.begin();
	while(lit1!=plugin_manager::_ref_interceptor_plugins.end())
	  {
	     interceptor_plugin *ip = (*lit1);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_interceptor_plugin(ip);
	     ++lit1;
	  }

	std::vector<action_plugin*>::const_iterator lit2
	  = plugin_manager::_ref_action_plugins.begin();
	while(lit2!=plugin_manager::_ref_action_plugins.end())
	  {
	     action_plugin *ip = (*lit2);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_action_plugin(ip);
	     ++lit2;
	  }

	std::vector<filter_plugin*>::const_iterator lit3
	  = plugin_manager::_ref_filter_plugins.begin();
	while(lit3!=plugin_manager::_ref_filter_plugins.end())
	  {
	     filter_plugin *ip = (*lit3);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_filter_plugin(ip);
	     ++lit3;
	  }

	// debug
	/* std::cout << "[Debug]:plugin_manager::get_url_plugin: interceptor plugins: "
	  << csp->_interceptor_plugins.size() << std::endl; */
	//debug
     }

   plugin* plugin_manager::get_plugin(const std::string &name)
     {
	std::vector<plugin*>::const_iterator vit = plugin_manager::_plugins.begin();
	while(vit!=plugin_manager::_plugins.end())
	  {
	     if ((*vit)->get_name() == name)
	       return (*vit);
	     ++vit;
	  }
	return NULL;
     }

} /* end of namespace. */
<commit_msg>plugin_manager change to start plugins after they all registered<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "plugin_manager.h"

#include "seeks_proxy.h"
#include "proxy_configuration.h"
#include "errlog.h"

#include "plugin.h"
#include "interceptor_plugin.h"
#include "action_plugin.h"
#include "filter_plugin.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>  // linux, TODO: windows.

#include <list>
#include <iostream>

#include <assert.h>

using sp::proxy_configuration;

namespace sp
{
   // variables.
   std::vector<plugin*> plugin_manager::_plugins = std::vector<plugin*>();
   std::vector<interceptor_plugin*> plugin_manager::_ref_interceptor_plugins
     = std::vector<interceptor_plugin*>();
   std::vector<action_plugin*> plugin_manager::_ref_action_plugins
     = std::vector<action_plugin*>();
   std::vector<filter_plugin*> plugin_manager::_ref_filter_plugins
     = std::vector<filter_plugin*>();

   hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr> plugin_manager::_cgi_dispatchers
     = hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>();

   std::string plugin_manager::_plugin_repository = "";

   std::map<std::string,maker_ptr*,std::less<std::string> > plugin_manager::_factory
     = std::map<std::string,maker_ptr*,std::less<std::string> >();

   std::list<void*> plugin_manager::_dl_list = std::list<void*>();

   std::map<std::string,configuration_spec*,std::less<std::string> > plugin_manager::_configurations
     = std::map<std::string,configuration_spec*,std::less<std::string> >();

   std::string plugin_manager::_config_html_template = "templates/pm_config.html";

   int plugin_manager::load_all_plugins()
     {
	/**
	 * Defaults the plugin repository to the base directory, only if the repository has not been set
	 * through the command line, or in the configuration file, in that order.
	 */
	if (plugin_manager::_plugin_repository.empty() && seeks_proxy::_config->_plugindir)
	  {
	     plugin_manager::_plugin_repository = std::string(seeks_proxy::_config->_plugindir);
	  }
	else if (plugin_manager::_plugin_repository.empty())
	  {
	     // basedir.
	     assert(seeks_proxy::_basedir);
	     plugin_manager::_plugin_repository = std::string(seeks_proxy::_basedir)
#ifdef unix
	       + "/plugins/"
#endif
	       ;
#if defined(_WIN32)
	     + "\plugins\\";
#endif
	  }

	unsigned int BUF_SIZE = 1024;

	// TODO: win32...

	std::string command_str = "find " + plugin_manager::_plugin_repository
#if defined(ON_OPENBSD)
	  + " -name *.so*";
#elsif defined (ON_OSX)
	+ " -name *plugin.dylib";
#else
	+ " -name *.so";
#endif
	FILE *dl = popen(command_str.c_str(), "r"); // reading directory.
	if (!dl)
	  {
	     perror("popen");
	     exit(-1);
	  }

	void *dlib;
	char name[1024];
	char in_buf[BUF_SIZE]; // input buffer for lib names.
	while(fgets(in_buf, BUF_SIZE, dl))
	  {
	     char *ws = strpbrk(in_buf, " \t\n"); // remove spaces.
	     if (ws) *ws = '\0';

	     sprintf(name, "%s", in_buf); // append './' to lib name.
	     dlib = dlopen(name, RTLD_NOW);  // NOW imposes resolving all symbols
	                                     // required for auto-registration.
	     if (dlib == NULL)
	       {
		  errlog::log_error(LOG_LEVEL_ERROR, "%s", dlerror());
		  //exit(-1);
	       }

	     plugin_manager::_dl_list.insert(plugin_manager::_dl_list.end(),dlib); // add lib handle to the list.

#if defined(ON_OPENBSD) || defined(ON_OSX)
	     maker_ptr *pl_fct = (maker_ptr*)dlsym(dlib,"maker");
	     if (!pl_fct)
	       continue;

	     plugin *pl = (*pl_fct)();
	     if (pl)
	       plugin_manager::_factory[pl->get_name()] = pl_fct;
#endif
	  }

	pclose(dl);

	//debug
	std::map<std::string,maker_ptr*,std::less<std::string> >::const_iterator mit
	  = plugin_manager::_factory.begin();
	while(mit!=plugin_manager::_factory.end())
	  {
	     errlog::log_error(LOG_LEVEL_INFO,"loaded plugin \t%s", (*mit).first.c_str());
	     mit++;
	  }
	//debug

	return 1;
     }

   int plugin_manager::close_all_plugins()
     {
	// destroy all plugins that have been created.
	std::vector<plugin*>::iterator vit = plugin_manager::_plugins.begin();
	while(vit!=plugin_manager::_plugins.end())
	  {
	     delete *vit;
	     ++vit;
	  }
	plugin_manager::_plugins.clear();

	// close all the opened dynamic libs.
	std::list<void*>::iterator lit = plugin_manager::_dl_list.begin();
	while(lit!=plugin_manager::_dl_list.end())
	  {
	     dlclose((*lit));
	     ++lit;
	  }

	return 1;
     }

   int plugin_manager::instanciate_plugins()
     {
	std::map<std::string,maker_ptr*,std::less<std::string> >::const_iterator mit
	  = plugin_manager::_factory.begin();
	while(mit!=plugin_manager::_factory.end())
	  {
	     plugin *p = (*mit).second(); // call to a maker function.

	     // register the plugin object and its functions, if activated.
	     if (seeks_proxy::_config->is_plugin_activated(p->get_name_cstr()))
		 {
		    plugin_manager::register_plugin(p);

		    // register the plugin elements.
		    if (p->_interceptor_plugin)
		      plugin_manager::_ref_interceptor_plugins.push_back(p->_interceptor_plugin);
		    if (p->_action_plugin)
		      plugin_manager::_ref_action_plugins.push_back(p->_action_plugin);
		    if (p->_filter_plugin)
		      plugin_manager::_ref_filter_plugins.push_back(p->_filter_plugin);
		 }
	     ++mit;
	  }

	// start registered plugins.
	std::vector<plugin*>::const_iterator vit = plugin_manager::_plugins.begin();
	while(vit!=plugin_manager::_plugins.end())
	  {
	     (*vit)->start();
	     ++vit;
	  }

	return 0;
     }

   //TODO: deinstanciate plugin = deregister + stop().

   void plugin_manager::register_plugin(plugin *p)
     {
	plugin_manager::_plugins.push_back(p);

	errlog::log_error(LOG_LEVEL_INFO,"Registering plugin %s, and %d CGI dispatchers",
			  p->get_name_cstr(), p->_cgi_dispatchers.size());

	std::vector<cgi_dispatcher*>::const_iterator vit = p->_cgi_dispatchers.begin();
	while(vit != p->_cgi_dispatchers.end())
	  {
	     cgi_dispatcher *cgid = (*vit);

	     hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>::iterator hit;
	     if ((hit = plugin_manager::_cgi_dispatchers.find(cgid->_name)) != plugin_manager::_cgi_dispatchers.end())
	       {
		  errlog::log_error(LOG_LEVEL_CGI, "CGI function %s of plugin %s, has already been registered by another plugin.",
				    cgid->_name, p->get_name_cstr());
	       }
	     else
	       {
		  errlog::log_error(LOG_LEVEL_INFO, "registering CGI dispatcher %s", cgid->_name);

		  plugin_manager::_cgi_dispatchers.insert(std::pair<const char*,cgi_dispatcher*>(cgid->_name,
												 cgid));
	       }

	     ++vit;
	  }
     }

   cgi_dispatcher* plugin_manager::find_plugin_cgi_dispatcher(const char *path)
     {
	hash_map<const char*,cgi_dispatcher*,hash<const char*>,eqstr>::const_iterator hit;
	if((hit = plugin_manager::_cgi_dispatchers.find(path)) != plugin_manager::_cgi_dispatchers.end())
	  return (*hit).second;
	else
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "Can't find any plugin dispatcher in %s", path);
	     return NULL;
	  }
     }

   void plugin_manager::get_url_plugins(client_state *csp, http_request *http)
     {
	std::vector<interceptor_plugin*>::const_iterator lit1
	  = plugin_manager::_ref_interceptor_plugins.begin();
	while(lit1!=plugin_manager::_ref_interceptor_plugins.end())
	  {
	     interceptor_plugin *ip = (*lit1);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_interceptor_plugin(ip);
	     ++lit1;
	  }

	std::vector<action_plugin*>::const_iterator lit2
	  = plugin_manager::_ref_action_plugins.begin();
	while(lit2!=plugin_manager::_ref_action_plugins.end())
	  {
	     action_plugin *ip = (*lit2);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_action_plugin(ip);
	     ++lit2;
	  }

	std::vector<filter_plugin*>::const_iterator lit3
	  = plugin_manager::_ref_filter_plugins.begin();
	while(lit3!=plugin_manager::_ref_filter_plugins.end())
	  {
	     filter_plugin *ip = (*lit3);
#ifdef PLUGIN_DEBUG
	     ip->reload();
#endif
	     if (ip->match_url(http))
	       csp->add_filter_plugin(ip);
	     ++lit3;
	  }

	// debug
	/* std::cout << "[Debug]:plugin_manager::get_url_plugin: interceptor plugins: "
	  << csp->_interceptor_plugins.size() << std::endl; */
	//debug
     }

   plugin* plugin_manager::get_plugin(const std::string &name)
     {
	std::vector<plugin*>::const_iterator vit = plugin_manager::_plugins.begin();
	while(vit!=plugin_manager::_plugins.end())
	  {
	     if ((*vit)->get_name() == name)
	       return (*vit);
	     ++vit;
	  }
	return NULL;
     }

} /* end of namespace. */
<|endoftext|>