<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "NaaliApplication.h"
#include "Framework.h"
#include "ConfigurationManager.h"

#include <QDir>
#include <QGraphicsView>
#include <QTranslator>
#include <QLocale>
#include <QIcon>

#include "MemoryLeakCheck.h"

namespace Foundation
{
    NaaliApplication::NaaliApplication(Framework *framework, int &argc, char **argv) :
        QApplication(argc, argv),
        framework_(framework),
        app_activated_(true),
        native_translator_(new QTranslator),
        app_translator_(new QTranslator)//,
//        main_window_(new MainWindow(framework_))
    {
#ifdef Q_WS_WIN
        // If under windows, add run_dir/plugins as library path
        // unix users will get plugins from their OS Qt installation folder automatically
        QString run_directory = applicationDirPath();
        run_directory += "/qtplugins";
        addLibraryPath(run_directory);
#endif

        QDir dir("data/translations/qt_native_translations");
        QStringList qmFiles = GetQmFiles(dir);

        // Search then that is there corresponding native translations for system locals.
        QString loc = QLocale::system().name();
        loc.chop(3);

        QString name = "data/translations/qt_native_translations/qt_" + loc + ".qm";
        QStringList lst = qmFiles.filter(name);
        if (!lst.empty() )
            native_translator_->load(lst[0]);

        this->installTranslator(native_translator_);

        std::string default_language = framework_->GetConfigManager()->DeclareSetting(Framework::ConfigurationGroup(),
            "language", std::string("data/translations/naali_en"));
        ChangeLanguage(QString::fromStdString(default_language));
    }

    NaaliApplication::~NaaliApplication()
    {
//        view_.reset();
        SAFE_DELETE(native_translator_);
        SAFE_DELETE(app_translator_);
//        SAFE_DELETE(main_window_);
    }
/*
    QGraphicsView *NaaliApplication::GetUIView() const
    {
        return view_.get();
    }

    void NaaliApplication::SetUIView(std::auto_ptr <QGraphicsView> view)
    {
        view_ = view;
    }

    MainWindow *NaaliApplication::GetMainWindow() const
    {
        return main_window_;
    }
*/
    QStringList NaaliApplication::GetQmFiles(const QDir& dir)
    {
         QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
         QMutableStringListIterator i(fileNames);
         while (i.hasNext())
         {
             i.next();
             i.setValue(dir.filePath(i.value()));
         }
         return fileNames;
    }

    void NaaliApplication::Go()
    {
        installEventFilter(this);

        QObject::connect(&frame_update_timer_, SIGNAL(timeout()), this, SLOT(UpdateFrame()));
        frame_update_timer_.setSingleShot (true);
        frame_update_timer_.start (0);

        try
        {
            exec ();
        }
        catch(const std::exception &e)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an unknown exception!"));
            throw;
        }
    }

    bool NaaliApplication::eventFilter(QObject *obj,  QEvent *event)
    {
        try
        {
            if (obj == this)
            {
                if (event->type() == QEvent::ApplicationActivate)
                    app_activated_ = true;
                if (event->type() == QEvent::ApplicationDeactivate)
                    app_activated_ = false;
                /*
                if (event->type() == QEvent::LanguageChange)
                {
                    // Now if exist remove our default translation engine.
                    if (translator_ != 0)
                        this->removeTranslator(translator_);
                }
                */
            }
            return QObject::eventFilter(obj, event);
        }
        catch(const std::exception &e)
        {
            std::cout << std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::eventFilter caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::ChangeLanguage(const QString& file)
    {
        QString filename = file;
        if (!filename.endsWith(".qm", Qt::CaseInsensitive))
            filename.append(".qm");
        QString tmp = filename;
        tmp.chop(3);
        QString str = tmp.right(2);

        QString name = "data/translations/qt_native_translations/qt_" + str + ".qm";

        // Remove old translators then change them to new.
        removeTranslator(native_translator_);

        if ( QFile::exists(name) )
        {
            if ( native_translator_ != 0)
            {
                native_translator_->load(name);
                installTranslator(native_translator_);
            }
        }
        else
        {
            if (native_translator_ != 0 && native_translator_->isEmpty())
            {
                installTranslator(native_translator_);
            }
            else
            {
                SAFE_DELETE(native_translator_);
                native_translator_ = new QTranslator;
                installTranslator(native_translator_);
            }
        }

        // Remove old translators then change them to new.
        removeTranslator(app_translator_);
        if (app_translator_->load(filename))
        {
            installTranslator(app_translator_);
            framework_->GetConfigManager()->SetSetting(Framework::ConfigurationGroup(), "language", file.toStdString());
        }

        emit LanguageChanged();
    }

    bool NaaliApplication::notify(QObject *receiver, QEvent *event)
    {
        try
        {
            return QApplication::notify(receiver, event);
        } catch(const std::exception &e)
        {
            std::cout << std::string("QApp::notify caught an exception: ") << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::notify caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::UpdateFrame()
    {
        try
        {
            QApplication::processEvents (QEventLoop::AllEvents, 1);
            QApplication::sendPostedEvents ();

            framework_-> ProcessOneFrame();

            // Reduce framerate when unfocused
            if (app_activated_)
                frame_update_timer_.start(0);
            else
                frame_update_timer_.start(5);
        }
        catch(const std::exception &e)
        {
            std::cout << "QApp::UpdateFrame caught an exception: " << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            std::cout << "QApp::UpdateFrame caught an unknown exception!" << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::AboutToExit()
    {
        emit ExitRequested();

        // If no-one canceled the exit as a response to the signal, exit
        if (framework_->IsExiting())
            quit();
    }
}
<commit_msg>Enabling flash plugin if one exists.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "NaaliApplication.h"
#include "Framework.h"
#include "ConfigurationManager.h"

#include <QDir>
#include <QGraphicsView>
#include <QTranslator>
#include <QLocale>
#include <QIcon>
#include <QWebSettings>

#include "MemoryLeakCheck.h"

namespace Foundation
{
    NaaliApplication::NaaliApplication(Framework *framework, int &argc, char **argv) :
        QApplication(argc, argv),
        framework_(framework),
        app_activated_(true),
        native_translator_(new QTranslator),
        app_translator_(new QTranslator)//,
//        main_window_(new MainWindow(framework_))
    {
#ifdef Q_WS_WIN
        // If under windows, add run_dir/plugins as library path
        // unix users will get plugins from their OS Qt installation folder automatically
        QString run_directory = applicationDirPath();
        run_directory += "/qtplugins";
        addLibraryPath(run_directory);
#endif

        QDir dir("data/translations/qt_native_translations");
        QStringList qmFiles = GetQmFiles(dir);

        // Search then that is there corresponding native translations for system locals.
        QString loc = QLocale::system().name();
        loc.chop(3);

        QString name = "data/translations/qt_native_translations/qt_" + loc + ".qm";
        QStringList lst = qmFiles.filter(name);
        if (!lst.empty() )
            native_translator_->load(lst[0]);

        this->installTranslator(native_translator_);

        std::string default_language = framework_->GetConfigManager()->DeclareSetting(Framework::ConfigurationGroup(),
            "language", std::string("data/translations/naali_en"));
        ChangeLanguage(QString::fromStdString(default_language));

        QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true); //enablig flash
    }

    NaaliApplication::~NaaliApplication()
    {
//        view_.reset();
        SAFE_DELETE(native_translator_);
        SAFE_DELETE(app_translator_);
//        SAFE_DELETE(main_window_);
    }
/*
    QGraphicsView *NaaliApplication::GetUIView() const
    {
        return view_.get();
    }

    void NaaliApplication::SetUIView(std::auto_ptr <QGraphicsView> view)
    {
        view_ = view;
    }

    MainWindow *NaaliApplication::GetMainWindow() const
    {
        return main_window_;
    }
*/
    QStringList NaaliApplication::GetQmFiles(const QDir& dir)
    {
         QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
         QMutableStringListIterator i(fileNames);
         while (i.hasNext())
         {
             i.next();
             i.setValue(dir.filePath(i.value()));
         }
         return fileNames;
    }

    void NaaliApplication::Go()
    {
        installEventFilter(this);

        QObject::connect(&frame_update_timer_, SIGNAL(timeout()), this, SLOT(UpdateFrame()));
        frame_update_timer_.setSingleShot (true);
        frame_update_timer_.start (0);

        try
        {
            exec ();
        }
        catch(const std::exception &e)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            RootLogCritical(std::string("NaaliApplication::Go caught an unknown exception!"));
            throw;
        }
    }

    bool NaaliApplication::eventFilter(QObject *obj,  QEvent *event)
    {
        try
        {
            if (obj == this)
            {
                if (event->type() == QEvent::ApplicationActivate)
                    app_activated_ = true;
                if (event->type() == QEvent::ApplicationDeactivate)
                    app_activated_ = false;
                /*
                if (event->type() == QEvent::LanguageChange)
                {
                    // Now if exist remove our default translation engine.
                    if (translator_ != 0)
                        this->removeTranslator(translator_);
                }
                */
            }
            return QObject::eventFilter(obj, event);
        }
        catch(const std::exception &e)
        {
            std::cout << std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::eventFilter caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::eventFilter caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::ChangeLanguage(const QString& file)
    {
        QString filename = file;
        if (!filename.endsWith(".qm", Qt::CaseInsensitive))
            filename.append(".qm");
        QString tmp = filename;
        tmp.chop(3);
        QString str = tmp.right(2);

        QString name = "data/translations/qt_native_translations/qt_" + str + ".qm";

        // Remove old translators then change them to new.
        removeTranslator(native_translator_);

        if ( QFile::exists(name) )
        {
            if ( native_translator_ != 0)
            {
                native_translator_->load(name);
                installTranslator(native_translator_);
            }
        }
        else
        {
            if (native_translator_ != 0 && native_translator_->isEmpty())
            {
                installTranslator(native_translator_);
            }
            else
            {
                SAFE_DELETE(native_translator_);
                native_translator_ = new QTranslator;
                installTranslator(native_translator_);
            }
        }

        // Remove old translators then change them to new.
        removeTranslator(app_translator_);
        if (app_translator_->load(filename))
        {
            installTranslator(app_translator_);
            framework_->GetConfigManager()->SetSetting(Framework::ConfigurationGroup(), "language", file.toStdString());
        }

        emit LanguageChanged();
    }

    bool NaaliApplication::notify(QObject *receiver, QEvent *event)
    {
        try
        {
            return QApplication::notify(receiver, event);
        } catch(const std::exception &e)
        {
            std::cout << std::string("QApp::notify caught an exception: ") << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        } catch(...)
        {
            std::cout << std::string("QApp::notify caught an unknown exception!") << std::endl;
            RootLogCritical(std::string("QApp::notify caught an unknown exception!"));
            throw;
        }
        return true;
    }

    void NaaliApplication::UpdateFrame()
    {
        try
        {
            QApplication::processEvents (QEventLoop::AllEvents, 1);
            QApplication::sendPostedEvents ();

            framework_-> ProcessOneFrame();

            // Reduce framerate when unfocused
            if (app_activated_)
                frame_update_timer_.start(0);
            else
                frame_update_timer_.start(5);
        }
        catch(const std::exception &e)
        {
            std::cout << "QApp::UpdateFrame caught an exception: " << (e.what() ? e.what() : "(null)") << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an exception: ") + (e.what() ? e.what() : "(null)"));
            throw;
        }
        catch(...)
        {
            std::cout << "QApp::UpdateFrame caught an unknown exception!" << std::endl;
            RootLogCritical(std::string("QApp::UpdateFrame caught an unknown exception!"));
            throw;
        }
    }

    void NaaliApplication::AboutToExit()
    {
        emit ExitRequested();

        // If no-one canceled the exit as a response to the signal, exit
        if (framework_->IsExiting())
            quit();
    }
}
<|endoftext|>


<commit_before>#include "ImporterScene.h"

#include "App.h"
#include "M_FileSystem.h"
#include "JsonFile.h"

#include "M_ResourceManager.h"
#include "M_GoManager.h"
#include "GameObject.h"
#include "Transform.h"
#include "Mesh.h"
#include "Material.h"

#include "Resource.h"
#include "ResourceMesh.h"
#include "ResourceMaterial.h"
#include "ResourceTexture.h"
#include "ResourceScene.h"

#include <cimport.h>
#include <scene.h>
#include <postprocess.h>
#include <cfileio.h>

ImporterScene::ImporterScene()
{
	_LOG("Scene importer: Created.");

	struct aiLogStream stream;
	stream = aiGetPredefinedLogStream(aiDefaultLogStream_DEBUGGER, nullptr);
	aiAttachLogStream(&stream);
}

ImporterScene::~ImporterScene()
{
	aiDetachAllLogStreams();
}

bool ImporterScene::Import(const char * originalFile, std::string & exportedFile, const char * originalFileExt, UID & resUID)
{
	bool ret = false;

	if (!originalFile || !originalFileExt)
		return ret;
	//TODO: Paths??
	char* buffer = nullptr;
	uint size = app->fs->Load(originalFile, &buffer);

	if (size > 0 && buffer)
	{
		const aiScene* scene = aiImportFileFromMemory(buffer, size, aiProcessPreset_TargetRealtime_MaxQuality, originalFileExt);
		RELEASE_ARRAY(buffer);

		if (scene && scene->HasMeshes())
		{
			std::string path, file;
			app->fs->SplitPath(originalFile, &path, &file);

			meshesImported.clear();

			GameObject* go = app->goManager->CreateGameObject();
			go->SetName(file.c_str());

			RecImport(scene, scene->mRootNode, go, path, file);

			//TODO: bones

			//TODO: Animations

			aiReleaseImport(scene);

			JsonFile save;
			save.AddArray("game_objects");

			for (auto child : go->childs)
			{
				go->OnSaveGo(save);
			}

			resUID = app->resources->GetNewUID();

			exportedFile = (std::to_string(resUID) + PREFAB_EXTENSION);

			char* buff = nullptr;
			uint s = save.WriteJson(&buff, false); //TODO: Fast

			if (app->fs->Save((PREFABS_SAVE_PATH + exportedFile).c_str(), buff, s) == s)
				ret = true;

			RELEASE_ARRAY(buff);
			go->Destroy();
		}
	}
	else
	{
		_LOG("ERROR: Could not load scene: %s.", originalFile);
	}

	return ret;
}

void ImporterScene::RecImport(const aiScene * scene, const aiNode * node, GameObject * parent, const std::string & basePath, const std::string & file)
{
	static std::string name;
	name = (node->mName.length > 0) ? node->mName.C_Str() : "unnamed";

	aiVector3D translation;
	aiVector3D scaling;
	aiQuaternion rotation;
	node->mTransformation.Decompose(scaling, rotation, translation);

	float3 pos(translation.x, translation.y, translation.z);
	float3 scl(scaling.x, scaling.y, scaling.z);
	Quat rot(rotation.x, rotation.y, rotation.z, rotation.w);

	// Name analysis to handle FBX dummy nodes
	// check bottom of http://g3d.cs.williams.edu/g3d/G3D10/assimp.lib/code/FBXImportSettings.h
	static const char* dummies[5] = {
		"$AssimpFbx$_PreRotation", "$AssimpFbx$_Rotation", "$AssimpFbx$_PostRotation",
		"$AssimpFbx$_Scaling", "$AssimpFbx$_Translation" };

	for (int i = 0; i < 5; ++i)
	{
		if (name.find(dummies[i]) != std::string::npos && node->mNumChildren == 1)
		{
			node = node->mChildren[0];

			node->mTransformation.Decompose(scaling, rotation, translation);

			pos += float3(translation.x, translation.y, translation.z);
			scl += float3(scaling.x, scaling.y, scaling.z);
			rot = rot * Quat(rotation.x, rotation.y, rotation.z, rotation.w);

			name = node->mName.C_Str();
			i = -1;
		}
	}

	GameObject* go = parent->CreateChild();
	go->SetName(name.c_str());

	Transform* trans = go->transform;

	trans->SetLocalPosition(pos);
	trans->SetLocalScale(scl);
	trans->SetLocalRotation(rot);

	//TODO: Load metadata

	for (uint i = 0; i < node->mNumMeshes; ++i)
	{
		const aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];

		GameObject* childGo = nullptr;

		if (node->mNumMeshes > 1)
		{
			name = mesh->mName.C_Str();
			if (name.length() == 0)
			{
				name = node->mName.C_Str();
				name += "_submesh";
			}
			childGo = go->CreateChild();
			childGo->SetName(name.c_str());
		}
		else
		{
			childGo = go;
		}

		//TODO: Material
		if (scene->HasMaterials())
		{
			aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
			Material* cMat = (Material*)childGo->CreateComponent(CMP_MATERIAL);
			cMat->SetResource(app->resources->ImportBuf(mat, 0, RES_MATERIAL, (basePath).c_str()));
		}

		Mesh* cMesh = (Mesh*)childGo->CreateComponent(CMP_MESH);
		cMesh->SetResource(app->resources->ImportBuf(mesh, 0, RES_MESH, (basePath + file).c_str()));
		//TODO: Resource instances??
	}

	for (uint i = 0; i < node->mNumChildren; ++i)
		RecImport(scene, node->mChildren[i], go, basePath, file);

}

bool ImporterScene::LoadResource(Resource * resource)
{
	return false;
}<commit_msg>Not importing material<commit_after>#include "ImporterScene.h"

#include "App.h"
#include "M_FileSystem.h"
#include "JsonFile.h"

#include "M_ResourceManager.h"
#include "M_GoManager.h"
#include "GameObject.h"
#include "Transform.h"
#include "Mesh.h"
#include "Material.h"

#include "Resource.h"
#include "ResourceMesh.h"
#include "ResourceMaterial.h"
#include "ResourceTexture.h"
#include "ResourceScene.h"

#include <cimport.h>
#include <scene.h>
#include <postprocess.h>
#include <cfileio.h>

ImporterScene::ImporterScene()
{
	_LOG("Scene importer: Created.");

	struct aiLogStream stream;
	stream = aiGetPredefinedLogStream(aiDefaultLogStream_DEBUGGER, nullptr);
	aiAttachLogStream(&stream);
}

ImporterScene::~ImporterScene()
{
	aiDetachAllLogStreams();
}

bool ImporterScene::Import(const char * originalFile, std::string & exportedFile, const char * originalFileExt, UID & resUID)
{
	bool ret = false;

	if (!originalFile || !originalFileExt)
		return ret;
	//TODO: Paths??
	char* buffer = nullptr;
	uint size = app->fs->Load(originalFile, &buffer);

	if (size > 0 && buffer)
	{
		const aiScene* scene = aiImportFileFromMemory(buffer, size, aiProcessPreset_TargetRealtime_MaxQuality, originalFileExt);
		RELEASE_ARRAY(buffer);

		if (scene && scene->HasMeshes())
		{
			std::string path, file;
			app->fs->SplitPath(originalFile, &path, &file);

			meshesImported.clear();

			GameObject* go = app->goManager->CreateGameObject();
			go->SetName(file.c_str());

			RecImport(scene, scene->mRootNode, go, path, file);

			//TODO: bones

			//TODO: Animations

			aiReleaseImport(scene);

			JsonFile save;
			save.AddArray("game_objects");

			for (auto child : go->childs)
			{
				go->OnSaveGo(save);
			}

			resUID = app->resources->GetNewUID();

			exportedFile = (std::to_string(resUID) + PREFAB_EXTENSION);

			char* buff = nullptr;
			uint s = save.WriteJson(&buff, false); //TODO: Fast

			if (app->fs->Save((PREFABS_SAVE_PATH + exportedFile).c_str(), buff, s) == s)
				ret = true;

			RELEASE_ARRAY(buff);
			go->Destroy();
		}
	}
	else
	{
		_LOG("ERROR: Could not load scene: %s.", originalFile);
	}

	return ret;
}

void ImporterScene::RecImport(const aiScene * scene, const aiNode * node, GameObject * parent, const std::string & basePath, const std::string & file)
{
	static std::string name;
	name = (node->mName.length > 0) ? node->mName.C_Str() : "unnamed";

	aiVector3D translation;
	aiVector3D scaling;
	aiQuaternion rotation;
	node->mTransformation.Decompose(scaling, rotation, translation);

	float3 pos(translation.x, translation.y, translation.z);
	float3 scl(scaling.x, scaling.y, scaling.z);
	Quat rot(rotation.x, rotation.y, rotation.z, rotation.w);

	// Name analysis to handle FBX dummy nodes
	// check bottom of http://g3d.cs.williams.edu/g3d/G3D10/assimp.lib/code/FBXImportSettings.h
	static const char* dummies[5] = {
		"$AssimpFbx$_PreRotation", "$AssimpFbx$_Rotation", "$AssimpFbx$_PostRotation",
		"$AssimpFbx$_Scaling", "$AssimpFbx$_Translation" };

	for (int i = 0; i < 5; ++i)
	{
		if (name.find(dummies[i]) != std::string::npos && node->mNumChildren == 1)
		{
			node = node->mChildren[0];

			node->mTransformation.Decompose(scaling, rotation, translation);

			pos += float3(translation.x, translation.y, translation.z);
			scl += float3(scaling.x, scaling.y, scaling.z);
			rot = rot * Quat(rotation.x, rotation.y, rotation.z, rotation.w);

			name = node->mName.C_Str();
			i = -1;
		}
	}

	GameObject* go = parent->CreateChild();
	go->SetName(name.c_str());

	Transform* trans = go->transform;

	trans->SetLocalPosition(pos);
	trans->SetLocalScale(scl);
	trans->SetLocalRotation(rot);

	//TODO: Load metadata

	for (uint i = 0; i < node->mNumMeshes; ++i)
	{
		const aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];

		GameObject* childGo = nullptr;

		if (node->mNumMeshes > 1)
		{
			name = mesh->mName.C_Str();
			if (name.length() == 0)
			{
				name = node->mName.C_Str();
				name += "_submesh";
			}
			childGo = go->CreateChild();
			childGo->SetName(name.c_str());
		}
		else
		{
			childGo = go;
		}

		//TODO: Material
		if (scene->HasMaterials())
		{
			aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
			Material* cMat = (Material*)childGo->CreateComponent(CMP_MATERIAL);
			//cMat->SetResource(app->resources->ImportBuf(mat, 0, RES_MATERIAL, (basePath).c_str()));
		}

		Mesh* cMesh = (Mesh*)childGo->CreateComponent(CMP_MESH);
		cMesh->SetResource(app->resources->ImportBuf(mesh, 0, RES_MESH, (basePath + file).c_str()));
		//TODO: Resource instances??
	}

	for (uint i = 0; i < node->mNumChildren; ++i)
		RecImport(scene, node->mChildren[i], go, basePath, file);

}

bool ImporterScene::LoadResource(Resource * resource)
{
	return false;
}<|endoftext|>


<commit_before>
#include <QtCore>
#include "module_uid.h"
#include "form_uid.h"
#include <qextserialport.h>
#include <qextserialenumerator.h>

Module_UID::Module_UID(QString moduleId)
    :RobotModule(moduleId)
{

    portSettings = new PortSettings();
    portSettings->BaudRate = BAUD115200;
    portSettings->DataBits = DATA_8;
    portSettings->Parity = PAR_NONE;
    portSettings->StopBits = STOP_1;
    portSettings->FlowControl = FLOW_OFF;
#ifdef OS_UNIX // linux only supports timeouts in tenth of seconds and rounds down
    portSettings->Timeout_Millisec = 100;
#else
    portSettings->Timeout_Millisec = 100;
#endif

    setDefaultValue("uidId", "UIDC0001");

    lastError = 0;

    uid = NULL;
    reset();

}

Module_UID::~Module_UID()
{
    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;
    }
}

void Module_UID::reset()
{
    QMutexLocker l(&this->moduleMutex);

    RobotModule::reset();

    if (!getSettings().value("enabled").toBool())
        return;

    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;

    }
    uid = findUIDPort();
    data["revision"] = this->UID_Revision();
    data["identity"] = this->UID_Identify();
}

QList<RobotModule*> Module_UID::getDependencies()
{
    return QList<RobotModule*>();
}

QWidget* Module_UID::createView(QWidget* parent)
{
    return new FormUID(this, parent);
}

void Module_UID::terminate()
{
    RobotModule::terminate();
}

QextSerialPort* Module_UID::findUIDPort()
{
    QMutexLocker l(&this->moduleMutex);

    QString Id = settings.value("uidId").toString();

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    logger->info("Trying out all available serial ports");

    QextSerialPort *p = NULL;

    foreach (QextPortInfo port, ports) {
            logger->debug("port name: "+port.portName);
            logger->debug("friendly name: "+ port.friendName);
            logger->debug("physical name: "+ port.physName);
            logger->debug("enumerator name: "+ port.enumName);
            logger->debug("===================================");

            p = tryOpenPort(Id, &port);

            if (p != NULL)
                break;
    }

    if (!p) {
        setHealthToSick("Didn't find any UID.");
    } else {
        setHealthToOk();
    }

    return p;
}

QextSerialPort* Module_UID::tryOpenPort(QString Id, QextPortInfo *port)
{
    QMutexLocker l(&this->moduleMutex);

#ifdef OS_UNIX // this platform-independent library puts the port name in different fields depending on the platform
    QextSerialPort* sport = new QextSerialPort( port->physName, *portSettings, QextSerialPort::Polling);
#else
    QextSerialPort* sport = new QextSerialPort( port->portName, *portSettings, QextSerialPort::Polling);
#endif

    const char sequence[] = {Module_UID::UID_IDENTIFY};
    char id[9];

    /* Probing LPT in Virtualbox hangs the Application.
     * Probling bluetooth on certain IBM Laptops kills Windows.
     */
    if (port->portName.contains("LPT") || port->friendName.contains("Bluetooth")) {
        logger->info("Skipping port "+port->portName+" since probing it would be asking for trouble.");
        return NULL;
    }

    logger->debug("Using timeout of "+QString::number(portSettings->Timeout_Millisec)+" ms.");

    if ( !(sport->open(QIODevice::ReadWrite | QIODevice::Unbuffered) ) ) {
        logger->debug("Could not open: "+sport->errorString());
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("connected successfully");

    sport->flush();
    if (sport->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discard them.");
        sport->flush();
        sport->readAll(); // don't care for the data
    }

    if ( (sport->write(sequence, 1)) == -1) {
        logger->debug("Writing Opcode failed");
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Could write to port");
    size_t bytesRead = sport->read(id, sizeof(id));
    if ( bytesRead < sizeof(id)) {
        logger->debug("No Id received, read only "+QString::number(bytesRead)+ " bytes.");
        sport->close();
        delete sport;
        return NULL;
    }

    if (QString::fromAscii(id,sizeof(id)-1) != Id) {
        logger->debug("Received id: " + QString::fromUtf8(id,8)+"; expected: "+Id);
        logger->debug("Wrong Id\r\nReceived: " + QString::fromUtf8(id,8));
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Found UID with id " + QString::fromAscii(id,8) + " on " + port->portName);
    sport->flush();
    return sport;

}

bool Module_UID::SendCommand(const char* sequence, unsigned char length) {
    QByteArray a(sequence, length);
    return SendCommand2(a);
}

bool Module_UID::SendCheckCommand(const QByteArray &send, char* recv, int recv_length)
{
    QMutexLocker l(&this->moduleMutex);
    return SendCommand2(send,recv, recv_length) && CheckErrorcode();
}

bool Module_UID::CheckErrorcode()
{
    QMutexLocker l(&this->moduleMutex);
    logger->trace("CheckErrorcode");

    char r[1];
    r[0] = 0;
    QByteArray s;
    s += 0xFF;
    if (!SendCommand2(s,r,1)) {
        setHealthToSick("Didn't get an error code!");
        return false;
    }
    lastError = r[0];
    logger->trace("Got error code: "+QString::number(lastError));
    return lastError == 0;
}

bool Module_UID::SendCommand2(const QByteArray& send, char* recv, int recv_length) {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("SendCommand2");

    QTime start(QTime::currentTime());

    logger->trace("Sending: 0x"+QString::fromAscii(send.toHex()));

    if (!uid) {
        logger->error("Can't do. UID not open.");
        lastError = E_USB;
        return false;
    }

    uid->flush();
    if (uid->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discarding them.");
        uid->flush();
        uid->readAll(); // don't care for the data
    }

    int sendRet = uid->write(send);
    if (sendRet==-1) {
        uid->flush();
        setHealthToSick("Connection to UID died: "+uid->errorString());
        lastError = E_USB;
        return false;
    }

    if (sendRet<send.size()) {
        setHealthToSick("Could not write the whole buffer.");
        lastError = E_USB;
        return false;
    }
    uid->flush();

    // we expect a return
    if (recv_length>0) {
        int recvRet = uid->read(recv,recv_length);
        if (recvRet==-1) {
            setHealthToSick("Connection to UID died: "+uid->errorString());
            lastError = E_USB;
            return false;
        }

        if (recvRet<recv_length) {
            logger->error("Received less data from UID than expected: "+QString::number(recv_length-recvRet)+" bytes missing.");
            lastError = E_SHORT_READ;
            // this is an indication for an error. but wait for check command
            QTime stop(QTime::currentTime());
            logger->trace("delta t: "+QString::number(stop.msecsTo(start)));
            return true;
        }

        if (uid->bytesAvailable()>0) {
            setHealthToSick("found some orphaned bytes in the uid serial buffer after doing a command 0x"+QString::number(send[0],16));
            uid->flush();
            uid->readAll(); // don't care for the data
        }

    }

    QTime stop(QTime::currentTime());
    logger->trace("delta t: "+QString::number(stop.msecsTo(start)));

    lastError = E_NO_ERROR;
    return true;
}

QString Module_UID::UID_Revision() {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("UID_Revision");

    QString identify;
    char sequence[] = {Module_UID::UID_REVISION};
    char result[8];
    if ( !(SendCommand(sequence, 1)) ) return QString("");
    qint64 ret = uid->read(result,sizeof(result));
    if (ret<=0) return QString("error2");
    return QString::fromAscii(result, ret-1);
}

bool Module_UID::UID_Available()
{
    QMutexLocker l(&this->moduleMutex);
    return uid != NULL;
}

void Module_UID::doHealthCheck()
{
    QMutexLocker l(&this->moduleMutex);
    logger->trace("doHealthCheck");
    if (!getSettings().value("enabled").toBool())
        return;

    QString Id = settings.value("uidId").toString();

    if ( uid == NULL ) {
        setHealthToSick("No uid open.");
        return;
    }

    QString received = UID_Identify();
    if ( received.length()==0) {
        return;
    }
    if ( received.length()>0 && received != Id) {
        setHealthToSick("Wrong Id, received: " + received);
        return;
    }

    setHealthToOk();
}

bool Module_UID::I2C_Write(unsigned char address, const char* data, short byteCount) {
    logger->trace("I2C_Write");

    QByteArray send;
    send += Module_UID::I2C_WRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send);
}

bool Module_UID::I2C_Read(unsigned char address, short byteCount, char* result) {
    logger->trace("I2C_Read");

    QByteArray send;
    send += Module_UID::I2C_READ;
    send += address;
    send += byteCount;
    return SendCheckCommand(send,result,byteCount);
}

QString Module_UID::UID_Identify() {
    // deadlock if commented in
    //QMutexLocker l(&this->moduleMutex);

    logger->trace("UID_Identify");

    char result[9];
    result[9]=0;
    QByteArray send;
    send += Module_UID::UID_IDENTIFY;
    bool ret = SendCheckCommand(send,result,9);
    if (!ret) {
        setHealthToSick(getLastError());
        return "";
    }

    return QString::fromAscii(result);

}

bool Module_UID::I2C_WriteRegister(unsigned char address, unsigned char reg, const char* data, short byteCount) {

    logger->trace("I2C_WriteRegister");

    QByteArray send;
    send += Module_UID::I2C_WRITEREGISTER;
    send += address;
    send += reg;
    send += byteCount;
    send.append(data, byteCount);

    return SendCheckCommand(send);

}

bool Module_UID::I2C_ReadRegisters(unsigned char address, unsigned char reg, short byteCount, char* result) {
    logger->trace("I2C_ReadRegisters");

    QByteArray send;
    send += Module_UID::I2C_READREGISTER;
    send += address;
    send += reg;
    send += byteCount;

    return SendCheckCommand(send,result, byteCount);
}

QVector<unsigned char> Module_UID::I2C_Scan() {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("I2C_Scan");
    char sequence[] = {Module_UID::I2C_SCAN};
    QVector<unsigned char> slaves(0);
    if (!SendCommand(sequence, sizeof(sequence))) return slaves;
    char result[127];
    qint64 read = uid->read(result, 127);
    if (read != -1) {
        for (int i=0; i<read; i++) slaves.append(result[i]);
    }
    return slaves;
}

bool Module_UID::SPI_Speed(unsigned char speed) {
    QByteArray send;
    send += Module_UID::SPI_SPEED;
    send += speed;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_SetPHA(bool phase) {
    QByteArray send;
    send += Module_UID::SPI_SETPHA;
    send += phase;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_SetPOL(bool pol){
    QByteArray send;
    send += Module_UID::SPI_SETPOL;
    send += pol;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_Read(unsigned char address, short byteCount, char* result) {
    QByteArray send;
    send += Module_UID::SPI_READ;
    send += address;
    send += byteCount;
    return SendCheckCommand(send, result, byteCount);
}

bool Module_UID::SPI_Write(unsigned char address, const char* data, short byteCount) {
    QByteArray send;
    send += Module_UID::SPI_WRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send);
}

bool Module_UID::SPI_WriteRead(unsigned char address, const char* data, short byteCount, char* result) {
    QByteArray send;
    send += Module_UID::SPI_READWRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send, result, byteCount);
}

bool Module_UID::I2C_Speed(Module_UID::I2CSpeed speed) {
    QByteArray send;
    send += Module_UID::I2C_SPEED;
    send += speed;
    return SendCheckCommand(send);
}

unsigned char Module_UID::countBitsSet( unsigned char bitmask ) {
    unsigned char bits = 0;
    while (bitmask>0) {
        bits += (bitmask&1);
        bitmask = bitmask >> 1;
    }
    return bits;
}

QString Module_UID::getLastError()
{
    switch(lastError)
    {
    case E_NO_ERROR: return "No error";
    case E_I2C_LOW: return "I2C Bus is low.";
    case E_I2C_START: return "Could not send I2C START";
    case E_I2C_MT_SLA_ACK: return "Slave didn't respond to SLA+W";
    case E_I2C_MR_SLA_ACK: return "Slave didn't respond to SLA+R";
    case E_I2C_MT_DATA_ACK: return "Slave didn't ACK data of SLA+W";
    case E_I2C_MR_DATA_ACK: return "Slave didn't ACK data of SLA+R";
    case E_I2C_MR_DATA_NACK: return "Slave didn't NACK data of SLA+R";
    case E_SHORT_READ: return "Read less bytes than expected.";
    case E_EXTRA_READ: return "Read more bytes than expected.";
    case E_USB: return "Serial connection to UID broke down.";
    default: return QString("Unknown error: %1").arg(lastError);
    }
}

bool Module_UID::isSlaveProblem()
{
    switch (lastError) {
    case E_I2C_MT_SLA_ACK:
    case E_I2C_MR_SLA_ACK:
    case E_I2C_MT_DATA_ACK:
    case E_I2C_MR_DATA_ACK:
    case E_I2C_MR_DATA_NACK:
    case E_EXTRA_READ:
        return true;
    default:
        return false;
    }
}
<commit_msg>workaround<commit_after>
#include <QtCore>
#include "module_uid.h"
#include "form_uid.h"
#include <qextserialport.h>
#include <qextserialenumerator.h>

Module_UID::Module_UID(QString moduleId)
    :RobotModule(moduleId)
{

    portSettings = new PortSettings();
    portSettings->BaudRate = BAUD115200;
    portSettings->DataBits = DATA_8;
    portSettings->Parity = PAR_NONE;
    portSettings->StopBits = STOP_1;
    portSettings->FlowControl = FLOW_OFF;
#ifdef OS_UNIX // linux only supports timeouts in tenth of seconds and rounds down
    portSettings->Timeout_Millisec = 100;
#else
    portSettings->Timeout_Millisec = 100;
#endif

    setDefaultValue("uidId", "UIDC0001");

    lastError = 0;

    uid = NULL;
    reset();

}

Module_UID::~Module_UID()
{
    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;
    }
}

void Module_UID::reset()
{
    QMutexLocker l(&this->moduleMutex);

    RobotModule::reset();

    if (!getSettings().value("enabled").toBool())
        return;

    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;

    }
    uid = findUIDPort();
    data["revision"] = this->UID_Revision();
    data["identity"] = this->UID_Identify();
}

QList<RobotModule*> Module_UID::getDependencies()
{
    return QList<RobotModule*>();
}

QWidget* Module_UID::createView(QWidget* parent)
{
    return new FormUID(this, parent);
}

void Module_UID::terminate()
{
    RobotModule::terminate();
}

QextSerialPort* Module_UID::findUIDPort()
{
    QMutexLocker l(&this->moduleMutex);

    QString Id = settings.value("uidId").toString();

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    logger->info("Trying out all available serial ports");

    QextSerialPort *p = NULL;

    foreach (QextPortInfo port, ports) {
            logger->debug("port name: "+port.portName);
            logger->debug("friendly name: "+ port.friendName);
            logger->debug("physical name: "+ port.physName);
            logger->debug("enumerator name: "+ port.enumName);
            logger->debug("===================================");

            p = tryOpenPort(Id, &port);

            if (p != NULL)
                break;
    }

    if (!p) {
        setHealthToSick("Didn't find any UID.");
    } else {
        setHealthToOk();
    }

    return p;
}

QextSerialPort* Module_UID::tryOpenPort(QString Id, QextPortInfo *port)
{
    QMutexLocker l(&this->moduleMutex);

#ifdef OS_UNIX // this platform-independent library puts the port name in different fields depending on the platform
    QextSerialPort* sport = new QextSerialPort( port->physName, *portSettings, QextSerialPort::Polling);
#else
    QextSerialPort* sport = new QextSerialPort( port->portName, *portSettings, QextSerialPort::Polling);
#endif

    const char sequence[] = {Module_UID::UID_IDENTIFY};
    char id[9];

    /* Probing LPT in Virtualbox hangs the Application.
     * Probling bluetooth on certain IBM Laptops kills Windows.
     */
    if (port->portName.contains("LPT") || port->friendName.contains("Bluetooth")) {
        logger->info("Skipping port "+port->portName+" since probing it would be asking for trouble.");
        return NULL;
    }

    logger->debug("Using timeout of "+QString::number(portSettings->Timeout_Millisec)+" ms.");

    if ( !(sport->open(QIODevice::ReadWrite | QIODevice::Unbuffered) ) ) {
        logger->debug("Could not open: "+sport->errorString());
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("connected successfully");

    sport->flush();
    if (sport->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discard them.");
        sport->flush();
        sport->readAll(); // don't care for the data
    }

    if ( (sport->write(sequence, 1)) == -1) {
        logger->debug("Writing Opcode failed");
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Could write to port");
    size_t bytesRead = sport->read(id, sizeof(id));
    if ( bytesRead < sizeof(id)) {
        logger->debug("No Id received, read only "+QString::number(bytesRead)+ " bytes.");
        sport->close();
        delete sport;
        return NULL;
    }

    if (QString::fromAscii(id,sizeof(id)-1) != Id) {
        logger->debug("Received id: " + QString::fromUtf8(id,8)+"; expected: "+Id);
        logger->debug("Wrong Id\r\nReceived: " + QString::fromUtf8(id,8));
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Found UID with id " + QString::fromAscii(id,8) + " on " + port->portName);
    sport->flush();
    return sport;

}

bool Module_UID::SendCommand(const char* sequence, unsigned char length) {
    QByteArray a(sequence, length);
    return SendCommand2(a);
}

bool Module_UID::SendCheckCommand(const QByteArray &send, char* recv, int recv_length)
{
    QMutexLocker l(&this->moduleMutex);
    return SendCommand2(send,recv, recv_length) && CheckErrorcode();
}

bool Module_UID::CheckErrorcode()
{
    QMutexLocker l(&this->moduleMutex);
    logger->trace("CheckErrorcode");

    char r[1];
    r[0] = 0;
    QByteArray s;
    s += 0xFF;
    if (!SendCommand2(s,r,1)) {
        setHealthToSick("Didn't get an error code!");
        return false;
    }
    lastError = r[0];
    logger->trace("Got error code: "+QString::number(lastError));
    return lastError == 0;
}

bool Module_UID::SendCommand2(const QByteArray& send, char* recv, int recv_length) {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("SendCommand2");

    QTime start(QTime::currentTime());

    logger->trace("Sending: 0x"+QString::fromAscii(send.toHex()));

    if (!uid) {
        logger->error("Can't do. UID not open.");
        lastError = E_USB;
        return false;
    }

    uid->flush();
    if (uid->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discarding them.");
        uid->flush();
        uid->readAll(); // don't care for the data
    }

    int sendRet = uid->write(send);
    if (sendRet==-1) {
        uid->flush();
        setHealthToSick("Connection to UID died: "+uid->errorString());
        lastError = E_USB;
        return false;
    }

    if (sendRet<send.size()) {
        setHealthToSick("Could not write the whole buffer.");
        lastError = E_USB;
        return false;
    }
    uid->flush();

    // we expect a return
    if (recv_length>0) {
        int recvRet = uid->read(recv,recv_length);
        if (recvRet==-1) {
            setHealthToSick("Connection to UID died: "+uid->errorString());
            lastError = E_USB;
            return false;
        }

        if (recvRet<recv_length) {
            logger->error("Received less data from UID than expected: "+QString::number(recv_length-recvRet)+" bytes missing.");
            lastError = E_SHORT_READ;
            // this is an indication for an error. but wait for check command
            QTime stop(QTime::currentTime());
            logger->trace("delta t: "+QString::number(stop.msecsTo(start)));
            return true;
        }

        if (uid->bytesAvailable()>0) {
            setHealthToSick("found some orphaned bytes in the uid serial buffer after doing a command 0x"+QString::number(send[0],16));
            uid->flush();
            uid->readAll(); // don't care for the data
        }

    }

    QTime stop(QTime::currentTime());
    logger->trace("delta t: "+QString::number(stop.msecsTo(start)));

    lastError = E_NO_ERROR;
    return true;
}

QString Module_UID::UID_Revision() {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("UID_Revision");

    QString identify;
    char sequence[] = {Module_UID::UID_REVISION};
    char result[8];
    if ( !(SendCommand(sequence, 1)) ) return QString("");
    qint64 ret = uid->read(result,sizeof(result));
    if (ret<=0) return QString("error2");
    return QString::fromAscii(result, ret-1);
}

bool Module_UID::UID_Available()
{
    QMutexLocker l(&this->moduleMutex);
    return uid != NULL;
}

void Module_UID::doHealthCheck()
{
    QMutexLocker l(&this->moduleMutex);
    logger->trace("doHealthCheck");
    if (!getSettings().value("enabled").toBool())
        return;

    QString Id = settings.value("uidId").toString();

    if ( uid == NULL ) {
        setHealthToSick("No uid open.");
        return;
    }

    QString received = UID_Identify();
    if ( received.length()==0) {
        return;
    }
    if ( received.length()>0 && received != Id) {
        setHealthToSick("Wrong Id, received: " + received);
        return;
    }

    setHealthToOk();
}

bool Module_UID::I2C_Write(unsigned char address, const char* data, short byteCount) {
    logger->trace("I2C_Write");

    QByteArray send;
    send += Module_UID::I2C_WRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send);
}

bool Module_UID::I2C_Read(unsigned char address, short byteCount, char* result) {
    logger->trace("I2C_Read");

    QByteArray send;
    send += Module_UID::I2C_READ;
    send += address;
    send += byteCount;
    return SendCheckCommand(send,result,byteCount);
}

QString Module_UID::UID_Identify() {
    // deadlock if commented in
    //QMutexLocker l(&this->moduleMutex);
    moduleMutex.lock();

    logger->trace("UID_Identify");

    char result[9];
    result[9]=0;
    QByteArray send;
    send += Module_UID::UID_IDENTIFY;
    bool ret = SendCheckCommand(send,result,9);
    if (!ret) {
        setHealthToSick(getLastError());
        moduleMutex.unlock();
        return "";
    }

    moduleMutex.unlock();
    return QString::fromAscii(result);

}

bool Module_UID::I2C_WriteRegister(unsigned char address, unsigned char reg, const char* data, short byteCount) {

    logger->trace("I2C_WriteRegister");

    QByteArray send;
    send += Module_UID::I2C_WRITEREGISTER;
    send += address;
    send += reg;
    send += byteCount;
    send.append(data, byteCount);

    return SendCheckCommand(send);

}

bool Module_UID::I2C_ReadRegisters(unsigned char address, unsigned char reg, short byteCount, char* result) {
    logger->trace("I2C_ReadRegisters");

    QByteArray send;
    send += Module_UID::I2C_READREGISTER;
    send += address;
    send += reg;
    send += byteCount;

    return SendCheckCommand(send,result, byteCount);
}

QVector<unsigned char> Module_UID::I2C_Scan() {
    QMutexLocker l(&this->moduleMutex);
    logger->trace("I2C_Scan");
    char sequence[] = {Module_UID::I2C_SCAN};
    QVector<unsigned char> slaves(0);
    if (!SendCommand(sequence, sizeof(sequence))) return slaves;
    char result[127];
    qint64 read = uid->read(result, 127);
    if (read != -1) {
        for (int i=0; i<read; i++) slaves.append(result[i]);
    }
    return slaves;
}

bool Module_UID::SPI_Speed(unsigned char speed) {
    QByteArray send;
    send += Module_UID::SPI_SPEED;
    send += speed;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_SetPHA(bool phase) {
    QByteArray send;
    send += Module_UID::SPI_SETPHA;
    send += phase;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_SetPOL(bool pol){
    QByteArray send;
    send += Module_UID::SPI_SETPOL;
    send += pol;
    return SendCheckCommand(send);
}

bool Module_UID::SPI_Read(unsigned char address, short byteCount, char* result) {
    QByteArray send;
    send += Module_UID::SPI_READ;
    send += address;
    send += byteCount;
    return SendCheckCommand(send, result, byteCount);
}

bool Module_UID::SPI_Write(unsigned char address, const char* data, short byteCount) {
    QByteArray send;
    send += Module_UID::SPI_WRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send);
}

bool Module_UID::SPI_WriteRead(unsigned char address, const char* data, short byteCount, char* result) {
    QByteArray send;
    send += Module_UID::SPI_READWRITE;
    send += address;
    send += byteCount;
    send.append(data, byteCount);
    return SendCheckCommand(send, result, byteCount);
}

bool Module_UID::I2C_Speed(Module_UID::I2CSpeed speed) {
    QByteArray send;
    send += Module_UID::I2C_SPEED;
    send += speed;
    return SendCheckCommand(send);
}

unsigned char Module_UID::countBitsSet( unsigned char bitmask ) {
    unsigned char bits = 0;
    while (bitmask>0) {
        bits += (bitmask&1);
        bitmask = bitmask >> 1;
    }
    return bits;
}

QString Module_UID::getLastError()
{
    switch(lastError)
    {
    case E_NO_ERROR: return "No error";
    case E_I2C_LOW: return "I2C Bus is low.";
    case E_I2C_START: return "Could not send I2C START";
    case E_I2C_MT_SLA_ACK: return "Slave didn't respond to SLA+W";
    case E_I2C_MR_SLA_ACK: return "Slave didn't respond to SLA+R";
    case E_I2C_MT_DATA_ACK: return "Slave didn't ACK data of SLA+W";
    case E_I2C_MR_DATA_ACK: return "Slave didn't ACK data of SLA+R";
    case E_I2C_MR_DATA_NACK: return "Slave didn't NACK data of SLA+R";
    case E_SHORT_READ: return "Read less bytes than expected.";
    case E_EXTRA_READ: return "Read more bytes than expected.";
    case E_USB: return "Serial connection to UID broke down.";
    default: return QString("Unknown error: %1").arg(lastError);
    }
}

bool Module_UID::isSlaveProblem()
{
    switch (lastError) {
    case E_I2C_MT_SLA_ACK:
    case E_I2C_MR_SLA_ACK:
    case E_I2C_MT_DATA_ACK:
    case E_I2C_MR_DATA_ACK:
    case E_I2C_MR_DATA_NACK:
    case E_EXTRA_READ:
        return true;
    default:
        return false;
    }
}
<|endoftext|>


<commit_before>//
// Copyright (C) 2013-2016 University of Amsterdam
//
// 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 "tabbar.h"
#include <QMessageBox>
#include "aboutdialog.h"
#include "widgets/ribbonbutton.h"

TabBar::TabBar(QWidget *parent) :
	QWidget(parent)
{
	_optionsTab = NULL;
	_helpTab = NULL;

	_background = new QWidget(this);
	_background->setObjectName("background");

	_backgroundLayout = new QGridLayout(this);
	_backgroundLayout->setMargin(0);
	_backgroundLayout->addWidget(_background);

	_layout = new QHBoxLayout(_background);
	_layout->setMargin(0);
	_background->setLayout(_layout);

	setLayout(_backgroundLayout);

	_layout->addStretch(1);
}

void TabBar::addTab(QString tabName)
{
	foreach (QPushButton *button, _tabButtons)
	{
		if (button->objectName() == tabName)
			return;
	}

	QPushButton *button = new QPushButton(tabName, this);
	button->setStyleSheet("border-top-left-radius:0px;border-top-right-radius:0px;");
	button->setObjectName(tabName);
	button->setCheckable(true);
	connect(button, SIGNAL(clicked()), this, SLOT(tabSelectedHandler()));

	if (_tabButtons.size() == 0)
		button->setObjectName("first");

	_layout->insertWidget(_tabButtons.size(), button);
	_tabButtons.append(button);
}

void TabBar::removeTab(int index)
{
	QPushButton *button = _tabButtons.at(index);
	_tabButtons.removeAt(index);
	delete button;
}

void TabBar::removeTab(QString tabName)
{
	foreach (QPushButton *button, _tabButtons)
	{
		if (button->objectName() == tabName)
		{
			_tabButtons.removeAll(button);
			delete button;

			return;
		}
	}
}

void TabBar::addOptionsTab()
{
	_optionsTab = new QPushButton("", this);

	_layout->addWidget(_optionsTab);

}

void TabBar::addHelpTab()
{

	RibbonButton *rb = new RibbonButton();
	rb->setIcon(QIcon(":/icons/summarize.svg"));
	rb->setPopupMode(QToolButton::InstantPopup);
	rb->setProperty("button-type", "summarize");
	rb->setMinimumSize(30,0);
	_layout->setContentsMargins(0,0,2,0);

	QMenu  *helpmenu   = new QMenu(this);

	QAction *act_about = new QAction("About",helpmenu);
	QAction *act_extrahelp = new QAction("Help",helpmenu);

	// About
	act_about->setObjectName("About");
	helpmenu->addAction(act_about);
	helpmenu->addSeparator();
	//helpmenu->setLayoutDirection(Qt::RightToLeft);

	//Special Help
	act_extrahelp->setObjectName("Special Help");
	act_extrahelp->setCheckable(true);
	act_extrahelp->setChecked(false);
	helpmenu->addAction(act_extrahelp);
	helpmenu->addSeparator();

	//Options
	QMenu *optionmenu   = new QMenu("Modules",this);
	QAction *sem = new QAction("SEM ToolBox",optionmenu);
	QAction *rei = new QAction("Reinforcement Learning Toolbox",optionmenu);
	QAction *summaryStats = new QAction("Summary Statistics Toolbox",optionmenu);

	//SEM
	QVariant sem_setting = _settings.value("plugins/sem", false);
	sem->setObjectName("SEM Toolbox");
	sem->setCheckable(true);
	sem->setChecked(sem_setting.canConvert(QVariant::Bool) && sem_setting.toBool());
	optionmenu->addAction(sem);

	//Reinforcement
	QVariant ri_setting = _settings.value("toolboxes/r11tLearn", false);
	rei->setObjectName("Reinforcement Learning Toolbox");
	rei->setCheckable(true);
	rei->setChecked(ri_setting.canConvert(QVariant::Bool) && ri_setting.toBool());

	//Summary Stats
	QVariant sumStats_setting = _settings.value("toolboxes/summaryStatistics", false);
	summaryStats->setObjectName("Summary Statistics Toolbox");
	summaryStats->setCheckable(true);
	summaryStats->setChecked(sumStats_setting.canConvert(QVariant::Bool) && sumStats_setting.toBool());

#ifdef QT_DEBUG
	optionmenu->addAction(rei);
	optionmenu->addAction(summaryStats);
#endif

	optionmenu->acceptDrops();
	helpmenu->acceptDrops();
	helpmenu->addMenu(optionmenu);

	rb->setMenu(helpmenu);
	_layout->addWidget(rb);

	//Slots helpmenu
	connect(act_about, SIGNAL(triggered()), this, SLOT(showAbout()));
	connect(act_extrahelp, SIGNAL(triggered()), this, SLOT(toggleHelp()));

	// Slots options
	connect(sem, SIGNAL(triggered()), this, SLOT(toggleSEM()));
	connect(rei, SIGNAL(triggered()), this, SLOT(toggleReinforcement()));
	connect(summaryStats, SIGNAL(triggered()), this, SLOT(toggleSummaryStats()));
}

void TabBar::showAbout()
{
	AboutDialog aboutdialog;
	aboutdialog.setModal(true);
	aboutdialog.exec();
}

void TabBar::toggleHelp()
{
	static bool on;
	on = ! on;
	helpToggledHandler(on);
}

void TabBar::toggleSEM()
{
	QVariant sem_setting = _settings.value("plugins/sem", false);
	static bool on = (sem_setting.canConvert(QVariant::Bool) && sem_setting.toBool());
	on = ! on;
	if (on)
		this->addTab("SEM");
	else
		this->removeTab("SEM");
}

void TabBar::toggleReinforcement()
{
	QVariant ri_setting = _settings.value("toolboxes/r11tLearn", false);
	static bool on = (ri_setting.canConvert(QVariant::Bool) && ri_setting.toBool());
	on = ! on;
	if (on)
		this->addTab("R11t Learn");
	else
		this->removeTab("R11t Learn");
}

void TabBar::toggleSummaryStats()
{
	QVariant sumStats_setting = _settings.value("toolboxes/summaryStatistics", false);
	static bool on = (sumStats_setting.canConvert(QVariant::Bool) && sumStats_setting.toBool());
	on = ! on;
	if (on)
		this->addTab("Summary Statistics");
	else
		this->removeTab("Summary Statistics");
}

int TabBar::count() const
{
	return _tabButtons.length() + (_optionsTab != NULL ? 1 : 0);
}

void TabBar::setCurrentIndex(int index)
{
	int i = 0;

	foreach (QPushButton *button, _tabButtons)
	{
		button->setChecked(i == index);
		i++;
	}

	if (_optionsTab != NULL)
		_optionsTab->setChecked(i == index);

	emit currentChanged(index);
}

void TabBar::tabSelectedHandler()
{
	QObject *source = this->sender();
	int i = 0;

	foreach (QPushButton *button, _tabButtons)
	{
		if (source == button)
		{
			_currentActiveTab = button->objectName();
			setCurrentIndex(i);
			return;
		}
		i++;
	}

	if (source == _optionsTab)
		setCurrentIndex(i);
}

QString TabBar::getCurrentActiveTab()
{
	return _currentActiveTab;
}

void TabBar::helpToggledHandler(bool on)
{
	emit helpToggled(on);
}
<commit_msg>Add Summary Statistics to Release version<commit_after>//
// Copyright (C) 2013-2016 University of Amsterdam
//
// 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 "tabbar.h"
#include <QMessageBox>
#include "aboutdialog.h"
#include "widgets/ribbonbutton.h"

TabBar::TabBar(QWidget *parent) :
	QWidget(parent)
{
	_optionsTab = NULL;
	_helpTab = NULL;

	_background = new QWidget(this);
	_background->setObjectName("background");

	_backgroundLayout = new QGridLayout(this);
	_backgroundLayout->setMargin(0);
	_backgroundLayout->addWidget(_background);

	_layout = new QHBoxLayout(_background);
	_layout->setMargin(0);
	_background->setLayout(_layout);

	setLayout(_backgroundLayout);

	_layout->addStretch(1);
}

void TabBar::addTab(QString tabName)
{
	foreach (QPushButton *button, _tabButtons)
	{
		if (button->objectName() == tabName)
			return;
	}

	QPushButton *button = new QPushButton(tabName, this);
	button->setStyleSheet("border-top-left-radius:0px;border-top-right-radius:0px;");
	button->setObjectName(tabName);
	button->setCheckable(true);
	connect(button, SIGNAL(clicked()), this, SLOT(tabSelectedHandler()));

	if (_tabButtons.size() == 0)
		button->setObjectName("first");

	_layout->insertWidget(_tabButtons.size(), button);
	_tabButtons.append(button);
    button->clicked();
}

void TabBar::removeTab(int index)
{
	QPushButton *button = _tabButtons.at(index);
	_tabButtons.removeAt(index);
	delete button;
}

void TabBar::removeTab(QString tabName)
{
    QPushButton *lastbutton;
	foreach (QPushButton *button, _tabButtons)
	{
		if (button->objectName() == tabName)
		{
			_tabButtons.removeAll(button);
			delete button;
            if (lastbutton) lastbutton->clicked();

			return;
		}
        lastbutton = button;
	}
}

void TabBar::addOptionsTab()
{
	_optionsTab = new QPushButton("", this);

	_layout->addWidget(_optionsTab);

}

void TabBar::addHelpTab()
{

	RibbonButton *rb = new RibbonButton();
	rb->setIcon(QIcon(":/icons/summarize.svg"));
	rb->setPopupMode(QToolButton::InstantPopup);
	rb->setProperty("button-type", "summarize");
	rb->setMinimumSize(30,0);
	_layout->setContentsMargins(0,0,2,0);

	QMenu  *helpmenu   = new QMenu(this);

	QAction *act_about = new QAction("About",helpmenu);
	QAction *act_extrahelp = new QAction("Help",helpmenu);

	// About
	act_about->setObjectName("About");
	helpmenu->addAction(act_about);
	helpmenu->addSeparator();
	//helpmenu->setLayoutDirection(Qt::RightToLeft);

	//Special Help
	act_extrahelp->setObjectName("Special Help");
	act_extrahelp->setCheckable(true);
	act_extrahelp->setChecked(false);
	helpmenu->addAction(act_extrahelp);
	helpmenu->addSeparator();

	//Options
	QMenu *optionmenu   = new QMenu("Modules",this);
	QAction *sem = new QAction("SEM ToolBox",optionmenu);
	QAction *rei = new QAction("Reinforcement Learning Toolbox",optionmenu);
	QAction *summaryStats = new QAction("Summary Statistics Toolbox",optionmenu);

	//SEM
	QVariant sem_setting = _settings.value("plugins/sem", false);
	sem->setObjectName("SEM Toolbox");
	sem->setCheckable(true);
	sem->setChecked(sem_setting.canConvert(QVariant::Bool) && sem_setting.toBool());
	optionmenu->addAction(sem);

	//Reinforcement
	QVariant ri_setting = _settings.value("toolboxes/r11tLearn", false);
	rei->setObjectName("Reinforcement Learning Toolbox");
	rei->setCheckable(true);
	rei->setChecked(ri_setting.canConvert(QVariant::Bool) && ri_setting.toBool());

	//Summary Stats
	QVariant sumStats_setting = _settings.value("toolboxes/summaryStatistics", false);
	summaryStats->setObjectName("Summary Statistics Toolbox");
	summaryStats->setCheckable(true);
	summaryStats->setChecked(sumStats_setting.canConvert(QVariant::Bool) && sumStats_setting.toBool());

#ifdef QT_DEBUG
	optionmenu->addAction(rei);
#endif
    optionmenu->addAction(summaryStats);

	optionmenu->acceptDrops();
	helpmenu->acceptDrops();
	helpmenu->addMenu(optionmenu);

	rb->setMenu(helpmenu);
	_layout->addWidget(rb);

	//Slots helpmenu
	connect(act_about, SIGNAL(triggered()), this, SLOT(showAbout()));
	connect(act_extrahelp, SIGNAL(triggered()), this, SLOT(toggleHelp()));

	// Slots options
	connect(sem, SIGNAL(triggered()), this, SLOT(toggleSEM()));
	connect(rei, SIGNAL(triggered()), this, SLOT(toggleReinforcement()));
	connect(summaryStats, SIGNAL(triggered()), this, SLOT(toggleSummaryStats()));
}

void TabBar::showAbout()
{
	AboutDialog aboutdialog;
	aboutdialog.setModal(true);
	aboutdialog.exec();
}

void TabBar::toggleHelp()
{
	static bool on;
	on = ! on;
	helpToggledHandler(on);
}

void TabBar::toggleSEM()
{
	QVariant sem_setting = _settings.value("plugins/sem", false);
	static bool on = (sem_setting.canConvert(QVariant::Bool) && sem_setting.toBool());
	on = ! on;
	if (on)
		this->addTab("SEM");
	else
		this->removeTab("SEM");
}

void TabBar::toggleReinforcement()
{
	QVariant ri_setting = _settings.value("toolboxes/r11tLearn", false);
	static bool on = (ri_setting.canConvert(QVariant::Bool) && ri_setting.toBool());
	on = ! on;
	if (on)
		this->addTab("R11t Learn");
	else
		this->removeTab("R11t Learn");
}

void TabBar::toggleSummaryStats()
{
	QVariant sumStats_setting = _settings.value("toolboxes/summaryStatistics", false);
	static bool on = (sumStats_setting.canConvert(QVariant::Bool) && sumStats_setting.toBool());
	on = ! on;
    if (on)
    {
		this->addTab("Summary Statistics");
    }
	else
    {
		this->removeTab("Summary Statistics");
    }
}

int TabBar::count() const
{
	return _tabButtons.length() + (_optionsTab != NULL ? 1 : 0);
}

void TabBar::setCurrentIndex(int index)
{
	int i = 0;

	foreach (QPushButton *button, _tabButtons)
	{
		button->setChecked(i == index);
		i++;
	}

	if (_optionsTab != NULL)
		_optionsTab->setChecked(i == index);

	emit currentChanged(index);
}

void TabBar::tabSelectedHandler()
{
	QObject *source = this->sender();
	int i = 0;

	foreach (QPushButton *button, _tabButtons)
	{
		if (source == button)
		{
			_currentActiveTab = button->objectName();
			setCurrentIndex(i);
			return;
		}
		i++;
	}

	if (source == _optionsTab)
		setCurrentIndex(i);
}

QString TabBar::getCurrentActiveTab()
{
	return _currentActiveTab;
}

void TabBar::helpToggledHandler(bool on)
{
	emit helpToggled(on);
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ruben Van Boxem
 *
 * 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 "test.h++"

#include "core/signal.h++"

namespace
{
  using skui::core::signal;

  void test_basic_operations()
  {
    // TODO test copy/move assignment operators
  }

  void test_simple_signal()
  {
    bool slot_called = false;
    auto slot = [&slot_called]() { slot_called = true; };

    signal<> simple_signal;
    simple_signal.connect(slot);

    simple_signal.emit();

    skui::test::assert(slot_called, "Simple slot not called through emit.");
  }

  void test_signal_with_argument()
  {
    bool slot_called = false;
    auto slot = [&slot_called](bool called) { slot_called = called; };

    signal<bool> signal_with_argument;
    signal_with_argument.connect(slot);

    signal_with_argument.emit(true);

    skui::test::assert(slot_called, "Argument not passed through signal.");
  }

  void test_signal_disconnect()
  {
    bool slot_called = false;
    bool other_slot_called = false;
    auto slot = [&slot_called]() { slot_called = true; };
    auto other_slot = [&other_slot_called]() { other_slot_called = true; };

    signal<> signal;
    signal.connect(slot);
    signal.connect(other_slot);
    signal.disconnect(slot);

    signal.emit();

    skui::test::assert(!slot_called, "Slot not disconnected.");
    skui::test::assert(other_slot_called, "Other slot still connected.");

    signal.disconnect_all();

    other_slot_called = false;
    signal.emit();

    skui::test::assert(!other_slot_called, "Disconnect all failed.");
  }
}

int main()
{
  test_basic_operations();
  test_simple_signal();
  test_signal_with_argument();
  test_signal_disconnect();
}
<commit_msg>Add move/copy tests for signal.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Ruben Van Boxem
 *
 * 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 "test.h++"

#include "core/signal.h++"

namespace
{
  using skui::test::assert;

  void test_signal_connect_emit()
  {
    bool slot_called = false;
    auto slot = [&slot_called]() { slot_called = true; };

    skui::core::signal<> signal;
    signal.connect(slot);

    signal.emit();

    assert(slot_called, "Simple slot called through emit.");
  }

  void test_basic_operations()
  {
    bool slot_called = false;
    auto slot = [&slot_called]() { slot_called = true; };
    skui::core::signal<> signal_one;
    skui::core::signal<> signal_two;

    signal_one.connect(slot);

    signal_two = signal_one; // copy

    signal_one.emit();
    assert(slot_called, "copied-from signal still connected");
    slot_called = false;
    signal_two.emit();
    assert(slot_called, "copied to signal connected");

    signal_two = std::move(signal_one);

    slot_called = false;
    signal_one.emit();

    assert(!slot_called, "moved-from signal still connected");

    signal_two.emit();

    assert(slot_called, "moved-to signal connected correclty");
  }

  void test_signal_with_argument()
  {
    bool slot_called = false;
    auto slot = [&slot_called](bool called) { slot_called = called; };

    skui::core::signal<bool> signal;
    signal.connect(slot);

    signal.emit(true);

    assert(slot_called, "Argument not passed through signal.");
  }

  void test_signal_disconnect()
  {
    bool slot_called = false;
    bool other_slot_called = false;
    auto slot = [&slot_called]() { slot_called = true; };
    auto other_slot = [&other_slot_called]() { other_slot_called = true; };

    skui::core::signal<> signal;
    signal.connect(slot);
    signal.connect(other_slot);
    signal.disconnect(slot);

    signal.emit();

    skui::test::assert(!slot_called, "Slot disconnected.");
    skui::test::assert(other_slot_called, "Other slot still connected.");

    signal.disconnect_all();

    other_slot_called = false;
    signal.emit();

    skui::test::assert(!other_slot_called, "Disconnect all slots.");
  }
}

int main()
{
  test_signal_connect_emit();
  test_basic_operations();
  test_signal_with_argument();
  test_signal_disconnect();
}
<|endoftext|>


<commit_before>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Mirko Boehm <mirko@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qlayout.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qlistview.h>
#include <qdragobject.h>

#include <kdialog.h>
#include <klocale.h>
#include <kabc/distributionlist.h>
#include <kabc/distributionlisteditor.h>
#include <klineeditdlg.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "addresseeutil.h"
#include "featuredistributionlist.h"
#include "featuredistributionlistview.h"

namespace KABC
{

// MOSTLY A COPY FROM kdelibs/kabc:
class EntryItem : public QListViewItem
{
  protected:
    FeatureDistributionList *list;

  public:
    EntryItem( FeatureDistributionList *l, QListView *parent,
               const Addressee &addressee, const QString &email = QString::null )
      : QListViewItem( parent ), list( l ), mAddressee( addressee ), mEmail( email )
    {
      setDropEnabled( true );
      setText( 0, addressee.realName() );
      if ( email.isEmpty() ) {
        setText( 1, addressee.preferredEmail() );
        setText( 2, i18n( "Yes" ) );
      } else {
        setText( 1, email );
        setText( 2, i18n( "No" ) );
      }
    }

    Addressee addressee() const
    {
      return mAddressee;
    }

    QString email() const
    {
      return mEmail;
    }

  protected:
    bool acceptDrop( const QMimeSource* )
    {
      // WORK_TO_DO: check data type
      return true;
    }

    void dropped( QDropEvent *e )
    {
      list->slotDropped( e );
    }

  private:
    Addressee mAddressee;
    QString mEmail;
};

}

FeatureDistributionList::FeatureDistributionList( KABC::AddressBook *doc,
                                            QWidget *parent, const char* name )
  : QWidget( parent, name ),
    mDoc( doc ),
    mManager( new KABC::DistributionListManager( doc ) )
{
  initGUI();

  connect( mLvAddressees, SIGNAL(selectionChanged()),
           SLOT(slotAddresseeSelectionChanged()));
  connect( mLvAddressees, SIGNAL(dropped(QDropEvent*)),
           SLOT(slotDropped(QDropEvent*)));

  mLvAddressees->addColumn( i18n( "Name" ) );
  mLvAddressees->addColumn( i18n( "Email" ) );
  mLvAddressees->addColumn( i18n( "Use Preferred" ) );

  mManager->load();
}

FeatureDistributionList::~FeatureDistributionList()
{
  delete mManager;
}

void FeatureDistributionList::update()
{
  int index = mCbListSelect->currentItem();

  mLvAddressees->clear();
  mCbListSelect->clear();
  mCbListSelect->insertStringList(mManager->listNames());

  if ( index < mCbListSelect->count() ) {
    mCbListSelect->setCurrentItem( index );
  }

  updateGUI();
}

void FeatureDistributionList::updateGUI()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if( !list ) {
    mPbListRename->setEnabled( false );
    mPbListRemove->setEnabled( false );
    mPbChangeEmail->setEnabled( false );
    mPbEntryRemove->setEnabled( false );
    mLvAddressees->setEnabled( false );
    mLvAddressees->clear();
    return;
  } else {
    mPbListRename->setEnabled( true );
    mPbListRemove->setEnabled( true );
    mLvAddressees->setEnabled( true );
    KABC::DistributionList::Entry::List entries = list->entries();
    KABC::DistributionList::Entry::List::ConstIterator it;
    for( it = entries.begin(); it != entries.end(); ++it ) {
      new KABC::EntryItem( this, mLvAddressees, (*it).addressee, (*it).email );
    }
  }

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );

  bool state = entryItem;
  mPbChangeEmail->setEnabled( state );
  mPbEntryRemove->setEnabled( state );
}

void FeatureDistributionList::showEvent( QShowEvent* )
{
  update();
}

void FeatureDistributionList::slotListNew()
{
  KLineEditDlg dlg( i18n( "Please enter name:" ), QString::null, this );
  dlg.setCaption( i18n("New Distribution List") );

  if ( !dlg.exec() )
    return;

  new KABC::DistributionList( mManager, dlg.text() );

  mCbListSelect->clear();
  mCbListSelect->insertStringList( mManager->listNames() );
  mCbListSelect->setCurrentItem( mCbListSelect->count() - 1 );

  commit();
  update();
}

void FeatureDistributionList::slotListRename()
{
  QString oldName = mCbListSelect->currentText();

  KLineEditDlg dlg( i18n( "Please change name:" ), oldName, this );
  dlg.setCaption( i18n( "Distribution List" ) );

  if ( !dlg.exec() )
    return;

  KABC::DistributionList *list = mManager->list( oldName );
  list->setName( dlg.text() );

  mCbListSelect->clear();
  mCbListSelect->insertStringList( mManager->listNames() );
  mCbListSelect->setCurrentItem( mCbListSelect->count() - 1 );

  commit();
  update();
}

void FeatureDistributionList::slotListRemove()
{
  int result = KMessageBox::warningContinueCancel( this,
                  i18n( "Delete distibution list '%1'?" ).arg( mCbListSelect->currentText() ),
                  QString::null, i18n( "Delete" ) );

  if ( result != KMessageBox::Continue)
    return;

  delete mManager->list( mCbListSelect->currentText() );
  mCbListSelect->removeItem( mCbListSelect->currentItem() );

  commit();
  updateGUI();
}

void FeatureDistributionList::slotEntryChangeEmail()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if ( !list )
    return;

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  if ( !entryItem )
    return;

  QString email = KABC::EmailSelectDialog::getEmail( entryItem->addressee().emails(),
                                                     entryItem->email(), this );
  list->removeEntry( entryItem->addressee(), entryItem->email() );
  list->insertEntry( entryItem->addressee(), email );

  commit();
  update();
}

void FeatureDistributionList::slotEntryRemove()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if ( !list )
    return;

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  if ( !entryItem )
    return;

  list->removeEntry( entryItem->addressee(), entryItem->email() );
  delete entryItem;

  commit();
}

void FeatureDistributionList::slotListSelected( int )
{
  update();
}

void FeatureDistributionList::slotAddresseeSelectionChanged()
{
  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  bool state = entryItem;

  mPbChangeEmail->setEnabled( state );
  mPbEntryRemove->setEnabled( state );
}

void FeatureDistributionList::commit()
{
  mManager->save();
  emit modified();
}

void FeatureDistributionList::dropEvent( QDropEvent *e )
{
  QString clipText;

  if ( QTextDrag::decode( e, clipText ) ) {
    KABC::Addressee::List list;
    list = AddresseeUtil::clipboardToAddressees( clipText );
    KABC::DistributionList *distributionList = mManager->list( mCbListSelect->currentText() );
    if ( !distributionList ) {
      kdDebug(5700) << "FeatureDistributionList::dropEvent: No dist list '"
                    << mCbListSelect->currentText() << "'" << endl;
      return;
    }

    KABC::Addressee::List::Iterator it;
    for ( it = list.begin(); it != list.end(); ++it )
      distributionList->insertEntry( *it );

    commit();
    update();
  }
}

void FeatureDistributionList::slotDropped( QDropEvent *e )
{
  dropEvent( e );
}

void FeatureDistributionList::initGUI()
{
  setCaption( i18n( "Edit Distribution Lists" ) );

  QGridLayout *layout = new QGridLayout( this, 1, 1, KDialog::marginHint(), KDialog::spacingHint() );
  QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
  layout->addMultiCell( spacer, 3, 4, 2, 2 );

  mCbListSelect = new QComboBox( false, this );
  layout->addWidget( mCbListSelect, 0, 0 );

  mPbListRename = new QPushButton( i18n( "Rename List..." ), this );
  layout->addWidget( mPbListRename, 2, 0 );

  mPbListRemove = new QPushButton( i18n( "Remove List" ), this );
  layout->addWidget( mPbListRemove, 3, 0 );

  QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
  layout->addItem( spacer_2, 4, 0 );

  mPbChangeEmail = new QPushButton( i18n( "Change Email..." ), this );
  layout->addWidget( mPbChangeEmail, 0, 2 );

  mPbEntryRemove = new QPushButton( i18n( "Remove Entry" ), this );
  layout->addWidget( mPbEntryRemove, 1, 2 );

  mPbListNew = new QPushButton( i18n( "New List..." ), this );
  layout->addWidget( mPbListNew, 1, 0 );

  mLvAddressees = new FeatureDistributionListView( this );
  layout->addMultiCellWidget( mLvAddressees, 0, 4, 1, 1 );

  resize( QSize(760, 500).expandedTo(sizeHint()) );

  // signals and slots connections
  connect( mPbListNew, SIGNAL( clicked() ), this, SLOT( slotListNew() ) );
  connect( mPbListRename, SIGNAL( clicked() ), this, SLOT( slotListRename() ) );
  connect( mPbListRemove, SIGNAL( clicked() ), this, SLOT( slotListRemove() ) );
  connect( mPbChangeEmail, SIGNAL( clicked() ), this, SLOT( slotEntryChangeEmail() ) );
  connect( mPbEntryRemove, SIGNAL( clicked() ), this, SLOT( slotEntryRemove() ) );
  connect( mCbListSelect, SIGNAL( activated(int) ), this, SLOT( slotListSelected(int) ) );
}

#include "featuredistributionlist.moc"
<commit_msg>- added a tool tip to help users understand that they can drop   addressees on the distribution list editor --Mirko.<commit_after>/*
    This file is part of KAddressBook.
    Copyright (c) 2002 Mirko Boehm <mirko@kde.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qlayout.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qlistview.h>
#include <qdragobject.h>
#include <qtooltip.h>

#include <kdialog.h>
#include <klocale.h>
#include <kabc/distributionlist.h>
#include <kabc/distributionlisteditor.h>
#include <klineeditdlg.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "addresseeutil.h"
#include "featuredistributionlist.h"
#include "featuredistributionlistview.h"

namespace KABC
{

// MOSTLY A COPY FROM kdelibs/kabc:
class EntryItem : public QListViewItem
{
  protected:
    FeatureDistributionList *list;

  public:
    EntryItem( FeatureDistributionList *l, QListView *parent,
               const Addressee &addressee, const QString &email = QString::null )
      : QListViewItem( parent ), list( l ), mAddressee( addressee ), mEmail( email )
    {
      setDropEnabled( true );
      setText( 0, addressee.realName() );
      if ( email.isEmpty() ) {
        setText( 1, addressee.preferredEmail() );
        setText( 2, i18n( "Yes" ) );
      } else {
        setText( 1, email );
        setText( 2, i18n( "No" ) );
      }
    }

    Addressee addressee() const
    {
      return mAddressee;
    }

    QString email() const
    {
      return mEmail;
    }

  protected:
    bool acceptDrop( const QMimeSource* )
    {
      // WORK_TO_DO: check data type
      return true;
    }

    void dropped( QDropEvent *e )
    {
      list->slotDropped( e );
    }

  private:
    Addressee mAddressee;
    QString mEmail;
};

}

FeatureDistributionList::FeatureDistributionList( KABC::AddressBook *doc,
                                            QWidget *parent, const char* name )
  : QWidget( parent, name ),
    mDoc( doc ),
    mManager( new KABC::DistributionListManager( doc ) )
{
  initGUI();

  connect( mLvAddressees, SIGNAL(selectionChanged()),
           SLOT(slotAddresseeSelectionChanged()));
  connect( mLvAddressees, SIGNAL(dropped(QDropEvent*)),
           SLOT(slotDropped(QDropEvent*)));

  mLvAddressees->addColumn( i18n( "Name" ) );
  mLvAddressees->addColumn( i18n( "Email" ) );
  mLvAddressees->addColumn( i18n( "Use Preferred" ) );

  mManager->load();
}

FeatureDistributionList::~FeatureDistributionList()
{
  delete mManager;
}

void FeatureDistributionList::update()
{
  int index = mCbListSelect->currentItem();

  mLvAddressees->clear();
  mCbListSelect->clear();
  mCbListSelect->insertStringList(mManager->listNames());

  if ( index < mCbListSelect->count() ) {
    mCbListSelect->setCurrentItem( index );
  }

  updateGUI();
}

void FeatureDistributionList::updateGUI()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if( !list ) {
    mPbListRename->setEnabled( false );
    mPbListRemove->setEnabled( false );
    mPbChangeEmail->setEnabled( false );
    mPbEntryRemove->setEnabled( false );
    mLvAddressees->setEnabled( false );
    mLvAddressees->clear();
    return;
  } else {
    mPbListRename->setEnabled( true );
    mPbListRemove->setEnabled( true );
    mLvAddressees->setEnabled( true );
    KABC::DistributionList::Entry::List entries = list->entries();
    KABC::DistributionList::Entry::List::ConstIterator it;
    for( it = entries.begin(); it != entries.end(); ++it ) {
      new KABC::EntryItem( this, mLvAddressees, (*it).addressee, (*it).email );
    }
  }

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );

  bool state = entryItem;
  mPbChangeEmail->setEnabled( state );
  mPbEntryRemove->setEnabled( state );
}

void FeatureDistributionList::showEvent( QShowEvent* )
{
  update();
}

void FeatureDistributionList::slotListNew()
{
  KLineEditDlg dlg( i18n( "Please enter name:" ), QString::null, this );
  dlg.setCaption( i18n("New Distribution List") );

  if ( !dlg.exec() )
    return;

  new KABC::DistributionList( mManager, dlg.text() );

  mCbListSelect->clear();
  mCbListSelect->insertStringList( mManager->listNames() );
  mCbListSelect->setCurrentItem( mCbListSelect->count() - 1 );

  commit();
  update();
}

void FeatureDistributionList::slotListRename()
{
  QString oldName = mCbListSelect->currentText();

  KLineEditDlg dlg( i18n( "Please change name:" ), oldName, this );
  dlg.setCaption( i18n( "Distribution List" ) );

  if ( !dlg.exec() )
    return;

  KABC::DistributionList *list = mManager->list( oldName );
  list->setName( dlg.text() );

  mCbListSelect->clear();
  mCbListSelect->insertStringList( mManager->listNames() );
  mCbListSelect->setCurrentItem( mCbListSelect->count() - 1 );

  commit();
  update();
}

void FeatureDistributionList::slotListRemove()
{
  int result = KMessageBox::warningContinueCancel( this,
                  i18n( "Delete distibution list '%1'?" ).arg( mCbListSelect->currentText() ),
                  QString::null, i18n( "Delete" ) );

  if ( result != KMessageBox::Continue)
    return;

  delete mManager->list( mCbListSelect->currentText() );
  mCbListSelect->removeItem( mCbListSelect->currentItem() );

  commit();
  updateGUI();
}

void FeatureDistributionList::slotEntryChangeEmail()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if ( !list )
    return;

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  if ( !entryItem )
    return;

  QString email = KABC::EmailSelectDialog::getEmail( entryItem->addressee().emails(),
                                                     entryItem->email(), this );
  list->removeEntry( entryItem->addressee(), entryItem->email() );
  list->insertEntry( entryItem->addressee(), email );

  commit();
  update();
}

void FeatureDistributionList::slotEntryRemove()
{
  KABC::DistributionList *list = mManager->list( mCbListSelect->currentText() );
  if ( !list )
    return;

  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  if ( !entryItem )
    return;

  list->removeEntry( entryItem->addressee(), entryItem->email() );
  delete entryItem;

  commit();
}

void FeatureDistributionList::slotListSelected( int )
{
  update();
}

void FeatureDistributionList::slotAddresseeSelectionChanged()
{
  KABC::EntryItem *entryItem = static_cast<KABC::EntryItem *>( mLvAddressees->selectedItem() );
  bool state = entryItem;

  mPbChangeEmail->setEnabled( state );
  mPbEntryRemove->setEnabled( state );
}

void FeatureDistributionList::commit()
{
  mManager->save();
  emit modified();
}

void FeatureDistributionList::dropEvent( QDropEvent *e )
{
  QString clipText;

  if ( QTextDrag::decode( e, clipText ) ) {
    KABC::Addressee::List list;
    list = AddresseeUtil::clipboardToAddressees( clipText );
    KABC::DistributionList *distributionList = mManager->list( mCbListSelect->currentText() );
    if ( !distributionList ) {
      kdDebug(5700) << "FeatureDistributionList::dropEvent: No dist list '"
                    << mCbListSelect->currentText() << "'" << endl;
      return;
    }

    KABC::Addressee::List::Iterator it;
    for ( it = list.begin(); it != list.end(); ++it )
      distributionList->insertEntry( *it );

    commit();
    update();
  }
}

void FeatureDistributionList::slotDropped( QDropEvent *e )
{
  dropEvent( e );
}

void FeatureDistributionList::initGUI()
{
  setCaption( i18n( "Edit Distribution Lists" ) );

  QGridLayout *layout = new QGridLayout( this, 1, 1, KDialog::marginHint(), KDialog::spacingHint() );
  QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
  layout->addMultiCell( spacer, 3, 4, 2, 2 );

  mCbListSelect = new QComboBox( false, this );
  layout->addWidget( mCbListSelect, 0, 0 );

  mPbListRename = new QPushButton( i18n( "Rename List..." ), this );
  layout->addWidget( mPbListRename, 2, 0 );

  mPbListRemove = new QPushButton( i18n( "Remove List" ), this );
  layout->addWidget( mPbListRemove, 3, 0 );

  QSpacerItem* spacer_2 = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
  layout->addItem( spacer_2, 4, 0 );

  mPbChangeEmail = new QPushButton( i18n( "Change Email..." ), this );
  layout->addWidget( mPbChangeEmail, 0, 2 );

  mPbEntryRemove = new QPushButton( i18n( "Remove Entry" ), this );
  layout->addWidget( mPbEntryRemove, 1, 2 );

  mPbListNew = new QPushButton( i18n( "New List..." ), this );
  layout->addWidget( mPbListNew, 1, 0 );

  mLvAddressees = new FeatureDistributionListView( this );
  layout->addMultiCellWidget( mLvAddressees, 0, 4, 1, 1 );
  QToolTip::add(mLvAddressees, i18n("Drag addressees here to add them to the distribution list."));

  resize( QSize(760, 500).expandedTo(sizeHint()) );

  // signals and slots connections
  connect( mPbListNew, SIGNAL( clicked() ), this, SLOT( slotListNew() ) );
  connect( mPbListRename, SIGNAL( clicked() ), this, SLOT( slotListRename() ) );
  connect( mPbListRemove, SIGNAL( clicked() ), this, SLOT( slotListRemove() ) );
  connect( mPbChangeEmail, SIGNAL( clicked() ), this, SLOT( slotEntryChangeEmail() ) );
  connect( mPbEntryRemove, SIGNAL( clicked() ), this, SLOT( slotEntryRemove() ) );
  connect( mCbListSelect, SIGNAL( activated(int) ), this, SLOT( slotListSelected(int) ) );
}

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