<commit_before>/***********************************************************************
    created:    Mon Mar 6 2006
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/XMLParserModules/Libxml2/XMLParser.h"
#include "CEGUI/System.h"
#include "CEGUI/String.h"
#include "CEGUI/ResourceProvider.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/XMLAttributes.h"
#include "CEGUI/XMLHandler.h"
#include "CEGUI/PropertyHelper.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlerror.h>

// Start of CEGUI namespace section
namespace CEGUI
{
// internal helper function to process elements
void processXMLElement(XMLHandler& handler, xmlNode* node)
{
    // build attributes block for the element
    XMLAttributes attrs;

    xmlAttrPtr currAttr = node->properties;
    while (currAttr)
    {
        xmlChar* val = xmlGetProp(node, currAttr->name);
        CEGUI::String value( reinterpret_cast<char*>(val) );
        attrs.add(currAttr->name, value);
        xmlFree(val);
        currAttr = currAttr->next;
    }

    // element start processing
    CEGUI::String nodeName( reinterpret_cast<char*>(node->name));
    handler.elementStart(nodeName, attrs);

    for (xmlNode* cur_node = node->children; cur_node; cur_node = cur_node->next)
    {
        switch(cur_node->type)
        {
        case XML_ELEMENT_NODE:
            processXMLElement(handler, cur_node);
            break;

        case XML_TEXT_NODE:
            if (cur_node->content != 0 && *cur_node->content!= '\0')
                handler.text(cur_node->content);
            break;

        default:
            break;
        }
    }

    // element end processing
    handler.elementEnd(nodeName);
}

LibxmlParser::LibxmlParser(void)
{
    d_identifierString = "CEGUI::LibxmlParser - Official libxml2 based parser module for CEGUI";
}

LibxmlParser::~LibxmlParser(void)
{
}

void LibxmlParser::parseXML(XMLHandler& handler,
                            const RawDataContainer& source,
                            const String& /*schemaName*/,
                            bool /*allowXmlValidation*/)
{
    xmlDocPtr doc = xmlParseMemory(
        reinterpret_cast<const char*>(source.getDataPtr()),
        source.getSize());

    if (!doc)
    {
        xmlError* err = xmlGetLastError();

        throw GenericException(
            String("xmlParseMemory failed in file: '") +
            err->file + "' at line number" +
            PropertyHelper<std::uint32_t>::toString(err->line) + ".  Error is:" +
            err->message);
    }

    // get root element
    xmlNode* root = xmlDocGetRootElement(doc);

    // process all elements from root to end of doc
    processXMLElement(handler, root);

    // release the xmlDoc
    xmlFreeDoc(doc);
}

bool LibxmlParser::initialiseImpl(void)
{
    LIBXML_TEST_VERSION;
    return true;
}

void LibxmlParser::cleanupImpl(void)
{
    xmlCleanupParser();
}

} // End of  CEGUI namespace section
<commit_msg>MOD: Fixing further libxml2 char* errors<commit_after>/***********************************************************************
    created:    Mon Mar 6 2006
    author:     Paul D Turner <paul@cegui.org.uk>
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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 "CEGUI/XMLParserModules/Libxml2/XMLParser.h"
#include "CEGUI/System.h"
#include "CEGUI/String.h"
#include "CEGUI/ResourceProvider.h"
#include "CEGUI/Exceptions.h"
#include "CEGUI/XMLAttributes.h"
#include "CEGUI/XMLHandler.h"
#include "CEGUI/PropertyHelper.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlerror.h>

// Start of CEGUI namespace section
namespace CEGUI
{
// internal helper function to process elements
void processXMLElement(XMLHandler& handler, xmlNode* node)
{
    // build attributes block for the element
    XMLAttributes attrs;

    xmlAttrPtr currAttr = node->properties;
    while (currAttr)
    {
        xmlChar* val = xmlGetProp(node, currAttr->name);
        CEGUI::String value( reinterpret_cast<char*>(val) );

        CEGUI::String attrName( reinterpret_cast<const char*>(currAttr->name));

        attrs.add(attrName, value);
        xmlFree(val);
        currAttr = currAttr->next;
    }

    // element start processing
    CEGUI::String nodeName( reinterpret_cast<const char*>(node->name));
    handler.elementStart(nodeName, attrs);

    for (xmlNode* cur_node = node->children; cur_node; cur_node = cur_node->next)
    {
        switch(cur_node->type)
        {
        case XML_ELEMENT_NODE:
            processXMLElement(handler, cur_node);
            break;

        case XML_TEXT_NODE:
            if (cur_node->content != 0 && *cur_node->content!= '\0')
            {
                String cureNodeContent( reinterpret_cast<const char*>(cur_node->content) );
                handler.text(cureNodeContent);
            }
            break;

        default:
            break;
        }
    }

    // element end processing
    handler.elementEnd(nodeName);
}

LibxmlParser::LibxmlParser(void)
{
    d_identifierString = "CEGUI::LibxmlParser - Official libxml2 based parser module for CEGUI";
}

LibxmlParser::~LibxmlParser(void)
{
}

void LibxmlParser::parseXML(XMLHandler& handler,
                            const RawDataContainer& source,
                            const String& /*schemaName*/,
                            bool /*allowXmlValidation*/)
{
    xmlDocPtr doc = xmlParseMemory(
        reinterpret_cast<const char*>(source.getDataPtr()),
        source.getSize());

    if (!doc)
    {
        xmlError* err = xmlGetLastError();

        throw GenericException(
            String("xmlParseMemory failed in file: '") +
            err->file + "' at line number" +
            PropertyHelper<std::uint32_t>::toString(err->line) + ".  Error is:" +
            err->message);
    }

    // get root element
    xmlNode* root = xmlDocGetRootElement(doc);

    // process all elements from root to end of doc
    processXMLElement(handler, root);

    // release the xmlDoc
    xmlFreeDoc(doc);
}

bool LibxmlParser::initialiseImpl(void)
{
    LIBXML_TEST_VERSION;
    return true;
}

void LibxmlParser::cleanupImpl(void)
{
    xmlCleanupParser();
}

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before>#include "render/init.h"

#include <SDL2/SDL_video.h>
#include "render/gl.h"

#include <iostream>

Init::Init() : ok(true) {
  const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
  if(!glad_result) {
    std::cerr << "Failed to init glad, error: " << glad_result
              << "\n";
    ok = false;
  }

  std::cout << "Vendor:         " << glGetString(GL_VENDOR) << "\n";
  std::cout << "Renderer:       " << glGetString(GL_RENDERER) << "\n";
  std::cout << "Version OpenGL: " << glGetString(GL_VERSION) << "\n";
  std::cout << "Version GLSL:   " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

  // todo: move this to a better place
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

Init::~Init() {
}

void Init::SetViewport(const Recti &viewport) {
  const vec2i top_left = viewport.TopLeft();
  glViewport(top_left.x, top_left.y, viewport.GetWidth(), viewport.GetHeight());
}

void Init::ClearScreen(const Rgb& color) {
  // 42.0f / 255, 45.0f / 255, 51.0f / 255
  glClearColor(color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
}
<commit_msg>added printing of attribute count<commit_after>#include "render/init.h"

#include <SDL2/SDL_video.h>
#include "render/gl.h"

#include <iostream>

Init::Init() : ok(true) {
  const int glad_result = gladLoadGLLoader(SDL_GL_GetProcAddress);
  if(!glad_result) {
    std::cerr << "Failed to init glad, error: " << glad_result
              << "\n";
    ok = false;
  }

  std::cout << "Vendor:         " << glGetString(GL_VENDOR) << "\n";
  std::cout << "Renderer:       " << glGetString(GL_RENDERER) << "\n";
  std::cout << "Version OpenGL: " << glGetString(GL_VERSION) << "\n";
  std::cout << "Version GLSL:   " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n";

  int attribute_count;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
  std::cout << "Max shader attribute count: " << attribute_count << "\n";

  // todo: move this to a better place
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

Init::~Init() {
}

void Init::SetViewport(const Recti &viewport) {
  const vec2i top_left = viewport.TopLeft();
  glViewport(top_left.x, top_left.y, viewport.GetWidth(), viewport.GetHeight());
}

void Init::ClearScreen(const Rgb& color) {
  // 42.0f / 255, 45.0f / 255, 51.0f / 255
  glClearColor(color.GetRed(), color.GetGreen(), color.GetBlue(), 1.0f);
  glClear(GL_COLOR_BUFFER_BIT);
}
<|endoftext|>


<commit_before>#pragma once

#include "types.hpp"
#include <vector>

namespace rltk {
namespace vterm {

class layer {
public:
	void resize(const std::pair<int,int> screen_size);
	void cls();
	inline int idx(const int x, const int y) { return (y*terminal_size.first)+x;  }
	inline void set(const int idx, const char_t target) { buffer[idx] = target; }
	inline void set(const int x, const int y, const char_t target) { set(idx(x,y),target);  }
	void print(const int idx, const std::string text, const color_t fg, const color_t bg);
	inline void print(const int x, const int y, const std::string text, const color_t fg, const color_t bg) { print(idx(x,y), text, fg, bg); };

	std::pair<int,int> font_size{8,8};
	std::pair<int,int> terminal_size;
	bool render_background = true;
	uint8_t alpha = 255;
	std::vector<char_t> buffer;
};

}
}
<commit_msg>Add missing include.<commit_after>#pragma once

#include "types.hpp"
#include <vector>
#include <string>

namespace rltk {
namespace vterm {

class layer {
public:
	void resize(const std::pair<int,int> screen_size);
	void cls();
	inline int idx(const int x, const int y) { return (y*terminal_size.first)+x;  }
	inline void set(const int idx, const char_t target) { buffer[idx] = target; }
	inline void set(const int x, const int y, const char_t target) { set(idx(x,y),target);  }
	void print(const int idx, const std::string text, const color_t fg, const color_t bg);
	inline void print(const int x, const int y, const std::string text, const color_t fg, const color_t bg) { print(idx(x,y), text, fg, bg); };

	std::pair<int,int> font_size{8,8};
	std::pair<int,int> terminal_size;
	bool render_background = true;
	uint8_t alpha = 255;
	std::vector<char_t> buffer;
};

}
}
<|endoftext|>


<commit_before>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "AFCPluginManager.h"
#include "SDK/Core/Base/AFPlatform.hpp"

#if ARK_PLATFORM == PLATFORM_UNIX
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/prctl.h>
#endif

#if ARK_PLATFORM == PLATFORM_WIN
#include <Dbghelp.h>
#pragma comment(lib, "DbgHelp")
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#pragma comment(lib, "AFCore_d.lib")
#else
#pragma comment(lib, "AFCore.lib")
#endif

bool bExitApp = false;
std::thread gBackThread;

// 创建Dump文件
void CreateDumpFile(const std::string& strDumpFilePathName, EXCEPTION_POINTERS* pException)
{
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(strDumpFilePathName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);
}

// 处理Unhandled Exception的回调函数
long ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf_s(szDmupName, "%04d_%02d_%02d_%02d_%02d_%02d.dmp",  ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    CreateDumpFile(szDmupName, pException);

    FatalAppExit(-1,  szDmupName);

    return EXCEPTION_EXECUTE_HANDLER;
}
#endif

void CloseXButton()
{
#if ARK_PLATFORM == PLATFORM_WIN
    HWND hWnd = GetConsoleWindow();
    if(hWnd)
    {
        HMENU hMenu = GetSystemMenu(hWnd, FALSE);
        EnableMenuItem(hMenu, SC_CLOSE, MF_DISABLED | MF_BYCOMMAND);
    }
#endif
}

void InitDaemon()
{
#if ARK_PLATFORM == PLATFORM_UNIX
    daemon(1, 0);

    // ignore signals
    signal(SIGINT, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
#endif
}

void EchoArkLogo()
{
#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif

    std::cout << "     _         _        ____  _             _ _       " << std::endl;
    std::cout << "    / \\   _ __| | __   / ___|| |_ _   _  __| (_) ___  " << std::endl;
    std::cout << "   / _ \\ | '__| |/ /   \\___ \\| __| | | |/ _` | |/ _ \\ " << std::endl;
    std::cout << "  / ___ \\| |  |   <     ___) | |_| |_| | (_| | | (_) |" << std::endl;
    std::cout << " /_/   \\_\\_|  |_|\\_\\   |____/ \\__|\\__,_|\\__,_|_|\\___/ " << std::endl;
    std::cout << std::endl;
    std::cout << "COPYRIGHT (c) 2013-2018 Ark Studio" << std::endl;
    std::cout << "All RIGHTS RESERVED." << std::endl;
    std::cout << "HTTPS://ARKGAME.NET" << std::endl;
    std::cout << "********************************************" << std::endl;

#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
}

void Usage()
{
    std::cout << "Ark PluginLoader usage:" << std::endl;
    std::cout << "./PluginLoader [options]" << std::endl;
    std::cout << "Option:" << std::endl;
    std::cout << "\t" << "-d, Run as daemon, just take effect in Linux" << std::endl;
    std::cout << "\t" << "-x, Remove close button, just take effect in Windows" << std::endl;
    std::cout << "\t" << "cfg=plugin.xml, plugin configuration files" << std::endl;
    std::cout << "\t" << "app_id=1, set application's id" << std::endl;
    std::cout << "\t" << "app_name=GameServer, set application's name" << std::endl;
    std::cout << "i.e. ./PluginLoader -d -x cfg=plugin.xml app_id=1 app_name=my_test" << std::endl;
}

void ThreadFunc()
{
    while(!bExitApp)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        std::string s;
        std::cin >> s;
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        if(s == "exit")
        {
            bExitApp = true;
        }
        else if(s == "help")
        {
            Usage();
        }
    }
}

void CreateBackThread()
{
    gBackThread = std::thread(std::bind(&ThreadFunc));
    //std::cout << "CreateBackThread, thread ID = " << gThread.get_id() << std::endl;
}

struct ApplicationConfig
{
    bool deamon = true;                     //run as deamon, Linux
    bool xbutton = true;                    //close X button in windows
    std::string plugin_file = "Plugin.xml"; //config file
    int app_id = 0;                 //app id
    std::string app_name = "";              //app name
};

#if ARK_PLATFORM == PLATFORM_UNIX
extern char** environ;

struct environ_guard
{
public:
    ~environ_guard()
    {
        if(env_buf)
        {
            delete[] env_buf;
            env_buf = nullptr;
        }
        if(environ)
        {
            delete[] environ;
            environ = nullptr;
        }
    }

    char* env_buf;
    char** environ;
};

environ_guard g_new_environ_guard{ nullptr, nullptr };

int realloc_environ()
{
    int var_count = 0;
    int env_size = 0;
    {
        char** ep = environ;
        while(*ep)
        {
            env_size += std::strlen(*ep) + 1;
            ++var_count;
            ++ep;
        }
    }

    char* new_env_buf = new char[env_size];
    std::memcpy((void *)new_env_buf, (void *)*environ, env_size);

    char** new_env = new char*[var_count + 1];
    {
        int var = 0;
        int offset = 0;
        char** ep = environ;
        while(*ep)
        {
            new_env[var++] = (new_env_buf + offset);
            offset += std::strlen(*ep) + 1;
            ++ep;
        }
    }
    new_env[var_count] = 0;

    // RAII to prevent memory leak
    g_new_environ_guard = environ_guard{ new_env_buf, new_env };

    environ = new_env;

    return env_size;
}

void setproctitle(const char* title, int argc, char** argv)
{
    int argv_size = 0;
    for(int i = 0; i < argc; ++i)
    {
        int len = std::strlen(argv[i]);
        std::memset(argv[i], 0, len);
        argv_size += len;
    }

    int to_be_copied = std::strlen(title);
    if(argv_size <= to_be_copied)
    {
        int env_size = realloc_environ();
        if(env_size < to_be_copied)
        {
            to_be_copied = env_size;
        }
    }

    std::strncpy(argv[0], title, to_be_copied);
    *(argv[0] + to_be_copied) = 0;
}

#endif

bool ProcArgList(int argc, char* argv[])
{
    //Echo logo
    EchoArkLogo();

    //Analyse arg list
    ApplicationConfig config;
    for(int i = 0; i < argc; ++i)
    {
        std::string arg = argv[i];
        if(arg == "-d")
        {
            config.deamon = true;
        }
        else if(arg == "-x")
        {
            config.xbutton = true;
        }
        else if(arg.find("cfg") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.plugin_file = arg.substr(pos + 1, arg.length() - pos - 1);
            }
        }
        else if(arg.find("app_id") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.app_id = ARK_LEXICAL_CAST<int>(arg.substr(pos + 1, arg.length() - pos - 1));
            }
        }
        else if(arg.find("app_name") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.app_name = arg.substr(pos + 1, arg.length() - pos - 1);
            }
        }
    }

    if(config.deamon)
    {
#if ARK_PLATFORM == PLATFORM_UNIX
        //Run as a daemon process
        signal(SIGPIPE, SIG_IGN);
        signal(SIGCHLD, SIG_IGN);
#endif
    }

    if(config.xbutton)
    {
#if ARK_PLATFORM == PLATFORM_WIN
        SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
        CloseXButton();
#endif
    }

    //暂时还从plugin.xml中获取app id,不做强制要求
    //如果要做多开，则需要自己处理
    //if(config.app_id == 0)
    //{
    //    std::cout << "parameter app_id is invalid, please check." << std::endl;
    //    return false;
    //}
    //暂时app name也可以不用传参
    //if(config.app_name.empty())
    //{
    //    std::cout << "parameter app_name is invalid, please check." << std::endl;
    //    return false;
    //}

    //Set plugin file
    AFCPluginManager::GetInstancePtr()->SetConfigName(config.plugin_file);
    AFCPluginManager::GetInstancePtr()->SetAppID(config.app_id);

    std::string process_name = "[" + config.app_name + ":" + ARK_TO_STRING(config.app_id) + "]";
    //Set process name
#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTitle(process_name.c_str());
#elif ARK_PLATFORM == PLATFORM_UNIX
    setproctitle(process_name, argc, argv);
#endif

    //Create back thread, for some cmd
    CreateBackThread();

    return true;
}

void MainLoop()
{
#if ARK_PLATFORM == PLATFORM_WIN
    __try
    {
        AFCPluginManager::GetInstancePtr()->Update();
    }
    __except(ApplicationCrashHandler(GetExceptionInformation()))
    {
    }
#else
    AFCPluginManager::GetInstancePtr()->Update();
#endif
}

int main(int argc, char* argv[])
{
    //arg list
    //-d, Run as daemon, just take effect in Linux
    //-x, Remove close button, just take effect in Windows
    //cfg=plugin.xml, plugin configuration files
    //app_id=1, set application's id
    //app_name=GameServer, set application's name
    if(!ProcArgList(argc, argv))
    {
        std::cout << "Application parameter is invalid, please check it..." << std::endl;
        Usage();

        return -1;
    }

    AFCPluginManager::GetInstancePtr()->Init();
    AFCPluginManager::GetInstancePtr()->PostInit();
    AFCPluginManager::GetInstancePtr()->CheckConfig();
    AFCPluginManager::GetInstancePtr()->PreUpdate();

    while(!bExitApp)     //DEBUG版本崩溃，RELEASE不崩
    {
        while(true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if(bExitApp)
            {
                break;
            }

            MainLoop();
        }
    }

    AFCPluginManager::GetInstancePtr()->PreShut();
    AFCPluginManager::GetInstancePtr()->Shut();

    AFCPluginManager::GetInstancePtr()->ReleaseInstance();

    gBackThread.join();

    return 0;
}<commit_msg>fix wrong code moving<commit_after>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "AFCPluginManager.h"
#include "SDK/Core/Base/AFPlatform.hpp"

#if ARK_PLATFORM == PLATFORM_UNIX
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/prctl.h>
#endif

bool bExitApp = false;
std::thread gBackThread;

#if ARK_PLATFORM == PLATFORM_WIN
#include <Dbghelp.h>
#pragma comment(lib, "DbgHelp")
#if ARK_RUN_MODE == ARK_RUN_MODE_DEBUG
#pragma comment(lib, "AFCore_d.lib")
#else
#pragma comment(lib, "AFCore.lib")
#endif

// 创建Dump文件
void CreateDumpFile(const std::string& strDumpFilePathName, EXCEPTION_POINTERS* pException)
{
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(strDumpFilePathName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);
}

// 处理Unhandled Exception的回调函数
long ApplicationCrashHandler(EXCEPTION_POINTERS* pException)
{
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf_s(szDmupName, "%04d_%02d_%02d_%02d_%02d_%02d.dmp",  ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    CreateDumpFile(szDmupName, pException);

    FatalAppExit(-1,  szDmupName);

    return EXCEPTION_EXECUTE_HANDLER;
}
#endif

void CloseXButton()
{
#if ARK_PLATFORM == PLATFORM_WIN
    HWND hWnd = GetConsoleWindow();
    if(hWnd)
    {
        HMENU hMenu = GetSystemMenu(hWnd, FALSE);
        EnableMenuItem(hMenu, SC_CLOSE, MF_DISABLED | MF_BYCOMMAND);
    }
#endif
}

void InitDaemon()
{
#if ARK_PLATFORM == PLATFORM_UNIX
    daemon(1, 0);

    // ignore signals
    signal(SIGINT, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);
    signal(SIGTERM, SIG_IGN);
#endif
}

void EchoArkLogo()
{
#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif

    std::cout << "     _         _        ____  _             _ _       " << std::endl;
    std::cout << "    / \\   _ __| | __   / ___|| |_ _   _  __| (_) ___  " << std::endl;
    std::cout << "   / _ \\ | '__| |/ /   \\___ \\| __| | | |/ _` | |/ _ \\ " << std::endl;
    std::cout << "  / ___ \\| |  |   <     ___) | |_| |_| | (_| | | (_) |" << std::endl;
    std::cout << " /_/   \\_\\_|  |_|\\_\\   |____/ \\__|\\__,_|\\__,_|_|\\___/ " << std::endl;
    std::cout << std::endl;
    std::cout << "COPYRIGHT (c) 2013-2018 Ark Studio" << std::endl;
    std::cout << "All RIGHTS RESERVED." << std::endl;
    std::cout << "HTTPS://ARKGAME.NET" << std::endl;
    std::cout << "********************************************" << std::endl;

#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
}

void Usage()
{
    std::cout << "Ark PluginLoader usage:" << std::endl;
    std::cout << "./PluginLoader [options]" << std::endl;
    std::cout << "Option:" << std::endl;
    std::cout << "\t" << "-d, Run as daemon, just take effect in Linux" << std::endl;
    std::cout << "\t" << "-x, Remove close button, just take effect in Windows" << std::endl;
    std::cout << "\t" << "cfg=plugin.xml, plugin configuration files" << std::endl;
    std::cout << "\t" << "app_id=1, set application's id" << std::endl;
    std::cout << "\t" << "app_name=GameServer, set application's name" << std::endl;
    std::cout << "i.e. ./PluginLoader -d -x cfg=plugin.xml app_id=1 app_name=my_test" << std::endl;
}

void ThreadFunc()
{
    while(!bExitApp)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));

        std::string s;
        std::cin >> s;
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        if(s == "exit")
        {
            bExitApp = true;
        }
        else if(s == "help")
        {
            Usage();
        }
    }
}

void CreateBackThread()
{
    gBackThread = std::thread(std::bind(&ThreadFunc));
    //std::cout << "CreateBackThread, thread ID = " << gThread.get_id() << std::endl;
}

struct ApplicationConfig
{
    bool deamon = true;                     //run as deamon, Linux
    bool xbutton = true;                    //close X button in windows
    std::string plugin_file = "Plugin.xml"; //config file
    int app_id = 0;                 //app id
    std::string app_name = "";              //app name
};

#if ARK_PLATFORM == PLATFORM_UNIX
extern char** environ;

struct environ_guard
{
public:
    ~environ_guard()
    {
        if(env_buf)
        {
            delete[] env_buf;
            env_buf = nullptr;
        }
        if(environ)
        {
            delete[] environ;
            environ = nullptr;
        }
    }

    char* env_buf;
    char** environ;
};

environ_guard g_new_environ_guard{ nullptr, nullptr };

int realloc_environ()
{
    int var_count = 0;
    int env_size = 0;
    {
        char** ep = environ;
        while(*ep)
        {
            env_size += std::strlen(*ep) + 1;
            ++var_count;
            ++ep;
        }
    }

    char* new_env_buf = new char[env_size];
    std::memcpy((void *)new_env_buf, (void *)*environ, env_size);

    char** new_env = new char*[var_count + 1];
    {
        int var = 0;
        int offset = 0;
        char** ep = environ;
        while(*ep)
        {
            new_env[var++] = (new_env_buf + offset);
            offset += std::strlen(*ep) + 1;
            ++ep;
        }
    }
    new_env[var_count] = 0;

    // RAII to prevent memory leak
    g_new_environ_guard = environ_guard{ new_env_buf, new_env };

    environ = new_env;

    return env_size;
}

void setproctitle(const char* title, int argc, char** argv)
{
    int argv_size = 0;
    for(int i = 0; i < argc; ++i)
    {
        int len = std::strlen(argv[i]);
        std::memset(argv[i], 0, len);
        argv_size += len;
    }

    int to_be_copied = std::strlen(title);
    if(argv_size <= to_be_copied)
    {
        int env_size = realloc_environ();
        if(env_size < to_be_copied)
        {
            to_be_copied = env_size;
        }
    }

    std::strncpy(argv[0], title, to_be_copied);
    *(argv[0] + to_be_copied) = 0;
}

#endif

bool ProcArgList(int argc, char* argv[])
{
    //Echo logo
    EchoArkLogo();

    //Analyse arg list
    ApplicationConfig config;
    for(int i = 0; i < argc; ++i)
    {
        std::string arg = argv[i];
        if(arg == "-d")
        {
            config.deamon = true;
        }
        else if(arg == "-x")
        {
            config.xbutton = true;
        }
        else if(arg.find("cfg") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.plugin_file = arg.substr(pos + 1, arg.length() - pos - 1);
            }
        }
        else if(arg.find("app_id") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.app_id = ARK_LEXICAL_CAST<int>(arg.substr(pos + 1, arg.length() - pos - 1));
            }
        }
        else if(arg.find("app_name") != std::string::npos)
        {
            size_t pos = arg.find("=");
            if(pos != std::string::npos)
            {
                config.app_name = arg.substr(pos + 1, arg.length() - pos - 1);
            }
        }
    }

    if(config.deamon)
    {
#if ARK_PLATFORM == PLATFORM_UNIX
        //Run as a daemon process
        signal(SIGPIPE, SIG_IGN);
        signal(SIGCHLD, SIG_IGN);
#endif
    }

    if(config.xbutton)
    {
#if ARK_PLATFORM == PLATFORM_WIN
        SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);
        CloseXButton();
#endif
    }

    //暂时还从plugin.xml中获取app id,不做强制要求
    //如果要做多开，则需要自己处理
    //if(config.app_id == 0)
    //{
    //    std::cout << "parameter app_id is invalid, please check." << std::endl;
    //    return false;
    //}
    //暂时app name也可以不用传参
    //if(config.app_name.empty())
    //{
    //    std::cout << "parameter app_name is invalid, please check." << std::endl;
    //    return false;
    //}

    //Set plugin file
    AFCPluginManager::GetInstancePtr()->SetConfigName(config.plugin_file);
    AFCPluginManager::GetInstancePtr()->SetAppID(config.app_id);

    std::string process_name = "[" + config.app_name + ":" + ARK_TO_STRING(config.app_id) + "]";
    //Set process name
#if ARK_PLATFORM == PLATFORM_WIN
    SetConsoleTitle(process_name.c_str());
#elif ARK_PLATFORM == PLATFORM_UNIX
    setproctitle(process_name, argc, argv);
#endif

    //Create back thread, for some cmd
    CreateBackThread();

    return true;
}

void MainLoop()
{
#if ARK_PLATFORM == PLATFORM_WIN
    __try
    {
        AFCPluginManager::GetInstancePtr()->Update();
    }
    __except(ApplicationCrashHandler(GetExceptionInformation()))
    {
    }
#else
    AFCPluginManager::GetInstancePtr()->Update();
#endif
}

int main(int argc, char* argv[])
{
    //arg list
    //-d, Run as daemon, just take effect in Linux
    //-x, Remove close button, just take effect in Windows
    //cfg=plugin.xml, plugin configuration files
    //app_id=1, set application's id
    //app_name=GameServer, set application's name
    if(!ProcArgList(argc, argv))
    {
        std::cout << "Application parameter is invalid, please check it..." << std::endl;
        Usage();

        return -1;
    }

    AFCPluginManager::GetInstancePtr()->Init();
    AFCPluginManager::GetInstancePtr()->PostInit();
    AFCPluginManager::GetInstancePtr()->CheckConfig();
    AFCPluginManager::GetInstancePtr()->PreUpdate();

    while(!bExitApp)     //DEBUG版本崩溃，RELEASE不崩
    {
        while(true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));

            if(bExitApp)
            {
                break;
            }

            MainLoop();
        }
    }

    AFCPluginManager::GetInstancePtr()->PreShut();
    AFCPluginManager::GetInstancePtr()->Shut();

    AFCPluginManager::GetInstancePtr()->ReleaseInstance();

    gBackThread.join();

    return 0;
}<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkLevelWindow.h"
#include "mitkImageSliceSelector.h"

#include <ipFunc/ipFunc.h>
#include <algorithm>

mitk::LevelWindow::LevelWindow(mitk::ScalarType level, mitk::ScalarType window) : m_Min(level-window/2.0), m_Max(level+window/2.0), m_RangeMin(-1024), m_RangeMax(4096)
{

}

mitk::LevelWindow::LevelWindow(const mitk::LevelWindow& levWin)
{
  *this=levWin;
}

mitk::LevelWindow::~LevelWindow()
{
}

mitk::ScalarType mitk::LevelWindow::GetLevel() const
{
  return (m_Max-m_Min)/2.0 + m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetWindow() const
{
  return (m_Max-m_Min);
}

mitk::ScalarType mitk::LevelWindow::GetMin() const
{
  return m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetMax() const
{
  return m_Max;
}

void mitk::LevelWindow::SetLevel(mitk::ScalarType level)
{
  mitk::ScalarType halfWindow = (m_Max - m_Min) / 2;
  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetWindow(mitk::ScalarType window)
{
  mitk::ScalarType level = m_Min + (m_Max - m_Min) / 2;
  mitk::ScalarType halfWindow = window / 2;

  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
{
  m_Min = level - window / 2.0;
  m_Max = level + window / 2.0;

  testValues();
}

void mitk::LevelWindow::SetMin(mitk::ScalarType min)
{
  m_Min = min;
  testValues();
}

void mitk::LevelWindow::SetMax(mitk::ScalarType max)
{
  m_Max = max;
  testValues();
}

void mitk::LevelWindow::SetMinMax(mitk::ScalarType min, mitk::ScalarType max)
{
  if(min>max)
    std::swap(min,max);

  SetMin(min);
  SetMax(max);
}

void mitk::LevelWindow::SetRangeMin(mitk::ScalarType min)
{
  m_RangeMin = min;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

void mitk::LevelWindow::SetRangeMax(mitk::ScalarType max)
{
  m_RangeMax = max;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

mitk::ScalarType mitk::LevelWindow::GetRangeMin() const
{
  return m_RangeMin;
}

mitk::ScalarType mitk::LevelWindow::GetRangeMax() const
{
  return m_RangeMax;
}

mitk::ScalarType mitk::LevelWindow::GetRange() const
{
  return  m_RangeMax - m_RangeMin;
}

void mitk::LevelWindow::SetAuto(mitk::Image* image, bool tryPicTags, bool guessByCentralSlice)
{
  if( image == NULL )
    return;

  if(tryPicTags)
  {
    if(SetAutoByPicTags(image->GetPic()))
      return;
  }

  mitk::Image* wholeImage = image;
  if(guessByCentralSlice)
  {
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
      sliceSelector->SetInput(image);
      sliceSelector->SetSliceNr(image->GetDimension(2)/2);
      sliceSelector->SetTimeNr(image->GetDimension(3)/2);
      sliceSelector->SetChannelNr(image->GetDimension(4)/2);
      sliceSelector->Update();

    image = sliceSelector->GetOutput();
  }
  ScalarType minValue = image->GetScalarValue2ndMin();
  ScalarType maxValue = image->GetScalarValue2ndMaxNoRecompute();
  if (minValue == maxValue)
  {
      // guessByCentralSlice seems to have failed, lets look at all data
      minValue = wholeImage->GetScalarValue2ndMin();
      maxValue = wholeImage->GetScalarValue2ndMaxNoRecompute();
  }
  SetRangeMin(minValue);
  SetRangeMax(maxValue);
  SetMinMax(minValue, maxValue);
}

bool mitk::LevelWindow::SetAutoByPicTags(const ipPicDescriptor* aPic)
{
  ipPicDescriptor* pic = const_cast<ipPicDescriptor*>(aPic);
  if ( pic == NULL )
  {
    return false;
  }
  ipPicTSV_t *tsv = ipPicQueryTag( pic, "LEVEL/WINDOW" );
  if( tsv != NULL )
  {
    double level = 0;
    double window = 0;
    #define GET_C_W( type, tsv, C, W )    \
      level = ((type *)tsv->value)[0];    \
      window = ((type *)tsv->value)[1];

    ipPicFORALL_2( GET_C_W, tsv, level, window );

    SetLevelWindow( level, window );
    return true;
  }
  return false;
}

bool mitk::LevelWindow::operator==(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return true;
    }
  else {
    return false;
  }
}

bool mitk::LevelWindow::operator!=(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return false;
    }
  else {
    return true;
  }
}

mitk::LevelWindow& mitk::LevelWindow::operator=(const mitk::LevelWindow& levWin)
{
  if (this == &levWin) {
    return *this;
  }
  else {
    m_RangeMin = levWin.GetRangeMin();
    m_RangeMax = levWin.GetRangeMax();
    m_Min= levWin.GetMin();
    m_Max= levWin.GetMax();
    return *this;
  }
}
<commit_msg>FIX: additional problem with auto level/window<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkLevelWindow.h"
#include "mitkImageSliceSelector.h"

#include <ipFunc/ipFunc.h>
#include <algorithm>

mitk::LevelWindow::LevelWindow(mitk::ScalarType level, mitk::ScalarType window) : m_Min(level-window/2.0), m_Max(level+window/2.0), m_RangeMin(-1024), m_RangeMax(4096)
{

}

mitk::LevelWindow::LevelWindow(const mitk::LevelWindow& levWin)
{
  *this=levWin;
}

mitk::LevelWindow::~LevelWindow()
{
}

mitk::ScalarType mitk::LevelWindow::GetLevel() const
{
  return (m_Max-m_Min)/2.0 + m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetWindow() const
{
  return (m_Max-m_Min);
}

mitk::ScalarType mitk::LevelWindow::GetMin() const
{
  return m_Min;
}

mitk::ScalarType mitk::LevelWindow::GetMax() const
{
  return m_Max;
}

void mitk::LevelWindow::SetLevel(mitk::ScalarType level)
{
  mitk::ScalarType halfWindow = (m_Max - m_Min) / 2;
  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetWindow(mitk::ScalarType window)
{
  mitk::ScalarType level = m_Min + (m_Max - m_Min) / 2;
  mitk::ScalarType halfWindow = window / 2;

  m_Min = level - halfWindow;
  m_Max = level + halfWindow;

  testValues();
}

void mitk::LevelWindow::SetLevelWindow(mitk::ScalarType level, mitk::ScalarType window)
{
  m_Min = level - window / 2.0;
  m_Max = level + window / 2.0;

  testValues();
}

void mitk::LevelWindow::SetMin(mitk::ScalarType min)
{
  m_Min = min;
  testValues();
}

void mitk::LevelWindow::SetMax(mitk::ScalarType max)
{
  m_Max = max;
  testValues();
}

void mitk::LevelWindow::SetMinMax(mitk::ScalarType min, mitk::ScalarType max)
{
  if(min>max)
    std::swap(min,max);

  SetMin(min);
  SetMax(max);
}

void mitk::LevelWindow::SetRangeMin(mitk::ScalarType min)
{
  m_RangeMin = min;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

void mitk::LevelWindow::SetRangeMax(mitk::ScalarType max)
{
  m_RangeMax = max;
  if(m_RangeMin > m_RangeMax)
    std::swap(m_RangeMin,m_RangeMax);
  testValues();
}

mitk::ScalarType mitk::LevelWindow::GetRangeMin() const
{
  return m_RangeMin;
}

mitk::ScalarType mitk::LevelWindow::GetRangeMax() const
{
  return m_RangeMax;
}

mitk::ScalarType mitk::LevelWindow::GetRange() const
{
  return  m_RangeMax - m_RangeMin;
}

void mitk::LevelWindow::SetAuto(mitk::Image* image, bool tryPicTags, bool guessByCentralSlice)
{
  if( image == NULL )
    return;

  if(tryPicTags)
  {
    if(SetAutoByPicTags(image->GetPic()))
      return;
  }

  mitk::Image* wholeImage = image;
  if(guessByCentralSlice)
  {
    mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New();
      sliceSelector->SetInput(image);
      sliceSelector->SetSliceNr(image->GetDimension(2)/2);
      sliceSelector->SetTimeNr(image->GetDimension(3)/2);
      sliceSelector->SetChannelNr(image->GetDimension(4)/2);
      sliceSelector->Update();

    image = sliceSelector->GetOutput();
  }
  ScalarType minValue = image->GetScalarValue2ndMin();
  ScalarType maxValue = image->GetScalarValue2ndMaxNoRecompute();
  if (minValue == maxValue)
  {
      // guessByCentralSlice seems to have failed, lets look at all data
      minValue = wholeImage->GetScalarValue2ndMin();
      maxValue = wholeImage->GetScalarValue2ndMaxNoRecompute();
  }
  if (minValue == maxValue)
  {
    maxValue = minValue+1;
  }
  SetRangeMin(minValue);
  SetRangeMax(maxValue);
  SetMinMax(minValue, maxValue);
}

bool mitk::LevelWindow::SetAutoByPicTags(const ipPicDescriptor* aPic)
{
  ipPicDescriptor* pic = const_cast<ipPicDescriptor*>(aPic);
  if ( pic == NULL )
  {
    return false;
  }
  ipPicTSV_t *tsv = ipPicQueryTag( pic, "LEVEL/WINDOW" );
  if( tsv != NULL )
  {
    double level = 0;
    double window = 0;
    #define GET_C_W( type, tsv, C, W )    \
      level = ((type *)tsv->value)[0];    \
      window = ((type *)tsv->value)[1];

    ipPicFORALL_2( GET_C_W, tsv, level, window );

    SetLevelWindow( level, window );
    return true;
  }
  return false;
}

bool mitk::LevelWindow::operator==(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return true;
    }
  else {
    return false;
  }
}

bool mitk::LevelWindow::operator!=(const mitk::LevelWindow& levWin) const
{
  if ( m_RangeMin == levWin.GetRangeMin() &&
    m_RangeMax == levWin.GetRangeMax() &&
    m_Min == levWin.GetMin() && m_Max == levWin.GetMax()) {

      return false;
    }
  else {
    return true;
  }
}

mitk::LevelWindow& mitk::LevelWindow::operator=(const mitk::LevelWindow& levWin)
{
  if (this == &levWin) {
    return *this;
  }
  else {
    m_RangeMin = levWin.GetRangeMin();
    m_RangeMax = levWin.GetRangeMax();
    m_Min= levWin.GetMin();
    m_Max= levWin.GetMax();
    return *this;
  }
}
<|endoftext|>


<commit_before>/*
* Pedis 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.
*
* You may obtain a copy of the License at
*
*     http://www.gnu.org/licenses
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*  Copyright (c) 2016-2026, Peng Jian, pstack@163.com. All rights reserved.
*
*/
#include "token_ring_manager.hh"
const std::vector<inet_address>& token_ring_manager::get_target_endpoints_for_key(const redis_key& rk) const
{
}

size_t token_ring_manager::token_to_index(const token& t) const
{
    assert(_sorted_tokens.empty() == false);
    auto it = std::lower_bound(_sorted_tokens.begin(), _sorted_tokens.end(), t);
    if (it == _sorted_tokens.end()) {
        return 0;
    }
    return std::distance(_sorted_tokens.begin(), it);
}

const std::vector<inet_address> token_ring_manager::get_replica_nodes_internal(const redis_key& rk) const
{
    auto first_token_index = token_to_index(token{ rk.hash() });
    auto& first_token = _sorted_tokens[first_token_index];
    auto targets = _token_write_targets_endpoints_cache.find(first_token);
    if (targets != _token_write_targets_endpoints_cache.end()) {
        return *targets;
    }
    std::vector<inet_address> new_targets;
    new_targets.reserve(_replica_count);

    auto all_tokens = _sorted_tokens.size();
    for (size_t i = 0; i < _replica_count; ++i) {
        new_targets.emplace_back(_token_to_endpoint[_sorted_tokens[(i + first_token_index) % all_tokens]]);
    }
    // cache the result
    _token_write_targets_endpoints_cache[first_token] = new_targets;
    return new_targets;
}

const std::vector<inet_address>& token_ring_manager::get_replica_nodes_for_write(const redis_key& rk) const
{
    return get_replica_nodes_internal(rk);
}

const inet_address token_ring_manager::get_replica_node_for_read(const redis_key& rk) const
{
    auto first_token_index = token_to_index(token{ rk.hash() });
    auto& first_token = _sorted_tokens[first_token_index];
    auto targets = _token_read_targets_endpoints_cache.find(first_token);
    if (targets != _token_read_targets_endpoints_cache.end()) {
        return *targets;
    }
    auto target = _token_to_endpoint[first_token_index];
    _token_read_targets_endpoints_cache[first_token] = target;
    return target;
}

void token_ring_manager::set_sorted_tokens(const std::vector<token>& tokens, const std::unordered_map<token, inet_address>& token_to_endpoint)
{
    _sorted_tokens = tokens;
    _token_to_endpoint = token_to_endpoint;
    _token_to_targets_endpoints_cache.clear();
}
<commit_msg>fix: collect the address of replica nodes<commit_after>/*
* Pedis 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.
*
* You may obtain a copy of the License at
*
*     http://www.gnu.org/licenses
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*
*  Copyright (c) 2016-2026, Peng Jian, pstack@163.com. All rights reserved.
*
*/
#include "token_ring_manager.hh"
const std::vector<inet_address>& token_ring_manager::get_target_endpoints_for_key(const redis_key& rk) const
{
}

size_t token_ring_manager::token_to_index(const token& t) const
{
    assert(_sorted_tokens.empty() == false);
    auto it = std::lower_bound(_sorted_tokens.begin(), _sorted_tokens.end(), t);
    if (it == _sorted_tokens.end()) {
        return 0;
    }
    return std::distance(_sorted_tokens.begin(), it);
}

const std::vector<inet_address> token_ring_manager::get_replica_nodes_internal(const redis_key& rk) const
{
    auto first_token_index = token_to_index(token{ rk.hash() });
    auto& first_token = _sorted_tokens[first_token_index];
    auto targets = _token_write_targets_endpoints_cache.find(first_token);
    if (targets != _token_write_targets_endpoints_cache.end()) {
        return *targets;
    }
    std::vector<inet_address> new_targets;
    new_targets.reserve(_replica_count);

    new_targets.emplace_back(_token_to_endpoint[first_token]);
    auto all_tokens = _sorted_tokens.size();
    for (size_t i = 1; i < _replica_count; ++i) {
        new_targets.emplace_back(_token_to_endpoint[_sorted_tokens[(i + first_token_index) % all_tokens]]);
    }
    // cache the result
    _token_write_targets_endpoints_cache[first_token] = new_targets;
    return new_targets;
}

const std::vector<inet_address>& token_ring_manager::get_replica_nodes_for_write(const redis_key& rk) const
{
    return get_replica_nodes_internal(rk);
}

const inet_address token_ring_manager::get_replica_node_for_read(const redis_key& rk) const
{
    auto first_token_index = token_to_index(token{ rk.hash() });
    auto& first_token = _sorted_tokens[first_token_index];
    auto targets = _token_read_targets_endpoints_cache.find(first_token);
    if (targets != _token_read_targets_endpoints_cache.end()) {
        return *targets;
    }
    auto target = _token_to_endpoint[first_token_index];
    _token_read_targets_endpoints_cache[first_token] = target;
    return target;
}

void token_ring_manager::set_sorted_tokens(const std::vector<token>& tokens, const std::unordered_map<token, inet_address>& token_to_endpoint)
{
    _sorted_tokens = tokens;
    _token_to_endpoint = token_to_endpoint;
    _token_to_targets_endpoints_cache.clear();
}
<|endoftext|>


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

#include <fstream>
#include <iostream>
#include "add_testcase.h"

void
add_testcase::add_known_testcase(std::string option,
                                 std::string util_with_section,
                                 std::string descr,
                                 std::string output,
                                 std::ofstream& test_script)
{
  std::string testcase_name;
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  // Add testcase name.
  test_script << "atf_test_case ";
  if (!option.empty()) {
    testcase_name = option;
    testcase_name.append("_flag");
  }
  else
    testcase_name = "no_arguments";
  test_script << testcase_name + "\n";

  // Add testcase description.
  test_script << testcase_name
               + "_head()\n{\n\tatf_set \"descr\" ";
  if (!descr.empty())
    test_script << descr;
  else
    test_script << "\"Verify the usage of option \'" + option + "\'\"";
  test_script << "\n}\n\n";

  // Add body of the testcase.
  test_script << testcase_name + "_body()\n{"
               + "\n\tatf_check -s exit:0 -o ";

  // Match the usage output if generated.
  if (!output.empty())
    test_script << "inline:\"" + output + "\" ";
  else
    test_script << "empty ";
  test_script << utility;
  if (!option.empty())
    test_script << " -" + option;
  test_script << "\n}\n\n";
}

void
add_testcase::add_unknown_testcase(std::string option,
                                   std::string util_with_section,
                                   std::string output,
                                   int exitstatus,
                                   std::string& testcase_buffer)
{
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  testcase_buffer.append("\n\tatf_check -s not-exit:0 -e ");

  // Check if a usage message was produced.
  if (!output.compare(0, 6, "usage:"))
    testcase_buffer.append("regex:\"$usage_output\" ");
  else if (!output.empty())
    testcase_buffer.append("inline:\"" + output + "\" ");
  else
    testcase_buffer.append("empty ");

  testcase_buffer.append(utility);

  if (!option.empty())
    testcase_buffer.append(" -" + option);
}

void
add_testcase::add_noargs_testcase(std::string util_with_section,
                                  std::pair<std::string, int> output,
                                  std::ofstream& test_script)
{
  std::string descr;
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  if (output.second) {
    // An error was encountered.
    test_script << std::string("atf_test_case no_arguments\n")
                  + "no_arguments_head()\n{\n\tatf_set \"descr\" ";
    if (!output.first.empty()) {
      // We expect a usage message to be generated in this case.
      if (!output.first.compare(0, 6, "usage:")) {
        descr = "\"Verify that " + util_with_section
              + " fails and generates a valid usage"
              + " message when no arguments are supplied\"";

        test_script << descr + "\n}\n\nno_arguments_body()\n{"
                      + "\n\tatf_check -s not-exit:0 -e regex:\"$usage_output\" "
                      + utility;
      }
      else {
        descr = "\"Verify that " + util_with_section
              + " fails and generates a valid output"
              + " when no arguments are supplied\"";

        test_script << descr + "\n}\n\nno_arguments_body()\n{"
                      + "\n\tatf_check -s not-exit:0 -e inline:\""
                      + output.first + "\" "
                      + utility;
      }
    }

    else {
      descr = "\"Verify that " + util_with_section
            + "fails silently when no arguments are supplied\"" ;
      test_script << descr + "\n}\n\nno_arguments_body()\n{"
                    + "\n\tatf_check -s not-exit:0 -e empty "
                    + utility;
    }

    test_script << "\n}\n\n";
  }

  else {
    // The command ran successfully, hence we guessed
    // a correct usage for the utility under test.
    if (!output.first.empty())
      descr = "\"Verify that " + util_with_section
            + " executes successfully and produces a valid"
            + " output when invoked without any arguments\"";
    else
      descr = "\"Verify that " + util_with_section
            + " executes successfully and silently"
            + " when invoked without any arguments\"";

    add_testcase::add_known_testcase("", util_with_section, descr,
                                     output.first, test_script);
  }
}
<commit_msg>Fix typo: "regex" => "match"<commit_after>//
// Copyright 2017 Shivansh Rai
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// $FreeBSD$

#include <fstream>
#include <iostream>
#include "add_testcase.h"

void
add_testcase::add_known_testcase(std::string option,
                                 std::string util_with_section,
                                 std::string descr,
                                 std::string output,
                                 std::ofstream& test_script)
{
  std::string testcase_name;
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  // Add testcase name.
  test_script << "atf_test_case ";
  if (!option.empty()) {
    testcase_name = option;
    testcase_name.append("_flag");
  }
  else
    testcase_name = "no_arguments";
  test_script << testcase_name + "\n";

  // Add testcase description.
  test_script << testcase_name
               + "_head()\n{\n\tatf_set \"descr\" ";
  if (!descr.empty())
    test_script << descr;
  else
    test_script << "\"Verify the usage of option \'" + option + "\'\"";
  test_script << "\n}\n\n";

  // Add body of the testcase.
  test_script << testcase_name + "_body()\n{"
               + "\n\tatf_check -s exit:0 -o ";

  // Match the usage output if generated.
  if (!output.empty())
    test_script << "inline:\"" + output + "\" ";
  else
    test_script << "empty ";
  test_script << utility;
  if (!option.empty())
    test_script << " -" + option;
  test_script << "\n}\n\n";
}

void
add_testcase::add_unknown_testcase(std::string option,
                                   std::string util_with_section,
                                   std::string output,
                                   int exitstatus,
                                   std::string& testcase_buffer)
{
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  testcase_buffer.append("\n\tatf_check -s not-exit:0 -e ");

  // Check if a usage message was produced.
  if (!output.compare(0, 6, "usage:"))
    testcase_buffer.append("match:\"$usage_output\" ");
  else if (!output.empty())
    testcase_buffer.append("inline:\"" + output + "\" ");
  else
    testcase_buffer.append("empty ");

  testcase_buffer.append(utility);

  if (!option.empty())
    testcase_buffer.append(" -" + option);
}

void
add_testcase::add_noargs_testcase(std::string util_with_section,
                                  std::pair<std::string, int> output,
                                  std::ofstream& test_script)
{
  std::string descr;
  std::string utility = util_with_section.substr(0,
                        util_with_section.length() - 3);

  if (output.second) {
    // An error was encountered.
    test_script << std::string("atf_test_case no_arguments\n")
                  + "no_arguments_head()\n{\n\tatf_set \"descr\" ";
    if (!output.first.empty()) {
      // We expect a usage message to be generated in this case.
      if (!output.first.compare(0, 6, "usage:")) {
        descr = "\"Verify that " + util_with_section
              + " fails and generates a valid usage"
              + " message when no arguments are supplied\"";

        test_script << descr + "\n}\n\nno_arguments_body()\n{"
                      + "\n\tatf_check -s not-exit:0 -e match:\"$usage_output\" "
                      + utility;
      }
      else {
        descr = "\"Verify that " + util_with_section
              + " fails and generates a valid output"
              + " when no arguments are supplied\"";

        test_script << descr + "\n}\n\nno_arguments_body()\n{"
                      + "\n\tatf_check -s not-exit:0 -e inline:\""
                      + output.first + "\" "
                      + utility;
      }
    }

    else {
      descr = "\"Verify that " + util_with_section
            + "fails silently when no arguments are supplied\"" ;
      test_script << descr + "\n}\n\nno_arguments_body()\n{"
                    + "\n\tatf_check -s not-exit:0 -e empty "
                    + utility;
    }

    test_script << "\n}\n\n";
  }

  else {
    // The command ran successfully, hence we guessed
    // a correct usage for the utility under test.
    if (!output.first.empty())
      descr = "\"Verify that " + util_with_section
            + " executes successfully and produces a valid"
            + " output when invoked without any arguments\"";
    else
      descr = "\"Verify that " + util_with_section
            + " executes successfully and silently"
            + " when invoked without any arguments\"";

    add_testcase::add_known_testcase("", util_with_section, descr,
                                     output.first, test_script);
  }
}
<|endoftext|>


<commit_before>#include "graphicalModel.h"

#include "logicalModel.h"

#include <QtCore/QUuid>
#include <QtCore/QDebug>

using namespace qReal;
using namespace models;
using namespace models::details;
using namespace modelsImplementation;

GraphicalModel::GraphicalModel(qrRepo::GraphicalRepoApi *repoApi, const EditorManager &editorManager)
	: AbstractModel(editorManager), mLogicalModelView(this), mApi(*repoApi)
{
	mRootItem = new GraphicalModelItem(Id::rootId(), Id(), NULL);
	init();
	mGraphicalAssistApi = new GraphicalModelAssistApi(*this, editorManager);
}

GraphicalModel::~GraphicalModel()
{
	delete mGraphicalAssistApi;
	cleanupTree(mRootItem);
}

void GraphicalModel::init()
{
	mModelItems.insert(Id::rootId(), mRootItem);
	mApi.setName(Id::rootId(), Id::rootId().toString());
	// Turn off view notification while loading. Model can be inconsistent during a process,
	// so views shall not update themselves before time. It is important for
	// scene, where adding edge before adding nodes may lead to disconnected edge.	blockSignals(true);
	blockSignals(true);
	loadSubtreeFromClient(static_cast<GraphicalModelItem *>(mRootItem));
	blockSignals(false);
}

void GraphicalModel::loadSubtreeFromClient(GraphicalModelItem * const parent)
{
	foreach (Id childId, mApi.children(parent->id())) {
		if (mApi.isGraphicalElement(childId)) {
			GraphicalModelItem *child = loadElement(parent, childId);
			loadSubtreeFromClient(child);
		}
	}
}

GraphicalModelItem *GraphicalModel::loadElement(GraphicalModelItem *parentItem, Id const &id)
{
	int newRow = parentItem->children().size();

	beginInsertRows(index(parentItem), newRow, newRow);
	Id const logicalId = mApi.logicalId(id);
	GraphicalModelItem *item = new GraphicalModelItem(id, logicalId, parentItem);
	parentItem->addChild(item);
	mModelItems.insert(id, item);
	endInsertRows();

	return item;
}

void GraphicalModel::connectToLogicalModel(LogicalModel * const logicalModel)
{
	mLogicalModelView.setModel(logicalModel);
}

AbstractModelItem *GraphicalModel::createModelItem(Id const &id, AbstractModelItem *parentItem) const
{
	return new GraphicalModelItem(id, Id(id.type(), QUuid::createUuid().toString())
								  , static_cast<GraphicalModelItem *>(parentItem));
}

void GraphicalModel::updateElements(Id const &logicalId, QString const &name)
{
	foreach (AbstractModelItem *item,  mModelItems.values()) {
		GraphicalModelItem *graphicalItem = static_cast<GraphicalModelItem *>(item);
		if (graphicalItem->logicalId() == logicalId) {
			mApi.setName(graphicalItem->id(), name);
			emit dataChanged(index(graphicalItem), index(graphicalItem));
		}
	}
}

void GraphicalModel::addElementToModel(const Id &parent, const Id &id
		, const Id &logicalId, const QString &name, const QPointF &position)
{
	Q_ASSERT_X(mModelItems.contains(parent), "addElementToModel", "Adding element to non-existing parent");
	AbstractModelItem *parentItem = mModelItems[parent];

	GraphicalModelItem *newGraphicalModelItem = NULL;
	Id actualLogicalId = logicalId;
	if (logicalId == Id::rootId()) {
		AbstractModelItem *newItem = createModelItem(id, parentItem);
		newGraphicalModelItem = static_cast<GraphicalModelItem *>(newItem);
		actualLogicalId = newGraphicalModelItem->logicalId();
	} else {
		GraphicalModelItem *graphicalParentItem = static_cast<GraphicalModelItem *>(parentItem);
		newGraphicalModelItem = new GraphicalModelItem(id, logicalId, graphicalParentItem);
	}
	initializeElement(id, actualLogicalId, parentItem, newGraphicalModelItem, name, position);
}

void GraphicalModel::initializeElement(const Id &id, const Id &logicalId, modelsImplementation::AbstractModelItem *parentItem
		, modelsImplementation::AbstractModelItem *item, const QString &name, const QPointF &position)
{
	int const newRow = parentItem->children().size();

	beginInsertRows(index(parentItem), newRow, newRow);
	parentItem->addChild(item);
	mApi.addChild(parentItem->id(), id, logicalId);
	mApi.setName(id, name);
	mApi.setFromPort(id, 0.0);
	mApi.setToPort(id, 0.0);
	mApi.setFrom(id, Id::rootId());
	mApi.setTo(id, Id::rootId());
	mApi.setProperty(id, "links", IdListHelper::toVariant(IdList()));
	mApi.setPosition(id, position);
	mApi.setConfiguration(id, QVariant(QPolygon()));
	mModelItems.insert(id, item);
	endInsertRows();
}

QVariant GraphicalModel::data(const QModelIndex &index, int role) const
{
	if (index.isValid()) {
		GraphicalModelItem *item = static_cast<GraphicalModelItem*>(index.internalPointer());
		Q_ASSERT(item);
		switch (role) {
		case Qt::DisplayRole:
		case Qt::EditRole:
			return mApi.name(item->id());
		case Qt::DecorationRole:
			return mEditorManager.icon(item->id());
		case roles::idRole:
			return item->id().toVariant();
		case roles::logicalIdRole:
			return item->logicalId().toVariant();
		case roles::positionRole:
			return mApi.position(item->id());
		case roles::fromRole:
			return mApi.from(item->id()).toVariant();
		case roles::toRole:
			return mApi.to(item->id()).toVariant();
		case roles::fromPortRole:
			return mApi.fromPort(item->id());
		case roles::toPortRole:
			return mApi.toPort(item->id());
		case roles::configurationRole:
			return mApi.configuration(item->id());
		}
		if (role >= roles::customPropertiesBeginRole) {
			return QVariant();  // Custom properties are invalid for graphical objects for now.
		}
		Q_ASSERT(role < Qt::UserRole);
		return QVariant();
	} else {
		return QVariant();
	}
}

bool GraphicalModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if (index.isValid()) {
		AbstractModelItem *item = static_cast<AbstractModelItem *>(index.internalPointer());
		switch (role) {
		case Qt::DisplayRole:
		case Qt::EditRole:
			mApi.setName(item->id(), value.toString());
			emit nameChanged(item->id());
			break;
		case roles::positionRole:
			mApi.setPosition(item->id(), value);
			break;
		case roles::configurationRole:
			mApi.setConfiguration(item->id(), value);
			break;
		case roles::fromRole:
			mApi.setFrom(item->id(), value.value<Id>());
			break;
		case roles::toRole:
			mApi.setTo(item->id(), value.value<Id>());
			break;
		case roles::fromPortRole:
			mApi.setFromPort(item->id(), value.toDouble());
			break;
		case roles::toPortRole:
			mApi.setToPort(item->id(), value.toDouble());
			break;
		default:
			if (role >= roles::customPropertiesBeginRole) {
				QString selectedProperty = findPropertyName(item->id(), role);
				mApi.setProperty(item->id(), selectedProperty, value);
				break;
			}
			Q_ASSERT(role < Qt::UserRole);
			return false;
		}
		emit dataChanged(index, index);
		return true;
	}
	return false;
}

void GraphicalModel::changeParent(QModelIndex const &element, QModelIndex const &parent, QPointF const &position)
{
	if (!parent.isValid() || element.parent() == parent) {
		return;
	}

	int destinationRow = parentAbstractItem(parent)->children().size();

	if (beginMoveRows(element.parent(), element.row(), element.row(), parent, destinationRow)) {
		AbstractModelItem *elementItem = static_cast<AbstractModelItem*>(element.internalPointer());
		QVariant configuration = mApi.configuration(elementItem->id());
		elementItem->parent()->removeChild(elementItem);
		AbstractModelItem *parentItem = parentAbstractItem(parent);

		mApi.setParent(elementItem->id(), parentItem->id());

		elementItem->setParent(parentItem);

		parentItem->addChild(elementItem);

		mApi.setPosition(elementItem->id(), position);
		mApi.setConfiguration(elementItem->id(), configuration);
		endMoveRows();
		if (parent.row() < element.row())
			emit dataChanged(parent, element);
	}
}

void GraphicalModel::stackBefore(const QModelIndex &element, const QModelIndex &sibling)
{
	if (element == sibling) {
		return;
	}

	if (beginMoveRows(element.parent(), element.row(), element.row(), element.parent(), sibling.row())) {
		AbstractModelItem *parent = static_cast<AbstractModelItem *>(element.parent().internalPointer()),
			*item = static_cast<AbstractModelItem *>(element.internalPointer()),
			*siblingItem = static_cast<AbstractModelItem *>(sibling.internalPointer());

		parent->stackBefore(item, siblingItem);
		mApi.stackBefore(parent->id(), item->id(), siblingItem->id());
		endMoveRows();
	} else {
		qDebug() << "GraphicalModel::stackBefore : problem with beginMoveRows";
	}
}

qrRepo::GraphicalRepoApi const &GraphicalModel::api() const
{
	return mApi;
}

qrRepo::GraphicalRepoApi &GraphicalModel::mutableApi() const
{
	return mApi;
}

GraphicalModelAssistApi &GraphicalModel::graphicalModelAssistApi() const
{
	return *mGraphicalAssistApi;
}

bool GraphicalModel::removeRows(int row, int count, QModelIndex const &parent)
{
	AbstractModelItem *parentItem = parentAbstractItem(parent);
	if (parentItem->children().size() < row + count)
		return false;
	else {
		for (int i = row; i < row + count; ++i) {
			AbstractModelItem *child = parentItem->children().at(i);
			removeModelItems(child);

			int childRow = child->row();
			beginRemoveRows(parent, childRow, childRow);
			child->parent()->removeChild(child);
			mModelItems.remove(child->id());
			mApi.removeChild(parentItem->id(), child->id());
			mApi.removeElement(child->id());
			delete child;
			endRemoveRows();
		}
		return true;
	}
}

void GraphicalModel::removeModelItemFromApi(details::modelsImplementation::AbstractModelItem *const root, details::modelsImplementation::AbstractModelItem *child)
{
	mApi.removeProperty(child->id(), "position");
	mApi.removeProperty(child->id(), "configuration");
	if (mModelItems.count(child->id()) == 0) {
		mApi.removeChild(root->id(),child->id());
	}
	mApi.removeElement(child->id());
}

QList<QPersistentModelIndex> GraphicalModel::indexesWithLogicalId(Id const &logicalId) const
{
	QList<QPersistentModelIndex> indexes;
	foreach (AbstractModelItem *item, mModelItems.values()) {
		if (static_cast<GraphicalModelItem *>(item)->logicalId() == logicalId)
			indexes.append(index(item));
	}
	return indexes;
}

qReal::details::ModelsAssistInterface* GraphicalModel::modelAssistInterface() const
{
	return mGraphicalAssistApi;
}
<commit_msg>поправлено немного в синхронизации<commit_after>#include "graphicalModel.h"

#include "logicalModel.h"

#include <QtCore/QUuid>
#include <QtCore/QDebug>

using namespace qReal;
using namespace models;
using namespace models::details;
using namespace modelsImplementation;

GraphicalModel::GraphicalModel(qrRepo::GraphicalRepoApi *repoApi, const EditorManager &editorManager)
	: AbstractModel(editorManager), mLogicalModelView(this), mApi(*repoApi)
{
	mRootItem = new GraphicalModelItem(Id::rootId(), Id(), NULL);
	init();
	mGraphicalAssistApi = new GraphicalModelAssistApi(*this, editorManager);
}

GraphicalModel::~GraphicalModel()
{
	delete mGraphicalAssistApi;
	cleanupTree(mRootItem);
}

void GraphicalModel::init()
{
	mModelItems.insert(Id::rootId(), mRootItem);
	mApi.setName(Id::rootId(), Id::rootId().toString());
	// Turn off view notification while loading. Model can be inconsistent during a process,
	// so views shall not update themselves before time. It is important for
	// scene, where adding edge before adding nodes may lead to disconnected edge.	blockSignals(true);
	blockSignals(true);
	loadSubtreeFromClient(static_cast<GraphicalModelItem *>(mRootItem));
	blockSignals(false);
}

void GraphicalModel::loadSubtreeFromClient(GraphicalModelItem * const parent)
{
	foreach (Id childId, mApi.children(parent->id())) {
		if (mApi.isGraphicalElement(childId)) {
			GraphicalModelItem *child = loadElement(parent, childId);
			loadSubtreeFromClient(child);
		}
	}
}

GraphicalModelItem *GraphicalModel::loadElement(GraphicalModelItem *parentItem, Id const &id)
{
	int newRow = parentItem->children().size();

	beginInsertRows(index(parentItem), newRow, newRow);
	Id const logicalId = mApi.logicalId(id);
	GraphicalModelItem *item = new GraphicalModelItem(id, logicalId, parentItem);
	parentItem->addChild(item);
	mModelItems.insert(id, item);
	endInsertRows();

	return item;
}

void GraphicalModel::connectToLogicalModel(LogicalModel * const logicalModel)
{
	mLogicalModelView.setModel(logicalModel);
}

AbstractModelItem *GraphicalModel::createModelItem(Id const &id, AbstractModelItem *parentItem) const
{
	return new GraphicalModelItem(id, Id(id.type(), QUuid::createUuid().toString())
								  , static_cast<GraphicalModelItem *>(parentItem));
}

void GraphicalModel::updateElements(Id const &logicalId, QString const &name)
{
	foreach (AbstractModelItem *item,  mModelItems.values()) {
		GraphicalModelItem *graphicalItem = static_cast<GraphicalModelItem *>(item);
		if (graphicalItem->logicalId() == logicalId) {
			mApi.setName(graphicalItem->id(), name);
			emit dataChanged(index(graphicalItem), index(graphicalItem));
		}
	}
}

void GraphicalModel::addElementToModel(const Id &parent, const Id &id
		, const Id &logicalId, const QString &name, const QPointF &position)
{
	Q_ASSERT_X(mModelItems.contains(parent), "addElementToModel", "Adding element to non-existing parent");
	AbstractModelItem *parentItem = mModelItems[parent];

	GraphicalModelItem *newGraphicalModelItem = NULL;
	Id actualLogicalId = logicalId;
	if (logicalId == Id::rootId()) {
		AbstractModelItem *newItem = createModelItem(id, parentItem);
		newGraphicalModelItem = static_cast<GraphicalModelItem *>(newItem);
		actualLogicalId = newGraphicalModelItem->logicalId();
	} else {
		GraphicalModelItem *graphicalParentItem = static_cast<GraphicalModelItem *>(parentItem);
		newGraphicalModelItem = new GraphicalModelItem(id, logicalId, graphicalParentItem);
	}
	initializeElement(id, actualLogicalId, parentItem, newGraphicalModelItem, name, position);
}

void GraphicalModel::initializeElement(const Id &id, const Id &logicalId, modelsImplementation::AbstractModelItem *parentItem
		, modelsImplementation::AbstractModelItem *item, const QString &name, const QPointF &position)
{
	int const newRow = parentItem->children().size();

	beginInsertRows(index(parentItem), newRow, newRow);
	parentItem->addChild(item);
	mApi.addChild(parentItem->id(), id, logicalId);
	mApi.setName(id, name);
	mApi.setFromPort(id, 0.0);
	mApi.setToPort(id, 0.0);
	mApi.setFrom(id, Id::rootId());
	mApi.setTo(id, Id::rootId());
	mApi.setProperty(id, "links", IdListHelper::toVariant(IdList()));
	mApi.setPosition(id, position);
	mApi.setConfiguration(id, QVariant(QPolygon()));
	mModelItems.insert(id, item);
	endInsertRows();
}

QVariant GraphicalModel::data(const QModelIndex &index, int role) const
{
	if (index.isValid()) {
		GraphicalModelItem *item = static_cast<GraphicalModelItem*>(index.internalPointer());
		Q_ASSERT(item);
		switch (role) {
		case Qt::DisplayRole:
		case Qt::EditRole:
			return mApi.name(item->id());
		case Qt::DecorationRole:
			return mEditorManager.icon(item->id());
		case roles::idRole:
			return item->id().toVariant();
		case roles::logicalIdRole:
			return item->logicalId().toVariant();
		case roles::positionRole:
			return mApi.position(item->id());
		case roles::fromRole:
			return mApi.from(item->id()).toVariant();
		case roles::toRole:
			return mApi.to(item->id()).toVariant();
		case roles::fromPortRole:
			return mApi.fromPort(item->id());
		case roles::toPortRole:
			return mApi.toPort(item->id());
		case roles::configurationRole:
			return mApi.configuration(item->id());
		}
		if (role >= roles::customPropertiesBeginRole) {
			return QVariant();  // Custom properties are invalid for graphical objects for now.
		}
		Q_ASSERT(role < Qt::UserRole);
		return QVariant();
	} else {
		return QVariant();
	}
}

bool GraphicalModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if (index.isValid()) {
		AbstractModelItem *item = static_cast<AbstractModelItem *>(index.internalPointer());
		switch (role) {
		case Qt::DisplayRole:
		case Qt::EditRole:
			mApi.setName(item->id(), value.toString());
			emit nameChanged(item->id());
			break;
		case roles::positionRole:
			mApi.setPosition(item->id(), value);
			break;
		case roles::configurationRole:
			mApi.setConfiguration(item->id(), value);
			break;
		case roles::fromRole:
			mApi.setFrom(item->id(), value.value<Id>());
			break;
		case roles::toRole:
			mApi.setTo(item->id(), value.value<Id>());
			break;
		case roles::fromPortRole:
			mApi.setFromPort(item->id(), value.toDouble());
			break;
		case roles::toPortRole:
			mApi.setToPort(item->id(), value.toDouble());
			break;
		default:
			if (role >= roles::customPropertiesBeginRole) {
				QString selectedProperty = findPropertyName(item->id(), role);
				mApi.setProperty(item->id(), selectedProperty, value);
				break;
			}
			Q_ASSERT(role < Qt::UserRole);
			return false;
		}
		emit dataChanged(index, index);
		return true;
	}
	return false;
}

void GraphicalModel::changeParent(QModelIndex const &element, QModelIndex const &parent, QPointF const &position)
{
	if (!parent.isValid() || element.parent() == parent) {
		return;
	}

	int destinationRow = parentAbstractItem(parent)->children().size();

	if (beginMoveRows(element.parent(), element.row(), element.row(), parent, destinationRow)) {
		AbstractModelItem *elementItem = static_cast<AbstractModelItem*>(element.internalPointer());
		QVariant configuration = mApi.configuration(elementItem->id());
		elementItem->parent()->removeChild(elementItem);
		AbstractModelItem *parentItem = parentAbstractItem(parent);

		mApi.setParent(elementItem->id(), parentItem->id());

		elementItem->setParent(parentItem);

		parentItem->addChild(elementItem);

		mApi.setPosition(elementItem->id(), position);
		mApi.setConfiguration(elementItem->id(), configuration);
		endMoveRows();
		if (parent.row() != element.row())
			emit dataChanged(parent, element);
	}
}

void GraphicalModel::stackBefore(const QModelIndex &element, const QModelIndex &sibling)
{
	if (element == sibling) {
		return;
	}

	if (beginMoveRows(element.parent(), element.row(), element.row(), element.parent(), sibling.row())) {
		AbstractModelItem *parent = static_cast<AbstractModelItem *>(element.parent().internalPointer()),
			*item = static_cast<AbstractModelItem *>(element.internalPointer()),
			*siblingItem = static_cast<AbstractModelItem *>(sibling.internalPointer());

		parent->stackBefore(item, siblingItem);
		mApi.stackBefore(parent->id(), item->id(), siblingItem->id());
		endMoveRows();
	} else {
		qDebug() << "GraphicalModel::stackBefore : problem with beginMoveRows";
	}
}

qrRepo::GraphicalRepoApi const &GraphicalModel::api() const
{
	return mApi;
}

qrRepo::GraphicalRepoApi &GraphicalModel::mutableApi() const
{
	return mApi;
}

GraphicalModelAssistApi &GraphicalModel::graphicalModelAssistApi() const
{
	return *mGraphicalAssistApi;
}

bool GraphicalModel::removeRows(int row, int count, QModelIndex const &parent)
{
	AbstractModelItem *parentItem = parentAbstractItem(parent);
	if (parentItem->children().size() < row + count)
		return false;
	else {
		for (int i = row; i < row + count; ++i) {
			AbstractModelItem *child = parentItem->children().at(i);
			removeModelItems(child);

			int childRow = child->row();
			beginRemoveRows(parent, childRow, childRow);
			child->parent()->removeChild(child);
			mModelItems.remove(child->id());
			mApi.removeChild(parentItem->id(), child->id());
			mApi.removeElement(child->id());
			delete child;
			endRemoveRows();
		}
		return true;
	}
}

void GraphicalModel::removeModelItemFromApi(details::modelsImplementation::AbstractModelItem *const root, details::modelsImplementation::AbstractModelItem *child)
{
	mApi.removeProperty(child->id(), "position");
	mApi.removeProperty(child->id(), "configuration");
	if (mModelItems.count(child->id()) == 0) {
		mApi.removeChild(root->id(),child->id());
	}
	mApi.removeElement(child->id());
}

QList<QPersistentModelIndex> GraphicalModel::indexesWithLogicalId(Id const &logicalId) const
{
	QList<QPersistentModelIndex> indexes;
	foreach (AbstractModelItem *item, mModelItems.values()) {
		if (static_cast<GraphicalModelItem *>(item)->logicalId() == logicalId)
			indexes.append(index(item));
	}
	return indexes;
}

qReal::details::ModelsAssistInterface* GraphicalModel::modelAssistInterface() const
{
	return mGraphicalAssistApi;
}
<|endoftext|>