<commit_before>#include "cvm.h"

#include "defaults_shared.h"

DabClass &DabVM::define_builtin_class(const std::string &name, dab_class_t class_index,
                                      dab_class_t superclass_index)
{
    DabClass klass;
    klass.index            = class_index;
    klass.name             = name;
    klass.builtin          = true;
    klass.superclass_index = superclass_index;
    classes[class_index]   = klass;
    return classes[class_index];
}

void DabVM::predefine_default_classes()
{
    fprintf(stderr, "vm: predefine default classes\n");

    define_builtin_class("Object", CLASS_OBJECT);
    define_builtin_class("String", CLASS_STRING);
    define_builtin_class("Fixnum", CLASS_FIXNUM);
    define_builtin_class("Boolean", CLASS_BOOLEAN);
    define_builtin_class("NilClass", CLASS_NILCLASS);
    define_builtin_class("Array", CLASS_ARRAY);
    define_builtin_class("Uint8", CLASS_UINT8, CLASS_FIXNUM);
    define_builtin_class("Uint16", CLASS_UINT16, CLASS_FIXNUM);
    define_builtin_class("Uint32", CLASS_UINT32, CLASS_FIXNUM);
    define_builtin_class("Uint64", CLASS_UINT64, CLASS_FIXNUM);
    define_builtin_class("Int8", CLASS_INT8, CLASS_FIXNUM);
    define_builtin_class("Int16", CLASS_INT16, CLASS_FIXNUM);
    define_builtin_class("Int32", CLASS_INT32, CLASS_FIXNUM);
    define_builtin_class("Int64", CLASS_INT64, CLASS_FIXNUM);
    define_builtin_class("Method", CLASS_METHOD);
    define_builtin_class("IntPtr", CLASS_INTPTR);
    define_builtin_class("ByteBuffer", CLASS_BYTEBUFFER);
    define_builtin_class("LiteralString", CLASS_LITERALSTRING, CLASS_STRING);
    define_builtin_class("DynamicString", CLASS_DYNAMICSTRING, CLASS_STRING);
}

void DabVM::define_default_classes()
{
    fprintf(stderr, "vm: define default classes\n");

    auto &object_class = get_class(CLASS_OBJECT);
    object_class.add_static_reg_function("new", [this](DabValue self, std::vector<DabValue>) {
        auto arg = self;
        assert(arg.data.type == TYPE_CLASS);
        auto instance = arg.create_instance();
        cinstcall(instance, "__construct");
        return instance;
    });
    object_class.add_reg_function(
        "class", [](DabValue self, std::vector<DabValue>) { return self.get_class(); });
    object_class.add_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self.print_value();
    });
    object_class.add_reg_function("__construct", [](DabValue, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return nullptr;
    });
    object_class.add_reg_function("__destruct", [](DabValue, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return nullptr;
    });
    object_class.add_reg_function("is", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        return arg0.is_a(arg1.get_class());
    });
    object_class.add_static_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self.class_name();
    });
    object_class.add_static_reg_function("==", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_CLASS);
        assert(arg1.data.type == TYPE_CLASS);
        return DabValue(arg0.data.fixnum == arg1.data.fixnum);
    });

    auto &string_class = get_class(CLASS_STRING);
    string_class.add_reg_function("upcase", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto s = self.string();
        std::transform(s.begin(), s.end(), s.begin(), ::toupper);
        return s;
    });
    string_class.add_reg_function("length", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto     s = self.string();
        DabValue ret(CLASS_INT32, (int)s.size());
        return ret;
    });
    string_class.add_reg_function("[]", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = $VM->cast(args[0], CLASS_FIXNUM);
        auto s   = self.string();
        auto n   = arg.data.fixnum;
        return DabValue(s.substr(n, 1));
    });
    string_class.add_reg_function("+", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = $VM->cast(args[0], CLASS_STRING);
        auto s0   = arg0.string();
        auto s1   = arg1.string();
        return DabValue(s0 + s1);
    });
    string_class.add_static_reg_function("new", [](DabValue, std::vector<DabValue> args) {
        auto argc = args.size();
        assert(argc <= 2);
        DabValue ret_value;
        ret_value.data.type = TYPE_STRING;
        if (argc == 2)
        {
            auto        arg1   = $VM->cast(args[0], CLASS_BYTEBUFFER);
            auto        arg2   = $VM->cast(args[1], CLASS_FIXNUM);
            const auto &buffer = arg1.bytebuffer();
            const auto  length = arg2.data.fixnum;
            if (length)
            {
                ret_value.data.legacy_string = std::string((const char *)&buffer[0], length);
            }
        }
        else if (argc == 1)
        {
            ret_value.data.legacy_string = args[0].string();
        }
        return ret_value;
    });
    string_class.add_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self;
    });
    DAB_MEMBER_EQUALS_OPERATORS(string_class, CLASS_STRING, .string());
    DAB_MEMBER_COMPARE_OPERATORS(string_class, CLASS_STRING, .string());

    auto &fixnum_class = get_class(CLASS_FIXNUM);
    fixnum_class.add_static_reg_function("new", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() <= 1);
        auto     klass = self;
        DabValue ret_value;
        ret_value.data.type   = TYPE_FIXNUM;
        ret_value.data.fixnum = 0;
        if (args.size() == 1)
        {
            auto arg = args[0];
            assert(arg.data.type == TYPE_FIXNUM);
            ret_value.data.fixnum = arg.data.fixnum;
        }
        return ret_value;
    });
    DAB_MEMBER_NUMERIC_OPERATORS(fixnum_class, CLASS_FIXNUM, uint64_t, .data.fixnum);

    define_default_classes_int();

    auto &intptr_class = get_class(CLASS_INTPTR);
    intptr_class.add_reg_function("fetch_int32", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto     ptr   = self.data.intptr;
        auto     iptr  = (int32_t *)ptr;
        auto     value = *iptr;
        DabValue ret(CLASS_INT32, value);
        return ret;
    });

    auto &boolean_class = get_class(CLASS_BOOLEAN);
    DAB_MEMBER_EQUALS_OPERATORS(boolean_class, CLASS_BOOLEAN, .data.boolean);

    auto &array_class = get_class(CLASS_ARRAY);
    array_class.add_reg_function("count", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        assert(self.data.type == TYPE_ARRAY);
        return (uint64_t)self.array().size();
    });
    array_class.add_reg_function("shift", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        assert(self.data.type == TYPE_ARRAY);
        auto &a = self.array();
        if (a.size() == 0)
        {
            return DabValue(nullptr);
        }
        else
        {
            auto ret = a[0];
            a.erase(a.begin());
            return ret;
        }
    });
    array_class.add_reg_function("insert", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = args[0];
        assert(self.data.type == TYPE_ARRAY);
        auto &a = self.array();
        a.push_back(arg);
        return nullptr;
    });
    array_class.add_reg_function("[]", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_ARRAY);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.array();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
            return DabValue(nullptr);
        else
            return a[n];
    });
    array_class.add_reg_function("[]=", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 2);
        auto arg0 = self;
        auto arg1 = args[0];
        auto arg2 = args[1];
        assert(arg0.data.type == TYPE_ARRAY);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.array();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
        {
            fprintf(stderr, "vm: index outside of array bounds.\n");
            exit(1);
        }
        else
        {
            a[n] = arg2;
        }
        return nullptr;
    });
    array_class.add_reg_function("join", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        std::string ret;
        auto &      a = self.array();
        for (size_t i = 0; i < a.size(); i++)
        {
            if (i)
                ret += ", ";
            auto val = cinstcall(a[i], "to_s");
            ret += val.string();
        }
        return ret;
    });
    array_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto inner = cinstcall(self, "join");
        return std::string("[" + inner.string() + "]");
    });
    array_class.add_reg_function("+", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = $VM->cast(args[0], CLASS_ARRAY);
        return $VM->merge_arrays(self, arg);
    });

    auto &method_class = get_class(CLASS_METHOD);
    method_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return std::string("@method(" + self.string() + ")");
    });

    auto &bytebuffer_class = get_class(CLASS_BYTEBUFFER);
    bytebuffer_class.add_static_reg_function("new", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto klass = self;
        assert(klass.data.type == TYPE_CLASS);

        auto instance = klass.create_instance();

        auto _size = $VM->cast(args[0], CLASS_FIXNUM);
        auto size  = _size.data.fixnum;
        instance.bytebuffer().resize(size);
        return instance;
    });
    bytebuffer_class.add_reg_function("[]", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_BYTEBUFFER);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.bytebuffer();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
            return DabValue(nullptr);
        else
            return DabValue(CLASS_UINT8, a[n]);
    });
    bytebuffer_class.add_reg_function("[]=", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 2);
        auto arg0 = self;
        auto arg1 = args[0];
        auto arg2 = args[1];
        assert(arg0.data.type == TYPE_BYTEBUFFER);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.bytebuffer();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n >= 0 && n < (int64_t)a.size())
        {
            a[n] = $VM->cast(arg2, CLASS_UINT8).data.num_uint8;
        }
        return nullptr;
    });
    bytebuffer_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        std::string ret;
        auto &      a = self.bytebuffer();
        for (size_t i = 0; i < a.size(); i++)
        {
            if (i)
                ret += ", ";
            char string[32];
            sprintf(string, "%d", (int)a[i]);
            ret += string;
        }
        return "[" + ret + "]";
    });
}
<commit_msg>vm: safe release of cinstcall values (part 1)<commit_after>#include "cvm.h"

#include "defaults_shared.h"

DabClass &DabVM::define_builtin_class(const std::string &name, dab_class_t class_index,
                                      dab_class_t superclass_index)
{
    DabClass klass;
    klass.index            = class_index;
    klass.name             = name;
    klass.builtin          = true;
    klass.superclass_index = superclass_index;
    classes[class_index]   = klass;
    return classes[class_index];
}

void DabVM::predefine_default_classes()
{
    fprintf(stderr, "vm: predefine default classes\n");

    define_builtin_class("Object", CLASS_OBJECT);
    define_builtin_class("String", CLASS_STRING);
    define_builtin_class("Fixnum", CLASS_FIXNUM);
    define_builtin_class("Boolean", CLASS_BOOLEAN);
    define_builtin_class("NilClass", CLASS_NILCLASS);
    define_builtin_class("Array", CLASS_ARRAY);
    define_builtin_class("Uint8", CLASS_UINT8, CLASS_FIXNUM);
    define_builtin_class("Uint16", CLASS_UINT16, CLASS_FIXNUM);
    define_builtin_class("Uint32", CLASS_UINT32, CLASS_FIXNUM);
    define_builtin_class("Uint64", CLASS_UINT64, CLASS_FIXNUM);
    define_builtin_class("Int8", CLASS_INT8, CLASS_FIXNUM);
    define_builtin_class("Int16", CLASS_INT16, CLASS_FIXNUM);
    define_builtin_class("Int32", CLASS_INT32, CLASS_FIXNUM);
    define_builtin_class("Int64", CLASS_INT64, CLASS_FIXNUM);
    define_builtin_class("Method", CLASS_METHOD);
    define_builtin_class("IntPtr", CLASS_INTPTR);
    define_builtin_class("ByteBuffer", CLASS_BYTEBUFFER);
    define_builtin_class("LiteralString", CLASS_LITERALSTRING, CLASS_STRING);
    define_builtin_class("DynamicString", CLASS_DYNAMICSTRING, CLASS_STRING);
}

void DabVM::define_default_classes()
{
    fprintf(stderr, "vm: define default classes\n");

    auto &object_class = get_class(CLASS_OBJECT);
    object_class.add_static_reg_function("new", [this](DabValue self, std::vector<DabValue>) {
        auto arg = self;
        assert(arg.data.type == TYPE_CLASS);
        auto instance = arg.create_instance();
        cinstcall(instance, "__construct");
        return instance;
    });
    object_class.add_reg_function(
        "class", [](DabValue self, std::vector<DabValue>) { return self.get_class(); });
    object_class.add_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self.print_value();
    });
    object_class.add_reg_function("__construct", [](DabValue, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return nullptr;
    });
    object_class.add_reg_function("__destruct", [](DabValue, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return nullptr;
    });
    object_class.add_reg_function("is", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        return arg0.is_a(arg1.get_class());
    });
    object_class.add_static_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self.class_name();
    });
    object_class.add_static_reg_function("==", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_CLASS);
        assert(arg1.data.type == TYPE_CLASS);
        return DabValue(arg0.data.fixnum == arg1.data.fixnum);
    });

    auto &string_class = get_class(CLASS_STRING);
    string_class.add_reg_function("upcase", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto s = self.string();
        std::transform(s.begin(), s.end(), s.begin(), ::toupper);
        return s;
    });
    string_class.add_reg_function("length", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto     s = self.string();
        DabValue ret(CLASS_INT32, (int)s.size());
        return ret;
    });
    string_class.add_reg_function("[]", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = $VM->cast(args[0], CLASS_FIXNUM);
        auto s   = self.string();
        auto n   = arg.data.fixnum;
        return DabValue(s.substr(n, 1));
    });
    string_class.add_reg_function("+", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = $VM->cast(args[0], CLASS_STRING);
        auto s0   = arg0.string();
        auto s1   = arg1.string();
        return DabValue(s0 + s1);
    });
    string_class.add_static_reg_function("new", [](DabValue, std::vector<DabValue> args) {
        auto argc = args.size();
        assert(argc <= 2);
        DabValue ret_value;
        ret_value.data.type = TYPE_STRING;
        if (argc == 2)
        {
            auto        arg1   = $VM->cast(args[0], CLASS_BYTEBUFFER);
            auto        arg2   = $VM->cast(args[1], CLASS_FIXNUM);
            const auto &buffer = arg1.bytebuffer();
            const auto  length = arg2.data.fixnum;
            if (length)
            {
                ret_value.data.legacy_string = std::string((const char *)&buffer[0], length);
            }
        }
        else if (argc == 1)
        {
            ret_value.data.legacy_string = args[0].string();
        }
        return ret_value;
    });
    string_class.add_reg_function("to_s", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return self;
    });
    DAB_MEMBER_EQUALS_OPERATORS(string_class, CLASS_STRING, .string());
    DAB_MEMBER_COMPARE_OPERATORS(string_class, CLASS_STRING, .string());

    auto &fixnum_class = get_class(CLASS_FIXNUM);
    fixnum_class.add_static_reg_function("new", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() <= 1);
        auto     klass = self;
        DabValue ret_value;
        ret_value.data.type   = TYPE_FIXNUM;
        ret_value.data.fixnum = 0;
        if (args.size() == 1)
        {
            auto arg = args[0];
            assert(arg.data.type == TYPE_FIXNUM);
            ret_value.data.fixnum = arg.data.fixnum;
        }
        return ret_value;
    });
    DAB_MEMBER_NUMERIC_OPERATORS(fixnum_class, CLASS_FIXNUM, uint64_t, .data.fixnum);

    define_default_classes_int();

    auto &intptr_class = get_class(CLASS_INTPTR);
    intptr_class.add_reg_function("fetch_int32", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto     ptr   = self.data.intptr;
        auto     iptr  = (int32_t *)ptr;
        auto     value = *iptr;
        DabValue ret(CLASS_INT32, value);
        return ret;
    });

    auto &boolean_class = get_class(CLASS_BOOLEAN);
    DAB_MEMBER_EQUALS_OPERATORS(boolean_class, CLASS_BOOLEAN, .data.boolean);

    auto &array_class = get_class(CLASS_ARRAY);
    array_class.add_reg_function("count", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        assert(self.data.type == TYPE_ARRAY);
        return (uint64_t)self.array().size();
    });
    array_class.add_reg_function("shift", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        assert(self.data.type == TYPE_ARRAY);
        auto &a = self.array();
        if (a.size() == 0)
        {
            return DabValue(nullptr);
        }
        else
        {
            auto ret = a[0];
            a.erase(a.begin());
            return ret;
        }
    });
    array_class.add_reg_function("insert", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = args[0];
        assert(self.data.type == TYPE_ARRAY);
        auto &a = self.array();
        a.push_back(arg);
        return nullptr;
    });
    array_class.add_reg_function("[]", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_ARRAY);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.array();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
            return DabValue(nullptr);
        else
            return a[n];
    });
    array_class.add_reg_function("[]=", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 2);
        auto arg0 = self;
        auto arg1 = args[0];
        auto arg2 = args[1];
        assert(arg0.data.type == TYPE_ARRAY);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.array();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
        {
            fprintf(stderr, "vm: index outside of array bounds.\n");
            exit(1);
        }
        else
        {
            a[n] = arg2;
        }
        return nullptr;
    });
    array_class.add_reg_function("join", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        std::string ret;
        auto &      a = self.array();
        for (size_t i = 0; i < a.size(); i++)
        {
            if (i)
                ret += ", ";
            auto val = cinstcall(a[i], "to_s");
            ret += val.string();
        }
        return ret;
    });
    array_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        auto inner = cinstcall(self, "join");
        auto ret   = std::string("[" + inner.string() + "]");
        if (!$VM->options.autorelease)
        {
            inner.release();
        }
        return ret;
    });
    array_class.add_reg_function("+", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg = $VM->cast(args[0], CLASS_ARRAY);
        return $VM->merge_arrays(self, arg);
    });

    auto &method_class = get_class(CLASS_METHOD);
    method_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        return std::string("@method(" + self.string() + ")");
    });

    auto &bytebuffer_class = get_class(CLASS_BYTEBUFFER);
    bytebuffer_class.add_static_reg_function("new", [](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto klass = self;
        assert(klass.data.type == TYPE_CLASS);

        auto instance = klass.create_instance();

        auto _size = $VM->cast(args[0], CLASS_FIXNUM);
        auto size  = _size.data.fixnum;
        instance.bytebuffer().resize(size);
        return instance;
    });
    bytebuffer_class.add_reg_function("[]", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 1);
        auto arg0 = self;
        auto arg1 = args[0];
        assert(arg0.data.type == TYPE_BYTEBUFFER);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.bytebuffer();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n < 0 || n >= (int64_t)a.size())
            return DabValue(nullptr);
        else
            return DabValue(CLASS_UINT8, a[n]);
    });
    bytebuffer_class.add_reg_function("[]=", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 2);
        auto arg0 = self;
        auto arg1 = args[0];
        auto arg2 = args[1];
        assert(arg0.data.type == TYPE_BYTEBUFFER);
        assert(arg1.data.type == TYPE_FIXNUM);
        auto &a = arg0.bytebuffer();
        auto  n = arg1.data.fixnum;
        if (n < 0)
            n = a.size() + n;
        if (n >= 0 && n < (int64_t)a.size())
        {
            a[n] = $VM->cast(arg2, CLASS_UINT8).data.num_uint8;
        }
        return nullptr;
    });
    bytebuffer_class.add_reg_function("to_s", [this](DabValue self, std::vector<DabValue> args) {
        assert(args.size() == 0);
        std::string ret;
        auto &      a = self.bytebuffer();
        for (size_t i = 0; i < a.size(); i++)
        {
            if (i)
                ret += ", ";
            char string[32];
            sprintf(string, "%d", (int)a[i]);
            ret += string;
        }
        return "[" + ret + "]";
    });
}
<|endoftext|>


<commit_before>#include "ChSolverParallel.h"
using namespace chrono;

void ChSolverParallel::InitAPGD(custom_vector<real> &x) {
	ms.resize(x.size());
	mg_tmp2.resize(x.size());
	mb_tmp.resize(x.size());
	mg_tmp.resize(x.size());
	mg_tmp1.resize(x.size());
	mg.resize(x.size());
	ml.resize(x.size());
	mx.resize(x.size());
	my.resize(x.size());

}

uint ChSolverParallel::SolveAPGD(custom_vector<real> &x, const custom_vector<real> &b, const uint max_iter) {
	bool verbose = false;
	real gdiff = 0.000001;

	real lastgoodres=10e30;
	real theta_k=1.0;
	real theta_k1=theta_k;
	real beta_k1=0.0;
	ml = x;
	Project(x);
	ShurProduct(x,mg);
	Sub(mg,mg,b);     //mg = mg -b;

		thrust::fill(mb_tmp.begin(),mb_tmp.end(),-1.0);
		PLUS_EQ(mb_tmp,x);//mb_tmp+=x;
		ShurProduct(mb_tmp,mg_tmp);
		real L_k;
		real mb_tmp_norm = Norm(mb_tmp);
		if (mb_tmp_norm == 0) {
			L_k = 1;
		} else {
			L_k =Norm(mg_tmp) / mb_tmp_norm;
		}

		real t_k = 1.0 / L_k;
		if (verbose) cout << "L_k:" << L_k << " t_k:" << -t_k << "\n";
		my = x;
		mx = x;

		real obj1=0.0;
		real obj2=0.0;

		for (current_iteration = 0; current_iteration < max_iter; current_iteration++) {
			ShurProduct(my,mg_tmp1);
			Sub(mg,mg_tmp1,b);     //mg = mg_tmp1-b;
			SEAXPY(-t_k, mg, my, mx);// mx = my + mg*(t_k);
			Project(mx);
			ShurProduct(mx,mg_tmp);
			Sub(mg_tmp2,mg_tmp,b);//mg_tmp2 = mg_tmp-b
			SEAXMY(.5,mg_tmp,b,ms);//use ms as a temp variable
			obj1 = Dot(mx, ms);
			SEAXMY(.5,mg_tmp1,b,ms);//use ms as a temp variable
			obj2 = Dot(my, ms);
			Sub(ms,mx,my);//ms = mx - my;

			while (obj1 > obj2 + Dot(mg, ms) + 0.5 * L_k * powf(Norm(ms), 2.0)) {
				L_k = 2 * L_k;
				t_k = 1.0 / L_k;
				SEAXPY(-t_k, mg, my, mx);     // mx = my + mg*(t_k);
				Project(mx);

				ShurProduct(mx,mg_tmp);
				Sub(mg_tmp2,mg_tmp,b);//mg_tmp2 = mg_tmp-b
				SEAXMY(.5,mg_tmp,b,ms);//use ms as a temp variable
				obj1 = Dot(mx, ms);
				Sub(ms,mx,my);//ms = mx - my;
			}
			theta_k1 = (-pow(theta_k, 2) + theta_k * sqrt(pow(theta_k, 2) + 4)) / 2.0;
			beta_k1 = theta_k * (1.0 - theta_k) / (pow(theta_k, 2) + theta_k1);

			Sub(ms,mx,ml);     //ms = mx - ml;
			SEAXPY(beta_k1,ms,mx,my);//my = mx + beta_k1 * (ms);

			if (Dot(mg, ms) > 0) {
				my = mx;
				theta_k1 = 1.0;
			}
			L_k = 0.9 * L_k;
			t_k = 1.0 / L_k;

			ml = mx;
			x = mx;
			theta_k = theta_k1;

			//this is res1
			//real g_proj_norm=fmax(real(0.0),-min_val);
			real g_proj_norm=0;//CompRes(mg_tmp2,number_of_rigid_rigid);
			real temp_norm = 0;

			temp_norm = mg_tmp2[thrust::min_element(thrust::omp::par,mg_tmp2.begin(),mg_tmp2.end())-mg_tmp2.begin()];
			//cout<<"norm1: "<<temp_norm<<endl;
			//g_proj_norm = fmax(real(0.0),-temp_norm);
			//temp_norm = mg_tmp2[thrust::min_element(thrust::omp::par,mg_tmp2.begin()+number_of_rigid_rigid*6,mg_tmp2.end())-mg_tmp2.begin()];
			//cout<<"norm2: "<<temp_norm<<endl;
			g_proj_norm = fmax(g_proj_norm,-temp_norm);
//
//			int count_resolved = mg_tmp2.size();
//
//			for(int i=0; i<mg_tmp2.size(); i++) {
//				if(mg_tmp2[i]<tolerance) {
//
//					count_resolved --;
//				}
//			}
//			cout<<"resolved "<<count_resolved<<endl;
			//cout<<"MINVAL "<<g_proj_norm<<" "<<fmax(real(0.0),-min_val)<<endl;
			//this is res4
			//SEAXPY(-gdiff, mg_tmp2, x, mb_tmp); //mb_tmp=x+mg_tmp2*(-gdiff)
			//Project(mb_tmp);
			//d01=mb_tmp-x;
			//mb_tmp = (-1.0/gdiff)*d01;
			//real g_proj_norm = Norm(mb_tmp);

			if(g_proj_norm < lastgoodres) {
				lastgoodres = g_proj_norm;
				//ml_candidate = ml;
			}

			residual=lastgoodres;
			real maxdeltalambda = CompRes(b,number_of_rigid_rigid);     //NormInf(ms);

			AtIterationEnd(residual, maxdeltalambda, current_iteration);

			if (residual < tolerance) {
				break;
			}
		}
		//cout<<x<<endl;
//x=ml_candidate;
		return current_iteration;
	}

<commit_msg>using residual 4 for APGD solver<commit_after>#include "ChSolverParallel.h"
using namespace chrono;

void ChSolverParallel::InitAPGD(custom_vector<real> &x) {
	ms.resize(x.size());
	mg_tmp2.resize(x.size());
	mb_tmp.resize(x.size());
	mg_tmp.resize(x.size());
	mg_tmp1.resize(x.size());
	mg.resize(x.size());
	ml.resize(x.size());
	mx.resize(x.size());
	my.resize(x.size());

}

uint ChSolverParallel::SolveAPGD(custom_vector<real> &x, const custom_vector<real> &b, const uint max_iter) {
	bool verbose = false;
	real gdiff = 0.000001;

	real lastgoodres=10e30;
	real theta_k=1.0;
	real theta_k1=theta_k;
	real beta_k1=0.0;
	ml = x;
	Project(x);
	ShurProduct(x,mg);
	Sub(mg,mg,b);     //mg = mg -b;

		thrust::fill(mb_tmp.begin(),mb_tmp.end(),-1.0);
		PLUS_EQ(mb_tmp,x);//mb_tmp+=x;
		ShurProduct(mb_tmp,mg_tmp);
		real L_k;
		real mb_tmp_norm = Norm(mb_tmp);
		if (mb_tmp_norm == 0) {
			L_k = 1;
		} else {
			L_k =Norm(mg_tmp) / mb_tmp_norm;
		}

		real t_k = 1.0 / L_k;
		if (verbose) cout << "L_k:" << L_k << " t_k:" << -t_k << "\n";
		my = x;
		mx = x;

		real obj1=0.0;
		real obj2=0.0;

		for (current_iteration = 0; current_iteration < max_iter; current_iteration++) {
			ShurProduct(my,mg_tmp1);
			Sub(mg,mg_tmp1,b);     //mg = mg_tmp1-b;
			SEAXPY(-t_k, mg, my, mx);// mx = my + mg*(t_k);
			Project(mx);
			ShurProduct(mx,mg_tmp);
			Sub(mg_tmp2,mg_tmp,b);//mg_tmp2 = mg_tmp-b
			SEAXMY(.5,mg_tmp,b,ms);//use ms as a temp variable
			obj1 = Dot(mx, ms);
			SEAXMY(.5,mg_tmp1,b,ms);//use ms as a temp variable
			obj2 = Dot(my, ms);
			Sub(ms,mx,my);//ms = mx - my;

			while (obj1 > obj2 + Dot(mg, ms) + 0.5 * L_k * powf(Norm(ms), 2.0)) {
				L_k = 2 * L_k;
				t_k = 1.0 / L_k;
				SEAXPY(-t_k, mg, my, mx);     // mx = my + mg*(t_k);
				Project(mx);

				ShurProduct(mx,mg_tmp);
				Sub(mg_tmp2,mg_tmp,b);//mg_tmp2 = mg_tmp-b
				SEAXMY(.5,mg_tmp,b,ms);//use ms as a temp variable
				obj1 = Dot(mx, ms);
				Sub(ms,mx,my);//ms = mx - my;
			}
			theta_k1 = (-pow(theta_k, 2) + theta_k * sqrt(pow(theta_k, 2) + 4)) / 2.0;
			beta_k1 = theta_k * (1.0 - theta_k) / (pow(theta_k, 2) + theta_k1);

			Sub(ms,mx,ml);     //ms = mx - ml;
			SEAXPY(beta_k1,ms,mx,my);//my = mx + beta_k1 * (ms);

			if (Dot(mg, ms) > 0) {
				my = mx;
				theta_k1 = 1.0;
			}
			L_k = 0.9 * L_k;
			t_k = 1.0 / L_k;

			ml = mx;
			x = mx;
			theta_k = theta_k1;

			//this is res1
			//real g_proj_norm=fmax(real(0.0),-min_val);
			//real g_proj_norm=0;//CompRes(mg_tmp2,number_of_rigid_rigid);
			//real temp_norm = 0;

			//temp_norm = mg_tmp2[thrust::min_element(thrust::omp::par,mg_tmp2.begin(),mg_tmp2.end())-mg_tmp2.begin()];
			//cout<<"norm1: "<<temp_norm<<endl;
			//g_proj_norm = fmax(real(0.0),-temp_norm);
			//temp_norm = mg_tmp2[thrust::min_element(thrust::omp::par,mg_tmp2.begin()+number_of_rigid_rigid*6,mg_tmp2.end())-mg_tmp2.begin()];
			//cout<<"norm2: "<<temp_norm<<endl;
			//g_proj_norm = fmax(g_proj_norm,-temp_norm);
//
//			int count_resolved = mg_tmp2.size();
//
//			for(int i=0; i<mg_tmp2.size(); i++) {
//				if(mg_tmp2[i]<tolerance) {
//
//					count_resolved --;
//				}
//			}
//			cout<<"resolved "<<count_resolved<<endl;
			//cout<<"MINVAL "<<g_proj_norm<<" "<<fmax(real(0.0),-min_val)<<endl;
			//this is res4
			SEAXPY(-gdiff, mg_tmp2, x, mb_tmp); //mb_tmp=x+mg_tmp2*(-gdiff)
			Project(mb_tmp);
			custom_vector<real> d01=mb_tmp-x;
			mb_tmp = (-1.0/gdiff)*d01;
			real g_proj_norm = Norm(mb_tmp);

			if(g_proj_norm < lastgoodres) {
				lastgoodres = g_proj_norm;
				//ml_candidate = ml;
			}

			residual=lastgoodres;
			real maxdeltalambda = CompRes(b,number_of_rigid_rigid);     //NormInf(ms);

			AtIterationEnd(residual, maxdeltalambda, current_iteration);

			if (residual < tolerance) {
				break;
			}
		}
		//cout<<x<<endl;
//x=ml_candidate;
		return current_iteration;
	}

<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "strigithread.h"
#include "strigi_thread.h"
#include "strigilogging.h"

#include <string>
#include <cstring>
#include <errno.h>
#include <signal.h>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>

// define two enums and a constant for use of ioprio
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE
};

enum {
    IOPRIO_WHO_PROCESS = 1,
    IOPRIO_WHO_PGRP,
    IOPRIO_WHO_USER
};
#define IOPRIO_CLASS_SHIFT  13

using namespace std;

vector<StrigiThread*> threads;

void
StrigiThread::stopThreads() {
    vector<StrigiThread*>::const_iterator i;
    for (i=threads.begin(); i!=threads.end(); ++i) {
        STRIGI_LOG_INFO ("strigi.daemon", string("stopping thread ")
            + (*i)->name);
        (*i)->stop();
        STRIGI_LOG_INFO ("strigi.daemon", "stopped another thread ");
    }
}

extern "C" void
quit_daemon(int signum) {
    STRIGI_LOG_INFO("strigi.daemon", "quit_daemon");
    static int interruptcount = 0;
    vector<StrigiThread*>::const_iterator i;
    switch (++interruptcount) {
    case 1:
        STRIGI_LOG_INFO ("strigi.daemon", "stopping threads ");
        StrigiThread::stopThreads();
        break;
    case 2:
        STRIGI_LOG_INFO ("strigi.daemon", "terminating threads ");
        for (i=threads.begin(); i!=threads.end(); ++i) {
            (*i)->terminate();
        }
        break;
    case 3:
    default:
        STRIGI_LOG_FATAL ("strigi.daemon", "calling exit(1)")
        exit(1);
    }
}

struct sigaction quitaction;
void
set_quit_on_signal(int signum) {
    quitaction.sa_handler = quit_daemon;
    sigaction(signum, &quitaction, 0);
}
struct sigaction dummyaction;
extern "C" void nothing(int) {}
void
set_wakeup_on_signal(int signum) {
    dummyaction.sa_handler = nothing;
    sigaction(signum, &dummyaction, 0);
}

extern "C" void*
threadstarter(void *d) {
    // give this thread job batch job priority
    struct sched_param param;
    memset(&param, 0, sizeof(param));
    param.sched_priority = 0;
    StrigiThread* thread = static_cast<StrigiThread*>(d);

#ifndef __APPLE__
    if (thread->getPriority() > 0) {
#ifndef SCHED_BATCH
#define SCHED_BATCH 3
#endif
        // renice the thread
        int r  = setpriority(PRIO_PROCESS, 0, thread->getPriority());
        if (r != 0) {
            STRIGI_LOG_ERROR (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting priority: ") + strerror(errno));
        }
        r = sched_setscheduler(0, SCHED_BATCH, &param);
        if (r != 0) {
            STRIGI_LOG_INFO (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting to batch: ") + strerror(errno));
        }
#ifdef SYS_ioprio_set
        if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                IOPRIO_CLASS_IDLE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
            fprintf(stderr, "cannot set io scheduling to idle (%s). "
                "Trying best effort.\n",  strerror( errno ));
            if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                    7|IOPRIO_CLASS_BE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
                fprintf( stderr, "cannot set io scheduling to best effort.\n");
            }
        }
#endif
    }
#endif

    // start the actual work
    thread->run(0);
    STRIGI_LOG_DEBUG(string("strigi.daemon.") + thread->name + ".threadstarter", "end of thread");
    STRIGI_THREAD_EXIT(0);
    return 0;
}

StrigiThread::StrigiThread(const char* n) :state(Idling),thread(0),  name(n) {
    priority = 0;
    STRIGI_MUTEX_INIT(&lock);
}
StrigiThread::~StrigiThread() {
    STRIGI_MUTEX_DESTROY(&lock);
}
void
StrigiThread::setState(State s) {
    STRIGI_MUTEX_LOCK(&lock);
    state = s;
    STRIGI_MUTEX_UNLOCK(&lock);
}
StrigiThread::State
StrigiThread::getState() {
    State s;
    STRIGI_MUTEX_LOCK(&lock);
    s = state;
    STRIGI_MUTEX_UNLOCK(&lock);
    return s;
}
std::string
StrigiThread::getStringState() {
    State s = getState();
    std::string str;
    switch (s) {
    case Idling:
        str = "idling";
        break;
    case Working:
        str = "working";
        break;
    case Stopping:
        str = "stopping";
        break;
    }
    return str;
}
int
StrigiThread::start(int prio) {
    // set up signal handling
    set_quit_on_signal(SIGINT);
    set_quit_on_signal(SIGQUIT);
    set_quit_on_signal(SIGTERM);
    set_wakeup_on_signal(SIGALRM);
    threads.push_back(this);

    priority = prio;
    // start the indexer thread
    int r = STRIGI_THREAD_CREATE(&thread, threadstarter, this);
    if (r < 0) {
        STRIGI_LOG_ERROR ("strigi.daemon." + string(name),
                          "cannot create thread");
        return 1;
    }
    return 0;
}
void
StrigiThread::stop() {
    state = Stopping;
    stopThread();
    if (thread) {
        // signal the thread to wake up
        pthread_kill(thread, SIGALRM);
        // wait for the thread to finish
        STRIGI_THREAD_JOIN(thread);
    }
    thread = 0;
}
void
StrigiThread::terminate() {
    // TODO
}
<commit_msg>That should make GCC 4.4 happier (again)<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "strigithread.h"
#include "strigi_thread.h"
#include "strigilogging.h"

#include <string>
#include <cstring>
#include <cstdio>
#include <errno.h>
#include <signal.h>
#include <vector>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>

// define two enums and a constant for use of ioprio
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE
};

enum {
    IOPRIO_WHO_PROCESS = 1,
    IOPRIO_WHO_PGRP,
    IOPRIO_WHO_USER
};
#define IOPRIO_CLASS_SHIFT  13

using namespace std;

vector<StrigiThread*> threads;

void
StrigiThread::stopThreads() {
    vector<StrigiThread*>::const_iterator i;
    for (i=threads.begin(); i!=threads.end(); ++i) {
        STRIGI_LOG_INFO ("strigi.daemon", string("stopping thread ")
            + (*i)->name);
        (*i)->stop();
        STRIGI_LOG_INFO ("strigi.daemon", "stopped another thread ");
    }
}

extern "C" void
quit_daemon(int signum) {
    STRIGI_LOG_INFO("strigi.daemon", "quit_daemon");
    static int interruptcount = 0;
    vector<StrigiThread*>::const_iterator i;
    switch (++interruptcount) {
    case 1:
        STRIGI_LOG_INFO ("strigi.daemon", "stopping threads ");
        StrigiThread::stopThreads();
        break;
    case 2:
        STRIGI_LOG_INFO ("strigi.daemon", "terminating threads ");
        for (i=threads.begin(); i!=threads.end(); ++i) {
            (*i)->terminate();
        }
        break;
    case 3:
    default:
        STRIGI_LOG_FATAL ("strigi.daemon", "calling exit(1)")
        exit(1);
    }
}

struct sigaction quitaction;
void
set_quit_on_signal(int signum) {
    quitaction.sa_handler = quit_daemon;
    sigaction(signum, &quitaction, 0);
}
struct sigaction dummyaction;
extern "C" void nothing(int) {}
void
set_wakeup_on_signal(int signum) {
    dummyaction.sa_handler = nothing;
    sigaction(signum, &dummyaction, 0);
}

extern "C" void*
threadstarter(void *d) {
    // give this thread job batch job priority
    struct sched_param param;
    memset(&param, 0, sizeof(param));
    param.sched_priority = 0;
    StrigiThread* thread = static_cast<StrigiThread*>(d);

#ifndef __APPLE__
    if (thread->getPriority() > 0) {
#ifndef SCHED_BATCH
#define SCHED_BATCH 3
#endif
        // renice the thread
        int r  = setpriority(PRIO_PROCESS, 0, thread->getPriority());
        if (r != 0) {
            STRIGI_LOG_ERROR (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting priority: ") + strerror(errno));
        }
        r = sched_setscheduler(0, SCHED_BATCH, &param);
        if (r != 0) {
            STRIGI_LOG_INFO (string("strigi.daemon.") + thread->name
                + ".threadstarter",
                string("error setting to batch: ") + strerror(errno));
        }
#ifdef SYS_ioprio_set
        if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                IOPRIO_CLASS_IDLE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
            fprintf(stderr, "cannot set io scheduling to idle (%s). "
                "Trying best effort.\n",  strerror( errno ));
            if (syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0,
                    7|IOPRIO_CLASS_BE<<IOPRIO_CLASS_SHIFT ) < 0 ) {
                fprintf( stderr, "cannot set io scheduling to best effort.\n");
            }
        }
#endif
    }
#endif

    // start the actual work
    thread->run(0);
    STRIGI_LOG_DEBUG(string("strigi.daemon.") + thread->name + ".threadstarter", "end of thread");
    STRIGI_THREAD_EXIT(0);
    return 0;
}

StrigiThread::StrigiThread(const char* n) :state(Idling),thread(0),  name(n) {
    priority = 0;
    STRIGI_MUTEX_INIT(&lock);
}
StrigiThread::~StrigiThread() {
    STRIGI_MUTEX_DESTROY(&lock);
}
void
StrigiThread::setState(State s) {
    STRIGI_MUTEX_LOCK(&lock);
    state = s;
    STRIGI_MUTEX_UNLOCK(&lock);
}
StrigiThread::State
StrigiThread::getState() {
    State s;
    STRIGI_MUTEX_LOCK(&lock);
    s = state;
    STRIGI_MUTEX_UNLOCK(&lock);
    return s;
}
std::string
StrigiThread::getStringState() {
    State s = getState();
    std::string str;
    switch (s) {
    case Idling:
        str = "idling";
        break;
    case Working:
        str = "working";
        break;
    case Stopping:
        str = "stopping";
        break;
    }
    return str;
}
int
StrigiThread::start(int prio) {
    // set up signal handling
    set_quit_on_signal(SIGINT);
    set_quit_on_signal(SIGQUIT);
    set_quit_on_signal(SIGTERM);
    set_wakeup_on_signal(SIGALRM);
    threads.push_back(this);

    priority = prio;
    // start the indexer thread
    int r = STRIGI_THREAD_CREATE(&thread, threadstarter, this);
    if (r < 0) {
        STRIGI_LOG_ERROR ("strigi.daemon." + string(name),
                          "cannot create thread");
        return 1;
    }
    return 0;
}
void
StrigiThread::stop() {
    state = Stopping;
    stopThread();
    if (thread) {
        // signal the thread to wake up
        pthread_kill(thread, SIGALRM);
        // wait for the thread to finish
        STRIGI_THREAD_JOIN(thread);
    }
    thread = 0;
}
void
StrigiThread::terminate() {
    // TODO
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2004 The Apache Software Foundation.  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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanParsedURI.hpp"

#include "XalanUnicode.hpp"

XALAN_CPP_NAMESPACE_BEGIN

#if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG)
const int	XalanParsedURI::d_scheme;
const int	XalanParsedURI::d_authority;
const int	XalanParsedURI::d_query;
const int	XalanParsedURI::d_fragment;
#endif

/* Merge the components back into a complete URI string */
XalanDOMString XalanParsedURI::make() const
{
	XalanDOMString uri;
	if (m_defined & d_scheme)
	{
		uri += m_scheme;
		uri += XalanUnicode::charColon;
	}
	if (m_defined & d_authority)
	{
		uri += XalanUnicode::charSolidus;
		uri += XalanUnicode::charSolidus;
		uri += m_authority;
	}
	uri += m_path;
	if (m_defined & d_query)
	{
		uri += XalanUnicode::charQuestionMark;
		uri += m_query;
	}
	if (m_defined & d_fragment)
	{
		uri += XalanUnicode::charNumberSign;
		uri += m_fragment;
	}
	return uri;
}

/* Parse a URI into component parts.
   Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 */
void XalanParsedURI::parse(
	const XalanDOMChar*			uriString,
	XalanDOMString::size_type	uriStringLen
)
{
	XalanDOMString::size_type index = 0;

	// Clear the components present mask
	m_defined = 0;

	// Scheme portion
	while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charColon &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}

	if (index > 0 && uriString[index] == XalanUnicode::charColon)
	{
		m_scheme = XalanDOMString(uriString, index);
		++index;
		m_defined |= d_scheme;
	}
	else
	{
		index = 0;
		m_scheme.clear();
	}

	// Authority portion
	if (index < uriStringLen - 1 &&
		uriString[index] == XalanUnicode::charSolidus &&
		uriString[index+1] == XalanUnicode::charSolidus)
	{
		index += 2;
		XalanDOMString::size_type authority = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_authority = XalanDOMString(uriString + authority, index - authority);
		m_defined |= d_authority;
	}
	else
	{
		m_authority.clear();
	}

	// Path portion
	XalanDOMString::size_type path = index;
	while (index < uriStringLen &&
			uriString[index] != XalanUnicode::charQuestionMark &&
			uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}
	m_path = XalanDOMString(uriString + path, index - path);

	// Query portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark)
	{
		++index;
		XalanDOMString::size_type query = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_query = XalanDOMString(uriString + query, index - query);
		m_defined |= d_query;
	}
	else
	{
		m_query.clear();
	}

	// Fragment portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign)
	{
		++index;
		m_fragment = XalanDOMString(uriString + index, uriStringLen - index);
		m_defined |= d_fragment;
	}
	else
	{
		m_fragment.clear();
	}
}

/* Case insensitive comparison for URIs.  Limited to A-Za-z */
static int ci_equals(const XalanDOMString &s1, const XalanDOMString &s2)
{
	if (s1.length() != s2.length())
		return false;

	const XalanDOMChar *p1 = s1.c_str(), *p2 = s2.c_str();
	for ( ; *p1 ; p1++, p2++)
	{
		XalanDOMChar c1 = *p1, c2 = *p2;
		if (c1 >= XalanUnicode::charLetter_A && c1 <= XalanUnicode::charLetter_Z)
			c1 = XalanUnicode::charLetter_a + (c1 - XalanUnicode::charLetter_A);
		if (c2 >= XalanUnicode::charLetter_A && c2 <= XalanUnicode::charLetter_Z)
			c2 = XalanUnicode::charLetter_a + (c2 - XalanUnicode::charLetter_A);
		if (c1 != c2)
			return false;
	}

	return true;
}

/* Resolve this URI relative to another according to RFC2396, section 5.2 */
void XalanParsedURI::resolve(
	const XalanParsedURI &base
)
{
	// Handle references to the current document (step 2)
	if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
		m_path.empty())
	{
		m_scheme	= base.m_scheme;
		m_authority = base.m_authority;
		m_path		= base.m_path;
		m_query		= base.m_query;

		// There is an error/unclarity in the specification in step 2 in that
		// it doesn't state that the fragment should be inherited; however
		// it is clear from the examples that it should be
		if (!(m_defined & d_fragment))
		{
			m_fragment = base.m_fragment;
		}

		m_defined |= base.m_defined;
		return;
	}

	// A defined scheme component implies that this is an absolute URI (step 3)
	// Also allow a scheme without authority that matches the base scheme to be
	// interpreted as a relative URI
	if (!(m_defined & d_scheme) || (
			(base.m_defined & d_scheme) && !(m_defined & d_authority)
			&& ci_equals(m_scheme, base.m_scheme)))
	{
		// Inherit the base scheme
		m_scheme = base.m_scheme;
		m_defined |= d_scheme;

		// Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
		if (!(m_defined & d_authority))
		{
			// Inherit the base authority
			m_authority = base.m_authority;
			m_defined |= d_authority;

			// Step 5: if the path starts with a / then it is absolute
			if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
			{
				// Step 6: merge relative path components

				// a) strip off characters after the right most slash in the base path
				XalanDOMString::size_type pathEnd = base.m_path.length();
				while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
				{
					--pathEnd;
				}

				if (pathEnd > 0)
				{
					// b) append relative path
					// This inserts the path portion from base...
					m_path.insert(0, base.m_path, 0, pathEnd);
				}
				else
				{
					// TODO, maybe raise an error here as this
					// is a severely wonky looking URI
				}

				// c)->g remove various "./" and "../" segments
				for (XalanDOMString::size_type index = 0; index < m_path.length(); )
				{
					// remove '<segment>/../' and ./
					if (m_path[index] == XalanUnicode::charFullStop)
					{
						if (index < m_path.length()-1 &&
							m_path[index+1] == XalanUnicode::charSolidus) // ./
						{
							m_path.erase(index,2);
							continue;
						}
						else if (index == m_path.length()-1) // trailing /.
						{
							m_path.erase(index,1);
							continue;
						}
						// Note: also strips leading ../ in an attempt to get
						// something out of a bad m_path
						else if (index < m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop &&
									m_path[index+2] == XalanUnicode::charSolidus) // ../
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							if (index > 0) --index;
							m_path.erase(index, end - index);
							continue;
						}
						else if (index == m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							m_path.erase(index, end - index);
							continue;
						}
					}
					for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
					{
					}
					++index;
				}
			}
		}
	}
}

/* Static helper function to perform a resolve without mucking about with this class */
XalanDOMString XalanParsedURI::resolve(
	const XalanDOMChar			*relative,
	XalanDOMString::size_type	relativeLen,
	const XalanDOMChar			*base,
	XalanDOMString::size_type	baseLen
)
{
	XalanParsedURI relativeURI(relative, relativeLen);
	XalanParsedURI baseURI(base, baseLen);

	relativeURI.resolve(baseURI);
	return relativeURI.make();
}

XALAN_CPP_NAMESPACE_END
<commit_msg>Use DOMStringHelper function for case-insensitive compare.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2004 The Apache Software Foundation.  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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanParsedURI.hpp"

#include "DOMStringHelper.hpp"
#include "XalanUnicode.hpp"

XALAN_CPP_NAMESPACE_BEGIN

#if defined(XALAN_INLINE_INITIALIZATION) && !defined(XALAN_INLINE_INITIALIZATION_IS_DEFINITION_BUG)
const int	XalanParsedURI::d_scheme;
const int	XalanParsedURI::d_authority;
const int	XalanParsedURI::d_query;
const int	XalanParsedURI::d_fragment;
#endif

/* Merge the components back into a complete URI string */
XalanDOMString XalanParsedURI::make() const
{
	XalanDOMString uri;
	if (m_defined & d_scheme)
	{
		uri += m_scheme;
		uri += XalanUnicode::charColon;
	}
	if (m_defined & d_authority)
	{
		uri += XalanUnicode::charSolidus;
		uri += XalanUnicode::charSolidus;
		uri += m_authority;
	}
	uri += m_path;
	if (m_defined & d_query)
	{
		uri += XalanUnicode::charQuestionMark;
		uri += m_query;
	}
	if (m_defined & d_fragment)
	{
		uri += XalanUnicode::charNumberSign;
		uri += m_fragment;
	}
	return uri;
}

/* Parse a URI into component parts.
   Essentially implements the regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 */
void XalanParsedURI::parse(
	const XalanDOMChar*			uriString,
	XalanDOMString::size_type	uriStringLen
)
{
	XalanDOMString::size_type index = 0;

	// Clear the components present mask
	m_defined = 0;

	// Scheme portion
	while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charColon &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}

	if (index > 0 && uriString[index] == XalanUnicode::charColon)
	{
		m_scheme = XalanDOMString(uriString, index);
		++index;
		m_defined |= d_scheme;
	}
	else
	{
		index = 0;
		m_scheme.clear();
	}

	// Authority portion
	if (index < uriStringLen - 1 &&
		uriString[index] == XalanUnicode::charSolidus &&
		uriString[index+1] == XalanUnicode::charSolidus)
	{
		index += 2;
		XalanDOMString::size_type authority = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charSolidus &&
				uriString[index] != XalanUnicode::charQuestionMark &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_authority = XalanDOMString(uriString + authority, index - authority);
		m_defined |= d_authority;
	}
	else
	{
		m_authority.clear();
	}

	// Path portion
	XalanDOMString::size_type path = index;
	while (index < uriStringLen &&
			uriString[index] != XalanUnicode::charQuestionMark &&
			uriString[index] != XalanUnicode::charNumberSign)
	{
		++index;
	}
	m_path = XalanDOMString(uriString + path, index - path);

	// Query portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charQuestionMark)
	{
		++index;
		XalanDOMString::size_type query = index;

		while (index < uriStringLen &&
				uriString[index] != XalanUnicode::charNumberSign)
		{
			++index;
		}
		m_query = XalanDOMString(uriString + query, index - query);
		m_defined |= d_query;
	}
	else
	{
		m_query.clear();
	}

	// Fragment portion
	if (index < uriStringLen && uriString[index] == XalanUnicode::charNumberSign)
	{
		++index;
		m_fragment = XalanDOMString(uriString + index, uriStringLen - index);
		m_defined |= d_fragment;
	}
	else
	{
		m_fragment.clear();
	}
}

/* Resolve this URI relative to another according to RFC2396, section 5.2 */
void XalanParsedURI::resolve(
	const XalanParsedURI &base
)
{
	// Handle references to the current document (step 2)
	if ((m_defined & (d_scheme | d_authority | d_query)) == 0 &&
		m_path.empty())
	{
		m_scheme	= base.m_scheme;
		m_authority = base.m_authority;
		m_path		= base.m_path;
		m_query		= base.m_query;

		// There is an error/unclarity in the specification in step 2 in that
		// it doesn't state that the fragment should be inherited; however
		// it is clear from the examples that it should be
		if (!(m_defined & d_fragment))
		{
			m_fragment = base.m_fragment;
		}

		m_defined |= base.m_defined;
		return;
	}

	// A defined scheme component implies that this is an absolute URI (step 3)
	// Also allow a scheme without authority that matches the base scheme to be
	// interpreted as a relative URI
	if (!(m_defined & d_scheme) || (
			(base.m_defined & d_scheme) && !(m_defined & d_authority)
			&& equalsIgnoreCaseASCII(m_scheme, base.m_scheme)))
	{
		// Inherit the base scheme
		m_scheme = base.m_scheme;
		m_defined |= d_scheme;

		// Step 4: If the authority is unm_defined then inherit it, otherwise skip to step 7
		if (!(m_defined & d_authority))
		{
			// Inherit the base authority
			m_authority = base.m_authority;
			m_defined |= d_authority;

			// Step 5: if the path starts with a / then it is absolute
			if (!(m_path.length() > 0 && m_path[0] == XalanUnicode::charSolidus))
			{
				// Step 6: merge relative path components

				// a) strip off characters after the right most slash in the base path
				XalanDOMString::size_type pathEnd = base.m_path.length();
				while (pathEnd > 0 && base.m_path[pathEnd - 1] != XalanUnicode::charSolidus)
				{
					--pathEnd;
				}

				if (pathEnd > 0)
				{
					// b) append relative path
					// This inserts the path portion from base...
					m_path.insert(0, base.m_path, 0, pathEnd);
				}
				else
				{
					// TODO, maybe raise an error here as this
					// is a severely wonky looking URI
				}

				// c)->g remove various "./" and "../" segments
				for (XalanDOMString::size_type index = 0; index < m_path.length(); )
				{
					// remove '<segment>/../' and ./
					if (m_path[index] == XalanUnicode::charFullStop)
					{
						if (index < m_path.length()-1 &&
							m_path[index+1] == XalanUnicode::charSolidus) // ./
						{
							m_path.erase(index,2);
							continue;
						}
						else if (index == m_path.length()-1) // trailing /.
						{
							m_path.erase(index,1);
							continue;
						}
						// Note: also strips leading ../ in an attempt to get
						// something out of a bad m_path
						else if (index < m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop &&
									m_path[index+2] == XalanUnicode::charSolidus) // ../
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							if (index > 0) --index;
							m_path.erase(index, end - index);
							continue;
						}
						else if (index == m_path.length()-2 &&
									m_path[index+1] == XalanUnicode::charFullStop) // trailing /..
						{
							const XalanDOMString::size_type		end = index + 2;
							if (index > 0) --index;
							for ( ; index > 0 && m_path[index-1] != XalanUnicode::charSolidus; index--)
								;
							m_path.erase(index, end - index);
							continue;
						}
					}
					for ( ; index < m_path.length() && m_path[index] != XalanUnicode::charSolidus ; ++index)
					{
					}
					++index;
				}
			}
		}
	}
}

/* Static helper function to perform a resolve without mucking about with this class */
XalanDOMString XalanParsedURI::resolve(
	const XalanDOMChar			*relative,
	XalanDOMString::size_type	relativeLen,
	const XalanDOMChar			*base,
	XalanDOMString::size_type	baseLen
)
{
	XalanParsedURI relativeURI(relative, relativeLen);
	XalanParsedURI baseURI(base, baseLen);

	relativeURI.resolve(baseURI);
	return relativeURI.make();
}

XALAN_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>// PARAVIS : ParaView wrapper SALOME module
//
// Copyright (C) 2010-2012  CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File   : PVGUI_Module_MenuActions.cxx
// Author : Margarita KARPUNINA
//

#include "PVGUI_Module.h"

#include <QtxActionToolMgr.h>
#include <LightApp_Application.h>
#include <SUIT_Desktop.h>

#include <QApplication>
#include <QAction>
#include <QDockWidget>
#include <QToolBar>
#include <QStatusBar>
#include <QShortcut>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QShowEvent>

#include <pqAnimationViewWidget.h>
#include <pqAnimationWidget.h>

#include <pqApplicationCore.h>
#include <pqComparativeVisPanel.h>
#include <pqObjectInspectorWidget.h>
#include <pqPipelineBrowserWidget.h>
//#include <pqProxyTabWidget.h>
#include <pqObjectInspectorWidget.h>
#include <pqProxyInformationWidget.h>
#include <pqDisplayProxyEditorWidget.h>
#include <pqSettings.h>
#include <pqDataInformationWidget.h>
#include <pqPVAnimationWidget.h>
#include <pqSelectionInspectorWidget.h>
#include <pqProgressWidget.h>

#include <pqAlwaysConnectedBehavior.h>
#include <pqApplicationCore.h>
#include <pqAutoLoadPluginXMLBehavior.h>
#include <pqCommandLineOptionsBehavior.h>
#include <pqCrashRecoveryBehavior.h>
#include <pqDataTimeStepBehavior.h>
#include <pqDefaultViewBehavior.h>
#include <pqDeleteBehavior.h>
#include <pqPersistentMainWindowStateBehavior.h>
#include <pqPluginActionGroupBehavior.h>
#include <pqPluginDockWidgetsBehavior.h>
#include <pqPluginManager.h>
#include <pqPVNewSourceBehavior.h>
#include <pqSpreadSheetVisibilityBehavior.h>
#include <pqStandardViewModules.h>
#include <pqUndoRedoBehavior.h>
#include <pqViewFrameActionsBehavior.h>
#include <pqParaViewMenuBuilders.h>
#include <pqCollaborationPanel.h>
#include <pqMemoryInspectorPanel.h>

class ResizeHelper : public pqPVAnimationWidget
{
  // TEMPORARILY WORKAROUND AROUND PARAVIEW 3.14 BUG:
  // WHEN ANIMATION VIEW IS RESIZED, ITS CONTENTS IS NOT PREPERLY RE-ARRANGED
  // CAUSING SOME CONTROLS TO STAY NON-VISIBLE
  // THIS BUG IS NATURALLY FIXED BY ADDING
  //      this->updateGeometries();
  // TO THE
  //     void pqAnimationWidget::resizeEvent(QResizeEvent* e);
  // BUT THIS CANNOT BE DONE DIRECTLY, SINCE CORRESPONDING API IS NOT PUBLIC
  // THE ONLY WAY TO DO THIS BY SENDING SHOW EVENT TO THE WIDGET

public:
  ResizeHelper( QWidget* parent ) : pqPVAnimationWidget( parent ) {}
protected:
  void resizeEvent(QResizeEvent* e)
  {
    pqAnimationWidget* w = findChild<pqAnimationWidget*>( "pqAnimationWidget" );
    if ( w ) {
      QShowEvent e;
      QApplication::sendEvent( w, &e );
    }
    pqPVAnimationWidget::resizeEvent( e );
  }
};

/*!
  \brief Create dock widgets for ParaView widgets such as object inspector, pipeline browser, etc.
  ParaView pqMainWIndowCore class is fully responsible for these dock widgets' contents.
*/
void PVGUI_Module::setupDockWidgets()
{
  SUIT_Desktop* desk = application()->desktop();

  desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

  // Pipeline
  QDockWidget* pipelineBrowserDock = new QDockWidget( tr( "TTL_PIPELINE_BROWSER" ), desk );
  pipelineBrowserDock->setObjectName("pipelineBrowserDock");
  pipelineBrowserDock->setAllowedAreas( Qt::LeftDockWidgetArea|Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::LeftDockWidgetArea, pipelineBrowserDock );
  pqPipelineBrowserWidget* browser = new pqPipelineBrowserWidget(pipelineBrowserDock);
  pqParaViewMenuBuilders::buildPipelineBrowserContextMenu(*browser);
  pipelineBrowserDock->setWidget(browser);
  myDockWidgets[pipelineBrowserDock] = true;

  //Object inspector
  QDockWidget* objectInspectorDock = new QDockWidget( tr( "TTL_OBJECT_INSPECTOR" ), desk );
  objectInspectorDock->setObjectName("objectInspectorDock");
  objectInspectorDock->setAllowedAreas( Qt::LeftDockWidgetArea|Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::LeftDockWidgetArea, objectInspectorDock );

  pqObjectInspectorWidget* objectInspectorWidget = new pqObjectInspectorWidget(objectInspectorDock);
  objectInspectorDock->setObjectName("objectInspectorWidget");
  objectInspectorWidget->setShowOnAccept(true);
  objectInspectorDock->setWidget(objectInspectorWidget);
  connect( objectInspectorWidget, SIGNAL( helpRequested(const QString&, const QString&) ),  this, SLOT( showHelpForProxy(const QString&, const QString&) ) );
  myDockWidgets[objectInspectorDock] = true;

  //Display Dock
  QDockWidget* displayDock = new QDockWidget( tr( "TTL_DISPLAY" ), desk );
  displayDock->setObjectName("displayDock");
  QWidget* displayWidgetFrame = new QWidget(displayDock);
  displayWidgetFrame->setObjectName("displayWidgetFrame");
  displayDock->setWidget(displayWidgetFrame);

  QScrollArea* displayScrollArea = new QScrollArea(displayWidgetFrame);
  displayScrollArea->setObjectName("displayScrollArea");
  displayScrollArea->setWidgetResizable(true);

  QVBoxLayout* verticalLayout = new QVBoxLayout(displayWidgetFrame);
  verticalLayout->setSpacing(0);
  verticalLayout->setContentsMargins(0, 0, 0, 0);

  pqDisplayProxyEditorWidget* displayWidget = new pqDisplayProxyEditorWidget(displayDock);
  displayWidget->setObjectName("displayWidget");
  displayScrollArea->setWidget(displayWidget);
  verticalLayout->addWidget(displayScrollArea);

  myDockWidgets[displayDock] = true;

  // information dock
  QDockWidget* informationDock = new QDockWidget(tr( "TTL_INFORMATION" ), desk);
  informationDock->setObjectName("informationDock");

  QWidget* informationWidgetFrame = new QWidget(informationDock);
  informationWidgetFrame->setObjectName("informationWidgetFrame");

  QVBoxLayout* verticalLayout_2 = new QVBoxLayout(informationWidgetFrame);
  verticalLayout_2->setSpacing(0);
  verticalLayout_2->setContentsMargins(0, 0, 0, 0);

  QScrollArea* informationScrollArea = new QScrollArea(informationWidgetFrame);
  informationScrollArea->setObjectName("informationScrollArea") ;
  informationScrollArea->setWidgetResizable(true);

  pqProxyInformationWidget* informationWidget = new pqProxyInformationWidget();
  informationWidget->setObjectName("informationWidget");
  informationWidget->setGeometry(QRect(0, 0, 77, 214));
  informationScrollArea->setWidget(informationWidget);

  verticalLayout_2->addWidget(informationScrollArea);
  informationDock->setWidget(informationWidgetFrame);

  myDockWidgets[informationDock] = true;

  desk->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
  desk->tabifyDockWidget(objectInspectorDock, displayDock);
  desk->tabifyDockWidget(objectInspectorDock, informationDock);
  objectInspectorDock->raise();

  // Statistic View
  QDockWidget* statisticsViewDock  = new QDockWidget( tr( "TTL_STATISTICS_VIEW" ), desk );
  statisticsViewDock->setObjectName("statisticsViewDock");
  statisticsViewDock->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::LeftDockWidgetArea|
                                      Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::BottomDockWidgetArea, statisticsViewDock );
  pqDataInformationWidget* aStatWidget = new pqDataInformationWidget(statisticsViewDock);
  statisticsViewDock->setWidget(aStatWidget);
  myDockWidgets[statisticsViewDock] = false; // hidden by default

  //Animation view
  QDockWidget* animationViewDock     = new QDockWidget( tr( "TTL_ANIMATION_VIEW" ), desk );
  animationViewDock->setObjectName("animationViewDock");
  desk->addDockWidget( Qt::BottomDockWidgetArea, animationViewDock );
  pqPVAnimationWidget* animation_panel = new ResizeHelper(animationViewDock); //pqPVAnimationWidget
  animationViewDock->setWidget(animation_panel);
  myDockWidgets[animationViewDock] = false; // hidden by default

  desk->tabifyDockWidget(animationViewDock,  statisticsViewDock);

  // Selection view
  QDockWidget* selectionInspectorDock = new QDockWidget( tr( "TTL_SELECTION_INSPECTOR" ), desk );
  selectionInspectorDock->setObjectName("selectionInspectorDock");
  selectionInspectorDock->setAllowedAreas( Qt::AllDockWidgetAreas );
  desk->addDockWidget( Qt::LeftDockWidgetArea, selectionInspectorDock );
  pqSelectionInspectorPanel* aSelInspector = new pqSelectionInspectorWidget(selectionInspectorDock);
  selectionInspectorDock->setWidget(aSelInspector);
  myDockWidgets[selectionInspectorDock] = false; // hidden by default

  // Comparative View
  QDockWidget* comparativePanelDock  = new QDockWidget( tr( "TTL_COMPARATIVE_VIEW_INSPECTOR" ), desk );
  comparativePanelDock->setObjectName("comparativePanelDock");
  desk->addDockWidget( Qt::LeftDockWidgetArea, comparativePanelDock );
  pqComparativeVisPanel* cv_panel = new pqComparativeVisPanel( comparativePanelDock );
  comparativePanelDock->setWidget(cv_panel);
  myDockWidgets[comparativePanelDock] = false; // hidden by default

  // Collaboration view
  QDockWidget* collaborationPanelDock = new QDockWidget(tr( "TTL_COLLABORATIVE_DOCK" ), desk);
  collaborationPanelDock->setObjectName("collaborationPanelDock");
  pqCollaborationPanel* collaborationPanel = new pqCollaborationPanel();
  collaborationPanel->setObjectName("collaborationPanel");
  collaborationPanelDock->setWidget(collaborationPanel);
  desk->addDockWidget(Qt::RightDockWidgetArea, collaborationPanelDock);
  myDockWidgets[collaborationPanelDock] = false; // hidden by default

  // Memory inspector dock
  QDockWidget* memoryInspectorDock = new QDockWidget(tr( "TTL_MEMORY_INSPECTOR" ), desk);
  memoryInspectorDock->setObjectName("memoryInspectorDock");
  pqMemoryInspectorPanel* dockWidgetContents = new pqMemoryInspectorPanel();
  dockWidgetContents->setObjectName("dockWidgetContents");
  memoryInspectorDock->setWidget(dockWidgetContents);
  desk->addDockWidget(Qt::RightDockWidgetArea, memoryInspectorDock);
  myDockWidgets[memoryInspectorDock] = false; // hidden by default

  // Setup the statusbar ...
  pqProgressWidget* aProgress = new pqProgressWidget(desk->statusBar());
  desk->statusBar()->addPermanentWidget(aProgress);

  // Set up the dock window corners to give the vertical docks more room.
  desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

  // Setup the default dock configuration ...
  statisticsViewDock->hide();
  comparativePanelDock->hide();
  animationViewDock->hide();
  selectionInspectorDock->hide();
  collaborationPanelDock->hide();
  memoryInspectorDock->hide();

  // Setup quick-launch shortcuts.
  QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, desk);
  QObject::connect(ctrlSpace, SIGNAL(activated()), pqApplicationCore::instance(), SLOT(quickLaunch()));
  QShortcut *altSpace = new QShortcut(Qt::ALT + Qt::Key_Space, desk);
  QObject::connect(altSpace, SIGNAL(activated()), pqApplicationCore::instance(), SLOT(quickLaunch()));

}

/*!
  \brief Save states of dockable ParaView widgets.
*/
void PVGUI_Module::saveDockWidgetsState()
{
  SUIT_Desktop* desk = application()->desktop();

  // VSR: 19/06/2011: do not use Paraview's methods, since it conflicts with SALOME GUI architecture
  // ... the following code is commented...
  // Save the state of the window ...
  // pqApplicationCore::instance()->settings()->saveState(*desk, "MainWindow");
  //
  //for (int i = 0; i < myDockWidgets.size(); ++i)
  //  myDockWidgets.at(i)->setParent(0);
  // ... and replaced - manually hide dock windows

  // store dock widgets visibility state and hide'em all
  QMapIterator<QWidget*, bool> it1( myDockWidgets );
  while( it1.hasNext() ) {
    it1.next();
    QDockWidget* dw = qobject_cast<QDockWidget*>( it1.key() );
    myDockWidgets[dw] = dw->isVisible();
    dw->setVisible( false );
    dw->toggleViewAction()->setVisible( false );
  }
  // store toolbar breaks state and remove all tollbar breaks
  QMapIterator<QWidget*, bool> it2( myToolbarBreaks );
  while( it2.hasNext() ) {
    it2.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it2.key() );
    myToolbarBreaks[tb] = desk->toolBarBreak( tb );
    if ( myToolbarBreaks[tb] )
      desk->removeToolBarBreak( tb );
  }
  // store toolbars visibility state and hide'em all
  QMapIterator<QWidget*, bool> it3( myToolbars );
  while( it3.hasNext() ) {
    it3.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it3.key() );
    myToolbars[tb] = tb->isVisible();
    tb->setVisible( false );
    tb->toggleViewAction()->setVisible( false );
  }
}

/*!
  \brief Restore states of dockable ParaView widgets.
*/
void PVGUI_Module::restoreDockWidgetsState()
{
  SUIT_Desktop* desk = application()->desktop();

  // VSR: 19/06/2011: do not use Paraview's methods, since it conflicts with SALOME GUI architecture
  // ... the following code is commented...
  //for (int i = 0; i < myDockWidgets.size(); ++i)
  //  myDockWidgets.at(i)->setParent(desk);
  //
  // Restore the state of the window ...
  //pqApplicationCore::instance()->settings()->restoreState("MainWindow", *desk);
  // ... and replaced - manually hide dock windows

  // restore dock widgets visibility state
  QMapIterator<QWidget*, bool> it1( myDockWidgets );
  while( it1.hasNext() ) {
    it1.next();
    QDockWidget* dw = qobject_cast<QDockWidget*>( it1.key() );
    dw->setVisible( it1.value() );
    dw->toggleViewAction()->setVisible( true );
  }
  // restore toolbar breaks state
  QMapIterator<QWidget*, bool> it2( myToolbarBreaks );
  while( it2.hasNext() ) {
    it2.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it2.key() );
    if ( myToolbarBreaks[tb] )
      desk->insertToolBarBreak( tb );
  }
  // restore toolbar visibility state
  QMapIterator<QWidget*, bool> it3( myToolbars );
  while( it3.hasNext() ) {
    it3.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it3.key() );
    tb->setVisible( it3.value() );
    tb->toggleViewAction()->setVisible( true );
  }
}
<commit_msg>#22153: Progress bar missing<commit_after>// PARAVIS : ParaView wrapper SALOME module
//
// Copyright (C) 2010-2012  CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File   : PVGUI_Module_MenuActions.cxx
// Author : Margarita KARPUNINA
//

#include "PVGUI_Module.h"

#include <QtxActionToolMgr.h>
#include <LightApp_Application.h>
#include <SUIT_Desktop.h>

#include <QApplication>
#include <QAction>
#include <QDockWidget>
#include <QToolBar>
#include <QStatusBar>
#include <QShortcut>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QShowEvent>
#include <QToolButton>

#include <pqAnimationViewWidget.h>
#include <pqAnimationWidget.h>

#include <pqApplicationCore.h>
#include <pqComparativeVisPanel.h>
#include <pqObjectInspectorWidget.h>
#include <pqPipelineBrowserWidget.h>
//#include <pqProxyTabWidget.h>
#include <pqObjectInspectorWidget.h>
#include <pqProxyInformationWidget.h>
#include <pqDisplayProxyEditorWidget.h>
#include <pqSettings.h>
#include <pqDataInformationWidget.h>
#include <pqPVAnimationWidget.h>
#include <pqSelectionInspectorWidget.h>
#include <pqProgressWidget.h>
#include <pqProgressManager.h>

#include <pqAlwaysConnectedBehavior.h>
#include <pqApplicationCore.h>
#include <pqAutoLoadPluginXMLBehavior.h>
#include <pqCommandLineOptionsBehavior.h>
#include <pqCrashRecoveryBehavior.h>
#include <pqDataTimeStepBehavior.h>
#include <pqDefaultViewBehavior.h>
#include <pqDeleteBehavior.h>
#include <pqPersistentMainWindowStateBehavior.h>
#include <pqPluginActionGroupBehavior.h>
#include <pqPluginDockWidgetsBehavior.h>
#include <pqPluginManager.h>
#include <pqPVNewSourceBehavior.h>
#include <pqSpreadSheetVisibilityBehavior.h>
#include <pqStandardViewModules.h>
#include <pqUndoRedoBehavior.h>
#include <pqViewFrameActionsBehavior.h>
#include <pqParaViewMenuBuilders.h>
#include <pqCollaborationPanel.h>
#include <pqMemoryInspectorPanel.h>

class ResizeHelper : public pqPVAnimationWidget
{
  // TEMPORARILY WORKAROUND AROUND PARAVIEW 3.14 BUG:
  // WHEN ANIMATION VIEW IS RESIZED, ITS CONTENTS IS NOT PREPERLY RE-ARRANGED
  // CAUSING SOME CONTROLS TO STAY NON-VISIBLE
  // THIS BUG IS NATURALLY FIXED BY ADDING
  //      this->updateGeometries();
  // TO THE
  //     void pqAnimationWidget::resizeEvent(QResizeEvent* e);
  // BUT THIS CANNOT BE DONE DIRECTLY, SINCE CORRESPONDING API IS NOT PUBLIC
  // THE ONLY WAY TO DO THIS BY SENDING SHOW EVENT TO THE WIDGET

public:
  ResizeHelper( QWidget* parent ) : pqPVAnimationWidget( parent ) {}
protected:
  void resizeEvent(QResizeEvent* e)
  {
    pqAnimationWidget* w = findChild<pqAnimationWidget*>( "pqAnimationWidget" );
    if ( w ) {
      QShowEvent e;
      QApplication::sendEvent( w, &e );
    }
    pqPVAnimationWidget::resizeEvent( e );
  }
};

/*!
  \brief Create dock widgets for ParaView widgets such as object inspector, pipeline browser, etc.
  ParaView pqMainWIndowCore class is fully responsible for these dock widgets' contents.
*/
void PVGUI_Module::setupDockWidgets()
{
  SUIT_Desktop* desk = application()->desktop();

  desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

  // Pipeline
  QDockWidget* pipelineBrowserDock = new QDockWidget( tr( "TTL_PIPELINE_BROWSER" ), desk );
  pipelineBrowserDock->setObjectName("pipelineBrowserDock");
  pipelineBrowserDock->setAllowedAreas( Qt::LeftDockWidgetArea|Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::LeftDockWidgetArea, pipelineBrowserDock );
  pqPipelineBrowserWidget* browser = new pqPipelineBrowserWidget(pipelineBrowserDock);
  pqParaViewMenuBuilders::buildPipelineBrowserContextMenu(*browser);
  pipelineBrowserDock->setWidget(browser);
  myDockWidgets[pipelineBrowserDock] = true;

  //Object inspector
  QDockWidget* objectInspectorDock = new QDockWidget( tr( "TTL_OBJECT_INSPECTOR" ), desk );
  objectInspectorDock->setObjectName("objectInspectorDock");
  objectInspectorDock->setAllowedAreas( Qt::LeftDockWidgetArea|Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::LeftDockWidgetArea, objectInspectorDock );

  pqObjectInspectorWidget* objectInspectorWidget = new pqObjectInspectorWidget(objectInspectorDock);
  objectInspectorDock->setObjectName("objectInspectorWidget");
  objectInspectorWidget->setShowOnAccept(true);
  objectInspectorDock->setWidget(objectInspectorWidget);
  connect( objectInspectorWidget, SIGNAL( helpRequested(const QString&, const QString&) ),  this, SLOT( showHelpForProxy(const QString&, const QString&) ) );
  myDockWidgets[objectInspectorDock] = true;

  //Display Dock
  QDockWidget* displayDock = new QDockWidget( tr( "TTL_DISPLAY" ), desk );
  displayDock->setObjectName("displayDock");
  QWidget* displayWidgetFrame = new QWidget(displayDock);
  displayWidgetFrame->setObjectName("displayWidgetFrame");
  displayDock->setWidget(displayWidgetFrame);

  QScrollArea* displayScrollArea = new QScrollArea(displayWidgetFrame);
  displayScrollArea->setObjectName("displayScrollArea");
  displayScrollArea->setWidgetResizable(true);

  QVBoxLayout* verticalLayout = new QVBoxLayout(displayWidgetFrame);
  verticalLayout->setSpacing(0);
  verticalLayout->setContentsMargins(0, 0, 0, 0);

  pqDisplayProxyEditorWidget* displayWidget = new pqDisplayProxyEditorWidget(displayDock);
  displayWidget->setObjectName("displayWidget");
  displayScrollArea->setWidget(displayWidget);
  verticalLayout->addWidget(displayScrollArea);

  myDockWidgets[displayDock] = true;

  // information dock
  QDockWidget* informationDock = new QDockWidget(tr( "TTL_INFORMATION" ), desk);
  informationDock->setObjectName("informationDock");

  QWidget* informationWidgetFrame = new QWidget(informationDock);
  informationWidgetFrame->setObjectName("informationWidgetFrame");

  QVBoxLayout* verticalLayout_2 = new QVBoxLayout(informationWidgetFrame);
  verticalLayout_2->setSpacing(0);
  verticalLayout_2->setContentsMargins(0, 0, 0, 0);

  QScrollArea* informationScrollArea = new QScrollArea(informationWidgetFrame);
  informationScrollArea->setObjectName("informationScrollArea") ;
  informationScrollArea->setWidgetResizable(true);

  pqProxyInformationWidget* informationWidget = new pqProxyInformationWidget();
  informationWidget->setObjectName("informationWidget");
  informationWidget->setGeometry(QRect(0, 0, 77, 214));
  informationScrollArea->setWidget(informationWidget);

  verticalLayout_2->addWidget(informationScrollArea);
  informationDock->setWidget(informationWidgetFrame);

  myDockWidgets[informationDock] = true;

  desk->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
  desk->tabifyDockWidget(objectInspectorDock, displayDock);
  desk->tabifyDockWidget(objectInspectorDock, informationDock);
  objectInspectorDock->raise();

  // Statistic View
  QDockWidget* statisticsViewDock  = new QDockWidget( tr( "TTL_STATISTICS_VIEW" ), desk );
  statisticsViewDock->setObjectName("statisticsViewDock");
  statisticsViewDock->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::LeftDockWidgetArea|
                                      Qt::NoDockWidgetArea|Qt::RightDockWidgetArea );
  desk->addDockWidget( Qt::BottomDockWidgetArea, statisticsViewDock );
  pqDataInformationWidget* aStatWidget = new pqDataInformationWidget(statisticsViewDock);
  statisticsViewDock->setWidget(aStatWidget);
  myDockWidgets[statisticsViewDock] = false; // hidden by default

  //Animation view
  QDockWidget* animationViewDock     = new QDockWidget( tr( "TTL_ANIMATION_VIEW" ), desk );
  animationViewDock->setObjectName("animationViewDock");
  desk->addDockWidget( Qt::BottomDockWidgetArea, animationViewDock );
  pqPVAnimationWidget* animation_panel = new ResizeHelper(animationViewDock); //pqPVAnimationWidget
  animationViewDock->setWidget(animation_panel);
  myDockWidgets[animationViewDock] = false; // hidden by default

  desk->tabifyDockWidget(animationViewDock,  statisticsViewDock);

  // Selection view
  QDockWidget* selectionInspectorDock = new QDockWidget( tr( "TTL_SELECTION_INSPECTOR" ), desk );
  selectionInspectorDock->setObjectName("selectionInspectorDock");
  selectionInspectorDock->setAllowedAreas( Qt::AllDockWidgetAreas );
  desk->addDockWidget( Qt::LeftDockWidgetArea, selectionInspectorDock );
  pqSelectionInspectorPanel* aSelInspector = new pqSelectionInspectorWidget(selectionInspectorDock);
  selectionInspectorDock->setWidget(aSelInspector);
  myDockWidgets[selectionInspectorDock] = false; // hidden by default

  // Comparative View
  QDockWidget* comparativePanelDock  = new QDockWidget( tr( "TTL_COMPARATIVE_VIEW_INSPECTOR" ), desk );
  comparativePanelDock->setObjectName("comparativePanelDock");
  desk->addDockWidget( Qt::LeftDockWidgetArea, comparativePanelDock );
  pqComparativeVisPanel* cv_panel = new pqComparativeVisPanel( comparativePanelDock );
  comparativePanelDock->setWidget(cv_panel);
  myDockWidgets[comparativePanelDock] = false; // hidden by default

  // Collaboration view
  QDockWidget* collaborationPanelDock = new QDockWidget(tr( "TTL_COLLABORATIVE_DOCK" ), desk);
  collaborationPanelDock->setObjectName("collaborationPanelDock");
  pqCollaborationPanel* collaborationPanel = new pqCollaborationPanel();
  collaborationPanel->setObjectName("collaborationPanel");
  collaborationPanelDock->setWidget(collaborationPanel);
  desk->addDockWidget(Qt::RightDockWidgetArea, collaborationPanelDock);
  myDockWidgets[collaborationPanelDock] = false; // hidden by default

  // Memory inspector dock
  QDockWidget* memoryInspectorDock = new QDockWidget(tr( "TTL_MEMORY_INSPECTOR" ), desk);
  memoryInspectorDock->setObjectName("memoryInspectorDock");
  pqMemoryInspectorPanel* dockWidgetContents = new pqMemoryInspectorPanel();
  dockWidgetContents->setObjectName("dockWidgetContents");
  memoryInspectorDock->setWidget(dockWidgetContents);
  desk->addDockWidget(Qt::RightDockWidgetArea, memoryInspectorDock);
  myDockWidgets[memoryInspectorDock] = false; // hidden by default

  // Setup the statusbar ...
  pqProgressManager* progress_manager =
    pqApplicationCore::instance()->getProgressManager();

  // Progress bar/button management
  pqProgressWidget* aProgress = new pqProgressWidget(desk->statusBar());
  progress_manager->addNonBlockableObject(aProgress);
  progress_manager->addNonBlockableObject(aProgress->getAbortButton());

  QObject::connect( progress_manager, SIGNAL(enableProgress(bool)),
                    aProgress,        SLOT(enableProgress(bool)));

  QObject::connect( progress_manager, SIGNAL(progress(const QString&, int)),
                    aProgress,        SLOT(setProgress(const QString&, int)));

  QObject::connect( progress_manager, SIGNAL(enableAbort(bool)),
                    aProgress,        SLOT(enableAbort(bool)));

  QObject::connect( aProgress,        SIGNAL(abortPressed()),
                    progress_manager, SLOT(triggerAbort()));

  desk->statusBar()->addPermanentWidget(aProgress);
  aProgress->setEnabled(true);

  // Set up the dock window corners to give the vertical docks more room.
  desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);

  // Setup the default dock configuration ...
  statisticsViewDock->hide();
  comparativePanelDock->hide();
  animationViewDock->hide();
  selectionInspectorDock->hide();
  collaborationPanelDock->hide();
  memoryInspectorDock->hide();

  // Setup quick-launch shortcuts.
  QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, desk);
  QObject::connect(ctrlSpace, SIGNAL(activated()), pqApplicationCore::instance(), SLOT(quickLaunch()));
  QShortcut *altSpace = new QShortcut(Qt::ALT + Qt::Key_Space, desk);
  QObject::connect(altSpace, SIGNAL(activated()), pqApplicationCore::instance(), SLOT(quickLaunch()));

}

/*!
  \brief Save states of dockable ParaView widgets.
*/
void PVGUI_Module::saveDockWidgetsState()
{
  SUIT_Desktop* desk = application()->desktop();

  // VSR: 19/06/2011: do not use Paraview's methods, since it conflicts with SALOME GUI architecture
  // ... the following code is commented...
  // Save the state of the window ...
  // pqApplicationCore::instance()->settings()->saveState(*desk, "MainWindow");
  //
  //for (int i = 0; i < myDockWidgets.size(); ++i)
  //  myDockWidgets.at(i)->setParent(0);
  // ... and replaced - manually hide dock windows

  // store dock widgets visibility state and hide'em all
  QMapIterator<QWidget*, bool> it1( myDockWidgets );
  while( it1.hasNext() ) {
    it1.next();
    QDockWidget* dw = qobject_cast<QDockWidget*>( it1.key() );
    myDockWidgets[dw] = dw->isVisible();
    dw->setVisible( false );
    dw->toggleViewAction()->setVisible( false );
  }
  // store toolbar breaks state and remove all tollbar breaks
  QMapIterator<QWidget*, bool> it2( myToolbarBreaks );
  while( it2.hasNext() ) {
    it2.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it2.key() );
    myToolbarBreaks[tb] = desk->toolBarBreak( tb );
    if ( myToolbarBreaks[tb] )
      desk->removeToolBarBreak( tb );
  }
  // store toolbars visibility state and hide'em all
  QMapIterator<QWidget*, bool> it3( myToolbars );
  while( it3.hasNext() ) {
    it3.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it3.key() );
    myToolbars[tb] = tb->isVisible();
    tb->setVisible( false );
    tb->toggleViewAction()->setVisible( false );
  }
}

/*!
  \brief Restore states of dockable ParaView widgets.
*/
void PVGUI_Module::restoreDockWidgetsState()
{
  SUIT_Desktop* desk = application()->desktop();

  // VSR: 19/06/2011: do not use Paraview's methods, since it conflicts with SALOME GUI architecture
  // ... the following code is commented...
  //for (int i = 0; i < myDockWidgets.size(); ++i)
  //  myDockWidgets.at(i)->setParent(desk);
  //
  // Restore the state of the window ...
  //pqApplicationCore::instance()->settings()->restoreState("MainWindow", *desk);
  // ... and replaced - manually hide dock windows

  // restore dock widgets visibility state
  QMapIterator<QWidget*, bool> it1( myDockWidgets );
  while( it1.hasNext() ) {
    it1.next();
    QDockWidget* dw = qobject_cast<QDockWidget*>( it1.key() );
    dw->setVisible( it1.value() );
    dw->toggleViewAction()->setVisible( true );
  }
  // restore toolbar breaks state
  QMapIterator<QWidget*, bool> it2( myToolbarBreaks );
  while( it2.hasNext() ) {
    it2.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it2.key() );
    if ( myToolbarBreaks[tb] )
      desk->insertToolBarBreak( tb );
  }
  // restore toolbar visibility state
  QMapIterator<QWidget*, bool> it3( myToolbars );
  while( it3.hasNext() ) {
    it3.next();
    QToolBar* tb = qobject_cast<QToolBar*>( it3.key() );
    tb->setVisible( it3.value() );
    tb->toggleViewAction()->setVisible( true );
  }
}
<|endoftext|>